After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 380281 - Enabling extension events breaks motion-notify hint events
Enabling extension events breaks motion-notify hint events
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: Other
2.10.x
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2006-11-28 20:56 UTC by Tommi Komulainen
Modified: 2007-03-01 14:15 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gdk_event_request_motions() patch (7.50 KB, patch)
2007-02-06 15:04 UTC, Tim Janik
none Details | Review

Description Tommi Komulainen 2006-11-28 20:56:06 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.
Comment 1 Tim Janik 2007-01-23 14:42:31 UTC
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.
Comment 2 Tommi Komulainen 2007-01-24 09:35:00 UTC
(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.
Comment 3 Tim Janik 2007-01-24 10:05:09 UTC
(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.
Comment 4 Tim Janik 2007-01-30 14:56:06 UTC
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).
Comment 5 Tim Janik 2007-02-06 15:04:04 UTC
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.