This is a significant shift in how input events are perceived. The common
approach was to treat a core event as a different entity than the XI event.
This could result in the XI event being delivered to a different client than
the core event. This doesn't work nicely if they come from the same device.
Instead, we treat an input event as a single event, that is delivered through
two separate APIs. So when delivering an event, we first try the XI event,
then the core event. If the window want's neither, we go to the parent and
repeat. Once either core or XI has been delivered, the processing stops.
Important: Different to the previous method, if a client registers for core
button events, the parent window will not get XI events. This should only
cause problems when you're mixing core and XI events, so don't do that!
Generic events don't fit into this yet, they cause me headaches.
This should restore the correct passive grab processing. When checking for
passive grabs, the core event is emulated and we check first for XI grabs on
the window, then for core grabs. Regardless of which event activates the grab,
the XI event is stored in the device's EQ.
When replaying the event, we take the XI event and replay it on the next
window, again including the emulation of the core event.
If two devices are attached to the same master device, pressing button 1 on
each of them leads to two button presses from the same device. Some apps
really don't like that.
So we just put a counter in place and only send the first press and the last
release.
If we have one global filter, one pointer may change the filter value and
affect another pointer.
Reproduceable effect:
blackbox and xterm, start dragging xterm then click anywhere with the other
pointer (attached to different masterd device!). The button release resets
the filter[Motion_Filter(button)] value, thus stopping dragging and no event
is sent to the client anymore.
Having the filters set per device gets around this.
Sometimes (e.g. on my debian ppc box) maxKeysPerModifier of the SD is 0. So we
try to malloc(0), bringing the whole server down with a FatalError because it
looks as if the malloc failed. This is bad, so only alloc if we actually have
something to alloc.
Turns out it's really really hard synchronising device state across multiple
duplicated events if they all share the same struct. So instead of doing so,
when the SD changes deep-copy all it's classes into the MD. The MD then has
the same capabilities, but the state can be set separately. This should fix
xkb, key state, repeat etc. problems.
Updating the device state allows us to remove the SwitchCoreKeyboard from the
event gathering, it's all done during event processing now.
The master needs to have the same devPrivate as the slave, in case a client
issues a request that goes down to the driver.
Example: if a driver wants to ring the keyboard bell, it'll pick a keyboard.
The KeyClassPtr will direct it to the matching method in the driver, but
because the MD doesn't have the devPrivate set the driver segfaults.
Even if all drivers were updated to not dereference the nullpointer, nothing
would actually ever happen.
To avoid this, we flip the master's public.devPrivate to the last SDs
devPrivate.
POE now only deals with processing the event and calling the appropriate
delivery methods. Actually modifying the device state is done in
UpdateDeviceState. This separation should make it easier to avoid setting the
state twice when master events are processed.
Each time a different slave device sends through a master, an
DeviceClassesChangedEvent is enqueued. When this event is processed, all
classes of the matching master device are changed, and the event is sent to
the clients.
Next time the master is queried, it thus shows the evclasses of the last slave
device. The original classes are stored in the devPrivates.
TODO: if all slave devices are removed, the master's original classes need to
be restored.
Let the drivers only generate XI events and put those into the event queue.
When processing events, generate core events as needed. This fixes a number of
problems with XKB and the DIX in general.
The previous approach was to put core events and XI events as separate events
into the event queue. When being processed, the server had no knowledge of
them coming from the same device state change. Anything that would then change
the state of the device accordingly was in danger of changing it twice,
leading to some funny (i.e. not funny at all) results.
Emulating core events while processing XI events fixes this, there is only one
path that actually changes the device state now. Although we have to be
careful when replaying events from synced devices, otherwise we may lose
events.
Note: XI has precedence over core for passive grabs, but core events are
delivered to the client first.
This removes the wrapping added in 340911d724
Followup to [1].
If a core grab causes the device to freeze, it overwrites the processInputProc
of the device. [1] would then overwrite this while unwrapping, the device
does not thaw anymore.
Changing this to only re-wrap if the processInputProc hasn't been changed
during the event handling.
[1] 340911d724
When processing events from the EQ, _always_ call the processInputProc of the
matching device. For XI devices, this proc is wrapped in three layers.
Core event handling is wrapped by XI event handling, which is wrapped by XKB.
A core event now passes through XKB -> XI -> DIX.
This gets rid of a sync'd grab problem: with the previous code, core events
did disappear during a sync'd device grab on account of mieqProcessInputEvents
calling the processInputProc of the VCP/VCK instead of the actual device. This
lead to the event being processed as normal instead of being enqueued for
later replaying.
The device state needs to be changed while processing the XI event. Core
events are always processed after XI, so by then the device is already set up
properly. However, we now rely on DeviceButtonMotionMask to be equal to
ButtonMotionMask. It already is, but stick a big fat warning in so nobody
attempts to change it.
This commit disables XKB for the VCK, thus essentially for all devices.
Temporarily anyway.
This is definitely necessary in CheckDeviceGrabAndHintWindow (thanks to Paulo
Zanoni for spotting it). We're resetting it everywhere else too, just to be
save.
Device drivers flush their buttons on device init and cause a button down
event to be generated. If we unconditionally decrease the buttons, we won't be
able to ever get a passive device grab.
Format documentation for CheckDeviceGrabs to make it readable.
(cherry picked from commit 3e894974cd)
Conflicts:
Xi/exevents.c
Device drivers flush their buttons on device init and cause a button down
event to be generated. If we unconditionally decrease the buttons, we won't be
able to ever get a passive device grab.
Format documentation for CheckDeviceGrabs to make it readable.