GNOME Bugzilla – Bug 380281
Enabling extension events breaks motion-notify hint events
Last modified: 2007-03-01 14:15:37 UTC
If you enable extension events on widgets, the handling of motion-notify hint events gets broken in some widgets, you get only one motion-notify event as the hint is not handled properly. The basic pattern is something like if (event->is_hint) gdk_window_get_pointer (event->window, NULL, NULL, NULL); With core events one must call XQueryPointer or XGetMotionEvents whereas with XInput enabled one must call XQueryDeviceState or XGetDeviceMotionEvents. gdk_window_get_pointer only calls XQueryPointer. One way to fix this would be to replace above with if (event->is_hint) gdk_device_get_state (event->device, event->window, NULL, NULL); which would do the right thing for core events as well.
since this change is in place, only to request new motion hint events, we might as well add: void gdk_event_request_motions (GdkEvent *event) { if (event->type == MOTION && event->motion.is_hint) gdk_device_get_state (event->device, event->window, NULL, NULL); } this might make sense special casing for backends different from X11 even. in any case, the user code is simplified that way (stripping the if (event->motion.is_hint) check and extra args) and says what it's meant to do.
(In reply to comment #1) Yes, that probably makes sense. I'm a bit fuzzy on the details, but there may be situations where you'd want to get the current x/y coordinates instead of the ones in the GdkEvent, but with gdk_device_get_state() that's fairly cumbersome. It might be worth considering including a way to get the coordinates, no strong feelings though.
(In reply to comment #2) > (In reply to comment #1) > > Yes, that probably makes sense. > > I'm a bit fuzzy on the details, but there may be situations where you'd want to > get the current x/y coordinates instead of the ones in the GdkEvent, but with > gdk_device_get_state() that's fairly cumbersome. It might be worth considering > including a way to get the coordinates, no strong feelings though. usually, the x/y coords returned from get_pointer during motin hint events are bogus anyways. consider a delayed client which gets sent (press, motion-hint, release) in a bunch before it's able to handle anything. using event->x/y from motion hint will correctly/drag/draw/select/etc. according to the user action. using round-trip get_pointer() coords instead will operate on the "future" coordinates that the pointer moved to *after* release. that's the basic reasoning for why it's almost always bad to use get_pointer() coords instead of event->x/y. the one other typical case is an application like gimp, when drawing you actually want to get+process all of the device motion history upon receiving a motion (hint) event. however that requires additional gdk_device_* functions anyway (and doesn't have the "bogus future coords" problem). so gdk_event_request_motions(event) should stay that way i think, and if it was changed to return coords, those should be event->x/y, not get_pointer results.
looking into a proper patch for this, it turns out that: - in most places where gtk uses gdk_window_get_pointer due to an is_hint event, it's got a GdkEventMotion* argument, so: gdk_event_request_motions (GdkEventMotion *event); might be a better signature. - using event->x/y instead of gdk_window_get_pointer (mywindow, &x, &y, 0) turns out to be tricky, because often mywindow != event->window, which means that event->x/y need to be translated to be mywindow relative. in some cases that's easy, but doing this generically would require a server round trip via XTranslateCoordinates(3). so i think we're best of with writing new code as: motion_event_handler (GdkEventMotion *event) { if (event->window == mywindow) { gdk_event_request_motions (event); do_stuff (mywindow, event->x, event->y); } } and only adapt old code if that is reasonably easy (i.e without using server side coordination translation).
Created attachment 82022 [details] [review] gdk_event_request_motions() patch this is the gdk_event_request_motions() patch as it went into SVN. files using gdk_window_get_pointer() in response to motion hints that were not converted are: gtkclist.c, gtklist.c, gtktext.c, gtklabel.c, gtknotebook.c, gtkrange.c, gtkwindow-decorate.c.