exevents.c revision f5d46ea4
1706f2543Smrg/************************************************************ 2706f2543Smrg 3706f2543SmrgCopyright 1989, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included in 12706f2543Smrgall copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20706f2543Smrg 21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 23706f2543Smrgin this Software without prior written authorization from The Open Group. 24706f2543Smrg 25706f2543SmrgCopyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26706f2543Smrg 27706f2543Smrg All Rights Reserved 28706f2543Smrg 29706f2543SmrgPermission to use, copy, modify, and distribute this software and its 30706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 31706f2543Smrgprovided that the above copyright notice appear in all copies and that 32706f2543Smrgboth that copyright notice and this permission notice appear in 33706f2543Smrgsupporting documentation, and that the name of Hewlett-Packard not be 34706f2543Smrgused in advertising or publicity pertaining to distribution of the 35706f2543Smrgsoftware without specific, written prior permission. 36706f2543Smrg 37706f2543SmrgHEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39706f2543SmrgHEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43706f2543SmrgSOFTWARE. 44706f2543Smrg 45706f2543Smrg********************************************************/ 46706f2543Smrg 47706f2543Smrg/******************************************************************** 48706f2543Smrg * 49706f2543Smrg * Routines to register and initialize extension input devices. 50706f2543Smrg * This also contains ProcessOtherEvent, the routine called from DDX 51706f2543Smrg * to route extension events. 52706f2543Smrg * 53706f2543Smrg */ 54706f2543Smrg 55706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 56706f2543Smrg#include <dix-config.h> 57706f2543Smrg#endif 58706f2543Smrg 59706f2543Smrg#include "inputstr.h" 60706f2543Smrg#include <X11/X.h> 61706f2543Smrg#include <X11/Xproto.h> 62706f2543Smrg#include <X11/extensions/XI.h> 63706f2543Smrg#include <X11/extensions/XIproto.h> 64706f2543Smrg#include <X11/extensions/XI2proto.h> 65706f2543Smrg#include <X11/extensions/geproto.h> 66706f2543Smrg#include "windowstr.h" 67706f2543Smrg#include "miscstruct.h" 68706f2543Smrg#include "region.h" 69706f2543Smrg#include "exevents.h" 70706f2543Smrg#include "extnsionst.h" 71706f2543Smrg#include "exglobals.h" 72706f2543Smrg#include "dixevents.h" /* DeliverFocusedEvent */ 73706f2543Smrg#include "dixgrabs.h" /* CreateGrab() */ 74706f2543Smrg#include "scrnintstr.h" 75706f2543Smrg#include "listdev.h" /* for CopySwapXXXClass */ 76706f2543Smrg#include "xace.h" 77706f2543Smrg#include "xiquerydevice.h" /* For List*Info */ 78706f2543Smrg#include "eventconvert.h" 79706f2543Smrg#include "eventstr.h" 80706f2543Smrg 81706f2543Smrg#include <X11/extensions/XKBproto.h> 82706f2543Smrg#include "xkbsrv.h" 83706f2543Smrg 84706f2543Smrg#define WID(w) ((w) ? ((w)->drawable.id) : 0) 85706f2543Smrg#define AllModifiersMask ( \ 86706f2543Smrg ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 87706f2543Smrg Mod3Mask | Mod4Mask | Mod5Mask ) 88706f2543Smrg#define AllButtonsMask ( \ 89706f2543Smrg Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 90706f2543Smrg 91706f2543SmrgBool ShouldFreeInputMasks(WindowPtr /* pWin */ , 92706f2543Smrg Bool /* ignoreSelectedEvents */ 93706f2543Smrg ); 94706f2543Smrgstatic Bool MakeInputMasks(WindowPtr /* pWin */ 95706f2543Smrg ); 96706f2543Smrg 97706f2543Smrg/* 98706f2543Smrg * Only let the given client know of core events which will affect its 99706f2543Smrg * interpretation of input events, if the client's ClientPointer (or the 100706f2543Smrg * paired keyboard) is the current device. 101706f2543Smrg */ 102706f2543Smrgint 103706f2543SmrgXIShouldNotify(ClientPtr client, DeviceIntPtr dev) 104706f2543Smrg{ 105706f2543Smrg DeviceIntPtr current_ptr = PickPointer(client); 106706f2543Smrg DeviceIntPtr current_kbd = GetPairedDevice(current_ptr); 107706f2543Smrg 108706f2543Smrg if (dev == current_kbd || dev == current_ptr) 109706f2543Smrg return 1; 110706f2543Smrg 111706f2543Smrg return 0; 112706f2543Smrg} 113706f2543Smrg 114706f2543SmrgBool 115706f2543SmrgIsPointerEvent(InternalEvent* event) 116706f2543Smrg{ 117706f2543Smrg switch(event->any.type) 118706f2543Smrg { 119706f2543Smrg case ET_ButtonPress: 120706f2543Smrg case ET_ButtonRelease: 121706f2543Smrg case ET_Motion: 122706f2543Smrg /* XXX: enter/leave ?? */ 123706f2543Smrg return TRUE; 124706f2543Smrg default: 125706f2543Smrg break; 126706f2543Smrg } 127706f2543Smrg return FALSE; 128706f2543Smrg} 129706f2543Smrg 130706f2543Smrg/** 131706f2543Smrg * @return the device matching the deviceid of the device set in the event, or 132706f2543Smrg * NULL if the event is not an XInput event. 133706f2543Smrg */ 134706f2543SmrgDeviceIntPtr 135706f2543SmrgXIGetDevice(xEvent* xE) 136706f2543Smrg{ 137706f2543Smrg DeviceIntPtr pDev = NULL; 138706f2543Smrg 139706f2543Smrg if (xE->u.u.type == DeviceButtonPress || 140706f2543Smrg xE->u.u.type == DeviceButtonRelease || 141706f2543Smrg xE->u.u.type == DeviceMotionNotify || 142706f2543Smrg xE->u.u.type == ProximityIn || 143706f2543Smrg xE->u.u.type == ProximityOut || 144706f2543Smrg xE->u.u.type == DevicePropertyNotify) 145706f2543Smrg { 146706f2543Smrg int rc; 147706f2543Smrg int id; 148706f2543Smrg 149706f2543Smrg id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS; 150706f2543Smrg 151706f2543Smrg rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess); 152706f2543Smrg if (rc != Success) 153706f2543Smrg ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc); 154706f2543Smrg } 155706f2543Smrg return pDev; 156706f2543Smrg} 157706f2543Smrg 158706f2543Smrg 159706f2543Smrg/** 160706f2543Smrg * Copy the device->key into master->key and send a mapping notify to the 161706f2543Smrg * clients if appropriate. 162706f2543Smrg * master->key needs to be allocated by the caller. 163706f2543Smrg * 164706f2543Smrg * Device is the slave device. If it is attached to a master device, we may 165706f2543Smrg * need to send a mapping notify to the client because it causes the MD 166706f2543Smrg * to change state. 167706f2543Smrg * 168706f2543Smrg * Mapping notify needs to be sent in the following cases: 169706f2543Smrg * - different slave device on same master 170706f2543Smrg * - different master 171706f2543Smrg * 172706f2543Smrg * XXX: They way how the code is we also send a map notify if the slave device 173706f2543Smrg * stays the same, but the master changes. This isn't really necessary though. 174706f2543Smrg * 175706f2543Smrg * XXX: this gives you funny behaviour with the ClientPointer. When a 176706f2543Smrg * MappingNotify is sent to the client, the client usually responds with a 177706f2543Smrg * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard 178706f2543Smrg * mapping, regardless of which keyboard sent the last mapping notify request. 179706f2543Smrg * So depending on the CP setting, your keyboard may change layout in each 180706f2543Smrg * app... 181706f2543Smrg * 182706f2543Smrg * This code is basically the old SwitchCoreKeyboard. 183706f2543Smrg */ 184706f2543Smrg 185706f2543Smrgvoid 186706f2543SmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) 187706f2543Smrg{ 188706f2543Smrg KeyClassPtr mk = master->key; 189706f2543Smrg 190706f2543Smrg if (device == master) 191706f2543Smrg return; 192706f2543Smrg 193706f2543Smrg mk->sourceid = device->id; 194706f2543Smrg 195706f2543Smrg 196706f2543Smrg if (!XkbCopyDeviceKeymap(master, device)) 197706f2543Smrg FatalError("Couldn't pivot keymap from device to core!\n"); 198706f2543Smrg} 199706f2543Smrg 200706f2543Smrg/** 201706f2543Smrg * Copies the feedback classes from device "from" into device "to". Classes 202706f2543Smrg * are duplicated (not just flipping the pointers). All feedback classes are 203706f2543Smrg * linked lists, the full list is duplicated. 204706f2543Smrg */ 205706f2543Smrgstatic void 206706f2543SmrgDeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) 207706f2543Smrg{ 208706f2543Smrg ClassesPtr classes; 209706f2543Smrg 210706f2543Smrg 211706f2543Smrg if (from->intfeed) 212706f2543Smrg { 213706f2543Smrg IntegerFeedbackPtr *i, it; 214706f2543Smrg 215706f2543Smrg if (!to->intfeed) 216706f2543Smrg { 217706f2543Smrg classes = to->unused_classes; 218706f2543Smrg to->intfeed = classes->intfeed; 219706f2543Smrg classes->intfeed = NULL; 220706f2543Smrg } 221706f2543Smrg 222706f2543Smrg i = &to->intfeed; 223706f2543Smrg for (it = from->intfeed; it; it = it->next) 224706f2543Smrg { 225706f2543Smrg if (!(*i)) 226706f2543Smrg { 227706f2543Smrg *i = calloc(1, sizeof(IntegerFeedbackClassRec)); 228706f2543Smrg if (!(*i)) 229706f2543Smrg { 230706f2543Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 231706f2543Smrg return; 232706f2543Smrg } 233706f2543Smrg } 234706f2543Smrg (*i)->CtrlProc = it->CtrlProc; 235706f2543Smrg (*i)->ctrl = it->ctrl; 236706f2543Smrg 237706f2543Smrg i = &(*i)->next; 238706f2543Smrg } 239706f2543Smrg } else if (to->intfeed && !from->intfeed) 240706f2543Smrg { 241706f2543Smrg ClassesPtr classes; 242706f2543Smrg classes = to->unused_classes; 243706f2543Smrg classes->intfeed = to->intfeed; 244706f2543Smrg to->intfeed = NULL; 245706f2543Smrg } 246706f2543Smrg 247706f2543Smrg if (from->stringfeed) 248706f2543Smrg { 249706f2543Smrg StringFeedbackPtr *s, it; 250706f2543Smrg 251706f2543Smrg if (!to->stringfeed) 252706f2543Smrg { 253706f2543Smrg classes = to->unused_classes; 254706f2543Smrg to->stringfeed = classes->stringfeed; 255706f2543Smrg classes->stringfeed = NULL; 256706f2543Smrg } 257706f2543Smrg 258706f2543Smrg s = &to->stringfeed; 259706f2543Smrg for (it = from->stringfeed; it; it = it->next) 260706f2543Smrg { 261706f2543Smrg if (!(*s)) 262706f2543Smrg { 263706f2543Smrg *s = calloc(1, sizeof(StringFeedbackClassRec)); 264706f2543Smrg if (!(*s)) 265706f2543Smrg { 266706f2543Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 267706f2543Smrg return; 268706f2543Smrg } 269706f2543Smrg } 270706f2543Smrg (*s)->CtrlProc = it->CtrlProc; 271706f2543Smrg (*s)->ctrl = it->ctrl; 272706f2543Smrg 273706f2543Smrg s = &(*s)->next; 274706f2543Smrg } 275706f2543Smrg } else if (to->stringfeed && !from->stringfeed) 276706f2543Smrg { 277706f2543Smrg ClassesPtr classes; 278706f2543Smrg classes = to->unused_classes; 279706f2543Smrg classes->stringfeed = to->stringfeed; 280706f2543Smrg to->stringfeed = NULL; 281706f2543Smrg } 282706f2543Smrg 283706f2543Smrg if (from->bell) 284706f2543Smrg { 285706f2543Smrg BellFeedbackPtr *b, it; 286706f2543Smrg 287706f2543Smrg if (!to->bell) 288706f2543Smrg { 289706f2543Smrg classes = to->unused_classes; 290706f2543Smrg to->bell = classes->bell; 291706f2543Smrg classes->bell = NULL; 292706f2543Smrg } 293706f2543Smrg 294706f2543Smrg b = &to->bell; 295706f2543Smrg for (it = from->bell; it; it = it->next) 296706f2543Smrg { 297706f2543Smrg if (!(*b)) 298706f2543Smrg { 299706f2543Smrg *b = calloc(1, sizeof(BellFeedbackClassRec)); 300706f2543Smrg if (!(*b)) 301706f2543Smrg { 302706f2543Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 303706f2543Smrg return; 304706f2543Smrg } 305706f2543Smrg } 306706f2543Smrg (*b)->BellProc = it->BellProc; 307706f2543Smrg (*b)->CtrlProc = it->CtrlProc; 308706f2543Smrg (*b)->ctrl = it->ctrl; 309706f2543Smrg 310706f2543Smrg b = &(*b)->next; 311706f2543Smrg } 312706f2543Smrg } else if (to->bell && !from->bell) 313706f2543Smrg { 314706f2543Smrg ClassesPtr classes; 315706f2543Smrg classes = to->unused_classes; 316706f2543Smrg classes->bell = to->bell; 317706f2543Smrg to->bell = NULL; 318706f2543Smrg } 319706f2543Smrg 320706f2543Smrg if (from->leds) 321706f2543Smrg { 322706f2543Smrg LedFeedbackPtr *l, it; 323706f2543Smrg 324706f2543Smrg if (!to->leds) 325706f2543Smrg { 326706f2543Smrg classes = to->unused_classes; 327706f2543Smrg to->leds = classes->leds; 328706f2543Smrg classes->leds = NULL; 329706f2543Smrg } 330706f2543Smrg 331706f2543Smrg l = &to->leds; 332706f2543Smrg for (it = from->leds; it; it = it->next) 333706f2543Smrg { 334706f2543Smrg if (!(*l)) 335706f2543Smrg { 336706f2543Smrg *l = calloc(1, sizeof(LedFeedbackClassRec)); 337706f2543Smrg if (!(*l)) 338706f2543Smrg { 339706f2543Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 340706f2543Smrg return; 341706f2543Smrg } 342706f2543Smrg } 343706f2543Smrg (*l)->CtrlProc = it->CtrlProc; 344706f2543Smrg (*l)->ctrl = it->ctrl; 345706f2543Smrg if ((*l)->xkb_sli) 346706f2543Smrg XkbFreeSrvLedInfo((*l)->xkb_sli); 347706f2543Smrg (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l); 348706f2543Smrg 349706f2543Smrg l = &(*l)->next; 350706f2543Smrg } 351706f2543Smrg } else if (to->leds && !from->leds) 352706f2543Smrg { 353706f2543Smrg ClassesPtr classes; 354706f2543Smrg classes = to->unused_classes; 355706f2543Smrg classes->leds = to->leds; 356706f2543Smrg to->leds = NULL; 357706f2543Smrg } 358706f2543Smrg} 359706f2543Smrg 360706f2543Smrgstatic void 361706f2543SmrgDeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to) 362706f2543Smrg{ 363706f2543Smrg ClassesPtr classes; 364706f2543Smrg 365706f2543Smrg /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the 366706f2543Smrg * kbdfeed to be set up properly, so let's do the feedback classes first. 367706f2543Smrg */ 368706f2543Smrg if (from->kbdfeed) 369706f2543Smrg { 370706f2543Smrg KbdFeedbackPtr *k, it; 371706f2543Smrg 372706f2543Smrg if (!to->kbdfeed) 373706f2543Smrg { 374706f2543Smrg classes = to->unused_classes; 375706f2543Smrg 376706f2543Smrg to->kbdfeed = classes->kbdfeed; 377706f2543Smrg if (!to->kbdfeed) 378706f2543Smrg InitKeyboardDeviceStruct(to, NULL, NULL, NULL); 379706f2543Smrg classes->kbdfeed = NULL; 380706f2543Smrg } 381706f2543Smrg 382706f2543Smrg k = &to->kbdfeed; 383706f2543Smrg for(it = from->kbdfeed; it; it = it->next) 384706f2543Smrg { 385706f2543Smrg if (!(*k)) 386706f2543Smrg { 387706f2543Smrg *k = calloc(1, sizeof(KbdFeedbackClassRec)); 388706f2543Smrg if (!*k) 389706f2543Smrg { 390706f2543Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 391706f2543Smrg return; 392706f2543Smrg } 393706f2543Smrg } 394706f2543Smrg (*k)->BellProc = it->BellProc; 395706f2543Smrg (*k)->CtrlProc = it->CtrlProc; 396706f2543Smrg (*k)->ctrl = it->ctrl; 397706f2543Smrg if ((*k)->xkb_sli) 398706f2543Smrg XkbFreeSrvLedInfo((*k)->xkb_sli); 399706f2543Smrg (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL); 400706f2543Smrg 401706f2543Smrg k = &(*k)->next; 402706f2543Smrg } 403706f2543Smrg } else if (to->kbdfeed && !from->kbdfeed) 404706f2543Smrg { 405706f2543Smrg ClassesPtr classes; 406706f2543Smrg classes = to->unused_classes; 407706f2543Smrg classes->kbdfeed = to->kbdfeed; 408706f2543Smrg to->kbdfeed = NULL; 409706f2543Smrg } 410706f2543Smrg 411706f2543Smrg if (from->key) 412706f2543Smrg { 413706f2543Smrg if (!to->key) 414706f2543Smrg { 415706f2543Smrg classes = to->unused_classes; 416706f2543Smrg to->key = classes->key; 417706f2543Smrg if (!to->key) 418706f2543Smrg InitKeyboardDeviceStruct(to, NULL, NULL, NULL); 419706f2543Smrg else 420706f2543Smrg classes->key = NULL; 421706f2543Smrg } 422706f2543Smrg 423706f2543Smrg CopyKeyClass(from, to); 424706f2543Smrg } else if (to->key && !from->key) 425706f2543Smrg { 426706f2543Smrg ClassesPtr classes; 427706f2543Smrg classes = to->unused_classes; 428706f2543Smrg classes->key = to->key; 429706f2543Smrg to->key = NULL; 430706f2543Smrg } 431706f2543Smrg 432706f2543Smrg /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps 433706f2543Smrg * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo 434706f2543Smrg * didn't update the pointers so we need to do it manually here. 435706f2543Smrg */ 436706f2543Smrg if (to->kbdfeed) 437706f2543Smrg { 438706f2543Smrg KbdFeedbackPtr k; 439706f2543Smrg 440706f2543Smrg for (k = to->kbdfeed; k; k = k->next) 441706f2543Smrg { 442706f2543Smrg if (!k->xkb_sli) 443706f2543Smrg continue; 444706f2543Smrg if (k->xkb_sli->flags & XkbSLI_IsDefault) 445706f2543Smrg { 446706f2543Smrg k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators; 447706f2543Smrg k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps; 448706f2543Smrg } 449706f2543Smrg } 450706f2543Smrg } 451706f2543Smrg 452706f2543Smrg /* We can't just copy over the focus class. When an app sets the focus, 453706f2543Smrg * it'll do so on the master device. Copying the SDs focus means losing 454706f2543Smrg * the focus. 455706f2543Smrg * So we only copy the focus class if the device didn't have one, 456706f2543Smrg * otherwise we leave it as it is. 457706f2543Smrg */ 458706f2543Smrg if (from->focus) 459706f2543Smrg { 460706f2543Smrg if (!to->focus) 461706f2543Smrg { 462706f2543Smrg WindowPtr *oldTrace; 463706f2543Smrg 464706f2543Smrg classes = to->unused_classes; 465706f2543Smrg to->focus = classes->focus; 466706f2543Smrg if (!to->focus) 467706f2543Smrg { 468706f2543Smrg to->focus = calloc(1, sizeof(FocusClassRec)); 469706f2543Smrg if (!to->focus) 470706f2543Smrg FatalError("[Xi] no memory for class shift.\n"); 471706f2543Smrg } else 472706f2543Smrg classes->focus = NULL; 473706f2543Smrg 474706f2543Smrg oldTrace = to->focus->trace; 475706f2543Smrg memcpy(to->focus, from->focus, sizeof(FocusClassRec)); 476706f2543Smrg to->focus->trace = realloc(oldTrace, 477706f2543Smrg to->focus->traceSize * sizeof(WindowPtr)); 478706f2543Smrg if (!to->focus->trace && to->focus->traceSize) 479706f2543Smrg FatalError("[Xi] no memory for trace.\n"); 480706f2543Smrg memcpy(to->focus->trace, from->focus->trace, 481706f2543Smrg from->focus->traceSize * sizeof(WindowPtr)); 482706f2543Smrg to->focus->sourceid = from->id; 483706f2543Smrg } 484706f2543Smrg } else if (to->focus) 485706f2543Smrg { 486706f2543Smrg ClassesPtr classes; 487706f2543Smrg classes = to->unused_classes; 488706f2543Smrg classes->focus = to->focus; 489706f2543Smrg to->focus = NULL; 490706f2543Smrg } 491706f2543Smrg 492706f2543Smrg} 493706f2543Smrg 494706f2543Smrgstatic void 495706f2543SmrgDeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) 496706f2543Smrg{ 497706f2543Smrg ClassesPtr classes; 498706f2543Smrg 499706f2543Smrg /* Feedback classes must be copied first */ 500706f2543Smrg if (from->ptrfeed) 501706f2543Smrg { 502706f2543Smrg PtrFeedbackPtr *p, it; 503706f2543Smrg if (!to->ptrfeed) 504706f2543Smrg { 505706f2543Smrg classes = to->unused_classes; 506706f2543Smrg to->ptrfeed = classes->ptrfeed; 507706f2543Smrg classes->ptrfeed = NULL; 508706f2543Smrg } 509706f2543Smrg 510706f2543Smrg p = &to->ptrfeed; 511706f2543Smrg for (it = from->ptrfeed; it; it = it->next) 512706f2543Smrg { 513706f2543Smrg if (!(*p)) 514706f2543Smrg { 515706f2543Smrg *p = calloc(1, sizeof(PtrFeedbackClassRec)); 516706f2543Smrg if (!*p) 517706f2543Smrg { 518706f2543Smrg ErrorF("[Xi] Cannot alloc memory for class copy."); 519706f2543Smrg return; 520706f2543Smrg } 521706f2543Smrg } 522706f2543Smrg (*p)->CtrlProc = it->CtrlProc; 523706f2543Smrg (*p)->ctrl = it->ctrl; 524706f2543Smrg 525706f2543Smrg p = &(*p)->next; 526706f2543Smrg } 527706f2543Smrg } else if (to->ptrfeed && !from->ptrfeed) 528706f2543Smrg { 529706f2543Smrg ClassesPtr classes; 530706f2543Smrg classes = to->unused_classes; 531706f2543Smrg classes->ptrfeed = to->ptrfeed; 532706f2543Smrg to->ptrfeed = NULL; 533706f2543Smrg } 534706f2543Smrg 535706f2543Smrg if (from->valuator) 536706f2543Smrg { 537706f2543Smrg ValuatorClassPtr v; 538706f2543Smrg 539706f2543Smrg if (!to->valuator) 540706f2543Smrg { 541706f2543Smrg classes = to->unused_classes; 542706f2543Smrg to->valuator = classes->valuator; 543706f2543Smrg if (to->valuator) 544706f2543Smrg classes->valuator = NULL; 545706f2543Smrg } 546706f2543Smrg 547706f2543Smrg v = AllocValuatorClass(to->valuator, from->valuator->numAxes); 548706f2543Smrg 549706f2543Smrg if (!v) 550706f2543Smrg FatalError("[Xi] no memory for class shift.\n"); 551706f2543Smrg 552706f2543Smrg to->valuator = v; 553706f2543Smrg memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo)); 554706f2543Smrg 555706f2543Smrg v->sourceid = from->id; 556706f2543Smrg } else if (to->valuator && !from->valuator) 557706f2543Smrg { 558706f2543Smrg ClassesPtr classes; 559706f2543Smrg classes = to->unused_classes; 560706f2543Smrg classes->valuator = to->valuator; 561706f2543Smrg to->valuator = NULL; 562706f2543Smrg } 563706f2543Smrg 564706f2543Smrg if (from->button) 565706f2543Smrg { 566706f2543Smrg if (!to->button) 567706f2543Smrg { 568706f2543Smrg classes = to->unused_classes; 569706f2543Smrg to->button = classes->button; 570706f2543Smrg if (!to->button) 571706f2543Smrg { 572706f2543Smrg to->button = calloc(1, sizeof(ButtonClassRec)); 573706f2543Smrg if (!to->button) 574706f2543Smrg FatalError("[Xi] no memory for class shift.\n"); 575706f2543Smrg } else 576706f2543Smrg classes->button = NULL; 577706f2543Smrg } 578706f2543Smrg 579706f2543Smrg if (from->button->xkb_acts) 580706f2543Smrg { 581706f2543Smrg if (!to->button->xkb_acts) 582706f2543Smrg { 583706f2543Smrg to->button->xkb_acts = calloc(1, sizeof(XkbAction)); 584706f2543Smrg if (!to->button->xkb_acts) 585706f2543Smrg FatalError("[Xi] not enough memory for xkb_acts.\n"); 586706f2543Smrg } 587706f2543Smrg memcpy(to->button->xkb_acts, from->button->xkb_acts, 588706f2543Smrg sizeof(XkbAction)); 589d931189fSmrg } else { 590706f2543Smrg free(to->button->xkb_acts); 591d931189fSmrg to->button->xkb_acts = NULL; 592d931189fSmrg } 593706f2543Smrg 594706f2543Smrg memcpy(to->button->labels, from->button->labels, 595706f2543Smrg from->button->numButtons * sizeof(Atom)); 596706f2543Smrg to->button->sourceid = from->id; 597706f2543Smrg } else if (to->button && !from->button) 598706f2543Smrg { 599706f2543Smrg ClassesPtr classes; 600706f2543Smrg classes = to->unused_classes; 601706f2543Smrg classes->button = to->button; 602706f2543Smrg to->button = NULL; 603706f2543Smrg } 604706f2543Smrg 605706f2543Smrg if (from->proximity) 606706f2543Smrg { 607706f2543Smrg if (!to->proximity) 608706f2543Smrg { 609706f2543Smrg classes = to->unused_classes; 610706f2543Smrg to->proximity = classes->proximity; 611706f2543Smrg if (!to->proximity) 612706f2543Smrg { 613706f2543Smrg to->proximity = calloc(1, sizeof(ProximityClassRec)); 614706f2543Smrg if (!to->proximity) 615706f2543Smrg FatalError("[Xi] no memory for class shift.\n"); 616706f2543Smrg } else 617706f2543Smrg classes->proximity = NULL; 618706f2543Smrg } 619706f2543Smrg memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec)); 620706f2543Smrg to->proximity->sourceid = from->id; 621706f2543Smrg } else if (to->proximity) 622706f2543Smrg { 623706f2543Smrg ClassesPtr classes; 624706f2543Smrg classes = to->unused_classes; 625706f2543Smrg classes->proximity = to->proximity; 626706f2543Smrg to->proximity = NULL; 627706f2543Smrg } 628706f2543Smrg 629706f2543Smrg if (from->absolute) 630706f2543Smrg { 631706f2543Smrg if (!to->absolute) 632706f2543Smrg { 633706f2543Smrg classes = to->unused_classes; 634706f2543Smrg to->absolute = classes->absolute; 635706f2543Smrg if (!to->absolute) 636706f2543Smrg { 637706f2543Smrg to->absolute = calloc(1, sizeof(AbsoluteClassRec)); 638706f2543Smrg if (!to->absolute) 639706f2543Smrg FatalError("[Xi] no memory for class shift.\n"); 640706f2543Smrg } else 641706f2543Smrg classes->absolute = NULL; 642706f2543Smrg } 643706f2543Smrg memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec)); 644706f2543Smrg to->absolute->sourceid = from->id; 645706f2543Smrg } else if (to->absolute) 646706f2543Smrg { 647706f2543Smrg ClassesPtr classes; 648706f2543Smrg classes = to->unused_classes; 649706f2543Smrg classes->absolute = to->absolute; 650706f2543Smrg to->absolute = NULL; 651706f2543Smrg } 652706f2543Smrg} 653706f2543Smrg 654706f2543Smrg/** 655706f2543Smrg * Copies the CONTENT of the classes of device from into the classes in device 656706f2543Smrg * to. From and to are identical after finishing. 657706f2543Smrg * 658706f2543Smrg * If to does not have classes from currenly has, the classes are stored in 659706f2543Smrg * to's devPrivates system. Later, we recover it again from there if needed. 660706f2543Smrg * Saves a few memory allocations. 661706f2543Smrg */ 662706f2543Smrgvoid 663706f2543SmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce) 664706f2543Smrg{ 665706f2543Smrg /* generic feedback classes, not tied to pointer and/or keyboard */ 666706f2543Smrg DeepCopyFeedbackClasses(from, to); 667706f2543Smrg 668706f2543Smrg if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT)) 669706f2543Smrg DeepCopyKeyboardClasses(from, to); 670706f2543Smrg if ((dce->flags & DEVCHANGE_POINTER_EVENT)) 671706f2543Smrg DeepCopyPointerClasses(from, to); 672706f2543Smrg} 673706f2543Smrg 674706f2543Smrg 675706f2543Smrg/** 676706f2543Smrg * Send an XI2 DeviceChangedEvent to all interested clients. 677706f2543Smrg */ 678706f2543Smrgvoid 679706f2543SmrgXISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce) 680706f2543Smrg{ 681706f2543Smrg xXIDeviceChangedEvent *dcce; 682706f2543Smrg int rc; 683706f2543Smrg 684706f2543Smrg rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce); 685706f2543Smrg if (rc != Success) 686706f2543Smrg { 687706f2543Smrg ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc); 688706f2543Smrg return; 689706f2543Smrg } 690706f2543Smrg 691706f2543Smrg /* we don't actually swap if there's a NullClient, swapping is done 692706f2543Smrg * later when event is delivered. */ 693706f2543Smrg SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1); 694706f2543Smrg free(dcce); 695706f2543Smrg} 696706f2543Smrg 697706f2543Smrgstatic void 698706f2543SmrgChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce) 699706f2543Smrg{ 700706f2543Smrg DeviceIntPtr slave; 701706f2543Smrg int rc; 702706f2543Smrg 703706f2543Smrg /* For now, we don't have devices that change physically. */ 704706f2543Smrg if (!IsMaster(device)) 705706f2543Smrg return; 706706f2543Smrg 707706f2543Smrg rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess); 708706f2543Smrg 709706f2543Smrg if (rc != Success) 710706f2543Smrg return; /* Device has disappeared */ 711706f2543Smrg 712706f2543Smrg if (!slave->u.master) 713706f2543Smrg return; /* set floating since the event */ 714706f2543Smrg 715706f2543Smrg if (slave->u.master->id != dce->masterid) 716706f2543Smrg return; /* not our slave anymore, don't care */ 717706f2543Smrg 718706f2543Smrg /* FIXME: we probably need to send a DCE for the new slave now */ 719706f2543Smrg 720706f2543Smrg device->public.devicePrivate = slave->public.devicePrivate; 721706f2543Smrg 722706f2543Smrg /* FIXME: the classes may have changed since we generated the event. */ 723706f2543Smrg DeepCopyDeviceClasses(slave, device, dce); 724706f2543Smrg XISendDeviceChangedEvent(slave, device, dce); 725706f2543Smrg} 726706f2543Smrg 727706f2543Smrg/** 728706f2543Smrg * Update the device state according to the data in the event. 729706f2543Smrg * 730706f2543Smrg * return values are 731706f2543Smrg * DEFAULT ... process as normal 732706f2543Smrg * DONT_PROCESS ... return immediately from caller 733706f2543Smrg */ 734706f2543Smrg#define DEFAULT 0 735706f2543Smrg#define DONT_PROCESS 1 736706f2543Smrgint 737706f2543SmrgUpdateDeviceState(DeviceIntPtr device, DeviceEvent* event) 738706f2543Smrg{ 739706f2543Smrg int i; 740706f2543Smrg int key = 0, 741706f2543Smrg bit = 0, 742706f2543Smrg last_valuator; 743706f2543Smrg 744706f2543Smrg KeyClassPtr k = NULL; 745706f2543Smrg ButtonClassPtr b = NULL; 746706f2543Smrg ValuatorClassPtr v = NULL; 747706f2543Smrg 748706f2543Smrg /* This event is always the first we get, before the actual events with 749706f2543Smrg * the data. However, the way how the DDX is set up, "device" will 750706f2543Smrg * actually be the slave device that caused the event. 751706f2543Smrg */ 752706f2543Smrg switch(event->type) 753706f2543Smrg { 754706f2543Smrg case ET_DeviceChanged: 755706f2543Smrg ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event); 756706f2543Smrg return DONT_PROCESS; /* event has been sent already */ 757706f2543Smrg case ET_Motion: 758706f2543Smrg case ET_ButtonPress: 759706f2543Smrg case ET_ButtonRelease: 760706f2543Smrg case ET_KeyPress: 761706f2543Smrg case ET_KeyRelease: 762706f2543Smrg case ET_ProximityIn: 763706f2543Smrg case ET_ProximityOut: 764706f2543Smrg break; 765706f2543Smrg default: 766706f2543Smrg /* other events don't update the device */ 767706f2543Smrg return DEFAULT; 768706f2543Smrg } 769706f2543Smrg 770706f2543Smrg k = device->key; 771706f2543Smrg v = device->valuator; 772706f2543Smrg b = device->button; 773706f2543Smrg 774706f2543Smrg key = event->detail.key; 775706f2543Smrg bit = 1 << (key & 7); 776706f2543Smrg 777706f2543Smrg /* Update device axis */ 778706f2543Smrg /* Check valuators first */ 779706f2543Smrg last_valuator = -1; 780706f2543Smrg for (i = 0; i < MAX_VALUATORS; i++) 781706f2543Smrg { 782706f2543Smrg if (BitIsOn(&event->valuators.mask, i)) 783706f2543Smrg { 784706f2543Smrg if (!v) 785706f2543Smrg { 786706f2543Smrg ErrorF("[Xi] Valuators reported for non-valuator device '%s'. " 787706f2543Smrg "Ignoring event.\n", device->name); 788706f2543Smrg return DONT_PROCESS; 789706f2543Smrg } else if (v->numAxes < i) 790706f2543Smrg { 791706f2543Smrg ErrorF("[Xi] Too many valuators reported for device '%s'. " 792706f2543Smrg "Ignoring event.\n", device->name); 793706f2543Smrg return DONT_PROCESS; 794706f2543Smrg } 795706f2543Smrg last_valuator = i; 796706f2543Smrg } 797706f2543Smrg } 798706f2543Smrg 799706f2543Smrg for (i = 0; i <= last_valuator && i < v->numAxes; i++) 800706f2543Smrg { 801706f2543Smrg if (BitIsOn(&event->valuators.mask, i)) 802706f2543Smrg { 803706f2543Smrg /* XXX: Relative/Absolute mode */ 804706f2543Smrg v->axisVal[i] = event->valuators.data[i]; 805706f2543Smrg v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16)); 806706f2543Smrg } 807706f2543Smrg } 808706f2543Smrg 809706f2543Smrg if (event->type == ET_KeyPress) { 810706f2543Smrg if (!k) 811706f2543Smrg return DONT_PROCESS; 812706f2543Smrg 813706f2543Smrg /* don't allow ddx to generate multiple downs, but repeats are okay */ 814706f2543Smrg if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat) 815706f2543Smrg return DONT_PROCESS; 816706f2543Smrg 817706f2543Smrg if (device->valuator) 818706f2543Smrg device->valuator->motionHintWindow = NullWindow; 819706f2543Smrg set_key_down(device, key, KEY_PROCESSED); 820706f2543Smrg } else if (event->type == ET_KeyRelease) { 821706f2543Smrg if (!k) 822706f2543Smrg return DONT_PROCESS; 823706f2543Smrg 824706f2543Smrg if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */ 825706f2543Smrg return DONT_PROCESS; 826706f2543Smrg if (device->valuator) 827706f2543Smrg device->valuator->motionHintWindow = NullWindow; 828706f2543Smrg set_key_up(device, key, KEY_PROCESSED); 829706f2543Smrg } else if (event->type == ET_ButtonPress) { 830706f2543Smrg Mask mask; 831706f2543Smrg if (!b) 832706f2543Smrg return DONT_PROCESS; 833706f2543Smrg 834706f2543Smrg if (button_is_down(device, key, BUTTON_PROCESSED)) 835706f2543Smrg return DONT_PROCESS; 836706f2543Smrg 837706f2543Smrg set_button_down(device, key, BUTTON_PROCESSED); 838706f2543Smrg if (device->valuator) 839706f2543Smrg device->valuator->motionHintWindow = NullWindow; 840706f2543Smrg if (!b->map[key]) 841706f2543Smrg return DONT_PROCESS; 842706f2543Smrg b->buttonsDown++; 843706f2543Smrg b->motionMask = DeviceButtonMotionMask; 844706f2543Smrg if (b->map[key] <= 5) 845706f2543Smrg b->state |= (Button1Mask >> 1) << b->map[key]; 846706f2543Smrg 847706f2543Smrg /* Add state and motionMask to the filter for this event */ 848706f2543Smrg mask = DevicePointerMotionMask | b->state | b->motionMask; 849706f2543Smrg SetMaskForEvent(device->id, mask, DeviceMotionNotify); 850706f2543Smrg mask = PointerMotionMask | b->state | b->motionMask; 851706f2543Smrg SetMaskForEvent(device->id, mask, MotionNotify); 852706f2543Smrg } else if (event->type == ET_ButtonRelease) { 853706f2543Smrg Mask mask; 854706f2543Smrg if (!b) 855706f2543Smrg return DONT_PROCESS; 856706f2543Smrg 857706f2543Smrg if (!button_is_down(device, key, BUTTON_PROCESSED)) 858706f2543Smrg return DONT_PROCESS; 859706f2543Smrg if (IsMaster(device)) { 860706f2543Smrg DeviceIntPtr sd; 861706f2543Smrg 862706f2543Smrg /* 863706f2543Smrg * Leave the button down if any slave has the 864706f2543Smrg * button still down. Note that this depends on the 865706f2543Smrg * event being delivered through the slave first 866706f2543Smrg */ 867706f2543Smrg for (sd = inputInfo.devices; sd; sd = sd->next) { 868706f2543Smrg if (IsMaster(sd) || sd->u.master != device) 869706f2543Smrg continue; 870706f2543Smrg if (!sd->button) 871706f2543Smrg continue; 872706f2543Smrg for (i = 1; i <= sd->button->numButtons; i++) 873706f2543Smrg if (sd->button->map[i] == key && 874706f2543Smrg button_is_down(sd, i, BUTTON_PROCESSED)) 875706f2543Smrg return DONT_PROCESS; 876706f2543Smrg } 877706f2543Smrg } 878706f2543Smrg set_button_up(device, key, BUTTON_PROCESSED); 879706f2543Smrg if (device->valuator) 880706f2543Smrg device->valuator->motionHintWindow = NullWindow; 881706f2543Smrg if (!b->map[key]) 882706f2543Smrg return DONT_PROCESS; 883706f2543Smrg if (b->buttonsDown >= 1 && !--b->buttonsDown) 884706f2543Smrg b->motionMask = 0; 885706f2543Smrg if (b->map[key] <= 5) 886706f2543Smrg b->state &= ~((Button1Mask >> 1) << b->map[key]); 887706f2543Smrg 888706f2543Smrg /* Add state and motionMask to the filter for this event */ 889706f2543Smrg mask = DevicePointerMotionMask | b->state | b->motionMask; 890706f2543Smrg SetMaskForEvent(device->id, mask, DeviceMotionNotify); 891706f2543Smrg mask = PointerMotionMask | b->state | b->motionMask; 892706f2543Smrg SetMaskForEvent(device->id, mask, MotionNotify); 893706f2543Smrg } else if (event->type == ET_ProximityIn) 894706f2543Smrg device->proximity->in_proximity = TRUE; 895706f2543Smrg else if (event->type == ET_ProximityOut) 896706f2543Smrg device->proximity->in_proximity = FALSE; 897706f2543Smrg 898706f2543Smrg return DEFAULT; 899706f2543Smrg} 900706f2543Smrg 901706f2543Smrgstatic void 902706f2543SmrgProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) 903706f2543Smrg{ 904706f2543Smrg GrabPtr grab = device->deviceGrab.grab; 905706f2543Smrg 906706f2543Smrg if (grab) 907706f2543Smrg DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE); 908706f2543Smrg else { /* deliver to all root windows */ 909706f2543Smrg xEvent *xi; 910706f2543Smrg int i; 911706f2543Smrg 912706f2543Smrg i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); 913706f2543Smrg if (i != Success) 914706f2543Smrg { 915706f2543Smrg ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n", 916706f2543Smrg device->name, i); 917706f2543Smrg return; 918706f2543Smrg } 919706f2543Smrg 920706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 921706f2543Smrg DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, 922706f2543Smrg GetEventFilter(device, xi), NULL); 923706f2543Smrg free(xi); 924706f2543Smrg } 925706f2543Smrg} 926706f2543Smrg 927706f2543Smrg/** 928706f2543Smrg * Main device event processing function. 929706f2543Smrg * Called from when processing the events from the event queue. 930706f2543Smrg * 931706f2543Smrg */ 932706f2543Smrgvoid 933706f2543SmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) 934706f2543Smrg{ 935706f2543Smrg GrabPtr grab; 936706f2543Smrg Bool deactivateDeviceGrab = FALSE; 937706f2543Smrg int key = 0, rootX, rootY; 938706f2543Smrg ButtonClassPtr b; 939706f2543Smrg KeyClassPtr k; 940706f2543Smrg ValuatorClassPtr v; 941706f2543Smrg int ret = 0; 942706f2543Smrg int state, i; 943706f2543Smrg DeviceIntPtr mouse = NULL, kbd = NULL; 944706f2543Smrg DeviceEvent *event = &ev->device_event; 945706f2543Smrg 946706f2543Smrg CHECKEVENT(ev); 947706f2543Smrg 948706f2543Smrg if (ev->any.type == ET_RawKeyPress || 949706f2543Smrg ev->any.type == ET_RawKeyRelease || 950706f2543Smrg ev->any.type == ET_RawButtonPress || 951706f2543Smrg ev->any.type == ET_RawButtonRelease || 952706f2543Smrg ev->any.type == ET_RawMotion) 953706f2543Smrg { 954706f2543Smrg ProcessRawEvent(&ev->raw_event, device); 955706f2543Smrg return; 956706f2543Smrg } 957706f2543Smrg 958706f2543Smrg if (IsPointerDevice(device)) 959706f2543Smrg { 960706f2543Smrg kbd = GetPairedDevice(device); 961706f2543Smrg mouse = device; 962706f2543Smrg if (!kbd->key) /* can happen with floating SDs */ 963706f2543Smrg kbd = NULL; 964706f2543Smrg } else 965706f2543Smrg { 966706f2543Smrg mouse = GetPairedDevice(device); 967706f2543Smrg kbd = device; 968706f2543Smrg if (!mouse->valuator || !mouse->button) /* may be float. SDs */ 969706f2543Smrg mouse = NULL; 970706f2543Smrg } 971706f2543Smrg 972706f2543Smrg /* State needs to be assembled BEFORE the device is updated. */ 973706f2543Smrg state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0; 974706f2543Smrg state |= (mouse && mouse->button) ? (mouse->button->state) : 0; 975706f2543Smrg 976706f2543Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 977706f2543Smrg if (BitIsOn(mouse->button->down, i)) 978706f2543Smrg SetBit(event->buttons, i); 979706f2543Smrg 980706f2543Smrg if (kbd && kbd->key) 981706f2543Smrg { 982706f2543Smrg XkbStatePtr state; 983706f2543Smrg /* we need the state before the event happens */ 984706f2543Smrg if (event->type == ET_KeyPress || event->type == ET_KeyRelease) 985706f2543Smrg state = &kbd->key->xkbInfo->prev_state; 986706f2543Smrg else 987706f2543Smrg state = &kbd->key->xkbInfo->state; 988706f2543Smrg 989706f2543Smrg event->mods.base = state->base_mods; 990706f2543Smrg event->mods.latched = state->latched_mods; 991706f2543Smrg event->mods.locked = state->locked_mods; 992706f2543Smrg event->mods.effective = state->mods; 993706f2543Smrg 994706f2543Smrg event->group.base = state->base_group; 995706f2543Smrg event->group.latched = state->latched_group; 996706f2543Smrg event->group.locked = state->locked_group; 997706f2543Smrg event->group.effective = state->group; 998706f2543Smrg } 999706f2543Smrg 1000706f2543Smrg ret = UpdateDeviceState(device, event); 1001706f2543Smrg if (ret == DONT_PROCESS) 1002706f2543Smrg return; 1003706f2543Smrg 1004706f2543Smrg v = device->valuator; 1005706f2543Smrg b = device->button; 1006706f2543Smrg k = device->key; 1007706f2543Smrg 1008706f2543Smrg if (IsMaster(device) || !device->u.master) 1009706f2543Smrg CheckMotion(event, device); 1010706f2543Smrg 1011706f2543Smrg switch (event->type) 1012706f2543Smrg { 1013706f2543Smrg case ET_Motion: 1014706f2543Smrg case ET_ButtonPress: 1015706f2543Smrg case ET_ButtonRelease: 1016706f2543Smrg case ET_KeyPress: 1017706f2543Smrg case ET_KeyRelease: 1018706f2543Smrg case ET_ProximityIn: 1019706f2543Smrg case ET_ProximityOut: 1020706f2543Smrg GetSpritePosition(device, &rootX, &rootY); 1021706f2543Smrg event->root_x = rootX; 1022706f2543Smrg event->root_y = rootY; 1023706f2543Smrg NoticeEventTime((InternalEvent*)event); 1024706f2543Smrg event->corestate = state; 1025706f2543Smrg key = event->detail.key; 1026706f2543Smrg break; 1027706f2543Smrg default: 1028706f2543Smrg break; 1029706f2543Smrg } 1030706f2543Smrg 1031706f2543Smrg if (DeviceEventCallback && !syncEvents.playingEvents) { 1032706f2543Smrg DeviceEventInfoRec eventinfo; 1033706f2543Smrg SpritePtr pSprite = device->spriteInfo->sprite; 1034706f2543Smrg 1035706f2543Smrg /* see comment in EnqueueEvents regarding the next three lines */ 1036706f2543Smrg if (ev->any.type == ET_Motion) 1037706f2543Smrg ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 1038706f2543Smrg 1039706f2543Smrg eventinfo.device = device; 1040706f2543Smrg eventinfo.event = ev; 1041706f2543Smrg CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); 1042706f2543Smrg } 1043706f2543Smrg 1044706f2543Smrg grab = device->deviceGrab.grab; 1045706f2543Smrg 1046706f2543Smrg switch(event->type) 1047706f2543Smrg { 1048706f2543Smrg case ET_KeyPress: 1049706f2543Smrg if (!grab && CheckDeviceGrabs(device, event, 0)) { 1050706f2543Smrg device->deviceGrab.activatingKey = key; 1051706f2543Smrg return; 1052706f2543Smrg } 1053706f2543Smrg break; 1054706f2543Smrg case ET_KeyRelease: 1055706f2543Smrg if (grab && device->deviceGrab.fromPassiveGrab && 1056706f2543Smrg (key == device->deviceGrab.activatingKey) && 1057706f2543Smrg (device->deviceGrab.grab->type == KeyPress || 1058706f2543Smrg device->deviceGrab.grab->type == DeviceKeyPress || 1059706f2543Smrg device->deviceGrab.grab->type == XI_KeyPress)) 1060706f2543Smrg deactivateDeviceGrab = TRUE; 1061706f2543Smrg break; 1062706f2543Smrg case ET_ButtonPress: 1063706f2543Smrg event->detail.button = b->map[key]; 1064706f2543Smrg if (!event->detail.button) { /* there's no button 0 */ 1065706f2543Smrg event->detail.button = key; 1066706f2543Smrg return; 1067706f2543Smrg } 1068706f2543Smrg if (!grab && CheckDeviceGrabs(device, event, 0)) 1069706f2543Smrg { 1070706f2543Smrg /* if a passive grab was activated, the event has been sent 1071706f2543Smrg * already */ 1072706f2543Smrg return; 1073706f2543Smrg } 1074706f2543Smrg break; 1075706f2543Smrg case ET_ButtonRelease: 1076706f2543Smrg event->detail.button = b->map[key]; 1077706f2543Smrg if (!event->detail.button) { /* there's no button 0 */ 1078706f2543Smrg event->detail.button = key; 1079706f2543Smrg return; 1080706f2543Smrg } 1081706f2543Smrg if (grab && !b->buttonsDown && 1082706f2543Smrg device->deviceGrab.fromPassiveGrab && 1083706f2543Smrg (device->deviceGrab.grab->type == ButtonPress || 1084706f2543Smrg device->deviceGrab.grab->type == DeviceButtonPress || 1085706f2543Smrg device->deviceGrab.grab->type == XI_ButtonPress)) 1086706f2543Smrg deactivateDeviceGrab = TRUE; 1087706f2543Smrg default: 1088706f2543Smrg break; 1089706f2543Smrg } 1090706f2543Smrg 1091706f2543Smrg 1092706f2543Smrg if (grab) 1093706f2543Smrg DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab); 1094706f2543Smrg else if (device->focus && !IsPointerEvent((InternalEvent*)ev)) 1095706f2543Smrg DeliverFocusedEvent(device, (InternalEvent*)event, 1096706f2543Smrg GetSpriteWindow(device)); 1097706f2543Smrg else 1098706f2543Smrg DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event, 1099706f2543Smrg NullGrab, NullWindow, device); 1100706f2543Smrg 1101706f2543Smrg if (deactivateDeviceGrab == TRUE) 1102706f2543Smrg (*device->deviceGrab.DeactivateGrab) (device); 1103706f2543Smrg event->detail.key = key; 1104706f2543Smrg} 1105706f2543Smrg 1106706f2543Smrgint 1107706f2543SmrgInitProximityClassDeviceStruct(DeviceIntPtr dev) 1108706f2543Smrg{ 1109706f2543Smrg ProximityClassPtr proxc; 1110706f2543Smrg 1111706f2543Smrg proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec)); 1112706f2543Smrg if (!proxc) 1113706f2543Smrg return FALSE; 1114706f2543Smrg proxc->sourceid = dev->id; 1115706f2543Smrg proxc->in_proximity = TRUE; 1116706f2543Smrg dev->proximity = proxc; 1117706f2543Smrg return TRUE; 1118706f2543Smrg} 1119706f2543Smrg 1120706f2543Smrg/** 1121706f2543Smrg * Initialise the device's valuators. The memory must already be allocated, 1122706f2543Smrg * this function merely inits the matching axis (specified through axnum) to 1123706f2543Smrg * sane values. 1124706f2543Smrg * 1125706f2543Smrg * It is a condition that (minval < maxval). 1126706f2543Smrg * 1127706f2543Smrg * @see InitValuatorClassDeviceStruct 1128706f2543Smrg */ 1129706f2543Smrgvoid 1130706f2543SmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, 1131706f2543Smrg int resolution, int min_res, int max_res, int mode) 1132706f2543Smrg{ 1133706f2543Smrg AxisInfoPtr ax; 1134706f2543Smrg 1135706f2543Smrg if (!dev || !dev->valuator || minval > maxval) 1136706f2543Smrg return; 1137706f2543Smrg if (axnum >= dev->valuator->numAxes) 1138706f2543Smrg return; 1139706f2543Smrg 1140706f2543Smrg ax = dev->valuator->axes + axnum; 1141706f2543Smrg 1142706f2543Smrg ax->min_value = minval; 1143706f2543Smrg ax->max_value = maxval; 1144706f2543Smrg ax->resolution = resolution; 1145706f2543Smrg ax->min_resolution = min_res; 1146706f2543Smrg ax->max_resolution = max_res; 1147706f2543Smrg ax->label = label; 1148706f2543Smrg ax->mode = mode; 1149706f2543Smrg 1150706f2543Smrg if (mode & OutOfProximity) 1151706f2543Smrg dev->proximity->in_proximity = FALSE; 1152706f2543Smrg} 1153706f2543Smrg 1154706f2543Smrgstatic void 1155706f2543SmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k, 1156706f2543Smrg ButtonClassPtr b, ValuatorClassPtr v, int first) 1157706f2543Smrg{ 1158706f2543Smrg ev->type = DeviceStateNotify; 1159706f2543Smrg ev->deviceid = dev->id; 1160706f2543Smrg ev->time = currentTime.milliseconds; 1161706f2543Smrg ev->classes_reported = 0; 1162706f2543Smrg ev->num_keys = 0; 1163706f2543Smrg ev->num_buttons = 0; 1164706f2543Smrg ev->num_valuators = 0; 1165706f2543Smrg 1166706f2543Smrg if (b) { 1167706f2543Smrg ev->classes_reported |= (1 << ButtonClass); 1168706f2543Smrg ev->num_buttons = b->numButtons; 1169706f2543Smrg memcpy((char*)ev->buttons, (char*)b->down, 4); 1170706f2543Smrg } else if (k) { 1171706f2543Smrg ev->classes_reported |= (1 << KeyClass); 1172706f2543Smrg ev->num_keys = k->xkbInfo->desc->max_key_code - 1173706f2543Smrg k->xkbInfo->desc->min_key_code; 1174706f2543Smrg memmove((char *)&ev->keys[0], (char *)k->down, 4); 1175706f2543Smrg } 1176706f2543Smrg if (v) { 1177706f2543Smrg int nval = v->numAxes - first; 1178706f2543Smrg 1179706f2543Smrg ev->classes_reported |= (1 << ValuatorClass); 1180706f2543Smrg ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift; 1181706f2543Smrg ev->num_valuators = nval < 3 ? nval : 3; 1182706f2543Smrg switch (ev->num_valuators) { 1183706f2543Smrg case 3: 1184706f2543Smrg ev->valuator2 = v->axisVal[first + 2]; 1185706f2543Smrg case 2: 1186706f2543Smrg ev->valuator1 = v->axisVal[first + 1]; 1187706f2543Smrg case 1: 1188706f2543Smrg ev->valuator0 = v->axisVal[first]; 1189706f2543Smrg break; 1190706f2543Smrg } 1191706f2543Smrg } 1192706f2543Smrg} 1193706f2543Smrg 1194706f2543Smrgstatic void 1195706f2543SmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v, 1196706f2543Smrg int first) 1197706f2543Smrg{ 1198706f2543Smrg int nval = v->numAxes - first; 1199706f2543Smrg 1200706f2543Smrg ev->type = DeviceValuator; 1201706f2543Smrg ev->deviceid = dev->id; 1202706f2543Smrg ev->num_valuators = nval < 3 ? nval : 3; 1203706f2543Smrg ev->first_valuator = first; 1204706f2543Smrg switch (ev->num_valuators) { 1205706f2543Smrg case 3: 1206706f2543Smrg ev->valuator2 = v->axisVal[first + 2]; 1207706f2543Smrg case 2: 1208706f2543Smrg ev->valuator1 = v->axisVal[first + 1]; 1209706f2543Smrg case 1: 1210706f2543Smrg ev->valuator0 = v->axisVal[first]; 1211706f2543Smrg break; 1212706f2543Smrg } 1213706f2543Smrg first += ev->num_valuators; 1214706f2543Smrg} 1215706f2543Smrg 1216706f2543Smrgvoid 1217706f2543SmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, 1218706f2543Smrg WindowPtr pWin) 1219706f2543Smrg{ 1220706f2543Smrg deviceFocus event; 1221706f2543Smrg xXIFocusInEvent *xi2event; 1222706f2543Smrg DeviceIntPtr mouse; 1223706f2543Smrg int btlen, len, i; 1224706f2543Smrg 1225706f2543Smrg mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev; 1226706f2543Smrg 1227bde01a6bSmrg /* XI 2 event contains the logical button map - maps are CARD8 1228bde01a6bSmrg * so we need 256 bits for the possibly maximum mapping */ 1229bde01a6bSmrg btlen = (mouse->button) ? bits_to_bytes(256) : 0; 1230706f2543Smrg btlen = bytes_to_int32(btlen); 1231706f2543Smrg len = sizeof(xXIFocusInEvent) + btlen * 4; 1232706f2543Smrg 1233706f2543Smrg xi2event = calloc(1, len); 1234706f2543Smrg xi2event->type = GenericEvent; 1235706f2543Smrg xi2event->extension = IReqCode; 1236706f2543Smrg xi2event->evtype = type; 1237706f2543Smrg xi2event->length = bytes_to_int32(len - sizeof(xEvent)); 1238706f2543Smrg xi2event->buttons_len = btlen; 1239706f2543Smrg xi2event->detail = detail; 1240706f2543Smrg xi2event->time = currentTime.milliseconds; 1241706f2543Smrg xi2event->deviceid = dev->id; 1242706f2543Smrg xi2event->sourceid = dev->id; /* a device doesn't change focus by itself */ 1243706f2543Smrg xi2event->mode = mode; 1244706f2543Smrg xi2event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0); 1245706f2543Smrg xi2event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0); 1246706f2543Smrg 1247706f2543Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 1248706f2543Smrg if (BitIsOn(mouse->button->down, i)) 1249706f2543Smrg SetBit(&xi2event[1], i); 1250706f2543Smrg 1251706f2543Smrg if (dev->key) 1252706f2543Smrg { 1253706f2543Smrg xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods; 1254706f2543Smrg xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods; 1255706f2543Smrg xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods; 1256706f2543Smrg xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods; 1257706f2543Smrg 1258706f2543Smrg xi2event->group.base_group = dev->key->xkbInfo->state.base_group; 1259706f2543Smrg xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group; 1260706f2543Smrg xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group; 1261706f2543Smrg xi2event->group.effective_group = dev->key->xkbInfo->state.group; 1262706f2543Smrg } 1263706f2543Smrg 1264706f2543Smrg FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin, 1265706f2543Smrg None, FALSE); 1266706f2543Smrg 1267706f2543Smrg DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1, 1268706f2543Smrg GetEventFilter(dev, (xEvent*)xi2event), NullGrab); 1269706f2543Smrg 1270706f2543Smrg free(xi2event); 1271706f2543Smrg 1272706f2543Smrg /* XI 1.x event */ 1273706f2543Smrg event.deviceid = dev->id; 1274706f2543Smrg event.mode = mode; 1275706f2543Smrg event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut; 1276706f2543Smrg event.detail = detail; 1277706f2543Smrg event.window = pWin->drawable.id; 1278706f2543Smrg event.time = currentTime.milliseconds; 1279706f2543Smrg 1280706f2543Smrg DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1, 1281706f2543Smrg DeviceFocusChangeMask, NullGrab); 1282706f2543Smrg 1283706f2543Smrg if ((event.type == DeviceFocusIn) && 1284706f2543Smrg (wOtherInputMasks(pWin)) && 1285706f2543Smrg (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask)) 1286706f2543Smrg { 1287706f2543Smrg int evcount = 1; 1288f5d46ea4Smrg deviceStateNotify sev[6 + (MAX_VALUATORS + 2)/3]; 1289f5d46ea4Smrg deviceStateNotify *ev; 1290706f2543Smrg deviceKeyStateNotify *kev; 1291706f2543Smrg deviceButtonStateNotify *bev; 1292706f2543Smrg 1293706f2543Smrg KeyClassPtr k; 1294706f2543Smrg ButtonClassPtr b; 1295706f2543Smrg ValuatorClassPtr v; 1296706f2543Smrg int nval = 0, nkeys = 0, nbuttons = 0, first = 0; 1297706f2543Smrg 1298706f2543Smrg if ((b = dev->button) != NULL) { 1299706f2543Smrg nbuttons = b->numButtons; 1300706f2543Smrg if (nbuttons > 32) 1301706f2543Smrg evcount++; 1302706f2543Smrg } 1303706f2543Smrg if ((k = dev->key) != NULL) { 1304706f2543Smrg nkeys = k->xkbInfo->desc->max_key_code - 1305706f2543Smrg k->xkbInfo->desc->min_key_code; 1306706f2543Smrg if (nkeys > 32) 1307706f2543Smrg evcount++; 1308706f2543Smrg if (nbuttons > 0) { 1309706f2543Smrg evcount++; 1310706f2543Smrg } 1311706f2543Smrg } 1312706f2543Smrg if ((v = dev->valuator) != NULL) { 1313706f2543Smrg nval = v->numAxes; 1314706f2543Smrg 1315706f2543Smrg if (nval > 3) 1316706f2543Smrg evcount++; 1317706f2543Smrg if (nval > 6) { 1318706f2543Smrg if (!(k && b)) 1319706f2543Smrg evcount++; 1320706f2543Smrg if (nval > 9) 1321706f2543Smrg evcount += ((nval - 7) / 3); 1322706f2543Smrg } 1323706f2543Smrg } 1324706f2543Smrg 1325f5d46ea4Smrg ev = sev; 1326706f2543Smrg FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first); 1327706f2543Smrg 1328706f2543Smrg if (b != NULL) { 1329706f2543Smrg FixDeviceStateNotify(dev, ev++, NULL, b, v, first); 1330706f2543Smrg first += 3; 1331706f2543Smrg nval -= 3; 1332706f2543Smrg if (nbuttons > 32) { 1333706f2543Smrg (ev - 1)->deviceid |= MORE_EVENTS; 1334706f2543Smrg bev = (deviceButtonStateNotify *) ev++; 1335706f2543Smrg bev->type = DeviceButtonStateNotify; 1336706f2543Smrg bev->deviceid = dev->id; 1337706f2543Smrg memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4); 1338706f2543Smrg } 1339706f2543Smrg if (nval > 0) { 1340706f2543Smrg (ev - 1)->deviceid |= MORE_EVENTS; 1341706f2543Smrg FixDeviceValuator(dev, (deviceValuator *) ev++, v, first); 1342706f2543Smrg first += 3; 1343706f2543Smrg nval -= 3; 1344706f2543Smrg } 1345706f2543Smrg } 1346706f2543Smrg 1347706f2543Smrg if (k != NULL) { 1348706f2543Smrg FixDeviceStateNotify(dev, ev++, k, NULL, v, first); 1349706f2543Smrg first += 3; 1350706f2543Smrg nval -= 3; 1351706f2543Smrg if (nkeys > 32) { 1352706f2543Smrg (ev - 1)->deviceid |= MORE_EVENTS; 1353706f2543Smrg kev = (deviceKeyStateNotify *) ev++; 1354706f2543Smrg kev->type = DeviceKeyStateNotify; 1355706f2543Smrg kev->deviceid = dev->id; 1356706f2543Smrg memmove((char *)&kev->keys[0], (char *)&k->down[4], 28); 1357706f2543Smrg } 1358706f2543Smrg if (nval > 0) { 1359706f2543Smrg (ev - 1)->deviceid |= MORE_EVENTS; 1360706f2543Smrg FixDeviceValuator(dev, (deviceValuator *) ev++, v, first); 1361706f2543Smrg first += 3; 1362706f2543Smrg nval -= 3; 1363706f2543Smrg } 1364706f2543Smrg } 1365706f2543Smrg 1366706f2543Smrg while (nval > 0) { 1367706f2543Smrg FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first); 1368706f2543Smrg first += 3; 1369706f2543Smrg nval -= 3; 1370706f2543Smrg if (nval > 0) { 1371706f2543Smrg (ev - 1)->deviceid |= MORE_EVENTS; 1372706f2543Smrg FixDeviceValuator(dev, (deviceValuator *) ev++, v, first); 1373706f2543Smrg first += 3; 1374706f2543Smrg nval -= 3; 1375706f2543Smrg } 1376706f2543Smrg } 1377706f2543Smrg 1378706f2543Smrg DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount, 1379706f2543Smrg DeviceStateNotifyMask, NullGrab); 1380706f2543Smrg } 1381706f2543Smrg} 1382706f2543Smrg 1383706f2543Smrgint 1384706f2543SmrgCheckGrabValues(ClientPtr client, GrabParameters* param) 1385706f2543Smrg{ 1386706f2543Smrg if (param->grabtype != GRABTYPE_CORE && 1387706f2543Smrg param->grabtype != GRABTYPE_XI && 1388706f2543Smrg param->grabtype != GRABTYPE_XI2) 1389706f2543Smrg { 1390706f2543Smrg ErrorF("[Xi] grabtype is invalid. This is a bug.\n"); 1391706f2543Smrg return BadImplementation; 1392706f2543Smrg } 1393706f2543Smrg 1394706f2543Smrg if ((param->this_device_mode != GrabModeSync) && 1395706f2543Smrg (param->this_device_mode != GrabModeAsync)) { 1396706f2543Smrg client->errorValue = param->this_device_mode; 1397706f2543Smrg return BadValue; 1398706f2543Smrg } 1399706f2543Smrg if ((param->other_devices_mode != GrabModeSync) && 1400706f2543Smrg (param->other_devices_mode != GrabModeAsync)) { 1401706f2543Smrg client->errorValue = param->other_devices_mode; 1402706f2543Smrg return BadValue; 1403706f2543Smrg } 1404706f2543Smrg 1405706f2543Smrg if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) && 1406706f2543Smrg (param->modifiers & ~AllModifiersMask)) { 1407706f2543Smrg client->errorValue = param->modifiers; 1408706f2543Smrg return BadValue; 1409706f2543Smrg } 1410706f2543Smrg 1411706f2543Smrg if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) { 1412706f2543Smrg client->errorValue = param->ownerEvents; 1413706f2543Smrg return BadValue; 1414706f2543Smrg } 1415706f2543Smrg return Success; 1416706f2543Smrg} 1417706f2543Smrg 1418706f2543Smrgint 1419706f2543SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 1420706f2543Smrg int button, GrabParameters *param, GrabType grabtype, 1421706f2543Smrg GrabMask *mask) 1422706f2543Smrg{ 1423706f2543Smrg WindowPtr pWin, confineTo; 1424706f2543Smrg CursorPtr cursor; 1425706f2543Smrg GrabPtr grab; 1426706f2543Smrg int rc, type = -1; 1427706f2543Smrg Mask access_mode = DixGrabAccess; 1428706f2543Smrg 1429706f2543Smrg rc = CheckGrabValues(client, param); 1430706f2543Smrg if (rc != Success) 1431706f2543Smrg return rc; 1432706f2543Smrg if (param->confineTo == None) 1433706f2543Smrg confineTo = NullWindow; 1434706f2543Smrg else { 1435706f2543Smrg rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess); 1436706f2543Smrg if (rc != Success) 1437706f2543Smrg return rc; 1438706f2543Smrg } 1439706f2543Smrg if (param->cursor == None) 1440706f2543Smrg cursor = NullCursor; 1441706f2543Smrg else { 1442706f2543Smrg rc = dixLookupResourceByType((pointer *)&cursor, param->cursor, 1443706f2543Smrg RT_CURSOR, client, DixUseAccess); 1444706f2543Smrg if (rc != Success) 1445706f2543Smrg { 1446706f2543Smrg client->errorValue = param->cursor; 1447706f2543Smrg return rc; 1448706f2543Smrg } 1449706f2543Smrg access_mode |= DixForceAccess; 1450706f2543Smrg } 1451706f2543Smrg if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync) 1452706f2543Smrg access_mode |= DixFreezeAccess; 1453706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 1454706f2543Smrg if (rc != Success) 1455706f2543Smrg return rc; 1456706f2543Smrg rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 1457706f2543Smrg if (rc != Success) 1458706f2543Smrg return rc; 1459706f2543Smrg 1460706f2543Smrg if (grabtype == GRABTYPE_XI) 1461706f2543Smrg type = DeviceButtonPress; 1462706f2543Smrg else if (grabtype == GRABTYPE_XI2) 1463706f2543Smrg type = XI_ButtonPress; 1464706f2543Smrg 1465706f2543Smrg grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 1466706f2543Smrg mask, param, type, button, confineTo, cursor); 1467706f2543Smrg if (!grab) 1468706f2543Smrg return BadAlloc; 1469706f2543Smrg return AddPassiveGrabToList(client, grab); 1470706f2543Smrg} 1471706f2543Smrg 1472706f2543Smrg/** 1473706f2543Smrg * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If 1474706f2543Smrg * grabtype is GRABTYPE_XI2, the key is a keysym. 1475706f2543Smrg */ 1476706f2543Smrgint 1477706f2543SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, 1478706f2543Smrg int key, GrabParameters *param, GrabType grabtype, GrabMask *mask) 1479706f2543Smrg{ 1480706f2543Smrg WindowPtr pWin; 1481706f2543Smrg GrabPtr grab; 1482706f2543Smrg KeyClassPtr k = dev->key; 1483706f2543Smrg Mask access_mode = DixGrabAccess; 1484706f2543Smrg int rc, type = -1; 1485706f2543Smrg 1486706f2543Smrg rc = CheckGrabValues(client, param); 1487706f2543Smrg if (rc != Success) 1488706f2543Smrg return rc; 1489706f2543Smrg if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL) 1490706f2543Smrg return BadMatch; 1491706f2543Smrg if (grabtype == GRABTYPE_XI) 1492706f2543Smrg { 1493706f2543Smrg if ((key > k->xkbInfo->desc->max_key_code || 1494706f2543Smrg key < k->xkbInfo->desc->min_key_code) 1495706f2543Smrg && (key != AnyKey)) { 1496706f2543Smrg client->errorValue = key; 1497706f2543Smrg return BadValue; 1498706f2543Smrg } 1499706f2543Smrg type = DeviceKeyPress; 1500706f2543Smrg } else if (grabtype == GRABTYPE_XI2) 1501706f2543Smrg type = XI_KeyPress; 1502706f2543Smrg 1503706f2543Smrg rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 1504706f2543Smrg if (rc != Success) 1505706f2543Smrg return rc; 1506706f2543Smrg if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync) 1507706f2543Smrg access_mode |= DixFreezeAccess; 1508706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 1509706f2543Smrg if (rc != Success) 1510706f2543Smrg return rc; 1511706f2543Smrg 1512706f2543Smrg grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, 1513706f2543Smrg mask, param, type, key, NULL, NULL); 1514706f2543Smrg if (!grab) 1515706f2543Smrg return BadAlloc; 1516706f2543Smrg return AddPassiveGrabToList(client, grab); 1517706f2543Smrg} 1518706f2543Smrg 1519706f2543Smrg/* Enter/FocusIn grab */ 1520706f2543Smrgint 1521706f2543SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type, 1522706f2543Smrg GrabParameters *param, GrabMask *mask) 1523706f2543Smrg{ 1524706f2543Smrg WindowPtr pWin; 1525706f2543Smrg CursorPtr cursor; 1526706f2543Smrg GrabPtr grab; 1527706f2543Smrg Mask access_mode = DixGrabAccess; 1528706f2543Smrg int rc; 1529706f2543Smrg 1530706f2543Smrg rc = CheckGrabValues(client, param); 1531706f2543Smrg if (rc != Success) 1532706f2543Smrg return rc; 1533706f2543Smrg 1534706f2543Smrg rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); 1535706f2543Smrg if (rc != Success) 1536706f2543Smrg return rc; 1537706f2543Smrg if (param->cursor == None) 1538706f2543Smrg cursor = NullCursor; 1539706f2543Smrg else { 1540706f2543Smrg rc = dixLookupResourceByType((pointer *)&cursor, param->cursor, 1541706f2543Smrg RT_CURSOR, client, DixUseAccess); 1542706f2543Smrg if (rc != Success) 1543706f2543Smrg { 1544706f2543Smrg client->errorValue = param->cursor; 1545706f2543Smrg return rc; 1546706f2543Smrg } 1547706f2543Smrg access_mode |= DixForceAccess; 1548706f2543Smrg } 1549706f2543Smrg if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync) 1550706f2543Smrg access_mode |= DixFreezeAccess; 1551706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 1552706f2543Smrg if (rc != Success) 1553706f2543Smrg return rc; 1554706f2543Smrg 1555706f2543Smrg grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2, 1556706f2543Smrg mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 1557706f2543Smrg 0, NULL, cursor); 1558706f2543Smrg 1559706f2543Smrg if (!grab) 1560706f2543Smrg return BadAlloc; 1561706f2543Smrg 1562706f2543Smrg return AddPassiveGrabToList(client, grab); 1563706f2543Smrg} 1564706f2543Smrg 1565706f2543Smrgint 1566706f2543SmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, 1567706f2543Smrg Mask mask, Mask exclusivemasks) 1568706f2543Smrg{ 1569706f2543Smrg int mskidx = dev->id; 1570706f2543Smrg int i, ret; 1571706f2543Smrg Mask check; 1572706f2543Smrg InputClientsPtr others; 1573706f2543Smrg 1574706f2543Smrg check = (mask & exclusivemasks); 1575706f2543Smrg if (wOtherInputMasks(pWin)) { 1576706f2543Smrg if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different 1577706f2543Smrg * clients to select on any of the 1578706f2543Smrg * events for maskcheck. However, 1579706f2543Smrg * it is OK, for some client to 1580706f2543Smrg * continue selecting on one of those 1581706f2543Smrg * events. */ 1582706f2543Smrg for (others = wOtherInputMasks(pWin)->inputClients; others; 1583706f2543Smrg others = others->next) { 1584706f2543Smrg if (!SameClient(others, client) && (check & 1585706f2543Smrg others->mask[mskidx])) 1586706f2543Smrg return BadAccess; 1587706f2543Smrg } 1588706f2543Smrg } 1589706f2543Smrg for (others = wOtherInputMasks(pWin)->inputClients; others; 1590706f2543Smrg others = others->next) { 1591706f2543Smrg if (SameClient(others, client)) { 1592706f2543Smrg check = others->mask[mskidx]; 1593706f2543Smrg others->mask[mskidx] = mask; 1594706f2543Smrg if (mask == 0) { 1595706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 1596706f2543Smrg if (i != mskidx && others->mask[i] != 0) 1597706f2543Smrg break; 1598706f2543Smrg if (i == EMASKSIZE) { 1599706f2543Smrg RecalculateDeviceDeliverableEvents(pWin); 1600706f2543Smrg if (ShouldFreeInputMasks(pWin, FALSE)) 1601706f2543Smrg FreeResource(others->resource, RT_NONE); 1602706f2543Smrg return Success; 1603706f2543Smrg } 1604706f2543Smrg } 1605706f2543Smrg goto maskSet; 1606706f2543Smrg } 1607706f2543Smrg } 1608706f2543Smrg } 1609706f2543Smrg check = 0; 1610706f2543Smrg if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success) 1611706f2543Smrg return ret; 1612706f2543Smrg maskSet: 1613706f2543Smrg if (dev->valuator) 1614706f2543Smrg if ((dev->valuator->motionHintWindow == pWin) && 1615706f2543Smrg (mask & DevicePointerMotionHintMask) && 1616706f2543Smrg !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab) 1617706f2543Smrg dev->valuator->motionHintWindow = NullWindow; 1618706f2543Smrg RecalculateDeviceDeliverableEvents(pWin); 1619706f2543Smrg return Success; 1620706f2543Smrg} 1621706f2543Smrg 1622706f2543Smrgint 1623706f2543SmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx) 1624706f2543Smrg{ 1625706f2543Smrg InputClientsPtr others; 1626706f2543Smrg 1627706f2543Smrg if (!pWin->optional && !MakeWindowOptional(pWin)) 1628706f2543Smrg return BadAlloc; 1629706f2543Smrg others = calloc(1, sizeof(InputClients)); 1630706f2543Smrg if (!others) 1631706f2543Smrg return BadAlloc; 1632706f2543Smrg if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) 1633706f2543Smrg goto bail; 1634706f2543Smrg others->mask[mskidx] = mask; 1635706f2543Smrg others->resource = FakeClientID(client->index); 1636706f2543Smrg others->next = pWin->optional->inputMasks->inputClients; 1637706f2543Smrg pWin->optional->inputMasks->inputClients = others; 1638706f2543Smrg if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin)) 1639706f2543Smrg goto bail; 1640706f2543Smrg return Success; 1641706f2543Smrg 1642706f2543Smrgbail: 1643706f2543Smrg free(others); 1644706f2543Smrg return BadAlloc; 1645706f2543Smrg} 1646706f2543Smrg 1647706f2543Smrgstatic Bool 1648706f2543SmrgMakeInputMasks(WindowPtr pWin) 1649706f2543Smrg{ 1650706f2543Smrg struct _OtherInputMasks *imasks; 1651706f2543Smrg 1652706f2543Smrg imasks = calloc(1, sizeof(struct _OtherInputMasks)); 1653706f2543Smrg if (!imasks) 1654706f2543Smrg return FALSE; 1655706f2543Smrg pWin->optional->inputMasks = imasks; 1656706f2543Smrg return TRUE; 1657706f2543Smrg} 1658706f2543Smrg 1659706f2543Smrgvoid 1660706f2543SmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin) 1661706f2543Smrg{ 1662706f2543Smrg InputClientsPtr others; 1663706f2543Smrg struct _OtherInputMasks *inputMasks; /* default: NULL */ 1664706f2543Smrg WindowPtr pChild, tmp; 1665706f2543Smrg int i, j; 1666706f2543Smrg 1667706f2543Smrg pChild = pWin; 1668706f2543Smrg while (1) { 1669706f2543Smrg if ((inputMasks = wOtherInputMasks(pChild)) != 0) { 1670706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 1671706f2543Smrg memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i])); 1672706f2543Smrg for (others = inputMasks->inputClients; others; 1673706f2543Smrg others = others->next) { 1674706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 1675706f2543Smrg inputMasks->inputEvents[i] |= others->mask[i]; 1676706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 1677706f2543Smrg for (j = 0; j < XI2MASKSIZE; j++) 1678706f2543Smrg inputMasks->xi2mask[i][j] |= others->xi2mask[i][j]; 1679706f2543Smrg } 1680706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 1681706f2543Smrg inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; 1682706f2543Smrg for (tmp = pChild->parent; tmp; tmp = tmp->parent) 1683706f2543Smrg if (wOtherInputMasks(tmp)) 1684706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 1685706f2543Smrg inputMasks->deliverableEvents[i] |= 1686706f2543Smrg (wOtherInputMasks(tmp)->deliverableEvents[i] 1687706f2543Smrg & ~inputMasks-> 1688706f2543Smrg dontPropagateMask[i] & PropagateMask[i]); 1689706f2543Smrg } 1690706f2543Smrg if (pChild->firstChild) { 1691706f2543Smrg pChild = pChild->firstChild; 1692706f2543Smrg continue; 1693706f2543Smrg } 1694706f2543Smrg while (!pChild->nextSib && (pChild != pWin)) 1695706f2543Smrg pChild = pChild->parent; 1696706f2543Smrg if (pChild == pWin) 1697706f2543Smrg break; 1698706f2543Smrg pChild = pChild->nextSib; 1699706f2543Smrg } 1700706f2543Smrg} 1701706f2543Smrg 1702706f2543Smrgint 1703706f2543SmrgInputClientGone(WindowPtr pWin, XID id) 1704706f2543Smrg{ 1705706f2543Smrg InputClientsPtr other, prev; 1706706f2543Smrg 1707706f2543Smrg if (!wOtherInputMasks(pWin)) 1708706f2543Smrg return Success; 1709706f2543Smrg prev = 0; 1710706f2543Smrg for (other = wOtherInputMasks(pWin)->inputClients; other; 1711706f2543Smrg other = other->next) { 1712706f2543Smrg if (other->resource == id) { 1713706f2543Smrg if (prev) { 1714706f2543Smrg prev->next = other->next; 1715706f2543Smrg free(other); 1716706f2543Smrg } else if (!(other->next)) { 1717706f2543Smrg if (ShouldFreeInputMasks(pWin, TRUE)) { 1718706f2543Smrg wOtherInputMasks(pWin)->inputClients = other->next; 1719706f2543Smrg free(wOtherInputMasks(pWin)); 1720706f2543Smrg pWin->optional->inputMasks = (OtherInputMasks *) NULL; 1721706f2543Smrg CheckWindowOptionalNeed(pWin); 1722706f2543Smrg free(other); 1723706f2543Smrg } else { 1724706f2543Smrg other->resource = FakeClientID(0); 1725706f2543Smrg if (!AddResource(other->resource, RT_INPUTCLIENT, 1726706f2543Smrg (pointer) pWin)) 1727706f2543Smrg return BadAlloc; 1728706f2543Smrg } 1729706f2543Smrg } else { 1730706f2543Smrg wOtherInputMasks(pWin)->inputClients = other->next; 1731706f2543Smrg free(other); 1732706f2543Smrg } 1733706f2543Smrg RecalculateDeviceDeliverableEvents(pWin); 1734706f2543Smrg return Success; 1735706f2543Smrg } 1736706f2543Smrg prev = other; 1737706f2543Smrg } 1738706f2543Smrg FatalError("client not on device event list"); 1739706f2543Smrg} 1740706f2543Smrg 1741706f2543Smrgint 1742706f2543SmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, 1743706f2543Smrg xEvent * ev, Mask mask, int count) 1744706f2543Smrg{ 1745706f2543Smrg WindowPtr pWin; 1746706f2543Smrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 1747706f2543Smrg WindowPtr spriteWin = GetSpriteWindow(d); 1748706f2543Smrg 1749706f2543Smrg if (dest == PointerWindow) 1750706f2543Smrg pWin = spriteWin; 1751706f2543Smrg else if (dest == InputFocus) { 1752706f2543Smrg WindowPtr inputFocus; 1753706f2543Smrg 1754706f2543Smrg if (!d->focus) 1755706f2543Smrg inputFocus = spriteWin; 1756706f2543Smrg else 1757706f2543Smrg inputFocus = d->focus->win; 1758706f2543Smrg 1759706f2543Smrg if (inputFocus == FollowKeyboardWin) 1760706f2543Smrg inputFocus = inputInfo.keyboard->focus->win; 1761706f2543Smrg 1762706f2543Smrg if (inputFocus == NoneWin) 1763706f2543Smrg return Success; 1764706f2543Smrg 1765706f2543Smrg /* If the input focus is PointerRootWin, send the event to where 1766706f2543Smrg * the pointer is if possible, then perhaps propogate up to root. */ 1767706f2543Smrg if (inputFocus == PointerRootWin) 1768706f2543Smrg inputFocus = GetCurrentRootWindow(d); 1769706f2543Smrg 1770706f2543Smrg if (IsParent(inputFocus, spriteWin)) { 1771706f2543Smrg effectiveFocus = inputFocus; 1772706f2543Smrg pWin = spriteWin; 1773706f2543Smrg } else 1774706f2543Smrg effectiveFocus = pWin = inputFocus; 1775706f2543Smrg } else 1776706f2543Smrg dixLookupWindow(&pWin, dest, client, DixSendAccess); 1777706f2543Smrg if (!pWin) 1778706f2543Smrg return BadWindow; 1779706f2543Smrg if ((propagate != xFalse) && (propagate != xTrue)) { 1780706f2543Smrg client->errorValue = propagate; 1781706f2543Smrg return BadValue; 1782706f2543Smrg } 1783706f2543Smrg ev->u.u.type |= 0x80; 1784706f2543Smrg if (propagate) { 1785706f2543Smrg for (; pWin; pWin = pWin->parent) { 1786706f2543Smrg if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab)) 1787706f2543Smrg return Success; 1788706f2543Smrg if (pWin == effectiveFocus) 1789706f2543Smrg return Success; 1790706f2543Smrg if (wOtherInputMasks(pWin)) 1791706f2543Smrg mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id]; 1792706f2543Smrg if (!mask) 1793706f2543Smrg break; 1794706f2543Smrg } 1795706f2543Smrg } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count)) 1796706f2543Smrg DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab); 1797706f2543Smrg return Success; 1798706f2543Smrg} 1799706f2543Smrg 1800706f2543Smrgint 1801706f2543SmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) 1802706f2543Smrg{ 1803706f2543Smrg int i; 1804706f2543Smrg ButtonClassPtr b = dev->button; 1805706f2543Smrg 1806706f2543Smrg if (b == NULL) 1807706f2543Smrg return BadMatch; 1808706f2543Smrg 1809706f2543Smrg if (nElts != b->numButtons) { 1810706f2543Smrg client->errorValue = nElts; 1811706f2543Smrg return BadValue; 1812706f2543Smrg } 1813706f2543Smrg if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue)) 1814706f2543Smrg return BadValue; 1815706f2543Smrg for (i = 0; i < nElts; i++) 1816706f2543Smrg if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)) 1817706f2543Smrg return MappingBusy; 1818706f2543Smrg for (i = 0; i < nElts; i++) 1819706f2543Smrg b->map[i + 1] = map[i]; 1820706f2543Smrg return Success; 1821706f2543Smrg} 1822706f2543Smrg 1823706f2543Smrgint 1824706f2543SmrgChangeKeyMapping(ClientPtr client, 1825706f2543Smrg DeviceIntPtr dev, 1826706f2543Smrg unsigned len, 1827706f2543Smrg int type, 1828706f2543Smrg KeyCode firstKeyCode, 1829706f2543Smrg CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map) 1830706f2543Smrg{ 1831706f2543Smrg KeySymsRec keysyms; 1832706f2543Smrg KeyClassPtr k = dev->key; 1833706f2543Smrg 1834706f2543Smrg if (k == NULL) 1835706f2543Smrg return BadMatch; 1836706f2543Smrg 1837706f2543Smrg if (len != (keyCodes * keySymsPerKeyCode)) 1838706f2543Smrg return BadLength; 1839706f2543Smrg 1840706f2543Smrg if ((firstKeyCode < k->xkbInfo->desc->min_key_code) || 1841706f2543Smrg (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) { 1842706f2543Smrg client->errorValue = firstKeyCode; 1843706f2543Smrg return BadValue; 1844706f2543Smrg } 1845706f2543Smrg if (keySymsPerKeyCode == 0) { 1846706f2543Smrg client->errorValue = 0; 1847706f2543Smrg return BadValue; 1848706f2543Smrg } 1849706f2543Smrg keysyms.minKeyCode = firstKeyCode; 1850706f2543Smrg keysyms.maxKeyCode = firstKeyCode + keyCodes - 1; 1851706f2543Smrg keysyms.mapWidth = keySymsPerKeyCode; 1852706f2543Smrg keysyms.map = map; 1853706f2543Smrg 1854706f2543Smrg XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL, 1855706f2543Smrg serverClient); 1856706f2543Smrg 1857706f2543Smrg return Success; 1858706f2543Smrg} 1859706f2543Smrg 1860706f2543Smrgstatic void 1861706f2543SmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) 1862706f2543Smrg{ 1863706f2543Smrg WindowPtr parent; 1864706f2543Smrg 1865706f2543Smrg /* Deactivate any grabs performed on this window, before making 1866706f2543Smrg * any input focus changes. 1867706f2543Smrg * Deactivating a device grab should cause focus events. */ 1868706f2543Smrg 1869706f2543Smrg if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin)) 1870706f2543Smrg (*dev->deviceGrab.DeactivateGrab) (dev); 1871706f2543Smrg 1872706f2543Smrg /* If the focus window is a root window (ie. has no parent) 1873706f2543Smrg * then don't delete the focus from it. */ 1874706f2543Smrg 1875706f2543Smrg if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) { 1876706f2543Smrg int focusEventMode = NotifyNormal; 1877706f2543Smrg 1878706f2543Smrg /* If a grab is in progress, then alter the mode of focus events. */ 1879706f2543Smrg 1880706f2543Smrg if (dev->deviceGrab.grab) 1881706f2543Smrg focusEventMode = NotifyWhileGrabbed; 1882706f2543Smrg 1883706f2543Smrg switch (dev->focus->revert) { 1884706f2543Smrg case RevertToNone: 1885706f2543Smrg if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 1886706f2543Smrg DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 1887706f2543Smrg dev->focus->win = NoneWin; 1888706f2543Smrg dev->focus->traceGood = 0; 1889706f2543Smrg break; 1890706f2543Smrg case RevertToParent: 1891706f2543Smrg parent = pWin; 1892706f2543Smrg do { 1893706f2543Smrg parent = parent->parent; 1894706f2543Smrg dev->focus->traceGood--; 1895706f2543Smrg } 1896706f2543Smrg while (!parent->realized); 1897706f2543Smrg if (!ActivateFocusInGrab(dev, pWin, parent)) 1898706f2543Smrg DoFocusEvents(dev, pWin, parent, focusEventMode); 1899706f2543Smrg dev->focus->win = parent; 1900706f2543Smrg dev->focus->revert = RevertToNone; 1901706f2543Smrg break; 1902706f2543Smrg case RevertToPointerRoot: 1903706f2543Smrg if (!ActivateFocusInGrab(dev, pWin, PointerRootWin)) 1904706f2543Smrg DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode); 1905706f2543Smrg dev->focus->win = PointerRootWin; 1906706f2543Smrg dev->focus->traceGood = 0; 1907706f2543Smrg break; 1908706f2543Smrg case RevertToFollowKeyboard: 1909706f2543Smrg { 1910706f2543Smrg DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD); 1911706f2543Smrg if (!kbd || (kbd == dev && kbd != inputInfo.keyboard)) 1912706f2543Smrg kbd = inputInfo.keyboard; 1913706f2543Smrg if (kbd->focus->win) { 1914706f2543Smrg if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win)) 1915706f2543Smrg DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode); 1916706f2543Smrg dev->focus->win = FollowKeyboardWin; 1917706f2543Smrg dev->focus->traceGood = 0; 1918706f2543Smrg } else { 1919706f2543Smrg if (!ActivateFocusInGrab(dev, pWin, NoneWin)) 1920706f2543Smrg DoFocusEvents(dev, pWin, NoneWin, focusEventMode); 1921706f2543Smrg dev->focus->win = NoneWin; 1922706f2543Smrg dev->focus->traceGood = 0; 1923706f2543Smrg } 1924706f2543Smrg } 1925706f2543Smrg break; 1926706f2543Smrg } 1927706f2543Smrg } 1928706f2543Smrg 1929706f2543Smrg if (dev->valuator) 1930706f2543Smrg if (dev->valuator->motionHintWindow == pWin) 1931706f2543Smrg dev->valuator->motionHintWindow = NullWindow; 1932706f2543Smrg} 1933706f2543Smrg 1934706f2543Smrgvoid 1935706f2543SmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources) 1936706f2543Smrg{ 1937706f2543Smrg int i; 1938706f2543Smrg DeviceIntPtr dev; 1939706f2543Smrg InputClientsPtr ic; 1940706f2543Smrg struct _OtherInputMasks *inputMasks; 1941706f2543Smrg 1942706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) { 1943706f2543Smrg DeleteDeviceFromAnyExtEvents(pWin, dev); 1944706f2543Smrg } 1945706f2543Smrg 1946706f2543Smrg for (dev = inputInfo.off_devices; dev; dev = dev->next) 1947706f2543Smrg DeleteDeviceFromAnyExtEvents(pWin, dev); 1948706f2543Smrg 1949706f2543Smrg if (freeResources) 1950706f2543Smrg while ((inputMasks = wOtherInputMasks(pWin)) != 0) { 1951706f2543Smrg ic = inputMasks->inputClients; 1952706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 1953706f2543Smrg inputMasks->dontPropagateMask[i] = 0; 1954706f2543Smrg FreeResource(ic->resource, RT_NONE); 1955706f2543Smrg } 1956706f2543Smrg} 1957706f2543Smrg 1958706f2543Smrgint 1959706f2543SmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask) 1960706f2543Smrg{ 1961706f2543Smrg DeviceIntPtr dev; 1962706f2543Smrg 1963706f2543Smrg dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient, 1964706f2543Smrg DixReadAccess); 1965706f2543Smrg if (!dev) 1966706f2543Smrg return 0; 1967706f2543Smrg 1968706f2543Smrg if (pEvents->type == DeviceMotionNotify) { 1969706f2543Smrg if (mask & DevicePointerMotionHintMask) { 1970706f2543Smrg if (WID(dev->valuator->motionHintWindow) == pEvents->event) { 1971706f2543Smrg return 1; /* don't send, but pretend we did */ 1972706f2543Smrg } 1973706f2543Smrg pEvents->detail = NotifyHint; 1974706f2543Smrg } else { 1975706f2543Smrg pEvents->detail = NotifyNormal; 1976706f2543Smrg } 1977706f2543Smrg } 1978706f2543Smrg return 0; 1979706f2543Smrg} 1980706f2543Smrg 1981706f2543Smrgvoid 1982706f2543SmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, 1983706f2543Smrg deviceKeyButtonPointer * xE, GrabPtr grab, 1984706f2543Smrg ClientPtr client, Mask deliveryMask) 1985706f2543Smrg{ 1986706f2543Smrg DeviceIntPtr dev; 1987706f2543Smrg 1988706f2543Smrg dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient, 1989706f2543Smrg DixGrabAccess); 1990706f2543Smrg if (!dev) 1991706f2543Smrg return; 1992706f2543Smrg 1993706f2543Smrg if (type == DeviceMotionNotify) 1994706f2543Smrg dev->valuator->motionHintWindow = pWin; 1995706f2543Smrg else if ((type == DeviceButtonPress) && (!grab) && 1996706f2543Smrg (deliveryMask & DeviceButtonGrabMask)) { 1997706f2543Smrg GrabRec tempGrab; 1998706f2543Smrg 1999706f2543Smrg tempGrab.device = dev; 2000706f2543Smrg tempGrab.resource = client->clientAsMask; 2001706f2543Smrg tempGrab.window = pWin; 2002706f2543Smrg tempGrab.ownerEvents = 2003706f2543Smrg (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; 2004706f2543Smrg tempGrab.eventMask = deliveryMask; 2005706f2543Smrg tempGrab.keyboardMode = GrabModeAsync; 2006706f2543Smrg tempGrab.pointerMode = GrabModeAsync; 2007706f2543Smrg tempGrab.confineTo = NullWindow; 2008706f2543Smrg tempGrab.cursor = NullCursor; 2009706f2543Smrg tempGrab.next = NULL; 2010706f2543Smrg (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE); 2011706f2543Smrg } 2012706f2543Smrg} 2013706f2543Smrg 2014706f2543Smrgstatic Mask 2015706f2543SmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client) 2016706f2543Smrg{ 2017706f2543Smrg InputClientsPtr other; 2018706f2543Smrg 2019706f2543Smrg if (!wOtherInputMasks(pWin)) 2020706f2543Smrg return 0; 2021706f2543Smrg for (other = wOtherInputMasks(pWin)->inputClients; other; 2022706f2543Smrg other = other->next) { 2023706f2543Smrg if (SameClient(other, client)) 2024706f2543Smrg return other->mask[dev->id]; 2025706f2543Smrg } 2026706f2543Smrg return 0; 2027706f2543Smrg} 2028706f2543Smrg 2029706f2543Smrgvoid 2030706f2543SmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client) 2031706f2543Smrg{ 2032706f2543Smrg WindowPtr pWin; 2033706f2543Smrg GrabPtr grab = dev->deviceGrab.grab; 2034706f2543Smrg 2035706f2543Smrg pWin = dev->valuator->motionHintWindow; 2036706f2543Smrg 2037706f2543Smrg if ((grab && SameClient(grab, client) && 2038706f2543Smrg ((grab->eventMask & DevicePointerMotionHintMask) || 2039706f2543Smrg (grab->ownerEvents && 2040706f2543Smrg (DeviceEventMaskForClient(dev, pWin, client) & 2041706f2543Smrg DevicePointerMotionHintMask)))) || 2042706f2543Smrg (!grab && 2043706f2543Smrg (DeviceEventMaskForClient(dev, pWin, client) & 2044706f2543Smrg DevicePointerMotionHintMask))) 2045706f2543Smrg dev->valuator->motionHintWindow = NullWindow; 2046706f2543Smrg} 2047706f2543Smrg 2048706f2543Smrgint 2049706f2543SmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, 2050706f2543Smrg int maskndx) 2051706f2543Smrg{ 2052706f2543Smrg struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 2053706f2543Smrg 2054706f2543Smrg if (mask & ~PropagateMask[maskndx]) { 2055706f2543Smrg client->errorValue = mask; 2056706f2543Smrg return BadValue; 2057706f2543Smrg } 2058706f2543Smrg 2059706f2543Smrg if (mask == 0) { 2060706f2543Smrg if (inputMasks) 2061706f2543Smrg inputMasks->dontPropagateMask[maskndx] = mask; 2062706f2543Smrg } else { 2063706f2543Smrg if (!inputMasks) 2064706f2543Smrg AddExtensionClient(pWin, client, 0, 0); 2065706f2543Smrg inputMasks = wOtherInputMasks(pWin); 2066706f2543Smrg inputMasks->dontPropagateMask[maskndx] = mask; 2067706f2543Smrg } 2068706f2543Smrg RecalculateDeviceDeliverableEvents(pWin); 2069706f2543Smrg if (ShouldFreeInputMasks(pWin, FALSE)) 2070706f2543Smrg FreeResource(inputMasks->inputClients->resource, RT_NONE); 2071706f2543Smrg return Success; 2072706f2543Smrg} 2073706f2543Smrg 2074706f2543SmrgBool 2075706f2543SmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents) 2076706f2543Smrg{ 2077706f2543Smrg int i; 2078706f2543Smrg Mask allInputEventMasks = 0; 2079706f2543Smrg struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 2080706f2543Smrg 2081706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 2082706f2543Smrg allInputEventMasks |= inputMasks->dontPropagateMask[i]; 2083706f2543Smrg if (!ignoreSelectedEvents) 2084706f2543Smrg for (i = 0; i < EMASKSIZE; i++) 2085706f2543Smrg allInputEventMasks |= inputMasks->inputEvents[i]; 2086706f2543Smrg if (allInputEventMasks == 0) 2087706f2543Smrg return TRUE; 2088706f2543Smrg else 2089706f2543Smrg return FALSE; 2090706f2543Smrg} 2091706f2543Smrg 2092706f2543Smrg/*********************************************************************** 2093706f2543Smrg * 2094706f2543Smrg * Walk through the window tree, finding all clients that want to know 2095706f2543Smrg * about the Event. 2096706f2543Smrg * 2097706f2543Smrg */ 2098706f2543Smrg 2099706f2543Smrgstatic void 2100706f2543SmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, 2101706f2543Smrg xEvent * ev, int count) 2102706f2543Smrg{ 2103706f2543Smrg WindowPtr p2; 2104706f2543Smrg 2105706f2543Smrg while (p1) { 2106706f2543Smrg p2 = p1->firstChild; 2107706f2543Smrg DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab); 2108706f2543Smrg FindInterestedChildren(dev, p2, mask, ev, count); 2109706f2543Smrg p1 = p1->nextSib; 2110706f2543Smrg } 2111706f2543Smrg} 2112706f2543Smrg 2113706f2543Smrg/*********************************************************************** 2114706f2543Smrg * 2115706f2543Smrg * Send an event to interested clients in all windows on all screens. 2116706f2543Smrg * 2117706f2543Smrg */ 2118706f2543Smrg 2119706f2543Smrgvoid 2120706f2543SmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count) 2121706f2543Smrg{ 2122706f2543Smrg int i; 2123706f2543Smrg WindowPtr pWin, p1; 2124706f2543Smrg 2125706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) { 2126706f2543Smrg pWin = screenInfo.screens[i]->root; 2127706f2543Smrg if (!pWin) 2128706f2543Smrg continue; 2129706f2543Smrg DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab); 2130706f2543Smrg p1 = pWin->firstChild; 2131706f2543Smrg FindInterestedChildren(dev, p1, mask, ev, count); 2132706f2543Smrg } 2133706f2543Smrg} 2134706f2543Smrg 2135706f2543Smrg/** 2136706f2543Smrg * Set the XI2 mask for the given client on the given window. 2137706f2543Smrg * @param dev The device to set the mask for. 2138706f2543Smrg * @param win The window to set the mask on. 2139706f2543Smrg * @param client The client setting the mask. 2140706f2543Smrg * @param len Number of bytes in mask. 2141706f2543Smrg * @param mask Event mask in the form of (1 << eventtype) 2142706f2543Smrg */ 2143706f2543Smrgint 2144706f2543SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, 2145706f2543Smrg unsigned int len, unsigned char* mask) 2146706f2543Smrg{ 2147706f2543Smrg OtherInputMasks *masks; 2148706f2543Smrg InputClientsPtr others = NULL; 2149706f2543Smrg 2150706f2543Smrg masks = wOtherInputMasks(win); 2151706f2543Smrg if (masks) 2152706f2543Smrg { 2153706f2543Smrg for (others = wOtherInputMasks(win)->inputClients; others; 2154706f2543Smrg others = others->next) { 2155706f2543Smrg if (SameClient(others, client)) { 2156706f2543Smrg memset(others->xi2mask[dev->id], 0, 2157706f2543Smrg sizeof(others->xi2mask[dev->id])); 2158706f2543Smrg break; 2159706f2543Smrg } 2160706f2543Smrg } 2161706f2543Smrg } 2162706f2543Smrg 2163706f2543Smrg len = min(len, sizeof(others->xi2mask[dev->id])); 2164706f2543Smrg 2165706f2543Smrg if (len && !others) 2166706f2543Smrg { 2167706f2543Smrg if (AddExtensionClient(win, client, 0, 0) != Success) 2168706f2543Smrg return BadAlloc; 2169706f2543Smrg others= wOtherInputMasks(win)->inputClients; 2170706f2543Smrg } 2171706f2543Smrg 2172706f2543Smrg if (others) 2173706f2543Smrg memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id])); 2174706f2543Smrg 2175706f2543Smrg if (len) 2176706f2543Smrg memcpy(others->xi2mask[dev->id], mask, len); 2177706f2543Smrg 2178706f2543Smrg RecalculateDeviceDeliverableEvents(win); 2179706f2543Smrg 2180706f2543Smrg return Success; 2181706f2543Smrg} 2182