diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 18:24:03 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 18:24:03 +0000 |
commit | d3670d5856b59bfb45682bbfc29e6f1d0ccbea57 (patch) | |
tree | 7cc2005c59191b981a2056bcffa9d75fdf2e0d0e /xserver/hw/xwin/winwin32rootlesswndproc.c | |
parent | 04f51aaa1f5b0cac419d2891812446c790b9c581 (diff) |
Importing xserver from X.Org 7.2RC2
Diffstat (limited to 'xserver/hw/xwin/winwin32rootlesswndproc.c')
-rw-r--r-- | xserver/hw/xwin/winwin32rootlesswndproc.c | 1324 |
1 files changed, 1324 insertions, 0 deletions
diff --git a/xserver/hw/xwin/winwin32rootlesswndproc.c b/xserver/hw/xwin/winwin32rootlesswndproc.c new file mode 100644 index 000000000..ffa84938f --- /dev/null +++ b/xserver/hw/xwin/winwin32rootlesswndproc.c @@ -0,0 +1,1324 @@ +/* + *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 + */ +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" +#include <winuser.h> +#define _WINDOWSWM_SERVER_ +#include "windowswmstr.h" +#include "dixevents.h" +#include "propertyst.h" +#include <X11/Xatom.h> +#include "winmultiwindowclass.h" +#include "winmsg.h" + + +/* + * Constant defines + */ + +#define MOUSE_POLLING_INTERVAL 500 +#define MOUSE_ACTIVATE_DEFAULT TRUE +#define RAISE_ON_CLICK_DEFAULT FALSE + + +/* + * Global variables + */ + +extern Bool g_fNoConfigureWindow; +extern Bool g_fSoftwareCursor; + + +/* + * Local globals + */ + +static UINT_PTR g_uipMousePollingTimerID = 0; + + +/* + * Local function + */ + +DEFINE_ATOM_HELPER(AtmWindowsWmRaiseOnClick, WINDOWSWM_RAISE_ON_CLICK) +DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate, WINDOWSWM_MOUSE_ACTIVATE) +/* DEFINE_ATOM_HELPER(AtmWindowsWMClientWindow, WINDOWSWM_CLIENT_WINDOW) */ + +/* + * 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; +} + + +/* + * IsRaiseOnClick + */ + +static Bool +IsRaiseOnClick (WindowPtr pWin) +{ + + struct _Window *pwin; + struct _Property *prop; + WindowPtr pRoot = GetCurrentRootWindow (); + + if (!pWin) + { + ErrorF ("IsRaiseOnClick - no prop use default value:%d\n", + RAISE_ON_CLICK_DEFAULT); + return RAISE_ON_CLICK_DEFAULT; + } + + pwin = (struct _Window*) pWin; + + if (pwin->optional) + prop = (struct _Property *) pwin->optional->userProps; + else + prop = NULL; + + while (prop) + { + if (prop->propertyName == AtmWindowsWmRaiseOnClick () + && prop->type == XA_INTEGER + && prop->format == 32) + { + return *(int*)prop->data; + } + else + prop = prop->next; + } + + if (pWin != pRoot) + { + return IsRaiseOnClick (pRoot); + } + else + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("IsRaiseOnClick - no prop use default value:%d\n", + RAISE_ON_CLICK_DEFAULT); +#endif + return RAISE_ON_CLICK_DEFAULT; + } +} + + +/* + * IsMouseActive + */ + +static Bool +IsMouseActive (WindowPtr pWin) +{ + + struct _Window *pwin; + struct _Property *prop; + WindowPtr pRoot = GetCurrentRootWindow (); + + if (!pWin) + { + ErrorF ("IsMouseActive - pWin was NULL use default value:%d\n", + MOUSE_ACTIVATE_DEFAULT); + return MOUSE_ACTIVATE_DEFAULT; + } + + pwin = (struct _Window*) pWin; + + if (pwin->optional) + prop = (struct _Property *) pwin->optional->userProps; + else + prop = NULL; + + while (prop) + { + if (prop->propertyName == AtmWindowsWMMouseActivate () + && prop->type == XA_INTEGER + && prop->format == 32) + { + return *(int*)prop->data; + } + else + prop = prop->next; + } + + if (pWin != pRoot) + { + return IsMouseActive (pRoot); + } + else + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("IsMouseActive - no prop use default value:%d\n", + MOUSE_ACTIVATE_DEFAULT); +#endif + return MOUSE_ACTIVATE_DEFAULT; + } +} + + +/* + * winMWExtWMWindowProc - Window procedure + */ + +LRESULT CALLBACK +winMWExtWMWindowProc (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; + LPWINDOWPOS pWinPos = NULL; + RECT rcClient; + winWMMessageRec wmMsg; + Bool fWMMsgInitialized = FALSE; + + /* 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; + + wmMsg.msg = 0; + wmMsg.hwndWindow = hwnd; + wmMsg.iWindow = (Window)pWin->drawable.id; + + wmMsg.iX = pRLWinPriv->pFrame->x; + wmMsg.iY = pRLWinPriv->pFrame->y; + wmMsg.iWidth = pRLWinPriv->pFrame->width; + wmMsg.iHeight = pRLWinPriv->pFrame->height; + + fWMMsgInitialized = TRUE; +#if CYGDEBUG + winDebugWin32Message("winMWExtWMWindowProc", hwnd, message, wParam, lParam); + + winDebug ("\thWnd %08X\n", hwnd); + winDebug ("\tpScreenPriv %08X\n", pScreenPriv); + winDebug ("\tpScreenInfo %08X\n", pScreenInfo); + winDebug ("\thwndScreen %08X\n", hwndScreen); + winDebug ("winMWExtWMWindowProc (%08x) %08x %08x %08x\n", + pRLWinPriv, message, wParam, lParam); +#endif + } + /* Branch on message type */ + switch (message) + { + case WM_CREATE: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_CREATE\n"); +#endif + /* */ + SetProp (hwnd, + WIN_WINDOW_PROP, + (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams); + return 0; + + case WM_CLOSE: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_CLOSE %d\n", pRLWinPriv->fClose); +#endif + /* Tell window-manager to close window */ + if (pRLWinPriv->fClose) + { + DestroyWindow (hwnd); + } + else + { + if (winIsInternalWMRunning(pScreenInfo)) + { + /* Tell our Window Manager thread to kill the window */ + wmMsg.msg = WM_WM_KILL; + if (fWMMsgInitialized) + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); + } + winWindowsWMSendEvent(WindowsWMControllerNotify, + WindowsWMControllerNotifyMask, + 1, + WindowsWMCloseWindow, + pWin->drawable.id, + 0, 0, 0, 0); + } + return 0; + + case WM_DESTROY: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_DESTROY\n"); +#endif + /* Free the shaodw 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; + + /* Free shadow buffer info header */ + free (pRLWinPriv->pbmihShadow); + pRLWinPriv->pbmihShadow = NULL; + + pRLWinPriv->fResized = FALSE; + pRLWinPriv->pfb = NULL; + free (pRLWinPriv); + RemoveProp (hwnd, WIN_WINDOW_PROP); + break; + + case WM_MOUSEMOVE: +#if CYGMULTIWINDOW_DEBUG && 0 + winDebug ("winMWExtWMWindowProc - 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 ("winMWExtWMWindowProc - _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 && 0 + winDebug ("winMWExtWMWindowProc - 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 + winDebug ("winMWExtWMWindowProc - 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 + winDebug ("winMWExtWMWindowProc - WM_LBUTTONDBLCLK\n"); +#endif + if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) + break; + SetCapture (hwnd); + return winMouseButtonsHandle (pScreen, ButtonPress, Button1, wParam); + + case WM_LBUTTONUP: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - 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 + winDebug ("winMWExtWMWindowProc - WM_MBUTTONDBLCLK\n"); +#endif + if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) + break; + SetCapture (hwnd); + return winMouseButtonsHandle (pScreen, ButtonPress, Button2, wParam); + + case WM_MBUTTONUP: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - 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 + winDebug ("winMWExtWMWindowProc - WM_RBUTTONDBLCLK\n"); +#endif + if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) + break; + SetCapture (hwnd); + return winMouseButtonsHandle (pScreen, ButtonPress, Button3, wParam); + + case WM_RBUTTONUP: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_RBUTTONUP\n"); +#endif + if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) + break; + ReleaseCapture (); + return winMouseButtonsHandle (pScreen, ButtonRelease, Button3, wParam); + + case WM_XBUTTONDBLCLK: + case WM_XBUTTONDOWN: + if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) + break; + SetCapture (hwnd); + return winMouseButtonsHandle (pScreen, ButtonPress, HIWORD(wParam) + 5, wParam); + case WM_XBUTTONUP: + if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) + break; + ReleaseCapture (); + return winMouseButtonsHandle (pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam); + + case WM_MOUSEWHEEL: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_MOUSEWHEEL\n"); +#endif + + /* Pass the message to the root window */ + SendMessage (hwndScreen, message, wParam, lParam); + return 0; + + case WM_MOUSEACTIVATE: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n"); +#endif +#if 1 + /* Check if this window needs to be made active when clicked */ + if (winIsInternalWMRunning(pScreenInfo) && pWin->overrideRedirect) + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE - " + "MA_NOACTIVATE\n"); +#endif + + /* */ + return MA_NOACTIVATE; + } +#endif + if (!winIsInternalWMRunning(pScreenInfo) && !IsMouseActive (pWin)) + return MA_NOACTIVATE; + + 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 + winDebug ("winMWExtWMWindowProc - 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 + winDebug ("winMWExtWMWindowProc - WM_*KEYUP\n"); +#endif + + /* Pass the message to the root window */ + SendMessage (hwndScreen, message, wParam, lParam); + return 0; + + case WM_HOTKEY: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - 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 ("winMWExtWMWindowProc - BitBlt failed: %s\n", + (LPSTR)lpMsgBuf); + LocalFree (lpMsgBuf); + } + + /* EndPaint frees the DC */ + EndPaint (hwnd, &ps); + break; + + case WM_ACTIVATE: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_ACTIVATE\n"); +#endif + if (LOWORD(wParam) != WA_INACTIVE) + { + if (winIsInternalWMRunning(pScreenInfo)) + { +#if 0 + /* Raise the window to the top in Z order */ + wmMsg.msg = WM_WM_RAISE; + if (fWMMsgInitialized) + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); +#endif + /* Tell our Window Manager thread to activate the window */ + wmMsg.msg = WM_WM_ACTIVATE; + if (fWMMsgInitialized) + if (!pWin || !pWin->overrideRedirect) /* for OOo menus */ + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); + } + winWindowsWMSendEvent(WindowsWMControllerNotify, + WindowsWMControllerNotifyMask, + 1, + WindowsWMActivateWindow, + pWin->drawable.id, + 0, 0, + 0, 0); + } + return 0; + +#if 1 + case WM_WINDOWPOSCHANGING: + pWinPos = (LPWINDOWPOS)lParam; + if (!(pWinPos->flags & SWP_NOZORDER)) + { + if (pRLWinPriv->fRestackingNow || pScreenPriv->fRestacking) + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("Win %08x is now restacking.\n", (unsigned int)pRLWinPriv); +#endif + break; + } + + if (winIsInternalWMRunning(pScreenInfo) || IsRaiseOnClick (pWin)) + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("Win %08x has WINDOWSWM_RAISE_ON_CLICK.\n", (unsigned int)pRLWinPriv); +#endif + break; + } + +#if CYGMULTIWINDOW_DEBUG + winDebug ("Win %08x forbid to change z order (%08x).\n", + (unsigned int)pRLWinPriv, (unsigned int)pWinPos->hwndInsertAfter); +#endif + pWinPos->flags |= SWP_NOZORDER; + } + break; +#endif + + case WM_MOVE: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_MOVE - %d ms\n", + (unsigned int)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 + winDebug ("\t(%d, %d)\n", (short) LOWORD(lParam), (short) HIWORD(lParam)); +#endif + if (!pRLWinPriv->fMovingOrSizing) + { + if (winIsInternalWMRunning(pScreenInfo)) + winAdjustXWindow (pWin, hwnd); + + winMWExtWMMoveXWindow (pWin, + (LOWORD(lParam) - wBorderWidth (pWin) + - GetSystemMetrics (SM_XVIRTUALSCREEN)), + (HIWORD(lParam) - wBorderWidth (pWin) + - GetSystemMetrics (SM_YVIRTUALSCREEN))); + } + return 0; + + case WM_SHOWWINDOW: +#if CYGMULTIWINDOW_DEBUG || TRUE + winDebug ("winMWExtWMWindowProc - WM_SHOWWINDOW - %d ms\n", + (unsigned int)GetTickCount ()); +#endif + /* Bail out if the window is being hidden */ + if (!wParam) + return 0; + + if (!pScreenInfo->fInternalWM)//XXXX + return 0; + + winMWExtWMUpdateWindowDecoration (pRLWinPriv, pScreenInfo); + + if (winIsInternalWMRunning(pScreenInfo)) + { +#if CYGMULTIWINDOW_DEBUG || TRUE + winDebug ("\tMapWindow\n"); +#endif + /* Tell X to map the window */ + MapWindow (pWin, wClient(pWin)); + + if (!pRLWinPriv->pFrame->win->overrideRedirect) + /* Bring the Windows window to the foreground */ + SetForegroundWindow (hwnd); + + /* Setup the Window Manager message */ + wmMsg.msg = WM_WM_MAP; + wmMsg.iWidth = pRLWinPriv->pFrame->width; + wmMsg.iHeight = pRLWinPriv->pFrame->height; + + /* Tell our Window Manager thread to map the window */ + if (fWMMsgInitialized) + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); + } + break; + + 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: + { + pWinPos = (LPWINDOWPOS) lParam; +#if CYGMULTIWINDOW_DEBUG + winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n"); + winDebug("\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n", + (pWinPos->flags & SWP_DRAWFRAME)?"SWP_DRAWFRAME ":"", + (pWinPos->flags & SWP_FRAMECHANGED)?"SWP_FRAMECHANGED ":"", + (pWinPos->flags & SWP_HIDEWINDOW)?"SWP_HIDEWINDOW ":"", + (pWinPos->flags & SWP_NOACTIVATE)?"SWP_NOACTIVATE ":"", + (pWinPos->flags & SWP_NOCOPYBITS)?"SWP_NOCOPYBITS ":"", + (pWinPos->flags & SWP_NOMOVE)?"SWP_NOMOVE ":"", + (pWinPos->flags & SWP_NOOWNERZORDER)?"SWP_NOOWNERZORDER ":"", + (pWinPos->flags & SWP_NOSIZE)?"SWP_NOSIZE ":"", + (pWinPos->flags & SWP_NOREDRAW)?"SWP_NOREDRAW ":"", + (pWinPos->flags & SWP_NOSENDCHANGING)?"SWP_NOSENDCHANGING ":"", + (pWinPos->flags & SWP_NOZORDER)?"SWP_NOZORDER ":"", + (pWinPos->flags & SWP_SHOWWINDOW)?"SWP_SHOWWINDOW ":""); + winDebug("\tno_configure: %s\n", (g_fNoConfigureWindow?"Yes":"No")); + winDebug("\textend: (%d, %d, %d, %d)\n", + pWinPos->x, pWinPos->y, pWinPos->cx, pWinPos->cy); + +#endif + if (pWinPos->flags & SWP_HIDEWINDOW) break; + + /* Reorder if window z order was changed */ + if ((pScreenPriv != NULL) + && !(pWinPos->flags & SWP_NOZORDER) + && !(pWinPos->flags & SWP_SHOWWINDOW) + && winIsInternalWMRunning(pScreenInfo)) + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\twindow z order was changed\n"); +#endif + if (pWinPos->hwndInsertAfter == HWND_TOP + ||pWinPos->hwndInsertAfter == HWND_TOPMOST + ||pWinPos->hwndInsertAfter == HWND_NOTOPMOST) + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\traise to top\n"); +#endif + /* Raise the window to the top in Z order */ + wmMsg.msg = WM_WM_RAISE; + if (fWMMsgInitialized) + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); + } +#if 1 + else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) + { + } + else + { + /* Check if this window is top of X windows. */ + HWND hWndAbove = NULL; + DWORD dwCurrentProcessID = GetCurrentProcessId (); + DWORD dwWindowProcessID = 0; + + for (hWndAbove = pWinPos->hwndInsertAfter; + hWndAbove != NULL; + hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV)) + { + /* Ignore other XWin process's window */ + GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID); + + if ((dwWindowProcessID == dwCurrentProcessID) + && GetProp (hWndAbove, WIN_WINDOW_PROP) + && !IsWindowVisible (hWndAbove) + && !IsIconic (hWndAbove) ) /* ignore minimized windows */ + break; + } + /* If this is top of X windows in Windows stack, + raise it in X stack. */ + if (hWndAbove == NULL) + { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\traise to top\n"); +#endif + /* Raise the window to the top in Z order */ + wmMsg.msg = WM_WM_RAISE; + if (fWMMsgInitialized) + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); + } + } +#endif + } + + if (!(pWinPos->flags & SWP_NOSIZE)) { + if (IsIconic(hwnd)){ +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tIconic -> MINIMIZED\n"); +#endif + if (winIsInternalWMRunning(pScreenInfo)) + { + /* Raise the window to the top in Z order */ + wmMsg.msg = WM_WM_LOWER; + if (fWMMsgInitialized) + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); + } + winWindowsWMSendEvent(WindowsWMControllerNotify, + WindowsWMControllerNotifyMask, + 1, + WindowsWMMinimizeWindow, + pWin->drawable.id, + 0, 0, 0, 0); + } else if (IsZoomed(hwnd)){ +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tZoomed -> MAXIMIZED\n"); +#endif + winWindowsWMSendEvent(WindowsWMControllerNotify, + WindowsWMControllerNotifyMask, + 1, + WindowsWMMaximizeWindow, + pWin->drawable.id, + 0, 0, 0, 0); + } else { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tnone -> RESTORED\n"); +#endif + winWindowsWMSendEvent(WindowsWMControllerNotify, + WindowsWMControllerNotifyMask, + 1, + WindowsWMRestoreWindow, + pWin->drawable.id, + 0, 0, 0, 0); + } + } + if (!g_fNoConfigureWindow ) { + + if (!pRLWinPriv->fMovingOrSizing + /*&& (pWinPos->flags & SWP_SHOWWINDOW)*/) { + GetClientRect (hwnd, &rcClient); + MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2); + + if (!(pWinPos->flags & SWP_NOMOVE) + &&!(pWinPos->flags & SWP_NOSIZE)) { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tmove & resize\n"); +#endif + if (winIsInternalWMRunning(pScreenInfo)) + winAdjustXWindow (pWin, hwnd); + + winMWExtWMMoveResizeXWindow (pWin, + rcClient.left - wBorderWidth (pWin) + - GetSystemMetrics (SM_XVIRTUALSCREEN), + rcClient.top - wBorderWidth (pWin) + - GetSystemMetrics (SM_YVIRTUALSCREEN), + rcClient.right - rcClient.left + - wBorderWidth (pWin)*2, + rcClient.bottom - rcClient.top + - wBorderWidth (pWin)*2); + } else if (!(pWinPos->flags & SWP_NOMOVE)) { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tmove\n"); +#endif + if (winIsInternalWMRunning(pScreenInfo)) + winAdjustXWindow (pWin, hwnd); + + winMWExtWMMoveResizeXWindow (pWin, + rcClient.left - wBorderWidth (pWin) + - GetSystemMetrics (SM_XVIRTUALSCREEN), + rcClient.top - wBorderWidth (pWin) + - GetSystemMetrics (SM_YVIRTUALSCREEN), + rcClient.right - rcClient.left + - wBorderWidth (pWin)*2, + rcClient.bottom - rcClient.top + - wBorderWidth (pWin)*2); + } else if (!(pWinPos->flags & SWP_NOMOVE)) { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tmove\n"); +#endif + if (winIsInternalWMRunning(pScreenInfo)) + winAdjustXWindow (pWin, hwnd); + + winMWExtWMMoveXWindow (pWin, + rcClient.left - wBorderWidth (pWin) + - GetSystemMetrics (SM_XVIRTUALSCREEN), + rcClient.top - wBorderWidth (pWin) + - GetSystemMetrics (SM_YVIRTUALSCREEN)); + } else if (!(pWinPos->flags & SWP_NOSIZE)) { +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tresize\n"); +#endif + if (winIsInternalWMRunning(pScreenInfo)) + winAdjustXWindow (pWin, hwnd); + + winMWExtWMResizeXWindow (pWin, + rcClient.right - rcClient.left + - wBorderWidth (pWin)*2, + rcClient.bottom - rcClient.top + - wBorderWidth (pWin)*2); + } + } + } + } +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED - done.\n"); +#endif + return 0; + + case WM_SIZE: + /* see dix/window.c */ + /* FIXME: Maximize/Restore? */ +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_SIZE - %d ms\n", + (unsigned int)GetTickCount ()); +#endif +#if CYGMULTIWINDOW_DEBUG + winDebug ("\t(%d, %d) %d\n", (short) LOWORD(lParam), (short) HIWORD(lParam), g_fNoConfigureWindow); +#endif + if (g_fNoConfigureWindow) break; + + /* Branch on type of resizing occurring */ + switch (wParam) + { + case SIZE_MINIMIZED: +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tSIZE_MINIMIZED\n"); +#endif + if (winIsInternalWMRunning(pScreenInfo)) + { + /* Raise the window to the top in Z order */ + wmMsg.msg = WM_WM_LOWER; + if (fWMMsgInitialized) + winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); + } + winWindowsWMSendEvent(WindowsWMControllerNotify, + WindowsWMControllerNotifyMask, + 1, + WindowsWMMinimizeWindow, + pWin->drawable.id, + 0, 0, + LOWORD(lParam), HIWORD(lParam)); + break; + + case SIZE_RESTORED: +#if CYGMULTIWINDOW_DEBUG + winDebug ("\tSIZE_RESTORED\n"); +#endif + winWindowsWMSendEvent(WindowsWMControllerNotify, + WindowsWMControllerNotifyMask, + 1, + WindowsWMRestoreWindow, + pWin->drawable.id, + 0, 0, + LOWORD(lParam), HIWORD(lParam)); + break; + + case SIZE_MAXIMIZED: +#if CYGMULTIWINDOW_DEBUG + winDebug ("\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 (!pRLWinPriv->fMovingOrSizing) + { + if (winIsInternalWMRunning(pScreenInfo)) + winAdjustXWindow (pWin, hwnd); + + winMWExtWMResizeXWindow (pWin, + (short) LOWORD(lParam) + - wBorderWidth (pWin)*2, + (short) HIWORD(lParam) + - wBorderWidth (pWin)*2); + } + break; + + case WM_ACTIVATEAPP: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_ACTIVATEAPP - %d ms\n", + (unsigned int)GetTickCount ()); +#endif + if (wParam) + { + if (winIsInternalWMRunning(pScreenInfo)) + { + } + else + { + } + 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) + { + if (!g_fSoftwareCursor) SetCursor (pScreenPriv->cursor.handle); + return TRUE; + } + break; + + case WM_ENTERSIZEMOVE: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_ENTERSIZEMOVE - %d ms\n", + (unsigned int)GetTickCount ()); +#endif + pRLWinPriv->fMovingOrSizing = TRUE; + break; + + case WM_EXITSIZEMOVE: +#if CYGMULTIWINDOW_DEBUG + winDebug ("winMWExtWMWindowProc - WM_EXITSIZEMOVE - %d ms\n", + (unsigned int)GetTickCount ()); +#endif + pRLWinPriv->fMovingOrSizing = FALSE; + + GetClientRect (hwnd, &rcClient); + + MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2); + + if (winIsInternalWMRunning(pScreenInfo)) + winAdjustXWindow (pWin, hwnd); + + winMWExtWMMoveResizeXWindow (pWin, + rcClient.left - wBorderWidth (pWin) + - GetSystemMetrics (SM_XVIRTUALSCREEN), + rcClient.top - wBorderWidth (pWin) + - GetSystemMetrics (SM_YVIRTUALSCREEN), + rcClient.right - rcClient.left + - wBorderWidth (pWin)*2, + rcClient.bottom - rcClient.top + - wBorderWidth (pWin)*2); + break; + + case WM_MANAGE: + ErrorF ("winMWExtWMWindowProc - WM_MANAGE\n"); + break; + + case WM_UNMANAGE: + ErrorF ("winMWExtWMWindowProc - WM_UNMANAGE\n"); + break; + + default: + break; + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} |