Event redirection issue: determining the type of triggered grabs
Deron Johnson
Deron.Johnson at Sun.COM
Thu Jan 12 16:54:27 PST 2006
LG currently uses a scheme for handling 3D grabs which I would like to
change. Keith has suggested that for every 3D object which has a 3D
grab registered for it via the LG client API that we define a
corresponding "3D proxy window" and register the grab information on
that. This seems to me like it will work. However, in order for this
to work completely, the LG Display Server (DS) will need to know when
grabs trigger. Furthermore, the DS will need to know the TYPE of grab
which triggered (i.e. whether the grab was from a user-defined passive
grab, a default button passive grab, or an active grab). The DS needs
this information in order to determine the specific 3D object to which
the grab corresponds.
Currently, LG uses the child field of events being sent to the DS to
convey the needed information. I'd like to stop using this approach
and use something a bit cleaner. I started investigating adding a new
type of event called GrabStateChange, but then I discovered that the X
protocol already has an event which provides me with *ALMOST* all of
the information I need. Specifically, when a pointer grab is
activated Enter and Leave events are sent with mode = NotifyGrab and
when this grab is terminated Enter and Leave events are sent with mode
== NotifyUngrab. Likewise, when a keyboard grab is activated FocusIn
and FocusOut events are sent with mode = NotifyGrab and when this grab
is terminated FocusIn and FocusOut events are sent with mode ==
NotifyUngrab. So this tells me when grabs trigger and when they
terminate.
Unfortunately, there is no way provided through the current X protocol
which will allow me to figure out what type of grab triggered. If a
user-defined passive grab triggers, I need to determine the 3D grab
object by mapping the window ID in the Enter event (which is a 3D
proxy window) to the grab node. For this I use a hashtable that I
update whenever a 3D proxy window is added or removed. If a default
button grab triggers, I figure out the 3D object by simply using the
one from the previous event. (In general, the DS Picker stores a
1-to-1 mapping between 3D objects and the events they hit. This is
stored in a queue and is indexed by a "pick sequence" number which
travels along with the event as it goes through the X server and comes
back to the DS). Lastly, figuring out the 3D object for an active grab
is easy. Whenever an LG client calls a method which triggers an active
grab, I just maintain a queue of this information, and I whenever
I find out that an active grab has triggered I read this queue and
from it get the 3D grab object.
The problem is that these mappings depend on knowing what type of grab
triggered and with the current X protocol I have know way of knowing
this.
One possible way to solve the problem is to add to the X server the
notion of an "Notify Grab Verbose (or Extended)" mode. This would be a
global boolean mode of the server. When disabled, the X server would
behave as normal. When the mode is enabled, when grab activation and
deactivation generate enter, leave, focusin and focusout events whose
mode == NotifyGrab, the event will contain additional detail about the
type of grab. There are three possible states:
State 1: Grab was triggered due to an active grab
State 2: Grab was triggered due to a user-defined passive grab
State 3: Grab was triggered due to a default button passive grab
Therefore, it takes 2 bits to encode this information. There is enough
space for this in the focus event structure but, unfortunately, there
is only 1 bit free in the enterleave event structure. This bit is bit
15 of the state field (bits 0-12 are used by normal, unextended X and
bits 13 and 14 are used by XKB). Note that we cannot steal any bits
from any other fields in this structure because these fields are used
for value testing whereas the state field is the only field which is
accessed through bit testing.
So, unfortunately, piggybacking this information on the existing
enter/leave events isn't going to solve the problem--there isn't
enough space. I have thought about sending out two near-identical
enterleave events, one with active vs. passive encoded in
state[15] and the other with default vs. user-defined encoded
in state[15]. To unaware X clients these two events should
look identical. Many X clients will be able to handle this but
I can imagine some clients which will freak out if a window is
entered twice or left twice. So the idea of two enterleave events
isn't a very robust solution.
The only reasonable way I can think of to solve this problem is to
return to the idea of the new GrabStateChange event. This event
will provide 2 bits of information and will be sent out after
enterleave and focus events whose mode != NotifyNormal. To implement
this approach, we should abandon the idea of a global mode switch
and introduce a request which will tell the X server which window
(or windows) to which to send the new event.
Can you think of any other ways to solve this problem?
More information about the xorg-arch
mailing list