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