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