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 56070 - Can't click button after setting it sensitive.
Can't click button after setting it sensitive.
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: Other
2.12.x
Other Linux
: High major
: future
Assigned To: Cody Russell
gtk-bugs
: 125071 157932 169539 169570 169631 172004 314422 316125 316994 317937 319791 327408 327463 329391 333816 344835 351600 361214 371006 378468 389640 406543 419147 440433 446579 489584 504963 508082 546434 547379 557202 597143 (view as bug list)
Depends on:
Blocks: 52047 328710
 
 
Reported: 2001-06-11 18:43 UTC by Manuel Clos
Modified: 2010-06-16 00:44 UTC
See Also:
GNOME target: 2.24.x
GNOME version: ---


Attachments
Example showing this bug (728 bytes, text/plain)
2001-06-11 18:44 UTC, Manuel Clos
  Details
Another, perhaps more illustrative test case. (660 bytes, text/plain)
2005-01-19 00:28 UTC, Philip Langdale
  Details
Sample program hacking arround the problem in a cheap manner (3.02 KB, text/plain)
2005-08-27 20:03 UTC, Mathias Hasselmann (IRC: tbf)
  Details
gtk-sensitivity.patch (8.17 KB, patch)
2006-05-26 14:28 UTC, Ed Catmur
none Details | Review
gtk-sensitivity.patch (8.22 KB, patch)
2006-11-30 10:04 UTC, Ed Catmur
reviewed Details | Review
gtk-sensitivity.patch (11.75 KB, patch)
2007-01-02 21:29 UTC, Ed Catmur
none Details | Review
new patch (21.44 KB, patch)
2007-01-03 04:38 UTC, Matthias Clasen
none Details | Review
updated patch (12.50 KB, patch)
2007-01-06 23:58 UTC, Ed Catmur
none Details | Review
fixed patch (12.50 KB, patch)
2007-01-07 00:16 UTC, Ed Catmur
none Details | Review
gtk-sensitivity.patch (12.45 KB, patch)
2007-01-07 08:44 UTC, Ed Catmur
none Details | Review
gtk-sensitivity.patch (14.69 KB, patch)
2007-01-22 03:41 UTC, Ed Catmur
reviewed Details | Review
gtk-sensitivity.patch (15.14 KB, patch)
2007-02-05 13:10 UTC, Ed Catmur
none Details | Review
gtk-sensitivity.patch (15.14 KB, patch)
2007-02-11 01:23 UTC, Ed Catmur
none Details | Review
gtk-sensitivity.patch (15.93 KB, patch)
2007-02-12 19:12 UTC, Ed Catmur
none Details | Review
program to help test this (1.03 KB, text/plain)
2007-06-05 19:38 UTC, Johan (not receiving bugmail) Dahlin
  Details
Updated patch that applies against trunk (15.13 KB, patch)
2007-06-14 19:50 UTC, Cody Russell
none Details | Review
First stab at new test program (5.77 KB, text/x-csrc)
2007-06-18 21:51 UTC, Cody Russell
  Details
Updated test (6.23 KB, text/plain)
2007-06-18 22:19 UTC, Cody Russell
  Details
Updated to work around g_timeout_add_seconds() bug (6.23 KB, text/plain)
2007-06-18 23:23 UTC, Cody Russell
  Details
updated tests (8.24 KB, text/plain)
2007-06-19 04:59 UTC, Matthias Clasen
  Details
Update of mclasen's patch (8.24 KB, text/plain)
2007-06-19 16:22 UTC, Cody Russell
  Details
another round of patch (14.60 KB, patch)
2007-06-22 05:28 UTC, Matthias Clasen
none Details | Review
Updated patch (14.33 KB, patch)
2007-11-09 19:32 UTC, Cody Russell
none Details | Review
gtk-sensitivity.patch (16.15 KB, patch)
2008-04-25 22:49 UTC, Ed Catmur
none Details | Review
Add unit test (27.85 KB, patch)
2008-07-15 04:16 UTC, Cody Russell
none Details | Review
Check button sensitivity before calling gtk_button_leave() (28.14 KB, patch)
2008-07-15 06:11 UTC, Cody Russell
none Details | Review
Add establish-gtk-grab unit test. (29.61 KB, patch)
2008-07-15 21:07 UTC, Cody Russell
none Details | Review
Fix state-changing crossing events (17.68 KB, patch)
2008-07-17 23:05 UTC, Cody Russell
none Details | Review
Didn't have the unit test in the last patch (31.73 KB, patch)
2008-07-17 23:20 UTC, Cody Russell
none Details | Review
Updates for grab-shadowing (19.02 KB, patch)
2008-07-22 00:38 UTC, Cody Russell
none Details | Review
Unit test was missing in last patch (32.45 KB, patch)
2008-07-22 01:22 UTC, Cody Russell
none Details | Review
Add unit test for removing gtk grab (43.00 KB, patch)
2008-07-24 13:44 UTC, Cody Russell
none Details | Review
Updated patch, added unit tests for moving from and to grab shadowed widgets (34.21 KB, patch)
2008-07-31 05:27 UTC, Cody Russell
none Details | Review
Fix typo in unit test (34.21 KB, patch)
2008-07-31 14:29 UTC, Cody Russell
committed Details | Review

Description Manuel Clos 2001-06-11 18:43:53 UTC
I have many times reported that if you got the mouse just where the button
is going to appear (gdm, nautilus-installer, ...) you won't be able to
click the button, it is confusing and anoying.

Here is a simple example showing it. It raises a big window with a button
on it (set_sensitive = false). After 2 seconds, a timeout makes the button
sensitive. If you have the mouse over the button before the timeout sets it
sensitive, you WON'T be able to click the button, it will refuse to do so.
Leaving the button and entering it again makes it work.

I will love to fix it myself, but I don't have the skills.

As perhaps it is not a simple fix, I'm sending the bug here.

Try it out. Don't know if this applies to other widgets as well.

gcc button.c `gtk-config --cflags gtk` `gtk-config --libs gtk` -o button-bug

gcc button.c `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` -o
button-bug

Thanks.
Comment 1 Manuel Clos 2001-06-11 18:44:40 UTC
Created attachment 639 [details]
Example showing this bug
Comment 2 Owen Taylor 2001-06-23 15:44:55 UTC
Fixing this would require GTK+ to keep track of where the
mouse cursor is at all times, and synthesize enter events
when a widget becomes sensitive. Not easy at all. Future
plans include mostly getting rid of subwindows in GTK+,
which would make this easier.
Comment 3 Manuel Clos 2003-08-02 15:08:33 UTC
this is no longer true.

Tested with gtk+ 2.2.2.

Closing the bug.
Comment 4 Owen Taylor 2003-08-02 16:15:49 UTC
I know no reason why this bug should be now fixed.
Comment 5 Manuel Clos 2003-08-02 17:39:52 UTC
Hi Owen, I tried executing the button.c testcase again, and I can't
reproduce the bug.

There is no WORKSFORME resolution so I marked it fixed.

The testcase fails, so why do you want the bug open?
Comment 6 Owen Taylor 2003-08-02 18:03:46 UTC
The button still doesn't prelight properly in your test
case ... and the generic GTK+ problem

 "If a widget is under the cursor when the widget becomes
  sensitive, it won't get an ENTER event"

is still there.
Comment 7 Craig Shelley 2004-08-29 07:43:27 UTC
Looking at the code, it appears that it is not simple to fix. It also appears
that the root cause of this problem is the fact the underlying widget does not
see the enter event while it is insensitive.

Just wondering if it is possible to add an internal in_widget boolean property
so that the widget can keep track of the mouse position.
If the widget is then set sensitive, ENTER events could be generated if
in_widget is true.

I don't fully understand the code, so may talking rubbish here, it's just an idea.
Comment 8 Federico Mena Quintero 2004-12-14 23:59:03 UTC
Now that bug #82128 is fixed and we have a gtk_button_state_changed, I think
fixing this should be easy enough.  Just see if button->in_button is true at the
end of that function, and change the state to active if appropriate.
Comment 9 Owen Taylor 2004-12-15 02:49:58 UTC
Won't work because widgets don't receive events when insensitive.
Comment 10 Matthias Clasen 2004-12-23 05:14:28 UTC
*** Bug 125071 has been marked as a duplicate of this bug. ***
Comment 11 Philip Langdale 2005-01-19 00:28:31 UTC
Created attachment 36221 [details]
Another, perhaps more illustrative test case.

Well, this one's causing us lots of grief.

