summaryrefslogtreecommitdiff
path: root/dix/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'dix/events.c')
-rw-r--r--dix/events.c251
1 files changed, 167 insertions, 84 deletions
diff --git a/dix/events.c b/dix/events.c
index 87d2ef746..bb5520af9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -117,7 +117,6 @@ of the copyright holder.
#endif
#include <X11/X.h>
-#include <X11/keysym.h>
#include "misc.h"
#include "resource.h"
#include <X11/Xproto.h>
@@ -135,9 +134,6 @@ of the copyright holder.
#include <X11/extensions/XKBproto.h>
#include "xkbsrv.h"
-/* XKB FIXME: why is this here? */
-extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
-
#include "xace.h"
#ifdef XSERVER_DTRACE
@@ -167,6 +163,7 @@ typedef const char *string;
#include "geext.h"
#include "geint.h"
+#include "eventstr.h"
#include "enterleave.h"
#include "eventconvert.h"
@@ -233,6 +230,9 @@ static Bool CheckPassiveGrabsOnWindow(WindowPtr pWin,
DeviceEvent *event,
BOOL checkCore);
+/** Key repeat hack. Do not use but in TryClientEvents */
+extern BOOL EventIsKeyRepeat(xEvent *event);
+
/**
* Main input device struct.
* inputInfo.pointer
@@ -1551,7 +1551,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
Bool isPassive = autoGrab & ~ImplicitGrabMask;
/* slave devices need to float for the duration of the grab. */
- if (!(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
+ if (grab->grabtype == GRABTYPE_XI2 &&
+ !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
DetachFromMaster(mouse);
if (grab->confineTo)
@@ -1562,7 +1563,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
mouse->spriteInfo->sprite->hotPhys.y = 0;
ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
}
- DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
+ DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
mouse->valuator->motionHintWindow = NullWindow;
if (syncEvents.playingEvents)
grabinfo->grabTime = syncEvents.time;
@@ -1601,7 +1602,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
if (dev->deviceGrab.sync.other == grab)
dev->deviceGrab.sync.other = NullGrab;
}
- DoEnterLeaveEvents(mouse, grab->window,
+ DoEnterLeaveEvents(mouse, mouse->id, grab->window,
mouse->spriteInfo->sprite->win, NotifyUngrab);
if (grab->confineTo)
ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE);
@@ -1609,7 +1610,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
if (grab->cursor)
FreeCursor(grab->cursor, (Cursor)0);
- if (!wasImplicit)
+ if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
ReattachToOldMaster(mouse);
ComputeFreezes();
@@ -1627,7 +1628,9 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
WindowPtr oldWin;
/* slave devices need to float for the duration of the grab. */
- if (!(passive & ImplicitGrabMask) && !IsMaster(keybd))
+ if (grab->grabtype == GRABTYPE_XI2 &&
+ !(passive & ImplicitGrabMask) &&
+ !IsMaster(keybd))
DetachFromMaster(keybd);
if (grabinfo->grab)
@@ -1680,7 +1683,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
}
DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
- if (!wasImplicit)
+ if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
ReattachToOldMaster(keybd);
ComputeFreezes();
@@ -1924,70 +1927,124 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
int type;
#ifdef DEBUG_EVENTS
- ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d",
- pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
+ ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
+ pEvents->u.u.type, pEvents->u.u.detail, mask,
+ client ? client->index : -1,
+ (client && client->clientGone) ? " (gone)" : "");
#endif
- if ((client) && (client != serverClient) && (!client->clientGone) &&
- ((filter == CantBeFiltered) || (mask & filter)))
- {
- if (grab && !SameClient(grab, client))
- return -1; /* don't send, but notify caller */
- type = pEvents->u.u.type;
- if (type == MotionNotify)
- {
- if (mask & PointerMotionHintMask)
- {
- if (WID(dev->valuator->motionHintWindow) ==
- pEvents->u.keyButtonPointer.event)
- {
+
+ if (!client || client == serverClient || client->clientGone) {
#ifdef DEBUG_EVENTS
- ErrorF("[dix] \n");
- ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
+ ErrorF(" not delivered to fake/dead client\n");
#endif
- return 1; /* don't send, but pretend we did */
- }
- pEvents->u.u.detail = NotifyHint;
- }
- else
- {
- pEvents->u.u.detail = NotifyNormal;
- }
- }
- else
- {
- if ((type == DeviceMotionNotify) &&
- MaybeSendDeviceMotionNotifyHint
- ((deviceKeyButtonPointer*)pEvents, mask) != 0)
- return 1;
- }
- type &= 0177;
- if (type != KeymapNotify)
- {
- /* all extension events must have a sequence number */
- for (i = 0; i < count; i++)
- pEvents[i].u.u.sequenceNumber = client->sequence;
- }
+ return 0;
+ }
- if (BitIsOn(criticalEvents, type))
- {
- if (client->smart_priority < SMART_MAX_PRIORITY)
- client->smart_priority++;
- SetCriticalOutputPending();
- }
+ if (filter != CantBeFiltered && !(mask & filter))
+ {
+ #ifdef DEBUG_EVENTS
+ ErrorF(" filtered\n");
+ #endif
+ return 0;
+ }
- WriteEventsToClient(client, count, pEvents);
+ if (grab && !SameClient(grab, client))
+ {
#ifdef DEBUG_EVENTS
- ErrorF("[dix] delivered\n");
+ ErrorF(" not delivered due to grab\n");
#endif
- return 1;
+ return -1; /* don't send, but notify caller */
}
- else
+
+ type = pEvents->u.u.type;
+ if (type == MotionNotify)
{
+ if (mask & PointerMotionHintMask)
+ {
+ if (WID(dev->valuator->motionHintWindow) ==
+ pEvents->u.keyButtonPointer.event)
+ {
#ifdef DEBUG_EVENTS
- ErrorF("[dix] \n");
+ ErrorF("[dix] \n");
+ ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
#endif
- return 0;
+ return 1; /* don't send, but pretend we did */
+ }
+ pEvents->u.u.detail = NotifyHint;
+ }
+ else
+ {
+ pEvents->u.u.detail = NotifyNormal;
+ }
}
+ else if (type == DeviceMotionNotify)
+ {
+ if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents,
+ mask) != 0)
+ return 1;
+ } else if (type == KeyPress)
+ {
+ if (EventIsKeyRepeat(pEvents))
+ {
+ if (!_XkbWantsDetectableAutoRepeat(client))
+ {
+ xEvent release = *pEvents;
+ release.u.u.type = KeyRelease;
+ release.u.u.sequenceNumber = client->sequence;
+ WriteEventsToClient(client, 1, &release);
+#ifdef DEBUG_EVENTS
+ ErrorF(" (plus fake core release for repeat)");
+#endif
+ } else
+ {
+#ifdef DEBUG_EVENTS
+ ErrorF(" (detectable autorepeat for core)");
+#endif
+ }
+ }
+
+ } else if (type == DeviceKeyPress)
+ {
+ if (EventIsKeyRepeat(pEvents))
+ {
+ if (!_XkbWantsDetectableAutoRepeat(client))
+ {
+ deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
+ release.type = DeviceKeyRelease;
+ release.sequenceNumber = client->sequence;
+#ifdef DEBUG_EVENTS
+ ErrorF(" (plus fake xi1 release for repeat)");
+#endif
+ WriteEventsToClient(client, 1, (xEvent *) &release);
+ }
+ else {
+#ifdef DEBUG_EVENTS
+ ErrorF(" (detectable autorepeat for core)");
+#endif
+ }
+ }
+ }
+
+ type &= 0177;
+ if (type != KeymapNotify)
+ {
+ /* all extension events must have a sequence number */
+ for (i = 0; i < count; i++)
+ pEvents[i].u.u.sequenceNumber = client->sequence;
+ }
+
+ if (BitIsOn(criticalEvents, type))
+ {
+ if (client->smart_priority < SMART_MAX_PRIORITY)
+ client->smart_priority++;
+ SetCriticalOutputPending();
+ }
+
+ WriteEventsToClient(client, count, pEvents);
+#ifdef DEBUG_EVENTS
+ ErrorF("[dix] delivered\n");
+#endif
+ return 1;
}
@@ -2288,7 +2345,14 @@ FixUpEventFromWindow(
{
xXIDeviceEvent* event = (xXIDeviceEvent*)xE;
- if (event->evtype == XI_RawEvent)
+ if (event->evtype == XI_RawKeyPress ||
+ event->evtype == XI_RawKeyRelease ||
+ event->evtype == XI_RawButtonPress ||
+ event->evtype == XI_RawButtonRelease ||
+ event->evtype == XI_RawMotion ||
+ event->evtype == XI_DeviceChanged ||
+ event->evtype == XI_HierarchyChanged ||
+ event->evtype == XI_PropertyEvent)
return;
event->root = RootWindow(pDev)->drawable.id;
@@ -2740,7 +2804,7 @@ ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
if (dev->deviceGrab.grab->window == win ||
IsParent(dev->deviceGrab.grab->window, win))
return FALSE;
- DoEnterLeaveEvents(dev, old, win, XINotifyPassiveUngrab);
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
(*dev->deviceGrab.DeactivateGrab)(dev);
}
@@ -2757,7 +2821,7 @@ ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
event.detail.button = 0;
rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE);
if (rc)
- DoEnterLeaveEvents(dev, old, win, XINotifyPassiveUngrab);
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
return rc;
}
@@ -2780,7 +2844,7 @@ ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
if (dev->deviceGrab.grab->window == win ||
IsParent(dev->deviceGrab.grab->window, win))
return FALSE;
- DoEnterLeaveEvents(dev, old, win, XINotifyPassiveUngrab);
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
(*dev->deviceGrab.DeactivateGrab)(dev);
}
@@ -2794,7 +2858,7 @@ ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
event.detail.button = 0;
rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE);
if (rc)
- DoEnterLeaveEvents(dev, old, win, XINotifyPassiveGrab);
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
return rc;
}
@@ -2909,12 +2973,16 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
if (newSpriteWin != prevSpriteWin)
{
- if (!ev)
+ int sourceid;
+ if (!ev) {
UpdateCurrentTimeIf();
+ sourceid = pDev->id; /* when from WindowsRestructured */
+ } else
+ sourceid = ev->sourceid;
if (prevSpriteWin != NullWindow) {
if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
- DoEnterLeaveEvents(pDev, prevSpriteWin,
+ DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
newSpriteWin, NotifyNormal);
}
/* set pSprite->win after ActivateEnterGrab, otherwise
@@ -2937,7 +3005,7 @@ WindowsRestructured(void)
DeviceIntPtr pDev = inputInfo.devices;
while(pDev)
{
- if (DevHasCursor(pDev))
+ if (IsMaster(pDev) || !pDev->u.master)
CheckMotion(NULL, pDev);
pDev = pDev->next;
}
@@ -3543,6 +3611,7 @@ CheckPassiveGrabsOnWindow(
{
DeviceIntPtr gdev;
XkbSrvInfoPtr xkbi = NULL;
+ Mask mask = 0;
gdev= grab->modifierDevice;
if (grab->grabtype == GRABTYPE_CORE)
@@ -3570,8 +3639,6 @@ CheckPassiveGrabsOnWindow(
/* Check for XI2 and XI grabs first */
tempGrab.type = GetXI2Type((InternalEvent*)event);
tempGrab.grabtype = GRABTYPE_XI2;
- if (event->type == ET_KeyPress)
- tempGrab.detail.exact = XkbGetKeysym(device, event);
if (GrabMatchesSecond(&tempGrab, grab, FALSE))
match = XI2_MATCH;
@@ -3659,6 +3726,7 @@ CheckPassiveGrabsOnWindow(
}
xE = &core;
count = 1;
+ mask = grab->eventMask;
} else if (match & XI2_MATCH)
{
rc = EventToXI2((InternalEvent*)event, &xE);
@@ -3670,6 +3738,16 @@ CheckPassiveGrabsOnWindow(
continue;
}
count = 1;
+
+ /* FIXME: EventToXI2 returns NULL for enter events, so
+ * dereferencing the event is bad. Internal event types are
+ * aligned with core events, so the else clause is valid.
+ * long-term we should use internal events for enter/focus
+ * as well */
+ if (xE)
+ mask = grab->xi2mask[device->id][((xGenericEvent*)xE)->evtype/8];
+ else if (event->type == XI_Enter || event->type == XI_FocusIn)
+ mask = grab->xi2mask[device->id][event->type/8];
} else
{
rc = EventToXI((InternalEvent*)event, &xE, &count);
@@ -3680,6 +3758,7 @@ CheckPassiveGrabsOnWindow(
"(%d, %d).\n", device->name, event->type, rc);
continue;
}
+ mask = grab->eventMask;
}
(*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
@@ -3688,8 +3767,7 @@ CheckPassiveGrabsOnWindow(
{
FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
- TryClientEvents(rClient(grab), device, xE, count,
- GetEventFilter(device, xE),
+ TryClientEvents(rClient(grab), device, xE, count, mask,
GetEventFilter(device, xE), grab);
}
@@ -4404,6 +4482,7 @@ CoreEnterLeaveEvent(
void
DeviceEnterLeaveEvent(
DeviceIntPtr mouse,
+ int sourceid,
int type,
int mode,
int detail,
@@ -4420,8 +4499,8 @@ DeviceEnterLeaveEvent(
(mode == XINotifyPassiveUngrab && type == XI_Enter))
return;
- btlen = (mouse->button) ? (mouse->button->numButtons + 7)/8 : 0;
- btlen = (btlen + 3)/4;
+ btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
+ btlen = bytes_to_int32(btlen);
len = sizeof(xXIEnterEvent) + btlen * 4;
event = xcalloc(1, len);
@@ -4433,7 +4512,7 @@ DeviceEnterLeaveEvent(
event->detail = detail;
event->time = currentTime.milliseconds;
event->deviceid = mouse->id;
- event->sourceid = 0; /*XXX */
+ event->sourceid = sourceid;
event->mode = mode;
event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
@@ -5261,7 +5340,7 @@ ProcUngrabKey(ClientPtr client)
int rc;
REQUEST_SIZE_MATCH(xUngrabKeyReq);
- rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
+ rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
if (rc != Success)
return rc;
@@ -5729,8 +5808,8 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
int i,
eventlength = sizeof(xEvent);
- if (!XkbFilterEvents(pClient, count, events))
- return;
+ /* Let XKB rewrite the state, as it depends on client preferences. */
+ XkbFilterEvents(pClient, count, events);
#ifdef PANORAMIX
if(!noPanoramiXExtension &&
@@ -5842,21 +5921,25 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
* PickPointer()).
* If a keyboard is needed, the first keyboard paired with the CP is used.
*/
-Bool
+int
SetClientPointer(ClientPtr client, DeviceIntPtr device)
{
+ int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
+ if (rc != Success)
+ return rc;
+
if (!IsMaster(device))
{
ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
- return FALSE;
+ return BadDevice;
} else if (!device->spriteInfo->spriteOwner)
{
ErrorF("[dix] Device %d does not have a sprite. "
"Cannot be ClientPointer\n", device->id);
- return FALSE;
+ return BadDevice;
}
client->clientPtr = device;
- return TRUE;
+ return Success;
}
/* PickPointer will pick an appropriate pointer for the given client.