diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xwin')
26 files changed, 5226 insertions, 210 deletions
diff --git a/xc/programs/Xserver/hw/xwin/Imakefile b/xc/programs/Xserver/hw/xwin/Imakefile index 9d619501b..08699ab16 100644 --- a/xc/programs/Xserver/hw/xwin/Imakefile +++ b/xc/programs/Xserver/hw/xwin/Imakefile @@ -1,5 +1,5 @@ XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $ -XCOMM $XFree86: xc/programs/Xserver/hw/xwin/Imakefile,v 1.14 2002/10/17 08:18:18 alanh Exp $ +XCOMM $XFree86: xc/programs/Xserver/hw/xwin/Imakefile,v 1.15 2003/02/12 15:01:38 alanh Exp $ #include <Server.tmpl> @@ -44,7 +44,15 @@ SRCS = InitInput.c \ wincreatewnd.c \ winregistry.c \ winconfig.c \ - winmsg.c + winmsg.c \ + winmultiwindowwindow.c \ + winmultiwindowwm.c \ + winclipboardinit.c \ + winclipboardtextconv.c \ + winclipboardthread.c \ + winclipboardunicode.c \ + winclipboardwndproc.c \ + winclipboardxevents.c /* * NOTE: The windialogs.rc file is compiled into windialogs.res. @@ -89,7 +97,15 @@ OBJS = InitInput.o \ wincreatewnd.o \ winregistry.o \ winconfig.o \ - winmsg.o + winmsg.o \ + winmultiwindowwindow.o \ + winmultiwindowwm.o \ + winclipboardinit.o \ + winclipboardtextconv.o \ + winclipboardthread.o \ + winclipboardunicode.o \ + winclipboardwndproc.o \ + winclipboardxevents.o INCLUDES = -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ -I$(SERVERSRC)/fb -I$(SERVERSRC)/mi \ diff --git a/xc/programs/Xserver/hw/xwin/InitInput.c b/xc/programs/Xserver/hw/xwin/InitInput.c index 17b2edee0..a9f69aad5 100644 --- a/xc/programs/Xserver/hw/xwin/InitInput.c +++ b/xc/programs/Xserver/hw/xwin/InitInput.c @@ -26,7 +26,7 @@ from The Open Group. */ -/* $XFree86: xc/programs/Xserver/hw/xwin/InitInput.c,v 1.11 2002/07/05 09:19:25 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/InitInput.c,v 1.12 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -57,14 +57,14 @@ LegalModifier (unsigned int uiKey, DevicePtr pDevice) void ProcessInputEvents (void) { -#if CYGDEBUG +#if 0 ErrorF ("ProcessInputEvents\n"); #endif mieqProcessInputEvents (); miPointerUpdate (); -#if CYGDEBUG +#if 0 ErrorF ("ProcessInputEvents - returning\n"); #endif } diff --git a/xc/programs/Xserver/hw/xwin/InitOutput.c b/xc/programs/Xserver/hw/xwin/InitOutput.c index 29db17790..c434e58d1 100644 --- a/xc/programs/Xserver/hw/xwin/InitOutput.c +++ b/xc/programs/Xserver/hw/xwin/InitOutput.c @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/programs/Xserver/hw/xwin/InitOutput.c,v 1.30 2002/10/17 08:18:19 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/InitOutput.c,v 1.32 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" #include "winconfig.h" @@ -44,12 +44,14 @@ int g_iScreenPrivateIndex = -1; int g_iCmapPrivateIndex = -1; int g_iGCPrivateIndex = -1; int g_iPixmapPrivateIndex = -1; +int g_iWindowPrivateIndex = -1; unsigned long g_ulServerGeneration = 0; Bool g_fInitializedDefaultScreens = FALSE; FILE *g_pfLog = NULL; DWORD g_dwEnginesSupported = 0; HINSTANCE g_hInstance = 0; HWND g_hDlgDepthChange = NULL; +Bool g_fCalledSetLocale = FALSE; /* @@ -114,6 +116,10 @@ winInitializeDefaultScreens (void) ZeroMemory (g_ScreenInfo, MAXSCREENS * sizeof (winScreenInfo)); /* Get default width and height */ + /* + * NOTE: These defaults will cause the window to cover only + * the primary monitor in the case that we have multiple monitors. + */ dwWidth = GetSystemMetrics (SM_CXSCREEN); dwHeight = GetSystemMetrics (SM_CYSCREEN); @@ -128,6 +134,8 @@ winInitializeDefaultScreens (void) g_ScreenInfo[i].dwScreen = i; g_ScreenInfo[i].dwWidth = dwWidth; g_ScreenInfo[i].dwHeight = dwHeight; + g_ScreenInfo[i].dwUserWidth = dwWidth; + g_ScreenInfo[i].dwUserHeight = dwHeight; g_ScreenInfo[i].fUserGaveHeightAndWidth = WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH; g_ScreenInfo[i].dwBPP = WIN_DEFAULT_BPP; @@ -138,6 +146,9 @@ winInitializeDefaultScreens (void) g_ScreenInfo[i].fFullScreen = FALSE; g_ScreenInfo[i].fDecoration = TRUE; g_ScreenInfo[i].fRootless = FALSE; + g_ScreenInfo[i].fMultiWindow = FALSE; + g_ScreenInfo[i].fMultipleMonitors = FALSE; + g_ScreenInfo[i].fClipboard = FALSE; g_ScreenInfo[i].fLessPointer = FALSE; g_ScreenInfo[i].fScrollbars = FALSE; g_ScreenInfo[i].iE3BTimeout = WIN_E3B_OFF; @@ -302,6 +313,16 @@ ddxUseMsg (void) ErrorF ("-rootless\n" "\tEXPERIMENTAL: Run the server in pseudo-rootless mode.\n"); + ErrorF ("-multiwindow\n" + "\tEXPERIMENTAL: Run the server in multi-window mode.\n"); + + ErrorF ("-multiplemonitors\n" + "\tEXPERIMENTAL: Use the entire virtual screen if multiple\n" + "\tmonitors are present.\n"); + + ErrorF ("-clipboard\n" + "\tEXPERIMENTAL: Run the clipboard integration module.\n"); + 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" @@ -436,6 +457,8 @@ ddxProcessArgument (int argc, char *argv[], int i) g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE; g_ScreenInfo[nScreenNum].dwWidth = iWidth; g_ScreenInfo[nScreenNum].dwHeight = iHeight; + g_ScreenInfo[nScreenNum].dwUserWidth = iWidth; + g_ScreenInfo[nScreenNum].dwUserHeight = iHeight; } else if (i + 3 < argc && 1 == sscanf (argv[i + 2], "%d", @@ -448,6 +471,8 @@ ddxProcessArgument (int argc, char *argv[], int i) g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE; g_ScreenInfo[nScreenNum].dwWidth = iWidth; g_ScreenInfo[nScreenNum].dwHeight = iHeight; + g_ScreenInfo[nScreenNum].dwUserWidth = iWidth; + g_ScreenInfo[nScreenNum].dwUserHeight = iHeight; } else { @@ -652,6 +677,59 @@ ddxProcessArgument (int argc, char *argv[], int i) } /* + * Look for the '-multiwindow' argument + */ + if (strcmp (argv[i], "-multiwindow") == 0) + { + /* Is this parameter attached to a screen or is it global? */ + if (-1 == g_iLastScreen) + { + int j; + + /* Parameter is for all screens */ + for (j = 0; j < MAXSCREENS; j++) + { + g_ScreenInfo[j].fMultiWindow = TRUE; + } + } + else + { + /* Parameter is for a single screen */ + g_ScreenInfo[g_iLastScreen].fMultiWindow = TRUE; + } + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-multiplemonitors' argument + */ + if (strcmp (argv[i], "-multiplemonitors") == 0 + || strcmp (argv[i], "-multimonitors") == 0) + { + /* Is this parameter attached to a screen or is it global? */ + if (-1 == g_iLastScreen) + { + int j; + + /* Parameter is for all screens */ + for (j = 0; j < MAXSCREENS; j++) + { + g_ScreenInfo[j].fMultipleMonitors = TRUE; + } + } + else + { + /* Parameter is for a single screen */ + g_ScreenInfo[g_iLastScreen].fMultipleMonitors = TRUE; + } + + /* Indicate that we have processed this argument */ + return 1; + } + + /* * Look for the '-scrollbars' argument */ if (strcmp (argv[i], "-scrollbars") == 0) @@ -684,6 +762,32 @@ ddxProcessArgument (int argc, char *argv[], int i) } /* + * Look for the '-clipboard' argument + */ + if (strcmp (argv[i], "-clipboard") == 0) + { + /* Is this parameter attached to a screen or is it global? */ + if (-1 == g_iLastScreen) + { + int j; + + /* Parameter is for all screens */ + for (j = 0; j < MAXSCREENS; j++) + { + g_ScreenInfo[j].fClipboard = TRUE; + } + } + else + { + /* Parameter is for a single screen */ + g_ScreenInfo[g_iLastScreen].fClipboard = TRUE; + } + + /* Indicate that we have processed this argument */ + return 1; + } + + /* * Look for the '-ignoreinput' argument */ if (strcmp (argv[i], "-ignoreinput") == 0) @@ -1144,9 +1248,14 @@ InitOutput (ScreenInfo *screenInfo, int argc, char *argv[]) /* 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 CYGDEBUG || YES + ErrorF ("InitOutput - Returning.\n"); +#endif } diff --git a/xc/programs/Xserver/hw/xwin/win.h b/xc/programs/Xserver/hw/xwin/win.h index 1883ebb0d..684e98cc1 100644 --- a/xc/programs/Xserver/hw/xwin/win.h +++ b/xc/programs/Xserver/hw/xwin/win.h @@ -29,39 +29,32 @@ * Suhaib M Siddiqi * Peter Busch * Harold L Hunt II - * MATSUZAKI Kensuke + * Kensuke Matsuzaki */ -/* $XFree86: xc/programs/Xserver/hw/xwin/win.h,v 1.31 2002/10/17 08:18:21 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/win.h,v 1.34 2003/02/12 15:01:38 alanh Exp $ */ #ifndef _WIN_H_ #define _WIN_H_ #ifndef NO -#define NO 0 +#define NO 0 #endif #ifndef YES -#define YES 1 +#define YES 1 #endif /* * Build toggles for experimental features */ -#define WIN_NATIVE_GDI_SUPPORT YES -#define WIN_LAYER_SUPPORT NO -#define WIN_NEW_KEYBOARD_SUPPORT NO -#define WIN_EMULATE_PSEUDO_SUPPORT YES -#define WIN_UPDATE_STATS NO +#define WIN_NATIVE_GDI_SUPPORT YES +#define WIN_LAYER_SUPPORT NO +#define WIN_NEW_KEYBOARD_SUPPORT NO +#define WIN_EMULATE_PSEUDO_SUPPORT YES +#define WIN_UPDATE_STATS NO /* Turn debug messages on or off */ -#define CYGDEBUG NO - -/* Constant strings */ -#define WINDOW_CLASS "cygwin/xfree86" -#define WINDOW_TITLE "Cygwin/XFree86" -#define WIN_SCR_PROP "cyg_screen_prop" -#define WIN_MSG_QUEUE_FNAME "/dev/windows" -#define WIN_LOG_FNAME "/tmp/XWin.log" +#define CYGDEBUG NO #define NEED_EVENTS @@ -84,12 +77,12 @@ /* * Windows only supports 256 color palettes */ -#define WIN_NUM_PALETTE_ENTRIES 256 +#define WIN_NUM_PALETTE_ENTRIES 256 /* * Number of times to call Restore in an attempt to restore the primary surface */ -#define WIN_REGAIN_SURFACE_RETRIES 1 +#define WIN_REGAIN_SURFACE_RETRIES 1 /* * Build a supported display depths mask by shifting one to the left @@ -132,6 +125,7 @@ #include <sys/stat.h> #include <stdio.h> #include <errno.h> +#include <pthread.h> #include <X11/XWDFile.h> @@ -189,6 +183,13 @@ #include "winms.h" +/* + * Multi-Window Window Manager header + */ + +#include "winwindow.h" + + /* Cygwin's winuser.h does not define VK_KANA as of 28Mar2001 */ /* NOTE: Cygwin's winuser.h was fixed shortly after 28Mar2001. */ #ifndef VK_KANA @@ -286,16 +287,6 @@ typedef Bool (*winReleasePrimarySurfaceProcPtr)(ScreenPtr); /* - * Window privates - */ - -typedef struct -{ - DWORD dwDummy; -} winPrivWinRec, *winPrivWinPtr; - - -/* * GC (graphics context) privates */ @@ -342,7 +333,7 @@ typedef struct { DWORD dwXKeycodes[WIN_MAX_KEYS_PER_KEY]; DWORD dwReleaseModifiers; -} winKeyEventsRec, winKeyEventsPtr; +} winKeyEventsRec, *winKeyEventsPtr; #endif /* WIN_NEW_KEYBOARD_SUPPORT */ @@ -359,7 +350,12 @@ typedef struct Bool fUserGaveHeightAndWidth; DWORD dwScreen; + DWORD dwUserWidth; + DWORD dwUserHeight; DWORD dwWidth; + DWORD dwHeight; + DWORD dwWidth_mm; + DWORD dwHeight_mm; DWORD dwPaddedWidth; /* @@ -368,9 +364,6 @@ typedef struct * a rounding up of the width. */ DWORD dwStride; - DWORD dwHeight; - DWORD dwWidth_mm; - DWORD dwHeight_mm; /* Offset of the screen in the window when using scrollbars */ DWORD dwXOffset; @@ -389,6 +382,9 @@ typedef struct Bool fFullScreen; Bool fDecoration; Bool fRootless; + Bool fMultiWindow; + Bool fMultipleMonitors; + Bool fClipboard; Bool fLessPointer; Bool fScrollbars; int iE3BTimeout; @@ -406,7 +402,7 @@ typedef struct * Screen privates */ -typedef struct +typedef struct _winPrivScreenRec { winScreenInfoPtr pScreenInfo; @@ -414,7 +410,7 @@ typedef struct Bool fClosed; Bool fActive; Bool fBadDepth; - + int iDeltaZ; CloseScreenProcPtr CloseScreen; @@ -427,9 +423,13 @@ typedef struct DWORD dwModeKeyStates; /* Clipboard support */ + pthread_t ptClipboardProc; + +#if 0 HWND hwndNextViewer; void *display; int window; +#endif /* Last width, height, and depth of the Windows display */ DWORD dwLastWindowsWidth; @@ -480,6 +480,14 @@ typedef struct /* Privates used by both shadow fb DirectDraw servers */ LPDIRECTDRAWCLIPPER pddcPrimary; + /* Privates used by multi-window server */ + pthread_t ptWMProc; + void *pWMInfo; + + /* Privates used for any module running in a seperate thread */ + pthread_mutex_t pmServerStarted; + Bool fServerStarted; + /* Engine specific functions */ winAllocateFBProcPtr pwinAllocateFB; winShadowUpdateProcPtr pwinShadowUpdate; @@ -516,7 +524,11 @@ typedef struct ClearToBackgroundProcPtr ClearToBackground; ClipNotifyProcPtr ClipNotify; RestackWindowProcPtr RestackWindow; -} winPrivScreenRec, *winPrivScreenPtr; + ReparentWindowProcPtr ReparentWindow; +#ifdef SHAPE + SetShapeProcPtr SetShape; +#endif +} winPrivScreenRec; /* @@ -531,12 +543,14 @@ extern int g_iScreenPrivateIndex; extern int g_iCmapPrivateIndex; extern int g_iGCPrivateIndex; extern int g_iPixmapPrivateIndex; +extern int g_iWindowPrivateIndex; extern unsigned long g_ulServerGeneration; extern CARD32 g_c32LastInputEventTime; extern DWORD g_dwEnginesSupported; extern HINSTANCE g_hInstance; extern HWND g_hDlgDepthChange; + /* * Extern declares for dynamically loaded libraries and function pointers */ @@ -609,8 +623,14 @@ extern FARPROC g_fpTrackMouseEvent; * Window privates macros */ -#define winGetWindowPrivate(_pWin) ((winPrivWin *)\ - (_pWin)->devPrivates[winWindowPrivateIndex].ptr) +#define winGetWindowPriv(pWin) \ + ((winPrivWinPtr) (pWin)->devPrivates[g_iWindowPrivateIndex].ptr) + +#define winSetWindowPriv(pWin,v) \ + ((pWin)->devPrivates[g_iWindowPrivateIndex].ptr = (pointer) v) + +#define winWindowPriv(pWin) \ + winPrivWinPtr pWinPriv = winGetWindowPriv(pWin) /* @@ -675,6 +695,16 @@ winPixmapToRegionNativeGDI (PixmapPtr pPix); /* + * winclipboardinit.c + */ + +Bool +winInitClipboard (pthread_t *ptClipboardProc, + pthread_mutex_t *ppmServerStarted, + DWORD dwScreen); + + +/* * wincmap.c */ @@ -905,8 +935,7 @@ winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations); Bool winRandRSetConfig (ScreenPtr pScreen, Rotation rotateKind, - RRScreenSizePtr pSize, - RRVisualGroupPtr pVisualGroup); + RRScreenSizePtr pSize); Bool winRandRInit (ScreenPtr pScreen); @@ -1341,6 +1370,45 @@ winUnmapWindowPRootless (WindowPtr pWindow); Bool winMapWindowPRootless (WindowPtr pWindow); +#ifdef SHAPE +void +winSetShapePRootless (WindowPtr pWindow); +#endif + + +/* + * winmultiwindowwindow.c + */ + +Bool +winCreateWindowMultiWindow (WindowPtr pWindow); + +Bool +winDestroyWindowMultiWindow (WindowPtr pWindow); + +Bool +winPositionWindowMultiWindow (WindowPtr pWindow, int x, int y); + +Bool +winChangeWindowAttributesMultiWindow (WindowPtr pWindow, unsigned long mask); + +Bool +winUnmapWindowMultiWindow (WindowPtr pWindow); + +Bool +winMapWindowMultiWindow (WindowPtr pWindow); + +void +winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent); + +void +winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib); + +#ifdef SHAPE +void +winSetShapeMultiWindow (WindowPtr pWindow); +#endif + /* * winwndproc.c diff --git a/xc/programs/Xserver/hw/xwin/winallpriv.c b/xc/programs/Xserver/hw/xwin/winallpriv.c index fc32b9c86..a27309598 100644 --- a/xc/programs/Xserver/hw/xwin/winallpriv.c +++ b/xc/programs/Xserver/hw/xwin/winallpriv.c @@ -28,7 +28,7 @@ * Authors: Keith Packard, MIT X Consortium * Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winallpriv.c,v 1.11 2002/10/17 08:18:21 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winallpriv.c,v 1.12 2002/10/31 23:04:39 alanh Exp $ */ #include "win.h" @@ -60,6 +60,7 @@ winAllocatePrivates (ScreenPtr pScreen) g_iScreenPrivateIndex = AllocateScreenPrivateIndex (); g_iGCPrivateIndex = AllocateGCPrivateIndex (); g_iPixmapPrivateIndex = AllocatePixmapPrivateIndex (); + g_iWindowPrivateIndex = AllocateWindowPrivateIndex (); g_ulServerGeneration = serverGeneration; } @@ -97,6 +98,14 @@ winAllocatePrivates (ScreenPtr pScreen) return FALSE; } + /* Reserve Window memory for our privates */ + if (!AllocateWindowPrivate (pScreen, g_iWindowPrivateIndex, + sizeof (winPrivWinRec))) + { + ErrorF ("winAllocatePrivates () - AllocateWindowPrivates () failed\n"); + return FALSE; + } + return TRUE; } diff --git a/xc/programs/Xserver/hw/xwin/winblock.c b/xc/programs/Xserver/hw/xwin/winblock.c index f10645662..45d509fea 100644 --- a/xc/programs/Xserver/hw/xwin/winblock.c +++ b/xc/programs/Xserver/hw/xwin/winblock.c @@ -27,7 +27,7 @@ * * Authors: Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winblock.c,v 1.5 2002/10/17 08:18:22 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winblock.c,v 1.6 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -41,6 +41,30 @@ winBlockHandler (int nScreen, winScreenPriv((ScreenPtr)pBlockData); MSG msg; + /* Signal threaded modules to begin */ + if (pScreenPriv != NULL && !pScreenPriv->fServerStarted) + { + int iReturn; + + ErrorF ("winBlockHandler - Releasing pmServerStarted\n"); + + /* Flag that modules are to be started */ + pScreenPriv->fServerStarted = TRUE; + + /* Unlock the mutex for threaded modules */ + iReturn = pthread_mutex_unlock (&pScreenPriv->pmServerStarted); + if (iReturn != 0) + { + ErrorF ("winBlockHandler - pthread_mutex_unlock () failed: %d\n", + iReturn); + goto winBlockHandler_ProcessMessages; + } + + ErrorF ("winBlockHandler - pthread_mutex_unlock () returned\n"); + } + +winBlockHandler_ProcessMessages: + /* Process all messages on our queue */ while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { diff --git a/xc/programs/Xserver/hw/xwin/winclipboard.h b/xc/programs/Xserver/hw/xwin/winclipboard.h new file mode 100644 index 000000000..6e6cf44a9 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winclipboard.h @@ -0,0 +1,158 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold Hunt + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboard.h,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + + +#ifndef _WINCLIPBOARD_H_ +#define _WINCLIPBOARD_H_ + +/* Standard library headers */ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/select.h> +#include <fcntl.h> +#include <setjmp.h> +#include <pthread.h> + +/* X headers */ +#include "X.h" +#include "Xatom.h" +/* NOTE: For some unknown reason, including Xproto.h solves + * tons of problems with including windows.h. Unknowns reasons + * are usually bad, so someone should investigate this. + */ +#include "Xproto.h" +#include "Xutil.h" +#include "Xlocale.h" + +/* Fixups to prevent collisions between Windows and X headers */ +#define ATOM DWORD + +/* Windows headers */ +#include <windows.h> + + +/* Clipboard module constants */ +#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip" +#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip" +#define WIN_MSG_QUEUE_FNAME "/dev/windows" +#define WIN_CONNECT_RETRIES 3 +#define WIN_CONNECT_DELAY 4 +#define WIN_JMP_OKAY 0 +#define WIN_JMP_ERROR_IO 2 + +/* + * Argument structure for Clipboard module main thread + */ + +typedef struct _ClipboardProcArgRec { + DWORD dwScreen; + pthread_mutex_t *ppmServerStarted; +} ClipboardProcArgRec, *ClipboardProcArgPtr; + + +/* + * References to external symbols + */ + +extern char *display; +extern void ErrorF (const char* /*f*/, ...); + + +/* + * winclipboardinit.c + */ + +Bool +winInitClipboard (pthread_t *ptClipboardProc, + pthread_mutex_t *ppmServerStarted, + DWORD dwScreen); + +HWND +winClipboardCreateMessagingWindow (); + + +/* + * winclipboardtextconv.c + */ + +void +winClipboardDOStoUNIX (char *pszData, int iLength); + +void +winClipboardUNIXtoDOS (unsigned char **ppszData, int iLength); + + +/* + * winclipboardthread.c + */ + +void * +winClipboardProc (void *pArg); + + +/* + * winclipboardunicode.c + */ + +Bool +winClipboardDetectUnicodeSupport (); + + +/* + * winclipboardwndproc.c + */ + +BOOL +winClipboardFlushWindowsMessageQueue (HWND hwnd); + +LRESULT CALLBACK +winClipboardWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); + + +/* + * winclipboardxevents.c + */ + +Bool +winClipboardFlushXEvents (HWND hwnd, + Atom atomClipboard, + Atom atomLocalProperty, + Atom atomUTF8String, + Atom atomCompoundText, + Atom atomTargets, + Atom atomDeleteWindow, + int iWindow, + Display *pDisplay, + Bool fUnicodeSupport); +#endif diff --git a/xc/programs/Xserver/hw/xwin/winclipboardinit.c b/xc/programs/Xserver/hw/xwin/winclipboardinit.c new file mode 100644 index 000000000..22c068c48 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winclipboardinit.c @@ -0,0 +1,117 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboardinit.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "winclipboard.h" + + +/* + * Intialize the Clipboard module + */ + +Bool +winInitClipboard (pthread_t *ptClipboardProc, + pthread_mutex_t *ppmServerStarted, + DWORD dwScreen) +{ + ClipboardProcArgPtr pArg; + + ErrorF ("winInitClipboard ()\n"); + + /* Allocate the parameter structure */ + pArg = (ClipboardProcArgPtr) malloc (sizeof (ClipboardProcArgRec)); + if (pArg == NULL) + { + ErrorF ("winInitClipboard - malloc for ClipboardProcArgRec failed.\n"); + return FALSE; + } + + /* Setup the argument structure for the thread function */ + pArg->dwScreen = dwScreen; + pArg->ppmServerStarted = ppmServerStarted; + + /* Spawn a thread for the Clipboard module */ + if (pthread_create (ptClipboardProc, NULL, winClipboardProc, pArg)) + { + /* Bail if thread creation failed */ + ErrorF ("winInitClipboard - pthread_create failed.\n"); + return FALSE; + } + + return TRUE; +} + + +/* + * Create the Windows window that we use to recieve Windows messages + */ + +HWND +winClipboardCreateMessagingWindow () +{ + WNDCLASS wc; + HWND hwnd; + + /* Setup our window class */ + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = winClipboardWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle (NULL); + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS; + RegisterClass (&wc); + + /* Create the window */ + hwnd = CreateWindowExA (0, /* Extended styles */ + WIN_CLIPBOARD_WINDOW_CLASS,/* Class name */ + WIN_CLIPBOARD_WINDOW_TITLE,/* Window name */ + WS_OVERLAPPED, /* Not visible anyway */ + CW_USEDEFAULT, /* Horizontal position */ + CW_USEDEFAULT, /* Vertical position */ + CW_USEDEFAULT, /* Right edge */ + CW_USEDEFAULT, /* Bottom edge */ + (HWND) NULL, /* No parent or owner window */ + (HMENU) NULL, /* No menu */ + GetModuleHandle (NULL),/* Instance handle */ + NULL); /* ScreenPrivates */ + assert (hwnd != NULL); + + /* I'm not sure, but we may need to call this to start message processing */ + ShowWindow (hwnd, SW_HIDE); + + /* Similarly, we may need a call to this even though we don't paint */ + UpdateWindow (hwnd); + + return hwnd; +} diff --git a/xc/programs/Xserver/hw/xwin/winclipboardtextconv.c b/xc/programs/Xserver/hw/xwin/winclipboardtextconv.c new file mode 100644 index 000000000..f97681c5f --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winclipboardtextconv.c @@ -0,0 +1,153 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboardtextconv.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "win.h" +#include <stdio.h> +#include <stdlib.h> + + +/* + * Convert \r\n to \n + * + * NOTE: This was heavily inspired by, if not down right stolen from, + * Cygwin's winsup/cygwin/fhandler.cc/fhandler_base::read () + */ + +void +winClipboardDOStoUNIX (char *pszSrc, int iLength) +{ + char *pszDest = pszSrc; + char *pszEnd = pszSrc + iLength; + + /* Loop until the last character */ + while (pszSrc < pszEnd) + { + /* Copy the current source character to current destination character */ + *pszDest = *pszSrc; + + /* Advance to the next source character */ + pszSrc++; + + /* Don't advance the destination character if we need to drop an \r */ + if (*pszDest != '\r' || *pszSrc != '\n') + pszDest++; + } + + /* Move the terminating null */ + *pszDest = '\0'; +} + + +/* + * Convert \n to \r\n + */ + +void +winClipboardUNIXtoDOS (unsigned char **ppszData, int iLength) +{ + int iNewlineCount = 0; + unsigned char *pszSrc = *ppszData; + unsigned char *pszEnd = pszSrc + iLength; + unsigned char *pszDest = NULL, *pszDestBegin = NULL; + +#if 0 + ErrorF ("UNIXtoDOS () - Original data:\n%s\n", *ppszData); +#endif + + /* Count \n characters without leading \r */ + while (pszSrc < pszEnd) + { + /* Skip ahead two character if found set of \r\n */ + if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') + { + pszSrc += 2; + continue; + } + + /* Increment the count if found naked \n */ + if (*pszSrc == '\n') + { + iNewlineCount++; + } + + pszSrc++; + } + + /* Return if no naked \n's */ + if (iNewlineCount == 0) + return; + + /* Allocate a new string */ + pszDestBegin = pszDest = malloc (iLength + iNewlineCount + 1); + + /* Set source pointer to beginning of data string */ + pszSrc = *ppszData; + + /* Loop through all characters in source string */ + while (pszSrc < pszEnd) + { + /* Copy line endings that are already valid */ + if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') + { + *pszDest = *pszSrc; + *(pszDest + 1) = *(pszSrc + 1); + pszDest += 2; + pszSrc += 2; + continue; + } + + /* Add \r to naked \n's */ + if (*pszSrc == '\n') + { + *pszDest = '\r'; + *(pszDest + 1) = *pszSrc; + pszDest += 2; + pszSrc += 1; + continue; + } + + /* Copy normal characters */ + *pszDest = *pszSrc; + pszSrc++; + pszDest++; + } + + /* Put terminating null at end of new string */ + *pszDest = '\0'; + + /* Swap string pointers */ + free (*ppszData); + *ppszData = pszDestBegin; + +#if 0 + ErrorF ("UNIXtoDOS () - Final string:\n%s\n", pszDestBegin); +#endif +} diff --git a/xc/programs/Xserver/hw/xwin/winclipboardthread.c b/xc/programs/Xserver/hw/xwin/winclipboardthread.c new file mode 100644 index 000000000..ce4590b98 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winclipboardthread.c @@ -0,0 +1,463 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboardthread.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "winclipboard.h" + +/* + * References to external symbols + */ + +extern Bool g_fCalledSetLocale; + + +/* + * Global variables + */ + +static jmp_buf g_jmpEntry; + + +/* + * Local function prototypes + */ + +static int +winClipboardErrorHandler (Display *pDisplay, XErrorEvent *pErr); + +static int +winClipboardIOErrorHandler (Display *pDisplay); + + +/* + * Main thread function + */ + +void * +winClipboardProc (void *pArg) +{ + Atom atomClipboard, atomClipboardManager; + Atom atomLocalProperty, atomCompoundText; + Atom atomUTF8String, atomTargets; + int iReturn; + HWND hwnd = NULL; + int iConnectionNumber; + int fdMessageQueue; + fd_set fdsRead; + int iMaxDescriptor; + Display *pDisplay; + Window iWindow; + Atom atomDeleteWindow; + Bool fReturn; + int iRetries; + Bool fUnicodeSupport; + char szDisplay[512]; + int i; + ClipboardProcArgPtr pProcArg = (ClipboardProcArgPtr) pArg; + + ErrorF ("winClipboardProc - Hello\n"); + + /* Check that argument pointer is not invalid */ + if (pArg == NULL) + { + ErrorF ("winClipboardProc - pArg is NULL, bailing.\n"); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - Calling pthread_mutex_lock ()\n"); + + /* Grab our garbage mutex to satisfy pthread_cond_wait */ + iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted); + if (iReturn != 0) + { + ErrorF ("winClipboardProc - pthread_mutex_lock () failed: %d\n", + iReturn); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - pthread_mutex_lock () returned.\n"); + + /* Do we have Unicode support? */ + fUnicodeSupport = winClipboardDetectUnicodeSupport (); + + /* Set the current locale? What does this do? */ + if (fUnicodeSupport && !g_fCalledSetLocale) + { + ErrorF ("winClipboardProc - Calling setlocale ()\n"); + if (!setlocale (LC_ALL, "")) + { + ErrorF ("winClipboardProc - setlocale () error\n"); + pthread_exit (NULL); + } + ErrorF ("winClipboardProc - setlocale () returned\n"); + + /* See if X supports the current locale */ + if (XSupportsLocale () == False) + { + ErrorF ("winClipboardProc - Locale not supported by X\n"); + pthread_exit (NULL); + } + } + + /* Flag that we have called setlocale */ + g_fCalledSetLocale = TRUE; + + /* Release the garbage mutex */ + pthread_mutex_unlock (pProcArg->ppmServerStarted); + + ErrorF ("winClipboardProc - pthread_mutex_unlock () returned.\n"); + + /* Allow multiple threads to access Xlib */ + if (XInitThreads () == 0) + { + ErrorF ("winClipboardProc - XInitThreads failed.\n"); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - XInitThreads () returned.\n"); + + /* Set jump point for Error exits */ + iReturn = setjmp (g_jmpEntry); + + /* Check if we should continue operations */ + if (iReturn != WIN_JMP_ERROR_IO + && iReturn != WIN_JMP_OKAY) + { + /* setjmp returned an unknown value, exit */ + ErrorF ("winClipboardProc - setjmp returned: %d exiting\n", + iReturn); + pthread_exit (NULL); + } + else if (iReturn == WIN_JMP_ERROR_IO) + { + ErrorF ("winClipboardProc - setjmp returned and hwnd: %08x\n", hwnd); + } + + /* Initialize retry count */ + iRetries = 0; + +#if 0 + /* Setup the display connection string x */ + snprintf (szDisplay, 512, "127.0.0.1:%s.%d", display, pProcArg->dwScreen); +#else + /* Setup the display connection string x */ + snprintf (szDisplay, 512, ":%s.%d", display, pProcArg->dwScreen); +#endif + + /* Print the display connection string */ + ErrorF ("winClipboardProc - DISPLAY=%s\n", szDisplay); + + /* Open the X display */ + do + { + pDisplay = XOpenDisplay (szDisplay); + if (pDisplay == NULL) + { + ErrorF ("winClipboardProc - Could not open display, " + "try: %d, sleeping: %d\n", + iRetries + 1, WIN_CONNECT_DELAY); + ++iRetries; + sleep (WIN_CONNECT_DELAY); + continue; + } + else + break; + } + while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); + + /* Make sure that the display opened */ + if (pDisplay == NULL) + { + ErrorF ("winClipboardProc - Failed opening the display, giving up\n"); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - XOpenDisplay () returned and " + "successfully opened the display.\n"); + + /* Create Windows messaging window */ + hwnd = winClipboardCreateMessagingWindow (); + + /* Get our connection number */ + iConnectionNumber = ConnectionNumber (pDisplay); + + /* Open a file descriptor for the windows message queue */ + fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, O_RDONLY); + if (fdMessageQueue == -1) + { + ErrorF ("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME); + pthread_exit (NULL); + } + + /* Find max of our file descriptors */ + iMaxDescriptor = max (fdMessageQueue, iConnectionNumber) + 1; + + /* Select event types to watch */ + if (XSelectInput (pDisplay, + DefaultRootWindow (pDisplay), + SubstructureNotifyMask | + StructureNotifyMask | + PropertyChangeMask) == BadWindow) + ErrorF ("winClipboardProc - XSelectInput generated BadWindow " + "on RootWindow\n\n"); + + /* Create a messaging window */ + iWindow = XCreateSimpleWindow (pDisplay, + DefaultRootWindow (pDisplay), + 1, 1, + 500, 500, + 0, + BlackPixel (pDisplay, 0), + BlackPixel (pDisplay, 0)); + if (iWindow == 0) + { + ErrorF ("winClipboardProc - Could not create a window\n"); + pthread_exit (NULL); + } + + /* This looks like our only hope for getting a message before shutdown */ + /* Register for WM_DELETE_WINDOW message from window manager */ + atomDeleteWindow = XInternAtom (pDisplay, "WM_DELETE_WINDOW", False); + XSetWMProtocols (pDisplay, iWindow, &atomDeleteWindow, 1); + + /* Set error handler */ + XSetErrorHandler (winClipboardErrorHandler); + XSetIOErrorHandler (winClipboardIOErrorHandler); + + /* Create an atom for CLIPBOARD_MANAGER */ + atomClipboardManager = XInternAtom (pDisplay, "CLIPBOARD_MANAGER", False); + if (atomClipboardManager == None) + { + ErrorF ("winClipboardProc - Could not create CLIPBOARD_MANAGER atom\n"); + pthread_exit (NULL); + } + + /* Assert ownership of CLIPBOARD_MANAGER */ + iReturn = XSetSelectionOwner (pDisplay, atomClipboardManager, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("winClipboardProc - Could not set CLIPBOARD_MANAGER owner\n"); + pthread_exit (NULL); + } + + /* Create an atom for CLIPBOARD */ + atomClipboard = XInternAtom (pDisplay, "CLIPBOARD", False); + if (atomClipboard == None) + { + ErrorF ("winClipboardProc - Could not create CLIPBOARD atom\n"); + pthread_exit (NULL); + } + + /* Assert ownership of CLIPBOARD */ + iReturn = XSetSelectionOwner (pDisplay, atomClipboard, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("winClipboardProc - Could not set CLIPBOARD owner\n"); + pthread_exit (NULL); + } + + /* Assert ownership of PRIMARY */ + iReturn = XSetSelectionOwner (pDisplay, XA_PRIMARY, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("winClipboardProc - Could not set PRIMARY owner\n"); + pthread_exit (NULL); + } + + /* Local property to hold pasted data */ + atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False); + if (atomLocalProperty == None) + { + ErrorF ("winClipboardProc - Could not create CYGX_CUT_BUFFER atom\n"); + pthread_exit (NULL); + } + + /* Create an atom for UTF8_STRING */ + atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False); + if (atomUTF8String == None) + { + ErrorF ("winClipboardProc - Could not create UTF8_STRING atom\n"); + pthread_exit (NULL); + } + + /* Create an atom for COMPOUND_TEXT */ + atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False); + if (atomCompoundText == None) + { + ErrorF ("winClipboardProc - Could not create COMPOUND_TEXT atom\n"); + pthread_exit (NULL); + } + + /* Create an atom for TARGETS */ + atomTargets = XInternAtom (pDisplay, "TARGETS", False); + if (atomTargets == None) + { + ErrorF ("winClipboardProc - Could not create TARGETS atom\n"); + pthread_exit (NULL); + } + + /* Pre-flush X events */ + /* + * NOTE: Apparently you'll freeze if you don't do this, + * because there may be events in local data structures + * already. + */ + winClipboardFlushXEvents (hwnd, + atomClipboard, + atomLocalProperty, + atomUTF8String, + atomCompoundText, + atomTargets, + atomDeleteWindow, + iWindow, + pDisplay, + fUnicodeSupport); + + /* Pre-flush Windows messages */ + if (!winClipboardFlushWindowsMessageQueue (hwnd)) + return 0; + + /* Loop for X events */ + while (1) + { + /* Setup the file descriptor set */ + /* + * NOTE: You have to do this before every call to select + * because select modifies the mask to indicate + * which descriptors are ready. + */ + FD_ZERO (&fdsRead); + FD_SET (fdMessageQueue, &fdsRead); + FD_SET (iConnectionNumber, &fdsRead); + + /* Wait for a Windows event or an X event */ + iReturn = select (iMaxDescriptor, /* Highest fds number */ + &fdsRead, /* Read mask */ + NULL, /* No write mask */ + NULL, /* No exception mask */ + NULL); /* No timeout */ + if (iReturn <= 0) + { + ErrorF ("winClipboardProc - Call to select () failed: %d. " + "Bailing.\n", iReturn); + break; + } + + /* Branch on which descriptor became active */ + if (FD_ISSET (iConnectionNumber, &fdsRead)) + { + /* X event ready */ +#if 0 + ErrorF ("winClipboardProc - X event ready\n"); +#endif + + /* Process X events */ + /* Exit when we see that server is shutting down */ + fReturn = winClipboardFlushXEvents (hwnd, + atomClipboard, + atomLocalProperty, + atomUTF8String, + atomCompoundText, + atomTargets, + atomDeleteWindow, + iWindow, + pDisplay, + fUnicodeSupport); + if (!fReturn) + { + ErrorF ("winClipboardProc - Caught WM_DELETE_WINDOW - " + "shutting down\n"); + break; + } + } + + /* Check for Windows event ready */ + if (FD_ISSET (fdMessageQueue, &fdsRead)) + { + /* Windows event ready */ +#if 0 + ErrorF ("winClipboardProc - Windows event ready\n"); +#endif + + /* Process Windows messages */ + if (!winClipboardFlushWindowsMessageQueue (hwnd)) + break; + } + } + + return 0; +} + + +/* + * winClipboardErrorHandler - Our application specific error handler + */ + +static int +winClipboardErrorHandler (Display *pDisplay, XErrorEvent *pErr) +{ + char pszErrorMsg[100]; + + XGetErrorText (pDisplay, + pErr->error_code, + pszErrorMsg, + sizeof (pszErrorMsg)); + ErrorF ("winClipboardErrorHandler - ERROR: \n\t%s\n", pszErrorMsg); + + if (pErr->error_code==BadWindow + || pErr->error_code==BadMatch + || pErr->error_code==BadDrawable) + { + pthread_exit (NULL); + } + + pthread_exit (NULL); + + return 0; +} + + +/* + * winClipboardIOErrorHandler - Our application specific IO error handler + */ + +static int +winClipboardIOErrorHandler (Display *pDisplay) +{ + printf ("\nwinClipboardIOErrorHandler!\n\n"); + + /* Restart at the main entry point */ + longjmp (g_jmpEntry, WIN_JMP_ERROR_IO); + + return 0; +} diff --git a/xc/programs/Xserver/hw/xwin/winclipboardunicode.c b/xc/programs/Xserver/hw/xwin/winclipboardunicode.c new file mode 100644 index 000000000..fdbcb8e69 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winclipboardunicode.c @@ -0,0 +1,68 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboardunicode.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "win.h" + + +/* + * Determine whether we suport Unicode or not. + * NOTE: Currently, just check if we are on an NT-based platform or not. + */ + +Bool +winClipboardDetectUnicodeSupport () +{ + Bool fReturn = FALSE; + OSVERSIONINFO osvi; + + /* Get operating system version information */ + ZeroMemory (&osvi, sizeof (osvi)); + osvi.dwOSVersionInfoSize = sizeof (osvi); + GetVersionEx (&osvi); + + /* Branch on platform ID */ + switch (osvi.dwPlatformId) + { + case VER_PLATFORM_WIN32_NT: + /* Engine 4 is supported on NT only */ + ErrorF ("DetectUnicodeSupport - Windows NT/2000/XP\n"); + fReturn = TRUE; + break; + + case VER_PLATFORM_WIN32_WINDOWS: + /* Engine 4 is supported on NT only */ + ErrorF ("DetectUnicodeSupport - Windows 95/98/Me\n"); + fReturn = FALSE; + break; + } + + return fReturn; +} diff --git a/xc/programs/Xserver/hw/xwin/winclipboardwndproc.c b/xc/programs/Xserver/hw/xwin/winclipboardwndproc.c new file mode 100644 index 000000000..d27bb4861 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winclipboardwndproc.c @@ -0,0 +1,86 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboardwndproc.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "winclipboard.h" + + +/* + * Process a given Windows message + */ + +LRESULT CALLBACK +winClipboardWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + /* Branch on message type */ + switch (message) + { + case WM_DESTROY: + PostQuitMessage (0); + return 0; + + case WM_CREATE: +#if 0 + ErrorF ("WindowProc - WM_CREATE\n"); +#endif + return 0; + } + + /* Let Windows perform default processing for unhandled messages */ + return DefWindowProc (hwnd, message, wParam, lParam); +} + + +/* + * Process any pending Windows messages + */ + +BOOL +winClipboardFlushWindowsMessageQueue (HWND hwnd) +{ + MSG msg; + + /* Flush the messaging window queue */ + /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage, + * as this will filter out many non-window-specific messages that + * are sent to our thread, such as WM_QUIT. + */ + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + /* Dispatch the message if not WM_QUIT */ + if (msg.message == WM_QUIT) + return FALSE; + else + DispatchMessage (&msg); + } + + return TRUE; +} diff --git a/xc/programs/Xserver/hw/xwin/winclipboardxevents.c b/xc/programs/Xserver/hw/xwin/winclipboardxevents.c new file mode 100644 index 000000000..a09c7c185 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winclipboardxevents.c @@ -0,0 +1,722 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboardxevents.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "winclipboard.h" + + +/* + * Process any pending X events + */ + +Bool +winClipboardFlushXEvents (HWND hwnd, + Atom atomClipboard, + Atom atomLocalProperty, + Atom atomUTF8String, + Atom atomCompoundText, + Atom atomTargets, + Atom atomDeleteWindow, + int iWindow, + Display *pDisplay, + Bool fUnicodeSupport) +{ + Atom atomReturnType; + int iReturnFormat; + unsigned long ulReturnItems; + XTextProperty xtpText; + XEvent event; + XSelectionEvent eventSelection; + unsigned long ulReturnBytesLeft; + unsigned char *pszReturnData = NULL; + char *pszGlobalData = NULL; + int iReturn; + HGLOBAL hGlobal; + Bool fReturn = TRUE; + XICCEncodingStyle xiccesStyle; + int iUTF8; + char *pszUTF8 = NULL; + char *pszTextList[2]; + int iCount; + char **ppszTextList = NULL; + wchar_t *pwszUnicodeStr = NULL; + int iUnicodeLen = 0; + + /* Process all pending events */ + while (XPending (pDisplay)) + { + /* Get the next event - will not block because one is ready */ + XNextEvent (pDisplay, &event); + + /* Branch on the event type */ + switch (event.type) + { + case ClientMessage: + if (event.xclient.data.l[0] == atomDeleteWindow) + { + ErrorF ("\nReceived WM_DELETE_WINDOW\n\n"); + fReturn = FALSE; + } + else + ErrorF ("\nUnknown ClientMessage\n\n"); + break; + + case SelectionClear: + /* Request the lost selection contents */ + iReturn = XConvertSelection (pDisplay, + event.xselectionclear.selection, + atomCompoundText, + atomLocalProperty, + iWindow, + CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("SelectionClear - XConvertSelection () failed\n"); + pthread_exit (NULL); + } + break; + + + /* + * SelectionRequest + */ + + case SelectionRequest: +#if 0 + char *pszAtomName = NULL + + ErrorF ("SelectionRequest - target %d\n", + event.xselectionrequest.target); + + pszAtomName = XGetAtomName (pDisplay, + event.xselectionrequest.target); + ErrorF ("SelectionRequest - Target atom name %s\n", pszAtomName); + XFree (pszAtomName); + pszAtomName = NULL; +#endif + + /* Abort if invalid target type */ + if (event.xselectionrequest.target != XA_STRING + && event.xselectionrequest.target != atomUTF8String + && event.xselectionrequest.target != atomCompoundText + && event.xselectionrequest.target != atomTargets) + { + /* Setup selection notify event */ + eventSelection.type = SelectionNotify; + eventSelection.send_event = True; + eventSelection.display = pDisplay; + eventSelection.requestor = event.xselectionrequest.requestor; + eventSelection.selection = event.xselectionrequest.selection; + eventSelection.target = event.xselectionrequest.target; + eventSelection.property = None; + eventSelection.time = event.xselectionrequest.time; + + /* Notify the requesting window that the operation is complete */ + iReturn = XSendEvent (pDisplay, + eventSelection.requestor, + False, + 0L, + (XEvent *) &eventSelection); + if (iReturn == BadValue || iReturn == BadWindow) + { + ErrorF ("SelectionRequest - XSendEvent () failed\n"); + pthread_exit (NULL); + } + + break; + } + + /* Handle targets type of request */ + if (event.xselectionrequest.target == atomTargets) + { + Atom atomTargetArr[4] = {atomTargets, + atomCompoundText, + atomUTF8String, + XA_STRING}; + + /* Try to change the property */ + iReturn = XChangeProperty (pDisplay, + event.xselectionrequest.requestor, + event.xselectionrequest.property, + event.xselectionrequest.target, + 8, + PropModeReplace, + (char *) atomTargetArr, + sizeof (atomTargetArr)); + if (iReturn == BadAlloc + || iReturn == BadAtom + || iReturn == BadMatch + || iReturn == BadValue + || iReturn == BadWindow) + { + ErrorF ("SelectionRequest - XChangeProperty failed: %d\n", + iReturn); + } + + /* Setup selection notify xevent */ + eventSelection.type = SelectionNotify; + eventSelection.send_event = True; + eventSelection.display = pDisplay; + eventSelection.requestor = event.xselectionrequest.requestor; + eventSelection.selection = event.xselectionrequest.selection; + eventSelection.target = event.xselectionrequest.target; + eventSelection.property = event.xselectionrequest.property; + eventSelection.time = event.xselectionrequest.time; + + /* + * Notify the requesting window that + * the operation has completed + */ + iReturn = XSendEvent (pDisplay, + eventSelection.requestor, + False, + 0L, + (XEvent *) &eventSelection); + if (iReturn == BadValue || iReturn == BadWindow) + { + ErrorF ("SelectionRequest - XSendEvent () failed\n"); + } + break; + } + + /* Access the clipboard */ + if (!OpenClipboard (hwnd)) + { + ErrorF ("SelectionRequest - OpenClipboard () failed: %08x\n", + GetLastError ()); + pthread_exit (NULL); + } + + /* Setup the string style */ + if (event.xselectionrequest.target == XA_STRING) + xiccesStyle = XStringStyle; + else if (event.xselectionrequest.target == atomUTF8String) + xiccesStyle = XUTF8StringStyle; + else if (event.xselectionrequest.target == atomCompoundText) + xiccesStyle = XCompoundTextStyle; + else + xiccesStyle = XStringStyle; + + /* + * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me + */ + + /* Get a pointer to the clipboard text */ + if (fUnicodeSupport) + hGlobal = GetClipboardData (CF_UNICODETEXT); + else + hGlobal = GetClipboardData (CF_TEXT); + if (!hGlobal) + { + ErrorF ("SelectionRequest - GetClipboardData () failed: %08x\n", + GetLastError ()); + pthread_exit (NULL); + } + pszGlobalData = (char *) GlobalLock (hGlobal); + + /* Convert the Unicode string to UTF8 (MBCS) */ + if (fUnicodeSupport) + { + iUTF8 = WideCharToMultiByte (CP_UTF8, + 0, + (LPCWSTR)pszGlobalData, + -1, + NULL, + 0, + NULL, + NULL); + pszUTF8 = (char *) malloc (iUTF8); /* Don't need +1 */ + WideCharToMultiByte (CP_UTF8, + 0, + (LPCWSTR)pszGlobalData, + -1, + pszUTF8, + iUTF8, + NULL, + NULL); + } + + /* Convert DOS string to UNIX string */ + if (fUnicodeSupport) + { + winClipboardDOStoUNIX (pszUTF8, strlen (pszUTF8)); + + /* Setup our text list */ + pszTextList[0] = pszUTF8; + pszTextList[1] = NULL; + + /* Initialize the text property */ + xtpText.value = NULL; + + /* Create the text property from the text list */ + iReturn = Xutf8TextListToTextProperty (pDisplay, + pszTextList, + 1, + xiccesStyle, + &xtpText); + if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) + { + ErrorF ("SelectionRequest - Xutf8TextListToTextProperty " + "failed: %d\n", + iReturn); + exit(1); + } + + /* Free the UTF8 string */ + free (pszUTF8); + } + else + winClipboardDOStoUNIX (pszGlobalData, strlen (pszGlobalData)); + + /* + * FIXME: Pass pszGlobalData and strlen (pszGlobalData( + * on 1 byte, pass xtpText.value and xtpText.nitems + * on 2 byte. + */ + + /* Copy the clipboard text to the requesting window */ + if (fUnicodeSupport) + iReturn = XChangeProperty (pDisplay, + event.xselectionrequest.requestor, + event.xselectionrequest.property, + event.xselectionrequest.target, + 8, + PropModeReplace, + xtpText.value, + xtpText.nitems); + else + iReturn = XChangeProperty (pDisplay, + event.xselectionrequest.requestor, + event.xselectionrequest.property, + event.xselectionrequest.target, + 8, + PropModeReplace, + pszGlobalData, + strlen (pszGlobalData)); + if (iReturn == BadAlloc || iReturn == BadAtom + || iReturn == BadMatch || iReturn == BadValue + || iReturn == BadWindow) + { + ErrorF ("SelectionRequest - XChangeProperty failed: %d\n", + iReturn); + pthread_exit (NULL); + } + + /* Release the clipboard data */ + GlobalUnlock (hGlobal); + pszGlobalData = NULL; + CloseClipboard (); + + /* FIXME: Don't clean up on 1 byte. */ + if (fUnicodeSupport) + { + XFree (xtpText.value); + xtpText.value = NULL; + } + + /* Setup selection notify event */ + eventSelection.type = SelectionNotify; + eventSelection.send_event = True; + eventSelection.display = pDisplay; + eventSelection.requestor = event.xselectionrequest.requestor; + eventSelection.selection = event.xselectionrequest.selection; + eventSelection.target = event.xselectionrequest.target; + eventSelection.property = event.xselectionrequest.property; + eventSelection.time = event.xselectionrequest.time; + + /* Notify the requesting window that the operation has completed */ + iReturn = XSendEvent (pDisplay, + eventSelection.requestor, + False, + 0L, + (XEvent *) &eventSelection); + if (iReturn == BadValue || iReturn == BadWindow) + { + ErrorF ("SelectionRequest - XSendEvent () failed\n"); + pthread_exit (NULL); + } + break; + + + /* + * SelectionNotify + */ + + case SelectionNotify: +#if 0 + ErrorF ("SelectionNotify\n"); +#endif + { + char *pszAtomName; + + pszAtomName = XGetAtomName (pDisplay, + event.xselection.selection); + + ErrorF ("SelectionNotify - ATOM: %s\n", + pszAtomName); + + XFree (pszAtomName); + } + +#if 0 + /* + * TEMP: Bail if selection is anything other than CLIPBOARD + */ + + if (event.xselection.selection != atomClipboard) + break; +#endif + + /* + * + * What are we doing here? + * + */ + if (fUnicodeSupport) + { + if (event.xselection.property == None) + { + if(event.xselection.target == XA_STRING) + { +#if 0 + ErrorF ("SelectionNotify XA_STRING\n"); +#endif + return fReturn; + } + else if (event.xselection.target == atomUTF8String) + { + ErrorF ("SelectionNotify UTF8\n"); + iReturn = XConvertSelection (pDisplay, + event.xselection.selection, + XA_STRING, + atomLocalProperty, + iWindow, + CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("SelectionNotify - XConvertSelection () " + "failed\n"); + pthread_exit (NULL); + } + return fReturn; + } + else if (event.xselection.target == atomCompoundText) + { + ErrorF ("SelectionNotify CompoundText\n"); + iReturn = XConvertSelection (pDisplay, + event.xselection.selection, + atomUTF8String, + atomLocalProperty, + iWindow, + CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("SelectionNotify - XConvertSelection () " + "failed\n"); + pthread_exit (NULL); + } + return fReturn; + } + else + { + ErrorF("Unknown format\n"); + return fReturn; + } + } + } + + /* Retrieve the size of the stored data */ + if (fUnicodeSupport) + iReturn = XGetWindowProperty (pDisplay, + iWindow, + atomLocalProperty, + 0, + 0, /* Don't get data, just size */ + False, + AnyPropertyType, + &xtpText.encoding, + &xtpText.format, + &xtpText.nitems, + &ulReturnBytesLeft, + &xtpText.value); + else + iReturn = XGetWindowProperty (pDisplay, + iWindow, + atomLocalProperty, + 0, + 0, /* Don't get data, just size */ + False, + AnyPropertyType, + &atomReturnType, + &iReturnFormat, + &ulReturnItems, + &ulReturnBytesLeft, + &pszReturnData); + if (iReturn != Success) + { + ErrorF ("SelectionNotify - XGetWindowProperty () failed\n"); + pthread_exit (NULL); + } + +#if 0 + if (fUnicodeSupport) + ErrorF ("SelectionNotify - returned data %d left %d\n", + xtpText.nitems, ulReturnBytesLeft); + else + ErrorF ("SelectionNotify - returned data %d left %d\n", + ulReturnItems, ulReturnBytesLeft); +#endif + + /* Request the selection data */ + if (fUnicodeSupport) + iReturn = XGetWindowProperty (pDisplay, + iWindow, + atomLocalProperty, + 0, + ulReturnBytesLeft, + False, + AnyPropertyType, + &xtpText.encoding, + &xtpText.format, + &xtpText.nitems, + &ulReturnBytesLeft, + &xtpText.value); + else + iReturn = XGetWindowProperty (pDisplay, + iWindow, + atomLocalProperty, + 0, + ulReturnBytesLeft, + False, + AnyPropertyType, + &atomReturnType, + &iReturnFormat, + &ulReturnItems, + &ulReturnBytesLeft, + &pszReturnData); + if (iReturn != Success) + { + ErrorF ("SelectionNotify - XGetWindowProperty () failed\n"); + pthread_exit (NULL); + } + + if (fUnicodeSupport) + { +#if 0 + char *pszAtomName = NULL; + + ErrorF ("SelectionNotify - returned data %d left %d\n", + prop.nitems, ulReturnBytesLeft); + + pszAtomName = XGetAtomName(pDisplay, prop.encoding); + ErrorF ("Notify atom name %s\n", pszAtomName); + XFree (pszAtomName); + pszAtomName = NULL; +#endif + + /* Convert the text property to a text list */ + Xutf8TextPropertyToTextList (pDisplay, + &xtpText, + &ppszTextList, + &iCount); + if (iCount > 0) + { + pszReturnData = malloc (strlen (ppszTextList[0]) + 1); + strcpy (pszReturnData, ppszTextList[0]); + } + else + { + pszReturnData = malloc (1); + pszReturnData[0] = 0; + } + + /* Free the data returned from XGetWindowProperty */ + XFreeStringList (ppszTextList); + XFree (xtpText.value); + } + + /* Convert the X clipboard string to DOS format */ + winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData)); + + if (fUnicodeSupport) + { + /* Find out how much space needed to convert MBCS to Unicode */ + iUnicodeLen = MultiByteToWideChar (CP_UTF8, + 0, + pszReturnData, + -1, + NULL, + 0); + + /* Allocate memory for the Unicode string */ + pwszUnicodeStr + = (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1)); + + /* Do the actual conversion */ + MultiByteToWideChar (CP_UTF8, + 0, + pszReturnData, + -1, + pwszUnicodeStr, + iUnicodeLen); + } + + /* Access the Windows clipboard */ + if (!OpenClipboard (hwnd)) + { + ErrorF ("OpenClipboard () failed: %08x\n", GetLastError ()); + pthread_exit (NULL); + } + + /* Take ownership of the Window clipboard */ + if (!EmptyClipboard ()) + { + ErrorF ("EmptyClipboard () failed: %08x\n", GetLastError ()); + pthread_exit (NULL); + } + + /* Allocate global memory for the X clipboard data */ + if (fUnicodeSupport) + hGlobal = GlobalAlloc (GMEM_MOVEABLE, + sizeof (wchar_t) * (iUnicodeLen + 1)); + else + hGlobal = GlobalAlloc (GMEM_MOVEABLE, strlen (pszReturnData) + 1); + + /* Obtain a pointer to the global memory */ + pszGlobalData = GlobalLock (hGlobal); + if (pszGlobalData == NULL) + { + ErrorF ("Could not lock global memory for clipboard transfer\n"); + pthread_exit (NULL); + } + + /* Copy the returned string into the global memory */ + if (fUnicodeSupport) + memcpy (pszGlobalData, + pwszUnicodeStr, + sizeof (wchar_t) * (iUnicodeLen + 1)); + else + strcpy (pszGlobalData, pszReturnData); + + /* Free the data returned from XGetWindowProperty */ + if (fUnicodeSupport) + { + free (pwszUnicodeStr); + pwszUnicodeStr = NULL; + } + else + { + XFree (pszReturnData); + pszReturnData = NULL; + } + + /* Release the pointer to the global memory */ + GlobalUnlock (hGlobal); + pszGlobalData = NULL; + + /* Push the selection data to the Windows clipboard */ + if (fUnicodeSupport) + SetClipboardData (CF_UNICODETEXT, hGlobal); + else + SetClipboardData (CF_TEXT, hGlobal); + + /* + * NOTE: Do not try to free pszGlobalData, it is owned by + * Windows after the call to SetClipboardData (). + */ + + /* Release the clipboard */ + if (!CloseClipboard ()) + { + ErrorF ("CloseClipboard () failed: %08x\n", GetLastError ()); + pthread_exit (NULL); + } + + /* Reassert ownership of the selection */ + iReturn = XSetSelectionOwner (pDisplay, + event.xselection.selection, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + char *pszAtomName = NULL; + + pszAtomName = XGetAtomName (pDisplay, + event.xselection.selection); + ErrorF ("SelectionNotify - Could not reassert ownership " + "of selection ATOM: %s\n", pszAtomName); + XFree (pszAtomName); + pszAtomName = NULL; + pthread_exit (NULL); + } + else + { +#if 0 + char *pszAtomName = NULL; + + pszAtomName = XGetAtomName (pDisplay, + event.xselection.selection); + ErrorF ("SelectionNotify - Reasserted ownership of ATOM: %s\n", + pszAtomName); + XFree (pszAtomName); + pszAtomName = NULL; +#endif + } +#if 0 + /* Reassert ownership of the CLIPBOARD */ + iReturn = XSetSelectionOwner (pDisplay, + atomClipboard, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("Could not reassert ownership of selection\n"); + pthread_exit (NULL); + } +#endif + break; + +#if 0 + case CreateNotify: + ErrorF ("FlushXEvents - CreateNotify parent: %ld\twindow: %ld\n", + event.xcreatewindow.parent, event.xcreatewindow.window); + break; + + case DestroyNotify: + ErrorF ("FlushXEvents - DestroyNotify window: %ld\tevent: %ld\n", + event.xdestroywindow.window, event.xdestroywindow.event); + break; +#endif + + default: + break; + } + } + + return fReturn; +} diff --git a/xc/programs/Xserver/hw/xwin/wincreatewnd.c b/xc/programs/Xserver/hw/xwin/wincreatewnd.c index 300a8f447..3c725f248 100644 --- a/xc/programs/Xserver/hw/xwin/wincreatewnd.c +++ b/xc/programs/Xserver/hw/xwin/wincreatewnd.c @@ -27,7 +27,7 @@ * * Authors: Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/wincreatewnd.c,v 1.4 2002/10/17 08:18:22 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/wincreatewnd.c,v 1.5 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" #include "shellapi.h" @@ -38,6 +38,9 @@ */ static Bool +winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo); + +static Bool winAdjustForAutoHide (RECT *prcWorkArea); @@ -65,7 +68,7 @@ winCreateBoundingWindowFullScreen (ScreenPtr pScreen) wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; - wc.hIcon = LoadIcon (g_hInstance, IDI_XWIN); + wc.hIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE(IDI_XWIN)); wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = NULL; @@ -119,20 +122,25 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - int iWidth = pScreenInfo->dwWidth; - int iHeight = pScreenInfo->dwHeight; + int iWidth = pScreenInfo->dwUserWidth; + int iHeight = pScreenInfo->dwUserHeight; HWND *phwnd = &pScreenPriv->hwndScreen; WNDCLASS wc; RECT rcClient, rcWorkArea; DWORD dwWindowStyle; - ErrorF ("winCreateBoundingWindowWindowed - Initial w: %d h: %d\n", - iWidth, iHeight); + ErrorF ("winCreateBoundingWindowWindowed - User w: %d h: %d\n", + pScreenInfo->dwUserWidth, pScreenInfo->dwUserHeight); + ErrorF ("winCreateBoundingWindowWindowed - Current w: %d h: %d\n", + pScreenInfo->dwWidth, pScreenInfo->dwHeight); + /* Set the common window style flags */ dwWindowStyle = WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX; /* Decorated or undecorated window */ - if (pScreenInfo->fDecoration && !pScreenInfo->fRootless) + if (pScreenInfo->fDecoration + && !pScreenInfo->fRootless + && !pScreenInfo->fMultiWindow) { dwWindowStyle |= WS_CAPTION; if (pScreenInfo->fScrollbars) @@ -147,7 +155,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; - wc.hIcon = LoadIcon (g_hInstance, IDI_XWIN); + wc.hIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE(IDI_XWIN)); wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wc.lpszMenuName = NULL; @@ -155,7 +163,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) RegisterClass (&wc); /* Get size of work area */ - SystemParametersInfo (SPI_GETWORKAREA, 0, &rcWorkArea, 0); + winGetWorkArea (&rcWorkArea, pScreenInfo); /* Adjust for auto-hide taskbars */ winAdjustForAutoHide (&rcWorkArea); @@ -170,7 +178,9 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) #endif /* Adjust the window width and height for borders and title bar */ - if (pScreenInfo->fDecoration && !pScreenInfo->fRootless) + if (pScreenInfo->fDecoration + && !pScreenInfo->fRootless + && !pScreenInfo->fMultiWindow) { #if CYGDEBUG ErrorF ("winCreateBoundingWindowWindowed - Window has decoration\n"); @@ -206,8 +216,16 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) * In this case we have to ignore the requested width and height * and instead use the largest possible window that we can. */ - iWidth = GetSystemMetrics (SM_CXSCREEN); - iHeight = GetSystemMetrics (SM_CYSCREEN); + if (pScreenInfo->fMultipleMonitors) + { + iWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN); + iHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN); + } + else + { + iWidth = GetSystemMetrics (SM_CXSCREEN); + iHeight = GetSystemMetrics (SM_CYSCREEN); + } } } else @@ -217,10 +235,18 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) ErrorF ("winCreateBoundingWindowWindowed - User did not give " "height and width\n"); #endif + /* Defaults are wrong if we have multiple monitors */ + if (pScreenInfo->fMultipleMonitors) + { + iWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN); + iHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN); + } } /* Clean up the scrollbars flag, if necessary */ - if ((!pScreenInfo->fDecoration || pScreenInfo->fRootless) + if ((!pScreenInfo->fDecoration + || pScreenInfo->fRootless + || pScreenInfo->fMultiWindow) && pScreenInfo->fScrollbars) { /* We cannot have scrollbars if we do not have a window border */ @@ -342,7 +368,10 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) #endif /* Show the window */ - ShowWindow (*phwnd, SW_SHOWNORMAL); + if (pScreenInfo->fMultiWindow) + ShowWindow (*phwnd, SW_SHOWMINNOACTIVE); + else + ShowWindow (*phwnd, SW_SHOWNORMAL); if (!UpdateWindow (*phwnd)) { ErrorF ("winCreateBoundingWindowWindowed - UpdateWindow () failed\n"); @@ -368,6 +397,77 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen) /* + * Find the work area of all attached monitors + */ + +static Bool +winGetWorkArea (RECT *prcWorkArea, winScreenInfo *pScreenInfo) +{ + int iPrimaryWidth, iPrimaryHeight; + int iWidth, iHeight; + int iLeft, iTop; + int iPrimaryNonWorkAreaWidth, iPrimaryNonWorkAreaHeight; + + /* SPI_GETWORKAREA only gets the work area of the primary screen. */ + SystemParametersInfo (SPI_GETWORKAREA, 0, prcWorkArea, 0); + + /* Bail out here if we aren't using multiple monitors */ + if (!pScreenInfo->fMultipleMonitors) + return TRUE; + + ErrorF ("winGetWorkArea - Original WorkArea: %d %d %d %d\n", + prcWorkArea->top, prcWorkArea->left, + prcWorkArea->bottom, prcWorkArea->right); + + /* Get size of full virtual screen */ + iWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN); + iHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN); + + ErrorF ("winGetWorkArea - Virtual screen is %d x %d\n", iWidth, iHeight); + + /* Get origin of full virtual screen */ + iLeft = GetSystemMetrics (SM_XVIRTUALSCREEN); + iTop = GetSystemMetrics (SM_YVIRTUALSCREEN); + + ErrorF ("winGetWorkArea - Virtual screen origin is %d, %d\n", iLeft, iTop); + + /* Get size of primary screen */ + iPrimaryWidth = GetSystemMetrics (SM_CXSCREEN); + iPrimaryHeight = GetSystemMetrics (SM_CYSCREEN); + + ErrorF ("winGetWorkArea - Primary screen is %d x %d\n", + iPrimaryWidth, iPrimaryHeight); + + /* Work out how much of the primary screen we aren't using */ + iPrimaryNonWorkAreaWidth = iPrimaryWidth - (prcWorkArea->right - + prcWorkArea->left); + iPrimaryNonWorkAreaHeight = iPrimaryHeight - (prcWorkArea->bottom + - prcWorkArea->top); + + /* Update the rectangle to include all monitors */ + if (iLeft < 0) + { + prcWorkArea->left = iLeft; + } + if (iTop < 0) + { + prcWorkArea->top = iTop; + } + prcWorkArea->right = prcWorkArea->left + iWidth - + iPrimaryNonWorkAreaWidth; + prcWorkArea->bottom = prcWorkArea->top + iHeight - + iPrimaryNonWorkAreaHeight; + + ErrorF ("winGetWorkArea - Adjusted WorkArea for multiple " + "monitors: %d %d %d %d\n", + prcWorkArea->top, prcWorkArea->left, + prcWorkArea->bottom, prcWorkArea->right); + + return TRUE; +} + + +/* * Adjust the client area so that any auto-hide toolbars * will work correctly. */ diff --git a/xc/programs/Xserver/hw/xwin/winengine.c b/xc/programs/Xserver/hw/xwin/winengine.c index 6324c8fe2..aff90bdaf 100644 --- a/xc/programs/Xserver/hw/xwin/winengine.c +++ b/xc/programs/Xserver/hw/xwin/winengine.c @@ -27,7 +27,7 @@ * * Authors: Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winengine.c,v 1.3 2002/07/05 09:19:26 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winengine.c,v 1.4 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -174,6 +174,17 @@ winSetEngine (ScreenPtr pScreen) return TRUE; } + /* ShadowGDI is the only engine that supports Multi Window Mode */ + if (pScreenInfo->fMultiWindow) + { + ErrorF ("winSetEngine - Multi Window => ShadowGDI\n"); + pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI; + + /* Set engine function pointers */ + winSetEngineFunctionsShadowGDI (pScreen); + return TRUE; + } + /* If the user's choice is supported, we'll use that */ if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred) { diff --git a/xc/programs/Xserver/hw/xwin/winerror.c b/xc/programs/Xserver/hw/xwin/winerror.c index d9ae1918b..c18f10dde 100644 --- a/xc/programs/Xserver/hw/xwin/winerror.c +++ b/xc/programs/Xserver/hw/xwin/winerror.c @@ -27,7 +27,7 @@ * * Authors: Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winerror.c,v 1.3 2001/10/23 22:22:47 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winerror.c,v 1.4 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -37,14 +37,22 @@ extern FILE *g_pfLog; void OsVendorVErrorF (const char *pszFormat, va_list va_args) { + static pthread_mutex_t s_pmPrinting = PTHREAD_MUTEX_INITIALIZER; + /* Check we opened the log file first */ if (g_pfLog == NULL) return; + /* Lock the printing mutex */ + pthread_mutex_lock (&s_pmPrinting); + /* Print the error message to a log file, could be stderr */ vfprintf (g_pfLog, pszFormat, va_args); /* Flush after every write, to make updates show up quickly */ fflush (g_pfLog); + + /* Unlock the printing mutex */ + pthread_mutex_unlock (&s_pmPrinting); } #endif diff --git a/xc/programs/Xserver/hw/xwin/winlayer.c b/xc/programs/Xserver/hw/xwin/winlayer.c index f9c320651..9d03dbf74 100644 --- a/xc/programs/Xserver/hw/xwin/winlayer.c +++ b/xc/programs/Xserver/hw/xwin/winlayer.c @@ -27,7 +27,7 @@ * * Authors: Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winlayer.c,v 1.8 2002/07/05 09:19:26 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winlayer.c,v 1.9 2002/10/31 23:04:39 alanh Exp $ */ #include "win.h" @@ -109,8 +109,6 @@ winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; int n; - RRVisualGroupPtr pVisualGroup; - RRGroupOfVisualGroupPtr pGroupOfVisualGroup = NULL; Rotation rotateKind; RRScreenSizePtr pSize; @@ -119,51 +117,14 @@ winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) /* Don't support rotations, yet */ *pRotations = RR_Rotate_0; /* | RR_Rotate_90 | RR_Rotate_180 | ... */ +#if 0 /* Check for something naughty. Don't know what exactly... */ for (n = 0; n < pScreen->numDepths; n++) if (pScreen->allowedDepths[n].numVids) break; if (n == pScreen->numDepths) return FALSE; - - /* Create an RandR visual group */ - pVisualGroup = RRCreateVisualGroup (pScreen); - if (!pVisualGroup) - return FALSE; - - - /* Not sure what this does */ - if (!RRAddDepthToVisualGroup (pScreen, - pVisualGroup, - &pScreen->allowedDepths[n])) - { - RRDestroyVisualGroup (pScreen, pVisualGroup); - return FALSE; - } - - /* Register the RandR visual group */ - pVisualGroup = RRRegisterVisualGroup (pScreen, pVisualGroup); - if (!pVisualGroup) - return FALSE; - - pGroupOfVisualGroup = RRRegisterGroupOfVisualGroup (pScreen, - pGroupOfVisualGroup); - - /* You have to be kidding */ - if (!RRAddVisualGroupToGroupOfVisualGroup (pScreen, - pGroupOfVisualGroup, - pVisualGroup)) - { - RRDestroyGroupOfVisualGroup (pScreen, pGroupOfVisualGroup); - /* pVisualGroup left until screen closed */ - return FALSE; - } - - /* I can't afford a clue */ - pGroupOfVisualGroup = RRRegisterGroupOfVisualGroup (pScreen, - pGroupOfVisualGroup); - if (!pGroupOfVisualGroup) - return FALSE; +#endif /* * Register supported sizes. This can be called many times, but @@ -173,14 +134,13 @@ winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) pScreenInfo->dwWidth, pScreenInfo->dwHeight, pScreenInfo->dwWidth_mm, - pScreenInfo->dwHeight_mm, - pGroupOfVisualGroup); + pScreenInfo->dwHeight_mm); /* Only one allowed rotation for now */ rotateKind = RR_Rotate_0; - + /* Tell RandR what the current config is */ - RRSetCurrentConfig (pScreen, rotateKind, pSize, pVisualGroup); + RRSetCurrentConfig (pScreen, rotateKind, pSize); return TRUE; } @@ -193,8 +153,7 @@ winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations) Bool winRandRSetConfig (ScreenPtr pScreen, Rotation rotateKind, - RRScreenSizePtr pSize, - RRVisualGroupPtr pVisualGroup) + RRScreenSizePtr pSize) { ErrorF ("winRandRSetConfig ()\n"); diff --git a/xc/programs/Xserver/hw/xwin/winmultiwindowwindow.c b/xc/programs/Xserver/hw/xwin/winmultiwindowwindow.c new file mode 100644 index 000000000..57d209e2a --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winmultiwindowwindow.c @@ -0,0 +1,1574 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Kensuke Matsuzaki + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winmultiwindowwindow.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "win.h" +#include "dixevents.h" + + +/* + * Prototypes for local functions + */ + +static void +winCreateWindowsWindow (WindowPtr pWin); + +static void +winDestroyWindowsWindow (WindowPtr pWin); + +static void +winUpdateWindowsWindow (WindowPtr pWin); + +static XID +winGetWindowID (WindowPtr pWin); + +static void +SendConfigureNotify (WindowPtr pWin); + +static +void +winUpdateRgn (WindowPtr pWindow); + +#ifdef SHAPE +static +void +winReshape (WindowPtr pWin); +#endif + + +/* + * Local globals + */ + +static UINT s_nIDPollingMouse = 2; + +#if 0 +static BOOL s_fMoveByX = FALSE; +#endif + + +/* + * Constant defines + */ + + +#define MOUSE_POLLING_INTERVAL 500 +#define WIN_MULTIWINDOW_SHAPE YES + +/* + * Macros + */ + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +/* + * CreateWindow - See Porting Layer Definition - p. 37 + */ + +Bool +winCreateWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + winWindowPriv(pWin); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winCreateWindowMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped CreateWindow function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->CreateWindow) + fResult = winGetScreenPriv(pWin->drawable.pScreen)->CreateWindow (pWin); + + /* Initialize some privates values */ + pWinPriv->hRgn = NULL; + pWinPriv->hWnd = NULL; + pWinPriv->pScreenPriv = winGetScreenPriv(pWin->drawable.pScreen); + pWinPriv->fXKilled = FALSE; + + return fResult; +} + + +/* + * DestroyWindow - See Porting Layer Definition - p. 37 + */ + +Bool +winDestroyWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + winWindowPriv(pWin); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winDestroyWindowMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped DestroyWindow function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->DestroyWindow) + fResult = winGetScreenPriv(pWin->drawable.pScreen)->DestroyWindow (pWin); + + /* Flag that the window has been destroyed */ + pWinPriv->fXKilled = TRUE; + + /* Kill the MS Windows window associated with this window */ + winDestroyWindowsWindow (pWin); + + return fResult; +} + + +/* + * PositionWindow - See Porting Layer Definition - p. 37 + */ + +Bool +winPositionWindowMultiWindow (WindowPtr pWin, int x, int y) +{ + Bool fResult = TRUE; + int iX, iY, iWidth, iHeight, iBorder; + winWindowPriv(pWin); + HWND hWnd = pWinPriv->hWnd; + RECT rcNew; + RECT rcOld; +#if CYGMULTIWINDOW_DEBUG + RECT rcClient; + RECT *lpRc; +#endif + DWORD dwExStyle; + DWORD dwStyle; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winPositionWindowMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped PositionWindow function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->PositionWindow) + fResult = winGetScreenPriv(pWin->drawable.pScreen)->PositionWindow (pWin, x, y); + + /* Bail out if the Windows window handle is bad */ + if (!hWnd) + return fResult; + + /* Get the Windows window style and extended style */ + dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE); + dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE); + + /* Get the width of the X window border */ + iBorder = wBorderWidth (pWin); + + /* Get the X and Y location of the X window */ + iX = pWin->drawable.x; + iY = pWin->drawable.y; + + /* Get the height and width of the X window */ + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* Store the origin, height, and width in a rectangle structure */ + SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight); + +#if CYGMULTIWINDOW_DEBUG + lpRc = &rcNew; + ErrorF ("winPositionWindowMultiWindow - (%d ms)drawable (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); +#endif + + /* + * Calculate the required size of the Windows window rectangle, + * given the size of the Windows window client area. + */ + AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle); + + /* Get a rectangle describing the old Windows window */ + GetWindowRect (hWnd, &rcOld); + +#if CYGMULTIWINDOW_DEBUG + /* Get a rectangle describing the Windows window client area */ + GetClientRect (hWnd, &rcClient); + + lpRc = &rcNew; + ErrorF ("winPositionWindowMultiWindow - (%d ms)rcNew (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); + + lpRc = &rcOld; + ErrorF ("winPositionWindowMultiWindow - (%d ms)rcOld (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); + + lpRc = &rcClient; + ErrorF ("(%d ms)rcClient (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); +#endif + + /* Check if the old rectangle and new rectangle are the same */ + if (!EqualRect (&rcNew, &rcOld)) + { +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winPositionWindowMultiWindow - Need to move\n"); +#endif + + /* Change the position and dimensions of the Windows window */ + MoveWindow (hWnd, + rcNew.left, rcNew.top, + rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, + TRUE); + } + else + { +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winPositionWindowMultiWindow - Not need to move\n"); +#endif + } + + return fResult; +} + + +/* + * ChangeWindowAttributes - See Porting Layer Definition - p. 37 + */ + +Bool +winChangeWindowAttributesMultiWindow (WindowPtr pWin, unsigned long mask) +{ + Bool fResult = TRUE; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winChangeWindowAttributesMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped ChangeWindowAttributes function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->ChangeWindowAttributes) + fResult = winGetScreenPriv(pWin->drawable.pScreen)->ChangeWindowAttributes (pWin, mask); + + /* + * NOTE: We do not currently need to do anything here. + */ + + return fResult; +} + + +/* + * UnmapWindow - See Porting Layer Definition - p. 37 + * Also referred to as UnrealizeWindow + */ + +Bool +winUnmapWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + winWindowPriv(pWin); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winUnmapWindowMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped UnrealizeWindow function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->UnrealizeWindow) + fResult = winGetScreenPriv(pWin->drawable.pScreen)->UnrealizeWindow (pWin); + + /* Flag that the window has been killed */ + pWinPriv->fXKilled = TRUE; + + /* Destroy the Windows window associated with this X window */ + winDestroyWindowsWindow (pWin); + + return fResult; +} + + +/* + * MapWindow - See Porting Layer Definition - p. 37 + * Also referred to as RealizeWindow + */ + +Bool +winMapWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + winWindowPriv(pWin); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winMapWindowMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped RealizeWindow function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->RealizeWindow) + fResult = winGetScreenPriv(pWin->drawable.pScreen)->RealizeWindow (pWin); + + /* Flag that this window has not been destroyed */ + pWinPriv->fXKilled = FALSE; + + /* Refresh/redisplay the Windows window associated with this X window */ + winUpdateWindowsWindow (pWin); + +#if WIN_MULTIWINDOW_SHAPE + winReshape (pWin); + winUpdateRgn (pWin); +#endif + + return fResult; +} + + +/* + * ReparentWindow - See Porting Layer Definition - p. 42 + */ + +void +winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent) +{ +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winReparentMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped ReparentWindow function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->ReparentWindow) + winGetScreenPriv(pWin->drawable.pScreen)->ReparentWindow (pWin, + pPriorParent); + + /* Update the Windows window associated with this X window */ + winUpdateWindowsWindow (pWin); +} + + +/* + * RestackWindow - Shuffle the z-order of a window + */ + +void +winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib) +{ + WindowPtr pPrevWin; + UINT uFlags; + HWND hInsertAfter; + winWindowPriv(pWin); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winRestackMultiWindow - %08x\n", pWin); +#endif + + /* Call any wrapped RestackWindow function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->RestackWindow) + winGetScreenPriv(pWin->drawable.pScreen)->RestackWindow (pWin, + pOldNextSib); + + /* Bail out if no window privates or window handle is invalid */ + if (!pWinPriv || !pWinPriv->hWnd) + return; + + /* Get a pointer to our previous sibling window */ + pPrevWin = pWin->prevSib; + + /* + * Look for a sibling window with + * valid privates and window handle + */ + while (pPrevWin + && !winGetWindowPriv(pPrevWin) + && !winGetWindowPriv(pPrevWin)->hWnd) + pPrevWin = pPrevWin->prevSib; + + /* Check if we found a valid sibling */ + if (pPrevWin) + { + /* Valid sibling - get handle to insert window after */ + hInsertAfter = winGetWindowPriv(pPrevWin)->hWnd; + uFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; + } + else + { + /* No valid sibling - make this window the top window */ + hInsertAfter = HWND_TOP; + uFlags = SWP_NOMOVE | SWP_NOSIZE; + } + + /* Perform the restacking operation in Windows */ + SetWindowPos (pWinPriv->hWnd, + hInsertAfter, + 0, 0, + 0, 0, + uFlags); +} + + +/* + * SetShape - See Porting Layer Definition - p. 42 + */ + +#ifdef SHAPE +void +winSetShapeMultiWindow (WindowPtr pWin) +{ +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winSetShapeMultiWindow - pWin: %08x\n", pWin); +#endif + + /* Call any wrapped SetShape function */ + if (winGetScreenPriv(pWin->drawable.pScreen)->SetShape) + winGetScreenPriv(pWin->drawable.pScreen)->SetShape (pWin); + + /* + * NOTE: We do not currently do anything here. + */ + +#if WIN_MULTIWINDOW_SHAPE + winReshape (pWin); + winUpdateRgn (pWin); +#endif + + return; +} +#endif + + +/* + * winUpdateRgn - Local function to update a Windows window region + */ + +static +void +winUpdateRgn (WindowPtr pWin) +{ +#if 1 + SetWindowRgn (winGetWindowPriv(pWin)->hWnd, + winGetWindowPriv(pWin)->hRgn, TRUE); +#endif +} + + +/* + * winReshape - Computes the composite clipping region for a window + */ + +#ifdef SHAPE +static +void +winReshape (WindowPtr pWin) +{ + int nRects; + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec rrNewShape; + BoxPtr pShape, pRects, pEnd; + HRGN hRgn, hRgnRect; + winWindowPriv(pWin); + +#if CYGDEBUG + ErrorF ("winReshape ()\n"); +#endif + + /* Bail if the window is the root window */ + if (pWin->parent == NULL) + return; + + /* Bail if the window is not top level */ + if (pWin->parent->parent != NULL) + return; + + /* Bail if Windows window handle is invalid */ + if (pWinPriv->hWnd == NULL) + return; + + /* Free any existing window region stored in the window privates */ + if (pWinPriv->hRgn != NULL) + { + DeleteObject (pWinPriv->hRgn); + pWinPriv->hRgn = NULL; + } + + /* Bail if the window has no bounding region defined */ + if (!wBoundingShape (pWin)) + return; + + REGION_INIT(pScreen, &rrNewShape, NullBox, 0); + REGION_COPY(pScreen, &rrNewShape, wBoundingShape(pWin)); + REGION_TRANSLATE(pScreen, + &rrNewShape, + pWin->borderWidth, + pWin->borderWidth); + + nRects = REGION_NUM_RECTS(&rrNewShape); + pShape = REGION_RECTS(&rrNewShape); + + /* Don't do anything if there are no rectangles in the region */ + if (nRects > 0) + { + RECT rcClient; + RECT rcWindow; + int iOffsetX, iOffsetY; + + /* Get client rectangle */ + if (!GetClientRect (pWinPriv->hWnd, &rcClient)) + { + ErrorF ("winReshape - GetClientRect failed, bailing: %d\n", + GetLastError ()); + return; + } + + /* Translate client rectangle coords to screen coords */ + /* NOTE: Only transforms top and left members */ + ClientToScreen (pWinPriv->hWnd, (LPPOINT) &rcClient); + + /* Get window rectangle */ + if (!GetWindowRect (pWinPriv->hWnd, &rcWindow)) + { + ErrorF ("winReshape - GetWindowRect failed, bailing: %d\n", + GetLastError ()); + return; + } + + /* Calculate offset from window upper-left to client upper-left */ + iOffsetX = rcClient.left - rcWindow.left; + iOffsetY = rcClient.top - rcWindow.top; + + /* Create initial Windows region for title bar */ + /* FIXME: Mean, nasty, ugly hack!!! */ + hRgn = CreateRectRgn (0, 0, rcWindow.right, iOffsetY); + if (hRgn == NULL) + { + ErrorF ("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) " + "failed: %d\n", + 0, 0, rcWindow.right, iOffsetY, GetLastError ()); + } + + /* Loop through all rectangles in the X region */ + for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) + { + /* Create a Windows region for the X rectangle */ + hRgnRect = CreateRectRgn (pRects->x1 + iOffsetX - 1, + pRects->y1 + iOffsetY - 1, + pRects->x2 + iOffsetX - 1, + pRects->y2 + iOffsetY - 1); + if (hRgnRect == NULL) + { + ErrorF ("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) " + "failed: %d\n" + "\tx1: %d x2: %d xOff: %d y1: %d y2: %d yOff: %d\n", + pRects->x1 + iOffsetX - 1, + pRects->y1 + iOffsetY - 1, + pRects->x2 + iOffsetX - 1, + pRects->y2 + iOffsetY - 1, + GetLastError (), + pRects->x1, pRects->x2, iOffsetX, + pRects->y1, pRects->y2, iOffsetY); + } + + /* Merge the Windows region with the accumulated region */ + if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) + { + ErrorF ("winReshape - CombineRgn () failed: %d\n", + GetLastError ()); + } + + /* Delete the temporary Windows region */ + DeleteObject (hRgnRect); + } + + /* Save a handle to the composite region in the window privates */ + pWinPriv->hRgn = hRgn; + } + + REGION_UNINIT(pScreen, &rrNewShape); + + return; +} +#endif + + +/* + * winTopLevelWindowProc - Window procedure for all top-level Windows windows. + */ + +LRESULT CALLBACK +winTopLevelWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + POINT ptMouse; + HDC hdcUpdate; + PAINTSTRUCT ps; + WindowPtr pWin = NULL; + winPrivWinPtr pWinPriv = NULL; + ScreenPtr s_pScreen = NULL; + winPrivScreenPtr s_pScreenPriv = NULL; + winScreenInfo *s_pScreenInfo = NULL; + HWND hwndScreen = NULL; + DrawablePtr pDraw = NULL; + int iX, iY, iWidth, iHeight, iBorder; + winWMMessageRec wmMsg; + static Bool s_fTracking = FALSE; + static Bool s_fCursor = TRUE; + + /* Check if the Windows window property for our X window pointer is valid */ + if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL) + { + /* Our X window pointer is valid */ + + /* Get pointers to the drawable and the screen */ + pDraw = &pWin->drawable; + s_pScreen = pWin->drawable.pScreen; + + /* Get a pointer to our window privates */ + pWinPriv = winGetWindowPriv(pWin); + + /* Get pointers to our screen privates and screen info */ + s_pScreenPriv = pWinPriv->pScreenPriv; + s_pScreenInfo = s_pScreenPriv->pScreenInfo; + + /* Get the handle for our screen-sized window */ + /* NOTE: This will be going away at some point, right? Harold Hunt - 2003/01/15 */ + hwndScreen = s_pScreenPriv->hwndScreen; + + /* */ + wmMsg.msg = 0; + wmMsg.hwndWindow = hwnd; + wmMsg.iWindow = (Window)GetProp (hwnd, WIN_WID_PROP); + +#if 1 + wmMsg.iX = pWinPriv->iX; + wmMsg.iY = pWinPriv->iY; + wmMsg.iWidth = pWinPriv->iWidth; + wmMsg.iHeight = pWinPriv->iHeight; +#else + wmMsg.iX = pDraw.x; + wmMsg.iY = pDraw.y; + wmMsg.iWidth = pDraw.width; + wmMsg.iHeight = pDraw.height; +#endif + + +#if 0 + /* + * Print some debugging information + */ + + ErrorF ("hWnd %08X\n", hwnd); + ErrorF ("pWin %08X\n", pWin); + ErrorF ("pDraw %08X\n", pDraw); + ErrorF ("\ttype %08X\n", pWin->drawable.type); + ErrorF ("\tclass %08X\n", pWin->drawable.class); + ErrorF ("\tdepth %08X\n", pWin->drawable.depth); + ErrorF ("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel); + ErrorF ("\tid %08X\n", pWin->drawable.id); + ErrorF ("\tx %08X\n", pWin->drawable.x); + ErrorF ("\ty %08X\n", pWin->drawable.y); + ErrorF ("\twidth %08X\n", pWin->drawable.width); + ErrorF ("\thenght %08X\n", pWin->drawable.height); + ErrorF ("\tpScreen %08X\n", pWin->drawable.pScreen); + ErrorF ("\tserialNumber %08X\n", pWin->drawable.serialNumber); + ErrorF ("g_iWindowPrivateIndex %d\n", g_iWindowPrivateIndex); + ErrorF ("pWinPriv %08X\n", pWinPriv); + ErrorF ("s_pScreenPriv %08X\n", s_pScreenPriv); + ErrorF ("s_pScreenInfo %08X\n", s_pScreenInfo); + ErrorF ("hwndScreen %08X\n", hwndScreen); +#endif + } + + + + /* Branch on message type */ + switch (message) + { + case WM_CREATE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_CREATE\n"); +#endif + + /* */ + SetProp (hwnd, + WIN_WINDOW_PROP, + (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams); + + /* */ + SetProp (hwnd, + WIN_WID_PROP, + (HANDLE)winGetWindowID (((LPCREATESTRUCT) lParam)->lpCreateParams)); + return 0; + + case WM_PAINT: + /* Only paint if our window handle is valid */ + if (hwndScreen == NULL) + break; + + /* BeginPaint gives us an hdc that clips to the invalidated region */ + hdcUpdate = BeginPaint (hwnd, &ps); + +#if 0 + /* NOTE: Doesn't appear to be used - Harold Hunt - 2003/01/15 */ + /* Get the dimensions of the client area */ + GetClientRect (hwnd, &rcClient); +#endif + + /* Get the position and dimensions of the window */ + iBorder = wBorderWidth (pWin); + iX = pWin->drawable.x; + iY = pWin->drawable.y; + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* Try to copy from the shadow buffer */ + if (!BitBlt (hdcUpdate, + 0, 0, + iWidth, iHeight, + s_pScreenPriv->hdcShadow, + iX, iY, + SRCCOPY)) + { + 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), // Default language + (LPTSTR) &lpMsgBuf, + 0, NULL); + + ErrorF ("winTopLevelWindowProc - BitBlt failed: %s\n", + (LPSTR)lpMsgBuf); + LocalFree (lpMsgBuf); + } + + /* EndPaint frees the DC */ + EndPaint (hwndScreen, &ps); + return 0; + + +#if 1 + case WM_MOUSEMOVE: + /* Unpack the client area mouse coordinates */ + ptMouse.x = GET_X_LPARAM(lParam); + ptMouse.y = GET_Y_LPARAM(lParam); + + /* Translate the client area mouse coordinates to screen coordinates */ + ClientToScreen (hwnd, &ptMouse); + + /* We can't do anything without privates */ + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + + /* Has the mouse pointer crossed screens? */ + if (s_pScreen != miPointerCurrentScreen ()) + miPointerSetNewScreen (s_pScreenInfo->dwScreen, + ptMouse.x - s_pScreenInfo->dwXOffset, + ptMouse.y - s_pScreenInfo->dwYOffset); + + /* Are we tracking yet? */ + if (!s_fTracking) + { + TRACKMOUSEEVENT tme; + + /* Setup data structure */ + ZeroMemory (&tme, sizeof (tme)); + tme.cbSize = sizeof (tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hwnd; + + /* Call the tracking function */ + if (!(*g_fpTrackMouseEvent) (&tme)) + ErrorF ("winTopLevelWindowProc - _TrackMouseEvent failed\n"); + + /* Flag that we are tracking now */ + s_fTracking = TRUE; + } + + /* Hide or show the Windows mouse cursor */ + if (s_fCursor) + { + /* Hide Windows cursor */ + s_fCursor = FALSE; + ShowCursor (FALSE); + KillTimer (hwnd, s_nIDPollingMouse); + } + + /* Deliver absolute cursor position to X Server */ + miPointerAbsoluteCursor (ptMouse.x - s_pScreenInfo->dwXOffset, + ptMouse.y - s_pScreenInfo->dwYOffset, + g_c32LastInputEventTime = GetTickCount ()); + return 0; + + case WM_NCMOUSEMOVE: + /* + * We break instead of returning 0 since we need to call + * DefWindowProc to get the mouse cursor changes + * and min/max/close button highlighting in Windows XP. + * The Platform SDK says that you should return 0 if you + * process this message, but it fails to mention that you + * will give up any default functionality if you do return 0. + */ + + /* We can't do anything without privates */ + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + + /* Non-client mouse movement, show Windows cursor */ + if (!s_fCursor) + { + s_fCursor = TRUE; + ShowCursor (TRUE); + SetTimer (hwnd, s_nIDPollingMouse, MOUSE_POLLING_INTERVAL, NULL); + } + break; + + case WM_MOUSELEAVE: + /* Mouse has left our client area */ + + /* Flag that we are no longer tracking */ + s_fTracking = FALSE; + + /* Show the mouse cursor, if necessary */ + if (!s_fCursor) + { + s_fCursor = TRUE; + ShowCursor (TRUE); + SetTimer (hwnd, s_nIDPollingMouse, MOUSE_POLLING_INTERVAL, NULL); + } + return 0; + + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam); + + case WM_LBUTTONUP: + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam); + + case WM_MBUTTONDBLCLK: + case WM_MBUTTONDOWN: + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam); + + case WM_MBUTTONUP: + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam); + + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam); + + case WM_RBUTTONUP: + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; + return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam); + +#else + + case WM_MOUSEMOVE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_MOUSEMOVE*\n"); +#endif + + /* Unpack the client area mouse coordinates */ + ptMouse.x = GET_X_LPARAM(lParam); + ptMouse.y = GET_Y_LPARAM(lParam); + + /* Translate the client area mouse coordinates to screen coordinates */ + ClientToScreen (hwnd, &ptMouse); + + /* Pass the message to the root window */ + SendMessage (hwndScreen, message, wParam, MAKELONG(ptMouse.x, ptMouse.y)); + return 0; + + case WM_NCMOUSEMOVE: + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSELEAVE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_*BUTTON*\n"); +#endif + + /* Pass the message to the root window */ + SendMessage(hwndScreen, message, wParam, MAKELONG(ptMouse.x, ptMouse.y)); + return 0; +#endif + + case WM_MOUSEWHEEL: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_MOUSEWHEEL\n"); +#endif + + /* Pass the message to the root window */ + SendMessage(hwndScreen, message, wParam, lParam); + return 0; + + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_SYSDEADCHAR: + case WM_KEYDOWN: + case WM_KEYUP: + case WM_DEADCHAR: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_*KEY*\n"); +#endif + + /* Pass the message to the root window */ + SendMessage (hwndScreen, message, wParam, lParam); + return 0; + + case WM_HOTKEY: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_HOTKEY\n"); +#endif + + /* Pass the message to the root window */ + SendMessage (hwndScreen, message, wParam, lParam); + return 0; + + +#if 1 + case WM_ACTIVATE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_ACTIVATE\n"); +#endif + + /* Pass the message to the root window */ + SendMessage (hwndScreen, message, wParam, lParam); + + /* Bail if inactivating */ + if (LOWORD(wParam) == WA_INACTIVE) + return 0; + + /* Check if the current window is the active window in Windows */ + if (GetActiveWindow () == hwnd) + { + /* Tell our Window Manager thread to raise the window */ + wmMsg.msg = WM_WM_RAISE; + winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); + } + + /* Tell our Window Manager thread to activate the window */ + wmMsg.msg = WM_WM_ACTIVATE; + winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); + + return 0; + + case WM_ACTIVATEAPP: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_ACTIVATEAPP\n"); +#endif + + /* Pass the message to the root window */ + SendMessage (hwndScreen, message, wParam, lParam); + return 0; +#endif + + + case WM_CLOSE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_CLOSE\n"); +#endif + /* Branch on if the window was killed in X already */ + if (pWinPriv->fXKilled) + { + /* Window was killed, go ahead and destroy the window */ + DestroyWindow (hwnd); + } + else + { + /* Tell our Window Manager thread to kill the window */ + wmMsg.msg = WM_WM_KILL; + winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); + } + return 0; + + case WM_DESTROY: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_DESTROY\n"); +#endif + + /* Branch on if the window was killed in X already */ + if (pWinPriv && !pWinPriv->fXKilled) + { + ErrorF ("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n"); + + /* Tell our Window Manager thread to kill the window */ + wmMsg.msg = WM_WM_KILL; + winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_DESTROY\n"); +#endif + break; + + case WM_MOVE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_MOVE - %d ms\n", GetTickCount ()); +#endif + + /* Bail if Windows window is not actually moving */ + if (pWinPriv->iX == (short) LOWORD(lParam) + && pWinPriv->iY == (short) HIWORD(lParam)) + break; + + /* Get new position */ + pWinPriv->iX = (short) LOWORD(lParam); + pWinPriv->iY = (short) HIWORD(lParam); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\t(%d, %d)\n", pWinPriv->iX, pWinPriv->iY); +#endif + + /* Notify the X client that its window is moving */ + if (SubStrSend(pWin, pWin->parent)) + SendConfigureNotify (pWin); + + /* Tell X that the window is moving */ + (s_pScreen->MoveWindow) (pWin, + (int)(short) LOWORD(lParam) - wBorderWidth (pWin), + (int)(short) HIWORD(lParam) - wBorderWidth (pWin), + pWin->nextSib, + VTMove); + return 0; + + case WM_SHOWWINDOW: + /* Bail out if the window is being hidden */ + if (!wParam) + return 0; + + /* Tell X to map the window */ + MapWindow (pWin, wClient(pWin)); + + /* */ + if (!pWin->overrideRedirect) + { + DWORD dwExStyle; + DWORD dwStyle; + RECT rcNew; + int iDx, iDy; + + /* Flag that this window needs to be made active when clicked */ + SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1); + + /* Get the standard and extended window style information */ + dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE); + dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE); + + /* */ + if (dwExStyle != WS_EX_APPWINDOW) + { + /* Setup a rectangle with the X window position and size */ + SetRect (&rcNew, + pWinPriv->iX, + pWinPriv->iY, + pWinPriv->iX + pWinPriv->iWidth, + pWinPriv->iY + pWinPriv->iHeight); + +#if 0 + ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, + rcNew.right, rcNew.bottom); +#endif + + /* */ + AdjustWindowRectEx (&rcNew, + WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW, + FALSE, + WS_EX_APPWINDOW); + + /* Calculate position deltas */ + iDx = pWinPriv->iX - rcNew.left; + iDy = pWinPriv->iY - rcNew.top; + + /* Calculate new rectangle */ + rcNew.left += iDx; + rcNew.right += iDx; + rcNew.top += iDy; + rcNew.bottom += iDy; + +#if 0 + ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, + rcNew.right, rcNew.bottom); +#endif + + /* Set the window extended style flags */ + SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW); + + /* Set the window standard style flags */ + SetWindowLongPtr (hwnd, GWL_STYLE, WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW); + + /* Positon the Windows window */ + SetWindowPos (hwnd, HWND_TOP, + rcNew.left, rcNew.top, + rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, + SWP_NOMOVE | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE); + + /* Bring the Window window to the foreground */ + SetForegroundWindow (hwnd); + } + } + + /* Setup the Window Manager message */ + wmMsg.msg = WM_WM_MAP; + wmMsg.iWidth = pWinPriv->iWidth; + wmMsg.iHeight = pWinPriv->iHeight; + + /* Tell our Window Manager thread to map the window */ + winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); + + /* Setup the Window Manager message */ + wmMsg.msg = WM_WM_RAISE; + + /* Tell our Window Manager thread to raise the window */ + winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); + return 0; + + case WM_SIZE: + /* see dix/window.c */ + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_SIZE - %d ms\n", GetTickCount ()); +#endif + + switch (wParam) + { + case SIZE_MINIMIZED: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tSIZE_MINIMIZED\n"); +#endif + + wmMsg.msg = WM_WM_LOWER; + + /* Tell our Window Manager thread to lower the window */ + winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); + break; + + case SIZE_RESTORED: + case SIZE_MAXIMIZED: + if (pWinPriv->iWidth == (short) LOWORD(lParam) + && pWinPriv->iHeight == (short) HIWORD(lParam)) + break; + + /* Get the dimensions of the Windows window */ + pWinPriv->iWidth = (short) LOWORD(lParam); + pWinPriv->iHeight = (short) HIWORD(lParam); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\t(%d, %d)\n", pWinPriv->iWidth, pWinPriv->iHeight); +#endif + + /* Check if resize events are redirected */ + if ((pWin->eventMask | wOtherEventMasks (pWin)) & ResizeRedirectMask) + { + xEvent eventT; + + /* Setup the X event structure */ + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = pWinPriv->iWidth; + eventT.u.resizeRequest.height = pWinPriv->iHeight; + + /* */ + if (MaybeDeliverEventsToClient (pWin, &eventT, 1, + ResizeRedirectMask, + wClient(pWin)) == 1) + break; + } + + /* Notify the X client that its window is being resized */ + if (SubStrSend (pWin, pWin->parent)) + SendConfigureNotify (pWin); + + /* Tell the X server that the window is being resized */ + (s_pScreen->ResizeWindow) (pWin, + pWinPriv->iX - wBorderWidth (pWin), + pWinPriv->iY - wBorderWidth (pWin), + pWinPriv->iWidth, + pWinPriv->iHeight, + pWin->nextSib); + + /* Tell X to redraw the exposed portions of the window */ + { + RegionRec temp; + + /* Get the region describing the X window clip list */ + REGION_INIT(s_pScreen, &temp, NullBox, 0); + REGION_COPY(s_pScreen, &temp, &pWin->clipList); + + /* Expose the clipped region */ + (*s_pScreen->WindowExposures) (pWin, &temp, NullRegion); + + /* Free the region */ + REGION_UNINIT(s_pScreen, &temp); + } + break; + +#if 0 + case SIZE_MAXIMIZED: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tSIZE_MAXIMIZED\n"); +#endif + + /* Get the dimensions of the window */ + pWinPriv->iWidth = (int)(short) LOWORD(lParam); + pWinPriv->iHeight = (int)(short) HIWORD(lParam); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\t(%d, %d)\n", pWinPriv->iWidth, pWinPriv->iHeight); +#endif + + /* */ + if ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask) + { + xEvent eventT; + + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = pWinPriv->iWidth; + eventT.u.resizeRequest.height = pWinPriv->iHeight; + if (MaybeDeliverEventsToClient (pWin, &eventT, 1, + ResizeRedirectMask, + wClient(pWin)) == 1); + } + + + (s_pScreen->ResizeWindow) (pWin, + pWinPriv->iX - wBorderWidth (pWin), + pWinPriv->iY - wBorderWidth (pWin), + pWinPriv->iWidth, + pWinPriv->iHeight, + pWin->nextSib); + break; +#endif + + default: + break; + } + return 0; + + case WM_MOUSEACTIVATE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_MOUSEACTIVATE\n"); +#endif + + /* Check if this window needs to be made active when clicked */ + if (!GetProp (pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) + { +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_MOUSEACTIVATE - MA_NOACTIVATE\n"); +#endif + + /* */ + return MA_NOACTIVATE; + } + break; + + case WM_TIMER: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winTopLevelWindowProc - WM_TIMER - %d ms\n", GetTickCount ()); +#endif + + /* Branch on the type of timer event that fired */ + if (wParam == s_nIDPollingMouse) + { + POINT point; + + /* Get the current position of the mouse cursor */ + GetCursorPos (&point); + + /* Deliver absolute cursor position to X Server */ + miPointerAbsoluteCursor (point.x, point.y, + g_c32LastInputEventTime = GetTickCount ()); + } + else + { + ErrorF ("winTopLevelWindowProc - Unknown WM_TIMER\n"); + } + return 0; + + default: + break; + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} + + +/* + * winCreateWindowsWindow - Create a Windows window associated with an X window + */ + +static void +winCreateWindowsWindow (WindowPtr pWin) +{ + int iX, iY; + int iWidth; + int iHeight; + int iBorder; + HWND hWnd; + WNDCLASS wc; + winWindowPriv(pWin); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winCreateWindowsWindow - pWin: %08x\n", pWin); +#endif + + iBorder = wBorderWidth (pWin); + + iX = pWin->drawable.x; + iY = pWin->drawable.y; + + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* Setup our window class */ + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = winTopLevelWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = g_hInstance; + wc.hIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE(IDI_XWIN)); + wc.hCursor = 0; + wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = WINDOW_CLASS_X; + RegisterClass (&wc); + + /* Create the window */ + hWnd = CreateWindowExA (WS_EX_TOOLWINDOW, /* Extended styles */ + WINDOW_CLASS_X, /* Class name */ + WINDOW_TITLE_X, /* Window name */ + WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + iX, /* Horizontal position */ + iY, /* Vertical position */ + iWidth, /* Right edge */ + iHeight, /* Bottom edge */ + (HWND) NULL, /* No parent or owner window */ + (HMENU) NULL, /* No menu */ + GetModuleHandle (NULL), /* Instance handle */ + pWin); /* ScreenPrivates */ + if (hWnd == NULL) + { + ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", + GetLastError ()); + } + + pWinPriv->hWnd = hWnd; + + + SetProp (pWinPriv->hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin)); + + /* Flag that this Windows window handles its own activation */ + SetProp (pWinPriv->hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0); +} + + +/* + * winDestroyWindowsWindow - Destroy a Windows window associated with an X window + */ + +static void +winDestroyWindowsWindow (WindowPtr pWin) +{ + MSG msg; + winWindowPriv(pWin); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winDestroyWindowsWindow\n"); +#endif + + + /* Bail out if the Windows window handle is invalid */ + if (pWinPriv->hWnd == NULL) + return; + + + SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, 0); + + DestroyWindow (pWinPriv->hWnd); + + pWinPriv->hWnd = NULL; + + /* Process all messages on our queue */ + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + if (g_hDlgDepthChange == 0 || !IsDialogMessage (g_hDlgDepthChange, &msg)) + { + DispatchMessage (&msg); + } + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("-winDestroyWindowsWindow\n"); +#endif +} + + +/* + * winUpdateWindowsWindow - Redisplay/redraw a Windows window associated with an X window + */ + +static void +winUpdateWindowsWindow (WindowPtr pWin) +{ + winWindowPriv(pWin); + HWND hWnd = pWinPriv->hWnd; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winUpdateWindowsWindow\n"); +#endif + + /* Check if the Windows window's parents have been destroyed */ + if (pWin->parent != NULL + && pWin->parent->parent == NULL + && pWin->mapped) + { + /* Create the Windows window if it has been destroyed */ + if (hWnd == NULL) + { + winCreateWindowsWindow (pWin); + assert (pWinPriv->hWnd != NULL); + } + + /* Display the window without activating it */ + ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + /* Send first paint message */ + UpdateWindow (pWinPriv->hWnd); + } + else if (hWnd != NULL) + { + /* Destroy the Windows window if its parents are destroyed */ + winDestroyWindowsWindow (pWin); + assert (pWinPriv->hWnd == NULL); + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("-winUpdateWindowsWindow\n"); +#endif +} + + + + + + + + +typedef struct { + pointer value; + XID id; +} WindowIDPairRec, *WindowIDPairPtr; + + + + + +/* + * winFindWindow - + */ + +static void +winFindWindow (pointer value, XID id, pointer cdata) +{ + WindowIDPairPtr wi = (WindowIDPairPtr)cdata; + + if (value == wi->value) + { + wi->id = id; + } +} + + +/* + * winGetWindowID - + */ + +static XID +winGetWindowID (WindowPtr pWin) +{ + WindowIDPairRec wi = {pWin, 0}; + ClientPtr c = wClient(pWin); + + /* */ + FindClientResourcesByType (c, RT_WINDOW, winFindWindow, &wi); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winGetWindowID - Window ID: %d\n", wi.id); +#endif + + return wi.id; +} + + +/* + * SendConfigureNotify - + */ + +static void +SendConfigureNotify(WindowPtr pWin) +{ + xEvent event; + winWindowPriv(pWin); + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + + if (pWin->nextSib) + event.u.configureNotify.aboveSibling = pWin->nextSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + + event.u.configureNotify.x = pWinPriv->iX - wBorderWidth (pWin); + event.u.configureNotify.y = pWinPriv->iY - wBorderWidth (pWin); + + event.u.configureNotify.width = pWinPriv->iWidth; + event.u.configureNotify.height = pWinPriv->iHeight; + + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + + event.u.configureNotify.override = pWin->overrideRedirect; + + /* */ + DeliverEvents (pWin, &event, 1, NullWindow); +} diff --git a/xc/programs/Xserver/hw/xwin/winmultiwindowwm.c b/xc/programs/Xserver/hw/xwin/winmultiwindowwm.c new file mode 100644 index 000000000..ab4dd27f6 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winmultiwindowwm.c @@ -0,0 +1,907 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Kensuke Matsuzaki + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winmultiwindowwm.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +/* X headers */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/select.h> +#include <fcntl.h> +#include <setjmp.h> +#include <pthread.h> +#include <X11/X.h> +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xlocale.h> +#include <X11/Xproto.h> +#include <X11/Xutil.h> + +/* Fixups to prevent collisions between Windows and X headers */ +#define ATOM DWORD + +/* Windows headers */ +#include <windows.h> + +/* Local headers */ +#include "winwindow.h" + + +/* + * Constant defines + */ + +#define WIN_CONNECT_RETRIES 5 +#define WIN_CONNECT_DELAY 5 +#define WIN_MSG_QUEUE_FNAME "/dev/windows" +#define WM_WM_X_EVENT 1 +#define WIN_JMP_OKAY 0 +#define WIN_JMP_ERROR_IO 2 + + +/* + * Local structures + */ + +typedef struct _WMMsgNodeRec { + winWMMessageRec msg; + struct _WMMsgNodeRec *pNext; +} WMMsgNodeRec, *WMMsgNodePtr; + +typedef struct _WMMsgQueueRec { + struct _WMMsgNodeRec *pHead; + struct _WMMsgNodeRec *pTail; + pthread_mutex_t pmMutex; + pthread_cond_t pcNotEmpty; +} WMMsgQueueRec, *WMMsgQueuePtr; + +typedef struct _WMInfo { + Display *pDisplay; + WMMsgQueueRec wmMsgQueue; + Atom atmWmProtos; + Atom atmWmDelete; +} WMInfoRec, *WMInfoPtr; + +typedef struct _WMProcArgRec { + DWORD dwScreen; + WMInfoPtr pWMInfo; + pthread_mutex_t *ppmServerStarted; +} WMProcArgRec, *WMProcArgPtr; + + +/* + * References to external symbols + */ + +extern char *display; +extern void ErrorF (const char* /*f*/, ...); +extern Bool g_fCalledSetLocale; + + +/* + * Prototypes for local functions + */ + +static void +PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode); + +static WMMsgNodePtr +PopMessage (WMMsgQueuePtr pQueue); + +static Bool +InitQueue (WMMsgQueuePtr pQueue); + +static void +GetWindowName (Display * pDpy, Window iWin, char **ppName); + +static int +SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData); + +static void* +winMultiWindowWMProc (void* pArg); + +static Bool +FlushXEvents (WMInfoPtr pWMInfo); + +static int +winMultiWindowWMErrorHandler (Display *pDisp, XErrorEvent *e); + +static void +winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg); + +static int +winMutliWindowWMIOErrorHandler (Display *pDisplay); + + +/* + * Local globals + */ + +static int g_nQueueSize; +static jmp_buf g_jmpEntry; + + + +/* + * PushMessage - Push a message onto the queue + */ + +static void +PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) +{ + + /* Lock the queue mutex */ + pthread_mutex_lock (&pQueue->pmMutex); + + pNode->pNext = NULL; + + if (pQueue->pTail != NULL) + { + pQueue->pTail->pNext = pNode; + } + pQueue->pTail = pNode; + + if (pQueue->pHead == NULL) + { + pQueue->pHead = pNode; + } + + +#if 0 + switch (pNode->msg.msg) + { + case WM_WM_MOVE: + ErrorF ("\tWM_WM_MOVE\n"); + break; + case WM_WM_RAISE: + ErrorF ("\tWM_WM_RAISE\n"); + break; + case WM_WM_LOWER: + ErrorF ("\tWM_WM_RAISE\n"); + break; + case WM_WM_MAP: + ErrorF ("\tWM_WM_MAP\n"); + break; + case WM_WM_UNMAP: + ErrorF ("\tWM_WM_UNMAP\n"); + break; + case WM_WM_KILL: + ErrorF ("\tWM_WM_KILL\n"); + break; + default: + ErrorF ("Unknown Message.\n"); + break; + } +#endif + + /* Increase the count of elements in the queue by one */ + ++g_nQueueSize; + + /* Release the queue mutex */ + pthread_mutex_unlock (&pQueue->pmMutex); + + /* Signal that the queue is not empty */ + pthread_cond_signal (&pQueue->pcNotEmpty); +} + + +#if 0 +/* + * QueueSize - Return the size of the queue + */ + +static int +QueueSize (WMMsgQueuePtr pQueue) +{ + WMMsgNodePtr pNode; + int nSize = 0; + + /* Loop through all elements in the queue */ + for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) + ++nSize; + + return nSize; +} +#endif + + +/* + * PopMessage - + */ + +static WMMsgNodePtr +PopMessage (WMMsgQueuePtr pQueue) +{ + WMMsgNodePtr pNode; + + /* Lock the queue mutex */ + pthread_mutex_lock (&pQueue->pmMutex); + + /* Wait for --- */ + while (pQueue->pHead == NULL) + { + pthread_cond_wait (&pQueue->pcNotEmpty, &pQueue->pmMutex); + } + + pNode = pQueue->pHead; + if (pQueue->pHead != NULL) + { + pQueue->pHead = pQueue->pHead->pNext; + } + + if (pQueue->pTail == pNode) + { + pQueue->pTail = NULL; + } + + /* Drop the number of elements in the queue by one */ + --g_nQueueSize; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("Queue Size %d %d\n", g_nQueueSize, QueueSize(pQueue)); +#endif + + /* Release the queue mutex */ + pthread_mutex_unlock (&pQueue->pmMutex); + + return pNode; +} + + +#if 0 +/* + * HaveMessage - + */ + +static Bool +HaveMessage (WMMsgQueuePtr pQueue, UINT msg, Window iWindow) +{ + WMMsgNodePtr pNode; + + for (pNode = pQueue->pHead; pNode != NULL; pNode = pNode->pNext) + { + if (pNode->msg.msg==msg && pNode->msg.iWindow==iWindow) + return True; + } + + return False; +} +#endif + + +/* + * InitQueue - Initialize the Window Manager message queue + */ + +static +Bool +InitQueue (WMMsgQueuePtr pQueue) +{ + /* Check if the pQueue pointer is NULL */ + if (pQueue == NULL) + { + ErrorF ("InitQueue - pQueue is NULL. Exiting.\n"); + return FALSE; + } + + /* Set the head and tail to NULL */ + pQueue->pHead = NULL; + pQueue->pTail = NULL; + + /* There are no elements initially */ + g_nQueueSize = 0; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("InitQueue - Queue Size %d %d\n", g_nQueueSize, QueueSize(pQueue)); +#endif + + ErrorF ("InitQueue - Calling pthread_mutex_init\n"); + + /* Create synchronization objects */ + pthread_mutex_init (&pQueue->pmMutex, NULL); + + ErrorF ("InitQueue - pthread_mutex_init returned\n"); + ErrorF ("InitQueue - Calling pthread_cond_init\n"); + + pthread_cond_init (&pQueue->pcNotEmpty, NULL); + + ErrorF ("InitQueue - pthread_cond_init returned\n"); + + return TRUE; +} + + +/* + * GetWindowName - + */ + +static void +GetWindowName (Display *pDisplay, Window iWin, char **ppName) +{ + int nResult, nNum; + char **ppList; + XTextProperty xtpName; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("GetWindowName\n"); +#endif + + /* Intialize ppName to NULL */ + *ppName = NULL; + + /* Try to get --- */ + nResult = XGetWMName (pDisplay, iWin, &xtpName); + if (!nResult || !xtpName.value || !xtpName.nitems) + { + ErrorF ("GetWindowName - XGetWMName failed. No name.\n"); + return; + } + + /* */ + if (xtpName.encoding == XA_STRING) + { + /* */ + if (xtpName.value) + { + *ppName = strdup ((char*)xtpName.value); + XFree (xtpName.value); + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("XA_STRING %s\n", *ppName); +#endif + } + else + { + XmbTextPropertyToTextList (pDisplay, &xtpName, &ppList, &nNum); + + /* */ + if (nNum && *ppList) + { + XFree (xtpName.value); + *ppName = strdup (*ppList); + XFreeStringList (ppList); + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("%s %s\n", XGetAtomName (pDisplay, xtpName.encoding), *ppName); +#endif + } + + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("-GetWindowName\n"); +#endif +} + + +/* + * Send a message to the X server from the WM thread + */ + +static int +SendXMessage (Display *pDisplay, Window iWin, Atom atmType, long nData) +{ + XEvent e; + + /* Prepare the X event structure */ + e.type = ClientMessage; + e.xclient.window = iWin; + e.xclient.message_type = atmType; + e.xclient.format = 32; + e.xclient.data.l[0] = nData; + e.xclient.data.l[1] = CurrentTime; + + /* Send the event to X */ + return XSendEvent (pDisplay, iWin, False, NoEventMask, &e); +} + + +/* + * winMultiWindowWMProc + */ + +static void * +winMultiWindowWMProc (void *pArg) +{ + WMProcArgPtr pProcArg = (WMProcArgPtr)pArg; + WMInfoPtr pWMInfo = pProcArg->pWMInfo; + + /* Initialize the Window Manager */ + winInitMultiWindowWM (pWMInfo, pProcArg); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winMultiWindowWMProc ()\n"); +#endif + + /* Loop until we explicity break out */ + for (;;) + { + WMMsgNodePtr pNode; + + /* Pop a message off of our queue */ + pNode = PopMessage (&pWMInfo->wmMsgQueue); + if (pNode == NULL) + { + /* Bail if PopMessage returns without a message */ + /* NOTE: Remember that PopMessage is a blocking function. */ + ErrorF ("winMultiWindowWMProc - Queue is Empty?\n"); + pthread_exit (NULL); + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winMultiWindowWMProc - %d ms MSG: %d ID: %d\n", + GetTickCount (), (int)pNode->msg.msg, (int)pNode->msg.dwID); +#endif + + /* Branch on the message type */ + switch (pNode->msg.msg) + { +#if 0 + case WM_WM_MOVE: + ErrorF ("\tWM_WM_MOVE\n"); + break; + + case WM_WM_SIZE: + ErrorF ("\tWM_WM_SIZE\n"); + break; +#endif + + case WM_WM_RAISE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_RAISE\n"); +#endif + + /* Raise the window */ + XRaiseWindow (pWMInfo->pDisplay, pNode->msg.iWindow); + break; + + case WM_WM_LOWER: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_LOWER\n"); +#endif + + /* Lower the window */ + XLowerWindow (pWMInfo->pDisplay, pNode->msg.iWindow); + break; + + case WM_WM_MAP: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_MAP\n"); +#endif + { + XWindowAttributes attr; + char *pszName; +#if 0 + XWMHints *pHints; +#endif + + /* Get the window attributes */ + XGetWindowAttributes (pWMInfo->pDisplay, + pNode->msg.iWindow, + &attr); + if (!attr.override_redirect) + { + /* Set the Windows window name */ + GetWindowName(pWMInfo->pDisplay, pNode->msg.iWindow, &pszName); + SetWindowText (pNode->msg.hwndWindow, pszName); + free (pszName); + } + } + break; + + case WM_WM_UNMAP: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_UNMAP\n"); +#endif + + /* Unmap the window */ + XUnmapWindow(pWMInfo->pDisplay, pNode->msg.iWindow); + break; + + case WM_WM_KILL: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_KILL\n"); +#endif + { + int i, n, found = 0; + Atom *protocols; + + /* --- */ + if (XGetWMProtocols (pWMInfo->pDisplay, + pNode->msg.iWindow, + &protocols, + &n)) + { + for (i = 0; i < n; ++i) + if (protocols[i] == pWMInfo->atmWmDelete) + ++found; + + XFree (protocols); + } + + /* --- */ + if (found) + SendXMessage (pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmWmProtos, + pWMInfo->atmWmDelete); + else + XKillClient (pWMInfo->pDisplay, + pNode->msg.iWindow); + } + break; + + case WM_WM_ACTIVATE: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_ACTIVATE\n"); +#endif + + /* Set the input focus */ + XSetInputFocus (pWMInfo->pDisplay, + pNode->msg.iWindow, + RevertToPointerRoot, + CurrentTime); + break; + + case WM_WM_X_EVENT: + /* Process all X events in the Window Manager event queue */ + FlushXEvents (pWMInfo); + break; + + default: + ErrorF ("winMultiWindowWMProc - Unknown Message.\n"); + pthread_exit (NULL); + break; + } + + /* Free the retrieved message */ + free (pNode); + + /* Flush any pending events on our display */ + XFlush (pWMInfo->pDisplay); + } + + /* Free the condition variable */ + pthread_cond_destroy (&pWMInfo->wmMsgQueue.pcNotEmpty); + + /* Free the mutex variable */ + pthread_mutex_destroy (&pWMInfo->wmMsgQueue.pmMutex); + + /* Free the passed-in argument */ + free (pProcArg); + +#if CYGMULTIWINDOW_DEBUG + ErrorF("-winMultiWindowWMProc ()\n"); +#endif +} + + +/* + * FlushXEvents - Process any pending X events + */ + +static Bool +FlushXEvents (WMInfoPtr pWMInfo) +{ + XEvent event; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("FlushXEvents ()\n"); +#endif + + /* Process all pending events */ + while (XPending (pWMInfo->pDisplay)) + { + /* Get the next event - will not block because one is ready */ + XNextEvent (pWMInfo->pDisplay, &event); + +#if 0 + /* Branch on the event type */ + switch (event.type) + { + } +#endif + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("-FlushXEvents ()\n"); +#endif + + return True; +} + + +/* + * winMultiWindowWMErrorHandler - Our application specific error handler + */ + +static int +winMultiWindowWMErrorHandler (Display *pDisplay, XErrorEvent *pErr) +{ + char pszErrorMsg[100]; + + if (pErr->request_code == X_ChangeWindowAttributes + && pErr->error_code == BadAccess) + { + ErrorF ("ChangeWindowAttributes BadAccess.\n"); + pthread_exit (NULL); + } + + XGetErrorText (pDisplay, + pErr->error_code, + pszErrorMsg, + sizeof (pszErrorMsg)); + ErrorF ("ERROR: %s\n", pszErrorMsg); + + if (pErr->error_code==BadWindow + || pErr->error_code==BadMatch + || pErr->error_code==BadDrawable) + { + pthread_exit (NULL); + } + + pthread_exit (NULL); + return 0; +} + + +/* + * winInitWM - Entry point for the X server to spawn + * the Window Manager thread. Called from + * winscrinit.c/winFinishScreenInitFB (). + */ + +Bool +winInitWM (void **ppWMInfo, + pthread_t *ptWMProc, + pthread_mutex_t *ppmServerStarted, + int dwScreen) +{ + WMProcArgPtr pArg = (WMProcArgPtr)malloc (sizeof(WMProcArgRec)); + WMInfoPtr pWMInfo = (WMInfoPtr)malloc (sizeof(WMInfoRec)); + + /* Bail if the input parameters are bad */ + if (pArg == NULL || pWMInfo == NULL) + { + ErrorF ("winInitWM - malloc fail.\n"); + return FALSE; + } + + /* Set a return pointer to the Window Manager info structure */ + *ppWMInfo = pWMInfo; + + /* Setup the argument structure for the thread function */ + pArg->dwScreen = dwScreen; + pArg->pWMInfo = pWMInfo; + pArg->ppmServerStarted = ppmServerStarted; + + /* Intialize the message queue */ + if (!InitQueue (&pWMInfo->wmMsgQueue)) + { + ErrorF ("winInitWM - InitQueue () failed.\n"); + return FALSE; + } + + /* Spawn a thread for the Window Manager */ + if (pthread_create (ptWMProc, NULL, winMultiWindowWMProc, pArg)) + { + /* Bail if thread creation failed */ + ErrorF ("winInitWM - pthread_create failed.\n"); + return FALSE; + } + +#if CYGDEBUG || YES + ErrorF ("winInitWM - Returning.\n"); +#endif + + return TRUE; +} + + +/* + * winInitMultiWindowWM - + */ + +Bool +winClipboardDetectUnicodeSupport (); + +static void +winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) +{ + int iRetries = 0; + char pszDisplay[512]; + int iReturn; + Bool fUnicodeSupport; + + ErrorF ("winInitMultiWindowWM - Hello\n"); + + /* Check that argument pointer is not invalid */ + if (pProcArg == NULL) + { + ErrorF ("winInitMultiWindowWM - pProcArg is NULL, bailing.\n"); + pthread_exit (NULL); + } + + ErrorF ("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n"); + + /* Grab our garbage mutex to satisfy pthread_cond_wait */ + iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted); + if (iReturn != 0) + { + ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () failed: %d\n", + iReturn); + pthread_exit (NULL); + } + + ErrorF ("winInitMultiWindowWM - pthread_mutex_lock () returned.\n"); + + /* Do we have Unicode support? */ + fUnicodeSupport = winClipboardDetectUnicodeSupport (); + + /* Set the current locale? What does this do? */ + if (fUnicodeSupport && !g_fCalledSetLocale) + { + ErrorF ("winInitMultiWindowWM - Calling setlocale ()\n"); + if (!setlocale (LC_ALL, "")) + { + ErrorF ("winInitMultiWindowWM - setlocale () error\n"); + pthread_exit (NULL); + } + ErrorF ("winInitMultiWindowWM - setlocale () returned\n"); + + /* See if X supports the current locale */ + if (XSupportsLocale () == False) + { + ErrorF ("winInitMultiWindowWM - Locale not supported by X\n"); + pthread_exit (NULL); + } + } + + /* Flag that we have called setlocale */ + g_fCalledSetLocale = TRUE; + + /* Release the garbage mutex */ + pthread_mutex_unlock (pProcArg->ppmServerStarted); + + ErrorF ("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n"); + + /* Allow multiple threads to access Xlib */ + if (XInitThreads () == 0) + { + ErrorF ("winInitMultiWindowWM - XInitThreads () failed.\n"); + pthread_exit (NULL); + } + + ErrorF ("winInitMultiWindowWM - XInitThreads () returned.\n"); + + /* Set jump point for Error exits */ + iReturn = setjmp (g_jmpEntry); + + /* Check if we should continue operations */ + if (iReturn != WIN_JMP_ERROR_IO + && iReturn != WIN_JMP_OKAY) + { + /* setjmp returned an unknown value, exit */ + ErrorF ("winInitMultiWindowWM - setjmp returned: %d exiting\n", + iReturn); + pthread_exit (NULL); + } + else if (iReturn == WIN_JMP_ERROR_IO) + { + ErrorF ("winInitMultiWindowWM - setjmp returned WIN_JMP_ERROR_IO\n"); + } + + /* Setup the display connection string x */ + snprintf (pszDisplay, 512, "127.0.0.1:%s.%d", display, pProcArg->dwScreen); + + /* Print the display connection string */ + ErrorF ("winInitMultiWindowWM - DISPLAY=%s\n", pszDisplay); + + /* Open the X display */ + do + { + /* Try to open the display */ + pWMInfo->pDisplay = XOpenDisplay (pszDisplay); + if (pWMInfo->pDisplay == NULL) + { + ErrorF ("winInitMultiWindowWM - Could not open display, try: %d, " + "sleeping: %d\n\f", + iRetries + 1, WIN_CONNECT_DELAY); + ++iRetries; + sleep (WIN_CONNECT_DELAY); + continue; + } + else + break; + } + while (pWMInfo->pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); + + /* Make sure that the display opened */ + if (pWMInfo->pDisplay == NULL) + { + ErrorF ("winInitMultiWindowWM - Failed opening the display, " + "giving up.\n\f"); + pthread_exit (NULL); + } + + ErrorF ("winInitMultiWindowWM - XOpenDisplay () returned and " + "successfully opened the display.\n"); + + /* Install our error handler */ + XSetErrorHandler (winMultiWindowWMErrorHandler); + XSetIOErrorHandler (winMutliWindowWMIOErrorHandler); + + /* Create some atoms */ + pWMInfo->atmWmProtos = XInternAtom (pWMInfo->pDisplay, + "WM_PROTOCOLS", + False); + pWMInfo->atmWmDelete = XInternAtom (pWMInfo->pDisplay, + "WM_DELETE_WINDOW", + False); +} + + +/* + * winSendMessageToWM - Send a message from the X thread to the WM thread + */ + +void +winSendMessageToWM (void *pWMInfo, winWMMessagePtr pMsg) +{ + WMMsgNodePtr pNode; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winSendMessageToWM ()\n"); +#endif + + pNode = (WMMsgNodePtr)malloc(sizeof(WMMsgNodeRec)); + if (pNode != NULL) + { + memcpy (&pNode->msg, pMsg, sizeof(winWMMessageRec)); + PushMessage (&((WMInfoPtr)pWMInfo)->wmMsgQueue, pNode); + } +} + + +/* + * winMutliWindowWMIOErrorHandler - Our application specific IO error handler + */ + +static int +winMutliWindowWMIOErrorHandler (Display *pDisplay) +{ + printf ("\nwinMutliWindowWMIOErrorHandler!\n\n"); + + /* Restart at the main entry point */ + longjmp (g_jmpEntry, WIN_JMP_ERROR_IO); + + return 0; +} diff --git a/xc/programs/Xserver/hw/xwin/winscrinit.c b/xc/programs/Xserver/hw/xwin/winscrinit.c index 4b6aa689e..41811d253 100644 --- a/xc/programs/Xserver/hw/xwin/winscrinit.c +++ b/xc/programs/Xserver/hw/xwin/winscrinit.c @@ -29,9 +29,9 @@ * Suhaib M Siddiqi * Peter Busch * Harold L Hunt II - * MATSUZAKI Kensuke + * Kensuke Matsuzaki */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winscrinit.c,v 1.24 2002/10/17 08:18:24 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winscrinit.c,v 1.26 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -50,13 +50,6 @@ winScreenInit (int index, winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index]; winPrivScreenPtr pScreenPriv; HDC hdc; -#if 0 - DEBUG_FN_NAME("winScreenInit"); - DEBUGVARS; - /*DEBUGPROC_MSG;*/ - - DEBUG_MSG ("Hello"); -#endif #if CYGDEBUG ErrorF ("winScreenInit - dwWidth: %d dwHeight: %d\n", @@ -113,6 +106,19 @@ winScreenInit (int index, #endif } + /* + * Check that all monitors have the same display depth if we are using + * multiple monitors + */ + if (pScreenInfo->fMultipleMonitors + && !GetSystemMetrics (SM_SAMEDISPLAYFORMAT)) + { + ErrorF ("winScreenInit - Monitors do not all have same pixel format / " + "display depth.\n" + "Using primary display only.\n"); + pScreenInfo->fMultipleMonitors = FALSE; + } + /* Create display window */ if (!(*pScreenPriv->pwinCreateBoundingWindow) (pScreen)) { @@ -121,12 +127,40 @@ winScreenInit (int index, return FALSE; } - /* Store the initial height, width, and depth of the display */ + /* Get a device context */ hdc = GetDC (pScreenPriv->hwndScreen); - pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXSCREEN); - pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYSCREEN); - pScreenPriv->dwLastWindowsBitsPixel - = GetDeviceCaps (hdc, BITSPIXEL); + + /* Store the initial height, width, and depth of the display */ + /* Are we using multiple monitors? */ + if (pScreenInfo->fMultipleMonitors) + { + pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN); + pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN); + + /* + * In this case, some of the defaults set in + * winInitializeDefaultScreens () are not correct ... + */ + if (!pScreenInfo->fUserGaveHeightAndWidth) + { + pScreenInfo->dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN); + pScreenInfo->dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN); + pScreenInfo->dwWidth_mm = (pScreenInfo->dwWidth / + WIN_DEFAULT_DPI) * 25.4; + pScreenInfo->dwHeight_mm = (pScreenInfo->dwHeight / + WIN_DEFAULT_DPI) * 25.4; + } + } + else + { + pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXSCREEN); + pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYSCREEN); + } + + /* Save the original bits per pixel */ + pScreenPriv->dwLastWindowsBitsPixel = GetDeviceCaps (hdc, BITSPIXEL); + + /* Release the device context */ ReleaseDC (pScreenPriv->hwndScreen, hdc); /* Clear the visuals list */ @@ -161,6 +195,7 @@ winFinishScreenInitFB (int index, winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; VisualPtr pVisual = NULL; char *pbits = NULL; + int iReturn; #if WIN_LAYER_SUPPORT pScreenPriv->dwLayerKind = LAYER_SHADOW; @@ -390,6 +425,9 @@ winFinishScreenInitFB (int index, WRAP(UnrealizeWindow); WRAP(PositionWindow); WRAP(ChangeWindowAttributes); +#ifdef SHAPE + WRAP(SetShape); +#endif /* Assign pseudo-rootless window procedures to be top level procedures */ pScreen->CreateWindow = winCreateWindowPRootless; @@ -398,6 +436,50 @@ winFinishScreenInitFB (int index, pScreen->ChangeWindowAttributes = winChangeWindowAttributesPRootless; pScreen->RealizeWindow = winMapWindowPRootless; pScreen->UnrealizeWindow = winUnmapWindowPRootless; +#ifdef SHAPE + pScreen->SetShape = winSetShapePRootless; +#endif + + /* Undefine the WRAP macro, as it is not needed elsewhere */ +#undef WRAP + } + /* Handle multi window mode */ + else if (pScreenInfo->fMultiWindow) + { + /* Define the WRAP macro temporarily for local use */ +#define WRAP(a) \ + if (pScreen->a) { \ + pScreenPriv->a = pScreen->a; \ + } else { \ + ErrorF("null screen fn " #a "\n"); \ + pScreenPriv->a = NULL; \ + } + + /* Save a pointer to each lower-level window procedure */ + WRAP(CreateWindow); + WRAP(DestroyWindow); + WRAP(RealizeWindow); + WRAP(UnrealizeWindow); + WRAP(PositionWindow); + WRAP(ChangeWindowAttributes); + WRAP(ReparentWindow); + WRAP(RestackWindow); +#ifdef SHAPE + WRAP(SetShape); +#endif + + /* Assign multi-window window procedures to be top level procedures */ + pScreen->CreateWindow = winCreateWindowMultiWindow; + pScreen->DestroyWindow = winDestroyWindowMultiWindow; + pScreen->PositionWindow = winPositionWindowMultiWindow; + pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow; + pScreen->RealizeWindow = winMapWindowMultiWindow; + pScreen->UnrealizeWindow = winUnmapWindowMultiWindow; + pScreen->ReparentWindow = winReparentWindowMultiWindow; + pScreen->RestackWindow = winRestackWindowMultiWindow; +#ifdef SHAPE + pScreen->SetShape = winSetShapeMultiWindow; +#endif /* Undefine the WRAP macro, as it is not needed elsewhere */ #undef WRAP @@ -407,13 +489,65 @@ winFinishScreenInitFB (int index, pScreenPriv->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = pScreenPriv->pwinCloseScreen; + /* Create a mutex for modules in seperate threads to wait for */ + iReturn = pthread_mutex_init (&pScreenPriv->pmServerStarted, NULL); + if (iReturn != 0) + { + ErrorF ("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n", + iReturn); + return FALSE; + } + + /* Own the mutex for modules in seperate threads */ + iReturn = pthread_mutex_lock (&pScreenPriv->pmServerStarted); + if (iReturn != 0) + { + ErrorF ("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n", + iReturn); + return FALSE; + } + + /* Set the ServerStarted flag to false */ + pScreenPriv->fServerStarted = FALSE; + +#if CYGDEBUG || YES + if (pScreenInfo->fMultiWindow) + ErrorF ("winFinishScreenInitFB - Calling winInitWM.\n"); +#endif + + /* Initialize multi window mode */ + if (pScreenInfo->fMultiWindow + && !winInitWM (&pScreenPriv->pWMInfo, + &pScreenPriv->ptWMProc, + &pScreenPriv->pmServerStarted, + pScreenInfo->dwScreen)) + { + ErrorF ("winFinishScreenInitFB - winInitWM () failed.\n"); + return FALSE; + } + +#if CYGDEBUG || YES + if (pScreenInfo->fClipboard) + ErrorF ("winFinishScreenInitFB - Calling winInitClipboard.\n"); +#endif + + /* Initialize the clipboard manager */ + if (pScreenInfo->fClipboard + && !winInitClipboard (&pScreenPriv->ptClipboardProc, + &pScreenPriv->pmServerStarted, + pScreenInfo->dwScreen)) + { + ErrorF ("winFinishScreenInitFB - winClipboardInit () failed.\n"); + return FALSE; + } + /* Tell the server that we are enabled */ pScreenPriv->fEnabled = TRUE; /* Tell the server that we have a valid depth */ pScreenPriv->fBadDepth = FALSE; -#if CYGDEBUG +#if CYGDEBUG || YES ErrorF ("winFinishScreenInitFB - returning\n"); #endif diff --git a/xc/programs/Xserver/hw/xwin/winshaddd.c b/xc/programs/Xserver/hw/xwin/winshaddd.c index 451d822aa..9c14ebf34 100644 --- a/xc/programs/Xserver/hw/xwin/winshaddd.c +++ b/xc/programs/Xserver/hw/xwin/winshaddd.c @@ -30,7 +30,7 @@ * Peter Busch * Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winshaddd.c,v 1.22 2002/10/17 08:18:24 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winshaddd.c,v 1.23 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -124,18 +124,19 @@ winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen) ErrorF ("winReleasePrimarySurfaceShadowDD - Hello\n"); - /* - * Detach the clipper from the primary surface. - * NOTE: We do this explicity for clarity. The Clipper is not released. - */ - IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary, - NULL); - - ErrorF ("winReleasePrimarySurfaceShadowDD - Detached clipper\n"); - - /* Release the primary surface, if there is one */ + /* Release the primary surface and clipper, if they exist */ if (pScreenPriv->pddsPrimary) { + /* + * Detach the clipper from the primary surface. + * NOTE: We do this explicity for clarity. The Clipper is not released. + */ + IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary, + NULL); + + ErrorF ("winReleasePrimarySurfaceShadowDD - Detached clipper\n"); + + /* Release the primary surface */ IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary); pScreenPriv->pddsPrimary = NULL; } @@ -289,10 +290,11 @@ winAllocateFBShadowDD (ScreenPtr pScreen) } /* Only change the video mode when different than current mode */ - if (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN) - || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN) - || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL) - || pScreenInfo->dwRefreshRate != 0) + if (!pScreenInfo->fMultipleMonitors + && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN) + || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN) + || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL) + || pScreenInfo->dwRefreshRate != 0)) { ErrorF ("winAllocateFBShadowDD - Changing video mode\n"); @@ -639,7 +641,7 @@ winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen) if (pScreenPriv->pddcPrimary) { /* Detach the clipper */ - IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary, + IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary, NULL); /* Release the clipper object */ @@ -676,6 +678,9 @@ winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen) pScreenPriv->hwndScreen = NULL; } + /* Destroy the thread startup mutex */ + pthread_mutex_destroy (&pScreenPriv->pmServerStarted); + /* Kill our screeninfo's pointer to the screen */ pScreenInfo->pScreen = NULL; @@ -992,7 +997,7 @@ winBltExposedRegionsShadowDD (ScreenPtr pScreen) /* Try to restore the surface, once */ ddrval = IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary); ErrorF ("winBltExposedRegionsShadowDDNL - " - "IDirectDrawSurface4_Restore returned: "); + "IDirectDrawSurface2_Restore returned: "); if (ddrval == DD_OK) continue; else if (ddrval == DDERR_WRONGMODE) diff --git a/xc/programs/Xserver/hw/xwin/winshadddnl.c b/xc/programs/Xserver/hw/xwin/winshadddnl.c index e1cbffeb7..69396a79b 100644 --- a/xc/programs/Xserver/hw/xwin/winshadddnl.c +++ b/xc/programs/Xserver/hw/xwin/winshadddnl.c @@ -30,7 +30,7 @@ * Peter Busch * Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winshadddnl.c,v 1.23 2002/10/17 08:18:25 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winshadddnl.c,v 1.24 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -123,18 +123,19 @@ winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen) ErrorF ("winReleasePrimarySurfaceShadowDDNL - Hello\n"); - /* - * Detach the clipper from the primary surface. - * NOTE: We do this explicity for clarity. The Clipper is not released. - */ - IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, - NULL); - - ErrorF ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n"); - - /* Release the primary surface, if there is one */ + /* Release the primary surface and clipper, if they exist */ if (pScreenPriv->pddsPrimary4) { + /* + * Detach the clipper from the primary surface. + * NOTE: We do this explicity for clarity. The Clipper is not released. + */ + IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, + NULL); + + ErrorF ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n"); + + /* Release the primary surface */ IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4); pScreenPriv->pddsPrimary4 = NULL; } @@ -307,10 +308,11 @@ winAllocateFBShadowDDNL (ScreenPtr pScreen) } /* Only change the video mode when different than current mode */ - if (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN) - || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN) - || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL) - || pScreenInfo->dwRefreshRate != 0) + if (!pScreenInfo->fMultipleMonitors + && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN) + || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN) + || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL) + || pScreenInfo->dwRefreshRate != 0)) { ErrorF ("winAllocateFBShadowDDNL - Changing video mode\n"); @@ -418,7 +420,7 @@ winAllocateFBShadowDDNL (ScreenPtr pScreen) return FALSE; } -#if CYGDEBUG +#if CYGDEBUG || YES ErrorF ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n", ddsdShadow.u1.lPitch); #endif @@ -427,6 +429,11 @@ winAllocateFBShadowDDNL (ScreenPtr pScreen) pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8) / pScreenInfo->dwBPP; +#if CYGDEBUG || YES + ErrorF ("winAllocateFBShadowDDNL - Created shadow stride: %d\n", + pScreenInfo->dwStride); +#endif + /* Save the pointer to our surface memory */ pScreenInfo->pfb = lpSurface; @@ -541,9 +548,6 @@ winShadowUpdateDDNL (ScreenPtr pScreen, ErrorF ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n", pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2, pBoxExtents->y2); - ErrorF ("winShadowUpdateDDNL - cl l %d t %d r %d b %d\n", - rcClient.left, rcClient.top, - rcClient.right, rcClient.bottom); #endif /* Calculating a bounding box for the source is easy */ @@ -653,9 +657,15 @@ winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen) pScreenPriv->hwndScreen = NULL; } + /* Destroy the thread startup mutex */ + pthread_mutex_destroy (&pScreenPriv->pmServerStarted); + /* Kill our screeninfo's pointer to the screen */ pScreenInfo->pScreen = NULL; + /* Invalidate the ScreenInfo's fb pointer */ + pScreenInfo->pfb = NULL; + /* Free the screen privates for this screen */ free ((pointer) pScreenPriv); diff --git a/xc/programs/Xserver/hw/xwin/winshadgdi.c b/xc/programs/Xserver/hw/xwin/winshadgdi.c index db90e8884..d2f72f20d 100644 --- a/xc/programs/Xserver/hw/xwin/winshadgdi.c +++ b/xc/programs/Xserver/hw/xwin/winshadgdi.c @@ -27,11 +27,19 @@ * * Authors: Harold L Hunt II */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winshadgdi.c,v 1.21 2002/10/17 08:18:25 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winshadgdi.c,v 1.22 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" /* + * Local function prototypes + */ + +BOOL CALLBACK +winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam); + + +/* * Internal function to get the DIB format that is compatible with the screen */ @@ -198,6 +206,27 @@ winQueryRGBBitsAndMasks (ScreenPtr pScreen) /* + * Redraw all ---? + */ + +BOOL CALLBACK +winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam) +{ + char strClassName[100]; + + if (GetClassName (hwnd, strClassName, 100)) + { + if(strcmp (WINDOW_CLASS_X, strClassName) == 0) + { + InvalidateRect (hwnd, NULL, FALSE); + UpdateWindow (hwnd); + } + } + return TRUE; +} + + +/* * Allocate a DIB for the shadow framebuffer GDI server */ @@ -207,9 +236,7 @@ winAllocateFBShadowGDI (ScreenPtr pScreen) winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; BITMAPINFOHEADER *pbmih = NULL; -#if CYGDEBUG DIBSECTION dibsection; -#endif Bool fReturn = TRUE; /* Get device contexts for the screen and shadow bitmap */ @@ -232,6 +259,10 @@ winAllocateFBShadowGDI (ScreenPtr pScreen) pbmih->biWidth = pScreenInfo->dwWidth; pbmih->biHeight = -pScreenInfo->dwHeight; + ErrorF ("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d " + "depth: %d\n", + pbmih->biWidth, -pbmih->biHeight, pbmih->biBitCount); + /* Create a DI shadow bitmap with a bit pointer */ pScreenPriv->hbmpShadow = CreateDIBSection (pScreenPriv->hdcScreen, (BITMAPINFO *) pbmih, @@ -251,14 +282,18 @@ winAllocateFBShadowGDI (ScreenPtr pScreen) #endif } -#if CYGDEBUG /* Get information about the bitmap that was allocated */ - GetObject (pScreenPriv->hbmpShadow, sizeof (dibsection), + GetObject (pScreenPriv->hbmpShadow, + sizeof (dibsection), &dibsection); +#if CYGDEBUG || YES /* Print information about bitmap allocated */ - ErrorF ("winAllocateFBShadowGDI - Dibsection width: %d height: %d\n", - dibsection.dsBmih.biWidth, dibsection.dsBmih.biHeight); + ErrorF ("winAllocateFBShadowGDI - Dibsection width: %d height: %d " + "depth: %d size image: %d\n", + dibsection.dsBmih.biWidth, dibsection.dsBmih.biHeight, + dibsection.dsBmih.biBitCount, + dibsection.dsBmih.biSizeImage); #endif /* Select the shadow bitmap into the shadow DC */ @@ -289,8 +324,14 @@ winAllocateFBShadowGDI (ScreenPtr pScreen) } /* Set screeninfo stride */ - pScreenInfo->dwStride = (pScreenInfo->dwPaddedWidth * 8) - / pScreenInfo->dwBPP; + pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage + / dibsection.dsBmih.biHeight) + * 8) / pScreenInfo->dwBPP; + +#if CYGDEBUG || YES + ErrorF ("winAllocateFBShadowGDI - Created shadow stride: %d\n", + pScreenInfo->dwStride); +#endif /* See if the shadow bitmap will be larger than the DIB size limit */ if (pScreenInfo->dwWidth * pScreenInfo->dwHeight * pScreenInfo->dwBPP @@ -311,6 +352,9 @@ winAllocateFBShadowGDI (ScreenPtr pScreen) return FALSE; } + /* Redraw all windows */ + if (pScreenInfo->fMultiWindow) EnumWindows(winRedrawAllProcShadowGDI, 0); + return fReturn; } @@ -428,6 +472,9 @@ winShadowUpdateGDI (ScreenPtr pScreen, /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } + + /* Redraw all windows */ + if (pScreenInfo->fMultiWindow) EnumWindows(winRedrawAllProcShadowGDI, 0); } @@ -475,6 +522,9 @@ winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen) pScreenPriv->hwndScreen = NULL; } + /* Destroy the thread startup mutex */ + pthread_mutex_destroy (&pScreenPriv->pmServerStarted); + /* Invalidate our screeninfo's pointer to the screen */ pScreenInfo->pScreen = NULL; @@ -715,6 +765,9 @@ winBltExposedRegionsShadowGDI (ScreenPtr pScreen) /* EndPaint frees the DC */ EndPaint (pScreenPriv->hwndScreen, &ps); + /* Redraw all windows */ + if (pScreenInfo->fMultiWindow) EnumWindows(winRedrawAllProcShadowGDI, 0); + return TRUE; } @@ -782,6 +835,8 @@ winRedrawScreenShadowGDI (ScreenPtr pScreen) 0, 0, SRCCOPY); + /* Redraw all windows */ + if (pScreenInfo->fMultiWindow) EnumWindows(winRedrawAllProcShadowGDI, 0); return TRUE; } @@ -886,6 +941,9 @@ winInstallColormapShadowGDI (ColormapPtr pColormap) /* Save a pointer to the newly installed colormap */ pScreenPriv->pcmapInstalled = pColormap; + /* Redraw all windows */ + if (pScreenInfo->fMultiWindow) EnumWindows(winRedrawAllProcShadowGDI, 0); + return TRUE; } diff --git a/xc/programs/Xserver/hw/xwin/winwindow.c b/xc/programs/Xserver/hw/xwin/winwindow.c index ae8643b32..b2469c30a 100644 --- a/xc/programs/Xserver/hw/xwin/winwindow.c +++ b/xc/programs/Xserver/hw/xwin/winwindow.c @@ -26,9 +26,9 @@ *from the XFree86 Project. * * Authors: Harold L Hunt II - * MATSUZAKI Kensuke + * Kensuke Matsuzaki */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winwindow.c,v 1.3 2002/10/17 08:18:25 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winwindow.c,v 1.6 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" @@ -39,9 +39,15 @@ static int winAddRgn (WindowPtr pWindow, pointer data); -static void +static +void winUpdateRgn (WindowPtr pWindow); +#ifdef SHAPE +static +void +winReshape (WindowPtr pWin); +#endif /* See Porting Layer Definition - p. 37 */ @@ -50,7 +56,7 @@ winUpdateRgn (WindowPtr pWindow); Bool winCreateWindowNativeGDI (WindowPtr pWin) { - ErrorF ("winCreateWindow()\n"); + ErrorF ("winCreateWindowNativeGDI ()\n"); return TRUE; } @@ -61,7 +67,7 @@ winCreateWindowNativeGDI (WindowPtr pWin) Bool winDestroyWindowNativeGDI (WindowPtr pWin) { - ErrorF ("winDestroyWindow()\n"); + ErrorF ("winDestroyWindowNativeGDI ()\n"); return TRUE; } @@ -72,7 +78,7 @@ winDestroyWindowNativeGDI (WindowPtr pWin) Bool winPositionWindowNativeGDI (WindowPtr pWin, int x, int y) { - ErrorF ("winPositionWindow()\n"); + ErrorF ("winPositionWindowNativeGDI ()\n"); return TRUE; } @@ -85,7 +91,7 @@ winCopyWindowNativeGDI (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { - ErrorF ("winCopyWindow()\n"); + ErrorF ("winCopyWindowNativeGDI ()\n"); } @@ -95,7 +101,7 @@ winCopyWindowNativeGDI (WindowPtr pWin, Bool winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask) { - ErrorF ("winChangeWindowAttributes()\n"); + ErrorF ("winChangeWindowAttributesNativeGDI ()\n"); return TRUE; } @@ -107,7 +113,7 @@ winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask) Bool winUnmapWindowNativeGDI (WindowPtr pWindow) { - ErrorF ("winUnmapWindow()\n"); + ErrorF ("winUnmapWindowNativeGDI ()\n"); /* This functions is empty in the CFB, * we probably won't need to do anything */ @@ -122,7 +128,7 @@ winUnmapWindowNativeGDI (WindowPtr pWindow) Bool winMapWindowNativeGDI (WindowPtr pWindow) { - ErrorF ("winMapWindow()\n"); + ErrorF ("winMapWindowNativeGDI ()\n"); /* This function is empty in the CFB, * we probably won't need to do anything */ @@ -138,13 +144,15 @@ Bool winCreateWindowPRootless (WindowPtr pWin) { Bool fResult = FALSE; + winWindowPriv(pWin); #if CYGDEBUG - ErrorF ("winCreateWindowPRootless()\n"); + ErrorF ("winCreateWindowPRootless ()\n"); #endif fResult = winGetScreenPriv(pWin->drawable.pScreen)->CreateWindow(pWin); + pWinPriv->hRgn = NULL; /*winUpdateRgn (pWin);*/ return fResult; @@ -158,13 +166,20 @@ Bool winDestroyWindowPRootless (WindowPtr pWin) { Bool fResult = FALSE; + winWindowPriv(pWin); #if CYGDEBUG - ErrorF ("winDestroyWindowPRootless()\n"); + ErrorF ("winDestroyWindowPRootless ()\n"); #endif fResult = winGetScreenPriv(pWin->drawable.pScreen)->DestroyWindow(pWin); + if (pWinPriv->hRgn != NULL) + { + DeleteObject(pWinPriv->hRgn); + pWinPriv->hRgn = NULL; + } + winUpdateRgn (pWin); return fResult; @@ -180,7 +195,7 @@ winPositionWindowPRootless (WindowPtr pWin, int x, int y) Bool fResult = FALSE; #if CYGDEBUG - ErrorF ("winPositionWindowPRootless()\n"); + ErrorF ("winPositionWindowPRootless ()\n"); #endif fResult = winGetScreenPriv(pWin->drawable.pScreen)->PositionWindow(pWin, x, y); @@ -200,7 +215,7 @@ winChangeWindowAttributesPRootless (WindowPtr pWin, unsigned long mask) Bool fResult = FALSE; #if CYGDEBUG - ErrorF ("winChangeWindowAttributesPRootless()\n"); + ErrorF ("winChangeWindowAttributesPRootless ()\n"); #endif fResult = winGetScreenPriv(pWin->drawable.pScreen)->ChangeWindowAttributes(pWin, mask); @@ -219,13 +234,20 @@ Bool winUnmapWindowPRootless (WindowPtr pWin) { Bool fResult = FALSE; + winWindowPriv(pWin); #if CYGDEBUG - ErrorF ("winUnmapWindowPRootless()\n"); + ErrorF ("winUnmapWindowPRootless ()\n"); #endif fResult = winGetScreenPriv(pWin->drawable.pScreen)->UnrealizeWindow(pWin); + if (pWinPriv->hRgn != NULL) + { + DeleteObject(pWinPriv->hRgn); + pWinPriv->hRgn = NULL; + } + winUpdateRgn (pWin); return fResult; @@ -242,57 +264,92 @@ winMapWindowPRootless (WindowPtr pWin) Bool fResult = FALSE; #if CYGDEBUG - ErrorF ("winMapWindowPRootless()\n"); + ErrorF ("winMapWindowPRootless ()\n"); #endif fResult = winGetScreenPriv(pWin->drawable.pScreen)->RealizeWindow(pWin); + winReshape (pWin); + winUpdateRgn (pWin); return fResult; } +#ifdef SHAPE +void +winSetShapePRootless (WindowPtr pWin) +{ +#if CYGDEBUG + ErrorF ("winSetShapePRootless ()\n"); +#endif + + winGetScreenPriv(pWin->drawable.pScreen)->SetShape(pWin); + + winReshape (pWin); + winUpdateRgn (pWin); + + return; +} +#endif + + /* * Local function for adding a region to the Windows window region */ static int -winAddRgn (WindowPtr pWindow, pointer data) +winAddRgn (WindowPtr pWin, pointer data) { int iX, iY, iWidth, iHeight, iBorder; HRGN hRgn = *(HRGN*)data; HRGN hRgnWin; + winWindowPriv(pWin); - /* If pWindow is not Root */ - if (pWindow->parent != NULL) + /* If pWin is not Root */ + if (pWin->parent != NULL) { - ErrorF("winAddRgn()\n"); - if (pWindow->mapped) +#if CYGDEBUG + ErrorF ("winAddRgn ()\n"); +#endif + if (pWin->mapped) { - iBorder = wBorderWidth (pWindow); + iBorder = wBorderWidth (pWin); + + iX = pWin->drawable.x - iBorder; + iY = pWin->drawable.y - iBorder; - iX = pWindow->drawable.x - iBorder; - iY = pWindow->drawable.y - iBorder; + iWidth = pWin->drawable.width + iBorder * 2; + iHeight = pWin->drawable.height + iBorder * 2; - iWidth = pWindow->drawable.width + iBorder * 2; - iHeight = pWindow->drawable.height + iBorder * 2; + hRgnWin = CreateRectRgn (0, 0, iWidth, iHeight); - hRgnWin = CreateRectRgn (iX, iY, iX + iWidth, iY + iHeight); if (hRgnWin == NULL) { - ErrorF ("winAddRgn - CreateRectRgn() failed\n"); + ErrorF ("winAddRgn - CreateRectRgn () failed\n"); ErrorF (" Rect %d %d %d %d\n", - iX, iY, iX + iWidth, iY + iHeight); + iX, iY, iX + iWidth, iY + iHeight); + } + + if (pWinPriv->hRgn) + { + if (CombineRgn (hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND) + == ERROR) + { + ErrorF ("winAddRgn - CombineRgn () failed\n"); + } } + + OffsetRgn (hRgnWin, iX, iY); if (CombineRgn (hRgn, hRgn, hRgnWin, RGN_OR) == ERROR) { - ErrorF("winAddRgn - CombineRgn() failed\n"); + ErrorF ("winAddRgn - CombineRgn () failed\n"); } - DeleteObject(hRgnWin); + DeleteObject (hRgnWin); } return WT_DONTWALKCHILDREN; } @@ -309,18 +366,98 @@ winAddRgn (WindowPtr pWindow, pointer data) static void -winUpdateRgn (WindowPtr pWindow) +winUpdateRgn (WindowPtr pWin) { HRGN hRgn = CreateRectRgn (0, 0, 0, 0); if (hRgn != NULL) { - WalkTree (pWindow->drawable.pScreen, winAddRgn, &hRgn); - SetWindowRgn (winGetScreenPriv(pWindow->drawable.pScreen)->hwndScreen, + WalkTree (pWin->drawable.pScreen, winAddRgn, &hRgn); + SetWindowRgn (winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen, hRgn, TRUE); } else { - ErrorF ("winUpdateRgn fail to CreateRectRgn\n"); + ErrorF ("winUpdateRgn - CreateRectRgn failed.\n"); } } + + +#ifdef SHAPE +static +void +winReshape (WindowPtr pWin) +{ + int nRects; + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec rrNewShape; + BoxPtr pShape, pRects, pEnd; + HRGN hRgn, hRgnRect; + winWindowPriv(pWin); + +#if CYGDEBUG + ErrorF ("winReshape ()\n"); +#endif + + /* Bail if the window is the root window */ + if (pWin->parent == NULL) + return; + + /* Bail if the window is not top level */ + if (pWin->parent->parent != NULL) + return; + + /* Free any existing window region stored in the window privates */ + if (pWinPriv->hRgn != NULL) + { + DeleteObject (pWinPriv->hRgn); + pWinPriv->hRgn = NULL; + } + + /* Bail if the window has no bounding region defined */ + if (!wBoundingShape (pWin)) + return; + + REGION_INIT(pScreen, &rrNewShape, NullBox, 0); + REGION_COPY(pScreen, &rrNewShape, wBoundingShape(pWin)); + REGION_TRANSLATE(pScreen, &rrNewShape, pWin->borderWidth, + pWin->borderWidth); + + nRects = REGION_NUM_RECTS(&rrNewShape); + pShape = REGION_RECTS(&rrNewShape); + + if (nRects > 0) + { + /* Create initial empty Windows region */ + hRgn = CreateRectRgn (0, 0, 0, 0); + + /* Loop through all rectangles in the X region */ + for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) + { + /* Create a Windows region for the X rectangle */ + hRgnRect = CreateRectRgn (pRects->x1, pRects->y1, + pRects->x2, pRects->y2); + if (hRgnRect == NULL) + { + ErrorF("winReshape - CreateRectRgn() failed\n"); + } + + /* Merge the Windows region with the accumulated region */ + if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) + { + ErrorF("winReshape - CombineRgn() failed\n"); + } + + /* Delete the temporary Windows region */ + DeleteObject (hRgnRect); + } + + /* Save a handle to the composite region in the window privates */ + pWinPriv->hRgn = hRgn; + } + + REGION_UNINIT(pScreen, &rrNewShape); + + return; +} +#endif diff --git a/xc/programs/Xserver/hw/xwin/winwindow.h b/xc/programs/Xserver/hw/xwin/winwindow.h new file mode 100644 index 000000000..d828b4c70 --- /dev/null +++ b/xc/programs/Xserver/hw/xwin/winwindow.h @@ -0,0 +1,118 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *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 XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Kensuke Matsuzaki + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winwindow.h,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + + +#ifndef _WINWINDOW_H_ +#define _WINWINDOW_H_ + +#ifndef NO +#define NO 0 +#endif +#ifndef YES +#define YES 1 +#endif + +/* Constant strings */ +#define WINDOW_CLASS "cygwin/xfree86 rl" +#define WINDOW_TITLE "Cygwin/XFree86 rl" +#define WIN_SCR_PROP "cyg_screen_prop_rl" +#define WINDOW_CLASS_X "cygwin/xfree86 X rl" +#define WINDOW_TITLE_X "Cygwin/XFree86 X rl" +#define WIN_WINDOW_PROP "cyg_window_prop_rl" +#define WIN_MSG_QUEUE_FNAME "/dev/windows" +#define WIN_LOG_FNAME "/tmp/XWinrl.log" +#define WIN_WID_PROP "cyg_wid_prop_rl" +#define WIN_NEEDMANAGE_PROP "cyg_override_redirect_prop_rl" +#define CYGMULTIWINDOW_DEBUG NO + +typedef struct _winPrivScreenRec *winPrivScreenPtr; + +/* + * Window privates + */ + +typedef struct +{ + DWORD dwDummy; + HRGN hRgn; + HWND hWnd; + winPrivScreenPtr pScreenPriv; + int iX; + int iY; + int iWidth; + int iHeight; + Bool fXKilled; +} winPrivWinRec, *winPrivWinPtr; + +typedef struct _winWMMessageRec{ + DWORD dwID; + DWORD msg; + int iWindow; + HWND hwndWindow; + int iX, iY; + int iWidth, iHeight; +} winWMMessageRec, *winWMMessagePtr; + +/* + * winrootlesswm.c + */ +#define WM_WM_MOVE (WM_USER + 1) +#define WM_WM_SIZE (WM_USER + 2) +#define WM_WM_RAISE (WM_USER + 3) +#define WM_WM_LOWER (WM_USER + 4) +#define WM_WM_MAP (WM_USER + 5) +#define WM_WM_UNMAP (WM_USER + 6) +#define WM_WM_KILL (WM_USER + 7) +#define WM_WM_ACTIVATE (WM_USER + 8) + +#define WMMSG_MSG 10 + + +/* + * winmultiwindowwm.c + */ + +void +winSendMessageToWM (void *pWMInfo, winWMMessagePtr msg); + +Bool +winInitWM (void **ppWMInfo, + pthread_t *ptWMProc, +#if 0 + pthread_cond_t *ppcServerStarted, +#endif + pthread_mutex_t *ppmServerStarted, +#if 0 + Bool *pfServerStarted, +#endif + int dwScreen); + +#endif diff --git a/xc/programs/Xserver/hw/xwin/winwndproc.c b/xc/programs/Xserver/hw/xwin/winwndproc.c index 5bdd18c82..6aa29316d 100644 --- a/xc/programs/Xserver/hw/xwin/winwndproc.c +++ b/xc/programs/Xserver/hw/xwin/winwndproc.c @@ -31,7 +31,7 @@ * Harold L Hunt II * MATSUZAKI Kensuke */ -/* $XFree86: xc/programs/Xserver/hw/xwin/winwndproc.c,v 1.23 2002/10/17 08:18:25 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winwndproc.c,v 1.24 2003/02/12 15:01:38 alanh Exp $ */ #include "win.h" #include <commctrl.h> @@ -300,6 +300,7 @@ winWindowProc (HWND hwnd, UINT message, if (!s_pScreenInfo->fScrollbars || !s_pScreenInfo->fDecoration || s_pScreenInfo->fRootless + || s_pScreenInfo->fMultiWindow || s_pScreenInfo->fFullScreen) break; @@ -569,7 +570,8 @@ winWindowProc (HWND hwnd, UINT message, || !s_pScreenInfo->fScrollbars || s_pScreenInfo->fFullScreen || !s_pScreenInfo->fDecoration - || s_pScreenInfo->fRootless) + || s_pScreenInfo->fRootless + || s_pScreenInfo->fMultiWindow) break; /* |