InitOutput.c revision 1b5d61b8
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#include "X11/Xlocale.h"
39#ifdef DPMSExtension
40#include "dpmsproc.h"
41#endif
42#ifdef __CYGWIN__
43#include <mntent.h>
44#endif
45#if defined(WIN32)
46#include "xkbsrv.h"
47#endif
48#ifdef RELOCATE_PROJECTROOT
49#pragma push_macro("Status")
50#undef Status
51#define Status wStatus
52#include <shlobj.h>
53#pragma pop_macro("Status")
54typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
55                                              int nFolder,
56                                              HANDLE hToken,
57                                              DWORD dwFlags, LPTSTR pszPath);
58#endif
59
60#include "winmonitors.h"
61#include "nonsdk_extinit.h"
62#include "pseudoramiX/pseudoramiX.h"
63
64#include "glx_extinit.h"
65#ifdef XWIN_GLX_WINDOWS
66#include "glx/glwindows.h"
67#include "dri/windowsdri.h"
68#endif
69
70/*
71 * References to external symbols
72 */
73
74/*
75 * Function prototypes
76 */
77
78void
79 winLogCommandLine(int argc, char *argv[]);
80
81void
82 winLogVersionInfo(void);
83
84Bool
85 winValidateArgs(void);
86
87#ifdef RELOCATE_PROJECTROOT
88const 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
104static 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
114static 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 */
126static
127void 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 seperate threads cleanly.
143 */
144
145void
146ddxBeforeReset(void)
147{
148    winDebug("ddxBeforeReset - Hello\n");
149
150    winClipboardShutdown();
151}
152#endif
153
154int
155main(int argc, char *argv[], char *envp[])
156{
157    int iReturn;
158
159    /* Create & acquire the termination mutex */
160    iReturn = pthread_mutex_init(&g_pmTerminating, NULL);
161    if (iReturn != 0) {
162        ErrorF("ddxMain - pthread_mutex_init () failed: %d\n", iReturn);
163    }
164
165    iReturn = pthread_mutex_lock(&g_pmTerminating);
166    if (iReturn != 0) {
167        ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn);
168    }
169
170    return dix_main(argc, argv, envp);
171}
172
173/* See Porting Layer Definition - p. 57 */
174void
175ddxGiveUp(enum ExitCode error)
176{
177    int i;
178
179#if CYGDEBUG
180    winDebug("ddxGiveUp\n");
181#endif
182
183    /* Perform per-screen deinitialization */
184    for (i = 0; i < g_iNumScreens; ++i) {
185        /* Delete the tray icon */
186        if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen)
187            winDeleteNotifyIcon(winGetScreenPriv(g_ScreenInfo[i].pScreen));
188    }
189
190    /* Unload libraries for taskbar grouping */
191    winPropertyStoreDestroy();
192
193    /* Notify the worker threads we're exiting */
194    winDeinitMultiWindowWM();
195
196#ifdef HAS_DEVWINDOWS
197    /* Close our handle to our message queue */
198    if (g_fdMessageQueue != WIN_FD_INVALID) {
199        /* Close /dev/windows */
200        close(g_fdMessageQueue);
201
202        /* Set the file handle to invalid */
203        g_fdMessageQueue = WIN_FD_INVALID;
204    }
205#endif
206
207    if (!g_fLogInited) {
208        g_pszLogFile = LogInit(g_pszLogFile, ".old");
209        g_fLogInited = TRUE;
210    }
211    LogClose(error);
212
213    /*
214     * At this point we aren't creating any new screens, so
215     * we are guaranteed to not need the DirectDraw functions.
216     */
217    winReleaseDDProcAddresses();
218
219    /* Free concatenated command line */
220    free(g_pszCommandLine);
221    g_pszCommandLine = NULL;
222
223    /* Remove our keyboard hook if it is installed */
224    winRemoveKeyboardHookLL();
225
226    /* Tell Windows that we want to end the app */
227    PostQuitMessage(0);
228
229    {
230        int iReturn = pthread_mutex_unlock(&g_pmTerminating);
231
232        winDebug("ddxGiveUp - Releasing termination mutex\n");
233
234        if (iReturn != 0) {
235            ErrorF("winMsgWindowProc - pthread_mutex_unlock () failed: %d\n",
236                   iReturn);
237        }
238    }
239
240    winDebug("ddxGiveUp - End\n");
241}
242
243/* See Porting Layer Definition - p. 57 */
244void
245AbortDDX(enum ExitCode error)
246{
247#if CYGDEBUG
248    winDebug("AbortDDX\n");
249#endif
250    ddxGiveUp(error);
251}
252
253#ifdef __CYGWIN__
254/* hasmntopt is currently not implemented for cygwin */
255static const char *
256winCheckMntOpt(const struct mntent *mnt, const char *opt)
257{
258    const char *s;
259    size_t len;
260
261    if (mnt == NULL)
262        return NULL;
263    if (opt == NULL)
264        return NULL;
265    if (mnt->mnt_opts == NULL)
266        return NULL;
267
268    len = strlen(opt);
269    s = strstr(mnt->mnt_opts, opt);
270    if (s == NULL)
271        return NULL;
272    if ((s == mnt->mnt_opts || *(s - 1) == ',') &&
273        (s[len] == 0 || s[len] == ','))
274        return (char *) opt;
275    return NULL;
276}
277
278static void
279winCheckMount(void)
280{
281    FILE *mnt;
282    struct mntent *ent;
283
284    enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
285        level = none, curlevel;
286    BOOL binary = TRUE;
287
288    mnt = setmntent("/etc/mtab", "r");
289    if (mnt == NULL) {
290        ErrorF("setmntent failed");
291        return;
292    }
293
294    while ((ent = getmntent(mnt)) != NULL) {
295        BOOL sys = (winCheckMntOpt(ent, "user") != NULL);
296        BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
297        BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
298
299        if (sys) {
300            if (root)
301                curlevel = sys_root;
302            else if (tmp)
303                curlevel = sys_tmp;
304            else
305                continue;
306        }
307        else {
308            if (root)
309                curlevel = user_root;
310            else if (tmp)
311                curlevel = user_tmp;
312            else
313                continue;
314        }
315
316        if (curlevel <= level)
317            continue;
318        level = curlevel;
319
320        if ((winCheckMntOpt(ent, "binary") == NULL) &&
321            (winCheckMntOpt(ent, "binmode") == NULL))
322            binary = FALSE;
323        else
324            binary = TRUE;
325    }
326
327    if (endmntent(mnt) != 1) {
328        ErrorF("endmntent failed");
329        return;
330    }
331
332    if (!binary)
333        winMsg(X_WARNING, "/tmp mounted in textmode\n");
334}
335#else
336static void
337winCheckMount(void)
338{
339}
340#endif
341
342#ifdef RELOCATE_PROJECTROOT
343const char *
344winGetBaseDir(void)
345{
346    static BOOL inited = FALSE;
347    static char buffer[MAX_PATH];
348
349    if (!inited) {
350        char *fendptr;
351        HMODULE module = GetModuleHandle(NULL);
352        DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
353
354        if (sizeof(buffer) > 0)
355            buffer[sizeof(buffer) - 1] = 0;
356
357        fendptr = buffer + size;
358        while (fendptr > buffer) {
359            if (*fendptr == '\\' || *fendptr == '/') {
360                *fendptr = 0;
361                break;
362            }
363            fendptr--;
364        }
365        inited = TRUE;
366    }
367    return buffer;
368}
369#endif
370
371static void
372winFixupPaths(void)
373{
374    BOOL changed_fontpath = FALSE;
375    MessageType font_from = X_DEFAULT;
376
377#ifdef RELOCATE_PROJECTROOT
378    const char *basedir = winGetBaseDir();
379    size_t basedirlen = strlen(basedir);
380#endif
381
382#ifdef READ_FONTDIRS
383    {
384        /* Open fontpath configuration file */
385        FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
386
387        if (fontdirs != NULL) {
388            char buffer[256];
389            int needs_sep = TRUE;
390            int comment_block = FALSE;
391
392            /* get default fontpath */
393            char *fontpath = strdup(defaultFontPath);
394            size_t size = strlen(fontpath);
395
396            /* read all lines */
397            while (!feof(fontdirs)) {
398                size_t blen;
399                char *hashchar;
400                char *str;
401                int has_eol = FALSE;
402
403                /* read one line */
404                str = fgets(buffer, sizeof(buffer), fontdirs);
405                if (str == NULL)        /* stop on error or eof */
406                    break;
407
408                if (strchr(str, '\n') != NULL)
409                    has_eol = TRUE;
410
411                /* check if block is continued comment */
412                if (comment_block) {
413                    /* ignore all input */
414                    *str = 0;
415                    blen = 0;
416                    if (has_eol)        /* check if line ended in this block */
417                        comment_block = FALSE;
418                }
419                else {
420                    /* find comment character. ignore all trailing input */
421                    hashchar = strchr(str, '#');
422                    if (hashchar != NULL) {
423                        *hashchar = 0;
424                        if (!has_eol)   /* mark next block as continued comment */
425                            comment_block = TRUE;
426                    }
427                }
428
429                /* strip whitespaces from beginning */
430                while (*str == ' ' || *str == '\t')
431                    str++;
432
433                /* get size, strip whitespaces from end */
434                blen = strlen(str);
435                while (blen > 0 && (str[blen - 1] == ' ' ||
436                                    str[blen - 1] == '\t' ||
437                                    str[blen - 1] == '\n')) {
438                    str[--blen] = 0;
439                }
440
441                /* still something left to add? */
442                if (blen > 0) {
443                    size_t newsize = size + blen;
444
445                    /* reserve one character more for ',' */
446                    if (needs_sep)
447                        newsize++;
448
449                    /* allocate memory */
450                    if (fontpath == NULL)
451                        fontpath = malloc(newsize + 1);
452                    else
453                        fontpath = realloc(fontpath, newsize + 1);
454
455                    /* add separator */
456                    if (needs_sep) {
457                        fontpath[size] = ',';
458                        size++;
459                        needs_sep = FALSE;
460                    }
461
462                    /* mark next line as new entry */
463                    if (has_eol)
464                        needs_sep = TRUE;
465
466                    /* add block */
467                    strncpy(fontpath + size, str, blen);
468                    fontpath[newsize] = 0;
469                    size = newsize;
470                }
471            }
472
473            /* cleanup */
474            fclose(fontdirs);
475            defaultFontPath = strdup(fontpath);
476            free(fontpath);
477            changed_fontpath = TRUE;
478            font_from = X_CONFIG;
479        }
480    }
481#endif                          /* READ_FONTDIRS */
482#ifdef RELOCATE_PROJECTROOT
483    {
484        const char *libx11dir = PROJECTROOT "/lib/X11";
485        size_t libx11dir_len = strlen(libx11dir);
486        char *newfp = NULL;
487        size_t newfp_len = 0;
488        const char *endptr, *ptr, *oldptr = defaultFontPath;
489
490        endptr = oldptr + strlen(oldptr);
491        ptr = strchr(oldptr, ',');
492        if (ptr == NULL)
493            ptr = endptr;
494        while (ptr != NULL) {
495            size_t oldfp_len = (ptr - oldptr);
496            size_t newsize = oldfp_len;
497            char *newpath = malloc(newsize + 1);
498
499            strncpy(newpath, oldptr, newsize);
500            newpath[newsize] = 0;
501
502            if (strncmp(libx11dir, newpath, libx11dir_len) == 0) {
503                char *compose;
504
505                newsize = newsize - libx11dir_len + basedirlen;
506                compose = malloc(newsize + 1);
507                strcpy(compose, basedir);
508                strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
509                compose[newsize] = 0;
510                free(newpath);
511                newpath = compose;
512            }
513
514            oldfp_len = newfp_len;
515            if (oldfp_len > 0)
516                newfp_len++;    /* space for separator */
517            newfp_len += newsize;
518
519            if (newfp == NULL)
520                newfp = malloc(newfp_len + 1);
521            else
522                newfp = realloc(newfp, newfp_len + 1);
523
524            if (oldfp_len > 0) {
525                strcpy(newfp + oldfp_len, ",");
526                oldfp_len++;
527            }
528            strcpy(newfp + oldfp_len, newpath);
529
530            free(newpath);
531
532            if (*ptr == 0) {
533                oldptr = ptr;
534                ptr = NULL;
535            }
536            else {
537                oldptr = ptr + 1;
538                ptr = strchr(oldptr, ',');
539                if (ptr == NULL)
540                    ptr = endptr;
541            }
542        }
543
544        defaultFontPath = strdup(newfp);
545        free(newfp);
546        changed_fontpath = TRUE;
547    }
548#endif                          /* RELOCATE_PROJECTROOT */
549    if (changed_fontpath)
550        winMsg(font_from, "FontPath set to \"%s\"\n", defaultFontPath);
551
552#ifdef RELOCATE_PROJECTROOT
553    if (getenv("XKEYSYMDB") == NULL) {
554        char buffer[MAX_PATH];
555
556        snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB", basedir);
557        buffer[sizeof(buffer) - 1] = 0;
558        putenv(buffer);
559    }
560    if (getenv("XERRORDB") == NULL) {
561        char buffer[MAX_PATH];
562
563        snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB", basedir);
564        buffer[sizeof(buffer) - 1] = 0;
565        putenv(buffer);
566    }
567    if (getenv("XLOCALEDIR") == NULL) {
568        char buffer[MAX_PATH];
569
570        snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale", basedir);
571        buffer[sizeof(buffer) - 1] = 0;
572        putenv(buffer);
573    }
574    if (getenv("HOME") == NULL) {
575        char buffer[MAX_PATH + 5];
576
577        strncpy(buffer, "HOME=", 5);
578
579        /* query appdata directory */
580        if (SHGetFolderPathA
581            (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0,
582             buffer + 5) == 0) {
583            putenv(buffer);
584        }
585        else {
586            winMsg(X_ERROR, "Can not determine HOME directory\n");
587        }
588    }
589    if (!g_fLogFileChanged) {
590        static char buffer[MAX_PATH];
591        DWORD size = GetTempPath(sizeof(buffer), buffer);
592
593        if (size && size < sizeof(buffer)) {
594            snprintf(buffer + size, sizeof(buffer) - size,
595                     "XWin.%s.log", display);
596            buffer[sizeof(buffer) - 1] = 0;
597            g_pszLogFile = buffer;
598            winMsg(X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile);
599        }
600    }
601    {
602        static char xkbbasedir[MAX_PATH];
603
604        snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkb", basedir);
605        if (sizeof(xkbbasedir) > 0)
606            xkbbasedir[sizeof(xkbbasedir) - 1] = 0;
607        XkbBaseDirectory = xkbbasedir;
608        XkbBinDirectory = basedir;
609    }
610#endif                          /* RELOCATE_PROJECTROOT */
611}
612
613void
614OsVendorInit(void)
615{
616    /* Re-initialize global variables on server reset */
617    winInitializeGlobals();
618
619    winFixupPaths();
620
621#ifdef DDXOSVERRORF
622    if (!OsVendorVErrorFProc)
623        OsVendorVErrorFProc = OsVendorVErrorF;
624#endif
625
626    if (!g_fLogInited) {
627        /* keep this order. If LogInit fails it calls Abort which then calls
628         * ddxGiveUp where LogInit is called again and creates an infinite
629         * recursion. If we set g_fLogInited to TRUE before the init we
630         * avoid the second call
631         */
632        g_fLogInited = TRUE;
633        g_pszLogFile = LogInit(g_pszLogFile, ".old");
634
635    }
636    LogSetParameter(XLOG_FLUSH, 1);
637    LogSetParameter(XLOG_VERBOSITY, g_iLogVerbose);
638    LogSetParameter(XLOG_FILE_VERBOSITY, g_iLogVerbose);
639
640    /* Log the version information */
641    if (serverGeneration == 1)
642        winLogVersionInfo();
643
644    winCheckMount();
645
646    /* Add a default screen if no screens were specified */
647    if (g_iNumScreens == 0) {
648        winDebug("OsVendorInit - Creating default screen 0\n");
649
650        /*
651         * We need to initialize the default screen 0 if no -screen
652         * arguments were processed.
653         *
654         * Add a screen 0 using the defaults set by winInitializeDefaultScreens()
655         * and any additional default screen parameters given
656         */
657        winInitializeScreens(1);
658
659        /* We have to flag this as an explicit screen, even though it isn't */
660        g_ScreenInfo[0].fExplicitScreen = TRUE;
661    }
662
663    /* Work out what the default emulate3buttons setting should be, and apply
664       it if nothing was explicitly specified */
665    {
666        int mouseButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
667        int j;
668
669        for (j = 0; j < g_iNumScreens; j++) {
670            if (g_ScreenInfo[j].iE3BTimeout == WIN_E3B_DEFAULT) {
671                if (mouseButtons < 3) {
672                    static Bool reportOnce = TRUE;
673
674                    g_ScreenInfo[j].iE3BTimeout = WIN_DEFAULT_E3B_TIME;
675                    if (reportOnce) {
676                        reportOnce = FALSE;
677                        winMsg(X_PROBED,
678                               "Windows reports only %d mouse buttons, defaulting to -emulate3buttons\n",
679                               mouseButtons);
680                    }
681                }
682                else {
683                    g_ScreenInfo[j].iE3BTimeout = WIN_E3B_OFF;
684                }
685            }
686        }
687    }
688
689    /* Work out what the default resize setting should be, and apply it if it
690     was not explicitly specified */
691    {
692        int j;
693        for (j = 0; j < g_iNumScreens; j++) {
694            if (g_ScreenInfo[j].iResizeMode == resizeDefault) {
695                if (g_ScreenInfo[j].fFullScreen)
696                    g_ScreenInfo[j].iResizeMode = resizeNotAllowed;
697                else
698                    g_ScreenInfo[j].iResizeMode = resizeWithRandr;
699                }
700        }
701    }
702}
703
704static void
705winUseMsg(void)
706{
707    ErrorF("\n");
708    ErrorF("\n");
709    ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n");
710    ErrorF("\n");
711
712    ErrorF("-[no]clipboard\n"
713           "\tEnable [disable] the clipboard integration. Default is enabled.\n");
714
715    ErrorF("-clipupdates num_boxes\n"
716           "\tUse a clipping region to constrain shadow update blits to\n"
717           "\tthe updated region when num_boxes, or more, are in the\n"
718           "\tupdated region.\n");
719
720#ifdef XWIN_XF86CONFIG
721    ErrorF("-config\n" "\tSpecify a configuration file.\n");
722
723    ErrorF("-configdir\n" "\tSpecify a configuration directory.\n");
724#endif
725
726    ErrorF("-depth bits_per_pixel\n"
727           "\tSpecify an optional bitdepth to use in fullscreen mode\n"
728           "\twith a DirectDraw engine.\n");
729
730    ErrorF("-[no]emulate3buttons [timeout]\n"
731           "\tEmulate 3 button mouse with an optional timeout in\n"
732           "\tmilliseconds.\n");
733
734#ifdef XWIN_EMULATEPSEUDO
735    ErrorF("-emulatepseudo\n"
736           "\tCreate a depth 8 PseudoColor visual when running in\n"
737           "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
738           "\tdepths.  The PseudoColor visual does not have correct colors,\n"
739           "\tand it may crash, but it at least allows you to run your\n"
740           "\tapplication in TrueColor modes.\n");
741#endif
742
743    ErrorF("-engine engine_type_id\n"
744           "\tOverride the server's automatically selected engine type:\n"
745           "\t\t1 - Shadow GDI\n"
746           "\t\t4 - Shadow DirectDraw4 Non-Locking\n"
747        );
748
749    ErrorF("-fullscreen\n" "\tRun the server in fullscreen mode.\n");
750
751    ErrorF("-[no]hostintitle\n"
752           "\tIn multiwindow mode, add remote host names to window titles.\n");
753
754    ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n");
755
756#ifdef XWIN_XF86CONFIG
757    ErrorF("-keyboard\n"
758           "\tSpecify a keyboard device from the configuration file.\n");
759#endif
760
761    ErrorF("-[no]keyhook\n"
762           "\tGrab special Windows keypresses like Alt-Tab or the Menu "
763           "key.\n");
764
765    ErrorF("-lesspointer\n"
766           "\tHide the windows mouse pointer when it is over any\n"
767           "\t" EXECUTABLE_NAME
768           " window.  This prevents ghost cursors appearing when\n"
769           "\tthe Windows cursor is drawn on top of the X cursor\n");
770
771    ErrorF("-logfile filename\n" "\tWrite log messages to <filename>.\n");
772
773    ErrorF("-logverbose verbosity\n"
774           "\tSet the verbosity of log messages. [NOTE: Only a few messages\n"
775           "\trespect the settings yet]\n"
776           "\t\t0 - only print fatal error.\n"
777           "\t\t1 - print additional configuration information.\n"
778           "\t\t2 - print additional runtime information [default].\n"
779           "\t\t3 - print debugging and tracing information.\n");
780
781    ErrorF("-[no]multimonitors or -[no]multiplemonitors\n"
782           "\tUse the entire virtual screen if multiple\n"
783           "\tmonitors are present.\n");
784
785    ErrorF("-multiwindow\n" "\tRun the server in multi-window mode.\n");
786
787#ifdef XWIN_MULTIWINDOWEXTWM
788    ErrorF("-mwextwm\n"
789           "\tRun the server in multi-window external window manager mode.\n");
790#endif
791
792    ErrorF("-nodecoration\n"
793           "\tDo not draw a window border, title bar, etc.  Windowed\n"
794           "\tmode only.\n");
795
796    ErrorF("-nounicodeclipboard\n"
797           "\tDo not use Unicode clipboard even if on a NT-based platform.\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"
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 */
862void
863ddxUseMsg(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
892void
893InitOutput(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              QueryMonitor(iMonitor, &data);
984              if (data.bMonitorSpecifiedExists)
985                {
986                  MONITORINFO mi;
987                  mi.cbSize = sizeof(MONITORINFO);
988
989                  if (GetMonitorInfo(data.monitorHandle, &mi))
990                    {
991                      /* pass == 1 XOR primary monitor flags is set */
992                      if ((!(pass == 1)) != (!(mi.dwFlags & MONITORINFOF_PRIMARY)))
993                        {
994                          /*
995                            Note the screen origin in a normalized coordinate space where (0,0) is at the top left
996                            of the native virtual desktop area
997                          */
998                          data.monitorOffsetX = data.monitorOffsetX - GetSystemMetrics(SM_XVIRTUALSCREEN);
999                          data.monitorOffsetY = data.monitorOffsetY - GetSystemMetrics(SM_YVIRTUALSCREEN);
1000
1001                          winDebug ("InitOutput - screen %d added at virtual desktop coordinate (%d,%d) (pseudoramiX) \n",
1002                                    iMonitor-1, data.monitorOffsetX, data.monitorOffsetY);
1003
1004                          PseudoramiXAddScreen(data.monitorOffsetX, data.monitorOffsetY,
1005                                               data.monitorWidth, data.monitorHeight);
1006                        }
1007                    }
1008                }
1009              else
1010                break;
1011            }
1012        }
1013    }
1014
1015    xorgGlxCreateVendor();
1016
1017    /* Generate a cookie used by internal clients for authorization */
1018    if (g_fXdmcpEnabled || g_fAuthEnabled)
1019        winGenerateAuthorization();
1020
1021    /* Perform some one time initialization */
1022    if (1 == serverGeneration) {
1023        /*
1024         * setlocale applies to all threads in the current process.
1025         * Apply locale specified in LANG environment variable.
1026         */
1027        setlocale(LC_ALL, "");
1028    }
1029
1030#if CYGDEBUG || YES
1031    winDebug("InitOutput - Returning.\n");
1032#endif
1033}
1034