First import
[xorg_rtime.git] / xorg-server-1.4 / mi / mieq.c
blob20c4b6201b90e7745c7615dc7d1177a47456da33
1 /*
3 Copyright 1990, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 * Author: Keith Packard, MIT X Consortium
29 * mieq.c
31 * Machine independent event queue
35 #if HAVE_DIX_CONFIG_H
36 #include <dix-config.h>
37 #endif
39 # define NEED_EVENTS
40 # include <X11/X.h>
41 # include <X11/Xmd.h>
42 # include <X11/Xproto.h>
43 # include "misc.h"
44 # include "windowstr.h"
45 # include "pixmapstr.h"
46 # include "inputstr.h"
47 # include "mi.h"
48 # include "mipointer.h"
49 # include "scrnintstr.h"
50 # include <X11/extensions/XI.h>
51 # include <X11/extensions/XIproto.h>
52 # include "extinit.h"
53 # include "exglobals.h"
55 #ifdef DPMSExtension
56 # include "dpmsproc.h"
57 # define DPMS_SERVER
58 # include <X11/extensions/dpms.h>
59 #endif
61 #define QUEUE_SIZE 512
63 typedef struct _Event {
64 xEvent event[7];
65 int nevents;
66 ScreenPtr pScreen;
67 DeviceIntPtr pDev; /* device this event _originated_ from */
68 } EventRec, *EventPtr;
70 typedef struct _EventQueue {
71 HWEventQueueType head, tail; /* long for SetInputCheck */
72 CARD32 lastEventTime; /* to avoid time running backwards */
73 int lastMotion; /* device ID if last event motion? */
74 EventRec events[QUEUE_SIZE]; /* static allocation for signals */
75 ScreenPtr pEnqueueScreen; /* screen events are being delivered to */
76 ScreenPtr pDequeueScreen; /* screen events are being dispatched to */
77 mieqHandler handlers[128]; /* custom event handler */
78 } EventQueueRec, *EventQueuePtr;
80 static EventQueueRec miEventQueue;
82 Bool
83 mieqInit(void)
85 int i;
87 miEventQueue.head = miEventQueue.tail = 0;
88 miEventQueue.lastEventTime = GetTimeInMillis ();
89 miEventQueue.lastMotion = FALSE;
90 miEventQueue.pEnqueueScreen = screenInfo.screens[0];
91 miEventQueue.pDequeueScreen = miEventQueue.pEnqueueScreen;
92 for (i = 0; i < 128; i++)
93 miEventQueue.handlers[i] = NULL;
94 SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
95 return TRUE;
99 * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
100 * will never be interrupted. If this is called from both signal
101 * handlers and regular code, make sure the signal is suspended when
102 * called from regular code.
105 void
106 mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
108 unsigned int oldtail = miEventQueue.tail, newtail;
109 int isMotion = 0;
110 deviceValuator *v = (deviceValuator *) e;
111 EventPtr laste = &miEventQueue.events[(oldtail - 1) %
112 QUEUE_SIZE];
113 deviceKeyButtonPointer *lastkbp = (deviceKeyButtonPointer *)
114 &laste->event[0];
116 if (e->u.u.type == MotionNotify)
117 isMotion = inputInfo.pointer->id;
118 else if (e->u.u.type == DeviceMotionNotify)
119 isMotion = pDev->id;
121 /* We silently steal valuator events: just tack them on to the last
122 * motion event they need to be attached to. Sigh. */
123 if (e->u.u.type == DeviceValuator) {
124 if (laste->nevents > 6) {
125 ErrorF("mieqEnqueue: more than six valuator events; dropping.\n");
126 return;
128 if (oldtail == miEventQueue.head ||
129 !(lastkbp->type == DeviceMotionNotify ||
130 lastkbp->type == DeviceButtonPress ||
131 lastkbp->type == DeviceButtonRelease) ||
132 ((lastkbp->deviceid & DEVICE_BITS) !=
133 (v->deviceid & DEVICE_BITS))) {
134 ErrorF("mieqEnequeue: out-of-order valuator event; dropping.\n");
135 return;
137 memcpy(&(laste->event[laste->nevents++]), e, sizeof(xEvent));
138 return;
141 if (isMotion && isMotion == miEventQueue.lastMotion &&
142 oldtail != miEventQueue.head) {
143 oldtail = (oldtail - 1) % QUEUE_SIZE;
145 else {
146 newtail = (oldtail + 1) % QUEUE_SIZE;
147 /* Toss events which come in late. Usually this means your server's
148 * stuck in an infinite loop somewhere, but SIGIO is still getting
149 * handled. */
150 if (newtail == miEventQueue.head) {
151 ErrorF("tossed event which came in late\n");
152 return;
154 miEventQueue.tail = newtail;
157 memcpy(&(miEventQueue.events[oldtail].event[0]), e, sizeof(xEvent));
158 miEventQueue.events[oldtail].nevents = 1;
160 /* Make sure that event times don't go backwards - this
161 * is "unnecessary", but very useful. */
162 if (e->u.keyButtonPointer.time < miEventQueue.lastEventTime &&
163 miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
164 miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time =
165 miEventQueue.lastEventTime;
167 miEventQueue.lastEventTime =
168 miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time;
169 miEventQueue.events[oldtail].pScreen = miEventQueue.pEnqueueScreen;
170 miEventQueue.events[oldtail].pDev = pDev;
172 miEventQueue.lastMotion = isMotion;
175 void
176 mieqSwitchScreen(ScreenPtr pScreen, Bool fromDIX)
178 miEventQueue.pEnqueueScreen = pScreen;
179 if (fromDIX)
180 miEventQueue.pDequeueScreen = pScreen;
183 void
184 mieqSetHandler(int event, mieqHandler handler)
186 if (handler && miEventQueue.handlers[event])
187 ErrorF("mieq: warning: overriding existing handler %p with %p for "
188 "event %d\n", miEventQueue.handlers[event], handler, event);
190 miEventQueue.handlers[event] = handler;
193 /* Call this from ProcessInputEvents(). */
194 void
195 mieqProcessInputEvents(void)
197 EventRec *e = NULL;
198 int x = 0, y = 0;
199 DeviceIntPtr dev = NULL;
201 while (miEventQueue.head != miEventQueue.tail) {
202 if (screenIsSaved == SCREEN_SAVER_ON)
203 SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
204 #ifdef DPMSExtension
205 else if (DPMSPowerLevel != DPMSModeOn)
206 SetScreenSaverTimer();
208 if (DPMSPowerLevel != DPMSModeOn)
209 DPMSSet(DPMSModeOn);
210 #endif
212 e = &miEventQueue.events[miEventQueue.head];
213 /* Assumption - screen switching can only occur on motion events. */
214 miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
216 if (e->pScreen != miEventQueue.pDequeueScreen) {
217 miEventQueue.pDequeueScreen = e->pScreen;
218 x = e->event[0].u.keyButtonPointer.rootX;
219 y = e->event[0].u.keyButtonPointer.rootY;
220 NewCurrentScreen (miEventQueue.pDequeueScreen, x, y);
222 else {
223 /* If someone's registered a custom event handler, let them
224 * steal it. */
225 if (miEventQueue.handlers[e->event->u.u.type]) {
226 miEventQueue.handlers[e->event->u.u.type](miEventQueue.pDequeueScreen->myNum,
227 e->event, dev,
228 e->nevents);
229 return;
232 /* If this is a core event, make sure our keymap, et al, is
233 * changed to suit. */
234 if (e->event[0].u.u.type == KeyPress ||
235 e->event[0].u.u.type == KeyRelease) {
236 SwitchCoreKeyboard(e->pDev);
237 dev = inputInfo.keyboard;
239 else if (e->event[0].u.u.type == MotionNotify ||
240 e->event[0].u.u.type == ButtonPress ||
241 e->event[0].u.u.type == ButtonRelease) {
242 SwitchCorePointer(e->pDev);
243 dev = inputInfo.pointer;
245 else {
246 dev = e->pDev;
249 dev->public.processInputProc(e->event, dev, e->nevents);