~gerchanovsky/xorg-server/trusty

« back to all changes in this revision

Viewing changes to hw/xquartz/darwinEvents.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2016-01-13 00:01:28 UTC
  • Revision ID: package-import@ubuntu.com-20160113000128-oc1wb1mr1zfjqlm5
Tags: upstream-1.17.2
ImportĀ upstreamĀ versionĀ 1.17.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Darwin event queue and event handling
 
3
 *
 
4
 * Copyright 2007-2008 Apple Inc.
 
5
 * Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
 
6
 * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
 
7
 *
 
8
 * This file is based on mieq.c by Keith Packard,
 
9
 * which contains the following copyright:
 
10
 * Copyright 1990, 1998  The Open Group
 
11
 *
 
12
 *
 
13
 * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
 
14
 *
 
15
 * Permission is hereby granted, free of charge, to any person
 
16
 * obtaining a copy of this software and associated documentation files
 
17
 * (the "Software"), to deal in the Software without restriction,
 
18
 * including without limitation the rights to use, copy, modify, merge,
 
19
 * publish, distribute, sublicense, and/or sell copies of the Software,
 
20
 * and to permit persons to whom the Software is furnished to do so,
 
21
 * subject to the following conditions:
 
22
 *
 
23
 * The above copyright notice and this permission notice shall be
 
24
 * included in all copies or substantial portions of the Software.
 
25
 *
 
26
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
27
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
28
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
29
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
 
30
 * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
31
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
32
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
33
 * DEALINGS IN THE SOFTWARE.
 
34
 *
 
35
 * Except as contained in this notice, the name(s) of the above
 
36
 * copyright holders shall not be used in advertising or otherwise to
 
37
 * promote the sale, use or other dealings in this Software without
 
38
 * prior written authorization.
 
39
 */
 
40
 
 
41
#include "sanitizedCarbon.h"
 
42
 
 
43
#ifdef HAVE_DIX_CONFIG_H
 
44
#include <dix-config.h>
 
45
#endif
 
46
 
 
47
#include <X11/X.h>
 
48
#include <X11/Xmd.h>
 
49
#include <X11/Xproto.h>
 
50
#include "misc.h"
 
51
#include "windowstr.h"
 
52
#include "pixmapstr.h"
 
53
#include "inputstr.h"
 
54
#include "inpututils.h"
 
55
#include "eventstr.h"
 
56
#include "mi.h"
 
57
#include "scrnintstr.h"
 
58
#include "mipointer.h"
 
59
#include "os.h"
 
60
#include "exglobals.h"
 
61
 
 
62
#include "darwin.h"
 
63
#include "quartz.h"
 
64
#include "quartzKeyboard.h"
 
65
#include "quartzRandR.h"
 
66
#include "darwinEvents.h"
 
67
 
 
68
#include <sys/types.h>
 
69
#include <sys/uio.h>
 
70
#include <unistd.h>
 
71
#include <pthread.h>
 
72
#include <errno.h>
 
73
#include <time.h>
 
74
 
 
75
#include <IOKit/hidsystem/IOLLEvent.h>
 
76
 
 
77
#include <X11/extensions/applewmconst.h>
 
78
#include "applewmExt.h"
 
79
 
 
80
/* FIXME: Abstract this better */
 
81
extern Bool
 
82
QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
 
83
 
 
84
int darwin_all_modifier_flags = 0;  // last known modifier state
 
85
int darwin_all_modifier_mask = 0;
 
86
int darwin_x11_modifier_mask = 0;
 
87
 
 
88
#define FD_ADD_MAX 128
 
89
static int fd_add[FD_ADD_MAX];
 
90
int fd_add_count = 0;
 
91
static pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
 
92
static pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
 
93
static pthread_t fd_add_tid = NULL;
 
94
 
 
95
static InternalEvent* darwinEvents = NULL;
 
96
 
 
97
static pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
 
98
static pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
 
99
 
 
100
/*** Pthread Magics ***/
 
101
static pthread_t
 
102
create_thread(void *(*func)(void *), void *arg)
 
103
{
 
104
    pthread_attr_t attr;
 
105
    pthread_t tid;
 
106
 
 
107
    pthread_attr_init(&attr);
 
108
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
 
109
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
110
    pthread_create(&tid, &attr, func, arg);
 
111
    pthread_attr_destroy(&attr);
 
112
 
 
113
    return tid;
 
114
}
 
115
 
 
116
void
 
117
darwinEvents_lock(void);
 
118
void
 
