2
* Darwin event queue and event handling
5
Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
7
This file is based on mieq.c by Keith Packard,
8
which contains the following copyright:
9
Copyright 1990, 1998 The Open Group
11
Permission to use, copy, modify, distribute, and sell this software and its
12
documentation for any purpose is hereby granted without fee, provided that
13
the above copyright notice appear in all copies and that both that
14
copyright notice and this permission notice appear in supporting
17
The above copyright notice and this permission notice shall be included in
18
all copies or substantial portions of the Software.
20
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
Except as contained in this notice, the name of The Open Group shall not be
28
used in advertising or otherwise to promote the sale, use or other dealings
29
in this Software without prior written authorization from The Open Group.
37
#include "windowstr.h"
38
#include "pixmapstr.h"
41
#include "scrnintstr.h"
42
#include "mipointer.h"
45
#include "quartz/quartz.h"
47
#include <sys/types.h>
50
#include <IOKit/hidsystem/IOLLEvent.h>
52
/* Fake button press/release for scroll wheel move. */
53
#define SCROLLWHEELUPFAKE 4
54
#define SCROLLWHEELDOWNFAKE 5
56
#define QUEUE_SIZE 256
58
typedef struct _Event {
61
} EventRec, *EventPtr;
63
typedef struct _EventQueue {
64
HWEventQueueType head, tail; /* long for SetInputCheck */
65
CARD32 lastEventTime; /* to avoid time running backwards */
67
EventRec events[QUEUE_SIZE]; /* static allocation for signals */
68
DevicePtr pKbd, pPtr; /* device pointer, to get funcs */
69
ScreenPtr pEnqueueScreen; /* screen events are being delivered to */
70
ScreenPtr pDequeueScreen; /* screen events are being dispatched to */
71
} EventQueueRec, *EventQueuePtr;
73
static EventQueueRec darwinEventQueue;
77
* DarwinPressModifierMask
78
* Press or release the given modifier key, specified by its mask.
80
static void DarwinPressModifierMask(
81
xEvent *xe, // must already have type, time and mouse location
82
int mask) // one of NX_*MASK constants
84
int key = DarwinModifierNXMaskToNXKey(mask);
87
int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
89
xe->u.u.detail = keycode + MIN_KEYCODE;
90
(*darwinEventQueue.pKbd->processInputProc)(xe,
91
(DeviceIntPtr)darwinEventQueue.pKbd, 1);
98
* DarwinUpdateModifiers
99
* Send events to update the modifier state.
101
static void DarwinUpdateModifiers(
102
xEvent *xe, // event template with time and mouse position set
103
int pressed, // KeyPress or KeyRelease
104
int flags ) // modifier flags that have changed
106
xe->u.u.type = pressed;
107
if (flags & NX_ALPHASHIFTMASK) {
108
DarwinPressModifierMask(xe, NX_ALPHASHIFTMASK);
110
if (flags & NX_COMMANDMASK) {
111
DarwinPressModifierMask(xe, NX_COMMANDMASK);
113
if (flags & NX_CONTROLMASK) {
114
DarwinPressModifierMask(xe, NX_CONTROLMASK);
116
if (flags & NX_ALTERNATEMASK) {
117
DarwinPressModifierMask(xe, NX_ALTERNATEMASK);
119
if (flags & NX_SHIFTMASK) {
120
DarwinPressModifierMask(xe, NX_SHIFTMASK);
122
if (flags & NX_SECONDARYFNMASK) {
123
DarwinPressModifierMask(xe, NX_SECONDARYFNMASK);
129
* DarwinSimulateMouseClick
130
* Send a mouse click to X when multiple mouse buttons are simulated
131
* with modifier-clicks, such as command-click for button 2. The dix
132
* layer is told that the previously pressed modifier key(s) are
133
* released, the simulated click event is sent. After the mouse button
134
* is released, the modifier keys are reverted to their actual state,
135
* which may or may not be pressed at that point. This is usually
136
* closest to what the user wants. Ie. the user typically wants to
137
* simulate a button 2 press instead of Command-button 2.
139
static void DarwinSimulateMouseClick(
140
xEvent *xe, // event template with time and
141
// mouse position filled in
142
int whichButton, // mouse button to be pressed
143
int modifierMask) // modifiers used for the fake click
145
// first fool X into forgetting about the keys
146
DarwinUpdateModifiers(xe, KeyRelease, modifierMask);
148
// push the mouse button
149
xe->u.u.type = ButtonPress;
150
xe->u.u.detail = whichButton;
151
(*darwinEventQueue.pPtr->processInputProc)
152
(xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
161
darwinEventQueue.head = darwinEventQueue.tail = 0;
162
darwinEventQueue.lastEventTime = GetTimeInMillis ();
163
darwinEventQueue.pKbd = pKbd;
164
darwinEventQueue.pPtr = pPtr;
165
darwinEventQueue.pEnqueueScreen = screenInfo.screens[0];
166
darwinEventQueue.pDequeueScreen = darwinEventQueue.pEnqueueScreen;
167
SetInputCheck (&darwinEventQueue.head, &darwinEventQueue.tail);
174
* Must be thread safe with ProcessInputEvents.
175
* DarwinEQEnqueue - called from event gathering thread
176
* ProcessInputEvents - called from X server thread
177
* DarwinEQEnqueue should never be called from more than one thread.
183
HWEventQueueType oldtail, newtail;
185
oldtail = darwinEventQueue.tail;
187
// mieqEnqueue() collapses successive motion events into one event.
188
// This is difficult to do in a thread-safe way and rarely useful.
190
newtail = oldtail + 1;
191
if (newtail == QUEUE_SIZE)
193
/* Toss events which come in late */
194
if (newtail == darwinEventQueue.head)
197
darwinEventQueue.events[oldtail].event = *e;
199
* Make sure that event times don't go backwards - this
200
* is "unnecessary", but very useful
202
if (e->u.keyButtonPointer.time < darwinEventQueue.lastEventTime &&
203
darwinEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
205
darwinEventQueue.events[oldtail].event.u.keyButtonPointer.time =
206
darwinEventQueue.lastEventTime;
208
darwinEventQueue.events[oldtail].pScreen = darwinEventQueue.pEnqueueScreen;
210
// Update the tail after the event is prepared
211
darwinEventQueue.tail = newtail;
216
* DarwinEQPointerPost
217
* Post a pointer event. Used by the mipointer.c routines.
223
(*darwinEventQueue.pPtr->processInputProc)
224
(e, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
229
DarwinEQSwitchScreen(
233
darwinEventQueue.pEnqueueScreen = pScreen;
235
darwinEventQueue.pDequeueScreen = pScreen;
241
* Read and process events from the event queue until it is empty.
243
void ProcessInputEvents(void)
248
static int old_flags = 0; // last known modifier state
249
// button number and modifier mask of currently pressed fake button
250
static int darwinFakeMouseButtonDown = 0;
251
static int darwinFakeMouseButtonMask = 0;
253
// Empty the signaling pipe
255
while (x == sizeof(xe)) {
256
x = read(darwinEventFD, &xe, sizeof(xe));
259
while (darwinEventQueue.head != darwinEventQueue.tail)
261
if (screenIsSaved == SCREEN_SAVER_ON)
262
SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
264
e = &darwinEventQueue.events[darwinEventQueue.head];
267
// Shift from global screen coordinates to coordinates relative to
268
// the origin of the current screen.
269
xe.u.keyButtonPointer.rootX -= darwinMainScreenX +
270
dixScreenOrigins[miPointerCurrentScreen()->myNum].x;
271
xe.u.keyButtonPointer.rootY -= darwinMainScreenY +
272
dixScreenOrigins[miPointerCurrentScreen()->myNum].y;
275
* Assumption - screen switching can only occur on motion events
277
if (e->pScreen != darwinEventQueue.pDequeueScreen)
279
darwinEventQueue.pDequeueScreen = e->pScreen;
280
x = xe.u.keyButtonPointer.rootX;
281
y = xe.u.keyButtonPointer.rootY;
282
if (darwinEventQueue.head == QUEUE_SIZE - 1)
283
darwinEventQueue.head = 0;
285
++darwinEventQueue.head;
286
NewCurrentScreen (darwinEventQueue.pDequeueScreen, x, y);
290
if (darwinEventQueue.head == QUEUE_SIZE - 1)
291
darwinEventQueue.head = 0;
293
++darwinEventQueue.head;
298
xe.u.u.detail += MIN_KEYCODE;
299
(*darwinEventQueue.pKbd->processInputProc)
300
(&xe, (DeviceIntPtr)darwinEventQueue.pKbd, 1);
304
miPointerAbsoluteCursor(xe.u.keyButtonPointer.rootX,
305
xe.u.keyButtonPointer.rootY,
306
xe.u.keyButtonPointer.time);
307
if (darwinFakeButtons && xe.u.u.detail == 1) {
308
// Mimic multi-button mouse with modifier-clicks
309
// If both sets of modifiers are pressed,
310
// button 2 is clicked.
311
if ((old_flags & darwinFakeMouse2Mask) ==
312
darwinFakeMouse2Mask)
314
DarwinSimulateMouseClick(&xe, 2, darwinFakeMouse2Mask);
315
darwinFakeMouseButtonDown = 2;
316
darwinFakeMouseButtonMask = darwinFakeMouse2Mask;
319
else if ((old_flags & darwinFakeMouse3Mask) ==
320
darwinFakeMouse3Mask)
322
DarwinSimulateMouseClick(&xe, 3, darwinFakeMouse3Mask);
323
darwinFakeMouseButtonDown = 3;
324
darwinFakeMouseButtonMask = darwinFakeMouse3Mask;
328
(*darwinEventQueue.pPtr->processInputProc)
329
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
333
miPointerAbsoluteCursor(xe.u.keyButtonPointer.rootX,
334
xe.u.keyButtonPointer.rootY,
335
xe.u.keyButtonPointer.time);
336
if (darwinFakeButtons && xe.u.u.detail == 1 &&
337
darwinFakeMouseButtonDown)
339
// If last mousedown was a fake click, don't check for
340
// mouse modifiers here. The user may have released the
341
// modifiers before the mouse button.
342
xe.u.u.detail = darwinFakeMouseButtonDown;
343
darwinFakeMouseButtonDown = 0;
344
(*darwinEventQueue.pPtr->processInputProc)
345
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
347
// Bring modifiers back up to date
348
DarwinUpdateModifiers(&xe, KeyPress,
349
darwinFakeMouseButtonMask & old_flags);
350
darwinFakeMouseButtonMask = 0;
352
(*darwinEventQueue.pPtr->processInputProc)
353
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
358
miPointerAbsoluteCursor(xe.u.keyButtonPointer.rootX,
359
xe.u.keyButtonPointer.rootY,
360
xe.u.keyButtonPointer.time);
363
case kXDarwinUpdateModifiers:
365
// Update modifier state.
366
// Any amount of modifiers may have changed.
367
int flags = xe.u.clientMessage.u.l.longs0;
368
DarwinUpdateModifiers(&xe, KeyRelease,
370
DarwinUpdateModifiers(&xe, KeyPress,
376
case kXDarwinUpdateButtons:
378
long hwDelta = xe.u.clientMessage.u.l.longs0;
379
long hwButtons = xe.u.clientMessage.u.l.longs1;
382
for (i = 1; i < 5; i++) {
383
if (hwDelta & (1 << i)) {
384
// IOKit and X have different numbering for the
385
// middle and right mouse buttons.
391
xe.u.u.detail = i + 1;
393
if (hwButtons & (1 << i)) {
394
xe.u.u.type = ButtonPress;
396
xe.u.u.type = ButtonRelease;
398
(*darwinEventQueue.pPtr->processInputProc)
399
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
405
case kXDarwinScrollWheel:
407
short count = xe.u.clientMessage.u.s.shorts0;
410
xe.u.u.detail = SCROLLWHEELUPFAKE;
412
xe.u.u.detail = SCROLLWHEELDOWNFAKE;
416
for (; count; --count) {
417
xe.u.u.type = ButtonPress;
418
(*darwinEventQueue.pPtr->processInputProc)
419
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
420
xe.u.u.type = ButtonRelease;
421
(*darwinEventQueue.pPtr->processInputProc)
422
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
429
QuartzProcessEvent(&xe);
431
ErrorF("Unknown X event caught: %d\n", xe.u.u.type);