This test case illustrates our particular case where the net result of a code
path is synchronously toggling the sensitivity of a clicked button to false and
back again. Until the mouse leaves and re-enters, it will act insensitive
(although keyboard activation works fine, as you'd expect).
Comment 12 Martin Pool 2005-01-25 21:19:22 UTC
Could the button perhaps check the pointer position at the moment it becomes
sensitive, or at least queue up such a check for the next event loop pass?
Comment 13 Owen Taylor 2005-01-25 23:28:58 UTC
Huge performance hit ... querying pointer position is a round-trip to
the server.
Comment 14 Martin Pool 2005-01-26 00:10:56 UTC
Right, so that means we probably shouldn't do it from
gtk_widget_set_sensitive(); we wouldn't want to incur dozens of roundtrips if
the program sensitized dozens of controls.

However it seems like we could stand to incur one roundtrip per event loop for
the particular case where the sensitivity of a control has changed. 
set_sensitive should set a flag saying to do this.  

To me, having the GUI behave correctly and not ignore user input is important
enough to justify the expense.  (I guess as an optimization you might check for
events, and see if any of them have told you the current mouse position, and if
you got it then you wouldn't need to ask.)
Comment 15 Noah Levitt 2005-03-08 23:22:23 UTC
*** Bug 169631 has been marked as a duplicate of this bug. ***
Comment 16 Matthias Clasen 2005-03-09 16:11:28 UTC
*** Bug 169570 has been marked as a duplicate of this bug. ***
Comment 17 Felix Kater 2005-03-09 22:09:44 UTC
I am the author of the dup 169570:

I've mentioned that a click to a button in this case does not change *nothing*
but shifts at least the focus (dotted square) to it.

So, even if the ENTER event is missing and the button is not prelighted -- the
button seems to get *some* event here. (I do not know the internals here.)

Couldn't we use this as the trigger to treat this button as one which was
entered and force it to behave normal?
Comment 18 Mathias Hasselmann (IRC: tbf) 2005-08-27 01:23:30 UTC
Problem is this:

static void
gtk_button_state_changed (GtkWidget    *widget,
                          GtkStateType  previous_state)
{
  GtkButton *button = GTK_BUTTON (widget);

  if (!GTK_WIDGET_IS_SENSITIVE (widget))
    {
      button->in_button = FALSE;
      gtk_real_button_released (button);
    }
}

Have this feeling, this makes sense in some situations, but it gives you serious
trouble, when you dynamically toggle sensitivity of buttons in dependency for
instance on some changing (icon view) selection.
Comment 19 Mathias Hasselmann (IRC: tbf) 2005-08-27 20:03:32 UTC
Created attachment 51436 [details]
Sample program hacking arround the problem in a cheap manner

This sample program is based on comment #2. Works as long as nobody blocks the
motion-notify-event (guess that's where Owen's concerns came from). Well, but
this problem also should be solvable, by placing a hook into GTK+'s event loop.
Comment 20 Matthias Clasen 2005-09-15 13:09:01 UTC
*** Bug 157932 has been marked as a duplicate of this bug. ***
Comment 21 Gabriel Schulhof 2005-10-15 22:22:29 UTC
Well, FWIW, this bug is still not fixed in 2.6.8.
Comment 22 Billy Biggs 2005-10-25 21:23:05 UTC
*** Bug 319791 has been marked as a duplicate of this bug. ***
Comment 23 Alexander “weej” Jones 2005-10-26 09:27:26 UTC
Wow, this is an oldie. 2.8 here, still unfixed.

:(
Comment 24 Alexander “weej” Jones 2005-11-03 12:20:18 UTC
What is the problem with allowing insensitive widgets to receive events? If that
happens, surely the problem just goes away...
Comment 25 Christian Persch 2005-12-31 21:28:21 UTC
*** Bug 169539 has been marked as a duplicate of this bug. ***
Comment 26 Daniel Holbach 2006-01-01 10:19:07 UTC
*** Bug 317937 has been marked as a duplicate of this bug. ***
Comment 27 Owen Taylor 2006-03-08 02:15:37 UTC
*** Bug 333816 has been marked as a duplicate of this bug. ***
Comment 28 Vincent Untz 2006-03-25 14:38:01 UTC
*** Bug 329391 has been marked as a duplicate of this bug. ***
Comment 29 Johannes Buchner 2006-04-03 07:56:47 UTC
Though this might be a dumb question...

I understand, that polling the cursor position is considered non-performant. 

Trying to understand this one: 
The button is not highlighted because ...?
 ... there was no mouse-in event, right? 

And it is not clickable because ... ?
 .... no click-event was registered?

I can accept that the button isn't highlighted, but the click funktion should be available since this is a loss of functionality (although this bug is not dramatically) and it destroys the workflow and the nice look and feel of WMs. 
Comment 30 Alexander “weej” Jones 2006-04-03 11:44:17 UTC
I /really/ don't understand why we can't just set the highlighted state on insensitive buttons. This problem would go away, then.
Comment 31 danny.milo 2006-04-20 21:28:39 UTC
Setting highlighted state would suggest to the user that the insensitive button can be clicked / used, which would be wrong. Probably the GUI part of it could be special-cased though (when highlighted state is set, check insensitive before drawing?)
Comment 32 Alexander “weej” Jones 2006-04-20 22:06:10 UTC
I thought that was fairly obvious, but if not it would explain why we're still pondering over this!

A button in that is both HIGHLIGHTED and INSENSITIVE should be rendered without regards to the highlighted state. Solved!
Comment 33 Alexander “weej” Jones 2006-04-20 22:36:02 UTC
I think I might have cottoned the problem. Is it that a widget can only hold one exclusive state?

I think logic suggests that the "highlighted" flag should be independent of "insensitive". Would this be such a bitch to implement?
Comment 34 Ed Catmur 2006-05-26 14:28:07 UTC
Created attachment 66285 [details] [review]
gtk-sensitivity.patch

Patch, against 2.9.1.

At bug 316125, Tim Janik wrote:
> this is a symptom of the more general problem that gtk doesn't synthesize
> enter/leave events upon changing the sensitivity (or global grab) state of a
> widget the way X does when windows are covered/uncovered by other windows.

This patch creates a private flag PRIVATE_GTK_SYNTH_CROSSING (GTK_WIDGET_SYNTH_CROSSING) which tracks whether the pointer is in the control. When the sensitivity/global grab state changes it synthesises enter/leave events accordingly.

Detail:
* gtkprivate.h, gtktypebuiltins.c: define GTK_WIDGET_SYNTH_CROSSING
* gtkmain.c: gtk_main_do_event(): update GTK_WIDGET_SYNTH_CROSSING with enter/leave
* gtkwidget.{c,h}: _gtk_widget_synthesise_crossing_from_{grab_notify,state_changed}(): functions to call from grab-notify and state-changed to synthesise enter/leave events as appropriate. Common code in _gtk_widget_synthesise_crossing_event().
* gtkwidget.c, gtkbutton.c: call synthesis functions from grab-notify and state-changed. (gtkbutton.c needs its own callouts because a GtkButton is a NO_WINDOW control, but has its own GdkWindow. This means that the enter/leave events do not get synthesised (NO_WINDOW controls don't receive events) in gtkwidget.c. Any other control that handles its own GdkWindow outside of the GtkWidget system will need to copy the callouts in gtkbutton.c.)

This appears to work well, and I think it's correct. Of course, I haven't tested it all that much yet.

Changes to ABI:
* added private functions _gtk_widget_synthesise_crossing_from_*. No libversion change needed.

Changes to API:
* private flag, functions added. No-one other than widget implementors need to care.

Changes to behaviour:
* widgets can receive enter events immediately after turning sensitive. This is practically indistinguishable from the user moving pointer into widget immediately after turning sensitive. The only situation I can imagine this causing trouble is in workarounds to this very bug.
* widgets can receive leave events immediately after turning insensitive. I don't see this being a problem.
Comment 35 Ed Catmur 2006-05-26 14:42:00 UTC
Performance: client overhead is low, using one bit in GtkPrivateFlags. Synthesis tests are mostly cheap bitfield checks, with the heavy stuff (gtk_widget_is_ancestor) at the end of a short-circuit so it'll only kick in if a widget is made sensitive while a grab is in effect. 

Actual event synthesis involves two roundtrips: gdk_display_get_pointer (QueryPointer) and gdk_window_get_origin (TranslateCoordinates). I don't know how to improve this; perhaps some Xlib guru could help?
Comment 36 Markku Vire 2006-05-30 20:20:44 UTC
*** Bug 314422 has been marked as a duplicate of this bug. ***
Comment 37 Stef Walter 2006-06-14 02:36:01 UTC
*** Bug 344835 has been marked as a duplicate of this bug. ***
Comment 38 Stef Walter 2006-06-14 02:42:29 UTC
The patch on bug 344835 has a very simple patch which solves the common problem of:

 - mouse pointer is above button
 - button becomes insensitive
 - user keeps mouse pointer there
 - button becomes sensitive
 - user tries to click

This happens in places like:
 - Find Dialogs 
 - Debuggers
 - Other 'Next' or 'Find Next' Buttons

Comment 39 Ed Catmur 2006-06-14 02:56:52 UTC
It solves that situation, but it doesn't fix the underlying bug, and it breaks widget invariants. Care to comment on my patch? 
Comment 40 Matthias Clasen 2006-06-14 18:03:02 UTC
Thanks, I'll look at your patch sometime soon.

Would be really nice to get Owen's comment, too.
Comment 41 Alexey Rusakov 2006-06-15 06:40:38 UTC
I applied Ed's patch and Gtk+ in Sisyphus repository now ships with it. In these two weeks, everything's ok: the patch solves the issue and doesn't seem to break anything.
Comment 42 Stef Walter 2006-06-17 03:01:06 UTC
I'm running with the patch. Works nicely.
Comment 43 Johannes Schmid 2006-07-30 09:04:05 UTC
*** Bug 316994 has been marked as a duplicate of this bug. ***
Comment 44 Johannes Schmid 2006-07-30 09:06:32 UTC
Would be great if the patch could go in soon as this is very annoying in anjuta:

- You cannot press "Next" in the debugger toolbar (gets insensitive when the debugger is working)
- You cannot use the "Find" button twice

Regards,
Johannes
Comment 45 danny.milo 2006-08-04 09:31:58 UTC
For the record, I'm running the gtk-sensitivity patch for 5 weeks by now. Works fine.
Comment 46 Matthias Clasen 2006-08-05 20:09:36 UTC
*** Bug 327463 has been marked as a duplicate of this bug. ***
Comment 47 Alan Horkan 2006-09-01 21:06:47 UTC
*** Bug 327408 has been marked as a duplicate of this bug. ***
Comment 48 Bruno Boaventura 2006-10-14 04:17:55 UTC
*** Bug 351600 has been marked as a duplicate of this bug. ***
Comment 49 Bruno Boaventura 2006-10-14 04:19:13 UTC
*** Bug 361214 has been marked as a duplicate of this bug. ***
Comment 50 Bruno Boaventura 2006-10-14 04:25:34 UTC
*** Bug 172004 has been marked as a duplicate of this bug. ***
Comment 51 Colin Leroy 2006-10-14 07:32:25 UTC
good luck guys :)
Comment 52 André Klapper 2006-10-19 12:18:13 UTC
summarizing:
this bug report has 20 duplicates so far, plus it would make the life on the anjuta guys easier (comment 44). the patch has been tested by a few people (see comment 41 and comment 42). however, this could introduce new problems (comment 39).

matthias, any news here (comment 40)?
Comment 53 Ed Catmur 2006-10-20 06:52:13 UTC
(In reply to comment #52)
> summarizing:
> this bug report has 20 duplicates so far, plus it would make the life on the
> anjuta guys easier (comment 44). the patch has been tested by a few people (see
> comment 41 and comment 42). however, this could introduce new problems (comment
> 39).

No, comment 39 is about a different patch.  The patch on this bug is not known to introduce any new problems.
Comment 54 André Klapper 2006-10-24 23:03:58 UTC
ok, then we should get a review for that patch - matthias: *ping*?
Comment 55 Dodji Seketeli 2006-11-19 21:23:27 UTC
Hello,

This bug is really annoying for the nemiver debugger as well.
Matthias, please, could you tell us what you think about the last patch that seems to fix it ?

Cheers,
Dodji
Comment 56 Pascal Terjan 2006-11-21 22:04:55 UTC
This bug appears in several other apps in addition to the list from duplicates :

- in xsane when we finish scanning a document, we can't press the button again for the next one
- in gthumb when deleting an image with keyboard we can't press next to go the next image

And I'm sure I already faced that behaviour in other apps, so yes it's really annoying and it would be nice to handle this quickly now that there is patch :)
Comment 57 Elijah Newren 2006-11-25 01:20:35 UTC
*** Bug 378468 has been marked as a duplicate of this bug. ***
Comment 58 Ed Catmur 2006-11-30 10:04:55 UTC
Created attachment 77408 [details] [review]
gtk-sensitivity.patch

Fix a possible assert if a button doesn't have a window.

This patch is over 6 months old - any chance of a review?
Comment 59 Sam Morris 2006-12-19 22:04:03 UTC
Please could someone review the patch. The bug prevents the user from clicking the Step Over/Step Into/etc buttons in the Nemiver debugger. :)
Comment 60 Matthias Clasen 2006-12-26 05:05:55 UTC
*** Bug 316125 has been marked as a duplicate of this bug. ***
Comment 61 Matthias Clasen 2006-12-26 05:45:32 UTC
Some comments on the patch:

1) I think we generally write synthesize in GTK+, not synthesise

2) Regarding the 2 roundtrips to set x/y_root and x/y in the event,
   one idea would be to simply not fill these fields, and document
   that crossing events with send_event = 1 and crossing.detail == unknown
   may not have theese fields filled. 

3) I don't know what invariants we really guarantee for enter/leave
   events, but shouldn't these be generated in pairs ? I.e. when generating
   an enter event, the pointer logically comes from somewhere else.
   Do we need to generate a leave event there ?
