1575 lines
40 KiB
C
1575 lines
40 KiB
C
/*
|
|
*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);
|
|
}
|