RE: GII event system
Hi I just got one device which will be not so good to drive with your conception of dividing space and click data: This is touch screen. I think you used bank machines or something like that :) Best Regards. Dmitry -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Friday, October 22, 1999 3:05 AM To: [EMAIL PROTECTED] Subject: Re: GII event system Hi ! 1. Mouse is a human input device, as well as others pointing device. Practically buttons are related to mouse position and usual human expects reasonable button action right in place where he has clicked it. Yes. This however does not mean, that the driver producing the "clicks" has to know anything about the driver producing the moves. This is why the moves and clicks are separate. Please note, that it is possible to mix relative and absolute pointer events. A simple example of that would be keyboard emulated mouse (which only makes sense as relative events) on a absolute-mouse target like X. What have we do with GII. Something like that collecting: pmove1 abs pbutton pmove2 abs will do (pmove1.x +pmove2.x)/2 and the same for y. ??? What ? I'll sketch how a LibGGI mouse handling routine for a system that expects to work with absolute coordinates is intended to look like: { static int mousex,mousey; ... ggiEventPoll(vis, emKey|emPointer, NULL); events = ggiEventsQueued(vis, emKey|emPointer); while (events--) { ggiEventRead(vis, event, emKey|emPointer); switch(event.any.type) { case evPtrButtonPress: switch(event.pbutton.button) { case GII_PBUTTON_FIRST: do_something_as_appropriate(mousex,mousey); break; case GII_PBUTTON_SECOND: ... } break; case evPtrButtonRelease: ... if needed ... break; case evPtrAbsolute: mousex = event.pmove.x; mousey = event.pmove.y; break; case evPtrRelative: mousex += event.pmove.x; mousey += event.pmove.y; break; } /* Constrain mouse in any case */ if (mousex 0) mousex = 0; if (mousey 0) mousey = 0; if (mousex xmax) mousex = xmax; if (mousey ymax) mousey = ymax; } /* while */ } As you can see, this nicely symmetriyes the cases of abs and rel events. Basically the same can be done for apps that expect relative events, though those might get trouble on absolute input data when trying to "keep turning left" or similar. Was it good? It is no good, at least because gii client software is not right place to do it. To do what ? (pmove1.x +pmove2.x)/2 ? There is no reasonable place to do such a calculation at all. To make sense at all, you would have to make a weighted mean based on the time between the individual event's timestamps. There is no assumption of something like a linear motion between points between move events, and for sure no assumption, that the click happens in the middle of that. The expected behaviour is, that the above used mousex,mousey variables express the correct position of the pointer, when a click comes in. If the mouse was moved between the last move and the click, the driver is expected to send another move and then the click to correctly position the pointer before transmitting the click. Why do I need to keep every pmove message until get pbutton and pmove again? That is not pretty at least. You don't. See above. In case that delivers incorrect results, we have a bug in a driver or backend and need to fix the driver or flame the backend authors. I understand that it is my task to determinate correct click place in case of relative move messages and I do. But I really hope I will be able to avoid mouse cursor software emulation(what I have done because of no choice) and to forget about relative messages for pointing device like mouse in the future when GGI will take care about hardware cursor. GGI will never take away the information you get from the input device. While we may provide a method to place a hardware sprite on the display, thus allowing to easily make up a mouse pointer, this will not influence the pointer data sent from the input device. I repeat ones more I am discussing only about the case when cursor generation is not my task. I still do not get what cursor generation has to do with input handling. There are some applications that would be pretty unhappy, if we converted all input to absolute pointer events. Guess why the X target has the relmouse mode ... In the depth My question was why after calling poll(I call it with 0 time delay) the queued function shows only one message we have inside of queue but actually there are many (inside of some internal buffers). If that is the case, this is a bug and should be fixed. I think poll function really poll only one message for each message type per one call, does not it? No. It should check and queue all attached in
GII event system
1. Why GII gii_event.pbutton does not have cursor coordinate information in case of GII buffering and sending data which have absolute cursor position(x target and may be future fb target with hardware cursor). 2. Why GII does not use button data in case of sending pmove event? 3. I found some strange behavior inside of GII. -I poll GII one time -I read all events queued inside GII in my internal buffer with keeping only onepmove message inside of my buffer -I read one message from my buffer. -I move my cursor in case of pmove data -I call ggUSleep(10); -I see funny effect on the screen: my cursor making always is to late :) It looks like GII buffer can not giveme back all messages by one polling. if I do poll and read queued messages like this: while(Poll()); instead of one polling where Poll is something like this. (DO not forget I do not save reputed pmove messages. I cleaned that code to save space.) bool wipGII::Poll() { bool r=false; timeval val; val.tv_sec=0; val.tv_usec=0; ggiEventPoll(graph-vis, emAll, val); for (int n=ggiEventsQueued(graph-vis, emAll); n; n--) { ggiEventRead(graph-vis, ev[(unsigned char)(ev_ptr+ev_qty)], emAll); if (ev_qty!=0xff) ev_qty++; else ev_ptr++; r=true; } return r; } I've found no problem with my cursor. Thank you Dmitry
Re: GII event system
Hi ! 1. Why GII gii_event.pbutton does not have cursor coordinate information Because the buttons and the pointer position are not related in any way theoretically. Using the mapper filters, you can push "mouse buttons" on the keyboard and vice versa ... in case of GII buffering and sending data which have absolute cursor position (x target and may be future fb target with hardware cursor). ? I don't get you here. What has absoluet cursor position to do with buttons ? 2. Why GII does not use button data in case of sending pmove event? Same reason, see above. 3. I found some strange behavior inside of GII. -I poll GII one time -I read all events queued inside GII in my internal buffer with keeping only one pmove message inside of my buffer -I read one message from my buffer. -I move my cursor in case of pmove data -I call ggUSleep(10); -I see funny effect on the screen: my cursor making always is to late :) It looks like GII buffer can not give me back all messages by one polling. if I do poll and read queued messages like this: while(Poll()); instead of one polling where Poll is something like this [... snip ...] I've found no problem with my cursor. Hmm - I get you right, that gii events are kept queued inside gii when you try to read them - right ? Well, there is a possible simple explanation: ggiPoll unblocks _as_soon_as_ one of the associated FDs gets readable. Now, if the Mouse e.g. first sends a Pointer-update-packet or similar, this gets read into LibGGI immediately during the poll. The poll then unblocks, as data is available. At that point, there is only the first sent event from the mouse available. The mouse keeps sending data, but the LibGII poll routine has already terminated, as it terminates as soon as the first event gets readable. For such situations, where this behaviour is undesireable, as there are long delays between frames, it might make sense to use something like while(ggiPoll()) { do_the_evenht_reading(); eventually_wait_a_short_grace_time(); } This allows for "slow" devices that do not instantaneously deliver all data. What mouse do you have ? we might want to check the driver, if it does the expected thing, which is to loop in its poll handler as long as data is incoming. CU, Andy -- Andreas Beck | Email : [EMAIL PROTECTED]
RE: GII event system
Hi Thanks for your reply 1. Mouse is a human input device, as well as others pointing device. Practically buttons are related to mouse position and usual human expects reasonable button action right in place where he has clicked it. What have we do with GII. Something like that collecting: pmove1 abs pbutton pmove2 abs will do (pmove1.x +pmove2.x)/2 and the same for y. Was it good? It is no good, at least because gii client software is not right place to do it. Why do I need to keep every pmove message until get pbutton and pmove again? That is not pretty at least. I understand that it is my task to determinate correct click place in case of relative move messages and I do. But I really hope I will be able to avoid mouse cursor software emulation(what I have done because of no choice) and to forget about relative messages for pointing device like mouse in the future when GGI will take care about hardware cursor. Also I do not see any problem with "Using the mapper filters, you can push "mouse buttons" on the keyboard and vice versa ..." For example Button can be the "reset button" on the computer instead of left or middle mouse button, but if human thinks that that one has functionality related to the mouse cursor it should be and We have to have xyz closure to the click place inside of point device driver. I repeat ones more I am discussing only about the case when cursor generation is not my task. 2. Please refer my old mail. I already found the way how to live together with poll, and read functions :) In the depth My question was why after calling poll(I call it with 0 time delay) the queued function shows only one message we have inside of queue but actually there are many(inside of some internal buffers). I think poll function really poll only one message for each message type per one call, does not it? Using of gii like this: poll n=queued while(n--) read is bad in case of i have some internal buffers and some other cases. Actually I have to do following code to have all last messages n=0; do { while(n--) read; poll() } while (n=queued); It seems a strange for me behavior like that I expected that after Poll funk Queued will report all messages from internal buffers. Best regards, Dmitry Semenov -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Thursday, October 21, 1999 18:02 To: [EMAIL PROTECTED] Subject: Re: GII event system Hi ! 1. Why GII gii_event.pbutton does not have cursor coordinate information Because the buttons and the pointer position are not related in any way theoretically. Using the mapper filters, you can push "mouse buttons" on the keyboard and vice versa ... in case of GII buffering and sending data which have absolute cursor position (x target and may be future fb target with hardware cursor). ? I don't get you here. What has absoluet cursor position to do with buttons ? 2. Why GII does not use button data in case of sending pmove event? Same reason, see above. 3. I found some strange behavior inside of GII. -I poll GII one time -I read all events queued inside GII in my internal buffer with keeping only one pmove message inside of my buffer -I read one message from my buffer. -I move my cursor in case of pmove data -I call ggUSleep(10); -I see funny effect on the screen: my cursor making always is to late :) It looks like GII buffer can not give me back all messages by one polling. if I do poll and read queued messages like this: while(Poll()); instead of one polling where Poll is something like this [... snip ...] I've found no problem with my cursor. Hmm - I get you right, that gii events are kept queued inside gii when you try to read them - right ? Well, there is a possible simple explanation: ggiPoll unblocks _as_soon_as_ one of the associated FDs gets readable. Now, if the Mouse e.g. first sends a Pointer-update-packet or similar, this gets read into LibGGI immediately during the poll. The poll then unblocks, as data is available. At that point, there is only the first sent event from the mouse available. The mouse keeps sending data, but the LibGII poll routine has already terminated, as it terminates as soon as the first event gets readable. For such situations, where this behaviour is undesireable, as there are long delays between frames, it might make sense to use something like while(ggiPoll()) do_the_evenht_reading(); eventually_wait_a_short_grace_time(); } This allows for "slow" devices that do not instantaneously deliver all data. What mouse do you have ? we might want to check the driver, if it does the expected thing, which is to loop in its poll handler as long as data is incoming. CU, Andy -- Andreas Beck | Email : [EMAIL PROTECTED]
Re: GII event system
Hi ! 1. Mouse is a human input device, as well as others pointing device. Practically buttons are related to mouse position and usual human expects reasonable button action right in place where he has clicked it. Yes. This however does not mean, that the driver producing the "clicks" has to know anything about the driver producing the moves. This is why the moves and clicks are separate. Please note, that it is possible to mix relative and absolute pointer events. A simple example of that would be keyboard emulated mouse (which only makes sense as relative events) on a absolute-mouse target like X. What have we do with GII. Something like that collecting: pmove1 abs pbutton pmove2 abs will do (pmove1.x +pmove2.x)/2 and the same for y. ??? What ? I'll sketch how a LibGGI mouse handling routine for a system that expects to work with absolute coordinates is intended to look like: { static int mousex,mousey; ... ggiEventPoll(vis, emKey|emPointer, NULL); events = ggiEventsQueued(vis, emKey|emPointer); while (events--) { ggiEventRead(vis, event, emKey|emPointer); switch(event.any.type) { case evPtrButtonPress: switch(event.pbutton.button) { case GII_PBUTTON_FIRST: do_something_as_appropriate(mousex,mousey); break; case GII_PBUTTON_SECOND: ... } break; case evPtrButtonRelease: ... if needed ... break; case evPtrAbsolute: mousex = event.pmove.x; mousey = event.pmove.y; break; case evPtrRelative: mousex += event.pmove.x; mousey += event.pmove.y; break; } /* Constrain mouse in any case */ if (mousex 0) mousex = 0; if (mousey 0) mousey = 0; if (mousex xmax) mousex = xmax; if (mousey ymax) mousey = ymax; } /* while */ } As you can see, this nicely symmetriyes the cases of abs and rel events. Basically the same can be done for apps that expect relative events, though those might get trouble on absolute input data when trying to "keep turning left" or similar. Was it good? It is no good, at least because gii client software is not right place to do it. To do what ? (pmove1.x +pmove2.x)/2 ? There is no reasonable place to do such a calculation at all. To make sense at all, you would have to make a weighted mean based on the time between the individual event's timestamps. There is no assumption of something like a linear motion between points between move events, and for sure no assumption, that the click happens in the middle of that. The expected behaviour is, that the above used mousex,mousey variables express the correct position of the pointer, when a click comes in. If the mouse was moved between the last move and the click, the driver is expected to send another move and then the click to correctly position the pointer before transmitting the click. Why do I need to keep every pmove message until get pbutton and pmove again? That is not pretty at least. You don't. See above. In case that delivers incorrect results, we have a bug in a driver or backend and need to fix the driver or flame the backend authors. I understand that it is my task to determinate correct click place in case of relative move messages and I do. But I really hope I will be able to avoid mouse cursor software emulation(what I have done because of no choice) and to forget about relative messages for pointing device like mouse in the future when GGI will take care about hardware cursor. GGI will never take away the information you get from the input device. While we may provide a method to place a hardware sprite on the display, thus allowing to easily make up a mouse pointer, this will not influence the pointer data sent from the input device. I repeat ones more I am discussing only about the case when cursor generation is not my task. I still do not get what cursor generation has to do with input handling. There are some applications that would be pretty unhappy, if we converted all input to absolute pointer events. Guess why the X target has the relmouse mode ... In the depth My question was why after calling poll(I call it with 0 time delay) the queued function shows only one message we have inside of queue but actually there are many (inside of some internal buffers). If that is the case, this is a bug and should be fixed. I think poll function really poll only one message for each message type per one call, does not it? No. It should check and queue all attached inputs, and all inputs should read their sources until they are drained. It seems a strange for me behavior like that I expected that after Poll funk Queued will report all messages from internal buffers. Yes. This is the intended behaviour. However it could well be, that it is not correctly implemented in all targets. If you could send some code that clearly shows the problem together with the
Re: GII event system
Andreas Beck wrote: In the depth My question was why after calling poll(I call it with 0 time delay) the queued function shows only one message we have inside of queue but actually there are many (inside of some internal buffers). If that is the case, this is a bug and should be fixed. I think poll function really poll only one message for each message type per one call, does not it? No. It should check and queue all attached inputs, and all inputs should read their sources until they are drained. Well, this is only a problem for broken or really strange apps, but I think we should still provide a way around it: Let gq be the number of events queued in LibGII and kq be the number of events queued in the kernel. Initial state: gq = 0, kq = 3 giiEventPoll() is called == fetches all events == gq = 3; kq = 0; giiEventRead() is called, but only twice == gq = 1; kq = 0; Now the user moves the mouse arround == gq = 1; kq = 5; giiEventPoll() is called == as gq 0 no events are fetched from kq into gq. This is 100% correct due to performance reasons, BUT: When giiEventsQueued() is called and returns the number of events in the queue you get 1 allthough there are more events that could be read. My suggestion is that we add a new function int giiQueuedAfterPoll(struct gii_input *inp, gii_event_mask mask); which will first poll all relevant input sources, regardless of the number of events queued, and then return the number of events available. When I think of it we should definitely add this function, because it will allow the following common code: struct timeval tv = { 0, 0}; if (giiEventPoll(inp, mask, tv)) { n = giiEventsQueued(inp, mask); while (n--) { giiEventRead(inp, ev, mask); process_event(%ev); } } to be replaced with: n = giiQueuedAfterPoll(inp, mask); while (n--) { giiEventRead(inp, ev, mask); process_event(%ev); } Unless there are any objections or suggestions for a better name I'll add this function to LibGII (and it's companion in LibGGI). //Marcus -- ---+ Marcus Sundberg| http://www.stacken.kth.se/~mackan/ Royal Institute of Technology | Phone: +46 707 295404 Stockholm, Sweden | E-Mail: [EMAIL PROTECTED]
RE: GII event system
Hi Ok, 1. Anyway that is no so big problem if you do not want to keep space data together with buttons. As I got from you message you can guaranty last pmove message(s) contains right data for the determination of pointer position in the time of clicking. It's more than enough. By the way my code is looks like the same of yours except I avoid of calling 3rd party libraries directly and I use own wrappers. My experience showed me that code for really good system has to be not depended from any other library(thats funny when I see MFC programmers who made software(and own brain) absolutely mot portable). I make semi-embedded software like navigational systems, marine simulators. Ask me how many libraries graphics libraries and input system I changed for the last 10 years? A lot of. Know I can just make one more wrapper over existing libraries and keep my other code just untouchable. Absent of space data and click data made me a little confused because GGI is the first library I have seen making this dividing :) 2. Event generation has not so many to do with cursor generation. But If GGI library do not provide cursor monitoring and generation of it the GGI users have to do this job manually. IMHO it will be nice for many users of really nice GGI, if GGI will work together with GII to provide mouse cursor monitoring when GGI will get hardware cursor access. 3. Marcus already gave some explanation for the Poll. Thanks. May be letter it will good to show my code as one more gui development system using GGI. Best regards, Dmitry -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Friday, October 22, 1999 3:05 AM To: [EMAIL PROTECTED] Subject: Re: GII event system Hi ! 1. Mouse is a human input device, as well as others pointing device. Practically buttons are related to mouse position and usual human expects reasonable button action right in place where he has clicked it. Yes. This however does not mean, that the driver producing the "clicks" has to know anything about the driver producing the moves. This is why the moves and clicks are separate. Please note, that it is possible to mix relative and absolute pointer events. A simple example of that would be keyboard emulated mouse (which only makes sense as relative events) on a absolute-mouse target like X. What have we do with GII. Something like that collecting: pmove1 abs pbutton pmove2 abs will do (pmove1.x +pmove2.x)/2 and the same for y. ??? What ? I'll sketch how a LibGGI mouse handling routine for a system that expects to work with absolute coordinates is intended to look like: { static int mousex,mousey; ... ggiEventPoll(vis, emKey|emPointer, NULL); events = ggiEventsQueued(vis, emKey|emPointer); while (events--) { ggiEventRead(vis, event, emKey|emPointer); switch(event.any.type) { case evPtrButtonPress: switch(event.pbutton.button) { case GII_PBUTTON_FIRST: do_something_as_appropriate(mousex,mousey); break; case GII_PBUTTON_SECOND: ... } break; case evPtrButtonRelease: ... if needed ... break; case evPtrAbsolute: mousex = event.pmove.x; mousey = event.pmove.y; break; case evPtrRelative: mousex += event.pmove.x; mousey += event.pmove.y; break; } /* Constrain mouse in any case */ if (mousex 0) mousex = 0; if (mousey 0) mousey = 0; if (mousex xmax) mousex = xmax; if (mousey ymax) mousey = ymax; } /* while */ } As you can see, this nicely symmetriyes the cases of abs and rel events. Basically the same can be done for apps that expect relative events, though those might get trouble on absolute input data when trying to "keep turning left" or similar. Was it good? It is no good, at least because gii client software is not right place to do it. To do what ? (pmove1.x +pmove2.x)/2 ? There is no reasonable place to do such a calculation at all. To make sense at all, you would have to make a weighted mean based on the time between the individual event's timestamps. There is no assumption of something like a linear motion between points between move events, and for sure no assumption, that the click happens in the middle of that. The expected behaviour is, that the above used mousex,mousey variables express the correct position of the pointer, when a click comes in. If the mouse was moved between the last move and the click, the driver is expected to send another move and then the click to correctly position the pointer before transmitting the click. Why do I need to keep every pmove message until get pbutton and pmove again? That is not pretty at least. You don't. See above. In case that delivers incorrect results, we have a bug in a driver or backend and need to fix the driver or flame the backend authors. I understand that it is my task to determinate
RE: GII event system
Dear Marcus Well, this is only a problem for broken or really strange apps, but I think we should still provide a way around it: This is of semantic problem. IMHO When I call something like Poll at first and GetQueued I expect (very deep inside of my mind) to get all events "already" buffered by an input library. As I told it was not a problem. It seemed strange to me behavior like that because it is different from expected by me. Of course software uses only GII buffering will never understand this problem. But Any software uses own buffering immediately get it. You can ask me why do I need to use own buffer? Let se some my explanation provided to Andreas under topic 1. Thanks Dmitry -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]On Behalf Of Marcus Sundberg Sent: Friday, October 22, 1999 8:19 AM To: [EMAIL PROTECTED] Subject: Re: GII event system Andreas Beck wrote: In the depth My question was why after calling poll(I call it with 0 time delay) the queued function shows only one message we have inside of queue but actually there are many (inside of some internal buffers). If that is the case, this is a bug and should be fixed. I think poll function really poll only one message for each message type per one call, does not it? No. It should check and queue all attached inputs, and all inputs should read their sources until they are drained. Well, this is only a problem for broken or really strange apps, but I think we should still provide a way around it: Let gq be the number of events queued in LibGII and kq be the number of events queued in the kernel. Initial state: gq = 0, kq = 3 giiEventPoll() is called == fetches all events == gq = 3; kq = 0; giiEventRead() is called, but only twice == gq = 1; kq = 0; Now the user moves the mouse arround == gq = 1; kq = 5; giiEventPoll() is called == as gq 0 no events are fetched from kq into gq. This is 100% correct due to performance reasons, BUT: When giiEventsQueued() is called and returns the number of events in the queue you get 1 allthough there are more events that could be read. My suggestion is that we add a new function int giiQueuedAfterPoll(struct gii_input *inp, gii_event_mask mask); which will first poll all relevant input sources, regardless of the number of events queued, and then return the number of events available. When I think of it we should definitely add this function, because it will allow the following common code: struct timeval tv = { 0, 0}; if (giiEventPoll(inp, mask, tv)) { n = giiEventsQueued(inp, mask); while (n--) { giiEventRead(inp, ev, mask); process_event(%ev); } } to be replaced with: n = giiQueuedAfterPoll(inp, mask); while (n--) { giiEventRead(inp, ev, mask); process_event(%ev); } Unless there are any objections or suggestions for a better name I'll add this function to LibGII (and it's companion in LibGGI). //Marcus -- ---+ Marcus Sundberg| http://www.stacken.kth.se/~mackan/ Royal Institute of Technology | Phone: +46 707 295404 Stockholm, Sweden | E-Mail: [EMAIL PROTECTED]