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 107320 - Popup windows do not close when window loses focus
Popup windows do not close when window loses focus
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Backend: Win32
2.4.x
Other Windows
: Normal normal
: ---
Assigned To: gtk-win32 maintainers
gtk-bugs
: 124140 124144 132427 139264 145156 160395 168272 311029 (view as bug list)
Depends on:
Blocks: 114175
 
 
Reported: 2003-03-01 05:32 UTC by Simon Cooke
Modified: 2011-02-04 16:18 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Deactivate menu shell if lose focu (5.19 KB, patch)
2004-04-22 22:33 UTC, John Ehresman
none Details | Review
grab-broken implementation (8.70 KB, patch)
2005-01-07 17:22 UTC, John Ehresman
none Details | Review
more complete grab-broken implementation (14.76 KB, patch)
2005-06-24 20:29 UTC, Matthias Clasen
none Details | Review

Description Simon Cooke 2003-03-01 05:32:45 UTC
Popup menus and windows should close when the user moves to another 
application - by clicking on its window, or selecting it from the taskbar. 
At present, they remain open - even if another application completely 
obscures their owner/parent window.

Cause:
Modal message loops should be used to display popups and to prevent them 
from taking activation status from the owner window. Pan appears to be 
showing the windows as simple popup-windows, and is not tracking the 
activation state of the parent. When the parent becomes inactive, a click 
occurs outside of the popup window on the parent window, or the message 
loop receives a WM_CANCELMODE message, the popup window should be 
immediately destroyed (or hidden).
Comment 1 Charles Kerr 2003-03-01 11:31:36 UTC
Pan just uses vanilla GtkItemFactory for menus;
this is probably something to bounce to the gtk team.
Comment 2 Charles Kerr 2003-03-26 19:13:16 UTC
Reassigning to the owner of the gtk win32 component
Comment 3 Owen Taylor 2003-06-05 17:48:39 UTC
If you have a (native) menu up in win32, does a click on the 
title bar of another window immediately activate that window,
or does the first click deactivate the menu and a second
click is required to focus the window?

In current GTK+ operation, window deactivation is done
with a global pointer grab; if such a grab isn't possible
in Windows, we may have to add additional code to 
GtkMenu to also deactivate the menu when the toplevel
loses activation.

(Doing this for popups is much harder, and in fact, not
possible for most GTK+ apps without application modification,
since GTK+ has no idea what window the popup belongs to)
Comment 4 Josh Steiner 2003-10-16 01:34:37 UTC
"If you have a (native) menu up in win32, does a click on the 
title bar of another window immediately activate that window,
or does the first click deactivate the menu and a second
click is required to focus the window?"

it immediately activates the window.
Comment 5 Tor Lillqvist 2003-10-16 01:48:03 UTC
Implementing pointer grabs that would work like on X11 is hellish on 
Windows... 
Comment 6 Tor Lillqvist 2003-10-16 22:45:19 UTC
*** Bug 124140 has been marked as a duplicate of this bug. ***
Comment 7 Tor Lillqvist 2003-10-17 10:01:45 UTC
I have high hopes that rewriting the pointer and keyboard grab code 
in gdk/win32 to use low-level mouse and keyboard hooks will fix this 
and many other problems. (Low-level hooks are present only in 
NT/2k/XP.) I have already mostly done the pointer grab rewrite, and 
see a clear improvement. Will do the keyboard grab next.

Most apps written natively for Win32 pop down menus at once when the 
Alt key is pressed. Should GTK apps behave the same? It isn't obvious 
to me how well this would fit into GTK .
Comment 8 Tor Lillqvist 2003-11-07 03:08:17 UTC
*** Bug 124144 has been marked as a duplicate of this bug. ***
Comment 9 Arnaud Charlet 2003-11-14 15:54:48 UTC
Any news on this issue ?

Apparently Windows apps will handle the alt key in the following
way: pressing alt will select the menu bar without opening/displaying
it. Pressing alt again if the menu is selected or display will
automatically close the menu and unselect it.

Arno
Comment 10 Tor Lillqvist 2003-11-15 04:04:03 UTC
I did commit a hackish stopgap fix for this to the stable branch on 
2003-10-25:

 On WM_CANCELMODE, if the pointer and keyboard are grabbed, fake a
 mouse click on the root window. This is an awful hack to get menus
 to pop down properly when switching to another top-level window
 using the task switcher (Alt-Tab). Using low-level hooks to
 implement pointer and keyboard grabbing would be cleaner, but
 low-level hooks sound a bit dangerous, and Owen says we should
 avoid using them if at all possible. Fix for #107320.

