1145 lines
30 KiB
C
1145 lines
30 KiB
C
/*
|
|
|
|
Copyright 1993, 1998 The Open Group
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
other dealings in this Software without prior written authorization
|
|
from The Open Group.
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_XWIN_CONFIG_H
|
|
#include <xwin-config.h>
|
|
#endif
|
|
#include "win.h"
|
|
#include "winmsg.h"
|
|
#include "winconfig.h"
|
|
#include "winprefs.h"
|
|
#ifdef XWIN_CLIPBOARD
|
|
#include "X11/Xlocale.h"
|
|
#endif
|
|
#ifdef DPMSExtension
|
|
#include "dpmsproc.h"
|
|
#endif
|
|
#ifdef __CYGWIN__
|
|
#include <mntent.h>
|
|
#endif
|
|
#if defined(XKB) && defined(WIN32)
|
|
#include <xkbsrv.h>
|
|
#endif
|
|
#ifdef RELOCATE_PROJECTROOT
|
|
#include <shlobj.h>
|
|
typedef HRESULT (*SHGETFOLDERPATHPROC)(
|
|
HWND hwndOwner,
|
|
int nFolder,
|
|
HANDLE hToken,
|
|
DWORD dwFlags,
|
|
LPTSTR pszPath
|
|
);
|
|
#endif
|
|
|
|
|
|
/*
|
|
* References to external symbols
|
|
*/
|
|
|
|
extern int g_iNumScreens;
|
|
extern winScreenInfo g_ScreenInfo[];
|
|
extern int g_iLastScreen;
|
|
extern char * g_pszCommandLine;
|
|
extern Bool g_fSilentFatalError;
|
|
|
|
extern char * g_pszLogFile;
|
|
extern Bool g_fLogFileChanged;
|
|
extern int g_iLogVerbose;
|
|
Bool g_fLogInited;
|
|
|
|
extern Bool g_fXdmcpEnabled;
|
|
#ifdef HAS_DEVWINDOWS
|
|
extern int g_fdMessageQueue;
|
|
#endif
|
|
extern const char * g_pszQueryHost;
|
|
extern HINSTANCE g_hInstance;
|
|
|
|
#ifdef XWIN_CLIPBOARD
|
|
extern Bool g_fUnicodeClipboard;
|
|
extern Bool g_fClipboardLaunched;
|
|
extern Bool g_fClipboardStarted;
|
|
extern pthread_t g_ptClipboardProc;
|
|
extern HWND g_hwndClipboard;
|
|
extern Bool g_fClipboard;
|
|
#endif
|
|
|
|
extern HMODULE g_hmodDirectDraw;
|
|
extern FARPROC g_fpDirectDrawCreate;
|
|
extern FARPROC g_fpDirectDrawCreateClipper;
|
|
|
|
extern HMODULE g_hmodCommonControls;
|
|
extern FARPROC g_fpTrackMouseEvent;
|
|
extern Bool g_fNoHelpMessageBox;
|
|
extern Bool g_fSilentDupError;
|
|
|
|
|
|
/*
|
|
* Function prototypes
|
|
*/
|
|
|
|
#ifdef XWIN_CLIPBOARD
|
|
static void
|
|
winClipboardShutdown (void);
|
|
#endif
|
|
|
|
#if defined(DDXOSVERRORF)
|
|
void
|
|
OsVendorVErrorF (const char *pszFormat, va_list va_args);
|
|
#endif
|
|
|
|
void
|
|
winInitializeDefaultScreens (void);
|
|
|
|
static Bool
|
|
winCheckDisplayNumber (void);
|
|
|
|
void
|
|
winLogCommandLine (int argc, char *argv[]);
|
|
|
|
void
|
|
winLogVersionInfo (void);
|
|
|
|
Bool
|
|
winValidateArgs (void);
|
|
|
|
#ifdef RELOCATE_PROJECTROOT
|
|
const char *
|
|
winGetBaseDir(void);
|
|
#endif
|
|
|
|
/*
|
|
* For the depth 24 pixmap we default to 32 bits per pixel, but
|
|
* we change this pixmap format later if we detect that the display
|
|
* is going to be running at 24 bits per pixel.
|
|
*
|
|
* FIXME: On second thought, don't DIBs only support 32 bits per pixel?
|
|
* DIBs are the underlying bitmap used for DirectDraw surfaces, so it
|
|
* seems that all pixmap formats with depth 24 would be 32 bits per pixel.
|
|
* Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep
|
|
* the bits per pixel adjustment and update this comment to reflect the
|
|
* situation. Harold Hunt - 2002/07/02
|
|
*/
|
|
|
|
static PixmapFormatRec g_PixmapFormats[] = {
|
|
{ 1, 1, BITMAP_SCANLINE_PAD },
|
|
{ 4, 8, BITMAP_SCANLINE_PAD },
|
|
{ 8, 8, BITMAP_SCANLINE_PAD },
|
|
{ 15, 16, BITMAP_SCANLINE_PAD },
|
|
{ 16, 16, BITMAP_SCANLINE_PAD },
|
|
{ 24, 32, BITMAP_SCANLINE_PAD },
|
|
#ifdef RENDER
|
|
{ 32, 32, BITMAP_SCANLINE_PAD }
|
|
#endif
|
|
};
|
|
|
|
const int NUMFORMATS = sizeof (g_PixmapFormats) / sizeof (g_PixmapFormats[0]);
|
|
|
|
#ifdef XWIN_CLIPBOARD
|
|
static void
|
|
winClipboardShutdown (void)
|
|
{
|
|
/* Close down clipboard resources */
|
|
if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted)
|
|
{
|
|
/* Synchronously destroy the clipboard window */
|
|
if (g_hwndClipboard != NULL)
|
|
{
|
|
SendMessage (g_hwndClipboard, WM_DESTROY, 0, 0);
|
|
/* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
|
|
}
|
|
else
|
|
return;
|
|
|
|
/* Wait for the clipboard thread to exit */
|
|
pthread_join (g_ptClipboardProc, NULL);
|
|
|
|
g_fClipboardLaunched = FALSE;
|
|
g_fClipboardStarted = FALSE;
|
|
|
|
winDebug ("winClipboardShutdown - Clipboard thread has exited.\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined(DDXBEFORERESET)
|
|
/*
|
|
* Called right before KillAllClients when the server is going to reset,
|
|
* allows us to shutdown our seperate threads cleanly.
|
|
*/
|
|
|
|
void
|
|
ddxBeforeReset (void)
|
|
{
|
|
winDebug ("ddxBeforeReset - Hello\n");
|
|
|
|
#ifdef XWIN_CLIPBOARD
|
|
winClipboardShutdown ();
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
/* See Porting Layer Definition - p. 57 */
|
|
void
|
|
ddxGiveUp (void)
|
|
{
|
|
int i;
|
|
|
|
#if CYGDEBUG
|
|
winDebug ("ddxGiveUp\n");
|
|
#endif
|
|
|
|
/* Perform per-screen deinitialization */
|
|
for (i = 0; i < g_iNumScreens; ++i)
|
|
{
|
|
/* Delete the tray icon */
|
|
if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen)
|
|
winDeleteNotifyIcon (winGetScreenPriv (g_ScreenInfo[i].pScreen));
|
|
}
|
|
|
|
#ifdef XWIN_MULTIWINDOW
|
|
/* Notify the worker threads we're exiting */
|
|
winDeinitMultiWindowWM ();
|
|
#endif
|
|
|
|
#ifdef HAS_DEVWINDOWS
|
|
/* Close our handle to our message queue */
|
|
if (g_fdMessageQueue != WIN_FD_INVALID)
|
|
{
|
|
/* Close /dev/windows */
|
|
close (g_fdMessageQueue);
|
|
|
|
/* Set the file handle to invalid */
|
|
g_fdMessageQueue = WIN_FD_INVALID;
|
|
}
|
|
#endif
|
|
|
|
if (!g_fLogInited) {
|
|
LogInit (g_pszLogFile, NULL);
|
|
g_fLogInited = TRUE;
|
|
}
|
|
LogClose ();
|
|
|
|
/*
|
|
* At this point we aren't creating any new screens, so
|
|
* we are guaranteed to not need the DirectDraw functions.
|
|
*/
|
|
if (g_hmodDirectDraw != NULL)
|
|
{
|
|
FreeLibrary (g_hmodDirectDraw);
|
|
g_hmodDirectDraw = NULL;
|
|
g_fpDirectDrawCreate = NULL;
|
|
g_fpDirectDrawCreateClipper = NULL;
|
|
}
|
|
|
|
/* Unload our TrackMouseEvent funtion pointer */
|
|
if (g_hmodCommonControls != NULL)
|
|
{
|
|
FreeLibrary (g_hmodCommonControls);
|
|
g_hmodCommonControls = NULL;
|
|
g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
|
|
}
|
|
|
|
/* Free concatenated command line */
|
|
if (g_pszCommandLine)
|
|
{
|
|
free (g_pszCommandLine);
|
|
g_pszCommandLine = NULL;
|
|
}
|
|
|
|
/* Remove our keyboard hook if it is installed */
|
|
winRemoveKeyboardHookLL ();
|
|
|
|
/* Tell Windows that we want to end the app */
|
|
PostQuitMessage (0);
|
|
}
|
|
|
|
|
|
/* See Porting Layer Definition - p. 57 */
|
|
void
|
|
AbortDDX (void)
|
|
{
|
|
#if CYGDEBUG
|
|
winDebug ("AbortDDX\n");
|
|
#endif
|
|
ddxGiveUp ();
|
|
}
|
|
|
|
#ifdef __CYGWIN__
|
|
/* hasmntopt is currently not implemented for cygwin */
|
|
static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt)
|
|
{
|
|
const char *s;
|
|
size_t len;
|
|
if (mnt == NULL)
|
|
return NULL;
|
|
if (opt == NULL)
|
|
return NULL;
|
|
if (mnt->mnt_opts == NULL)
|
|
return NULL;
|
|
|
|
len = strlen(opt);
|
|
s = strstr(mnt->mnt_opts, opt);
|
|
if (s == NULL)
|
|
return NULL;
|
|
if ((s == mnt->mnt_opts || *(s-1) == ',') && (s[len] == 0 || s[len] == ','))
|
|
return (char *)opt;
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
winCheckMount(void)
|
|
{
|
|
FILE *mnt;
|
|
struct mntent *ent;
|
|
|
|
enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
|
|
level = none, curlevel;
|
|
BOOL binary = TRUE;
|
|
|
|
mnt = setmntent("/etc/mtab", "r");
|
|
if (mnt == NULL)
|
|
{
|
|
ErrorF("setmntent failed");
|
|
return;
|
|
}
|
|
|
|
while ((ent = getmntent(mnt)) != NULL)
|
|
{
|
|
BOOL system = (strcmp(ent->mnt_type, "system") == 0);
|
|
BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
|
|
BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
|
|
|
|
if (system)
|
|
{
|
|
if (root)
|
|
curlevel = sys_root;
|
|
else if (tmp)
|
|
curlevel = sys_tmp;
|
|
else
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (root)
|
|
curlevel = user_root;
|
|
else if (tmp)
|
|
curlevel = user_tmp;
|
|
else
|
|
continue;
|
|
}
|
|
|
|
if (curlevel <= level)
|
|
continue;
|
|
level = curlevel;
|
|
|
|
if (winCheckMntOpt(ent, "binmode") == NULL)
|
|
binary = 0;
|
|
else
|
|
binary = 1;
|
|
}
|
|
|
|
if (endmntent(mnt) != 1)
|
|
{
|
|
ErrorF("endmntent failed");
|
|
return;
|
|
}
|
|
|
|
if (!binary)
|
|
winMsg(X_WARNING, "/tmp mounted int textmode\n");
|
|
}
|
|
#else
|
|
static void
|
|
winCheckMount(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#ifdef RELOCATE_PROJECTROOT
|
|
const char *
|
|
winGetBaseDir(void)
|
|
{
|
|
static BOOL inited = FALSE;
|
|
static char buffer[MAX_PATH];
|
|
if (!inited)
|
|
{
|
|
char *fendptr;
|
|
HMODULE module = GetModuleHandle(NULL);
|
|
DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
|
|
if (sizeof(buffer) > 0)
|
|
buffer[sizeof(buffer)-1] = 0;
|
|
|
|
fendptr = buffer + size;
|
|
while (fendptr > buffer)
|
|
{
|
|
if (*fendptr == '\\' || *fendptr == '/')
|
|
{
|
|
*fendptr = 0;
|
|
break;
|
|
}
|
|
fendptr--;
|
|
}
|
|
inited = TRUE;
|
|
}
|
|
return buffer;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
winFixupPaths (void)
|
|
{
|
|
BOOL changed_fontpath = FALSE;
|
|
MessageType font_from = X_DEFAULT;
|
|
#ifdef RELOCATE_PROJECTROOT
|
|
const char *basedir = winGetBaseDir();
|
|
size_t basedirlen = strlen(basedir);
|
|
#endif
|
|
|
|
#ifdef READ_FONTDIRS
|
|
{
|
|
/* Open fontpath configuration file */
|
|
FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
|
|
if (fontdirs != NULL)
|
|
{
|
|
char buffer[256];
|
|
int needs_sep = TRUE;
|
|
int comment_block = FALSE;
|
|
|
|
/* get defautl fontpath */
|
|
char *fontpath = xstrdup(defaultFontPath);
|
|
size_t size = strlen(fontpath);
|
|
|
|
/* read all lines */
|
|
while (!feof(fontdirs))
|
|
{
|
|
size_t blen;
|
|
char *hashchar;
|
|
char *str;
|
|
int has_eol = FALSE;
|
|
|
|
/* read one line */
|
|
str = fgets(buffer, sizeof(buffer), fontdirs);
|
|
if (str == NULL) /* stop on error or eof */
|
|
break;
|
|
|
|
if (strchr(str, '\n') != NULL)
|
|
has_eol = TRUE;
|
|
|
|
/* check if block is continued comment */
|
|
if (comment_block)
|
|
{
|
|
/* ignore all input */
|
|
*str = 0;
|
|
blen = 0;
|
|
if (has_eol) /* check if line ended in this block */
|
|
comment_block = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* find comment character. ignore all trailing input */
|
|
hashchar = strchr(str, '#');
|
|
if (hashchar != NULL)
|
|
{
|
|
*hashchar = 0;
|
|
if (!has_eol) /* mark next block as continued comment */
|
|
comment_block = TRUE;
|
|
}
|
|
}
|
|
|
|
/* strip whitespaces from beginning */
|
|
while (*str == ' ' || *str == '\t')
|
|
str++;
|
|
|
|
/* get size, strip whitespaces from end */
|
|
blen = strlen(str);
|
|
while (blen > 0 && (str[blen-1] == ' ' ||
|
|
str[blen-1] == '\t' || str[blen-1] == '\n'))
|
|
{
|
|
str[--blen] = 0;
|
|
}
|
|
|
|
/* still something left to add? */
|
|
if (blen > 0)
|
|
{
|
|
size_t newsize = size + blen;
|
|
/* reserve one character more for ',' */
|
|
if (needs_sep)
|
|
newsize++;
|
|
|
|
/* allocate memory */
|
|
if (fontpath == NULL)
|
|
fontpath = malloc(newsize+1);
|
|
else
|
|
fontpath = realloc(fontpath, newsize+1);
|
|
|
|
/* add separator */
|
|
if (needs_sep)
|
|
{
|
|
fontpath[size] = ',';
|
|
size++;
|
|
needs_sep = FALSE;
|
|
}
|
|
|
|
/* mark next line as new entry */
|
|
if (has_eol)
|
|
needs_sep = TRUE;
|
|
|
|
/* add block */
|
|
strncpy(fontpath + size, str, blen);
|
|
fontpath[newsize] = 0;
|
|
size = newsize;
|
|
}
|
|
}
|
|
|
|
/* cleanup */
|
|
fclose(fontdirs);
|
|
defaultFontPath = xstrdup(fontpath);
|
|
free(fontpath);
|
|
changed_fontpath = TRUE;
|
|
font_from = X_CONFIG;
|
|
}
|
|
}
|
|
#endif /* READ_FONTDIRS */
|
|
#ifdef RELOCATE_PROJECTROOT
|
|
{
|
|
const char *libx11dir = PROJECTROOT "/lib/X11";
|
|
size_t libx11dir_len = strlen(libx11dir);
|
|
char *newfp = NULL;
|
|
size_t newfp_len = 0;
|
|
const char *endptr, *ptr, *oldptr = defaultFontPath;
|
|
|
|
endptr = oldptr + strlen(oldptr);
|
|
ptr = strchr(oldptr, ',');
|
|
if (ptr == NULL)
|
|
ptr = endptr;
|
|
while (ptr != NULL)
|
|
{
|
|
size_t oldfp_len = (ptr - oldptr);
|
|
size_t newsize = oldfp_len;
|
|
char *newpath = malloc(newsize + 1);
|
|
strncpy(newpath, oldptr, newsize);
|
|
newpath[newsize] = 0;
|
|
|
|
|
|
if (strncmp(libx11dir, newpath, libx11dir_len) == 0)
|
|
{
|
|
char *compose;
|
|
newsize = newsize - libx11dir_len + basedirlen;
|
|
compose = malloc(newsize + 1);
|
|
strcpy(compose, basedir);
|
|
strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
|
|
compose[newsize] = 0;
|
|
free(newpath);
|
|
newpath = compose;
|
|
}
|
|
|
|
oldfp_len = newfp_len;
|
|
if (oldfp_len > 0)
|
|
newfp_len ++; /* space for separator */
|
|
newfp_len += newsize;
|
|
|
|
if (newfp == NULL)
|
|
newfp = malloc(newfp_len + 1);
|
|
else
|
|
newfp = realloc(newfp, newfp_len + 1);
|
|
|
|
if (oldfp_len > 0)
|
|
{
|
|
strcpy(newfp + oldfp_len, ",");
|
|
oldfp_len++;
|
|
}
|
|
strcpy(newfp + oldfp_len, newpath);
|
|
|
|
free(newpath);
|
|
|
|
if (*ptr == 0)
|
|
{
|
|
oldptr = ptr;
|
|
ptr = NULL;
|
|
} else
|
|
{
|
|
oldptr = ptr + 1;
|
|
ptr = strchr(oldptr, ',');
|
|
if (ptr == NULL)
|
|
ptr = endptr;
|
|
}
|
|
}
|
|
|
|
defaultFontPath = xstrdup(newfp);
|
|
free(newfp);
|
|
changed_fontpath = TRUE;
|
|
}
|
|
#endif /* RELOCATE_PROJECTROOT */
|
|
if (changed_fontpath)
|
|
winMsg (font_from, "FontPath set to \"%s\"\n", defaultFontPath);
|
|
|
|
#ifdef RELOCATE_PROJECTROOT
|
|
if (getenv("XKEYSYMDB") == NULL)
|
|
{
|
|
char buffer[MAX_PATH];
|
|
snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB",
|
|
basedir);
|
|
buffer[sizeof(buffer)-1] = 0;
|
|
putenv(buffer);
|
|
}
|
|
if (getenv("XERRORDB") == NULL)
|
|
{
|
|
char buffer[MAX_PATH];
|
|
snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB",
|
|
basedir);
|
|
buffer[sizeof(buffer)-1] = 0;
|
|
putenv(buffer);
|
|
}
|
|
if (getenv("XLOCALEDIR") == NULL)
|
|
{
|
|
char buffer[MAX_PATH];
|
|
snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale",
|
|
basedir);
|
|
buffer[sizeof(buffer)-1] = 0;
|
|
putenv(buffer);
|
|
}
|
|
if (getenv("HOME") == NULL)
|
|
{
|
|
HMODULE shfolder;
|
|
SHGETFOLDERPATHPROC shgetfolderpath = NULL;
|
|
char buffer[MAX_PATH + 5];
|
|
strncpy(buffer, "HOME=", 5);
|
|
|
|
/* Try to load SHGetFolderPath from shfolder.dll and shell32.dll */
|
|
|
|
shfolder = LoadLibrary("shfolder.dll");
|
|
/* fallback to shell32.dll */
|
|
if (shfolder == NULL)
|
|
shfolder = LoadLibrary("shell32.dll");
|
|
|
|
/* resolve SHGetFolderPath */
|
|
if (shfolder != NULL)
|
|
shgetfolderpath = (SHGETFOLDERPATHPROC)GetProcAddress(shfolder, "SHGetFolderPathA");
|
|
|
|
/* query appdata directory */
|
|
if (shgetfolderpath &&
|
|
shgetfolderpath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0,
|
|
buffer + 5) == 0)
|
|
{
|
|
putenv(buffer);
|
|
} else
|
|
{
|
|
winMsg (X_ERROR, "Can not determine HOME directory\n");
|
|
}
|
|
if (shfolder != NULL)
|
|
FreeLibrary(shfolder);
|
|
}
|
|
if (!g_fLogFileChanged) {
|
|
static char buffer[MAX_PATH];
|
|
DWORD size = GetTempPath(sizeof(buffer), buffer);
|
|
if (size && size < sizeof(buffer))
|
|
{
|
|
snprintf(buffer + size, sizeof(buffer) - size,
|
|
"XWin.%s.log", display);
|
|
buffer[sizeof(buffer)-1] = 0;
|
|
g_pszLogFile = buffer;
|
|
winMsg (X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile);
|
|
}
|
|
}
|
|
#ifdef XKB
|
|
{
|
|
static char xkbbasedir[MAX_PATH];
|
|
|
|
snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkb", basedir);
|
|
if (sizeof(xkbbasedir) > 0)
|
|
xkbbasedir[sizeof(xkbbasedir)-1] = 0;
|
|
XkbBaseDirectory = xkbbasedir;
|
|
XkbBinDirectory = basedir;
|
|
}
|
|
#endif /* XKB */
|
|
#endif /* RELOCATE_PROJECTROOT */
|
|
}
|
|
|
|
void
|
|
OsVendorInit (void)
|
|
{
|
|
/* Re-initialize global variables on server reset */
|
|
winInitializeGlobals ();
|
|
|
|
LogInit (NULL, NULL);
|
|
LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose);
|
|
|
|
winFixupPaths();
|
|
|
|
#ifdef DDXOSVERRORF
|
|
if (!OsVendorVErrorFProc)
|
|
OsVendorVErrorFProc = OsVendorVErrorF;
|
|
#endif
|
|
|
|
if (!g_fLogInited) {
|
|
/* keep this order. If LogInit fails it calls Abort which then calls
|
|
* ddxGiveUp where LogInit is called again and creates an infinite
|
|
* recursion. If we set g_fLogInited to TRUE before the init we
|
|
* avoid the second call
|
|
*/
|
|
g_fLogInited = TRUE;
|
|
LogInit (g_pszLogFile, NULL);
|
|
}
|
|
LogSetParameter (XLOG_FLUSH, 1);
|
|
LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose);
|
|
LogSetParameter (XLOG_FILE_VERBOSITY, 1);
|
|
|
|
/* Log the version information */
|
|
if (serverGeneration == 1)
|
|
winLogVersionInfo ();
|
|
|
|
winCheckMount();
|
|
|
|
/* Add a default screen if no screens were specified */
|
|
if (g_iNumScreens == 0)
|
|
{
|
|
winDebug ("OsVendorInit - Creating bogus screen 0\n");
|
|
|
|
/*
|
|
* We need to initialize default screens if no arguments
|
|
* were processed. Otherwise, the default screens would
|
|
* already have been initialized by ddxProcessArgument ().
|
|
*/
|
|
winInitializeDefaultScreens ();
|
|
|
|
/*
|
|
* Add a screen 0 using the defaults set by
|
|
* winInitializeDefaultScreens () and any additional parameters
|
|
* processed by ddxProcessArgument ().
|
|
*/
|
|
g_iNumScreens = 1;
|
|
g_iLastScreen = 0;
|
|
|
|
/* We have to flag this as an explicit screen, even though it isn't */
|
|
g_ScreenInfo[0].fExplicitScreen = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
winUseMsg (void)
|
|
{
|
|
ErrorF ("-depth bits_per_pixel\n"
|
|
"\tSpecify an optional bitdepth to use in fullscreen mode\n"
|
|
"\twith a DirectDraw engine.\n");
|
|
|
|
ErrorF ("-emulate3buttons [timeout]\n"
|
|
"\tEmulate 3 button mouse with an optional timeout in\n"
|
|
"\tmilliseconds.\n");
|
|
|
|
ErrorF ("-engine engine_type_id\n"
|
|
"\tOverride the server's automatically selected engine type:\n"
|
|
"\t\t1 - Shadow GDI\n"
|
|
"\t\t2 - Shadow DirectDraw\n"
|
|
"\t\t4 - Shadow DirectDraw4 Non-Locking\n"
|
|
#ifdef XWIN_NATIVEGDI
|
|
"\t\t16 - Native GDI - experimental\n"
|
|
#endif
|
|
);
|
|
|
|
ErrorF ("-fullscreen\n"
|
|
"\tRun the server in fullscreen mode.\n");
|
|
|
|
ErrorF ("-refresh rate_in_Hz\n"
|
|
"\tSpecify an optional refresh rate to use in fullscreen mode\n"
|
|
"\twith a DirectDraw engine.\n");
|
|
|
|
ErrorF ("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n"
|
|
"\tEnable screen scr_num and optionally specify a width and\n"
|
|
"\theight and initial position for that screen. Additionally\n"
|
|
"\ta monitor number can be specified to start the server on,\n"
|
|
"\tat which point, all coordinates become relative to that\n"
|
|
"\tmonitor (Not for Windows NT4 and 95). Examples:\n"
|
|
"\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n"
|
|
"\t -screen 0 1024x768@3 ; 3rd monitor size 1024x768\n"
|
|
"\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n");
|
|
|
|
ErrorF ("-lesspointer\n"
|
|
"\tHide the windows mouse pointer when it is over an inactive\n"
|
|
"\t" PROJECT_NAME " window. This prevents ghost cursors appearing where\n"
|
|
"\tthe Windows cursor is drawn overtop of the X cursor\n");
|
|
|
|
ErrorF ("-nodecoration\n"
|
|
"\tDo not draw a window border, title bar, etc. Windowed\n"
|
|
"\tmode only.\n");
|
|
|
|
#ifdef XWIN_MULTIWINDOWEXTWM
|
|
ErrorF ("-mwextwm\n"
|
|
"\tRun the server in multi-window external window manager mode.\n");
|
|
|
|
ErrorF ("-internalwm\n"
|
|
"\tRun the internal window manager.\n");
|
|
#endif
|
|
|
|
ErrorF ("-rootless\n"
|
|
"\tRun the server in rootless mode.\n");
|
|
|
|
#ifdef XWIN_MULTIWINDOW
|
|
ErrorF ("-multiwindow\n"
|
|
"\tRun the server in multi-window mode.\n");
|
|
#endif
|
|
|
|
ErrorF ("-multiplemonitors\n"
|
|
"\tEXPERIMENTAL: Use the entire virtual screen if multiple\n"
|
|
"\tmonitors are present.\n");
|
|
|
|
#ifdef XWIN_CLIPBOARD
|
|
ErrorF ("-clipboard\n"
|
|
"\tRun the clipboard integration module.\n"
|
|
"\tDo not use at the same time as 'xwinclip'.\n");
|
|
|
|
ErrorF ("-nounicodeclipboard\n"
|
|
"\tDo not use Unicode clipboard even if NT-based platform.\n");
|
|
#endif
|
|
|
|
ErrorF ("-scrollbars\n"
|
|
"\tIn windowed mode, allow screens bigger than the Windows desktop.\n"
|
|
"\tMoreover, if the window has decorations, one can now resize\n"
|
|
"\tit.\n");
|
|
|
|
ErrorF ("-[no]trayicon\n"
|
|
"\tDo not create a tray icon. Default is to create one\n"
|
|
"\ticon per screen. You can globally disable tray icons with\n"
|
|
"\t-notrayicon, then enable it for specific screens with\n"
|
|
"\t-trayicon for those screens.\n");
|
|
|
|
ErrorF ("-clipupdates num_boxes\n"
|
|
"\tUse a clipping region to constrain shadow update blits to\n"
|
|
"\tthe updated region when num_boxes, or more, are in the\n"
|
|
"\tupdated region. Currently supported only by `-engine 1'.\n");
|
|
|
|
#ifdef XWIN_EMULATEPSEUDO
|
|
ErrorF ("-emulatepseudo\n"
|
|
"\tCreate a depth 8 PseudoColor visual when running in\n"
|
|
"\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
|
|
"\tdepths. The PseudoColor visual does not have correct colors,\n"
|
|
"\tand it may crash, but it at least allows you to run your\n"
|
|
"\tapplication in TrueColor modes.\n");
|
|
#endif
|
|
|
|
ErrorF ("-[no]unixkill\n"
|
|
"\tCtrl+Alt+Backspace exits the X Server.\n");
|
|
|
|
ErrorF ("-[no]winkill\n"
|
|
"\tAlt+F4 exits the X Server.\n");
|
|
|
|
#ifdef XWIN_XF86CONFIG
|
|
ErrorF ("-config\n"
|
|
"\tSpecify a configuration file.\n");
|
|
|
|
ErrorF ("-keyboard\n"
|
|
"\tSpecify a keyboard device from the configuration file.\n");
|
|
#endif
|
|
|
|
#ifdef XKB
|
|
ErrorF ("-xkbrules XKBRules\n"
|
|
"\tEquivalent to XKBRules in XF86Config files.\n");
|
|
|
|
ErrorF ("-xkbmodel XKBModel\n"
|
|
"\tEquivalent to XKBModel in XF86Config files.\n");
|
|
|
|
ErrorF ("-xkblayout XKBLayout\n"
|
|
"\tEquivalent to XKBLayout in XF86Config files.\n"
|
|
"\tFor example: -xkblayout de\n");
|
|
|
|
ErrorF ("-xkbvariant XKBVariant\n"
|
|
"\tEquivalent to XKBVariant in XF86Config files.\n"
|
|
"\tFor example: -xkbvariant nodeadkeys\n");
|
|
|
|
ErrorF ("-xkboptions XKBOptions\n"
|
|
"\tEquivalent to XKBOptions in XF86Config files.\n");
|
|
#endif
|
|
|
|
ErrorF ("-logfile filename\n"
|
|
"\tWrite logmessages to <filename> instead of /tmp/Xwin.log.\n");
|
|
|
|
ErrorF ("-logverbose verbosity\n"
|
|
"\tSet the verbosity of logmessages. [NOTE: Only a few messages\n"
|
|
"\trespect the settings yet]\n"
|
|
"\t\t0 - only print fatal error.\n"
|
|
"\t\t1 - print additional configuration information.\n"
|
|
"\t\t2 - print additional runtime information [default].\n"
|
|
"\t\t3 - print debugging and tracing information.\n");
|
|
|
|
ErrorF ("-[no]keyhook\n"
|
|
"\tGrab special windows key combinations like Alt-Tab or the Menu "
|
|
"key.\n These keys are discarded by default.\n");
|
|
|
|
ErrorF ("-swcursor\n"
|
|
"\tDisable the usage of the windows cursor and use the X11 software "
|
|
"cursor instead\n");
|
|
}
|
|
|
|
/* See Porting Layer Definition - p. 57 */
|
|
void
|
|
ddxUseMsg(void)
|
|
{
|
|
/* Set a flag so that FatalError won't give duplicate warning message */
|
|
g_fSilentFatalError = TRUE;
|
|
|
|
winUseMsg();
|
|
|
|
/* Log file will not be opened for UseMsg unless we open it now */
|
|
if (!g_fLogInited) {
|
|
LogInit (g_pszLogFile, NULL);
|
|
g_fLogInited = TRUE;
|
|
}
|
|
LogClose ();
|
|
|
|
/* Notify user where UseMsg text can be found.*/
|
|
if (!g_fNoHelpMessageBox)
|
|
winMessageBoxF ("The " PROJECT_NAME " help text has been printed to "
|
|
"/tmp/XWin.log.\n"
|
|
"Please open /tmp/XWin.log to read the help text.\n",
|
|
MB_ICONINFORMATION);
|
|
}
|
|
|
|
/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
|
|
void ddxInitGlobals(void)
|
|
{
|
|
}
|
|
|
|
/* See Porting Layer Definition - p. 20 */
|
|
/*
|
|
* Do any global initialization, then initialize each screen.
|
|
*
|
|
* NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv
|
|
*/
|
|
|
|
void
|
|
InitOutput (ScreenInfo *screenInfo, int argc, char *argv[])
|
|
{
|
|
int i;
|
|
|
|
/* Log the command line */
|
|
winLogCommandLine (argc, argv);
|
|
|
|
#if CYGDEBUG
|
|
winDebug ("InitOutput\n");
|
|
#endif
|
|
|
|
/* Validate command-line arguments */
|
|
if (serverGeneration == 1 && !winValidateArgs ())
|
|
{
|
|
FatalError ("InitOutput - Invalid command-line arguments found. "
|
|
"Exiting.\n");
|
|
}
|
|
|
|
/* Check for duplicate invocation on same display number.*/
|
|
if (serverGeneration == 1 && !winCheckDisplayNumber ())
|
|
{
|
|
if (g_fSilentDupError)
|
|
g_fSilentFatalError = TRUE;
|
|
FatalError ("InitOutput - Duplicate invocation on display "
|
|
"number: %s. Exiting.\n", display);
|
|
}
|
|
|
|
#ifdef XWIN_XF86CONFIG
|
|
/* Try to read the xorg.conf-style configuration file */
|
|
if (!winReadConfigfile ())
|
|
winErrorFVerb (1, "InitOutput - Error reading config file\n");
|
|
#else
|
|
winMsg(X_INFO, "XF86Config is not supported\n");
|
|
winMsg(X_INFO, "See http://x.cygwin.com/docs/faq/cygwin-x-faq.html "
|
|
"for more information\n");
|
|
winConfigFiles ();
|
|
#endif
|
|
|
|
/* Load preferences from XWinrc file */
|
|
LoadPreferences();
|
|
|
|
/* Setup global screen info parameters */
|
|
screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
|
|
screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
|
|
screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
|
|
screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
|
|
screenInfo->numPixmapFormats = NUMFORMATS;
|
|
|
|
/* Describe how we want common pixmap formats padded */
|
|
for (i = 0; i < NUMFORMATS; i++)
|
|
{
|
|
screenInfo->formats[i] = g_PixmapFormats[i];
|
|
}
|
|
|
|
/* Load pointers to DirectDraw functions */
|
|
winGetDDProcAddresses ();
|
|
|
|
/* Detect supported engines */
|
|
winDetectSupportedEngines ();
|
|
|
|
/* Load common controls library */
|
|
g_hmodCommonControls = LoadLibraryEx ("comctl32.dll", NULL, 0);
|
|
|
|
/* Load TrackMouseEvent function pointer */
|
|
g_fpTrackMouseEvent = GetProcAddress (g_hmodCommonControls,
|
|
"_TrackMouseEvent");
|
|
if (g_fpTrackMouseEvent == NULL)
|
|
{
|
|
winErrorFVerb (1, "InitOutput - Could not get pointer to function\n"
|
|
"\t_TrackMouseEvent in comctl32.dll. Try installing\n"
|
|
"\tInternet Explorer 3.0 or greater if you have not\n"
|
|
"\talready.\n");
|
|
|
|
/* Free the library since we won't need it */
|
|
FreeLibrary (g_hmodCommonControls);
|
|
g_hmodCommonControls = NULL;
|
|
|
|
/* Set function pointer to point to no operation function */
|
|
g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
|
|
}
|
|
|
|
/* Store the instance handle */
|
|
g_hInstance = GetModuleHandle (NULL);
|
|
|
|
/* Initialize each screen */
|
|
for (i = 0; i < g_iNumScreens; ++i)
|
|
{
|
|
/* Initialize the screen */
|
|
if (-1 == AddScreen (winScreenInit, argc, argv))
|
|
{
|
|
FatalError ("InitOutput - Couldn't add screen %d", i);
|
|
}
|
|
}
|
|
|
|
#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
|
|
|
|
#if defined(XCSECURITY)
|
|
/* Generate a cookie used by internal clients for authorization */
|
|
if (g_fXdmcpEnabled)
|
|
winGenerateAuthorization ();
|
|
#endif
|
|
|
|
/* Perform some one time initialization */
|
|
if (1 == serverGeneration)
|
|
{
|
|
/*
|
|
* setlocale applies to all threads in the current process.
|
|
* Apply locale specified in LANG environment variable.
|
|
*/
|
|
setlocale (LC_ALL, "");
|
|
}
|
|
#endif
|
|
|
|
#if CYGDEBUG || YES
|
|
winDebug ("InitOutput - Returning.\n");
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* winCheckDisplayNumber - Check if another instance of Cygwin/X is
|
|
* already running on the same display number. If no one exists,
|
|
* make a mutex to prevent new instances from running on the same display.
|
|
*
|
|
* return FALSE if the display number is already used.
|
|
*/
|
|
|
|
static Bool
|
|
winCheckDisplayNumber ()
|
|
{
|
|
int nDisp;
|
|
HANDLE mutex;
|
|
char name[MAX_PATH];
|
|
char * pszPrefix = '\0';
|
|
OSVERSIONINFO osvi = {0};
|
|
|
|
/* Check display range */
|
|
nDisp = atoi (display);
|
|
if (nDisp < 0 || nDisp > 65535)
|
|
{
|
|
ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Set first character of mutex name to null */
|
|
name[0] = '\0';
|
|
|
|
/* Get operating system version information */
|
|
osvi.dwOSVersionInfoSize = sizeof (osvi);
|
|
GetVersionEx (&osvi);
|
|
|
|
/* Want a mutex shared among all terminals on NT > 4.0 */
|
|
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT
|
|
&& osvi.dwMajorVersion >= 5)
|
|
{
|
|
pszPrefix = "Global\\";
|
|
}
|
|
|
|
/* Setup Cygwin/X specific part of name */
|
|
snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp);
|
|
|
|
/* Windows automatically releases the mutex when this process exits */
|
|
mutex = CreateMutex (NULL, FALSE, name);
|
|
if (!mutex)
|
|
{
|
|
LPVOID lpMsgBuf;
|
|
|
|
/* Display a fancy error message */
|
|
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
GetLastError (),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPTSTR) &lpMsgBuf,
|
|
0, NULL);
|
|
ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n",
|
|
(LPSTR)lpMsgBuf);
|
|
LocalFree (lpMsgBuf);
|
|
|
|
return FALSE;
|
|
}
|
|
if (GetLastError () == ERROR_ALREADY_EXISTS)
|
|
{
|
|
ErrorF ("winCheckDisplayNumber - "
|
|
PROJECT_NAME " is already running on display %d\n",
|
|
nDisp);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef DPMSExtension
|
|
Bool DPMSSupported(void)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
void DPMSSet(int level)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int DPMSGet(int *plevel)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|