Comment 62 Matthias Clasen 2006-12-27 00:36:59 UTC
*** Bug 389640 has been marked as a duplicate of this bug. ***
Comment 63 Ed Catmur 2007-01-02 17:46:55 UTC
(In reply to comment #61)
> Some comments on the patch:
> 
> 1) I think we generally write synthesize in GTK+, not synthesise
Foiled! Curses!

> 2) Regarding the 2 roundtrips to set x/y_root and x/y in the event,
>    one idea would be to simply not fill these fields, and document
>    that crossing events with send_event = 1 and crossing.detail == unknown
>    may not have theese fields filled. 
Yeah, that sounds like an option.  I'd prefer to create a new GdkNotifyType in that case, maybe GDK_NOTIFY_SYNTHESIZED.

> 3) I don't know what invariants we really guarantee for enter/leave
>    events, but shouldn't these be generated in pairs ? I.e. when generating
>    an enter event, the pointer logically comes from somewhere else.
>    Do we need to generate a leave event there ?
Actually, no.  When the pointer moves from a sensitive parent widget into an insensitive child widget, a leave_notify event is emitted on the parent but no corresponding enter_notify event is emitted.  So if the application is keeping track of which widget the pointer is above, when the pointer is above an insensitive widget it will report the same as when the pointer is outside the application's main window.
The invariant here is that keeping track of enter/leave notifies, the pointer is in at most one widget, which must be sensitive. This patch strengthens the invariant to: the pointer is in the widget it is above if and only if that widget is sensitive.

Right, I'll work on your comments.
Comment 64 Ed Catmur 2007-01-02 21:29:50 UTC
Created attachment 79225 [details] [review]
gtk-sensitivity.patch

Patch implementing changes suggested in comment 61.

Instead of a new GdkNotifyType, created a new GdkCrossingMode, GDK_CROSSING_SYNTHESIZED. Seemed more appropriate.
Comment 65 Matthias Clasen 2007-01-03 04:38:08 UTC
Some comments:

- I believe you are leaking the synthesized event.

- I don't think we need the mode argument, since all callers
  are passing GDK_CROSSING_SYNTHESIZED

- I think gdk_widget_synthesize_crossing_for_foo should be 
  public api, so that 3rd party no-window widgets can enjoy
  the same fix as GtkButton.

- When making those functions public, it would be nicer IMO
  to pull the GDK_WIDGET_SYNTH_CROSSING() check into the functions.


Here is an updated patch that addresses these points. 
Do you agree to make those functions public ?
Comment 66 Matthias Clasen 2007-01-03 04:38:49 UTC
Created attachment 79248 [details] [review]
new patch
Comment 67 Michail Crayson 2007-01-06 23:06:27 UTC
I'm wondering whether fixing this bug will also fix the following issue that I'm having on Windows XP using GTK+ 2.10.6:

1) Start up GIMP.
2) With the brush tool selected in the tool panel, click the button for
selecting a brush. This opens a dropdown panel.
3) Without moving the mouse, click again to close the panel.
4) The button is now not lit up and does not respond to mouse clicks.
5) Move the pointer off the button and back in again. Then it works again.

