New rootless mode that use generic rootless code. Add windows rootless

window management extension.
This commit is contained in:
Kensuke Matsuzaki 2003-12-05 03:37:26 +00:00
parent 35e83daf20
commit 4e7ade29ed
12 changed files with 2817 additions and 42 deletions

View file

@ -638,7 +638,7 @@ typedef struct {
((WindowPtr) (pWin))->devPrivates[fbWinPrivateIndex].ptr)
#endif
#ifdef __DARWIN__
#if defined(__DARWIN__)||defined(__CYGWIN__)
#define __fbPixOriginX(pPix) ((pPix)->drawable.x)
#define __fbPixOriginY(pPix) ((pPix)->drawable.y)
#else

View file

@ -172,6 +172,7 @@
#include "shadow.h"
#include "fb.h"
#include "layer.h"
#include "rootless.h"
#ifdef RENDER
#include "mipict.h"
@ -498,6 +499,16 @@ typedef struct _winPrivScreenRec
/* Privates used by both shadow fb DirectDraw servers */
LPDIRECTDRAWCLIPPER pddcPrimary;
/* Privates used by rootless server */
RootlessFrameID widTop;
QueryBestSizeProcPtr QueryBestSize;
miPointerSpriteFuncPtr spriteFuncs;
HCURSOR hCursor;
Bool fCursorVisible;
int nCX;
int nCY;
/* Privates used by multi-window server */
pthread_t ptWMProc;
pthread_t ptXMsgProc;
@ -553,6 +564,22 @@ typedef struct _winPrivScreenRec
} winPrivScreenRec;
typedef struct {
RootlessWindowPtr pFrame;
HWND hWnd;
int dwWidthBytes;
BITMAPINFOHEADER *pbmihShadow;
HBITMAP hbmpShadow;
HDC hdcShadow;
HDC hdcScreen;
BOOL fResized;
BOOL fRestackingNow;
BOOL fClose;
BOOL fDestroyed;//for debug
char *pfb;
} win32RootlessWindowRec, *win32RootlessWindowPtr;
typedef struct {
pointer value;
XID id;
@ -1529,6 +1556,112 @@ winWindowProc (HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
/*
* winwin32rootless.c
*/
Bool
winWin32RootlessCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen,
int newX, int newY, RegionPtr pShape);
void
winWin32RootlessDestroyFrame (RootlessFrameID wid);
void
winWin32RootlessMoveFrame (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
void
winWin32RootlessResizeFrame (RootlessFrameID wid, ScreenPtr pScreen,
int newX, int newY, unsigned int newW, unsigned int newH,
unsigned int gravity);
void
winWin32RootlessRestackFrame (RootlessFrameID wid, RootlessFrameID nextWid);
void
winWin32RootlessReshapeFrame (RootlessFrameID wid, RegionPtr pShape);
void
winWin32RootlessUnmapFrame (RootlessFrameID wid);
void
winWin32RootlessStartDrawing (RootlessFrameID wid, char **pixelData, int *bytesPerRow);
void
winWin32RootlessStopDrawing (RootlessFrameID wid, Bool flush);
void
winWin32RootlessUpdateRegion (RootlessFrameID wid, RegionPtr pDamage);
void
winWin32RootlessDamageRects (RootlessFrameID wid, int count, const BoxRec *rects,
int shift_x, int shift_y);
void
winWin32RootlessRootlessSwitchWindow (RootlessWindowPtr pFrame, WindowPtr oldWin);
void
winWin32RootlessCopyBytes (unsigned int width, unsigned int height,
const void *src, unsigned int srcRowBytes,
void *dst, unsigned int dstRowBytes);
void
winWin32RootlessFillBytes (unsigned int width, unsigned int height, unsigned int value,
void *dst, unsigned int dstRowBytes);
int
winWin32RootlessCompositePixels (unsigned int width, unsigned int height, unsigned int function,
void *src[2], unsigned int srcRowBytes[2],
void *mask, unsigned int maskRowBytes,
void *dst[2], unsigned int dstRowBytes[2]);
void
winWin32RootlessCopyWindow (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
int dx, int dy);
/*
* winwin32rootlesswindow.c
*/
void
winWin32RootlessReorderWindows (ScreenPtr pScreen);
void
winWin32RootlessMoveXWindow (WindowPtr pWin, int x, int y);
void
winWin32RootlessResizeXWindow (WindowPtr pWin, int w, int h);
void
winWin32RootlessUpdateIcon (Window id);
/*
* winwin32rootlesscursor.c
*/
Bool
winWin32RootlessInitCursor (ScreenPtr pScreen);
/*
* winwin32rootlesswndproc.c
*/
LRESULT CALLBACK
winWin32RootlessWindowProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
/*
* winwindowswm.c
*/
void
winWindowsWMExtensionInit ();
/*
* END DDX and DIX Function Prototypes
*/

View file

@ -76,5 +76,10 @@ winBlockHandler_ProcessMessages:
DispatchMessage (&msg);
}
}
if (pScreenPriv->pScreenInfo->fMultiWindow)
winReorderWindowsMultiWindow ((ScreenPtr)pBlockData);
if (pScreenPriv->pScreenInfo->fRootless)
winWin32RootlessReorderWindows ((ScreenPtr)pBlockData);
}

View file

