1/**************************************************************
2 *
3 * Xquartz initialization code
4 *
5 * Copyright (c) 2007-2012 Apple Inc.
6 * Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Except as contained in this notice, the name(s) of the above copyright
27 * holders shall not be used in advertising or otherwise to promote the sale,
28 * use or other dealings in this Software without prior written authorization.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H
32#include <dix-config.h>
33#endif
34
35#include <X11/X.h>
36#include <X11/Xproto.h>
37#include "os.h"
38#include "servermd.h"
39#include "inputstr.h"
40#include "scrnintstr.h"
41#include "mipointer.h"          // mi software cursor
42#include "micmap.h"             // mi colormap code
43#include "fb.h"                 // fb framebuffer code
44#include "globals.h"
45#include "dix.h"
46#include "xkbsrv.h"
47
48#include <X11/extensions/XI.h>
49#include <X11/extensions/XIproto.h>
50#include "exevents.h"
51#include "extinit.h"
52#include "glx_extinit.h"
53#include "xserver-properties.h"
54
55#include <sys/types.h>
56#include <sys/time.h>
57#include <sys/stat.h>
58#include <sys/syslimits.h>
59#include <stdio.h>
60#include <fcntl.h>
61#include <unistd.h>
62#include <stdarg.h>
63
64#define HAS_UTSNAME 1
65#include <sys/utsname.h>
66
67#define NO_CFPLUGIN
68#include <IOKit/hidsystem/IOHIDLib.h>
69
70#ifdef MITSHM
71#include "shmint.h"
72#endif
73
74#include "darwin.h"
75#include "darwinEvents.h"
76#include "quartzKeyboard.h"
77#include "quartz.h"
78
79#include "X11Application.h"
80
81aslclient aslc;
82
83void
84xq_asl_log(int level, const char *subsystem, const char *file,
85           const char *function, int line, const char *fmt,
86           ...)
87{
88    va_list args;
89    aslmsg msg = asl_new(ASL_TYPE_MSG);
90
91    if (msg) {
92        char *_line;
93
94        asl_set(msg, "File", file);
95        asl_set(msg, "Function", function);
96        asprintf(&_line, "%d", line);
97        if (_line) {
98            asl_set(msg, "Line", _line);
99            free(_line);
100        }
101        if (subsystem)
102            asl_set(msg, "Subsystem", subsystem);
103    }
104
105    va_start(args, fmt);
106    asl_vlog(aslc, msg, level, fmt, args);
107    va_end(args);
108
109    if (msg)
110        asl_free(msg);
111}
112
113/*
114 * X server shared global variables
115 */
116int darwinScreensFound = 0;
117DevPrivateKeyRec darwinScreenKeyRec;
118io_connect_t darwinParamConnect = 0;
119int darwinEventReadFD = -1;
120int darwinEventWriteFD = -1;
121// int                     darwinMouseAccelChange = 1;
122int darwinFakeButtons = 0;
123
124// location of X11's (0,0) point in global screen coordinates
125int darwinMainScreenX = 0;
126int darwinMainScreenY = 0;
127
128// parameters read from the command line or user preferences
129int darwinDesiredDepth = -1;
130int darwinSyncKeymap = FALSE;
131
132// modifier masks for faking mouse buttons - ANY of these bits trigger it  (not all)
133#ifdef NX_DEVICELCMDKEYMASK
134int darwinFakeMouse2Mask = NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
135int darwinFakeMouse3Mask = NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK;
136#else
137int darwinFakeMouse2Mask = NX_ALTERNATEMASK;
138int darwinFakeMouse3Mask = NX_COMMANDMASK;
139#endif
140
141// Modifier mask for overriding event delivery to appkit (might be useful to set this to rcommand for input menu
142unsigned int darwinAppKitModMask = 0;            // Any of these bits
143
144// Modifier mask for items in the Window menu (0 and -1 cause shortcuts to be disabled)
145unsigned int windowItemModMask = NX_COMMANDMASK;
146
147// devices
148DeviceIntPtr darwinKeyboard = NULL;
149DeviceIntPtr darwinPointer = NULL;
150DeviceIntPtr darwinTabletStylus = NULL;
151DeviceIntPtr darwinTabletCursor = NULL;
152DeviceIntPtr darwinTabletEraser = NULL;
153
154// Common pixmap formats
155static PixmapFormatRec formats[] = {
156    { 1,  1,  BITMAP_SCANLINE_PAD    },
157    { 4,  8,  BITMAP_SCANLINE_PAD    },
158    { 8,  8,  BITMAP_SCANLINE_PAD    },
159    { 15, 16, BITMAP_SCANLINE_PAD    },
160    { 16, 16, BITMAP_SCANLINE_PAD    },
161    { 24, 32, BITMAP_SCANLINE_PAD    },
162    { 32, 32, BITMAP_SCANLINE_PAD    }
163};
164
165void
166DarwinPrintBanner(void)
167{
168    ErrorF("Xquartz starting:\n");
169    ErrorF("X.Org X Server %s\n", XSERVER_VERSION);
170}
171
172/*
173 * DarwinScreenInit
174 *  This is a callback from dix during AddScreen() from InitOutput().
175 *  Initialize the screen and communicate information about it back to dix.
176 */
177static Bool
178DarwinScreenInit(ScreenPtr pScreen, int argc, char **argv)
179{
180    int dpi;
181    static int foundIndex = 0;
182    Bool ret;
183    DarwinFramebufferPtr dfb;
184
185    if (!dixRegisterPrivateKey(&darwinScreenKeyRec, PRIVATE_SCREEN, 0))
186        return FALSE;
187
188    // reset index of found screens for each server generation
189    if (pScreen->myNum == 0) {
190        foundIndex = 0;
191
192        // reset the visual list
193        miClearVisualTypes();
194    }
195
196    // allocate space for private per screen storage
197    dfb = malloc(sizeof(DarwinFramebufferRec));
198
199    // SCREEN_PRIV(pScreen) = dfb;
200    dixSetPrivate(&pScreen->devPrivates, darwinScreenKey, dfb);
201
202    // setup hardware/mode specific details
203    ret = QuartzAddScreen(foundIndex, pScreen);
204    foundIndex++;
205    if (!ret)
206        return FALSE;
207
208    // setup a single visual appropriate for our pixel type
209    if (!miSetVisualTypesAndMasks(dfb->depth, dfb->visuals, dfb->bitsPerRGB,
210                                  dfb->preferredCVC, dfb->redMask,
211                                  dfb->greenMask, dfb->blueMask)) {
212        return FALSE;
213    }
214
215    // TODO: Make PseudoColor visuals not suck in TrueColor mode
216    // if(dfb->depth > 8)
217    //    miSetVisualTypesAndMasks(8, PseudoColorMask, 8, PseudoColor, 0, 0, 0);
218    //
219    // TODO: Re-add support for 15bit
220    // if (dfb->depth > 15)
221    //    miSetVisualTypesAndMasks(15, TrueColorMask, 5, TrueColor,
222    //                             RM_ARGB(0, 5, 5, 5), GM_ARGB(0, 5, 5,
223    //                                                          5),
224    //                             BM_ARGB(0, 5, 5, 5));
225    if (dfb->depth > 24)
226        miSetVisualTypesAndMasks(24, TrueColorMask, 8, TrueColor,
227                                 RM_ARGB(0, 8, 8, 8), GM_ARGB(0, 8, 8,
228                                                              8),
229                                 BM_ARGB(0, 8, 8, 8));
230
231    miSetPixmapDepths();
232
233    // machine independent screen init
234    // setup _Screen structure in pScreen
235    if (monitorResolution)
236        dpi = monitorResolution;
237    else
238        dpi = 96;
239
240    // initialize fb
241    if (!fbScreenInit(pScreen,
242                      dfb->framebuffer,                  // pointer to screen bitmap
243                      dfb->width, dfb->height,           // screen size in pixels
244                      dpi, dpi,                          // dots per inch
245                      dfb->pitch / (dfb->bitsPerPixel / 8), // pixel width of framebuffer
246                      dfb->bitsPerPixel)) {              // bits per pixel for screen
247        return FALSE;
248    }
249
250    if (!fbPictureInit(pScreen, 0, 0)) {
251        return FALSE;
252    }
253
254#ifdef MITSHM
255    ShmRegisterFbFuncs(pScreen);
256#endif
257
258    // finish mode dependent screen setup including cursor support
259    if (!QuartzSetupScreen(pScreen->myNum, pScreen)) {
260        return FALSE;
261    }
262
263    // create and install the default colormap and
264    // set pScreen->blackPixel / pScreen->white
265    if (!miCreateDefColormap(pScreen)) {
266        return FALSE;
267    }
268
269    pScreen->x = dfb->x;
270    pScreen->y = dfb->y;
271
272    /*    ErrorF("Screen %d added: %dx%d @ (%d,%d)\n",
273       index, dfb->width, dfb->height, dfb->x, dfb->y); */
274
275    return TRUE;
276}
277
278/*
279   =============================================================================
280
281   mouse and keyboard callbacks
282
283   =============================================================================
284 */
285
286static void
287DarwinInputHandlerNotify(int fd __unused, int ready __unused, void *data __unused)
288{
289}
290
291/*
292 * DarwinMouseProc: Handle the initialization, etc. of a mouse
293 */
294static int
295DarwinMouseProc(DeviceIntPtr pPointer, int what)
296{
297#define NBUTTONS 3
298#define NAXES    6
299    // 3 buttons: left, middle, right
300    CARD8 map[NBUTTONS + 1] = { 0, 1, 2, 3};
301    Atom btn_labels[NBUTTONS] = { 0 };
302    Atom axes_labels[NAXES] = { 0 };
303
304    switch (what) {
305    case DEVICE_INIT:
306        pPointer->public.on = FALSE;
307
308        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
309        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
310        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
311
312        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
313        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
314        axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
315        axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
316        axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL);
317        axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL);
318
319        // Set button map.
320        InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS,
321                                btn_labels,
322                                (PtrCtrlProcPtr)NoopDDA,
323                                GetMotionHistorySize(), NAXES,
324                                axes_labels);
325        InitValuatorAxisStruct(pPointer, 0, axes_labels[0],
326                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
327                               0, 0, 0, Absolute);
328        InitValuatorAxisStruct(pPointer, 1, axes_labels[1],
329                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
330                               0, 0, 0, Absolute);
331        InitValuatorAxisStruct(pPointer, 2, axes_labels[2],
332                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
333                               1, 0, 1, Relative);
334        InitValuatorAxisStruct(pPointer, 3, axes_labels[3],
335                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
336                               1, 0, 1, Relative);
337        InitValuatorAxisStruct(pPointer, 4, axes_labels[4],
338                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
339                               1, 0, 1, Relative);
340        InitValuatorAxisStruct(pPointer, 5, axes_labels[5],
341                               NO_AXIS_LIMITS, NO_AXIS_LIMITS,
342                               1, 0, 1, Relative);
343
344        SetScrollValuator(pPointer, 4, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED);
345        SetScrollValuator(pPointer, 5, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE);
346        break;
347
348    case DEVICE_ON:
349        pPointer->public.on = TRUE;
350        SetNotifyFd(darwinEventReadFD, DarwinInputHandlerNotify, X_NOTIFY_READ, NULL);
351        return Success;
352
353    case DEVICE_CLOSE:
354    case DEVICE_OFF:
355        pPointer->public.on = FALSE;
356        RemoveNotifyFd(darwinEventReadFD);
357        return Success;
358    }
359
360    return Success;
361#undef NBUTTONS
362#undef NAXES
363}
364
365static int
366DarwinTabletProc(DeviceIntPtr pPointer, int what)
367{
368#define NBUTTONS 3
369#define NAXES    5
370    CARD8 map[NBUTTONS + 1] = { 0, 1, 2, 3 };
371    Atom btn_labels[NBUTTONS] = { 0 };
372    Atom axes_labels[NAXES] = { 0 };
373
374    switch (what) {
375    case DEVICE_INIT:
376        pPointer->public.on = FALSE;
377
378        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
379        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
380        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
381
382        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
383        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
384        axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
385        axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X);
386        axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y);
387
388        // Set button map.
389        InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS,
390                                btn_labels,
391                                (PtrCtrlProcPtr)NoopDDA,
392                                GetMotionHistorySize(), NAXES,
393                                axes_labels);
394        InitProximityClassDeviceStruct(pPointer);
395
396        InitValuatorAxisStruct(pPointer, 0, axes_labels[0],
397                               0, XQUARTZ_VALUATOR_LIMIT,
398                               1, 0, 1, Absolute);
399        InitValuatorAxisStruct(pPointer, 1, axes_labels[1],
400                               0, XQUARTZ_VALUATOR_LIMIT,
401                               1, 0, 1, Absolute);
402        InitValuatorAxisStruct(pPointer, 2, axes_labels[2],
403                               0, XQUARTZ_VALUATOR_LIMIT,
404                               1, 0, 1, Absolute);
405        InitValuatorAxisStruct(pPointer, 3, axes_labels[3],
406                               -XQUARTZ_VALUATOR_LIMIT,
407                               XQUARTZ_VALUATOR_LIMIT,
408                               1, 0, 1, Absolute);
409        InitValuatorAxisStruct(pPointer, 4, axes_labels[4],
410                               -XQUARTZ_VALUATOR_LIMIT,
411                               XQUARTZ_VALUATOR_LIMIT,
412                               1, 0, 1, Absolute);
413
414        //          pPointer->use = IsXExtensionDevice;
415        break;
416
417    case DEVICE_ON:
418        pPointer->public.on = TRUE;
419        SetNotifyFd(darwinEventReadFD, DarwinInputHandlerNotify, X_NOTIFY_READ, NULL);
420        return Success;
421
422    case DEVICE_CLOSE:
423    case DEVICE_OFF:
424        pPointer->public.on = FALSE;
425        RemoveNotifyFd(darwinEventReadFD);
426        return Success;
427    }
428    return Success;
429#undef NBUTTONS
430#undef NAXES
431}
432
433/*
434 * DarwinKeybdProc
435 *  Callback from X
436 */
437static int
438DarwinKeybdProc(DeviceIntPtr pDev, int onoff)
439{
440    switch (onoff) {
441    case DEVICE_INIT:
442        DarwinKeyboardInit(pDev);
443        break;
444
445    case DEVICE_ON:
446        pDev->public.on = TRUE;
447        SetNotifyFd(darwinEventReadFD, DarwinInputHandlerNotify, X_NOTIFY_READ, NULL);
448        break;
449
450    case DEVICE_OFF:
451        pDev->public.on = FALSE;
452        RemoveNotifyFd(darwinEventReadFD);
453        break;
454
455    case DEVICE_CLOSE:
456        break;
457    }
458
459    return Success;
460}
461
462/*
463   ===========================================================================
464
465   Utility routines
466
467   ===========================================================================
468 */
469
470/*
471 * DarwinParseModifierList
472 *  Parse a list of modifier names and return a corresponding modifier mask
473 */
474int
475DarwinParseModifierList(const char *constmodifiers, int separatelr)
476{
477    int result = 0;
478
479    if (constmodifiers) {
480        char *modifiers = strdup(constmodifiers);
481        char *modifier;
482        int nxkey;
483        char *p = modifiers;
484
485        while (p) {
486            modifier = strsep(&p, " ,+&|/"); // allow lots of separators
487            nxkey = DarwinModifierStringToNXMask(modifier, separatelr);
488            if (nxkey)
489                result |= nxkey;
490            else
491                ErrorF("fakebuttons: Unknown modifier \"%s\"\n", modifier);
492        }
493        free(modifiers);
494    }
495    return result;
496}
497
498/*
499   ===========================================================================
500
501   Functions needed to link against device independent X
502
503   ===========================================================================
504 */
505
506/*
507 * InitInput
508 *  Register the keyboard and mouse devices
509 */
510void
511InitInput(int argc, char **argv)
512{
513    XkbRMLVOSet rmlvo = {
514        .rules   = "base", .model         = "empty", .layout = "empty",
515        .variant = NULL,   .options       = NULL
516    };
517
518    /* We need to really have rules... or something... */
519    XkbSetRulesDflts(&rmlvo);
520
521    assert(Success == AllocDevicePair(serverClient, "xquartz virtual",
522                                      &darwinPointer, &darwinKeyboard,
523                                      DarwinMouseProc, DarwinKeybdProc, FALSE));
524
525    /* here's the snippet from the current gdk sources:
526       if (!strcmp (tmp_name, "pointer"))
527       gdkdev->info.source = GDK_SOURCE_MOUSE;
528       else if (!strcmp (tmp_name, "wacom") ||
529       !strcmp (tmp_name, "pen"))
530       gdkdev->info.source = GDK_SOURCE_PEN;
531       else if (!strcmp (tmp_name, "eraser"))
532       gdkdev->info.source = GDK_SOURCE_ERASER;
533       else if (!strcmp (tmp_name, "cursor"))
534       gdkdev->info.source = GDK_SOURCE_CURSOR;
535       else
536       gdkdev->info.source = GDK_SOURCE_PEN;
537     */
538
539    darwinTabletStylus = AddInputDevice(serverClient, DarwinTabletProc, TRUE);
540    assert(darwinTabletStylus);
541    darwinTabletStylus->name = strdup("pen");
542
543    darwinTabletCursor = AddInputDevice(serverClient, DarwinTabletProc, TRUE);
544    assert(darwinTabletCursor);
545    darwinTabletCursor->name = strdup("cursor");
546
547    darwinTabletEraser = AddInputDevice(serverClient, DarwinTabletProc, TRUE);
548    assert(darwinTabletEraser);
549    darwinTabletEraser->name = strdup("eraser");
550
551    DarwinEQInit();
552
553    QuartzInitInput(argc, argv);
554}
555
556void
557CloseInput(void)
558{
559    DarwinEQFini();
560}
561
562/*
563 * DarwinAdjustScreenOrigins
564 *  Shift all screens so the X11 (0, 0) coordinate is at the top
565 *  left of the global screen coordinates.
566 *
567 *  Screens can be arranged so the top left isn't on any screen, so
568 *  instead use the top left of the leftmost screen as (0,0). This
569 *  may mean some screen space is in -y, but it's better that (0,0)
570 *  be onscreen, or else default xterms disappear. It's better that
571 *  -y be used than -x, because when popup menus are forced
572 *  "onscreen" by dumb window managers like twm, they'll shift the
573 *  menus down instead of left, which still looks funny but is an
574 *  easier target to hit.
575 */
576void
577DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo)
578{
579    int i, left, top;
580
581    left = pScreenInfo->screens[0]->x;
582    top = pScreenInfo->screens[0]->y;
583
584    /* Find leftmost screen. If there's a tie, take the topmost of the two. */
585    for (i = 1; i < pScreenInfo->numScreens; i++) {
586        if (pScreenInfo->screens[i]->x < left ||
587            (pScreenInfo->screens[i]->x == left &&
588             pScreenInfo->screens[i]->y < top)) {
589            left = pScreenInfo->screens[i]->x;
590            top = pScreenInfo->screens[i]->y;
591        }
592    }
593
594    darwinMainScreenX = left;
595    darwinMainScreenY = top;
596
597    DEBUG_LOG("top = %d, left=%d\n", top, left);
598
599    /* Shift all screens so that there is a screen whose top left
600     * is at X11 (0,0) and at global screen coordinate
601     * (darwinMainScreenX, darwinMainScreenY).
602     */
603
604    if (darwinMainScreenX != 0 || darwinMainScreenY != 0) {
605        for (i = 0; i < pScreenInfo->numScreens; i++) {
606            pScreenInfo->screens[i]->x -= darwinMainScreenX;
607            pScreenInfo->screens[i]->y -= darwinMainScreenY;
608            DEBUG_LOG("Screen %d placed at X11 coordinate (%d,%d).\n",
609                      i, pScreenInfo->screens[i]->x,
610                      pScreenInfo->screens[i]->y);
611        }
612    }
613
614    /* Update screenInfo.x/y */
615    update_desktop_dimensions();
616}
617
618/*
619 * InitOutput
620 *  Initialize screenInfo for all actually accessible framebuffers.
621 *
622 *  The display mode dependent code gets called three times. The mode
623 *  specific InitOutput routines are expected to discover the number
624 *  of potentially useful screens and cache routes to them internally.
625 *  Inside DarwinScreenInit are two other mode specific calls.
626 *  A mode specific AddScreen routine is called for each screen to
627 *  actually initialize the screen with the ScreenPtr structure.
628 *  After other screen setup has been done, a mode specific
629 *  SetupScreen function can be called to finalize screen setup.
630 */
631void
632InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
633{
634    int i;
635
636    pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
637    pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
638    pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
639    pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
640
641    // List how we want common pixmap formats to be padded
642    pScreenInfo->numPixmapFormats = ARRAY_SIZE(formats);
643    for (i = 0; i < ARRAY_SIZE(formats); i++)
644        pScreenInfo->formats[i] = formats[i];
645
646    // Discover screens and do mode specific initialization
647    QuartzInitOutput(argc, argv);
648
649    // Add screens
650    for (i = 0; i < darwinScreensFound; i++) {
651        AddScreen(DarwinScreenInit, argc, argv);
652    }
653
654    xorgGlxCreateVendor();
655
656    DarwinAdjustScreenOrigins(pScreenInfo);
657}
658
659/*
660 * OsVendorFatalError
661 */
662void
663OsVendorFatalError(const char *f, va_list args)
664{
665}
666
667/*
668 * OsVendorInit
669 *  Initialization of Darwin OS support.
670 */
671void
672OsVendorInit(void)
673{
674    if (serverGeneration == 1) {
675        char *lf;
676        char *home = getenv("HOME");
677        assert(home);
678        assert(0 < asprintf(&lf, "%s/Library/Logs/X11", home));
679
680        /* Ignore errors.  If EEXIST, we don't care.  If anything else,
681         * LogInit will handle it for us.
682         */
683        (void)mkdir(lf, S_IRWXU | S_IRWXG | S_IRWXO);
684        free(lf);
685
686        assert(0 <
687               asprintf(&lf, "%s/Library/Logs/X11/%s.log", home,
688                        bundle_id_prefix));
689        LogInit(lf, ".old");
690        free(lf);
691
692        DarwinPrintBanner();
693    }
694}
695
696/*
697 * ddxProcessArgument
698 *  Process device-dependent command line args. Returns 0 if argument is
699 *  not device dependent, otherwise Count of number of elements of argv
700 *  that are part of a device dependent commandline option.
701 */
702int
703ddxProcessArgument(int argc, char *argv[], int i)
704{
705    //    if ( !strcmp( argv[i], "-fullscreen" ) ) {
706    //        ErrorF( "Running full screen in parallel with Mac OS X Quartz window server.\n" );
707    //        return 1;
708    //    }
709
710    //    if ( !strcmp( argv[i], "-rootless" ) ) {
711    //        ErrorF( "Running rootless inside Mac OS X window server.\n" );
712    //        return 1;
713    //    }
714
715    // This command line arg is passed when launched from the Aqua GUI.
716    if (!strncmp(argv[i], "-psn_", 5)) {
717        return 1;
718    }
719
720    if (!strcmp(argv[i], "-fakebuttons")) {
721        darwinFakeButtons = TRUE;
722        ErrorF("Faking a three button mouse\n");
723        return 1;
724    }
725
726    if (!strcmp(argv[i], "-nofakebuttons")) {
727        darwinFakeButtons = FALSE;
728        ErrorF("Not faking a three button mouse\n");
729        return 1;
730    }
731
732    if (!strcmp(argv[i], "-fakemouse2")) {
733        if (i == argc - 1) {
734            FatalError("-fakemouse2 must be followed by a modifier list\n");
735        }
736        if (!strcasecmp(argv[i + 1], "none") || !strcmp(argv[i + 1], ""))
737            darwinFakeMouse2Mask = 0;
738        else
739            darwinFakeMouse2Mask = DarwinParseModifierList(argv[i + 1], 1);
740        ErrorF("Modifier mask to fake mouse button 2 = 0x%x\n",
741               darwinFakeMouse2Mask);
742        return 2;
743    }
744
745    if (!strcmp(argv[i], "-fakemouse3")) {
746        if (i == argc - 1) {
747            FatalError("-fakemouse3 must be followed by a modifier list\n");
748        }
749        if (!strcasecmp(argv[i + 1], "none") || !strcmp(argv[i + 1], ""))
750            darwinFakeMouse3Mask = 0;
751        else
752            darwinFakeMouse3Mask = DarwinParseModifierList(argv[i + 1], 1);
753        ErrorF("Modifier mask to fake mouse button 3 = 0x%x\n",
754               darwinFakeMouse3Mask);
755        return 2;
756    }
757
758    if (!strcmp(argv[i], "+synckeymap")) {
759        darwinSyncKeymap = TRUE;
760        return 1;
761    }
762
763    if (!strcmp(argv[i], "-synckeymap")) {
764        darwinSyncKeymap = FALSE;
765        return 1;
766    }
767
768    if (!strcmp(argv[i], "-depth")) {
769        if (i == argc - 1) {
770            FatalError("-depth must be followed by a number\n");
771        }
772        darwinDesiredDepth = atoi(argv[i + 1]);
773        if (darwinDesiredDepth != -1 &&
774            darwinDesiredDepth != 8 &&
775            darwinDesiredDepth != 15 &&
776            darwinDesiredDepth != 24) {
777            FatalError("Unsupported pixel depth. Use 8, 15, or 24 bits\n");
778        }
779
780        ErrorF("Attempting to use pixel depth of %i\n", darwinDesiredDepth);
781        return 2;
782    }
783
784    if (!strcmp(argv[i], "-showconfig") || !strcmp(argv[i], "-version")) {
785        DarwinPrintBanner();
786        exit(0);
787    }
788
789    return 0;
790}
791
792/*
793 * ddxUseMsg --
794 *  Print out correct use of device dependent commandline options.
795 *  Maybe the user now knows what really to do ...
796 */
797void
798ddxUseMsg(void)
799{
800    ErrorF("\n");
801    ErrorF("\n");
802    ErrorF("Device Dependent Usage:\n");
803    ErrorF("\n");
804    ErrorF("-depth <8,15,24> : use this bit depth.\n");
805    ErrorF(
806        "-fakebuttons : fake a three button mouse with Command and Option keys.\n");
807    ErrorF("-nofakebuttons : don't fake a three button mouse.\n");
808    ErrorF(
809        "-fakemouse2 <modifiers> : fake middle mouse button with modifier keys.\n");
810    ErrorF(
811        "-fakemouse3 <modifiers> : fake right mouse button with modifier keys.\n");
812    ErrorF(
813        "  ex: -fakemouse2 \"option,shift\" = option-shift-click is middle button.\n");
814    ErrorF("-version : show the server version.\n");
815    ErrorF("\n");
816}
817
818/*
819 * ddxGiveUp --
820 *      Device dependent cleanup. Called by dix before normal server death.
821 */
822void
823ddxGiveUp(enum ExitCode error)
824{
825    LogClose(error);
826}
827
828#if INPUTTHREAD
829/** This function is called in Xserver/os/inputthread.c when starting
830    the input thread. */
831void
832ddxInputThreadInit(void)
833{
834}
835#endif
836