mieq.c revision 1b5d61b8
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 9035c4bbdfSmrgstatic size_t 9135c4bbdfSmrgmieqNumEnqueued(EventQueuePtr eventQueue) 9235c4bbdfSmrg{ 9335c4bbdfSmrg size_t n_enqueued = 0; 9435c4bbdfSmrg 9535c4bbdfSmrg if (eventQueue->nevents) { 9635c4bbdfSmrg /* % is not well-defined with negative numbers... sigh */ 9735c4bbdfSmrg n_enqueued = eventQueue->tail - eventQueue->head + eventQueue->nevents; 9835c4bbdfSmrg if (n_enqueued >= eventQueue->nevents) 9935c4bbdfSmrg n_enqueued -= eventQueue->nevents; 10035c4bbdfSmrg } 10135c4bbdfSmrg return n_enqueued; 10235c4bbdfSmrg} 10335c4bbdfSmrg 1041b5d61b8Smrg/* Pre-condition: Called with input_lock held */ 10535c4bbdfSmrgstatic Bool 10635c4bbdfSmrgmieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) 10735c4bbdfSmrg{ 10835c4bbdfSmrg size_t i, n_enqueued, first_hunk; 10935c4bbdfSmrg EventRec *new_events; 11035c4bbdfSmrg 11135c4bbdfSmrg if (!eventQueue) { 11235c4bbdfSmrg ErrorF("[mi] mieqGrowQueue called with a NULL eventQueue\n"); 11335c4bbdfSmrg return FALSE; 11435c4bbdfSmrg } 11535c4bbdfSmrg 11635c4bbdfSmrg if (new_nevents <= eventQueue->nevents) 11735c4bbdfSmrg return FALSE; 11835c4bbdfSmrg 11935c4bbdfSmrg new_events = calloc(new_nevents, sizeof(EventRec)); 12035c4bbdfSmrg if (new_events == NULL) { 12135c4bbdfSmrg ErrorF("[mi] mieqGrowQueue memory allocation error.\n"); 12235c4bbdfSmrg return FALSE; 12335c4bbdfSmrg } 12435c4bbdfSmrg 12535c4bbdfSmrg n_enqueued = mieqNumEnqueued(eventQueue); 12635c4bbdfSmrg 12735c4bbdfSmrg /* First copy the existing events */ 12835c4bbdfSmrg first_hunk = eventQueue->nevents - eventQueue->head; 12935c4bbdfSmrg memcpy(new_events, 13035c4bbdfSmrg &eventQueue->events[eventQueue->head], 13135c4bbdfSmrg first_hunk * sizeof(EventRec)); 13235c4bbdfSmrg memcpy(&new_events[first_hunk], 13335c4bbdfSmrg eventQueue->events, eventQueue->head * sizeof(EventRec)); 13435c4bbdfSmrg 13535c4bbdfSmrg /* Initialize the new portion */ 13635c4bbdfSmrg for (i = eventQueue->nevents; i < new_nevents; i++) { 13735c4bbdfSmrg InternalEvent *evlist = InitEventList(1); 13835c4bbdfSmrg 13935c4bbdfSmrg if (!evlist) { 14035c4bbdfSmrg size_t j; 14135c4bbdfSmrg 14235c4bbdfSmrg for (j = 0; j < i; j++) 14335c4bbdfSmrg FreeEventList(new_events[j].events, 1); 14435c4bbdfSmrg free(new_events); 14535c4bbdfSmrg return FALSE; 14635c4bbdfSmrg } 14735c4bbdfSmrg new_events[i].events = evlist; 14835c4bbdfSmrg } 14935c4bbdfSmrg 15035c4bbdfSmrg /* And update our record */ 15135c4bbdfSmrg eventQueue->tail = n_enqueued; 15235c4bbdfSmrg eventQueue->head = 0; 15335c4bbdfSmrg eventQueue->nevents = new_nevents; 15435c4bbdfSmrg free(eventQueue->events); 15535c4bbdfSmrg eventQueue->events = new_events; 15635c4bbdfSmrg 15735c4bbdfSmrg return TRUE; 15835c4bbdfSmrg} 15935c4bbdfSmrg 16005b261ecSmrgBool 16105b261ecSmrgmieqInit(void) 16205b261ecSmrg{ 16335c4bbdfSmrg memset(&miEventQueue, 0, sizeof(miEventQueue)); 16435c4bbdfSmrg miEventQueue.lastEventTime = GetTimeInMillis(); 16505b261ecSmrg 1661b5d61b8Smrg input_lock(); 16735c4bbdfSmrg if (!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE)) 16835c4bbdfSmrg FatalError("Could not allocate event queue.\n"); 1691b5d61b8Smrg input_unlock(); 1704642e01fSmrg 17105b261ecSmrg SetInputCheck(&miEventQueue.head, &miEventQueue.tail); 17205b261ecSmrg return TRUE; 17305b261ecSmrg} 17405b261ecSmrg 1754642e01fSmrgvoid 1766747b715SmrgmieqFini(void) 1774642e01fSmrg{ 1784642e01fSmrg int i; 17935c4bbdfSmrg 18035c4bbdfSmrg for (i = 0; i < miEventQueue.nevents; i++) { 18135c4bbdfSmrg if (miEventQueue.events[i].events != NULL) { 18235c4bbdfSmrg FreeEventList(miEventQueue.events[i].events, 1); 18335c4bbdfSmrg miEventQueue.events[i].events = NULL; 18435c4bbdfSmrg } 18535c4bbdfSmrg } 18635c4bbdfSmrg free(miEventQueue.events); 18735c4bbdfSmrg} 18835c4bbdfSmrg 18905b261ecSmrg/* 19005b261ecSmrg * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue 1911b5d61b8Smrg * will never be interrupted. Must be called with input_lock held 19205b261ecSmrg */ 19305b261ecSmrg 19405b261ecSmrgvoid 1956747b715SmrgmieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) 19605b261ecSmrg{ 19735c4bbdfSmrg unsigned int oldtail = miEventQueue.tail; 19835c4bbdfSmrg InternalEvent *evt; 19935c4bbdfSmrg int isMotion = 0; 20035c4bbdfSmrg int evlen; 20135c4bbdfSmrg Time time; 20235c4bbdfSmrg size_t n_enqueued; 20305b261ecSmrg 20435c4bbdfSmrg verify_internal_event(e); 20535c4bbdfSmrg 20635c4bbdfSmrg n_enqueued = mieqNumEnqueued(&miEventQueue); 2076747b715Smrg 2084642e01fSmrg /* avoid merging events from different devices */ 2096747b715Smrg if (e->any.type == ET_Motion) 21005b261ecSmrg isMotion = pDev->id; 21105b261ecSmrg 21205b261ecSmrg if (isMotion && isMotion == miEventQueue.lastMotion && 21305b261ecSmrg oldtail != miEventQueue.head) { 21435c4bbdfSmrg oldtail = (oldtail - 1) % miEventQueue.nevents; 21505b261ecSmrg } 2161b5d61b8Smrg else if (n_enqueued + 1 == miEventQueue.nevents) { 2171b5d61b8Smrg if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) { 2181b5d61b8Smrg /* Toss events which come in late. Usually this means your server's 2191b5d61b8Smrg * stuck in an infinite loop in the main thread. 2201b5d61b8Smrg */ 2211b5d61b8Smrg miEventQueue.dropped++; 2221b5d61b8Smrg if (miEventQueue.dropped == 1) { 2231b5d61b8Smrg ErrorFSigSafe("[mi] EQ overflowing. Additional events will be " 2241b5d61b8Smrg "discarded until existing events are processed.\n"); 2251b5d61b8Smrg xorg_backtrace(); 2261b5d61b8Smrg ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to " 2271b5d61b8Smrg "a culprit higher up the stack.\n"); 2281b5d61b8Smrg ErrorFSigSafe("[mi] mieq is *NOT* the cause. It is a victim.\n"); 2291b5d61b8Smrg } 2301b5d61b8Smrg else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 && 2311b5d61b8Smrg miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <= 2321b5d61b8Smrg QUEUE_DROP_BACKTRACE_MAX) { 2331b5d61b8Smrg ErrorFSigSafe("[mi] EQ overflow continuing. %zu events have been " 2341b5d61b8Smrg "dropped.\n", miEventQueue.dropped); 2351b5d61b8Smrg if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY == 2361b5d61b8Smrg QUEUE_DROP_BACKTRACE_MAX) { 2371b5d61b8Smrg ErrorFSigSafe("[mi] No further overflow reports will be " 2381b5d61b8Smrg "reported until the clog is cleared.\n"); 2391b5d61b8Smrg } 2401b5d61b8Smrg xorg_backtrace(); 2416747b715Smrg } 2421b5d61b8Smrg return; 24305b261ecSmrg } 2441b5d61b8Smrg oldtail = miEventQueue.tail; 24505b261ecSmrg } 24605b261ecSmrg 24735c4bbdfSmrg evlen = e->any.length; 24835c4bbdfSmrg evt = miEventQueue.events[oldtail].events; 24935c4bbdfSmrg memcpy(evt, e, evlen); 25005b261ecSmrg 2516747b715Smrg time = e->any.time; 25205b261ecSmrg /* Make sure that event times don't go backwards - this 25305b261ecSmrg * is "unnecessary", but very useful. */ 2546747b715Smrg if (time < miEventQueue.lastEventTime && 2556747b715Smrg miEventQueue.lastEventTime - time < 10000) 2566747b715Smrg e->any.time = miEventQueue.lastEventTime; 2574642e01fSmrg 25835c4bbdfSmrg miEventQueue.lastEventTime = evt->any.time; 2596747b715Smrg miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL; 26005b261ecSmrg miEventQueue.events[oldtail].pDev = pDev; 26105b261ecSmrg 26205b261ecSmrg miEventQueue.lastMotion = isMotion; 26335c4bbdfSmrg miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents; 26405b261ecSmrg} 26505b261ecSmrg 26635c4bbdfSmrg/** 26735c4bbdfSmrg * Changes the screen reference events are being enqueued from. 26835c4bbdfSmrg * Input events are enqueued with a screen reference and dequeued and 26935c4bbdfSmrg * processed with a (potentially different) screen reference. 27035c4bbdfSmrg * This function is called whenever a new event has changed screen but is 27135c4bbdfSmrg * still logically on the previous screen as seen by the client. 27235c4bbdfSmrg * This usually happens whenever the visible cursor moves across screen 27335c4bbdfSmrg * boundaries during event generation, before the same event is processed 27435c4bbdfSmrg * and sent down the wire. 27535c4bbdfSmrg * 27635c4bbdfSmrg * @param pDev The device that triggered a screen change. 27735c4bbdfSmrg * @param pScreen The new screen events are being enqueued for. 27835c4bbdfSmrg * @param set_dequeue_screen If TRUE, pScreen is set as both enqueue screen 27935c4bbdfSmrg * and dequeue screen. 28035c4bbdfSmrg */ 28105b261ecSmrgvoid 28235c4bbdfSmrgmieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool set_dequeue_screen) 28305b261ecSmrg{ 2844642e01fSmrg EnqueueScreen(pDev) = pScreen; 28535c4bbdfSmrg if (set_dequeue_screen) 2866747b715Smrg DequeueScreen(pDev) = pScreen; 28705b261ecSmrg} 28805b261ecSmrg 28905b261ecSmrgvoid 29005b261ecSmrgmieqSetHandler(int event, mieqHandler handler) 29105b261ecSmrg{ 29205b261ecSmrg if (handler && miEventQueue.handlers[event]) 2934642e01fSmrg ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for " 29405b261ecSmrg "event %d\n", miEventQueue.handlers[event], handler, event); 29505b261ecSmrg 29605b261ecSmrg miEventQueue.handlers[event] = handler; 2974642e01fSmrg} 2984642e01fSmrg 2994642e01fSmrg/** 3004642e01fSmrg * Change the device id of the given event to the given device's id. 3014642e01fSmrg */ 3024642e01fSmrgstatic void 30335c4bbdfSmrgChangeDeviceID(DeviceIntPtr dev, InternalEvent *event) 3044642e01fSmrg{ 30535c4bbdfSmrg switch (event->any.type) { 30635c4bbdfSmrg case ET_Motion: 30735c4bbdfSmrg case ET_KeyPress: 30835c4bbdfSmrg case ET_KeyRelease: 30935c4bbdfSmrg case ET_ButtonPress: 31035c4bbdfSmrg case ET_ButtonRelease: 31135c4bbdfSmrg case ET_ProximityIn: 31235c4bbdfSmrg case ET_ProximityOut: 31335c4bbdfSmrg case ET_Hierarchy: 31435c4bbdfSmrg case ET_DeviceChanged: 31535c4bbdfSmrg case ET_TouchBegin: 31635c4bbdfSmrg case ET_TouchUpdate: 31735c4bbdfSmrg case ET_TouchEnd: 31835c4bbdfSmrg event->device_event.deviceid = dev->id; 31935c4bbdfSmrg break; 32035c4bbdfSmrg case ET_TouchOwnership: 32135c4bbdfSmrg event->touch_ownership_event.deviceid = dev->id; 32235c4bbdfSmrg break; 3231b5d61b8Smrg#ifdef XFreeXDGA 32435c4bbdfSmrg case ET_DGAEvent: 32535c4bbdfSmrg break; 3266747b715Smrg#endif 32735c4bbdfSmrg case ET_RawKeyPress: 32835c4bbdfSmrg case ET_RawKeyRelease: 32935c4bbdfSmrg case ET_RawButtonPress: 33035c4bbdfSmrg case ET_RawButtonRelease: 33135c4bbdfSmrg case ET_RawMotion: 33235c4bbdfSmrg case ET_RawTouchBegin: 33335c4bbdfSmrg case ET_RawTouchEnd: 33435c4bbdfSmrg case ET_RawTouchUpdate: 33535c4bbdfSmrg event->raw_event.deviceid = dev->id; 33635c4bbdfSmrg break; 33735c4bbdfSmrg case ET_BarrierHit: 33835c4bbdfSmrg case ET_BarrierLeave: 33935c4bbdfSmrg event->barrier_event.deviceid = dev->id; 34035c4bbdfSmrg break; 34135c4bbdfSmrg default: 34235c4bbdfSmrg ErrorF("[mi] Unknown event type (%d), cannot change id.\n", 34335c4bbdfSmrg event->any.type); 3446747b715Smrg } 34505b261ecSmrg} 34605b261ecSmrg 3474642e01fSmrgstatic void 3486747b715SmrgFixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev, 34935c4bbdfSmrg InternalEvent *original, InternalEvent *master) 3504642e01fSmrg{ 35135c4bbdfSmrg verify_internal_event(original); 35235c4bbdfSmrg verify_internal_event(master); 3534642e01fSmrg /* Ensure chained button mappings, i.e. that the detail field is the 3544642e01fSmrg * value of the mapped button on the SD, not the physical button */ 3556747b715Smrg if (original->any.type == ET_ButtonPress || 35635c4bbdfSmrg original->any.type == ET_ButtonRelease) { 3576747b715Smrg int btn = original->device_event.detail.button; 35835c4bbdfSmrg 3594642e01fSmrg if (!sdev->button) 36035c4bbdfSmrg return; /* Should never happen */ 3614642e01fSmrg 3626747b715Smrg master->device_event.detail.button = sdev->button->map[btn]; 3634642e01fSmrg } 3644642e01fSmrg} 3654642e01fSmrg 3664642e01fSmrg/** 3674642e01fSmrg * Copy the given event into master. 3684642e01fSmrg * @param sdev The slave device the original event comes from 3694642e01fSmrg * @param original The event as it came from the EQ 3706747b715Smrg * @param copy The event after being copied 3716747b715Smrg * @return The master device or NULL if the device is a floating slave. 3724642e01fSmrg */ 3736747b715SmrgDeviceIntPtr 3746747b715SmrgCopyGetMasterEvent(DeviceIntPtr sdev, 37535c4bbdfSmrg InternalEvent *original, InternalEvent *copy) 3764642e01fSmrg{ 3776747b715Smrg DeviceIntPtr mdev; 3786747b715Smrg int len = original->any.length; 3798223e2f2Smrg int type = original->any.type; 38035c4bbdfSmrg int mtype; /* which master type? */ 3814642e01fSmrg 38235c4bbdfSmrg verify_internal_event(original); 3834642e01fSmrg 3846747b715Smrg /* ET_XQuartz has sdev == NULL */ 38535c4bbdfSmrg if (!sdev || IsMaster(sdev) || IsFloating(sdev)) 3866747b715Smrg return NULL; 3874642e01fSmrg 3881b5d61b8Smrg#ifdef XFreeXDGA 3898223e2f2Smrg if (type == ET_DGAEvent) 3908223e2f2Smrg type = original->dga_event.subtype; 3918223e2f2Smrg#endif 3928223e2f2Smrg 39335c4bbdfSmrg switch (type) { 39435c4bbdfSmrg case ET_KeyPress: 39535c4bbdfSmrg case ET_KeyRelease: 39635c4bbdfSmrg mtype = MASTER_KEYBOARD; 39735c4bbdfSmrg break; 39835c4bbdfSmrg case ET_ButtonPress: 39935c4bbdfSmrg case ET_ButtonRelease: 40035c4bbdfSmrg case ET_Motion: 40135c4bbdfSmrg case ET_ProximityIn: 40235c4bbdfSmrg case ET_ProximityOut: 40335c4bbdfSmrg mtype = MASTER_POINTER; 40435c4bbdfSmrg break; 40535c4bbdfSmrg default: 40635c4bbdfSmrg mtype = MASTER_ATTACHED; 40735c4bbdfSmrg break; 4084642e01fSmrg } 4096747b715Smrg 41035c4bbdfSmrg mdev = GetMaster(sdev, mtype); 4116747b715Smrg memcpy(copy, original, len); 4126747b715Smrg ChangeDeviceID(mdev, copy); 4136747b715Smrg FixUpEventForMaster(mdev, sdev, original, copy); 4146747b715Smrg 4156747b715Smrg return mdev; 4164642e01fSmrg} 4174642e01fSmrg 41835c4bbdfSmrgstatic void 41935c4bbdfSmrgmieqMoveToNewScreen(DeviceIntPtr dev, ScreenPtr screen, DeviceEvent *event) 42035c4bbdfSmrg{ 42135c4bbdfSmrg if (dev && screen && screen != DequeueScreen(dev)) { 42235c4bbdfSmrg int x = 0, y = 0; 42335c4bbdfSmrg 42435c4bbdfSmrg DequeueScreen(dev) = screen; 42535c4bbdfSmrg x = event->root_x; 42635c4bbdfSmrg y = event->root_y; 42735c4bbdfSmrg NewCurrentScreen(dev, DequeueScreen(dev), x, y); 42835c4bbdfSmrg } 42935c4bbdfSmrg} 4304642e01fSmrg 4316747b715Smrg/** 4326747b715Smrg * Post the given @event through the device hierarchy, as appropriate. 4336747b715Smrg * Use this function if an event must be posted for a given device during the 4346747b715Smrg * usual event processing cycle. 4356747b715Smrg */ 4366747b715Smrgvoid 43735c4bbdfSmrgmieqProcessDeviceEvent(DeviceIntPtr dev, InternalEvent *event, ScreenPtr screen) 4386747b715Smrg{ 4396747b715Smrg mieqHandler handler; 4406747b715Smrg DeviceIntPtr master; 44135c4bbdfSmrg InternalEvent mevent; /* master event */ 4426747b715Smrg 44335c4bbdfSmrg verify_internal_event(event); 44435c4bbdfSmrg 44535c4bbdfSmrg /* refuse events from disabled devices */ 44635c4bbdfSmrg if (dev && !dev->enabled) 44735c4bbdfSmrg return; 4486747b715Smrg 4496747b715Smrg /* Custom event handler */ 4506747b715Smrg handler = miEventQueue.handlers[event->any.type]; 4516747b715Smrg 4526747b715Smrg switch (event->any.type) { 4536747b715Smrg /* Catch events that include valuator information and check if they 4546747b715Smrg * are changing the screen */ 45535c4bbdfSmrg case ET_Motion: 45635c4bbdfSmrg case ET_KeyPress: 45735c4bbdfSmrg case ET_KeyRelease: 45835c4bbdfSmrg case ET_ButtonPress: 45935c4bbdfSmrg case ET_ButtonRelease: 46035c4bbdfSmrg if (!handler) 46135c4bbdfSmrg mieqMoveToNewScreen(dev, screen, &event->device_event); 46235c4bbdfSmrg break; 46335c4bbdfSmrg case ET_TouchBegin: 46435c4bbdfSmrg case ET_TouchUpdate: 46535c4bbdfSmrg case ET_TouchEnd: 46635c4bbdfSmrg if (!handler && (event->device_event.flags & TOUCH_POINTER_EMULATED)) 46735c4bbdfSmrg mieqMoveToNewScreen(dev, screen, &event->device_event); 46835c4bbdfSmrg break; 46935c4bbdfSmrg default: 47035c4bbdfSmrg break; 4716747b715Smrg } 4726747b715Smrg master = CopyGetMasterEvent(dev, event, &mevent); 4736747b715Smrg 4746747b715Smrg if (master) 47535c4bbdfSmrg master->lastSlave = dev; 4766747b715Smrg 4776747b715Smrg /* If someone's registered a custom event handler, let them 4786747b715Smrg * steal it. */ 47935c4bbdfSmrg if (handler) { 48035c4bbdfSmrg int screenNum = dev && 48135c4bbdfSmrg DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen-> 48235c4bbdfSmrg myNum : 0); 4836747b715Smrg handler(screenNum, event, dev); 4846747b715Smrg /* Check for the SD's master in case the device got detached 4856747b715Smrg * during event processing */ 48635c4bbdfSmrg if (master && !IsFloating(dev)) 4876747b715Smrg handler(screenNum, &mevent, master); 48835c4bbdfSmrg } 48935c4bbdfSmrg else { 4906747b715Smrg /* process slave first, then master */ 4916747b715Smrg dev->public.processInputProc(event, dev); 4926747b715Smrg 4936747b715Smrg /* Check for the SD's master in case the device got detached 4946747b715Smrg * during event processing */ 49535c4bbdfSmrg if (master && !IsFloating(dev)) 4966747b715Smrg master->public.processInputProc(&mevent, master); 4976747b715Smrg } 4986747b715Smrg} 4994642e01fSmrg 50005b261ecSmrg/* Call this from ProcessInputEvents(). */ 50105b261ecSmrgvoid 50205b261ecSmrgmieqProcessInputEvents(void) 50305b261ecSmrg{ 50405b261ecSmrg EventRec *e = NULL; 5054642e01fSmrg ScreenPtr screen; 50635c4bbdfSmrg InternalEvent event; 50735c4bbdfSmrg DeviceIntPtr dev = NULL, master = NULL; 50835c4bbdfSmrg static Bool inProcessInputEvents = FALSE; 5094642e01fSmrg 5101b5d61b8Smrg input_lock(); 5114642e01fSmrg 51235c4bbdfSmrg /* 51335c4bbdfSmrg * report an error if mieqProcessInputEvents() is called recursively; 51435c4bbdfSmrg * this can happen, e.g., if something in the mieqProcessDeviceEvent() 51535c4bbdfSmrg * call chain calls UpdateCurrentTime() instead of UpdateCurrentTimeIf() 51635c4bbdfSmrg */ 51735c4bbdfSmrg BUG_WARN_MSG(inProcessInputEvents, "[mi] mieqProcessInputEvents() called recursively.\n"); 51835c4bbdfSmrg inProcessInputEvents = TRUE; 51935c4bbdfSmrg 52035c4bbdfSmrg if (miEventQueue.dropped) { 52135c4bbdfSmrg ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n", 52235c4bbdfSmrg (unsigned long) miEventQueue.dropped); 52335c4bbdfSmrg ErrorF 52435c4bbdfSmrg ("[mi] This may be caused by a misbehaving driver monopolizing the server's resources.\n"); 52535c4bbdfSmrg miEventQueue.dropped = 0; 52635c4bbdfSmrg } 5274642e01fSmrg 52835c4bbdfSmrg while (miEventQueue.head != miEventQueue.tail) { 52935c4bbdfSmrg e = &miEventQueue.events[miEventQueue.head]; 5304642e01fSmrg 53135c4bbdfSmrg event = *e->events; 53235c4bbdfSmrg dev = e->pDev; 53335c4bbdfSmrg screen = e->pScreen; 5344642e01fSmrg 53535c4bbdfSmrg miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents; 5364642e01fSmrg 5371b5d61b8Smrg input_unlock(); 5386747b715Smrg 53935c4bbdfSmrg master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL; 5404642e01fSmrg 54105b261ecSmrg if (screenIsSaved == SCREEN_SAVER_ON) 54235c4bbdfSmrg dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); 54305b261ecSmrg#ifdef DPMSExtension 54405b261ecSmrg else if (DPMSPowerLevel != DPMSModeOn) 54505b261ecSmrg SetScreenSaverTimer(); 54605b261ecSmrg 54705b261ecSmrg if (DPMSPowerLevel != DPMSModeOn) 5484642e01fSmrg DPMSSet(serverClient, DPMSModeOn); 54905b261ecSmrg#endif 55005b261ecSmrg 55135c4bbdfSmrg mieqProcessDeviceEvent(dev, &event, screen); 55205b261ecSmrg 5534642e01fSmrg /* Update the sprite now. Next event may be from different device. */ 55435c4bbdfSmrg if (master && 55535c4bbdfSmrg (event.any.type == ET_Motion || 55635c4bbdfSmrg ((event.any.type == ET_TouchBegin || 55735c4bbdfSmrg event.any.type == ET_TouchUpdate) && 55835c4bbdfSmrg event.device_event.flags & TOUCH_POINTER_EMULATED))) 5594642e01fSmrg miPointerUpdateSprite(dev); 56005b261ecSmrg 5611b5d61b8Smrg input_lock(); 56205b261ecSmrg } 56335c4bbdfSmrg 56435c4bbdfSmrg inProcessInputEvents = FALSE; 56535c4bbdfSmrg 5661b5d61b8Smrg input_unlock(); 56705b261ecSmrg} 568