1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun Copyright 1990, 1998 The Open Group
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun * Author: Keith Packard, MIT X Consortium
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * mieq.c
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * Machine independent event queue
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #if HAVE_DIX_CONFIG_H
36*4882a593Smuzhiyun #include <dix-config.h>
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include <X11/X.h>
40*4882a593Smuzhiyun #include <X11/Xmd.h>
41*4882a593Smuzhiyun #include <X11/Xproto.h>
42*4882a593Smuzhiyun #include "misc.h"
43*4882a593Smuzhiyun #include "windowstr.h"
44*4882a593Smuzhiyun #include "pixmapstr.h"
45*4882a593Smuzhiyun #include "inputstr.h"
46*4882a593Smuzhiyun #include "inpututils.h"
47*4882a593Smuzhiyun #include "mi.h"
48*4882a593Smuzhiyun #include "mipointer.h"
49*4882a593Smuzhiyun #include "scrnintstr.h"
50*4882a593Smuzhiyun #include <X11/extensions/XI.h>
51*4882a593Smuzhiyun #include <X11/extensions/XIproto.h>
52*4882a593Smuzhiyun #include <X11/extensions/geproto.h>
53*4882a593Smuzhiyun #include "extinit.h"
54*4882a593Smuzhiyun #include "exglobals.h"
55*4882a593Smuzhiyun #include "eventstr.h"
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun #ifdef DPMSExtension
58*4882a593Smuzhiyun #include "dpmsproc.h"
59*4882a593Smuzhiyun #include <X11/extensions/dpmsconst.h>
60*4882a593Smuzhiyun #endif
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /* Maximum size should be initial size multiplied by a power of 2 */
63*4882a593Smuzhiyun #define QUEUE_INITIAL_SIZE 512
64*4882a593Smuzhiyun #define QUEUE_RESERVED_SIZE 64
65*4882a593Smuzhiyun #define QUEUE_MAXIMUM_SIZE 4096
66*4882a593Smuzhiyun #define QUEUE_DROP_BACKTRACE_FREQUENCY 100
67*4882a593Smuzhiyun #define QUEUE_DROP_BACKTRACE_MAX 10
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
70*4882a593Smuzhiyun #define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun typedef struct _Event {
73*4882a593Smuzhiyun InternalEvent *events;
74*4882a593Smuzhiyun ScreenPtr pScreen;
75*4882a593Smuzhiyun DeviceIntPtr pDev; /* device this event _originated_ from */
76*4882a593Smuzhiyun } EventRec, *EventPtr;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun typedef struct _EventQueue {
79*4882a593Smuzhiyun HWEventQueueType head, tail; /* long for SetInputCheck */
80*4882a593Smuzhiyun CARD32 lastEventTime; /* to avoid time running backwards */
81*4882a593Smuzhiyun int lastMotion; /* device ID if last event motion? */
82*4882a593Smuzhiyun EventRec *events; /* our queue as an array */
83*4882a593Smuzhiyun size_t nevents; /* the number of buckets in our queue */
84*4882a593Smuzhiyun size_t dropped; /* counter for number of consecutive dropped events */
85*4882a593Smuzhiyun mieqHandler handlers[128]; /* custom event handler */
86*4882a593Smuzhiyun } EventQueueRec, *EventQueuePtr;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun static EventQueueRec miEventQueue;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun static size_t
mieqNumEnqueued(EventQueuePtr eventQueue)91*4882a593Smuzhiyun mieqNumEnqueued(EventQueuePtr eventQueue)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun size_t n_enqueued = 0;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun if (eventQueue->nevents) {
96*4882a593Smuzhiyun /* % is not well-defined with negative numbers... sigh */
97*4882a593Smuzhiyun n_enqueued = eventQueue->tail - eventQueue->head + eventQueue->nevents;
98*4882a593Smuzhiyun if (n_enqueued >= eventQueue->nevents)
99*4882a593Smuzhiyun n_enqueued -= eventQueue->nevents;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun return n_enqueued;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /* Pre-condition: Called with input_lock held */
105*4882a593Smuzhiyun static Bool
mieqGrowQueue(EventQueuePtr eventQueue,size_t new_nevents)106*4882a593Smuzhiyun mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun size_t i, n_enqueued, first_hunk;
109*4882a593Smuzhiyun EventRec *new_events;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun if (!eventQueue) {
112*4882a593Smuzhiyun ErrorF("[mi] mieqGrowQueue called with a NULL eventQueue\n");
113*4882a593Smuzhiyun return FALSE;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (new_nevents <= eventQueue->nevents)
117*4882a593Smuzhiyun return FALSE;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun new_events = calloc(new_nevents, sizeof(EventRec));
120*4882a593Smuzhiyun if (new_events == NULL) {
121*4882a593Smuzhiyun ErrorF("[mi] mieqGrowQueue memory allocation error.\n");
122*4882a593Smuzhiyun return FALSE;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun n_enqueued = mieqNumEnqueued(eventQueue);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* First copy the existing events */
128*4882a593Smuzhiyun first_hunk = eventQueue->nevents - eventQueue->head;
129*4882a593Smuzhiyun memcpy(new_events,
130*4882a593Smuzhiyun &eventQueue->events[eventQueue->head],
131*4882a593Smuzhiyun first_hunk * sizeof(EventRec));
132*4882a593Smuzhiyun memcpy(&new_events[first_hunk],
133*4882a593Smuzhiyun eventQueue->events, eventQueue->head * sizeof(EventRec));
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /* Initialize the new portion */
136*4882a593Smuzhiyun for (i = eventQueue->nevents; i < new_nevents; i++) {
137*4882a593Smuzhiyun InternalEvent *evlist = InitEventList(1);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun if (!evlist) {
140*4882a593Smuzhiyun size_t j;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun for (j = 0; j < i; j++)
143*4882a593Smuzhiyun FreeEventList(new_events[j].events, 1);
144*4882a593Smuzhiyun free(new_events);
145*4882a593Smuzhiyun return FALSE;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun new_events[i].events = evlist;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* And update our record */
151*4882a593Smuzhiyun eventQueue->tail = n_enqueued;
152*4882a593Smuzhiyun eventQueue->head = 0;
153*4882a593Smuzhiyun eventQueue->nevents = new_nevents;
154*4882a593Smuzhiyun free(eventQueue->events);
155*4882a593Smuzhiyun eventQueue->events = new_events;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun return TRUE;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun Bool
mieqInit(void)161*4882a593Smuzhiyun mieqInit(void)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun memset(&miEventQueue, 0, sizeof(miEventQueue));
164*4882a593Smuzhiyun miEventQueue.lastEventTime = GetTimeInMillis();
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun input_lock();
167*4882a593Smuzhiyun if (!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE))
168*4882a593Smuzhiyun FatalError("Could not allocate event queue.\n");
169*4882a593Smuzhiyun input_unlock();
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
172*4882a593Smuzhiyun return TRUE;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun void
mieqFini(void)176*4882a593Smuzhiyun mieqFini(void)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun int i;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun for (i = 0; i < miEventQueue.nevents; i++) {
181*4882a593Smuzhiyun if (miEventQueue.events[i].events != NULL) {
182*4882a593Smuzhiyun FreeEventList(miEventQueue.events[i].events, 1);
183*4882a593Smuzhiyun miEventQueue.events[i].events = NULL;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun free(miEventQueue.events);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /*
190*4882a593Smuzhiyun * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
191*4882a593Smuzhiyun * will never be interrupted. Must be called with input_lock held
192*4882a593Smuzhiyun */
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun void
mieqEnqueue(DeviceIntPtr pDev,InternalEvent * e)195*4882a593Smuzhiyun mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun unsigned int oldtail = miEventQueue.tail;
198*4882a593Smuzhiyun InternalEvent *evt;
199*4882a593Smuzhiyun int isMotion = 0;
200*4882a593Smuzhiyun int evlen;
201*4882a593Smuzhiyun Time time;
202*4882a593Smuzhiyun size_t n_enqueued;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun verify_internal_event(e);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun n_enqueued = mieqNumEnqueued(&miEventQueue);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* avoid merging events from different devices */
209*4882a593Smuzhiyun if (e->any.type == ET_Motion)
210*4882a593Smuzhiyun isMotion = pDev->id;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun if (isMotion && isMotion == miEventQueue.lastMotion &&
213*4882a593Smuzhiyun oldtail != miEventQueue.head) {
214*4882a593Smuzhiyun oldtail = (oldtail - 1) % miEventQueue.nevents;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun else if (n_enqueued + 1 == miEventQueue.nevents) {
217*4882a593Smuzhiyun if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) {
218*4882a593Smuzhiyun /* Toss events which come in late. Usually this means your server's
219*4882a593Smuzhiyun * stuck in an infinite loop in the main thread.
220*4882a593Smuzhiyun */
221*4882a593Smuzhiyun miEventQueue.dropped++;
222*4882a593Smuzhiyun if (miEventQueue.dropped == 1) {
223*4882a593Smuzhiyun ErrorFSigSafe("[mi] EQ overflowing. Additional events will be "
224*4882a593Smuzhiyun "discarded until existing events are processed.\n");
225*4882a593Smuzhiyun xorg_backtrace();
226*4882a593Smuzhiyun ErrorFSigSafe("[mi] These backtraces from mieqEnqueue may point to "
227*4882a593Smuzhiyun "a culprit higher up the stack.\n");
228*4882a593Smuzhiyun ErrorFSigSafe("[mi] mieq is *NOT* the cause. It is a victim.\n");
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 &&
231*4882a593Smuzhiyun miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <=
232*4882a593Smuzhiyun QUEUE_DROP_BACKTRACE_MAX) {
233*4882a593Smuzhiyun ErrorFSigSafe("[mi] EQ overflow continuing. %zu events have been "
234*4882a593Smuzhiyun "dropped.\n", miEventQueue.dropped);
235*4882a593Smuzhiyun if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY ==
236*4882a593Smuzhiyun QUEUE_DROP_BACKTRACE_MAX) {
237*4882a593Smuzhiyun ErrorFSigSafe("[mi] No further overflow reports will be "
238*4882a593Smuzhiyun "reported until the clog is cleared.\n");
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun xorg_backtrace();
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun return;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun oldtail = miEventQueue.tail;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun evlen = e->any.length;
248*4882a593Smuzhiyun evt = miEventQueue.events[oldtail].events;
249*4882a593Smuzhiyun memcpy(evt, e, evlen);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun time = e->any.time;
252*4882a593Smuzhiyun /* Make sure that event times don't go backwards - this
253*4882a593Smuzhiyun * is "unnecessary", but very useful. */
254*4882a593Smuzhiyun if (time < miEventQueue.lastEventTime &&
255*4882a593Smuzhiyun miEventQueue.lastEventTime - time < 10000)
256*4882a593Smuzhiyun e->any.time = miEventQueue.lastEventTime;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun miEventQueue.lastEventTime = evt->any.time;
259*4882a593Smuzhiyun miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL;
260*4882a593Smuzhiyun miEventQueue.events[oldtail].pDev = pDev;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun miEventQueue.lastMotion = isMotion;
263*4882a593Smuzhiyun miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /**
267*4882a593Smuzhiyun * Changes the screen reference events are being enqueued from.
268*4882a593Smuzhiyun * Input events are enqueued with a screen reference and dequeued and
269*4882a593Smuzhiyun * processed with a (potentially different) screen reference.
270*4882a593Smuzhiyun * This function is called whenever a new event has changed screen but is
271*4882a593Smuzhiyun * still logically on the previous screen as seen by the client.
272*4882a593Smuzhiyun * This usually happens whenever the visible cursor moves across screen
273*4882a593Smuzhiyun * boundaries during event generation, before the same event is processed
274*4882a593Smuzhiyun * and sent down the wire.
275*4882a593Smuzhiyun *
276*4882a593Smuzhiyun * @param pDev The device that triggered a screen change.
277*4882a593Smuzhiyun * @param pScreen The new screen events are being enqueued for.
278*4882a593Smuzhiyun * @param set_dequeue_screen If TRUE, pScreen is set as both enqueue screen
279*4882a593Smuzhiyun * and dequeue screen.
280*4882a593Smuzhiyun */
281*4882a593Smuzhiyun void
mieqSwitchScreen(DeviceIntPtr pDev,ScreenPtr pScreen,Bool set_dequeue_screen)282*4882a593Smuzhiyun mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool set_dequeue_screen)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun EnqueueScreen(pDev) = pScreen;
285*4882a593Smuzhiyun if (set_dequeue_screen)
286*4882a593Smuzhiyun DequeueScreen(pDev) = pScreen;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun void
mieqSetHandler(int event,mieqHandler handler)290*4882a593Smuzhiyun mieqSetHandler(int event, mieqHandler handler)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun if (handler && miEventQueue.handlers[event])
293*4882a593Smuzhiyun ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for "
294*4882a593Smuzhiyun "event %d\n", miEventQueue.handlers[event], handler, event);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun miEventQueue.handlers[event] = handler;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun /**
300*4882a593Smuzhiyun * Change the device id of the given event to the given device's id.
301*4882a593Smuzhiyun */
302*4882a593Smuzhiyun static void
ChangeDeviceID(DeviceIntPtr dev,InternalEvent * event)303*4882a593Smuzhiyun ChangeDeviceID(DeviceIntPtr dev, InternalEvent *event)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun switch (event->any.type) {
306*4882a593Smuzhiyun case ET_Motion:
307*4882a593Smuzhiyun case ET_KeyPress:
308*4882a593Smuzhiyun case ET_KeyRelease:
309*4882a593Smuzhiyun case ET_ButtonPress:
310*4882a593Smuzhiyun case ET_ButtonRelease:
311*4882a593Smuzhiyun case ET_ProximityIn:
312*4882a593Smuzhiyun case ET_ProximityOut:
313*4882a593Smuzhiyun case ET_Hierarchy:
314*4882a593Smuzhiyun case ET_DeviceChanged:
315*4882a593Smuzhiyun case ET_TouchBegin:
316*4882a593Smuzhiyun case ET_TouchUpdate:
317*4882a593Smuzhiyun case ET_TouchEnd:
318*4882a593Smuzhiyun event->device_event.deviceid = dev->id;
319*4882a593Smuzhiyun break;
320*4882a593Smuzhiyun case ET_TouchOwnership:
321*4882a593Smuzhiyun event->touch_ownership_event.deviceid = dev->id;
322*4882a593Smuzhiyun break;
323*4882a593Smuzhiyun #ifdef XFreeXDGA
324*4882a593Smuzhiyun case ET_DGAEvent:
325*4882a593Smuzhiyun break;
326*4882a593Smuzhiyun #endif
327*4882a593Smuzhiyun case ET_RawKeyPress:
328*4882a593Smuzhiyun case ET_RawKeyRelease:
329*4882a593Smuzhiyun case ET_RawButtonPress:
330*4882a593Smuzhiyun case ET_RawButtonRelease:
331*4882a593Smuzhiyun case ET_RawMotion:
332*4882a593Smuzhiyun case ET_RawTouchBegin:
333*4882a593Smuzhiyun case ET_RawTouchEnd:
334*4882a593Smuzhiyun case ET_RawTouchUpdate:
335*4882a593Smuzhiyun event->raw_event.deviceid = dev->id;
336*4882a593Smuzhiyun break;
337*4882a593Smuzhiyun case ET_BarrierHit:
338*4882a593Smuzhiyun case ET_BarrierLeave:
339*4882a593Smuzhiyun event->barrier_event.deviceid = dev->id;
340*4882a593Smuzhiyun break;
341*4882a593Smuzhiyun default:
342*4882a593Smuzhiyun ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
343*4882a593Smuzhiyun event->any.type);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun static void
FixUpEventForMaster(DeviceIntPtr mdev,DeviceIntPtr sdev,InternalEvent * original,InternalEvent * master)348*4882a593Smuzhiyun FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev,
349*4882a593Smuzhiyun InternalEvent *original, InternalEvent *master)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun verify_internal_event(original);
352*4882a593Smuzhiyun verify_internal_event(master);
353*4882a593Smuzhiyun /* Ensure chained button mappings, i.e. that the detail field is the
354*4882a593Smuzhiyun * value of the mapped button on the SD, not the physical button */
355*4882a593Smuzhiyun if (original->any.type == ET_ButtonPress ||
356*4882a593Smuzhiyun original->any.type == ET_ButtonRelease) {
357*4882a593Smuzhiyun int btn = original->device_event.detail.button;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if (!sdev->button)
360*4882a593Smuzhiyun return; /* Should never happen */
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun master->device_event.detail.button = sdev->button->map[btn];
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /**
367*4882a593Smuzhiyun * Copy the given event into master.
368*4882a593Smuzhiyun * @param sdev The slave device the original event comes from
369*4882a593Smuzhiyun * @param original The event as it came from the EQ
370*4882a593Smuzhiyun * @param copy The event after being copied
371*4882a593Smuzhiyun * @return The master device or NULL if the device is a floating slave.
372*4882a593Smuzhiyun */
373*4882a593Smuzhiyun DeviceIntPtr
CopyGetMasterEvent(DeviceIntPtr sdev,InternalEvent * original,InternalEvent * copy)374*4882a593Smuzhiyun CopyGetMasterEvent(DeviceIntPtr sdev,
375*4882a593Smuzhiyun InternalEvent *original, InternalEvent *copy)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun DeviceIntPtr mdev;
378*4882a593Smuzhiyun int len = original->any.length;
379*4882a593Smuzhiyun int type = original->any.type;
380*4882a593Smuzhiyun int mtype; /* which master type? */
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun verify_internal_event(original);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /* ET_XQuartz has sdev == NULL */
385*4882a593Smuzhiyun if (!sdev || IsMaster(sdev) || IsFloating(sdev))
386*4882a593Smuzhiyun return NULL;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun #ifdef XFreeXDGA
389*4882a593Smuzhiyun if (type == ET_DGAEvent)
390*4882a593Smuzhiyun type = original->dga_event.subtype;
391*4882a593Smuzhiyun #endif
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun switch (type) {
394*4882a593Smuzhiyun case ET_KeyPress:
395*4882a593Smuzhiyun case ET_KeyRelease:
396*4882a593Smuzhiyun mtype = MASTER_KEYBOARD;
397*4882a593Smuzhiyun break;
398*4882a593Smuzhiyun case ET_ButtonPress:
399*4882a593Smuzhiyun case ET_ButtonRelease:
400*4882a593Smuzhiyun case ET_Motion:
401*4882a593Smuzhiyun case ET_ProximityIn:
402*4882a593Smuzhiyun case ET_ProximityOut:
403*4882a593Smuzhiyun mtype = MASTER_POINTER;
404*4882a593Smuzhiyun break;
405*4882a593Smuzhiyun default:
406*4882a593Smuzhiyun mtype = MASTER_ATTACHED;
407*4882a593Smuzhiyun break;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun mdev = GetMaster(sdev, mtype);
411*4882a593Smuzhiyun memcpy(copy, original, len);
412*4882a593Smuzhiyun ChangeDeviceID(mdev, copy);
413*4882a593Smuzhiyun FixUpEventForMaster(mdev, sdev, original, copy);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun return mdev;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun static void
mieqMoveToNewScreen(DeviceIntPtr dev,ScreenPtr screen,DeviceEvent * event)419*4882a593Smuzhiyun mieqMoveToNewScreen(DeviceIntPtr dev, ScreenPtr screen, DeviceEvent *event)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun if (dev && screen && screen != DequeueScreen(dev)) {
422*4882a593Smuzhiyun int x = 0, y = 0;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun DequeueScreen(dev) = screen;
425*4882a593Smuzhiyun x = event->root_x;
426*4882a593Smuzhiyun y = event->root_y;
427*4882a593Smuzhiyun NewCurrentScreen(dev, DequeueScreen(dev), x, y);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun /**
432*4882a593Smuzhiyun * Post the given @event through the device hierarchy, as appropriate.
433*4882a593Smuzhiyun * Use this function if an event must be posted for a given device during the
434*4882a593Smuzhiyun * usual event processing cycle.
435*4882a593Smuzhiyun */
436*4882a593Smuzhiyun void
mieqProcessDeviceEvent(DeviceIntPtr dev,InternalEvent * event,ScreenPtr screen)437*4882a593Smuzhiyun mieqProcessDeviceEvent(DeviceIntPtr dev, InternalEvent *event, ScreenPtr screen)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun mieqHandler handler;
440*4882a593Smuzhiyun DeviceIntPtr master;
441*4882a593Smuzhiyun InternalEvent mevent; /* master event */
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun verify_internal_event(event);
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun /* refuse events from disabled devices */
446*4882a593Smuzhiyun if (dev && !dev->enabled)
447*4882a593Smuzhiyun return;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /* Custom event handler */
450*4882a593Smuzhiyun handler = miEventQueue.handlers[event->any.type];
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun switch (event->any.type) {
453*4882a593Smuzhiyun /* Catch events that include valuator information and check if they
454*4882a593Smuzhiyun * are changing the screen */
455*4882a593Smuzhiyun case ET_Motion:
456*4882a593Smuzhiyun case ET_KeyPress:
457*4882a593Smuzhiyun case ET_KeyRelease:
458*4882a593Smuzhiyun case ET_ButtonPress:
459*4882a593Smuzhiyun case ET_ButtonRelease:
460*4882a593Smuzhiyun if (!handler)
461*4882a593Smuzhiyun mieqMoveToNewScreen(dev, screen, &event->device_event);
462*4882a593Smuzhiyun break;
463*4882a593Smuzhiyun case ET_TouchBegin:
464*4882a593Smuzhiyun case ET_TouchUpdate:
465*4882a593Smuzhiyun case ET_TouchEnd:
466*4882a593Smuzhiyun if (!handler && (event->device_event.flags & TOUCH_POINTER_EMULATED))
467*4882a593Smuzhiyun mieqMoveToNewScreen(dev, screen, &event->device_event);
468*4882a593Smuzhiyun break;
469*4882a593Smuzhiyun default:
470*4882a593Smuzhiyun break;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun master = CopyGetMasterEvent(dev, event, &mevent);
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun if (master)
475*4882a593Smuzhiyun master->lastSlave = dev;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun /* If someone's registered a custom event handler, let them
478*4882a593Smuzhiyun * steal it. */
479*4882a593Smuzhiyun if (handler) {
480*4882a593Smuzhiyun int screenNum = dev &&
481*4882a593Smuzhiyun DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->
482*4882a593Smuzhiyun myNum : 0);
483*4882a593Smuzhiyun handler(screenNum, event, dev);
484*4882a593Smuzhiyun /* Check for the SD's master in case the device got detached
485*4882a593Smuzhiyun * during event processing */
486*4882a593Smuzhiyun if (master && !IsFloating(dev))
487*4882a593Smuzhiyun handler(screenNum, &mevent, master);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun else {
490*4882a593Smuzhiyun /* process slave first, then master */
491*4882a593Smuzhiyun dev->public.processInputProc(event, dev);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /* Check for the SD's master in case the device got detached
494*4882a593Smuzhiyun * during event processing */
495*4882a593Smuzhiyun if (master && !IsFloating(dev))
496*4882a593Smuzhiyun master->public.processInputProc(&mevent, master);
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun /* Call this from ProcessInputEvents(). */
501*4882a593Smuzhiyun void
mieqProcessInputEvents(void)502*4882a593Smuzhiyun mieqProcessInputEvents(void)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun EventRec *e = NULL;
505*4882a593Smuzhiyun ScreenPtr screen;
506*4882a593Smuzhiyun InternalEvent event;
507*4882a593Smuzhiyun DeviceIntPtr dev = NULL, master = NULL;
508*4882a593Smuzhiyun static Bool inProcessInputEvents = FALSE;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun input_lock();
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun /*
513*4882a593Smuzhiyun * report an error if mieqProcessInputEvents() is called recursively;
514*4882a593Smuzhiyun * this can happen, e.g., if something in the mieqProcessDeviceEvent()
515*4882a593Smuzhiyun * call chain calls UpdateCurrentTime() instead of UpdateCurrentTimeIf()
516*4882a593Smuzhiyun */
517*4882a593Smuzhiyun BUG_WARN_MSG(inProcessInputEvents, "[mi] mieqProcessInputEvents() called recursively.\n");
518*4882a593Smuzhiyun inProcessInputEvents = TRUE;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun if (miEventQueue.dropped) {
521*4882a593Smuzhiyun ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n",
522*4882a593Smuzhiyun (unsigned long) miEventQueue.dropped);
523*4882a593Smuzhiyun ErrorF
524*4882a593Smuzhiyun ("[mi] This may be caused by a misbehaving driver monopolizing the server's resources.\n");
525*4882a593Smuzhiyun miEventQueue.dropped = 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun while (miEventQueue.head != miEventQueue.tail) {
529*4882a593Smuzhiyun e = &miEventQueue.events[miEventQueue.head];
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun event = *e->events;
532*4882a593Smuzhiyun dev = e->pDev;
533*4882a593Smuzhiyun screen = e->pScreen;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun input_unlock();
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun if (screenIsSaved == SCREEN_SAVER_ON)
542*4882a593Smuzhiyun dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
543*4882a593Smuzhiyun #ifdef DPMSExtension
544*4882a593Smuzhiyun else if (DPMSPowerLevel != DPMSModeOn)
545*4882a593Smuzhiyun SetScreenSaverTimer();
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun if (DPMSPowerLevel != DPMSModeOn)
548*4882a593Smuzhiyun DPMSSet(serverClient, DPMSModeOn);
549*4882a593Smuzhiyun #endif
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun mieqProcessDeviceEvent(dev, &event, screen);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun /* Update the sprite now. Next event may be from different device. */
554*4882a593Smuzhiyun if (master &&
555*4882a593Smuzhiyun (event.any.type == ET_Motion ||
556*4882a593Smuzhiyun ((event.any.type == ET_TouchBegin ||
557*4882a593Smuzhiyun event.any.type == ET_TouchUpdate) &&
558*4882a593Smuzhiyun event.device_event.flags & TOUCH_POINTER_EMULATED)))
559*4882a593Smuzhiyun miPointerUpdateSprite(dev);
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun input_lock();
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun inProcessInputEvents = FALSE;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun input_unlock();
567*4882a593Smuzhiyun }
568