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