This situation is a bit different in that the button is never actually made insensitive, but I'm guessing the dropdown panel is a modal window? I'm seeing the same behaviour in my own application when opening a modal window in response to a mouse click and then closing it again shortly after.
Comment 68 Ed Catmur 2007-01-06 23:47:26 UTC
(In reply to comment #65)
> Some comments:
> 
> - I believe you are leaking the synthesized event.
Oops.

> - I don't think we need the mode argument, since all callers
>   are passing GDK_CROSSING_SYNTHESIZED
Yes.

> - I think gdk_widget_synthesize_crossing_for_foo should be 
>   public api, so that 3rd party no-window widgets can enjoy
>   the same fix as GtkButton.
Yes, that makes sense.  This allows gtk_widget_synthesize_crossing_event to be made static and simplified, as you have done.

> - When making those functions public, it would be nicer IMO
>   to pull the GDK_WIDGET_SYNTH_CROSSING() check into the functions.
Yes, if it's external API.

> Here is an updated patch that addresses these points. 
> Do you agree to make those functions public ?
Yes, good idea.
Comment 69 Ed Catmur 2007-01-06 23:55:33 UTC
(In reply to comment #66)
> Created an attachment (id=79248) [edit]
> new patch

Ah... Comments:

1. You've omitted the addition to gtk_private_flags_get_type() in gtk/gtktypebuiltins.c?

2. In gtk_widget_synthesize_crossing_event(), you're leaking two refs to window.

3. You've omitted the addition to gdk/gdkevents.h in gdk/gdkevents.h?

Other than that, great.
Comment 70 Ed Catmur 2007-01-06 23:57:12 UTC
re comment 67: the current patch handles grab notifies, so it could well fix that case.
Comment 71 Ed Catmur 2007-01-06 23:58:53 UTC
Created attachment 79585 [details] [review]
updated patch
Comment 72 Ed Catmur 2007-01-07 00:16:17 UTC
Created attachment 79586 [details] [review]
fixed patch

broken patch, sorry :(
Comment 73 Owen Taylor 2007-01-07 04:53:02 UTC
Hmm, in one sense, I like the patch a lot ... the approach of sending enters/leave is is much better than GtkButton querying the pointer when it's sensitivity is changed or something.

But I have some reservations as well:

 - Crossing events are not a widget thing (despite the current LEAVE_PENDING 
   flag), but rather a GdkWindow thing. If you try to track the enter/leave 
   state per widget, then you have problems with widgets with multiple windows.

 - I forsee problems from ignoring the detail field of the crossing event. The 
   detail field is important if you, for example, want to distinguish the 
   pointer being in a window or any descendent from the pointer being in 
   the window itself. Sending events with a detail of NOTIFY_UNKNOWN basically
   means that any such tracking is a lost cause.

 - I don't like the way, in your patch, that 
    gtk_widget_synthesize_crossing_from_grab_notify
    gtk_widget_synthesize_crossing_from_state_changed
   are made public and then GtkButton calls them. That seems to me like
   confusion over this is something maintained by the core widget system
   or by widgets. What we really want to do is make any tricky invariants
   handled by the core widget system, and remove hacks from the widgets.

   Really, if the generation of synthetic crossing events is handled properly,
   we should be able to remove the setting of button->in_button() from
   gtk_button_state_changed() and gtk_button_grab_notify().

 - Should GTK_LEAVE_PENDING be removed? The purpose of it overlaps entirely
   with this patch, though it only handles the LEAVE side, not the ENTER side.

Without working through all the details, the way I would have approached this
issue is to track two "pointer windows" for each toplevel. The real pointer
window is defined by the events delivered by X. (If crossing events aren't
selected for a window, then it can never be the real pointer window.) The effective pointer window is:

 - The root window, if the widget that owns the real pointer window is
   insenstive, or if there is a grab widget that is not an ancestor of
   the real pointer window's widget.

 - The real pointer window otherwise.

When the effective pointer window changes for a reason other than an
event delivered from the window system, that's when we synthesize crossing
events... we deliver all the crossing events that are defined by the
X protocol spec ... so this well generally include "VIRTUAL" enters and
leaves on the ancestor windows of the real pointer window. If you don't
sent those VIRTUAL events, then the accounting won't work right in complex
situations, where children are made insensitive, parents are made insensitive,
the pointer is moved, widgets are made sensitive again ... things like that.

I know that sounds like a lot more complex than what you have now ... probably
not more code, but maybe trickier code. And after all those patch 
iterations too! But we have to keep the events that get generated well
defined or it's basically impossible to know what to expect. And since
the existing GTK+ system (complexity layered on top of complexity inherited
from X) is complex, it's hard to make changes to it that are simple.


Comment 74 Ed Catmur 2007-01-07 08:44:16 UTC
Created attachment 79610 [details] [review]
gtk-sensitivity.patch

re comment 69: the refs to window aren't leaked, they're released by gdk_event_free(). I'm an idiot.
Comment 75 Matthias Clasen 2007-01-07 20:10:52 UTC
As usual, Owen has the best idea. The approach described in comment 73 is going to work much more reliable and correctly than anything based on widget flags.
Too bad it will take a bit of work to implement...
Comment 76 John 2007-01-08 19:12:28 UTC
Just wanted to note that not only debuggers are blessed with the effects of this
bug: Xsane: You cannot scan several pages without exiting/entering the scan
button (my wife _hates_ that, and now resorts to using Ctl-Enter). Sylpheed,
you cannot 'get' mail again without same.
Please?
Comment 77 Scott Horowitz 2007-01-08 21:04:36 UTC
This is ridiculously irritating, I have run up against this in my application as well.
Comment 78 Ed Catmur 2007-01-22 03:41:02 UTC
Created attachment 80856 [details] [review]
gtk-sensitivity.patch

Ugh.  I had written a point-by-point response to comment 73.  Here's some code instead; untested but it should show what I intend.
Comment 79 Matthias Clasen 2007-01-24 05:58:27 UTC
Impressive patch. It will certainly be fun to test this. 

It has quite a bit of overhead though, since you store the pointer window per-widget. Since your patch seems to satisfy the following conditions:

1) at most one widget at a time can have the HAS_POINTER flag set

2) you only ever look at the pointer window of a widget if it has HAS_POINTER set

it should be possible to take Owens approach of storing a global pointer window
per display instead. Right ?

One detail I wonder about is if it can happen in _gtk_widget_synthesize_crossing
that from != to but from_window == to_window (thinking of no-window widgets sharing the window with their parent), in which case

+  else if (from_window == to_window)
+    ;

may cause missed events. But maybe that case can never happen...
Comment 80 Federico Mena Quintero 2007-01-30 16:15:09 UTC
Note to self: this is https://bugzilla.novell.com/show_bug.cgi?id=239565

Looks like we all owe a beer to Ed :)
Comment 81 Ed Catmur 2007-02-05 13:10:29 UTC
Created attachment 81931 [details] [review]
gtk-sensitivity.patch

> it should be possible to take Owens approach of storing a global pointer window
> per display instead. Right ?
Per-screen, you mean?  This iteration stores the global pointer window in a qdata on the GdkScreen; there doesn't seem to be anywhere I can add a member to a struct, unfortunately.

> One detail I wonder about is if it can happen in
> _gtk_widget_synthesize_crossing
> that from != to but from_window == to_window (thinking of no-window widgets
> sharing the window with their parent), in which case
> 
> +  else if (from_window == to_window)
> +    ;
> 
> may cause missed events. But maybe that case can never happen...
No, it does happen fairly often e.g. in menus or scrollbars, where a no-window widget gets Gtk+ grab.  But it won't leak events, because the no-window widget isn't expecting enter/leave events anyway.
Comment 82 Ed Catmur 2007-02-11 01:23:01 UTC
Created attachment 82307 [details] [review]
gtk-sensitivity.patch

Fix a stupid typo.
Comment 83 Ed Catmur 2007-02-12 19:12:14 UTC
Created attachment 82412 [details] [review]
gtk-sensitivity.patch

Currently we get reentrancy in gtk_window_unset_transient_for() caused by grab removal changing selected item on menus.  The easiest way to fix this is to reorder the function.
Comment 84 Matthias Clasen 2007-03-19 05:44:36 UTC
*** Bug 419147 has been marked as a duplicate of this bug. ***
Comment 85 nicola 2007-03-24 02:45:56 UTC
What's the state of the bug? I think it is a really annoying one, a MAjor one!!!
Comment 86 Matthias Clasen 2007-03-24 02:58:23 UTC
It needs someone with the necessary time to sit down and test it thoroughly - it should produce essentially the sequence of events that are required by the X protocol specification.
Comment 87 Alexander “weej” Jones 2007-03-24 03:34:14 UTC
I don't understand why it has to be so unnecessarily complicated - why not just consider HIGHLIGHTED and SENSITIVE to be independent flags?
Comment 88 Stefan de Konink 2007-05-07 20:37:14 UTC
Can someone increase the priority on this bug. People... 2001... we need a fix :)
Comment 89 Alexander “weej” Jones 2007-05-07 20:54:29 UTC
Can somebody *please* comment on my suggestion in Comment #87?
Comment 90 Scott Horowitz 2007-05-08 00:40:38 UTC
For what it's worth, developers can work around this bug by simply hiding/showing the button after they make the button sensitive again. This will too fast for the user to see, and it will allow them to click the button without moving their mouse from the button.

I forget where I read about this workaround (kudos to whoever came up with it!), but I've been using it in my application without any problems.
Comment 91 Paul Ellender 2007-05-10 05:58:22 UTC
I agree with Stefan this should have a Higher priority. I'm rather new to the Linux desktop community and I noticed this during the install process... And now i encounter it during regular use, constantly having to move off a button and back on to click it... It is quite noticeable so much so that I spent time finding this bug posting. Which was not very easy to find. I think if this post was easier to locate you would have a LOT more people commenting on it :)

All those migrating from windows or mac to linux will notice this. It is one of those it has to "Just Work" kind of things. Gives a very bad first impression cause it happens all the time.

Now I also realize free software is um free :) so I'm not holding my breath but I think this should have a Higher priority... It really surprises me that this kind of bug can exist for so long... 6 years... :( 

In any case other than this 1 thing, the rest of GTK is awesome ;) Best Wishes
Comment 92 Matthias Clasen 2007-05-18 04:40:00 UTC
*** Bug 406543 has been marked as a duplicate of this bug. ***
Comment 93 bi2h5da02 2007-05-18 04:53:01 UTC
This has been annoying me for so long I decided that it must not be a bug.  I figured it was an intentional feature for preventing accidental clicks when a new window appears.  :-)  Otherwise it would have been fixed by now, right?

If KDE doesn't have this problem, can you emulate their functionality?

