InitOutput.c revision 5a7dfde8
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
154#if INPUTTHREAD
155/** This function is called in Xserver/os/inputthread.c when starting
156    the input thread. */
157void
158ddxInputThreadInit(void)
159{
160}
161#endif
162
163int
164main(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 */
183void
184ddxGiveUp(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/* See Porting Layer Definition - p. 57 */
253void
254AbortDDX(enum ExitCode error)
255{
256#if CYGDEBUG
257    winDebug("AbortDDX\n");
258#endif
259    ddxGiveUp(error);
260}
261
262#ifdef __CYGWIN__
263/* hasmntopt is currently not implemented for cygwin */
264static const char *
265winCheckMntOpt(const struct mntent *mnt, const char *opt)
266{
267    const char *s;
268    size_t len;
269
270    if (mnt == NULL)
271        return NULL;
272    if (opt == NULL)
273        return NULL;
274    if (mnt->mnt_opts == NULL)
275        return NULL;
276
277    len = strlen(opt);
278    s = strstr(mnt->mnt_opts, opt);
279    if (s == NULL)
280        return NULL;
281    if ((s == mnt->mnt_opts || *(s - 1) == ',') &&
282        (s[len] == 0 || s[len] == ','))
283        return (char *) opt;
284    return NULL;
285}
286
287static void
288winCheckMount(void)
289{
290    FILE *mnt;
291    struct mntent *ent;
292
293    enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
294        level = none, curlevel;
295    BOOL binary = TRUE;
296
297    mnt = setmntent("/etc/mtab", "r");
298    if (mnt == NULL) {
299        ErrorF("setmntent failed");
300        return;
301    }
302
303    while ((ent = getmntent(mnt)) != NULL) {
304        BOOL sys = (winCheckMntOpt(ent, "user") != NULL);
305        BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
306        BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
307
308        if (sys) {
309            if (root)
310                curlevel = sys_root;
311            else if (tmp)
312                curlevel = sys_tmp;
313            else
314                continue;
315        }
316        else {
317            if (root)
318                curlevel = user_root;
319            else if (tmp)
320                curlevel = user_tmp;
321            else
322                continue;
323        }
324
325        if (curlevel <= level)
326            continue;
327        level = curlevel;
328
329        if ((winCheckMntOpt(ent, "binary") == NULL) &&
330            (winCheckMntOpt(ent, "binmode") == NULL))
331            binary = FALSE;
332        else
333            binary = TRUE;
334    }
335
336    if (endmntent(mnt) != 1) {
337        ErrorF("endmntent failed");
338        return;
339    }
340
341    if (!binary)
342        winMsg(X_WARNING, "/tmp mounted in textmode\n");
343}
344#else
345static void
346winCheckMount(void)
347{
348}
349#endif
350
351#ifdef RELOCATE_PROJECTROOT
352const char *
353winGetBaseDir(void)
354{
355    static BOOL inited = FALSE;
356    static char buffer[MAX_PATH];
357
358    if (!inited) {
359        char *fendptr;
360        HMODULE module = GetModuleHandle(NULL);
361        DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
362
363        if (sizeof(buffer) > 0)
364            buffer[sizeof(buffer) - 1] = 0;
365
366        fendptr = buffer + size;
367        while (fendptr > buffer) {
368            if (*fendptr == '\\' || *fendptr == '/') {
369                *fendptr = 0;
370                break;
371            }
372            fendptr--;
373        }
374        inited = TRUE;
375    }
376    return buffer;
377}
378#endif
379
380static void
381winFixupPaths(void)
382{
383    BOOL changed_fontpath = FALSE;
384    MessageType font_from = X_DEFAULT;
385
386#ifdef RELOCATE_PROJECTROOT
387    const char *basedir = winGetBaseDir();
388    size_t basedirlen = strlen(basedir);
389#endif
390
391#ifdef READ_FONTDIRS
392    {
393        /* Open fontpath configuration file */
394        FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
395
396        if (fontdirs != NULL) {
397            char buffer[256];
398            int needs_sep = TRUE;
399            int comment_block = FALSE;
400
401            /* get default fontpath */
402            char *fontpath = strdup(defaultFontPath);
403            size_t size = strlen(fontpath);
404
405            /* read all lines */
406            while (!feof(fontdirs)) {
407                size_t blen;
408                char *hashchar;
409                char *str;
410                int has_eol = FALSE;
411
412                /* read one line */
413                str = fgets(buffer, sizeof(buffer), fontdirs);
414                if (str == NULL)        /* stop on error or eof */
415                    break;
416
417                if (strchr(str, '\n') != NULL)
418                    has_eol = TRUE;
419
420                /* check if block is continued comment */
421                if (comment_block) {
422                    /* ignore all input */
423                    *str = 0;
424                    blen = 0;
425                    if (has_eol)        /* check if line ended in this block */
426                        comment_block = FALSE;
427                }
428                else {
429                    /* find comment character. ignore all trailing input */
430                    hashchar = strchr(str, '#');
431                    if (hashchar != NULL) {
432                        *hashchar = 0;
433                        if (!has_eol)   /* mark next block as continued comment */
434                            comment_block = TRUE;
435                    }
436                }
437
438                /* strip whitespaces from beginning */
439                while (*str == ' ' || *str == '\t')
440                    str++;
441
442                /* get size, strip whitespaces from end */
443                blen = strlen(str);
444                while (blen > 0 && (str[blen - 1] == ' ' ||
445                                    str[blen - 1] == '\t' ||
446                                    str[blen - 1] == '\n')) {
447                    str[--blen] = 0;
448                }
449
450                /* still something left to add? */
451                if (blen > 0) {
452                    size_t newsize = size + blen;
453
454                    /* reserve one character more for ',' */
455                    if (needs_sep)
456                        newsize++;
457
458                    /* allocate memory */
459                    if (fontpath == NULL)
460                        fontpath = malloc(newsize + 1);
461                    else
462                        fontpath = realloc(fontpath, newsize + 1);
463
464                    /* add separator */
465                    if (needs_sep) {
466                        fontpath[size] = ',';
467                        size++;
468                        needs_sep = FALSE;
469                    }
470
471                    /* mark next line as new entry */
472                    if (has_eol)
473                        needs_sep = TRUE;
474
475                    /* add block */
476                    strncpy(fontpath + size, str, blen);
477                    fontpath[newsize] = 0;
478                    size = newsize;
479                }
480            }
481
482            /* cleanup */
483            fclose(fontdirs);
484            defaultFontPath = strdup(fontpath);
485            free(fontpath);
486            changed_fontpath = TRUE;
487            font_from = X_CONFIG;
488        }
489    }
490#endif                          /* READ_FONTDIRS */
491#ifdef RELOCATE_PROJECTROOT
492    {
493        const char *libx11dir = PROJECTROOT "/lib/X11";
494        size_t libx11dir_len = strlen(libx11dir);
495        char *newfp = NULL;
496        size_t newfp_len = 0;
497        const char *endptr, *ptr, *oldptr = defaultFontPath;
498
499        endptr = oldptr + strlen(oldptr);
500        ptr = strchr(oldptr, ',');
501        if (ptr == NULL)
502            ptr = endptr;
503        while (ptr != NULL) {
504            size_t oldfp_len = (ptr - oldptr);
505            size_t newsize = oldfp_len;
506            char *newpath = malloc(newsize + 1);
507
508            strncpy(newpath, oldptr, newsize);
509            newpath[newsize] = 0;
510
511            if (strncmp(libx11dir, newpath, libx11dir_len) == 0) {
512                char *compose;
513
514                newsize = newsize - libx11dir_len + basedirlen;
515                compose = malloc(newsize + 1);
516                strcpy(compose, basedir);
517                strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
518                compose[newsize] = 0;
519                free(newpath);
520                newpath = compose;
521            }
522
523            oldfp_len = newfp_len;
524            if (oldfp_len > 0)
525                newfp_len++;    /* space for separator */
526            newfp_len += newsize;
527
528            if (newfp == NULL)
529                newfp = malloc(newfp_len + 1);
530            else
531                newfp = realloc(newfp, newfp_len + 1);
532
533            if (oldfp_len > 0) {
534                strcpy(newfp + oldfp_len, ",");
535                oldfp_len++;
536            }
537            strcpy(newfp + oldfp_len, newpath);
538
539            free(newpath);
540
541            if (*ptr == 0) {
542                oldptr = ptr;
543                ptr = NULL;
544            }
545            else {
546                oldptr = ptr + 1;
547                ptr = strchr(oldptr, ',');
548                if (ptr == NULL)
549                    ptr = endptr;
550            }
551        }
552
553        defaultFontPath = strdup(newfp);
554        free(newfp);
555        changed_fontpath = TRUE;
556    }
557#endif                          /* RELOCATE_PROJECTROOT */
558    if (changed_fontpath)
559        winMsg(font_from, "FontPath set to \"%s\"\n", defaultFontPath);
560
561#ifdef RELOCATE_PROJECTROOT
562    if (getenv("XKEYSYMDB") == NULL) {
563        char buffer[MAX_PATH];
564
565        snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB", basedir);
566        buffer[sizeof(buffer) - 1] = 0;
567        putenv(buffer);
568    }
569    if (getenv("XERRORDB") == NULL) {
570        char buffer[MAX_PATH];
571
572        snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB", basedir);
573        buffer[sizeof(buffer) - 1] = 0;
574        putenv(buffer);
575    }
576    if (getenv("XLOCALEDIR") == NULL) {
577        char buffer[MAX_PATH];
578
579        snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale", basedir);
580        buffer[sizeof(buffer) - 1] = 0;
581        putenv(buffer);
582    }
583    if (getenv("HOME") == NULL) {
584        char buffer[MAX_PATH + 5];
585
586        strncpy(buffer, "HOME=", 5);
587
588        /* query appdata directory */
589        if (SHGetFolderPathA
590            (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0,
591             buffer + 5) == 0) {
592            putenv(buffer);
593        }
594        else {
595            winMsg(X_ERROR, "Can not determine HOME directory\n");
596        }
597    }
598    if (!g_fLogFileChanged) {
599        static char buffer[MAX_PATH];
600        DWORD size = GetTempPath(sizeof(buffer), buffer);
601
602        if (size && size < sizeof(buffer)) {
603            snprintf(buffer + size, sizeof(buffer) - size,
604                     "XWin.%s.log", display);
605            buffer[sizeof(buffer) - 1] = 0;
606            g_pszLogFile = buffer;
607            winMsg(X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile);
608        }
609    }
610    {
611        static char xkbbasedir[MAX_PATH];
612
613        snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkb", basedir);
614        if (sizeof(xkbbasedir) > 0)
615            xkbbasedir[sizeof(xkbbasedir) - 1] = 0;
616        XkbBaseDirectory = xkbbasedir;
617        XkbBinDirectory = basedir;
618    }
619#endif                          /* RELOCATE_PROJECTROOT */
620}
621
622void
623OsVendorInit(void)
624{
625    /* Re-initialize global variables on server reset */
626    winInitializeGlobals();
627
628    winFixupPaths();
629
630#ifdef DDXOSVERRORF
631    if (!OsVendorVErrorFProc)
632        OsVendorVErrorFProc = OsVendorVErrorF;
633#endif
634
635    if (!g_fLogInited) {
636        /* keep this order. If LogInit fails it calls Abort which then calls
637         * ddxGiveUp where LogInit is called again and creates an infinite
638         * recursion. If we set g_fLogInited to TRUE before the init we
639         * avoid the second call
640         */
641        g_fLogInited = TRUE;
642        g_pszLogFile = LogInit(g_pszLogFile, ".old");
643
644    }
645    LogSetParameter(XLOG_FLUSH, 1);
646    LogSetParameter(XLOG_VERBOSITY, g_iLogVerbose);
647    LogSetParameter(XLOG_FILE_VERBOSITY, g_iLogVerbose);
648
649    /* Log the version information */
650    if (serverGeneration == 1)
651        winLogVersionInfo();
652
653    winCheckMount();
654
655    /* Add a default screen if no screens were specified */
656    if (g_iNumScreens == 0) {
657        winDebug("OsVendorInit - Creating default screen 0\n");
658
659        /*
660         * We need to initialize the default screen 0 if no -screen
661         * arguments were processed.
662         *
663         * Add a screen 0 using the defaults set by winInitializeDefaultScreens()
664         * and any additional default screen parameters given
665         */
666        winInitializeScreens(1);
667
668        /* We have to flag this as an explicit screen, even though it isn't */
669        g_ScreenInfo[0].fExplicitScreen = TRUE;
670    }
671
672    /* Work out what the default emulate3buttons setting should be, and apply
673       it if nothing was explicitly specified */
674    {
675        int mouseButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
676        int j;
677
678        for (j = 0; j < g_iNumScreens; j++) {
679            if (g_ScreenInfo[j].iE3BTimeout == WIN_E3B_DEFAULT) {
680                if (mouseButtons < 3) {
681                    static Bool reportOnce = TRUE;
682
683                    g_ScreenInfo[j].iE3BTimeout = WIN_DEFAULT_E3B_TIME;
684                    if (reportOnce) {
685                        reportOnce = FALSE;
686                        winMsg(X_PROBED,
687                               "Windows reports only %d mouse buttons, defaulting to -emulate3buttons\n",
688                               mouseButtons);
689                    }
690                }
691                else {
692                    g_ScreenInfo[j].iE3BTimeout = WIN_E3B_OFF;
693                }
694            }
695        }
696    }
697
698    /* Work out what the default resize setting should be, and apply it if it
699     was not explicitly specified */
700    {
701        int j;
702        for (j = 0; j < g_iNumScreens; j++) {
703            if (g_ScreenInfo[j].iResizeMode == resizeDefault) {
704                if (g_ScreenInfo[j].fFullScreen)
705                    g_ScreenInfo[j].iResizeMode = resizeNotAllowed;
706                else
707                    g_ScreenInfo[j].iResizeMode = resizeWithRandr;
708                }
709        }
710    }
711}
712
713static void
714winUseMsg(void)
715{
716    ErrorF("\n");
717    ErrorF("\n");
718    ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n");
719    ErrorF("\n");
720
721    ErrorF("-[no]clipboard\n"
722           "\tEnable [disable] the clipboard integration. Default is enabled.\n");
723
724    ErrorF("-clipupdates num_boxes\n"
725           "\tUse a clipping region to constrain shadow update blits to\n"
726           "\tthe updated region when num_boxes, or more, are in the\n"
727           "\tupdated region.\n");
728
729#ifdef XWIN_XF86CONFIG
730    ErrorF("-config\n" "\tSpecify a configuration file.\n");
731
732    ErrorF("-configdir\n" "\tSpecify a configuration directory.\n");
733#endif
734
735    ErrorF("-depth bits_per_pixel\n"
736           "\tSpecify an optional bitdepth to use in fullscreen mode\n"
737           "\twith a DirectDraw engine.\n");
738
739    ErrorF("-[no]emulate3buttons [timeout]\n"
740           "\tEmulate 3 button mouse with an optional timeout in\n"
741           "\tmilliseconds.\n");
742
743#ifdef XWIN_EMULATEPSEUDO
744    ErrorF("-emulatepseudo\n"
745           "\tCreate a depth 8 PseudoColor visual when running in\n"
746           "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
747           "\tdepths.  The PseudoColor visual does not have correct colors,\n"
748           "\tand it may crash, but it at least allows you to run your\n"
749           "\tapplication in TrueColor modes.\n");
750#endif
751
752    ErrorF("-engine engine_type_id\n"
753           "\tOverride the server's automatically selected engine type:\n"
754           "\t\t1 - Shadow GDI\n"
755           "\t\t4 - Shadow DirectDraw4 Non-Locking\n"
756        );
757
758    ErrorF("-fullscreen\n" "\tRun the server in fullscreen mode.\n");
759
760    ErrorF("-[no]hostintitle\n"
761           "\tIn multiwindow mode, add remote host names to window titles.\n");
762
763    ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n");
764
765#ifdef XWIN_XF86CONFIG
766    ErrorF("-keyboard\n"
767           "\tSpecify a keyboard device from the configuration file.\n");
768#endif
769
770    ErrorF("-[no]keyhook\n"
771           "\tGrab special Windows keypresses like Alt-Tab or the Menu "
772           "key.\n");
773
774    ErrorF("-lesspointer\n"
775           "\tHide the windows mouse pointer when it is over any\n"
776           "\t" EXECUTABLE_NAME
777           " window.  This prevents ghost cursors appearing when\n"
778           "\tthe Windows cursor is drawn on top of the X cursor\n");
779
780    ErrorF("-logfile filename\n" "\tWrite log messages to <filename>.\n");
781
782    ErrorF("-logverbose verbosity\n"
783           "\tSet the verbosity of log messages. [NOTE: Only a few messages\n"
784           "\trespect the settings yet]\n"
785           "\t\t0 - only print fatal error.\n"
786           "\t\t1 - print additional configuration information.\n"
787           "\t\t2 - print additional runtime information [default].\n"
788           "\t\t3 - print debugging and tracing information.\n");
789
790    ErrorF("-[no]multimonitors or -[no]multiplemonitors\n"
791           "\tUse the entire virtual screen if multiple\n"
792           "\tmonitors are present.\n");
793
794    ErrorF("-multiwindow\n" "\tRun the server in multi-window mode.\n");
795
796#ifdef XWIN_MULTIWINDOWEXTWM
797    ErrorF("-mwextwm\n"
798           "\tRun the server in multi-window external window manager mode.\n");
799#endif
800
801    ErrorF("-nodecoration\n"
802           "\tDo not draw a window border, title bar, etc.  Windowed\n"
803           "\tmode only.\n");
804
805    ErrorF("-nounicodeclipboard\n"
806           "\tDo not use Unicode clipboard even if on a NT-based platform.\n");
807
808    ErrorF("-[no]primary\n"
809           "\tWhen clipboard integration is enabled, map the X11 PRIMARY selection\n"
810           "\tto the Windows clipboard. Default is enabled.\n");
811
812    ErrorF("-refresh rate_in_Hz\n"
813           "\tSpecify an optional refresh rate to use in fullscreen mode\n"
814           "\twith a DirectDraw engine.\n");
815
816    ErrorF("-resize=none|scrollbars|randr"
817           "\tIn windowed mode, [don't] allow resizing of the window. 'scrollbars'\n"
818           "\tmode gives the window scrollbars as needed, 'randr' mode uses the RANR\n"
819           "\textension to resize the X screen.  'randr' is the default.\n");
820
821    ErrorF("-rootless\n" "\tRun the server in rootless mode.\n");
822
823    ErrorF("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n"
824           "\tEnable screen scr_num and optionally specify a width and\n"
825           "\theight and initial position for that screen. Additionally\n"
826           "\ta monitor number can be specified to start the server on,\n"
827           "\tat which point, all coordinates become relative to that\n"
828           "\tmonitor. Examples:\n"
829           "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n"
830           "\t -screen 0 1024x768@3        ; 3rd monitor size 1024x768\n"
831           "\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n");
832
833    ErrorF("-swcursor\n"
834           "\tDisable the usage of the Windows cursor and use the X11 software\n"
835           "\tcursor instead.\n");
836
837    ErrorF("-[no]trayicon\n"
838           "\tDo not create a tray icon.  Default is to create one\n"
839           "\ticon per screen.  You can globally disable tray icons with\n"
840           "\t-notrayicon, then enable it for specific screens with\n"
841           "\t-trayicon for those screens.\n");
842
843    ErrorF("-[no]unixkill\n" "\tCtrl+Alt+Backspace exits the X Server.\n");
844
845#ifdef XWIN_GLX_WINDOWS
846    ErrorF("-[no]wgl\n"
847           "\tEnable the GLX extension to use the native Windows WGL interface for hardware-accelerated OpenGL\n");
848#endif
849
850    ErrorF("-[no]winkill\n" "\tAlt+F4 exits the X Server.\n");
851
852    ErrorF("-xkblayout XKBLayout\n"
853           "\tEquivalent to XKBLayout in XF86Config files.\n"
854           "\tFor example: -xkblayout de\n");
855
856    ErrorF("-xkbmodel XKBModel\n"
857           "\tEquivalent to XKBModel in XF86Config files.\n");
858
859    ErrorF("-xkboptions XKBOptions\n"
860           "\tEquivalent to XKBOptions in XF86Config files.\n");
861
862    ErrorF("-xkbrules XKBRules\n"
863           "\tEquivalent to XKBRules in XF86Config files.\n");
864
865    ErrorF("-xkbvariant XKBVariant\n"
866           "\tEquivalent to XKBVariant in XF86Config files.\n"
867           "\tFor example: -xkbvariant nodeadkeys\n");
868}
869
870/* See Porting Layer Definition - p. 57 */
871void
872ddxUseMsg(void)
873{
874    /* Set a flag so that FatalError won't give duplicate warning message */
875    g_fSilentFatalError = TRUE;
876
877    winUseMsg();
878
879    /* Log file will not be opened for UseMsg unless we open it now */
880    if (!g_fLogInited) {
881        g_pszLogFile = LogInit(g_pszLogFile, ".old");
882        g_fLogInited = TRUE;
883    }
884    LogClose(EXIT_NO_ERROR);
885
886    /* Notify user where UseMsg text can be found. */
887    if (!g_fNoHelpMessageBox)
888        winMessageBoxF("The " PROJECT_NAME " help text has been printed to "
889                       "%s.\n"
890                       "Please open %s to read the help text.\n",
891                       MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile);
892}
893
894/* See Porting Layer Definition - p. 20 */
895/*
896 * Do any global initialization, then initialize each screen.
897 *
898 * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv
899 */
900
901void
902InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
903{
904    int i;
905
906    if (serverGeneration == 1)
907        XwinExtensionInit();
908
909    /* Log the command line */
910    winLogCommandLine(argc, argv);
911
912#if CYGDEBUG
913    winDebug("InitOutput\n");
914#endif
915
916    /* Validate command-line arguments */
917    if (serverGeneration == 1 && !winValidateArgs()) {
918        FatalError("InitOutput - Invalid command-line arguments found.  "
919                   "Exiting.\n");
920    }
921
922#ifdef XWIN_XF86CONFIG
923    /* Try to read the xorg.conf-style configuration file */
924    if (!winReadConfigfile())
925        winErrorFVerb(1, "InitOutput - Error reading config file\n");
926#else
927    winMsg(X_INFO, "xorg.conf is not supported\n");
928    winMsg(X_INFO, "See http://x.cygwin.com/docs/faq/cygwin-x-faq.html "
929           "for more information\n");
930    winConfigFiles();
931#endif
932
933    /* Load preferences from XWinrc file */
934    LoadPreferences();
935
936    /* Setup global screen info parameters */
937    pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
938    pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
939    pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
940    pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
941    pScreenInfo->numPixmapFormats = ARRAY_SIZE(g_PixmapFormats);
942
943    /* Describe how we want common pixmap formats padded */
944    for (i = 0; i < ARRAY_SIZE(g_PixmapFormats); i++) {
945        pScreenInfo->formats[i] = g_PixmapFormats[i];
946    }
947
948    /* Load pointers to DirectDraw functions */
949    winGetDDProcAddresses();
950
951    /* Detect supported engines */
952    winDetectSupportedEngines();
953    /* Load libraries for taskbar grouping */
954    winPropertyStoreInit();
955
956    /* Store the instance handle */
957    g_hInstance = GetModuleHandle(NULL);
958
959    /* Create the messaging window */
960    if (serverGeneration == 1)
961        winCreateMsgWindowThread();
962
963    /* Initialize each screen */
964    for (i = 0; i < g_iNumScreens; ++i) {
965        /* Initialize the screen */
966        if (-1 == AddScreen(winScreenInit, argc, argv)) {
967            FatalError("InitOutput - Couldn't add screen %d", i);
968        }
969    }
970
971  /*
972     Unless full xinerama has been explicitly enabled, register all native screens with pseudoramiX
973  */
974  if (!noPanoramiXExtension)
975      noPseudoramiXExtension = TRUE;
976
977  if ((g_ScreenInfo[0].fMultipleMonitors) && !noPseudoramiXExtension)
978    {
979      int pass;
980
981      PseudoramiXExtensionInit();
982
983      /* Add primary monitor on pass 0, other monitors on pass 1, to ensure
984       the primary monitor is first in XINERAMA list */
985      for (pass = 0; pass < 2; pass++)
986        {
987          int iMonitor;
988
989          for (iMonitor = 1; ; iMonitor++)
990            {
991              struct GetMonitorInfoData data;
992              QueryMonitor(iMonitor, &data);
993              if (data.bMonitorSpecifiedExists)
994                {
995                  MONITORINFO mi;
996                  mi.cbSize = sizeof(MONITORINFO);
997
998                  if (GetMonitorInfo(data.monitorHandle, &mi))
999                    {
1000                      /* pass == 1 XOR primary monitor flags is set */
1001                      if ((!(pass == 1)) != (!(mi.dwFlags & MONITORINFOF_PRIMARY)))
1002                        {
1003                          /*
1004                            Note the screen origin in a normalized coordinate space where (0,0) is at the top left
1005                            of the native virtual desktop area
1006                          */
1007                          data.monitorOffsetX = data.monitorOffsetX - GetSystemMetrics(SM_XVIRTUALSCREEN);
1008                          data.monitorOffsetY = data.monitorOffsetY - GetSystemMetrics(SM_YVIRTUALSCREEN);
1009
1010                          winDebug ("InitOutput - screen %d added at virtual desktop coordinate (%d,%d) (pseudoramiX) \n",
1011                                    iMonitor-1, data.monitorOffsetX, data.monitorOffsetY);
1012
1013                          PseudoramiXAddScreen(data.monitorOffsetX, data.monitorOffsetY,
1014                                               data.monitorWidth, data.monitorHeight);
1015                        }
1016                    }
1017                }
1018              else
1019                break;
1020            }
1021        }
1022    }
1023
1024    xorgGlxCreateVendor();
1025
1026    /* Generate a cookie used by internal clients for authorization */
1027    if (g_fXdmcpEnabled || g_fAuthEnabled)
1028        winGenerateAuthorization();
1029
1030    /* Perform some one time initialization */
1031    if (1 == serverGeneration) {
1032        /*
1033         * setlocale applies to all threads in the current process.
1034         * Apply locale specified in LANG environment variable.
1035         */
1036        setlocale(LC_ALL, "");
1037    }
1038
1039#if CYGDEBUG || YES
1040    winDebug("InitOutput - Returning.\n");
1041#endif
1042}
1043