Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. | |
3 | * | |
4 | * All Rights Reserved. | |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person obtaining | |
7 | * a copy of this software and associated documentation files (the | |
8 | * "Software"), to deal in the Software without restriction, including | |
9 | * without limitation on the rights to use, copy, modify, merge, | |
10 | * publish, distribute, sublicense, and/or sell copies of the Software, | |
11 | * and to permit persons to whom the Software is furnished to do so, | |
12 | * subject to the following conditions: | |
13 | * | |
14 | * The above copyright notice and this permission notice (including the | |
15 | * next paragraph) shall be included in all copies or substantial | |
16 | * portions of the Software. | |
17 | * | |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
21 | * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS | |
22 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
23 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
25 | * SOFTWARE. | |
26 | */ | |
27 | ||
28 | /* | |
29 | * Authors: | |
30 | * Kevin E. Martin <kem@redhat.com> | |
31 | * David H. Dawes <dawes@xfree86.org> | |
32 | * Rickard E. (Rik) Faith <faith@redhat.com> | |
33 | * | |
34 | */ | |
35 | ||
36 | /** \file | |
37 | * Provide expected functions for initialization from the ddx layer and | |
38 | * global variables for the DMX server. */ | |
39 | ||
40 | #ifdef HAVE_DMX_CONFIG_H | |
41 | #include <dmx-config.h> | |
42 | #endif | |
43 | ||
44 | #include "dmx.h" | |
45 | #include "dmxinit.h" | |
46 | #include "dmxsync.h" | |
47 | #include "dmxlog.h" | |
48 | #include "dmxinput.h" | |
49 | #include "dmxscrinit.h" | |
50 | #include "dmxcursor.h" | |
51 | #include "dmxfont.h" | |
52 | #include "config/dmxconfig.h" | |
53 | #include "dmxcb.h" | |
54 | #include "dmxprop.h" | |
55 | #include "dmxstat.h" | |
56 | #include "dmxpict.h" | |
57 | ||
58 | #include <X11/Xos.h> /* For gettimeofday */ | |
59 | #include <X11/Xmu/SysUtil.h> /* For XmuGetHostname */ | |
60 | #include "dixstruct.h" | |
61 | #ifdef PANORAMIX | |
62 | #include "panoramiXsrv.h" | |
63 | #endif | |
64 | ||
65 | #include <signal.h> /* For SIGQUIT */ | |
66 | ||
67 | #ifdef GLXEXT | |
68 | #include <GL/glx.h> | |
69 | #include <GL/glxint.h> | |
70 | #include "dmx_glxvisuals.h" | |
71 | #include "glx_extinit.h" | |
72 | #include <X11/extensions/Xext.h> | |
73 | #include <X11/extensions/extutil.h> | |
74 | #endif /* GLXEXT */ | |
75 | ||
76 | #include <X11/extensions/dmxproto.h> | |
77 | ||
78 | /* Global variables available to all Xserver/hw/dmx routines. */ | |
79 | int dmxNumScreens; | |
80 | DMXScreenInfo *dmxScreens; | |
81 | ||
82 | int dmxNumInputs; | |
83 | DMXInputInfo *dmxInputs; | |
84 | ||
85 | XErrorEvent dmxLastErrorEvent; | |
86 | Bool dmxErrorOccurred = FALSE; | |
87 | ||
88 | char *dmxFontPath = NULL; | |
89 | ||
90 | Bool dmxOffScreenOpt = TRUE; | |
91 | ||
92 | Bool dmxSubdividePrimitives = TRUE; | |
93 | ||
94 | Bool dmxLazyWindowCreation = TRUE; | |
95 | ||
96 | Bool dmxUseXKB = TRUE; | |
97 | ||
98 | int dmxDepth = 0; | |
99 | ||
100 | #ifndef GLXEXT | |
101 | static Bool dmxGLXProxy = FALSE; | |
102 | #else | |
103 | Bool dmxGLXProxy = TRUE; | |
104 | ||
105 | Bool dmxGLXSwapGroupSupport = TRUE; | |
106 | ||
107 | Bool dmxGLXSyncSwap = FALSE; | |
108 | ||
109 | Bool dmxGLXFinishSwap = FALSE; | |
110 | #endif | |
111 | ||
112 | RESTYPE RRProviderType = 0; | |
113 | ||
114 | Bool dmxIgnoreBadFontPaths = FALSE; | |
115 | ||
116 | Bool dmxAddRemoveScreens = FALSE; | |
117 | ||
118 | /* dmxErrorHandler catches errors that occur when calling one of the | |
119 | * back-end servers. Some of this code is based on _XPrintDefaultError | |
120 | * in xc/lib/X11/XlibInt.c */ | |
121 | static int | |
122 | dmxErrorHandler(Display * dpy, XErrorEvent * ev) | |
123 | { | |
124 | #define DMX_ERROR_BUF_SIZE 256 | |
125 | /* RATS: these buffers are only used in | |
126 | * length-limited calls. */ | |
127 | char buf[DMX_ERROR_BUF_SIZE]; | |
128 | char request[DMX_ERROR_BUF_SIZE]; | |
129 | _XExtension *ext = NULL; | |
130 | ||
131 | dmxErrorOccurred = TRUE; | |
132 | dmxLastErrorEvent = *ev; | |
133 | ||
134 | XGetErrorText(dpy, ev->error_code, buf, sizeof(buf)); | |
135 | dmxLog(dmxWarning, "dmxErrorHandler: %s\n", buf); | |
136 | ||
137 | /* Find major opcode name */ | |
138 | if (ev->request_code < 128) { | |
139 | snprintf(request, sizeof(request), "%d", ev->request_code); | |
140 | XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf)); | |
141 | } | |
142 | else { | |
143 | for (ext = dpy->ext_procs; | |
144 | ext && ext->codes.major_opcode != ev->request_code; | |
145 | ext = ext->next); | |
146 | if (ext) | |
147 | strlcpy(buf, ext->name, sizeof(buf)); | |
148 | else | |
149 | buf[0] = '\0'; | |
150 | } | |
151 | dmxLog(dmxWarning, " Major opcode: %d (%s)\n", | |
152 | ev->request_code, buf); | |
153 | ||
154 | /* Find minor opcode name */ | |
155 | if (ev->request_code >= 128 && ext) { | |
156 | snprintf(request, sizeof(request), "%d", ev->request_code); | |
157 | snprintf(request, sizeof(request), "%s.%d", ext->name, ev->minor_code); | |
158 | XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf)); | |
159 | dmxLog(dmxWarning, " Minor opcode: %d (%s)\n", | |
160 | ev->minor_code, buf); | |
161 | } | |
162 | ||
163 | /* Provide value information */ | |
164 | switch (ev->error_code) { | |
165 | case BadValue: | |
166 | dmxLog(dmxWarning, " Value: 0x%x\n", | |
167 | ev->resourceid); | |
168 | break; | |
169 | case BadAtom: | |
170 | dmxLog(dmxWarning, " AtomID: 0x%x\n", | |
171 | ev->resourceid); | |
172 | break; | |
173 | default: | |
174 | dmxLog(dmxWarning, " ResourceID: 0x%x\n", | |
175 | ev->resourceid); | |
176 | break; | |
177 | } | |
178 | ||
179 | /* Provide serial number information */ | |
180 | dmxLog(dmxWarning, " Failed serial number: %d\n", | |
181 | ev->serial); | |
182 | dmxLog(dmxWarning, " Current serial number: %d\n", | |
183 | dpy->request); | |
184 | return 0; | |
185 | } | |
186 | ||
187 | #ifdef GLXEXT | |
188 | static int | |
189 | dmxNOPErrorHandler(Display * dpy, XErrorEvent * ev) | |
190 | { | |
191 | return 0; | |
192 | } | |
193 | #endif | |
194 | ||
195 | Bool | |
196 | dmxOpenDisplay(DMXScreenInfo * dmxScreen) | |
197 | { | |
198 | if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->name))) | |
199 | return FALSE; | |
200 | ||
201 | dmxPropertyDisplay(dmxScreen); | |
202 | return TRUE; | |
203 | } | |
204 | ||
205 | void | |
206 | dmxSetErrorHandler(DMXScreenInfo * dmxScreen) | |
207 | { | |
208 | XSetErrorHandler(dmxErrorHandler); | |
209 | } | |
210 | ||
211 | static void | |
212 | dmxPrintScreenInfo(DMXScreenInfo * dmxScreen) | |
213 | { | |
214 | XWindowAttributes attribs; | |
215 | int ndepths = 0, *depths = NULL; | |
216 | int i; | |
217 | Display *dpy = dmxScreen->beDisplay; | |
218 | Screen *s = DefaultScreenOfDisplay(dpy); | |
219 | int scr = DefaultScreen(dpy); | |
220 | ||
221 | XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs); | |
222 | if (!(depths = XListDepths(dpy, scr, &ndepths))) | |
223 | ndepths = 0; | |
224 | ||
225 | dmxLogOutput(dmxScreen, "Name of display: %s\n", DisplayString(dpy)); | |
226 | dmxLogOutput(dmxScreen, "Version number: %d.%d\n", | |
227 | ProtocolVersion(dpy), ProtocolRevision(dpy)); | |
228 | dmxLogOutput(dmxScreen, "Vendor string: %s\n", ServerVendor(dpy)); | |
229 | if (!strstr(ServerVendor(dpy), "XFree86")) { | |
230 | dmxLogOutput(dmxScreen, "Vendor release: %d\n", VendorRelease(dpy)); | |
231 | } | |
232 | else { | |
233 | /* This code based on xdpyinfo.c */ | |
234 | int v = VendorRelease(dpy); | |
235 | int major = -1, minor = -1, patch = -1, subpatch = -1; | |
236 | ||
237 | if (v < 336) | |
238 | major = v / 100, minor = (v / 10) % 10, patch = v % 10; | |
239 | else if (v < 3900) { | |
240 | major = v / 1000; | |
241 | minor = (v / 100) % 10; | |
242 | if (((v / 10) % 10) || (v % 10)) { | |
243 | patch = (v / 10) % 10; | |
244 | if (v % 10) | |
245 | subpatch = v % 10; | |
246 | } | |
247 | } | |
248 | else if (v < 40000000) { | |
249 | major = v / 1000; | |
250 | minor = (v / 10) % 10; | |
251 | if (v % 10) | |
252 | patch = v % 10; | |
253 | } | |
254 | else { | |
255 | major = v / 10000000; | |
256 | minor = (v / 100000) % 100; | |
257 | patch = (v / 1000) % 100; | |
258 | if (v % 1000) | |
259 | subpatch = v % 1000; | |
260 | } | |
261 | dmxLogOutput(dmxScreen, "Vendor release: %d (XFree86 version: %d.%d", | |
262 | v, major, minor); | |
263 | if (patch > 0) | |
264 | dmxLogOutputCont(dmxScreen, ".%d", patch); | |
265 | if (subpatch > 0) | |
266 | dmxLogOutputCont(dmxScreen, ".%d", subpatch); | |
267 | dmxLogOutputCont(dmxScreen, ")\n"); | |
268 | } | |
269 | ||
270 | dmxLogOutput(dmxScreen, "Dimensions: %dx%d pixels\n", | |
271 | attribs.width, attribs.height); | |
272 | dmxLogOutput(dmxScreen, "%d depths on screen %d: ", ndepths, scr); | |
273 | for (i = 0; i < ndepths; i++) | |
274 | dmxLogOutputCont(dmxScreen, "%c%d", i ? ',' : ' ', depths[i]); | |
275 | dmxLogOutputCont(dmxScreen, "\n"); | |
276 | dmxLogOutput(dmxScreen, "Depth of root window: %d plane%s (%d)\n", | |
277 | attribs.depth, attribs.depth == 1 ? "" : "s", | |
278 | DisplayPlanes(dpy, scr)); | |
279 | dmxLogOutput(dmxScreen, "Number of colormaps: %d min, %d max\n", | |
280 | MinCmapsOfScreen(s), MaxCmapsOfScreen(s)); | |
281 | dmxLogOutput(dmxScreen, "Options: backing-store %s, save-unders %s\n", | |
282 | (DoesBackingStore(s) == NotUseful) ? "no" : | |
283 | ((DoesBackingStore(s) == Always) ? "yes" : "when mapped"), | |
284 | DoesSaveUnders(s) ? "yes" : "no"); | |
285 | dmxLogOutput(dmxScreen, "Window Manager running: %s\n", | |
286 | (dmxScreen->WMRunningOnBE) ? "yes" : "no"); | |
287 | ||
288 | if (dmxScreen->WMRunningOnBE) { | |
289 | dmxLogOutputWarning(dmxScreen, | |
290 | "Window manager running " | |
291 | "-- colormaps not supported\n"); | |
292 | } | |
293 | XFree(depths); | |
294 | } | |
295 | ||
296 | void | |
297 | dmxGetScreenAttribs(DMXScreenInfo * dmxScreen) | |
298 | { | |
299 | XWindowAttributes attribs; | |
300 | Display *dpy = dmxScreen->beDisplay; | |
301 | ||
302 | #ifdef GLXEXT | |
303 | int dummy; | |
304 | #endif | |
305 | ||
306 | XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs); | |
307 | ||
308 | dmxScreen->beWidth = attribs.width; | |
309 | dmxScreen->beHeight = attribs.height; | |
310 | ||
311 | /* Fill in missing geometry information */ | |
312 | if (dmxScreen->scrnXSign < 0) { | |
313 | if (dmxScreen->scrnWidth) { | |
314 | dmxScreen->scrnX = (attribs.width - dmxScreen->scrnWidth | |
315 | - dmxScreen->scrnX); | |
316 | } | |
317 | else { | |
318 | dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX; | |
319 | dmxScreen->scrnX = 0; | |
320 | } | |
321 | } | |
322 | if (dmxScreen->scrnYSign < 0) { | |
323 | if (dmxScreen->scrnHeight) { | |
324 | dmxScreen->scrnY = (attribs.height - dmxScreen->scrnHeight | |
325 | - dmxScreen->scrnY); | |
326 | } | |
327 | else { | |
328 | dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY; | |
329 | dmxScreen->scrnY = 0; | |
330 | } | |
331 | } | |
332 | if (!dmxScreen->scrnWidth) | |
333 | dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX; | |
334 | if (!dmxScreen->scrnHeight) | |
335 | dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY; | |
336 | ||
337 | if (!dmxScreen->rootWidth) | |
338 | dmxScreen->rootWidth = dmxScreen->scrnWidth; | |
339 | if (!dmxScreen->rootHeight) | |
340 | dmxScreen->rootHeight = dmxScreen->scrnHeight; | |
341 | if (dmxScreen->rootWidth + dmxScreen->rootX > dmxScreen->scrnWidth) | |
342 | dmxScreen->rootWidth = dmxScreen->scrnWidth - dmxScreen->rootX; | |
343 | if (dmxScreen->rootHeight + dmxScreen->rootY > dmxScreen->scrnHeight) | |
344 | dmxScreen->rootHeight = dmxScreen->scrnHeight - dmxScreen->rootY; | |
345 | ||
346 | /* FIXME: Get these from the back-end server */ | |
347 | dmxScreen->beXDPI = 75; | |
348 | dmxScreen->beYDPI = 75; | |
349 | ||
350 | dmxScreen->beDepth = attribs.depth; /* FIXME: verify that this | |
351 | * works always. In | |
352 | * particular, this will work | |
353 | * well for depth=16, will fail | |
354 | * because of colormap issues | |
355 | * at depth 8. More work needs | |
356 | * to be done here. */ | |
357 | ||
358 | if (dmxScreen->beDepth <= 8) | |
359 | dmxScreen->beBPP = 8; | |
360 | else if (dmxScreen->beDepth <= 16) | |
361 | dmxScreen->beBPP = 16; | |
362 | else | |
363 | dmxScreen->beBPP = 32; | |
364 | ||
365 | #ifdef GLXEXT | |
366 | /* get the majorOpcode for the back-end GLX extension */ | |
367 | XQueryExtension(dpy, "GLX", &dmxScreen->glxMajorOpcode, | |
368 | &dummy, &dmxScreen->glxErrorBase); | |
369 | #endif | |
370 | ||
371 | dmxPrintScreenInfo(dmxScreen); | |
372 | dmxLogOutput(dmxScreen, "%dx%d+%d+%d on %dx%d at depth=%d, bpp=%d\n", | |
373 | dmxScreen->scrnWidth, dmxScreen->scrnHeight, | |
374 | dmxScreen->scrnX, dmxScreen->scrnY, | |
375 | dmxScreen->beWidth, dmxScreen->beHeight, | |
376 | dmxScreen->beDepth, dmxScreen->beBPP); | |
377 | if (dmxScreen->beDepth == 8) | |
378 | dmxLogOutputWarning(dmxScreen, | |
379 | "Support for depth == 8 is not complete\n"); | |
380 | } | |
381 | ||
382 | Bool | |
383 | dmxGetVisualInfo(DMXScreenInfo * dmxScreen) | |
384 | { | |
385 | int i; | |
386 | XVisualInfo visinfo; | |
387 | ||
388 | visinfo.screen = DefaultScreen(dmxScreen->beDisplay); | |
389 | dmxScreen->beVisuals = XGetVisualInfo(dmxScreen->beDisplay, | |
390 | VisualScreenMask, | |
391 | &visinfo, &dmxScreen->beNumVisuals); | |
392 | ||
393 | dmxScreen->beDefVisualIndex = -1; | |
394 | ||
395 | if (defaultColorVisualClass >= 0 || dmxDepth > 0) { | |
396 | for (i = 0; i < dmxScreen->beNumVisuals; i++) | |
397 | if (defaultColorVisualClass >= 0) { | |
398 | if (dmxScreen->beVisuals[i].class == defaultColorVisualClass) { | |
399 | if (dmxDepth > 0) { | |
400 | if (dmxScreen->beVisuals[i].depth == dmxDepth) { | |
401 | dmxScreen->beDefVisualIndex = i; | |
402 | break; | |
403 | } | |
404 | } | |
405 | else { | |
406 | dmxScreen->beDefVisualIndex = i; | |
407 | break; | |
408 | } | |
409 | } | |
410 | } | |
411 | else if (dmxScreen->beVisuals[i].depth == dmxDepth) { | |
412 | dmxScreen->beDefVisualIndex = i; | |
413 | break; | |
414 | } | |
415 | } | |
416 | else { | |
417 | visinfo.visualid = | |
418 | XVisualIDFromVisual(DefaultVisual(dmxScreen->beDisplay, | |
419 | visinfo.screen)); | |
420 | ||
421 | for (i = 0; i < dmxScreen->beNumVisuals; i++) | |
422 | if (visinfo.visualid == dmxScreen->beVisuals[i].visualid) { | |
423 | dmxScreen->beDefVisualIndex = i; | |
424 | break; | |
425 | } | |
426 | } | |
427 | ||
428 | for (i = 0; i < dmxScreen->beNumVisuals; i++) | |
429 | dmxLogVisual(dmxScreen, &dmxScreen->beVisuals[i], | |
430 | (i == dmxScreen->beDefVisualIndex)); | |
431 | ||
432 | return dmxScreen->beDefVisualIndex >= 0; | |
433 | } | |
434 | ||
435 | void | |
436 | dmxGetColormaps(DMXScreenInfo * dmxScreen) | |
437 | { | |
438 | int i; | |
439 | ||
440 | dmxScreen->beNumDefColormaps = dmxScreen->beNumVisuals; | |
441 | dmxScreen->beDefColormaps = malloc(dmxScreen->beNumDefColormaps * | |
442 | sizeof(*dmxScreen->beDefColormaps)); | |
443 | ||
444 | for (i = 0; i < dmxScreen->beNumDefColormaps; i++) | |
445 | dmxScreen->beDefColormaps[i] = | |
446 | XCreateColormap(dmxScreen->beDisplay, | |
447 | DefaultRootWindow(dmxScreen->beDisplay), | |
448 | dmxScreen->beVisuals[i].visual, AllocNone); | |
449 | ||
450 | dmxScreen->beBlackPixel = BlackPixel(dmxScreen->beDisplay, | |
451 | DefaultScreen(dmxScreen->beDisplay)); | |
452 | dmxScreen->beWhitePixel = WhitePixel(dmxScreen->beDisplay, | |
453 | DefaultScreen(dmxScreen->beDisplay)); | |
454 | } | |
455 | ||
456 | void | |
457 | dmxGetPixmapFormats(DMXScreenInfo * dmxScreen) | |
458 | { | |
459 | dmxScreen->beDepths = | |
460 | XListDepths(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay), | |
461 | &dmxScreen->beNumDepths); | |
462 | ||
463 | dmxScreen->bePixmapFormats = | |
464 | XListPixmapFormats(dmxScreen->beDisplay, | |
465 | &dmxScreen->beNumPixmapFormats); | |
466 | } | |
467 | ||
468 | static Bool | |
469 | dmxSetPixmapFormats(ScreenInfo * pScreenInfo, DMXScreenInfo * dmxScreen) | |
470 | { | |
471 | XPixmapFormatValues *bePixmapFormat; | |
472 | PixmapFormatRec *format; | |
473 | int i, j; | |
474 | ||
475 | pScreenInfo->imageByteOrder = ImageByteOrder(dmxScreen->beDisplay); | |
476 | pScreenInfo->bitmapScanlineUnit = BitmapUnit(dmxScreen->beDisplay); | |
477 | pScreenInfo->bitmapScanlinePad = BitmapPad(dmxScreen->beDisplay); | |
478 | pScreenInfo->bitmapBitOrder = BitmapBitOrder(dmxScreen->beDisplay); | |
479 | ||
480 | pScreenInfo->numPixmapFormats = 0; | |
481 | for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { | |
482 | bePixmapFormat = &dmxScreen->bePixmapFormats[i]; | |
483 | for (j = 0; j < dmxScreen->beNumDepths; j++) | |
484 | if ((bePixmapFormat->depth == 1) || | |
485 | (bePixmapFormat->depth == dmxScreen->beDepths[j])) { | |
486 | format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats]; | |
487 | ||
488 | format->depth = bePixmapFormat->depth; | |
489 | format->bitsPerPixel = bePixmapFormat->bits_per_pixel; | |
490 | format->scanlinePad = bePixmapFormat->scanline_pad; | |
491 | ||
492 | pScreenInfo->numPixmapFormats++; | |
493 | break; | |
494 | } | |
495 | } | |
496 | ||
497 | return TRUE; | |
498 | } | |
499 | ||
500 | void | |
501 | dmxCheckForWM(DMXScreenInfo * dmxScreen) | |
502 | { | |
503 | Status status; | |
504 | XWindowAttributes xwa; | |
505 | ||
506 | status = XGetWindowAttributes(dmxScreen->beDisplay, | |
507 | DefaultRootWindow(dmxScreen->beDisplay), | |
508 | &xwa); | |
509 | dmxScreen->WMRunningOnBE = | |
510 | (status && | |
511 | ((xwa.all_event_masks & SubstructureRedirectMask) || | |
512 | (xwa.all_event_masks & SubstructureNotifyMask))); | |
513 | } | |
514 | ||
515 | /** Initialize the display and collect relevant information about the | |
516 | * display properties */ | |
517 | static void | |
518 | dmxDisplayInit(DMXScreenInfo * dmxScreen) | |
519 | { | |
520 | if (!dmxOpenDisplay(dmxScreen)) | |
521 | dmxLog(dmxFatal, | |
522 | "dmxOpenDisplay: Unable to open display %s\n", dmxScreen->name); | |
523 | ||
524 | dmxSetErrorHandler(dmxScreen); | |
525 | dmxCheckForWM(dmxScreen); | |
526 | dmxGetScreenAttribs(dmxScreen); | |
527 | ||
528 | if (!dmxGetVisualInfo(dmxScreen)) | |
529 | dmxLog(dmxFatal, "dmxGetVisualInfo: No matching visuals found\n"); | |
530 | ||
531 | dmxGetColormaps(dmxScreen); | |
532 | dmxGetPixmapFormats(dmxScreen); | |
533 | } | |
534 | ||
535 | /* If this doesn't compile, just add || defined(yoursystem) to the line | |
536 | * below. This information is to help with bug reports and is not | |
537 | * critical. */ | |
538 | #if !defined(_POSIX_SOURCE) | |
539 | static const char * | |
540 | dmxExecOS(void) | |
541 | { | |
542 | return ""; | |
543 | } | |
544 | #else | |
545 | #include <sys/utsname.h> | |
546 | static const char * | |
547 | dmxExecOS(void) | |
548 | { | |
549 | static char buffer[128]; | |
550 | static int initialized = 0; | |
551 | struct utsname u; | |
552 | ||
553 | if (!initialized++) { | |
554 | memset(buffer, 0, sizeof(buffer)); | |
555 | uname(&u); | |
556 | snprintf(buffer, sizeof(buffer) - 1, "%s %s %s", | |
557 | u.sysname, u.release, u.version); | |
558 | } | |
559 | return buffer; | |
560 | } | |
561 | #endif | |
562 | ||
563 | static const char * | |
564 | dmxBuildCompiler(void) | |
565 | { | |
566 | static char buffer[128]; | |
567 | static int initialized = 0; | |
568 | ||
569 | if (!initialized++) { | |
570 | memset(buffer, 0, sizeof(buffer)); | |
571 | #if defined(__GNUC__) && defined(__GNUC_MINOR__) &&defined(__GNUC_PATCHLEVEL__) | |
572 | snprintf(buffer, sizeof(buffer) - 1, "gcc %d.%d.%d", | |
573 | __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); | |
574 | #endif | |
575 | } | |
576 | return buffer; | |
577 | } | |
578 | ||
579 | static const char * | |
580 | dmxExecHost(void) | |
581 | { | |
582 | static char buffer[128]; | |
583 | static int initialized = 0; | |
584 | ||
585 | if (!initialized++) { | |
586 | memset(buffer, 0, sizeof(buffer)); | |
587 | XmuGetHostname(buffer, sizeof(buffer) - 1); | |
588 | } | |
589 | return buffer; | |
590 | } | |
591 | ||
592 | static void dmxAddExtensions(Bool glxSupported) | |
593 | { | |
594 | const ExtensionModule dmxExtensions[] = { | |
595 | { DMXExtensionInit, DMX_EXTENSION_NAME, NULL }, | |
596 | #ifdef GLXEXT | |
597 | { GlxExtensionInit, "GLX", &glxSupported }, | |
598 | #endif | |
599 | }; | |
600 | int i; | |
601 | ||
602 | for (i = 0; i < ARRAY_SIZE(dmxExtensions); i++) | |
603 | LoadExtension(&dmxExtensions[i], TRUE); | |
604 | } | |
605 | ||
606 | /** This routine is called in Xserver/dix/main.c from \a main(). */ | |
607 | void | |
608 | InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) | |
609 | { | |
610 | int i; | |
611 | static unsigned long dmxGeneration = 0; | |
612 | ||
613 | #ifdef GLXEXT | |
614 | static Bool glxSupported = TRUE; | |
615 | #else | |
616 | const Bool glxSupported = FALSE; | |
617 | #endif | |
618 | ||
619 | if (dmxGeneration != serverGeneration) { | |
620 | int vendrel = VENDOR_RELEASE; | |
621 | int major, minor, year, month, day; | |
622 | ||
623 | dmxGeneration = serverGeneration; | |
624 | ||
625 | major = vendrel / 100000000; | |
626 | vendrel -= major * 100000000; | |
627 | minor = vendrel / 1000000; | |
628 | vendrel -= minor * 1000000; | |
629 | year = vendrel / 10000; | |
630 | vendrel -= year * 10000; | |
631 | month = vendrel / 100; | |
632 | vendrel -= month * 100; | |
633 | day = vendrel; | |
634 | ||
635 | /* Add other epoch tests here */ | |
636 | if (major > 0 && minor > 0) | |
637 | year += 2000; | |
638 | ||
639 | dmxLog(dmxInfo, "Generation: %d\n", dmxGeneration); | |
640 | dmxLog(dmxInfo, "DMX version: %d.%d.%02d%02d%02d (%s)\n", | |
641 | major, minor, year, month, day, VENDOR_STRING); | |
642 | ||
643 | SetVendorRelease(VENDOR_RELEASE); | |
644 | SetVendorString(VENDOR_STRING); | |
645 | ||
646 | if (dmxGeneration == 1) { | |
647 | dmxLog(dmxInfo, "DMX Build OS: %s (%s)\n", OSNAME, OSVENDOR); | |
648 | dmxLog(dmxInfo, "DMX Build Compiler: %s\n", dmxBuildCompiler()); | |
649 | dmxLog(dmxInfo, "DMX Execution OS: %s\n", dmxExecOS()); | |
650 | dmxLog(dmxInfo, "DMX Execution Host: %s\n", dmxExecHost()); | |
651 | } | |
652 | dmxLog(dmxInfo, "MAXSCREENS: %d\n", MAXSCREENS); | |
653 | ||
654 | for (i = 0; i < dmxNumScreens; i++) { | |
655 | if (dmxScreens[i].beDisplay) | |
656 | dmxLog(dmxWarning, "Display \"%s\" still open\n", | |
657 | dmxScreens[i].name); | |
658 | dmxStatFree(dmxScreens[i].stat); | |
659 | dmxScreens[i].stat = NULL; | |
660 | } | |
661 | for (i = 0; i < dmxNumInputs; i++) | |
662 | dmxInputFree(&dmxInputs[i]); | |
663 | free(dmxScreens); | |
664 | free(dmxInputs); | |
665 | dmxScreens = NULL; | |
666 | dmxInputs = NULL; | |
667 | dmxNumScreens = 0; | |
668 | dmxNumInputs = 0; | |
669 | } | |
670 | ||
671 | /* Make sure that the command-line arguments are sane. */ | |
672 | if (dmxAddRemoveScreens && dmxGLXProxy) { | |
673 | /* Currently it is not possible to support GLX and Render | |
674 | * extensions with dynamic screen addition/removal due to the | |
675 | * state that each extension keeps, which cannot be restored. */ | |
676 | dmxLog(dmxWarning, | |
677 | "GLX Proxy and Render extensions do not yet support dynamic\n"); | |
678 | dmxLog(dmxWarning, | |
679 | "screen addition and removal. Please specify -noglxproxy\n"); | |
680 | dmxLog(dmxWarning, | |
681 | "and -norender on the command line or in the configuration\n"); | |
682 | dmxLog(dmxWarning, | |
683 | "file to disable these two extensions if you wish to use\n"); | |
684 | dmxLog(dmxWarning, | |
685 | "the dynamic addition and removal of screens support.\n"); | |
686 | dmxLog(dmxFatal, | |
687 | "Dynamic screen addition/removal error (see above).\n"); | |
688 | } | |
689 | ||
690 | /* ddxProcessArgument has been called at this point, but any data | |
691 | * from the configuration file has not been applied. Do so, and be | |
692 | * sure we have at least one back-end display. */ | |
693 | dmxConfigConfigure(); | |
694 | if (!dmxNumScreens) | |
695 | dmxLog(dmxFatal, "InitOutput: no back-end displays found\n"); | |
696 | if (!dmxNumInputs) | |
697 | dmxLog(dmxInfo, "InitOutput: no inputs found\n"); | |
698 | ||
699 | /* Disable lazy window creation optimization if offscreen | |
700 | * optimization is disabled */ | |
701 | if (!dmxOffScreenOpt && dmxLazyWindowCreation) { | |
702 | dmxLog(dmxInfo, | |
703 | "InitOutput: Disabling lazy window creation optimization\n"); | |
704 | dmxLog(dmxInfo, | |
705 | " since it requires the offscreen optimization\n"); | |
706 | dmxLog(dmxInfo, " to function properly.\n"); | |
707 | dmxLazyWindowCreation = FALSE; | |
708 | } | |
709 | ||
710 | /* Open each display and gather information about it. */ | |
711 | for (i = 0; i < dmxNumScreens; i++) | |
712 | dmxDisplayInit(&dmxScreens[i]); | |
713 | ||
714 | #if PANORAMIX | |
715 | /* Register a Xinerama callback which will run from within | |
716 | * PanoramiXCreateConnectionBlock. We can use the callback to | |
717 | * determine if Xinerama is loaded and to check the visuals | |
718 | * determined by PanoramiXConsolidate. */ | |
719 | XineramaRegisterConnectionBlockCallback(dmxConnectionBlockCallback); | |
720 | #endif | |
721 | ||
722 | /* Since we only have a single screen thus far, we only need to set | |
723 | the pixmap formats to match that screen. FIXME: this isn't true. */ | |
724 | if (!dmxSetPixmapFormats(pScreenInfo, &dmxScreens[0])) | |
725 | return; | |
726 | ||
727 | /* Might want to install a signal handler to allow cleaning up after | |
728 | * unexpected signals. The DIX/OS layer already handles SIGINT and | |
729 | * SIGTERM, so everything is OK for expected signals. --DD | |
730 | * | |
731 | * SIGHUP, SIGINT, and SIGTERM are trapped in os/connection.c | |
732 | * SIGQUIT is another common signal that is sent from the keyboard. | |
733 | * Trap it here, to ensure that the keyboard modifier map and other | |
734 | * state for the input devices are restored. (This makes the | |
735 | * behavior of SIGQUIT somewhat unexpected, since it will be the | |
736 | * same as the behavior of SIGINT. However, leaving the modifier | |
737 | * map of the input devices empty is even more unexpected.) --RF | |
738 | */ | |
739 | OsSignal(SIGQUIT, GiveUp); | |
740 | ||
741 | #ifdef GLXEXT | |
742 | /* Check if GLX extension exists on all back-end servers */ | |
743 | for (i = 0; i < dmxNumScreens; i++) | |
744 | glxSupported &= (dmxScreens[i].glxMajorOpcode > 0); | |
745 | #endif | |
746 | ||
747 | if (serverGeneration == 1) | |
748 | dmxAddExtensions(glxSupported); | |
749 | ||
750 | /* Tell dix layer about the backend displays */ | |
751 | for (i = 0; i < dmxNumScreens; i++) { | |
752 | ||
753 | #ifdef GLXEXT | |
754 | if (glxSupported) { | |
755 | /* | |
756 | * Builds GLX configurations from the list of visuals | |
757 | * supported by the back-end server, and give that | |
758 | * configuration list to the glx layer - so that he will | |
759 | * build the visuals accordingly. | |
760 | */ | |
761 | ||
762 | DMXScreenInfo *dmxScreen = &dmxScreens[i]; | |
763 | __GLXvisualConfig *configs = NULL; | |
764 | dmxGlxVisualPrivate **configprivs = NULL; | |
765 | int nconfigs = 0; | |
766 | int (*oldErrorHandler) (Display *, XErrorEvent *); | |
767 | int i; | |
768 | ||
769 | /* Catch errors if when using an older GLX w/o FBconfigs */ | |
770 | oldErrorHandler = XSetErrorHandler(dmxNOPErrorHandler); | |
771 | ||
772 | /* Get FBConfigs of the back-end server */ | |
773 | dmxScreen->fbconfigs = GetGLXFBConfigs(dmxScreen->beDisplay, | |
774 | dmxScreen->glxMajorOpcode, | |
775 | &dmxScreen->numFBConfigs); | |
776 | ||
777 | XSetErrorHandler(oldErrorHandler); | |
778 | ||
779 | dmxScreen->glxVisuals = | |
780 | GetGLXVisualConfigs(dmxScreen->beDisplay, | |
781 | DefaultScreen(dmxScreen->beDisplay), | |
782 | &dmxScreen->numGlxVisuals); | |
783 | ||
784 | if (dmxScreen->fbconfigs) { | |
785 | configs = | |
786 | GetGLXVisualConfigsFromFBConfigs(dmxScreen->fbconfigs, | |
787 | dmxScreen->numFBConfigs, | |
788 | dmxScreen->beVisuals, | |
789 | dmxScreen->beNumVisuals, | |
790 | dmxScreen->glxVisuals, | |
791 | dmxScreen->numGlxVisuals, | |
792 | &nconfigs); | |
793 | } | |
794 | else { | |
795 | configs = dmxScreen->glxVisuals; | |
796 | nconfigs = dmxScreen->numGlxVisuals; | |
797 | } | |
798 | ||
799 | configprivs = malloc(nconfigs * sizeof(dmxGlxVisualPrivate *)); | |
800 | ||
801 | if (configs != NULL && configprivs != NULL) { | |
802 | ||
803 | /* Initialize our private info for each visual | |
804 | * (currently only x_visual_depth and x_visual_class) | |
805 | */ | |
806 | for (i = 0; i < nconfigs; i++) { | |
807 | ||
808 | configprivs[i] = (dmxGlxVisualPrivate *) | |
809 | malloc(sizeof(dmxGlxVisualPrivate)); | |
810 | configprivs[i]->x_visual_depth = 0; | |
811 | configprivs[i]->x_visual_class = 0; | |
812 | ||
813 | /* Find the visual depth */ | |
814 | if (configs[i].vid > 0) { | |
815 | int j; | |
816 | ||
817 | for (j = 0; j < dmxScreen->beNumVisuals; j++) { | |
818 | if (dmxScreen->beVisuals[j].visualid == | |
819 | configs[i].vid) { | |
820 | configprivs[i]->x_visual_depth = | |
821 | dmxScreen->beVisuals[j].depth; | |
822 | configprivs[i]->x_visual_class = | |
823 | dmxScreen->beVisuals[j].class; | |
824 | break; | |
825 | } | |
826 | } | |
827 | } | |
828 | } | |
829 | ||
830 | XFlush(dmxScreen->beDisplay); | |
831 | } | |
832 | } | |
833 | #endif /* GLXEXT */ | |
834 | ||
835 | AddScreen(dmxScreenInit, argc, argv); | |
836 | } | |
837 | ||
838 | /* Compute origin information. */ | |
839 | dmxInitOrigins(); | |
840 | ||
841 | /* Compute overlap information. */ | |
842 | dmxInitOverlap(); | |
843 | ||
844 | /* Make sure there is a global width/height available */ | |
845 | dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX); | |
846 | ||
847 | /* FIXME: The following is temporarily placed here. When the DMX | |
848 | * extension is available, it will be move there. | |
849 | */ | |
850 | dmxInitFonts(); | |
851 | ||
852 | /* Initialize the render extension */ | |
853 | if (!noRenderExtension) | |
854 | dmxInitRender(); | |
855 | ||
856 | /* Initialized things that need timer hooks */ | |
857 | dmxStatInit(); | |
858 | dmxSyncInit(); /* Calls RegisterBlockAndWakeupHandlers */ | |
859 | } | |
860 | ||
861 | /* RATS: Assuming the fp string (which comes from the command-line argv | |
862 | vector) is NULL-terminated, the buffer is large enough for the | |
863 | strcpy. */ | |
864 | static void | |
865 | dmxSetDefaultFontPath(const char *fp) | |
866 | { | |
867 | if (dmxFontPath) { | |
868 | int fplen = strlen(fp) + 1; | |
869 | int len = strlen(dmxFontPath); | |
870 | ||
871 | dmxFontPath = realloc(dmxFontPath, len + fplen + 1); | |
872 | dmxFontPath[len] = ','; | |
873 | strncpy(&dmxFontPath[len + 1], fp, fplen); | |
874 | } | |
875 | else { | |
876 | dmxFontPath = strdup(fp); | |
877 | } | |
878 | ||
879 | defaultFontPath = dmxFontPath; | |
880 | } | |
881 | ||
882 | /** This function is called in Xserver/os/utils.c from \a AbortServer(). | |
883 | * We must ensure that backend and console state is restored in the | |
884 | * event the server shutdown wasn't clean. */ | |
885 | void | |
886 | AbortDDX(enum ExitCode error) | |
887 | { | |
888 | int i; | |
889 | ||
890 | for (i = 0; i < dmxNumScreens; i++) { | |
891 | DMXScreenInfo *dmxScreen = &dmxScreens[i]; | |
892 | ||
893 | if (dmxScreen->beDisplay) | |
894 | XCloseDisplay(dmxScreen->beDisplay); | |
895 | dmxScreen->beDisplay = NULL; | |
896 | } | |
897 | } | |
898 | ||
899 | #ifdef DDXBEFORERESET | |
900 | void | |
901 | ddxBeforeReset(void) | |
902 | { | |
903 | } | |
904 | #endif | |
905 | ||
906 | /** This function is called in Xserver/dix/main.c from \a main() when | |
907 | * dispatchException & DE_TERMINATE (which is the only way to exit the | |
908 | * main loop without an interruption. */ | |
909 | void | |
910 | ddxGiveUp(enum ExitCode error) | |
911 | { | |
912 | AbortDDX(error); | |
913 | } | |
914 | ||
915 | /** This function is called in Xserver/os/osinit.c from \a OsInit(). */ | |
916 | void | |
917 | OsVendorInit(void) | |
918 | { | |
919 | } | |
920 | ||
921 | /** This function is called in Xserver/os/utils.c from \a FatalError() | |
922 | * and \a VFatalError(). (Note that setting the function pointer \a | |
923 | * OsVendorVErrorFProc will cause \a VErrorF() (which is called by the | |
924 | * two routines mentioned here, as well as by others) to use the | |
925 | * referenced routine instead of \a vfprintf().) */ | |
926 | void | |
927 | OsVendorFatalError(const char *f, va_list args) | |
928 | { | |
929 | } | |
930 | ||
931 | /** Process our command line arguments. */ | |
932 | int | |
933 | ddxProcessArgument(int argc, char *argv[], int i) | |
934 | { | |
935 | int retval = 0; | |
936 | ||
937 | if (!strcmp(argv[i], "-display")) { | |
938 | if (++i < argc) | |
939 | dmxConfigStoreDisplay(argv[i]); | |
940 | retval = 2; | |
941 | } | |
942 | else if (!strcmp(argv[i], "-inputfrom") || !strcmp(argv[i], "-input")) { | |
943 | if (++i < argc) | |
944 | dmxConfigStoreInput(argv[i]); | |
945 | retval = 2; | |
946 | } | |
947 | else if (!strcmp(argv[i], "-xinputfrom") || !strcmp(argv[i], "-xinput")) { | |
948 | if (++i < argc) | |
949 | dmxConfigStoreXInput(argv[i]); | |
950 | retval = 2; | |
951 | } | |
952 | else if (!strcmp(argv[i], "-noshadowfb")) { | |
953 | retval = 1; | |
954 | } | |
955 | else if (!strcmp(argv[i], "-nomulticursor")) { | |
956 | dmxCursorNoMulti(); | |
957 | retval = 1; | |
958 | } | |
959 | else if (!strcmp(argv[i], "-shadowfb")) { | |
960 | retval = 1; | |
961 | } | |
962 | else if (!strcmp(argv[i], "-configfile")) { | |
963 | if (++i < argc) | |
964 | dmxConfigStoreFile(argv[i]); | |
965 | retval = 2; | |
966 | } | |
967 | else if (!strcmp(argv[i], "-config")) { | |
968 | if (++i < argc) | |
969 | dmxConfigStoreConfig(argv[i]); | |
970 | retval = 2; | |
971 | } | |
972 | else if (!strcmp(argv[i], "-fontpath")) { | |
973 | if (++i < argc) | |
974 | dmxSetDefaultFontPath(argv[i]); | |
975 | retval = 2; | |
976 | } | |
977 | else if (!strcmp(argv[i], "-stat")) { | |
978 | if ((i += 2) < argc) | |
979 | dmxStatActivate(argv[i - 1], argv[i]); | |
980 | retval = 3; | |
981 | } | |
982 | else if (!strcmp(argv[i], "-syncbatch")) { | |
983 | if (++i < argc) | |
984 | dmxSyncActivate(argv[i]); | |
985 | retval = 2; | |
986 | } | |
987 | else if (!strcmp(argv[i], "-nooffscreenopt")) { | |
988 | dmxOffScreenOpt = FALSE; | |
989 | retval = 1; | |
990 | } | |
991 | else if (!strcmp(argv[i], "-nosubdivprims")) { | |
992 | dmxSubdividePrimitives = FALSE; | |
993 | retval = 1; | |
994 | } | |
995 | else if (!strcmp(argv[i], "-nowindowopt")) { | |
996 | dmxLazyWindowCreation = FALSE; | |
997 | retval = 1; | |
998 | } | |
999 | else if (!strcmp(argv[i], "-noxkb")) { | |
1000 | dmxUseXKB = FALSE; | |
1001 | retval = 1; | |
1002 | } | |
1003 | else if (!strcmp(argv[i], "-depth")) { | |
1004 | if (++i < argc) | |
1005 | dmxDepth = atoi(argv[i]); | |
1006 | retval = 2; | |
1007 | } | |
1008 | else if (!strcmp(argv[i], "-norender")) { | |
1009 | noRenderExtension = TRUE; | |
1010 | retval = 1; | |
1011 | #ifdef GLXEXT | |
1012 | } | |
1013 | else if (!strcmp(argv[i], "-noglxproxy")) { | |
1014 | dmxGLXProxy = FALSE; | |
1015 | retval = 1; | |
1016 | } | |
1017 | else if (!strcmp(argv[i], "-noglxswapgroup")) { | |
1018 | dmxGLXSwapGroupSupport = FALSE; | |
1019 | retval = 1; | |
1020 | } | |
1021 | else if (!strcmp(argv[i], "-glxsyncswap")) { | |
1022 | dmxGLXSyncSwap = TRUE; | |
1023 | retval = 1; | |
1024 | } | |
1025 | else if (!strcmp(argv[i], "-glxfinishswap")) { | |
1026 | dmxGLXFinishSwap = TRUE; | |
1027 | retval = 1; | |
1028 | #endif | |
1029 | } | |
1030 | else if (!strcmp(argv[i], "-ignorebadfontpaths")) { | |
1031 | dmxIgnoreBadFontPaths = TRUE; | |
1032 | retval = 1; | |
1033 | } | |
1034 | else if (!strcmp(argv[i], "-addremovescreens")) { | |
1035 | dmxAddRemoveScreens = TRUE; | |
1036 | retval = 1; | |
1037 | } | |
1038 | else if (!strcmp(argv[i], "-param")) { | |
1039 | if ((i += 2) < argc) { | |
1040 | if (!strcasecmp(argv[i - 1], "xkbrules")) | |
1041 | dmxConfigSetXkbRules(argv[i]); | |
1042 | else if (!strcasecmp(argv[i - 1], "xkbmodel")) | |
1043 | dmxConfigSetXkbModel(argv[i]); | |
1044 | else if (!strcasecmp(argv[i - 1], "xkblayout")) | |
1045 | dmxConfigSetXkbLayout(argv[i]); | |
1046 | else if (!strcasecmp(argv[i - 1], "xkbvariant")) | |
1047 | dmxConfigSetXkbVariant(argv[i]); | |
1048 | else if (!strcasecmp(argv[i - 1], "xkboptions")) | |
1049 | dmxConfigSetXkbOptions(argv[i]); | |
1050 | else | |
1051 | dmxLog(dmxWarning, | |
1052 | "-param requires: XkbRules, XkbModel, XkbLayout," | |
1053 | " XkbVariant, or XkbOptions\n"); | |
1054 | } | |
1055 | retval = 3; | |
1056 | } | |
1057 | if (!serverGeneration) | |
1058 | dmxConfigSetMaxScreens(); | |
1059 | return retval; | |
1060 | } | |
1061 | ||
1062 | /** Provide succinct usage information for the DMX server. */ | |
1063 | void | |
1064 | ddxUseMsg(void) | |
1065 | { | |
1066 | ErrorF("\n\nDevice Dependent Usage:\n"); | |
1067 | ErrorF("-display string Specify the back-end display(s)\n"); | |
1068 | ErrorF("-input string Specify input source for core device\n"); | |
1069 | ErrorF("-xinput string Specify input source for XInput device\n"); | |
1070 | ErrorF("-shadowfb Enable shadow frame buffer\n"); | |
1071 | ErrorF("-configfile file Read from a configuration file\n"); | |
1072 | ErrorF("-config config Select a specific configuration\n"); | |
1073 | ErrorF("-nomulticursor Turn of multiple cursor support\n"); | |
1074 | ErrorF("-fontpath Sets the default font path\n"); | |
1075 | ErrorF("-stat inter scrns Print out performance statistics\n"); | |
1076 | ErrorF("-syncbatch inter Set interval for XSync batching\n"); | |
1077 | ErrorF("-nooffscreenopt Disable offscreen optimization\n"); | |
1078 | ErrorF("-nosubdivprims Disable primitive subdivision\n"); | |
1079 | ErrorF(" optimization\n"); | |
1080 | ErrorF("-nowindowopt Disable lazy window creation optimization\n"); | |
1081 | ErrorF("-noxkb Disable use of the XKB extension with\n"); | |
1082 | ErrorF(" backend displays (cf. -kb).\n"); | |
1083 | ErrorF("-depth Specify the default root window depth\n"); | |
1084 | ErrorF("-norender Disable RENDER extension support\n"); | |
1085 | #ifdef GLXEXT | |
1086 | ErrorF("-noglxproxy Disable GLX Proxy\n"); | |
1087 | ErrorF("-noglxswapgroup Disable swap group and swap barrier\n"); | |
1088 | ErrorF(" extensions in GLX proxy\n"); | |
1089 | ErrorF("-glxsyncswap Force XSync after swap buffers\n"); | |
1090 | ErrorF("-glxfinishswap Force glFinish after swap buffers\n"); | |
1091 | #endif | |
1092 | ErrorF | |
1093 | ("-ignorebadfontpaths Ignore bad font paths during initialization\n"); | |
1094 | ErrorF("-addremovescreens Enable dynamic screen addition/removal\n"); | |
1095 | ErrorF("-param ... Specify configuration parameters (e.g.,\n"); | |
1096 | ErrorF(" XkbRules, XkbModel, XkbLayout, etc.)\n"); | |
1097 | ErrorF("\n"); | |
1098 | ErrorF(" If the -input string matches a -display string, then input\n" | |
1099 | " is taken from that backend display. (XInput cannot be taken\n" | |
1100 | " from a backend display.) Placing \",console\" after the\n" | |
1101 | " display name will force a console window to be opened on\n" | |
1102 | " that display in addition to the backend input. This is\n" | |
1103 | " useful if the backend window does not cover the whole\n" | |
1104 | " physical display.\n\n"); | |
1105 | ||
1106 | ErrorF(" Otherwise, if the -input or -xinput string specifies another\n" | |
1107 | " X display, then a console window will be created on that\n" | |
1108 | " display. Placing \",windows\" or \",nowindows\" after the\n" | |
1109 | " display name will control the display of window outlines in\n" | |
1110 | " the console.\n\n"); | |
1111 | ||
1112 | ErrorF(" -input or -xinput dummy specifies no input.\n"); | |
1113 | ErrorF(" -input or -xinput local specifies the use of a raw keyboard,\n" | |
1114 | " mouse, or other (extension) device:\n" | |
1115 | " -input local,kbd,ps2 will use a ps2 mouse\n" | |
1116 | " -input local,kbd,ms will use a serial mouse\n" | |
1117 | " -input local,usb-kbd,usb-mou will use USB devices \n" | |
1118 | " -xinput local,usb-oth will use a non-mouse and\n" | |
1119 | " non-keyboard USB device with XInput\n\n"); | |
1120 | ||
1121 | ErrorF(" Special Keys:\n"); | |
1122 | ErrorF(" Ctrl-Alt-g Server grab/ungrab (console only)\n"); | |
1123 | ErrorF(" Ctrl-Alt-f Fine (1-pixel) mouse mode (console only)\n"); | |
1124 | ErrorF(" Ctrl-Alt-q Quit (core devices only)\n"); | |
1125 | ErrorF(" Ctrl-Alt-F* Switch to VC (local only)\n"); | |
1126 | } |