exevents.c revision a1e1cf94
105b261ecSmrg/************************************************************ 205b261ecSmrg 305b261ecSmrgCopyright 1989, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrgCopyright 1989 by Hewlett-Packard Company, Palo Alto, California. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 2905b261ecSmrgPermission to use, copy, modify, and distribute this software and its 3005b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 3205b261ecSmrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Hewlett-Packard not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 3505b261ecSmrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgHEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgHEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg********************************************************/ 4605b261ecSmrg 4735c4bbdfSmrg/* 4835c4bbdfSmrg * Copyright © 2010 Collabora Ltd. 4935c4bbdfSmrg * Copyright © 2011 Red Hat, Inc. 5035c4bbdfSmrg * 5135c4bbdfSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5235c4bbdfSmrg * copy of this software and associated documentation files (the "Software"), 5335c4bbdfSmrg * to deal in the Software without restriction, including without limitation 5435c4bbdfSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 5535c4bbdfSmrg * and/or sell copies of the Software, and to permit persons to whom the 5635c4bbdfSmrg * Software is furnished to do so, subject to the following conditions: 5735c4bbdfSmrg * 5835c4bbdfSmrg * The above copyright notice and this permission notice (including the next 5935c4bbdfSmrg * paragraph) shall be included in all copies or substantial portions of the 6035c4bbdfSmrg * Software. 6135c4bbdfSmrg * 6235c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6335c4bbdfSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6435c4bbdfSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 6535c4bbdfSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 6635c4bbdfSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 6735c4bbdfSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 6835c4bbdfSmrg * DEALINGS IN THE SOFTWARE. 6935c4bbdfSmrg * 7035c4bbdfSmrg * Author: Daniel Stone <daniel@fooishbar.org> 7135c4bbdfSmrg */ 7235c4bbdfSmrg 7305b261ecSmrg/******************************************************************** 7405b261ecSmrg * 7505b261ecSmrg * Routines to register and initialize extension input devices. 7605b261ecSmrg * This also contains ProcessOtherEvent, the routine called from DDX 7705b261ecSmrg * to route extension events. 7805b261ecSmrg * 7905b261ecSmrg */ 8005b261ecSmrg 8105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 8205b261ecSmrg#include <dix-config.h> 8305b261ecSmrg#endif 8405b261ecSmrg 856747b715Smrg#include "inputstr.h" 8605b261ecSmrg#include <X11/X.h> 8705b261ecSmrg#include <X11/Xproto.h> 8805b261ecSmrg#include <X11/extensions/XI.h> 8905b261ecSmrg#include <X11/extensions/XIproto.h> 906747b715Smrg#include <X11/extensions/XI2proto.h> 914642e01fSmrg#include <X11/extensions/geproto.h> 9205b261ecSmrg#include "windowstr.h" 9305b261ecSmrg#include "miscstruct.h" 9405b261ecSmrg#include "region.h" 9505b261ecSmrg#include "exevents.h" 9605b261ecSmrg#include "extnsionst.h" 9705b261ecSmrg#include "exglobals.h" 98ed6184dfSmrg#include "eventstr.h" 9935c4bbdfSmrg#include "dixevents.h" /* DeliverFocusedEvent */ 10035c4bbdfSmrg#include "dixgrabs.h" /* CreateGrab() */ 10105b261ecSmrg#include "scrnintstr.h" 10235c4bbdfSmrg#include "listdev.h" /* for CopySwapXXXClass */ 1034642e01fSmrg#include "xace.h" 10435c4bbdfSmrg#include "xiquerydevice.h" /* For List*Info */ 1056747b715Smrg#include "eventconvert.h" 1066747b715Smrg#include "eventstr.h" 10735c4bbdfSmrg#include "inpututils.h" 10835c4bbdfSmrg#include "mi.h" 10905b261ecSmrg 1104642e01fSmrg#include <X11/extensions/XKBproto.h> 11105b261ecSmrg#include "xkbsrv.h" 11205b261ecSmrg 11305b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0) 11405b261ecSmrg#define AllModifiersMask ( \ 11505b261ecSmrg ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 11605b261ecSmrg Mod3Mask | Mod4Mask | Mod5Mask ) 11705b261ecSmrg#define AllButtonsMask ( \ 11805b261ecSmrg Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 11905b261ecSmrg 1204642e01fSmrgBool ShouldFreeInputMasks(WindowPtr /* pWin */ , 12135c4bbdfSmrg Bool /* ignoreSelectedEvents */ 12205b261ecSmrg ); 12335c4bbdfSmrgstatic Bool MakeInputMasks(WindowPtr /* pWin */ 12405b261ecSmrg ); 12505b261ecSmrg 1266747b715Smrg/* 1276747b715Smrg * Only let the given client know of core events which will affect its 1286747b715Smrg * interpretation of input events, if the client's ClientPointer (or the 1296747b715Smrg * paired keyboard) is the current device. 1306747b715Smrg */ 1316747b715Smrgint 1326747b715SmrgXIShouldNotify(ClientPtr client, DeviceIntPtr dev) 1336747b715Smrg{ 1346747b715Smrg DeviceIntPtr current_ptr = PickPointer(client); 13535c4bbdfSmrg DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT); 1366747b715Smrg 1376747b715Smrg if (dev == current_kbd || dev == current_ptr) 1386747b715Smrg return 1; 1394642e01fSmrg 1406747b715Smrg return 0; 1416747b715Smrg} 14205b261ecSmrg 1434642e01fSmrgBool 14435c4bbdfSmrgIsPointerEvent(InternalEvent *event) 1454642e01fSmrg{ 14635c4bbdfSmrg switch (event->any.type) { 14735c4bbdfSmrg case ET_ButtonPress: 14835c4bbdfSmrg case ET_ButtonRelease: 14935c4bbdfSmrg case ET_Motion: 15035c4bbdfSmrg /* XXX: enter/leave ?? */ 15135c4bbdfSmrg return TRUE; 15235c4bbdfSmrg default: 15335c4bbdfSmrg break; 15435c4bbdfSmrg } 15535c4bbdfSmrg return FALSE; 15635c4bbdfSmrg} 15735c4bbdfSmrg 15835c4bbdfSmrgBool 15935c4bbdfSmrgIsTouchEvent(InternalEvent *event) 16035c4bbdfSmrg{ 16135c4bbdfSmrg switch (event->any.type) { 16235c4bbdfSmrg case ET_TouchBegin: 16335c4bbdfSmrg case ET_TouchUpdate: 16435c4bbdfSmrg case ET_TouchEnd: 16535c4bbdfSmrg return TRUE; 16635c4bbdfSmrg default: 16735c4bbdfSmrg break; 1684642e01fSmrg } 1694642e01fSmrg return FALSE; 1704642e01fSmrg} 1714642e01fSmrg 172ed6184dfSmrgBool 173ed6184dfSmrgIsGestureEvent(InternalEvent *event) 174ed6184dfSmrg{ 175ed6184dfSmrg switch (event->any.type) { 176ed6184dfSmrg case ET_GesturePinchBegin: 177ed6184dfSmrg case ET_GesturePinchUpdate: 178ed6184dfSmrg case ET_GesturePinchEnd: 179ed6184dfSmrg case ET_GestureSwipeBegin: 180ed6184dfSmrg case ET_GestureSwipeUpdate: 181ed6184dfSmrg case ET_GestureSwipeEnd: 182ed6184dfSmrg return TRUE; 183ed6184dfSmrg default: 184ed6184dfSmrg break; 185ed6184dfSmrg } 186ed6184dfSmrg return FALSE; 187ed6184dfSmrg} 188ed6184dfSmrg 189ed6184dfSmrgBool 190ed6184dfSmrgIsGestureBeginEvent(InternalEvent *event) 191ed6184dfSmrg{ 192ed6184dfSmrg switch (event->any.type) { 193ed6184dfSmrg case ET_GesturePinchBegin: 194ed6184dfSmrg case ET_GestureSwipeBegin: 195ed6184dfSmrg return TRUE; 196ed6184dfSmrg default: 197ed6184dfSmrg break; 198ed6184dfSmrg } 199ed6184dfSmrg return FALSE; 200ed6184dfSmrg} 201ed6184dfSmrg 202ed6184dfSmrgBool 203ed6184dfSmrgIsGestureEndEvent(InternalEvent *event) 204ed6184dfSmrg{ 205ed6184dfSmrg switch (event->any.type) { 206ed6184dfSmrg case ET_GesturePinchEnd: 207ed6184dfSmrg case ET_GestureSwipeEnd: 208ed6184dfSmrg return TRUE; 209ed6184dfSmrg default: 210ed6184dfSmrg break; 211ed6184dfSmrg } 212ed6184dfSmrg return FALSE; 213ed6184dfSmrg} 214ed6184dfSmrg 2154642e01fSmrg/** 2164642e01fSmrg * @return the device matching the deviceid of the device set in the event, or 2174642e01fSmrg * NULL if the event is not an XInput event. 2184642e01fSmrg */ 2194642e01fSmrgDeviceIntPtr 22035c4bbdfSmrgXIGetDevice(xEvent *xE) 22105b261ecSmrg{ 2224642e01fSmrg DeviceIntPtr pDev = NULL; 2234642e01fSmrg 2244642e01fSmrg if (xE->u.u.type == DeviceButtonPress || 2254642e01fSmrg xE->u.u.type == DeviceButtonRelease || 2264642e01fSmrg xE->u.u.type == DeviceMotionNotify || 2274642e01fSmrg xE->u.u.type == ProximityIn || 22835c4bbdfSmrg xE->u.u.type == ProximityOut || xE->u.u.type == DevicePropertyNotify) { 2294642e01fSmrg int rc; 2304642e01fSmrg int id; 2314642e01fSmrg 23235c4bbdfSmrg id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS; 2334642e01fSmrg 2344642e01fSmrg rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess); 2354642e01fSmrg if (rc != Success) 2364642e01fSmrg ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc); 2374642e01fSmrg } 2384642e01fSmrg return pDev; 2394642e01fSmrg} 2404642e01fSmrg 2414642e01fSmrg/** 2424642e01fSmrg * Copy the device->key into master->key and send a mapping notify to the 2434642e01fSmrg * clients if appropriate. 2444642e01fSmrg * master->key needs to be allocated by the caller. 2454642e01fSmrg * 2464642e01fSmrg * Device is the slave device. If it is attached to a master device, we may 2474642e01fSmrg * need to send a mapping notify to the client because it causes the MD 2484642e01fSmrg * to change state. 2494642e01fSmrg * 2504642e01fSmrg * Mapping notify needs to be sent in the following cases: 2514642e01fSmrg * - different slave device on same master 2524642e01fSmrg * - different master 2534642e01fSmrg * 2544642e01fSmrg * XXX: They way how the code is we also send a map notify if the slave device 2554642e01fSmrg * stays the same, but the master changes. This isn't really necessary though. 2564642e01fSmrg * 2574642e01fSmrg * XXX: this gives you funny behaviour with the ClientPointer. When a 2584642e01fSmrg * MappingNotify is sent to the client, the client usually responds with a 2594642e01fSmrg * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard 2604642e01fSmrg * mapping, regardless of which keyboard sent the last mapping notify request. 2614642e01fSmrg * So depending on the CP setting, your keyboard may change layout in each 2624642e01fSmrg * app... 2634642e01fSmrg * 2644642e01fSmrg * This code is basically the old SwitchCoreKeyboard. 2654642e01fSmrg */ 2664642e01fSmrg 2674642e01fSmrgvoid 2684642e01fSmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) 2694642e01fSmrg{ 2706747b715Smrg KeyClassPtr mk = master->key; 2714642e01fSmrg 2724642e01fSmrg if (device == master) 2734642e01fSmrg return; 2744642e01fSmrg 2756747b715Smrg mk->sourceid = device->id; 2764642e01fSmrg 27735c4bbdfSmrg if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc)) 2786747b715Smrg FatalError("Couldn't pivot keymap from device to core!\n"); 2794642e01fSmrg} 28005b261ecSmrg 2814642e01fSmrg/** 2824642e01fSmrg * Copies the feedback classes from device "from" into device "to". Classes 2834642e01fSmrg * are duplicated (not just flipping the pointers). All feedback classes are 2844642e01fSmrg * linked lists, the full list is duplicated. 2854642e01fSmrg */ 2864642e01fSmrgstatic void 2874642e01fSmrgDeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) 2884642e01fSmrg{ 2894642e01fSmrg ClassesPtr classes; 2904642e01fSmrg 29135c4bbdfSmrg if (from->intfeed) { 2924642e01fSmrg IntegerFeedbackPtr *i, it; 2934642e01fSmrg 29435c4bbdfSmrg if (!to->intfeed) { 2956747b715Smrg classes = to->unused_classes; 2964642e01fSmrg to->intfeed = classes->intfeed; 2976747b715Smrg classes->intfeed = NULL; 2984642e01fSmrg } 2994642e01fSmrg 3004642e01fSmrg i = &to->intfeed; 30135c4bbdfSmrg for (it = from->intfeed; it; it = it->next) { 30235c4bbdfSmrg if (!(*i)) { 3036747b715Smrg *i = calloc(1, sizeof(IntegerFeedbackClassRec)); 30435c4bbdfSmrg if (!(*i)) { 3054642e01fSmrg ErrorF("[Xi] Cannot alloc memory for class copy."); 3064642e01fSmrg return; 3074642e01fSmrg } 3084642e01fSmrg } 3094642e01fSmrg (*i)->CtrlProc = it->CtrlProc; 31035c4bbdfSmrg (*i)->ctrl = it->ctrl; 3114642e01fSmrg 3124642e01fSmrg i = &(*i)->next; 3134642e01fSmrg } 31435c4bbdfSmrg } 31535c4bbdfSmrg else if (to->intfeed && !from->intfeed) { 3166747b715Smrg classes = to->unused_classes; 3174642e01fSmrg classes->intfeed = to->intfeed; 31835c4bbdfSmrg to->intfeed = NULL; 3194642e01fSmrg } 3204642e01fSmrg 32135c4bbdfSmrg if (from->stringfeed) { 3224642e01fSmrg StringFeedbackPtr *s, it; 3234642e01fSmrg 32435c4bbdfSmrg if (!to->stringfeed) { 3256747b715Smrg classes = to->unused_classes; 3264642e01fSmrg to->stringfeed = classes->stringfeed; 3276747b715Smrg classes->stringfeed = NULL; 3284642e01fSmrg } 3294642e01fSmrg 3304642e01fSmrg s = &to->stringfeed; 33135c4bbdfSmrg for (it = from->stringfeed; it; it = it->next) { 33235c4bbdfSmrg if (!(*s)) { 3336747b715Smrg *s = calloc(1, sizeof(StringFeedbackClassRec)); 33435c4bbdfSmrg if (!(*s)) { 3354642e01fSmrg ErrorF("[Xi] Cannot alloc memory for class copy."); 3364642e01fSmrg return; 3374642e01fSmrg } 3384642e01fSmrg } 3394642e01fSmrg (*s)->CtrlProc = it->CtrlProc; 34035c4bbdfSmrg (*s)->ctrl = it->ctrl; 3414642e01fSmrg 3424642e01fSmrg s = &(*s)->next; 3434642e01fSmrg } 34435c4bbdfSmrg } 34535c4bbdfSmrg else if (to->stringfeed && !from->stringfeed) { 3466747b715Smrg classes = to->unused_classes; 3474642e01fSmrg classes->stringfeed = to->stringfeed; 34835c4bbdfSmrg to->stringfeed = NULL; 3494642e01fSmrg } 3504642e01fSmrg 35135c4bbdfSmrg if (from->bell) { 3524642e01fSmrg BellFeedbackPtr *b, it; 3534642e01fSmrg 35435c4bbdfSmrg if (!to->bell) { 3556747b715Smrg classes = to->unused_classes; 3564642e01fSmrg to->bell = classes->bell; 3576747b715Smrg classes->bell = NULL; 3584642e01fSmrg } 3594642e01fSmrg 3604642e01fSmrg b = &to->bell; 36135c4bbdfSmrg for (it = from->bell; it; it = it->next) { 36235c4bbdfSmrg if (!(*b)) { 3636747b715Smrg *b = calloc(1, sizeof(BellFeedbackClassRec)); 36435c4bbdfSmrg if (!(*b)) { 3654642e01fSmrg ErrorF("[Xi] Cannot alloc memory for class copy."); 3664642e01fSmrg return; 3674642e01fSmrg } 3684642e01fSmrg } 3694642e01fSmrg (*b)->BellProc = it->BellProc; 3704642e01fSmrg (*b)->CtrlProc = it->CtrlProc; 37135c4bbdfSmrg (*b)->ctrl = it->ctrl; 3724642e01fSmrg 3734642e01fSmrg b = &(*b)->next; 3744642e01fSmrg } 37535c4bbdfSmrg } 37635c4bbdfSmrg else if (to->bell && !from->bell) { 3776747b715Smrg classes = to->unused_classes; 3784642e01fSmrg classes->bell = to->bell; 37935c4bbdfSmrg to->bell = NULL; 3804642e01fSmrg } 3814642e01fSmrg 38235c4bbdfSmrg if (from->leds) { 3834642e01fSmrg LedFeedbackPtr *l, it; 3844642e01fSmrg 38535c4bbdfSmrg if (!to->leds) { 3866747b715Smrg classes = to->unused_classes; 3874642e01fSmrg to->leds = classes->leds; 3886747b715Smrg classes->leds = NULL; 3894642e01fSmrg } 3904642e01fSmrg 3914642e01fSmrg l = &to->leds; 39235c4bbdfSmrg for (it = from->leds; it; it = it->next) { 39335c4bbdfSmrg if (!(*l)) { 3946747b715Smrg *l = calloc(1, sizeof(LedFeedbackClassRec)); 39535c4bbdfSmrg if (!(*l)) { 3964642e01fSmrg ErrorF("[Xi] Cannot alloc memory for class copy."); 3974642e01fSmrg return; 3984642e01fSmrg } 3994642e01fSmrg } 4004642e01fSmrg (*l)->CtrlProc = it->CtrlProc; 40135c4bbdfSmrg (*l)->ctrl = it->ctrl; 4024642e01fSmrg if ((*l)->xkb_sli) 4034642e01fSmrg XkbFreeSrvLedInfo((*l)->xkb_sli); 4044642e01fSmrg (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l); 4054642e01fSmrg 4064642e01fSmrg l = &(*l)->next; 4074642e01fSmrg } 40835c4bbdfSmrg } 40935c4bbdfSmrg else if (to->leds && !from->leds) { 4106747b715Smrg classes = to->unused_classes; 4114642e01fSmrg classes->leds = to->leds; 41235c4bbdfSmrg to->leds = NULL; 4134642e01fSmrg } 4144642e01fSmrg} 4154642e01fSmrg 4166747b715Smrgstatic void 4176747b715SmrgDeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to) 4184642e01fSmrg{ 4194642e01fSmrg ClassesPtr classes; 4204642e01fSmrg 4214642e01fSmrg /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the 4224642e01fSmrg * kbdfeed to be set up properly, so let's do the feedback classes first. 4234642e01fSmrg */ 42435c4bbdfSmrg if (from->kbdfeed) { 4256747b715Smrg KbdFeedbackPtr *k, it; 4266747b715Smrg 42735c4bbdfSmrg if (!to->kbdfeed) { 4286747b715Smrg classes = to->unused_classes; 4296747b715Smrg 4306747b715Smrg to->kbdfeed = classes->kbdfeed; 4316747b715Smrg if (!to->kbdfeed) 4326747b715Smrg InitKeyboardDeviceStruct(to, NULL, NULL, NULL); 4336747b715Smrg classes->kbdfeed = NULL; 4346747b715Smrg } 4356747b715Smrg 4366747b715Smrg k = &to->kbdfeed; 43735c4bbdfSmrg for (it = from->kbdfeed; it; it = it->next) { 43835c4bbdfSmrg if (!(*k)) { 4396747b715Smrg *k = calloc(1, sizeof(KbdFeedbackClassRec)); 44035c4bbdfSmrg if (!*k) { 4416747b715Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 4426747b715Smrg return; 4436747b715Smrg } 4446747b715Smrg } 4456747b715Smrg (*k)->BellProc = it->BellProc; 4466747b715Smrg (*k)->CtrlProc = it->CtrlProc; 44735c4bbdfSmrg (*k)->ctrl = it->ctrl; 4486747b715Smrg if ((*k)->xkb_sli) 4496747b715Smrg XkbFreeSrvLedInfo((*k)->xkb_sli); 4506747b715Smrg (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL); 4516747b715Smrg 4526747b715Smrg k = &(*k)->next; 4536747b715Smrg } 45435c4bbdfSmrg } 45535c4bbdfSmrg else if (to->kbdfeed && !from->kbdfeed) { 4566747b715Smrg classes = to->unused_classes; 4576747b715Smrg classes->kbdfeed = to->kbdfeed; 45835c4bbdfSmrg to->kbdfeed = NULL; 4596747b715Smrg } 4604642e01fSmrg 46135c4bbdfSmrg if (from->key) { 46235c4bbdfSmrg if (!to->key) { 4636747b715Smrg classes = to->unused_classes; 4644642e01fSmrg to->key = classes->key; 4654642e01fSmrg if (!to->key) 4666747b715Smrg InitKeyboardDeviceStruct(to, NULL, NULL, NULL); 4676747b715Smrg else 4686747b715Smrg classes->key = NULL; 4696747b715Smrg } 4706747b715Smrg 4716747b715Smrg CopyKeyClass(from, to); 47235c4bbdfSmrg } 47335c4bbdfSmrg else if (to->key && !from->key) { 4746747b715Smrg classes = to->unused_classes; 4756747b715Smrg classes->key = to->key; 47635c4bbdfSmrg to->key = NULL; 4776747b715Smrg } 4786747b715Smrg 4796747b715Smrg /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps 4806747b715Smrg * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo 4816747b715Smrg * didn't update the pointers so we need to do it manually here. 4826747b715Smrg */ 48335c4bbdfSmrg if (to->kbdfeed) { 4846747b715Smrg KbdFeedbackPtr k; 4856747b715Smrg 48635c4bbdfSmrg for (k = to->kbdfeed; k; k = k->next) { 4876747b715Smrg if (!k->xkb_sli) 4886747b715Smrg continue; 48935c4bbdfSmrg if (k->xkb_sli->flags & XkbSLI_IsDefault) { 4906747b715Smrg k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators; 4916747b715Smrg k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps; 4926747b715Smrg } 4936747b715Smrg } 4946747b715Smrg } 4956747b715Smrg 4966747b715Smrg /* We can't just copy over the focus class. When an app sets the focus, 4976747b715Smrg * it'll do so on the master device. Copying the SDs focus means losing 4986747b715Smrg * the focus. 4996747b715Smrg * So we only copy the focus class if the device didn't have one, 5006747b715Smrg * otherwise we leave it as it is. 5016747b715Smrg */ 50235c4bbdfSmrg if (from->focus) { 50335c4bbdfSmrg if (!to->focus) { 5046747b715Smrg WindowPtr *oldTrace; 5056747b715Smrg 5066747b715Smrg classes = to->unused_classes; 5076747b715Smrg to->focus = classes->focus; 50835c4bbdfSmrg if (!to->focus) { 5096747b715Smrg to->focus = calloc(1, sizeof(FocusClassRec)); 5106747b715Smrg if (!to->focus) 5114642e01fSmrg FatalError("[Xi] no memory for class shift.\n"); 51235c4bbdfSmrg } 51335c4bbdfSmrg else 5146747b715Smrg classes->focus = NULL; 5156747b715Smrg 5166747b715Smrg oldTrace = to->focus->trace; 5176747b715Smrg memcpy(to->focus, from->focus, sizeof(FocusClassRec)); 51835c4bbdfSmrg to->focus->trace = reallocarray(oldTrace, 51935c4bbdfSmrg to->focus->traceSize, 52035c4bbdfSmrg sizeof(WindowPtr)); 5216747b715Smrg if (!to->focus->trace && to->focus->traceSize) 5226747b715Smrg FatalError("[Xi] no memory for trace.\n"); 5236747b715Smrg memcpy(to->focus->trace, from->focus->trace, 52435c4bbdfSmrg from->focus->traceSize * sizeof(WindowPtr)); 5256747b715Smrg to->focus->sourceid = from->id; 5264642e01fSmrg } 52735c4bbdfSmrg } 52835c4bbdfSmrg else if (to->focus) { 5296747b715Smrg classes = to->unused_classes; 5306747b715Smrg classes->focus = to->focus; 53135c4bbdfSmrg to->focus = NULL; 5326747b715Smrg } 5334642e01fSmrg 5346747b715Smrg} 5354642e01fSmrg 53635c4bbdfSmrg/* FIXME: this should really be shared with the InitValuatorAxisClassRec and 53735c4bbdfSmrg * similar */ 5386747b715Smrgstatic void 5396747b715SmrgDeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) 5406747b715Smrg{ 5416747b715Smrg ClassesPtr classes; 5426747b715Smrg 5436747b715Smrg /* Feedback classes must be copied first */ 54435c4bbdfSmrg if (from->ptrfeed) { 5456747b715Smrg PtrFeedbackPtr *p, it; 54635c4bbdfSmrg 54735c4bbdfSmrg if (!to->ptrfeed) { 5486747b715Smrg classes = to->unused_classes; 5496747b715Smrg to->ptrfeed = classes->ptrfeed; 5506747b715Smrg classes->ptrfeed = NULL; 5514642e01fSmrg } 5524642e01fSmrg 5536747b715Smrg p = &to->ptrfeed; 55435c4bbdfSmrg for (it = from->ptrfeed; it; it = it->next) { 55535c4bbdfSmrg if (!(*p)) { 5566747b715Smrg *p = calloc(1, sizeof(PtrFeedbackClassRec)); 55735c4bbdfSmrg if (!*p) { 5586747b715Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 5596747b715Smrg return; 5606747b715Smrg } 5616747b715Smrg } 5626747b715Smrg (*p)->CtrlProc = it->CtrlProc; 56335c4bbdfSmrg (*p)->ctrl = it->ctrl; 5644642e01fSmrg 5656747b715Smrg p = &(*p)->next; 5666747b715Smrg } 56735c4bbdfSmrg } 56835c4bbdfSmrg else if (to->ptrfeed && !from->ptrfeed) { 5696747b715Smrg classes = to->unused_classes; 5706747b715Smrg classes->ptrfeed = to->ptrfeed; 57135c4bbdfSmrg to->ptrfeed = NULL; 5724642e01fSmrg } 5734642e01fSmrg 57435c4bbdfSmrg if (from->valuator) { 5754642e01fSmrg ValuatorClassPtr v; 5769ace9065Smrg 57735c4bbdfSmrg if (!to->valuator) { 5786747b715Smrg classes = to->unused_classes; 5794642e01fSmrg to->valuator = classes->valuator; 5804642e01fSmrg if (to->valuator) 5814642e01fSmrg classes->valuator = NULL; 5824642e01fSmrg } 5834642e01fSmrg 5849ace9065Smrg v = AllocValuatorClass(to->valuator, from->valuator->numAxes); 5859ace9065Smrg 5864642e01fSmrg if (!v) 5874642e01fSmrg FatalError("[Xi] no memory for class shift.\n"); 5884642e01fSmrg 5899ace9065Smrg to->valuator = v; 5904642e01fSmrg memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo)); 5914642e01fSmrg 5926747b715Smrg v->sourceid = from->id; 59335c4bbdfSmrg } 59435c4bbdfSmrg else if (to->valuator && !from->valuator) { 5956747b715Smrg classes = to->unused_classes; 5964642e01fSmrg classes->valuator = to->valuator; 59735c4bbdfSmrg to->valuator = NULL; 5984642e01fSmrg } 5994642e01fSmrg 60035c4bbdfSmrg if (from->button) { 60135c4bbdfSmrg if (!to->button) { 6026747b715Smrg classes = to->unused_classes; 6034642e01fSmrg to->button = classes->button; 60435c4bbdfSmrg if (!to->button) { 6056747b715Smrg to->button = calloc(1, sizeof(ButtonClassRec)); 6064642e01fSmrg if (!to->button) 6074642e01fSmrg FatalError("[Xi] no memory for class shift.\n"); 60835c4bbdfSmrg } 60935c4bbdfSmrg else 6104642e01fSmrg classes->button = NULL; 6114642e01fSmrg } 6124642e01fSmrg 61335c4bbdfSmrg if (from->button->xkb_acts) { 61435c4bbdfSmrg if (!to->button->xkb_acts) { 6156747b715Smrg to->button->xkb_acts = calloc(1, sizeof(XkbAction)); 6164642e01fSmrg if (!to->button->xkb_acts) 6174642e01fSmrg FatalError("[Xi] not enough memory for xkb_acts.\n"); 6184642e01fSmrg } 6194642e01fSmrg memcpy(to->button->xkb_acts, from->button->xkb_acts, 62035c4bbdfSmrg sizeof(XkbAction)); 62135c4bbdfSmrg } 622a1e1cf94Smrg else { 6236747b715Smrg free(to->button->xkb_acts); 624a1e1cf94Smrg to->button->xkb_acts = NULL; 625a1e1cf94Smrg } 6266747b715Smrg 62735c4bbdfSmrg memcpy(to->button->labels, from->button->labels, 62835c4bbdfSmrg from->button->numButtons * sizeof(Atom)); 6296747b715Smrg to->button->sourceid = from->id; 63035c4bbdfSmrg } 63135c4bbdfSmrg else if (to->button && !from->button) { 6326747b715Smrg classes = to->unused_classes; 6334642e01fSmrg classes->button = to->button; 63435c4bbdfSmrg to->button = NULL; 6354642e01fSmrg } 6364642e01fSmrg 63735c4bbdfSmrg if (from->proximity) { 63835c4bbdfSmrg if (!to->proximity) { 6396747b715Smrg classes = to->unused_classes; 6404642e01fSmrg to->proximity = classes->proximity; 64135c4bbdfSmrg if (!to->proximity) { 6426747b715Smrg to->proximity = calloc(1, sizeof(ProximityClassRec)); 6434642e01fSmrg if (!to->proximity) 6444642e01fSmrg FatalError("[Xi] no memory for class shift.\n"); 64535c4bbdfSmrg } 64635c4bbdfSmrg else 6474642e01fSmrg classes->proximity = NULL; 6484642e01fSmrg } 6494642e01fSmrg memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec)); 6506747b715Smrg to->proximity->sourceid = from->id; 65135c4bbdfSmrg } 65235c4bbdfSmrg else if (to->proximity) { 6536747b715Smrg classes = to->unused_classes; 6544642e01fSmrg classes->proximity = to->proximity; 65535c4bbdfSmrg to->proximity = NULL; 6564642e01fSmrg } 6574642e01fSmrg 65835c4bbdfSmrg if (from->touch) { 65935c4bbdfSmrg TouchClassPtr t, f; 66035c4bbdfSmrg 66135c4bbdfSmrg if (!to->touch) { 6626747b715Smrg classes = to->unused_classes; 66335c4bbdfSmrg to->touch = classes->touch; 66435c4bbdfSmrg if (!to->touch) { 66535c4bbdfSmrg int i; 66635c4bbdfSmrg 66735c4bbdfSmrg to->touch = calloc(1, sizeof(TouchClassRec)); 66835c4bbdfSmrg if (!to->touch) 66935c4bbdfSmrg FatalError("[Xi] no memory for class shift.\n"); 67035c4bbdfSmrg to->touch->num_touches = from->touch->num_touches; 67135c4bbdfSmrg to->touch->touches = calloc(to->touch->num_touches, 67235c4bbdfSmrg sizeof(TouchPointInfoRec)); 67335c4bbdfSmrg for (i = 0; i < to->touch->num_touches; i++) 67435c4bbdfSmrg TouchInitTouchPoint(to->touch, to->valuator, i); 67535c4bbdfSmrg if (!to->touch) 6764642e01fSmrg FatalError("[Xi] no memory for class shift.\n"); 67735c4bbdfSmrg } 67835c4bbdfSmrg else 67935c4bbdfSmrg classes->touch = NULL; 6804642e01fSmrg } 68135c4bbdfSmrg 68235c4bbdfSmrg t = to->touch; 68335c4bbdfSmrg f = from->touch; 68435c4bbdfSmrg t->sourceid = f->sourceid; 68535c4bbdfSmrg t->max_touches = f->max_touches; 68635c4bbdfSmrg t->mode = f->mode; 68735c4bbdfSmrg t->buttonsDown = f->buttonsDown; 68835c4bbdfSmrg t->state = f->state; 68935c4bbdfSmrg t->motionMask = f->motionMask; 69035c4bbdfSmrg /* to->touches and to->num_touches are separate on the master, 69135c4bbdfSmrg * don't copy */ 6926747b715Smrg } 69335c4bbdfSmrg /* Don't remove touch class if from->touch is non-existent. The to device 69435c4bbdfSmrg * may have an active touch grab, so we need to keep the touch class record 69535c4bbdfSmrg * around. */ 696ed6184dfSmrg 697ed6184dfSmrg if (from->gesture) { 698ed6184dfSmrg if (!to->gesture) { 699ed6184dfSmrg classes = to->unused_classes; 700ed6184dfSmrg to->gesture = classes->gesture; 701ed6184dfSmrg if (!to->gesture) { 702ed6184dfSmrg if (!InitGestureClassDeviceStruct(to, from->gesture->max_touches)) 703ed6184dfSmrg FatalError("[Xi] no memory for class shift.\n"); 704ed6184dfSmrg } 705ed6184dfSmrg else 706ed6184dfSmrg classes->gesture = NULL; 707ed6184dfSmrg } 708ed6184dfSmrg 709ed6184dfSmrg to->gesture->sourceid = from->gesture->sourceid; 710ed6184dfSmrg /* to->gesture->gesture is separate on the master, don't copy */ 711ed6184dfSmrg } 712ed6184dfSmrg /* Don't remove gesture class if from->gesture is non-existent. The to device 713ed6184dfSmrg * may have an active gesture grab, so we need to keep the gesture class record 714ed6184dfSmrg * around. */ 7156747b715Smrg} 7166747b715Smrg 7176747b715Smrg/** 7186747b715Smrg * Copies the CONTENT of the classes of device from into the classes in device 7196747b715Smrg * to. From and to are identical after finishing. 7206747b715Smrg * 721ed6184dfSmrg * If to does not have classes from currently has, the classes are stored in 7226747b715Smrg * to's devPrivates system. Later, we recover it again from there if needed. 7236747b715Smrg * Saves a few memory allocations. 7246747b715Smrg */ 7256747b715Smrgvoid 72635c4bbdfSmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, 72735c4bbdfSmrg DeviceChangedEvent *dce) 7286747b715Smrg{ 7291b5d61b8Smrg input_lock(); 73035c4bbdfSmrg 7316747b715Smrg /* generic feedback classes, not tied to pointer and/or keyboard */ 7326747b715Smrg DeepCopyFeedbackClasses(from, to); 7336747b715Smrg 7346747b715Smrg if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT)) 7356747b715Smrg DeepCopyKeyboardClasses(from, to); 7366747b715Smrg if ((dce->flags & DEVCHANGE_POINTER_EVENT)) 7376747b715Smrg DeepCopyPointerClasses(from, to); 7386747b715Smrg 7391b5d61b8Smrg input_unlock(); 74035c4bbdfSmrg} 7416747b715Smrg 7426747b715Smrg/** 7436747b715Smrg * Send an XI2 DeviceChangedEvent to all interested clients. 7446747b715Smrg */ 7456747b715Smrgvoid 74635c4bbdfSmrgXISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce) 7476747b715Smrg{ 7486747b715Smrg xXIDeviceChangedEvent *dcce; 7496747b715Smrg int rc; 7506747b715Smrg 75135c4bbdfSmrg rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce); 75235c4bbdfSmrg if (rc != Success) { 7536747b715Smrg ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc); 7546747b715Smrg return; 7554642e01fSmrg } 7566747b715Smrg 7576747b715Smrg /* we don't actually swap if there's a NullClient, swapping is done 7586747b715Smrg * later when event is delivered. */ 75935c4bbdfSmrg SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent *) dcce, 1); 7606747b715Smrg free(dcce); 7614642e01fSmrg} 7624642e01fSmrg 7636747b715Smrgstatic void 7646747b715SmrgChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce) 7656747b715Smrg{ 7666747b715Smrg DeviceIntPtr slave; 7676747b715Smrg int rc; 7686747b715Smrg 7696747b715Smrg /* For now, we don't have devices that change physically. */ 7706747b715Smrg if (!IsMaster(device)) 7716747b715Smrg return; 7726747b715Smrg 7736747b715Smrg rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess); 7746747b715Smrg 7756747b715Smrg if (rc != Success) 77635c4bbdfSmrg return; /* Device has disappeared */ 7776747b715Smrg 77835c4bbdfSmrg if (IsMaster(slave)) 77935c4bbdfSmrg return; 78035c4bbdfSmrg 78135c4bbdfSmrg if (IsFloating(slave)) 78235c4bbdfSmrg return; /* set floating since the event */ 7836747b715Smrg 78435c4bbdfSmrg if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid) 78535c4bbdfSmrg return; /* not our slave anymore, don't care */ 7866747b715Smrg 7876747b715Smrg /* FIXME: we probably need to send a DCE for the new slave now */ 7886747b715Smrg 7896747b715Smrg device->public.devicePrivate = slave->public.devicePrivate; 7906747b715Smrg 7916747b715Smrg /* FIXME: the classes may have changed since we generated the event. */ 7926747b715Smrg DeepCopyDeviceClasses(slave, device, dce); 79335c4bbdfSmrg dce->deviceid = device->id; 79435c4bbdfSmrg XISendDeviceChangedEvent(device, dce); 79535c4bbdfSmrg} 79635c4bbdfSmrg 79735c4bbdfSmrg/** 79835c4bbdfSmrg * Add state and motionMask to the filter for this event. The protocol 79935c4bbdfSmrg * supports some extra masks for motion when a button is down: 80035c4bbdfSmrg * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at 80135c4bbdfSmrg * least one button (or that specific button is down). These masks need to 80235c4bbdfSmrg * be added to the filters for core/XI motion events. 80335c4bbdfSmrg * 80435c4bbdfSmrg * @param device The device to update the mask for 80535c4bbdfSmrg * @param state The current button state mask 80635c4bbdfSmrg * @param motion_mask The motion mask (DeviceButtonMotionMask or 0) 80735c4bbdfSmrg */ 80835c4bbdfSmrgstatic void 80935c4bbdfSmrgUpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state, 81035c4bbdfSmrg Mask motion_mask) 81135c4bbdfSmrg{ 81235c4bbdfSmrg Mask mask; 81335c4bbdfSmrg 81435c4bbdfSmrg mask = PointerMotionMask | state | motion_mask; 815ed6184dfSmrg SetMaskForEvent(device->id, mask, DeviceMotionNotify); 81635c4bbdfSmrg SetMaskForEvent(device->id, mask, MotionNotify); 81735c4bbdfSmrg} 81835c4bbdfSmrg 81935c4bbdfSmrgstatic void 82035c4bbdfSmrgIncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down, 82135c4bbdfSmrg Mask *motion_mask, unsigned short *state) 82235c4bbdfSmrg{ 82335c4bbdfSmrg if (dev->valuator) 82435c4bbdfSmrg dev->valuator->motionHintWindow = NullWindow; 82535c4bbdfSmrg 82635c4bbdfSmrg (*buttons_down)++; 82735c4bbdfSmrg *motion_mask = DeviceButtonMotionMask; 82835c4bbdfSmrg if (dev->button->map[key] <= 5) 82935c4bbdfSmrg *state |= (Button1Mask >> 1) << dev->button->map[key]; 83035c4bbdfSmrg} 83135c4bbdfSmrg 83235c4bbdfSmrgstatic void 83335c4bbdfSmrgDecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down, 83435c4bbdfSmrg Mask *motion_mask, unsigned short *state) 83535c4bbdfSmrg{ 83635c4bbdfSmrg if (dev->valuator) 83735c4bbdfSmrg dev->valuator->motionHintWindow = NullWindow; 83835c4bbdfSmrg 83935c4bbdfSmrg if (*buttons_down >= 1 && !--(*buttons_down)) 84035c4bbdfSmrg *motion_mask = 0; 84135c4bbdfSmrg if (dev->button->map[key] <= 5) 84235c4bbdfSmrg *state &= ~((Button1Mask >> 1) << dev->button->map[key]); 8436747b715Smrg} 8444642e01fSmrg 8454642e01fSmrg/** 8464642e01fSmrg * Update the device state according to the data in the event. 8474642e01fSmrg * 8484642e01fSmrg * return values are 8494642e01fSmrg * DEFAULT ... process as normal 8504642e01fSmrg * DONT_PROCESS ... return immediately from caller 8514642e01fSmrg */ 8524642e01fSmrg#define DEFAULT 0 8534642e01fSmrg#define DONT_PROCESS 1 8544642e01fSmrgint 85535c4bbdfSmrgUpdateDeviceState(DeviceIntPtr device, DeviceEvent *event) 8564642e01fSmrg{ 8574642e01fSmrg int i; 85835c4bbdfSmrg int key = 0, last_valuator; 8594642e01fSmrg 86035c4bbdfSmrg KeyClassPtr k = NULL; 86135c4bbdfSmrg ButtonClassPtr b = NULL; 86235c4bbdfSmrg ValuatorClassPtr v = NULL; 86335c4bbdfSmrg TouchClassPtr t = NULL; 8644642e01fSmrg 8656747b715Smrg /* This event is always the first we get, before the actual events with 8666747b715Smrg * the data. However, the way how the DDX is set up, "device" will 8676747b715Smrg * actually be the slave device that caused the event. 8686747b715Smrg */ 86935c4bbdfSmrg switch (event->type) { 87035c4bbdfSmrg case ET_DeviceChanged: 87135c4bbdfSmrg ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event); 87235c4bbdfSmrg return DONT_PROCESS; /* event has been sent already */ 87335c4bbdfSmrg case ET_Motion: 87435c4bbdfSmrg case ET_ButtonPress: 87535c4bbdfSmrg case ET_ButtonRelease: 87635c4bbdfSmrg case ET_KeyPress: 87735c4bbdfSmrg case ET_KeyRelease: 87835c4bbdfSmrg case ET_ProximityIn: 87935c4bbdfSmrg case ET_ProximityOut: 88035c4bbdfSmrg case ET_TouchBegin: 88135c4bbdfSmrg case ET_TouchUpdate: 88235c4bbdfSmrg case ET_TouchEnd: 88335c4bbdfSmrg break; 88435c4bbdfSmrg default: 88535c4bbdfSmrg /* other events don't update the device */ 88635c4bbdfSmrg return DEFAULT; 8876747b715Smrg } 8884642e01fSmrg 8894642e01fSmrg k = device->key; 8904642e01fSmrg v = device->valuator; 8914642e01fSmrg b = device->button; 89235c4bbdfSmrg t = device->touch; 8934642e01fSmrg 8946747b715Smrg key = event->detail.key; 8954642e01fSmrg 8966747b715Smrg /* Update device axis */ 8976747b715Smrg /* Check valuators first */ 8986747b715Smrg last_valuator = -1; 89935c4bbdfSmrg for (i = 0; i < MAX_VALUATORS; i++) { 90035c4bbdfSmrg if (BitIsOn(&event->valuators.mask, i)) { 90135c4bbdfSmrg if (!v) { 9026747b715Smrg ErrorF("[Xi] Valuators reported for non-valuator device '%s'. " 90335c4bbdfSmrg "Ignoring event.\n", device->name); 9046747b715Smrg return DONT_PROCESS; 90535c4bbdfSmrg } 90635c4bbdfSmrg else if (v->numAxes < i) { 9076747b715Smrg ErrorF("[Xi] Too many valuators reported for device '%s'. " 90835c4bbdfSmrg "Ignoring event.\n", device->name); 9096747b715Smrg return DONT_PROCESS; 9106747b715Smrg } 9116747b715Smrg last_valuator = i; 9126747b715Smrg } 9134642e01fSmrg } 9144642e01fSmrg 91535c4bbdfSmrg for (i = 0; i <= last_valuator && i < v->numAxes; i++) { 91635c4bbdfSmrg /* XXX: Relative/Absolute mode */ 9176747b715Smrg if (BitIsOn(&event->valuators.mask, i)) 9186747b715Smrg v->axisVal[i] = event->valuators.data[i]; 9194642e01fSmrg } 92005b261ecSmrg 9216747b715Smrg if (event->type == ET_KeyPress) { 92205b261ecSmrg if (!k) 9234642e01fSmrg return DONT_PROCESS; 92405b261ecSmrg 92535c4bbdfSmrg /* don't allow ddx to generate multiple downs, but repeats are okay */ 92635c4bbdfSmrg if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat) 92735c4bbdfSmrg return DONT_PROCESS; 9286747b715Smrg 92935c4bbdfSmrg if (device->valuator) 93035c4bbdfSmrg device->valuator->motionHintWindow = NullWindow; 93135c4bbdfSmrg set_key_down(device, key, KEY_PROCESSED); 93235c4bbdfSmrg } 93335c4bbdfSmrg else if (event->type == ET_KeyRelease) { 93405b261ecSmrg if (!k) 9354642e01fSmrg return DONT_PROCESS; 93605b261ecSmrg 93735c4bbdfSmrg if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */ 93835c4bbdfSmrg return DONT_PROCESS; 93935c4bbdfSmrg if (device->valuator) 94035c4bbdfSmrg device->valuator->motionHintWindow = NullWindow; 94135c4bbdfSmrg set_key_up(device, key, KEY_PROCESSED); 94235c4bbdfSmrg } 94335c4bbdfSmrg else if (event->type == ET_ButtonPress) { 94405b261ecSmrg if (!b) 9454642e01fSmrg return DONT_PROCESS; 9464642e01fSmrg 9476747b715Smrg if (button_is_down(device, key, BUTTON_PROCESSED)) 9484642e01fSmrg return DONT_PROCESS; 9496747b715Smrg 9506747b715Smrg set_button_down(device, key, BUTTON_PROCESSED); 95135c4bbdfSmrg 9524642e01fSmrg if (!b->map[key]) 9534642e01fSmrg return DONT_PROCESS; 95435c4bbdfSmrg 95535c4bbdfSmrg IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, 95635c4bbdfSmrg &b->state); 95735c4bbdfSmrg UpdateDeviceMotionMask(device, b->state, b->motionMask); 95835c4bbdfSmrg } 95935c4bbdfSmrg else if (event->type == ET_ButtonRelease) { 96005b261ecSmrg if (!b) 9614642e01fSmrg return DONT_PROCESS; 9624642e01fSmrg 9636747b715Smrg if (!button_is_down(device, key, BUTTON_PROCESSED)) 9644642e01fSmrg return DONT_PROCESS; 9656747b715Smrg if (IsMaster(device)) { 9664642e01fSmrg DeviceIntPtr sd; 9674642e01fSmrg 9684642e01fSmrg /* 9694642e01fSmrg * Leave the button down if any slave has the 9704642e01fSmrg * button still down. Note that this depends on the 9714642e01fSmrg * event being delivered through the slave first 9724642e01fSmrg */ 9734642e01fSmrg for (sd = inputInfo.devices; sd; sd = sd->next) { 97435c4bbdfSmrg if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device) 9754642e01fSmrg continue; 9766747b715Smrg if (!sd->button) 9776747b715Smrg continue; 9788223e2f2Smrg for (i = 1; i <= sd->button->numButtons; i++) 9798223e2f2Smrg if (sd->button->map[i] == key && 9808223e2f2Smrg button_is_down(sd, i, BUTTON_PROCESSED)) 9818223e2f2Smrg return DONT_PROCESS; 9824642e01fSmrg } 9834642e01fSmrg } 9846747b715Smrg set_button_up(device, key, BUTTON_PROCESSED); 9854642e01fSmrg if (!b->map[key]) 9864642e01fSmrg return DONT_PROCESS; 98735c4bbdfSmrg 98835c4bbdfSmrg DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, 98935c4bbdfSmrg &b->state); 99035c4bbdfSmrg UpdateDeviceMotionMask(device, b->state, b->motionMask); 99135c4bbdfSmrg } 99235c4bbdfSmrg else if (event->type == ET_ProximityIn) 99335c4bbdfSmrg device->proximity->in_proximity = TRUE; 9946747b715Smrg else if (event->type == ET_ProximityOut) 99535c4bbdfSmrg device->proximity->in_proximity = FALSE; 99635c4bbdfSmrg else if (event->type == ET_TouchBegin) { 99735c4bbdfSmrg BUG_RETURN_VAL(!b || !v, DONT_PROCESS); 99835c4bbdfSmrg BUG_RETURN_VAL(!t, DONT_PROCESS); 9994642e01fSmrg 100035c4bbdfSmrg if (!b->map[key]) 100135c4bbdfSmrg return DONT_PROCESS; 10024642e01fSmrg 100335c4bbdfSmrg if (!(event->flags & TOUCH_POINTER_EMULATED) || 100435c4bbdfSmrg (event->flags & TOUCH_REPLAYING)) 100535c4bbdfSmrg return DONT_PROCESS; 10066747b715Smrg 100735c4bbdfSmrg IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, 100835c4bbdfSmrg &t->state); 100935c4bbdfSmrg UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask); 101035c4bbdfSmrg } 101135c4bbdfSmrg else if (event->type == ET_TouchEnd) { 101235c4bbdfSmrg BUG_RETURN_VAL(!b || !v, DONT_PROCESS); 101335c4bbdfSmrg BUG_RETURN_VAL(!t, DONT_PROCESS); 10146747b715Smrg 101535c4bbdfSmrg if (t->buttonsDown <= 0 || !b->map[key]) 101635c4bbdfSmrg return DONT_PROCESS; 101735c4bbdfSmrg 101835c4bbdfSmrg if (!(event->flags & TOUCH_POINTER_EMULATED)) 101935c4bbdfSmrg return DONT_PROCESS; 10206747b715Smrg 102135c4bbdfSmrg DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, 102235c4bbdfSmrg &t->state); 102335c4bbdfSmrg UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask); 10246747b715Smrg } 102535c4bbdfSmrg 102635c4bbdfSmrg return DEFAULT; 10276747b715Smrg} 10286747b715Smrg 10294642e01fSmrg/** 103035c4bbdfSmrg * A client that does not have the TouchOwnership mask set may not receive a 103135c4bbdfSmrg * TouchBegin event if there is at least one grab active. 10324642e01fSmrg * 103335c4bbdfSmrg * @return TRUE if the client selected for ownership events on the given 103435c4bbdfSmrg * window for this device, FALSE otherwise 10354642e01fSmrg */ 103635c4bbdfSmrgstatic inline Bool 103735c4bbdfSmrgTouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev, 103835c4bbdfSmrg WindowPtr win) 10394642e01fSmrg{ 104035c4bbdfSmrg InputClients *iclient; 10416747b715Smrg 104235c4bbdfSmrg nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next) { 104335c4bbdfSmrg if (rClient(iclient) != client) 104435c4bbdfSmrg continue; 10456747b715Smrg 104635c4bbdfSmrg return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership); 10476747b715Smrg } 10484642e01fSmrg 104935c4bbdfSmrg return FALSE; 105035c4bbdfSmrg} 10514642e01fSmrg 105235c4bbdfSmrgstatic void 105335c4bbdfSmrgTouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason, 105435c4bbdfSmrg XID resource) 105535c4bbdfSmrg{ 105635c4bbdfSmrg int nev, i; 105735c4bbdfSmrg InternalEvent *tel = InitEventList(GetMaximumEventsNum()); 10586747b715Smrg 105935c4bbdfSmrg nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0); 106035c4bbdfSmrg for (i = 0; i < nev; i++) 106135c4bbdfSmrg mieqProcessDeviceEvent(dev, tel + i, NULL); 10626747b715Smrg 106335c4bbdfSmrg FreeEventList(tel, GetMaximumEventsNum()); 106435c4bbdfSmrg} 10656747b715Smrg 106635c4bbdfSmrg/** 106735c4bbdfSmrg * Attempts to deliver a touch event to the given client. 106835c4bbdfSmrg */ 106935c4bbdfSmrgstatic Bool 107035c4bbdfSmrgDeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti, 107135c4bbdfSmrg GrabPtr grab, WindowPtr win, InternalEvent *ev) 107235c4bbdfSmrg{ 107335c4bbdfSmrg int err; 107435c4bbdfSmrg xEvent *xi2; 107535c4bbdfSmrg Mask filter; 107635c4bbdfSmrg Window child = DeepestSpriteWin(&ti->sprite)->drawable.id; 107735c4bbdfSmrg 107835c4bbdfSmrg /* FIXME: owner event handling */ 107935c4bbdfSmrg 108035c4bbdfSmrg /* If the client does not have the ownership mask set and is not 108135c4bbdfSmrg * the current owner of the touch, only pretend we delivered */ 108235c4bbdfSmrg if (!grab && ti->num_grabs != 0 && 108335c4bbdfSmrg !TouchClientWantsOwnershipEvents(client, dev, win)) 108435c4bbdfSmrg return TRUE; 108535c4bbdfSmrg 108635c4bbdfSmrg /* If we fail here, we're going to leave a client hanging. */ 108735c4bbdfSmrg err = EventToXI2(ev, &xi2); 108835c4bbdfSmrg if (err != Success) 108935c4bbdfSmrg FatalError("[Xi] %s: XI2 conversion failed in %s" 109035c4bbdfSmrg " (%d)\n", dev->name, __func__, err); 109135c4bbdfSmrg 109235c4bbdfSmrg FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE); 109335c4bbdfSmrg filter = GetEventFilter(dev, xi2); 109435c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success) 109535c4bbdfSmrg return FALSE; 109635c4bbdfSmrg err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab); 109735c4bbdfSmrg free(xi2); 109835c4bbdfSmrg 109935c4bbdfSmrg /* Returning the value from TryClientEvents isn't useful, since all our 110035c4bbdfSmrg * resource-gone cleanups will update the delivery list anyway. */ 110135c4bbdfSmrg return TRUE; 110235c4bbdfSmrg} 11036747b715Smrg 110435c4bbdfSmrgstatic void 110535c4bbdfSmrgActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) 110635c4bbdfSmrg{ 110735c4bbdfSmrg ClientPtr client; 110835c4bbdfSmrg XID error; 110935c4bbdfSmrg GrabPtr grab = ti->listeners[0].grab; 11104642e01fSmrg 1111ed6184dfSmrg BUG_RETURN(ti->listeners[0].type != TOUCH_LISTENER_GRAB && 1112ed6184dfSmrg ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB); 111335c4bbdfSmrg BUG_RETURN(!grab); 11144642e01fSmrg 111535c4bbdfSmrg client = rClient(grab); 11164642e01fSmrg 111735c4bbdfSmrg if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id, 111835c4bbdfSmrg ti->listeners[0].window->drawable.id, &error) != Success) 111935c4bbdfSmrg ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n"); 112035c4bbdfSmrg} 11214642e01fSmrg 112235c4bbdfSmrg/** 112335c4bbdfSmrg * Find the oldest touch that still has a pointer emulation client. 112435c4bbdfSmrg * 112535c4bbdfSmrg * Pointer emulation can only be performed for the oldest touch. Otherwise, the 112635c4bbdfSmrg * order of events seen by the client will be wrong. This function helps us find 112735c4bbdfSmrg * the next touch to be emulated. 112835c4bbdfSmrg * 112935c4bbdfSmrg * @param dev The device to find touches for. 113035c4bbdfSmrg */ 113135c4bbdfSmrgstatic TouchPointInfoPtr 113235c4bbdfSmrgFindOldestPointerEmulatedTouch(DeviceIntPtr dev) 113335c4bbdfSmrg{ 113435c4bbdfSmrg TouchPointInfoPtr oldest = NULL; 113535c4bbdfSmrg int i; 11366747b715Smrg 113735c4bbdfSmrg for (i = 0; i < dev->touch->num_touches; i++) { 113835c4bbdfSmrg TouchPointInfoPtr ti = dev->touch->touches + i; 113935c4bbdfSmrg int j; 11404642e01fSmrg 114135c4bbdfSmrg if (!ti->active || !ti->emulate_pointer) 114235c4bbdfSmrg continue; 11434642e01fSmrg 114435c4bbdfSmrg for (j = 0; j < ti->num_listeners; j++) { 1145ed6184dfSmrg if (ti->listeners[j].type == TOUCH_LISTENER_POINTER_GRAB || 1146ed6184dfSmrg ti->listeners[j].type == TOUCH_LISTENER_POINTER_REGULAR) 114735c4bbdfSmrg break; 114835c4bbdfSmrg } 114935c4bbdfSmrg if (j == ti->num_listeners) 115035c4bbdfSmrg continue; 11514642e01fSmrg 115235c4bbdfSmrg if (!oldest) { 115335c4bbdfSmrg oldest = ti; 115435c4bbdfSmrg continue; 115535c4bbdfSmrg } 11564642e01fSmrg 115735c4bbdfSmrg if (oldest->client_id - ti->client_id < UINT_MAX / 2) 115835c4bbdfSmrg oldest = ti; 11594642e01fSmrg } 116005b261ecSmrg 116135c4bbdfSmrg return oldest; 116205b261ecSmrg} 116305b261ecSmrg 116435c4bbdfSmrg/** 116535c4bbdfSmrg * If the current owner has rejected the event, deliver the 116635c4bbdfSmrg * TouchOwnership/TouchBegin to the next item in the sprite stack. 116735c4bbdfSmrg */ 116835c4bbdfSmrgstatic void 116935c4bbdfSmrgTouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, 117035c4bbdfSmrg TouchOwnershipEvent *ev) 117105b261ecSmrg{ 117235c4bbdfSmrg TouchListener *listener = &ti->listeners[0]; /* new owner */ 1173ed6184dfSmrg int accepted_early = listener->state == TOUCH_LISTENER_EARLY_ACCEPT; 117435c4bbdfSmrg 117535c4bbdfSmrg /* Deliver the ownership */ 1176ed6184dfSmrg if (listener->state == TOUCH_LISTENER_AWAITING_OWNER || accepted_early) 117735c4bbdfSmrg DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 117835c4bbdfSmrg listener->listener); 1179ed6184dfSmrg else if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) { 118035c4bbdfSmrg /* We can't punt to a pointer listener unless all older pointer 118135c4bbdfSmrg * emulated touches have been seen already. */ 1182ed6184dfSmrg if ((listener->type == TOUCH_LISTENER_POINTER_GRAB || 1183ed6184dfSmrg listener->type == TOUCH_LISTENER_POINTER_REGULAR) && 118435c4bbdfSmrg ti != FindOldestPointerEmulatedTouch(dev)) 118535c4bbdfSmrg return; 118605b261ecSmrg 118735c4bbdfSmrg TouchEventHistoryReplay(ti, dev, listener->listener); 118835c4bbdfSmrg } 118905b261ecSmrg 119035c4bbdfSmrg /* New owner has Begin/Update but not end. If touch is pending_finish, 119135c4bbdfSmrg * emulate the TouchEnd now */ 119235c4bbdfSmrg if (ti->pending_finish) { 119335c4bbdfSmrg TouchEmitTouchEnd(dev, ti, 0, 0); 119435c4bbdfSmrg 119535c4bbdfSmrg /* If the last owner is not a touch grab, finalise the touch, we 119635c4bbdfSmrg won't get more correspondence on this. 119735c4bbdfSmrg */ 119835c4bbdfSmrg if (ti->num_listeners == 1 && 119935c4bbdfSmrg (ti->num_grabs == 0 || 120035c4bbdfSmrg listener->grab->grabtype != XI2 || 120135c4bbdfSmrg !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) { 120235c4bbdfSmrg TouchEndTouch(dev, ti); 120335c4bbdfSmrg return; 120435c4bbdfSmrg } 120535c4bbdfSmrg } 120635c4bbdfSmrg 120735c4bbdfSmrg if (accepted_early) 120835c4bbdfSmrg ActivateEarlyAccept(dev, ti); 120935c4bbdfSmrg} 121035c4bbdfSmrg 121135c4bbdfSmrg/** 121235c4bbdfSmrg * Check the oldest touch to see if it needs to be replayed to its pointer 121335c4bbdfSmrg * owner. 121435c4bbdfSmrg * 121535c4bbdfSmrg * Touch event propagation is paused if it hits a pointer listener while an 121635c4bbdfSmrg * older touch with a pointer listener is waiting on accept or reject. This 121735c4bbdfSmrg * function will restart propagation of a paused touch if needed. 121835c4bbdfSmrg * 121935c4bbdfSmrg * @param dev The device to check touches for. 122035c4bbdfSmrg */ 122135c4bbdfSmrgstatic void 122235c4bbdfSmrgCheckOldestTouch(DeviceIntPtr dev) 122335c4bbdfSmrg{ 122435c4bbdfSmrg TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev); 122535c4bbdfSmrg 1226ed6184dfSmrg if (oldest && oldest->listeners[0].state == TOUCH_LISTENER_AWAITING_BEGIN) 122735c4bbdfSmrg TouchPuntToNextOwner(dev, oldest, NULL); 122835c4bbdfSmrg} 122935c4bbdfSmrg 123035c4bbdfSmrg/** 123135c4bbdfSmrg * Process a touch rejection. 123235c4bbdfSmrg * 123335c4bbdfSmrg * @param sourcedev The source device of the touch sequence. 123435c4bbdfSmrg * @param ti The touchpoint info record. 123535c4bbdfSmrg * @param resource The resource of the client rejecting the touch. 123635c4bbdfSmrg * @param ev TouchOwnership event to send. Set to NULL if no event should be 123735c4bbdfSmrg * sent. 123835c4bbdfSmrg */ 123935c4bbdfSmrgvoid 124035c4bbdfSmrgTouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource, 124135c4bbdfSmrg TouchOwnershipEvent *ev) 124235c4bbdfSmrg{ 124335c4bbdfSmrg Bool was_owner = (resource == ti->listeners[0].listener); 124435c4bbdfSmrg int i; 124535c4bbdfSmrg 124635c4bbdfSmrg /* Send a TouchEnd event to the resource being removed, but only if they 124735c4bbdfSmrg * haven't received one yet already */ 124835c4bbdfSmrg for (i = 0; i < ti->num_listeners; i++) { 124935c4bbdfSmrg if (ti->listeners[i].listener == resource) { 1250ed6184dfSmrg if (ti->listeners[i].state != TOUCH_LISTENER_HAS_END) 125135c4bbdfSmrg TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource); 125235c4bbdfSmrg break; 125335c4bbdfSmrg } 125435c4bbdfSmrg } 125535c4bbdfSmrg 125635c4bbdfSmrg /* Remove the resource from the listener list, updating 125735c4bbdfSmrg * ti->num_listeners, as well as ti->num_grabs if it was a grab. */ 125835c4bbdfSmrg TouchRemoveListener(ti, resource); 125935c4bbdfSmrg 126035c4bbdfSmrg /* If the current owner was removed and there are further listeners, deliver 126135c4bbdfSmrg * the TouchOwnership or TouchBegin event to the new owner. */ 126235c4bbdfSmrg if (ev && ti->num_listeners > 0 && was_owner) 126335c4bbdfSmrg TouchPuntToNextOwner(sourcedev, ti, ev); 126435c4bbdfSmrg else if (ti->num_listeners == 0) 126535c4bbdfSmrg TouchEndTouch(sourcedev, ti); 126635c4bbdfSmrg 126735c4bbdfSmrg CheckOldestTouch(sourcedev); 126835c4bbdfSmrg} 126935c4bbdfSmrg 127035c4bbdfSmrg/** 127135c4bbdfSmrg * Processes a TouchOwnership event, indicating a grab has accepted the touch 127235c4bbdfSmrg * it currently owns, or a grab or selection has been removed. Will generate 127335c4bbdfSmrg * and send TouchEnd events to all clients removed from the delivery list, as 127435c4bbdfSmrg * well as possibly sending the new TouchOwnership event. May end the 127535c4bbdfSmrg * touchpoint if it is pending finish. 127635c4bbdfSmrg */ 127735c4bbdfSmrgstatic void 127835c4bbdfSmrgProcessTouchOwnershipEvent(TouchOwnershipEvent *ev, 127935c4bbdfSmrg DeviceIntPtr dev) 128035c4bbdfSmrg{ 128135c4bbdfSmrg TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid); 128235c4bbdfSmrg 128335c4bbdfSmrg if (!ti) { 128435c4bbdfSmrg DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n", 128535c4bbdfSmrg dev->name, ev->type, ev->touchid); 128635c4bbdfSmrg return; 128735c4bbdfSmrg } 128835c4bbdfSmrg 128935c4bbdfSmrg if (ev->reason == XIRejectTouch) 129035c4bbdfSmrg TouchRejected(dev, ti, ev->resource, ev); 129135c4bbdfSmrg else if (ev->reason == XIAcceptTouch) { 129235c4bbdfSmrg int i; 129335c4bbdfSmrg 129435c4bbdfSmrg 129535c4bbdfSmrg /* For pointer-emulated listeners that ungrabbed the active grab, 1296ed6184dfSmrg * the state was forced to TOUCH_LISTENER_HAS_END. Still go 129735c4bbdfSmrg * through the motions of ending the touch if the listener has 129835c4bbdfSmrg * already seen the end. This ensures that the touch record is ended in 129935c4bbdfSmrg * the server. 130035c4bbdfSmrg */ 1301ed6184dfSmrg if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END) 130235c4bbdfSmrg TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener); 130335c4bbdfSmrg 130435c4bbdfSmrg /* The touch owner has accepted the touch. Send TouchEnd events to 130535c4bbdfSmrg * everyone else, and truncate the list of listeners. */ 130635c4bbdfSmrg for (i = 1; i < ti->num_listeners; i++) 130735c4bbdfSmrg TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener); 130835c4bbdfSmrg 130935c4bbdfSmrg while (ti->num_listeners > 1) 131035c4bbdfSmrg TouchRemoveListener(ti, ti->listeners[1].listener); 131135c4bbdfSmrg /* Owner accepted after receiving end */ 1312ed6184dfSmrg if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END) 131335c4bbdfSmrg TouchEndTouch(dev, ti); 131435c4bbdfSmrg else 1315ed6184dfSmrg ti->listeners[0].state = TOUCH_LISTENER_HAS_ACCEPTED; 131635c4bbdfSmrg } 131735c4bbdfSmrg else { /* this is the very first ownership event for a grab */ 131835c4bbdfSmrg DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource); 131935c4bbdfSmrg } 132035c4bbdfSmrg} 132135c4bbdfSmrg 132235c4bbdfSmrg/** 132335c4bbdfSmrg * Copy the event's valuator information into the touchpoint, we may need 132435c4bbdfSmrg * this for emulated TouchEnd events. 132535c4bbdfSmrg */ 132635c4bbdfSmrgstatic void 132735c4bbdfSmrgTouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti) 132835c4bbdfSmrg{ 132935c4bbdfSmrg int i; 133035c4bbdfSmrg 133135c4bbdfSmrg for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++) 133235c4bbdfSmrg if (BitIsOn(ev->valuators.mask, i)) 133335c4bbdfSmrg valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]); 133435c4bbdfSmrg} 133535c4bbdfSmrg 133635c4bbdfSmrg/** 133735c4bbdfSmrg * Given a touch event and a potential listener, retrieve info needed for 133835c4bbdfSmrg * processing the event. 133935c4bbdfSmrg * 134035c4bbdfSmrg * @param dev The device generating the touch event. 134135c4bbdfSmrg * @param ti The touch point info record for the touch event. 134235c4bbdfSmrg * @param ev The touch event to process. 134335c4bbdfSmrg * @param listener The touch event listener that may receive the touch event. 134435c4bbdfSmrg * @param[out] client The client that should receive the touch event. 134535c4bbdfSmrg * @param[out] win The window to deliver the event on. 134635c4bbdfSmrg * @param[out] grab The grab to deliver the event through, if any. 134735c4bbdfSmrg * @param[out] mask The XI 2.x event mask of the grab or selection, if any. 134835c4bbdfSmrg * @return TRUE if an event should be delivered to the listener, FALSE 134935c4bbdfSmrg * otherwise. 135035c4bbdfSmrg */ 135135c4bbdfSmrgstatic Bool 135235c4bbdfSmrgRetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti, 135335c4bbdfSmrg InternalEvent *ev, TouchListener * listener, 135435c4bbdfSmrg ClientPtr *client, WindowPtr *win, GrabPtr *grab, 135535c4bbdfSmrg XI2Mask **mask) 135635c4bbdfSmrg{ 135735c4bbdfSmrg int rc; 135835c4bbdfSmrg InputClients *iclients = NULL; 135935c4bbdfSmrg *mask = NULL; 136035c4bbdfSmrg 1361ed6184dfSmrg if (listener->type == TOUCH_LISTENER_GRAB || 1362ed6184dfSmrg listener->type == TOUCH_LISTENER_POINTER_GRAB) { 136335c4bbdfSmrg *grab = listener->grab; 136435c4bbdfSmrg 136535c4bbdfSmrg BUG_RETURN_VAL(!*grab, FALSE); 136635c4bbdfSmrg 136735c4bbdfSmrg *client = rClient(*grab); 136835c4bbdfSmrg *win = (*grab)->window; 136935c4bbdfSmrg *mask = (*grab)->xi2mask; 137035c4bbdfSmrg } 137135c4bbdfSmrg else { 137235c4bbdfSmrg rc = dixLookupResourceByType((void **) win, listener->listener, 137335c4bbdfSmrg listener->resource_type, 137435c4bbdfSmrg serverClient, DixSendAccess); 137535c4bbdfSmrg if (rc != Success) 137635c4bbdfSmrg return FALSE; 137735c4bbdfSmrg 137835c4bbdfSmrg if (listener->level == XI2) { 137935c4bbdfSmrg int evtype; 138035c4bbdfSmrg 138135c4bbdfSmrg if (ti->emulate_pointer && 1382ed6184dfSmrg listener->type == TOUCH_LISTENER_POINTER_REGULAR) 138335c4bbdfSmrg evtype = GetXI2Type(TouchGetPointerEventType(ev)); 138435c4bbdfSmrg else 138535c4bbdfSmrg evtype = GetXI2Type(ev->any.type); 138635c4bbdfSmrg 138735c4bbdfSmrg nt_list_for_each_entry(iclients, 138835c4bbdfSmrg wOtherInputMasks(*win)->inputClients, next) 138935c4bbdfSmrg if (xi2mask_isset(iclients->xi2mask, dev, evtype)) 139035c4bbdfSmrg break; 139135c4bbdfSmrg 139235c4bbdfSmrg BUG_RETURN_VAL(!iclients, FALSE); 139335c4bbdfSmrg 139435c4bbdfSmrg *mask = iclients->xi2mask; 139535c4bbdfSmrg *client = rClient(iclients); 139635c4bbdfSmrg } 139735c4bbdfSmrg else if (listener->level == XI) { 139835c4bbdfSmrg int xi_type = GetXIType(TouchGetPointerEventType(ev)); 139935c4bbdfSmrg Mask xi_filter = event_get_filter_from_type(dev, xi_type); 140035c4bbdfSmrg 140135c4bbdfSmrg nt_list_for_each_entry(iclients, 140235c4bbdfSmrg wOtherInputMasks(*win)->inputClients, next) 140335c4bbdfSmrg if (iclients->mask[dev->id] & xi_filter) 140435c4bbdfSmrg break; 140535c4bbdfSmrg BUG_RETURN_VAL(!iclients, FALSE); 140635c4bbdfSmrg 140735c4bbdfSmrg *client = rClient(iclients); 140835c4bbdfSmrg } 140935c4bbdfSmrg else { 141035c4bbdfSmrg int coretype = GetCoreType(TouchGetPointerEventType(ev)); 141135c4bbdfSmrg Mask core_filter = event_get_filter_from_type(dev, coretype); 141235c4bbdfSmrg OtherClients *oclients; 141335c4bbdfSmrg 141435c4bbdfSmrg /* all others */ 141535c4bbdfSmrg nt_list_for_each_entry(oclients, 141635c4bbdfSmrg (OtherClients *) wOtherClients(*win), next) 141735c4bbdfSmrg if (oclients->mask & core_filter) 141835c4bbdfSmrg break; 141935c4bbdfSmrg 142035c4bbdfSmrg /* if owner selected, oclients is NULL */ 142135c4bbdfSmrg *client = oclients ? rClient(oclients) : wClient(*win); 142235c4bbdfSmrg } 1423ed6184dfSmrg 1424ed6184dfSmrg *grab = NULL; 142535c4bbdfSmrg } 142635c4bbdfSmrg 142735c4bbdfSmrg return TRUE; 142835c4bbdfSmrg} 142935c4bbdfSmrg 143035c4bbdfSmrgstatic int 143135c4bbdfSmrgDeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 143235c4bbdfSmrg InternalEvent *ev, TouchListener * listener, 143335c4bbdfSmrg ClientPtr client, WindowPtr win, GrabPtr grab, 143435c4bbdfSmrg XI2Mask *xi2mask) 143535c4bbdfSmrg{ 143635c4bbdfSmrg InternalEvent motion, button; 143735c4bbdfSmrg InternalEvent *ptrev = &motion; 143835c4bbdfSmrg int nevents; 143935c4bbdfSmrg DeviceIntPtr kbd; 144035c4bbdfSmrg 1441ed6184dfSmrg /* There may be a pointer grab on the device */ 1442ed6184dfSmrg if (!grab) { 1443ed6184dfSmrg grab = dev->deviceGrab.grab; 1444ed6184dfSmrg if (grab) { 1445ed6184dfSmrg win = grab->window; 1446ed6184dfSmrg xi2mask = grab->xi2mask; 1447ed6184dfSmrg client = rClient(grab); 1448ed6184dfSmrg } 1449ed6184dfSmrg } 1450ed6184dfSmrg 145135c4bbdfSmrg /* We don't deliver pointer events to non-owners */ 145235c4bbdfSmrg if (!TouchResourceIsOwner(ti, listener->listener)) 145335c4bbdfSmrg return !Success; 145435c4bbdfSmrg 145535c4bbdfSmrg if (!ti->emulate_pointer) 145635c4bbdfSmrg return !Success; 145735c4bbdfSmrg 145835c4bbdfSmrg nevents = TouchConvertToPointerEvent(ev, &motion, &button); 145935c4bbdfSmrg BUG_RETURN_VAL(nevents == 0, BadValue); 146035c4bbdfSmrg 1461ed6184dfSmrg /* Note that here we deliver only part of the events that are generated by the touch event: 1462ed6184dfSmrg * 1463ed6184dfSmrg * TouchBegin results in ButtonPress (motion is handled in DeliverEmulatedMotionEvent) 1464ed6184dfSmrg * TouchUpdate results in Motion 1465ed6184dfSmrg * TouchEnd results in ButtonRelease (motion is handled in DeliverEmulatedMotionEvent) 1466ed6184dfSmrg */ 146735c4bbdfSmrg if (nevents > 1) 146835c4bbdfSmrg ptrev = &button; 146935c4bbdfSmrg 147035c4bbdfSmrg kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 147135c4bbdfSmrg event_set_state(dev, kbd, &ptrev->device_event); 147235c4bbdfSmrg ptrev->device_event.corestate = event_get_corestate(dev, kbd); 147335c4bbdfSmrg 147435c4bbdfSmrg if (grab) { 147535c4bbdfSmrg /* this side-steps the usual activation mechanisms, but... */ 147635c4bbdfSmrg if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab) 147735c4bbdfSmrg ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */ 147835c4bbdfSmrg else { 147935c4bbdfSmrg int deliveries = 0; 148035c4bbdfSmrg 148135c4bbdfSmrg /* 'grab' is the passive grab, but if the grab isn't active, 148235c4bbdfSmrg * don't deliver */ 148335c4bbdfSmrg if (!dev->deviceGrab.grab) 148435c4bbdfSmrg return !Success; 148535c4bbdfSmrg 148635c4bbdfSmrg if (grab->ownerEvents) { 148735c4bbdfSmrg WindowPtr focus = NullWindow; 148835c4bbdfSmrg WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 148935c4bbdfSmrg 149035c4bbdfSmrg deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev); 149135c4bbdfSmrg } 149235c4bbdfSmrg 149335c4bbdfSmrg if (!deliveries) 149435c4bbdfSmrg deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype); 149535c4bbdfSmrg 149635c4bbdfSmrg /* We must accept the touch sequence once a pointer listener has 149735c4bbdfSmrg * received one event past ButtonPress. */ 149835c4bbdfSmrg if (deliveries && ev->any.type != ET_TouchBegin && 149935c4bbdfSmrg !(ev->device_event.flags & TOUCH_CLIENT_ID)) 150035c4bbdfSmrg TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 150135c4bbdfSmrg 150235c4bbdfSmrg if (ev->any.type == ET_TouchEnd && 150335c4bbdfSmrg ti->num_listeners == 1 && 150435c4bbdfSmrg !dev->button->buttonsDown && 150535c4bbdfSmrg dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { 150635c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 150735c4bbdfSmrg CheckOldestTouch(dev); 150835c4bbdfSmrg return Success; 150935c4bbdfSmrg } 151035c4bbdfSmrg } 151135c4bbdfSmrg } 151235c4bbdfSmrg else { 151335c4bbdfSmrg GrabPtr devgrab = dev->deviceGrab.grab; 151435c4bbdfSmrg WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite); 151535c4bbdfSmrg 151635c4bbdfSmrg DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev); 151735c4bbdfSmrg /* FIXME: bad hack 151835c4bbdfSmrg * Implicit passive grab activated in response to this event. Store 151935c4bbdfSmrg * the event. 152035c4bbdfSmrg */ 152135c4bbdfSmrg if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) { 152235c4bbdfSmrg TouchListener *l; 152335c4bbdfSmrg GrabPtr g; 152435c4bbdfSmrg 152535c4bbdfSmrg devgrab = dev->deviceGrab.grab; 152635c4bbdfSmrg g = AllocGrab(devgrab); 152735c4bbdfSmrg BUG_WARN(!g); 152835c4bbdfSmrg 1529dc61d50dSmrg CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev); 153035c4bbdfSmrg 153135c4bbdfSmrg /* The listener array has a sequence of grabs and then one event 153235c4bbdfSmrg * selection. Implicit grab activation occurs through delivering an 153335c4bbdfSmrg * event selection. Thus, we update the last listener in the array. 153435c4bbdfSmrg */ 153535c4bbdfSmrg l = &ti->listeners[ti->num_listeners - 1]; 153635c4bbdfSmrg l->listener = g->resource; 153735c4bbdfSmrg l->grab = g; 153835c4bbdfSmrg //l->resource_type = RT_NONE; 153935c4bbdfSmrg 154035c4bbdfSmrg if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin) 1541ed6184dfSmrg l->type = TOUCH_LISTENER_POINTER_GRAB; 154235c4bbdfSmrg else 1543ed6184dfSmrg l->type = TOUCH_LISTENER_GRAB; 154435c4bbdfSmrg } 154535c4bbdfSmrg 154635c4bbdfSmrg } 154735c4bbdfSmrg if (ev->any.type == ET_TouchBegin) 1548ed6184dfSmrg listener->state = TOUCH_LISTENER_IS_OWNER; 154935c4bbdfSmrg else if (ev->any.type == ET_TouchEnd) 1550ed6184dfSmrg listener->state = TOUCH_LISTENER_HAS_END; 155135c4bbdfSmrg 155235c4bbdfSmrg return Success; 155335c4bbdfSmrg} 155435c4bbdfSmrg 155535c4bbdfSmrgstatic void 155635c4bbdfSmrgDeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 155735c4bbdfSmrg InternalEvent *ev) 155835c4bbdfSmrg{ 155935c4bbdfSmrg DeviceEvent motion; 156035c4bbdfSmrg 156135c4bbdfSmrg if (ti->num_listeners) { 156235c4bbdfSmrg ClientPtr client; 156335c4bbdfSmrg WindowPtr win; 156435c4bbdfSmrg GrabPtr grab; 156535c4bbdfSmrg XI2Mask *mask; 156635c4bbdfSmrg 1567ed6184dfSmrg if (ti->listeners[0].type != TOUCH_LISTENER_POINTER_REGULAR && 1568ed6184dfSmrg ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB) 156935c4bbdfSmrg return; 157035c4bbdfSmrg 157135c4bbdfSmrg motion = ev->device_event; 157235c4bbdfSmrg motion.type = ET_TouchUpdate; 157335c4bbdfSmrg motion.detail.button = 0; 157435c4bbdfSmrg 157535c4bbdfSmrg if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion, 157635c4bbdfSmrg &ti->listeners[0], &client, &win, &grab, 157735c4bbdfSmrg &mask)) 157835c4bbdfSmrg return; 157935c4bbdfSmrg 158035c4bbdfSmrg DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client, 158135c4bbdfSmrg win, grab, mask); 158235c4bbdfSmrg } 158335c4bbdfSmrg else { 158435c4bbdfSmrg InternalEvent button; 158535c4bbdfSmrg int converted; 158635c4bbdfSmrg 158735c4bbdfSmrg converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button); 158835c4bbdfSmrg 158935c4bbdfSmrg BUG_WARN(converted == 0); 159035c4bbdfSmrg if (converted) 159135c4bbdfSmrg ProcessOtherEvent((InternalEvent*)&motion, dev); 159235c4bbdfSmrg } 159335c4bbdfSmrg} 159435c4bbdfSmrg 159535c4bbdfSmrg/** 159635c4bbdfSmrg * Processes and delivers a TouchBegin, TouchUpdate, or a 159735c4bbdfSmrg * TouchEnd event. 159835c4bbdfSmrg * 159935c4bbdfSmrg * Due to having rather different delivery semantics (see the Xi 2.2 protocol 160035c4bbdfSmrg * spec for more information), this implements its own grab and event-selection 160135c4bbdfSmrg * delivery logic. 160235c4bbdfSmrg */ 160335c4bbdfSmrgstatic void 160435c4bbdfSmrgProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) 160535c4bbdfSmrg{ 160635c4bbdfSmrg TouchClassPtr t = dev->touch; 160735c4bbdfSmrg TouchPointInfoPtr ti; 160835c4bbdfSmrg uint32_t touchid; 160935c4bbdfSmrg int type = ev->any.type; 161035c4bbdfSmrg int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED); 161135c4bbdfSmrg DeviceIntPtr kbd; 161235c4bbdfSmrg 161335c4bbdfSmrg if (!t) 161435c4bbdfSmrg return; 161535c4bbdfSmrg 161635c4bbdfSmrg touchid = ev->device_event.touchid; 161735c4bbdfSmrg 161835c4bbdfSmrg if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) { 161935c4bbdfSmrg ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 162035c4bbdfSmrg emulate_pointer); 162135c4bbdfSmrg } 162235c4bbdfSmrg else 162335c4bbdfSmrg ti = TouchFindByClientID(dev, touchid); 162435c4bbdfSmrg 162535c4bbdfSmrg /* Active pointer grab */ 162635c4bbdfSmrg if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab && 162735c4bbdfSmrg (dev->deviceGrab.grab->grabtype == CORE || 162835c4bbdfSmrg dev->deviceGrab.grab->grabtype == XI || 162935c4bbdfSmrg !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) 163035c4bbdfSmrg { 163135c4bbdfSmrg /* Active pointer grab on touch point and we get a TouchEnd - claim this 163235c4bbdfSmrg * touchpoint accepted, otherwise clients waiting for ownership will 163335c4bbdfSmrg * wait on this touchpoint until this client ungrabs, or the cows come 163435c4bbdfSmrg * home, whichever is earlier */ 163535c4bbdfSmrg if (ti && type == ET_TouchEnd) 163635c4bbdfSmrg TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); 163735c4bbdfSmrg else if (!ti && type != ET_TouchBegin) { 163835c4bbdfSmrg /* Under the following circumstances we create a new touch record for an 163935c4bbdfSmrg * existing touch: 164035c4bbdfSmrg * 164135c4bbdfSmrg * - The touch may be pointer emulated 164235c4bbdfSmrg * - An explicit grab is active on the device 164335c4bbdfSmrg * - The grab is a pointer grab 164435c4bbdfSmrg * 164535c4bbdfSmrg * This allows for an explicit grab to receive pointer events for an already 164635c4bbdfSmrg * active touch. 164735c4bbdfSmrg */ 164835c4bbdfSmrg ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, 164935c4bbdfSmrg emulate_pointer); 165035c4bbdfSmrg if (!ti) { 165135c4bbdfSmrg DebugF("[Xi] %s: Failed to create new dix record for explicitly " 165235c4bbdfSmrg "grabbed touchpoint %d\n", 165335c4bbdfSmrg dev->name, touchid); 165435c4bbdfSmrg return; 165535c4bbdfSmrg } 165635c4bbdfSmrg 165735c4bbdfSmrg TouchBuildSprite(dev, ti, ev); 165835c4bbdfSmrg TouchSetupListeners(dev, ti, ev); 165935c4bbdfSmrg } 166035c4bbdfSmrg } 166135c4bbdfSmrg 166235c4bbdfSmrg if (!ti) { 166335c4bbdfSmrg DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n", 166435c4bbdfSmrg dev->name, type, touchid); 166535c4bbdfSmrg goto out; 166635c4bbdfSmrg } 166735c4bbdfSmrg 166835c4bbdfSmrg /* if emulate_pointer is set, emulate the motion event right 166935c4bbdfSmrg * here, so we can ignore it for button event emulation. TouchUpdate 167035c4bbdfSmrg * events which _only_ emulate motion just work normally */ 1671ed6184dfSmrg if (emulate_pointer && (ev->any.type == ET_TouchBegin || 1672ed6184dfSmrg (ev->any.type == ET_TouchEnd && ti->num_listeners > 0))) 167335c4bbdfSmrg DeliverEmulatedMotionEvent(dev, ti, ev); 167435c4bbdfSmrg 167535c4bbdfSmrg if (emulate_pointer && IsMaster(dev)) 167635c4bbdfSmrg CheckMotion(&ev->device_event, dev); 167735c4bbdfSmrg 167835c4bbdfSmrg kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 167935c4bbdfSmrg event_set_state(NULL, kbd, &ev->device_event); 168035c4bbdfSmrg ev->device_event.corestate = event_get_corestate(NULL, kbd); 168135c4bbdfSmrg 168235c4bbdfSmrg /* Make sure we have a valid window trace for event delivery; must be 168335c4bbdfSmrg * called after event type mutation. Touch end events are always processed 168435c4bbdfSmrg * in order to end touch records. */ 168535c4bbdfSmrg /* FIXME: check this */ 168635c4bbdfSmrg if ((type == ET_TouchBegin && 168735c4bbdfSmrg !(ev->device_event.flags & TOUCH_REPLAYING) && 168835c4bbdfSmrg !TouchBuildSprite(dev, ti, ev)) || 168935c4bbdfSmrg (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0)) 169035c4bbdfSmrg return; 169135c4bbdfSmrg 169235c4bbdfSmrg TouchCopyValuatorData(&ev->device_event, ti); 169335c4bbdfSmrg /* WARNING: the event type may change to TouchUpdate in 169435c4bbdfSmrg * DeliverTouchEvents if a TouchEnd was delivered to a grabbing 169535c4bbdfSmrg * owner */ 169635c4bbdfSmrg DeliverTouchEvents(dev, ti, ev, ev->device_event.resource); 169735c4bbdfSmrg if (ev->any.type == ET_TouchEnd) 169835c4bbdfSmrg TouchEndTouch(dev, ti); 169935c4bbdfSmrg 170035c4bbdfSmrg out: 170135c4bbdfSmrg if (emulate_pointer) 170235c4bbdfSmrg UpdateDeviceState(dev, &ev->device_event); 170335c4bbdfSmrg} 170435c4bbdfSmrg 170535c4bbdfSmrgstatic void 170635c4bbdfSmrgProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev) 170735c4bbdfSmrg{ 170835c4bbdfSmrg Mask filter; 170935c4bbdfSmrg WindowPtr pWin; 171035c4bbdfSmrg BarrierEvent *be = &e->barrier_event; 171135c4bbdfSmrg xEvent *ev; 171235c4bbdfSmrg int rc; 171335c4bbdfSmrg GrabPtr grab = dev->deviceGrab.grab; 171435c4bbdfSmrg 171535c4bbdfSmrg if (!IsMaster(dev)) 171635c4bbdfSmrg return; 171735c4bbdfSmrg 171835c4bbdfSmrg if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success) 171935c4bbdfSmrg return; 172035c4bbdfSmrg 172135c4bbdfSmrg if (grab) 172235c4bbdfSmrg be->flags |= XIBarrierDeviceIsGrabbed; 172335c4bbdfSmrg 172435c4bbdfSmrg rc = EventToXI2(e, &ev); 172535c4bbdfSmrg if (rc != Success) { 172635c4bbdfSmrg ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc); 172735c4bbdfSmrg return; 172835c4bbdfSmrg } 172935c4bbdfSmrg 173035c4bbdfSmrg /* A client has a grab, deliver to this client if the grab_window is the 173135c4bbdfSmrg barrier window. 173235c4bbdfSmrg 173335c4bbdfSmrg Otherwise, deliver normally to the client. 173435c4bbdfSmrg */ 173535c4bbdfSmrg if (grab && 173635c4bbdfSmrg CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) && 173735c4bbdfSmrg grab->window->drawable.id == be->window) { 173835c4bbdfSmrg DeliverGrabbedEvent(e, dev, FALSE); 173935c4bbdfSmrg } else { 174035c4bbdfSmrg filter = GetEventFilter(dev, ev); 174135c4bbdfSmrg 174235c4bbdfSmrg DeliverEventsToWindow(dev, pWin, ev, 1, 174335c4bbdfSmrg filter, NullGrab); 174435c4bbdfSmrg } 174535c4bbdfSmrg free(ev); 174635c4bbdfSmrg} 174735c4bbdfSmrg 1748ed6184dfSmrgstatic BOOL 1749ed6184dfSmrgIsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev) 1750ed6184dfSmrg{ 1751ed6184dfSmrg GestureClassPtr g = dev->gesture; 1752ed6184dfSmrg if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) { 1753ed6184dfSmrg return TRUE; 1754ed6184dfSmrg } 1755ed6184dfSmrg return FALSE; 1756ed6184dfSmrg} 1757ed6184dfSmrg 1758ed6184dfSmrg/** 1759ed6184dfSmrg * Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}. 1760ed6184dfSmrg * 1761ed6184dfSmrg * Due to having rather different delivery semantics (see the Xi 2.4 protocol 1762ed6184dfSmrg * spec for more information), this implements its own grab and event-selection 1763ed6184dfSmrg * delivery logic. 1764ed6184dfSmrg */ 1765ed6184dfSmrgvoid 1766ed6184dfSmrgProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev) 1767ed6184dfSmrg{ 1768ed6184dfSmrg GestureInfoPtr gi; 1769ed6184dfSmrg DeviceIntPtr kbd; 1770ed6184dfSmrg Bool deactivateGestureGrab = FALSE; 1771ed6184dfSmrg Bool delivered = FALSE; 1772ed6184dfSmrg 1773ed6184dfSmrg if (!dev->gesture) 1774ed6184dfSmrg return; 1775ed6184dfSmrg 1776ed6184dfSmrg if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev)) 1777ed6184dfSmrg return; 1778ed6184dfSmrg 1779ed6184dfSmrg if (IsGestureBeginEvent(ev)) 1780ed6184dfSmrg gi = GestureBeginGesture(dev, ev); 1781ed6184dfSmrg else 1782ed6184dfSmrg gi = GestureFindActiveByEventType(dev, ev->any.type); 1783ed6184dfSmrg 1784ed6184dfSmrg if (!gi) { 1785ed6184dfSmrg /* This may happen if gesture is no longer active or was never started. */ 1786ed6184dfSmrg return; 1787ed6184dfSmrg } 1788ed6184dfSmrg 1789ed6184dfSmrg kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); 1790ed6184dfSmrg event_set_state_gesture(kbd, &ev->gesture_event); 1791ed6184dfSmrg 1792ed6184dfSmrg if (IsGestureBeginEvent(ev)) 1793ed6184dfSmrg GestureSetupListener(dev, gi, ev); 1794ed6184dfSmrg 1795ed6184dfSmrg if (IsGestureEndEvent(ev) && 1796ed6184dfSmrg dev->deviceGrab.grab && 1797ed6184dfSmrg dev->deviceGrab.fromPassiveGrab && 1798ed6184dfSmrg GrabIsGestureGrab(dev->deviceGrab.grab)) 1799ed6184dfSmrg deactivateGestureGrab = TRUE; 1800ed6184dfSmrg 1801ed6184dfSmrg delivered = DeliverGestureEventToOwner(dev, gi, ev); 1802ed6184dfSmrg 1803ed6184dfSmrg if (delivered && !deactivateGestureGrab && 1804ed6184dfSmrg (IsGestureBeginEvent(ev) || IsGestureEndEvent(ev))) 1805ed6184dfSmrg FreezeThisEventIfNeededForSyncGrab(dev, ev); 1806ed6184dfSmrg 1807ed6184dfSmrg if (IsGestureEndEvent(ev)) 1808ed6184dfSmrg GestureEndGesture(gi); 1809ed6184dfSmrg 1810ed6184dfSmrg if (deactivateGestureGrab) 1811ed6184dfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 1812ed6184dfSmrg} 1813ed6184dfSmrg 181435c4bbdfSmrg/** 181535c4bbdfSmrg * Process DeviceEvents and DeviceChangedEvents. 181635c4bbdfSmrg */ 181735c4bbdfSmrgstatic void 181835c4bbdfSmrgProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device) 181935c4bbdfSmrg{ 182035c4bbdfSmrg GrabPtr grab; 182135c4bbdfSmrg Bool deactivateDeviceGrab = FALSE; 182235c4bbdfSmrg int key = 0, rootX, rootY; 182335c4bbdfSmrg ButtonClassPtr b; 182435c4bbdfSmrg int ret = 0; 182535c4bbdfSmrg int corestate; 182635c4bbdfSmrg DeviceIntPtr mouse = NULL, kbd = NULL; 182735c4bbdfSmrg DeviceEvent *event = &ev->device_event; 182835c4bbdfSmrg 182935c4bbdfSmrg if (IsPointerDevice(device)) { 183035c4bbdfSmrg kbd = GetMaster(device, KEYBOARD_OR_FLOAT); 183135c4bbdfSmrg mouse = device; 183235c4bbdfSmrg if (!kbd->key) /* can happen with floating SDs */ 183335c4bbdfSmrg kbd = NULL; 183435c4bbdfSmrg } 183535c4bbdfSmrg else { 183635c4bbdfSmrg mouse = GetMaster(device, POINTER_OR_FLOAT); 183735c4bbdfSmrg kbd = device; 183835c4bbdfSmrg if (!mouse->valuator || !mouse->button) /* may be float. SDs */ 183935c4bbdfSmrg mouse = NULL; 184035c4bbdfSmrg } 184135c4bbdfSmrg 184235c4bbdfSmrg corestate = event_get_corestate(mouse, kbd); 184335c4bbdfSmrg event_set_state(mouse, kbd, event); 184435c4bbdfSmrg 184535c4bbdfSmrg ret = UpdateDeviceState(device, event); 184635c4bbdfSmrg if (ret == DONT_PROCESS) 184735c4bbdfSmrg return; 184835c4bbdfSmrg 184935c4bbdfSmrg b = device->button; 185035c4bbdfSmrg 185135c4bbdfSmrg if (IsMaster(device) || IsFloating(device)) 185235c4bbdfSmrg CheckMotion(event, device); 185335c4bbdfSmrg 185435c4bbdfSmrg switch (event->type) { 185535c4bbdfSmrg case ET_Motion: 185635c4bbdfSmrg case ET_ButtonPress: 185735c4bbdfSmrg case ET_ButtonRelease: 185835c4bbdfSmrg case ET_KeyPress: 185935c4bbdfSmrg case ET_KeyRelease: 186035c4bbdfSmrg case ET_ProximityIn: 186135c4bbdfSmrg case ET_ProximityOut: 186235c4bbdfSmrg GetSpritePosition(device, &rootX, &rootY); 186335c4bbdfSmrg event->root_x = rootX; 186435c4bbdfSmrg event->root_y = rootY; 186535c4bbdfSmrg NoticeEventTime((InternalEvent *) event, device); 186635c4bbdfSmrg event->corestate = corestate; 186735c4bbdfSmrg key = event->detail.key; 186835c4bbdfSmrg break; 186935c4bbdfSmrg default: 187035c4bbdfSmrg break; 187135c4bbdfSmrg } 187235c4bbdfSmrg 187335c4bbdfSmrg /* send KeyPress and KeyRelease events to XACE plugins */ 187435c4bbdfSmrg if (XaceHookIsSet(XACE_KEY_AVAIL) && 187535c4bbdfSmrg (event->type == ET_KeyPress || event->type == ET_KeyRelease)) { 187635c4bbdfSmrg xEvent *core; 187735c4bbdfSmrg int count; 187835c4bbdfSmrg 187935c4bbdfSmrg if (EventToCore(ev, &core, &count) == Success && count > 0) { 188035c4bbdfSmrg XaceHook(XACE_KEY_AVAIL, core, device, 0); 188135c4bbdfSmrg free(core); 188235c4bbdfSmrg } 188335c4bbdfSmrg } 188435c4bbdfSmrg 188535c4bbdfSmrg if (DeviceEventCallback && !syncEvents.playingEvents) { 188635c4bbdfSmrg DeviceEventInfoRec eventinfo; 188735c4bbdfSmrg SpritePtr pSprite = device->spriteInfo->sprite; 188835c4bbdfSmrg 188935c4bbdfSmrg /* see comment in EnqueueEvents regarding the next three lines */ 189035c4bbdfSmrg if (ev->any.type == ET_Motion) 189135c4bbdfSmrg ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 189235c4bbdfSmrg 189335c4bbdfSmrg eventinfo.device = device; 189435c4bbdfSmrg eventinfo.event = ev; 189535c4bbdfSmrg CallCallbacks(&DeviceEventCallback, (void *) &eventinfo); 189635c4bbdfSmrg } 189735c4bbdfSmrg 189835c4bbdfSmrg grab = device->deviceGrab.grab; 189935c4bbdfSmrg 190035c4bbdfSmrg switch (event->type) { 190135c4bbdfSmrg case ET_KeyPress: 19021b5d61b8Smrg /* Don't deliver focus events (e.g. from KeymapNotify when running 19031b5d61b8Smrg * nested) to clients. */ 19041b5d61b8Smrg if (event->source_type == EVENT_SOURCE_FOCUS) 19051b5d61b8Smrg return; 1906ed6184dfSmrg if (!grab && CheckDeviceGrabs(device, ev, 0)) 190735c4bbdfSmrg return; 190835c4bbdfSmrg break; 190935c4bbdfSmrg case ET_KeyRelease: 191035c4bbdfSmrg if (grab && device->deviceGrab.fromPassiveGrab && 191135c4bbdfSmrg (key == device->deviceGrab.activatingKey) && 191235c4bbdfSmrg GrabIsKeyboardGrab(device->deviceGrab.grab)) 191335c4bbdfSmrg deactivateDeviceGrab = TRUE; 191435c4bbdfSmrg break; 191535c4bbdfSmrg case ET_ButtonPress: 191635c4bbdfSmrg if (b->map[key] == 0) /* there's no button 0 */ 191735c4bbdfSmrg return; 191835c4bbdfSmrg event->detail.button = b->map[key]; 1919ed6184dfSmrg if (!grab && CheckDeviceGrabs(device, ev, 0)) { 192035c4bbdfSmrg /* if a passive grab was activated, the event has been sent 192135c4bbdfSmrg * already */ 192235c4bbdfSmrg return; 192335c4bbdfSmrg } 192435c4bbdfSmrg break; 192535c4bbdfSmrg case ET_ButtonRelease: 192635c4bbdfSmrg if (b->map[key] == 0) /* there's no button 0 */ 192735c4bbdfSmrg return; 192835c4bbdfSmrg event->detail.button = b->map[key]; 192935c4bbdfSmrg if (grab && !b->buttonsDown && 193035c4bbdfSmrg device->deviceGrab.fromPassiveGrab && 193135c4bbdfSmrg GrabIsPointerGrab(device->deviceGrab.grab)) 193235c4bbdfSmrg deactivateDeviceGrab = TRUE; 193335c4bbdfSmrg default: 193435c4bbdfSmrg break; 193535c4bbdfSmrg } 193635c4bbdfSmrg 19371b5d61b8Smrg /* Don't deliver focus events (e.g. from KeymapNotify when running 19381b5d61b8Smrg * nested) to clients. */ 19391b5d61b8Smrg if (event->source_type != EVENT_SOURCE_FOCUS) { 19401b5d61b8Smrg if (grab) 19411b5d61b8Smrg DeliverGrabbedEvent((InternalEvent *) event, device, 19421b5d61b8Smrg deactivateDeviceGrab); 19431b5d61b8Smrg else if (device->focus && !IsPointerEvent(ev)) 19441b5d61b8Smrg DeliverFocusedEvent(device, (InternalEvent *) event, 19451b5d61b8Smrg GetSpriteWindow(device)); 19461b5d61b8Smrg else 19471b5d61b8Smrg DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event, 19481b5d61b8Smrg NullGrab, NullWindow, device); 19491b5d61b8Smrg } 195035c4bbdfSmrg 195135c4bbdfSmrg if (deactivateDeviceGrab == TRUE) { 195235c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 195335c4bbdfSmrg 195435c4bbdfSmrg if (!IsMaster (device) && !IsFloating (device)) { 195535c4bbdfSmrg int flags, num_events = 0; 195635c4bbdfSmrg InternalEvent dce; 195735c4bbdfSmrg 195835c4bbdfSmrg flags = (IsPointerDevice (device)) ? 195935c4bbdfSmrg DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT; 196035c4bbdfSmrg UpdateFromMaster (&dce, device, flags, &num_events); 196135c4bbdfSmrg BUG_WARN(num_events > 1); 196235c4bbdfSmrg 196335c4bbdfSmrg if (num_events == 1) 196435c4bbdfSmrg ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED), 196535c4bbdfSmrg &dce.changed_event); 196635c4bbdfSmrg } 196735c4bbdfSmrg 196835c4bbdfSmrg } 196935c4bbdfSmrg 197035c4bbdfSmrg event->detail.key = key; 197135c4bbdfSmrg} 197235c4bbdfSmrg 197335c4bbdfSmrg/** 197435c4bbdfSmrg * Main device event processing function. 197535c4bbdfSmrg * Called from when processing the events from the event queue. 197635c4bbdfSmrg * 197735c4bbdfSmrg */ 197835c4bbdfSmrgvoid 197935c4bbdfSmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) 198035c4bbdfSmrg{ 198135c4bbdfSmrg verify_internal_event(ev); 198235c4bbdfSmrg 198335c4bbdfSmrg switch (ev->any.type) { 198435c4bbdfSmrg case ET_RawKeyPress: 198535c4bbdfSmrg case ET_RawKeyRelease: 198635c4bbdfSmrg case ET_RawButtonPress: 198735c4bbdfSmrg case ET_RawButtonRelease: 198835c4bbdfSmrg case ET_RawMotion: 198935c4bbdfSmrg case ET_RawTouchBegin: 199035c4bbdfSmrg case ET_RawTouchUpdate: 199135c4bbdfSmrg case ET_RawTouchEnd: 199235c4bbdfSmrg DeliverRawEvent(&ev->raw_event, device); 199335c4bbdfSmrg break; 199435c4bbdfSmrg case ET_TouchBegin: 199535c4bbdfSmrg case ET_TouchUpdate: 199635c4bbdfSmrg case ET_TouchEnd: 199735c4bbdfSmrg ProcessTouchEvent(ev, device); 199835c4bbdfSmrg break; 199935c4bbdfSmrg case ET_TouchOwnership: 200035c4bbdfSmrg /* TouchOwnership events are handled separately from the rest, as they 200135c4bbdfSmrg * have more complex semantics. */ 200235c4bbdfSmrg ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device); 200335c4bbdfSmrg break; 200435c4bbdfSmrg case ET_BarrierHit: 200535c4bbdfSmrg case ET_BarrierLeave: 200635c4bbdfSmrg ProcessBarrierEvent(ev, device); 200735c4bbdfSmrg break; 2008ed6184dfSmrg case ET_GesturePinchBegin: 2009ed6184dfSmrg case ET_GesturePinchUpdate: 2010ed6184dfSmrg case ET_GesturePinchEnd: 2011ed6184dfSmrg case ET_GestureSwipeBegin: 2012ed6184dfSmrg case ET_GestureSwipeUpdate: 2013ed6184dfSmrg case ET_GestureSwipeEnd: 2014ed6184dfSmrg ProcessGestureEvent(ev, device); 2015ed6184dfSmrg break; 201635c4bbdfSmrg default: 201735c4bbdfSmrg ProcessDeviceEvent(ev, device); 201835c4bbdfSmrg break; 201935c4bbdfSmrg } 202035c4bbdfSmrg} 202135c4bbdfSmrg 202235c4bbdfSmrgstatic int 202335c4bbdfSmrgDeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, 202435c4bbdfSmrg InternalEvent *ev, TouchListener * listener, 202535c4bbdfSmrg ClientPtr client, WindowPtr win, GrabPtr grab, 202635c4bbdfSmrg XI2Mask *xi2mask) 202735c4bbdfSmrg{ 202835c4bbdfSmrg enum TouchListenerState state; 202935c4bbdfSmrg int rc = Success; 203035c4bbdfSmrg Bool has_ownershipmask; 203135c4bbdfSmrg 2032ed6184dfSmrg if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2033ed6184dfSmrg listener->type == TOUCH_LISTENER_POINTER_GRAB) { 203435c4bbdfSmrg rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 203535c4bbdfSmrg grab, xi2mask); 203635c4bbdfSmrg if (rc == Success) { 2037ed6184dfSmrg listener->state = TOUCH_LISTENER_IS_OWNER; 203835c4bbdfSmrg /* async grabs cannot replay, so automatically accept this touch */ 2039ed6184dfSmrg if (listener->type == TOUCH_LISTENER_POINTER_GRAB && 204035c4bbdfSmrg dev->deviceGrab.grab && 204135c4bbdfSmrg dev->deviceGrab.fromPassiveGrab && 204235c4bbdfSmrg dev->deviceGrab.grab->pointerMode == GrabModeAsync) 204335c4bbdfSmrg ActivateEarlyAccept(dev, ti); 204435c4bbdfSmrg } 204535c4bbdfSmrg goto out; 204635c4bbdfSmrg } 204735c4bbdfSmrg 204835c4bbdfSmrg has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 204935c4bbdfSmrg 205035c4bbdfSmrg if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask) 205135c4bbdfSmrg rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 205235c4bbdfSmrg if (!TouchResourceIsOwner(ti, listener->listener)) { 205335c4bbdfSmrg if (has_ownershipmask) 2054ed6184dfSmrg state = TOUCH_LISTENER_AWAITING_OWNER; 205535c4bbdfSmrg else 2056ed6184dfSmrg state = TOUCH_LISTENER_AWAITING_BEGIN; 205735c4bbdfSmrg } 205835c4bbdfSmrg else { 205935c4bbdfSmrg if (has_ownershipmask) 206035c4bbdfSmrg TouchSendOwnershipEvent(dev, ti, 0, listener->listener); 206135c4bbdfSmrg 2062ed6184dfSmrg if (listener->type == TOUCH_LISTENER_REGULAR) 2063ed6184dfSmrg state = TOUCH_LISTENER_HAS_ACCEPTED; 206435c4bbdfSmrg else 2065ed6184dfSmrg state = TOUCH_LISTENER_IS_OWNER; 206635c4bbdfSmrg } 206735c4bbdfSmrg listener->state = state; 206835c4bbdfSmrg 206935c4bbdfSmrg out: 207035c4bbdfSmrg return rc; 207135c4bbdfSmrg} 207235c4bbdfSmrg 207335c4bbdfSmrgstatic int 207435c4bbdfSmrgDeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 207535c4bbdfSmrg TouchListener * listener, ClientPtr client, 207635c4bbdfSmrg WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 207735c4bbdfSmrg{ 207835c4bbdfSmrg int rc = Success; 207935c4bbdfSmrg 2080ed6184dfSmrg if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2081ed6184dfSmrg listener->type == TOUCH_LISTENER_POINTER_GRAB) { 208235c4bbdfSmrg /* Note: If the active grab was ungrabbed, we already changed the 2083ed6184dfSmrg * state to TOUCH_LISTENER_HAS_END but still get here. So we mustn't 208435c4bbdfSmrg * actually send the event. 208535c4bbdfSmrg * This is part two of the hack in DeactivatePointerGrab 208635c4bbdfSmrg */ 2087ed6184dfSmrg if (listener->state != TOUCH_LISTENER_HAS_END) { 208835c4bbdfSmrg rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, 208935c4bbdfSmrg grab, xi2mask); 209035c4bbdfSmrg 209135c4bbdfSmrg /* Once we send a TouchEnd to a legacy listener, we're already well 209235c4bbdfSmrg * past the accepting/rejecting stage (can only happen on 209335c4bbdfSmrg * GrabModeSync + replay. This listener now gets the end event, 209435c4bbdfSmrg * and we can continue. 209535c4bbdfSmrg */ 209635c4bbdfSmrg if (rc == Success) 2097ed6184dfSmrg listener->state = TOUCH_LISTENER_HAS_END; 209835c4bbdfSmrg } 209935c4bbdfSmrg goto out; 210035c4bbdfSmrg } 210135c4bbdfSmrg 210235c4bbdfSmrg /* A client is waiting for the begin, don't give it a TouchEnd */ 2103ed6184dfSmrg if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) { 2104ed6184dfSmrg listener->state = TOUCH_LISTENER_HAS_END; 210535c4bbdfSmrg goto out; 210635c4bbdfSmrg } 210735c4bbdfSmrg 210835c4bbdfSmrg /* Event in response to reject */ 210935c4bbdfSmrg if (ev->device_event.flags & TOUCH_REJECT || 211035c4bbdfSmrg (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) { 211135c4bbdfSmrg /* Touch has been rejected, or accepted by its owner which is not this listener */ 2112ed6184dfSmrg if (listener->state != TOUCH_LISTENER_HAS_END) 211335c4bbdfSmrg rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2114ed6184dfSmrg listener->state = TOUCH_LISTENER_HAS_END; 211535c4bbdfSmrg } 211635c4bbdfSmrg else if (TouchResourceIsOwner(ti, listener->listener)) { 211735c4bbdfSmrg Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT); 211835c4bbdfSmrg 211935c4bbdfSmrg /* FIXME: what about early acceptance */ 2120ed6184dfSmrg if (normal_end && listener->state != TOUCH_LISTENER_HAS_END) 212135c4bbdfSmrg rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 212235c4bbdfSmrg 212335c4bbdfSmrg if ((ti->num_listeners > 1 || 2124ed6184dfSmrg (ti->num_grabs > 0 && listener->state != TOUCH_LISTENER_HAS_ACCEPTED)) && 212535c4bbdfSmrg (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) { 212635c4bbdfSmrg ev->any.type = ET_TouchUpdate; 212735c4bbdfSmrg ev->device_event.flags |= TOUCH_PENDING_END; 212835c4bbdfSmrg ti->pending_finish = TRUE; 212935c4bbdfSmrg } 213035c4bbdfSmrg 213135c4bbdfSmrg if (normal_end) 2132ed6184dfSmrg listener->state = TOUCH_LISTENER_HAS_END; 213335c4bbdfSmrg } 213435c4bbdfSmrg 213535c4bbdfSmrg out: 213635c4bbdfSmrg return rc; 213735c4bbdfSmrg} 213835c4bbdfSmrg 213935c4bbdfSmrgstatic int 214035c4bbdfSmrgDeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, 214135c4bbdfSmrg TouchListener * listener, ClientPtr client, 214235c4bbdfSmrg WindowPtr win, GrabPtr grab, XI2Mask *xi2mask) 214335c4bbdfSmrg{ 214435c4bbdfSmrg Bool has_ownershipmask = FALSE; 214535c4bbdfSmrg int rc = Success; 214635c4bbdfSmrg 214735c4bbdfSmrg if (xi2mask) 214835c4bbdfSmrg has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership); 214935c4bbdfSmrg 215035c4bbdfSmrg if (ev->any.type == ET_TouchOwnership) { 215135c4bbdfSmrg ev->touch_ownership_event.deviceid = dev->id; 215235c4bbdfSmrg if (!TouchResourceIsOwner(ti, listener->listener)) 215335c4bbdfSmrg goto out; 215435c4bbdfSmrg rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 2155ed6184dfSmrg listener->state = TOUCH_LISTENER_IS_OWNER; 215635c4bbdfSmrg } 215735c4bbdfSmrg else 215835c4bbdfSmrg ev->device_event.deviceid = dev->id; 215935c4bbdfSmrg 216035c4bbdfSmrg if (ev->any.type == ET_TouchBegin) { 216135c4bbdfSmrg rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, 216235c4bbdfSmrg xi2mask); 216335c4bbdfSmrg } 216435c4bbdfSmrg else if (ev->any.type == ET_TouchUpdate) { 2165ed6184dfSmrg if (listener->type == TOUCH_LISTENER_POINTER_REGULAR || 2166ed6184dfSmrg listener->type == TOUCH_LISTENER_POINTER_GRAB) 216735c4bbdfSmrg DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, 216835c4bbdfSmrg xi2mask); 216935c4bbdfSmrg else if (TouchResourceIsOwner(ti, listener->listener) || 217035c4bbdfSmrg has_ownershipmask) 217135c4bbdfSmrg rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); 217235c4bbdfSmrg } 217335c4bbdfSmrg else if (ev->any.type == ET_TouchEnd) 217435c4bbdfSmrg rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, 217535c4bbdfSmrg xi2mask); 217635c4bbdfSmrg 217735c4bbdfSmrg out: 217835c4bbdfSmrg return rc; 217935c4bbdfSmrg} 218035c4bbdfSmrg 218135c4bbdfSmrg/** 218235c4bbdfSmrg * Delivers a touch events to all interested clients. For TouchBegin events, 218335c4bbdfSmrg * will update ti->listeners, ti->num_listeners, and ti->num_grabs. 218435c4bbdfSmrg * May also mutate ev (type and flags) upon successful delivery. If 218535c4bbdfSmrg * @resource is non-zero, will only attempt delivery to the owner of that 218635c4bbdfSmrg * resource. 218735c4bbdfSmrg * 218835c4bbdfSmrg * @return TRUE if the event was delivered at least once, FALSE otherwise 218935c4bbdfSmrg */ 219035c4bbdfSmrgvoid 219135c4bbdfSmrgDeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, 219235c4bbdfSmrg InternalEvent *ev, XID resource) 219335c4bbdfSmrg{ 219435c4bbdfSmrg int i; 219535c4bbdfSmrg 219635c4bbdfSmrg if (ev->any.type == ET_TouchBegin && 219735c4bbdfSmrg !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING))) 219835c4bbdfSmrg TouchSetupListeners(dev, ti, ev); 219935c4bbdfSmrg 220035c4bbdfSmrg TouchEventHistoryPush(ti, &ev->device_event); 220135c4bbdfSmrg 220235c4bbdfSmrg for (i = 0; i < ti->num_listeners; i++) { 220335c4bbdfSmrg GrabPtr grab = NULL; 220435c4bbdfSmrg ClientPtr client; 220535c4bbdfSmrg WindowPtr win; 220635c4bbdfSmrg XI2Mask *mask; 220735c4bbdfSmrg TouchListener *listener = &ti->listeners[i]; 220835c4bbdfSmrg 220935c4bbdfSmrg if (resource && listener->listener != resource) 221035c4bbdfSmrg continue; 221135c4bbdfSmrg 221235c4bbdfSmrg if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win, 221335c4bbdfSmrg &grab, &mask)) 221435c4bbdfSmrg continue; 221535c4bbdfSmrg 221635c4bbdfSmrg DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask); 221735c4bbdfSmrg } 221835c4bbdfSmrg} 221935c4bbdfSmrg 2220ed6184dfSmrg/** 2221ed6184dfSmrg * Attempts to deliver a gesture event to the given client. 2222ed6184dfSmrg */ 2223ed6184dfSmrgstatic Bool 2224ed6184dfSmrgDeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi, 2225ed6184dfSmrg GrabPtr grab, WindowPtr win, InternalEvent *ev) 2226ed6184dfSmrg{ 2227ed6184dfSmrg int err; 2228ed6184dfSmrg xEvent *xi2; 2229ed6184dfSmrg Mask filter; 2230ed6184dfSmrg Window child = DeepestSpriteWin(&gi->sprite)->drawable.id; 2231ed6184dfSmrg 2232ed6184dfSmrg /* If we fail here, we're going to leave a client hanging. */ 2233ed6184dfSmrg err = EventToXI2(ev, &xi2); 2234ed6184dfSmrg if (err != Success) 2235ed6184dfSmrg FatalError("[Xi] %s: XI2 conversion failed in %s" 2236ed6184dfSmrg " (%d)\n", dev->name, __func__, err); 2237ed6184dfSmrg 2238ed6184dfSmrg FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE); 2239ed6184dfSmrg filter = GetEventFilter(dev, xi2); 2240ed6184dfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success) 2241ed6184dfSmrg return FALSE; 2242ed6184dfSmrg err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab); 2243ed6184dfSmrg free(xi2); 2244ed6184dfSmrg 2245ed6184dfSmrg /* Returning the value from TryClientEvents isn't useful, since all our 2246ed6184dfSmrg * resource-gone cleanups will update the delivery list anyway. */ 2247ed6184dfSmrg return TRUE; 2248ed6184dfSmrg} 2249ed6184dfSmrg 2250ed6184dfSmrg/** 2251ed6184dfSmrg * Given a gesture event and a potential listener, retrieve info needed for processing the event. 2252ed6184dfSmrg * 2253ed6184dfSmrg * @param dev The device generating the gesture event. 2254ed6184dfSmrg * @param ev The gesture event to process. 2255ed6184dfSmrg * @param listener The gesture event listener that may receive the gesture event. 2256ed6184dfSmrg * @param[out] client The client that should receive the gesture event. 2257ed6184dfSmrg * @param[out] win The window to deliver the event on. 2258ed6184dfSmrg * @param[out] grab The grab to deliver the event through, if any. 2259ed6184dfSmrg * @return TRUE if an event should be delivered to the listener, FALSE 2260ed6184dfSmrg * otherwise. 2261ed6184dfSmrg */ 2262ed6184dfSmrgstatic Bool 2263ed6184dfSmrgRetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener, 2264ed6184dfSmrg ClientPtr *client, WindowPtr *win, GrabPtr *grab) 2265ed6184dfSmrg{ 2266ed6184dfSmrg int rc; 2267ed6184dfSmrg int evtype; 2268ed6184dfSmrg InputClients *iclients = NULL; 2269ed6184dfSmrg *grab = NULL; 2270ed6184dfSmrg 2271ed6184dfSmrg if (listener->type == GESTURE_LISTENER_GRAB || 2272ed6184dfSmrg listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) { 2273ed6184dfSmrg *grab = listener->grab; 2274ed6184dfSmrg 2275ed6184dfSmrg BUG_RETURN_VAL(!*grab, FALSE); 2276ed6184dfSmrg 2277ed6184dfSmrg *client = rClient(*grab); 2278ed6184dfSmrg *win = (*grab)->window; 2279ed6184dfSmrg } 2280ed6184dfSmrg else { 2281ed6184dfSmrg rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type, 2282ed6184dfSmrg serverClient, DixSendAccess); 2283ed6184dfSmrg if (rc != Success) 2284ed6184dfSmrg return FALSE; 2285ed6184dfSmrg 2286ed6184dfSmrg /* note that we only will have XI2 listeners as 2287ed6184dfSmrg listener->type == GESTURE_LISTENER_REGULAR */ 2288ed6184dfSmrg evtype = GetXI2Type(ev->any.type); 2289ed6184dfSmrg 2290ed6184dfSmrg nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next) 2291ed6184dfSmrg if (xi2mask_isset(iclients->xi2mask, dev, evtype)) 2292ed6184dfSmrg break; 2293ed6184dfSmrg 2294ed6184dfSmrg BUG_RETURN_VAL(!iclients, FALSE); 2295ed6184dfSmrg 2296ed6184dfSmrg *client = rClient(iclients); 2297ed6184dfSmrg } 2298ed6184dfSmrg 2299ed6184dfSmrg return TRUE; 2300ed6184dfSmrg} 2301ed6184dfSmrg 2302ed6184dfSmrg/** 2303ed6184dfSmrg * Delivers a gesture to the owner, if possible and needed. Returns whether 2304ed6184dfSmrg * an event was delivered. 2305ed6184dfSmrg */ 2306ed6184dfSmrgBool 2307ed6184dfSmrgDeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev) 2308ed6184dfSmrg{ 2309ed6184dfSmrg GrabPtr grab = NULL; 2310ed6184dfSmrg ClientPtr client; 2311ed6184dfSmrg WindowPtr win; 2312ed6184dfSmrg 2313ed6184dfSmrg if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) { 2314ed6184dfSmrg return 0; 2315ed6184dfSmrg } 2316ed6184dfSmrg 2317ed6184dfSmrg if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab)) 2318ed6184dfSmrg return 0; 2319ed6184dfSmrg 2320ed6184dfSmrg ev->gesture_event.deviceid = dev->id; 2321ed6184dfSmrg 2322ed6184dfSmrg return DeliverOneGestureEvent(client, dev, gi, grab, win, ev); 2323ed6184dfSmrg} 2324ed6184dfSmrg 232535c4bbdfSmrgint 232635c4bbdfSmrgInitProximityClassDeviceStruct(DeviceIntPtr dev) 232735c4bbdfSmrg{ 232835c4bbdfSmrg ProximityClassPtr proxc; 232935c4bbdfSmrg 233035c4bbdfSmrg BUG_RETURN_VAL(dev == NULL, FALSE); 233135c4bbdfSmrg BUG_RETURN_VAL(dev->proximity != NULL, FALSE); 233235c4bbdfSmrg 233335c4bbdfSmrg proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec)); 233435c4bbdfSmrg if (!proxc) 233535c4bbdfSmrg return FALSE; 233635c4bbdfSmrg proxc->sourceid = dev->id; 233735c4bbdfSmrg proxc->in_proximity = TRUE; 233835c4bbdfSmrg dev->proximity = proxc; 233935c4bbdfSmrg return TRUE; 234035c4bbdfSmrg} 234135c4bbdfSmrg 234235c4bbdfSmrg/** 234335c4bbdfSmrg * Initialise the device's valuators. The memory must already be allocated, 23444642e01fSmrg * this function merely inits the matching axis (specified through axnum) to 23454642e01fSmrg * sane values. 23464642e01fSmrg * 23474642e01fSmrg * It is a condition that (minval < maxval). 23484642e01fSmrg * 23494642e01fSmrg * @see InitValuatorClassDeviceStruct 23504642e01fSmrg */ 235135c4bbdfSmrgBool 235235c4bbdfSmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, 235335c4bbdfSmrg int maxval, int resolution, int min_res, int max_res, 235435c4bbdfSmrg int mode) 235505b261ecSmrg{ 235605b261ecSmrg AxisInfoPtr ax; 23574642e01fSmrg 235835c4bbdfSmrg BUG_RETURN_VAL(dev == NULL, FALSE); 235935c4bbdfSmrg BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 236035c4bbdfSmrg BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 236135c4bbdfSmrg BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE); 236205b261ecSmrg 236305b261ecSmrg ax = dev->valuator->axes + axnum; 236405b261ecSmrg 236505b261ecSmrg ax->min_value = minval; 236605b261ecSmrg ax->max_value = maxval; 236705b261ecSmrg ax->resolution = resolution; 236805b261ecSmrg ax->min_resolution = min_res; 236905b261ecSmrg ax->max_resolution = max_res; 23706747b715Smrg ax->label = label; 23719ace9065Smrg ax->mode = mode; 23729ace9065Smrg 23739ace9065Smrg if (mode & OutOfProximity) 23749ace9065Smrg dev->proximity->in_proximity = FALSE; 237505b261ecSmrg 237635c4bbdfSmrg return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE); 237705b261ecSmrg} 237805b261ecSmrg 237935c4bbdfSmrg/** 238035c4bbdfSmrg * Set the given axis number as a scrolling valuator. 238135c4bbdfSmrg */ 238235c4bbdfSmrgBool 238335c4bbdfSmrgSetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, 238435c4bbdfSmrg double increment, int flags) 238505b261ecSmrg{ 238635c4bbdfSmrg AxisInfoPtr ax; 238735c4bbdfSmrg int *current_ax; 238835c4bbdfSmrg InternalEvent dce; 238935c4bbdfSmrg DeviceIntPtr master; 239035c4bbdfSmrg 239135c4bbdfSmrg BUG_RETURN_VAL(dev == NULL, FALSE); 239235c4bbdfSmrg BUG_RETURN_VAL(dev->valuator == NULL, FALSE); 239335c4bbdfSmrg BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE); 239435c4bbdfSmrg 239535c4bbdfSmrg switch (type) { 239635c4bbdfSmrg case SCROLL_TYPE_VERTICAL: 239735c4bbdfSmrg current_ax = &dev->valuator->v_scroll_axis; 239835c4bbdfSmrg break; 239935c4bbdfSmrg case SCROLL_TYPE_HORIZONTAL: 240035c4bbdfSmrg current_ax = &dev->valuator->h_scroll_axis; 240135c4bbdfSmrg break; 240235c4bbdfSmrg case SCROLL_TYPE_NONE: 240335c4bbdfSmrg ax = &dev->valuator->axes[axnum]; 240435c4bbdfSmrg ax->scroll.type = type; 240535c4bbdfSmrg return TRUE; 240635c4bbdfSmrg default: 240735c4bbdfSmrg return FALSE; 240805b261ecSmrg } 240905b261ecSmrg 241035c4bbdfSmrg if (increment == 0.0) 241135c4bbdfSmrg return FALSE; 24126747b715Smrg 241335c4bbdfSmrg if (*current_ax != -1 && axnum != *current_ax) { 241435c4bbdfSmrg ax = &dev->valuator->axes[*current_ax]; 241535c4bbdfSmrg if (ax->scroll.type == type && 241635c4bbdfSmrg (flags & SCROLL_FLAG_PREFERRED) && 241735c4bbdfSmrg (ax->scroll.flags & SCROLL_FLAG_PREFERRED)) 241835c4bbdfSmrg return FALSE; 24196747b715Smrg } 242035c4bbdfSmrg *current_ax = axnum; 242105b261ecSmrg 242235c4bbdfSmrg ax = &dev->valuator->axes[axnum]; 242335c4bbdfSmrg ax->scroll.type = type; 242435c4bbdfSmrg ax->scroll.increment = increment; 242535c4bbdfSmrg ax->scroll.flags = flags; 24266747b715Smrg 242735c4bbdfSmrg master = GetMaster(dev, MASTER_ATTACHED); 242835c4bbdfSmrg CreateClassesChangedEvent(&dce, master, dev, 242935c4bbdfSmrg DEVCHANGE_POINTER_EVENT | 243035c4bbdfSmrg DEVCHANGE_DEVICE_CHANGE); 243135c4bbdfSmrg XISendDeviceChangedEvent(dev, &dce.changed_event); 24326747b715Smrg 243335c4bbdfSmrg /* if the current slave is us, update the master. If not, we'll update 243435c4bbdfSmrg * whenever the next slave switch happens anyway. CMDC sends the event 243535c4bbdfSmrg * for us */ 243635c4bbdfSmrg if (master && master->lastSlave == dev) 243735c4bbdfSmrg ChangeMasterDeviceClasses(master, &dce.changed_event); 243805b261ecSmrg 243935c4bbdfSmrg return TRUE; 244005b261ecSmrg} 244105b261ecSmrg 244205b261ecSmrgint 244335c4bbdfSmrgCheckGrabValues(ClientPtr client, GrabParameters *param) 244405b261ecSmrg{ 244535c4bbdfSmrg if (param->grabtype != CORE && 244635c4bbdfSmrg param->grabtype != XI && param->grabtype != XI2) { 24476747b715Smrg ErrorF("[Xi] grabtype is invalid. This is a bug.\n"); 24486747b715Smrg return BadImplementation; 24496747b715Smrg } 245005b261ecSmrg 24516747b715Smrg if ((param->this_device_mode != GrabModeSync) && 245235c4bbdfSmrg (param->this_device_mode != GrabModeAsync) && 245335c4bbdfSmrg (param->this_device_mode != XIGrabModeTouch)) { 245435c4bbdfSmrg client->errorValue = param->this_device_mode; 245535c4bbdfSmrg return BadValue; 245605b261ecSmrg } 24576747b715Smrg if ((param->other_devices_mode != GrabModeSync) && 245835c4bbdfSmrg (param->other_devices_mode != GrabModeAsync) && 245935c4bbdfSmrg (param->other_devices_mode != XIGrabModeTouch)) { 246035c4bbdfSmrg client->errorValue = param->other_devices_mode; 246135c4bbdfSmrg return BadValue; 246205b261ecSmrg } 24636747b715Smrg 246435c4bbdfSmrg if (param->modifiers != AnyModifier && 246535c4bbdfSmrg param->modifiers != XIAnyModifier && 24666747b715Smrg (param->modifiers & ~AllModifiersMask)) { 246735c4bbdfSmrg client->errorValue = param->modifiers; 246835c4bbdfSmrg return BadValue; 246905b261ecSmrg } 24706747b715Smrg 24716747b715Smrg if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) { 247235c4bbdfSmrg client->errorValue = param->ownerEvents; 247335c4bbdfSmrg return BadValue; 247405b261ecSmrg } 24756747b715Smrg return Success; 24766747b715Smrg} 24776747b715Smrg 24786747b715Smrgint 24796747b715SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 248035c4bbdfSmrg int button, GrabParameters *param, enum InputLevel grabtype, 248135c4bbdfSmrg GrabMask *mask) 24826747b715Smrg{ 24836747b715Smrg WindowPtr pWin, confineTo; 24846747b715Smrg CursorPtr cursor; 24856747b715Smrg GrabPtr grab; 24866747b715Smrg int rc, type = -1; 24876747b715Smrg Mask access_mode = DixGrabAccess; 24886747b715Smrg 24896747b715Smrg rc = CheckGrabValues(client, param); 249005b261ecSmrg if (rc != Success) 249135c4bbdfSmrg return rc; 24926747b715Smrg if (param->confineTo == None) 249335c4bbdfSmrg confineTo = NullWindow; 249405b261ecSmrg else { 249535c4bbdfSmrg rc = dixLookupWindow(&confineTo, param->confineTo, client, 249635c4bbdfSmrg DixSetAttrAccess); 249735c4bbdfSmrg if (rc != Success) 249835c4bbdfSmrg return rc; 249905b261ecSmrg } 25006747b715Smrg if (param->cursor == None) 250135c4bbdfSmrg cursor = NullCursor; 250205b261ecSmrg else { 250335c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, param->cursor, 250435c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 250535c4bbdfSmrg if (rc != Success) { 250635c4bbdfSmrg client->errorValue = param->cursor; 250735c4bbdfSmrg return rc; 250835c4bbdfSmrg } 250935c4bbdfSmrg access_mode |= DixForceAccess; 251035c4bbdfSmrg } 251135c4bbdfSmrg if (param->this_device_mode == GrabModeSync || 251235c4bbdfSmrg param->other_devices_mode == GrabModeSync) 251335c4bbdfSmrg access_mode |= DixFreezeAccess; 25144642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 25156747b715Smrg if (rc != Success) 251635c4bbdfSmrg return rc; 25176747b715Smrg rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 25184642e01fSmrg if (rc != Success) 251935c4bbdfSmrg return rc; 252005b261ecSmrg 252135c4bbdfSmrg if (grabtype == XI) 25226747b715Smrg type = DeviceButtonPress; 252335c4bbdfSmrg else if (grabtype == XI2) 25246747b715Smrg type = XI_ButtonPress; 25256747b715Smrg 25266747b715Smrg grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 25276747b715Smrg mask, param, type, button, confineTo, cursor); 252805b261ecSmrg if (!grab) 252935c4bbdfSmrg return BadAlloc; 25304642e01fSmrg return AddPassiveGrabToList(client, grab); 253105b261ecSmrg} 253205b261ecSmrg 25336747b715Smrg/** 253435c4bbdfSmrg * Grab the given key. 25356747b715Smrg */ 253605b261ecSmrgint 25376747b715SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 253835c4bbdfSmrg int key, GrabParameters *param, enum InputLevel grabtype, 253935c4bbdfSmrg GrabMask *mask) 254005b261ecSmrg{ 254105b261ecSmrg WindowPtr pWin; 254205b261ecSmrg GrabPtr grab; 254305b261ecSmrg KeyClassPtr k = dev->key; 25444642e01fSmrg Mask access_mode = DixGrabAccess; 25456747b715Smrg int rc, type = -1; 254605b261ecSmrg 25476747b715Smrg rc = CheckGrabValues(client, param); 25486747b715Smrg if (rc != Success) 25496747b715Smrg return rc; 2550475c125cSmrg if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL) 255135c4bbdfSmrg return BadMatch; 255235c4bbdfSmrg if (grabtype == XI) { 25536747b715Smrg if ((key > k->xkbInfo->desc->max_key_code || 255435c4bbdfSmrg key < k->xkbInfo->desc->min_key_code) 255535c4bbdfSmrg && (key != AnyKey)) { 25566747b715Smrg client->errorValue = key; 25576747b715Smrg return BadValue; 25586747b715Smrg } 25596747b715Smrg type = DeviceKeyPress; 256035c4bbdfSmrg } 256135c4bbdfSmrg else if (grabtype == XI2) 25626747b715Smrg type = XI_KeyPress; 25636747b715Smrg 25646747b715Smrg rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 25654642e01fSmrg if (rc != Success) 256635c4bbdfSmrg return rc; 256735c4bbdfSmrg if (param->this_device_mode == GrabModeSync || 256835c4bbdfSmrg param->other_devices_mode == GrabModeSync) 256935c4bbdfSmrg access_mode |= DixFreezeAccess; 25704642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 257105b261ecSmrg if (rc != Success) 257235c4bbdfSmrg return rc; 257305b261ecSmrg 25746747b715Smrg grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 25756747b715Smrg mask, param, type, key, NULL, NULL); 257605b261ecSmrg if (!grab) 257735c4bbdfSmrg return BadAlloc; 25784642e01fSmrg return AddPassiveGrabToList(client, grab); 257905b261ecSmrg} 258005b261ecSmrg 25816747b715Smrg/* Enter/FocusIn grab */ 25826747b715Smrgint 25836747b715SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type, 25846747b715Smrg GrabParameters *param, GrabMask *mask) 25856747b715Smrg{ 25866747b715Smrg WindowPtr pWin; 25876747b715Smrg CursorPtr cursor; 25886747b715Smrg GrabPtr grab; 25896747b715Smrg Mask access_mode = DixGrabAccess; 25906747b715Smrg int rc; 25916747b715Smrg 25926747b715Smrg rc = CheckGrabValues(client, param); 25936747b715Smrg if (rc != Success) 25946747b715Smrg return rc; 25956747b715Smrg 25966747b715Smrg rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 25976747b715Smrg if (rc != Success) 259835c4bbdfSmrg return rc; 25996747b715Smrg if (param->cursor == None) 260035c4bbdfSmrg cursor = NullCursor; 26016747b715Smrg else { 260235c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, param->cursor, 260335c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 260435c4bbdfSmrg if (rc != Success) { 260535c4bbdfSmrg client->errorValue = param->cursor; 260635c4bbdfSmrg return rc; 260735c4bbdfSmrg } 260835c4bbdfSmrg access_mode |= DixForceAccess; 260935c4bbdfSmrg } 261035c4bbdfSmrg if (param->this_device_mode == GrabModeSync || 261135c4bbdfSmrg param->other_devices_mode == GrabModeSync) 261235c4bbdfSmrg access_mode |= DixFreezeAccess; 26136747b715Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 26146747b715Smrg if (rc != Success) 261535c4bbdfSmrg return rc; 261635c4bbdfSmrg 261735c4bbdfSmrg grab = CreateGrab(client->index, dev, dev, pWin, XI2, 261835c4bbdfSmrg mask, param, 261935c4bbdfSmrg (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0, 262035c4bbdfSmrg NULL, cursor); 262135c4bbdfSmrg 262235c4bbdfSmrg if (!grab) 262335c4bbdfSmrg return BadAlloc; 262435c4bbdfSmrg 262535c4bbdfSmrg return AddPassiveGrabToList(client, grab); 262635c4bbdfSmrg} 262735c4bbdfSmrg 262835c4bbdfSmrg/* Touch grab */ 262935c4bbdfSmrgint 2630ed6184dfSmrgGrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev, 2631ed6184dfSmrg int type, GrabParameters *param, GrabMask *mask) 263235c4bbdfSmrg{ 263335c4bbdfSmrg WindowPtr pWin; 263435c4bbdfSmrg GrabPtr grab; 263535c4bbdfSmrg int rc; 263635c4bbdfSmrg 263735c4bbdfSmrg rc = CheckGrabValues(client, param); 263835c4bbdfSmrg if (rc != Success) 263935c4bbdfSmrg return rc; 26406747b715Smrg 264135c4bbdfSmrg rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 264235c4bbdfSmrg if (rc != Success) 264335c4bbdfSmrg return rc; 264435c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess); 264535c4bbdfSmrg if (rc != Success) 264635c4bbdfSmrg return rc; 26476747b715Smrg 264835c4bbdfSmrg grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2, 2649ed6184dfSmrg mask, param, type, 0, NullWindow, NullCursor); 26506747b715Smrg if (!grab) 26516747b715Smrg return BadAlloc; 26526747b715Smrg 26536747b715Smrg return AddPassiveGrabToList(client, grab); 26546747b715Smrg} 26556747b715Smrg 265605b261ecSmrgint 265705b261ecSmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, 265835c4bbdfSmrg Mask mask, Mask exclusivemasks) 265905b261ecSmrg{ 266005b261ecSmrg int mskidx = dev->id; 266105b261ecSmrg int i, ret; 266205b261ecSmrg Mask check; 266305b261ecSmrg InputClientsPtr others; 266405b261ecSmrg 266505b261ecSmrg check = (mask & exclusivemasks); 266605b261ecSmrg if (wOtherInputMasks(pWin)) { 266735c4bbdfSmrg if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { 266835c4bbdfSmrg /* It is illegal for two different clients to select on any of 266935c4bbdfSmrg * the events for maskcheck. However, it is OK, for some client 267035c4bbdfSmrg * to continue selecting on one of those events. 267135c4bbdfSmrg */ 267235c4bbdfSmrg for (others = wOtherInputMasks(pWin)->inputClients; others; 267335c4bbdfSmrg others = others->next) { 267435c4bbdfSmrg if (!SameClient(others, client) && (check & 267535c4bbdfSmrg others->mask[mskidx])) 267635c4bbdfSmrg return BadAccess; 267735c4bbdfSmrg } 267835c4bbdfSmrg } 267935c4bbdfSmrg for (others = wOtherInputMasks(pWin)->inputClients; others; 268035c4bbdfSmrg others = others->next) { 268135c4bbdfSmrg if (SameClient(others, client)) { 268235c4bbdfSmrg check = others->mask[mskidx]; 268335c4bbdfSmrg others->mask[mskidx] = mask; 268435c4bbdfSmrg if (mask == 0) { 268535c4bbdfSmrg for (i = 0; i < EMASKSIZE; i++) 268635c4bbdfSmrg if (i != mskidx && others->mask[i] != 0) 268735c4bbdfSmrg break; 268835c4bbdfSmrg if (i == EMASKSIZE) { 268935c4bbdfSmrg RecalculateDeviceDeliverableEvents(pWin); 269035c4bbdfSmrg if (ShouldFreeInputMasks(pWin, FALSE)) 269135c4bbdfSmrg FreeResource(others->resource, RT_NONE); 269235c4bbdfSmrg return Success; 269335c4bbdfSmrg } 269435c4bbdfSmrg } 269535c4bbdfSmrg goto maskSet; 269635c4bbdfSmrg } 269735c4bbdfSmrg } 269805b261ecSmrg } 269905b261ecSmrg check = 0; 270005b261ecSmrg if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success) 270135c4bbdfSmrg return ret; 270235c4bbdfSmrg maskSet: 270305b261ecSmrg if (dev->valuator) 270435c4bbdfSmrg if ((dev->valuator->motionHintWindow == pWin) && 270535c4bbdfSmrg (mask & DevicePointerMotionHintMask) && 270635c4bbdfSmrg !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab) 270735c4bbdfSmrg dev->valuator->motionHintWindow = NullWindow; 270805b261ecSmrg RecalculateDeviceDeliverableEvents(pWin); 270905b261ecSmrg return Success; 271005b261ecSmrg} 271105b261ecSmrg 271235c4bbdfSmrgstatic void 271335c4bbdfSmrgFreeInputClient(InputClientsPtr * other) 271435c4bbdfSmrg{ 271535c4bbdfSmrg xi2mask_free(&(*other)->xi2mask); 271635c4bbdfSmrg free(*other); 271735c4bbdfSmrg *other = NULL; 271835c4bbdfSmrg} 271935c4bbdfSmrg 272035c4bbdfSmrgstatic InputClientsPtr 272135c4bbdfSmrgAllocInputClient(void) 272235c4bbdfSmrg{ 272335c4bbdfSmrg return calloc(1, sizeof(InputClients)); 272435c4bbdfSmrg} 272535c4bbdfSmrg 272605b261ecSmrgint 272705b261ecSmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx) 272805b261ecSmrg{ 272905b261ecSmrg InputClientsPtr others; 273005b261ecSmrg 273105b261ecSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 273235c4bbdfSmrg return BadAlloc; 273335c4bbdfSmrg others = AllocInputClient(); 273405b261ecSmrg if (!others) 273535c4bbdfSmrg return BadAlloc; 273605b261ecSmrg if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) 273735c4bbdfSmrg goto bail; 273835c4bbdfSmrg others->xi2mask = xi2mask_new(); 273935c4bbdfSmrg if (!others->xi2mask) 274035c4bbdfSmrg goto bail; 274105b261ecSmrg others->mask[mskidx] = mask; 274205b261ecSmrg others->resource = FakeClientID(client->index); 274305b261ecSmrg others->next = pWin->optional->inputMasks->inputClients; 274405b261ecSmrg pWin->optional->inputMasks->inputClients = others; 274535c4bbdfSmrg if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin)) 274635c4bbdfSmrg goto bail; 274705b261ecSmrg return Success; 27489ace9065Smrg 274935c4bbdfSmrg bail: 275035c4bbdfSmrg FreeInputClient(&others); 27519ace9065Smrg return BadAlloc; 275205b261ecSmrg} 275305b261ecSmrg 275405b261ecSmrgstatic Bool 275505b261ecSmrgMakeInputMasks(WindowPtr pWin) 275605b261ecSmrg{ 275705b261ecSmrg struct _OtherInputMasks *imasks; 275805b261ecSmrg 27596747b715Smrg imasks = calloc(1, sizeof(struct _OtherInputMasks)); 276005b261ecSmrg if (!imasks) 276135c4bbdfSmrg return FALSE; 276235c4bbdfSmrg imasks->xi2mask = xi2mask_new(); 276335c4bbdfSmrg if (!imasks->xi2mask) { 276435c4bbdfSmrg free(imasks); 276535c4bbdfSmrg return FALSE; 276635c4bbdfSmrg } 276705b261ecSmrg pWin->optional->inputMasks = imasks; 276805b261ecSmrg return TRUE; 276905b261ecSmrg} 277005b261ecSmrg 277135c4bbdfSmrgstatic void 277235c4bbdfSmrgFreeInputMask(OtherInputMasks ** imask) 277335c4bbdfSmrg{ 277435c4bbdfSmrg xi2mask_free(&(*imask)->xi2mask); 277535c4bbdfSmrg free(*imask); 277635c4bbdfSmrg *imask = NULL; 277735c4bbdfSmrg} 277835c4bbdfSmrg 2779ed6184dfSmrg#define XIPropagateMask (KeyPressMask | \ 2780ed6184dfSmrg KeyReleaseMask | \ 2781ed6184dfSmrg ButtonPressMask | \ 2782ed6184dfSmrg ButtonReleaseMask | \ 2783ed6184dfSmrg PointerMotionMask) 2784ed6184dfSmrg 278505b261ecSmrgvoid 278605b261ecSmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin) 278705b261ecSmrg{ 278805b261ecSmrg InputClientsPtr others; 278935c4bbdfSmrg struct _OtherInputMasks *inputMasks; /* default: NULL */ 279005b261ecSmrg WindowPtr pChild, tmp; 279135c4bbdfSmrg int i; 279205b261ecSmrg 279305b261ecSmrg pChild = pWin; 279405b261ecSmrg while (1) { 279535c4bbdfSmrg if ((inputMasks = wOtherInputMasks(pChild)) != 0) { 279635c4bbdfSmrg xi2mask_zero(inputMasks->xi2mask, -1); 279735c4bbdfSmrg for (others = inputMasks->inputClients; others; 279835c4bbdfSmrg others = others->next) { 27996747b715Smrg for (i = 0; i < EMASKSIZE; i++) 280035c4bbdfSmrg inputMasks->inputEvents[i] |= others->mask[i]; 280135c4bbdfSmrg xi2mask_merge(inputMasks->xi2mask, others->xi2mask); 280235c4bbdfSmrg } 280335c4bbdfSmrg for (i = 0; i < EMASKSIZE; i++) 280435c4bbdfSmrg inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; 280535c4bbdfSmrg for (tmp = pChild->parent; tmp; tmp = tmp->parent) 280635c4bbdfSmrg if (wOtherInputMasks(tmp)) 280735c4bbdfSmrg for (i = 0; i < EMASKSIZE; i++) 280835c4bbdfSmrg inputMasks->deliverableEvents[i] |= 280935c4bbdfSmrg (wOtherInputMasks(tmp)->deliverableEvents[i] 281035c4bbdfSmrg & ~inputMasks->dontPropagateMask[i] & 2811ed6184dfSmrg XIPropagateMask); 281235c4bbdfSmrg } 281335c4bbdfSmrg if (pChild->firstChild) { 281435c4bbdfSmrg pChild = pChild->firstChild; 281535c4bbdfSmrg continue; 281635c4bbdfSmrg } 281735c4bbdfSmrg while (!pChild->nextSib && (pChild != pWin)) 281835c4bbdfSmrg pChild = pChild->parent; 281935c4bbdfSmrg if (pChild == pWin) 282035c4bbdfSmrg break; 282135c4bbdfSmrg pChild = pChild->nextSib; 282205b261ecSmrg } 282305b261ecSmrg} 282405b261ecSmrg 282505b261ecSmrgint 282605b261ecSmrgInputClientGone(WindowPtr pWin, XID id) 282705b261ecSmrg{ 282805b261ecSmrg InputClientsPtr other, prev; 282905b261ecSmrg 283005b261ecSmrg if (!wOtherInputMasks(pWin)) 283135c4bbdfSmrg return Success; 283205b261ecSmrg prev = 0; 283305b261ecSmrg for (other = wOtherInputMasks(pWin)->inputClients; other; 283435c4bbdfSmrg other = other->next) { 283535c4bbdfSmrg if (other->resource == id) { 283635c4bbdfSmrg if (prev) { 283735c4bbdfSmrg prev->next = other->next; 283835c4bbdfSmrg FreeInputClient(&other); 283935c4bbdfSmrg } 284035c4bbdfSmrg else if (!(other->next)) { 284135c4bbdfSmrg if (ShouldFreeInputMasks(pWin, TRUE)) { 284235c4bbdfSmrg OtherInputMasks *mask = wOtherInputMasks(pWin); 284335c4bbdfSmrg 284435c4bbdfSmrg mask->inputClients = other->next; 284535c4bbdfSmrg FreeInputMask(&mask); 284635c4bbdfSmrg pWin->optional->inputMasks = (OtherInputMasks *) NULL; 284735c4bbdfSmrg CheckWindowOptionalNeed(pWin); 284835c4bbdfSmrg FreeInputClient(&other); 284935c4bbdfSmrg } 285035c4bbdfSmrg else { 285135c4bbdfSmrg other->resource = FakeClientID(0); 285235c4bbdfSmrg if (!AddResource(other->resource, RT_INPUTCLIENT, 285335c4bbdfSmrg (void *) pWin)) 285435c4bbdfSmrg return BadAlloc; 285535c4bbdfSmrg } 285635c4bbdfSmrg } 285735c4bbdfSmrg else { 285835c4bbdfSmrg wOtherInputMasks(pWin)->inputClients = other->next; 285935c4bbdfSmrg FreeInputClient(&other); 286035c4bbdfSmrg } 286135c4bbdfSmrg RecalculateDeviceDeliverableEvents(pWin); 286235c4bbdfSmrg return Success; 286335c4bbdfSmrg } 286435c4bbdfSmrg prev = other; 286505b261ecSmrg } 286605b261ecSmrg FatalError("client not on device event list"); 286705b261ecSmrg} 286805b261ecSmrg 286935c4bbdfSmrg/** 287035c4bbdfSmrg * Search for window in each touch trace for each device. Remove the window 287135c4bbdfSmrg * and all its subwindows from the trace when found. The initial window 287235c4bbdfSmrg * order is preserved. 287335c4bbdfSmrg */ 287435c4bbdfSmrgvoid 287535c4bbdfSmrgWindowGone(WindowPtr win) 287635c4bbdfSmrg{ 287735c4bbdfSmrg DeviceIntPtr dev; 287835c4bbdfSmrg 287935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 288035c4bbdfSmrg TouchClassPtr t = dev->touch; 288135c4bbdfSmrg int i; 288235c4bbdfSmrg 288335c4bbdfSmrg if (!t) 288435c4bbdfSmrg continue; 288535c4bbdfSmrg 288635c4bbdfSmrg for (i = 0; i < t->num_touches; i++) { 288735c4bbdfSmrg SpritePtr sprite = &t->touches[i].sprite; 288835c4bbdfSmrg int j; 288935c4bbdfSmrg 289035c4bbdfSmrg for (j = 0; j < sprite->spriteTraceGood; j++) { 289135c4bbdfSmrg if (sprite->spriteTrace[j] == win) { 289235c4bbdfSmrg sprite->spriteTraceGood = j; 289335c4bbdfSmrg break; 289435c4bbdfSmrg } 289535c4bbdfSmrg } 289635c4bbdfSmrg } 289735c4bbdfSmrg } 289835c4bbdfSmrg} 289935c4bbdfSmrg 290005b261ecSmrgint 290105b261ecSmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, 290235c4bbdfSmrg xEvent *ev, Mask mask, int count) 290305b261ecSmrg{ 290405b261ecSmrg WindowPtr pWin; 290535c4bbdfSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 29064642e01fSmrg WindowPtr spriteWin = GetSpriteWindow(d); 290705b261ecSmrg 290805b261ecSmrg if (dest == PointerWindow) 290935c4bbdfSmrg pWin = spriteWin; 291005b261ecSmrg else if (dest == InputFocus) { 291135c4bbdfSmrg WindowPtr inputFocus; 291235c4bbdfSmrg 291335c4bbdfSmrg if (!d->focus) 291435c4bbdfSmrg inputFocus = spriteWin; 291535c4bbdfSmrg else 291635c4bbdfSmrg inputFocus = d->focus->win; 291735c4bbdfSmrg 291835c4bbdfSmrg if (inputFocus == FollowKeyboardWin) 291935c4bbdfSmrg inputFocus = inputInfo.keyboard->focus->win; 292035c4bbdfSmrg 292135c4bbdfSmrg if (inputFocus == NoneWin) 292235c4bbdfSmrg return Success; 292335c4bbdfSmrg 292435c4bbdfSmrg /* If the input focus is PointerRootWin, send the event to where 2925ed6184dfSmrg * the pointer is if possible, then perhaps propagate up to root. */ 292635c4bbdfSmrg if (inputFocus == PointerRootWin) 292735c4bbdfSmrg inputFocus = GetCurrentRootWindow(d); 292835c4bbdfSmrg 292935c4bbdfSmrg if (IsParent(inputFocus, spriteWin)) { 293035c4bbdfSmrg effectiveFocus = inputFocus; 293135c4bbdfSmrg pWin = spriteWin; 293235c4bbdfSmrg } 293335c4bbdfSmrg else 293435c4bbdfSmrg effectiveFocus = pWin = inputFocus; 293535c4bbdfSmrg } 293635c4bbdfSmrg else 293735c4bbdfSmrg dixLookupWindow(&pWin, dest, client, DixSendAccess); 293805b261ecSmrg if (!pWin) 293935c4bbdfSmrg return BadWindow; 294005b261ecSmrg if ((propagate != xFalse) && (propagate != xTrue)) { 294135c4bbdfSmrg client->errorValue = propagate; 294235c4bbdfSmrg return BadValue; 294305b261ecSmrg } 294405b261ecSmrg ev->u.u.type |= 0x80; 294505b261ecSmrg if (propagate) { 294635c4bbdfSmrg for (; pWin; pWin = pWin->parent) { 294735c4bbdfSmrg if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab)) 294835c4bbdfSmrg return Success; 294935c4bbdfSmrg if (pWin == effectiveFocus) 295035c4bbdfSmrg return Success; 295135c4bbdfSmrg if (wOtherInputMasks(pWin)) 295235c4bbdfSmrg mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id]; 295335c4bbdfSmrg if (!mask) 295435c4bbdfSmrg break; 295535c4bbdfSmrg } 295635c4bbdfSmrg } 295735c4bbdfSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count)) 295835c4bbdfSmrg DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab); 295905b261ecSmrg return Success; 296005b261ecSmrg} 296105b261ecSmrg 296205b261ecSmrgint 296305b261ecSmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) 296405b261ecSmrg{ 296505b261ecSmrg int i; 296605b261ecSmrg ButtonClassPtr b = dev->button; 296705b261ecSmrg 296805b261ecSmrg if (b == NULL) 296935c4bbdfSmrg return BadMatch; 297005b261ecSmrg 297105b261ecSmrg if (nElts != b->numButtons) { 297235c4bbdfSmrg client->errorValue = nElts; 297335c4bbdfSmrg return BadValue; 297405b261ecSmrg } 297505b261ecSmrg if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue)) 297635c4bbdfSmrg return BadValue; 297705b261ecSmrg for (i = 0; i < nElts; i++) 297835c4bbdfSmrg if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)) 297935c4bbdfSmrg return MappingBusy; 298005b261ecSmrg for (i = 0; i < nElts; i++) 298135c4bbdfSmrg b->map[i + 1] = map[i]; 298205b261ecSmrg return Success; 298305b261ecSmrg} 298405b261ecSmrg 298505b261ecSmrgint 298605b261ecSmrgChangeKeyMapping(ClientPtr client, 298735c4bbdfSmrg DeviceIntPtr dev, 298835c4bbdfSmrg unsigned len, 298935c4bbdfSmrg int type, 299035c4bbdfSmrg KeyCode firstKeyCode, 299135c4bbdfSmrg CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map) 299205b261ecSmrg{ 299305b261ecSmrg KeySymsRec keysyms; 299405b261ecSmrg KeyClassPtr k = dev->key; 299505b261ecSmrg 299605b261ecSmrg if (k == NULL) 299735c4bbdfSmrg return BadMatch; 299805b261ecSmrg 299905b261ecSmrg if (len != (keyCodes * keySymsPerKeyCode)) 300035c4bbdfSmrg return BadLength; 300105b261ecSmrg 30026747b715Smrg if ((firstKeyCode < k->xkbInfo->desc->min_key_code) || 300335c4bbdfSmrg (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) { 300435c4bbdfSmrg client->errorValue = firstKeyCode; 300535c4bbdfSmrg return BadValue; 300605b261ecSmrg } 300705b261ecSmrg if (keySymsPerKeyCode == 0) { 300835c4bbdfSmrg client->errorValue = 0; 300935c4bbdfSmrg return BadValue; 301005b261ecSmrg } 301105b261ecSmrg keysyms.minKeyCode = firstKeyCode; 301205b261ecSmrg keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; 301305b261ecSmrg keysyms.mapWidth = keySymsPerKeyCode; 301405b261ecSmrg keysyms.map = map; 30156747b715Smrg 30166747b715Smrg XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL, 30176747b715Smrg serverClient); 30186747b715Smrg 30196747b715Smrg return Success; 302005b261ecSmrg} 302105b261ecSmrg 302205b261ecSmrgstatic void 302305b261ecSmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) 302405b261ecSmrg{ 302505b261ecSmrg WindowPtr parent; 302605b261ecSmrg 302705b261ecSmrg /* Deactivate any grabs performed on this window, before making 302805b261ecSmrg * any input focus changes. 302905b261ecSmrg * Deactivating a device grab should cause focus events. */ 303005b261ecSmrg 30314642e01fSmrg if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin)) 303235c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 303305b261ecSmrg 30344642e01fSmrg /* If the focus window is a root window (ie. has no parent) 303505b261ecSmrg * then don't delete the focus from it. */ 303605b261ecSmrg 303705b261ecSmrg if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) { 303835c4bbdfSmrg int focusEventMode = NotifyNormal; 303935c4bbdfSmrg 304035c4bbdfSmrg /* If a grab is in progress, then alter the mode of focus events. */ 304135c4bbdfSmrg 304235c4bbdfSmrg if (dev->deviceGrab.grab) 304335c4bbdfSmrg focusEventMode = NotifyWhileGrabbed; 304435c4bbdfSmrg 304535c4bbdfSmrg switch (dev->focus->revert) { 304635c4bbdfSmrg case RevertToNone: 304735c4bbdfSmrg if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 304835c4bbdfSmrg DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 304935c4bbdfSmrg dev->focus->win = NoneWin; 305035c4bbdfSmrg dev->focus->traceGood = 0; 305135c4bbdfSmrg break; 305235c4bbdfSmrg case RevertToParent: 305335c4bbdfSmrg parent = pWin; 305435c4bbdfSmrg do { 305535c4bbdfSmrg parent = parent->parent; 305635c4bbdfSmrg dev->focus->traceGood--; 305735c4bbdfSmrg } 305835c4bbdfSmrg while (!parent->realized); 305935c4bbdfSmrg if (!ActivateFocusInGrab(dev, pWin, parent)) 306035c4bbdfSmrg DoFocusEvents(dev, pWin, parent, focusEventMode); 306135c4bbdfSmrg dev->focus->win = parent; 306235c4bbdfSmrg dev->focus->revert = RevertToNone; 306335c4bbdfSmrg break; 306435c4bbdfSmrg case RevertToPointerRoot: 306535c4bbdfSmrg if (!ActivateFocusInGrab(dev, pWin, PointerRootWin)) 306635c4bbdfSmrg DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); 306735c4bbdfSmrg dev->focus->win = PointerRootWin; 306835c4bbdfSmrg dev->focus->traceGood = 0; 306935c4bbdfSmrg break; 307035c4bbdfSmrg case RevertToFollowKeyboard: 307135c4bbdfSmrg { 307235c4bbdfSmrg DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD); 307335c4bbdfSmrg 307435c4bbdfSmrg if (!kbd || (kbd == dev && kbd != inputInfo.keyboard)) 307535c4bbdfSmrg kbd = inputInfo.keyboard; 307635c4bbdfSmrg if (kbd->focus->win) { 307735c4bbdfSmrg if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win)) 307835c4bbdfSmrg DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode); 307935c4bbdfSmrg dev->focus->win = FollowKeyboardWin; 308035c4bbdfSmrg dev->focus->traceGood = 0; 308135c4bbdfSmrg } 308235c4bbdfSmrg else { 30836747b715Smrg if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 30846747b715Smrg DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 308535c4bbdfSmrg dev->focus->win = NoneWin; 308635c4bbdfSmrg dev->focus->traceGood = 0; 30876747b715Smrg } 308835c4bbdfSmrg } 308935c4bbdfSmrg break; 309035c4bbdfSmrg } 309105b261ecSmrg } 309205b261ecSmrg 309305b261ecSmrg if (dev->valuator) 309435c4bbdfSmrg if (dev->valuator->motionHintWindow == pWin) 309535c4bbdfSmrg dev->valuator->motionHintWindow = NullWindow; 309605b261ecSmrg} 309705b261ecSmrg 309805b261ecSmrgvoid 309905b261ecSmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources) 310005b261ecSmrg{ 310105b261ecSmrg int i; 310205b261ecSmrg DeviceIntPtr dev; 310305b261ecSmrg InputClientsPtr ic; 310405b261ecSmrg struct _OtherInputMasks *inputMasks; 310505b261ecSmrg 310605b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 310735c4bbdfSmrg DeleteDeviceFromAnyExtEvents(pWin, dev); 310805b261ecSmrg } 310905b261ecSmrg 311005b261ecSmrg for (dev = inputInfo.off_devices; dev; dev = dev->next) 311135c4bbdfSmrg DeleteDeviceFromAnyExtEvents(pWin, dev); 311205b261ecSmrg 311305b261ecSmrg if (freeResources) 311435c4bbdfSmrg while ((inputMasks = wOtherInputMasks(pWin)) != 0) { 311535c4bbdfSmrg ic = inputMasks->inputClients; 311635c4bbdfSmrg for (i = 0; i < EMASKSIZE; i++) 311735c4bbdfSmrg inputMasks->dontPropagateMask[i] = 0; 311835c4bbdfSmrg FreeResource(ic->resource, RT_NONE); 311935c4bbdfSmrg } 312005b261ecSmrg} 312105b261ecSmrg 312205b261ecSmrgint 312335c4bbdfSmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask) 312405b261ecSmrg{ 312505b261ecSmrg DeviceIntPtr dev; 312605b261ecSmrg 31274642e01fSmrg dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient, 312835c4bbdfSmrg DixReadAccess); 312905b261ecSmrg if (!dev) 313005b261ecSmrg return 0; 313105b261ecSmrg 313205b261ecSmrg if (pEvents->type == DeviceMotionNotify) { 313335c4bbdfSmrg if (mask & DevicePointerMotionHintMask) { 313435c4bbdfSmrg if (WID(dev->valuator->motionHintWindow) == pEvents->event) { 313535c4bbdfSmrg return 1; /* don't send, but pretend we did */ 313635c4bbdfSmrg } 313735c4bbdfSmrg pEvents->detail = NotifyHint; 313835c4bbdfSmrg } 313935c4bbdfSmrg else { 314035c4bbdfSmrg pEvents->detail = NotifyNormal; 314135c4bbdfSmrg } 314205b261ecSmrg } 31436747b715Smrg return 0; 314405b261ecSmrg} 314505b261ecSmrg 314605b261ecSmrgvoid 314705b261ecSmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, 314835c4bbdfSmrg deviceKeyButtonPointer *xE, GrabPtr grab, 314935c4bbdfSmrg ClientPtr client, Mask deliveryMask) 315005b261ecSmrg{ 315105b261ecSmrg DeviceIntPtr dev; 315205b261ecSmrg 31534642e01fSmrg dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient, 315435c4bbdfSmrg DixGrabAccess); 315505b261ecSmrg if (!dev) 315605b261ecSmrg return; 315705b261ecSmrg 315805b261ecSmrg if (type == DeviceMotionNotify) 315935c4bbdfSmrg dev->valuator->motionHintWindow = pWin; 316005b261ecSmrg else if ((type == DeviceButtonPress) && (!grab) && 316135c4bbdfSmrg (deliveryMask & DeviceButtonGrabMask)) { 316235c4bbdfSmrg GrabPtr tempGrab; 316305b261ecSmrg 316435c4bbdfSmrg tempGrab = AllocGrab(NULL); 316535c4bbdfSmrg if (!tempGrab) 316635c4bbdfSmrg return; 316735c4bbdfSmrg 316835c4bbdfSmrg tempGrab->device = dev; 316935c4bbdfSmrg tempGrab->resource = client->clientAsMask; 317035c4bbdfSmrg tempGrab->window = pWin; 317135c4bbdfSmrg tempGrab->ownerEvents = 317235c4bbdfSmrg (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; 317335c4bbdfSmrg tempGrab->eventMask = deliveryMask; 317435c4bbdfSmrg tempGrab->keyboardMode = GrabModeAsync; 317535c4bbdfSmrg tempGrab->pointerMode = GrabModeAsync; 317635c4bbdfSmrg tempGrab->confineTo = NullWindow; 317735c4bbdfSmrg tempGrab->cursor = NullCursor; 317835c4bbdfSmrg tempGrab->next = NULL; 317935c4bbdfSmrg (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE); 318035c4bbdfSmrg FreeGrab(tempGrab); 318105b261ecSmrg } 318205b261ecSmrg} 318305b261ecSmrg 318405b261ecSmrgstatic Mask 318505b261ecSmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client) 318605b261ecSmrg{ 318705b261ecSmrg InputClientsPtr other; 318805b261ecSmrg 318905b261ecSmrg if (!wOtherInputMasks(pWin)) 319035c4bbdfSmrg return 0; 319105b261ecSmrg for (other = wOtherInputMasks(pWin)->inputClients; other; 319235c4bbdfSmrg other = other->next) { 319335c4bbdfSmrg if (SameClient(other, client)) 319435c4bbdfSmrg return other->mask[dev->id]; 319505b261ecSmrg } 319605b261ecSmrg return 0; 319705b261ecSmrg} 319805b261ecSmrg 319905b261ecSmrgvoid 320005b261ecSmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client) 320105b261ecSmrg{ 320205b261ecSmrg WindowPtr pWin; 32034642e01fSmrg GrabPtr grab = dev->deviceGrab.grab; 320405b261ecSmrg 320505b261ecSmrg pWin = dev->valuator->motionHintWindow; 320605b261ecSmrg 320705b261ecSmrg if ((grab && SameClient(grab, client) && 320835c4bbdfSmrg ((grab->eventMask & DevicePointerMotionHintMask) || 320935c4bbdfSmrg (grab->ownerEvents && 321035c4bbdfSmrg (DeviceEventMaskForClient(dev, pWin, client) & 321135c4bbdfSmrg DevicePointerMotionHintMask)))) || 321235c4bbdfSmrg (!grab && 321335c4bbdfSmrg (DeviceEventMaskForClient(dev, pWin, client) & 321435c4bbdfSmrg DevicePointerMotionHintMask))) 321535c4bbdfSmrg dev->valuator->motionHintWindow = NullWindow; 321605b261ecSmrg} 321705b261ecSmrg 321805b261ecSmrgint 321905b261ecSmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, 322035c4bbdfSmrg int maskndx) 322105b261ecSmrg{ 322205b261ecSmrg struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 322305b261ecSmrg 3224ed6184dfSmrg if (mask & ~XIPropagateMask) { 322535c4bbdfSmrg client->errorValue = mask; 322635c4bbdfSmrg return BadValue; 322705b261ecSmrg } 322805b261ecSmrg 322905b261ecSmrg if (mask == 0) { 323035c4bbdfSmrg if (inputMasks) 323135c4bbdfSmrg inputMasks->dontPropagateMask[maskndx] = mask; 323235c4bbdfSmrg } 323335c4bbdfSmrg else { 323435c4bbdfSmrg if (!inputMasks) 323535c4bbdfSmrg AddExtensionClient(pWin, client, 0, 0); 323635c4bbdfSmrg inputMasks = wOtherInputMasks(pWin); 323735c4bbdfSmrg inputMasks->dontPropagateMask[maskndx] = mask; 323805b261ecSmrg } 323905b261ecSmrg RecalculateDeviceDeliverableEvents(pWin); 324005b261ecSmrg if (ShouldFreeInputMasks(pWin, FALSE)) 324135c4bbdfSmrg FreeResource(inputMasks->inputClients->resource, RT_NONE); 324205b261ecSmrg return Success; 324305b261ecSmrg} 324405b261ecSmrg 32454642e01fSmrgBool 324605b261ecSmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents) 324705b261ecSmrg{ 324805b261ecSmrg int i; 324905b261ecSmrg Mask allInputEventMasks = 0; 325005b261ecSmrg struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 325105b261ecSmrg 325205b261ecSmrg for (i = 0; i < EMASKSIZE; i++) 325335c4bbdfSmrg allInputEventMasks |= inputMasks->dontPropagateMask[i]; 325405b261ecSmrg if (!ignoreSelectedEvents) 325535c4bbdfSmrg for (i = 0; i < EMASKSIZE; i++) 325635c4bbdfSmrg allInputEventMasks |= inputMasks->inputEvents[i]; 325705b261ecSmrg if (allInputEventMasks == 0) 325835c4bbdfSmrg return TRUE; 325905b261ecSmrg else 326035c4bbdfSmrg return FALSE; 326105b261ecSmrg} 326205b261ecSmrg 326305b261ecSmrg/*********************************************************************** 326405b261ecSmrg * 326505b261ecSmrg * Walk through the window tree, finding all clients that want to know 326605b261ecSmrg * about the Event. 326705b261ecSmrg * 326805b261ecSmrg */ 326905b261ecSmrg 327005b261ecSmrgstatic void 327105b261ecSmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, 327235c4bbdfSmrg xEvent *ev, int count) 327305b261ecSmrg{ 327405b261ecSmrg WindowPtr p2; 327505b261ecSmrg 327605b261ecSmrg while (p1) { 327705b261ecSmrg p2 = p1->firstChild; 32786747b715Smrg DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab); 327905b261ecSmrg FindInterestedChildren(dev, p2, mask, ev, count); 328005b261ecSmrg p1 = p1->nextSib; 328105b261ecSmrg } 328205b261ecSmrg} 328305b261ecSmrg 328405b261ecSmrg/*********************************************************************** 328505b261ecSmrg * 328605b261ecSmrg * Send an event to interested clients in all windows on all screens. 328705b261ecSmrg * 328805b261ecSmrg */ 328905b261ecSmrg 329005b261ecSmrgvoid 329135c4bbdfSmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count) 329205b261ecSmrg{ 329305b261ecSmrg int i; 329405b261ecSmrg WindowPtr pWin, p1; 329505b261ecSmrg 329605b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) { 32976747b715Smrg pWin = screenInfo.screens[i]->root; 32984642e01fSmrg if (!pWin) 32994642e01fSmrg continue; 33006747b715Smrg DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab); 330105b261ecSmrg p1 = pWin->firstChild; 330205b261ecSmrg FindInterestedChildren(dev, p1, mask, ev, count); 330305b261ecSmrg } 330405b261ecSmrg} 33054642e01fSmrg 33066747b715Smrg/** 33076747b715Smrg * Set the XI2 mask for the given client on the given window. 33086747b715Smrg * @param dev The device to set the mask for. 33096747b715Smrg * @param win The window to set the mask on. 33106747b715Smrg * @param client The client setting the mask. 33116747b715Smrg * @param len Number of bytes in mask. 33126747b715Smrg * @param mask Event mask in the form of (1 << eventtype) 33136747b715Smrg */ 33146747b715Smrgint 33156747b715SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 331635c4bbdfSmrg unsigned int len, unsigned char *mask) 33176747b715Smrg{ 33186747b715Smrg OtherInputMasks *masks; 33196747b715Smrg InputClientsPtr others = NULL; 33206747b715Smrg 33216747b715Smrg masks = wOtherInputMasks(win); 332235c4bbdfSmrg if (masks) { 332335c4bbdfSmrg for (others = wOtherInputMasks(win)->inputClients; others; 332435c4bbdfSmrg others = others->next) { 332535c4bbdfSmrg if (SameClient(others, client)) { 332635c4bbdfSmrg xi2mask_zero(others->xi2mask, dev->id); 33276747b715Smrg break; 33286747b715Smrg } 33296747b715Smrg } 33306747b715Smrg } 33316747b715Smrg 333235c4bbdfSmrg if (len && !others) { 33336747b715Smrg if (AddExtensionClient(win, client, 0, 0) != Success) 33346747b715Smrg return BadAlloc; 333535c4bbdfSmrg others = wOtherInputMasks(win)->inputClients; 33366747b715Smrg } 33376747b715Smrg 333835c4bbdfSmrg if (others) { 333935c4bbdfSmrg xi2mask_zero(others->xi2mask, dev->id); 334035c4bbdfSmrg len = min(len, xi2mask_mask_size(others->xi2mask)); 334135c4bbdfSmrg } 33426747b715Smrg 334335c4bbdfSmrg if (len) { 334435c4bbdfSmrg xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len); 334535c4bbdfSmrg } 33466747b715Smrg 33476747b715Smrg RecalculateDeviceDeliverableEvents(win); 33486747b715Smrg 33496747b715Smrg return Success; 33506747b715Smrg} 3351