119
darwinEvents_lock(void)
 
120
{
 
121
    int err;
 
122
    if ((err = pthread_mutex_lock(&mieq_lock))) {
 
123
        ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
 
124
               __FILE__, __FUNCTION__, __LINE__, err);
 
125
        xorg_backtrace();
 
126
    }
 
127
    if (darwinEvents == NULL) {
 
128
        pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
 
129
    }
 
130
}
 
131
 
 
132
void
 
133
darwinEvents_unlock(void);
 
134
void
 
135
darwinEvents_unlock(void)
 
136
{
 
137
    int err;
 
138
    if ((err = pthread_mutex_unlock(&mieq_lock))) {
 
139
        ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
 
140
               __FILE__, __FUNCTION__, __LINE__, err);
 
141
        xorg_backtrace();
 
142
    }
 
143
}
 
144
 
 
145
/*
 
146
 * DarwinPressModifierKey
 
147
 * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
 
148
 */
 
149
static void
 
150
DarwinPressModifierKey(int pressed, int key)
 
151
{
 
152
    int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
 
153
 
 
154
    if (keycode == 0) {
 
155
        ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
 
156
        return;
 
157
    }
 
158
 
 
159
    DarwinSendKeyboardEvents(pressed, keycode);
 
160
}
 
161
 
 
162
/*
 
163
 * DarwinUpdateModifiers
 
164
 *  Send events to update the modifier state.
 
165
 */
 
166
 
 
167
static int darwin_x11_modifier_mask_list[] = {
 
168
#ifdef NX_DEVICELCMDKEYMASK
 
169
    NX_DEVICELCTLKEYMASK,   NX_DEVICERCTLKEYMASK,
 
170
    NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
 
171
    NX_DEVICELCMDKEYMASK,   NX_DEVICERCMDKEYMASK,
 
172
    NX_DEVICELALTKEYMASK,   NX_DEVICERALTKEYMASK,
 
173
#else
 
174
    NX_CONTROLMASK,         NX_SHIFTMASK,          NX_COMMANDMASK,
 
175
    NX_ALTERNATEMASK,
 
176
#endif
 
177
    NX_ALPHASHIFTMASK,
 
178
    0
 
179
};
 
180
 
 
181
static int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, };
 
182
 
 
183
static void
 
184
DarwinUpdateModifiers(int pressed,                    // KeyPress or KeyRelease
 
185
                      int flags)                      // modifier flags that have changed
 
186
{
 
187
    int *f;
 
188
    int key;
 
189
 
 
190
    /* Capslock is special.  This mask is the state of capslock (on/off),
 
191
     * not the state of the button.  Hopefully we can find a better solution.
 
192
     */
 
193
    if (NX_ALPHASHIFTMASK & flags) {
 
194
        DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
 
195
        DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
 
196
    }
 
197
 
 
198
    for (f = darwin_x11_modifier_mask_list; *f; f++)
 
199
        if (*f & flags && *f != NX_ALPHASHIFTMASK) {
 
200
            key = DarwinModifierNXMaskToNXKey(*f);
 
201
            if (key == -1)
 
202
                ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n",
 
203
                       *f);
 
204
            else
 
205
                DarwinPressModifierKey(pressed, key);
 
206
        }
 
207
}
 
208
 
 
209
/* Generic handler for Xquartz-specifc events.  When possible, these should
 
210
   be moved into their own individual functions and set as handlers using
 
211
   mieqSetHandler. */
 
212
 
 
213
static void
 
214
DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev)
 
