/* *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 #define _WINDOWSWM_SERVER_ #include "windowswmstr.h" #include "dixevents.h" #include "propertyst.h" #include "Xatom.h" #include "winmultiwindowclass.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; XID vlist[2]; /* 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 0 winDebug ("hWnd %08X\n", hwnd); winDebug ("pScreenPriv %08X\n", pScreenPriv); winDebug ("pScreenInfo %08X\n", pScreenInfo); winDebug ("hwndScreen %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 { 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 0 /* Check if this window needs to be made active when clicked */ if (pWin->overrideRedirect) { #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE - " "MA_NOACTIVATE\n"); #endif /* */ return MA_NOACTIVATE; } #endif if (!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) { 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) { #if CYGMULTIWINDOW_DEBUG winDebug ("Win %08x is now restacking.\n", (unsigned int)pRLWinPriv); #endif break; } if (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) { winMWExtWMMoveXWindow (pWin, (LOWORD(lParam) - wBorderWidth (pWin) - GetSystemMetrics (SM_XVIRTUALSCREEN)), (HIWORD(lParam) - wBorderWidth (pWin) - GetSystemMetrics (SM_YVIRTUALSCREEN))); } return 0; case WM_SHOWWINDOW: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_SHOWWINDOW - %d ms\n", (unsigned int)GetTickCount ()); #endif 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: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n"); #endif { pWinPos = (LPWINDOWPOS) lParam; #if CYGMULTIWINDOW_DEBUG winDebug("flags: "); if (pWinPos->flags & SWP_DRAWFRAME) winDebug("SWP_DRAWFRAME "); if (pWinPos->flags & SWP_FRAMECHANGED) winDebug("SWP_FRAMECHANGED "); if (pWinPos->flags & SWP_HIDEWINDOW) winDebug("SWP_HIDEWINDOW "); if (pWinPos->flags & SWP_NOACTIVATE) winDebug("SWP_NOACTIVATE "); if (pWinPos->flags & SWP_NOCOPYBITS) winDebug("SWP_NOCOPYBITS "); if (pWinPos->flags & SWP_NOMOVE) winDebug("SWP_NOMOVE "); if (pWinPos->flags & SWP_NOOWNERZORDER) winDebug("SWP_NOOWNERZORDER "); if (pWinPos->flags & SWP_NOSIZE) winDebug("SWP_NOSIZE "); if (pWinPos->flags & SWP_NOREDRAW) winDebug("SWP_NOREDRAW "); if (pWinPos->flags & SWP_NOSENDCHANGING) winDebug("SWP_NOSENDCHANGING "); if (pWinPos->flags & SWP_NOZORDER) winDebug("SWP_NOZORDER "); if (pWinPos->flags & SWP_SHOWWINDOW) winDebug("SWP_SHOWWINDOW "); winDebug("\n"); #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)) { if (pWinPos->hwndInsertAfter == HWND_TOP ||pWinPos->hwndInsertAfter == HWND_TOPMOST ||pWinPos->hwndInsertAfter == HWND_NOTOPMOST) { vlist[0] = Above; ConfigureWindow (pWin, CWStackMode, vlist, wClient(pWin)); } #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 (Above, WIN_WINDOW_PROP) && !IsIconic (hWndAbove) ) /* ignore minimized windows */ break; } /* If this is top of X windows in Windows stack, raise it in X stack. */ if (hWndAbove == NULL) { vlist[0] = Above; ConfigureWindow (pWin, CWStackMode, vlist, wClient(pWin)); } } #endif } if (!(pWinPos->flags & SWP_NOSIZE)) { if (IsIconic(hwnd)){ #if CYGMULTIWINDOW_DEBUG winDebug ("\tIconic -> MINIMIZED\n"); #endif 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 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 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 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 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) { winMWExtWMResizeXWindow (pWin, (short) LOWORD(lParam) - wBorderWidth (pWin)*2, (short) HIWORD(lParam) - wBorderWidth (pWin)*2); } 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) { 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); 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; default: break; } return DefWindowProc (hwnd, message, wParam, lParam); }