(In reply to comment #91)
> It really surprises me that this
> kind of bug can exist for so long... 6 years... :( 

That's free software for you...
Comment 94 Stefan de Konink 2007-05-18 11:41:55 UTC
(In reply to comment #93)
> This has been annoying me for so long I decided that it must not be a bug.  I
> figured it was an intentional feature for preventing accidental clicks when a
> new window appears.  :-)  Otherwise it would have been fixed by now, right?
> 
> If KDE doesn't have this problem, can you emulate their functionality?
> 
> (In reply to comment #91)
> > It really surprises me that this
> > kind of bug can exist for so long... 6 years... :( 
> 
> That's free software for you...

BS, look how many patches are posted to solve this issue.

Comment 95 Ed Catmur 2007-05-21 20:14:45 UTC
(In reply to comment #87)
> I don't understand why it has to be so unnecessarily complicated - why not just
> consider HIGHLIGHTED and SENSITIVE to be independent flags?

That would be difficult; HIGHLIGHTED (actually PRELIGHT) and (IN)SENSITIVE are members of the GtkStateType[1] enumeration, and so PRELIGHT_INSENSITIVE would be difficult to add (lots of theme code would need changing); moreover, prelight state is set by the widget implementation, not by GTK+ core (i.e. gtkmain.c) so the only way to tell a widget to transition to a prelight state consistently with the logic as it stands is to send it a mouse-entered event.  Take a look at gtk_button_enter_notify in gtkbutton.c, and note how it's the widget itself that controls the SENSITIVE state.  Changing that at this stage, when there are hundreds of GTK+ widgets outside the GTK tree, would be... challenging.

1. http://developer.gnome.org/doc/API/2.0/gtk/gtk-Standard-Enumerations.html#GtkStateType
Comment 96 Ben Van Aerde 2007-06-01 09:51:53 UTC
*** Bug 440433 has been marked as a duplicate of this bug. ***
Comment 97 Johan (not receiving bugmail) Dahlin 2007-06-05 19:38:24 UTC
Created attachment 89429 [details]
program to help test this

Here is a small program I wrote while trying to test this, but it's rather tricky, the only synthesized events I got were the three newly introduced ones [gtk grab, gtk ungrab, state changed].

Hope this is useful for someone.
Comment 98 Emmanuele Bassi (:ebassi) 2007-06-12 09:40:37 UTC
*** Bug 446579 has been marked as a duplicate of this bug. ***
Comment 99 Matthias Clasen 2007-06-14 03:25:57 UTC
Ok, trying to write down some kind of test plan. 

Concepts (as outlined by Owen)

- The real pointer window: this is the window that we most recently received an
  enter notify for (windows that don't select for crossing events can't become 
  the real pointer window)

- The real pointer widget: this is the widget to which the real pointer window 
  belongs

- The effective pointer window: this is the same as the real pointer window,
  unless the real pointer widget is either insensitive or there is a grab 
  on a widget that is not an ancestor of the real pointer widget, in which 
  case it is the root window.

Theory of operation

When the effective pointer window is the same as the real pointer window, we receive crossing events from the window system. When the effective pointer 
window changes to be different from the real pointer window, we synthesize crossing events according to the rules of the X protocol about crossing events:

If the root window is becoming the effective pointer window, we generate

 - a leave notify with detail Ancestor on the real pointer window
 - leave notifies with detail Virtual on any ancestor of the real 
   pointer window up to the toplevel
 - an enter notify with detail Inferior on the root window

If the root window stops being the effective pointer window, we generate

 - a leave notify with detail Inferior on the root window
 - enter notifies with detail Virtual on any ancestor of the real 
   pointer pointer window, starting at the toplevel
 - an enter notify with detail Ancestor on the real pointer window


What to test: 

- Check that the tracking of real and effective pointer window and 
  widget works correctly

- Verify that we generate the expected sequence of crossing events with
  correct details when the real pointer widget becomes insensitive

- Verify the event sequence when the real pointer widget becomes sensitive
  again

- Verify the event sequence when a sibling widget of the real pointer widget
  establishes a GTK grab

- Verify the event sequence when the sibling widget releases the grab again

All this should be done with multi-window widgets, too


Comment 100 Matthias Clasen 2007-06-14 11:44:05 UTC
Two more test cases:

- Start with the real pointer widget being insensitive, verify that moving
  the pointer to a sensitive sibling widget creates the expected event sequence

- Start with the real pointer widget being grab-shadowed, verify that moving
  the pointer to a not grab-shadowed widget creates the expected event sequence


This testing should be fully automatable using  gdk_display_warp_pointer().

For comparison purposes, warping the pointer to/from the root window should 
give the same sequence of crossing events. 
Comment 101 Owen Taylor 2007-06-14 12:19:08 UTC
This looks right to me. The one case that isn't explicitly mentioned in
your test plain is when the user moves the pointer into a window owned
by an insensitive widget. In that case, the *ideal* sequence of events
would be to treat things as if the effective pointer window moved directly
to the root window, but it's probably easier to allow some extra events
so, if you have window C within window B within Window A, and C's owner
is insensitive and the pointer moves directly from A to C (imagine that
C and B are the same size), you'd ideally want to send only a leave
on A with a detail of Ancestor, but the easier thing is likely:

 leave on A with detail inferior
 enter on B with detail virtual
 <real enter on C with detail ancestor not delivered>
 <synthetic leave on C with detail ancestor *not delivered*>
 leave on B with detail virtual
 leave on A with detail virtual
Comment 102 Cody Russell 2007-06-14 19:50:25 UTC
Created attachment 89967 [details] [review]
Updated patch that applies against trunk

I'm reviewing/testing now, just posting an updated patch.
Comment 103 Cody Russell 2007-06-18 21:51:22 UTC
Created attachment 90241 [details]
First stab at new test program

Here's my first stab at a new automated test program.
Comment 104 Cody Russell 2007-06-18 22:19:17 UTC
Created attachment 90242 [details]
Updated test

Prints the detail of the crossing event.
Comment 105 Cody Russell 2007-06-18 23:23:45 UTC
Created attachment 90246 [details]
Updated to work around g_timeout_add_seconds() bug

I was having issues with g_timeout_add_seconds(4, ...) so I changed this test program to use g_timeout_add (4000, ...) instead.  Also Created bug 448943 for anyone who cares. :)
Comment 106 Matthias Clasen 2007-06-19 04:59:42 UTC
Created attachment 90254 [details]
updated tests

Here is a slightly enhanced version of the test which dumps out more event details.
Comment 107 Cody Russell 2007-06-19 16:22:58 UTC
Created attachment 90280 [details]
Update of mclasen's patch

This updates Matthias's patch to use g_timeout_add() instead of g_timeout_add_seconds().
Comment 108 Matthias Clasen 2007-06-22 05:28:47 UTC
Created attachment 90432 [details] [review]
another round of patch

Here is another version of the patch that tries harder to implement the semantics outlined by Owen. It doesn't get all details right, but the event sequences look much closer to the expected ones.
Comment 109 Markus Berg 2007-07-11 08:30:11 UTC
FWIW, I'm unable to replicate this bug with sloppy-focus.  Mouse-focus also
works fine, but click-focus does replicate it.  I'm on Fedora7, and I've been
using the testcase from comment #11.
Comment 110 Mantas Kriaučiūnas 2007-07-27 11:43:34 UTC
Please, tell be when clicking on GTK button starts to work. I'm talking about such case, like described in bug https://bugs.launchpad.net/bugs/108164 :

2: Forward button on installer dialog box does not respond to mouse clicks if mouse cursor isn't moved between 2 steps. Moving mouse cursor or the dialog box makes button "Forward" responsible again.
Comment 111 antistress 2007-10-17 22:11:16 UTC
After celebrating the 10 years birthday of GNOME, will we have to "celebrate" the 10 years birthday of this bug ? ;-)
Comment 112 Xan Lopez 2007-10-24 08:35:51 UTC
*** Bug 489584 has been marked as a duplicate of this bug. ***
Comment 113 Cody Russell 2007-11-09 19:32:35 UTC
Created attachment 98835 [details] [review]
Updated patch
Comment 114 Cody Russell 2007-11-20 17:42:55 UTC
Matthias, regarding your comment #108, do you remember what you thought was not yet finished in it, or what it didn't yet get right?  It's unclear to me in my testing what is not working as expected.
Comment 115 John Boncek 2007-12-19 15:30:05 UTC
25 duplicates.
Comment 116 Xan Lopez 2007-12-23 01:13:34 UTC
*** Bug 504963 has been marked as a duplicate of this bug. ***
Comment 117 Mathias Hasselmann (IRC: tbf) 2007-12-23 09:25:33 UTC
This bug is getting ridiculous!

Can we finally apply one of the suggested patches please? Each of the patches might be broken in one or the other way, but nevertheless they all have one __giant advantage__: They work arround or even solve this very visible and embarrassingly issue.
Comment 118 Jan Niklas Hasse (Account disabled) 2007-12-23 11:23:14 UTC
i think exactly the same as mathias. please apply a patch.
Comment 119 bi2h5da02 2007-12-23 14:32:37 UTC
(In reply to comment #117)
> This bug is getting ridiculous!
> 
> Can we finally apply one of the suggested patches please?

Agreed.  Try navigating through pictures with gThumb and deleting a few as you go.  You have to wiggle the mouse around at just the right time to get the button to respond.  Otherwise it does nothing when you try to navigate.

I thought this was a problem with my own computer for the first few months of using Linux, because I didn't believe something this fundamentally broken would be allowed to exist in open-source software.  I'm amazed that patches exist and haven't been implemented, no matter how imperfect.
Comment 120 Luca Bruno 2008-01-08 20:35:05 UTC
I do agree too. It has been a very long time since this bug has been reported and it's really boring. I guess won't be terrible to change the patch later or revert it a day.
Comment 121 Cody Russell 2008-01-08 21:56:41 UTC
Can people please stop adding comments that basically just agree with what tbf said?  Adding more "I agree" comments is not productive and it's just cluttering the bug report.

If we don't manage to finish the patch before the Berlin hackfest, perhaps we can allocate some time there towards this.

I did devote some time to try to understand what is missing from the current patch, but I wasn't as thorough as I need to be.  I'll be willing to take a stab at improving the patch once I have a better understanding of what's missing.  Here's what I -think- is not correct at the moment.

Matthias said in comment #99 that if the root window becomes the effective window pointer we generate:
 - leave notify on real pointer window, with detail Ancestor [1]
 - leave notify on ancestors of real pointer window, with detail Virtual [2]
 - enter notify on root window with detail Inferior [3]

From what I can tell, here's what is actually happening:
 [1] - leave notify on real pointer window, detail nonlinear
 [2] - leave notify on ancestors, detail nonlinear-virtual
 [3] - Not watching the root window (need to improve the test program)


And if the root window stops being the effective pointer window generate:
 - leave notify on root window, detail Inferior [4]
 - enter notify on ancestors of the real pointer window, detail Virtual [5]
 - enter notify on real pointer window, detail Ancestor [6]

What I think is happening:
 [4] - Unsure, not watching the root window yet
 [5] - enter notify on ancestors, detail nonlinear-virtual
 [6] - enter notify on real pointer window, detail nonlinear
Comment 122 Cody Russell 2008-01-09 00:08:10 UTC
Correction to what I posted before (sorry, it's been awhile since I was looking at this stuff).

What's currently happening when the root window becomes the effective window pointer is that we generate:
 - leave notify on real pointer window, detail Ancestor
 - leave notify on ancestors, detail virtual

And this is correct in itself.  However, the opposite is not correct I think:

When the root window stops being the effective pointer window it looks like we generate:
 - enter notify on window (*), detail ancestor
 - leave notify on window (*), detail inferior
 - enter notify on other ancestors, detail virtual
 - enter notify on real pointer window, detail ancestor

(*) Note that in this case 'window' is an ancestor of real pointer window.


So if the mouse then moves back to the root window, you'll get this sequence:
 - leave notify on real pointer window, detail ancestor
 - leave notify on ancestors of real pointer window, detail virtual
 - leave notify on window, detail virtual

So what is not happening correctly (the way I understand it) in our test is that window (our bottom ancestor) receives "enter notify, detail ancestor" then immediately "leave notify, detail inferior" when the mouse pointer enters our real pointer window and then when the mouse pointer leaves the real pointer window, we get another leave notify on the window.
Comment 123 Mathias Hasselmann (IRC: tbf) 2008-01-12 11:19:18 UTC
*** Bug 508082 has been marked as a duplicate of this bug. ***
Comment 124 Mathias Hasselmann (IRC: tbf) 2008-01-12 11:20:44 UTC
Yet another variation of this bug: As bug 508082 describes, button also miss
mouse entering, when some other window has grabbed the pointer. We should
consider this case, when fixing bug 56070.
Comment 125 André Klapper 2008-01-12 11:44:15 UTC
(restoring previous state)
Comment 126 Johan (not receiving bugmail) Dahlin 2008-01-12 11:59:35 UTC
I disagree that this is a blocker for GNOME 2.22, it has been without a proper solution for more than 6 years. It seems unlikely that a new release of GNOME cannot be released without this bug properly fixed.

Besides, I am not sure if the Gtk+ maintainers are willing to include the proposed patch in a stable release series, it's rather intrusive and needs to be tested thoroughly. 

According to the Bugzilla descriptions, the severity 'Major' or even 'Normal' seems to be the proper one, since this bug is not blocking development or testing, nor does it cause crashes, loss of data or memory leaks.
Comment 127 Mathias Hasselmann (IRC: tbf) 2008-01-12 12:23:47 UTC
Johan: IMHO this bug is open still for social, but not for technical reasons - since there is a simple solution for the original problem. I am using it for years now:

==== photobuch-com.h ===

#define gtk_widget_set_sensitive gtk_widget_set_sensitive_if_changed

==== photobuch-com.c ===

#undef gtk_widget_set_sensitive

static void
adjust_hover_state (GtkWidget *widget)
{
  /* GNOME-Bug 56070: Simulate MOUSE-ENTER effect when needed */

  if (GTK_IS_BUTTON (widget) && GTK_WIDGET_IS_SENSITIVE (widget)) 
    {
      gint x, y;

      gtk_widget_get_pointer (widget, &x, &y);

      GTK_BUTTON (widget)->in_button =
        x >= 0 && x < widget->allocation.width &&
        y >= 0 && y < widget->allocation.height;
    }
}

void 
gtk_widget_set_sensitive_if_changed (GtkWidget *widget,
                                     gboolean   sensitive)
{
  g_return_if_fail (GTK_IS_WIDGET (widget));

  if (GTK_WIDGET_IS_SENSITIVE (widget) != sensitive)
    {
      gtk_widget_set_sensitive (widget, sensitive);
      adjust_hover_state (widget);
    }
}

#define gtk_widget_set_sensitive gtk_widget_set_sensitive_if_changed

=======================

This trivial approach for solving the problem was rejected since gtk_widget_get_pointer() causes an additional X server roundtrip.

So agreed: The patch isn't perfect. It is a hack, but it solves the problem.
Well, and this is were the social aspect of the problem kicks in: Rejecting a working solution 'cause of its uglyness, without providing a better solution within years, clearly is a social problem.

It's the social aspect, not the technical one, that qualifies this bug as BLOCKER - IMHO.
Comment 128 Cody Russell 2008-01-12 16:45:50 UTC
I think the worry is that if the patch is applied then we may get some weird bizarre bug affecting gtk+ a year or two later and have to waste a lot of time trying to figure out what's causing it, etc.  As tbf says, the patch here solves the issue at hand, so why don't we leave it up to the distributions to apply it until it gets finished and applied to gtk+ svn?  That seems like a perfectly sensible solution to me.

I'll try to devote more time to understand and improve the patch when I can.  Previously I wasn't sure what the problem with the patch is, and Matthias didn't remember anymore.  That's a blocker for improving the patch.  But now I know what's not working, and I've documented it here.  That's not as big of an improvement as posting a better patch, but it's still some progress.

I agree with Johan that it's not a blocker for GNOME 2.22.  It wasn't a blocker for any other version of GNOME, it was just annoying.  I still think if we don't solve it by GNOME 2.22 then maybe we can devote some time to it at the Berlin Hackfest.
Comment 129 André Klapper 2008-02-08 13:36:52 UTC
convinced.
Most people don't see this as a GNOME 2.22 blocker but as a highly annoying gtk+ blocker. Hackfest should definitely be the place to cook a patch together that makes everybody happy and to get this finally erased.
Comment 130 M Lange 2008-02-14 18:59:21 UTC
I've been watching the bug for years now. Enough's enough :)
Comment 131 R E Broadley 2008-02-29 15:40:34 UTC
a quick newbie question if I may (sometimes newbie questions are helpful!).

Anyone know how other OSs/GUIs deal with buttons becoming sensitive while the pointer is over them?

Is the complexity due to the way GTK has been designed compared with other GUIs?

Thanks, and apologies if this is not the place to ask this.
Comment 132 R E Broadley 2008-02-29 16:01:20 UTC
endolith makes a very valid comment in comment #93. It can often be a problem on Windows XP that a dialogue box can pop up with a button in the exact location where you were about to click on the button of another window/dialogue. I've had this happen to me.

Please can we bear this problem in mind (if applicable) when coding a solution. 
I.e. ideally there would be a user configurable delay before a button becomes clickable if the dialogue box containing it has only just appeared.

If we can achieve this, then we'll actually have one up on Microsoft latest OS!
Comment 133 David (djst) Tenser 2008-02-29 19:44:36 UTC
10 years to (not) fix a serious usability issue. Wow. Gnome. Removing from cc list.
Comment 134 Cody Russell 2008-03-10 02:19:07 UTC
So I'm trying to get back into this now, and my comment #122 is not entirely accurate I see.

The issue is that when you move the pointer out of the window, the sequence of events is actually dependent upon how fast you move the mouse.  The same is also true when you move the pointer into the window.

For example, when moving the mouse out of the window rapidly:
 -- leave B: native, normal, nonlinear
 -- leave E: native, normal, nonlinear-virtual
 -- leave W: native, normal, nonlinear-virtual

If you move the mouse more slowly you would see:
 -- leave B: native, normal, ancestor
 -- leave E: native, normal, virtual
 ++ enter W: native, normal, inferior
 -- leave W: native, normal, nonlinear

(The opposite is true when entering the window.. you will get 3 enter events, plus a spurious leave event on the window).

So, I need to try to understand where this is coming from. :)
Comment 135 Jimmy Happy 2008-03-14 15:40:31 UTC
Wow. GNOME never fixes that bug??? No wonder KDE is getting good reviews.

(BUT GNOME is faster and usable, so I like GNOME better...)

As to the technical aspects of this, I had to wonder if this is a more complicated bug than it is.

In an older version of GTK+, the button bug is clearly visible. After I compiled a newer version of GTK+, the bug disappeared. (OS: Puppy Linux 2.14 - exact version)

Yet in Ubuntu there is the same bug in Feisty - which their GTK version is higher than the other one. (2.10.11 > 2.8.17)

This bug scared the people who I tried to convert then to Linux. It is just a terrible mess.

This bug should be fixed ASAP. There is no need for delay.
Comment 136 Jeff Walden (remove +bgo to email) 2008-03-14 15:56:29 UTC
Look, I'm sure everyone hates this bug as much as the next person, but can we please not make unnecessary comments and generate useles bugspam?  Everyone following this bug knows that everyone hates this bug and wants it fixed; commenting without providing useful technical details (e.g. even a half-working, proof-of-concept patch) regarding a fix is unproductive.  Complaints generally do not motivate someone to fix a bug.

Note that between the last comment and this one someone removed himself from the CC list -- why do you suppose he did so?

I can't find the GNOME version of the following document, but this is fairly generally applicable anyway:

https://bugzilla.mozilla.org/page.cgi?id=etiquette.html
Comment 137 Ed Catmur 2008-04-25 22:49:57 UTC
Created attachment 109938 [details] [review]
gtk-sensitivity.patch

Update for 2.13.0.
Comment 138 Cody Russell 2008-07-15 04:16:14 UTC
Created attachment 114569 [details] [review]
Add unit test
Comment 139 Cody Russell 2008-07-15 06:11:17 UTC
Created attachment 114571 [details] [review]
Check button sensitivity before calling gtk_button_leave()

This fixes the issue where a button could generate two synthesized leave events when it becomes insensitive while the pointer is in it.  See the change in gtk_button_leave_notify().
Comment 140 Cody Russell 2008-07-15 21:01:08 UTC
So everything before the grab add is correct now.  I'm not sure about after that.. here's the sequence of events I'm getting when I do gtk_grab_add() on the check button:

        Establishing GTK grab on check button C.
 -- leave W: synthesized, gtk-grab, ancestor
 ++ enter C: synthesized, gtk-grab, inferior
 -- leave E: synthesized, gtk-grab, ancestor
 ++ enter C: synthesized, gtk-grab, inferior
 -- leave B: synthesized, gtk-grab, ancestor
 ++ enter C: synthesized, gtk-grab, inferior


So what I'm wondering is, should each synthesized leave event on another widget also result in a synthesized enter event on the grabbed check button?  Or should we only be getting a single enter event on it?
Comment 141 Cody Russell 2008-07-15 21:07:54 UTC
Created attachment 114627 [details] [review]
Add establish-gtk-grab unit test.

This adds one more test, establish-gtk-grab.
Comment 142 Matthias Clasen 2008-07-17 04:56:17 UTC
Looking at your tests:

- it would be good to also check events on the root window

- it would be good to track the 'effective pointer window'

- cursor_on_sensitive: looks right, you are checking the expected sequence of native events.

- change_sensitivity: according to the theory layed out further up,
  what I would have expected here is:

 - a leave notify with detail Ancestor on the real pointer window
 - leave notifies with detail Virtual on any ancestor of the real 
   pointer window up to the toplevel
 - an enter notify with detail Inferior on the root window

As Owen said much further up: Sending events with a detail of NOTIFY_UNKNOWN basically means that any such tracking is a lost cause.


- cursor_from_insensitive_to_sensitive: what I would have expected here
  is:

 - a leave notify with detail Inferior on the root window
 - enter notifies with detail Virtual on any ancestor of the real 
   pointer pointer window, starting at the toplevel
 - an enter notify with detail Ancestor on the real pointer window

We seem to be missing the events on the intermediate windows, and on 
the one event we get, the detail is wrong. This is because the event
we get is a native one.

- cursor_from_sensitive_to_insensitive: pretty much the same comment,
  we don't get events on the intermediate windows, and the detail on
  the one event we get is wrong.


- establish_gtk_grab:
  What should be happening here is that first B is the effective pointer
  window, then when the grab takes place, B gets grab shadowed and the
  effective pointer window moves to root, so we should get leave notifies
  on B, E, W (with details Ancestor, Virtual, Virtual) and an enter 
  on the root window (with detail Inferior). The actual sequence looks
  nothing like it...
Comment 143 Matthias Clasen 2008-07-17 05:19:40 UTC
I assume what might be happening in the grab case is that we get multiple synthesize_crossing calls, because it gets called in grab_notify_foreach ?
Comment 144 Cody Russell 2008-07-17 16:32:49 UTC
"I assume what might be happening in the grab case is that we get multiple
synthesize_crossing calls, because it gets called in grab_notify_foreach ?"

Yes, that's exactly why we get what we get there.
Comment 145 Cody Russell 2008-07-17 20:29:54 UTC
I tried adding:

    gdk_window_add_filter (gdk_get_default_root_window (),
                           root_filter_func,
                           test->window);

But root_filter_func() seems to never be called.

"- change_sensitivity: according to the theory layed out further up,
  what I would have expected here is:

 - a leave notify with detail Ancestor on the real pointer window
 - leave notifies with detail Virtual on any ancestor of the real 
   pointer window up to the toplevel
 - an enter notify with detail Inferior on the root window

As Owen said much further up: Sending events with a detail of NOTIFY_UNKNOWN
basically means that any such tracking is a lost cause."

I've fixed this, I'll post an updated patch later today.
Comment 146 Cody Russell 2008-07-17 23:05:42 UTC
Created attachment 114739 [details] [review]
Fix state-changing crossing events

This corrects the crossing events on the state change and updates the unit test to reflect it.
Comment 147 Cody Russell 2008-07-17 23:20:32 UTC
Created attachment 114740 [details] [review]
Didn't have the unit test in the last patch

Sorry, generated the last patch from svn instead of git (don't ask) and forgot to svn add the unit test.  Here's an updated patch.

This also adds a new unit test for when the state changes from insensitive to sensitive.
Comment 148 Matthias Clasen 2008-07-18 03:59:44 UTC
The first three tests are good now, the last three need more work.

Wrt to the root window, you probably need to set an appropriate event mask:

      test->events_connected = TRUE;
      mask = gdk_window_get_events (gdk_get_default_root_window ());
      mask = mask | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
      gdk_window_set_events (gdk_get_default_root_window (), mask);

      gdk_window_add_filter (gdk_get_default_root_window (),
                             root_filter_func, test);

But of course, this is not going to be useful, since we are not generating
any native enter/leave events on the root window...
Comment 149 Cody Russell 2008-07-18 04:32:26 UTC
"But of course, this is not going to be useful, since we are not generating
any native enter/leave events on the root window..."

Does that mean I don't want to have this stuff?

+      synth_crossing (NULL, GDK_ENTER_NOTIFY,
+		      gtk_widget_get_root_window (from),
+		      mode, GDK_NOTIFY_INFERIOR);
Comment 150 Matthias Clasen 2008-07-18 05:08:01 UTC
If you look at the code for synth_crossing, calling it for the root window is a no-op, since gtk_get_event_widget returns NULL for the root window.
Comment 151 Cody Russell 2008-07-22 00:38:04 UTC
Created attachment 114966 [details] [review]
Updates for grab-shadowing

This update I think improves the events when the grab shadow is added or removed.  Here is the sequence of events I get with this patch:

        Establishing GTK grab on check button C.
 -- leave B: synthesized, gtk-grab, ancestor
 -- leave E: synthesized, gtk-grab, ancestor
 -- leave W: synthesized, gtk-grab, ancestor

        Removing GTK grab from check button.
 ++ enter B: synthesized, gtk-ungrab, ancestor
 ++ enter E: synthesized, gtk-ungrab, ancestor
 ++ enter W: synthesized, gtk-ungrab, ancestor


The four situations that are not currently working ideally are:

Moving from insensitive widget to sensitive widget C
 ++ enter C: native, normal, nonlinear

Moving from sensitive widget C back to insensitive widget
 -- leave C: native, normal, nonlinear

Moving from grab-shadowed widget to C
 -- leave C: native, normal, nonlinear
 ++ enter C: native, normal, nonlinear

Moving from C to grab-shadowed widget
 -- leave C: native, normal, nonlinear
 ++ enter C: native, normal, nonlinear


The first two I've spent some time trying to solve, and I've gotten nowhere.  My feeling is that I'd like to move on and ignore these two even though they're not working absolutely to the ideal.

I'm not sure about the last two, I'd like a little bit more time with those.
Comment 152 Cody Russell 2008-07-22 01:22:37 UTC
Created attachment 114967 [details] [review]
Unit test was missing in last patch

Somehow I missed the unit test again in that last patch.
Comment 153 Cody Russell 2008-07-24 13:44:07 UTC
Created attachment 115171 [details] [review]
Add unit test for removing gtk grab

Added remove-gtk-grab unit test.
Comment 154 Cody Russell 2008-07-31 05:27:15 UTC
Created attachment 115604 [details] [review]
Updated patch, added unit tests for moving from and to grab shadowed widgets
Comment 155 Cody Russell 2008-07-31 14:29:44 UTC
Created attachment 115622 [details] [review]
Fix typo in unit test

I was accidentally moving from B -> C for both of the last two unit tests.  The last one now moves C -> B.
Comment 156 Matthias Clasen 2008-08-01 02:56:41 UTC
A day of regular desktop use didn't reveal any problem with the patch, and I could verify that it indeed fixes several of the notorious button-becomes-sensitive issues in apps.

I agree that we should go with the patch as it is now.

Some small janitorial things are still left to do:

1) I believe most of the 'theory of operation' explained way up by Owen should go in the a comment somewhere, maybe the doc comment for _gtk_widget_synthesize_crossing.

2) The GtkPrivateFlags changes need to be reflected in the registration of the enum type in gtktypebuiltins.c

3) tests/simple.c seems to have some C99-style comments. Those should be converted to /* */

4) The docs for the new crossing modes should state that they were added in 2.14, and perhaps also that these modes are never native, but always synthesized (not sure)

