Remove ancient trunk folder from svn repository
[synfig.git] / synfig-osx / launcher / darwin.c
1 /**************************************************************
2  *
3  * Shared code for the Darwin X Server
4  * running with Quartz or the IOKit
5  *
6  **************************************************************/
7 /*
8  * Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
9  * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
25  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  *
29  * Except as contained in this notice, the name(s) of the above copyright
30  * holders shall not be used in advertising or otherwise to promote the sale,
31  * use or other dealings in this Software without prior written authorization.
32  */
33 /* $XFree86: xc/programs/Xserver/hw/darwin/darwin.c,v 1.45 2002/03/28 02:21:08 torrey Exp $ */
34
35 #include <CoreGraphics/CoreGraphics.h>
36
37 #include "X.h"
38 #include "Xproto.h"
39 #include "os.h"
40 #include "servermd.h"
41 #include "inputstr.h"
42 #include "scrnintstr.h"
43 #include "mibstore.h"           // mi backing store implementation
44 #include "mipointer.h"          // mi software cursor
45 #include "micmap.h"             // mi colormap code
46 #include "fb.h"                 // fb framebuffer code
47 #include "site.h"
48 #include "globals.h"
49 #include "xf86Version.h"
50 #include "dix.h"
51 #include "dri-surface.h"
52 #define _APPLEDRI_SERVER_
53 #include "appledristr.h"
54
55 #include <sys/types.h>
56 #include <sys/time.h>
57 #include <sys/syslimits.h>
58 #include <stdio.h>
59 #include <fcntl.h>
60 #include <unistd.h>
61 #include <dirent.h>
62
63 #define NO_CFPLUGIN
64 #include <IOKit/IOKitLib.h>
65 #include <IOKit/hidsystem/IOHIDLib.h>
66 #include <IOKit/hidsystem/ev_keymap.h>
67
68 #include "darwin.h"
69 #include "quartz.h"
70 #include "rootless-common.h"
71 #include "pseudoramiX.h"
72 #include "X11Application.h"
73
74 /* Fake button press/release for scroll wheel move. */
75 #define SCROLLWHEELUPFAKE       4
76 #define SCROLLWHEELDOWNFAKE     5
77
78 /* X server shared global variables */
79 int darwinScreensFound = 0;
80 int darwinScreenIndex = 0;
81 int darwinFakeButtons = 1;
82 Bool darwinSwapAltMeta = FALSE;
83
84 /* location of X11's (0,0) point in global screen coordinates */
85 int darwinMainScreenX = 0;
86 int darwinMainScreenY = 0;
87
88 /* parameters read from the command line or user preferences */
89 char *darwinKeymapFile;
90 Bool darwinSyncKeymap = TRUE;
91
92 /* modifier masks for faking mouse buttons */
93 static int darwinFakeMouse2Mask = Mod1Mask;     /* option */
94 static int darwinFakeMouse3Mask = Mod2Mask;     /* command */
95
96 static DeviceIntPtr darwinPointer;
97 static DeviceIntPtr darwinKeyboard;
98
99 /* Track our view of the keyboard state. Everything we sent to dix will
100    be represented here until released. */
101 static CARD8 keysDown[DOWN_LENGTH];
102 static int lockMods;
103
104 #define SetBit(ptr,bit) \
105     do {((BYTE *) ptr)[(bit) >> 3] |= (1 << ((bit) & 7));} while (0)
106
107 #define ClearBit(ptr,bit) \
108     do {((BYTE *) ptr)[(bit) >> 3] &= ~(1 << ((bit) & 7));} while (0)
109
110 /* Common pixmap formats */
111 static PixmapFormatRec formats[] = {
112         { 1,    1,      BITMAP_SCANLINE_PAD },
113         { 4,    8,      BITMAP_SCANLINE_PAD },
114         { 8,    8,      BITMAP_SCANLINE_PAD },
115         { 15,   16,     BITMAP_SCANLINE_PAD },
116         { 16,   16,     BITMAP_SCANLINE_PAD },
117         { 24,   32,     BITMAP_SCANLINE_PAD },
118         { 32,   32,     BITMAP_SCANLINE_PAD }
119 };
120 const int NUMFORMATS = sizeof(formats)/sizeof(formats[0]);
121
122 #ifndef OSNAME
123 #define OSNAME " Mac OS X"
124 #endif
125 #ifndef OSVENDOR
126 #define OSVENDOR " Apple"
127 #endif
128 #ifndef PRE_RELEASE
129 #define PRE_RELEASE XF86_VERSION_SNAP
130 #endif
131
132 extern void AppleDRIExtensionInit(void);
133 extern void AppleWMExtensionInit(void);
134
135 static void
136 DarwinPrintBanner (void)
137 {
138   ErrorF("\nXFree86 Version %d.%d.%d", XF86_VERSION_MAJOR, XF86_VERSION_MINOR,
139                                     XF86_VERSION_PATCH);
140 #if XF86_VERSION_SNAP > 0
141   ErrorF(".%d", XF86_VERSION_SNAP);
142 #endif
143
144 #if XF86_VERSION_SNAP >= 900
145   ErrorF(" (%d.%d.0 RC %d)", XF86_VERSION_MAJOR, XF86_VERSION_MINOR + 1,
146                                 XF86_VERSION_SNAP - 900);
147 #endif
148
149 #ifdef XF86_CUSTOM_VERSION
150   ErrorF(" (%s)", XF86_CUSTOM_VERSION);
151 #endif
152   ErrorF(" / X Window System\n");
153   ErrorF("(protocol Version %d, revision %d, vendor release %d)\n",
154          X_PROTOCOL, X_PROTOCOL_REVISION, VENDOR_RELEASE );
155 }
156
157 /* X screensaver support. Not implemented. */
158 static Bool
159 DarwinSaveScreen (ScreenPtr pScreen, int on)
160 {
161     return TRUE;
162 }
163
164 /* This is a callback from dix during AddScreen() from InitOutput().
165    Initialize the screen and communicate information about it back to dix. */
166 static Bool
167 DarwinAddScreen (int index, ScreenPtr pScreen, int argc, char **argv)
168 {
169     int         i, dpi;
170     static int  foundIndex = 0;
171     Bool        ret;
172     VisualPtr   visual;
173     DarwinFramebufferPtr dfb;
174
175     /* reset index of found screens for each server generation */
176     if (index == 0)
177         foundIndex = 0;
178
179     /* allocate space for private per screen storage */
180     dfb = xalloc (sizeof (DarwinFramebufferRec));
181     SCREEN_PRIV(pScreen) = dfb;
182
183     /* setup hardware/mode specific details */
184     ret = QuartzAddScreen (foundIndex, pScreen);
185     foundIndex++;
186     if (!ret)
187         return FALSE;
188
189     /* reset the visual list */
190     miClearVisualTypes();
191
192     /* setup a single visual appropriate for our pixel type. Note: we use
193        TrueColor, not DirectColor */
194     if (dfb->componentCount != 1)
195     {
196         if (!miSetVisualTypes (dfb->colorBitsPerPixel, TrueColorMask,
197                                dfb->bitsPerComponent, TrueColor))
198             return FALSE;
199 #ifdef ENABLE_PSEUDOCOLOR
200         /* FIXME: currently we can't handle pseudocolor windows
201            inside truecolor top-level windows, so disable this. */
202         if (!miSetVisualTypes (8, PseudoColorMask, 8, PseudoColor))
203             return FALSE;
204 #endif
205     }
206     else
207     {
208         if (!miSetVisualTypes (8, PseudoColorMask, 8, PseudoColor))
209             return FALSE;
210     }
211
212     /* create the common 8 bit PseudoColor visual; do this last to prevent
213        it becoming the root visual. */
214
215     miSetPixmapDepths();
216
217     /* Machine independent screen init */
218     if (monitorResolution)
219         dpi = monitorResolution;
220     else
221         dpi = 75;
222
223     /* initialize fb */
224     if (!fbScreenInit (pScreen, dfb->framebuffer, dfb->width,
225                        dfb->height, dpi, dpi,
226                        dfb->pitch/(dfb->bitsPerPixel/8), dfb->bitsPerPixel))
227     {
228         return FALSE;
229     }
230
231     /* set the RGB order correctly for TrueColor */
232     if (dfb->bitsPerPixel > 8)
233     {
234         int bitsPerRGB = dfb->bitsPerComponent;
235
236         for (i = 0, visual = pScreen->visuals;
237             i < pScreen->numVisuals; i++, visual++)
238         {
239             if (visual->class == TrueColor) {
240                 visual->offsetRed = bitsPerRGB * 2;
241                 visual->offsetGreen = bitsPerRGB;
242                 visual->offsetBlue = 0;
243                 visual->redMask = ((1<<bitsPerRGB)-1) << visual->offsetRed;
244                 visual->greenMask = ((1<<bitsPerRGB)-1) << visual->offsetGreen;
245                 visual->blueMask = ((1<<bitsPerRGB)-1) << visual->offsetBlue;
246             }
247         }
248     }
249
250 #ifdef RENDER
251     if (! fbPictureInit (pScreen, 0, 0))
252         return FALSE;
253 #endif
254
255 #ifdef MITSHM
256     ShmRegisterFbFuncs (pScreen);
257 #endif
258
259     /* this must be initialized (why doesn't X have a default?) */
260     pScreen->SaveScreen = DarwinSaveScreen;
261
262     /* finish mode dependent screen setup including cursor support */
263     if (!QuartzSetupScreen (index, pScreen))
264         return FALSE;
265
266     /* create and install the default colormap and set black / white pixels */
267     if (!miCreateDefColormap (pScreen))
268         return FALSE;
269
270     dixScreenOrigins[index].x = dfb->x;
271     dixScreenOrigins[index].y = dfb->y;
272
273     ErrorF("Screen %d added: %dx%d @ (%d,%d)\n",
274             index, dfb->width, dfb->height, dfb->x, dfb->y);
275
276     return TRUE;
277 }
278
279 /* Search for a file in the standard Library paths, which are (in order):
280
281       ~/Library/              user specific
282       /Library/               host specific
283       /Network/Library/       LAN specific
284       /System/Library/        OS specific
285
286    A sub-path can be specified to search in below the various Library
287    directories. Returns a new character string (owned by the caller)
288    containing the full path to the first file found. */
289
290 /* Library search paths */
291 static const char *libraryPathList[] = {
292     "",
293     "/Network",
294     "/System",
295     NULL
296 };
297
298 char *
299 DarwinFindLibraryFile (const char *file, const char *pathext)
300 {
301     char *home;
302     char *fullPath;
303     int i = 0;
304
305     // Return the file name as is if it is already a fully qualified path.
306     if (!access(file, F_OK)) {
307         fullPath = xalloc(strlen(file)+1);
308         strcpy(fullPath, file);
309         return fullPath;
310     }
311
312     fullPath = xalloc(PATH_MAX);
313
314     home = getenv("HOME");
315     if (home) {
316         snprintf(fullPath, PATH_MAX, "%s/Library/%s/%s", home, pathext, file);
317         if (!access(fullPath, F_OK))
318             return fullPath;
319     }
320
321     while (libraryPathList[i]) {
322         snprintf(fullPath, PATH_MAX, "%s/Library/%s/%s", libraryPathList[i++],
323                  pathext, file);
324         if (!access(fullPath, F_OK))
325             return fullPath;
326     }
327
328     xfree(fullPath);
329     return NULL;
330 }
331
332 /* Press or release the given key, specified by NX keycode. xe must already
333    have event time and mouse location filled in. pressed is KeyPress or
334    KeyRelease. keycode is NX keycode without MIN_KEYCODE adjustment. */
335 static inline void
336 DarwinPressKeycode (xEvent *xe, int pressed, int keycode)
337 {
338     if (pressed == KeyRelease && !BitIsOn (keysDown, keycode + MIN_KEYCODE))
339     {
340         /* Don't release keys that aren't pressed. It generates extra
341            KeyPress events instead of just discarding them. */
342
343         return;
344     }
345
346     if (pressed == KeyPress)
347         SetBit (keysDown, keycode + MIN_KEYCODE);
348     else
349         ClearBit (keysDown, keycode + MIN_KEYCODE);
350
351     xe->u.u.type = pressed;
352     xe->u.u.detail = keycode + MIN_KEYCODE;
353     (darwinKeyboard->public.processInputProc) (xe, darwinKeyboard, 1);
354 }
355
356 /* Ensure that X's idea of what modifiers are down matches the real
357    window server's. Do this by looking at what keys we previously sent
358    X and deciding if they need to be released/toggled yet to make FLAGS
359    become X's current modifier state. */
360 static void
361 DarwinUpdateModifiers (xEvent xe, unsigned int flags)
362 {
363     static const struct {int mask; int nxkey;} pairs[] = {
364         {ShiftMask, NX_MODIFIERKEY_SHIFT},
365         {ControlMask, NX_MODIFIERKEY_CONTROL},
366         {Mod1Mask, NX_MODIFIERKEY_ALTERNATE},
367         {Mod2Mask, NX_MODIFIERKEY_COMMAND},
368         {Mod3Mask, NX_MODIFIERKEY_SECONDARYFN}
369     };
370
371     int i, keycode;
372
373     for (i = 0; i < (int) (sizeof (pairs) / sizeof (pairs[0])); i++)
374     {
375         keycode = DarwinModifierNXKeyToNXKeycode (pairs[i].nxkey, 0);
376
377         if (keycode == 0)
378             continue;
379
380         /* For each known modifier, sync up the state of the key X thinks
381            it's bound to and the real value of the flag. */
382
383         if ((flags & pairs[i].mask)
384             && !BitIsOn (keysDown, keycode + MIN_KEYCODE))
385         {
386             DarwinPressKeycode (&xe, KeyPress, keycode);
387         }
388         else if (!(flags & pairs[i].mask)
389                  && BitIsOn (keysDown, keycode + MIN_KEYCODE))
390         {
391             DarwinPressKeycode (&xe, KeyRelease, keycode);
392         }
393     }
394
395     /* Do the same for Lock, but need both press and release to toggle it. */
396
397     if ((flags ^ lockMods) & LockMask)
398     {
399         keycode = DarwinModifierNXKeyToNXKeycode (NX_MODIFIERKEY_ALPHALOCK, 0);
400
401         if (keycode != 0)
402         {
403             DarwinPressKeycode (&xe, KeyPress, keycode);
404             DarwinPressKeycode (&xe, KeyRelease, keycode);
405
406             lockMods ^= LockMask;
407         }
408     }
409 }
410
411 /* Release all non-modifier keys that we think are currently pressed.
412    Usually this is done when X becomes inactive to avoid leaving keys
413    stuck down when we become active again. Modifiers are handled separately
414    in the function above. */
415 static void
416 DarwinReleaseKeys (void)
417 {
418     KeyClassPtr keyc = darwinKeyboard->key;
419     xEvent xe;
420     int i, x, y;
421
422     memset (&xe, 0, sizeof (xe));
423     xe.u.keyButtonPointer.time = GetTimeInMillis ();
424     xe.u.keyButtonPointer.state = darwinKeyboard->key->state;
425     GetSpritePosition (&x, &y);
426     xe.u.keyButtonPointer.rootX = x;
427     xe.u.keyButtonPointer.rootY = y;
428     
429     for (i = 0; i < DOWN_LENGTH * 8; i++)
430     {
431         if (!keyc->modifierMap[i] && BitIsOn (keysDown, i))
432             DarwinPressKeycode (&xe, KeyRelease, i - MIN_KEYCODE);
433     }
434 }
435
436 static int
437 parseModifierString (const char *str)
438 {
439     if (strcasecmp (str, "shift") == 0)
440         return ShiftMask;
441     else if (strcasecmp (str, "control") == 0)
442         return ControlMask;
443     else if (strcasecmp (str, "option") == 0)
444         return Mod1Mask;
445     else if (strcasecmp (str, "command") == 0)
446         return Mod2Mask;
447     else if (strcasecmp (str, "fn") == 0)
448         return Mod3Mask;
449     else
450         return 0;
451 }
452
453 /* Parse a list of modifier names and return a corresponding modifier mask */
454 static int
455 DarwinParseModifierList (const char *constmodifiers)
456 {
457     int result, mask;
458     char *modifiers, *modifier, *p;
459
460     if (constmodifiers == NULL
461         || strlen (constmodifiers) == 0
462         || strcasecmp (constmodifiers, "none") == 0)
463     {
464         return 0;
465     }
466
467     modifiers = strdup (constmodifiers);
468     p = modifiers;
469     result = 0;
470
471     while (p != NULL)
472     {
473         modifier = strsep (&p, " ,+&|/"); /* allow lots of separators */
474         mask = parseModifierString (modifier);
475         if (mask != 0)
476             result |= mask;
477         else
478             ErrorF ("fakebuttons: Unknown modifier \"%s\"\n", modifier);
479     }
480
481     free (modifiers);
482     return result;
483 }
484
485 void
486 DarwinSetFakeButtons (const char *mod2, const char *mod3)
487 {
488     if (mod2 != NULL)
489         darwinFakeMouse2Mask = DarwinParseModifierList (mod2);
490     if (mod3 != NULL)
491         darwinFakeMouse3Mask = DarwinParseModifierList (mod3);
492 }
493
494 /* Read and process events from the event pipe until it is empty. */
495 void
496 ProcessInputEvents (void)
497 {
498     static int here_before = 0;
499
500     /* last known modifier state */
501     static unsigned int current_flags = 0;
502
503     /* button number and modifier mask of currently pressed fake button */
504     static int fake_button;
505     static unsigned int fake_button_mask, fake_button_modifier;
506
507     xEvent xe;
508
509     if (!here_before)
510     {
511         X11ApplicationServerReady ();
512         here_before = TRUE;
513     }
514
515     while (DarwinDequeueEvent (&xe))
516     {
517         unsigned int real_state;
518
519         real_state = xe.u.keyButtonPointer.state;
520         xe.u.keyButtonPointer.state |= fake_button_modifier;
521
522         /* Filter event for faked mouse button presses. */
523         if (darwinFakeButtons)
524         {
525             switch (xe.u.u.type)
526             {
527             case ButtonPress:
528                 if (xe.u.u.detail != 1)
529                     break;
530                 if ((xe.u.keyButtonPointer.state & darwinFakeMouse2Mask)
531                     == darwinFakeMouse2Mask)
532                 {
533                     fake_button = 2;
534                     fake_button_modifier = Button2Mask;
535                     fake_button_mask = darwinFakeMouse2Mask;
536                     xe.u.u.detail = 2;
537                 }
538                 else if ((xe.u.keyButtonPointer.state & darwinFakeMouse3Mask)
539                          == darwinFakeMouse3Mask)
540                 {
541                     fake_button = 3;
542                     fake_button_modifier = Button3Mask;
543                     fake_button_mask = darwinFakeMouse3Mask;
544                     xe.u.u.detail = 3;
545                 }
546                 break;
547
548             case ButtonRelease:
549                 if (fake_button != 0 && xe.u.u.detail == 1)
550                     xe.u.u.detail = fake_button;
551                 break;
552             }
553         }
554
555         xe.u.keyButtonPointer.state &= ~fake_button_mask;
556
557         switch (xe.u.u.type)
558         {
559         case 0: /* flags-changed */
560         case KeyPress:
561             if (current_flags == 0
562                 && darwinSyncKeymap && darwinKeymapFile == NULL)
563             {
564                 /* See if keymap has changed. */
565
566                 static unsigned int last_seed;
567                 unsigned int this_seed;
568
569                 this_seed = DarwinSystemKeymapSeed ();
570                 if (this_seed != last_seed)
571                 {
572                     last_seed = this_seed;
573                     DarwinKeyboardReload (darwinKeyboard);
574                 }
575             }
576             /* fall through */
577
578         case KeyRelease:
579         case ButtonPress:
580         case ButtonRelease:
581         case MotionNotify:
582
583             /* Initialize time field. */
584
585             xe.u.keyButtonPointer.time = GetTimeInMillis ();
586
587             /* Update X's idea of what modifiers are set. */
588
589             if (xe.u.keyButtonPointer.state != 0xffff
590                 && current_flags != xe.u.keyButtonPointer.state)
591             {
592                 current_flags = xe.u.keyButtonPointer.state;
593                 DarwinUpdateModifiers (xe, current_flags);
594             }
595         }
596
597         switch (xe.u.u.type)
598         {
599         case 0:
600             break;
601
602         case MotionNotify:
603             if (!quartzServerVisible)
604             {
605                 xp_window_id wid;
606
607                 /* Sigh. Need to check that we're really over one of
608                    our windows. (We need to receive pointer events while
609                    not in the foreground, and the only way to do that
610                    right now is to ask for _all_ pointer events..) */
611
612                 wid = 0;
613                 xp_find_window (xe.u.keyButtonPointer.rootX,
614                                 xe.u.keyButtonPointer.rootY, 0, &wid);
615                 if (wid == 0)
616                     break;
617             }
618
619             /* Shift from global screen coordinates to coordinates
620                relative to the origin of the current screen. */
621
622             xe.u.keyButtonPointer.rootX -= darwinMainScreenX -
623                     dixScreenOrigins[miPointerCurrentScreen()->myNum].x;
624             xe.u.keyButtonPointer.rootY -= darwinMainScreenY -
625                     dixScreenOrigins[miPointerCurrentScreen()->myNum].y;
626
627             miPointerAbsoluteCursor (xe.u.keyButtonPointer.rootX,
628                                      xe.u.keyButtonPointer.rootY,
629                                      xe.u.keyButtonPointer.time);
630             break;
631
632         case ButtonPress:
633         case ButtonRelease:
634             darwinPointer->public.processInputProc (&xe, darwinPointer, 1);
635             break;
636
637         case KeyPress:
638         case KeyRelease:
639             DarwinPressKeycode (&xe, xe.u.u.type, xe.u.u.detail);
640             break;
641
642         case ClientMessage:
643             /* Update server's current time, since we may generate
644                events, and it's nice if the timestamps are correct. */
645             currentTime.milliseconds = GetTimeInMillis ();
646
647             switch (xe.u.clientMessage.u.l.type)
648             {
649             case kXdarwinQuit:
650                 GiveUp (0);
651                 break;
652
653             case kXquartzDeactivate:
654                 DarwinReleaseKeys ();
655                 /* fall through */
656
657             default:
658                 if (xe.u.clientMessage.u.l.type >= kXquartzFirstEvent
659                     && xe.u.clientMessage.u.l.type <= kXquartzLastEvent)
660                 {
661                     QuartzClientMessage (&xe);
662                 }
663                 else
664                 {
665                     ErrorF ("Unknown application defined event: %d.\n",
666                             xe.u.clientMessage.u.l.longs0);
667                 }
668                 break;
669             }
670             break;
671
672         default:
673             ErrorF("Unknown event caught: %d\n", xe.u.u.type);
674             break;
675         }
676
677         /* Filter event for faked mouse button releases. */
678         if (fake_button != 0 && xe.u.u.type == ButtonRelease)
679         {
680             current_flags |= (real_state & fake_button_mask);
681             DarwinUpdateModifiers (xe, current_flags);
682
683             fake_button = 0;
684             fake_button_modifier = 0;
685             fake_button_mask = 0;
686         }
687     }
688
689     miPointerUpdate ();
690 }
691
692 void
693 DarwinEnqueuePointerEvent (xEvent *xe)
694 {
695     darwinPointer->public.processInputProc (xe, darwinPointer, 1);
696 }
697
698 /* Register the keyboard and mouse devices */
699 void
700 InitInput (int argc, char **argv)
701 {
702     DarwinInputInit ();
703
704     darwinPointer = AddInputDevice(DarwinMouseProc, TRUE);
705     RegisterPointerDevice( darwinPointer );
706
707     darwinKeyboard = AddInputDevice(DarwinKeybdProc, TRUE);
708     RegisterKeyboardDevice( darwinKeyboard );
709 }
710
711 void
712 DarwinAdjustScreenOrigins (ScreenInfo *pScreenInfo)
713 {
714     int i, left, top;
715
716     /* Shift all screens so the X11 (0, 0) coordinate is at the top
717        left of the global screen coordinates.
718
719        Screens can be arranged so the top left isn't on any screen, so
720        instead use the top left of the leftmost screen as (0,0). This
721        may mean some screen space is in -y, but it's better that (0,0)
722        be onscreen, or else default xterms disappear. It's better that
723        -y be used than -x, because when popup menus are forced
724        "onscreen" by dumb window managers like twm, they'll shift the
725        menus down instead of left, which still looks funny but is an
726        easier target to hit. */
727
728     left = dixScreenOrigins[0].x;
729     top  = dixScreenOrigins[0].y;
730
731     /* Find leftmost screen. If there's a tie, take the topmost of the two. */
732     for (i = 1; i < pScreenInfo->numScreens; i++) {
733         if (dixScreenOrigins[i].x < left  ||
734             (dixScreenOrigins[i].x == left &&
735              dixScreenOrigins[i].y < top))
736         {
737             left = dixScreenOrigins[i].x;
738             top = dixScreenOrigins[i].y;
739         }
740     }
741
742     darwinMainScreenX = left;
743     darwinMainScreenY = top;
744
745     /* Shift all screens so that there is a screen whose top left
746        is at X11 (0,0) and at global screen coordinate
747        (darwinMainScreenX, darwinMainScreenY). */
748
749     if (darwinMainScreenX != 0 || darwinMainScreenY != 0) {
750         for (i = 0; i < pScreenInfo->numScreens; i++) {
751             dixScreenOrigins[i].x -= darwinMainScreenX;
752             dixScreenOrigins[i].y -= darwinMainScreenY;
753             ErrorF("Screen %d placed at X11 coordinate (%d,%d).\n",
754                    i, dixScreenOrigins[i].x, dixScreenOrigins[i].y);
755         }
756     }
757 }
758
759 /* Initialize screenInfo for all actually accessible framebuffers.
760
761    The display mode dependent code gets called three times. The mode
762    specific InitOutput routines are expected to discover the number of
763    potentially useful screens and cache routes to them internally.
764    Inside DarwinAddScreen are two other mode specific calls. A mode
765    specific AddScreen routine is called for each screen to actually
766    initialize the screen with the ScreenPtr structure. After other
767    screen setup has been done, a mode specific SetupScreen function can
768    be called to finalize screen setup. */
769
770 void
771 InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
772 {
773     int i;
774     static unsigned long generation = 0;
775
776     pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
777     pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
778     pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
779     pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
780
781     /* List how we want common pixmap formats to be padded */
782     pScreenInfo->numPixmapFormats = NUMFORMATS;
783     for (i = 0; i < NUMFORMATS; i++)
784         pScreenInfo->formats[i] = formats[i];
785
786     /* Allocate private storage for each screen's Darwin specific info */
787     if (generation != serverGeneration) {
788         darwinScreenIndex = AllocateScreenPrivateIndex();
789         generation = serverGeneration;
790     }
791
792     /* Discover screens and do mode specific initialization */
793     QuartzInitOutput(argc, argv);
794
795     for (i = 0; i < darwinScreensFound; i++)
796         AddScreen( DarwinAddScreen, argc, argv );
797
798     DarwinAdjustScreenOrigins (pScreenInfo);
799
800     PseudoramiXExtensionInit (argc, argv);
801     AppleDRIExtensionInit ();
802     AppleWMExtensionInit ();
803
804     DRIExtensionInit ();
805 }
806
807 void
808 OsVendorFatalError (void)
809 {
810     ErrorF( "   OsVendorFatalError\n" );
811 }
812
813 void
814 OsVendorInit (void)
815 {
816     if (serverGeneration == 1)
817         DarwinPrintBanner();
818 }
819
820 /* Process device-dependent command line args. Returns 0 if argument is
821    not device dependent, otherwise Count of number of elements of argv
822    that are part of a device dependent commandline option. */
823 int
824 ddxProcessArgument (int argc, char *argv[], int i)
825 {
826     int numDone;
827
828     if ((numDone = QuartzProcessArgument( argc, argv, i )))
829         return numDone;
830
831     if ( !strcmp( argv[i], "-fakebuttons" ) ) {
832         darwinFakeButtons = TRUE;
833         ErrorF( "Faking a three button mouse\n" );
834         return 1;
835     }
836
837     if ( !strcmp( argv[i], "-nofakebuttons" ) ) {
838         darwinFakeButtons = FALSE;
839         ErrorF( "Not faking a three button mouse\n" );
840         return 1;
841     }
842
843     if (!strcmp( argv[i], "-fakemouse2" ) ) {
844         if ( i == argc-1 ) {
845             FatalError( "-fakemouse2 must be followed by a modifer list\n" );
846         }
847         darwinFakeMouse2Mask = DarwinParseModifierList(argv[i+1]);
848         return 2;
849     }
850
851     if (!strcmp( argv[i], "-fakemouse3" ) ) {
852         if ( i == argc-1 ) {
853             FatalError( "-fakemouse3 must be followed by a modifer list\n" );
854         }
855         darwinFakeMouse3Mask = DarwinParseModifierList(argv[i+1]);
856         return 2;
857     }
858
859     if ( !strcmp( argv[i], "-keymap" ) ) {
860         if ( i == argc-1 ) {
861             FatalError( "-keymap must be followed by a filename\n" );
862         }
863         darwinKeymapFile = argv[i+1];
864         return 2;
865     }
866
867     if ( !strcmp( argv[i], "-nokeymap" ) ) {
868         darwinKeymapFile = NULL;
869         return 1;
870     }
871
872     if ( !strcmp( argv[i], "+synckeymap" ) ) {
873         darwinSyncKeymap = TRUE;
874         return 1;
875     }
876     if ( !strcmp( argv[i], "-synckeymap" ) ) {
877         darwinSyncKeymap = FALSE;
878         return 1;
879     }
880
881     if (strcmp (argv[i], "-swapAltMeta") == 0) {
882         darwinSwapAltMeta = TRUE;
883         return 1;
884     }
885
886     if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) {
887         DarwinPrintBanner();
888         exit(0);
889     }
890
891     /* XDarwinStartup uses this argument to indicate the IOKit X server
892        should be started. Ignore it here. */
893     if ( !strcmp( argv[i], "-iokit" ) ) {
894         return 1;
895     }
896
897     return 0;
898 }
899
900 /* Print out correct use of device dependent commandline options.
901    Maybe the user now knows what really to do ... */
902 void
903 ddxUseMsg (void)
904 {
905     ErrorF("\n");
906     ErrorF("\n");
907     ErrorF("Device Dependent Usage:\n");
908     ErrorF("\n");
909     ErrorF("-depth <depth>         use <depth> bits per pixel. Options: 8, 15, 24\b\n");
910     ErrorF("-fakebuttons           fake a 3 button mouse with Command and Option\n");
911     ErrorF("-nofakebuttons\n");
912     ErrorF("-fakemouse2 <keys>     fake middle mouse button with modifier keys\n");
913     ErrorF("-fakemouse3 <keys>     fake right mouse button with modifier keys\n");
914     ErrorF("                         e.g.: -fakemouse2 \"option,shift\"\n");
915     ErrorF("-keymap <file>         read the keymap from <file>\n");
916     ErrorF("-nokeymap\n");
917     ErrorF("+synckeymap            synchronize X keymap with system keymap\n");
918     ErrorF("-synckeymap            only set X keymap on server startup\n");
919     ErrorF("-swapAltMeta           swap meaning of Alt and Meta modifiers\n");
920     ErrorF("-version               show server version.\n");
921     ErrorF("\n");
922 }
923
924 /* Device dependent cleanup. Called by dix before normal server death. */
925 void
926 ddxGiveUp (void)
927 {
928     ErrorF( "Quitting XDarwin...\n" );
929     QuartzGiveUp();
930 }
931
932 /* DDX - specific abort routine.  Called by AbortServer(). The attempt is
933    made to restore all original setting of the displays. Also all devices
934    are closed. */
935 void
936 AbortDDX (void)
937 {
938     ErrorF( "   AbortDDX\n" );
939
940     /* This is needed for a abnormal server exit, since the normal exit stuff
941        MUST also be performed (i.e. the vt must be left in a defined state) */
942     ddxGiveUp();
943 }
944
945 extern void GlxExtensionInit();
946 extern void GlxWrapInitVisuals(void *procPtr);
947 void DarwinGlxExtensionInit (void) { GlxExtensionInit (); }
948 void DarwinGlxWrapInitVisuals (void *ptr) { GlxWrapInitVisuals (ptr); }
949
950 #ifdef DPMSExtension
951 Bool
952 DPMSSupported (void)
953 {
954     return FALSE;
955 }
956
957 void
958 DPMSSet (int level)
959 {
960 }
961
962 int
963 DPMSGet (int *level)
964 {
965     return -1;
966 }
967 #endif
968
969 #ifdef DDXTIME
970 CARD32
971 GetTimeInMillis (void)
972 {
973     extern void Microseconds ();
974     UnsignedWide usec;
975
976     /* This doesn't involve trapping into the kernel, unlike gettimeofday. */
977     Microseconds (&usec);
978
979     /* Should be good enough? (-2% error) */
980     return (usec.hi << 22) | (usec.lo >> 10);
981 }
982 #endif