diff options
Diffstat (limited to 'xorg-server/Xi/exevents.c')
-rw-r--r-- | xorg-server/Xi/exevents.c | 1403 |
1 files changed, 740 insertions, 663 deletions
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index 56e1d4439..edd775c3b 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -52,19 +52,19 @@ SOFTWARE. * */ -#define NEED_EVENTS #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #else #define XINPUT #endif +#include "inputstr.h" #include <X11/X.h> #include <X11/Xproto.h> #include <X11/extensions/XI.h> #include <X11/extensions/XIproto.h> +#include <X11/extensions/XI2proto.h> #include <X11/extensions/geproto.h> -#include "inputstr.h" #include "windowstr.h" #include "miscstruct.h" #include "region.h" @@ -76,12 +76,12 @@ SOFTWARE. #include "scrnintstr.h" #include "listdev.h" /* for CopySwapXXXClass */ #include "xace.h" +#include "xiquerydevice.h" /* For List*Info */ +#include "eventconvert.h" +#include "eventstr.h" -#ifdef XKB #include <X11/extensions/XKBproto.h> #include "xkbsrv.h" -extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); -#endif #define WID(w) ((w) ? ((w)->drawable.id) : 0) #define AllModifiersMask ( \ @@ -89,8 +89,6 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); Mod3Mask | Mod4Mask | Mod5Mask ) #define AllButtonsMask ( \ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) -#define Motion_Filter(class) (DevicePointerMotionMask | \ - (class)->state | (class)->motionMask) Bool ShouldFreeInputMasks(WindowPtr /* pWin */ , Bool /* ignoreSelectedEvents */ @@ -101,6 +99,22 @@ static Bool MakeInputMasks(WindowPtr /* pWin */ /* Used to sture classes currently not in use by an MD */ extern DevPrivateKey UnusedClassesPrivateKey; +/* + * Only let the given client know of core events which will affect its + * interpretation of input events, if the client's ClientPointer (or the + * paired keyboard) is the current device. + */ +int +XIShouldNotify(ClientPtr client, DeviceIntPtr dev) +{ + DeviceIntPtr current_ptr = PickPointer(client); + DeviceIntPtr current_kbd = GetPairedDevice(current_ptr); + + if (dev == current_kbd || dev == current_ptr) + return 1; + + return 0; +} void RegisterOtherDevice(DeviceIntPtr device) @@ -110,25 +124,17 @@ RegisterOtherDevice(DeviceIntPtr device) } Bool -IsPointerEvent(xEvent* xE) +IsPointerEvent(InternalEvent* event) { - switch(xE->u.u.type) + switch(event->any.type) { - case ButtonPress: - case ButtonRelease: - case MotionNotify: - case EnterNotify: - case LeaveNotify: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_Motion: + /* XXX: enter/leave ?? */ return TRUE; default: - if (xE->u.u.type == DeviceButtonPress || - xE->u.u.type == DeviceButtonRelease || - xE->u.u.type == DeviceMotionNotify || - xE->u.u.type == ProximityIn || - xE->u.u.type == ProximityOut) - { - return TRUE; - } + break; } return FALSE; } @@ -188,88 +194,23 @@ XIGetDevice(xEvent* xE) * This code is basically the old SwitchCoreKeyboard. */ -void +static void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) { - static DeviceIntPtr lastMapNotifyDevice = NULL; - KeyClassPtr mk, dk; /* master, device */ - BOOL sendNotify = FALSE; + KeyClassPtr mk = master->key; + KeyClassPtr dk = device->key; int i; if (device == master) return; - dk = device->key; - mk = master->key; + mk->sourceid = device->id; - if (device != dixLookupPrivate(&master->devPrivates, - CoreDevicePrivateKey)) { - memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH); + for (i = 0; i < 8; i++) + mk->modifierKeyCount[i] = dk->modifierKeyCount[i]; - if (dk->maxKeysPerModifier) - { - mk->modifierKeyMap = xrealloc(mk->modifierKeyMap, - 8 * dk->maxKeysPerModifier); - if (!mk->modifierKeyMap) - FatalError("[Xi] no memory for class shift.\n"); - memcpy(mk->modifierKeyMap, dk->modifierKeyMap, - (8 * dk->maxKeysPerModifier)); - } else - { - xfree(mk->modifierKeyMap); - mk->modifierKeyMap = NULL; - } - - mk->maxKeysPerModifier = dk->maxKeysPerModifier; - mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode; - mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode; - SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms); - - /* - * Copy state from the extended keyboard to core. If you omit this, - * holding Ctrl on keyboard one, and pressing Q on keyboard two, will - * cause your app to quit. This feels wrong to me, hence the below - * code. - * - * XXX: If you synthesise core modifier events, the state will get - * clobbered here. You'll have to work out something sensible - * to fix that. Good luck. - */ - -#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \ - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) - mk->state &= ~(KEYBOARD_MASK); - mk->state |= (dk->state & KEYBOARD_MASK); -#undef KEYBOARD_MASK - for (i = 0; i < 8; i++) - mk->modifierKeyCount[i] = dk->modifierKeyCount[i]; - -#ifdef XKB - if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) { - if (!mk->xkbInfo || !mk->xkbInfo->desc) - { - XkbInitDevice(master); - XkbFinishDeviceInit(master); - } - if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True)) - FatalError("Couldn't pivot keymap from device to core!\n"); - } -#endif - - dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, device); - sendNotify = TRUE; - } else if (lastMapNotifyDevice != master) - sendNotify = TRUE; - - if (sendNotify) - { - SendMappingNotify(master, MappingKeyboard, - mk->curKeySyms.minKeyCode, - (mk->curKeySyms.maxKeyCode - - mk->curKeySyms.minKeyCode), - serverClient); - lastMapNotifyDevice = master; - } + if (!XkbCopyDeviceKeymap(master, device)) + FatalError("Couldn't pivot keymap from device to core!\n"); } /** @@ -282,82 +223,6 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) { ClassesPtr classes; - if (from->kbdfeed) - { - KbdFeedbackPtr *k, it; - - if (!to->kbdfeed) - { - classes = dixLookupPrivate(&to->devPrivates, - UnusedClassesPrivateKey); - to->kbdfeed = classes->kbdfeed; - } - - k = &to->kbdfeed; - for(it = from->kbdfeed; it; it = it->next) - { - if (!(*k)) - { - *k = xcalloc(1, sizeof(KbdFeedbackClassRec)); - if (!*k) - { - ErrorF("[Xi] Cannot alloc memory for class copy."); - return; - } - } - (*k)->BellProc = it->BellProc; - (*k)->CtrlProc = it->CtrlProc; - (*k)->ctrl = it->ctrl; -#ifdef XKB - if ((*k)->xkb_sli) - XkbFreeSrvLedInfo((*k)->xkb_sli); - (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL); -#endif - - k = &(*k)->next; - } - } else if (to->kbdfeed && !from->kbdfeed) - { - ClassesPtr classes; - classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); - classes->kbdfeed = to->kbdfeed; - to->kbdfeed = NULL; - } - - if (from->ptrfeed) - { - PtrFeedbackPtr *p, it; - if (!to->ptrfeed) - { - classes = dixLookupPrivate(&to->devPrivates, - UnusedClassesPrivateKey); - to->ptrfeed = classes->ptrfeed; - } - - p = &to->ptrfeed; - for (it = from->ptrfeed; it; it = it->next) - { - if (!(*p)) - { - *p = xcalloc(1, sizeof(PtrFeedbackClassRec)); - if (!*p) - { - ErrorF("[Xi] Cannot alloc memory for class copy."); - return; - } - } - (*p)->CtrlProc = it->CtrlProc; - (*p)->ctrl = it->ctrl; - - p = &(*p)->next; - } - } else if (to->ptrfeed && !from->ptrfeed) - { - ClassesPtr classes; - classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); - classes->ptrfeed = to->ptrfeed; - to->ptrfeed = NULL; - } if (from->intfeed) { @@ -493,11 +358,9 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) } (*l)->CtrlProc = it->CtrlProc; (*l)->ctrl = it->ctrl; -#ifdef XKB if ((*l)->xkb_sli) XkbFreeSrvLedInfo((*l)->xkb_sli); (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l); -#endif l = &(*l)->next; } @@ -510,74 +373,161 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) } } -/** - * Copies the CONTENT of the classes of device from into the classes in device - * to. From and to are identical after finishing. - * - * If to does not have classes from currenly has, the classes are stored in - * to's devPrivates system. Later, we recover it again from there if needed. - * Saves a few memory allocations. - */ - -void -DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) +static void +DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to) { ClassesPtr classes; /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the * kbdfeed to be set up properly, so let's do the feedback classes first. */ - DeepCopyFeedbackClasses(from, to); + if (from->kbdfeed) + { + KbdFeedbackPtr *k, it; + + if (!to->kbdfeed) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + + to->kbdfeed = classes->kbdfeed; + if (!to->kbdfeed) + InitKeyboardDeviceStruct(to, NULL, NULL, NULL); + } + + k = &to->kbdfeed; + for(it = from->kbdfeed; it; it = it->next) + { + if (!(*k)) + { + *k = xcalloc(1, sizeof(KbdFeedbackClassRec)); + if (!*k) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*k)->BellProc = it->BellProc; + (*k)->CtrlProc = it->CtrlProc; + (*k)->ctrl = it->ctrl; + if ((*k)->xkb_sli) + XkbFreeSrvLedInfo((*k)->xkb_sli); + (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL); + + k = &(*k)->next; + } + } else if (to->kbdfeed && !from->kbdfeed) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->kbdfeed = to->kbdfeed; + to->kbdfeed = NULL; + } if (from->key) { - KeyCode *oldModKeyMap; - KeySym *oldMap; -#ifdef XKB - struct _XkbSrvInfo *oldXkbInfo; -#endif if (!to->key) { classes = dixLookupPrivate(&to->devPrivates, - UnusedClassesPrivateKey); + UnusedClassesPrivateKey); to->key = classes->key; if (!to->key) + InitKeyboardDeviceStruct(to, NULL, NULL, NULL); + else + classes->key = NULL; + } + + CopyKeyClass(from, to); + } else if (to->key && !from->key) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->key = to->key; + to->key = NULL; + } + + /* We can't just copy over the focus class. When an app sets the focus, + * it'll do so on the master device. Copying the SDs focus means losing + * the focus. + * So we only copy the focus class if the device didn't have one, + * otherwise we leave it as it is. + */ + if (from->focus) + { + if (!to->focus) + { + WindowPtr *oldTrace; + + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->focus = classes->focus; + if (!to->focus) { - to->key = xcalloc(1, sizeof(KeyClassRec)); - if (!to->key) + to->focus = xcalloc(1, sizeof(FocusClassRec)); + if (!to->focus) FatalError("[Xi] no memory for class shift.\n"); } else - classes->key = NULL; + classes->focus = NULL; + + oldTrace = to->focus->trace; + memcpy(to->focus, from->focus, sizeof(FocusClassRec)); + to->focus->trace = xrealloc(oldTrace, + to->focus->traceSize * sizeof(WindowPtr)); + if (!to->focus->trace && to->focus->traceSize) + FatalError("[Xi] no memory for trace.\n"); + memcpy(to->focus->trace, from->focus->trace, + from->focus->traceSize * sizeof(WindowPtr)); + to->focus->sourceid = from->id; } + } else if (to->focus) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->focus = to->focus; + to->focus = NULL; + } - oldModKeyMap = to->key->modifierKeyMap; - oldMap = to->key->curKeySyms.map; -#ifdef XKB - oldXkbInfo = to->key->xkbInfo; -#endif +} - if (!oldMap) /* newly created key struct */ +static void +DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) +{ + ClassesPtr classes; + + /* Feedback classes must be copied first */ + if (from->ptrfeed) + { + PtrFeedbackPtr *p, it; + if (!to->ptrfeed) { - int bytes = (to->key->curKeySyms.maxKeyCode - - to->key->curKeySyms.minKeyCode + 1) * - to->key->curKeySyms.mapWidth; - oldMap = (KeySym *)xcalloc(sizeof(KeySym), bytes); - memcpy(oldMap, from->key->curKeySyms.map, bytes); + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->ptrfeed = classes->ptrfeed; } - to->key->modifierKeyMap = oldModKeyMap; - to->key->curKeySyms.map = oldMap; -#ifdef XKB - to->key->xkbInfo = oldXkbInfo; -#endif + p = &to->ptrfeed; + for (it = from->ptrfeed; it; it = it->next) + { + if (!(*p)) + { + *p = xcalloc(1, sizeof(PtrFeedbackClassRec)); + if (!*p) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*p)->CtrlProc = it->CtrlProc; + (*p)->ctrl = it->ctrl; - CopyKeyClass(from, to); - } else if (to->key && !from->key) + p = &(*p)->next; + } + } else if (to->ptrfeed && !from->ptrfeed) { ClassesPtr classes; classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); - classes->key = to->key; - to->key = NULL; + classes->ptrfeed = to->ptrfeed; + to->ptrfeed = NULL; } if (from->valuator) @@ -594,7 +544,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) + from->valuator->numAxes * sizeof(AxisInfo) + - from->valuator->numAxes * sizeof(unsigned int)); + from->valuator->numAxes * sizeof(double)); v = to->valuator; if (!v) FatalError("[Xi] no memory for class shift.\n"); @@ -603,7 +553,9 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) v->axes = (AxisInfoPtr)&v[1]; memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo)); - v->axisVal = (int*)(v->axes + from->valuator->numAxes); + v->axisVal = (double*)(v->axes + from->valuator->numAxes); + v->sourceid = from->id; + v->mode = from->valuator->mode; } else if (to->valuator && !from->valuator) { ClassesPtr classes; @@ -628,7 +580,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) classes->button = NULL; } -#ifdef XKB if (from->button->xkb_acts) { if (!to->button->xkb_acts) @@ -641,7 +592,10 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) sizeof(XkbAction)); } else xfree(to->button->xkb_acts); -#endif + + memcpy(to->button->labels, from->button->labels, + from->button->numButtons * sizeof(Atom)); + to->button->sourceid = from->id; } else if (to->button && !from->button) { ClassesPtr classes; @@ -650,47 +604,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) to->button = NULL; } - - /* We can't just copy over the focus class. When an app sets the focus, - * it'll do so on the master device. Copying the SDs focus means losing - * the focus. - * So we only copy the focus class if the device didn't have one, - * otherwise we leave it as it is. - */ - if (from->focus) - { - if (!to->focus) - { - WindowPtr *oldTrace; - - classes = dixLookupPrivate(&to->devPrivates, - UnusedClassesPrivateKey); - to->focus = classes->focus; - if (!to->focus) - { - to->focus = xcalloc(1, sizeof(FocusClassRec)); - if (!to->focus) - FatalError("[Xi] no memory for class shift.\n"); - } else - classes->focus = NULL; - - oldTrace = to->focus->trace; - memcpy(to->focus, from->focus, sizeof(FocusClassRec)); - to->focus->trace = xrealloc(oldTrace, - to->focus->traceSize * sizeof(WindowPtr)); - if (!to->focus->trace && to->focus->traceSize) - FatalError("[Xi] no memory for trace.\n"); - memcpy(to->focus->trace, from->focus->trace, - from->focus->traceSize * sizeof(WindowPtr)); - } - } else if (to->focus) - { - ClassesPtr classes; - classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); - classes->focus = to->focus; - to->focus = NULL; - } - if (from->proximity) { if (!to->proximity) @@ -707,6 +620,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) classes->proximity = NULL; } memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec)); + to->proximity->sourceid = from->id; } else if (to->proximity) { ClassesPtr classes; @@ -731,6 +645,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) classes->absolute = NULL; } memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec)); + to->absolute->sourceid = from->id; } else if (to->absolute) { ClassesPtr classes; @@ -740,6 +655,78 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) } } +/** + * Copies the CONTENT of the classes of device from into the classes in device + * to. From and to are identical after finishing. + * + * If to does not have classes from currenly has, the classes are stored in + * to's devPrivates system. Later, we recover it again from there if needed. + * Saves a few memory allocations. + */ +void +DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce) +{ + /* generic feedback classes, not tied to pointer and/or keyboard */ + DeepCopyFeedbackClasses(from, to); + + if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT)) + DeepCopyKeyboardClasses(from, to); + if ((dce->flags & DEVCHANGE_POINTER_EVENT)) + DeepCopyPointerClasses(from, to); +} + + +/** + * Send an XI2 DeviceChangedEvent to all interested clients. + */ +void +XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce) +{ + xXIDeviceChangedEvent *dcce; + int rc; + + rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce); + if (rc != Success) + { + ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc); + return; + } + + /* we don't actually swap if there's a NullClient, swapping is done + * later when event is delivered. */ + SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1); + xfree(dcce); +} + +static void +ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce) +{ + DeviceIntPtr slave; + int rc; + + /* For now, we don't have devices that change physically. */ + if (!IsMaster(device)) + return; + + rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess); + + if (rc != Success) + return; /* Device has disappeared */ + + if (!slave->u.master) + return; /* set floating since the event */ + + if (slave->u.master->id != dce->masterid) + return; /* not our slave anymore, don't care */ + + /* FIXME: we probably need to send a DCE for the new slave now */ + + device->public.devicePrivate = slave->public.devicePrivate; + + /* FIXME: the classes may have changed since we generated the event. */ + DeepCopyDeviceClasses(slave, device, dce); + XISendDeviceChangedEvent(slave, device, dce); +} /** * Update the device state according to the data in the event. @@ -747,147 +734,106 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) * return values are * DEFAULT ... process as normal * DONT_PROCESS ... return immediately from caller - * IS_REPEAT .. event is a repeat event. */ #define DEFAULT 0 #define DONT_PROCESS 1 -#define IS_REPEAT 2 int -UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count) +UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event) { int i; int key = 0, - bit = 0; + bit = 0, + last_valuator; KeyClassPtr k = NULL; ButtonClassPtr b = NULL; ValuatorClassPtr v = NULL; - deviceValuator *xV = (deviceValuator *) xE; BYTE *kptr = NULL; - CARD16 modifiers = 0, - mask = 0; - /* currently no other generic event modifies the device */ - if (xE->u.u.type == GenericEvent) - return DEFAULT; + /* This event is always the first we get, before the actual events with + * the data. However, the way how the DDX is set up, "device" will + * actually be the slave device that caused the event. + */ + switch(event->type) + { + case ET_DeviceChanged: + ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event); + return DONT_PROCESS; /* event has been sent already */ + case ET_Motion: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ProximityIn: + case ET_ProximityOut: + break; + default: + /* other events don't update the device */ + return DEFAULT; + } k = device->key; v = device->valuator; b = device->button; + key = event->detail.key; + bit = 1 << (key & 7); - if (xE->u.u.type != DeviceValuator) + /* Update device axis */ + /* Check valuators first */ + last_valuator = -1; + for (i = 0; i < MAX_VALUATORS; i++) { - key = xE->u.u.detail; - bit = 1 << (key & 7); + if (BitIsOn(&event->valuators.mask, i)) + { + if (!v) + { + ErrorF("[Xi] Valuators reported for non-valuator device '%s'. " + "Ignoring event.\n", device->name); + return DONT_PROCESS; + } else if (v->numAxes < i) + { + ErrorF("[Xi] Too many valuators reported for device '%s'. " + "Ignoring event.\n", device->name); + return DONT_PROCESS; + } + last_valuator = i; + } } - /* Update device axis */ - /* Don't update valuators for the VCP, it never sends XI events anyway */ - for (i = 1; !device->isMaster && i < count; i++) { - if ((++xV)->type == DeviceValuator) { - int *axisvals; - int first = xV->first_valuator; - BOOL change = FALSE; - - - if (xV->num_valuators && - (!v || (xV->num_valuators && - (first + xV->num_valuators > v->numAxes)))) - FatalError("Bad valuators reported for device %s\n", - device->name); - if (v && v->axisVal) { - /* v->axisVal is always in absolute coordinates. Only the - * delivery mode changes. - * If device is mode Absolute - * dev = event - * If device is mode Relative - * swap = (event - device) - * dev = event - * event = delta - */ - int delta; - axisvals = v->axisVal; - if (v->mode == Relative) /* device reports relative */ - change = TRUE; - - switch (xV->num_valuators) { - case 6: - if (change) delta = xV->valuator5 - *(axisvals + first + 5); - *(axisvals + first + 5) = xV->valuator5; - if (change) xV->valuator5 = delta; - case 5: - if (change) delta = xV->valuator4 - *(axisvals + first + 4); - *(axisvals + first + 4) = xV->valuator4; - if (change) xV->valuator4 = delta; - case 4: - if (change) delta = xV->valuator3 - *(axisvals + first + 3); - *(axisvals + first + 3) = xV->valuator3; - if (change) xV->valuator3 = delta; - case 3: - if (change) delta = xV->valuator2 - *(axisvals + first + 2); - *(axisvals + first + 2) = xV->valuator2; - if (change) xV->valuator2 = delta; - case 2: - if (change) delta = xV->valuator1 - *(axisvals + first + 1); - *(axisvals + first + 1) = xV->valuator1; - if (change) xV->valuator1 = delta; - case 1: - if (change) delta = xV->valuator0 - *(axisvals + first); - *(axisvals + first) = xV->valuator0; - if (change) xV->valuator0 = delta; - case 0: - default: - break; - } - } - } + for (i = 0; i <= last_valuator && i < v->numAxes; i++) + { + if (BitIsOn(&event->valuators.mask, i)) + { + /* XXX: Relative/Absolute mode */ + v->axisVal[i] = event->valuators.data[i]; + v->axisVal[i] += event->valuators.data_frac[i]; + } } - if (xE->u.u.type == DeviceKeyPress) { + if (event->type == ET_KeyPress) { if (!k) return DONT_PROCESS; - modifiers = k->modifierMap[key]; kptr = &k->down[key >> 3]; - if (*kptr & bit) { /* allow ddx to generate multiple downs */ - return IS_REPEAT; - } + /* don't allow ddx to generate multiple downs, but repeats are okay */ + if ((*kptr & bit) && !event->key_repeat) + return DONT_PROCESS; if (device->valuator) device->valuator->motionHintWindow = NullWindow; *kptr |= bit; - k->prev_state = k->state; - for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { - if (mask & modifiers) { - /* This key affects modifier "i" */ - k->modifierKeyCount[i]++; - k->state |= mask; - modifiers &= ~mask; - } - } - } else if (xE->u.u.type == DeviceKeyRelease) { + } else if (event->type == ET_KeyRelease) { if (!k) return DONT_PROCESS; kptr = &k->down[key >> 3]; if (!(*kptr & bit)) /* guard against duplicates */ return DONT_PROCESS; - modifiers = k->modifierMap[key]; if (device->valuator) device->valuator->motionHintWindow = NullWindow; *kptr &= ~bit; - k->prev_state = k->state; - for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { - if (mask & modifiers) { - /* This key affects modifier "i" */ - if (--k->modifierKeyCount[i] <= 0) { - k->modifierKeyCount[i] = 0; - k->state &= ~mask; - } - modifiers &= ~mask; - } - } - } else if (xE->u.u.type == DeviceButtonPress) { + } else if (event->type == ET_ButtonPress) { + Mask mask; if (!b) return DONT_PROCESS; @@ -903,15 +849,21 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count) b->motionMask = DeviceButtonMotionMask; if (b->map[key] <= 5) b->state |= (Button1Mask >> 1) << b->map[key]; - SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify); - } else if (xE->u.u.type == DeviceButtonRelease) { + + /* Add state and motionMask to the filter for this event */ + mask = DevicePointerMotionMask | b->state | b->motionMask; + SetMaskForEvent(device->id, mask, DeviceMotionNotify); + mask = PointerMotionMask | b->state | b->motionMask; + SetMaskForEvent(device->id, mask, MotionNotify); + } else if (event->type == ET_ButtonRelease) { + Mask mask; if (!b) return DONT_PROCESS; kptr = &b->down[key>>3]; if (!(*kptr & bit)) return DONT_PROCESS; - if (device->isMaster) { + if (IsMaster(device)) { DeviceIntPtr sd; /* @@ -920,7 +872,9 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count) * event being delivered through the slave first */ for (sd = inputInfo.devices; sd; sd = sd->next) { - if (sd->isMaster || sd->u.master != device) + if (IsMaster(sd) || sd->u.master != device) + continue; + if (!sd->button) continue; if ((sd->button->down[key>>3] & bit) != 0) return DONT_PROCESS; @@ -935,35 +889,76 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count) b->motionMask = 0; if (b->map[key] <= 5) b->state &= ~((Button1Mask >> 1) << b->map[key]); - SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify); - } else if (xE->u.u.type == ProximityIn) + + /* Add state and motionMask to the filter for this event */ + mask = DevicePointerMotionMask | b->state | b->motionMask; + SetMaskForEvent(device->id, mask, DeviceMotionNotify); + mask = PointerMotionMask | b->state | b->motionMask; + SetMaskForEvent(device->id, mask, MotionNotify); + } else if (event->type == ET_ProximityIn) device->valuator->mode &= ~OutOfProximity; - else if (xE->u.u.type == ProximityOut) + else if (event->type == ET_ProximityOut) device->valuator->mode |= OutOfProximity; return DEFAULT; } +static void +ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) +{ + GrabPtr grab = device->deviceGrab.grab; + + if (grab) + DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE); + else { /* deliver to all root windows */ + xEvent *xi; + int i; + + i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); + if (i != Success) + { + ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n", + device->name, i); + return; + } + + for (i = 0; i < screenInfo.numScreens; i++) + DeliverEventsToWindow(device, WindowTable[i], xi, 1, + GetEventFilter(device, xi), NULL); + xfree(xi); + } +} + /** * Main device event processing function. * Called from when processing the events from the event queue. * */ void -ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) +ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) { - int i; - CARD16 modifiers; - GrabPtr grab = device->deviceGrab.grab; + GrabPtr grab; Bool deactivateDeviceGrab = FALSE; int key = 0, rootX, rootY; ButtonClassPtr b; KeyClassPtr k; ValuatorClassPtr v; - deviceValuator *xV = (deviceValuator *) xE; int ret = 0; - int state; + int state, i; DeviceIntPtr mouse = NULL, kbd = NULL; + DeviceEvent *event = (DeviceEvent*)ev; + + CHECKEVENT(ev); + + if (ev->any.type == ET_RawKeyPress || + ev->any.type == ET_RawKeyRelease || + ev->any.type == ET_RawButtonPress || + ev->any.type == ET_RawButtonRelease || + ev->any.type == ET_RawMotion) + { + ProcessRawEvent((RawDeviceEvent*)ev, device); + return; + } if (IsPointerDevice(device)) { @@ -980,10 +975,34 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) } /* State needs to be assembled BEFORE the device is updated. */ - state = (kbd) ? kbd->key->state : 0; - state |= (mouse) ? (mouse->button->state) : 0; + state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0; + state |= (mouse && mouse->button) ? (mouse->button->state) : 0; + + for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) + if (BitIsOn(mouse->button->down, i)) + SetBit(event->buttons, i); - ret = UpdateDeviceState(device, xE, count); + if (kbd && kbd->key) + { + XkbStatePtr state; + /* we need the state before the event happens */ + if (event->type == ET_KeyPress || event->type == ET_KeyRelease) + state = &kbd->key->xkbInfo->prev_state; + else + state = &kbd->key->xkbInfo->state; + + event->mods.base = state->base_mods; + event->mods.latched = state->latched_mods; + event->mods.locked = state->locked_mods; + event->mods.effective = state->mods; + + event->group.base = state->base_group; + event->group.latched = state->latched_group; + event->group.locked = state->locked_group; + event->group.effective = state->group; + } + + ret = UpdateDeviceState(device, event); if (ret == DONT_PROCESS) return; @@ -991,19 +1010,31 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) b = device->button; k = device->key; - if (device->isMaster) - CheckMotion(xE, device); - - if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) { - GetSpritePosition(device, &rootX, &rootY); - xE->u.keyButtonPointer.rootX = rootX; - xE->u.keyButtonPointer.rootY = rootY; - NoticeEventTime(xE); + if (IsMaster(device) || !device->u.master) + CheckMotion(event, device); - xE->u.keyButtonPointer.state = state; - - key = xE->u.u.detail; + switch (event->type) + { + case ET_Motion: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ProximityIn: + case ET_ProximityOut: + GetSpritePosition(device, &rootX, &rootY); + event->root_x = rootX; + event->root_y = rootY; + NoticeEventTime((InternalEvent*)event); + event->corestate = state; + key = event->detail.key; + break; + default: + break; } + +#if 0 + /* FIXME: I'm broken. Please fix me. Thanks */ if (DeviceEventCallback) { DeviceEventInfoRec eventinfo; @@ -1011,84 +1042,70 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) eventinfo.count = count; CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); } +#endif + grab = device->deviceGrab.grab; - /* Valuator event handling */ - /* Don't care about valuators for the VCP, it never sends XI events */ - - for (i = 1; !device->isMaster && i < count; i++) { - if ((++xV)->type == DeviceValuator) { - int first = xV->first_valuator; - if (xV->num_valuators - && (!v - || (xV->num_valuators - && (first + xV->num_valuators > v->numAxes)))) - FatalError("Bad valuators reported for device %s\n", - device->name); - xV->device_state = 0; - if (k) - xV->device_state |= k->state; - if (b) - xV->device_state |= b->state; - } + switch(event->type) + { + case ET_KeyPress: + if (!grab && CheckDeviceGrabs(device, event, 0)) { + device->deviceGrab.activatingKey = key; + return; + } + break; + case ET_KeyRelease: + if (grab && device->deviceGrab.fromPassiveGrab && + (key == device->deviceGrab.activatingKey) && + (device->deviceGrab.grab->type == KeyPress || + device->deviceGrab.grab->type == DeviceKeyPress || + device->deviceGrab.grab->type == XI_KeyPress)) + deactivateDeviceGrab = TRUE; + break; + case ET_ButtonPress: + event->detail.button = b->map[key]; + if (!event->detail.button) { /* there's no button 0 */ + event->detail.button = key; + return; + } + if (!grab && CheckDeviceGrabs(device, event, 0)) + { + /* if a passive grab was activated, the event has been sent + * already */ + return; + } + break; + case ET_ButtonRelease: + event->detail.button = b->map[key]; + if (!event->detail.button) { /* there's no button 0 */ + event->detail.button = key; + return; + } + if (grab && !b->buttonsDown && + device->deviceGrab.fromPassiveGrab && + (device->deviceGrab.grab->type == ButtonPress || + device->deviceGrab.grab->type == DeviceButtonPress || + device->deviceGrab.grab->type == XI_ButtonPress)) + deactivateDeviceGrab = TRUE; + default: + break; } - if (xE->u.u.type == DeviceKeyPress) { - if (ret == IS_REPEAT) { /* allow ddx to generate multiple downs */ - modifiers = k->modifierMap[key]; - if (!modifiers) { - xE->u.u.type = DeviceKeyRelease; - ProcessOtherEvent(xE, device, count); - xE->u.u.type = DeviceKeyPress; - /* release can have side effects, don't fall through */ - ProcessOtherEvent(xE, device, count); - } - return; - } - if (!grab && CheckDeviceGrabs(device, xE, 0, count)) { - device->deviceGrab.activatingKey = key; - return; - } - } else if (xE->u.u.type == DeviceKeyRelease) { - if (device->deviceGrab.fromPassiveGrab && - (key == device->deviceGrab.activatingKey)) - deactivateDeviceGrab = TRUE; - } else if (xE->u.u.type == DeviceButtonPress) { - xE->u.u.detail = b->map[key]; - if (xE->u.u.detail == 0) { - xE->u.u.detail = key; - return; - } - if (!grab && CheckDeviceGrabs(device, xE, 0, count)) - { - /* if a passive grab was activated, the event has been sent - * already */ - return; - } - - } else if (xE->u.u.type == DeviceButtonRelease) { - xE->u.u.detail = b->map[key]; - if (xE->u.u.detail == 0) { - xE->u.u.detail = key; - return; - } - if (!b->buttonsDown && device->deviceGrab.fromPassiveGrab) - deactivateDeviceGrab = TRUE; - } if (grab) - DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count); - else if (device->focus && !IsPointerEvent(xE)) - DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count); + DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab); + else if (device->focus && !IsPointerEvent((InternalEvent*)ev)) + DeliverFocusedEvent(device, (InternalEvent*)event, + GetSpriteWindow(device)); else - DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow, - device, count); + DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event, + NullGrab, NullWindow, device); if (deactivateDeviceGrab == TRUE) (*device->deviceGrab.DeactivateGrab) (device); - xE->u.u.detail = key; + event->detail.key = key; } -_X_EXPORT int +int InitProximityClassDeviceStruct(DeviceIntPtr dev) { ProximityClassPtr proxc; @@ -1096,6 +1113,7 @@ InitProximityClassDeviceStruct(DeviceIntPtr dev) proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec)); if (!proxc) return FALSE; + proxc->sourceid = dev->id; dev->proximity = proxc; return TRUE; } @@ -1109,14 +1127,16 @@ InitProximityClassDeviceStruct(DeviceIntPtr dev) * * @see InitValuatorClassDeviceStruct */ -_X_EXPORT void -InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval, +void +InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, int resolution, int min_res, int max_res) { AxisInfoPtr ax; if (!dev || !dev->valuator || minval > maxval) return; + if (axnum >= dev->valuator->numAxes) + return; ax = dev->valuator->axes + axnum; @@ -1125,6 +1145,7 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval, ax->resolution = resolution; ax->min_resolution = min_res; ax->max_resolution = max_res; + ax->label = label; } static void @@ -1145,7 +1166,8 @@ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k, memcpy((char*)ev->buttons, (char*)b->down, 4); } else if (k) { ev->classes_reported |= (1 << KeyClass); - ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode; + ev->num_keys = k->xkbInfo->desc->max_key_code - + k->xkbInfo->desc->min_key_code; memmove((char *)&ev->keys[0], (char *)k->down, 4); } if (v) { @@ -1193,21 +1215,65 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) { deviceFocus event; + xXIFocusInEvent *xi2event; + DeviceIntPtr mouse; + int btlen, len, i; + + mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev; + + /* XI 2 event */ + btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; + btlen = bytes_to_int32(btlen); + len = sizeof(xXIFocusInEvent) + btlen * 4; + + xi2event = xcalloc(1, len); + xi2event->type = GenericEvent; + xi2event->extension = IReqCode; + xi2event->evtype = type; + xi2event->length = bytes_to_int32(len - sizeof(xEvent)); + xi2event->buttons_len = btlen; + xi2event->detail = detail; + xi2event->time = currentTime.milliseconds; + xi2event->deviceid = dev->id; + xi2event->sourceid = dev->id; /* a device doesn't change focus by itself */ + xi2event->mode = mode; + xi2event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0); + xi2event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0); + + for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) + if (BitIsOn(mouse->button->down, i)) + SetBit(&xi2event[1], i); + + if (dev->key) + { + xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods; + xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods; + xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods; + xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods; + + xi2event->group.base_group = dev->key->xkbInfo->state.base_group; + xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group; + xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group; + xi2event->group.effective_group = dev->key->xkbInfo->state.group; + } - if (type == FocusIn) - type = DeviceFocusIn; - else - type = DeviceFocusOut; + FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE); + + DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1, + GetEventFilter(dev, (xEvent*)xi2event), NullGrab); + xfree(xi2event); + + /* XI 1.x event */ event.deviceid = dev->id; event.mode = mode; - event.type = type; + event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut; event.detail = detail; event.window = pWin->drawable.id; event.time = currentTime.milliseconds; - (void)DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1, - DeviceFocusChangeMask, NullGrab, dev->id); + DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1, + DeviceFocusChangeMask, NullGrab); if ((type == DeviceFocusIn) && (wOtherInputMasks(pWin)) && @@ -1229,7 +1295,8 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, evcount++; } if ((k = dev->key) != NULL) { - nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode; + nkeys = k->xkbInfo->desc->max_key_code - + k->xkbInfo->desc->min_key_code; if (nkeys > 32) evcount++; if (nbuttons > 0) { @@ -1302,147 +1369,203 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, } } - (void)DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount, - DeviceStateNotifyMask, NullGrab, dev->id); + DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount, + DeviceStateNotifyMask, NullGrab); xfree(sev); } } int -GrabButton(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode, - BYTE other_devices_mode, CARD16 modifiers, - DeviceIntPtr modifier_device, CARD8 button, Window grabWindow, - BOOL ownerEvents, Cursor rcursor, Window rconfineTo, Mask eventMask) +CheckGrabValues(ClientPtr client, GrabParameters* param) { - WindowPtr pWin, confineTo; - CursorPtr cursor; - GrabPtr grab; - Mask access_mode = DixGrabAccess; - int rc; + if (param->grabtype != GRABTYPE_CORE && + param->grabtype != GRABTYPE_XI && + param->grabtype != GRABTYPE_XI2) + { + ErrorF("[Xi] grabtype is invalid. This is a bug.\n"); + return BadImplementation; + } - if ((this_device_mode != GrabModeSync) && - (this_device_mode != GrabModeAsync)) { - client->errorValue = this_device_mode; + if ((param->this_device_mode != GrabModeSync) && + (param->this_device_mode != GrabModeAsync)) { + client->errorValue = param->this_device_mode; return BadValue; } - if ((other_devices_mode != GrabModeSync) && - (other_devices_mode != GrabModeAsync)) { - client->errorValue = other_devices_mode; + if ((param->other_devices_mode != GrabModeSync) && + (param->other_devices_mode != GrabModeAsync)) { + client->errorValue = param->other_devices_mode; return BadValue; } - if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) { - client->errorValue = modifiers; + + if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) && + (param->modifiers & ~AllModifiersMask)) { + client->errorValue = param->modifiers; return BadValue; } - if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) { - client->errorValue = ownerEvents; + + if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) { + client->errorValue = param->ownerEvents; return BadValue; } - rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); + return Success; +} + +int +GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, + int button, GrabParameters *param, GrabType grabtype, + GrabMask *mask) +{ + WindowPtr pWin, confineTo; + CursorPtr cursor; + GrabPtr grab; + int rc, type = -1; + Mask access_mode = DixGrabAccess; + + rc = CheckGrabValues(client, param); if (rc != Success) return rc; - if (rconfineTo == None) + if (param->confineTo == None) confineTo = NullWindow; else { - rc = dixLookupWindow(&confineTo, rconfineTo, client, DixSetAttrAccess); + rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess); if (rc != Success) return rc; } - if (rcursor == None) + if (param->cursor == None) cursor = NullCursor; else { - rc = dixLookupResourceByType((pointer *)&cursor, rcursor, RT_CURSOR, - client, DixUseAccess); + rc = dixLookupResourceByType((pointer *)&cursor, param->cursor, + RT_CURSOR, client, DixUseAccess); if (rc != Success) { - client->errorValue = rcursor; + client->errorValue = param->cursor; return (rc == BadValue) ? BadCursor : rc; } access_mode |= DixForceAccess; } - if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync) + if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync) access_mode |= DixFreezeAccess; rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); if (rc != Success) return rc; + rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); + if (rc != Success) + return rc; - grab = CreateGrab(client->index, dev, pWin, eventMask, - (Bool) ownerEvents, (Bool) this_device_mode, - (Bool) other_devices_mode, modifier_device, modifiers, - DeviceButtonPress, button, confineTo, cursor); + if (grabtype == GRABTYPE_XI) + type = DeviceButtonPress; + else if (grabtype == GRABTYPE_XI2) + type = XI_ButtonPress; + + grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, + mask, param, type, button, confineTo, cursor); if (!grab) return BadAlloc; return AddPassiveGrabToList(client, grab); } +/** + * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If + * grabtype is GRABTYPE_XI2, the key is a keysym. + */ int -GrabKey(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode, - BYTE other_devices_mode, CARD16 modifiers, - DeviceIntPtr modifier_device, CARD8 key, Window grabWindow, - BOOL ownerEvents, Mask mask) +GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, + int key, GrabParameters *param, GrabType grabtype, GrabMask *mask) { WindowPtr pWin; GrabPtr grab; KeyClassPtr k = dev->key; Mask access_mode = DixGrabAccess; - int rc; + int rc, type = -1; + rc = CheckGrabValues(client, param); + if (rc != Success) + return rc; if (k == NULL) return BadMatch; - if ((other_devices_mode != GrabModeSync) && - (other_devices_mode != GrabModeAsync)) { - client->errorValue = other_devices_mode; - return BadValue; - } - if ((this_device_mode != GrabModeSync) && - (this_device_mode != GrabModeAsync)) { - client->errorValue = this_device_mode; - return BadValue; - } - if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode)) - && (key != AnyKey)) { - client->errorValue = key; - return BadValue; - } - if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) { - client->errorValue = modifiers; - return BadValue; - } - if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) { - client->errorValue = ownerEvents; - return BadValue; - } - rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); + if (grabtype == GRABTYPE_XI) + { + if ((key > k->xkbInfo->desc->max_key_code || + key < k->xkbInfo->desc->min_key_code) + && (key != AnyKey)) { + client->errorValue = key; + return BadValue; + } + type = DeviceKeyPress; + } else if (grabtype == GRABTYPE_XI2) + type = XI_KeyPress; + + rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); if (rc != Success) return rc; - if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync) + if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync) access_mode |= DixFreezeAccess; rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); if (rc != Success) return rc; - grab = CreateGrab(client->index, dev, pWin, - mask, ownerEvents, this_device_mode, other_devices_mode, - modifier_device, modifiers, DeviceKeyPress, key, - NullWindow, NullCursor); + grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, + mask, param, type, key, NULL, NULL); if (!grab) return BadAlloc; return AddPassiveGrabToList(client, grab); } +/* Enter/FocusIn grab */ +int +GrabWindow(ClientPtr client, DeviceIntPtr dev, int type, + GrabParameters *param, GrabMask *mask) +{ + WindowPtr pWin; + CursorPtr cursor; + GrabPtr grab; + Mask access_mode = DixGrabAccess; + int rc; + + rc = CheckGrabValues(client, param); + if (rc != Success) + return rc; + + rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); + if (rc != Success) + return rc; + if (param->cursor == None) + cursor = NullCursor; + else { + rc = dixLookupResourceByType((pointer *)&cursor, param->cursor, + RT_CURSOR, client, DixUseAccess); + if (rc != Success) + { + client->errorValue = param->cursor; + return (rc == BadValue) ? BadCursor : rc; + } + access_mode |= DixForceAccess; + } + if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync) + access_mode |= DixFreezeAccess; + rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); + if (rc != Success) + return rc; + + grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2, + mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, + 0, NULL, cursor); + + if (!grab) + return BadAlloc; + + return AddPassiveGrabToList(client, grab); +} + int SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, - Mask mask, Mask exclusivemasks, Mask validmasks) + Mask mask, Mask exclusivemasks) { int mskidx = dev->id; int i, ret; Mask check; InputClientsPtr others; - if (mask & ~validmasks) { - client->errorValue = mask; - return BadValue; - } check = (mask & exclusivemasks); if (wOtherInputMasks(pWin)) { if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different @@ -1530,15 +1653,20 @@ RecalculateDeviceDeliverableEvents(WindowPtr pWin) InputClientsPtr others; struct _OtherInputMasks *inputMasks; /* default: NULL */ WindowPtr pChild, tmp; - int i; + int i, j; pChild = pWin; while (1) { if ((inputMasks = wOtherInputMasks(pChild)) != 0) { + for (i = 0; i < EMASKSIZE; i++) + memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i])); for (others = inputMasks->inputClients; others; others = others->next) { for (i = 0; i < EMASKSIZE; i++) inputMasks->inputEvents[i] |= others->mask[i]; + for (i = 0; i < EMASKSIZE; i++) + for (j = 0; j < XI2MASKSIZE; j++) + inputMasks->xi2mask[i][j] |= others->xi2mask[i][j]; } for (i = 0; i < EMASKSIZE; i++) inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; @@ -1646,7 +1774,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, ev->u.u.type |= 0x80; if (propagate) { for (; pWin; pWin = pWin->parent) { - if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id)) + if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab)) return Success; if (pWin == effectiveFocus) return Success; @@ -1656,7 +1784,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, break; } } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count)) - (void)(DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id)); + DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab); return Success; } @@ -1684,111 +1812,6 @@ SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) } int -SetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen, - int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k) -{ - KeyCode *map = NULL; - int inputMapLen; - int i; - - *k = dev->key; - if (*k == NULL) - return BadMatch; - if (len != ((numKeyPerModifier << 1) + rlen)) - return BadLength; - - inputMapLen = 8 * numKeyPerModifier; - - /* - * Now enforce the restriction that "all of the non-zero keycodes must be - * in the range specified by min-keycode and max-keycode in the - * connection setup (else a Value error)" - */ - i = inputMapLen; - while (i--) { - if (inputMap[i] - && (inputMap[i] < (*k)->curKeySyms.minKeyCode - || inputMap[i] > (*k)->curKeySyms.maxKeyCode)) { - client->errorValue = inputMap[i]; - return -1; /* BadValue collides with MappingFailed */ - } - } - - /* - * Now enforce the restriction that none of the old or new - * modifier keys may be down while we change the mapping, and - * that the DDX layer likes the choice. - */ - if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap, - (int)(*k)->maxKeysPerModifier, inputMap, - (int)numKeyPerModifier) - || !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier, - (*k)->modifierKeyMap, - (int)(*k)->maxKeysPerModifier)) { - return MappingBusy; - } else { - for (i = 0; i < inputMapLen; i++) { - if (inputMap[i] && !LegalModifier(inputMap[i], dev)) { - return MappingFailed; - } - } - } - - /* - * Now build the keyboard's modifier bitmap from the - * list of keycodes. - */ - if (inputMapLen) { - map = (KeyCode *) xalloc(inputMapLen); - if (!map) - return BadAlloc; - } - if ((*k)->modifierKeyMap) - xfree((*k)->modifierKeyMap); - if (inputMapLen) { - (*k)->modifierKeyMap = map; - memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen); - } else - (*k)->modifierKeyMap = NULL; - - (*k)->maxKeysPerModifier = numKeyPerModifier; - for (i = 0; i < MAP_LENGTH; i++) - (*k)->modifierMap[i] = 0; - for (i = 0; i < inputMapLen; i++) - if (inputMap[i]) { - (*k)->modifierMap[inputMap[i]] - |= (1 << (i / (*k)->maxKeysPerModifier)); - } - - return (MappingSuccess); -} - -void -SendDeviceMappingNotify(ClientPtr client, CARD8 request, - KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev) -{ - xEvent event; - deviceMappingNotify *ev = (deviceMappingNotify *) & event; - - ev->type = DeviceMappingNotify; - ev->request = request; - ev->deviceid = dev->id; - ev->time = currentTime.milliseconds; - if (request == MappingKeyboard) { - ev->firstKeyCode = firstKeyCode; - ev->count = count; - } - -#ifdef XKB - if (!noXkbExtension && (request == MappingKeyboard || - request == MappingModifier)) - XkbApplyMappingChange(dev, request, firstKeyCode, count, client); -#endif - - SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1); -} - -int ChangeKeyMapping(ClientPtr client, DeviceIntPtr dev, unsigned len, @@ -1805,8 +1828,8 @@ ChangeKeyMapping(ClientPtr client, if (len != (keyCodes * keySymsPerKeyCode)) return BadLength; - if ((firstKeyCode < k->curKeySyms.minKeyCode) || - (firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) { + if ((firstKeyCode < k->xkbInfo->desc->min_key_code) || + (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) { client->errorValue = firstKeyCode; return BadValue; } @@ -1818,9 +1841,10 @@ ChangeKeyMapping(ClientPtr client, keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; keysyms.mapWidth = keySymsPerKeyCode; keysyms.map = map; - if (!SetKeySymsMap(&k->curKeySyms, &keysyms)) - return BadAlloc; - SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev); + + XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL, + serverClient); + return client->noClientException; } @@ -1849,7 +1873,8 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) switch (dev->focus->revert) { case RevertToNone: - DoFocusEvents(dev, pWin, NoneWin, focusEventMode); + if (!ActivateFocusInGrab(dev, pWin, NoneWin)) + DoFocusEvents(dev, pWin, NoneWin, focusEventMode); dev->focus->win = NoneWin; dev->focus->traceGood = 0; break; @@ -1860,26 +1885,34 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) dev->focus->traceGood--; } while (!parent->realized); - DoFocusEvents(dev, pWin, parent, focusEventMode); + if (!ActivateFocusInGrab(dev, pWin, parent)) + DoFocusEvents(dev, pWin, parent, focusEventMode); dev->focus->win = parent; dev->focus->revert = RevertToNone; break; case RevertToPointerRoot: - DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); + if (!ActivateFocusInGrab(dev, pWin, PointerRootWin)) + DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); dev->focus->win = PointerRootWin; dev->focus->traceGood = 0; break; case RevertToFollowKeyboard: - if (inputInfo.keyboard->focus->win) { - DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win, - focusEventMode); + { + DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD); + if (!kbd || (kbd == dev && kbd != inputInfo.keyboard)) + kbd = inputInfo.keyboard; + if (kbd->focus->win) { + if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win)) + DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode); dev->focus->win = FollowKeyboardWin; dev->focus->traceGood = 0; } else { - DoFocusEvents(dev, pWin, NoneWin, focusEventMode); + if (!ActivateFocusInGrab(dev, pWin, NoneWin)) + DoFocusEvents(dev, pWin, NoneWin, focusEventMode); dev->focus->win = NoneWin; dev->focus->traceGood = 0; } + } break; } } @@ -1898,8 +1931,6 @@ DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources) struct _OtherInputMasks *inputMasks; for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev == inputInfo.pointer || dev == inputInfo.keyboard) - continue; DeleteDeviceFromAnyExtEvents(pWin, dev); } @@ -1946,7 +1977,7 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, DeviceIntPtr dev; dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient, - DixReadAccess); + DixGrabAccess); if (!dev) return; @@ -1966,7 +1997,6 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, tempGrab.pointerMode = GrabModeAsync; tempGrab.confineTo = NullWindow; tempGrab.cursor = NullCursor; - tempGrab.genericMasks = NULL; tempGrab.next = NULL; (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE); } @@ -2065,7 +2095,7 @@ FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, while (p1) { p2 = p1->firstChild; - (void)DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab, dev->id); + DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab); FindInterestedChildren(dev, p2, mask, ev, count); p1 = p1->nextSib; } @@ -2087,9 +2117,56 @@ SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count) pWin = WindowTable[i]; if (!pWin) continue; - (void)DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab, dev->id); + DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab); p1 = pWin->firstChild; FindInterestedChildren(dev, p1, mask, ev, count); } } +/** + * Set the XI2 mask for the given client on the given window. + * @param dev The device to set the mask for. + * @param win The window to set the mask on. + * @param client The client setting the mask. + * @param len Number of bytes in mask. + * @param mask Event mask in the form of (1 << eventtype) + */ +int +XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, + unsigned int len, unsigned char* mask) +{ + OtherInputMasks *masks; + InputClientsPtr others = NULL; + + masks = wOtherInputMasks(win); + if (masks) + { + for (others = wOtherInputMasks(win)->inputClients; others; + others = others->next) { + if (SameClient(others, client)) { + memset(others->xi2mask[dev->id], 0, + sizeof(others->xi2mask[dev->id])); + break; + } + } + } + + len = min(len, sizeof(others->xi2mask[dev->id])); + + if (len && !others) + { + if (AddExtensionClient(win, client, 0, 0) != Success) + return BadAlloc; + others= wOtherInputMasks(win)->inputClients; + } + + if (others) + memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id])); + + if (len) + memcpy(others->xi2mask[dev->id], mask, len); + + RecalculateDeviceDeliverableEvents(win); + + return Success; +} |