Please commit it with those changes. Congratulations on killing one of the longest-standing open bugs in GTK+. 
Comment 157 Cody Russell 2008-08-01 03:30:55 UTC
2008-07-31  Cody Russell  <bratsche@gnome.org>

        Bug 56070 – Can't click button after setting it sensitive.

        * gtk/gtkwidget.[ch] 
        * gtk/gtkwindow.c
        * gtk/gtkmain.c
        * gtk/gtkbutton.c
        * gtk/gtkprivate.h
        * gdk/gdkevents.h: Synthesize crossing events events where necessary.

        * gtk/tests/crossingevents.c: Add unit tests for crossing events.

        Big thanks to Ed Catmur, Matthias Clasen, and everyone else who
        has worked on and helped out with this.
Comment 158 Wouter Bolsterlee (uws) 2008-08-01 08:23:04 UTC
Wow... congratulations!

             ,   ,   ,   ,             
           , |_,_|_,_|_,_| ,           
       _,-=|;  |,  |,  |,  |;=-_       
     .-_| , | , | , | , | , |  _-.     
     |:  -|:._|___|___|__.|:=-  :|     
     ||*:  :    .     .    :  |*||     
     || |  | *  |  *  |  * |  | ||     
 _.-=|:*|  |    |     |    |  |*:|=-._ 