I am not very fond of that fake mouse click solution, though. I have 
code sitting on my disk that uses low-level hooks, and solves this 
and related problems a bit better, perhaps. But, unfortunately I have 
found one minor regression so far with it: If you have clicked a 
mouse button just once on a button, scroll bar, etc in the GTK app, 
and then move the mouse to the bottom edge of the screen, Explorer 
doesn't display it's auto-hidden taskbar... You have to click once on 
the desktop to "wake up" Explorer. 

Anyway, perhaps I should commit what I have so far, to the stable 
branch? The use of low-level hooks can be skipped using a command-
line switch or environment variable, if it does cause some more 
serious problems. (Owen mentions possible interaction with on-screen 
keyboards, drivers for two-wheel mice, etc.)

I think much of these problems wouldn't occur if gtk would handle 
loss of focus in more places? (As it is more or less impossible on 
X11 to lose focus if you have the mouse and keyboard grabbed (I 
think), this problem doesn't occur on X11.) I did try to hack this 
into some place in gtk, but got nowhere.

To summarize: I don't know what the correct way to go forward is;-) I 
have a fix, but it probably isn't the Right Way to do it. On the 
other hand, the Right Way might be something for HEAD only.

Owen said in a private mail:

 instead of trying to *exactly* duplicate the X11 behavior 
 on Windows, I'd like to instead to decide what behaviors we want
 the user to see, and make sure we have the necessary APIs to allow
 widgets to robustly implement those behaviors.

 There are a whole large list of problems with pointer grabs on X11
 that I could go into here ... and *with* actual support in the 
 windowing system. Trying to duplicate the X grab model on Windows
 really doesn't seem like a good idea to me.
Comment 11 Martyn Russell 2003-12-18 18:25:25 UTC
I'm not sure if this is any help, but I have experienced this problem too.

I showed the application to a hardcore windows programmer and he
noticed it and said that if the context menu's parent window does NOT
have focus at the time of creation, the menu behaves this way.

Does this help?
Comment 12 Martyn Russell 2004-01-13 16:59:53 UTC
This bug should be a MAJOR severity atleast.  This problem seems to
cause other problems too.

I have been working on a work around for the menus staying up.  I did
this with the focus-out-event calling gtk_menu_shell_deactivate() on
the menubar.  This seems to work ok, but, I have found a similar,
perhaps related bug.

If I open a menu, then move the mouse over a button on the same
window, and click that button, the menu is deactivated, BUT the button
is unclickable.  Only when the mouse cursor is moved off the button's
dimensions, and back on again, can i click it.  

The funny thing is, I can press spacebar to activate the button at any
time.  I did some testing, it is not a timing issue, also, I tried
using GetCursorPos() and SetCursorPos() and that makes no difference
at all ? If I use gtk_widget_grab_focus(), gtk_widget_show(),
gtk_widget_hide(), gtk_widget_set_sensitive() on any other widget or
the same widget, it makes no difference either.

Should I raise a separate bug for this other problem?

Can we mark this bug as a priority ?
Comment 13 Tor Lillqvist 2004-01-28 02:50:39 UTC
*** Bug 132427 has been marked as a duplicate of this bug. ***
Comment 14 Hans Breuer 2004-04-06 18:35:38 UTC
*** Bug 139264 has been marked as a duplicate of this bug. ***
Comment 15 Tor Lillqvist 2004-04-07 04:25:44 UTC
Please note that what I wrote in comment 10 about the "stable" branch referred 
to GTK+ 2.2.x. Now, GTK+ 2.4 is the officially stable branch, and there won't 
be any more GTK+ 2.2.x (source) releases. (I did release a binary snapshot 
builds for Windows, gtk+-2.2.4-20040124, and might do another one if it seems 
necessary.) 
Comment 16 John Ehresman 2004-04-07 13:19:23 UTC
Yes, this bug is in 2.4 and IMHO is a major bug that needs attention.  I'm
willing to put together a patch for it, but the question is what event should be
returned when the grab is broken.  We do want the behavior that switching apps
does end the mouse & keyboard grabs because this is what other win32 apps do. 
But because this is not possible on X11, it's not clear to me how to implement it.

Is there a list somewhere of fixes in 2.2.x that are not in 2.4.x?
Comment 17 John Ehresman 2004-04-22 22:33:58 UTC
Created attachment 26984 [details] [review]
Deactivate menu shell if lose focu

Following up on Owen's suggestion on gtk-devel-list that menus should watch the
focus signal, I've put together this patch which adds the focus_out_event menu
handler to GtkMenuShell and modifies the win32 backend code to emit focus out
to the pointer grabbing widget if FOCUS_CHANGE is in its event mask.  A focus
out is also emitted to the toplevel window losing focus because I think it will
want it whether or not there's a grab in affect.

Is this the correct approach?  If so, I can go through gtk and add focus out
handlers where needed.
Comment 18 Simon Cooke 2004-04-22 23:07:19 UTC
In case it's useful, you can find an excellent example of how to build "fake" 
menus that work correctly under Windows in the Microsoft Windows Platform SDK, 
under:

\PlatformSDK\Samples\winui\Shell\Fakemenu

Full source code is provided... although ideas for how to integrate it with 
GTK's way of doing things are not...
Comment 19 John Ehresman 2004-04-28 21:26:00 UTC
Is there a way to print all the gdk events dispatched to gtk?  I'd like to do 
this on both X11 and win32.
Comment 20 Tor Lillqvist 2004-04-28 23:43:08 UTC
Yes, start the app with --gdk-debug=events (or set the GDK_DEBUG environment 
variable to "events"). 
Comment 21 Tor Lillqvist 2004-06-30 22:00:40 UTC
*** Bug 145156 has been marked as a duplicate of this bug. ***
Comment 22 Daniel Atallah 2004-08-20 00:01:44 UTC
This still happens in 2.4.7.  Perhaps the Version should be updated to 2.4.x.
Comment 23 Tor Lillqvist 2004-08-20 00:06:47 UTC
Yes.
Comment 24 John Ehresman 2004-09-14 14:31:08 UTC
This bug occurs on X11 as well as on win32 and some sort of grab broken
notification is needed to fix it.  To reproduce it on X11, press the mouse
button down, switch to another virtual desktop with a key accelerator, and then
release the mouse button.  When you return to the original desktop, the button
will still appear depressed when the mouse is over it because it never received
a mouse up event.

This discussion regarding grabs and window visibility is also relevant here:
http://mail.gnome.org/archives/gtk-devel-list/2003-June/msg00034.html

Unless gdk objects are going to start emitting signals that are handled by gtk,
I think the thing to do here is to define a GDK_EVENT_GRAB_BROKEN event and a
'grab_broken' signal on GtkWidget that can be handled by widgets that want to
detect broken grabs.  I can put together a patch to implement this if this is
the approach we want to take.
Comment 25 Tor Lillqvist 2004-12-15 09:40:20 UTC
jpe, have you had any time or inspiration to work on that grab broken 
signal/event idea?
Comment 26 John Ehresman 2004-12-17 12:54:18 UTC
I'll try to put together the start of a patch after Christmas and then send a
message to gtk-devel asking for feedback.
Comment 27 John Ehresman 2005-01-07 17:22:58 UTC
Created attachment 35625 [details] [review]
grab-broken implementation

This patch adds a grab-broken gdk event and gtk widget signal.	The win32
backend emits it in response to a WM_KILLFOCUS if an explicit or implicit grab
is active.  The GtkMenuShell and GtkButton provide handlers for the associated
signal that deactivates the menu or releases the button, respectively, when the
grab is lost.

More widgets probably need to handle the grab broken signal and the X11 backend
needs to emit it when an implicit mouse grab is broken by switching to a new
virtual console via a keyboard accelerator.  I will work on completing the
patch if I get feedback that this to the right direction to take this.
Comment 28 Arnaud Charlet 2005-02-16 16:56:36 UTC
Any feedback on the suggested patch and possible follow ups ?

I guess many Windows users would love to see this fixed, so it would
be great if we could make some prgoress on this issue.

Arno
Comment 29 Tor Lillqvist 2005-02-23 21:40:29 UTC
*** Bug 168272 has been marked as a duplicate of this bug. ***
Comment 30 Simon Cooke 2005-02-24 07:39:01 UTC
I reported this bug over 2 years ago.

So much for the "many eyes" making "quick bugfixes" with Open Source, eh?
Comment 31 Tor Lillqvist 2005-02-24 08:18:27 UTC
There aren't really that many eyes working on the Win32 backend. New volunteers
ar always needed. Plus, as can be seen from John Ehresman's patch above, fixing
this properly requires changes also to the backend-independent parts of GTK+,
which means it needs wider review and approval.
Comment 32 Tor Lillqvist 2005-03-20 18:11:15 UTC
*** Bug 160395 has been marked as a duplicate of this bug. ***
Comment 33 Matthias Clasen 2005-06-22 02:32:54 UTC
This is a near-duplicate of bug 114744, which asks for notification on lost
grabs and viewability changes.
Comment 34 Matthias Clasen 2005-06-24 20:29:11 UTC
Created attachment 48300 [details] [review]
more complete grab-broken implementation

I took jpe's patch and implemented grab-broken for x11, too. 
I also added some docs. I tested the menushell thing, and 
it in fact fixes the problem with menus staying up if the
current desktop gets "spontaneously" changed.

We should probably add the same code in other places where we 
pop up override-redirects under grabs, like gtkcombobox.
Comment 35 Matthias Clasen 2005-06-25 07:09:43 UTC
Committed this now. Still need to go over the remaining grabs
and see where we need grab_broken implementations.

2005-06-25  Matthias Clasen  <mclasen@redhat.com>

	Add a GrabBroken event to GDK, and a grab-broken-event
	signal to GtkWidget.  (#107320, Simon Cooke, initial patch 
	by John Ehresman)

	* gdk/gdkevents.h: Add a GDK_GRAB_BROKEN event type,
	define a GdkEventGrabBroken event struct.

	* gdk/win32/gdkevents-win32.c (gdk_event_translate): 
	Generate GrabBroken events in response to WM_KILLFOCUS.

	* gdk/x11/gdkmain-x11.c: Generate GrabBroken events
	when a grab is broken by the window becoming unviewable,
	or by another grab from the same client.
	
	* gtk/gtkwidget.h (GtkWidgetClass): Add grab_broken_event.

	* gtk/gtkwidget.c (gtk_widget_event_internal): Translate
	GrabBroken events into grab_broken_event signals.

	* gtk/gtkmain.c (gtk_main_do_event): Propagate GrabBroken
	events.

	* gtk/gtkmenushell.c (gtk_menu_shell_grab_broken): Deactivate
	the menu when the grab is broken.

	* gtk/gtkcolorsel.c (gtk_color_selection_grab_broken): Stop 
	the color picker if the grab is broken.

	* gtk/gtkpaned.c (gtk_paned_grab_broken): Stop the drag if
	the grab is broken.
Comment 36 Dennis Cranston 2005-06-25 17:27:12 UTC
After rebuilding gtk+ with this patch applied, nautilus' desktop popup menu
cannot be displayed.
Comment 37 Michele Baldessari 2005-06-26 16:06:08 UTC
It's been fixed with this commit FYI:

Sun Jun 26 00:04:36 2005  Manish Singh  <yosh@gimp.org>

        * gdk/gdkevents.c (gdk_event_get_time, gdk_event_get_state): add
        GDK_GRAB_BROKEN to the switch cases.

        * gtk/gtkmenushell.c (gtk_menu_shell_grab_broken): remove unused
        variables.

        * gtk/gtkpaned.c (gtk_paned_grab_broken): return TRUE.
Comment 38 Owen Taylor 2005-06-26 16:18:19 UTC
More likely by:

2005-06-25  Matthias Clasen  <mclasen@redhat.com>

        * gdk/x11/gdkmain-x11.c (gdk_keyboard_grab, gdk_pointer_grab):
        Don't emit grab-broken for overgrabbing, until we figure
        out how to do that without breaking the menu code
Comment 39 Matthias Clasen 2005-06-27 21:14:31 UTC
I have committed further changes which make GrabBroken events useful for
reporting grabs that are broken by overgrabbing inside the same application.
The win32 code will need to be changed to emit those as well.

2005-06-27  Matthias Clasen  <mclasen@redhat.com>

	* gtk/gtkmenushell.c (gtk_menu_shell_grab_broken): Ignore
	GrabBroken events which are caused by overgrabbing inside
	the application; menus rely on these for their operation.
	
	* gdk/gdkevents.h (struct _GdkEventGrabBroken): Add a 
	grab_window field.

	* gdk/win32/gdkevents-win32.c (gdk_event_translate): Set
	grab_window to NULL when generating GrabBroken events for
	WM_KILLFOCUS messages.

	* gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_unmap) 
	(_gdk_xgrab_check_destroy): Set grab_window to NULL when
	generating GrabBroken events when the grab window becomes
	unviewable or is destroyed.

	* gdk/x11/gdkmain-x11.c (gdk_pointer_grab, gdk_keyboard_grab): 
	Generate GrabBroken events when overriding a grab inside
	the application. In this case, set grab_window to the new
	grab_window.
Comment 40 Tor Lillqvist 2005-07-28 23:23:09 UTC
Now also the Win32 code emits GrabBroken events also when overgrabbing. Can this
bug be resolved now?

2005-07-29  Tor Lillqvist  <tml@novell.com>

	* gdk/win32/gdkevents-win32.c (generate_grab_broken_event): New
	static function to generate and append the GDK_GRAB_BROKEN events.

	(gdk_pointer_grab, gdk_keyboard_grab): Generate grab broken events
	when overriding a grab inside the application, like in the X11
	backend. Final bits of the fix for #107320, hopefully.

	(print_event): Handle also GDK_SETTING, GDK_OWNER_CHANGE and
	GDK_GRAB_BROKEN events.

	(gdk_event_translate): Call generate_grab_broken_event() in place
	of inline code.
Comment 41 Matthias Clasen 2005-08-01 05:41:52 UTC
I think so.
Comment 42 Tor Lillqvist 2005-10-05 18:06:39 UTC
*** Bug 311029 has been marked as a duplicate of this bug. ***