Simon, Raphael, All...

I had the opportunity to spend three or four hours
yesterday afternoon/evening (GMT -5.00) seeking ways
to rescue Marching Ants (#10498).

I can confidently report that a call such as:

return_val = gdk_pointer_grab (gdisp->canvas->window, FALSE,
             GDK_BUTTON1_MOTION_MASK |
             NULL, NULL, bevent->time);

does not behave identically for core events (Defined in the
original X11 protocol) and XInput Extension events. This is
true when GTK+-1.2.8 has been built with the --xinput=xfree
option. While the GDK event request list is honored for core
X11 protocol events, the XInput events are subject to
special handling. The culprit,
gdk_input_common_find_events(), while nominally in charge of
just mapping the the GDK event request list into appropriate
XInput device classes [gtk+-1.2.8/gdk/gdkinputcommon.h], it
in fact asserts an internal policy of linking symmetric
events.  That is, this code virtually adds
GDK_BUTTON_PRESS_MASK when a client requests only
GDK_BUTTON_RELEASE_MASK -- and vice-versa.

The comment is unhelpful:

  /* We have to track press and release events in pairs to keep
     track of button state correctly and implement grabbing for
     the gxi support */
      DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
      if (class != 0)
   classes[i++] = class;

[gdk_input_common_find_event() gdkinputcommon.h Line 322 ff]

It is not clear to me why "button state" matters to GDK or
why GTK+-1.2.8/GDK requires events to be linked in this
fashion -- for XInput Extension devices only.

To the contrary, Gimp' family of selection tools require the
alternate circumstance: that during the grab, button press
events cannot be permitted to arrive, else the grand Gimp
event dispatcher, gdisplay_canvas_events()
[disp_callbacks.c], would divert Gimp process flow into a
(likely) menu dispatch. Since many menu implementations are
"tool-like", this can lead to the unloading of the current
selection tool before it has had opportunity to put its
persistent state in order -- thaw the undo stack, for
example. This is especially true for the "Trojan Horse"
tool, edit-select, which, through invitation by some other
select tool (invoking init_edit_selection()), temporarily
substitutes its predecessor's tool methods for its
own. Should this tool become unloaded because of a
menu-related button press, the predecessor's finalize
methods are not called and the tool itself does not have
full opportunity to clean up.

What to do?

Certainly, bug reports to GTK are in order: GTK "promises"
to abstract the pointer so that the application writer does
not have to do anything special with core and extension type
events. Grab semantics should be uniform. Now that I am
confident of the chain of causuality, I can handle that.

In light of an (is it coming? Really?) 1.2 Release
The question I have for the group is:

1) Document, warn, but otherwise ignore the problem.
   It affects users with a certain type of tablet hardware
   and only when that hardware is being used as an explicit
   XInput device. Wait for a GDK fix to remove its hidden policy?

2) Make a Gimp level hack in the much-abused event loop to
   filter button presses that originate from devices when
   a grab is in effect. (not pretty -- except for possibly
   being pretty lame)?

3) Re-engineer select tool code to be more robust in button
   press events (much work here)?

Which of these is the best line of action? Do you have other

If no one objects, I would like to elevate #10498 from 'critical'
to 'grave.' Through a chain of causuality originating with edit-select
not being able to perform a thaw, eventually (sometimes) there is
a fatal crash in undo. Not sure why, but grave bugs are the ones
that crash Gimp - at least sometimes.

Thank you to Simon and Raphael for thoughts, observations, snippets
of test code. As an aside, I think Simon is correct in observing
that this bug is also related to Bug #6901, "Can not continually move a
floating selection with a pressure sensitive pointer."?

Be good, be well


Reply via email to