215
{
 
216
    XQuartzEvent *e = &(ie->xquartz_event);
 
217
 
 
218
    switch (e->subtype) {
 
219
    case kXquartzControllerNotify:
 
220
        DEBUG_LOG("kXquartzControllerNotify\n");
 
221
        AppleWMSendEvent(AppleWMControllerNotify,
 
222
                         AppleWMControllerNotifyMask,
 
223
                         e->data[0],
 
224
                         e->data[1]);
 
225
        break;
 
226
 
 
227
    case kXquartzPasteboardNotify:
 
228
        DEBUG_LOG("kXquartzPasteboardNotify\n");
 
229
        AppleWMSendEvent(AppleWMPasteboardNotify,
 
230
                         AppleWMPasteboardNotifyMask,
 
231
                         e->data[0],
 
232
                         e->data[1]);
 
233
        break;
 
234
 
 
235
    case kXquartzActivate:
 
236
        DEBUG_LOG("kXquartzActivate\n");
 
237
        QuartzShow();
 
238
        AppleWMSendEvent(AppleWMActivationNotify,
 
239
                         AppleWMActivationNotifyMask,
 
240
                         AppleWMIsActive, 0);
 
241
        break;
 
242
 
 
243
    case kXquartzDeactivate:
 
244
        DEBUG_LOG("kXquartzDeactivate\n");
 
245
        AppleWMSendEvent(AppleWMActivationNotify,
 
246
                         AppleWMActivationNotifyMask,
 
247
                         AppleWMIsInactive, 0);
 
248
        QuartzHide();
 
249
        break;
 
250
 
 
251
    case kXquartzReloadPreferences:
 
252
        DEBUG_LOG("kXquartzReloadPreferences\n");
 
253
        AppleWMSendEvent(AppleWMActivationNotify,
 
254
                         AppleWMActivationNotifyMask,
 
255
                         AppleWMReloadPreferences, 0);
 
256
        break;
 
257
 
 
258
    case kXquartzToggleFullscreen:
 
259
        DEBUG_LOG("kXquartzToggleFullscreen\n");
 
260
        if (XQuartzIsRootless)
 
261
            ErrorF(
 
262
                "Ignoring kXquartzToggleFullscreen because of rootless mode.");
 
263
        else
 
264
            QuartzRandRToggleFullscreen();
 
265
        break;
 
266
 
 
267
    case kXquartzSetRootless:
 
268
        DEBUG_LOG("kXquartzSetRootless\n");
 
269
        if (e->data[0]) {
 
270
            QuartzRandRSetFakeRootless();
 
271
        }
 
272
        else {
 
273
            QuartzRandRSetFakeFullscreen(FALSE);
 
274
        }
 
275
        break;
 
276
 
 
277
    case kXquartzSetRootClip:
 
278
        QuartzSetRootClip((Bool)e->data[0]);
 
279
        break;
 
280
 
 
281
    case kXquartzQuit:
 
282
        GiveUp(0);
 
283
        break;
 
284
 
 
285
    case kXquartzSpaceChanged:
 
286
        DEBUG_LOG("kXquartzSpaceChanged\n");
 
287
        QuartzSpaceChanged(e->data[0]);
 
288
        break;
 
289
 
 
290
    case kXquartzListenOnOpenFD:
 
291
        ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
 
292
        ListenOnOpenFD((int)e->data[0], 1);
 
293
        break;
 
294
 
 
295
    case kXquartzReloadKeymap:
 
296
        DarwinKeyboardReloadHandler();
 
297
        break;
 
298
 
 
299
    case kXquartzDisplayChanged:
 
300
        DEBUG_LOG("kXquartzDisplayChanged\n");
 
301
        QuartzUpdateScreens();
 
302
 
 
303
        /* Update our RandR info */
 
304
        QuartzRandRUpdateFakeModes(TRUE);
 
305
        break;
 
306
 
 
307
    default:
 
308
        if (!QuartzModeEventHandler(screenNum, e, dev))
 
309
            ErrorF("Unknown application defined event type %d.\n", e->subtype);
 
310
    }
 
311
}
 
312
 
 
313
void
 
314
DarwinListenOnOpenFD(int fd)
 
315
{
 
316
    ErrorF("DarwinListenOnOpenFD: %d\n", fd);
 
317
 
 
318
    pthread_mutex_lock(&fd_add_lock);
 
319
    if (fd_add_count < FD_ADD_MAX)
 
320
        fd_add[fd_add_count++] = fd;
 
321
    else
 
322
        ErrorF("FD Addition buffer at max.  Dropping fd addition request.\n");
 
323
 
 
324
    pthread_cond_broadcast(&fd_add_ready_cond);
 
325
    pthread_mutex_unlock(&fd_add_lock);
 
326
}
 
327
 
 
328
static void *
 
329
DarwinProcessFDAdditionQueue_thread(void *args)
 
330
{
 
331
    /* TODO: Possibly adjust this to no longer be a race... maybe trigger this
 
332
     *       once a client connects and claims to be the WM.
 
333
     *
 
334
     * From ajax:
 
335
     * There's already an internal callback chain for setting selection [in 1.5]
 
336
     * ownership.  See the CallSelectionCallback at the bottom of
 
337
     * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
 
338
     * into it.
 
339
     */
 
340
 
 
341
    struct timespec sleep_for;
 
342
    struct timespec sleep_remaining;
 
343
 
 
344
    sleep_for.tv_sec = 3;
 
345
    sleep_for.tv_nsec = 0;
 
346
 
 
347
    ErrorF(
 
348
        "X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n");
 
349
    while (nanosleep(&sleep_for, &sleep_remaining) != 0) {
 
350
        sleep_for = sleep_remaining;
 
351
    }
 
352
 
 
353
    pthread_mutex_lock(&fd_add_lock);
 
354
    while (true) {
 
355
        while (fd_add_count) {
 
356
            DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1,
 
357
                               fd_add[--fd_add_count]);
 
358
        }
 
359
        pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
 
360
    }
 