-    `._:  | *  |  *  |  * |  :_.'    -
 =_      -=:.___:_____|___.: =-     _= 
    - . _ __ ___  ___  ___ __ _ . -    

Enjoy the pie!
Comment 159 Murray Cumming 2008-08-01 08:33:09 UTC
Cody, we owe you (and the others who provide previous attempts at patches) big time.
Comment 160 André Klapper 2008-08-01 08:38:35 UTC
Oh god it's fixed. Thanks so much, Cody!!!
Comment 161 Sri Ramkrishna 2008-08-01 09:06:08 UTC
Woohoo!  Good job, Cody and others!

sri
Comment 162 Federico Mena Quintero 2008-08-01 15:25:00 UTC
Vla the Impaler strikes again.  Thanks, Cody :)
Comment 163 anthony taranto 2008-08-01 16:28:07 UTC
Cody is a hero to millions! Congrats guys.
Comment 164 Jan Schampera 2008-08-01 16:45:37 UTC
Respect and thatnk you. I remember that bug annoyed me in our assistant window some years(!) ago. I never found a solution until now ;-)

J.
Comment 165 Behdad Esfahbod 2008-08-01 17:03:39 UTC
Just took seven years.  Not bad.  Now Cody can start working on some bug from 2002.  Keep up the good job dude!
Comment 166 John Boncek 2008-08-01 21:57:09 UTC
What GTK+ stable release will have the correction?  2.14, I presume?
Comment 167 André Klapper 2008-08-01 22:55:28 UTC
It will be included in 2.14, yes.
Comment 168 Sitsofe Wheeler 2008-08-02 10:51:25 UTC
Thanks for fixing this Cody - much appreciated.
Comment 169 Stu Hood 2008-08-02 17:20:07 UTC
Hooray! I had subconsciously worked around this bug (and seen others do the same) by moving my mouse away from a button I was expecting to appear, and then back in when it was ready to click.

Thanks tons for fixing it.
Comment 170 DavidCognito 2008-08-02 21:44:57 UTC
Anyone know if GTK+ 2.14 will get in to Ubuntu 8.10?
Comment 171 André Klapper 2008-08-02 21:57:14 UTC
I guess Ubuntu 8.10 will ship GNOME 2.24 which will include gtk+ 2.14. This is totally a distro decision so you might want to ask them, but I'm quite sure about this.
Comment 172 DavidCognito 2008-08-02 22:52:57 UTC
Thanks Andre.

And thanks to everyone involved in fixing this.
Comment 173 Sébastien Granjoux 2008-08-05 17:46:26 UTC
*** Bug 546434 has been marked as a duplicate of this bug. ***
Comment 174 klange 2008-08-09 19:13:35 UTC
(In reply to comment #171)
> I guess Ubuntu 8.10 will ship GNOME 2.24 which will include gtk+ 2.14. This is
> totally a distro decision so you might want to ask them, but I'm quite sure
> about this.
> 

A forum post reports that the required bug fix is present in Ubuntu 8.10 already. I have confirmed that I can't recreate the problem any more. <http://ubuntuforums.org/showthread.php?t=884134>
Comment 175 Cody Russell 2008-08-12 05:06:07 UTC
*** Bug 547379 has been marked as a duplicate of this bug. ***
Comment 176 Roland Illig 2008-10-21 13:18:42 UTC
*** Bug 557202 has been marked as a duplicate of this bug. ***
Comment 177 Mikel Ward 2008-10-31 01:29:34 UTC
I had filed this as "gdm buttons don't work at first" <https://bugzilla.redhat.com/show_bug.cgi?id=468107>.

Glad to hear it's finally been fixed, and thanks to all commenters (particularly Wouter) for brightening my day. :-)
Comment 178 Jimmy Happy 2009-04-23 22:09:10 UTC
It's FINALLY fixed! Thanks to the devs who fixed it. :)

Looks like it's still going around... :P Don't know why...

Read "Rick's Opinion", scroll to see.
Comment 179 Christian Hammond 2009-10-02 00:26:16 UTC
(In reply to comment #158)
> Wow... congratulations!
> 
>              ,   ,   ,   ,             
>            , |_,_|_,_|_,_| ,           
>        _,-=|;  |,  |,  |,  |;=-_       
>      .-_| , | , | , | , | , |  _-.     
>      |:  -|:._|___|___|__.|:=-  :|     
>      ||*:  :    .     .    :  |*||     
>      || |  | *  |  *  |  * |  | ||     
>  _.-=|:*|  |    |     |    |  |*:|=-._ 
> -    `._:  | *  |  *  |  * |  :_.'    -
>  =_      -=:.___:_____|___.: =-     _= 
>     - . _ __ ___  ___  ___ __ _ . -    


