105b261ecSmrg/* 205b261ecSmrg * 305b261ecSmrgCopyright 1990, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg * 2505b261ecSmrg * Author: Keith Packard, MIT X Consortium 2605b261ecSmrg */ 2705b261ecSmrg 2805b261ecSmrg/* 2905b261ecSmrg * mieq.c 3005b261ecSmrg * 3105b261ecSmrg * Machine independent event queue 3205b261ecSmrg * 3305b261ecSmrg */ 3405b261ecSmrg 3505b261ecSmrg#if HAVE_DIX_CONFIG_H 3605b261ecSmrg#include <dix-config.h> 3705b261ecSmrg#endif 3805b261ecSmrg 3935c4bbdfSmrg#include <X11/X.h> 4035c4bbdfSmrg#include <X11/Xmd.h> 4135c4bbdfSmrg#include <X11/Xproto.h> 4235c4bbdfSmrg#include "misc.h" 4335c4bbdfSmrg#include "windowstr.h" 4435c4bbdfSmrg#include "pixmapstr.h" 4535c4bbdfSmrg#include "inputstr.h" 4635c4bbdfSmrg#include "inpututils.h" 4735c4bbdfSmrg#include "mi.h" 4835c4bbdfSmrg#include "mipointer.h" 4935c4bbdfSmrg#include "scrnintstr.h" 5035c4bbdfSmrg#include <X11/extensions/XI.h> 5135c4bbdfSmrg#include <X11/extensions/XIproto.h> 5235c4bbdfSmrg#include <X11/extensions/geproto.h> 5335c4bbdfSmrg#include "extinit.h" 5435c4bbdfSmrg#include "exglobals.h" 5535c4bbdfSmrg#include "eventstr.h" 5605b261ecSmrg 5705b261ecSmrg#ifdef DPMSExtension 5835c4bbdfSmrg#include "dpmsproc.h" 5935c4bbdfSmrg#include <X11/extensions/dpmsconst.h> 6005b261ecSmrg#endif 6105b261ecSmrg 6235c4bbdfSmrg/* Maximum size should be initial size multiplied by a power of 2 */ 6335c4bbdfSmrg#define QUEUE_INITIAL_SIZE 512 6435c4bbdfSmrg#define QUEUE_RESERVED_SIZE 64 6535c4bbdfSmrg#define QUEUE_MAXIMUM_SIZE 4096 6635c4bbdfSmrg#define QUEUE_DROP_BACKTRACE_FREQUENCY 100 6735c4bbdfSmrg#define QUEUE_DROP_BACKTRACE_MAX 10 6805b261ecSmrg 694642e01fSmrg#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen 704642e01fSmrg#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen 714642e01fSmrg 7205b261ecSmrgtypedef struct _Event { 7335c4bbdfSmrg InternalEvent *events; 7435c4bbdfSmrg ScreenPtr pScreen; 7535c4bbdfSmrg DeviceIntPtr pDev; /* device this event _originated_ from */ 7605b261ecSmrg} EventRec, *EventPtr; 7705b261ecSmrg 7805b261ecSmrgtypedef struct _EventQueue { 7935c4bbdfSmrg HWEventQueueType head, tail; /* long for SetInputCheck */ 8035c4bbdfSmrg CARD32 lastEventTime; /* to avoid time running backwards */ 8135c4bbdfSmrg int lastMotion; /* device ID if last event motion? */ 8235c4bbdfSmrg EventRec *events; /* our queue as an array */ 8335c4bbdfSmrg size_t nevents; /* the number of buckets in our queue */ 8435c4bbdfSmrg size_t dropped; /* counter for number of consecutive dropped events */ 8535c4bbdfSmrg mieqHandler handlers[128]; /* custom event handler */ 8605b261ecSmrg} EventQueueRec, *EventQueuePtr; 8705b261ecSmrg 8805b261ecSmrgstatic EventQueueRec miEventQueue; 894642e01fSmrg 90ed6184dfSmrgstatic CallbackListPtr miCallbacksWhenDrained = NULL; 91ed6184dfSmrg 9235c4bbdfSmrgstatic size_t 9335c4bbdfSmrgmieqNumEnqueued(EventQueuePtr eventQueue) 9435c4bbdfSmrg{ 9535c4bbdfSmrg size_t n_enqueued = 0; 9635c4bbdfSmrg 9735c4bbdfSmrg if (eventQueue->nevents) { 9835c4bbdfSmrg /* % is not well-defined with negative numbers... sigh */ 9935c4bbdfSmrg n_enqueued = eventQueue->tail - eventQueue->head + eventQueue->nevents; 10035c4bbdfSmrg if (n_enqueued >= eventQueue->nevents) 10135c4bbdfSmrg n_enqueued -= eventQueue->nevents; 10235c4bbdfSmrg } 10335c4bbdfSmrg return n_enqueued; 10435c4bbdfSmrg} 10535c4bbdfSmrg 1061b5d61b8Smrg/* Pre-condition: Called with input_lock held */ 10735c4bbdfSmrgstatic Bool 10835c4bbdfSmrgmieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) 10935c4bbdfSmrg{ 11035c4bbdfSmrg size_t i, n_enqueued, first_hunk; 11135c4bbdfSmrg EventRec *new_events; 11235c4bbdfSmrg 11335c4bbdfSmrg if (!eventQueue) { 11435c4bbdfSmrg ErrorF("[mi] mieqGrowQueue called with a NULL eventQueue\n"); 11535c4bbdfSmrg return FALSE; 11635c4bbdfSmrg } 11735c4bbdfSmrg 11835c4bbdfSmrg if (new_nevents <= eventQueue->nevents) 11935c4bbdfSmrg return FALSE; 12035c4bbdfSmrg 12135c4bbdfSmrg new_events = calloc(new_nevents, sizeof(EventRec)); 12235c4bbdfSmrg if (new_events == NULL) { 12335c4bbdfSmrg ErrorF("[mi] mieqGrowQueue memory allocation error.\n"); 12435c4bbdfSmrg return FALSE; 12535c4bbdfSmrg } 12635c4bbdfSmrg 12735c4bbdfSmrg n_enqueued = mieqNumEnqueued(eventQueue); 12835c4bbdfSmrg 12935c4bbdfSmrg /* First copy the existing events */ 13035c4bbdfSmrg first_hunk = eventQueue->nevents - eventQueue->head; 131ed6184dfSmrg if (eventQueue->events) { 132ed6184dfSmrg memcpy(new_events, 133ed6184dfSmrg &eventQueue->events[eventQueue->head], 134ed6184dfSmrg first_hunk * sizeof(EventRec)); 135ed6184dfSmrg memcpy(&new_events[first_hunk], 136ed6184dfSmrg eventQueue->events, eventQueue->head * sizeof(EventRec)); 137ed6184dfSmrg } 13835c4bbdfSmrg 13935c4bbdfSmrg /* Initialize the new portion */ 14035c4bbdfSmrg for (i = eventQueue->nevents; i < new_nevents; i++) { 14135c4bbdfSmrg InternalEvent *evlist = InitEventList(1); 14235c4bbdfSmrg 14335c4bbdfSmrg if (!evlist) { 14435c4bbdfSmrg size_t j; 14535c4bbdfSmrg 14635c4bbdfSmrg for (j = 0; j < i; j++) 14735c4bbdfSmrg FreeEventList(new_events[j].events, 1); 14835c4bbdfSmrg free(new_events); 14935c4bbdfSmrg return FALSE; 15035c4bbdfSmrg } 15135c4bbdfSmrg new_events[i].events = evlist; 15235c4bbdfSmrg } 15335c4bbdfSmrg 15435c4bbdfSmrg /* And update our record */ 15535c4bbdfSmrg eventQueue->tail = n_enqueued; 15635c4bbdfSmrg eventQueue->head = 0; 15735c4bbdfSmrg eventQueue->nevents = new_nevents; 15835c4bbdfSmrg free(eventQueue->events); 15935c4bbdfSmrg eventQueue->events = new_events; 16035c4bbdfSmrg 16135c4bbdfSmrg return TRUE; 16235c4bbdfSmrg} 16335c4bbdfSmrg 16405b261ecSmrgBool 16505b261ecSmrgmieqInit(void) 16605b261ecSmrg{ 16735c4bbdfSmrg memset(&miEventQueue, 0, sizeof(miEventQueue)); 16835c4bbdfSmrg miEventQueue.lastEventTime = GetTimeInMillis(); 16905b261ecSmrg 1701b5d61b8Smrg input_lock(); 17135c4bbdfSmrg if (!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE)) 17235c4bbdfSmrg FatalError("Could not allocate event queue.\n"); 1731b5d61b8Smrg input_unlock(); 1744642e01fSmrg 17505b261ecSmrg SetInputCheck(&miEventQueue.head, &miEventQueue.tail); 17605b261ecSmrg return TRUE; 17705b261ecSmrg} 17805b261ecSmrg 1794642e01fSmrgvoid 1806747b715SmrgmieqFini(void) 1814642e01fSmrg{ 1824642e01fSmrg int i; 18335c4bbdfSmrg 18435c4bbdfSmrg for (i = 0; i < miEventQueue.nevents; i++) { 18535c4bbdfSmrg if (miEventQueue.events[i].events != NULL) { 18635c4bbdfSmrg FreeEventList(miEventQueue.events[i].events, 1); 18735c4bbdfSmrg miEventQueue.events[i].events = NULL; 18835c4bbdfSmrg } 18935c4bbdfSmrg } 19035c4bbdfSmrg free(miEventQueue.events); 19135c4bbdfSmrg} 19235c4bbdfSmrg 19305b261ecSmrg/* 19405b261ecSmrg * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue 1951b5d61b8Smrg * will never be interrupted. Must be called with input_lock held 19605b261ecSmrg */ 19705b261ecSmrg 19805b261ecSmrgvoid 1996747b715SmrgmieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) 20005b261ecSmrg{ 20135c4bbdfSmrg unsigned int oldtail = miEventQueue.tail; 20235c4bbdfSmrg InternalEvent *evt; 20335c4bbdfSmrg int isMotion = 0; 20435c4bbdfSmrg int evlen; 20535c4bbdfSmrg Time time; 20635c4bbdfSmrg size_t n_enqueued; 20705b261ecSmrg 20835c4bbdfSmrg verify_internal_event(e); 20935c4bbdfSmrg 21035c4bbdfSmrg n_enqueued = mieqNumEnqueued(&miEventQueue); 2116747b715Smrg 2124642e01fSmrg /* avoid merging events from different devices */ 2136747b715Smrg if (e->any.type == ET_Motion) 21405b261ecSmrg isMotion = pDev->id; 21505b261ecSmrg 21605b261ecSmrg if (isMotion && isMotion == miEventQueue.lastMotion && 21705b261ecSmrg oldtail != miEventQueue.head) { 21835c4bbdfSmrg oldtail = (oldtail - 1) % miEventQueue.nevents; 21905b261ecSmrg } 2201b5d61b8Smrg else if (n_enqueued + 1 == miEventQueue.nevents) { 2211b5d61b8Smrg if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) { 2221b5d61b8Smrg /* Toss events which come in late. Usually this means your server's 2231b5d61b8Smrg * stuck in an infinite loop in the main thread. 2241b5d61b8Smrg */ 2251b5d61b8Smrg miEventQueue.dropped++; 2261b5d61b8Smrg if (miEventQueue.dropped == 1) { 2271b5d61b8Smrg ErrorFSigSafe("[mi] EQ overflowing. Additional events will be " 2281b5d61b8Smrg "discarded until existing events are processed.\n"); 2291b5d61b8Smrg xorg_backtrace(); 2301b5d61b8Smrg ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to " 2311b5d61b8Smrg "a culprit higher up the stack.\n"); 2321b5d61b8Smrg ErrorFSigSafe("[mi] mieq is *NOT* the cause. It is a victim.\n"); 2331b5d61b8Smrg } 2341b5d61b8Smrg else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 && 2351b5d61b8Smrg miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <= 2361b5d61b8Smrg QUEUE_DROP_BACKTRACE_MAX) { 2371b5d61b8Smrg ErrorFSigSafe("[mi] EQ overflow continuing. %zu events have been " 2381b5d61b8Smrg "dropped.\n", miEventQueue.dropped); 2391b5d61b8Smrg if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY == 2401b5d61b8Smrg QUEUE_DROP_BACKTRACE_MAX) { 2411b5d61b8Smrg ErrorFSigSafe("[mi] No further overflow reports will be " 2421b5d61b8Smrg "reported until the clog is cleared.\n"); 2431b5d61b8Smrg } 2441b5d61b8Smrg xorg_backtrace(); 2456747b715Smrg } 2461b5d61b8Smrg return; 24705b261ecSmrg } 2481b5d61b8Smrg oldtail = miEventQueue.tail; 24905b261ecSmrg } 25005b261ecSmrg 25135c4bbdfSmrg evlen = e->any.length; 25235c4bbdfSmrg evt = miEventQueue.events[oldtail].events; 25335c4bbdfSmrg memcpy(evt, e, evlen); 25405b261ecSmrg 2556747b715Smrg time = e->any.time; 25605b261ecSmrg /* Make sure that event times don't go backwards - this 25705b261ecSmrg * is "unnecessary", but very useful. */ 2586747b715Smrg if (time < miEventQueue.lastEventTime && 2596747b715Smrg miEventQueue.lastEventTime - time < 10000) 2606747b715Smrg e->any.time = miEventQueue.lastEventTime; 2614642e01fSmrg 26235c4bbdfSmrg miEventQueue.lastEventTime = evt->any.time; 2636747b715Smrg miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL; 26405b261ecSmrg miEventQueue.events[oldtail].pDev = pDev; 26505b261ecSmrg 26605b261ecSmrg miEventQueue.lastMotion = isMotion; 26735c4bbdfSmrg miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents; 26805b261ecSmrg} 26905b261ecSmrg 27035c4bbdfSmrg/** 27135c4bbdfSmrg * Changes the screen reference events are being enqueued from. 27235c4bbdfSmrg * Input events are enqueued with a screen reference and dequeued and 27335c4bbdfSmrg * processed with a (potentially different) screen reference. 27435c4bbdfSmrg * This function is called whenever a new event has changed screen but is 27535c4bbdfSmrg * still logically on the previous screen as seen by the client. 27635c4bbdfSmrg * This usually happens whenever the visible cursor moves across screen 27735c4bbdfSmrg * boundaries during event generation, before the same event is processed 27835c4bbdfSmrg * and sent down the wire. 27935c4bbdfSmrg * 28035c4bbdfSmrg * @param pDev The device that triggered a screen change. 28135c4bbdfSmrg * @param pScreen The new screen events are being enqueued for. 28235c4bbdfSmrg * @param set_dequeue_screen If TRUE, pScreen is set as both enqueue screen 28335c4bbdfSmrg * and dequeue screen. 28435c4bbdfSmrg */ 28505b261ecSmrgvoid 28635c4bbdfSmrgmieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool set_dequeue_screen) 28705b261ecSmrg{ 2884642e01fSmrg EnqueueScreen(pDev) = pScreen; 28935c4bbdfSmrg if (set_dequeue_screen) 2906747b715Smrg DequeueScreen(pDev) = pScreen; 29105b261ecSmrg} 29205b261ecSmrg 29305b261ecSmrgvoid 29405b261ecSmrgmieqSetHandler(int event, mieqHandler handler) 29505b261ecSmrg{ 296ed6184dfSmrg if (handler && miEventQueue.handlers[event] != handler) 2974642e01fSmrg ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for " 29805b261ecSmrg "event %d\n", miEventQueue.handlers[event], handler, event); 29905b261ecSmrg 30005b261ecSmrg miEventQueue.handlers[event] = handler; 3014642e01fSmrg} 3024642e01fSmrg 3034642e01fSmrg/** 3044642e01fSmrg * Change the device id of the given event to the given device's id. 3054642e01fSmrg */ 3064642e01fSmrgstatic void 30735c4bbdfSmrgChangeDeviceID(DeviceIntPtr dev, InternalEvent *event) 3084642e01fSmrg{ 30935c4bbdfSmrg switch (event->any.type) { 31035c4bbdfSmrg case ET_Motion: 31135c4bbdfSmrg case ET_KeyPress: 31235c4bbdfSmrg case ET_KeyRelease: 31335c4bbdfSmrg case ET_ButtonPress: 31435c4bbdfSmrg case ET_ButtonRelease: 31535c4bbdfSmrg case ET_ProximityIn: 31635c4bbdfSmrg case ET_ProximityOut: 31735c4bbdfSmrg case ET_Hierarchy: 31835c4bbdfSmrg case ET_DeviceChanged: 31935c4bbdfSmrg case ET_TouchBegin: 32035c4bbdfSmrg case ET_TouchUpdate: 32135c4bbdfSmrg case ET_TouchEnd: 32235c4bbdfSmrg event->device_event.deviceid = dev->id; 32335c4bbdfSmrg break; 32435c4bbdfSmrg case ET_TouchOwnership: 32535c4bbdfSmrg event->touch_ownership_event.deviceid = dev->id; 32635c4bbdfSmrg break; 3271b5d61b8Smrg#ifdef XFreeXDGA 32835c4bbdfSmrg case ET_DGAEvent: 32935c4bbdfSmrg break; 3306747b715Smrg#endif 33135c4bbdfSmrg case ET_RawKeyPress: 33235c4bbdfSmrg case ET_RawKeyRelease: 33335c4bbdfSmrg case ET_RawButtonPress: 33435c4bbdfSmrg case ET_RawButtonRelease: 33535c4bbdfSmrg case ET_RawMotion: 33635c4bbdfSmrg case ET_RawTouchBegin: 33735c4bbdfSmrg case ET_RawTouchEnd: 33835c4bbdfSmrg case ET_RawTouchUpdate: 33935c4bbdfSmrg event->raw_event.deviceid = dev->id; 34035c4bbdfSmrg break; 34135c4bbdfSmrg case ET_BarrierHit: 34235c4bbdfSmrg case ET_BarrierLeave: 34335c4bbdfSmrg event->barrier_event.deviceid = dev->id; 34435c4bbdfSmrg break; 345ed6184dfSmrg case ET_GesturePinchBegin: 346ed6184dfSmrg case ET_GesturePinchUpdate: 347ed6184dfSmrg case ET_GesturePinchEnd: 348ed6184dfSmrg case ET_GestureSwipeBegin: 349ed6184dfSmrg case ET_GestureSwipeUpdate: 350ed6184dfSmrg case ET_GestureSwipeEnd: 351ed6184dfSmrg event->gesture_event.deviceid = dev->id; 352ed6184dfSmrg break; 35335c4bbdfSmrg default: 35435c4bbdfSmrg ErrorF("[mi] Unknown event type (%d), cannot change id.\n", 35535c4bbdfSmrg event->any.type); 3566747b715Smrg } 35705b261ecSmrg} 35805b261ecSmrg 3594642e01fSmrgstatic void 3606747b715SmrgFixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev, 36135c4bbdfSmrg InternalEvent *original, InternalEvent *master) 3624642e01fSmrg{ 36335c4bbdfSmrg verify_internal_event(original); 36435c4bbdfSmrg verify_internal_event(master); 3654642e01fSmrg /* Ensure chained button mappings, i.e. that the detail field is the 3664642e01fSmrg * value of the mapped button on the SD, not the physical button */ 3676747b715Smrg if (original->any.type == ET_ButtonPress || 36835c4bbdfSmrg original->any.type == ET_ButtonRelease) { 3696747b715Smrg int btn = original->device_event.detail.button; 37035c4bbdfSmrg 3714642e01fSmrg if (!sdev->button) 37235c4bbdfSmrg return; /* Should never happen */ 3734642e01fSmrg 3746747b715Smrg master->device_event.detail.button = sdev->button->map[btn]; 3754642e01fSmrg } 3764642e01fSmrg} 3774642e01fSmrg 3784642e01fSmrg/** 3794642e01fSmrg * Copy the given event into master. 3804642e01fSmrg * @param sdev The slave device the original event comes from 3814642e01fSmrg * @param original The event as it came from the EQ 3826747b715Smrg * @param copy The event after being copied 3836747b715Smrg * @return The master device or NULL if the device is a floating slave. 3844642e01fSmrg */ 3856747b715SmrgDeviceIntPtr 3866747b715SmrgCopyGetMasterEvent(DeviceIntPtr sdev, 38735c4bbdfSmrg InternalEvent *original, InternalEvent *copy) 3884642e01fSmrg{ 3896747b715Smrg DeviceIntPtr mdev; 3906747b715Smrg int len = original->any.length; 3918223e2f2Smrg int type = original->any.type; 39235c4bbdfSmrg int mtype; /* which master type? */ 3934642e01fSmrg 39435c4bbdfSmrg verify_internal_event(original); 3954642e01fSmrg 3966747b715Smrg /* ET_XQuartz has sdev == NULL */ 39735c4bbdfSmrg if (!sdev || IsMaster(sdev) || IsFloating(sdev)) 3986747b715Smrg return NULL; 3994642e01fSmrg 4001b5d61b8Smrg#ifdef XFreeXDGA 4018223e2f2Smrg if (type == ET_DGAEvent) 4028223e2f2Smrg type = original->dga_event.subtype; 4038223e2f2Smrg#endif 4048223e2f2Smrg 40535c4bbdfSmrg switch (type) { 40635c4bbdfSmrg case ET_KeyPress: 40735c4bbdfSmrg case ET_KeyRelease: 40835c4bbdfSmrg mtype = MASTER_KEYBOARD; 40935c4bbdfSmrg break; 41035c4bbdfSmrg case ET_ButtonPress: 41135c4bbdfSmrg case ET_ButtonRelease: 41235c4bbdfSmrg case ET_Motion: 41335c4bbdfSmrg case ET_ProximityIn: 41435c4bbdfSmrg case ET_ProximityOut: 41535c4bbdfSmrg mtype = MASTER_POINTER; 41635c4bbdfSmrg break; 41735c4bbdfSmrg default: 41835c4bbdfSmrg mtype = MASTER_ATTACHED; 41935c4bbdfSmrg break; 4204642e01fSmrg } 4216747b715Smrg 42235c4bbdfSmrg mdev = GetMaster(sdev, mtype); 4236747b715Smrg memcpy(copy, original, len); 4246747b715Smrg ChangeDeviceID(mdev, copy); 4256747b715Smrg FixUpEventForMaster(mdev, sdev, original, copy); 4266747b715Smrg 4276747b715Smrg return mdev; 4284642e01fSmrg} 4294642e01fSmrg 43035c4bbdfSmrgstatic void 43135c4bbdfSmrgmieqMoveToNewScreen(DeviceIntPtr dev, ScreenPtr screen, DeviceEvent *event) 43235c4bbdfSmrg{ 43335c4bbdfSmrg if (dev && screen && screen != DequeueScreen(dev)) { 43435c4bbdfSmrg int x = 0, y = 0; 43535c4bbdfSmrg 43635c4bbdfSmrg DequeueScreen(dev) = screen; 43735c4bbdfSmrg x = event->root_x; 43835c4bbdfSmrg y = event->root_y; 43935c4bbdfSmrg NewCurrentScreen(dev, DequeueScreen(dev), x, y); 44035c4bbdfSmrg } 44135c4bbdfSmrg} 4424642e01fSmrg 4436747b715Smrg/** 4446747b715Smrg * Post the given @event through the device hierarchy, as appropriate. 4456747b715Smrg * Use this function if an event must be posted for a given device during the 4466747b715Smrg * usual event processing cycle. 4476747b715Smrg */ 4486747b715Smrgvoid 44935c4bbdfSmrgmieqProcessDeviceEvent(DeviceIntPtr dev, InternalEvent *event, ScreenPtr screen) 4506747b715Smrg{ 4516747b715Smrg mieqHandler handler; 4526747b715Smrg DeviceIntPtr master; 45335c4bbdfSmrg InternalEvent mevent; /* master event */ 4546747b715Smrg 45535c4bbdfSmrg verify_internal_event(event); 45635c4bbdfSmrg 45735c4bbdfSmrg /* refuse events from disabled devices */ 45835c4bbdfSmrg if (dev && !dev->enabled) 45935c4bbdfSmrg return; 4606747b715Smrg 4616747b715Smrg /* Custom event handler */ 4626747b715Smrg handler = miEventQueue.handlers[event->any.type]; 4636747b715Smrg 4646747b715Smrg switch (event->any.type) { 4656747b715Smrg /* Catch events that include valuator information and check if they 4666747b715Smrg * are changing the screen */ 46735c4bbdfSmrg case ET_Motion: 46835c4bbdfSmrg case ET_KeyPress: 46935c4bbdfSmrg case ET_KeyRelease: 47035c4bbdfSmrg case ET_ButtonPress: 47135c4bbdfSmrg case ET_ButtonRelease: 47235c4bbdfSmrg if (!handler) 47335c4bbdfSmrg mieqMoveToNewScreen(dev, screen, &event->device_event); 47435c4bbdfSmrg break; 47535c4bbdfSmrg case ET_TouchBegin: 47635c4bbdfSmrg case ET_TouchUpdate: 47735c4bbdfSmrg case ET_TouchEnd: 47835c4bbdfSmrg if (!handler && (event->device_event.flags & TOUCH_POINTER_EMULATED)) 47935c4bbdfSmrg mieqMoveToNewScreen(dev, screen, &event->device_event); 48035c4bbdfSmrg break; 48135c4bbdfSmrg default: 48235c4bbdfSmrg break; 4836747b715Smrg } 4846747b715Smrg master = CopyGetMasterEvent(dev, event, &mevent); 4856747b715Smrg 4866747b715Smrg if (master) 48735c4bbdfSmrg master->lastSlave = dev; 4886747b715Smrg 4896747b715Smrg /* If someone's registered a custom event handler, let them 4906747b715Smrg * steal it. */ 49135c4bbdfSmrg if (handler) { 49235c4bbdfSmrg int screenNum = dev && 49335c4bbdfSmrg DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen-> 49435c4bbdfSmrg myNum : 0); 4956747b715Smrg handler(screenNum, event, dev); 4966747b715Smrg /* Check for the SD's master in case the device got detached 4976747b715Smrg * during event processing */ 49835c4bbdfSmrg if (master && !IsFloating(dev)) 4996747b715Smrg handler(screenNum, &mevent, master); 50035c4bbdfSmrg } 50135c4bbdfSmrg else { 5026747b715Smrg /* process slave first, then master */ 5036747b715Smrg dev->public.processInputProc(event, dev); 5046747b715Smrg 5056747b715Smrg /* Check for the SD's master in case the device got detached 5066747b715Smrg * during event processing */ 50735c4bbdfSmrg if (master && !IsFloating(dev)) 5086747b715Smrg master->public.processInputProc(&mevent, master); 5096747b715Smrg } 5106747b715Smrg} 5114642e01fSmrg 51205b261ecSmrg/* Call this from ProcessInputEvents(). */ 51305b261ecSmrgvoid 51405b261ecSmrgmieqProcessInputEvents(void) 51505b261ecSmrg{ 51605b261ecSmrg EventRec *e = NULL; 5174642e01fSmrg ScreenPtr screen; 51835c4bbdfSmrg InternalEvent event; 51935c4bbdfSmrg DeviceIntPtr dev = NULL, master = NULL; 52035c4bbdfSmrg static Bool inProcessInputEvents = FALSE; 5214642e01fSmrg 5221b5d61b8Smrg input_lock(); 5234642e01fSmrg 52435c4bbdfSmrg /* 52535c4bbdfSmrg * report an error if mieqProcessInputEvents() is called recursively; 52635c4bbdfSmrg * this can happen, e.g., if something in the mieqProcessDeviceEvent() 52735c4bbdfSmrg * call chain calls UpdateCurrentTime() instead of UpdateCurrentTimeIf() 52835c4bbdfSmrg */ 52935c4bbdfSmrg BUG_WARN_MSG(inProcessInputEvents, "[mi] mieqProcessInputEvents() called recursively.\n"); 53035c4bbdfSmrg inProcessInputEvents = TRUE; 53135c4bbdfSmrg 53235c4bbdfSmrg if (miEventQueue.dropped) { 53335c4bbdfSmrg ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n", 53435c4bbdfSmrg (unsigned long) miEventQueue.dropped); 53535c4bbdfSmrg ErrorF 53635c4bbdfSmrg ("[mi] This may be caused by a misbehaving driver monopolizing the server's resources.\n"); 53735c4bbdfSmrg miEventQueue.dropped = 0; 53835c4bbdfSmrg } 5394642e01fSmrg 54035c4bbdfSmrg while (miEventQueue.head != miEventQueue.tail) { 54135c4bbdfSmrg e = &miEventQueue.events[miEventQueue.head]; 5424642e01fSmrg 54335c4bbdfSmrg event = *e->events; 54435c4bbdfSmrg dev = e->pDev; 54535c4bbdfSmrg screen = e->pScreen; 5464642e01fSmrg 54735c4bbdfSmrg miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents; 5484642e01fSmrg 5491b5d61b8Smrg input_unlock(); 5506747b715Smrg 55135c4bbdfSmrg master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL; 5524642e01fSmrg 55305b261ecSmrg if (screenIsSaved == SCREEN_SAVER_ON) 55435c4bbdfSmrg dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); 55505b261ecSmrg#ifdef DPMSExtension 55605b261ecSmrg else if (DPMSPowerLevel != DPMSModeOn) 55705b261ecSmrg SetScreenSaverTimer(); 55805b261ecSmrg 55905b261ecSmrg if (DPMSPowerLevel != DPMSModeOn) 5604642e01fSmrg DPMSSet(serverClient, DPMSModeOn); 56105b261ecSmrg#endif 56205b261ecSmrg 56335c4bbdfSmrg mieqProcessDeviceEvent(dev, &event, screen); 56405b261ecSmrg 5654642e01fSmrg /* Update the sprite now. Next event may be from different device. */ 56635c4bbdfSmrg if (master && 56735c4bbdfSmrg (event.any.type == ET_Motion || 56835c4bbdfSmrg ((event.any.type == ET_TouchBegin || 56935c4bbdfSmrg event.any.type == ET_TouchUpdate) && 57035c4bbdfSmrg event.device_event.flags & TOUCH_POINTER_EMULATED))) 5714642e01fSmrg miPointerUpdateSprite(dev); 57205b261ecSmrg 5731b5d61b8Smrg input_lock(); 57405b261ecSmrg } 57535c4bbdfSmrg 57635c4bbdfSmrg inProcessInputEvents = FALSE; 57735c4bbdfSmrg 578ed6184dfSmrg CallCallbacks(&miCallbacksWhenDrained, NULL); 579ed6184dfSmrg 580ed6184dfSmrg input_unlock(); 581ed6184dfSmrg} 582ed6184dfSmrg 583ed6184dfSmrgvoid mieqAddCallbackOnDrained(CallbackProcPtr callback, void *param) 584ed6184dfSmrg{ 585ed6184dfSmrg input_lock(); 586ed6184dfSmrg AddCallback(&miCallbacksWhenDrained, callback, param); 587ed6184dfSmrg input_unlock(); 588ed6184dfSmrg} 589ed6184dfSmrg 590ed6184dfSmrgvoid mieqRemoveCallbackOnDrained(CallbackProcPtr callback, void *param) 591ed6184dfSmrg{ 592ed6184dfSmrg input_lock(); 593ed6184dfSmrg DeleteCallback(&miCallbacksWhenDrained, callback, param); 5941b5d61b8Smrg input_unlock(); 59505b261ecSmrg} 596