Re: NotifyUngrab handling



Owen Taylor writes: 
 > Do you have code that demonstrates the problem? 

Ok, try the following:

1) Start up gnome with the gnome-session manager.

2) Start up a gnome-terminal (with an enabled menubar).

3) Execute the command:

	$ save-session &

4) Quickly click on one of the menus on the gnome-terminal and move 
   the mouse away over onto the root window (so that the menu stays up).
   The gnome-terminal will now have a grab on the pointer waiting
   for a button press or for a motion event over the menu.

5) Wait for a few seconds until gnome-session has started the
   save and gnome-terminal has responded by executing the following 
   code in gnome-client.c(save_yourself_callback):

   gdk_pointer_ungrab (GDK_CURRENT_TIME);
   gdk_keyboard_ungrab (GDK_CURRENT_TIME);
   gtk_grab_add (client_grab_widget);

   This code removes the grab held by the gnome-terminal. The
   pointer icon changes to reflect this event and a NotifyUngrab
   is sent by the Xserver (see XUngrabPointer (3)).

6) Now, when you press the mouse button the gnome-terminal menu
   does not recieve the event because it does not have the grab.
   As a result, the menu stays may it is and remains there
   until you send an event to the gnome terminal itself. 

7) For example, you can drag the gnome-terminal out from under 
   the menu using the window manager handles on its frame, but 
   if you click on the gnome-terminal client window then the menu 
   gets the event and pops down (gnome-client.c will have released 
   its grab by now).

Similar effects can be generated by the Xserver spontaneously
when it issues a NotifyUngrab as a result of the menu becoming
obscured. However, these are more tricky to reproduce because 
the NotifyUngrab is rarely the LAST event to be recieved by the
gtk app. Usually, the WM sends some other event (e.g. FocusOut) 
which causes the menu system to close down. 

That said, I have seen menus left hanging on the screen 
occaisonally and my diagnosis of the problem lies with missed
NotifyUngrab messages.

 > Offhand, I don't understand why the app needs to 
 > to worry about NotifyUngrab at all. (Not saying there
 > isn't a reason, I just don't know it.)

The reason is not to difficult to root out.

Grabs are set so that events that would usually go somewhere else
go to the window with the grab. This must mean that the window
intends to respond to these events in some way (e.g. deactivating
a menu). If the grab is taken away then the events that the window
was waiting for will go somewhere else. As a result the window
will be left waiting for something that does not get there.

In most circumstances, some other event gets through that has the 
same effect as the events that were missed and there is no visible
bug. However, this is a hit and miss approach that resembles
reading from a stream without checking that the connection is still
open and free of io errors.

 > Currently, enter/Leave events with Notify[Un]grab are propagated
 > normally, ...

The point that I was making is that all enter/leave events are 
redirected to the widget with the gtk grab in gtkmain.c
(gtk_main_do_event). However, it is not appropriate to redirect all 
types of event to the grab widget as the following comment in the 
gtkmain.c code makes clear:

  /* Not all events get sent to the grabbing widget.
   * The delete, destroy, expose, focus change and resize
   *  events still get sent to the event widget because
   *  1) these events have no meaning for the grabbing widget
   *  and 2) redirecting these events to the grabbing widget
   *  could cause the display to be messed up.
   * 
   * Drag events are also not redirected, since it isn't
   *  clear what the semantics of that would be.
   */

I was suggesting that the NotifyUngrab type enter/leave events
should be among the events that go to the event widget since they
are only meaningful to the widget that has the pointer grab. 
This widget is usually the widget with the gtk grab as well
(i.e. the grab widget == the event widget). 

However, the code in gnome-client.c provides an example of
where the widget with the pointer grab (the gtk menu) may 
not be the same as the grab widget (i.e. client_grab_widget).

 > ... Focus events (from XGrabKeybaord) are stripped to avoid
 > confusing how we set focus for input methods.

If we are throwing away events to simplify coding then that 
suggests that we have failed to understand the reason why 
they are being sent...

Felix



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]