361
 
 
362
    return NULL;
 
363
}
 
364
 
 
365
Bool
 
366
DarwinEQInit(void)
 
367
{
 
368
    int *p;
 
369
 
 
370
    for (p = darwin_x11_modifier_mask_list, darwin_all_modifier_mask = 0; *p;
 
371
         p++) {
 
372
        darwin_x11_modifier_mask |= *p;
 
373
    }
 
374
 
 
375
    for (p = darwin_all_modifier_mask_additions,
 
376
         darwin_all_modifier_mask = darwin_x11_modifier_mask;
 
377
         *p; p++) {
 
378
        darwin_all_modifier_mask |= *p;
 
379
    }
 
380
 
 
381
    mieqInit();
 
382
    mieqSetHandler(ET_XQuartz, DarwinEventHandler);
 
383
 
 
384
    /* Note that this *could* cause a potential async issue, since we're checking
 
385
     * darwinEvents without holding the lock, but darwinEvents is only ever set
 
386
     * here, so I don't bother.
 
387
     */
 
388
    if (!darwinEvents) {
 
389
        darwinEvents = InitEventList(GetMaximumEventsNum());
 
390
        ;
 
391
 
 
392
        if (!darwinEvents)
 
393
            FatalError("Couldn't allocate event buffer\n");
 
394
 
 
395
        darwinEvents_lock();
 
396
        pthread_cond_broadcast(&mieq_ready_cond);
 
397
        darwinEvents_unlock();
 
398
    }
 
399
 
 
400
    if (!fd_add_tid)
 
401
        fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
 
402
 
 
403
    return TRUE;
 
404
}
 
405
 
 
406
void
 
407
DarwinEQFini(void)
 
408
{
 
409
    mieqFini();
 
410
}
 
411
 
 
412
/*
 
413
 * ProcessInputEvents
 
414
 *  Read and process events from the event queue until it is empty.
 
415
 */
 
416
void
 
417
ProcessInputEvents(void)
 
418
{
 
419
    char nullbyte;
 
420
    int x = sizeof(nullbyte);
 
421
 
 
422
    mieqProcessInputEvents();
 
423
 
 
424
    // Empty the signaling pipe
 
425
    while (x == sizeof(nullbyte)) {
 
426
        x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
 
427
    }
 
428
}
 
429
 
 
430
/* Sends a null byte down darwinEventWriteFD, which will cause the
 
431
   Dispatch() event loop to check out event queue */
 
432
static void
 
433
DarwinPokeEQ(void)
 
434
{
 
435
    char nullbyte = 0;
 
436
    //  <daniels> oh, i ... er ... christ.
 
437
    write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
 
438
}
 
439
 
 
440
void
 
441
DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev)
 
442
{
 
443
    darwinEvents_lock();
 
444
    {
 
445
        int i;
 
446
        if (pDev->button) {
 
447
            for (i = 0; i < pDev->button->numButtons; i++) {
 
448
                if (BitIsOn(pDev->button->down, i)) {
 
449
                    QueuePointerEvents(pDev, ButtonRelease, i,
 
450
                                       POINTER_ABSOLUTE,
 
451
                                       NULL);
 
452
                }
 
453
            }
 
454
        }
 
455
 
 
456
        if (pDev->key) {
 
457
            for (i = 0; i < NUM_KEYCODES; i++) {
 
458
                if (BitIsOn(pDev->key->down, i + MIN_KEYCODE)) {
 
459
                    QueueKeyboardEvents(pDev, KeyRelease, i + MIN_KEYCODE,
 
460
                                        NULL);
 
461
                }
 
462
            }
 
463
        }
 
464
        DarwinPokeEQ();
 
465
    } darwinEvents_unlock();
 
466
}
 
467
 
 
468
void
 
469
DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
 
470
                       double pointer_x, double pointer_y,
 
471
                       double pressure, double tilt_x,
 
472
                       double tilt_y)
 
