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