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