12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071 |
- /************************************************************
- Copyright 1989, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Hewlett-Packard not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ********************************************************/
- /*
- * Copyright © 2010 Collabora Ltd.
- * Copyright © 2011 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Daniel Stone <daniel@fooishbar.org>
- */
- /********************************************************************
- *
- * Routines to register and initialize extension input devices.
- * This also contains ProcessOtherEvent, the routine called from DDX
- * to route extension events.
- *
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "inputstr.h"
- #include <X11/X.h>
- #include <X11/Xproto.h>
- #include <X11/extensions/XI.h>
- #include <X11/extensions/XIproto.h>
- #include <X11/extensions/XI2proto.h>
- #include <X11/extensions/geproto.h>
- #include "windowstr.h"
- #include "miscstruct.h"
- #include "region.h"
- #include "exevents.h"
- #include "extnsionst.h"
- #include "exglobals.h"
- #include "dixevents.h" /* DeliverFocusedEvent */
- #include "dixgrabs.h" /* CreateGrab() */
- #include "scrnintstr.h"
- #include "listdev.h" /* for CopySwapXXXClass */
- #include "xace.h"
- #include "xiquerydevice.h" /* For List*Info */
- #include "eventconvert.h"
- #include "eventstr.h"
- #include "inpututils.h"
- #include "mi.h"
- #include <X11/extensions/XKBproto.h>
- #include "xkbsrv.h"
- #define WID(w) ((w) ? ((w)->drawable.id) : 0)
- #define AllModifiersMask ( \
- ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
- Mod3Mask | Mod4Mask | Mod5Mask )
- #define AllButtonsMask ( \
- Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
- Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
- Bool /* ignoreSelectedEvents */
- );
- static Bool MakeInputMasks(WindowPtr /* pWin */
- );
- /*
- * Only let the given client know of core events which will affect its
- * interpretation of input events, if the client's ClientPointer (or the
- * paired keyboard) is the current device.
- */
- int
- XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
- {
- DeviceIntPtr current_ptr = PickPointer(client);
- DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT);
- if (dev == current_kbd || dev == current_ptr)
- return 1;
- return 0;
- }
- Bool
- IsPointerEvent(InternalEvent *event)
- {
- switch (event->any.type) {
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_Motion:
- /* XXX: enter/leave ?? */
- return TRUE;
- default:
- break;
- }
- return FALSE;
- }
- Bool
- IsTouchEvent(InternalEvent *event)
- {
- switch (event->any.type) {
- case ET_TouchBegin:
- case ET_TouchUpdate:
- case ET_TouchEnd:
- return TRUE;
- default:
- break;
- }
- return FALSE;
- }
- /**
- * @return the device matching the deviceid of the device set in the event, or
- * NULL if the event is not an XInput event.
- */
- DeviceIntPtr
- XIGetDevice(xEvent *xE)
- {
- DeviceIntPtr pDev = NULL;
- if (xE->u.u.type == DeviceButtonPress ||
- xE->u.u.type == DeviceButtonRelease ||
- xE->u.u.type == DeviceMotionNotify ||
- xE->u.u.type == ProximityIn ||
- xE->u.u.type == ProximityOut || xE->u.u.type == DevicePropertyNotify) {
- int rc;
- int id;
- id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS;
- rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
- if (rc != Success)
- ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
- }
- return pDev;
- }
- /**
- * Copy the device->key into master->key and send a mapping notify to the
- * clients if appropriate.
- * master->key needs to be allocated by the caller.
- *
- * Device is the slave device. If it is attached to a master device, we may
- * need to send a mapping notify to the client because it causes the MD
- * to change state.
- *
- * Mapping notify needs to be sent in the following cases:
- * - different slave device on same master
- * - different master
- *
- * XXX: They way how the code is we also send a map notify if the slave device
- * stays the same, but the master changes. This isn't really necessary though.
- *
- * XXX: this gives you funny behaviour with the ClientPointer. When a
- * MappingNotify is sent to the client, the client usually responds with a
- * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
- * mapping, regardless of which keyboard sent the last mapping notify request.
- * So depending on the CP setting, your keyboard may change layout in each
- * app...
- *
- * This code is basically the old SwitchCoreKeyboard.
- */
- void
- CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
- {
- KeyClassPtr mk = master->key;
- if (device == master)
- return;
- mk->sourceid = device->id;
- if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc))
- FatalError("Couldn't pivot keymap from device to core!\n");
- }
- /**
- * Copies the feedback classes from device "from" into device "to". Classes
- * are duplicated (not just flipping the pointers). All feedback classes are
- * linked lists, the full list is duplicated.
- */
- static void
- DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
- {
- ClassesPtr classes;
- if (from->intfeed) {
- IntegerFeedbackPtr *i, it;
- if (!to->intfeed) {
- classes = to->unused_classes;
- to->intfeed = classes->intfeed;
- classes->intfeed = NULL;
- }
- i = &to->intfeed;
- for (it = from->intfeed; it; it = it->next) {
- if (!(*i)) {
- *i = calloc(1, sizeof(IntegerFeedbackClassRec));
- if (!(*i)) {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*i)->CtrlProc = it->CtrlProc;
- (*i)->ctrl = it->ctrl;
- i = &(*i)->next;
- }
- }
- else if (to->intfeed && !from->intfeed) {
- classes = to->unused_classes;
- classes->intfeed = to->intfeed;
- to->intfeed = NULL;
- }
- if (from->stringfeed) {
- StringFeedbackPtr *s, it;
- if (!to->stringfeed) {
- classes = to->unused_classes;
- to->stringfeed = classes->stringfeed;
- classes->stringfeed = NULL;
- }
- s = &to->stringfeed;
- for (it = from->stringfeed; it; it = it->next) {
- if (!(*s)) {
- *s = calloc(1, sizeof(StringFeedbackClassRec));
- if (!(*s)) {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*s)->CtrlProc = it->CtrlProc;
- (*s)->ctrl = it->ctrl;
- s = &(*s)->next;
- }
- }
- else if (to->stringfeed && !from->stringfeed) {
- classes = to->unused_classes;
- classes->stringfeed = to->stringfeed;
- to->stringfeed = NULL;
- }
- if (from->bell) {
- BellFeedbackPtr *b, it;
- if (!to->bell) {
- classes = to->unused_classes;
- to->bell = classes->bell;
- classes->bell = NULL;
- }
- b = &to->bell;
- for (it = from->bell; it; it = it->next) {
- if (!(*b)) {
- *b = calloc(1, sizeof(BellFeedbackClassRec));
- if (!(*b)) {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*b)->BellProc = it->BellProc;
- (*b)->CtrlProc = it->CtrlProc;
- (*b)->ctrl = it->ctrl;
- b = &(*b)->next;
- }
- }
- else if (to->bell && !from->bell) {
- classes = to->unused_classes;
- classes->bell = to->bell;
- to->bell = NULL;
- }
- if (from->leds) {
- LedFeedbackPtr *l, it;
- if (!to->leds) {
- classes = to->unused_classes;
- to->leds = classes->leds;
- classes->leds = NULL;
- }
- l = &to->leds;
- for (it = from->leds; it; it = it->next) {
- if (!(*l)) {
- *l = calloc(1, sizeof(LedFeedbackClassRec));
- if (!(*l)) {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*l)->CtrlProc = it->CtrlProc;
- (*l)->ctrl = it->ctrl;
- if ((*l)->xkb_sli)
- XkbFreeSrvLedInfo((*l)->xkb_sli);
- (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
- l = &(*l)->next;
- }
- }
- else if (to->leds && !from->leds) {
- classes = to->unused_classes;
- classes->leds = to->leds;
- to->leds = NULL;
- }
- }
- static void
- DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
- {
- ClassesPtr classes;
- /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
- * kbdfeed to be set up properly, so let's do the feedback classes first.
- */
- if (from->kbdfeed) {
- KbdFeedbackPtr *k, it;
- if (!to->kbdfeed) {
- classes = to->unused_classes;
- to->kbdfeed = classes->kbdfeed;
- if (!to->kbdfeed)
- InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
- classes->kbdfeed = NULL;
- }
- k = &to->kbdfeed;
- for (it = from->kbdfeed; it; it = it->next) {
- if (!(*k)) {
- *k = calloc(1, sizeof(KbdFeedbackClassRec));
- if (!*k) {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*k)->BellProc = it->BellProc;
- (*k)->CtrlProc = it->CtrlProc;
- (*k)->ctrl = it->ctrl;
- if ((*k)->xkb_sli)
- XkbFreeSrvLedInfo((*k)->xkb_sli);
- (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
- k = &(*k)->next;
- }
- }
- else if (to->kbdfeed && !from->kbdfeed) {
- classes = to->unused_classes;
- classes->kbdfeed = to->kbdfeed;
- to->kbdfeed = NULL;
- }
- if (from->key) {
- if (!to->key) {
- classes = to->unused_classes;
- to->key = classes->key;
- if (!to->key)
- InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
- else
- classes->key = NULL;
- }
- CopyKeyClass(from, to);
- }
- else if (to->key && !from->key) {
- classes = to->unused_classes;
- classes->key = to->key;
- to->key = NULL;
- }
- /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
- * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
- * didn't update the pointers so we need to do it manually here.
- */
- if (to->kbdfeed) {
- KbdFeedbackPtr k;
- for (k = to->kbdfeed; k; k = k->next) {
- if (!k->xkb_sli)
- continue;
- if (k->xkb_sli->flags & XkbSLI_IsDefault) {
- k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
- k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
- }
- }
- }
- /* We can't just copy over the focus class. When an app sets the focus,
- * it'll do so on the master device. Copying the SDs focus means losing
- * the focus.
- * So we only copy the focus class if the device didn't have one,
- * otherwise we leave it as it is.
- */
- if (from->focus) {
- if (!to->focus) {
- WindowPtr *oldTrace;
- classes = to->unused_classes;
- to->focus = classes->focus;
- if (!to->focus) {
- to->focus = calloc(1, sizeof(FocusClassRec));
- if (!to->focus)
- FatalError("[Xi] no memory for class shift.\n");
- }
- else
- classes->focus = NULL;
- oldTrace = to->focus->trace;
- memcpy(to->focus, from->focus, sizeof(FocusClassRec));
- to->focus->trace = realloc(oldTrace,
- to->focus->traceSize *
- sizeof(WindowPtr));
- if (!to->focus->trace && to->focus->traceSize)
- FatalError("[Xi] no memory for trace.\n");
- memcpy(to->focus->trace, from->focus->trace,
- from->focus->traceSize * sizeof(WindowPtr));
- to->focus->sourceid = from->id;
- }
- }
- else if (to->focus) {
- classes = to->unused_classes;
- classes->focus = to->focus;
- to->focus = NULL;
- }
- }
- /* FIXME: this should really be shared with the InitValuatorAxisClassRec and
- * similar */
- static void
- DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
- {
- ClassesPtr classes;
- /* Feedback classes must be copied first */
- if (from->ptrfeed) {
- PtrFeedbackPtr *p, it;
- if (!to->ptrfeed) {
- classes = to->unused_classes;
- to->ptrfeed = classes->ptrfeed;
- classes->ptrfeed = NULL;
- }
- p = &to->ptrfeed;
- for (it = from->ptrfeed; it; it = it->next) {
- if (!(*p)) {
- *p = calloc(1, sizeof(PtrFeedbackClassRec));
- if (!*p) {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*p)->CtrlProc = it->CtrlProc;
- (*p)->ctrl = it->ctrl;
- p = &(*p)->next;
- }
- }
- else if (to->ptrfeed && !from->ptrfeed) {
- classes = to->unused_classes;
- classes->ptrfeed = to->ptrfeed;
- to->ptrfeed = NULL;
- }
- if (from->valuator) {
- ValuatorClassPtr v;
- if (!to->valuator) {
- classes = to->unused_classes;
- to->valuator = classes->valuator;
- if (to->valuator)
- classes->valuator = NULL;
- }
- v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
- if (!v)
- FatalError("[Xi] no memory for class shift.\n");
- to->valuator = v;
- memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
- v->sourceid = from->id;
- }
- else if (to->valuator && !from->valuator) {
- classes = to->unused_classes;
- classes->valuator = to->valuator;
- to->valuator = NULL;
- }
- if (from->button) {
- if (!to->button) {
- classes = to->unused_classes;
- to->button = classes->button;
- if (!to->button) {
- to->button = calloc(1, sizeof(ButtonClassRec));
- if (!to->button)
- FatalError("[Xi] no memory for class shift.\n");
- }
- else
- classes->button = NULL;
- }
- if (from->button->xkb_acts) {
- if (!to->button->xkb_acts) {
- to->button->xkb_acts = calloc(1, sizeof(XkbAction));
- if (!to->button->xkb_acts)
- FatalError("[Xi] not enough memory for xkb_acts.\n");
- }
- memcpy(to->button->xkb_acts, from->button->xkb_acts,
- sizeof(XkbAction));
- }
- else
- free(to->button->xkb_acts);
- memcpy(to->button->labels, from->button->labels,
- from->button->numButtons * sizeof(Atom));
- to->button->sourceid = from->id;
- }
- else if (to->button && !from->button) {
- classes = to->unused_classes;
- classes->button = to->button;
- to->button = NULL;
- }
- if (from->proximity) {
- if (!to->proximity) {
- classes = to->unused_classes;
- to->proximity = classes->proximity;
- if (!to->proximity) {
- to->proximity = calloc(1, sizeof(ProximityClassRec));
- if (!to->proximity)
- FatalError("[Xi] no memory for class shift.\n");
- }
- else
- classes->proximity = NULL;
- }
- memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
- to->proximity->sourceid = from->id;
- }
- else if (to->proximity) {
- classes = to->unused_classes;
- classes->proximity = to->proximity;
- to->proximity = NULL;
- }
- if (from->touch) {
- TouchClassPtr t, f;
- if (!to->touch) {
- classes = to->unused_classes;
- to->touch = classes->touch;
- if (!to->touch) {
- int i;
- to->touch = calloc(1, sizeof(TouchClassRec));
- if (!to->touch)
- FatalError("[Xi] no memory for class shift.\n");
- to->touch->num_touches = from->touch->num_touches;
- to->touch->touches = calloc(to->touch->num_touches,
- sizeof(TouchPointInfoRec));
- for (i = 0; i < to->touch->num_touches; i++)
- TouchInitTouchPoint(to->touch, to->valuator, i);
- if (!to->touch)
- FatalError("[Xi] no memory for class shift.\n");
- }
- else
- classes->touch = NULL;
- }
- t = to->touch;
- f = from->touch;
- t->sourceid = f->sourceid;
- t->max_touches = f->max_touches;
- t->mode = f->mode;
- t->buttonsDown = f->buttonsDown;
- t->state = f->state;
- t->motionMask = f->motionMask;
- /* to->touches and to->num_touches are separate on the master,
- * don't copy */
- }
- /* Don't remove touch class if from->touch is non-existent. The to device
- * may have an active touch grab, so we need to keep the touch class record
- * around. */
- }
- /**
- * Copies the CONTENT of the classes of device from into the classes in device
- * to. From and to are identical after finishing.
- *
- * If to does not have classes from currenly has, the classes are stored in
- * to's devPrivates system. Later, we recover it again from there if needed.
- * Saves a few memory allocations.
- */
- void
- DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
- DeviceChangedEvent *dce)
- {
- OsBlockSIGIO();
- /* generic feedback classes, not tied to pointer and/or keyboard */
- DeepCopyFeedbackClasses(from, to);
- if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
- DeepCopyKeyboardClasses(from, to);
- if ((dce->flags & DEVCHANGE_POINTER_EVENT))
- DeepCopyPointerClasses(from, to);
- OsReleaseSIGIO();
- }
- /**
- * Send an XI2 DeviceChangedEvent to all interested clients.
- */
- void
- XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
- {
- xXIDeviceChangedEvent *dcce;
- int rc;
- rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce);
- if (rc != Success) {
- ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
- return;
- }
- /* we don't actually swap if there's a NullClient, swapping is done
- * later when event is delivered. */
- SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent *) dcce, 1);
- free(dcce);
- }
- static void
- ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
- {
- DeviceIntPtr slave;
- int rc;
- /* For now, we don't have devices that change physically. */
- if (!IsMaster(device))
- return;
- rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
- if (rc != Success)
- return; /* Device has disappeared */
- if (IsMaster(slave))
- return;
- if (IsFloating(slave))
- return; /* set floating since the event */
- if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
- return; /* not our slave anymore, don't care */
- /* FIXME: we probably need to send a DCE for the new slave now */
- device->public.devicePrivate = slave->public.devicePrivate;
- /* FIXME: the classes may have changed since we generated the event. */
- DeepCopyDeviceClasses(slave, device, dce);
- dce->deviceid = device->id;
- XISendDeviceChangedEvent(device, dce);
- }
- /**
- * Add state and motionMask to the filter for this event. The protocol
- * supports some extra masks for motion when a button is down:
- * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
- * least one button (or that specific button is down). These masks need to
- * be added to the filters for core/XI motion events.
- *
- * @param device The device to update the mask for
- * @param state The current button state mask
- * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
- */
- static void
- UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
- Mask motion_mask)
- {
- Mask mask;
- mask = DevicePointerMotionMask | state | motion_mask;
- SetMaskForEvent(device->id, mask, DeviceMotionNotify);
- mask = PointerMotionMask | state | motion_mask;
- SetMaskForEvent(device->id, mask, MotionNotify);
- }
- static void
- IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
- Mask *motion_mask, unsigned short *state)
- {
- if (dev->valuator)
- dev->valuator->motionHintWindow = NullWindow;
- (*buttons_down)++;
- *motion_mask = DeviceButtonMotionMask;
- if (dev->button->map[key] <= 5)
- *state |= (Button1Mask >> 1) << dev->button->map[key];
- }
- static void
- DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
- Mask *motion_mask, unsigned short *state)
- {
- if (dev->valuator)
- dev->valuator->motionHintWindow = NullWindow;
- if (*buttons_down >= 1 && !--(*buttons_down))
- *motion_mask = 0;
- if (dev->button->map[key] <= 5)
- *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
- }
- /**
- * Update the device state according to the data in the event.
- *
- * return values are
- * DEFAULT ... process as normal
- * DONT_PROCESS ... return immediately from caller
- */
- #define DEFAULT 0
- #define DONT_PROCESS 1
- int
- UpdateDeviceState(DeviceIntPtr device, DeviceEvent *event)
- {
- int i;
- int key = 0, last_valuator;
- KeyClassPtr k = NULL;
- ButtonClassPtr b = NULL;
- ValuatorClassPtr v = NULL;
- TouchClassPtr t = NULL;
- /* This event is always the first we get, before the actual events with
- * the data. However, the way how the DDX is set up, "device" will
- * actually be the slave device that caused the event.
- */
- switch (event->type) {
- case ET_DeviceChanged:
- ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event);
- return DONT_PROCESS; /* event has been sent already */
- case ET_Motion:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- case ET_TouchBegin:
- case ET_TouchUpdate:
- case ET_TouchEnd:
- break;
- default:
- /* other events don't update the device */
- return DEFAULT;
- }
- k = device->key;
- v = device->valuator;
- b = device->button;
- t = device->touch;
- key = event->detail.key;
- /* Update device axis */
- /* Check valuators first */
- last_valuator = -1;
- for (i = 0; i < MAX_VALUATORS; i++) {
- if (BitIsOn(&event->valuators.mask, i)) {
- if (!v) {
- ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
- "Ignoring event.\n", device->name);
- return DONT_PROCESS;
- }
- else if (v->numAxes < i) {
- ErrorF("[Xi] Too many valuators reported for device '%s'. "
- "Ignoring event.\n", device->name);
- return DONT_PROCESS;
- }
- last_valuator = i;
- }
- }
- for (i = 0; i <= last_valuator && i < v->numAxes; i++) {
- /* XXX: Relative/Absolute mode */
- if (BitIsOn(&event->valuators.mask, i))
- v->axisVal[i] = event->valuators.data[i];
- }
- if (event->type == ET_KeyPress) {
- if (!k)
- return DONT_PROCESS;
- /* don't allow ddx to generate multiple downs, but repeats are okay */
- if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
- return DONT_PROCESS;
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- set_key_down(device, key, KEY_PROCESSED);
- }
- else if (event->type == ET_KeyRelease) {
- if (!k)
- return DONT_PROCESS;
- if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */
- return DONT_PROCESS;
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- set_key_up(device, key, KEY_PROCESSED);
- }
- else if (event->type == ET_ButtonPress) {
- if (!b)
- return DONT_PROCESS;
- if (button_is_down(device, key, BUTTON_PROCESSED))
- return DONT_PROCESS;
- set_button_down(device, key, BUTTON_PROCESSED);
- if (!b->map[key])
- return DONT_PROCESS;
- IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
- &b->state);
- UpdateDeviceMotionMask(device, b->state, b->motionMask);
- }
- else if (event->type == ET_ButtonRelease) {
- if (!b)
- return DONT_PROCESS;
- if (!button_is_down(device, key, BUTTON_PROCESSED))
- return DONT_PROCESS;
- if (IsMaster(device)) {
- DeviceIntPtr sd;
- /*
- * Leave the button down if any slave has the
- * button still down. Note that this depends on the
- * event being delivered through the slave first
- */
- for (sd = inputInfo.devices; sd; sd = sd->next) {
- if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
- continue;
- if (!sd->button)
- continue;
- for (i = 1; i <= sd->button->numButtons; i++)
- if (sd->button->map[i] == key &&
- button_is_down(sd, i, BUTTON_PROCESSED))
- return DONT_PROCESS;
- }
- }
- set_button_up(device, key, BUTTON_PROCESSED);
- if (!b->map[key])
- return DONT_PROCESS;
- DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
- &b->state);
- UpdateDeviceMotionMask(device, b->state, b->motionMask);
- }
- else if (event->type == ET_ProximityIn)
- device->proximity->in_proximity = TRUE;
- else if (event->type == ET_ProximityOut)
- device->proximity->in_proximity = FALSE;
- else if (event->type == ET_TouchBegin) {
- BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
- BUG_RETURN_VAL(!t, DONT_PROCESS);
- if (!b->map[key])
- return DONT_PROCESS;
- if (!(event->flags & TOUCH_POINTER_EMULATED) ||
- (event->flags & TOUCH_REPLAYING))
- return DONT_PROCESS;
- IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
- &t->state);
- UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
- }
- else if (event->type == ET_TouchEnd) {
- BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
- BUG_RETURN_VAL(!t, DONT_PROCESS);
- if (t->buttonsDown <= 0 || !b->map[key])
- return DONT_PROCESS;
- if (!(event->flags & TOUCH_POINTER_EMULATED))
- return DONT_PROCESS;
- DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
- &t->state);
- UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
- }
- return DEFAULT;
- }
- /**
- * A client that does not have the TouchOwnership mask set may not receive a
- * TouchBegin event if there is at least one grab active.
- *
- * @return TRUE if the client selected for ownership events on the given
- * window for this device, FALSE otherwise
- */
- static inline Bool
- TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev,
- WindowPtr win)
- {
- InputClients *iclient;
- nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next) {
- if (rClient(iclient) != client)
- continue;
- return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
- }
- return FALSE;
- }
- static void
- TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason,
- XID resource)
- {
- int nev, i;
- InternalEvent *tel = InitEventList(GetMaximumEventsNum());
- nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
- for (i = 0; i < nev; i++)
- mieqProcessDeviceEvent(dev, tel + i, NULL);
- FreeEventList(tel, GetMaximumEventsNum());
- }
- /**
- * Attempts to deliver a touch event to the given client.
- */
- static Bool
- DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
- GrabPtr grab, WindowPtr win, InternalEvent *ev)
- {
- int err;
- xEvent *xi2;
- Mask filter;
- Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
- /* FIXME: owner event handling */
- /* If the client does not have the ownership mask set and is not
- * the current owner of the touch, only pretend we delivered */
- if (!grab && ti->num_grabs != 0 &&
- !TouchClientWantsOwnershipEvents(client, dev, win))
- return TRUE;
- /* If we fail here, we're going to leave a client hanging. */
- err = EventToXI2(ev, &xi2);
- if (err != Success)
- FatalError("[Xi] %s: XI2 conversion failed in %s"
- " (%d)\n", dev->name, __func__, err);
- FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
- filter = GetEventFilter(dev, xi2);
- if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
- return FALSE;
- err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
- free(xi2);
- /* Returning the value from TryClientEvents isn't useful, since all our
- * resource-gone cleanups will update the delivery list anyway. */
- return TRUE;
- }
- static void
- ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
- {
- ClientPtr client;
- XID error;
- GrabPtr grab = ti->listeners[0].grab;
- BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
- ti->listeners[0].type != LISTENER_POINTER_GRAB);
- BUG_RETURN(!grab);
- client = rClient(grab);
- if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
- ti->listeners[0].window->drawable.id, &error) != Success)
- ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
- }
- /**
- * Find the oldest touch that still has a pointer emulation client.
- *
- * Pointer emulation can only be performed for the oldest touch. Otherwise, the
- * order of events seen by the client will be wrong. This function helps us find
- * the next touch to be emulated.
- *
- * @param dev The device to find touches for.
- */
- static TouchPointInfoPtr
- FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
- {
- TouchPointInfoPtr oldest = NULL;
- int i;
- for (i = 0; i < dev->touch->num_touches; i++) {
- TouchPointInfoPtr ti = dev->touch->touches + i;
- int j;
- if (!ti->active || !ti->emulate_pointer)
- continue;
- for (j = 0; j < ti->num_listeners; j++) {
- if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
- ti->listeners[j].type == LISTENER_POINTER_REGULAR)
- break;
- }
- if (j == ti->num_listeners)
- continue;
- if (!oldest) {
- oldest = ti;
- continue;
- }
- if (oldest->client_id - ti->client_id < UINT_MAX / 2)
- oldest = ti;
- }
- return oldest;
- }
- /**
- * If the current owner has rejected the event, deliver the
- * TouchOwnership/TouchBegin to the next item in the sprite stack.
- */
- static void
- TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
- TouchOwnershipEvent *ev)
- {
- TouchListener *listener = &ti->listeners[0]; /* new owner */
- int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
- /* Deliver the ownership */
- if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
- DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
- listener->listener);
- else if (listener->state == LISTENER_AWAITING_BEGIN) {
- /* We can't punt to a pointer listener unless all older pointer
- * emulated touches have been seen already. */
- if ((listener->type == LISTENER_POINTER_GRAB ||
- listener->type == LISTENER_POINTER_REGULAR) &&
- ti != FindOldestPointerEmulatedTouch(dev))
- return;
- TouchEventHistoryReplay(ti, dev, listener->listener);
- }
- /* New owner has Begin/Update but not end. If touch is pending_finish,
- * emulate the TouchEnd now */
- if (ti->pending_finish) {
- TouchEmitTouchEnd(dev, ti, 0, 0);
- /* If the last owner is not a touch grab, finalise the touch, we
- won't get more correspondence on this.
- */
- if (ti->num_listeners == 1 &&
- (ti->num_grabs == 0 ||
- listener->grab->grabtype != XI2 ||
- !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
- TouchEndTouch(dev, ti);
- return;
- }
- }
- if (accepted_early)
- ActivateEarlyAccept(dev, ti);
- }
- /**
- * Check the oldest touch to see if it needs to be replayed to its pointer
- * owner.
- *
- * Touch event propagation is paused if it hits a pointer listener while an
- * older touch with a pointer listener is waiting on accept or reject. This
- * function will restart propagation of a paused touch if needed.
- *
- * @param dev The device to check touches for.
- */
- static void
- CheckOldestTouch(DeviceIntPtr dev)
- {
- TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
- if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
- TouchPuntToNextOwner(dev, oldest, NULL);
- }
- /**
- * Process a touch rejection.
- *
- * @param sourcedev The source device of the touch sequence.
- * @param ti The touchpoint info record.
- * @param resource The resource of the client rejecting the touch.
- * @param ev TouchOwnership event to send. Set to NULL if no event should be
- * sent.
- */
- void
- TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
- TouchOwnershipEvent *ev)
- {
- Bool was_owner = (resource == ti->listeners[0].listener);
- int i;
- /* Send a TouchEnd event to the resource being removed, but only if they
- * haven't received one yet already */
- for (i = 0; i < ti->num_listeners; i++) {
- if (ti->listeners[i].listener == resource) {
- if (ti->listeners[i].state != LISTENER_HAS_END)
- TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
- break;
- }
- }
- /* Remove the resource from the listener list, updating
- * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
- TouchRemoveListener(ti, resource);
- /* If the current owner was removed and there are further listeners, deliver
- * the TouchOwnership or TouchBegin event to the new owner. */
- if (ev && ti->num_listeners > 0 && was_owner)
- TouchPuntToNextOwner(sourcedev, ti, ev);
- else if (ti->num_listeners == 0)
- TouchEndTouch(sourcedev, ti);
- CheckOldestTouch(sourcedev);
- }
- /**
- * Processes a TouchOwnership event, indicating a grab has accepted the touch
- * it currently owns, or a grab or selection has been removed. Will generate
- * and send TouchEnd events to all clients removed from the delivery list, as
- * well as possibly sending the new TouchOwnership event. May end the
- * touchpoint if it is pending finish.
- */
- static void
- ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
- DeviceIntPtr dev)
- {
- TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
- if (!ti) {
- DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
- dev->name, ev->type, ev->touchid);
- return;
- }
- if (ev->reason == XIRejectTouch)
- TouchRejected(dev, ti, ev->resource, ev);
- else if (ev->reason == XIAcceptTouch) {
- int i;
- /* For pointer-emulated listeners that ungrabbed the active grab,
- * the state was forced to LISTENER_HAS_END. Still go
- * through the motions of ending the touch if the listener has
- * already seen the end. This ensures that the touch record is ended in
- * the server.
- */
- if (ti->listeners[0].state == LISTENER_HAS_END)
- TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
- /* The touch owner has accepted the touch. Send TouchEnd events to
- * everyone else, and truncate the list of listeners. */
- for (i = 1; i < ti->num_listeners; i++)
- TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
- while (ti->num_listeners > 1)
- TouchRemoveListener(ti, ti->listeners[1].listener);
- /* Owner accepted after receiving end */
- if (ti->listeners[0].state == LISTENER_HAS_END)
- TouchEndTouch(dev, ti);
- else
- ti->listeners[0].state = LISTENER_HAS_ACCEPTED;
- }
- else { /* this is the very first ownership event for a grab */
- DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource);
- }
- }
- /**
- * Copy the event's valuator information into the touchpoint, we may need
- * this for emulated TouchEnd events.
- */
- static void
- TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++)
- if (BitIsOn(ev->valuators.mask, i))
- valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
- }
- /**
- * Given a touch event and a potential listener, retrieve info needed for
- * processing the event.
- *
- * @param dev The device generating the touch event.
- * @param ti The touch point info record for the touch event.
- * @param ev The touch event to process.
- * @param listener The touch event listener that may receive the touch event.
- * @param[out] client The client that should receive the touch event.
- * @param[out] win The window to deliver the event on.
- * @param[out] grab The grab to deliver the event through, if any.
- * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
- * @return TRUE if an event should be delivered to the listener, FALSE
- * otherwise.
- */
- static Bool
- RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
- InternalEvent *ev, TouchListener * listener,
- ClientPtr *client, WindowPtr *win, GrabPtr *grab,
- XI2Mask **mask)
- {
- int rc;
- InputClients *iclients = NULL;
- *mask = NULL;
- if (listener->type == LISTENER_GRAB ||
- listener->type == LISTENER_POINTER_GRAB) {
- *grab = listener->grab;
- BUG_RETURN_VAL(!*grab, FALSE);
- *client = rClient(*grab);
- *win = (*grab)->window;
- *mask = (*grab)->xi2mask;
- }
- else {
- rc = dixLookupResourceByType((void **) win, listener->listener,
- listener->resource_type,
- serverClient, DixSendAccess);
- if (rc != Success)
- return FALSE;
- if (listener->level == XI2) {
- int evtype;
- if (ti->emulate_pointer &&
- listener->type == LISTENER_POINTER_REGULAR)
- evtype = GetXI2Type(TouchGetPointerEventType(ev));
- else
- evtype = GetXI2Type(ev->any.type);
- nt_list_for_each_entry(iclients,
- wOtherInputMasks(*win)->inputClients, next)
- if (xi2mask_isset(iclients->xi2mask, dev, evtype))
- break;
- BUG_RETURN_VAL(!iclients, FALSE);
- *mask = iclients->xi2mask;
- *client = rClient(iclients);
- }
- else if (listener->level == XI) {
- int xi_type = GetXIType(TouchGetPointerEventType(ev));
- Mask xi_filter = event_get_filter_from_type(dev, xi_type);
- nt_list_for_each_entry(iclients,
- wOtherInputMasks(*win)->inputClients, next)
- if (iclients->mask[dev->id] & xi_filter)
- break;
- BUG_RETURN_VAL(!iclients, FALSE);
- *client = rClient(iclients);
- }
- else {
- int coretype = GetCoreType(TouchGetPointerEventType(ev));
- Mask core_filter = event_get_filter_from_type(dev, coretype);
- OtherClients *oclients;
- /* all others */
- nt_list_for_each_entry(oclients,
- (OtherClients *) wOtherClients(*win), next)
- if (oclients->mask & core_filter)
- break;
- /* if owner selected, oclients is NULL */
- *client = oclients ? rClient(oclients) : wClient(*win);
- }
- *grab = NULL;
- }
- return TRUE;
- }
- static int
- DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
- InternalEvent *ev, TouchListener * listener,
- ClientPtr client, WindowPtr win, GrabPtr grab,
- XI2Mask *xi2mask)
- {
- InternalEvent motion, button;
- InternalEvent *ptrev = &motion;
- int nevents;
- DeviceIntPtr kbd;
- /* We don't deliver pointer events to non-owners */
- if (!TouchResourceIsOwner(ti, listener->listener))
- return !Success;
- nevents = TouchConvertToPointerEvent(ev, &motion, &button);
- BUG_RETURN_VAL(nevents == 0, BadValue);
- if (nevents > 1)
- ptrev = &button;
- kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
- event_set_state(dev, kbd, &ptrev->device_event);
- ptrev->device_event.corestate = event_get_corestate(dev, kbd);
- if (grab) {
- /* this side-steps the usual activation mechanisms, but... */
- if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
- ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
- else {
- int deliveries = 0;
- /* 'grab' is the passive grab, but if the grab isn't active,
- * don't deliver */
- if (!dev->deviceGrab.grab)
- return !Success;
- if (grab->ownerEvents) {
- WindowPtr focus = NullWindow;
- WindowPtr sprite_win = dev->spriteInfo->sprite->win;
- deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
- }
- if (!deliveries)
- deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
- /* We must accept the touch sequence once a pointer listener has
- * received one event past ButtonPress. */
- if (deliveries && ev->any.type != ET_TouchBegin &&
- !(ev->device_event.flags & TOUCH_CLIENT_ID))
- TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
- if (ev->any.type == ET_TouchEnd &&
- ti->num_listeners == 1 &&
- !dev->button->buttonsDown &&
- dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
- (*dev->deviceGrab.DeactivateGrab) (dev);
- CheckOldestTouch(dev);
- return Success;
- }
- }
- }
- else {
- GrabPtr devgrab = dev->deviceGrab.grab;
- DeliverDeviceEvents(win, ptrev, grab, win, dev);
- /* FIXME: bad hack
- * Implicit passive grab activated in response to this event. Store
- * the event.
- */
- if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
- TouchListener *l;
- GrabPtr g;
- devgrab = dev->deviceGrab.grab;
- g = AllocGrab(devgrab);
- BUG_WARN(!g);
- *dev->deviceGrab.sync.event = ev->device_event;
- /* The listener array has a sequence of grabs and then one event
- * selection. Implicit grab activation occurs through delivering an
- * event selection. Thus, we update the last listener in the array.
- */
- l = &ti->listeners[ti->num_listeners - 1];
- l->listener = g->resource;
- l->grab = g;
- //l->resource_type = RT_NONE;
- if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
- l->type = LISTENER_POINTER_GRAB;
- else
- l->type = LISTENER_GRAB;
- }
- }
- if (ev->any.type == ET_TouchBegin)
- listener->state = LISTENER_IS_OWNER;
- else if (ev->any.type == ET_TouchEnd)
- listener->state = LISTENER_HAS_END;
- return Success;
- }
- static void
- DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
- InternalEvent *ev)
- {
- DeviceEvent motion;
- if (ti->num_listeners) {
- ClientPtr client;
- WindowPtr win;
- GrabPtr grab;
- XI2Mask *mask;
- if (ti->listeners[0].type != LISTENER_POINTER_REGULAR &&
- ti->listeners[0].type != LISTENER_POINTER_GRAB)
- return;
- motion = ev->device_event;
- motion.type = ET_TouchUpdate;
- motion.detail.button = 0;
- if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
- &ti->listeners[0], &client, &win, &grab,
- &mask))
- return;
- /* There may be a pointer grab on the device */
- if (!grab) {
- grab = dev->deviceGrab.grab;
- if (grab) {
- win = grab->window;
- mask = grab->xi2mask;
- client = rClient(grab);
- }
- }
- DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
- win, grab, mask);
- }
- else {
- InternalEvent button;
- int converted;
- converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
- BUG_WARN(converted == 0);
- if (converted)
- ProcessOtherEvent((InternalEvent*)&motion, dev);
- }
- }
- /**
- * Processes and delivers a TouchBegin, TouchUpdate, or a
- * TouchEnd event.
- *
- * Due to having rather different delivery semantics (see the Xi 2.2 protocol
- * spec for more information), this implements its own grab and event-selection
- * delivery logic.
- */
- static void
- ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
- {
- TouchClassPtr t = dev->touch;
- TouchPointInfoPtr ti;
- uint32_t touchid;
- int type = ev->any.type;
- int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED);
- DeviceIntPtr kbd;
- if (!t)
- return;
- touchid = ev->device_event.touchid;
- if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
- ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
- emulate_pointer);
- }
- else
- ti = TouchFindByClientID(dev, touchid);
- /* Active pointer grab */
- if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
- (dev->deviceGrab.grab->grabtype == CORE ||
- dev->deviceGrab.grab->grabtype == XI ||
- !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin)))
- {
- /* Active pointer grab on touch point and we get a TouchEnd - claim this
- * touchpoint accepted, otherwise clients waiting for ownership will
- * wait on this touchpoint until this client ungrabs, or the cows come
- * home, whichever is earlier */
- if (ti && type == ET_TouchEnd)
- TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
- else if (!ti && type != ET_TouchBegin) {
- /* Under the following circumstances we create a new touch record for an
- * existing touch:
- *
- * - The touch may be pointer emulated
- * - An explicit grab is active on the device
- * - The grab is a pointer grab
- *
- * This allows for an explicit grab to receive pointer events for an already
- * active touch.
- */
- ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
- emulate_pointer);
- if (!ti) {
- DebugF("[Xi] %s: Failed to create new dix record for explicitly "
- "grabbed touchpoint %d\n",
- dev->name, touchid);
- return;
- }
- TouchBuildSprite(dev, ti, ev);
- TouchSetupListeners(dev, ti, ev);
- }
- }
- if (!ti) {
- DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
- dev->name, type, touchid);
- return;
- }
- /* if emulate_pointer is set, emulate the motion event right
- * here, so we can ignore it for button event emulation. TouchUpdate
- * events which _only_ emulate motion just work normally */
- if (emulate_pointer && ev->any.type != ET_TouchUpdate)
- DeliverEmulatedMotionEvent(dev, ti, ev);
- if (emulate_pointer && IsMaster(dev))
- CheckMotion(&ev->device_event, dev);
- kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
- event_set_state(NULL, kbd, &ev->device_event);
- ev->device_event.corestate = event_get_corestate(NULL, kbd);
- /* Make sure we have a valid window trace for event delivery; must be
- * called after event type mutation. Touch end events are always processed
- * in order to end touch records. */
- /* FIXME: check this */
- if ((type == ET_TouchBegin &&
- !(ev->device_event.flags & TOUCH_REPLAYING) &&
- !TouchBuildSprite(dev, ti, ev)) ||
- (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
- return;
- TouchCopyValuatorData(&ev->device_event, ti);
- /* WARNING: the event type may change to TouchUpdate in
- * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
- * owner */
- DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
- if (ev->any.type == ET_TouchEnd)
- TouchEndTouch(dev, ti);
- if (emulate_pointer)
- UpdateDeviceState(dev, &ev->device_event);
- }
- static void
- ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
- {
- Mask filter;
- WindowPtr pWin;
- BarrierEvent *be = &e->barrier_event;
- xEvent *ev;
- int rc;
- GrabPtr grab = dev->deviceGrab.grab;
- if (!IsMaster(dev))
- return;
- if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
- return;
- if (grab)
- be->flags |= XIBarrierDeviceIsGrabbed;
- rc = EventToXI2(e, &ev);
- if (rc != Success) {
- ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
- return;
- }
- /* A client has a grab, deliver to this client if the grab_window is the
- barrier window.
- Otherwise, deliver normally to the client.
- */
- if (grab &&
- CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) &&
- grab->window->drawable.id == be->window) {
- DeliverGrabbedEvent(e, dev, FALSE);
- } else {
- filter = GetEventFilter(dev, ev);
- DeliverEventsToWindow(dev, pWin, ev, 1,
- filter, NullGrab);
- }
- free(ev);
- }
- /**
- * Process DeviceEvents and DeviceChangedEvents.
- */
- static void
- ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
- {
- GrabPtr grab;
- Bool deactivateDeviceGrab = FALSE;
- int key = 0, rootX, rootY;
- ButtonClassPtr b;
- int ret = 0;
- int corestate;
- DeviceIntPtr mouse = NULL, kbd = NULL;
- DeviceEvent *event = &ev->device_event;
- if (IsPointerDevice(device)) {
- kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
- mouse = device;
- if (!kbd->key) /* can happen with floating SDs */
- kbd = NULL;
- }
- else {
- mouse = GetMaster(device, POINTER_OR_FLOAT);
- kbd = device;
- if (!mouse->valuator || !mouse->button) /* may be float. SDs */
- mouse = NULL;
- }
- corestate = event_get_corestate(mouse, kbd);
- event_set_state(mouse, kbd, event);
- ret = UpdateDeviceState(device, event);
- if (ret == DONT_PROCESS)
- return;
- b = device->button;
- if (IsMaster(device) || IsFloating(device))
- CheckMotion(event, device);
- switch (event->type) {
- case ET_Motion:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- GetSpritePosition(device, &rootX, &rootY);
- event->root_x = rootX;
- event->root_y = rootY;
- NoticeEventTime((InternalEvent *) event, device);
- event->corestate = corestate;
- key = event->detail.key;
- break;
- default:
- break;
- }
- if (DeviceEventCallback && !syncEvents.playingEvents) {
- DeviceEventInfoRec eventinfo;
- SpritePtr pSprite = device->spriteInfo->sprite;
- /* see comment in EnqueueEvents regarding the next three lines */
- if (ev->any.type == ET_Motion)
- ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
- eventinfo.device = device;
- eventinfo.event = ev;
- CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
- }
- grab = device->deviceGrab.grab;
- switch (event->type) {
- case ET_KeyPress:
- if (!grab && CheckDeviceGrabs(device, event, 0))
- return;
- break;
- case ET_KeyRelease:
- if (grab && device->deviceGrab.fromPassiveGrab &&
- (key == device->deviceGrab.activatingKey) &&
- GrabIsKeyboardGrab(device->deviceGrab.grab))
- deactivateDeviceGrab = TRUE;
- break;
- case ET_ButtonPress:
- if (b->map[key] == 0) /* there's no button 0 */
- return;
- event->detail.button = b->map[key];
- if (!grab && CheckDeviceGrabs(device, event, 0)) {
- /* if a passive grab was activated, the event has been sent
- * already */
- return;
- }
- break;
- case ET_ButtonRelease:
- if (b->map[key] == 0) /* there's no button 0 */
- return;
- event->detail.button = b->map[key];
- if (grab && !b->buttonsDown &&
- device->deviceGrab.fromPassiveGrab &&
- GrabIsPointerGrab(device->deviceGrab.grab))
- deactivateDeviceGrab = TRUE;
- default:
- break;
- }
- if (grab)
- DeliverGrabbedEvent((InternalEvent *) event, device,
- deactivateDeviceGrab);
- else if (device->focus && !IsPointerEvent(ev))
- DeliverFocusedEvent(device, (InternalEvent *) event,
- GetSpriteWindow(device));
- else
- DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
- NullGrab, NullWindow, device);
- if (deactivateDeviceGrab == TRUE) {
- (*device->deviceGrab.DeactivateGrab) (device);
- if (!IsMaster (device) && !IsFloating (device)) {
- int flags, num_events = 0;
- InternalEvent dce;
- flags = (IsPointerDevice (device)) ?
- DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT;
- UpdateFromMaster (&dce, device, flags, &num_events);
- BUG_WARN(num_events > 1);
- if (num_events == 1)
- ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED),
- &dce.changed_event);
- }
- }
- event->detail.key = key;
- }
- /**
- * Main device event processing function.
- * Called from when processing the events from the event queue.
- *
- */
- void
- ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
- {
- verify_internal_event(ev);
- switch (ev->any.type) {
- case ET_RawKeyPress:
- case ET_RawKeyRelease:
- case ET_RawButtonPress:
- case ET_RawButtonRelease:
- case ET_RawMotion:
- case ET_RawTouchBegin:
- case ET_RawTouchUpdate:
- case ET_RawTouchEnd:
- DeliverRawEvent(&ev->raw_event, device);
- break;
- case ET_TouchBegin:
- case ET_TouchUpdate:
- case ET_TouchEnd:
- ProcessTouchEvent(ev, device);
- break;
- case ET_TouchOwnership:
- /* TouchOwnership events are handled separately from the rest, as they
- * have more complex semantics. */
- ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
- break;
- case ET_BarrierHit:
- case ET_BarrierLeave:
- ProcessBarrierEvent(ev, device);
- break;
- default:
- ProcessDeviceEvent(ev, device);
- break;
- }
- }
- static int
- DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
- InternalEvent *ev, TouchListener * listener,
- ClientPtr client, WindowPtr win, GrabPtr grab,
- XI2Mask *xi2mask)
- {
- enum TouchListenerState state;
- int rc = Success;
- Bool has_ownershipmask;
- if (listener->type == LISTENER_POINTER_REGULAR ||
- listener->type == LISTENER_POINTER_GRAB) {
- rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
- grab, xi2mask);
- if (rc == Success) {
- listener->state = LISTENER_IS_OWNER;
- /* async grabs cannot replay, so automatically accept this touch */
- if (listener->type == LISTENER_POINTER_GRAB &&
- dev->deviceGrab.grab &&
- dev->deviceGrab.fromPassiveGrab &&
- dev->deviceGrab.grab->pointerMode == GrabModeAsync)
- ActivateEarlyAccept(dev, ti);
- }
- goto out;
- }
- has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
- if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
- rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
- if (!TouchResourceIsOwner(ti, listener->listener)) {
- if (has_ownershipmask)
- state = LISTENER_AWAITING_OWNER;
- else
- state = LISTENER_AWAITING_BEGIN;
- }
- else {
- if (has_ownershipmask)
- TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
- if (listener->type == LISTENER_REGULAR)
- state = LISTENER_HAS_ACCEPTED;
- else
- state = LISTENER_IS_OWNER;
- }
- listener->state = state;
- out:
- return rc;
- }
- static int
- DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
- TouchListener * listener, ClientPtr client,
- WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
- {
- int rc = Success;
- if (listener->type == LISTENER_POINTER_REGULAR ||
- listener->type == LISTENER_POINTER_GRAB) {
- /* Note: If the active grab was ungrabbed, we already changed the
- * state to LISTENER_HAS_END but still get here. So we mustn't
- * actually send the event.
- * This is part two of the hack in DeactivatePointerGrab
- */
- if (listener->state != LISTENER_HAS_END) {
- rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
- grab, xi2mask);
- /* Once we send a TouchEnd to a legacy listener, we're already well
- * past the accepting/rejecting stage (can only happen on
- * GrabModeSync + replay. This listener now gets the end event,
- * and we can continue.
- */
- if (rc == Success)
- listener->state = LISTENER_HAS_END;
- }
- goto out;
- }
- /* A client is waiting for the begin, don't give it a TouchEnd */
- if (listener->state == LISTENER_AWAITING_BEGIN) {
- listener->state = LISTENER_HAS_END;
- goto out;
- }
- /* Event in response to reject */
- if (ev->device_event.flags & TOUCH_REJECT ||
- (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) {
- /* Touch has been rejected, or accepted by its owner which is not this listener */
- if (listener->state != LISTENER_HAS_END)
- rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
- listener->state = LISTENER_HAS_END;
- }
- else if (TouchResourceIsOwner(ti, listener->listener)) {
- Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
- /* FIXME: what about early acceptance */
- if (normal_end && listener->state != LISTENER_HAS_END)
- rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
- if ((ti->num_listeners > 1 ||
- (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
- (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
- ev->any.type = ET_TouchUpdate;
- ev->device_event.flags |= TOUCH_PENDING_END;
- ti->pending_finish = TRUE;
- }
- if (normal_end)
- listener->state = LISTENER_HAS_END;
- }
- out:
- return rc;
- }
- static int
- DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
- TouchListener * listener, ClientPtr client,
- WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
- {
- Bool has_ownershipmask = FALSE;
- int rc = Success;
- if (xi2mask)
- has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
- if (ev->any.type == ET_TouchOwnership) {
- ev->touch_ownership_event.deviceid = dev->id;
- if (!TouchResourceIsOwner(ti, listener->listener))
- goto out;
- rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
- listener->state = LISTENER_IS_OWNER;
- }
- else
- ev->device_event.deviceid = dev->id;
- if (ev->any.type == ET_TouchBegin) {
- rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
- xi2mask);
- }
- else if (ev->any.type == ET_TouchUpdate) {
- if (listener->type == LISTENER_POINTER_REGULAR ||
- listener->type == LISTENER_POINTER_GRAB)
- DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
- xi2mask);
- else if (TouchResourceIsOwner(ti, listener->listener) ||
- has_ownershipmask)
- rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
- }
- else if (ev->any.type == ET_TouchEnd)
- rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
- xi2mask);
- out:
- return rc;
- }
- /**
- * Delivers a touch events to all interested clients. For TouchBegin events,
- * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
- * May also mutate ev (type and flags) upon successful delivery. If
- * @resource is non-zero, will only attempt delivery to the owner of that
- * resource.
- *
- * @return TRUE if the event was delivered at least once, FALSE otherwise
- */
- void
- DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
- InternalEvent *ev, XID resource)
- {
- int i;
- if (ev->any.type == ET_TouchBegin &&
- !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING)))
- TouchSetupListeners(dev, ti, ev);
- TouchEventHistoryPush(ti, &ev->device_event);
- for (i = 0; i < ti->num_listeners; i++) {
- GrabPtr grab = NULL;
- ClientPtr client;
- WindowPtr win;
- XI2Mask *mask;
- TouchListener *listener = &ti->listeners[i];
- if (resource && listener->listener != resource)
- continue;
- if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
- &grab, &mask))
- continue;
- DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
- }
- }
- int
- InitProximityClassDeviceStruct(DeviceIntPtr dev)
- {
- ProximityClassPtr proxc;
- BUG_RETURN_VAL(dev == NULL, FALSE);
- BUG_RETURN_VAL(dev->proximity != NULL, FALSE);
- proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
- if (!proxc)
- return FALSE;
- proxc->sourceid = dev->id;
- proxc->in_proximity = TRUE;
- dev->proximity = proxc;
- return TRUE;
- }
- /**
- * Initialise the device's valuators. The memory must already be allocated,
- * this function merely inits the matching axis (specified through axnum) to
- * sane values.
- *
- * It is a condition that (minval < maxval).
- *
- * @see InitValuatorClassDeviceStruct
- */
- Bool
- InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
- int maxval, int resolution, int min_res, int max_res,
- int mode)
- {
- AxisInfoPtr ax;
- BUG_RETURN_VAL(dev == NULL, FALSE);
- BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
- BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
- BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE);
- ax = dev->valuator->axes + axnum;
- ax->min_value = minval;
- ax->max_value = maxval;
- ax->resolution = resolution;
- ax->min_resolution = min_res;
- ax->max_resolution = max_res;
- ax->label = label;
- ax->mode = mode;
- if (mode & OutOfProximity)
- dev->proximity->in_proximity = FALSE;
- return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
- }
- /**
- * Set the given axis number as a scrolling valuator.
- */
- Bool
- SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
- double increment, int flags)
- {
- AxisInfoPtr ax;
- int *current_ax;
- InternalEvent dce;
- DeviceIntPtr master;
- BUG_RETURN_VAL(dev == NULL, FALSE);
- BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
- BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
- switch (type) {
- case SCROLL_TYPE_VERTICAL:
- current_ax = &dev->valuator->v_scroll_axis;
- break;
- case SCROLL_TYPE_HORIZONTAL:
- current_ax = &dev->valuator->h_scroll_axis;
- break;
- case SCROLL_TYPE_NONE:
- ax = &dev->valuator->axes[axnum];
- ax->scroll.type = type;
- return TRUE;
- default:
- return FALSE;
- }
- if (increment == 0.0)
- return FALSE;
- if (*current_ax != -1 && axnum != *current_ax) {
- ax = &dev->valuator->axes[*current_ax];
- if (ax->scroll.type == type &&
- (flags & SCROLL_FLAG_PREFERRED) &&
- (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
- return FALSE;
- }
- *current_ax = axnum;
- ax = &dev->valuator->axes[axnum];
- ax->scroll.type = type;
- ax->scroll.increment = increment;
- ax->scroll.flags = flags;
- master = GetMaster(dev, MASTER_ATTACHED);
- CreateClassesChangedEvent(&dce, master, dev,
- DEVCHANGE_POINTER_EVENT |
- DEVCHANGE_DEVICE_CHANGE);
- XISendDeviceChangedEvent(dev, &dce.changed_event);
- /* if the current slave is us, update the master. If not, we'll update
- * whenever the next slave switch happens anyway. CMDC sends the event
- * for us */
- if (master && master->lastSlave == dev)
- ChangeMasterDeviceClasses(master, &dce.changed_event);
- return TRUE;
- }
- int
- CheckGrabValues(ClientPtr client, GrabParameters *param)
- {
- if (param->grabtype != CORE &&
- param->grabtype != XI && param->grabtype != XI2) {
- ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
- return BadImplementation;
- }
- if ((param->this_device_mode != GrabModeSync) &&
- (param->this_device_mode != GrabModeAsync) &&
- (param->this_device_mode != XIGrabModeTouch)) {
- client->errorValue = param->this_device_mode;
- return BadValue;
- }
- if ((param->other_devices_mode != GrabModeSync) &&
- (param->other_devices_mode != GrabModeAsync) &&
- (param->other_devices_mode != XIGrabModeTouch)) {
- client->errorValue = param->other_devices_mode;
- return BadValue;
- }
- if (param->modifiers != AnyModifier &&
- param->modifiers != XIAnyModifier &&
- (param->modifiers & ~AllModifiersMask)) {
- client->errorValue = param->modifiers;
- return BadValue;
- }
- if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
- client->errorValue = param->ownerEvents;
- return BadValue;
- }
- return Success;
- }
- int
- GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
- int button, GrabParameters *param, enum InputLevel grabtype,
- GrabMask *mask)
- {
- WindowPtr pWin, confineTo;
- CursorPtr cursor;
- GrabPtr grab;
- int rc, type = -1;
- Mask access_mode = DixGrabAccess;
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
- if (param->confineTo == None)
- confineTo = NullWindow;
- else {
- rc = dixLookupWindow(&confineTo, param->confineTo, client,
- DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
- if (param->cursor == None)
- cursor = NullCursor;
- else {
- rc = dixLookupResourceByType((void **) &cursor, param->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (rc != Success) {
- client->errorValue = param->cursor;
- return rc;
- }
- access_mode |= DixForceAccess;
- }
- if (param->this_device_mode == GrabModeSync ||
- param->other_devices_mode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
- if (rc != Success)
- return rc;
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- if (grabtype == XI)
- type = DeviceButtonPress;
- else if (grabtype == XI2)
- type = XI_ButtonPress;
- grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
- mask, param, type, button, confineTo, cursor);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
- }
- /**
- * Grab the given key.
- */
- int
- GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
- int key, GrabParameters *param, enum InputLevel grabtype,
- GrabMask *mask)
- {
- WindowPtr pWin;
- GrabPtr grab;
- KeyClassPtr k = dev->key;
- Mask access_mode = DixGrabAccess;
- int rc, type = -1;
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
- if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
- return BadMatch;
- if (grabtype == XI) {
- if ((key > k->xkbInfo->desc->max_key_code ||
- key < k->xkbInfo->desc->min_key_code)
- && (key != AnyKey)) {
- client->errorValue = key;
- return BadValue;
- }
- type = DeviceKeyPress;
- }
- else if (grabtype == XI2)
- type = XI_KeyPress;
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- if (param->this_device_mode == GrabModeSync ||
- param->other_devices_mode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
- if (rc != Success)
- return rc;
- grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
- mask, param, type, key, NULL, NULL);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
- }
- /* Enter/FocusIn grab */
- int
- GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
- GrabParameters *param, GrabMask *mask)
- {
- WindowPtr pWin;
- CursorPtr cursor;
- GrabPtr grab;
- Mask access_mode = DixGrabAccess;
- int rc;
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- if (param->cursor == None)
- cursor = NullCursor;
- else {
- rc = dixLookupResourceByType((void **) &cursor, param->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (rc != Success) {
- client->errorValue = param->cursor;
- return rc;
- }
- access_mode |= DixForceAccess;
- }
- if (param->this_device_mode == GrabModeSync ||
- param->other_devices_mode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
- if (rc != Success)
- return rc;
- grab = CreateGrab(client->index, dev, dev, pWin, XI2,
- mask, param,
- (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0,
- NULL, cursor);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
- }
- /* Touch grab */
- int
- GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
- GrabParameters *param, GrabMask *mask)
- {
- WindowPtr pWin;
- GrabPtr grab;
- int rc;
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
- if (rc != Success)
- return rc;
- grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
- mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
- }
- int
- SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
- Mask mask, Mask exclusivemasks)
- {
- int mskidx = dev->id;
- int i, ret;
- Mask check;
- InputClientsPtr others;
- check = (mask & exclusivemasks);
- if (wOtherInputMasks(pWin)) {
- if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {
- /* It is illegal for two different clients to select on any of
- * the events for maskcheck. However, it is OK, for some client
- * to continue selecting on one of those events.
- */
- for (others = wOtherInputMasks(pWin)->inputClients; others;
- others = others->next) {
- if (!SameClient(others, client) && (check &
- others->mask[mskidx]))
- return BadAccess;
- }
- }
- for (others = wOtherInputMasks(pWin)->inputClients; others;
- others = others->next) {
- if (SameClient(others, client)) {
- check = others->mask[mskidx];
- others->mask[mskidx] = mask;
- if (mask == 0) {
- for (i = 0; i < EMASKSIZE; i++)
- if (i != mskidx && others->mask[i] != 0)
- break;
- if (i == EMASKSIZE) {
- RecalculateDeviceDeliverableEvents(pWin);
- if (ShouldFreeInputMasks(pWin, FALSE))
- FreeResource(others->resource, RT_NONE);
- return Success;
- }
- }
- goto maskSet;
- }
- }
- }
- check = 0;
- if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
- return ret;
- maskSet:
- if (dev->valuator)
- if ((dev->valuator->motionHintWindow == pWin) &&
- (mask & DevicePointerMotionHintMask) &&
- !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
- dev->valuator->motionHintWindow = NullWindow;
- RecalculateDeviceDeliverableEvents(pWin);
- return Success;
- }
- static void
- FreeInputClient(InputClientsPtr * other)
- {
- xi2mask_free(&(*other)->xi2mask);
- free(*other);
- *other = NULL;
- }
- static InputClientsPtr
- AllocInputClient(void)
- {
- return calloc(1, sizeof(InputClients));
- }
- int
- AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
- {
- InputClientsPtr others;
- if (!pWin->optional && !MakeWindowOptional(pWin))
- return BadAlloc;
- others = AllocInputClient();
- if (!others)
- return BadAlloc;
- if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
- goto bail;
- others->xi2mask = xi2mask_new();
- if (!others->xi2mask)
- goto bail;
- others->mask[mskidx] = mask;
- others->resource = FakeClientID(client->index);
- others->next = pWin->optional->inputMasks->inputClients;
- pWin->optional->inputMasks->inputClients = others;
- if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
- goto bail;
- return Success;
- bail:
- FreeInputClient(&others);
- return BadAlloc;
- }
- static Bool
- MakeInputMasks(WindowPtr pWin)
- {
- struct _OtherInputMasks *imasks;
- imasks = calloc(1, sizeof(struct _OtherInputMasks));
- if (!imasks)
- return FALSE;
- imasks->xi2mask = xi2mask_new();
- if (!imasks->xi2mask) {
- free(imasks);
- return FALSE;
- }
- pWin->optional->inputMasks = imasks;
- return TRUE;
- }
- static void
- FreeInputMask(OtherInputMasks ** imask)
- {
- xi2mask_free(&(*imask)->xi2mask);
- free(*imask);
- *imask = NULL;
- }
- void
- RecalculateDeviceDeliverableEvents(WindowPtr pWin)
- {
- InputClientsPtr others;
- struct _OtherInputMasks *inputMasks; /* default: NULL */
- WindowPtr pChild, tmp;
- int i;
- pChild = pWin;
- while (1) {
- if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
- xi2mask_zero(inputMasks->xi2mask, -1);
- for (others = inputMasks->inputClients; others;
- others = others->next) {
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->inputEvents[i] |= others->mask[i];
- xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
- }
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
- for (tmp = pChild->parent; tmp; tmp = tmp->parent)
- if (wOtherInputMasks(tmp))
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->deliverableEvents[i] |=
- (wOtherInputMasks(tmp)->deliverableEvents[i]
- & ~inputMasks->dontPropagateMask[i] &
- PropagateMask[i]);
- }
- if (pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
- while (!pChild->nextSib && (pChild != pWin))
- pChild = pChild->parent;
- if (pChild == pWin)
- break;
- pChild = pChild->nextSib;
- }
- }
- int
- InputClientGone(WindowPtr pWin, XID id)
- {
- InputClientsPtr other, prev;
- if (!wOtherInputMasks(pWin))
- return Success;
- prev = 0;
- for (other = wOtherInputMasks(pWin)->inputClients; other;
- other = other->next) {
- if (other->resource == id) {
- if (prev) {
- prev->next = other->next;
- FreeInputClient(&other);
- }
- else if (!(other->next)) {
- if (ShouldFreeInputMasks(pWin, TRUE)) {
- OtherInputMasks *mask = wOtherInputMasks(pWin);
- mask->inputClients = other->next;
- FreeInputMask(&mask);
- pWin->optional->inputMasks = (OtherInputMasks *) NULL;
- CheckWindowOptionalNeed(pWin);
- FreeInputClient(&other);
- }
- else {
- other->resource = FakeClientID(0);
- if (!AddResource(other->resource, RT_INPUTCLIENT,
- (void *) pWin))
- return BadAlloc;
- }
- }
- else {
- wOtherInputMasks(pWin)->inputClients = other->next;
- FreeInputClient(&other);
- }
- RecalculateDeviceDeliverableEvents(pWin);
- return Success;
- }
- prev = other;
- }
- FatalError("client not on device event list");
- }
- /**
- * Search for window in each touch trace for each device. Remove the window
- * and all its subwindows from the trace when found. The initial window
- * order is preserved.
- */
- void
- WindowGone(WindowPtr win)
- {
- DeviceIntPtr dev;
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- TouchClassPtr t = dev->touch;
- int i;
- if (!t)
- continue;
- for (i = 0; i < t->num_touches; i++) {
- SpritePtr sprite = &t->touches[i].sprite;
- int j;
- for (j = 0; j < sprite->spriteTraceGood; j++) {
- if (sprite->spriteTrace[j] == win) {
- sprite->spriteTraceGood = j;
- break;
- }
- }
- }
- }
- }
- int
- SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
- xEvent *ev, Mask mask, int count)
- {
- WindowPtr pWin;
- WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
- WindowPtr spriteWin = GetSpriteWindow(d);
- if (dest == PointerWindow)
- pWin = spriteWin;
- else if (dest == InputFocus) {
- WindowPtr inputFocus;
- if (!d->focus)
- inputFocus = spriteWin;
- else
- inputFocus = d->focus->win;
- if (inputFocus == FollowKeyboardWin)
- inputFocus = inputInfo.keyboard->focus->win;
- if (inputFocus == NoneWin)
- return Success;
- /* If the input focus is PointerRootWin, send the event to where
- * the pointer is if possible, then perhaps propogate up to root. */
- if (inputFocus == PointerRootWin)
- inputFocus = GetCurrentRootWindow(d);
- if (IsParent(inputFocus, spriteWin)) {
- effectiveFocus = inputFocus;
- pWin = spriteWin;
- }
- else
- effectiveFocus = pWin = inputFocus;
- }
- else
- dixLookupWindow(&pWin, dest, client, DixSendAccess);
- if (!pWin)
- return BadWindow;
- if ((propagate != xFalse) && (propagate != xTrue)) {
- client->errorValue = propagate;
- return BadValue;
- }
- ev->u.u.type |= 0x80;
- if (propagate) {
- for (; pWin; pWin = pWin->parent) {
- if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
- return Success;
- if (pWin == effectiveFocus)
- return Success;
- if (wOtherInputMasks(pWin))
- mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
- if (!mask)
- break;
- }
- }
- else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
- DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
- return Success;
- }
- int
- SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
- {
- int i;
- ButtonClassPtr b = dev->button;
- if (b == NULL)
- return BadMatch;
- if (nElts != b->numButtons) {
- client->errorValue = nElts;
- return BadValue;
- }
- if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
- return BadValue;
- for (i = 0; i < nElts; i++)
- if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
- return MappingBusy;
- for (i = 0; i < nElts; i++)
- b->map[i + 1] = map[i];
- return Success;
- }
- int
- ChangeKeyMapping(ClientPtr client,
- DeviceIntPtr dev,
- unsigned len,
- int type,
- KeyCode firstKeyCode,
- CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
- {
- KeySymsRec keysyms;
- KeyClassPtr k = dev->key;
- if (k == NULL)
- return BadMatch;
- if (len != (keyCodes * keySymsPerKeyCode))
- return BadLength;
- if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
- (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
- client->errorValue = firstKeyCode;
- return BadValue;
- }
- if (keySymsPerKeyCode == 0) {
- client->errorValue = 0;
- return BadValue;
- }
- keysyms.minKeyCode = firstKeyCode;
- keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
- keysyms.mapWidth = keySymsPerKeyCode;
- keysyms.map = map;
- XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
- serverClient);
- return Success;
- }
- static void
- DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
- {
- WindowPtr parent;
- /* Deactivate any grabs performed on this window, before making
- * any input focus changes.
- * Deactivating a device grab should cause focus events. */
- if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
- (*dev->deviceGrab.DeactivateGrab) (dev);
- /* If the focus window is a root window (ie. has no parent)
- * then don't delete the focus from it. */
- if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
- int focusEventMode = NotifyNormal;
- /* If a grab is in progress, then alter the mode of focus events. */
- if (dev->deviceGrab.grab)
- focusEventMode = NotifyWhileGrabbed;
- switch (dev->focus->revert) {
- case RevertToNone:
- if (!ActivateFocusInGrab(dev, pWin, NoneWin))
- DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
- dev->focus->win = NoneWin;
- dev->focus->traceGood = 0;
- break;
- case RevertToParent:
- parent = pWin;
- do {
- parent = parent->parent;
- dev->focus->traceGood--;
- }
- while (!parent->realized);
- if (!ActivateFocusInGrab(dev, pWin, parent))
- DoFocusEvents(dev, pWin, parent, focusEventMode);
- dev->focus->win = parent;
- dev->focus->revert = RevertToNone;
- break;
- case RevertToPointerRoot:
- if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
- DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
- dev->focus->win = PointerRootWin;
- dev->focus->traceGood = 0;
- break;
- case RevertToFollowKeyboard:
- {
- DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
- if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
- kbd = inputInfo.keyboard;
- if (kbd->focus->win) {
- if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
- DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
- dev->focus->win = FollowKeyboardWin;
- dev->focus->traceGood = 0;
- }
- else {
- if (!ActivateFocusInGrab(dev, pWin, NoneWin))
- DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
- dev->focus->win = NoneWin;
- dev->focus->traceGood = 0;
- }
- }
- break;
- }
- }
- if (dev->valuator)
- if (dev->valuator->motionHintWindow == pWin)
- dev->valuator->motionHintWindow = NullWindow;
- }
- void
- DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
- {
- int i;
- DeviceIntPtr dev;
- InputClientsPtr ic;
- struct _OtherInputMasks *inputMasks;
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- DeleteDeviceFromAnyExtEvents(pWin, dev);
- }
- for (dev = inputInfo.off_devices; dev; dev = dev->next)
- DeleteDeviceFromAnyExtEvents(pWin, dev);
- if (freeResources)
- while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
- ic = inputMasks->inputClients;
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->dontPropagateMask[i] = 0;
- FreeResource(ic->resource, RT_NONE);
- }
- }
- int
- MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
- {
- DeviceIntPtr dev;
- dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
- DixReadAccess);
- if (!dev)
- return 0;
- if (pEvents->type == DeviceMotionNotify) {
- if (mask & DevicePointerMotionHintMask) {
- if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
- return 1; /* don't send, but pretend we did */
- }
- pEvents->detail = NotifyHint;
- }
- else {
- pEvents->detail = NotifyNormal;
- }
- }
- return 0;
- }
- void
- CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
- deviceKeyButtonPointer *xE, GrabPtr grab,
- ClientPtr client, Mask deliveryMask)
- {
- DeviceIntPtr dev;
- dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
- DixGrabAccess);
- if (!dev)
- return;
- if (type == DeviceMotionNotify)
- dev->valuator->motionHintWindow = pWin;
- else if ((type == DeviceButtonPress) && (!grab) &&
- (deliveryMask & DeviceButtonGrabMask)) {
- GrabPtr tempGrab;
- tempGrab = AllocGrab(NULL);
- if (!tempGrab)
- return;
- tempGrab->device = dev;
- tempGrab->resource = client->clientAsMask;
- tempGrab->window = pWin;
- tempGrab->ownerEvents =
- (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
- tempGrab->eventMask = deliveryMask;
- tempGrab->keyboardMode = GrabModeAsync;
- tempGrab->pointerMode = GrabModeAsync;
- tempGrab->confineTo = NullWindow;
- tempGrab->cursor = NullCursor;
- tempGrab->next = NULL;
- (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
- FreeGrab(tempGrab);
- }
- }
- static Mask
- DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
- {
- InputClientsPtr other;
- if (!wOtherInputMasks(pWin))
- return 0;
- for (other = wOtherInputMasks(pWin)->inputClients; other;
- other = other->next) {
- if (SameClient(other, client))
- return other->mask[dev->id];
- }
- return 0;
- }
- void
- MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
- {
- WindowPtr pWin;
- GrabPtr grab = dev->deviceGrab.grab;
- pWin = dev->valuator->motionHintWindow;
- if ((grab && SameClient(grab, client) &&
- ((grab->eventMask & DevicePointerMotionHintMask) ||
- (grab->ownerEvents &&
- (DeviceEventMaskForClient(dev, pWin, client) &
- DevicePointerMotionHintMask)))) ||
- (!grab &&
- (DeviceEventMaskForClient(dev, pWin, client) &
- DevicePointerMotionHintMask)))
- dev->valuator->motionHintWindow = NullWindow;
- }
- int
- DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
- int maskndx)
- {
- struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
- if (mask & ~PropagateMask[maskndx]) {
- client->errorValue = mask;
- return BadValue;
- }
- if (mask == 0) {
- if (inputMasks)
- inputMasks->dontPropagateMask[maskndx] = mask;
- }
- else {
- if (!inputMasks)
- AddExtensionClient(pWin, client, 0, 0);
- inputMasks = wOtherInputMasks(pWin);
- inputMasks->dontPropagateMask[maskndx] = mask;
- }
- RecalculateDeviceDeliverableEvents(pWin);
- if (ShouldFreeInputMasks(pWin, FALSE))
- FreeResource(inputMasks->inputClients->resource, RT_NONE);
- return Success;
- }
- Bool
- ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
- {
- int i;
- Mask allInputEventMasks = 0;
- struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
- for (i = 0; i < EMASKSIZE; i++)
- allInputEventMasks |= inputMasks->dontPropagateMask[i];
- if (!ignoreSelectedEvents)
- for (i = 0; i < EMASKSIZE; i++)
- allInputEventMasks |= inputMasks->inputEvents[i];
- if (allInputEventMasks == 0)
- return TRUE;
- else
- return FALSE;
- }
- /***********************************************************************
- *
- * Walk through the window tree, finding all clients that want to know
- * about the Event.
- *
- */
- static void
- FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
- xEvent *ev, int count)
- {
- WindowPtr p2;
- while (p1) {
- p2 = p1->firstChild;
- DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
- FindInterestedChildren(dev, p2, mask, ev, count);
- p1 = p1->nextSib;
- }
- }
- /***********************************************************************
- *
- * Send an event to interested clients in all windows on all screens.
- *
- */
- void
- SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
- {
- int i;
- WindowPtr pWin, p1;
- for (i = 0; i < screenInfo.numScreens; i++) {
- pWin = screenInfo.screens[i]->root;
- if (!pWin)
- continue;
- DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
- p1 = pWin->firstChild;
- FindInterestedChildren(dev, p1, mask, ev, count);
- }
- }
- /**
- * Set the XI2 mask for the given client on the given window.
- * @param dev The device to set the mask for.
- * @param win The window to set the mask on.
- * @param client The client setting the mask.
- * @param len Number of bytes in mask.
- * @param mask Event mask in the form of (1 << eventtype)
- */
- int
- XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
- unsigned int len, unsigned char *mask)
- {
- OtherInputMasks *masks;
- InputClientsPtr others = NULL;
- masks = wOtherInputMasks(win);
- if (masks) {
- for (others = wOtherInputMasks(win)->inputClients; others;
- others = others->next) {
- if (SameClient(others, client)) {
- xi2mask_zero(others->xi2mask, dev->id);
- break;
- }
- }
- }
- if (len && !others) {
- if (AddExtensionClient(win, client, 0, 0) != Success)
- return BadAlloc;
- others = wOtherInputMasks(win)->inputClients;
- }
- if (others) {
- xi2mask_zero(others->xi2mask, dev->id);
- len = min(len, xi2mask_mask_size(others->xi2mask));
- }
- if (len) {
- xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
- }
- RecalculateDeviceDeliverableEvents(win);
- return Success;
- }
|