@ -396,7 +396,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen)
#endif
/* Show the window */
if (pScreenInfo->fMultiWindow)
if (pScreenInfo->fMultiWindow || pScreenInfo->fRootless)
{
pScreenPriv->fRootWindowShown = FALSE;
ShowWindow (*phwnd, SW_HIDE);

View file

@ -182,9 +182,9 @@ winSetEngine (ScreenPtr pScreen)
}
/* ShadowGDI is the only engine that supports Multi Window Mode */
if (pScreenInfo->fMultiWindow)
if (pScreenInfo->fMultiWindow || pScreenInfo->fRootless)
{
ErrorF ("winSetEngine - Multi Window => ShadowGDI\n");
ErrorF ("winSetEngine - Multi Window or Rootless => ShadowGDI\n");
pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
/* Set engine function pointers */

View file

@ -34,6 +34,32 @@
/* $XFree86: xc/programs/Xserver/hw/xwin/winscrinit.c,v 1.28 2003/08/07 23:47:58 alanh Exp $ */
#include "win.h"
#include "safeAlpha.h"
static RootlessFrameProcsRec winWin32RootlessProcs = {
winWin32RootlessCreateFrame,
winWin32RootlessDestroyFrame,
winWin32RootlessMoveFrame,
winWin32RootlessResizeFrame,
winWin32RootlessRestackFrame,
winWin32RootlessReshapeFrame,
winWin32RootlessUnmapFrame,
winWin32RootlessStartDrawing,
winWin32RootlessStopDrawing,
winWin32RootlessUpdateRegion,
#ifndef ROOTLESS_TRACK_DAMAGE
winWin32RootlessDamageRects,
#endif
winWin32RootlessRootlessSwitchWindow,
NULL,//winWin32RootlessCopyBytes,
NULL,//winWin32RootlessFillBytes,
NULL,//winWin32RootlessCompositePixels,
winWin32RootlessCopyWindow
};
/*
@ -389,9 +415,10 @@ winFinishScreenInitFB (int index,
#if !WIN_LAYER_SUPPORT
/* Initialize the shadow framebuffer layer */
if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
|| pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
|| pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)
if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
|| pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
|| pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)
&&(!pScreenInfo->fRootless))
{
#if CYGDEBUG
ErrorF ("winFinishScreenInitFB - Calling shadowInit ()\n");
@ -410,39 +437,22 @@ winFinishScreenInitFB (int index,
/* Handle pseudo-rootless mode */
if (pScreenInfo->fRootless)
{
/* 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; \
}
ErrorF ("winScreenInit - RootlessInit\n");
RootlessInit(pScreen, &winWin32RootlessProcs);
ErrorF ("winScreenInit - RootlessInit - done\n");
rootless_CopyBytes_threshold = 0;
rootless_FillBytes_threshold = 0;
rootless_CompositePixels_threshold = 0;
rootless_CopyWindow_threshold = 1;/* FIXME: How many? Profiling needed? */
/* Save a pointer to each lower-level window procedure */
WRAP(CreateWindow);
WRAP(DestroyWindow);
WRAP(RealizeWindow);
WRAP(UnrealizeWindow);
WRAP(PositionWindow);
WRAP(ChangeWindowAttributes);
#ifdef SHAPE
WRAP(SetShape);
#endif
/* Assign pseudo-rootless window procedures to be top level procedures */
pScreen->CreateWindow = winCreateWindowPRootless;
pScreen->DestroyWindow = winDestroyWindowPRootless;
pScreen->PositionWindow = winPositionWindowPRootless;
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
if (!winWin32RootlessInitCursor (pScreen))
{
return FALSE;
}
winWindowsWMExtensionInit ();
}
/* Handle multi window mode */
else if (pScreenInfo->fMultiWindow)

View file

@ -41,9 +41,7 @@ winWakeupHandler (int nScreen,
unsigned long ulResult,
pointer pReadmask)
{
#if 0
winScreenPriv((ScreenPtr)pWakeupData);
#endif
MSG msg;
/* Process all messages on our queue */
@ -57,7 +55,12 @@ winWakeupHandler (int nScreen,
DispatchMessage (&msg);
}
}
winReorderWindowsMultiWindow ((ScreenPtr)pWakeupData);
if (pScreenPriv->pScreenInfo->fMultiWindow)
winReorderWindowsMultiWindow ((ScreenPtr)pWakeupData);
if (pScreenPriv->pScreenInfo->fRootless)
winWin32RootlessReorderWindows ((ScreenPtr)pWakeupData);
}

907
hw/xwin/winwin32rootless.c Executable file
View file

@ -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
* Earle F. Philhower, III
* Harold L Hunt II
*/
/*
* Look at hw/darwin/quartz/xpr/xprFrame.c and hw/darwin/quartz/cr/crFrame.c
*/
#include "win.h"
#include <winuser.h>
#define _WINDOWSWM_SERVER_
#include "windowswmstr.h"
#include "dixevents.h"
#include "winmultiwindowclass.h"
#include "winprefs.h"
/*
* Constant defines
*/
#define MOUSE_POLLING_INTERVAL 500
#define ULW_COLORKEY 0x00000001
#define ULW_ALPHA 0x00000002
#define ULW_OPAQUE 0x00000004
#define AC_SRC_ALPHA 0x01
#define CYGMULTIWINDOW_DEBUG YES
/*
* Global variables
*/
Bool g_fNoConfigureWindow = FALSE;
/*
* External global variables
*/
extern HICON g_hiconX;
/*
* Internal function to get the DIB format that is compatible with the screen
* Fixme: Share code with winshadgdi.c
*/
static
Bool
winWin32RootlessQueryDIBFormat (win32RootlessWindowPtr pRLWinPriv, BITMAPINFOHEADER *pbmih)
{
HBITMAP hbmp;
#if CYGDEBUG
LPDWORD pdw = NULL;
#endif
/* Create a memory bitmap compatible with the screen */
hbmp = CreateCompatibleBitmap (pRLWinPriv->hdcScreen, 1, 1);
if (hbmp == NULL)
{
ErrorF ("winWin32RootlessQueryDIBFormat - CreateCompatibleBitmap failed\n");
return FALSE;
}
/* Initialize our bitmap info header */
ZeroMemory (pbmih, sizeof (BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD));
pbmih->biSize = sizeof (BITMAPINFOHEADER);
/* Get the biBitCount */
if (!GetDIBits (pRLWinPriv->hdcScreen,
hbmp,
0, 1,
NULL,
(BITMAPINFO*) pbmih,
DIB_RGB_COLORS))
{
ErrorF ("winWin32RootlessQueryDIBFormat - First call to GetDIBits failed\n");
DeleteObject (hbmp);
return FALSE;
}
#if CYGDEBUG
/* Get a pointer to bitfields */
pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
ErrorF ("winWin32RootlessQueryDIBFormat - First call masks: %08x %08x %08x\n",
pdw[0], pdw[1], pdw[2]);
#endif
/* Get optimal color table, or the optimal bitfields */
if (!GetDIBits (pRLWinPriv->hdcScreen,
hbmp,
0, 1,
NULL,
(BITMAPINFO*)pbmih,
DIB_RGB_COLORS))
{
ErrorF ("winWin32RootlessQueryDIBFormat - Second call to GetDIBits "
"failed\n");
DeleteObject (hbmp);
return FALSE;
}
/* Free memory */
DeleteObject (hbmp);
return TRUE;
}
static HRGN
winWin32RootlessCreateRgnFromRegion (RegionPtr pShape)
{
int nRects;
BoxPtr pRects, pEnd;
HRGN hRgn, hRgnRect;
if (pShape == NULL) return NULL;
nRects = REGION_NUM_RECTS(pShape);
pRects = REGION_RECTS(pShape);
hRgn = CreateRectRgn (0, 0, 0, 0);
if (hRgn == NULL)
{
ErrorF ("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) "
"failed: %d\n",
0, 0, 0, 0, (int) GetLastError ());
}
/* Loop through all rectangles in the X region */
for (pEnd = pRects + 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 - Loop CreateRectRgn (%d, %d, %d, %d) "
"failed: %d\n",
pRects->x1,
pRects->y1,
pRects->x2,
pRects->y2,
(int) GetLastError ());
}
/* Merge the Windows region with the accumulated region */
if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR)
{
ErrorF ("winReshape - CombineRgn () failed: %d\n",
(int) GetLastError ());
}
/* Delete the temporary Windows region */
DeleteObject (hRgnRect);
}
return hRgn;
}
static void
InitWin32RootlessEngine (win32RootlessWindowPtr pRLWinPriv)
{
pRLWinPriv->hdcScreen = GetDC (pRLWinPriv->hWnd);
pRLWinPriv->hdcShadow = CreateCompatibleDC (pRLWinPriv->hdcScreen);
pRLWinPriv->hbmpShadow = NULL;
/* Allocate bitmap info header */
pRLWinPriv->pbmihShadow = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
+ 256 * sizeof (RGBQUAD));
if (pRLWinPriv->pbmihShadow == NULL)
{
ErrorF ("winWin32RootlessCreateFrame - malloc () failed\n");
return;
}
/* Query the screen format */
winWin32RootlessQueryDIBFormat (pRLWinPriv,
pRLWinPriv->pbmihShadow);
}
Bool
winWin32RootlessCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen,
int newX, int newY, RegionPtr pShape)
{
#define CLASS_NAME_LENGTH 512
Bool fResult = TRUE;
win32RootlessWindowPtr pRLWinPriv;
WNDCLASS wc;
char pszClass[CLASS_NAME_LENGTH], pszWindowID[12];
HICON hIcon;
char *res_name, *res_class, *res_role;
static int s_iWindowID = 0;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessCreateFrame %d %d - %d %d\n",
newX, newY, pFrame->width, pFrame->height);
#endif
pRLWinPriv = (win32RootlessWindowPtr) malloc (sizeof (win32RootlessWindowRec));
pRLWinPriv->pFrame = pFrame;
pRLWinPriv->pfb = NULL;
pRLWinPriv->hbmpShadow = NULL;
pRLWinPriv->hdcShadow = NULL;
pRLWinPriv->hdcScreen = NULL;
pRLWinPriv->fResized = TRUE;
pRLWinPriv->fClose = FALSE;
pRLWinPriv->fRestackingNow = FALSE;
pRLWinPriv->fDestroyed = FALSE;
// Store the implementation private frame ID
pFrame->wid = (RootlessFrameID) pRLWinPriv;
/* Load default X icon in case it's not ready yet */
if (!g_hiconX)
g_hiconX = (HICON)winOverrideDefaultIcon();
if (!g_hiconX)
g_hiconX = LoadIcon (g_hInstance, MAKEINTRESOURCE(IDI_XWIN));
/* Try and get the icon from WM_HINTS */
hIcon = winXIconToHICON (pFrame->win);
/* Use default X icon if no icon loaded from WM_HINTS */
if (!hIcon)
hIcon = g_hiconX;
/* Set standard class name prefix so we can identify window easily */
strncpy (pszClass, WINDOW_CLASS_X, strlen (WINDOW_CLASS_X));
if (winMultiWindowGetClassHint (pFrame->win, &res_name, &res_class))
{
strncat (pszClass, "-", 1);
strncat (pszClass, res_name, CLASS_NAME_LENGTH - strlen (pszClass));
strncat (pszClass, "-", 1);
strncat (pszClass, res_class, CLASS_NAME_LENGTH - strlen (pszClass));
/* Check if a window class is provided by the WM_WINDOW_ROLE property,
* if not use the WM_CLASS information.
* For further information see:
* http://tronche.com/gui/x/icccm/sec-5.html
*/
if (winMultiWindowGetWindowRole (pFrame->win, &res_role) )
{
strcat (pszClass, "-");
strcat (pszClass, res_role);
free (res_role);
}
free (res_name);
free (res_class);
}
/* Add incrementing window ID to make unique class name */
sprintf (pszWindowID, "-%x", s_iWindowID++);
strcat (pszClass, pszWindowID);
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winCreateWindowsWindow - Creating class: %s\n", pszClass);
#endif
/* Setup our window class */
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = winWin32RootlessWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInstance;
wc.hIcon = hIcon;
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = pszClass;
RegisterClass (&wc);
/* Create the window */
g_fNoConfigureWindow = TRUE;
pRLWinPriv->hWnd = CreateWindowExA (WS_EX_TOOLWINDOW, /* Extended styles */
pszClass, /* Class name */
WINDOW_TITLE_X, /* Window name */
WS_POPUP | WS_CLIPCHILDREN,
newX, /* Horizontal position */
newY, /* Vertical position */
pFrame->width, /* Right edge */
pFrame->height, /* Bottom edge */
(HWND) NULL, /* No parent or owner window */
(HMENU) NULL, /* No menu */
GetModuleHandle (NULL), /* Instance handle */
pRLWinPriv); /* ScreenPrivates */
if (pRLWinPriv->hWnd == NULL)
{
ErrorF ("winWin32RootlessCreateFrame - CreateWindowExA () failed: %d\n",
(int) GetLastError ());
fResult = FALSE;
}
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessCreateFrame - ShowWindow\n");
#endif
//ShowWindow (pRLWinPriv->hWnd, SW_SHOWNOACTIVATE);
g_fNoConfigureWindow = FALSE;
if (pShape != NULL)
{
winWin32RootlessReshapeFrame (pFrame->wid, pShape);
}
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessCreateFrame - (%08x) %08x\n",
(int) pFrame->wid, (int) pRLWinPriv->hWnd);
#if 0
{
WindowPtr pWin2 = NULL;
win32RootlessWindowPtr pRLWinPriv2 = NULL;
/* Check if the Windows window property for our X window pointer is valid */
if ((pWin2 = (WindowPtr)GetProp (pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL)
{
pRLWinPriv2 = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin2, FALSE);
}
ErrorF ("winWin32RootlessCreateFrame2 (%08x) %08x\n",
pRLWinPriv2, pRLWinPriv2->hWnd);
if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd)
{
ErrorF ("Error param missmatch\n");
}
}
#endif
#endif
return fResult;
}
void
winWin32RootlessDestroyFrame (RootlessFrameID wid)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessDestroyFrame (%08x) %08x\n",
(int) pRLWinPriv, (int) pRLWinPriv->hWnd);
#if 0
{
WindowPtr pWin2 = NULL;
win32RootlessWindowPtr pRLWinPriv2 = NULL;
/* Check if the Windows window property for our X window pointer is valid */
if ((pWin2 = (WindowPtr)GetProp (pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL)
{
pRLWinPriv2 = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin2, FALSE);
}
ErrorF ("winWin32RootlessDestroyFrame2 (%08x) %08x\n",
pRLWinPriv2, pRLWinPriv2->hWnd);
if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd)
{
ErrorF ("Error param missmatch\n");
*(int*)0 = 1;//raise exseption
}
}
#endif
#endif
pRLWinPriv->fClose = TRUE;
pRLWinPriv->fDestroyed = TRUE;
/* Destroy the Windows window */
DestroyWindow (pRLWinPriv->hWnd);
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessDestroyFrame - done\n");
#endif
}
void
winWin32RootlessMoveFrame (RootlessFrameID wid, ScreenPtr pScreen, int iNewX, int iNewY)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
RECT rcNew;
DWORD dwExStyle;
DWORD dwStyle;
int iX, iY, iWidth, iHeight;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessMoveFrame (%08x) (%d %d)\n", (int) pRLWinPriv, iNewX, iNewY);
#endif
/* Get the Windows window style and extended style */
dwExStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE);
dwStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE);
/* Get the X and Y location of the X window */
iX = iNewX + GetSystemMetrics (SM_XVIRTUALSCREEN);
iY = iNewY + GetSystemMetrics (SM_YVIRTUALSCREEN);
/* Get the height and width of the X window */
iWidth = pRLWinPriv->pFrame->width;
iHeight = pRLWinPriv->pFrame->height;
/* Store the origin, height, and width in a rectangle structure */
SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight);
/*
* Calculate the required size of the Windows window rectangle,
* given the size of the Windows window client area.
*/
AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle);
g_fNoConfigureWindow = TRUE;
SetWindowPos (pRLWinPriv->hWnd, NULL, rcNew.left, rcNew.top, 0, 0,
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
g_fNoConfigureWindow = FALSE;
}
void
winWin32RootlessResizeFrame (RootlessFrameID wid, ScreenPtr pScreen,
int iNewX, int iNewY,
unsigned int uiNewWidth, unsigned int uiNewHeight,
unsigned int uiGravity)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
RECT rcNew;
RECT rcOld;
DWORD dwExStyle;
DWORD dwStyle;
int iX, iY;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessResizeFrame (%08x) (%d %d)-(%d %d)\n",
(int) pRLWinPriv, iNewX, iNewY, uiNewWidth, uiNewHeight);
#endif
pRLWinPriv->fResized = TRUE;
/* Get the Windows window style and extended style */
dwExStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE);
dwStyle = GetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE);
/* Get the X and Y location of the X window */
iX = iNewX + GetSystemMetrics (SM_XVIRTUALSCREEN);
iY = iNewY + GetSystemMetrics (SM_YVIRTUALSCREEN);
/* Store the origin, height, and width in a rectangle structure */
SetRect (&rcNew, iX, iY, iX + uiNewWidth, iY + uiNewHeight);
/*
* 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 (pRLWinPriv->hWnd, &rcOld);
/* Check if the old rectangle and new rectangle are the same */
if (!EqualRect (&rcNew, &rcOld))
{
g_fNoConfigureWindow = TRUE;
MoveWindow (pRLWinPriv->hWnd,
rcNew.left, rcNew.top,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
TRUE);
g_fNoConfigureWindow = FALSE;
}
}
void
winWin32RootlessRestackFrame (RootlessFrameID wid, RootlessFrameID nextWid)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
win32RootlessWindowPtr pRLNextWinPriv = (win32RootlessWindowPtr) nextWid;
winScreenPriv(pRLWinPriv->pFrame->win->drawable.pScreen);
HWND hWnd;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessRestackFrame (%08x)\n", (int) pRLWinPriv);
#endif
if (pScreenPriv->fRestacking) return;
pRLWinPriv->fRestackingNow = TRUE;
/* Show window */
if(!IsWindowVisible (pRLWinPriv->hWnd))
ShowWindow (pRLWinPriv->hWnd, SW_SHOWNA);
if (pRLNextWinPriv == NULL)
{
//ErrorF ("Win %08x is top\n", pRLWinPriv);
pScreenPriv->widTop = wid;
SetWindowPos (pRLWinPriv->hWnd, HWND_TOP,
0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
}
else
{
//ErrorF ("Win %08x is not top\n", pRLWinPriv);
hWnd = GetNextWindow (pRLWinPriv->hWnd, GW_HWNDPREV);
do
{
if (hWnd == pRLNextWinPriv->hWnd)
{
SetWindowPos (pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
break;
}
hWnd = GetNextWindow (hWnd, GW_HWNDPREV);
}
while (hWnd);
}
pRLWinPriv->fRestackingNow = FALSE;
}
void
winWin32RootlessReshapeFrame (RootlessFrameID wid, RegionPtr pShape)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
HRGN hRgn;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessReshapeFrame (%08x)\n", (int) pRLWinPriv);
#endif
hRgn = winWin32RootlessCreateRgnFromRegion (pShape);
SetWindowRgn (pRLWinPriv->hWnd, hRgn, TRUE);
}
void
winWin32RootlessUnmapFrame (RootlessFrameID wid)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessUnmapFrame (%08x)\n", (int) pRLWinPriv);
#endif
g_fNoConfigureWindow = TRUE;
//ShowWindow (pRLWinPriv->hWnd, SW_MINIMIZE);
ShowWindow (pRLWinPriv->hWnd, SW_HIDE);
g_fNoConfigureWindow = FALSE;
}
/*
* Fixme: Code sharing with winshadgdi.c and other engine support
*/
void
winWin32RootlessStartDrawing (RootlessFrameID wid, char **pixelData, int *bytesPerRow)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
winPrivScreenPtr pScreenPriv = NULL;
winScreenInfo *pScreenInfo = NULL;
ScreenPtr pScreen = NULL;
DIBSECTION dibsection;
Bool fReturn = TRUE;
HDC hdcNew;
HBITMAP hbmpNew;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessStartDrawing (%08x) %08x\n", (int) pRLWinPriv, pRLWinPriv->fDestroyed);
#endif
if (!pRLWinPriv->fDestroyed)
{
pScreen = pRLWinPriv->pFrame->win->drawable.pScreen;
if (pScreen) pScreenPriv = winGetScreenPriv(pScreen);
if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("pScreenPriv %08X\n", (int) pScreenPriv);
ErrorF ("pScreenInfo %08X\n", (int) pScreenInfo);
#endif
if (pRLWinPriv->hdcScreen == NULL)
{
InitWin32RootlessEngine (pRLWinPriv);
}
if (pRLWinPriv->fResized)
{
hdcNew = CreateCompatibleDC (pRLWinPriv->hdcScreen);
/* Describe shadow bitmap to be created */
pRLWinPriv->pbmihShadow->biWidth = pRLWinPriv->pFrame->width;//pRLWinPriv->dwWidth;
pRLWinPriv->pbmihShadow->biHeight = -pRLWinPriv->pFrame->height;//pRLWinPriv->dwHeight;
/* Create a DI shadow bitmap with a bit pointer */
hbmpNew = CreateDIBSection (pRLWinPriv->hdcScreen,
(BITMAPINFO *) pRLWinPriv->pbmihShadow,
DIB_RGB_COLORS,
(VOID**) &pRLWinPriv->pfb,
NULL,
0);
if (hbmpNew == NULL || pRLWinPriv->pfb == NULL)
{
ErrorF ("winWin32RootlessStartDrawing - CreateDIBSection failed\n");
//return FALSE;
}
else
{
#if CYGDEBUG
ErrorF ("winWin32RootlessStartDrawing - Shadow buffer allocated\n");
#endif
}
/* Get information about the bitmap that was allocated */
GetObject (hbmpNew, sizeof (dibsection), &dibsection);
#if CYGDEBUG
/* Print information about bitmap allocated */
ErrorF ("winWin32RootlessStartDrawing - 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 */
SelectObject (hdcNew, hbmpNew);
#if CYGDEBUG
ErrorF ("winWin32RootlessStartDrawing - Attempting a shadow blit\n");
#endif
/* Blit from the old shadow to the new shadow */
fReturn = BitBlt (hdcNew,
0, 0,
pRLWinPriv->pFrame->width, pRLWinPriv->pFrame->height,
pRLWinPriv->hdcShadow,
0, 0,
SRCCOPY);
if (fReturn)
{
#if CYGDEBUG
ErrorF ("winWin32RootlessStartDrawing - Shadow blit success\n");
#endif
}
else
{
ErrorF ("winWin32RootlessStartDrawing - Shadow blit failure\n");
}
/* Look for height weirdness */
if (dibsection.dsBmih.biHeight < 0)
{
/* FIXME: Figure out why biHeight is sometimes negative */
ErrorF ("winWin32RootlessStartDrawing - WEIRDNESS - biHeight "
"still negative: %d\n"
"winAllocateFBShadowGDI - WEIRDNESS - Flipping biHeight sign\n",
(int) dibsection.dsBmih.biHeight);
dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
}
pRLWinPriv->dwWidthBytes = dibsection.dsBm.bmWidthBytes;
#if CYGDEBUG
ErrorF ("winWin32RootlessStartDrawing - bytesPerRow: %d\n",
dibsection.dsBm.bmWidthBytes);
#endif
/* Free the old shadow bitmap */
DeleteObject (pRLWinPriv->hdcShadow);
DeleteObject (pRLWinPriv->hbmpShadow);
pRLWinPriv->hdcShadow = hdcNew;
pRLWinPriv->hbmpShadow = hbmpNew;
pRLWinPriv->fResized = FALSE;
}
}
else
{
ErrorF ("winWin32RootlessStartDrawing - Already window was destoroyed \n");
}
#if CYGDEBUG
ErrorF ("winWin32RootlessStartDrawing - 0x%08x %d\n",
pRLWinPriv->pfb, dibsection.dsBm.bmWidthBytes);
#endif
*pixelData = pRLWinPriv->pfb;
*bytesPerRow = pRLWinPriv->dwWidthBytes;
}
void
winWin32RootlessStopDrawing (RootlessFrameID wid, Bool fFlush)
{
#if 0
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
BLENDFUNCTION bfBlend;
SIZE szWin;
POINT ptSrc;
#if CYGMULTIWINDOW_DEBUG || TRUE
ErrorF ("winWin32RootlessStopDrawing (%08x)\n", pRLWinPriv);
#endif
szWin.cx = pRLWinPriv->dwWidth;
szWin.cy = pRLWinPriv->dwHeight;
ptSrc.x = 0;
ptSrc.y = 0;
bfBlend.BlendOp = AC_SRC_OVER;
bfBlend.BlendFlags = 0;
bfBlend.SourceConstantAlpha = 255;
bfBlend.AlphaFormat = AC_SRC_ALPHA;
if (!UpdateLayeredWindow (pRLWinPriv->hWnd,
NULL, NULL, &szWin,
pRLWinPriv->hdcShadow, &ptSrc,
0, &bfBlend, ULW_ALPHA))
{
ErrorF ("winWin32RootlessStopDrawing - UpdateLayeredWindow failed\n");
}
#endif
}
void
winWin32RootlessUpdateRegion (RootlessFrameID wid, RegionPtr pDamage)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
#if 0
BLENDFUNCTION bfBlend;
SIZE szWin;
POINT ptSrc;
#endif
#if CYGMULTIWINDOW_DEBUG && 0
ErrorF ("winWin32RootlessUpdateRegion (%08x)\n", pRLWinPriv);
#endif
#if 0
szWin.cx = pRLWinPriv->dwWidth;
szWin.cy = pRLWinPriv->dwHeight;
ptSrc.x = 0;
ptSrc.y = 0;
bfBlend.BlendOp = AC_SRC_OVER;
bfBlend.BlendFlags = 0;
bfBlend.SourceConstantAlpha = 255;
bfBlend.AlphaFormat = AC_SRC_ALPHA;
if (!UpdateLayeredWindow (pRLWinPriv->hWnd,
NULL, NULL, &szWin,
pRLWinPriv->hdcShadow, &ptSrc,
0, &bfBlend, ULW_ALPHA))
{
LPVOID lpMsgBuf;
/* Display a fancy error message */
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError (),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL);
ErrorF ("winWin32RootlessUpdateRegion - UpdateLayeredWindow failed: %s\n",
(LPSTR)lpMsgBuf);
LocalFree (lpMsgBuf);
}
#endif
if (!g_fNoConfigureWindow) UpdateWindow (pRLWinPriv->hWnd);
}
void
winWin32RootlessDamageRects (RootlessFrameID wid, int nCount, const BoxRec *pRects,
int shift_x, int shift_y)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
const BoxRec *pEnd;
#if CYGMULTIWINDOW_DEBUG && 0
ErrorF ("winWin32RootlessDamageRects (%08x, %d, %08x, %d, %d)\n",
pRLWinPriv, nCount, pRects, shift_x, shift_y);
#endif
for (pEnd = pRects + nCount; pRects < pEnd; pRects++) {
RECT rcDmg;
rcDmg.left = pRects->x1 + shift_x;
rcDmg.top = pRects->y1 + shift_y;
rcDmg.right = pRects->x2 + shift_x;
rcDmg.bottom = pRects->y2 + shift_y;
InvalidateRect (pRLWinPriv->hWnd, &rcDmg, FALSE);
}
}
void
winWin32RootlessRootlessSwitchWindow (RootlessWindowPtr pFrame, WindowPtr oldWin)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessRootlessSwitchWindow (%08x) %08x\n",
(int) pRLWinPriv, (int) pRLWinPriv->hWnd);
#endif
pRLWinPriv->pFrame = pFrame;
pRLWinPriv->fResized = TRUE;
#if CYGMULTIWINDOW_DEBUG
#if 0
{
WindowPtr pWin2 = NULL;
win32RootlessWindowPtr pRLWinPriv2 = NULL;
/* Check if the Windows window property for our X window pointer is valid */
if ((pWin2 = (WindowPtr)GetProp (pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL)
{
pRLWinPriv2 = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin2, FALSE);
}
ErrorF ("winWin32RootlessSwitchFrame2 (%08x) %08x\n",
pRLWinPriv2, pRLWinPriv2->hWnd);
if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd)
{
ErrorF ("Error param missmatch\n");
}
}
#endif
#endif
}
void
winWin32RootlessCopyBytes (unsigned int width, unsigned int height,
const void *src, unsigned int srcRowBytes,
void *dst, unsigned int dstRowBytes)
{
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessCopyBytes - Not implemented\n");
#endif
}
void
winWin32RootlessFillBytes (unsigned int width, unsigned int height, unsigned int value,
void *dst, unsigned int dstRowBytes)
{
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessFillBytes - Not implemented\n");
#endif
}
int
winWin32RootlessCompositePixels (unsigned int width, unsigned int height, unsigned int function,
void *src[2], unsigned int srcRowBytes[2],
void *mask, unsigned int maskRowBytes,
void *dst[2], unsigned int dstRowBytes[2])
{
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessCompositePixels - Not implemented\n");
#endif
return 0;
}
void
winWin32RootlessCopyWindow (RootlessFrameID wid, int nDstRects, const BoxRec *pDstRects,
int nDx, int nDy)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
const BoxRec *pEnd;
RECT rcDmg;
#if CYGMULTIWINDOW_DEBUG || TRUE
ErrorF ("winWin32RootlessCopyWindow (%08x, %d, %08x, %d, %d)\n",
(int) pRLWinPriv, nDstRects, (int) pDstRects, nDx, nDy);
#endif
for (pEnd = pDstRects + nDstRects; pDstRects < pEnd; pDstRects++)
{
ErrorF ("BitBlt (%d, %d, %d, %d) (%d, %d)\n",
pDstRects->x1, pDstRects->y1,
pDstRects->x2 - pDstRects->x1,
pDstRects->y2 - pDstRects->y1,
pDstRects->x1 + nDx,
pDstRects->y1 + nDy);
if (!BitBlt (pRLWinPriv->hdcShadow,
pDstRects->x1, pDstRects->y1,
pDstRects->x2 - pDstRects->x1,
pDstRects->y2 - pDstRects->y1,
pRLWinPriv->hdcShadow,
pDstRects->x1 + nDx, pDstRects->y1 + nDy,
SRCCOPY))
{
ErrorF ("winWin32RootlessCopyWindow - BitBlt failed.\n");
}
rcDmg.left = pDstRects->x1;
rcDmg.top = pDstRects->y1;
rcDmg.right = pDstRects->x2;
rcDmg.bottom = pDstRects->y2;
InvalidateRect (pRLWinPriv->hWnd, &rcDmg, FALSE);
}
#if CYGMULTIWINDOW_DEBUG || TRUE
ErrorF ("winWin32RootlessCopyWindow - done\n");
#endif
}

