aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xi
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/Xi')
-rw-r--r--xorg-server/Xi/exevents.c4365
-rw-r--r--xorg-server/Xi/makefile55
-rw-r--r--xorg-server/Xi/opendev.c3
-rw-r--r--xorg-server/Xi/xichangehierarchy.c984
-rw-r--r--xorg-server/Xi/xipassivegrab.c614
-rw-r--r--xorg-server/Xi/xiquerydevice.c1006
-rw-r--r--xorg-server/Xi/xiquerypointer.c458
-rw-r--r--xorg-server/Xi/xiwarppointer.c406
8 files changed, 3976 insertions, 3915 deletions
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c
index c7089bb69..b17b61990 100644
--- a/xorg-server/Xi/exevents.c
+++ b/xorg-server/Xi/exevents.c
@@ -1,2178 +1,2187 @@
-/************************************************************
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Hewlett-Packard not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-********************************************************/
-
-/********************************************************************
- *
- * Routines to register and initialize extension input devices.
- * This also contains ProcessOtherEvent, the routine called from DDX
- * to route extension events.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#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 "windowstr.h"
-#include "miscstruct.h"
-#include "region.h"
-#include "exevents.h"
-#include "extnsionst.h"
-#include "exglobals.h"
-#include "dixevents.h" /* DeliverFocusedEvent */
-#include "dixgrabs.h" /* CreateGrab() */
-#include "scrnintstr.h"
-#include "listdev.h" /* for CopySwapXXXClass */
-#include "xace.h"
-#include "xiquerydevice.h" /* For List*Info */
-#include "eventconvert.h"
-#include "eventstr.h"
-
-#include <X11/extensions/XKBproto.h>
-#include "xkbsrv.h"
-
-#define WID(w) ((w) ? ((w)->drawable.id) : 0)
-#define AllModifiersMask ( \
- ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
- Mod3Mask | Mod4Mask | Mod5Mask )
-#define AllButtonsMask ( \
- Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
-
-Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
- Bool /* ignoreSelectedEvents */
- );
-static Bool MakeInputMasks(WindowPtr /* pWin */
- );
-
-/*
- * 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;
-}
-
-Bool
-IsPointerEvent(InternalEvent* event)
-{
- switch(event->any.type)
- {
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_Motion:
- /* XXX: enter/leave ?? */
- return TRUE;
- default:
- break;
- }
- return FALSE;
-}
-
-/**
- * @return the device matching the deviceid of the device set in the event, or
- * NULL if the event is not an XInput event.
- */
-DeviceIntPtr
-XIGetDevice(xEvent* xE)
-{
- DeviceIntPtr pDev = NULL;
-
- 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 ||
- xE->u.u.type == DevicePropertyNotify)
- {
- int rc;
- int id;
-
- id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
-
- rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
- if (rc != Success)
- ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
- }
- return pDev;
-}
-
-
-/**
- * Copy the device->key into master->key and send a mapping notify to the
- * clients if appropriate.
- * master->key needs to be allocated by the caller.
- *
- * Device is the slave device. If it is attached to a master device, we may
- * need to send a mapping notify to the client because it causes the MD
- * to change state.
- *
- * Mapping notify needs to be sent in the following cases:
- * - different slave device on same master
- * - different master
- *
- * XXX: They way how the code is we also send a map notify if the slave device
- * stays the same, but the master changes. This isn't really necessary though.
- *
- * XXX: this gives you funny behaviour with the ClientPointer. When a
- * MappingNotify is sent to the client, the client usually responds with a
- * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
- * mapping, regardless of which keyboard sent the last mapping notify request.
- * So depending on the CP setting, your keyboard may change layout in each
- * app...
- *
- * This code is basically the old SwitchCoreKeyboard.
- */
-
-void
-CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
-{
- KeyClassPtr mk = master->key;
-
- if (device == master)
- return;
-
- mk->sourceid = device->id;
-
-
- if (!XkbCopyDeviceKeymap(master, device))
- FatalError("Couldn't pivot keymap from device to core!\n");
-}
-
-/**
- * Copies the feedback classes from device "from" into device "to". Classes
- * are duplicated (not just flipping the pointers). All feedback classes are
- * linked lists, the full list is duplicated.
- */
-static void
-DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
-{
- ClassesPtr classes;
-
-
- if (from->intfeed)
- {
- IntegerFeedbackPtr *i, it;
-
- if (!to->intfeed)
- {
- classes = to->unused_classes;
- to->intfeed = classes->intfeed;
- classes->intfeed = NULL;
- }
-
- i = &to->intfeed;
- for (it = from->intfeed; it; it = it->next)
- {
- if (!(*i))
- {
- *i = calloc(1, sizeof(IntegerFeedbackClassRec));
- if (!(*i))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*i)->CtrlProc = it->CtrlProc;
- (*i)->ctrl = it->ctrl;
-
- i = &(*i)->next;
- }
- } else if (to->intfeed && !from->intfeed)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->intfeed = to->intfeed;
- to->intfeed = NULL;
- }
-
- if (from->stringfeed)
- {
- StringFeedbackPtr *s, it;
-
- if (!to->stringfeed)
- {
- classes = to->unused_classes;
- to->stringfeed = classes->stringfeed;
- classes->stringfeed = NULL;
- }
-
- s = &to->stringfeed;
- for (it = from->stringfeed; it; it = it->next)
- {
- if (!(*s))
- {
- *s = calloc(1, sizeof(StringFeedbackClassRec));
- if (!(*s))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*s)->CtrlProc = it->CtrlProc;
- (*s)->ctrl = it->ctrl;
-
- s = &(*s)->next;
- }
- } else if (to->stringfeed && !from->stringfeed)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->stringfeed = to->stringfeed;
- to->stringfeed = NULL;
- }
-
- if (from->bell)
- {
- BellFeedbackPtr *b, it;
-
- if (!to->bell)
- {
- classes = to->unused_classes;
- to->bell = classes->bell;
- classes->bell = NULL;
- }
-
- b = &to->bell;
- for (it = from->bell; it; it = it->next)
- {
- if (!(*b))
- {
- *b = calloc(1, sizeof(BellFeedbackClassRec));
- if (!(*b))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*b)->BellProc = it->BellProc;
- (*b)->CtrlProc = it->CtrlProc;
- (*b)->ctrl = it->ctrl;
-
- b = &(*b)->next;
- }
- } else if (to->bell && !from->bell)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->bell = to->bell;
- to->bell = NULL;
- }
-
- if (from->leds)
- {
- LedFeedbackPtr *l, it;
-
- if (!to->leds)
- {
- classes = to->unused_classes;
- to->leds = classes->leds;
- classes->leds = NULL;
- }
-
- l = &to->leds;
- for (it = from->leds; it; it = it->next)
- {
- if (!(*l))
- {
- *l = calloc(1, sizeof(LedFeedbackClassRec));
- if (!(*l))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*l)->CtrlProc = it->CtrlProc;
- (*l)->ctrl = it->ctrl;
- if ((*l)->xkb_sli)
- XkbFreeSrvLedInfo((*l)->xkb_sli);
- (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
-
- l = &(*l)->next;
- }
- } else if (to->leds && !from->leds)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->leds = to->leds;
- to->leds = NULL;
- }
-}
-
-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.
- */
- if (from->kbdfeed)
- {
- KbdFeedbackPtr *k, it;
-
- if (!to->kbdfeed)
- {
- classes = to->unused_classes;
-
- to->kbdfeed = classes->kbdfeed;
- if (!to->kbdfeed)
- InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
- classes->kbdfeed = NULL;
- }
-
- k = &to->kbdfeed;
- for(it = from->kbdfeed; it; it = it->next)
- {
- if (!(*k))
- {
- *k = calloc(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 = to->unused_classes;
- classes->kbdfeed = to->kbdfeed;
- to->kbdfeed = NULL;
- }
-
- if (from->key)
- {
- if (!to->key)
- {
- classes = to->unused_classes;
- 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 = to->unused_classes;
- classes->key = to->key;
- to->key = NULL;
- }
-
- /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
- * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
- * didn't update the pointers so we need to do it manually here.
- */
- if (to->kbdfeed)
- {
- KbdFeedbackPtr k;
-
- for (k = to->kbdfeed; k; k = k->next)
- {
- if (!k->xkb_sli)
- continue;
- if (k->xkb_sli->flags & XkbSLI_IsDefault)
- {
- k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
- k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
- }
- }
- }
-
- /* 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 = to->unused_classes;
- to->focus = classes->focus;
- if (!to->focus)
- {
- to->focus = calloc(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 = realloc(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 = to->unused_classes;
- classes->focus = to->focus;
- to->focus = NULL;
- }
-
-}
-
-static void
-DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
-{
- ClassesPtr classes;
-
- /* Feedback classes must be copied first */
- if (from->ptrfeed)
- {
- PtrFeedbackPtr *p, it;
- if (!to->ptrfeed)
- {
- classes = to->unused_classes;
- to->ptrfeed = classes->ptrfeed;
- classes->ptrfeed = NULL;
- }
-
- p = &to->ptrfeed;
- for (it = from->ptrfeed; it; it = it->next)
- {
- if (!(*p))
- {
- *p = calloc(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 = to->unused_classes;
- classes->ptrfeed = to->ptrfeed;
- to->ptrfeed = NULL;
- }
-
- if (from->valuator)
- {
- ValuatorClassPtr v;
- if (!to->valuator)
- {
- classes = to->unused_classes;
- to->valuator = classes->valuator;
- if (to->valuator)
- classes->valuator = NULL;
- }
-
- to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
- from->valuator->numAxes * sizeof(AxisInfo) +
- from->valuator->numAxes * sizeof(double));
- v = to->valuator;
- if (!v)
- FatalError("[Xi] no memory for class shift.\n");
-
- v->numAxes = from->valuator->numAxes;
- v->axes = (AxisInfoPtr)&v[1];
- memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
-
- v->axisVal = (double*)(v->axes + from->valuator->numAxes);
- v->sourceid = from->id;
- } else if (to->valuator && !from->valuator)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->valuator = to->valuator;
- to->valuator = NULL;
- }
-
- if (from->button)
- {
- if (!to->button)
- {
- classes = to->unused_classes;
- to->button = classes->button;
- if (!to->button)
- {
- to->button = calloc(1, sizeof(ButtonClassRec));
- if (!to->button)
- FatalError("[Xi] no memory for class shift.\n");
- } else
- classes->button = NULL;
- }
-
- if (from->button->xkb_acts)
- {
- if (!to->button->xkb_acts)
- {
- to->button->xkb_acts = calloc(1, sizeof(XkbAction));
- if (!to->button->xkb_acts)
- FatalError("[Xi] not enough memory for xkb_acts.\n");
- }
- memcpy(to->button->xkb_acts, from->button->xkb_acts,
- sizeof(XkbAction));
- } else
- free(to->button->xkb_acts);
-
- 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;
- classes = to->unused_classes;
- classes->button = to->button;
- to->button = NULL;
- }
-
- if (from->proximity)
- {
- if (!to->proximity)
- {
- classes = to->unused_classes;
- to->proximity = classes->proximity;
- if (!to->proximity)
- {
- to->proximity = calloc(1, sizeof(ProximityClassRec));
- if (!to->proximity)
- FatalError("[Xi] no memory for class shift.\n");
- } else
- classes->proximity = NULL;
- }
- memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
- to->proximity->sourceid = from->id;
- } else if (to->proximity)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->proximity = to->proximity;
- to->proximity = NULL;
- }
-
- if (from->absolute)
- {
- if (!to->absolute)
- {
- classes = to->unused_classes;
- to->absolute = classes->absolute;
- if (!to->absolute)
- {
- to->absolute = calloc(1, sizeof(AbsoluteClassRec));
- if (!to->absolute)
- FatalError("[Xi] no memory for class shift.\n");
- } else
- classes->absolute = NULL;
- }
- memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
- to->absolute->sourceid = from->id;
- } else if (to->absolute)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->absolute = to->absolute;
- to->absolute = NULL;
- }
-}
-
-/**
- * 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);
- free(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 (IsMaster(slave))
- return;
-
- if (IsFloating(slave))
- return; /* set floating since the event */
-
- if (GetMaster(slave, MASTER_ATTACHED)->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.
- *
- * return values are
- * DEFAULT ... process as normal
- * DONT_PROCESS ... return immediately from caller
- */
-#define DEFAULT 0
-#define DONT_PROCESS 1
-int
-UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
-{
- int i;
- int key = 0,
- bit = 0,
- last_valuator;
-
- KeyClassPtr k = NULL;
- ButtonClassPtr b = NULL;
- ValuatorClassPtr v = NULL;
-
- /* 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);
-
- /* Update device axis */
- /* Check valuators first */
- last_valuator = -1;
- for (i = 0; i < MAX_VALUATORS; i++)
- {
- 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;
- }
- }
-
- 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] * 1.0f / (1 << 16) / (1 << 16));
- }
- }
-
- if (event->type == ET_KeyPress) {
- if (!k)
- return DONT_PROCESS;
-
- /* don't allow ddx to generate multiple downs, but repeats are okay */
- if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
- return DONT_PROCESS;
-
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- set_key_down(device, key, KEY_PROCESSED);
- } else if (event->type == ET_KeyRelease) {
- if (!k)
- return DONT_PROCESS;
-
- if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */
- return DONT_PROCESS;
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- set_key_up(device, key, KEY_PROCESSED);
- } else if (event->type == ET_ButtonPress) {
- Mask mask;
- if (!b)
- return DONT_PROCESS;
-
- if (button_is_down(device, key, BUTTON_PROCESSED))
- return DONT_PROCESS;
-
- set_button_down(device, key, BUTTON_PROCESSED);
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- if (!b->map[key])
- return DONT_PROCESS;
- b->buttonsDown++;
- b->motionMask = DeviceButtonMotionMask;
- if (b->map[key] <= 5)
- b->state |= (Button1Mask >> 1) << b->map[key];
-
- /* 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;
-
- if (!button_is_down(device, key, BUTTON_PROCESSED))
- return DONT_PROCESS;
- if (IsMaster(device)) {
- DeviceIntPtr sd;
-
- /*
- * Leave the button down if any slave has the
- * button still down. Note that this depends on the
- * event being delivered through the slave first
- */
- for (sd = inputInfo.devices; sd; sd = sd->next) {
- if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
- continue;
- if (!sd->button)
- continue;
- for (i = 1; i <= sd->button->numButtons; i++)
- if (sd->button->map[i] == key &&
- button_is_down(sd, i, BUTTON_PROCESSED))
- return DONT_PROCESS;
- }
- }
- set_button_up(device, key, BUTTON_PROCESSED);
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- if (!b->map[key])
- return DONT_PROCESS;
- if (b->buttonsDown >= 1 && !--b->buttonsDown)
- b->motionMask = 0;
- if (b->map[key] <= 5)
- b->state &= ~((Button1Mask >> 1) << b->map[key]);
-
- /* 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->proximity->in_proximity = TRUE;
- else if (event->type == ET_ProximityOut)
- device->proximity->in_proximity = FALSE;
-
- 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, screenInfo.screens[i]->root, xi, 1,
- GetEventFilter(device, xi), NULL);
- free(xi);
- }
-}
-
-/**
- * Main device event processing function.
- * Called from when processing the events from the event queue.
- *
- */
-void
-ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
-{
- GrabPtr grab;
- Bool deactivateDeviceGrab = FALSE;
- int key = 0, rootX, rootY;
- ButtonClassPtr b;
- KeyClassPtr k;
- ValuatorClassPtr v;
- int ret = 0;
- int state, i;
- DeviceIntPtr mouse = NULL, kbd = NULL;
- DeviceEvent *event = &ev->device_event;
-
- 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(&ev->raw_event, device);
- return;
- }
-
- if (IsPointerDevice(device))
- {
- kbd = GetPairedDevice(device);
- mouse = device;
- if (!kbd->key) /* can happen with floating SDs */
- kbd = NULL;
- } else
- {
- mouse = GetPairedDevice(device);
- kbd = device;
- if (!mouse->valuator || !mouse->button) /* may be float. SDs */
- mouse = NULL;
- }
-
- /* State needs to be assembled BEFORE the device is updated. */
- 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);
-
- 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;
-
- v = device->valuator;
- b = device->button;
- k = device->key;
-
- if (IsMaster(device) || IsFloating(device))
- CheckMotion(event, device);
-
- 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 (DeviceEventCallback && !syncEvents.playingEvents) {
- DeviceEventInfoRec eventinfo;
- SpritePtr pSprite = device->spriteInfo->sprite;
-
- /* see comment in EnqueueEvents regarding the next three lines */
- if (ev->any.type == ET_Motion)
- ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
-
- eventinfo.device = device;
- eventinfo.event = ev;
- CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
- }
-
- grab = device->deviceGrab.grab;
-
- switch(event->type)
- {
- case ET_KeyPress:
- if (!grab && CheckDeviceGrabs(device, event, 0))
- 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 (grab)
- DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
- else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
- DeliverFocusedEvent(device, (InternalEvent*)event,
- GetSpriteWindow(device));
- else
- DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
- NullGrab, NullWindow, device);
-
- if (deactivateDeviceGrab == TRUE)
- (*device->deviceGrab.DeactivateGrab) (device);
- event->detail.key = key;
-}
-
-int
-InitProximityClassDeviceStruct(DeviceIntPtr dev)
-{
- ProximityClassPtr proxc;
-
- proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
- if (!proxc)
- return FALSE;
- proxc->sourceid = dev->id;
- proxc->in_proximity = TRUE;
- dev->proximity = proxc;
- return TRUE;
-}
-
-/**
- * Initialise the device's valuators. The memory must already be allocated,
- * this function merely inits the matching axis (specified through axnum) to
- * sane values.
- *
- * It is a condition that (minval < maxval).
- *
- * @see InitValuatorClassDeviceStruct
- */
-void
-InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
- int resolution, int min_res, int max_res, int mode)
-{
- AxisInfoPtr ax;
-
- if (!dev || !dev->valuator || minval > maxval)
- return;
- if (axnum >= dev->valuator->numAxes)
- return;
-
- ax = dev->valuator->axes + axnum;
-
- ax->min_value = minval;
- ax->max_value = maxval;
- ax->resolution = resolution;
- ax->min_resolution = min_res;
- ax->max_resolution = max_res;
- ax->label = label;
- ax->mode = mode;
-
- if (mode & OutOfProximity)
- dev->proximity->in_proximity = FALSE;
-}
-
-static void
-FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
- ButtonClassPtr b, ValuatorClassPtr v, int first)
-{
- ev->type = DeviceStateNotify;
- ev->deviceid = dev->id;
- ev->time = currentTime.milliseconds;
- ev->classes_reported = 0;
- ev->num_keys = 0;
- ev->num_buttons = 0;
- ev->num_valuators = 0;
-
- if (b) {
- ev->classes_reported |= (1 << ButtonClass);
- ev->num_buttons = b->numButtons;
- memcpy((char*)ev->buttons, (char*)b->down, 4);
- } else if (k) {
- ev->classes_reported |= (1 << KeyClass);
- 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) {
- int nval = v->numAxes - first;
-
- ev->classes_reported |= (1 << ValuatorClass);
- ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
- ev->num_valuators = nval < 3 ? nval : 3;
- switch (ev->num_valuators) {
- case 3:
- ev->valuator2 = v->axisVal[first + 2];
- case 2:
- ev->valuator1 = v->axisVal[first + 1];
- case 1:
- ev->valuator0 = v->axisVal[first];
- break;
- }
- }
-}
-
-static void
-FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
- int first)
-{
- int nval = v->numAxes - first;
-
- ev->type = DeviceValuator;
- ev->deviceid = dev->id;
- ev->num_valuators = nval < 3 ? nval : 3;
- ev->first_valuator = first;
- switch (ev->num_valuators) {
- case 3:
- ev->valuator2 = v->axisVal[first + 2];
- case 2:
- ev->valuator1 = v->axisVal[first + 1];
- case 1:
- ev->valuator0 = v->axisVal[first];
- break;
- }
- first += ev->num_valuators;
-}
-
-void
-DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
- WindowPtr pWin)
-{
- deviceFocus event;
- xXIFocusInEvent *xi2event;
- DeviceIntPtr mouse;
- int btlen, len, i;
-
- mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
-
- /* XI 2 event */
- btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
- btlen = bytes_to_int32(btlen);
- len = sizeof(xXIFocusInEvent) + btlen * 4;
-
- xi2event = calloc(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;
- }
-
- FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
- None, FALSE);
-
- DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
- GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
-
- free(xi2event);
-
- /* XI 1.x event */
- event.deviceid = dev->id;
- event.mode = mode;
- event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
- event.detail = detail;
- event.window = pWin->drawable.id;
- event.time = currentTime.milliseconds;
-
- DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
- DeviceFocusChangeMask, NullGrab);
-
- if ((event.type == DeviceFocusIn) &&
- (wOtherInputMasks(pWin)) &&
- (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
- {
- int evcount = 1;
- deviceStateNotify *ev, *sev;
- deviceKeyStateNotify *kev;
- deviceButtonStateNotify *bev;
-
- KeyClassPtr k;
- ButtonClassPtr b;
- ValuatorClassPtr v;
- int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
-
- if ((b = dev->button) != NULL) {
- nbuttons = b->numButtons;
- if (nbuttons > 32)
- evcount++;
- }
- if ((k = dev->key) != NULL) {
- nkeys = k->xkbInfo->desc->max_key_code -
- k->xkbInfo->desc->min_key_code;
- if (nkeys > 32)
- evcount++;
- if (nbuttons > 0) {
- evcount++;
- }
- }
- if ((v = dev->valuator) != NULL) {
- nval = v->numAxes;
-
- if (nval > 3)
- evcount++;
- if (nval > 6) {
- if (!(k && b))
- evcount++;
- if (nval > 9)
- evcount += ((nval - 7) / 3);
- }
- }
-
- sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
- FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
-
- if (b != NULL) {
- FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
- first += 3;
- nval -= 3;
- if (nbuttons > 32) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- bev = (deviceButtonStateNotify *) ev++;
- bev->type = DeviceButtonStateNotify;
- bev->deviceid = dev->id;
- memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
- }
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
- }
-
- if (k != NULL) {
- FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
- first += 3;
- nval -= 3;
- if (nkeys > 32) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- kev = (deviceKeyStateNotify *) ev++;
- kev->type = DeviceKeyStateNotify;
- kev->deviceid = dev->id;
- memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
- }
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
- }
-
- while (nval > 0) {
- FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
- first += 3;
- nval -= 3;
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
- }
-
- DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
- DeviceStateNotifyMask, NullGrab);
- free(sev);
- }
-}
-
-int
-CheckGrabValues(ClientPtr client, GrabParameters* param)
-{
- 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 ((param->this_device_mode != GrabModeSync) &&
- (param->this_device_mode != GrabModeAsync)) {
- client->errorValue = param->this_device_mode;
- return BadValue;
- }
- if ((param->other_devices_mode != GrabModeSync) &&
- (param->other_devices_mode != GrabModeAsync)) {
- client->errorValue = param->other_devices_mode;
- return BadValue;
- }
-
- if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
- (param->modifiers & ~AllModifiersMask)) {
- client->errorValue = param->modifiers;
- return BadValue;
- }
-
- if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
- client->errorValue = param->ownerEvents;
- return BadValue;
- }
- 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 (param->confineTo == None)
- confineTo = NullWindow;
- else {
- rc = dixLookupWindow(&confineTo, param->confineTo, 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;
- }
- 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;
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
- 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, 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, type = -1;
-
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
- if (k == NULL)
- return BadMatch;
- 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 (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, 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;
- }
- 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)
-{
- int mskidx = dev->id;
- int i, ret;
- Mask check;
- InputClientsPtr others;
-
- check = (mask & exclusivemasks);
- if (wOtherInputMasks(pWin)) {
- if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different
- * clients to select on any of the
- * events for maskcheck. However,
- * it is OK, for some client to
- * continue selecting on one of those
- * events. */
- for (others = wOtherInputMasks(pWin)->inputClients; others;
- others = others->next) {
- if (!SameClient(others, client) && (check &
- others->mask[mskidx]))
- return BadAccess;
- }
- }
- for (others = wOtherInputMasks(pWin)->inputClients; others;
- others = others->next) {
- if (SameClient(others, client)) {
- check = others->mask[mskidx];
- others->mask[mskidx] = mask;
- if (mask == 0) {
- for (i = 0; i < EMASKSIZE; i++)
- if (i != mskidx && others->mask[i] != 0)
- break;
- if (i == EMASKSIZE) {
- RecalculateDeviceDeliverableEvents(pWin);
- if (ShouldFreeInputMasks(pWin, FALSE))
- FreeResource(others->resource, RT_NONE);
- return Success;
- }
- }
- goto maskSet;
- }
- }
- }
- check = 0;
- if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
- return ret;
- maskSet:
- if (dev->valuator)
- if ((dev->valuator->motionHintWindow == pWin) &&
- (mask & DevicePointerMotionHintMask) &&
- !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
- dev->valuator->motionHintWindow = NullWindow;
- RecalculateDeviceDeliverableEvents(pWin);
- return Success;
-}
-
-int
-AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
-{
- InputClientsPtr others;
-
- if (!pWin->optional && !MakeWindowOptional(pWin))
- return BadAlloc;
- others = calloc(1, sizeof(InputClients));
- if (!others)
- return BadAlloc;
- if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
- return BadAlloc;
- others->mask[mskidx] = mask;
- others->resource = FakeClientID(client->index);
- others->next = pWin->optional->inputMasks->inputClients;
- pWin->optional->inputMasks->inputClients = others;
- if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
- return BadAlloc;
- return Success;
-}
-
-static Bool
-MakeInputMasks(WindowPtr pWin)
-{
- struct _OtherInputMasks *imasks;
-
- imasks = calloc(1, sizeof(struct _OtherInputMasks));
- if (!imasks)
- return FALSE;
- pWin->optional->inputMasks = imasks;
- return TRUE;
-}
-
-void
-RecalculateDeviceDeliverableEvents(WindowPtr pWin)
-{
- InputClientsPtr others;
- struct _OtherInputMasks *inputMasks; /* default: NULL */
- WindowPtr pChild, tmp;
- 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];
- for (tmp = pChild->parent; tmp; tmp = tmp->parent)
- if (wOtherInputMasks(tmp))
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->deliverableEvents[i] |=
- (wOtherInputMasks(tmp)->deliverableEvents[i]
- & ~inputMasks->
- dontPropagateMask[i] & PropagateMask[i]);
- }
- if (pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
- while (!pChild->nextSib && (pChild != pWin))
- pChild = pChild->parent;
- if (pChild == pWin)
- break;
- pChild = pChild->nextSib;
- }
-}
-
-int
-InputClientGone(WindowPtr pWin, XID id)
-{
- InputClientsPtr other, prev;
-
- if (!wOtherInputMasks(pWin))
- return Success;
- prev = 0;
- for (other = wOtherInputMasks(pWin)->inputClients; other;
- other = other->next) {
- if (other->resource == id) {
- if (prev) {
- prev->next = other->next;
- free(other);
- } else if (!(other->next)) {
- if (ShouldFreeInputMasks(pWin, TRUE)) {
- wOtherInputMasks(pWin)->inputClients = other->next;
- free(wOtherInputMasks(pWin));
- pWin->optional->inputMasks = (OtherInputMasks *) NULL;
- CheckWindowOptionalNeed(pWin);
- free(other);
- } else {
- other->resource = FakeClientID(0);
- if (!AddResource(other->resource, RT_INPUTCLIENT,
- (pointer) pWin))
- return BadAlloc;
- }
- } else {
- wOtherInputMasks(pWin)->inputClients = other->next;
- free(other);
- }
- RecalculateDeviceDeliverableEvents(pWin);
- return Success;
- }
- prev = other;
- }
- FatalError("client not on device event list");
-}
-
-int
-SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
- xEvent * ev, Mask mask, int count)
-{
- WindowPtr pWin;
- WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
- WindowPtr spriteWin = GetSpriteWindow(d);
-
- if (dest == PointerWindow)
- pWin = spriteWin;
- else if (dest == InputFocus) {
- WindowPtr inputFocus;
-
- if (!d->focus)
- inputFocus = spriteWin;
- else
- inputFocus = d->focus->win;
-
- if (inputFocus == FollowKeyboardWin)
- inputFocus = inputInfo.keyboard->focus->win;
-
- if (inputFocus == NoneWin)
- return Success;
-
- /* If the input focus is PointerRootWin, send the event to where
- * the pointer is if possible, then perhaps propogate up to root. */
- if (inputFocus == PointerRootWin)
- inputFocus = GetCurrentRootWindow(d);
-
- if (IsParent(inputFocus, spriteWin)) {
- effectiveFocus = inputFocus;
- pWin = spriteWin;
- } else
- effectiveFocus = pWin = inputFocus;
- } else
- dixLookupWindow(&pWin, dest, client, DixSendAccess);
- if (!pWin)
- return BadWindow;
- if ((propagate != xFalse) && (propagate != xTrue)) {
- client->errorValue = propagate;
- return BadValue;
- }
- ev->u.u.type |= 0x80;
- if (propagate) {
- for (; pWin; pWin = pWin->parent) {
- if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
- return Success;
- if (pWin == effectiveFocus)
- return Success;
- if (wOtherInputMasks(pWin))
- mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
- if (!mask)
- break;
- }
- } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
- DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
- return Success;
-}
-
-int
-SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
-{
- int i;
- ButtonClassPtr b = dev->button;
-
- if (b == NULL)
- return BadMatch;
-
- if (nElts != b->numButtons) {
- client->errorValue = nElts;
- return BadValue;
- }
- if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
- return BadValue;
- for (i = 0; i < nElts; i++)
- if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
- return MappingBusy;
- for (i = 0; i < nElts; i++)
- b->map[i + 1] = map[i];
- return Success;
-}
-
-int
-ChangeKeyMapping(ClientPtr client,
- DeviceIntPtr dev,
- unsigned len,
- int type,
- KeyCode firstKeyCode,
- CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
-{
- KeySymsRec keysyms;
- KeyClassPtr k = dev->key;
-
- if (k == NULL)
- return BadMatch;
-
- if (len != (keyCodes * keySymsPerKeyCode))
- return BadLength;
-
- if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
- (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
- client->errorValue = firstKeyCode;
- return BadValue;
- }
- if (keySymsPerKeyCode == 0) {
- client->errorValue = 0;
- return BadValue;
- }
- keysyms.minKeyCode = firstKeyCode;
- keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
- keysyms.mapWidth = keySymsPerKeyCode;
- keysyms.map = map;
-
- XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
- serverClient);
-
- return Success;
-}
-
-static void
-DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
-{
- WindowPtr parent;
-
- /* Deactivate any grabs performed on this window, before making
- * any input focus changes.
- * Deactivating a device grab should cause focus events. */
-
- if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
- (*dev->deviceGrab.DeactivateGrab) (dev);
-
- /* If the focus window is a root window (ie. has no parent)
- * then don't delete the focus from it. */
-
- if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
- int focusEventMode = NotifyNormal;
-
- /* If a grab is in progress, then alter the mode of focus events. */
-
- if (dev->deviceGrab.grab)
- focusEventMode = NotifyWhileGrabbed;
-
- switch (dev->focus->revert) {
- case RevertToNone:
- if (!ActivateFocusInGrab(dev, pWin, NoneWin))
- DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
- dev->focus->win = NoneWin;
- dev->focus->traceGood = 0;
- break;
- case RevertToParent:
- parent = pWin;
- do {
- parent = parent->parent;
- dev->focus->traceGood--;
- }
- while (!parent->realized);
- if (!ActivateFocusInGrab(dev, pWin, parent))
- DoFocusEvents(dev, pWin, parent, focusEventMode);
- dev->focus->win = parent;
- dev->focus->revert = RevertToNone;
- break;
- case RevertToPointerRoot:
- if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
- DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
- dev->focus->win = PointerRootWin;
- dev->focus->traceGood = 0;
- break;
- case RevertToFollowKeyboard:
- {
- 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 {
- if (!ActivateFocusInGrab(dev, pWin, NoneWin))
- DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
- dev->focus->win = NoneWin;
- dev->focus->traceGood = 0;
- }
- }
- break;
- }
- }
-
- if (dev->valuator)
- if (dev->valuator->motionHintWindow == pWin)
- dev->valuator->motionHintWindow = NullWindow;
-}
-
-void
-DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
-{
- int i;
- DeviceIntPtr dev;
- InputClientsPtr ic;
- struct _OtherInputMasks *inputMasks;
-
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- DeleteDeviceFromAnyExtEvents(pWin, dev);
- }
-
- for (dev = inputInfo.off_devices; dev; dev = dev->next)
- DeleteDeviceFromAnyExtEvents(pWin, dev);
-
- if (freeResources)
- while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
- ic = inputMasks->inputClients;
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->dontPropagateMask[i] = 0;
- FreeResource(ic->resource, RT_NONE);
- }
-}
-
-int
-MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
-{
- DeviceIntPtr dev;
-
- dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
- DixReadAccess);
- if (!dev)
- return 0;
-
- if (pEvents->type == DeviceMotionNotify) {
- if (mask & DevicePointerMotionHintMask) {
- if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
- return 1; /* don't send, but pretend we did */
- }
- pEvents->detail = NotifyHint;
- } else {
- pEvents->detail = NotifyNormal;
- }
- }
- return 0;
-}
-
-void
-CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
- deviceKeyButtonPointer * xE, GrabPtr grab,
- ClientPtr client, Mask deliveryMask)
-{
- DeviceIntPtr dev;
-
- dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
- DixGrabAccess);
- if (!dev)
- return;
-
- if (type == DeviceMotionNotify)
- dev->valuator->motionHintWindow = pWin;
- else if ((type == DeviceButtonPress) && (!grab) &&
- (deliveryMask & DeviceButtonGrabMask)) {
- GrabRec tempGrab;
-
- tempGrab.device = dev;
- tempGrab.resource = client->clientAsMask;
- tempGrab.window = pWin;
- tempGrab.ownerEvents =
- (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
- tempGrab.eventMask = deliveryMask;
- tempGrab.keyboardMode = GrabModeAsync;
- tempGrab.pointerMode = GrabModeAsync;
- tempGrab.confineTo = NullWindow;
- tempGrab.cursor = NullCursor;
- tempGrab.next = NULL;
- (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
- }
-}
-
-static Mask
-DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
-{
- InputClientsPtr other;
-
- if (!wOtherInputMasks(pWin))
- return 0;
- for (other = wOtherInputMasks(pWin)->inputClients; other;
- other = other->next) {
- if (SameClient(other, client))
- return other->mask[dev->id];
- }
- return 0;
-}
-
-void
-MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
-{
- WindowPtr pWin;
- GrabPtr grab = dev->deviceGrab.grab;
-
- pWin = dev->valuator->motionHintWindow;
-
- if ((grab && SameClient(grab, client) &&
- ((grab->eventMask & DevicePointerMotionHintMask) ||
- (grab->ownerEvents &&
- (DeviceEventMaskForClient(dev, pWin, client) &
- DevicePointerMotionHintMask)))) ||
- (!grab &&
- (DeviceEventMaskForClient(dev, pWin, client) &
- DevicePointerMotionHintMask)))
- dev->valuator->motionHintWindow = NullWindow;
-}
-
-int
-DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
- int maskndx)
-{
- struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
-
- if (mask & ~PropagateMask[maskndx]) {
- client->errorValue = mask;
- return BadValue;
- }
-
- if (mask == 0) {
- if (inputMasks)
- inputMasks->dontPropagateMask[maskndx] = mask;
- } else {
- if (!inputMasks)
- AddExtensionClient(pWin, client, 0, 0);
- inputMasks = wOtherInputMasks(pWin);
- inputMasks->dontPropagateMask[maskndx] = mask;
- }
- RecalculateDeviceDeliverableEvents(pWin);
- if (ShouldFreeInputMasks(pWin, FALSE))
- FreeResource(inputMasks->inputClients->resource, RT_NONE);
- return Success;
-}
-
-Bool
-ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
-{
- int i;
- Mask allInputEventMasks = 0;
- struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
-
- for (i = 0; i < EMASKSIZE; i++)
- allInputEventMasks |= inputMasks->dontPropagateMask[i];
- if (!ignoreSelectedEvents)
- for (i = 0; i < EMASKSIZE; i++)
- allInputEventMasks |= inputMasks->inputEvents[i];
- if (allInputEventMasks == 0)
- return TRUE;
- else
- return FALSE;
-}
-
-/***********************************************************************
- *
- * Walk through the window tree, finding all clients that want to know
- * about the Event.
- *
- */
-
-static void
-FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
- xEvent * ev, int count)
-{
- WindowPtr p2;
-
- while (p1) {
- p2 = p1->firstChild;
- DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
- FindInterestedChildren(dev, p2, mask, ev, count);
- p1 = p1->nextSib;
- }
-}
-
-/***********************************************************************
- *
- * Send an event to interested clients in all windows on all screens.
- *
- */
-
-void
-SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
-{
- int i;
- WindowPtr pWin, p1;
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- pWin = screenInfo.screens[i]->root;
- if (!pWin)
- continue;
- 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;
-}
+/************************************************************
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+/********************************************************************
+ *
+ * Routines to register and initialize extension input devices.
+ * This also contains ProcessOtherEvent, the routine called from DDX
+ * to route extension 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 "windowstr.h"
+#include "miscstruct.h"
+#include "region.h"
+#include "exevents.h"
+#include "extnsionst.h"
+#include "exglobals.h"
+#include "dixevents.h" /* DeliverFocusedEvent */
+#include "dixgrabs.h" /* CreateGrab() */
+#include "scrnintstr.h"
+#include "listdev.h" /* for CopySwapXXXClass */
+#include "xace.h"
+#include "xiquerydevice.h" /* For List*Info */
+#include "eventconvert.h"
+#include "eventstr.h"
+
+#include <X11/extensions/XKBproto.h>
+#include "xkbsrv.h"
+
+#define WID(w) ((w) ? ((w)->drawable.id) : 0)
+#define AllModifiersMask ( \
+ ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
+ Mod3Mask | Mod4Mask | Mod5Mask )
+#define AllButtonsMask ( \
+ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
+
+Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
+ Bool /* ignoreSelectedEvents */
+ );
+static Bool MakeInputMasks(WindowPtr /* pWin */
+ );
+
+/*
+ * 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;
+}
+
+Bool
+IsPointerEvent(InternalEvent* event)
+{
+ switch(event->any.type)
+ {
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_Motion:
+ /* XXX: enter/leave ?? */
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/**
+ * @return the device matching the deviceid of the device set in the event, or
+ * NULL if the event is not an XInput event.
+ */
+DeviceIntPtr
+XIGetDevice(xEvent* xE)
+{
+ DeviceIntPtr pDev = NULL;
+
+ 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 ||
+ xE->u.u.type == DevicePropertyNotify)
+ {
+ int rc;
+ int id;
+
+ id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
+
+ rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
+ if (rc != Success)
+ ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
+ }
+ return pDev;
+}
+
+
+/**
+ * Copy the device->key into master->key and send a mapping notify to the
+ * clients if appropriate.
+ * master->key needs to be allocated by the caller.
+ *
+ * Device is the slave device. If it is attached to a master device, we may
+ * need to send a mapping notify to the client because it causes the MD
+ * to change state.
+ *
+ * Mapping notify needs to be sent in the following cases:
+ * - different slave device on same master
+ * - different master
+ *
+ * XXX: They way how the code is we also send a map notify if the slave device
+ * stays the same, but the master changes. This isn't really necessary though.
+ *
+ * XXX: this gives you funny behaviour with the ClientPointer. When a
+ * MappingNotify is sent to the client, the client usually responds with a
+ * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
+ * mapping, regardless of which keyboard sent the last mapping notify request.
+ * So depending on the CP setting, your keyboard may change layout in each
+ * app...
+ *
+ * This code is basically the old SwitchCoreKeyboard.
+ */
+
+void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
+{
+ KeyClassPtr mk = master->key;
+
+ if (device == master)
+ return;
+
+ mk->sourceid = device->id;
+
+
+ if (!XkbCopyDeviceKeymap(master, device))
+ FatalError("Couldn't pivot keymap from device to core!\n");
+}
+
+/**
+ * Copies the feedback classes from device "from" into device "to". Classes
+ * are duplicated (not just flipping the pointers). All feedback classes are
+ * linked lists, the full list is duplicated.
+ */
+static void
+DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+ ClassesPtr classes;
+
+
+ if (from->intfeed)
+ {
+ IntegerFeedbackPtr *i, it;
+
+ if (!to->intfeed)
+ {
+ classes = to->unused_classes;
+ to->intfeed = classes->intfeed;
+ classes->intfeed = NULL;
+ }
+
+ i = &to->intfeed;
+ for (it = from->intfeed; it; it = it->next)
+ {
+ if (!(*i))
+ {
+ *i = calloc(1, sizeof(IntegerFeedbackClassRec));
+ if (!(*i))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*i)->CtrlProc = it->CtrlProc;
+ (*i)->ctrl = it->ctrl;
+
+ i = &(*i)->next;
+ }
+ } else if (to->intfeed && !from->intfeed)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->intfeed = to->intfeed;
+ to->intfeed = NULL;
+ }
+
+ if (from->stringfeed)
+ {
+ StringFeedbackPtr *s, it;
+
+ if (!to->stringfeed)
+ {
+ classes = to->unused_classes;
+ to->stringfeed = classes->stringfeed;
+ classes->stringfeed = NULL;
+ }
+
+ s = &to->stringfeed;
+ for (it = from->stringfeed; it; it = it->next)
+ {
+ if (!(*s))
+ {
+ *s = calloc(1, sizeof(StringFeedbackClassRec));
+ if (!(*s))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*s)->CtrlProc = it->CtrlProc;
+ (*s)->ctrl = it->ctrl;
+
+ s = &(*s)->next;
+ }
+ } else if (to->stringfeed && !from->stringfeed)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->stringfeed = to->stringfeed;
+ to->stringfeed = NULL;
+ }
+
+ if (from->bell)
+ {
+ BellFeedbackPtr *b, it;
+
+ if (!to->bell)
+ {
+ classes = to->unused_classes;
+ to->bell = classes->bell;
+ classes->bell = NULL;
+ }
+
+ b = &to->bell;
+ for (it = from->bell; it; it = it->next)
+ {
+ if (!(*b))
+ {
+ *b = calloc(1, sizeof(BellFeedbackClassRec));
+ if (!(*b))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*b)->BellProc = it->BellProc;
+ (*b)->CtrlProc = it->CtrlProc;
+ (*b)->ctrl = it->ctrl;
+
+ b = &(*b)->next;
+ }
+ } else if (to->bell && !from->bell)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->bell = to->bell;
+ to->bell = NULL;
+ }
+
+ if (from->leds)
+ {
+ LedFeedbackPtr *l, it;
+
+ if (!to->leds)
+ {
+ classes = to->unused_classes;
+ to->leds = classes->leds;
+ classes->leds = NULL;
+ }
+
+ l = &to->leds;
+ for (it = from->leds; it; it = it->next)
+ {
+ if (!(*l))
+ {
+ *l = calloc(1, sizeof(LedFeedbackClassRec));
+ if (!(*l))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*l)->CtrlProc = it->CtrlProc;
+ (*l)->ctrl = it->ctrl;
+ if ((*l)->xkb_sli)
+ XkbFreeSrvLedInfo((*l)->xkb_sli);
+ (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
+
+ l = &(*l)->next;
+ }
+ } else if (to->leds && !from->leds)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->leds = to->leds;
+ to->leds = NULL;
+ }
+}
+
+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.
+ */
+ if (from->kbdfeed)
+ {
+ KbdFeedbackPtr *k, it;
+
+ if (!to->kbdfeed)
+ {
+ classes = to->unused_classes;
+
+ to->kbdfeed = classes->kbdfeed;
+ if (!to->kbdfeed)
+ InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
+ classes->kbdfeed = NULL;
+ }
+
+ k = &to->kbdfeed;
+ for(it = from->kbdfeed; it; it = it->next)
+ {
+ if (!(*k))
+ {
+ *k = calloc(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 = to->unused_classes;
+ classes->kbdfeed = to->kbdfeed;
+ to->kbdfeed = NULL;
+ }
+
+ if (from->key)
+ {
+ if (!to->key)
+ {
+ classes = to->unused_classes;
+ 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 = to->unused_classes;
+ classes->key = to->key;
+ to->key = NULL;
+ }
+
+ /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
+ * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
+ * didn't update the pointers so we need to do it manually here.
+ */
+ if (to->kbdfeed)
+ {
+ KbdFeedbackPtr k;
+
+ for (k = to->kbdfeed; k; k = k->next)
+ {
+ if (!k->xkb_sli)
+ continue;
+ if (k->xkb_sli->flags & XkbSLI_IsDefault)
+ {
+ k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
+ k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
+ }
+ }
+ }
+
+ /* 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 = to->unused_classes;
+ to->focus = classes->focus;
+ if (!to->focus)
+ {
+ to->focus = calloc(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 = realloc(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 = to->unused_classes;
+ classes->focus = to->focus;
+ to->focus = NULL;
+ }
+
+}
+
+static void
+DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+ ClassesPtr classes;
+
+ /* Feedback classes must be copied first */
+ if (from->ptrfeed)
+ {
+ PtrFeedbackPtr *p, it;
+ if (!to->ptrfeed)
+ {
+ classes = to->unused_classes;
+ to->ptrfeed = classes->ptrfeed;
+ classes->ptrfeed = NULL;
+ }
+
+ p = &to->ptrfeed;
+ for (it = from->ptrfeed; it; it = it->next)
+ {
+ if (!(*p))
+ {
+ *p = calloc(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 = to->unused_classes;
+ classes->ptrfeed = to->ptrfeed;
+ to->ptrfeed = NULL;
+ }
+
+ if (from->valuator)
+ {
+ ValuatorClassPtr v;
+ if (!to->valuator)
+ {
+ classes = to->unused_classes;
+ to->valuator = classes->valuator;
+ if (to->valuator)
+ classes->valuator = NULL;
+ }
+
+ to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
+ from->valuator->numAxes * sizeof(AxisInfo) +
+ from->valuator->numAxes * sizeof(double));
+ v = to->valuator;
+ if (!v)
+ FatalError("[Xi] no memory for class shift.\n");
+
+ v->numAxes = from->valuator->numAxes;
+ v->axes = (AxisInfoPtr)&v[1];
+ memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
+
+ v->axisVal = (double*)(v->axes + from->valuator->numAxes);
+ v->sourceid = from->id;
+ } else if (to->valuator && !from->valuator)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->valuator = to->valuator;
+ to->valuator = NULL;
+ }
+
+ if (from->button)
+ {
+ if (!to->button)
+ {
+ classes = to->unused_classes;
+ to->button = classes->button;
+ if (!to->button)
+ {
+ to->button = calloc(1, sizeof(ButtonClassRec));
+ if (!to->button)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->button = NULL;
+ }
+
+ if (from->button->xkb_acts)
+ {
+ if (!to->button->xkb_acts)
+ {
+ to->button->xkb_acts = calloc(1, sizeof(XkbAction));
+ if (!to->button->xkb_acts)
+ FatalError("[Xi] not enough memory for xkb_acts.\n");
+ }
+ memcpy(to->button->xkb_acts, from->button->xkb_acts,
+ sizeof(XkbAction));
+ } else
+ free(to->button->xkb_acts);
+
+ 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;
+ classes = to->unused_classes;
+ classes->button = to->button;
+ to->button = NULL;
+ }
+
+ if (from->proximity)
+ {
+ if (!to->proximity)
+ {
+ classes = to->unused_classes;
+ to->proximity = classes->proximity;
+ if (!to->proximity)
+ {
+ to->proximity = calloc(1, sizeof(ProximityClassRec));
+ if (!to->proximity)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->proximity = NULL;
+ }
+ memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
+ to->proximity->sourceid = from->id;
+ } else if (to->proximity)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->proximity = to->proximity;
+ to->proximity = NULL;
+ }
+
+ if (from->absolute)
+ {
+ if (!to->absolute)
+ {
+ classes = to->unused_classes;
+ to->absolute = classes->absolute;
+ if (!to->absolute)
+ {
+ to->absolute = calloc(1, sizeof(AbsoluteClassRec));
+ if (!to->absolute)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->absolute = NULL;
+ }
+ memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
+ to->absolute->sourceid = from->id;
+ } else if (to->absolute)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->absolute = to->absolute;
+ to->absolute = NULL;
+ }
+}
+
+/**
+ * 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);
+ free(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 (IsMaster(slave))
+ return;
+
+ if (IsFloating(slave))
+ return; /* set floating since the event */
+
+ if (GetMaster(slave, MASTER_ATTACHED)->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.
+ *
+ * return values are
+ * DEFAULT ... process as normal
+ * DONT_PROCESS ... return immediately from caller
+ */
+#define DEFAULT 0
+#define DONT_PROCESS 1
+int
+UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
+{
+ int i;
+ int key = 0,
+ bit = 0,
+ last_valuator;
+
+ KeyClassPtr k = NULL;
+ ButtonClassPtr b = NULL;
+ ValuatorClassPtr v = NULL;
+
+ /* 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);
+
+ /* Update device axis */
+ /* Check valuators first */
+ last_valuator = -1;
+ for (i = 0; i < MAX_VALUATORS; i++)
+ {
+ 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;
+ }
+ }
+
+ 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] * 1.0f / (1 << 16) / (1 << 16));
+ }
+ }
+
+ if (event->type == ET_KeyPress) {
+ if (!k)
+ return DONT_PROCESS;
+
+ /* don't allow ddx to generate multiple downs, but repeats are okay */
+ if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
+ return DONT_PROCESS;
+
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ set_key_down(device, key, KEY_PROCESSED);
+ } else if (event->type == ET_KeyRelease) {
+ if (!k)
+ return DONT_PROCESS;
+
+ if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */
+ return DONT_PROCESS;
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ set_key_up(device, key, KEY_PROCESSED);
+ } else if (event->type == ET_ButtonPress) {
+ Mask mask;
+ if (!b)
+ return DONT_PROCESS;
+
+ if (button_is_down(device, key, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+
+ set_button_down(device, key, BUTTON_PROCESSED);
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ if (!b->map[key])
+ return DONT_PROCESS;
+ b->buttonsDown++;
+ b->motionMask = DeviceButtonMotionMask;
+ if (b->map[key] <= 5)
+ b->state |= (Button1Mask >> 1) << b->map[key];
+
+ /* 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;
+
+ if (!button_is_down(device, key, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+ if (IsMaster(device)) {
+ DeviceIntPtr sd;
+
+ /*
+ * Leave the button down if any slave has the
+ * button still down. Note that this depends on the
+ * event being delivered through the slave first
+ */
+ for (sd = inputInfo.devices; sd; sd = sd->next) {
+ if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
+ continue;
+ if (!sd->button)
+ continue;
+ for (i = 1; i <= sd->button->numButtons; i++)
+ if (sd->button->map[i] == key &&
+ button_is_down(sd, i, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+ }
+ }
+ set_button_up(device, key, BUTTON_PROCESSED);
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ if (!b->map[key])
+ return DONT_PROCESS;
+ if (b->buttonsDown >= 1 && !--b->buttonsDown)
+ b->motionMask = 0;
+ if (b->map[key] <= 5)
+ b->state &= ~((Button1Mask >> 1) << b->map[key]);
+
+ /* 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->proximity->in_proximity = TRUE;
+ else if (event->type == ET_ProximityOut)
+ device->proximity->in_proximity = FALSE;
+
+ 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++)
+ if (screenInfo.screens[i] && screenInfo.screens[i]->root)
+ DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
+ GetEventFilter(device, xi), NULL);
+ free(xi);
+ }
+}
+
+/**
+ * Main device event processing function.
+ * Called from when processing the events from the event queue.
+ *
+ */
+void
+ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
+{
+ GrabPtr grab;
+ Bool deactivateDeviceGrab = FALSE;
+ int key = 0, rootX, rootY;
+ ButtonClassPtr b;
+ KeyClassPtr k;
+ ValuatorClassPtr v;
+ int ret = 0;
+ int state, i;
+ DeviceIntPtr mouse = NULL, kbd = NULL;
+ DeviceEvent *event = &ev->device_event;
+
+ 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(&ev->raw_event, device);
+ return;
+ }
+
+ if (IsPointerDevice(device))
+ {
+ kbd = GetPairedDevice(device);
+ mouse = device;
+ if (kbd && !kbd->key) /* can happen with floating SDs */
+ kbd = NULL;
+ } else
+ {
+ mouse = GetPairedDevice(device);
+ kbd = device;
+ if (!mouse->valuator || !mouse->button) /* may be float. SDs */
+ mouse = NULL;
+ }
+
+ /* State needs to be assembled BEFORE the device is updated. */
+ 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);
+
+ 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;
+
+ v = device->valuator;
+ b = device->button;
+ k = device->key;
+
+ if (IsMaster(device) || IsFloating(device))
+ CheckMotion(event, device);
+
+ switch (event->type)
+ {
+ case ET_Motion:
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ if (!device->spriteInfo->sprite)
+ return;
+ 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 (DeviceEventCallback && !syncEvents.playingEvents) {
+ DeviceEventInfoRec eventinfo;
+ SpritePtr pSprite = device->spriteInfo->sprite;
+
+ /* see comment in EnqueueEvents regarding the next three lines */
+ if (ev->any.type == ET_Motion)
+ ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
+
+ eventinfo.device = device;
+ eventinfo.event = ev;
+ CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
+ }
+
+ grab = device->deviceGrab.grab;
+
+ switch(event->type)
+ {
+ case ET_KeyPress:
+ if (!grab && CheckDeviceGrabs(device, event, 0))
+ 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 (grab)
+ DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
+ else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
+ DeliverFocusedEvent(device, (InternalEvent*)event,
+ GetSpriteWindow(device));
+ else
+ DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
+ NullGrab, NullWindow, device);
+
+ if (deactivateDeviceGrab == TRUE)
+ (*device->deviceGrab.DeactivateGrab) (device);
+ event->detail.key = key;
+}
+
+int
+InitProximityClassDeviceStruct(DeviceIntPtr dev)
+{
+ ProximityClassPtr proxc;
+
+ proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
+ if (!proxc)
+ return FALSE;
+ proxc->sourceid = dev->id;
+ proxc->in_proximity = TRUE;
+ dev->proximity = proxc;
+ return TRUE;
+}
+
+/**
+ * Initialise the device's valuators. The memory must already be allocated,
+ * this function merely inits the matching axis (specified through axnum) to
+ * sane values.
+ *
+ * It is a condition that (minval < maxval).
+ *
+ * @see InitValuatorClassDeviceStruct
+ */
+void
+InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
+ int resolution, int min_res, int max_res, int mode)
+{
+ AxisInfoPtr ax;
+
+ if (!dev || !dev->valuator || minval > maxval)
+ return;
+ if (axnum >= dev->valuator->numAxes)
+ return;
+
+ ax = dev->valuator->axes + axnum;
+
+ ax->min_value = minval;
+ ax->max_value = maxval;
+ ax->resolution = resolution;
+ ax->min_resolution = min_res;
+ ax->max_resolution = max_res;
+ ax->label = label;
+ ax->mode = mode;
+
+ if (mode & OutOfProximity)
+ dev->proximity->in_proximity = FALSE;
+}
+
+static void
+FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
+ ButtonClassPtr b, ValuatorClassPtr v, int first)
+{
+ ev->type = DeviceStateNotify;
+ ev->deviceid = dev->id;
+ ev->time = currentTime.milliseconds;
+ ev->classes_reported = 0;
+ ev->num_keys = 0;
+ ev->num_buttons = 0;
+ ev->num_valuators = 0;
+
+ if (b) {
+ ev->classes_reported |= (1 << ButtonClass);
+ ev->num_buttons = b->numButtons;
+ memcpy((char*)ev->buttons, (char*)b->down, 4);
+ } else if (k) {
+ ev->classes_reported |= (1 << KeyClass);
+ 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) {
+ int nval = v->numAxes - first;
+
+ ev->classes_reported |= (1 << ValuatorClass);
+ ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
+ ev->num_valuators = nval < 3 ? nval : 3;
+ switch (ev->num_valuators) {
+ case 3:
+ ev->valuator2 = v->axisVal[first + 2];
+ case 2:
+ ev->valuator1 = v->axisVal[first + 1];
+ case 1:
+ ev->valuator0 = v->axisVal[first];
+ break;
+ }
+ }
+}
+
+static void
+FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
+ int first)
+{
+ int nval = v->numAxes - first;
+
+ ev->type = DeviceValuator;
+ ev->deviceid = dev->id;
+ ev->num_valuators = nval < 3 ? nval : 3;
+ ev->first_valuator = first;
+ switch (ev->num_valuators) {
+ case 3:
+ ev->valuator2 = v->axisVal[first + 2];
+ case 2:
+ ev->valuator1 = v->axisVal[first + 1];
+ case 1:
+ ev->valuator0 = v->axisVal[first];
+ break;
+ }
+ first += ev->num_valuators;
+}
+
+void
+DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
+ WindowPtr pWin)
+{
+ deviceFocus event;
+ xXIFocusInEvent *xi2event;
+ DeviceIntPtr mouse;
+ int btlen, len, i;
+
+ mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
+
+ /* XI 2 event */
+ btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
+ btlen = bytes_to_int32(btlen);
+ len = sizeof(xXIFocusInEvent) + btlen * 4;
+
+ xi2event = calloc(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;
+ }
+
+ FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
+ None, FALSE);
+
+ DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
+ GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
+
+ free(xi2event);
+
+ /* XI 1.x event */
+ event.deviceid = dev->id;
+ event.mode = mode;
+ event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
+ event.detail = detail;
+ event.window = pWin->drawable.id;
+ event.time = currentTime.milliseconds;
+
+ DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
+ DeviceFocusChangeMask, NullGrab);
+
+ if ((event.type == DeviceFocusIn) &&
+ (wOtherInputMasks(pWin)) &&
+ (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
+ {
+ int evcount = 1;
+ deviceStateNotify *ev, *sev;
+ deviceKeyStateNotify *kev;
+ deviceButtonStateNotify *bev;
+
+ KeyClassPtr k;
+ ButtonClassPtr b;
+ ValuatorClassPtr v;
+ int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
+
+ if ((b = dev->button) != NULL) {
+ nbuttons = b->numButtons;
+ if (nbuttons > 32)
+ evcount++;
+ }
+ if ((k = dev->key) != NULL) {
+ nkeys = k->xkbInfo->desc->max_key_code -
+ k->xkbInfo->desc->min_key_code;
+ if (nkeys > 32)
+ evcount++;
+ if (nbuttons > 0) {
+ evcount++;
+ }
+ }
+ if ((v = dev->valuator) != NULL) {
+ nval = v->numAxes;
+
+ if (nval > 3)
+ evcount++;
+ if (nval > 6) {
+ if (!(k && b))
+ evcount++;
+ if (nval > 9)
+ evcount += ((nval - 7) / 3);
+ }
+ }
+
+ sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
+ FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
+
+ if (b != NULL) {
+ FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
+ first += 3;
+ nval -= 3;
+ if (nbuttons > 32) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ bev = (deviceButtonStateNotify *) ev++;
+ bev->type = DeviceButtonStateNotify;
+ bev->deviceid = dev->id;
+ memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
+ }
+ if (nval > 0) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
+ first += 3;
+ nval -= 3;
+ }
+ }
+
+ if (k != NULL) {
+ FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
+ first += 3;
+ nval -= 3;
+ if (nkeys > 32) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ kev = (deviceKeyStateNotify *) ev++;
+ kev->type = DeviceKeyStateNotify;
+ kev->deviceid = dev->id;
+ memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
+ }
+ if (nval > 0) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
+ first += 3;
+ nval -= 3;
+ }
+ }
+
+ while (nval > 0) {
+ FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
+ first += 3;
+ nval -= 3;
+ if (nval > 0) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
+ first += 3;
+ nval -= 3;
+ }
+ }
+
+ DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
+ DeviceStateNotifyMask, NullGrab);
+ free(sev);
+ }
+}
+
+int
+CheckGrabValues(ClientPtr client, GrabParameters* param)
+{
+ 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 ((param->this_device_mode != GrabModeSync) &&
+ (param->this_device_mode != GrabModeAsync)) {
+ client->errorValue = param->this_device_mode;
+ return BadValue;
+ }
+ if ((param->other_devices_mode != GrabModeSync) &&
+ (param->other_devices_mode != GrabModeAsync)) {
+ client->errorValue = param->other_devices_mode;
+ return BadValue;
+ }
+
+ if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
+ (param->modifiers & ~AllModifiersMask)) {
+ client->errorValue = param->modifiers;
+ return BadValue;
+ }
+
+ if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
+ client->errorValue = param->ownerEvents;
+ return BadValue;
+ }
+ 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 (param->confineTo == None)
+ confineTo = NullWindow;
+ else {
+ rc = dixLookupWindow(&confineTo, param->confineTo, 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;
+ }
+ 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;
+ rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ 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, 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, type = -1;
+
+ rc = CheckGrabValues(client, param);
+ if (rc != Success)
+ return rc;
+ if (k == NULL)
+ return BadMatch;
+ 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 (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, 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;
+ }
+ 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)
+{
+ int mskidx = dev->id;
+ int i, ret;
+ Mask check;
+ InputClientsPtr others;
+
+ check = (mask & exclusivemasks);
+ if (wOtherInputMasks(pWin)) {
+ if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different
+ * clients to select on any of the
+ * events for maskcheck. However,
+ * it is OK, for some client to
+ * continue selecting on one of those
+ * events. */
+ for (others = wOtherInputMasks(pWin)->inputClients; others;
+ others = others->next) {
+ if (!SameClient(others, client) && (check &
+ others->mask[mskidx]))
+ return BadAccess;
+ }
+ }
+ for (others = wOtherInputMasks(pWin)->inputClients; others;
+ others = others->next) {
+ if (SameClient(others, client)) {
+ check = others->mask[mskidx];
+ others->mask[mskidx] = mask;
+ if (mask == 0) {
+ for (i = 0; i < EMASKSIZE; i++)
+ if (i != mskidx && others->mask[i] != 0)
+ break;
+ if (i == EMASKSIZE) {
+ RecalculateDeviceDeliverableEvents(pWin);
+ if (ShouldFreeInputMasks(pWin, FALSE))
+ FreeResource(others->resource, RT_NONE);
+ return Success;
+ }
+ }
+ goto maskSet;
+ }
+ }
+ }
+ check = 0;
+ if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
+ return ret;
+ maskSet:
+ if (dev->valuator)
+ if ((dev->valuator->motionHintWindow == pWin) &&
+ (mask & DevicePointerMotionHintMask) &&
+ !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
+ dev->valuator->motionHintWindow = NullWindow;
+ RecalculateDeviceDeliverableEvents(pWin);
+ return Success;
+}
+
+int
+AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
+{
+ InputClientsPtr others;
+
+ if (!pWin->optional && !MakeWindowOptional(pWin))
+ return BadAlloc;
+ others = calloc(1, sizeof(InputClients));
+ if (!others)
+ return BadAlloc;
+ if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
+ return BadAlloc;
+ others->mask[mskidx] = mask;
+ others->resource = FakeClientID(client->index);
+ others->next = pWin->optional->inputMasks->inputClients;
+ pWin->optional->inputMasks->inputClients = others;
+ if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
+ return BadAlloc;
+ return Success;
+}
+
+static Bool
+MakeInputMasks(WindowPtr pWin)
+{
+ struct _OtherInputMasks *imasks;
+
+ imasks = calloc(1, sizeof(struct _OtherInputMasks));
+ if (!imasks)
+ return FALSE;
+ pWin->optional->inputMasks = imasks;
+ return TRUE;
+}
+
+void
+RecalculateDeviceDeliverableEvents(WindowPtr pWin)
+{
+ InputClientsPtr others;
+ struct _OtherInputMasks *inputMasks; /* default: NULL */
+ WindowPtr pChild, tmp;
+ 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];
+ for (tmp = pChild->parent; tmp; tmp = tmp->parent)
+ if (wOtherInputMasks(tmp))
+ for (i = 0; i < EMASKSIZE; i++)
+ inputMasks->deliverableEvents[i] |=
+ (wOtherInputMasks(tmp)->deliverableEvents[i]
+ & ~inputMasks->
+ dontPropagateMask[i] & PropagateMask[i]);
+ }
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+#ifdef _MSC_VER
+#pragma warning(disable:4715) /* Not all control paths return a value */
+#endif
+
+int
+InputClientGone(WindowPtr pWin, XID id)
+{
+ InputClientsPtr other, prev;
+
+ if (!wOtherInputMasks(pWin))
+ return Success;
+ prev = 0;
+ for (other = wOtherInputMasks(pWin)->inputClients; other;
+ other = other->next) {
+ if (other->resource == id) {
+ if (prev) {
+ prev->next = other->next;
+ free(other);
+ } else if (!(other->next)) {
+ if (ShouldFreeInputMasks(pWin, TRUE)) {
+ wOtherInputMasks(pWin)->inputClients = other->next;
+ free(wOtherInputMasks(pWin));
+ pWin->optional->inputMasks = (OtherInputMasks *) NULL;
+ CheckWindowOptionalNeed(pWin);
+ free(other);
+ } else {
+ other->resource = FakeClientID(0);
+ if (!AddResource(other->resource, RT_INPUTCLIENT,
+ (pointer) pWin))
+ return BadAlloc;
+ }
+ } else {
+ wOtherInputMasks(pWin)->inputClients = other->next;
+ free(other);
+ }
+ RecalculateDeviceDeliverableEvents(pWin);
+ return Success;
+ }
+ prev = other;
+ }
+ FatalError("client not on device event list");
+}
+
+int
+SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
+ xEvent * ev, Mask mask, int count)
+{
+ WindowPtr pWin;
+ WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
+ WindowPtr spriteWin = GetSpriteWindow(d);
+
+ if (dest == PointerWindow)
+ pWin = spriteWin;
+ else if (dest == InputFocus) {
+ WindowPtr inputFocus;
+
+ if (!d->focus)
+ inputFocus = spriteWin;
+ else
+ inputFocus = d->focus->win;
+
+ if (inputFocus == FollowKeyboardWin)
+ inputFocus = inputInfo.keyboard->focus->win;
+
+ if (inputFocus == NoneWin)
+ return Success;
+
+ /* If the input focus is PointerRootWin, send the event to where
+ * the pointer is if possible, then perhaps propogate up to root. */
+ if (inputFocus == PointerRootWin)
+ inputFocus = GetCurrentRootWindow(d);
+
+ if (IsParent(inputFocus, spriteWin)) {
+ effectiveFocus = inputFocus;
+ pWin = spriteWin;
+ } else
+ effectiveFocus = pWin = inputFocus;
+ } else
+ dixLookupWindow(&pWin, dest, client, DixSendAccess);
+ if (!pWin)
+ return BadWindow;
+ if ((propagate != xFalse) && (propagate != xTrue)) {
+ client->errorValue = propagate;
+ return BadValue;
+ }
+ ev->u.u.type |= 0x80;
+ if (propagate) {
+ for (; pWin; pWin = pWin->parent) {
+ if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
+ return Success;
+ if (pWin == effectiveFocus)
+ return Success;
+ if (wOtherInputMasks(pWin))
+ mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
+ if (!mask)
+ break;
+ }
+ } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
+ DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
+ return Success;
+}
+
+int
+SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
+{
+ int i;
+ ButtonClassPtr b = dev->button;
+
+ if (b == NULL)
+ return BadMatch;
+
+ if (nElts != b->numButtons) {
+ client->errorValue = nElts;
+ return BadValue;
+ }
+ if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
+ return BadValue;
+ for (i = 0; i < nElts; i++)
+ if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
+ return MappingBusy;
+ for (i = 0; i < nElts; i++)
+ b->map[i + 1] = map[i];
+ return Success;
+}
+
+int
+ChangeKeyMapping(ClientPtr client,
+ DeviceIntPtr dev,
+ unsigned len,
+ int type,
+ KeyCode firstKeyCode,
+ CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
+{
+ KeySymsRec keysyms;
+ KeyClassPtr k = dev->key;
+
+ if (k == NULL)
+ return BadMatch;
+
+ if (len != (keyCodes * keySymsPerKeyCode))
+ return BadLength;
+
+ if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
+ (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
+ client->errorValue = firstKeyCode;
+ return BadValue;
+ }
+ if (keySymsPerKeyCode == 0) {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ keysyms.minKeyCode = firstKeyCode;
+ keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
+ keysyms.mapWidth = keySymsPerKeyCode;
+ keysyms.map = map;
+
+ XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
+ serverClient);
+
+ return Success;
+}
+
+static void
+DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
+{
+ WindowPtr parent;
+
+ /* Deactivate any grabs performed on this window, before making
+ * any input focus changes.
+ * Deactivating a device grab should cause focus events. */
+
+ if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
+ (*dev->deviceGrab.DeactivateGrab) (dev);
+
+ /* If the focus window is a root window (ie. has no parent)
+ * then don't delete the focus from it. */
+
+ if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
+ int focusEventMode = NotifyNormal;
+
+ /* If a grab is in progress, then alter the mode of focus events. */
+
+ if (dev->deviceGrab.grab)
+ focusEventMode = NotifyWhileGrabbed;
+
+ switch (dev->focus->revert) {
+ case RevertToNone:
+ if (!ActivateFocusInGrab(dev, pWin, NoneWin))
+ DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
+ dev->focus->win = NoneWin;
+ dev->focus->traceGood = 0;
+ break;
+ case RevertToParent:
+ parent = pWin;
+ do {
+ parent = parent->parent;
+ dev->focus->traceGood--;
+ }
+ while (!parent->realized);
+ if (!ActivateFocusInGrab(dev, pWin, parent))
+ DoFocusEvents(dev, pWin, parent, focusEventMode);
+ dev->focus->win = parent;
+ dev->focus->revert = RevertToNone;
+ break;
+ case RevertToPointerRoot:
+ if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
+ DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
+ dev->focus->win = PointerRootWin;
+ dev->focus->traceGood = 0;
+ break;
+ case RevertToFollowKeyboard:
+ {
+ 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 {
+ if (!ActivateFocusInGrab(dev, pWin, NoneWin))
+ DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
+ dev->focus->win = NoneWin;
+ dev->focus->traceGood = 0;
+ }
+ }
+ break;
+ }
+ }
+
+ if (dev->valuator)
+ if (dev->valuator->motionHintWindow == pWin)
+ dev->valuator->motionHintWindow = NullWindow;
+}
+
+void
+DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
+{
+ int i;
+ DeviceIntPtr dev;
+ InputClientsPtr ic;
+ struct _OtherInputMasks *inputMasks;
+
+ for (dev = inputInfo.devices; dev; dev = dev->next) {
+ DeleteDeviceFromAnyExtEvents(pWin, dev);
+ }
+
+ for (dev = inputInfo.off_devices; dev; dev = dev->next)
+ DeleteDeviceFromAnyExtEvents(pWin, dev);
+
+ if (freeResources)
+ while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
+ ic = inputMasks->inputClients;
+ for (i = 0; i < EMASKSIZE; i++)
+ inputMasks->dontPropagateMask[i] = 0;
+ FreeResource(ic->resource, RT_NONE);
+ }
+}
+
+int
+MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
+{
+ DeviceIntPtr dev;
+
+ dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
+ DixReadAccess);
+ if (!dev)
+ return 0;
+
+ if (pEvents->type == DeviceMotionNotify) {
+ if (mask & DevicePointerMotionHintMask) {
+ if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
+ return 1; /* don't send, but pretend we did */
+ }
+ pEvents->detail = NotifyHint;
+ } else {
+ pEvents->detail = NotifyNormal;
+ }
+ }
+ return 0;
+}
+
+void
+CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
+ deviceKeyButtonPointer * xE, GrabPtr grab,
+ ClientPtr client, Mask deliveryMask)
+{
+ DeviceIntPtr dev;
+
+ dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
+ DixGrabAccess);
+ if (!dev)
+ return;
+
+ if (type == DeviceMotionNotify)
+ dev->valuator->motionHintWindow = pWin;
+ else if ((type == DeviceButtonPress) && (!grab) &&
+ (deliveryMask & DeviceButtonGrabMask)) {
+ GrabRec tempGrab;
+
+ tempGrab.device = dev;
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.window = pWin;
+ tempGrab.ownerEvents =
+ (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
+ tempGrab.eventMask = deliveryMask;
+ tempGrab.keyboardMode = GrabModeAsync;
+ tempGrab.pointerMode = GrabModeAsync;
+ tempGrab.confineTo = NullWindow;
+ tempGrab.cursor = NullCursor;
+ tempGrab.next = NULL;
+ (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
+ }
+}
+
+static Mask
+DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
+{
+ InputClientsPtr other;
+
+ if (!wOtherInputMasks(pWin))
+ return 0;
+ for (other = wOtherInputMasks(pWin)->inputClients; other;
+ other = other->next) {
+ if (SameClient(other, client))
+ return other->mask[dev->id];
+ }
+ return 0;
+}
+
+void
+MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
+{
+ WindowPtr pWin;
+ GrabPtr grab = dev->deviceGrab.grab;
+
+ pWin = dev->valuator->motionHintWindow;
+
+ if ((grab && SameClient(grab, client) &&
+ ((grab->eventMask & DevicePointerMotionHintMask) ||
+ (grab->ownerEvents &&
+ (DeviceEventMaskForClient(dev, pWin, client) &
+ DevicePointerMotionHintMask)))) ||
+ (!grab &&
+ (DeviceEventMaskForClient(dev, pWin, client) &
+ DevicePointerMotionHintMask)))
+ dev->valuator->motionHintWindow = NullWindow;
+}
+
+int
+DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
+ int maskndx)
+{
+ struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+
+ if (mask & ~PropagateMask[maskndx]) {
+ client->errorValue = mask;
+ return BadValue;
+ }
+
+ if (mask == 0) {
+ if (inputMasks)
+ inputMasks->dontPropagateMask[maskndx] = mask;
+ } else {
+ if (!inputMasks)
+ AddExtensionClient(pWin, client, 0, 0);
+ inputMasks = wOtherInputMasks(pWin);
+ inputMasks->dontPropagateMask[maskndx] = mask;
+ }
+ RecalculateDeviceDeliverableEvents(pWin);
+ if (ShouldFreeInputMasks(pWin, FALSE))
+ FreeResource(inputMasks->inputClients->resource, RT_NONE);
+ return Success;
+}
+
+Bool
+ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
+{
+ int i;
+ Mask allInputEventMasks = 0;
+ struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+
+ for (i = 0; i < EMASKSIZE; i++)
+ allInputEventMasks |= inputMasks->dontPropagateMask[i];
+ if (!ignoreSelectedEvents)
+ for (i = 0; i < EMASKSIZE; i++)
+ allInputEventMasks |= inputMasks->inputEvents[i];
+ if (allInputEventMasks == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/***********************************************************************
+ *
+ * Walk through the window tree, finding all clients that want to know
+ * about the Event.
+ *
+ */
+
+static void
+FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
+ xEvent * ev, int count)
+{
+ WindowPtr p2;
+
+ while (p1) {
+ p2 = p1->firstChild;
+ DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
+ FindInterestedChildren(dev, p2, mask, ev, count);
+ p1 = p1->nextSib;
+ }
+}
+
+/***********************************************************************
+ *
+ * Send an event to interested clients in all windows on all screens.
+ *
+ */
+
+void
+SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pWin = screenInfo.screens[i]->root;
+ if (!pWin)
+ continue;
+ 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;
+}
diff --git a/xorg-server/Xi/makefile b/xorg-server/Xi/makefile
new file mode 100644
index 000000000..a466c84f0
--- /dev/null
+++ b/xorg-server/Xi/makefile
@@ -0,0 +1,55 @@
+CSRCS=allowev.c \
+ chgdctl.c \
+ chgfctl.c \
+ chgkbd.c \
+ chgkmap.c \
+ chgprop.c \
+ chgptr.c \
+ closedev.c \
+ devbell.c \
+ exevents.c \
+ extinit.c \
+ getbmap.c \
+ getdctl.c \
+ getfctl.c \
+ getfocus.c \
+ getkmap.c \
+ getmmap.c \
+ getprop.c \
+ getselev.c \
+ getvers.c \
+ grabdev.c \
+ grabdevb.c \
+ grabdevk.c \
+ gtmotion.c \
+ listdev.c \
+ opendev.c \
+ queryst.c \
+ selectev.c \
+ sendexev.c \
+ setbmap.c \
+ setdval.c \
+ setfocus.c \
+ setmmap.c \
+ setmode.c \
+ ungrdev.c \
+ ungrdevb.c \
+ ungrdevk.c \
+ xiallowev.c \
+ xichangecursor.c \
+ xichangehierarchy.c \
+ xigetclientpointer.c \
+ xigrabdev.c \
+ xipassivegrab.c \
+ xiproperty.c \
+ xiquerydevice.c \
+ xiquerypointer.c \
+ xiqueryversion.c \
+ xiselectev.c \
+ xisetclientpointer.c \
+ xisetdevfocus.c \
+ xiwarppointer.c \
+ stubs.c
+
+LIBRARY=libXi
+
diff --git a/xorg-server/Xi/opendev.c b/xorg-server/Xi/opendev.c
index 273cb2404..23a3a1b5b 100644
--- a/xorg-server/Xi/opendev.c
+++ b/xorg-server/Xi/opendev.c
@@ -115,9 +115,6 @@ ProcXOpenDevice(ClientPtr client)
if (IsMaster(dev))
return BadDevice;
- if (status != Success)
- return status;
-
memset(&rep, 0, sizeof(xOpenDeviceReply));
rep.repType = X_Reply;
rep.RepType = X_OpenDevice;
diff --git a/xorg-server/Xi/xichangehierarchy.c b/xorg-server/Xi/xichangehierarchy.c
index a3dcab57e..d48200b04 100644
--- a/xorg-server/Xi/xichangehierarchy.c
+++ b/xorg-server/Xi/xichangehierarchy.c
@@ -1,492 +1,492 @@
-/*
- * Copyright 2007-2008 Peter Hutterer
- * Copyright 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer, University of South Australia, NICTA
- */
-
-/***********************************************************************
- *
- * Request change in the device hierarchy.
- *
- */
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h> /* for inputstr.h */
-#include <X11/Xproto.h> /* Request macro */
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include "scrnintstr.h" /* screen structure */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XI2proto.h>
-#include <X11/extensions/geproto.h>
-#include "extnsionst.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "geext.h"
-#include "xace.h"
-#include "xiquerydevice.h" /* for GetDeviceUse */
-
-#include "xkbsrv.h"
-
-#include "xichangehierarchy.h"
-
-/**
- * Send the current state of the device hierarchy to all clients.
- */
-void XISendDeviceHierarchyEvent(int flags[MAXDEVICES])
-{
- xXIHierarchyEvent *ev;
- xXIHierarchyInfo *info;
- DeviceIntRec dummyDev;
- DeviceIntPtr dev;
- int i;
-
- if (!flags)
- return;
-
- ev = calloc(1, sizeof(xXIHierarchyEvent) +
- MAXDEVICES * sizeof(xXIHierarchyInfo));
- if (!ev)
- return;
- ev->type = GenericEvent;
- ev->extension = IReqCode;
- ev->evtype = XI_HierarchyChanged;
- ev->time = GetTimeInMillis();
- ev->flags = 0;
- ev->num_info = inputInfo.numDevices;
-
- info = (xXIHierarchyInfo*)&ev[1];
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- info->deviceid = dev->id;
- info->enabled = dev->enabled;
- info->use = GetDeviceUse(dev, &info->attachment);
- info->flags = flags[dev->id];
- ev->flags |= info->flags;
- info++;
- }
- for (dev = inputInfo.off_devices; dev; dev = dev->next)
- {
- info->deviceid = dev->id;
- info->enabled = dev->enabled;
- info->use = GetDeviceUse(dev, &info->attachment);
- info->flags = flags[dev->id];
- ev->flags |= info->flags;
- info++;
- }
-
-
- for (i = 0; i < MAXDEVICES; i++)
- {
- if (flags[i] & (XIMasterRemoved | XISlaveRemoved))
- {
- info->deviceid = i;
- info->enabled = FALSE;
- info->flags = flags[i];
- info->use = 0;
- ev->flags |= info->flags;
- ev->num_info++;
- info++;
- }
- }
-
- ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo));
-
- dummyDev.id = XIAllDevices;
- SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1);
- free(ev);
-}
-
-
-/***********************************************************************
- *
- * This procedure allows a client to change the device hierarchy through
- * adding new master devices, removing them, etc.
- *
- */
-
-int SProcXIChangeHierarchy(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIChangeHierarchyReq);
- swaps(&stuff->length, n);
- return (ProcXIChangeHierarchy(client));
-}
-
-static int
-add_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES])
-{
- DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
- char* name;
- int rc;
-
- name = calloc(c->name_len + 1, sizeof(char));
- strncpy(name, (char*)&c[1], c->name_len);
-
- rc = AllocDevicePair(client, name, &ptr, &keybd,
- CorePointerProc, CoreKeyboardProc, TRUE);
- if (rc != Success)
- goto unwind;
-
- if (!c->send_core)
- ptr->coreEvents = keybd->coreEvents = FALSE;
-
- /* Allocate virtual slave devices for xtest events */
- rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd);
- if (rc != Success)
- {
- DeleteInputDeviceRequest(ptr);
- DeleteInputDeviceRequest(keybd);
- goto unwind;
- }
-
- ActivateDevice(ptr, FALSE);
- ActivateDevice(keybd, FALSE);
- flags[ptr->id] |= XIMasterAdded;
- flags[keybd->id] |= XIMasterAdded;
-
- ActivateDevice(XTestptr, FALSE);
- ActivateDevice(XTestkeybd, FALSE);
- flags[XTestptr->id] |= XISlaveAdded;
- flags[XTestkeybd->id] |= XISlaveAdded;
-
- if (c->enable)
- {
- EnableDevice(ptr, FALSE);
- EnableDevice(keybd, FALSE);
- flags[ptr->id] |= XIDeviceEnabled;
- flags[keybd->id] |= XIDeviceEnabled;
-
- EnableDevice(XTestptr, FALSE);
- EnableDevice(XTestkeybd, FALSE);
- flags[XTestptr->id] |= XIDeviceEnabled;
- flags[XTestkeybd->id] |= XIDeviceEnabled;
- }
-
- /* Attach the XTest virtual devices to the newly
- created master device */
- AttachDevice(NULL, XTestptr, ptr);
- AttachDevice(NULL, XTestkeybd, keybd);
- flags[XTestptr->id] |= XISlaveAttached;
- flags[XTestkeybd->id] |= XISlaveAttached;
-
-unwind:
- free(name);
- return rc;
-}
-
-static int
-remove_master(ClientPtr client, xXIRemoveMasterInfo *r,
- int flags[MAXDEVICES])
-{
- DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
- int rc = Success;
-
- if (r->return_mode != XIAttachToMaster &&
- r->return_mode != XIFloating)
- return BadValue;
-
- rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- if (!IsMaster(ptr))
- {
- client->errorValue = r->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- /* XXX: For now, don't allow removal of VCP, VCK */
- if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard)
- {
- rc = BadDevice;
- goto unwind;
- }
-
-
- ptr = GetMaster(ptr, MASTER_POINTER);
- rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
- keybd = GetMaster(ptr, MASTER_KEYBOARD);
- rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- XTestptr = GetXTestDevice(ptr);
- rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- XTestkeybd = GetXTestDevice(keybd);
- rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client,
- DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- /* Disabling sends the devices floating, reattach them if
- * desired. */
- if (r->return_mode == XIAttachToMaster)
- {
- DeviceIntPtr attached,
- newptr,
- newkeybd;
-
- rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess);
- if (rc != Success)
- goto unwind;
-
- if (!IsMaster(newptr))
- {
- client->errorValue = r->return_pointer;
- rc = BadDevice;
- goto unwind;
- }
-
- rc = dixLookupDevice(&newkeybd, r->return_keyboard,
- client, DixAddAccess);
- if (rc != Success)
- goto unwind;
-
- if (!IsMaster(newkeybd))
- {
- client->errorValue = r->return_keyboard;
- rc = BadDevice;
- goto unwind;
- }
-
- for (attached = inputInfo.devices; attached; attached = attached->next)
- {
- if (!IsMaster(attached)) {
- if (GetMaster(attached, MASTER_ATTACHED) == ptr)
- {
- AttachDevice(client, attached, newptr);
- flags[attached->id] |= XISlaveAttached;
- }
- if (GetMaster(attached, MASTER_ATTACHED) == keybd)
- {
- AttachDevice(client, attached, newkeybd);
- flags[attached->id] |= XISlaveAttached;
- }
- }
- }
- }
-
- /* can't disable until we removed pairing */
- keybd->spriteInfo->paired = NULL;
- ptr->spriteInfo->paired = NULL;
- XTestptr->spriteInfo->paired = NULL;
- XTestkeybd->spriteInfo->paired = NULL;
-
- /* disable the remove the devices, XTest devices must be done first
- else the sprites they rely on will be destroyed */
- DisableDevice(XTestptr, FALSE);
- DisableDevice(XTestkeybd, FALSE);
- DisableDevice(keybd, FALSE);
- DisableDevice(ptr, FALSE);
- flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached;
- flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached;
- flags[keybd->id] |= XIDeviceDisabled;
- flags[ptr->id] |= XIDeviceDisabled;
-
- RemoveDevice(XTestptr, FALSE);
- RemoveDevice(XTestkeybd, FALSE);
- RemoveDevice(keybd, FALSE);
- RemoveDevice(ptr, FALSE);
- flags[XTestptr->id] |= XISlaveRemoved;
- flags[XTestkeybd->id] |= XISlaveRemoved;
- flags[keybd->id] |= XIMasterRemoved;
- flags[ptr->id] |= XIMasterRemoved;
-
-unwind:
- return rc;
-}
-
-static int
-detach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES])
-{
- DeviceIntPtr dev;
- int rc;
-
- rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess);
- if (rc != Success)
- goto unwind;
-
- if (IsMaster(dev))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- /* Don't allow changes to XTest Devices, these are fixed */
- if (IsXTestDevice(dev, NULL))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- AttachDevice(client, dev, NULL);
- flags[dev->id] |= XISlaveDetached;
-
-unwind:
- return rc;
-}
-
-static int
-attach_slave(ClientPtr client, xXIAttachSlaveInfo *c,
- int flags[MAXDEVICES])
-{
- DeviceIntPtr dev;
- DeviceIntPtr newmaster;
- int rc;
-
- rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess);
- if (rc != Success)
- goto unwind;
-
- if (IsMaster(dev))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- /* Don't allow changes to XTest Devices, these are fixed */
- if (IsXTestDevice(dev, NULL))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess);
- if (rc != Success)
- goto unwind;
- if (!IsMaster(newmaster))
- {
- client->errorValue = c->new_master;
- rc = BadDevice;
- goto unwind;
- }
-
- if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) ||
- (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev))))
- {
- rc = BadDevice;
- goto unwind;
- }
-
- AttachDevice(client, dev, newmaster);
- flags[dev->id] |= XISlaveAttached;
-
-unwind:
- return rc;
-}
-
-
-
-#define SWAPIF(cmd) if (client->swapped) { cmd; }
-
-int
-ProcXIChangeHierarchy(ClientPtr client)
-{
- xXIAnyHierarchyChangeInfo *any;
- int required_len = sizeof(xXIChangeHierarchyReq);
- char n;
- int rc = Success;
- int flags[MAXDEVICES] = {0};
-
- REQUEST(xXIChangeHierarchyReq);
- REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq);
-
- if (!stuff->num_changes)
- return rc;
-
- any = (xXIAnyHierarchyChangeInfo*)&stuff[1];
- while(stuff->num_changes--)
- {
- SWAPIF(swapl(&any->type, n));
- SWAPIF(swaps(&any->length, n));
-
- required_len += any->length;
- if ((stuff->length * 4) < required_len)
- return BadLength;
-
- switch(any->type)
- {
- case XIAddMaster:
- {
- xXIAddMasterInfo* c = (xXIAddMasterInfo*)any;
- SWAPIF(swaps(&c->name_len, n));
-
- rc = add_master(client, c, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- case XIRemoveMaster:
- {
- xXIRemoveMasterInfo* r = (xXIRemoveMasterInfo*)any;
-
- rc = remove_master(client, r, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- case XIDetachSlave:
- {
- xXIDetachSlaveInfo* c = (xXIDetachSlaveInfo*)any;
-
- rc = detach_slave(client, c, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- case XIAttachSlave:
- {
- xXIAttachSlaveInfo* c = (xXIAttachSlaveInfo*)any;
-
- rc = attach_slave(client, c, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- }
-
- any = (xXIAnyHierarchyChangeInfo*)((char*)any + any->length * 4);
- }
-
-unwind:
-
- XISendDeviceHierarchyEvent(flags);
- return rc;
-}
-
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Peter Hutterer, University of South Australia, NICTA
+ */
+
+/***********************************************************************
+ *
+ * Request change in the device hierarchy.
+ *
+ */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include "scrnintstr.h" /* screen structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XI2proto.h>
+#include <X11/extensions/geproto.h>
+#include "extnsionst.h"
+#include "exevents.h"
+#include "exglobals.h"
+#include "geext.h"
+#include "xace.h"
+#include "xiquerydevice.h" /* for GetDeviceUse */
+
+#include "xkbsrv.h"
+
+#include "xichangehierarchy.h"
+
+/**
+ * Send the current state of the device hierarchy to all clients.
+ */
+void XISendDeviceHierarchyEvent(int flags[MAXDEVICES])
+{
+ xXIHierarchyEvent *ev;
+ xXIHierarchyInfo *info;
+ DeviceIntRec dummyDev;
+ DeviceIntPtr dev;
+ int i;
+
+ if (!flags)
+ return;
+
+ ev = calloc(1, sizeof(xXIHierarchyEvent) +
+ MAXDEVICES * sizeof(xXIHierarchyInfo));
+ if (!ev)
+ return;
+ ev->type = GenericEvent;
+ ev->extension = IReqCode;
+ ev->evtype = XI_HierarchyChanged;
+ ev->time = GetTimeInMillis();
+ ev->flags = 0;
+ ev->num_info = inputInfo.numDevices;
+
+ info = (xXIHierarchyInfo*)&ev[1];
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ info->deviceid = dev->id;
+ info->enabled = dev->enabled;
+ info->use = GetDeviceUse(dev, &info->attachment);
+ info->flags = flags[dev->id];
+ ev->flags |= info->flags;
+ info++;
+ }
+ for (dev = inputInfo.off_devices; dev; dev = dev->next)
+ {
+ info->deviceid = dev->id;
+ info->enabled = dev->enabled;
+ info->use = GetDeviceUse(dev, &info->attachment);
+ info->flags = flags[dev->id];
+ ev->flags |= info->flags;
+ info++;
+ }
+
+
+ for (i = 0; i < MAXDEVICES; i++)
+ {
+ if (flags[i] & (XIMasterRemoved | XISlaveRemoved))
+ {
+ info->deviceid = i;
+ info->enabled = FALSE;
+ info->flags = flags[i];
+ info->use = 0;
+ ev->flags |= info->flags;
+ ev->num_info++;
+ info++;
+ }
+ }
+
+ ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo));
+
+ dummyDev.id = XIAllDevices;
+ SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1);
+ free(ev);
+}
+
+
+/***********************************************************************
+ *
+ * This procedure allows a client to change the device hierarchy through
+ * adding new master devices, removing them, etc.
+ *
+ */
+
+int SProcXIChangeHierarchy(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xXIChangeHierarchyReq);
+ swaps(&stuff->length, n);
+ return (ProcXIChangeHierarchy(client));
+}
+
+static int
+add_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES])
+{
+ DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
+ char* name;
+ int rc;
+
+ name = calloc(c->name_len + 1, sizeof(char));
+ strncpy(name, (char*)&c[1], c->name_len);
+
+ rc = AllocDevicePair(client, name, &ptr, &keybd,
+ CorePointerProc, CoreKeyboardProc, TRUE);
+ if (rc != Success)
+ goto unwind;
+
+ if (!c->send_core)
+ ptr->coreEvents = keybd->coreEvents = FALSE;
+
+ /* Allocate virtual slave devices for xtest events */
+ rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd);
+ if (rc != Success)
+ {
+ DeleteInputDeviceRequest(ptr);
+ DeleteInputDeviceRequest(keybd);
+ goto unwind;
+ }
+
+ ActivateDevice(ptr, FALSE);
+ ActivateDevice(keybd, FALSE);
+ flags[ptr->id] |= XIMasterAdded;
+ flags[keybd->id] |= XIMasterAdded;
+
+ ActivateDevice(XTestptr, FALSE);
+ ActivateDevice(XTestkeybd, FALSE);
+ flags[XTestptr->id] |= XISlaveAdded;
+ flags[XTestkeybd->id] |= XISlaveAdded;
+
+ if (c->enable)
+ {
+ EnableDevice(ptr, FALSE);
+ EnableDevice(keybd, FALSE);
+ flags[ptr->id] |= XIDeviceEnabled;
+ flags[keybd->id] |= XIDeviceEnabled;
+
+ EnableDevice(XTestptr, FALSE);
+ EnableDevice(XTestkeybd, FALSE);
+ flags[XTestptr->id] |= XIDeviceEnabled;
+ flags[XTestkeybd->id] |= XIDeviceEnabled;
+ }
+
+ /* Attach the XTest virtual devices to the newly
+ created master device */
+ AttachDevice(NULL, XTestptr, ptr);
+ AttachDevice(NULL, XTestkeybd, keybd);
+ flags[XTestptr->id] |= XISlaveAttached;
+ flags[XTestkeybd->id] |= XISlaveAttached;
+
+unwind:
+ free(name);
+ return rc;
+}
+
+static int
+remove_master(ClientPtr client, xXIRemoveMasterInfo *r,
+ int flags[MAXDEVICES])
+{
+ DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
+ int rc = Success;
+
+ if (r->return_mode != XIAttachToMaster &&
+ r->return_mode != XIFloating)
+ return BadValue;
+
+ rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess);
+ if (rc != Success)
+ goto unwind;
+
+ if (!IsMaster(ptr))
+ {
+ client->errorValue = r->deviceid;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ /* XXX: For now, don't allow removal of VCP, VCK */
+ if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard)
+ {
+ rc = BadDevice;
+ goto unwind;
+ }
+
+
+ ptr = GetMaster(ptr, MASTER_POINTER);
+ rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess);
+ if (rc != Success)
+ goto unwind;
+ keybd = GetMaster(ptr, MASTER_KEYBOARD);
+ rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess);
+ if (rc != Success)
+ goto unwind;
+
+ XTestptr = GetXTestDevice(ptr);
+ rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess);
+ if (rc != Success)
+ goto unwind;
+
+ XTestkeybd = GetXTestDevice(keybd);
+ rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client,
+ DixDestroyAccess);
+ if (rc != Success)
+ goto unwind;
+
+ /* Disabling sends the devices floating, reattach them if
+ * desired. */
+ if (r->return_mode == XIAttachToMaster)
+ {
+ DeviceIntPtr attached,
+ newptr,
+ newkeybd;
+
+ rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess);
+ if (rc != Success)
+ goto unwind;
+
+ if (!IsMaster(newptr))
+ {
+ client->errorValue = r->return_pointer;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ rc = dixLookupDevice(&newkeybd, r->return_keyboard,
+ client, DixAddAccess);
+ if (rc != Success)
+ goto unwind;
+
+ if (!IsMaster(newkeybd))
+ {
+ client->errorValue = r->return_keyboard;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ for (attached = inputInfo.devices; attached; attached = attached->next)
+ {
+ if (!IsMaster(attached)) {
+ if (GetMaster(attached, MASTER_ATTACHED) == ptr)
+ {
+ AttachDevice(client, attached, newptr);
+ flags[attached->id] |= XISlaveAttached;
+ }
+ if (GetMaster(attached, MASTER_ATTACHED) == keybd)
+ {
+ AttachDevice(client, attached, newkeybd);
+ flags[attached->id] |= XISlaveAttached;
+ }
+ }
+ }
+ }
+
+ /* can't disable until we removed pairing */
+ keybd->spriteInfo->paired = NULL;
+ ptr->spriteInfo->paired = NULL;
+ XTestptr->spriteInfo->paired = NULL;
+ XTestkeybd->spriteInfo->paired = NULL;
+
+ /* disable the remove the devices, XTest devices must be done first
+ else the sprites they rely on will be destroyed */
+ DisableDevice(XTestptr, FALSE);
+ DisableDevice(XTestkeybd, FALSE);
+ DisableDevice(keybd, FALSE);
+ DisableDevice(ptr, FALSE);
+ flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached;
+ flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached;
+ flags[keybd->id] |= XIDeviceDisabled;
+ flags[ptr->id] |= XIDeviceDisabled;
+
+ RemoveDevice(XTestptr, FALSE);
+ RemoveDevice(XTestkeybd, FALSE);
+ RemoveDevice(keybd, FALSE);
+ RemoveDevice(ptr, FALSE);
+ flags[XTestptr->id] |= XISlaveRemoved;
+ flags[XTestkeybd->id] |= XISlaveRemoved;
+ flags[keybd->id] |= XIMasterRemoved;
+ flags[ptr->id] |= XIMasterRemoved;
+
+unwind:
+ return rc;
+}
+
+static int
+detach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES])
+{
+ DeviceIntPtr dev;
+ int rc;
+
+ rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess);
+ if (rc != Success)
+ goto unwind;
+
+ if (IsMaster(dev))
+ {
+ client->errorValue = c->deviceid;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ /* Don't allow changes to XTest Devices, these are fixed */
+ if (IsXTestDevice(dev, NULL))
+ {
+ client->errorValue = c->deviceid;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ AttachDevice(client, dev, NULL);
+ flags[dev->id] |= XISlaveDetached;
+
+unwind:
+ return rc;
+}
+
+static int
+attach_slave(ClientPtr client, xXIAttachSlaveInfo *c,
+ int flags[MAXDEVICES])
+{
+ DeviceIntPtr dev;
+ DeviceIntPtr newmaster;
+ int rc;
+
+ rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess);
+ if (rc != Success)
+ goto unwind;
+
+ if (IsMaster(dev))
+ {
+ client->errorValue = c->deviceid;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ /* Don't allow changes to XTest Devices, these are fixed */
+ if (IsXTestDevice(dev, NULL))
+ {
+ client->errorValue = c->deviceid;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess);
+ if (rc != Success)
+ goto unwind;
+ if (!IsMaster(newmaster))
+ {
+ client->errorValue = c->new_master;
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) ||
+ (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev))))
+ {
+ rc = BadDevice;
+ goto unwind;
+ }
+
+ AttachDevice(client, dev, newmaster);
+ flags[dev->id] |= XISlaveAttached;
+
+unwind:
+ return rc;
+}
+
+
+
+#define SWAPIF(cmd) if (client->swapped) { cmd; }
+
+int
+ProcXIChangeHierarchy(ClientPtr client)
+{
+ xXIAnyHierarchyChangeInfo *any;
+ int required_len = sizeof(xXIChangeHierarchyReq);
+ char n;
+ int rc = Success;
+ int flags[MAXDEVICES] = {0};
+
+ REQUEST(xXIChangeHierarchyReq);
+ REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq);
+
+ if (!stuff->num_changes)
+ return rc;
+
+ any = (xXIAnyHierarchyChangeInfo*)&stuff[1];
+ while(stuff->num_changes--)
+ {
+ SWAPIF(swapl(&any->type, n));
+ SWAPIF(swaps(&any->length, n));
+
+ required_len += any->length;
+ if ((stuff->length * 4) < required_len)
+ return BadLength;
+
+ switch(any->type)
+ {
+ case XIAddMaster:
+ {
+ xXIAddMasterInfo* c = (xXIAddMasterInfo*)any;
+ SWAPIF(swaps(&c->name_len, n));
+
+ rc = add_master(client, c, flags);
+ if (rc != Success)
+ goto unwind;
+ }
+ break;
+ case XIRemoveMaster:
+ {
+ xXIRemoveMasterInfo* r = (xXIRemoveMasterInfo*)any;
+
+ rc = remove_master(client, r, flags);
+ if (rc != Success)
+ goto unwind;
+ }
+ break;
+ case XIDetachSlave:
+ {
+ xXIDetachSlaveInfo* c = (xXIDetachSlaveInfo*)any;
+
+ rc = detach_slave(client, c, flags);
+ if (rc != Success)
+ goto unwind;
+ }
+ break;
+ case XIAttachSlave:
+ {
+ xXIAttachSlaveInfo* c = (xXIAttachSlaveInfo*)any;
+
+ rc = attach_slave(client, c, flags);
+ if (rc != Success)
+ goto unwind;
+ }
+ break;
+ }
+
+ any = (xXIAnyHierarchyChangeInfo*)((char*)any + any->length * 4);
+ }
+
+unwind:
+
+ XISendDeviceHierarchyEvent(flags);
+ return rc;
+}
+
diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c
index 8663d12a1..3b98a79cd 100644
--- a/xorg-server/Xi/xipassivegrab.c
+++ b/xorg-server/Xi/xipassivegrab.c
@@ -1,307 +1,307 @@
-/*
- * Copyright © 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer
- */
-
-/***********************************************************************
- *
- * Request to grab or ungrab input device.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include <X11/extensions/XI2.h>
-#include <X11/extensions/XI2proto.h>
-#include "swaprep.h"
-
-#include "exglobals.h" /* BadDevice */
-#include "exevents.h"
-#include "xipassivegrab.h"
-#include "dixgrabs.h"
-
-int
-SProcXIPassiveGrabDevice(ClientPtr client)
-{
- int i;
- char n;
- xXIModifierInfo *mods;
-
- REQUEST(xXIPassiveGrabDeviceReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->grab_window, n);
- swapl(&stuff->cursor, n);
- swapl(&stuff->time, n);
- swapl(&stuff->detail, n);
- swaps(&stuff->mask_len, n);
- swaps(&stuff->num_modifiers, n);
-
- mods = (xXIModifierInfo*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, mods++)
- {
- swapl(&mods->base_mods, n);
- swapl(&mods->latched_mods, n);
- swapl(&mods->locked_mods, n);
- }
-
- return ProcXIPassiveGrabDevice(client);
-}
-
-int
-ProcXIPassiveGrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev, mod_dev;
- xXIPassiveGrabDeviceReply rep;
- int i, ret = Success;
- uint8_t status;
- uint32_t *modifiers;
- xXIGrabModifierInfo *modifiers_failed;
- GrabMask mask;
- GrabParameters param;
- void *tmp;
- int mask_len;
-
- REQUEST(xXIPassiveGrabDeviceReq);
- REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
-
- if (stuff->deviceid == XIAllDevices)
- dev = inputInfo.all_devices;
- else if (stuff->deviceid == XIAllMasterDevices)
- dev = inputInfo.all_master_devices;
- else
- {
- ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
- if (ret != Success)
- return ret;
- }
-
- if (stuff->grab_type != XIGrabtypeButton &&
- stuff->grab_type != XIGrabtypeKeycode &&
- stuff->grab_type != XIGrabtypeEnter &&
- stuff->grab_type != XIGrabtypeFocusIn)
- {
- client->errorValue = stuff->grab_type;
- return BadValue;
- }
-
- if ((stuff->grab_type == XIGrabtypeEnter ||
- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
- {
- client->errorValue = stuff->detail;
- return BadValue;
- }
-
- if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
- stuff->mask_len * 4) != Success)
- return BadValue;
-
- mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
- memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
- memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
-
- rep.repType = X_Reply;
- rep.RepType = X_XIPassiveGrabDevice;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.num_modifiers = 0;
-
- memset(&param, 0, sizeof(param));
- param.grabtype = GRABTYPE_XI2;
- param.ownerEvents = stuff->owner_events;
- param.this_device_mode = stuff->grab_mode;
- param.other_devices_mode = stuff->paired_device_mode;
- param.grabWindow = stuff->grab_window;
- param.cursor = stuff->cursor;
-
- if (stuff->cursor != None)
- {
- status = dixLookupResourceByType(&tmp, stuff->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (status != Success)
- {
- client->errorValue = stuff->cursor;
- return status;
- }
- }
-
- status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
- if (status != Success)
- return status;
-
- status = CheckGrabValues(client, &param);
-
- modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
- modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
- if (!modifiers_failed)
- return BadAlloc;
-
- mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- {
- param.modifiers = *modifiers;
- switch(stuff->grab_type)
- {
- case XIGrabtypeButton:
- status = GrabButton(client, dev, mod_dev, stuff->detail,
- &param, GRABTYPE_XI2, &mask);
- break;
- case XIGrabtypeKeycode:
- status = GrabKey(client, dev, mod_dev, stuff->detail,
- &param, GRABTYPE_XI2, &mask);
- break;
- case XIGrabtypeEnter:
- case XIGrabtypeFocusIn:
- status = GrabWindow(client, dev, stuff->grab_type,
- &param, &mask);
- break;
- }
-
- if (status != GrabSuccess)
- {
- xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
-
- info->status = status;
- info->modifiers = *modifiers;
- rep.num_modifiers++;
- rep.length++;
- }
- }
-
- WriteReplyToClient(client, sizeof(rep), &rep);
- if (rep.num_modifiers)
- {
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, rep.num_modifiers * 4, (char*)modifiers_failed);
- }
- free(modifiers_failed);
- return ret;
-}
-
-void
-SRepXIPassiveGrabDevice(ClientPtr client, int size,
- xXIPassiveGrabDeviceReply * rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swaps(&rep->num_modifiers, n);
-
- WriteToClient(client, size, (char *)rep);
-}
-
-int
-SProcXIPassiveUngrabDevice(ClientPtr client)
-{
- char n;
- int i;
- uint32_t *modifiers;
-
- REQUEST(xXIPassiveUngrabDeviceReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->grab_window, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->detail, n);
- swaps(&stuff->num_modifiers, n);
-
- modifiers = (uint32_t*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- swapl(modifiers, n);
-
- return ProcXIPassiveUngrabDevice(client);
-}
-
-int
-ProcXIPassiveUngrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev, mod_dev;
- WindowPtr win;
- GrabRec tempGrab;
- uint32_t* modifiers;
- int i, rc;
-
- REQUEST(xXIPassiveUngrabDeviceReq);
- REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
-
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
- if (rc != Success)
- return rc;
-
- if (stuff->grab_type != XIGrabtypeButton &&
- stuff->grab_type != XIGrabtypeKeycode &&
- stuff->grab_type != XIGrabtypeEnter &&
- stuff->grab_type != XIGrabtypeFocusIn)
- {
- client->errorValue = stuff->grab_type;
- return BadValue;
- }
-
- if ((stuff->grab_type == XIGrabtypeEnter ||
- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
- {
- client->errorValue = stuff->detail;
- return BadValue;
- }
-
- rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
- mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
-
- tempGrab.resource = client->clientAsMask;
- tempGrab.device = dev;
- tempGrab.window = win;
- switch(stuff->grab_type)
- {
- case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break;
- case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break;
- case XIGrabtypeEnter: tempGrab.type = XI_Enter; break;
- case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break;
- }
- tempGrab.grabtype = GRABTYPE_XI2;
- tempGrab.modifierDevice = mod_dev;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.detail.exact = stuff->detail;
- tempGrab.detail.pMask = NULL;
-
- modifiers = (uint32_t*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- {
- tempGrab.modifiersDetail.exact = *modifiers;
- DeletePassiveGrabFromList(&tempGrab);
- }
-
- return Success;
-}
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Peter Hutterer
+ */
+
+/***********************************************************************
+ *
+ * Request to grab or ungrab input device.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include <X11/extensions/XI2.h>
+#include <X11/extensions/XI2proto.h>
+#include "swaprep.h"
+
+#include "exglobals.h" /* BadDevice */
+#include "exevents.h"
+#include "xipassivegrab.h"
+#include "dixgrabs.h"
+
+int
+SProcXIPassiveGrabDevice(ClientPtr client)
+{
+ int i;
+ char n;
+ xXIModifierInfo *mods;
+
+ REQUEST(xXIPassiveGrabDeviceReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->grab_window, n);
+ swapl(&stuff->cursor, n);
+ swapl(&stuff->time, n);
+ swapl(&stuff->detail, n);
+ swaps(&stuff->mask_len, n);
+ swaps(&stuff->num_modifiers, n);
+
+ mods = (xXIModifierInfo*)&stuff[1];
+
+ for (i = 0; i < stuff->num_modifiers; i++, mods++)
+ {
+ swapl(&mods->base_mods, n);
+ swapl(&mods->latched_mods, n);
+ swapl(&mods->locked_mods, n);
+ }
+
+ return ProcXIPassiveGrabDevice(client);
+}
+
+int
+ProcXIPassiveGrabDevice(ClientPtr client)
+{
+ DeviceIntPtr dev, mod_dev;
+ xXIPassiveGrabDeviceReply rep;
+ int i, ret = Success;
+ uint8_t status;
+ uint32_t *modifiers;
+ xXIGrabModifierInfo *modifiers_failed;
+ GrabMask mask;
+ GrabParameters param;
+ void *tmp;
+ int mask_len;
+
+ REQUEST(xXIPassiveGrabDeviceReq);
+ REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
+
+ if (stuff->deviceid == XIAllDevices)
+ dev = inputInfo.all_devices;
+ else if (stuff->deviceid == XIAllMasterDevices)
+ dev = inputInfo.all_master_devices;
+ else
+ {
+ ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
+ if (ret != Success)
+ return ret;
+ }
+
+ if (stuff->grab_type != XIGrabtypeButton &&
+ stuff->grab_type != XIGrabtypeKeycode &&
+ stuff->grab_type != XIGrabtypeEnter &&
+ stuff->grab_type != XIGrabtypeFocusIn)
+ {
+ client->errorValue = stuff->grab_type;
+ return BadValue;
+ }
+
+ if ((stuff->grab_type == XIGrabtypeEnter ||
+ stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
+ {
+ client->errorValue = stuff->detail;
+ return BadValue;
+ }
+
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
+ stuff->mask_len * 4) != Success)
+ return BadValue;
+
+ mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
+ memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
+ memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_XIPassiveGrabDevice;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.num_modifiers = 0;
+
+ memset(&param, 0, sizeof(param));
+ param.grabtype = GRABTYPE_XI2;
+ param.ownerEvents = stuff->owner_events;
+ param.this_device_mode = stuff->grab_mode;
+ param.other_devices_mode = stuff->paired_device_mode;
+ param.grabWindow = stuff->grab_window;
+ param.cursor = stuff->cursor;
+
+ if (stuff->cursor != None)
+ {
+ status = dixLookupResourceByType(&tmp, stuff->cursor,
+ RT_CURSOR, client, DixUseAccess);
+ if (status != Success)
+ {
+ client->errorValue = stuff->cursor;
+ return status;
+ }
+ }
+
+ status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
+ if (status != Success)
+ return status;
+
+ status = CheckGrabValues(client, &param);
+
+ modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
+ modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
+ if (!modifiers_failed)
+ return BadAlloc;
+
+ mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
+
+ for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
+ {
+ param.modifiers = *modifiers;
+ switch(stuff->grab_type)
+ {
+ case XIGrabtypeButton:
+ status = GrabButton(client, dev, mod_dev, stuff->detail,
+ &param, GRABTYPE_XI2, &mask);
+ break;
+ case XIGrabtypeKeycode:
+ status = GrabKey(client, dev, mod_dev, stuff->detail,
+ &param, GRABTYPE_XI2, &mask);
+ break;
+ case XIGrabtypeEnter:
+ case XIGrabtypeFocusIn:
+ status = GrabWindow(client, dev, stuff->grab_type,
+ &param, &mask);
+ break;
+ }
+
+ if (status != GrabSuccess)
+ {
+ xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
+
+ info->status = status;
+ info->modifiers = *modifiers;
+ rep.num_modifiers++;
+ rep.length++;
+ }
+ }
+
+ WriteReplyToClient(client, sizeof(rep), &rep);
+ if (rep.num_modifiers)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
+ WriteSwappedDataToClient(client, rep.num_modifiers * 4, (char*)modifiers_failed);
+ }
+ free(modifiers_failed);
+ return ret;
+}
+
+void
+SRepXIPassiveGrabDevice(ClientPtr client, int size,
+ xXIPassiveGrabDeviceReply * rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->num_modifiers, n);
+
+ WriteToClient(client, size, (char *)rep);
+}
+
+int
+SProcXIPassiveUngrabDevice(ClientPtr client)
+{
+ char n;
+ int i;
+ uint32_t *modifiers;
+
+ REQUEST(xXIPassiveUngrabDeviceReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->grab_window, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->detail, n);
+ swaps(&stuff->num_modifiers, n);
+
+ modifiers = (uint32_t*)&stuff[1];
+
+ for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
+ swapl(modifiers, n);
+
+ return ProcXIPassiveUngrabDevice(client);
+}
+
+int
+ProcXIPassiveUngrabDevice(ClientPtr client)
+{
+ DeviceIntPtr dev, mod_dev;
+ WindowPtr win;
+ GrabRec tempGrab;
+ uint32_t* modifiers;
+ int i, rc;
+
+ REQUEST(xXIPassiveUngrabDeviceReq);
+ REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
+
+ rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->grab_type != XIGrabtypeButton &&
+ stuff->grab_type != XIGrabtypeKeycode &&
+ stuff->grab_type != XIGrabtypeEnter &&
+ stuff->grab_type != XIGrabtypeFocusIn)
+ {
+ client->errorValue = stuff->grab_type;
+ return BadValue;
+ }
+
+ if ((stuff->grab_type == XIGrabtypeEnter ||
+ stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
+ {
+ client->errorValue = stuff->detail;
+ return BadValue;
+ }
+
+ rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
+
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.device = dev;
+ tempGrab.window = win;
+ switch(stuff->grab_type)
+ {
+ case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break;
+ case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break;
+ case XIGrabtypeEnter: tempGrab.type = XI_Enter; break;
+ case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break;
+ }
+ tempGrab.grabtype = GRABTYPE_XI2;
+ tempGrab.modifierDevice = mod_dev;
+ tempGrab.modifiersDetail.pMask = NULL;
+ tempGrab.detail.exact = stuff->detail;
+ tempGrab.detail.pMask = NULL;
+
+ modifiers = (uint32_t*)&stuff[1];
+
+ for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
+ {
+ tempGrab.modifiersDetail.exact = *modifiers;
+ DeletePassiveGrabFromList(&tempGrab);
+ }
+
+ return Success;
+}
diff --git a/xorg-server/Xi/xiquerydevice.c b/xorg-server/Xi/xiquerydevice.c
index 8b5421130..f8a4eb8a5 100644
--- a/xorg-server/Xi/xiquerydevice.c
+++ b/xorg-server/Xi/xiquerydevice.c
@@ -1,503 +1,503 @@
-/*
- * Copyright © 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Peter Hutterer
- *
- */
-
-/**
- * @file Protocol handling for the XIQueryDevice request/reply.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h"
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/extensions/XI2proto.h>
-#include "xkbstr.h"
-#include "xkbsrv.h"
-#include "xserver-properties.h"
-#include "exevents.h"
-#include "xace.h"
-
-#include "xiquerydevice.h"
-
-static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
-static int
-ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info);
-static int SizeDeviceInfo(DeviceIntPtr dev);
-static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
-int
-SProcXIQueryDevice(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIQueryDeviceReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
-
- return ProcXIQueryDevice(client);
-}
-
-int
-ProcXIQueryDevice(ClientPtr client)
-{
- xXIQueryDeviceReply rep;
- DeviceIntPtr dev = NULL;
- int rc = Success;
- int i = 0, len = 0;
- char *info, *ptr;
- Bool *skip = NULL;
-
- REQUEST(xXIQueryDeviceReq);
- REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
-
- if (stuff->deviceid != XIAllDevices && stuff->deviceid != XIAllMasterDevices)
- {
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->deviceid;
- return rc;
- }
- len += SizeDeviceInfo(dev);
- }
- else
- {
- skip = calloc(sizeof(Bool), inputInfo.numDevices);
- if (!skip)
- return BadAlloc;
-
- for (dev = inputInfo.devices; dev; dev = dev->next, i++)
- {
- skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
- if (!skip[i])
- len += SizeDeviceInfo(dev);
- }
-
- for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
- {
- skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
- if (!skip[i])
- len += SizeDeviceInfo(dev);
- }
- }
-
- info = calloc(1, len);
- if (!info)
- return BadAlloc;
-
- memset(&rep, 0, sizeof(xXIQueryDeviceReply));
- rep.repType = X_Reply;
- rep.RepType = X_XIQueryDevice;
- rep.sequenceNumber = client->sequence;
- rep.length = len/4;
- rep.num_devices = 0;
-
- ptr = info;
- if (dev)
- {
- len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
- if (client->swapped)
- SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
- info += len;
- rep.num_devices = 1;
- } else
- {
- i = 0;
- for (dev = inputInfo.devices; dev; dev = dev->next, i++)
- {
- if (!skip[i])
- {
- len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
- if (client->swapped)
- SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
- info += len;
- rep.num_devices++;
- }
- }
-
- for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
- {
- if (!skip[i])
- {
- len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
- if (client->swapped)
- SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
- info += len;
- rep.num_devices++;
- }
- }
- }
-
- WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
- WriteToClient(client, rep.length * 4, ptr);
- free(ptr);
- free(skip);
- return rc;
-}
-
-void
-SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swaps(&rep->num_devices, n);
-
- /* Device info is already swapped, see ProcXIQueryDevice */
-
- WriteToClient(client, size, (char *)rep);
-}
-
-
-/**
- * @return Whether the device should be included in the returned list.
- */
-static Bool
-ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
-{
- /* if all devices are not being queried, only master devices are */
- if (deviceid == XIAllDevices || IsMaster(dev))
- {
- int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
- if (rc == Success)
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * @return The number of bytes needed to store this device's xXIDeviceInfo
- * (and its classes).
- */
-static int
-SizeDeviceInfo(DeviceIntPtr dev)
-{
- int len = sizeof(xXIDeviceInfo);
-
- /* 4-padded name */
- len += pad_to_int32(strlen(dev->name));
-
- return len + SizeDeviceClasses(dev);
-
-}
-
-/*
- * @return The number of bytes needed to store this device's classes.
- */
-int
-SizeDeviceClasses(DeviceIntPtr dev)
-{
- int len = 0;
-
- if (dev->button)
- {
- len += sizeof(xXIButtonInfo);
- len += dev->button->numButtons * sizeof(Atom);
- len += pad_to_int32(bits_to_bytes(dev->button->numButtons));
- }
-
- if (dev->key)
- {
- XkbDescPtr xkb = dev->key->xkbInfo->desc;
- len += sizeof(xXIKeyInfo);
- len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
- }
-
- if (dev->valuator)
- len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
-
- return len;
-}
-
-
-/**
- * Write button information into info.
- * @return Number of bytes written into info.
- */
-int
-ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info, Bool reportState)
-{
- unsigned char *bits;
- int mask_len;
- int i;
-
- if (!dev || !dev->button)
- return 0;
-
- mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons));
-
- info->type = ButtonClass;
- info->num_buttons = dev->button->numButtons;
- info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
- info->num_buttons + mask_len;
- info->sourceid = dev->button->sourceid;
-
- bits = (unsigned char*)&info[1];
- memset(bits, 0, mask_len * 4);
-
- if (reportState)
- for (i = 0; i < dev->button->numButtons; i++)
- if (BitIsOn(dev->button->down, i))
- SetBit(bits, i);
-
- bits += mask_len * 4;
- memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom));
-
- return info->length * 4;
-}
-
-static void
-SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info)
-{
- char n;
- Atom *btn;
- int i;
- swaps(&info->type, n);
- swaps(&info->length, n);
- swaps(&info->sourceid, n);
-
- for (i = 0, btn = (Atom*)&info[1]; i < info->num_buttons; i++, btn++)
- swaps(btn, n);
-
- swaps(&info->num_buttons, n);
-}
-
-/**
- * Write key information into info.
- * @return Number of bytes written into info.
- */
-int
-ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
-{
- int i;
- XkbDescPtr xkb = dev->key->xkbInfo->desc;
- uint32_t *kc;
-
- info->type = KeyClass;
- info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
- info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes;
- info->sourceid = dev->key->sourceid;
-
- kc = (uint32_t*)&info[1];
- for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
- *kc = i;
-
- return info->length * 4;
-}
-
-static void
-SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
-{
- char n;
- uint32_t *key;
- int i;
- swaps(&info->type, n);
- swaps(&info->length, n);
- swaps(&info->sourceid, n);
-
- for (i = 0, key = (uint32_t*)&info[1]; i < info->num_keycodes; i++, key++)
- swapl(key, n);
-
- swaps(&info->num_keycodes, n);
-}
-
-/**
- * List axis information for the given axis.
- *
- * @return The number of bytes written into info.
- */
-int
-ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber,
- Bool reportState)
-{
- ValuatorClassPtr v = dev->valuator;
-
- info->type = ValuatorClass;
- info->length = sizeof(xXIValuatorInfo)/4;
- info->label = v->axes[axisnumber].label;
- info->min.integral = v->axes[axisnumber].min_value;
- info->min.frac = 0;
- info->max.integral = v->axes[axisnumber].max_value;
- info->max.frac = 0;
- info->value.integral = (int)v->axisVal[axisnumber];
- info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16));
- info->resolution = v->axes[axisnumber].resolution;
- info->number = axisnumber;
- info->mode = valuator_get_mode(dev, axisnumber);
- info->sourceid = v->sourceid;
-
- if (!reportState)
- info->value = info->min;
-
- return info->length * 4;
-}
-
-static void
-SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info)
-{
- char n;
- swaps(&info->type, n);
- swaps(&info->length, n);
- swapl(&info->label, n);
- swapl(&info->min.integral, n);
- swapl(&info->min.frac, n);
- swapl(&info->max.integral, n);
- swapl(&info->max.frac, n);
- swaps(&info->number, n);
- swaps(&info->sourceid, n);
-}
-
-int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
-{
- DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
- int use;
-
- if (IsMaster(dev))
- {
- DeviceIntPtr paired = GetPairedDevice(dev);
- use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
- *attachment = (paired ? paired->id : 0);
- } else if (!IsFloating(dev))
- {
- use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
- *attachment = master->id;
- } else
- use = XIFloatingSlave;
-
- return use;
-}
-
-/**
- * Write the info for device dev into the buffer pointed to by info.
- *
- * @return The number of bytes used.
- */
-static int
-ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info)
-{
- char *any = (char*)&info[1];
- int len = 0, total_len = 0;
-
- info->deviceid = dev->id;
- info->use = GetDeviceUse(dev, &info->attachment);
- info->num_classes = 0;
- info->name_len = strlen(dev->name);
- info->enabled = dev->enabled;
- total_len = sizeof(xXIDeviceInfo);
-
- len = pad_to_int32(info->name_len);
- memset(any, 0, len);
- strncpy(any, dev->name, info->name_len);
- any += len;
- total_len += len;
-
- total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
- return total_len;
-}
-
-/**
- * Write the class info of the device into the memory pointed to by any, set
- * nclasses to the number of classes in total and return the number of bytes
- * written.
- */
-int
-ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
- char *any, uint16_t *nclasses)
-{
- int total_len = 0;
- int len;
- int i;
- int rc;
-
- /* Check if the current device state should be suppressed */
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
-
- if (dev->button)
- {
- (*nclasses)++;
- len = ListButtonInfo(dev, (xXIButtonInfo*)any, rc == Success);
- any += len;
- total_len += len;
- }
-
- if (dev->key)
- {
- (*nclasses)++;
- len = ListKeyInfo(dev, (xXIKeyInfo*)any);
- any += len;
- total_len += len;
- }
-
- for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++)
- {
- (*nclasses)++;
- len = ListValuatorInfo(dev, (xXIValuatorInfo*)any, i, rc == Success);
- any += len;
- total_len += len;
- }
-
- return total_len;
-}
-
-static void
-SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info)
-{
- char n;
- char *any = (char*)&info[1];
- int i;
-
- /* Skip over name */
- any += pad_to_int32(info->name_len);
-
- for (i = 0; i < info->num_classes; i++)
- {
- int len = ((xXIAnyInfo*)any)->length;
- switch(((xXIAnyInfo*)any)->type)
- {
- case XIButtonClass:
- SwapButtonInfo(dev, (xXIButtonInfo*)any);
- break;
- case XIKeyClass:
- SwapKeyInfo(dev, (xXIKeyInfo*)any);
- break;
- case XIValuatorClass:
- SwapValuatorInfo(dev, (xXIValuatorInfo*)any);
- break;
- }
-
- any += len * 4;
- }
-
- swaps(&info->deviceid, n);
- swaps(&info->use, n);
- swaps(&info->attachment, n);
- swaps(&info->num_classes, n);
- swaps(&info->name_len, n);
-
-}
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Peter Hutterer
+ *
+ */
+
+/**
+ * @file Protocol handling for the XIQueryDevice request/reply.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h"
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XI2proto.h>
+#include "xkbstr.h"
+#include "xkbsrv.h"
+#include "xserver-properties.h"
+#include "exevents.h"
+#include "xace.h"
+
+#include "xiquerydevice.h"
+
+static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
+static int
+ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info);
+static int SizeDeviceInfo(DeviceIntPtr dev);
+static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
+int
+SProcXIQueryDevice(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xXIQueryDeviceReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+
+ return ProcXIQueryDevice(client);
+}
+
+int
+ProcXIQueryDevice(ClientPtr client)
+{
+ xXIQueryDeviceReply rep;
+ DeviceIntPtr dev = NULL;
+ int rc = Success;
+ int i = 0, len = 0;
+ char *info, *ptr;
+ Bool *skip = NULL;
+
+ REQUEST(xXIQueryDeviceReq);
+ REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
+
+ if (stuff->deviceid != XIAllDevices && stuff->deviceid != XIAllMasterDevices)
+ {
+ rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->deviceid;
+ return rc;
+ }
+ len += SizeDeviceInfo(dev);
+ }
+ else
+ {
+ skip = calloc(sizeof(Bool), inputInfo.numDevices);
+ if (!skip)
+ return BadAlloc;
+
+ for (dev = inputInfo.devices; dev; dev = dev->next, i++)
+ {
+ skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
+ if (!skip[i])
+ len += SizeDeviceInfo(dev);
+ }
+
+ for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
+ {
+ skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
+ if (!skip[i])
+ len += SizeDeviceInfo(dev);
+ }
+ }
+
+ info = calloc(1, len);
+ if (!info)
+ return BadAlloc;
+
+ memset(&rep, 0, sizeof(xXIQueryDeviceReply));
+ rep.repType = X_Reply;
+ rep.RepType = X_XIQueryDevice;
+ rep.sequenceNumber = client->sequence;
+ rep.length = len/4;
+ rep.num_devices = 0;
+
+ ptr = info;
+ if (dev)
+ {
+ len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
+ if (client->swapped)
+ SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
+ info += len;
+ rep.num_devices = 1;
+ } else
+ {
+ i = 0;
+ for (dev = inputInfo.devices; dev; dev = dev->next, i++)
+ {
+ if (!skip[i])
+ {
+ len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
+ if (client->swapped)
+ SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
+ info += len;
+ rep.num_devices++;
+ }
+ }
+
+ for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
+ {
+ if (!skip[i])
+ {
+ len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
+ if (client->swapped)
+ SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
+ info += len;
+ rep.num_devices++;
+ }
+ }
+ }
+
+ WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
+ WriteToClient(client, rep.length * 4, ptr);
+ free(ptr);
+ free(skip);
+ return rc;
+}
+
+void
+SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->num_devices, n);
+
+ /* Device info is already swapped, see ProcXIQueryDevice */
+
+ WriteToClient(client, size, (char *)rep);
+}
+
+
+/**
+ * @return Whether the device should be included in the returned list.
+ */
+static Bool
+ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
+{
+ /* if all devices are not being queried, only master devices are */
+ if (deviceid == XIAllDevices || IsMaster(dev))
+ {
+ int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
+ if (rc == Success)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * @return The number of bytes needed to store this device's xXIDeviceInfo
+ * (and its classes).
+ */
+static int
+SizeDeviceInfo(DeviceIntPtr dev)
+{
+ int len = sizeof(xXIDeviceInfo);
+
+ /* 4-padded name */
+ len += pad_to_int32(strlen(dev->name));
+
+ return len + SizeDeviceClasses(dev);
+
+}
+
+/*
+ * @return The number of bytes needed to store this device's classes.
+ */
+int
+SizeDeviceClasses(DeviceIntPtr dev)
+{
+ int len = 0;
+
+ if (dev->button)
+ {
+ len += sizeof(xXIButtonInfo);
+ len += dev->button->numButtons * sizeof(Atom);
+ len += pad_to_int32(bits_to_bytes(dev->button->numButtons));
+ }
+
+ if (dev->key)
+ {
+ XkbDescPtr xkb = dev->key->xkbInfo->desc;
+ len += sizeof(xXIKeyInfo);
+ len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
+ }
+
+ if (dev->valuator)
+ len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
+
+ return len;
+}
+
+
+/**
+ * Write button information into info.
+ * @return Number of bytes written into info.
+ */
+int
+ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info, Bool reportState)
+{
+ unsigned char *bits;
+ int mask_len;
+ int i;
+
+ if (!dev || !dev->button)
+ return 0;
+
+ mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons));
+
+ info->type = ButtonClass;
+ info->num_buttons = dev->button->numButtons;
+ info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
+ info->num_buttons + mask_len;
+ info->sourceid = dev->button->sourceid;
+
+ bits = (unsigned char*)&info[1];
+ memset(bits, 0, mask_len * 4);
+
+ if (reportState)
+ for (i = 0; i < dev->button->numButtons; i++)
+ if (BitIsOn(dev->button->down, i))
+ SetBit(bits, i);
+
+ bits += mask_len * 4;
+ memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom));
+
+ return info->length * 4;
+}
+
+static void
+SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info)
+{
+ char n;
+ Atom *btn;
+ int i;
+ swaps(&info->type, n);
+ swaps(&info->length, n);
+ swaps(&info->sourceid, n);
+
+ for (i = 0, btn = (Atom*)&info[1]; i < info->num_buttons; i++, btn++)
+ swaps(btn, n);
+
+ swaps(&info->num_buttons, n);
+}
+
+/**
+ * Write key information into info.
+ * @return Number of bytes written into info.
+ */
+int
+ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
+{
+ int i;
+ XkbDescPtr xkb = dev->key->xkbInfo->desc;
+ uint32_t *kc;
+
+ info->type = KeyClass;
+ info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
+ info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes;
+ info->sourceid = dev->key->sourceid;
+
+ kc = (uint32_t*)&info[1];
+ for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
+ *kc = i;
+
+ return info->length * 4;
+}
+
+static void
+SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
+{
+ char n;
+ uint32_t *key;
+ int i;
+ swaps(&info->type, n);
+ swaps(&info->length, n);
+ swaps(&info->sourceid, n);
+
+ for (i = 0, key = (uint32_t*)&info[1]; i < info->num_keycodes; i++, key++)
+ swapl(key, n);
+
+ swaps(&info->num_keycodes, n);
+}
+
+/**
+ * List axis information for the given axis.
+ *
+ * @return The number of bytes written into info.
+ */
+int
+ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber,
+ Bool reportState)
+{
+ ValuatorClassPtr v = dev->valuator;
+
+ info->type = ValuatorClass;
+ info->length = sizeof(xXIValuatorInfo)/4;
+ info->label = v->axes[axisnumber].label;
+ info->min.integral = v->axes[axisnumber].min_value;
+ info->min.frac = 0;
+ info->max.integral = v->axes[axisnumber].max_value;
+ info->max.frac = 0;
+ info->value.integral = (int)v->axisVal[axisnumber];
+ info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16));
+ info->resolution = v->axes[axisnumber].resolution;
+ info->number = axisnumber;
+ info->mode = valuator_get_mode(dev, axisnumber);
+ info->sourceid = v->sourceid;
+
+ if (!reportState)
+ info->value = info->min;
+
+ return info->length * 4;
+}
+
+static void
+SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info)
+{
+ char n;
+ swaps(&info->type, n);
+ swaps(&info->length, n);
+ swapl(&info->label, n);
+ swapl(&info->min.integral, n);
+ swapl(&info->min.frac, n);
+ swapl(&info->max.integral, n);
+ swapl(&info->max.frac, n);
+ swaps(&info->number, n);
+ swaps(&info->sourceid, n);
+}
+
+int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
+{
+ DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
+ int use;
+
+ if (IsMaster(dev))
+ {
+ DeviceIntPtr paired = GetPairedDevice(dev);
+ use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
+ *attachment = (paired ? paired->id : 0);
+ } else if (!IsFloating(dev))
+ {
+ use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
+ *attachment = master->id;
+ } else
+ use = XIFloatingSlave;
+
+ return use;
+}
+
+/**
+ * Write the info for device dev into the buffer pointed to by info.
+ *
+ * @return The number of bytes used.
+ */
+static int
+ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info)
+{
+ char *any = (char*)&info[1];
+ int len = 0, total_len = 0;
+
+ info->deviceid = dev->id;
+ info->use = GetDeviceUse(dev, &info->attachment);
+ info->num_classes = 0;
+ info->name_len = strlen(dev->name);
+ info->enabled = dev->enabled;
+ total_len = sizeof(xXIDeviceInfo);
+
+ len = pad_to_int32(info->name_len);
+ memset(any, 0, len);
+ strncpy(any, dev->name, info->name_len);
+ any += len;
+ total_len += len;
+
+ total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
+ return total_len;
+}
+
+/**
+ * Write the class info of the device into the memory pointed to by any, set
+ * nclasses to the number of classes in total and return the number of bytes
+ * written.
+ */
+int
+ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
+ char *any, uint16_t *nclasses)
+{
+ int total_len = 0;
+ int len;
+ int i;
+ int rc;
+
+ /* Check if the current device state should be suppressed */
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
+
+ if (dev->button)
+ {
+ (*nclasses)++;
+ len = ListButtonInfo(dev, (xXIButtonInfo*)any, rc == Success);
+ any += len;
+ total_len += len;
+ }
+
+ if (dev->key)
+ {
+ (*nclasses)++;
+ len = ListKeyInfo(dev, (xXIKeyInfo*)any);
+ any += len;
+ total_len += len;
+ }
+
+ for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++)
+ {
+ (*nclasses)++;
+ len = ListValuatorInfo(dev, (xXIValuatorInfo*)any, i, rc == Success);
+ any += len;
+ total_len += len;
+ }
+
+ return total_len;
+}
+
+static void
+SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info)
+{
+ char n;
+ char *any = (char*)&info[1];
+ int i;
+
+ /* Skip over name */
+ any += pad_to_int32(info->name_len);
+
+ for (i = 0; i < info->num_classes; i++)
+ {
+ int len = ((xXIAnyInfo*)any)->length;
+ switch(((xXIAnyInfo*)any)->type)
+ {
+ case XIButtonClass:
+ SwapButtonInfo(dev, (xXIButtonInfo*)any);
+ break;
+ case XIKeyClass:
+ SwapKeyInfo(dev, (xXIKeyInfo*)any);
+ break;
+ case XIValuatorClass:
+ SwapValuatorInfo(dev, (xXIValuatorInfo*)any);
+ break;
+ }
+
+ any += len * 4;
+ }
+
+ swaps(&info->deviceid, n);
+ swaps(&info->use, n);
+ swaps(&info->attachment, n);
+ swaps(&info->num_classes, n);
+ swaps(&info->name_len, n);
+
+}
diff --git a/xorg-server/Xi/xiquerypointer.c b/xorg-server/Xi/xiquerypointer.c
index 51317994b..ce025432e 100644
--- a/xorg-server/Xi/xiquerypointer.c
+++ b/xorg-server/Xi/xiquerypointer.c
@@ -1,229 +1,229 @@
-/*
- * Copyright 2007-2008 Peter Hutterer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer, University of South Australia, NICTA
- */
-
-/***********************************************************************
- *
- * Request to query the pointer location of an extension input device.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h> /* for inputstr.h */
-#include <X11/Xproto.h> /* Request macro */
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XI2proto.h>
-#include "extnsionst.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "eventconvert.h"
-#include "scrnintstr.h"
-#include "xkbsrv.h"
-
-#ifdef PANORAMIX
-#include "panoramiXsrv.h"
-#endif
-
-#include "xiquerypointer.h"
-
-/***********************************************************************
- *
- * This procedure allows a client to query the pointer of a device.
- *
- */
-
-int
-SProcXIQueryPointer(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIQueryPointerReq);
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->win, n);
- return (ProcXIQueryPointer(client));
-}
-
-int
-ProcXIQueryPointer(ClientPtr client)
-{
- int rc;
- xXIQueryPointerReply rep;
- DeviceIntPtr pDev, kbd;
- WindowPtr pWin, t;
- SpritePtr pSprite;
- XkbStatePtr state;
- char *buttons = NULL;
- int buttons_size = 0; /* size of buttons array */
-
- REQUEST(xXIQueryPointerReq);
- REQUEST_SIZE_MATCH(xXIQueryPointerReq);
-
- rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->deviceid;
- return rc;
- }
-
- if (pDev->valuator == NULL || IsKeyboardDevice(pDev) ||
- (!IsMaster(pDev) && !IsFloating(pDev))) /* no attached devices */
- {
- client->errorValue = stuff->deviceid;
- return BadDevice;
- }
-
- rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess);
- if (rc != Success)
- {
- SendErrorToClient(client, IReqCode, X_XIQueryPointer,
- stuff->win, rc);
- return Success;
- }
-
- if (pDev->valuator->motionHintWindow)
- MaybeStopHint(pDev, client);
-
- if (IsMaster(pDev))
- kbd = GetPairedDevice(pDev);
- else
- kbd = (pDev->key) ? pDev : NULL;
-
- pSprite = pDev->spriteInfo->sprite;
-
- memset(&rep, 0, sizeof(rep));
- rep.repType = X_Reply;
- rep.RepType = X_XIQueryPointer;
- rep.length = 6;
- rep.sequenceNumber = client->sequence;
- rep.root = (GetCurrentRootWindow(pDev))->drawable.id;
- rep.root_x = FP1616(pSprite->hot.x, 0);
- rep.root_y = FP1616(pSprite->hot.y, 0);
- rep.child = None;
-
- if (kbd)
- {
- state = &kbd->key->xkbInfo->state;
- rep.mods.base_mods = state->base_mods;
- rep.mods.latched_mods = state->latched_mods;
- rep.mods.locked_mods = state->locked_mods;
-
- rep.group.base_group = state->base_group;
- rep.group.latched_group = state->latched_group;
- rep.group.locked_group = state->locked_group;
- }
-
- if (pDev->button)
- {
- int i, down;
- rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
- rep.length += rep.buttons_len;
- buttons_size = rep.buttons_len * 4;
- buttons = calloc(1, buttons_size);
- if (!buttons)
- return BadAlloc;
-
- down = pDev->button->buttonsDown;
-
- for (i = 0; i < pDev->button->numButtons && down; i++)
- {
- if (BitIsOn(pDev->button->down, i))
- {
- SetBit(buttons, i);
- down--;
- }
- }
- } else
- rep.buttons_len = 0;
-
- if (pSprite->hot.pScreen == pWin->drawable.pScreen)
- {
- rep.same_screen = xTrue;
- rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0);
- rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0);
- for (t = pSprite->win; t; t = t->parent)
- if (t->parent == pWin)
- {
- rep.child = t->drawable.id;
- break;
- }
- } else
- {
- rep.same_screen = xFalse;
- rep.win_x = 0;
- rep.win_y = 0;
- }
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- rep.root_x += FP1616(screenInfo.screens[0]->x, 0);
- rep.root_y += FP1616(screenInfo.screens[0]->y, 0);
- if (stuff->win == rep.root)
- {
- rep.win_x += FP1616(screenInfo.screens[0]->x, 0);
- rep.win_y += FP1616(screenInfo.screens[0]->y, 0);
- }
- }
-#endif
-
- WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep);
- if (buttons)
- WriteToClient(client, buttons_size, buttons);
-
- free(buttons);
-
- return Success;
-}
-
-/***********************************************************************
- *
- * This procedure writes the reply for the XIQueryPointer function,
- * if the client and server have a different byte ordering.
- *
- */
-
-void
-SRepXIQueryPointer(ClientPtr client, int size,
- xXIQueryPointerReply * rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swapl(&rep->root, n);
- swapl(&rep->child, n);
- swapl(&rep->root_x, n);
- swapl(&rep->root_y, n);
- swapl(&rep->win_x, n);
- swapl(&rep->win_y, n);
- swaps(&rep->buttons_len, n);
-
- WriteToClient(client, size, (char *)rep);
-}
-
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Peter Hutterer, University of South Australia, NICTA
+ */
+
+/***********************************************************************
+ *
+ * Request to query the pointer location of an extension input device.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XI2proto.h>
+#include "extnsionst.h"
+#include "exevents.h"
+#include "exglobals.h"
+#include "eventconvert.h"
+#include "scrnintstr.h"
+#include "xkbsrv.h"
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
+#include "xiquerypointer.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to query the pointer of a device.
+ *
+ */
+
+int
+SProcXIQueryPointer(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xXIQueryPointerReq);
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->win, n);
+ return (ProcXIQueryPointer(client));
+}
+
+int
+ProcXIQueryPointer(ClientPtr client)
+{
+ int rc;
+ xXIQueryPointerReply rep;
+ DeviceIntPtr pDev, kbd;
+ WindowPtr pWin, t;
+ SpritePtr pSprite;
+ XkbStatePtr state;
+ char *buttons = NULL;
+ int buttons_size = 0; /* size of buttons array */
+
+ REQUEST(xXIQueryPointerReq);
+ REQUEST_SIZE_MATCH(xXIQueryPointerReq);
+
+ rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->deviceid;
+ return rc;
+ }
+
+ if (pDev->valuator == NULL || IsKeyboardDevice(pDev) ||
+ (!IsMaster(pDev) && !IsFloating(pDev))) /* no attached devices */
+ {
+ client->errorValue = stuff->deviceid;
+ return BadDevice;
+ }
+
+ rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess);
+ if (rc != Success)
+ {
+ SendErrorToClient(client, IReqCode, X_XIQueryPointer,
+ stuff->win, rc);
+ return Success;
+ }
+
+ if (pDev->valuator->motionHintWindow)
+ MaybeStopHint(pDev, client);
+
+ if (IsMaster(pDev))
+ kbd = GetPairedDevice(pDev);
+ else
+ kbd = (pDev->key) ? pDev : NULL;
+
+ pSprite = pDev->spriteInfo->sprite;
+
+ memset(&rep, 0, sizeof(rep));
+ rep.repType = X_Reply;
+ rep.RepType = X_XIQueryPointer;
+ rep.length = 6;
+ rep.sequenceNumber = client->sequence;
+ rep.root = (GetCurrentRootWindow(pDev))->drawable.id;
+ rep.root_x = FP1616(pSprite->hot.x, 0);
+ rep.root_y = FP1616(pSprite->hot.y, 0);
+ rep.child = None;
+
+ if (kbd)
+ {
+ state = &kbd->key->xkbInfo->state;
+ rep.mods.base_mods = state->base_mods;
+ rep.mods.latched_mods = state->latched_mods;
+ rep.mods.locked_mods = state->locked_mods;
+
+ rep.group.base_group = state->base_group;
+ rep.group.latched_group = state->latched_group;
+ rep.group.locked_group = state->locked_group;
+ }
+
+ if (pDev->button)
+ {
+ int i, down;
+ rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
+ rep.length += rep.buttons_len;
+ buttons_size = rep.buttons_len * 4;
+ buttons = calloc(1, buttons_size);
+ if (!buttons)
+ return BadAlloc;
+
+ down = pDev->button->buttonsDown;
+
+ for (i = 0; i < pDev->button->numButtons && down; i++)
+ {
+ if (BitIsOn(pDev->button->down, i))
+ {
+ SetBit(buttons, i);
+ down--;
+ }
+ }
+ } else
+ rep.buttons_len = 0;
+
+ if (pSprite->hot.pScreen == pWin->drawable.pScreen)
+ {
+ rep.same_screen = xTrue;
+ rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0);
+ rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0);
+ for (t = pSprite->win; t; t = t->parent)
+ if (t->parent == pWin)
+ {
+ rep.child = t->drawable.id;
+ break;
+ }
+ } else
+ {
+ rep.same_screen = xFalse;
+ rep.win_x = 0;
+ rep.win_y = 0;
+ }
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ rep.root_x += FP1616(screenInfo.screens[0]->x, 0);
+ rep.root_y += FP1616(screenInfo.screens[0]->y, 0);
+ if (stuff->win == rep.root)
+ {
+ rep.win_x += FP1616(screenInfo.screens[0]->x, 0);
+ rep.win_y += FP1616(screenInfo.screens[0]->y, 0);
+ }
+ }
+#endif
+
+ WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep);
+ if (buttons)
+ WriteToClient(client, buttons_size, buttons);
+
+ free(buttons);
+
+ return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XIQueryPointer function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepXIQueryPointer(ClientPtr client, int size,
+ xXIQueryPointerReply * rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->root, n);
+ swapl(&rep->child, n);
+ swapl(&rep->root_x, n);
+ swapl(&rep->root_y, n);
+ swapl(&rep->win_x, n);
+ swapl(&rep->win_y, n);
+ swaps(&rep->buttons_len, n);
+
+ WriteToClient(client, size, (char *)rep);
+}
+
diff --git a/xorg-server/Xi/xiwarppointer.c b/xorg-server/Xi/xiwarppointer.c
index a463ab94d..66888008f 100644
--- a/xorg-server/Xi/xiwarppointer.c
+++ b/xorg-server/Xi/xiwarppointer.c
@@ -1,203 +1,203 @@
-/*
- * Copyright 2007-2008 Peter Hutterer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer, University of South Australia, NICTA
- */
-
-/***********************************************************************
- *
- * Request to Warp the pointer location of an extension input device.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h> /* for inputstr.h */
-#include <X11/Xproto.h> /* Request macro */
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include "scrnintstr.h" /* screen structure */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XI2proto.h>
-#include "extnsionst.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "mipointer.h" /* for miPointerUpdateSprite */
-
-
-#include "xiwarppointer.h"
-/***********************************************************************
- *
- * This procedure allows a client to warp the pointer of a device.
- *
- */
-
-int
-SProcXIWarpPointer(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIWarpPointerReq);
- swaps(&stuff->length, n);
- swapl(&stuff->src_win, n);
- swapl(&stuff->dst_win, n);
- swapl(&stuff->src_x, n);
- swapl(&stuff->src_y, n);
- swaps(&stuff->src_width, n);
- swaps(&stuff->src_height, n);
- swapl(&stuff->dst_x, n);
- swapl(&stuff->dst_y, n);
- swaps(&stuff->deviceid, n);
- return (ProcXIWarpPointer(client));
-}
-
-int
-ProcXIWarpPointer(ClientPtr client)
-{
- int rc;
- int x, y;
- WindowPtr dest = NULL;
- DeviceIntPtr pDev;
- SpritePtr pSprite;
- ScreenPtr newScreen;
- int src_x, src_y;
- int dst_x, dst_y;
-
- REQUEST(xXIWarpPointerReq);
- REQUEST_SIZE_MATCH(xXIWarpPointerReq);
-
- /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */
-
- rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
-
- if (rc != Success)
- {
- client->errorValue = stuff->deviceid;
- return rc;
- }
-
- if ((!IsMaster(pDev) && !IsFloating(pDev)) ||
- (IsMaster(pDev) && !IsPointerDevice(pDev)))
- {
- client->errorValue = stuff->deviceid;
- return BadDevice;
- }
-
- if (stuff->dst_win != None)
- {
- rc = dixLookupWindow(&dest, stuff->dst_win, client, DixGetAttrAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->dst_win;
- return rc;
- }
- }
-
- pSprite = pDev->spriteInfo->sprite;
- x = pSprite->hotPhys.x;
- y = pSprite->hotPhys.y;
-
- src_x = stuff->src_x / (double)(1 << 16);
- src_y = stuff->src_y / (double)(1 << 16);
- dst_x = stuff->dst_x / (double)(1 << 16);
- dst_y = stuff->dst_y / (double)(1 << 16);
-
- if (stuff->src_win != None)
- {
- int winX, winY;
- WindowPtr src;
-
- rc = dixLookupWindow(&src, stuff->src_win, client, DixGetAttrAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->src_win;
- return rc;
- }
-
- winX = src->drawable.x;
- winY = src->drawable.y;
- if (src->drawable.pScreen != pSprite->hotPhys.pScreen ||
- x < winX + src_x ||
- y < winY + src_y ||
- (stuff->src_width != 0 &&
- winX + src_x + (int)stuff->src_width < 0) ||
- (stuff->src_height != 0 &&
- winY + src_y + (int)stuff->src_height < y) ||
- !PointInWindowIsVisible(src, x, y))
- return Success;
- }
-
- if (dest)
- {
- x = dest->drawable.x;
- y = dest->drawable.y;
- newScreen = dest->drawable.pScreen;
- } else
- newScreen = pSprite->hotPhys.pScreen;
-
- x += dst_x;
- y += dst_y;
-
- if (x < 0)
- x = 0;
- else if (x > newScreen->width)
- x = newScreen->width - 1;
-
- if (y < 0)
- y = 0;
- else if (y > newScreen->height)
- y = newScreen->height - 1;
-
- if (newScreen == pSprite->hotPhys.pScreen)
- {
- if (x < pSprite->physLimits.x1)
- x = pSprite->physLimits.x1;
- else if (x >= pSprite->physLimits.x2)
- x = pSprite->physLimits.x2 - 1;
-
- if (y < pSprite->physLimits.y1)
- y = pSprite->physLimits.y1;
- else if (y >= pSprite->physLimits.y2)
- y = pSprite->physLimits.y2 - 1;
-
- if (pSprite->hotShape)
- ConfineToShape(pDev, pSprite->hotShape, &x, &y);
- (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE);
- } else if (!PointerConfinedToScreen(pDev))
- {
- NewCurrentScreen(pDev, newScreen, x, y);
- }
-
- /* if we don't update the device, we get a jump next time it moves */
- pDev->last.valuators[0] = x;
- pDev->last.valuators[1] = y;
- pDev->last.remainder[0] = 0;
- pDev->last.remainder[1] = 0;
- miPointerUpdateSprite(pDev);
-
- /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
- here though. */
- return Success;
-}
-
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Peter Hutterer, University of South Australia, NICTA
+ */
+
+/***********************************************************************
+ *
+ * Request to Warp the pointer location of an extension input device.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include "scrnintstr.h" /* screen structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XI2proto.h>
+#include "extnsionst.h"
+#include "exevents.h"
+#include "exglobals.h"
+#include "mipointer.h" /* for miPointerUpdateSprite */
+
+
+#include "xiwarppointer.h"
+/***********************************************************************
+ *
+ * This procedure allows a client to warp the pointer of a device.
+ *
+ */
+
+int
+SProcXIWarpPointer(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xXIWarpPointerReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->src_win, n);
+ swapl(&stuff->dst_win, n);
+ swapl(&stuff->src_x, n);
+ swapl(&stuff->src_y, n);
+ swaps(&stuff->src_width, n);
+ swaps(&stuff->src_height, n);
+ swapl(&stuff->dst_x, n);
+ swapl(&stuff->dst_y, n);
+ swaps(&stuff->deviceid, n);
+ return (ProcXIWarpPointer(client));
+}
+
+int
+ProcXIWarpPointer(ClientPtr client)
+{
+ int rc;
+ int x, y;
+ WindowPtr dest = NULL;
+ DeviceIntPtr pDev;
+ SpritePtr pSprite;
+ ScreenPtr newScreen;
+ int src_x, src_y;
+ int dst_x, dst_y;
+
+ REQUEST(xXIWarpPointerReq);
+ REQUEST_SIZE_MATCH(xXIWarpPointerReq);
+
+ /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */
+
+ rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
+
+ if (rc != Success)
+ {
+ client->errorValue = stuff->deviceid;
+ return rc;
+ }
+
+ if ((!IsMaster(pDev) && !IsFloating(pDev)) ||
+ (IsMaster(pDev) && !IsPointerDevice(pDev)))
+ {
+ client->errorValue = stuff->deviceid;
+ return BadDevice;
+ }
+
+ if (stuff->dst_win != None)
+ {
+ rc = dixLookupWindow(&dest, stuff->dst_win, client, DixGetAttrAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->dst_win;
+ return rc;
+ }
+ }
+
+ pSprite = pDev->spriteInfo->sprite;
+ x = pSprite->hotPhys.x;
+ y = pSprite->hotPhys.y;
+
+ src_x = stuff->src_x / (double)(1 << 16);
+ src_y = stuff->src_y / (double)(1 << 16);
+ dst_x = stuff->dst_x / (double)(1 << 16);
+ dst_y = stuff->dst_y / (double)(1 << 16);
+
+ if (stuff->src_win != None)
+ {
+ int winX, winY;
+ WindowPtr src;
+
+ rc = dixLookupWindow(&src, stuff->src_win, client, DixGetAttrAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->src_win;
+ return rc;
+ }
+
+ winX = src->drawable.x;
+ winY = src->drawable.y;
+ if (src->drawable.pScreen != pSprite->hotPhys.pScreen ||
+ x < winX + src_x ||
+ y < winY + src_y ||
+ (stuff->src_width != 0 &&
+ winX + src_x + (int)stuff->src_width < 0) ||
+ (stuff->src_height != 0 &&
+ winY + src_y + (int)stuff->src_height < y) ||
+ !PointInWindowIsVisible(src, x, y))
+ return Success;
+ }
+
+ if (dest)
+ {
+ x = dest->drawable.x;
+ y = dest->drawable.y;
+ newScreen = dest->drawable.pScreen;
+ } else
+ newScreen = pSprite->hotPhys.pScreen;
+
+ x += dst_x;
+ y += dst_y;
+
+ if (x < 0)
+ x = 0;
+ else if (x > newScreen->width)
+ x = newScreen->width - 1;
+
+ if (y < 0)
+ y = 0;
+ else if (y > newScreen->height)
+ y = newScreen->height - 1;
+
+ if (newScreen == pSprite->hotPhys.pScreen)
+ {
+ if (x < pSprite->physLimits.x1)
+ x = pSprite->physLimits.x1;
+ else if (x >= pSprite->physLimits.x2)
+ x = pSprite->physLimits.x2 - 1;
+
+ if (y < pSprite->physLimits.y1)
+ y = pSprite->physLimits.y1;
+ else if (y >= pSprite->physLimits.y2)
+ y = pSprite->physLimits.y2 - 1;
+
+ if (pSprite->hotShape)
+ ConfineToShape(pDev, pSprite->hotShape, &x, &y);
+ (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE);
+ } else if (!PointerConfinedToScreen(pDev))
+ {
+ NewCurrentScreen(pDev, newScreen, x, y);
+ }
+
+ /* if we don't update the device, we get a jump next time it moves */
+ pDev->last.valuators[0] = x;
+ pDev->last.valuators[1] = y;
+ pDev->last.remainder[0] = 0;
+ pDev->last.remainder[1] = 0;
+ miPointerUpdateSprite(pDev);
+
+ /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
+ here though. */
+ return Success;
+}
+