Really hate to say this, but... The cake is a lie.

Guess what broke with client-side windows? :( I can reproduce this with the test case already attached to this bug report.
Comment 180 Christian Hammond 2009-10-02 00:35:20 UTC
On an equally sad note, the workarounds no longer work.
Comment 181 Cody Russell 2009-10-02 01:37:07 UTC
I think synaptic used to have the workarounds in it.  Right now if I put my mouse pointer over "Reload" or "Mark All Upgrades" while they're insensitive and then they become sensitive, I can click them.

Also when I run the crossingevents test it says all the tests pass.

I'm using Ubuntu Karmic, so I definitely have client-side-windows.
Comment 182 Cody Russell 2009-10-02 01:45:08 UTC
Jon McCann tested and had the same results I did.  Let's leave this open for a couple days just to see what happens.  If we can't get anyone else to reproduce it then I'd like to close it again.
Comment 183 antistress 2009-10-02 01:49:16 UTC
i'm also using karmic and i can't reproduce the bug
Comment 184 Cody Russell 2009-10-02 02:10:34 UTC
I went ahead and closed this again.  Christian ran the unit test from gtk+ source and it all succeeded.  If it turns out we do have an issue we'll open a new bug report.
Comment 185 Diego Escalante Urrelo (not reading bugmail) 2009-10-02 03:34:13 UTC
ehm, i just ran into this while deleting messages from this bug in evolution :-). gtk+ 2.18.1 in debian.
Comment 186 Diego Escalante Urrelo (not reading bugmail) 2009-10-02 03:35:58 UTC
something sort of relevant: quickly clicking the same button works but doing it slowly will run into this bug.
Comment 187 André Klapper 2009-10-04 23:55:11 UTC
*** Bug 597143 has been marked as a duplicate of this bug. ***
Comment 188 Mathias Nedrebø 2009-10-06 10:19:27 UTC
This bug reappeared for me as well, when upgrading from gtk 2.18.0 to 2.18.1 some days ago using Arch Linux (Testing).
Comment 189 Pascal Terjan 2009-10-06 11:12:29 UTC
It is supposed to have been fixed in 2.18.2
Comment 190 Javier Jardón (IRC: jjardon) 2010-06-15 15:05:25 UTC
*** Bug 371006 has been marked as a duplicate of this bug. ***