172
hw/xwin/winwin32rootlesswindow.c Executable file
View file

@ -0,0 +1,172 @@
/*
*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
* Earle F. Philhower, III
* Harold L Hunt II
*/
#include "win.h"
#include "winprefs.h"
/*
* External global variables
*/
extern HICON g_hiconX;
/*
* winWin32RootlessReorderWindows
*/
void
winWin32RootlessReorderWindows (ScreenPtr pScreen)
{
winScreenPriv(pScreen);
HWND hwnd = NULL;
win32RootlessWindowPtr pRLWin = NULL;
win32RootlessWindowPtr pRLWinSib = NULL;
#if CYGMULTIWINDOW_DEBUG && FALSE
ErrorF ("winWin32RootlessReorderWindows\n");
#endif
pScreenPriv->fRestacking = TRUE;
if (pScreenPriv->fWindowOrderChanged)
{
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessReorderWindows - Need to restack\n");
#endif
hwnd = GetTopWindow (NULL);
while (hwnd)
{
if (GetProp (hwnd, WIN_WINDOW_PROP))
{
pRLWinSib = pRLWin;
pRLWin = (win32RootlessWindowPtr)GetProp (hwnd, WIN_WINDOW_PROP);
if (pRLWinSib)
{
XID *vlist = malloc (sizeof(long) * 2);
if (vlist == NULL)
{
ErrorF ("winWin32RootlessReorderWindows - malloc () "
"failed\n");
return;
}
((long*)vlist)[0] = pRLWinSib->pFrame->win->drawable.id;
((long*)vlist)[1] = Below;
ConfigureWindow (pRLWin->pFrame->win, CWSibling | CWStackMode,
vlist, wClient(pRLWin->pFrame->win));
free (vlist);
}
}
hwnd = GetNextWindow (hwnd, GW_HWNDNEXT);
}
}
pScreenPriv->fRestacking = FALSE;
pScreenPriv->fWindowOrderChanged = FALSE;
}
/*
* winWin32RootlessMoveXWindow
*/
void
winWin32RootlessMoveXWindow (WindowPtr pWin, int x, int y)
{
XID *vlist = malloc(sizeof(long)*2);
(CARD32*)vlist[0] = x;
(CARD32*)vlist[1] = y;
ConfigureWindow (pWin, CWX | CWY, vlist, wClient(pWin));
free(vlist);
}
/*
* winWin32RootlessResizeXWindow
*/
void
winWin32RootlessResizeXWindow (WindowPtr pWin, int w, int h)
{
XID *vlist = malloc(sizeof(long)*2);
(CARD32*)vlist[0] = w;
(CARD32*)vlist[1] = h;
ConfigureWindow (pWin, CWWidth | CWHeight, vlist, wClient(pWin));
free(vlist);
}
/*
* winWin32RootlessUpdateIcon
* Change the Windows window icon
*/
void
winWin32RootlessUpdateIcon (Window id)
{
WindowPtr pWin;
HICON hIcon, hiconOld;
pWin = LookupIDByType (id, RT_WINDOW);
hIcon = (HICON)winOverrideIcon ((unsigned long)pWin);
if (!hIcon)
hIcon = winXIconToHICON (pWin);
if (hIcon)
{
win32RootlessWindowPtr pRLWinPriv
= (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
if (pRLWinPriv->hWnd)
{
hiconOld = (HICON) SetClassLong (pRLWinPriv->hWnd,
GCL_HICON,
(int) hIcon);
/* Delete the icon if its not the default */
if (hiconOld != g_hiconX &&
!winIconIsOverride((unsigned long)hiconOld))
DeleteObject (hiconOld);
}
}
}

908
hw/xwin/winwin32rootlesswndproc.c Executable file
View file

@ -0,0 +1,908 @@
/*
*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
* Earle F. Philhower, III
* Harold L Hunt II
*/
#include "win.h"
#include <winuser.h>
#define _WINDOWSWM_SERVER_
#include "windowswmstr.h"
#include "dixevents.h"
#include "winmultiwindowclass.h"
/*
* Constant defines
*/
#define MOUSE_POLLING_INTERVAL 500
#define CYGMULTIWINDOW_DEBUG YES
/*
* Global variables
*/
extern HICON g_hiconX;
extern Bool g_fNoConfigureWindow;
/*
* Local globals
*/
static UINT_PTR g_uipMousePollingTimerID = 0;
/*
* ConstrainSize - Taken from TWM sources - Respects hints for sizing
*/
#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
static void
ConstrainSize (WinXSizeHints hints, int *widthp, int *heightp)
{
int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
int baseWidth, baseHeight;
int dwidth = *widthp, dheight = *heightp;
if (hints.flags & PMinSize)
{
minWidth = hints.min_width;
minHeight = hints.min_height;
}
else if (hints.flags & PBaseSize)
{
minWidth = hints.base_width;
minHeight = hints.base_height;
}
else
minWidth = minHeight = 1;
if (hints.flags & PBaseSize)
{
baseWidth = hints.base_width;
baseHeight = hints.base_height;
}
else if (hints.flags & PMinSize)
{
baseWidth = hints.min_width;
baseHeight = hints.min_height;
}
else
baseWidth = baseHeight = 0;
if (hints.flags & PMaxSize)
{
maxWidth = hints.max_width;
maxHeight = hints.max_height;
}
else
{
maxWidth = MAXINT;
maxHeight = MAXINT;
}
if (hints.flags & PResizeInc)
{
xinc = hints.width_inc;
yinc = hints.height_inc;
}
else
xinc = yinc = 1;
/*
* First, clamp to min and max values
*/
if (dwidth < minWidth)
dwidth = minWidth;
if (dheight < minHeight)
dheight = minHeight;
if (dwidth > maxWidth)
dwidth = maxWidth;
if (dheight > maxHeight)
dheight = maxHeight;
/*
* Second, fit to base + N * inc
*/
dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
/*
* Third, adjust for aspect ratio
*/
/*
* The math looks like this:
*
* minAspectX dwidth maxAspectX
* ---------- <= ------- <= ----------
* minAspectY dheight maxAspectY
*
* If that is multiplied out, then the width and height are
* invalid in the following situations:
*
* minAspectX * dheight > minAspectY * dwidth
* maxAspectX * dheight < maxAspectY * dwidth
*
*/
if (hints.flags & PAspect)
{
if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth)
{
delta = makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - dwidth, xinc);
if (dwidth + delta <= maxWidth)
dwidth += delta;
else
{
delta = makemult(dheight - dwidth*hints.min_aspect.y/hints.min_aspect.x, yinc);
if (dheight - delta >= minHeight)
dheight -= delta;
}
}
if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth)
{
delta = makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - dheight, yinc);
if (dheight + delta <= maxHeight)
dheight += delta;
else
{
delta = makemult(dwidth - hints.max_aspect.x*dheight/hints.max_aspect.y, xinc);
if (dwidth - delta >= minWidth)
dwidth -= delta;
}
}
}
/* Return computed values */
*widthp = dwidth;
*heightp = dheight;
}
#undef makemult
/*
* ValidateSizing - Ensures size request respects hints
*/
static int
ValidateSizing (HWND hwnd, WindowPtr pWin,
WPARAM wParam, LPARAM lParam)
{
WinXSizeHints sizeHints;
RECT *rect;
int iWidth, iHeight, iTopBorder;
POINT pt;
/* Invalid input checking */
if (pWin==NULL || lParam==0)
{
ErrorF ("Invalid input checking\n");
return FALSE;
}
/* No size hints, no checking */
if (!winMultiWindowGetWMNormalHints (pWin, &sizeHints))
{
ErrorF ("No size hints, no checking\n");
return FALSE;
}
/* Avoid divide-by-zero */
if (sizeHints.flags & PResizeInc)
{
if (sizeHints.width_inc == 0) sizeHints.width_inc = 1;
if (sizeHints.height_inc == 0) sizeHints.height_inc = 1;
}
rect = (RECT*)lParam;
iWidth = rect->right - rect->left;
iHeight = rect->bottom - rect->top;
/* Get title bar height, there must be an easier way?! */
pt.x = pt.y = 0;
ClientToScreen(hwnd, &pt);
iTopBorder = pt.y - rect->top;
/* Now remove size of any borders */
iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME);
iHeight -= GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
/* Constrain the size to legal values */
ConstrainSize (sizeHints, &iWidth, &iHeight);
/* Add back the borders */
iWidth += 2 * GetSystemMetrics(SM_CXSIZEFRAME);
iHeight += GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
/* Adjust size according to where we're dragging from */
switch(wParam) {
case WMSZ_TOP:
case WMSZ_TOPRIGHT:
case WMSZ_BOTTOM:
case WMSZ_BOTTOMRIGHT:
case WMSZ_RIGHT:
rect->right = rect->left + iWidth;
break;
default:
rect->left = rect->right - iWidth;
break;
}
switch(wParam) {
case WMSZ_BOTTOM:
case WMSZ_BOTTOMRIGHT:
case WMSZ_BOTTOMLEFT:
case WMSZ_RIGHT:
case WMSZ_LEFT:
rect->bottom = rect->top + iHeight;
break;
default:
rect->top = rect->bottom - iHeight;
break;
}
return TRUE;
}
/*
* winWin32RootlessWindowProc - Window procedure
*/
LRESULT CALLBACK
winWin32RootlessWindowProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
WindowPtr pWin = NULL;
win32RootlessWindowPtr pRLWinPriv = NULL;
ScreenPtr pScreen = NULL;
winPrivScreenPtr pScreenPriv = NULL;
winScreenInfo *pScreenInfo = NULL;
HWND hwndScreen = NULL;
POINT ptMouse;
static Bool s_fTracking = FALSE;
HDC hdcUpdate;
PAINTSTRUCT ps;
/* Check if the Windows window property for our X window pointer is valid */
if ((pRLWinPriv = (win32RootlessWindowPtr)GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
{
pWin = pRLWinPriv->pFrame->win;
pScreen = pWin->drawable.pScreen;
if (pScreen) pScreenPriv = winGetScreenPriv(pScreen);
if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
if (pScreenPriv) hwndScreen = pScreenPriv->hwndScreen;
#if 1
ErrorF ("hWnd %08X\n", hwnd);
ErrorF ("pScreenPriv %08X\n", pScreenPriv);
ErrorF ("pScreenInfo %08X\n", pScreenInfo);
ErrorF ("hwndScreen %08X\n", hwndScreen);
#endif
ErrorF ("winWin32RootlessWindowProc (%08x) %08x %08x %08x\n",
pRLWinPriv, message, wParam, lParam);
}
/* Branch on message type */
switch (message)
{
case WM_CREATE:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_CREATE\n");
#endif
/* */
SetProp (hwnd,
WIN_WINDOW_PROP,
(HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams);
return 0;
case WM_CLOSE:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_CLOSE %d\n", pRLWinPriv->fClose);
#endif
/* Tell window-manager to close window */
if (pRLWinPriv->fClose)
{
DestroyWindow (hwnd);
}
else
{
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
WindowsWMCloseWindow,
pWin->drawable.id,
0, 0, 0, 0);
}
return 0;
case WM_DESTROY:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_DESTROY\n");
#endif
/* Free the shadow DC; which allows the bitmap to be freed */
DeleteDC (pRLWinPriv->hdcShadow);
pRLWinPriv->hdcShadow = NULL;
/* Free the shadow bitmap */
DeleteObject (pRLWinPriv->hbmpShadow);
pRLWinPriv->hbmpShadow = NULL;
/* Free the screen DC */
ReleaseDC (pRLWinPriv->hWnd, pRLWinPriv->hdcScreen);
pRLWinPriv->hdcScreen = NULL;
pRLWinPriv->fResized = FALSE;
pRLWinPriv->pfb = NULL;
free (pRLWinPriv);
SetProp (hwnd, WIN_WINDOW_PROP, (HANDLE)NULL);
break;
case WM_MOUSEMOVE:
#if CYGMULTIWINDOW_DEBUG && 0
ErrorF ("winWin32RootlessWindowProc - 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);
/* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
/* We can't do anything without privates */
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
/* Has the mouse pointer crossed screens? */
if (pScreen != miPointerCurrentScreen ())
miPointerSetNewScreen (pScreenInfo->dwScreen,
ptMouse.x - pScreenInfo->dwXOffset,
ptMouse.y - 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 ("winWin32RootlessWindowProc - _TrackMouseEvent failed\n");
/* Flag that we are tracking now */
s_fTracking = TRUE;
}
/* Kill the timer used to poll mouse events */
if (g_uipMousePollingTimerID != 0)
{
KillTimer (pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
g_uipMousePollingTimerID = 0;
}
/* Deliver absolute cursor position to X Server */
miPointerAbsoluteCursor (ptMouse.x - pScreenInfo->dwXOffset,
ptMouse.y - pScreenInfo->dwYOffset,
g_c32LastInputEventTime = GetTickCount ());
return 0;
case WM_NCMOUSEMOVE:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_NCMOUSEMOVE\n");
#endif
/*
* 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 (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
/*
* Timer to poll mouse events. This is needed to make
* programs like xeyes follow the mouse properly.
*/
if (g_uipMousePollingTimerID == 0)
g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen,
WIN_POLLING_MOUSE_TIMER_ID,
MOUSE_POLLING_INTERVAL,
NULL);
break;
case WM_MOUSELEAVE:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_MOUSELEAVE\n");
#endif
/* Mouse has left our client area */
/* Flag that we are no longer tracking */
s_fTracking = FALSE;
/*
* Timer to poll mouse events. This is needed to make
* programs like xeyes follow the mouse properly.
*/
if (g_uipMousePollingTimerID == 0)
g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen,
WIN_POLLING_MOUSE_TIMER_ID,
MOUSE_POLLING_INTERVAL,
NULL);
return 0;
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_LBUTTONDBLCLK\n");
#endif
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
SetCapture (hwnd);
return winMouseButtonsHandle (pScreen, ButtonPress, Button1, wParam);
case WM_LBUTTONUP:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_LBUTTONUP\n");
#endif
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
ReleaseCapture ();
return winMouseButtonsHandle (pScreen, ButtonRelease, Button1, wParam);
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_MBUTTONDBLCLK\n");
#endif
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
SetCapture (hwnd);
return winMouseButtonsHandle (pScreen, ButtonPress, Button2, wParam);
case WM_MBUTTONUP:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_MBUTTONUP\n");
#endif
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
ReleaseCapture ();
return winMouseButtonsHandle (pScreen, ButtonRelease, Button2, wParam);
case WM_RBUTTONDBLCLK:
case WM_RBUTTONDOWN:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_RBUTTONDBLCLK\n");
#endif
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
SetCapture (hwnd);
return winMouseButtonsHandle (pScreen, ButtonPress, Button3, wParam);
case WM_RBUTTONUP:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_RBUTTONUP\n");
#endif
if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
break;
ReleaseCapture ();
return winMouseButtonsHandle (pScreen, ButtonRelease, Button3, wParam);
case WM_MOUSEWHEEL:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_MOUSEWHEEL\n");
#endif
/* Pass the message to the root window */
SendMessage (hwndScreen, message, wParam, lParam);
return 0;
case WM_MOUSEACTIVATE:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_MOUSEACTIVATE\n");
#endif
#if 0
/* Check if this window needs to be made active when clicked */
if (pWin->overrideRedirect)
{
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_MOUSEACTIVATE - "
"MA_NOACTIVATE\n");
#endif
/* */
return MA_NOACTIVATE;
}
#endif
break;
case WM_KILLFOCUS:
/* Pop any pressed keys since we are losing keyboard focus */
winKeybdReleaseKeys ();
return 0;
case WM_SYSDEADCHAR:
case WM_DEADCHAR:
/*
* NOTE: We do nothing with WM_*CHAR messages,
* nor does the root window, so we can just toss these messages.
*/
return 0;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_*KEYDOWN\n");
#endif
/*
* Don't pass Alt-F4 key combo to root window,
* let Windows translate to WM_CLOSE and close this top-level window.
*
* NOTE: We purposely don't check the fUseWinKillKey setting because
* it should only apply to the key handling for the root window,
* not for top-level window-manager windows.
*
* ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
* because that is a key combo that no X app should be expecting to
* receive, since it has historically been used to shutdown the X server.
* Passing Ctrl-Alt-Backspace to the root window preserves that
* behavior, assuming that -unixkill has been passed as a parameter.
*/
if (wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000))
break;
/* Pass the message to the root window */
SendMessage (hwndScreen, message, wParam, lParam);
return 0;
case WM_SYSKEYUP:
case WM_KEYUP:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_*KEYUP\n");
#endif
/* Pass the message to the root window */
SendMessage (hwndScreen, message, wParam, lParam);
return 0;
case WM_HOTKEY:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_HOTKEY\n");
#endif
/* Pass the message to the root window */
SendMessage (hwndScreen, message, wParam, lParam);
return 0;
case WM_PAINT:
/* BeginPaint gives us an hdc that clips to the invalidated region */
hdcUpdate = BeginPaint (hwnd, &ps);
/* Try to copy from the shadow buffer */
if (!BitBlt (hdcUpdate,
ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
pRLWinPriv->hdcShadow,
ps.rcPaint.left, ps.rcPaint.top,
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),
(LPTSTR) &lpMsgBuf,
0, NULL);
ErrorF ("winWin32RootlessWindowProc - BitBlt failed: %s\n",
(LPSTR)lpMsgBuf);
LocalFree (lpMsgBuf);
}
/* EndPaint frees the DC */
EndPaint (hwnd, &ps);
break;
case WM_ACTIVATE:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_ACTIVATE\n");
#endif
if (LOWORD(wParam) != WA_INACTIVE)
{
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
WindowsWMActivateWindow,
pWin->drawable.id,
0, 0,
0, 0);
}
return 0;
#if 0
case WM_WINDOWPOSCHANGING:
pWinPos = (LPWINDOWPOS)lParam;
/* Window manager does restacking */
if (!(pWinPos->flags & SWP_NOZORDER))
{
if (pRLWinPriv->fRestackingNow)
{
ErrorF ("Win %08x is now restacking.\n", pRLWinPriv);
return 0;
}
//if (pRLWinPriv->fXTop)
if (pScreenPriv->widTop == pRLWinPriv)
{
#if 0
if ((pWinPos->hwndInsertAfter == HWND_TOP)||
(pWinPos->hwndInsertAfter == HWND_TOPMOST)||
(pWinPos->hwndInsertAfter == HWND_NOTOPMOST))
{
ErrorF ("Win %08x is top and become top/topmost/notopmost.\n", pRLWinPriv);
return 0;
}
for (hInsWnd = GetNextWindow (hwnd, GW_HWNDPREV);
hInsWnd; hInsWnd = GetNextWindow (hInsWnd, GW_HWNDPREV))
{
if (hInsWnd == pWinPos->hwndInsertAfter)
{
ErrorF ("Win %08x is top and go above.\n",
pRLWinPriv);
return 0;
}
hInsWnd = GetNextWindow (hInsWnd, GW_HWNDPREV);
}
ErrorF ("Win %08x is top but forbid.\n", pRLWinPriv);
#endif
return 0;
}
ErrorF ("Win %08x forbid to change z order (%08x).\n",
pRLWinPriv, pWinPos->hwndInsertAfter);
pWinPos->flags |= SWP_NOZORDER;
}
break;
#endif
case WM_MOVE:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_MOVE - %d ms\n", GetTickCount ());
#endif
if (g_fNoConfigureWindow) break;
#if 0
/* Bail if Windows window is not actually moving */
if (pRLWinPriv->dwX == (short) LOWORD(lParam)
&& pRLWinPriv->dwY == (short) HIWORD(lParam))
break;
/* Also bail if we're maximizing, we'll do the whole thing in WM_SIZE */
{
WINDOWPLACEMENT windPlace;
windPlace.length = sizeof (WINDOWPLACEMENT);
/* Get current window placement */
GetWindowPlacement (hwnd, &windPlace);
/* Bail if maximizing */
if (windPlace.showCmd == SW_MAXIMIZE
|| windPlace.showCmd == SW_SHOWMAXIMIZED)
break;
}
#endif
#if CYGMULTIWINDOW_DEBUG
ErrorF ("\t(%d, %d)\n", (short) LOWORD(lParam), (short) HIWORD(lParam));
#endif
#if 0
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
WindowsWMMoveWindow,
pWin->drawable.id,
(LOWORD(lParam) - wBorderWidth (pWin) - GetSystemMetrics (SM_XVIRTUALSCREEN)),
(HIWORD(lParam) - wBorderWidth (pWin) - GetSystemMetrics (SM_YVIRTUALSCREEN)),
0, 0);
#else
winWin32RootlessMoveXWindow (pWin,
(LOWORD(lParam) - wBorderWidth (pWin)
- GetSystemMetrics (SM_XVIRTUALSCREEN)),
(HIWORD(lParam) - wBorderWidth (pWin)
- GetSystemMetrics (SM_YVIRTUALSCREEN)));
#endif
return 0;
case WM_SHOWWINDOW:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_SHOWWINDOW - %d ms\n", GetTickCount ());
#endif
/* Bail out if the window is being hidden */
if (!wParam)
return 0;
/* Tell X to map the window */
MapWindow (pWin, wClient(pWin));
if (pScreenPriv != NULL)
pScreenPriv->fWindowOrderChanged = TRUE;
return 0;
case WM_SIZING:
/* Need to legalize the size according to WM_NORMAL_HINTS */
/* for applications like xterm */
return ValidateSizing (hwnd, pWin, wParam, lParam);
case WM_WINDOWPOSCHANGED:
{
LPWINDOWPOS pwindPos = (LPWINDOWPOS) lParam;
/* Bail if window z order was not changed */
if (pwindPos->flags & SWP_NOZORDER)
break;
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winTopLevelWindowProc - hwndInsertAfter: %p\n",
pwindPos->hwndInsertAfter);
#endif
if (pScreenPriv != NULL)
pScreenPriv->fWindowOrderChanged = TRUE;
}
return 0;
case WM_SIZE:
/* see dix/window.c */
/* FIXME: Maximize/Restore? */
#if CYGMULTIWINDOW_DEBUG
ErrorF ("winWin32RootlessWindowProc - WM_SIZE - %d ms\n", GetTickCount ());
#endif
#if CYGMULTIWINDOW_DEBUG
ErrorF ("\t(%d, %d) %d\n", (short) LOWORD(lParam), (short) HIWORD(lParam), g_fNoConfigureWindow);
#endif
if (g_fNoConfigureWindow) break;
if (pScreenPriv != NULL)
pScreenPriv->fWindowOrderChanged = TRUE;
/* Branch on type of resizing occurring */
switch (wParam)
{
case SIZE_MINIMIZED:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("\tSIZE_MINIMIZED\n");
#endif
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
WindowsWMMinimizeWindow,
pWin->drawable.id,
0, 0,
LOWORD(lParam), HIWORD(lParam));
break;
case SIZE_RESTORED:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("\tSIZE_MINIMIZED\n");
#endif
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
WindowsWMRestoreWindow,
pWin->drawable.id,
0, 0,
LOWORD(lParam), HIWORD(lParam));
break;
case SIZE_MAXIMIZED:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("\tSIZE_MAXIMIZED\n");
#endif
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
WindowsWMMaximizeWindow,
pWin->drawable.id,
0, 0,
LOWORD(lParam), HIWORD(lParam));
break;
}
/* Perform the resize and notify the X client */
#if 0
winWindowsWMSendEvent(WindowsWMControllerNotify,
WindowsWMControllerNotifyMask,
1,
WindowsWMResizeWindow,
pWin->drawable.id,
0, 0,
LOWORD(lParam), HIWORD(lParam));
#else
winWin32RootlessResizeXWindow (pWin,
(short) LOWORD(lParam),
(short) HIWORD(lParam));
#endif
break;
case WM_ACTIVATEAPP:
if (wParam)
{
winWindowsWMSendEvent(WindowsWMActivationNotify,
WindowsWMActivationNotifyMask,
1,
WindowsWMIsActive,
pWin->drawable.id,
0, 0,
0, 0);
}
else
{
winWindowsWMSendEvent(WindowsWMActivationNotify,
WindowsWMActivationNotifyMask,
1,
WindowsWMIsInactive,
pWin->drawable.id,
0, 0,
0, 0);
}
break;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT)
{
SetCursor (pScreenPriv->hCursor);
return TRUE;
}
break;
default:
break;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}