473
{
 
474
    ScreenPtr screen;
 
475
    ValuatorMask valuators;
 
476
 
 
477
    if (!darwinEvents) {
 
478
        DEBUG_LOG("%s called before darwinEvents was initialized\n",
 
479
                  __FUNCTION__);
 
480
        return;
 
481
    }
 
482
 
 
483
    screen = miPointerGetScreen(pDev);
 
484
    if (!screen) {
 
485
        DEBUG_LOG("%s called before screen was initialized\n",
 
486
                  __FUNCTION__);
 
487
        return;
 
488
    }
 
489
 
 
490
    /* Fix offset between darwin and X screens */
 
491
    pointer_x -= darwinMainScreenX + screen->x;
 
492
    pointer_y -= darwinMainScreenY + screen->y;
 
493
 
 
494
    /* Adjust our pointer location to the [0,1] range */
 
495
    pointer_x = pointer_x / (double)screenInfo.width;
 
496
    pointer_y = pointer_y / (double)screenInfo.height;
 
497
 
 
498
    valuator_mask_zero(&valuators);
 
499
    valuator_mask_set_double(&valuators, 0, XQUARTZ_VALUATOR_LIMIT * pointer_x);
 
500
    valuator_mask_set_double(&valuators, 1, XQUARTZ_VALUATOR_LIMIT * pointer_y);
 
501
    valuator_mask_set_double(&valuators, 2, XQUARTZ_VALUATOR_LIMIT * pressure);
 
502
    valuator_mask_set_double(&valuators, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x);
 
503
    valuator_mask_set_double(&valuators, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y);
 
504
 
 
505
    darwinEvents_lock();
 
506
    {
 
507
        if (ev_type == ProximityIn || ev_type == ProximityOut) {
 
508
            QueueProximityEvents(pDev, ev_type, &valuators);
 
509
        } else {
 
510
            QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
 
511
                               &valuators);
 
512
        }
 
513
        DarwinPokeEQ();
 
514
    } darwinEvents_unlock();
 
515
}
 
516
 
 
517
void
 
518
DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button,
 
519
                        double pointer_x, double pointer_y,
 
520
                        double pointer_dx, double pointer_dy)
 
521
{
 
522
    static int darwinFakeMouseButtonDown = 0;
 
523
    ScreenPtr screen;
 
524
    ValuatorMask valuators;
 
525
 
 
526
    if (!darwinEvents) {
 
527
        DEBUG_LOG("%s called before darwinEvents was initialized\n",
 
528
                  __FUNCTION__);
 
529
        return;
 
530
    }
 
531
 
 
532
    screen = miPointerGetScreen(pDev);
 
533
    if (!screen) {
 
534
        DEBUG_LOG("%s called before screen was initialized\n",
 
535
                  __FUNCTION__);
 
536
        return;
 
537
    }
 
538
 
 
539
    /* Handle fake click */
 
540
    if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
 
541
        if (darwinFakeMouseButtonDown != 0) {
 
542
            /* We're currently "down" with another button, so release it first */
 
543
            DarwinSendPointerEvents(pDev, ButtonRelease,
 
544
                                    darwinFakeMouseButtonDown,
 
545
                                    pointer_x, pointer_y, 0.0, 0.0);
 
546
            darwinFakeMouseButtonDown = 0;
 
547
        }
 
548
        if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
 
549
            ev_button = 2;
 
550
            darwinFakeMouseButtonDown = 2;
 
551
            DarwinUpdateModKeys(
 
552
                darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
 
553
        }
 
554
        else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
 
555
            ev_button = 3;
 
556
            darwinFakeMouseButtonDown = 3;
 
557
            DarwinUpdateModKeys(
 
558
                darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
 
559
        }
 
560
    }
 
561
 
 
562
    if (ev_type == ButtonRelease && ev_button == 1) {
 
563
        if (darwinFakeMouseButtonDown) {
 
564
            ev_button = darwinFakeMouseButtonDown;
 
565
        }
 
566
 
 
567
        if (darwinFakeMouseButtonDown == 2) {
 
568
            DarwinUpdateModKeys(
 
569
                darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
 
570
        }
 
571
        else if (darwinFakeMouseButtonDown == 3) {
 
572
            DarwinUpdateModKeys(
 
573
                darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
 
574
        }
 
575
 
 
576
        darwinFakeMouseButtonDown = 0;
 
577
    }
 
578
 
 
579
    /* Fix offset between darwin and X screens */
 
580
    pointer_x -= darwinMainScreenX + screen->x;
 
581
    pointer_y -= darwinMainScreenY + screen->y;
 
582
 
 
583
    valuator_mask_zero(&valuators);
 
584
    valuator_mask_set_double(&valuators, 0, pointer_x);
 
585
    valuator_mask_set_double(&valuators, 1, pointer_y);
 
586
 
 
587
    if (ev_type == MotionNotify) {
 
588
        if (pointer_dx != 0.0)
 
589
            valuator_mask_set_double(&valuators, 2, pointer_dx);
 
590
        if (pointer_dy != 0.0)
 
591
            valuator_mask_set_double(&valuators, 3, pointer_dy);
 
592
    }
 
593
 
 
594
    darwinEvents_lock();
 
595
    {
 
596
        QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE,
 
597
                           &valuators);
 
598
        DarwinPokeEQ();
 
599
    } darwinEvents_unlock();
 
600
}
 
