Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xwin / InitOutput.c
CommitLineData
a09e091a
JB
1
2/*
3
4Copyright 1993, 1998 The Open Group
5Copyright (C) Colin Harrison 2005-2008
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included
14in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of The Open Group shall
25not be used in advertising or otherwise to promote the sale, use or
26other dealings in this Software without prior written authorization
27from The Open Group.
28
29*/
30
31#ifdef HAVE_XWIN_CONFIG_H
32#include <xwin-config.h>
33#endif
34#include "win.h"
35#include "winmsg.h"
36#include "winconfig.h"
37#include "winprefs.h"
38#ifdef XWIN_CLIPBOARD
39#include "X11/Xlocale.h"
40#endif
41#ifdef DPMSExtension
42#include "dpmsproc.h"
43#endif
44#ifdef __CYGWIN__
45#include <mntent.h>
46#endif
47#if defined(WIN32)
48#include "xkbsrv.h"
49#endif
50#ifdef RELOCATE_PROJECTROOT
51#pragma push_macro("Status")
52#undef Status
53#define Status wStatus
54#include <shlobj.h>
55#pragma pop_macro("Status")
56typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
57 int nFolder,
58 HANDLE hToken,
59 DWORD dwFlags, LPTSTR pszPath);
60#endif
61
62#include "glx_extinit.h"
63/*
64 * References to external symbols
65 */
66#ifdef XWIN_CLIPBOARD
67extern Bool g_fUnicodeClipboard;
68extern Bool g_fClipboardLaunched;
69extern Bool g_fClipboardStarted;
70extern pthread_t g_ptClipboardProc;
71extern HWND g_hwndClipboard;
72extern Bool g_fClipboard;
73#endif
74
75/*
76 * Function prototypes
77 */
78
79#ifdef XWIN_CLIPBOARD
80static void
81 winClipboardShutdown(void);
82#endif
83
84static Bool
85 winCheckDisplayNumber(void);
86
87void
88 winLogCommandLine(int argc, char *argv[]);
89
90void
91 winLogVersionInfo(void);
92
93Bool
94 winValidateArgs(void);
95
96#ifdef RELOCATE_PROJECTROOT
97const char *winGetBaseDir(void);
98#endif
99
100/*
101 * For the depth 24 pixmap we default to 32 bits per pixel, but
102 * we change this pixmap format later if we detect that the display
103 * is going to be running at 24 bits per pixel.
104 *
105 * FIXME: On second thought, don't DIBs only support 32 bits per pixel?
106 * DIBs are the underlying bitmap used for DirectDraw surfaces, so it
107 * seems that all pixmap formats with depth 24 would be 32 bits per pixel.
108 * Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep
109 * the bits per pixel adjustment and update this comment to reflect the
110 * situation. Harold Hunt - 2002/07/02
111 */
112
113static PixmapFormatRec g_PixmapFormats[] = {
114 {1, 1, BITMAP_SCANLINE_PAD},
115 {4, 8, BITMAP_SCANLINE_PAD},
116 {8, 8, BITMAP_SCANLINE_PAD},
117 {15, 16, BITMAP_SCANLINE_PAD},
118 {16, 16, BITMAP_SCANLINE_PAD},
119 {24, 32, BITMAP_SCANLINE_PAD},
120 {32, 32, BITMAP_SCANLINE_PAD}
121};
122
123const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]);
124
125#ifdef XWIN_CLIPBOARD
126static void
127winClipboardShutdown(void)
128{
129 /* Close down clipboard resources */
130 if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) {
131 /* Synchronously destroy the clipboard window */
132 if (g_hwndClipboard != NULL) {
133 SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
134 /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
135 }
136 else
137 return;
138
139 /* Wait for the clipboard thread to exit */
140 pthread_join(g_ptClipboardProc, NULL);
141
142 g_fClipboardLaunched = FALSE;
143 g_fClipboardStarted = FALSE;
144
145 winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
146 }
147}
148#endif
149
150static const ExtensionModule xwinExtensions[] = {
151#ifdef GLXEXT
152 { GlxExtensionInit, "GLX", &noGlxExtension },
153#endif
154};
155
156/*
157 * XwinExtensionInit
158 * Initialises Xwin-specific extensions.
159 */
160static
161void XwinExtensionInit(void)
162{
163 int i;
164
165#ifdef XWIN_GLX_WINDOWS
166 if (g_fNativeGl) {
167 /* install the native GL provider */
168 glxWinPushNativeProvider();
169 }
170#endif
171
172 for (i = 0; i < ARRAY_SIZE(xwinExtensions); i++)
173 LoadExtension(&xwinExtensions[i], TRUE);
174}
175
176#if defined(DDXBEFORERESET)
177/*
178 * Called right before KillAllClients when the server is going to reset,
179 * allows us to shutdown our seperate threads cleanly.
180 */
181
182void
183ddxBeforeReset(void)
184{
185 winDebug("ddxBeforeReset - Hello\n");
186
187#ifdef XWIN_CLIPBOARD
188 winClipboardShutdown();
189#endif
190}
191#endif
192
193int
194main(int argc, char *argv[], char *envp[])
195{
196 int iReturn;
197
198 /* Create & acquire the termination mutex */
199 iReturn = pthread_mutex_init(&g_pmTerminating, NULL);
200 if (iReturn != 0) {
201 ErrorF("ddxMain - pthread_mutex_init () failed: %d\n", iReturn);
202 }
203
204 iReturn = pthread_mutex_lock(&g_pmTerminating);
205 if (iReturn != 0) {
206 ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn);
207 }
208
209 return dix_main(argc, argv, envp);
210}
211
212/* See Porting Layer Definition - p. 57 */
213void
214ddxGiveUp(enum ExitCode error)
215{
216 int i;
217
218#if CYGDEBUG
219 winDebug("ddxGiveUp\n");
220#endif
221
222 /* Perform per-screen deinitialization */
223 for (i = 0; i < g_iNumScreens; ++i) {
224 /* Delete the tray icon */
225 if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen)
226 winDeleteNotifyIcon(winGetScreenPriv(g_ScreenInfo[i].pScreen));
227 }
228
229#ifdef XWIN_MULTIWINDOW
230 /* Unload libraries for taskbar grouping */
231 winPropertyStoreDestroy();
232
233 /* Notify the worker threads we're exiting */
234 winDeinitMultiWindowWM();
235#endif
236
237#ifdef HAS_DEVWINDOWS
238 /* Close our handle to our message queue */
239 if (g_fdMessageQueue != WIN_FD_INVALID) {
240 /* Close /dev/windows */
241 close(g_fdMessageQueue);
242
243 /* Set the file handle to invalid */
244 g_fdMessageQueue = WIN_FD_INVALID;
245 }
246#endif
247
248 if (!g_fLogInited) {
249 g_pszLogFile = LogInit(g_pszLogFile, NULL);
250 g_fLogInited = TRUE;
251 }
252 LogClose(error);
253
254 /*
255 * At this point we aren't creating any new screens, so
256 * we are guaranteed to not need the DirectDraw functions.
257 */
258 winReleaseDDProcAddresses();
259
260 /* Free concatenated command line */
261 free(g_pszCommandLine);
262 g_pszCommandLine = NULL;
263
264 /* Remove our keyboard hook if it is installed */
265 winRemoveKeyboardHookLL();
266
267 /* Tell Windows that we want to end the app */
268 PostQuitMessage(0);
269
270 {
271 winDebug("ddxGiveUp - Releasing termination mutex\n");
272
273 int iReturn = pthread_mutex_unlock(&g_pmTerminating);
274
275 if (iReturn != 0) {
276 ErrorF("winMsgWindowProc - pthread_mutex_unlock () failed: %d\n",
277 iReturn);
278 }
279 }
280
281 winDebug("ddxGiveUp - End\n");
282}
283
284/* See Porting Layer Definition - p. 57 */
285void
286AbortDDX(enum ExitCode error)
287{
288#if CYGDEBUG
289 winDebug("AbortDDX\n");
290#endif
291 ddxGiveUp(error);
292}
293
294#ifdef __CYGWIN__
295/* hasmntopt is currently not implemented for cygwin */
296static const char *
297winCheckMntOpt(const struct mntent *mnt, const char *opt)
298{
299 const char *s;
300 size_t len;
301
302 if (mnt == NULL)
303 return NULL;
304 if (opt == NULL)
305 return NULL;
306 if (mnt->mnt_opts == NULL)
307 return NULL;
308
309 len = strlen(opt);
310 s = strstr(mnt->mnt_opts, opt);
311 if (s == NULL)
312 return NULL;
313 if ((s == mnt->mnt_opts || *(s - 1) == ',') &&
314 (s[len] == 0 || s[len] == ','))
315 return (char *) opt;
316 return NULL;
317}
318
319static void
320winCheckMount(void)
321{
322 FILE *mnt;
323 struct mntent *ent;
324
325 enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
326 level = none, curlevel;
327 BOOL binary = TRUE;
328
329 mnt = setmntent("/etc/mtab", "r");
330 if (mnt == NULL) {
331 ErrorF("setmntent failed");
332 return;
333 }
334
335 while ((ent = getmntent(mnt)) != NULL) {
336 BOOL sys = (winCheckMntOpt(ent, "user") != NULL);
337 BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
338 BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
339
340 if (sys) {
341 if (root)
342 curlevel = sys_root;
343 else if (tmp)
344 curlevel = sys_tmp;
345 else
346 continue;
347 }
348 else {
349 if (root)
350 curlevel = user_root;
351 else if (tmp)
352 curlevel = user_tmp;
353 else
354 continue;
355 }
356
357 if (curlevel <= level)
358 continue;
359 level = curlevel;
360
361 if ((winCheckMntOpt(ent, "binary") == NULL) &&
362 (winCheckMntOpt(ent, "binmode") == NULL))
363 binary = FALSE;
364 else
365 binary = TRUE;
366 }
367
368 if (endmntent(mnt) != 1) {
369 ErrorF("endmntent failed");
370 return;
371 }
372
373 if (!binary)
374 winMsg(X_WARNING, "/tmp mounted in textmode\n");
375}
376#else
377static void
378winCheckMount(void)
379{
380}
381#endif
382
383#ifdef RELOCATE_PROJECTROOT
384const char *
385winGetBaseDir(void)
386{
387 static BOOL inited = FALSE;
388 static char buffer[MAX_PATH];
389
390 if (!inited) {
391 char *fendptr;
392 HMODULE module = GetModuleHandle(NULL);
393 DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
394
395 if (sizeof(buffer) > 0)
396 buffer[sizeof(buffer) - 1] = 0;
397
398 fendptr = buffer + size;
399 while (fendptr > buffer) {
400 if (*fendptr == '\\' || *fendptr == '/') {
401 *fendptr = 0;
402 break;
403 }
404 fendptr--;
405 }
406 inited = TRUE;
407 }
408 return buffer;
409}
410#endif
411
412static void
413winFixupPaths(void)
414{
415 BOOL changed_fontpath = FALSE;
416 MessageType font_from = X_DEFAULT;
417
418#ifdef RELOCATE_PROJECTROOT
419 const char *basedir = winGetBaseDir();
420 size_t basedirlen = strlen(basedir);
421#endif
422
423#ifdef READ_FONTDIRS
424 {
425 /* Open fontpath configuration file */
426 FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
427
428 if (fontdirs != NULL) {
429 char buffer[256];
430 int needs_sep = TRUE;
431 int comment_block = FALSE;
432
433 /* get default fontpath */
434 char *fontpath = strdup(defaultFontPath);
435 size_t size = strlen(fontpath);
436
437 /* read all lines */
438 while (!feof(fontdirs)) {
439 size_t blen;
440 char *hashchar;
441 char *str;
442 int has_eol = FALSE;
443
444 /* read one line */
445 str = fgets(buffer, sizeof(buffer), fontdirs);
446 if (str == NULL) /* stop on error or eof */
447 break;
448
449 if (strchr(str, '\n') != NULL)
450 has_eol = TRUE;
451
452 /* check if block is continued comment */
453 if (comment_block) {
454 /* ignore all input */
455 *str = 0;
456 blen = 0;
457 if (has_eol) /* check if line ended in this block */
458 comment_block = FALSE;
459 }
460 else {
461 /* find comment character. ignore all trailing input */
462 hashchar = strchr(str, '#');
463 if (hashchar != NULL) {
464 *hashchar = 0;
465 if (!has_eol) /* mark next block as continued comment */
466 comment_block = TRUE;
467 }
468 }
469
470 /* strip whitespaces from beginning */
471 while (*str == ' ' || *str == '\t')
472 str++;
473
474 /* get size, strip whitespaces from end */
475 blen = strlen(str);
476 while (blen > 0 && (str[blen - 1] == ' ' ||
477 str[blen - 1] == '\t' ||
478 str[blen - 1] == '\n')) {
479 str[--blen] = 0;
480 }
481
482 /* still something left to add? */
483 if (blen > 0) {
484 size_t newsize = size + blen;
485
486 /* reserve one character more for ',' */
487 if (needs_sep)
488 newsize++;
489
490 /* allocate memory */
491 if (fontpath == NULL)
492 fontpath = malloc(newsize + 1);
493 else
494 fontpath = realloc(fontpath, newsize + 1);
495
496 /* add separator */
497 if (needs_sep) {
498 fontpath[size] = ',';
499 size++;
500 needs_sep = FALSE;
501 }
502
503 /* mark next line as new entry */
504 if (has_eol)
505 needs_sep = TRUE;
506
507 /* add block */
508 strncpy(fontpath + size, str, blen);
509 fontpath[newsize] = 0;
510 size = newsize;
511 }
512 }
513
514 /* cleanup */
515 fclose(fontdirs);
516 defaultFontPath = strdup(fontpath);
517 free(fontpath);
518 changed_fontpath = TRUE;
519 font_from = X_CONFIG;
520 }
521 }
522#endif /* READ_FONTDIRS */
523#ifdef RELOCATE_PROJECTROOT
524 {
525 const char *libx11dir = PROJECTROOT "/lib/X11";
526 size_t libx11dir_len = strlen(libx11dir);
527 char *newfp = NULL;
528 size_t newfp_len = 0;
529 const char *endptr, *ptr, *oldptr = defaultFontPath;
530
531 endptr = oldptr + strlen(oldptr);
532 ptr = strchr(oldptr, ',');
533 if (ptr == NULL)
534 ptr = endptr;
535 while (ptr != NULL) {
536 size_t oldfp_len = (ptr - oldptr);
537 size_t newsize = oldfp_len;
538 char *newpath = malloc(newsize + 1);
539
540 strncpy(newpath, oldptr, newsize);
541 newpath[newsize] = 0;
542
543 if (strncmp(libx11dir, newpath, libx11dir_len) == 0) {
544 char *compose;
545
546 newsize = newsize - libx11dir_len + basedirlen;
547 compose = malloc(newsize + 1);
548 strcpy(compose, basedir);
549 strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
550 compose[newsize] = 0;
551 free(newpath);
552 newpath = compose;
553 }
554
555 oldfp_len = newfp_len;
556 if (oldfp_len > 0)
557 newfp_len++; /* space for separator */
558 newfp_len += newsize;
559
560 if (newfp == NULL)
561 newfp = malloc(newfp_len + 1);
562 else
563 newfp = realloc(newfp, newfp_len + 1);
564
565 if (oldfp_len > 0) {
566 strcpy(newfp + oldfp_len, ",");
567 oldfp_len++;
568 }
569 strcpy(newfp + oldfp_len, newpath);
570
571 free(newpath);
572
573 if (*ptr == 0) {
574 oldptr = ptr;
575 ptr = NULL;
576 }
577 else {
578 oldptr = ptr + 1;
579 ptr = strchr(oldptr, ',');
580 if (ptr == NULL)
581 ptr = endptr;
582 }
583 }
584
585 defaultFontPath = strdup(newfp);
586 free(newfp);
587 changed_fontpath = TRUE;
588 }
589#endif /* RELOCATE_PROJECTROOT */
590 if (changed_fontpath)
591 winMsg(font_from, "FontPath set to \"%s\"\n", defaultFontPath);
592
593#ifdef RELOCATE_PROJECTROOT
594 if (getenv("XKEYSYMDB") == NULL) {
595 char buffer[MAX_PATH];
596
597 snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB", basedir);
598 buffer[sizeof(buffer) - 1] = 0;
599 putenv(buffer);
600 }
601 if (getenv("XERRORDB") == NULL) {
602 char buffer[MAX_PATH];
603
604 snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB", basedir);
605 buffer[sizeof(buffer) - 1] = 0;
606 putenv(buffer);
607 }
608 if (getenv("XLOCALEDIR") == NULL) {
609 char buffer[MAX_PATH];
610
611 snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale", basedir);
612 buffer[sizeof(buffer) - 1] = 0;
613 putenv(buffer);
614 }
615 if (getenv("HOME") == NULL) {
616 char buffer[MAX_PATH + 5];
617
618 strncpy(buffer, "HOME=", 5);
619
620 /* query appdata directory */
621 if (SHGetFolderPathA
622 (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0,
623 buffer + 5) == 0) {
624 putenv(buffer);
625 }
626 else {
627 winMsg(X_ERROR, "Can not determine HOME directory\n");
628 }
629 }
630 if (!g_fLogFileChanged) {
631 static char buffer[MAX_PATH];
632 DWORD size = GetTempPath(sizeof(buffer), buffer);
633
634 if (size && size < sizeof(buffer)) {
635 snprintf(buffer + size, sizeof(buffer) - size,
636 "XWin.%s.log", display);
637 buffer[sizeof(buffer) - 1] = 0;
638 g_pszLogFile = buffer;
639 winMsg(X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile);
640 }
641 }
642 {
643 static char xkbbasedir[MAX_PATH];
644
645 snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkb", basedir);
646 if (sizeof(xkbbasedir) > 0)
647 xkbbasedir[sizeof(xkbbasedir) - 1] = 0;
648 XkbBaseDirectory = xkbbasedir;
649 XkbBinDirectory = basedir;
650 }
651#endif /* RELOCATE_PROJECTROOT */
652}
653
654void
655OsVendorInit(void)
656{
657 /* Re-initialize global variables on server reset */
658 winInitializeGlobals();
659
660 winFixupPaths();
661
662#ifdef DDXOSVERRORF
663 if (!OsVendorVErrorFProc)
664 OsVendorVErrorFProc = OsVendorVErrorF;
665#endif
666
667 if (!g_fLogInited) {
668 /* keep this order. If LogInit fails it calls Abort which then calls
669 * ddxGiveUp where LogInit is called again and creates an infinite
670 * recursion. If we set g_fLogInited to TRUE before the init we
671 * avoid the second call
672 */
673 g_fLogInited = TRUE;
674 g_pszLogFile = LogInit(g_pszLogFile, NULL);
675 }
676 LogSetParameter(XLOG_FLUSH, 1);
677 LogSetParameter(XLOG_VERBOSITY, g_iLogVerbose);
678 LogSetParameter(XLOG_FILE_VERBOSITY, g_iLogVerbose);
679
680 /* Log the version information */
681 if (serverGeneration == 1)
682 winLogVersionInfo();
683
684 winCheckMount();
685
686 /* Add a default screen if no screens were specified */
687 if (g_iNumScreens == 0) {
688 winDebug("OsVendorInit - Creating default screen 0\n");
689
690 /*
691 * We need to initialize the default screen 0 if no -screen
692 * arguments were processed.
693 *
694 * Add a screen 0 using the defaults set by winInitializeDefaultScreens()
695 * and any additional default screen parameters given
696 */
697 winInitializeScreens(1);
698
699 /* We have to flag this as an explicit screen, even though it isn't */
700 g_ScreenInfo[0].fExplicitScreen = TRUE;
701 }
702
703 /* Work out what the default emulate3buttons setting should be, and apply
704 it if nothing was explicitly specified */
705 {
706 int mouseButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
707 int j;
708
709 for (j = 0; j < g_iNumScreens; j++) {
710 if (g_ScreenInfo[j].iE3BTimeout == WIN_E3B_DEFAULT) {
711 if (mouseButtons < 3) {
712 static Bool reportOnce = TRUE;
713
714 g_ScreenInfo[j].iE3BTimeout = WIN_DEFAULT_E3B_TIME;
715 if (reportOnce) {
716 reportOnce = FALSE;
717 winMsg(X_PROBED,
718 "Windows reports only %d mouse buttons, defaulting to -emulate3buttons\n",
719 mouseButtons);
720 }
721 }
722 else {
723 g_ScreenInfo[j].iE3BTimeout = WIN_E3B_OFF;
724 }
725 }
726 }
727 }
728}
729
730static void
731winUseMsg(void)
732{
733 ErrorF("\n");
734 ErrorF("\n");
735 ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n");
736 ErrorF("\n");
737
738#ifdef XWIN_CLIPBOARD
739 ErrorF("-[no]clipboard\n"
740 "\tEnable [disable] the clipboard integration. Default is enabled.\n");
741#endif
742
743 ErrorF("-clipupdates num_boxes\n"
744 "\tUse a clipping region to constrain shadow update blits to\n"
745 "\tthe updated region when num_boxes, or more, are in the\n"
746 "\tupdated region.\n");
747
748#ifdef XWIN_XF86CONFIG
749 ErrorF("-config\n" "\tSpecify a configuration file.\n");
750
751 ErrorF("-configdir\n" "\tSpecify a configuration directory.\n");
752#endif
753
754 ErrorF("-depth bits_per_pixel\n"
755 "\tSpecify an optional bitdepth to use in fullscreen mode\n"
756 "\twith a DirectDraw engine.\n");
757
758 ErrorF("-[no]emulate3buttons [timeout]\n"
759 "\tEmulate 3 button mouse with an optional timeout in\n"
760 "\tmilliseconds.\n");
761
762#ifdef XWIN_EMULATEPSEUDO
763 ErrorF("-emulatepseudo\n"
764 "\tCreate a depth 8 PseudoColor visual when running in\n"
765 "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
766 "\tdepths. The PseudoColor visual does not have correct colors,\n"
767 "\tand it may crash, but it at least allows you to run your\n"
768 "\tapplication in TrueColor modes.\n");
769#endif
770
771 ErrorF("-engine engine_type_id\n"
772 "\tOverride the server's automatically selected engine type:\n"
773 "\t\t1 - Shadow GDI\n"
774 "\t\t2 - Shadow DirectDraw\n"
775 "\t\t4 - Shadow DirectDraw4 Non-Locking\n"
776#ifdef XWIN_PRIMARYFB
777 "\t\t8 - Primary DirectDraw - obsolete\n"
778#endif
779#ifdef XWIN_NATIVEGDI
780 "\t\t16 - Native GDI - experimental\n"
781#endif
782 );
783
784 ErrorF("-fullscreen\n" "\tRun the server in fullscreen mode.\n");
785
786 ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n");
787
788#ifdef XWIN_MULTIWINDOWEXTWM
789 ErrorF("-internalwm\n" "\tRun the internal window manager.\n");
790#endif
791
792#ifdef XWIN_XF86CONFIG
793 ErrorF("-keyboard\n"
794 "\tSpecify a keyboard device from the configuration file.\n");
795#endif
796
797 ErrorF("-[no]keyhook\n"
798 "\tGrab special Windows keypresses like Alt-Tab or the Menu "
799 "key.\n");
800
801 ErrorF("-lesspointer\n"
802 "\tHide the windows mouse pointer when it is over any\n"
803 "\t" EXECUTABLE_NAME
804 " window. This prevents ghost cursors appearing when\n"
805 "\tthe Windows cursor is drawn on top of the X cursor\n");
806
807 ErrorF("-logfile filename\n" "\tWrite log messages to <filename>.\n");
808
809 ErrorF("-logverbose verbosity\n"
810 "\tSet the verbosity of log messages. [NOTE: Only a few messages\n"
811 "\trespect the settings yet]\n"
812 "\t\t0 - only print fatal error.\n"
813 "\t\t1 - print additional configuration information.\n"
814 "\t\t2 - print additional runtime information [default].\n"
815 "\t\t3 - print debugging and tracing information.\n");
816
817 ErrorF("-[no]multimonitors or -[no]multiplemonitors\n"
818 "\tUse the entire virtual screen if multiple\n"
819 "\tmonitors are present.\n");
820
821#ifdef XWIN_MULTIWINDOW
822 ErrorF("-multiwindow\n" "\tRun the server in multi-window mode.\n");
823#endif
824
825#ifdef XWIN_MULTIWINDOWEXTWM
826 ErrorF("-mwextwm\n"
827 "\tRun the server in multi-window external window manager mode.\n");
828#endif
829
830 ErrorF("-nodecoration\n"
831 "\tDo not draw a window border, title bar, etc. Windowed\n"
832 "\tmode only.\n");
833
834#ifdef XWIN_CLIPBOARD
835 ErrorF("-nounicodeclipboard\n"
836 "\tDo not use Unicode clipboard even if on a NT-based platform.\n");
837#endif
838
839 ErrorF("-refresh rate_in_Hz\n"
840 "\tSpecify an optional refresh rate to use in fullscreen mode\n"
841 "\twith a DirectDraw engine.\n");
842
843 ErrorF("-resize=none|scrollbars|randr"
844 "\tIn windowed mode, [don't] allow resizing of the window. 'scrollbars'\n"
845 "\tmode gives the window scrollbars as needed, 'randr' mode uses the RANR\n"
846 "\textension to resize the X screen. 'randr' is the default.\n");
847
848 ErrorF("-rootless\n" "\tRun the server in rootless mode.\n");
849
850 ErrorF("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n"
851 "\tEnable screen scr_num and optionally specify a width and\n"
852 "\theight and initial position for that screen. Additionally\n"
853 "\ta monitor number can be specified to start the server on,\n"
854 "\tat which point, all coordinates become relative to that\n"
855 "\tmonitor. Examples:\n"
856 "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n"
857 "\t -screen 0 1024x768@3 ; 3rd monitor size 1024x768\n"
858 "\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n");
859
860 ErrorF("-silent-dup-error\n"
861 "\tIf another instance of " EXECUTABLE_NAME
862 " with the same display number is running\n"
863 "\texit silently and don't display any error message.\n");
864
865 ErrorF("-swcursor\n"
866 "\tDisable the usage of the Windows cursor and use the X11 software\n"
867 "\tcursor instead.\n");
868
869 ErrorF("-[no]trayicon\n"
870 "\tDo not create a tray icon. Default is to create one\n"
871 "\ticon per screen. You can globally disable tray icons with\n"
872 "\t-notrayicon, then enable it for specific screens with\n"
873 "\t-trayicon for those screens.\n");
874
875 ErrorF("-[no]unixkill\n" "\tCtrl+Alt+Backspace exits the X Server.\n");
876
877#ifdef XWIN_GLX_WINDOWS
878 ErrorF("-[no]wgl\n"
879 "\tEnable the GLX extension to use the native Windows WGL interface for hardware-accelerated OpenGL\n");
880#endif
881
882 ErrorF("-[no]winkill\n" "\tAlt+F4 exits the X Server.\n");
883
884 ErrorF("-xkblayout XKBLayout\n"
885 "\tEquivalent to XKBLayout in XF86Config files.\n"
886 "\tFor example: -xkblayout de\n");
887
888 ErrorF("-xkbmodel XKBModel\n"
889 "\tEquivalent to XKBModel in XF86Config files.\n");
890
891 ErrorF("-xkboptions XKBOptions\n"
892 "\tEquivalent to XKBOptions in XF86Config files.\n");
893
894 ErrorF("-xkbrules XKBRules\n"
895 "\tEquivalent to XKBRules in XF86Config files.\n");
896
897 ErrorF("-xkbvariant XKBVariant\n"
898 "\tEquivalent to XKBVariant in XF86Config files.\n"
899 "\tFor example: -xkbvariant nodeadkeys\n");
900}
901
902/* See Porting Layer Definition - p. 57 */
903void
904ddxUseMsg(void)
905{
906 /* Set a flag so that FatalError won't give duplicate warning message */
907 g_fSilentFatalError = TRUE;
908
909 winUseMsg();
910
911 /* Log file will not be opened for UseMsg unless we open it now */
912 if (!g_fLogInited) {
913 g_pszLogFile = LogInit(g_pszLogFile, NULL);
914 g_fLogInited = TRUE;
915 }
916 LogClose(EXIT_NO_ERROR);
917
918 /* Notify user where UseMsg text can be found. */
919 if (!g_fNoHelpMessageBox)
920 winMessageBoxF("The " PROJECT_NAME " help text has been printed to "
921 "%s.\n"
922 "Please open %s to read the help text.\n",
923 MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile);
924}
925
926/* See Porting Layer Definition - p. 20 */
927/*
928 * Do any global initialization, then initialize each screen.
929 *
930 * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv
931 */
932
933void
934InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
935{
936 int i;
937
938 if (serverGeneration == 1)
939 XwinExtensionInit();
940
941 /* Log the command line */
942 winLogCommandLine(argc, argv);
943
944#if CYGDEBUG
945 winDebug("InitOutput\n");
946#endif
947
948 /* Validate command-line arguments */
949 if (serverGeneration == 1 && !winValidateArgs()) {
950 FatalError("InitOutput - Invalid command-line arguments found. "
951 "Exiting.\n");
952 }
953
954 /* Check for duplicate invocation on same display number. */
955 if (serverGeneration == 1 && !winCheckDisplayNumber()) {
956 if (g_fSilentDupError)
957 g_fSilentFatalError = TRUE;
958 FatalError("InitOutput - Duplicate invocation on display "
959 "number: %s. Exiting.\n", display);
960 }
961
962#ifdef XWIN_XF86CONFIG
963 /* Try to read the xorg.conf-style configuration file */
964 if (!winReadConfigfile())
965 winErrorFVerb(1, "InitOutput - Error reading config file\n");
966#else
967 winMsg(X_INFO, "xorg.conf is not supported\n");
968 winMsg(X_INFO, "See http://x.cygwin.com/docs/faq/cygwin-x-faq.html "
969 "for more information\n");
970 winConfigFiles();
971#endif
972
973 /* Load preferences from XWinrc file */
974 LoadPreferences();
975
976 /* Setup global screen info parameters */
977 pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
978 pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
979 pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
980 pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
981 pScreenInfo->numPixmapFormats = NUMFORMATS;
982
983 /* Describe how we want common pixmap formats padded */
984 for (i = 0; i < NUMFORMATS; i++) {
985 pScreenInfo->formats[i] = g_PixmapFormats[i];
986 }
987
988 /* Load pointers to DirectDraw functions */
989 winGetDDProcAddresses();
990
991 /* Detect supported engines */
992 winDetectSupportedEngines();
993#ifdef XWIN_MULTIWINDOW
994 /* Load libraries for taskbar grouping */
995 winPropertyStoreInit();
996#endif
997
998 /* Store the instance handle */
999 g_hInstance = GetModuleHandle(NULL);
1000
1001 /* Create the messaging window */
1002 if (serverGeneration == 1)
1003 winCreateMsgWindowThread();
1004
1005 /* Initialize each screen */
1006 for (i = 0; i < g_iNumScreens; ++i) {
1007 /* Initialize the screen */
1008 if (-1 == AddScreen(winScreenInit, argc, argv)) {
1009 FatalError("InitOutput - Couldn't add screen %d", i);
1010 }
1011 }
1012
1013#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
1014
1015 /* Generate a cookie used by internal clients for authorization */
1016 if (g_fXdmcpEnabled || g_fAuthEnabled)
1017 winGenerateAuthorization();
1018
1019 /* Perform some one time initialization */
1020 if (1 == serverGeneration) {
1021 /*
1022 * setlocale applies to all threads in the current process.
1023 * Apply locale specified in LANG environment variable.
1024 */
1025 setlocale(LC_ALL, "");
1026 }
1027#endif
1028
1029#if CYGDEBUG || YES
1030 winDebug("InitOutput - Returning.\n");
1031#endif
1032}
1033
1034/*
1035 * winCheckDisplayNumber - Check if another instance of Cygwin/X is
1036 * already running on the same display number. If no one exists,
1037 * make a mutex to prevent new instances from running on the same display.
1038 *
1039 * return FALSE if the display number is already used.
1040 */
1041
1042static Bool
1043winCheckDisplayNumber(void)
1044{
1045 int nDisp;
1046 HANDLE mutex;
1047 char name[MAX_PATH];
1048 char *pszPrefix = '\0';
1049 OSVERSIONINFO osvi = { 0 };
1050
1051 /* Check display range */
1052 nDisp = atoi(display);
1053 if (nDisp < 0 || nDisp > 65535) {
1054 ErrorF("winCheckDisplayNumber - Bad display number: %d\n", nDisp);
1055 return FALSE;
1056 }
1057
1058 /* Set first character of mutex name to null */
1059 name[0] = '\0';
1060
1061 /* Get operating system version information */
1062 osvi.dwOSVersionInfoSize = sizeof(osvi);
1063 GetVersionEx(&osvi);
1064
1065 /* Want a mutex shared among all terminals on NT > 4.0 */
1066 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5) {
1067 pszPrefix = "Global\\";
1068 }
1069
1070 /* Setup Cygwin/X specific part of name */
1071 snprintf(name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp);
1072
1073 /* Windows automatically releases the mutex when this process exits */
1074 mutex = CreateMutex(NULL, FALSE, name);
1075 if (!mutex) {
1076 LPVOID lpMsgBuf;
1077
1078 /* Display a fancy error message */
1079 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1080 FORMAT_MESSAGE_FROM_SYSTEM |
1081 FORMAT_MESSAGE_IGNORE_INSERTS,
1082 NULL,
1083 GetLastError(),
1084 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1085 (LPTSTR) &lpMsgBuf, 0, NULL);
1086 ErrorF("winCheckDisplayNumber - CreateMutex failed: %s\n",
1087 (LPSTR) lpMsgBuf);
1088 LocalFree(lpMsgBuf);
1089
1090 return FALSE;
1091 }
1092 if (GetLastError() == ERROR_ALREADY_EXISTS) {
1093 ErrorF("winCheckDisplayNumber - "
1094 PROJECT_NAME " is already running on display %d\n", nDisp);
1095 return FALSE;
1096 }
1097
1098 return TRUE;
1099}