623
hw/xwin/winwindowswm.c Executable file
View file

@ -0,0 +1,623 @@
/* WindowsWM extension is based on AppleWM extension */
/**************************************************************************
Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
Copyright (c) 2003 Torrey T. Lyons. 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, sub license, 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 (including the
next paragraph) 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 NON-INFRINGEMENT.
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
**************************************************************************/
#include "win.h"
#define NEED_REPLIES
#define NEED_EVENTS
#include "misc.h"
#include "dixstruct.h"
#include "extnsionst.h"
#include "colormapst.h"
#include "cursorstr.h"
#include "scrnintstr.h"
#include "servermd.h"
#include "swaprep.h"
#define _WINDOWSWM_SERVER_
#include "windowswmstr.h"
static int WMErrorBase;
static DISPATCH_PROC(ProcWindowsWMDispatch);
static DISPATCH_PROC(SProcWindowsWMDispatch);
static void WindowsWMResetProc(ExtensionEntry* extEntry);
static unsigned char WMReqCode = 0;
static int WMEventBase = 0;
static RESTYPE ClientType, EventType; /* resource types for event masks */
static XID eventResource;
/* Currently selected events */
static unsigned int eventMask = 0;
static int WMFreeClient (pointer data, XID id);
static int WMFreeEvents (pointer data, XID id);
static void SNotifyEvent(xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *to);
typedef struct _WMEvent *WMEventPtr;
typedef struct _WMEvent {
WMEventPtr next;
ClientPtr client;
XID clientResource;
unsigned int mask;
} WMEventRec;
static inline BoxRec
make_box (int x, int y, int w, int h)
{
BoxRec r;
r.x1 = x;
r.y1 = y;
r.x2 = x + w;
r.y2 = y + h;
return r;
}
void
winWindowsWMExtensionInit ()
{
ExtensionEntry* extEntry;
ClientType = CreateNewResourceType(WMFreeClient);
EventType = CreateNewResourceType(WMFreeEvents);
eventResource = FakeClientID(0);
if (ClientType && EventType &&
(extEntry = AddExtension(WINDOWSWMNAME,
WindowsWMNumberEvents,
WindowsWMNumberErrors,
ProcWindowsWMDispatch,
SProcWindowsWMDispatch,
WindowsWMResetProc,
StandardMinorOpcode)))
{
WMReqCode = (unsigned char)extEntry->base;
WMErrorBase = extEntry->errorBase;
WMEventBase = extEntry->eventBase;
EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
}
}
/*ARGSUSED*/
static void
WindowsWMResetProc (ExtensionEntry* extEntry)
{
}
static int
ProcWindowsWMQueryVersion(register ClientPtr client)
{
xWindowsWMQueryVersionReply rep;
register int n;
REQUEST_SIZE_MATCH(xWindowsWMQueryVersionReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = WINDOWS_WM_MAJOR_VERSION;
rep.minorVersion = WINDOWS_WM_MINOR_VERSION;
rep.patchVersion = WINDOWS_WM_PATCH_VERSION;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
}
WriteToClient(client, sizeof(xWindowsWMQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
/* events */
static inline void
updateEventMask (WMEventPtr *pHead)
{
WMEventPtr pCur;
eventMask = 0;
for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
eventMask |= pCur->mask;
}
/*ARGSUSED*/
static int
WMFreeClient (pointer data, XID id)
{
WMEventPtr pEvent;
WMEventPtr *pHead, pCur, pPrev;
pEvent = (WMEventPtr) data;
pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
if (pHead)
{
pPrev = 0;
for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
pPrev = pCur;
if (pCur)
{
if (pPrev)
pPrev->next = pEvent->next;
else
*pHead = pEvent->next;
}
updateEventMask (pHead);
}
xfree ((pointer) pEvent);
return 1;
}
/*ARGSUSED*/
static int
WMFreeEvents (pointer data, XID id)
{
WMEventPtr *pHead, pCur, pNext;
pHead = (WMEventPtr *) data;
for (pCur = *pHead; pCur; pCur = pNext)
{
pNext = pCur->next;
FreeResource (pCur->clientResource, ClientType);
xfree ((pointer) pCur);
}
xfree ((pointer) pHead);
eventMask = 0;
return 1;
}
static int
ProcWindowsWMSelectInput (register ClientPtr client)
{
REQUEST(xWindowsWMSelectInputReq);
WMEventPtr pEvent, pNewEvent, *pHead;
XID clientResource;
REQUEST_SIZE_MATCH (xWindowsWMSelectInputReq);
pHead = (WMEventPtr *)SecurityLookupIDByType(client, eventResource,
EventType, SecurityWriteAccess);
if (stuff->mask != 0)
{
if (pHead)
{
/* check for existing entry. */
for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
{
if (pEvent->client == client)
{
pEvent->mask = stuff->mask;
updateEventMask (pHead);
return Success;
}
}
}
/* build the entry */
pNewEvent = (WMEventPtr) xalloc (sizeof (WMEventRec));
if (!pNewEvent)
return BadAlloc;
pNewEvent->next = 0;
pNewEvent->client = client;
pNewEvent->mask = stuff->mask;
/*
* add a resource that will be deleted when
* the client goes away
*/
clientResource = FakeClientID (client->index);
pNewEvent->clientResource = clientResource;
if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
return BadAlloc;
/*
* create a resource to contain a pointer to the list
* of clients selecting input. This must be indirect as
* the list may be arbitrarily rearranged which cannot be
* done through the resource database.
*/
if (!pHead)
{
pHead = (WMEventPtr *) xalloc (sizeof (WMEventPtr));
if (!pHead ||
!AddResource (eventResource, EventType, (pointer)pHead))
{
FreeResource (clientResource, RT_NONE);
return BadAlloc;
}
*pHead = 0;
}
pNewEvent->next = *pHead;
*pHead = pNewEvent;
updateEventMask (pHead);
}
else if (stuff->mask == 0)
{
/* delete the interest */
if (pHead)
{
pNewEvent = 0;
for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
{
if (pEvent->client == client)
break;
pNewEvent = pEvent;
}
if (pEvent)
{
FreeResource (pEvent->clientResource, ClientType);
if (pNewEvent)
pNewEvent->next = pEvent->next;
else
*pHead = pEvent->next;
xfree (pEvent);
updateEventMask (pHead);
}
}
}
else
{
client->errorValue = stuff->mask;
return BadValue;
}
return Success;
}
/*
* deliver the event
*/
void
winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
Window window, int x, int y, int w, int h)
{
WMEventPtr *pHead, pEvent;
ClientPtr client;
xWindowsWMNotifyEvent se;
ErrorF ("winWindowsWMSendEvent %d %d %d %d, %d %d - %d %d\n",
type, mask, which, arg, x, y, w, h);
pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
if (!pHead)
return;
for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
{
client = pEvent->client;
ErrorF ("winWindowsWMSendEvent - x%08x\n", (int) client);
if ((pEvent->mask & mask) == 0
|| client == serverClient || client->clientGone)
{
continue;
}
ErrorF ("winWindowsWMSendEvent - send\n");
se.type = type + WMEventBase;
se.kind = which;
se.window = window;
se.arg = arg;
se.x = x;
se.y = y;
se.w = w;
se.h = h;
se.sequenceNumber = client->sequence;
se.time = currentTime.milliseconds;
WriteEventsToClient (client, 1, (xEvent *) &se);
}
}
/* Safe to call from any thread. */
unsigned int
WindowsWMSelectedEvents (void)
{
return eventMask;
}
/* general utility functions */
static int
ProcWindowsWMDisableUpdate (register ClientPtr client)
{
REQUEST_SIZE_MATCH(xWindowsWMDisableUpdateReq);
//winDisableUpdate();
return (client->noClientException);
}
static int
ProcWindowsWMReenableUpdate (register ClientPtr client)
{
REQUEST_SIZE_MATCH(xWindowsWMReenableUpdateReq);
//winEnableUpdate();
return (client->noClientException);
}
/* window functions */
static int
ProcWindowsWMSetFrontProcess (register ClientPtr client)
{
REQUEST_SIZE_MATCH(xWindowsWMSetFrontProcessReq);
//QuartzMessageMainThread(kWindowsSetFrontProcess, NULL, 0);
return (client->noClientException);
}
/* frame functions */
static int
ProcWindowsWMFrameGetRect (register ClientPtr client)
{
xWindowsWMFrameGetRectReply rep;
BoxRec ir;
RECT rcNew;
REQUEST(xWindowsWMFrameGetRectReq);
ErrorF ("ProcWindowsWMFrameGetRect %d %d\n",
(sizeof(xWindowsWMFrameGetRectReq) >> 2), (int) client->req_len);
REQUEST_SIZE_MATCH(xWindowsWMFrameGetRectReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
if (stuff->frame_rect != 0)
{
ErrorF ("ProcWindowsWMFrameGetRect - stuff->frame_rect != 0\n");
return BadValue;
}
/* Store the origin, height, and width in a rectangle structure */
SetRect (&rcNew, stuff->ix, stuff->iy,
stuff->ix + stuff->iw, stuff->iy + stuff->ih);
ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
stuff->ix, stuff->iy, stuff->ix + stuff->iw, stuff->iy + stuff->ih);
/*
* Calculate the required size of the Windows window rectangle,
* given the size of the Windows window client area.
*/
AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
rep.x = rcNew.left;
rep.y = rcNew.top;
rep.w = rcNew.right - rcNew.left;
rep.h = rcNew.bottom - rcNew.top;
ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
rep.x, rep.y, rep.w, rep.h);
WriteToClient(client, sizeof(xWindowsWMFrameGetRectReply), (char *)&rep);
return (client->noClientException);
}
static int
ProcWindowsWMFrameDraw (register ClientPtr client)
{
BoxRec ir;
REQUEST(xWindowsWMFrameDrawReq);
WindowPtr pWin;
win32RootlessWindowPtr pRLWinPriv;
RECT rcNew;
WINDOWPLACEMENT wndpl;
REQUEST_SIZE_MATCH (xWindowsWMFrameDrawReq);
ErrorF ("ProcWindowsWMFrameDraw\n");
if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
client, SecurityReadAccess)))
{
return BadValue;
}
ErrorF ("ProcWindowsWMFrameDraw - Window found\n");
ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, TRUE);
if (pRLWinPriv == 0) return BadWindow;
ErrorF ("ProcWindowsWMFrameDraw - HWND 0x%08x 0x%08x 0x%08x",
(int) pRLWinPriv->hWnd, (int) stuff->frame_style,
(int) stuff->frame_style_ex);
ErrorF ("ProcWindowsWMFrameDraw - %d %d %d %d\n",
stuff->ix, stuff->iy, stuff->iw, stuff->ih);
GetWindowPlacement (pRLWinPriv->hWnd, &wndpl);
/* Store the origin, height, and width in a rectangle structure */
SetRect (&rcNew, stuff->ix, stuff->iy,
stuff->ix + stuff->iw, stuff->iy + stuff->ih);
/*
* Calculate the required size of the Windows window rectangle,
* given the size of the Windows window client area.
*/
AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
/* Set the window extended style flags */
if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE, stuff->frame_style_ex))
{
return BadValue;
}
/* Set the window standard style flags */
if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE, stuff->frame_style))
{
return BadValue;
}
/* Flush the window style */
if (!SetWindowPos (pRLWinPriv->hWnd, NULL,
0, 0,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED
/* | SWP_SHOWWINDOW*/ | SWP_NOACTIVATE))
{
return BadValue;
}
ShowWindow (pRLWinPriv->hWnd, wndpl.showCmd);
winWin32RootlessUpdateIcon (pWin->drawable.id);
ErrorF ("ProcWindowsWMFrameDraw - done\n");
return (client->noClientException);
}
static int
ProcWindowsWMFrameSetTitle(
register ClientPtr client
)
{
unsigned int title_length, title_max;
unsigned char *title_bytes;
REQUEST(xWindowsWMFrameSetTitleReq);
WindowPtr pWin;
win32RootlessWindowPtr pRLWinPriv;
ErrorF ("ProcWindowsWMFrameSetTitle\n");
REQUEST_AT_LEAST_SIZE(xWindowsWMFrameSetTitleReq);
if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
client, SecurityReadAccess)))
{
return BadValue;
}
ErrorF ("ProcWindowsWMFrameSetTitle - Window found\n");
title_length = stuff->title_length;
title_max = (stuff->length << 2) - sizeof(xWindowsWMFrameSetTitleReq);
if (title_max < title_length)
return BadValue;
ErrorF ("ProcWindowsWMFrameSetTitle - length is valid\n");
title_bytes = malloc (title_length+1);
strncpy (title_bytes, (unsigned char *) &stuff[1], title_length);
title_bytes[title_length] = '\0';
pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
if (pRLWinPriv == 0)
{
free (title_bytes);
return BadWindow;
}
/* Flush the window style */
SetWindowText (pRLWinPriv->hWnd, title_bytes);
free (title_bytes);
ErrorF ("ProcWindowsWMFrameSetTitle - done\n");
return (client->noClientException);
}
/* dispatch */
static int
ProcWindowsWMDispatch (register ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_WindowsWMQueryVersion:
return ProcWindowsWMQueryVersion(client);
}
if (!LocalClient(client))
return WMErrorBase + WindowsWMClientNotLocal;
switch (stuff->data)
{
case X_WindowsWMSelectInput:
return ProcWindowsWMSelectInput(client);
case X_WindowsWMDisableUpdate:
return ProcWindowsWMDisableUpdate(client);
case X_WindowsWMReenableUpdate:
return ProcWindowsWMReenableUpdate(client);
case X_WindowsWMSetFrontProcess:
return ProcWindowsWMSetFrontProcess(client);
case X_WindowsWMFrameGetRect:
return ProcWindowsWMFrameGetRect(client);
case X_WindowsWMFrameDraw:
return ProcWindowsWMFrameDraw(client);
case X_WindowsWMFrameSetTitle:
return ProcWindowsWMFrameSetTitle(client);
default:
return BadRequest;
}
}
static void
SNotifyEvent (xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *to)
{
to->type = from->type;
to->kind = from->kind;
cpswaps (from->sequenceNumber, to->sequenceNumber);
cpswapl (from->window, to->window);
cpswapl (from->time, to->time);
cpswapl (from->arg, to->arg);
}
static int
SProcWindowsWMQueryVersion (register ClientPtr client)
{
register int n;
REQUEST(xWindowsWMQueryVersionReq);
swaps(&stuff->length, n);
return ProcWindowsWMQueryVersion(client);
}
static int
SProcWindowsWMDispatch (register ClientPtr client)
{
REQUEST(xReq);
/* It is bound to be non-local when there is byte swapping */
if (!LocalClient(client))
return WMErrorBase + WindowsWMClientNotLocal;
/* only local clients are allowed WM access */
switch (stuff->data)
{
case X_WindowsWMQueryVersion:
return SProcWindowsWMQueryVersion(client);
default:
return BadRequest;
}
}

View file

@ -47,4 +47,18 @@
#endif /* __DARWIN__ */
#ifdef __CYGWIN__
# define ROOTLESS_ACCEL YES
# define ROOTLESS_GLOBAL_COORDS TRUE
# define ROOTLESS_PROTECT_ALPHA NO
# define ROOTLESS_REDISPLAY_DELAY 10
# define ROOTLESS_RESIZE_GRAVITY TRUE
# undef ROOTLESS_TRACK_DAMAGE
/*# define ROOTLESSDEBUG*/
# define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
#endif /* __CYGWIN__ */
#endif /* _ROOTLESSCONFIG_H */