601
 
 
602
void
 
603
DarwinSendKeyboardEvents(int ev_type, int keycode)
 
604
{
 
605
 
 
606
    if (!darwinEvents) {
 
607
        DEBUG_LOG(
 
608
            "DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
 
609
        return;
 
610
    }
 
611
 
 
612
    darwinEvents_lock();
 
613
    {
 
614
        QueueKeyboardEvents(darwinKeyboard, ev_type, keycode + MIN_KEYCODE,
 
615
                            NULL);
 
616
        DarwinPokeEQ();
 
617
    } darwinEvents_unlock();
 
618
}
 
619
 
 
620
/* Send the appropriate number of button clicks to emulate scroll wheel */
 
621
void
 
622
DarwinSendScrollEvents(double scroll_x, double scroll_y) {
 
623
    ScreenPtr screen;
 
624
    ValuatorMask valuators;
 
625
 
 
626
    if (!darwinEvents) {
 
627
        DEBUG_LOG(
 
628
            "DarwinSendScrollEvents called before darwinEvents was initialized\n");
 
629
        return;
 
630
    }
 
631
 
 
632
    screen = miPointerGetScreen(darwinPointer);
 
633
    if (!screen) {
 
634
        DEBUG_LOG(
 
635
            "DarwinSendScrollEvents called before screen was initialized\n");
 
636
        return;
 
637
    }
 
638
 
 
639
    valuator_mask_zero(&valuators);
 
640
    valuator_mask_set_double(&valuators, 4, scroll_y);
 
641
    valuator_mask_set_double(&valuators, 5, scroll_x);
 
642
 
 
643
    darwinEvents_lock();
 
644
    {
 
645
        QueuePointerEvents(darwinPointer, MotionNotify, 0,
 
646
                           POINTER_RELATIVE, &valuators);
 
647
        DarwinPokeEQ();
 
648
    } darwinEvents_unlock();
 
649
}
 
650
 
 
651
/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
 
652
   reflect changing modifier flags (alt, control, meta, etc) */
 
653
void
 
654
DarwinUpdateModKeys(int flags)
 
655
{
 
656
    DarwinUpdateModifiers(
 
657
        KeyRelease, darwin_all_modifier_flags & ~flags &
 
658
        darwin_x11_modifier_mask);
 
659
    DarwinUpdateModifiers(
 
660
        KeyPress, ~darwin_all_modifier_flags & flags &
 
661
        darwin_x11_modifier_mask);
 
662
    darwin_all_modifier_flags = flags;
 
663
}
 
664
 
 
665
/*
 
666
 * DarwinSendDDXEvent
 
667
 *  Send the X server thread a message by placing it on the event queue.
 
668
 */
 
669
void
 
670
DarwinSendDDXEvent(int type, int argc, ...)
 
671
{
 
672
    XQuartzEvent e;
 
673
    int i;
 
674
    va_list args;
 
675
 
 
676
    memset(&e, 0, sizeof(e));
 
677
    e.header = ET_Internal;
 
678
    e.type = ET_XQuartz;
 
679
    e.length = sizeof(e);
 
680
    e.time = GetTimeInMillis();
 
681
    e.subtype = type;
 
682
 
 
683
    if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
 
684
        va_start(args, argc);
 
685
        for (i = 0; i < argc; i++)
 
686
            e.data[i] = (uint32_t)va_arg(args, uint32_t);
 
687
        va_end(args);
 
688
    }
 
689
 
 
690
    darwinEvents_lock();
 
691
    {
 
692
        mieqEnqueue(NULL, (InternalEvent *)&e);
 
693
        DarwinPokeEQ();
 
694
    } darwinEvents_unlock();
 
695
}