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 != miPointerGetScreen(inputInfo.pointer)) miPointerSetScreen(inputInfo.pointer, 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 (!TrackMouseEvent(&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 */ winEnqueueMotion(ptMouse.x - pScreenInfo->dwXOffset, ptMouse.y - pScreenInfo->dwYOffset); 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_ERASEBKGND: #if CYGDEBUG winDebug("winMWExtWMWindowProc - WM_ERASEBKGND\n"); #endif /* * Pretend that we did erase the background but we don't care, * since we repaint the entire region anyhow * This avoids some flickering when resizing. */ return TRUE; 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); }
LRESULT CALLBACK winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static winPrivScreenPtr s_pScreenPriv = NULL; static winScreenInfo *s_pScreenInfo = NULL; static ScreenPtr s_pScreen = NULL; static HWND s_hwndLastPrivates = NULL; static HINSTANCE s_hInstance; static Bool s_fTracking = FALSE; static unsigned long s_ulServerGeneration = 0; static UINT s_uTaskbarRestart = 0; int iScanCode; int i; #if CYGDEBUG winDebugWin32Message("winWindowProc", hwnd, message, wParam, lParam); #endif /* Watch for server regeneration */ if (g_ulServerGeneration != s_ulServerGeneration) { /* Store new server generation */ s_ulServerGeneration = g_ulServerGeneration; } /* Only retrieve new privates pointers if window handle is null or changed */ if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates) && (s_pScreenPriv = GetProp(hwnd, WIN_SCR_PROP)) != NULL) { #if CYGDEBUG winDebug("winWindowProc - Setting privates handle\n"); #endif s_pScreenInfo = s_pScreenPriv->pScreenInfo; s_pScreen = s_pScreenInfo->pScreen; s_hwndLastPrivates = hwnd; } else if (s_pScreenPriv == NULL) { /* For safety, handle case that should never happen */ s_pScreenInfo = NULL; s_pScreen = NULL; s_hwndLastPrivates = NULL; } /* Branch on message type */ switch (message) { case WM_TRAYICON: return winHandleIconMessage(hwnd, message, wParam, lParam, s_pScreenPriv); case WM_CREATE: #if CYGDEBUG winDebug("winWindowProc - WM_CREATE\n"); #endif /* * Add a property to our display window that references * this screens' privates. * * This allows the window procedure to refer to the * appropriate window DC and shadow DC for the window that * it is processing. We use this to repaint exposed * areas of our display window. */ s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams; s_hInstance = ((LPCREATESTRUCT) lParam)->hInstance; s_pScreenInfo = s_pScreenPriv->pScreenInfo; s_pScreen = s_pScreenInfo->pScreen; s_hwndLastPrivates = hwnd; s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); SetProp(hwnd, WIN_SCR_PROP, s_pScreenPriv); /* Setup tray icon */ if (!s_pScreenInfo->fNoTrayIcon) { /* * NOTE: The WM_CREATE message is processed before CreateWindowEx * returns, so s_pScreenPriv->hwndScreen is invalid at this point. * We go ahead and copy our hwnd parameter over top of the screen * privates hwndScreen so that we have a valid value for * that member. Otherwise, the tray icon will disappear * the first time you move the mouse over top of it. */ s_pScreenPriv->hwndScreen = hwnd; winInitNotifyIcon(s_pScreenPriv); } return 0; case WM_DISPLAYCHANGE: /* WM_DISPLAYCHANGE seems to be sent when the monitor layout or any monitor's resolution or depth changes, but it's lParam and wParam always indicate the resolution and bpp for the primary monitor (so ignore that as we could be on any monitor...) */ /* We cannot handle a display mode change during initialization */ if (s_pScreenInfo == NULL) FatalError("winWindowProc - WM_DISPLAYCHANGE - The display " "mode changed while we were intializing. This is " "very bad and unexpected. Exiting.\n"); /* * We do not care about display changes with * fullscreen DirectDraw engines, because those engines set * their own mode when they become active. */ if (s_pScreenInfo->fFullScreen && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL #ifdef XWIN_PRIMARYFB || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD #endif )) { break; } ErrorF("winWindowProc - WM_DISPLAYCHANGE - new width: %d " "new height: %d new bpp: %d\n", LOWORD(lParam), HIWORD(lParam), wParam); /* 0 bpp has no defined meaning, ignore this message */ if (wParam == 0) break; /* * Check for a disruptive change in depth. * We can only display a message for a disruptive depth change, * we cannot do anything to correct the situation. */ /* XXX: maybe we need to check if GetSystemMetrics(SM_SAMEDISPLAYFORMAT) has changed as well... */ if (s_pScreenInfo->dwBPP != GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL)) { if ((s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL #ifdef XWIN_PRIMARYFB || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD #endif )) { /* Cannot display the visual until the depth is restored */ ErrorF("winWindowProc - Disruptive change in depth\n"); /* Display depth change dialog */ winDisplayDepthChangeDialog(s_pScreenPriv); /* Flag that we have an invalid screen depth */ s_pScreenPriv->fBadDepth = TRUE; /* Minimize the display window */ ShowWindow(hwnd, SW_MINIMIZE); } else { /* For GDI, performance may suffer until original depth is restored */ ErrorF ("winWindowProc - Performance may be non-optimal after change in depth\n"); } } else { /* Flag that we have a valid screen depth */ s_pScreenPriv->fBadDepth = FALSE; } /* If we could cheaply check if this WM_DISPLAYCHANGE change affects the monitor(s) which this X screen is displayed on then we should do so here. For the moment, assume it does. (this is probably usually the case so that might be an overoptimization) */ { /* In rootless modes which are monitor or virtual desktop size use RandR to resize the X screen */ if ((!s_pScreenInfo->fUserGaveHeightAndWidth) && (s_pScreenInfo->iResizeMode == resizeWithRandr) && (FALSE #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo-> fMWExtWM #endif || s_pScreenInfo-> fRootless #ifdef XWIN_MULTIWINDOW || s_pScreenInfo-> fMultiWindow #endif )) { DWORD dwWidth, dwHeight; if (s_pScreenInfo->fMultipleMonitors) { /* resize to new virtual desktop size */ dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); } else { /* resize to new size of specified monitor */ struct GetMonitorInfoData data; if (QueryMonitor(s_pScreenInfo->iMonitor, &data)) { if (data.bMonitorSpecifiedExists == TRUE) { dwWidth = data.monitorWidth; dwHeight = data.monitorHeight; /* XXX: monitor may have changed position, so we might need to update xinerama data */ } else { ErrorF("Monitor number %d no longer exists!\n", s_pScreenInfo->iMonitor); } } } /* XXX: probably a small bug here: we don't compute the work area and allow for task bar XXX: generally, we don't allow for the task bar being moved after the server is started */ /* Set screen size to match new size, if it is different to current */ if ((s_pScreenInfo->dwWidth != dwWidth) || (s_pScreenInfo->dwHeight != dwHeight)) { winDoRandRScreenSetSize(s_pScreen, dwWidth, dwHeight, (dwWidth * 25.4) / monitorResolution, (dwHeight * 25.4) / monitorResolution); } } else { /* * We can simply recreate the same-sized primary surface when * the display dimensions change. */ /* * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface * and CreatePrimarySurface function pointers to point * to the no operation function, NoopDDA. This allows us * to blindly call these functions, even if they are not * relevant to the current engine (e.g., Shadow GDI). */ winDebug ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n"); /* Release the old primary surface */ (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen); /* Create the new primary surface */ (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen); } } break; case WM_SIZE: { SCROLLINFO si; RECT rcWindow; int iWidth, iHeight; #if CYGDEBUG winDebug("winWindowProc - WM_SIZE\n"); #endif /* Break if we do not allow resizing */ if ((s_pScreenInfo->iResizeMode == notAllowed) || !s_pScreenInfo->fDecoration #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif || s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOW || s_pScreenInfo->fMultiWindow #endif || s_pScreenInfo->fFullScreen) break; /* No need to resize if we get minimized */ if (wParam == SIZE_MINIMIZED) return 0; ErrorF("winWindowProc - WM_SIZE - new client area w: %d h: %d\n", LOWORD(lParam), HIWORD(lParam)); if (s_pScreenInfo->iResizeMode == resizeWithRandr) { /* Actual resizing is done on WM_EXITSIZEMOVE */ return 0; } /* Otherwise iResizeMode == resizeWithScrollbars */ /* * Get the size of the whole window, including client area, * scrollbars, and non-client area decorations (caption, borders). * We do this because we need to check if the client area * without scrollbars is large enough to display the whole visual. * The new client area size passed by lParam already subtracts * the size of the scrollbars if they are currently displayed. * So checking is LOWORD(lParam) == visual_width and * HIWORD(lParam) == visual_height will never tell us to hide * the scrollbars because the client area would always be too small. * GetClientRect returns the same sizes given by lParam, so we * cannot use GetClientRect either. */ GetWindowRect(hwnd, &rcWindow); iWidth = rcWindow.right - rcWindow.left; iHeight = rcWindow.bottom - rcWindow.top; /* Subtract the frame size from the window size. */ iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME); iHeight -= (2 * GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION)); /* * Update scrollbar page sizes. * NOTE: If page size == range, then the scrollbar is * automatically hidden. */ /* Is the naked client area large enough to show the whole visual? */ if (iWidth < s_pScreenInfo->dwWidth || iHeight < s_pScreenInfo->dwHeight) { /* Client area too small to display visual, use scrollbars */ iWidth -= GetSystemMetrics(SM_CXVSCROLL); iHeight -= GetSystemMetrics(SM_CYHSCROLL); } /* Set the horizontal scrollbar page size */ si.cbSize = sizeof(si); si.fMask = SIF_PAGE | SIF_RANGE; si.nMin = 0; si.nMax = s_pScreenInfo->dwWidth - 1; si.nPage = iWidth; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); /* Set the vertical scrollbar page size */ si.cbSize = sizeof(si); si.fMask = SIF_PAGE | SIF_RANGE; si.nMin = 0; si.nMax = s_pScreenInfo->dwHeight - 1; si.nPage = iHeight; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); /* * NOTE: Scrollbars may have moved if they were at the * far right/bottom, so we query their current position. */ /* Get the horizontal scrollbar position and set the offset */ si.cbSize = sizeof(si); si.fMask = SIF_POS; GetScrollInfo(hwnd, SB_HORZ, &si); s_pScreenInfo->dwXOffset = -si.nPos; /* Get the vertical scrollbar position and set the offset */ si.cbSize = sizeof(si); si.fMask = SIF_POS; GetScrollInfo(hwnd, SB_VERT, &si); s_pScreenInfo->dwYOffset = -si.nPos; } return 0; case WM_SYSCOMMAND: if (s_pScreenInfo->iResizeMode == resizeWithRandr && ((wParam & 0xfff0) == SC_MAXIMIZE || (wParam & 0xfff0) == SC_RESTORE)) PostMessage(hwnd, WM_EXITSIZEMOVE, 0, 0); break; case WM_ENTERSIZEMOVE: ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n"); break; case WM_EXITSIZEMOVE: ErrorF("winWindowProc - WM_EXITSIZEMOVE\n"); if (s_pScreenInfo->iResizeMode == resizeWithRandr) { /* Set screen size to match new client area, if it is different to current */ RECT rcClient; DWORD dwWidth, dwHeight; GetClientRect(hwnd, &rcClient); dwWidth = rcClient.right - rcClient.left; dwHeight = rcClient.bottom - rcClient.top; if ((s_pScreenInfo->dwWidth != dwWidth) || (s_pScreenInfo->dwHeight != dwHeight)) { /* mm = dots * (25.4 mm / inch) / (dots / inch) */ winDoRandRScreenSetSize(s_pScreen, dwWidth, dwHeight, (dwWidth * 25.4) / monitorResolution, (dwHeight * 25.4) / monitorResolution); } } break; case WM_VSCROLL: { SCROLLINFO si; int iVertPos; #if CYGDEBUG winDebug("winWindowProc - WM_VSCROLL\n"); #endif /* Get vertical scroll bar info */ si.cbSize = sizeof(si); si.fMask = SIF_ALL; GetScrollInfo(hwnd, SB_VERT, &si); /* Save the vertical position for comparison later */ iVertPos = si.nPos; /* * Don't forget: * moving the scrollbar to the DOWN, scroll the content UP */ switch (LOWORD(wParam)) { case SB_TOP: si.nPos = si.nMin; break; case SB_BOTTOM: si.nPos = si.nMax - si.nPage + 1; break; case SB_LINEUP: si.nPos -= 1; break; case SB_LINEDOWN: si.nPos += 1; break; case SB_PAGEUP: si.nPos -= si.nPage; break; case SB_PAGEDOWN: si.nPos += si.nPage; break; case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; default: break; } /* * We retrieve the position after setting it, * because Windows may adjust it. */ si.fMask = SIF_POS; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); GetScrollInfo(hwnd, SB_VERT, &si); /* Scroll the window if the position has changed */ if (si.nPos != iVertPos) { /* Save the new offset for bit block transfers, etc. */ s_pScreenInfo->dwYOffset = -si.nPos; /* Change displayed region in the window */ ScrollWindowEx(hwnd, 0, iVertPos - si.nPos, NULL, NULL, NULL, NULL, SW_INVALIDATE); /* Redraw the window contents */ UpdateWindow(hwnd); } } return 0; case WM_HSCROLL: { SCROLLINFO si; int iHorzPos; #if CYGDEBUG winDebug("winWindowProc - WM_HSCROLL\n"); #endif /* Get horizontal scroll bar info */ si.cbSize = sizeof(si); si.fMask = SIF_ALL; GetScrollInfo(hwnd, SB_HORZ, &si); /* Save the horizontal position for comparison later */ iHorzPos = si.nPos; /* * Don't forget: * moving the scrollbar to the RIGHT, scroll the content LEFT */ switch (LOWORD(wParam)) { case SB_LEFT: si.nPos = si.nMin; break; case SB_RIGHT: si.nPos = si.nMax - si.nPage + 1; break; case SB_LINELEFT: si.nPos -= 1; break; case SB_LINERIGHT: si.nPos += 1; break; case SB_PAGELEFT: si.nPos -= si.nPage; break; case SB_PAGERIGHT: si.nPos += si.nPage; break; case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; default: break; } /* * We retrieve the position after setting it, * because Windows may adjust it. */ si.fMask = SIF_POS; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); GetScrollInfo(hwnd, SB_HORZ, &si); /* Scroll the window if the position has changed */ if (si.nPos != iHorzPos) { /* Save the new offset for bit block transfers, etc. */ s_pScreenInfo->dwXOffset = -si.nPos; /* Change displayed region in the window */ ScrollWindowEx(hwnd, iHorzPos - si.nPos, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE); /* Redraw the window contents */ UpdateWindow(hwnd); } } return 0; case WM_GETMINMAXINFO: { MINMAXINFO *pMinMaxInfo = (MINMAXINFO *) lParam; int iCaptionHeight; int iBorderHeight, iBorderWidth; #if CYGDEBUG winDebug("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %08x\n", s_pScreenInfo); #endif /* Can't do anything without screen info */ if (s_pScreenInfo == NULL || (s_pScreenInfo->iResizeMode != resizeWithScrollbars) || s_pScreenInfo->fFullScreen || !s_pScreenInfo->fDecoration #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif || s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOW || s_pScreenInfo->fMultiWindow #endif ) break; /* * Here we can override the maximum tracking size, which * is the largest size that can be assigned to our window * via the sizing border. */ /* * FIXME: Do we only need to do this once, since our visual size * does not change? Does Windows store this value statically * once we have set it once? */ /* Get the border and caption sizes */ iCaptionHeight = GetSystemMetrics(SM_CYCAPTION); iBorderWidth = 2 * GetSystemMetrics(SM_CXSIZEFRAME); iBorderHeight = 2 * GetSystemMetrics(SM_CYSIZEFRAME); /* Allow the full visual to be displayed */ pMinMaxInfo->ptMaxTrackSize.x = s_pScreenInfo->dwWidth + iBorderWidth; pMinMaxInfo->ptMaxTrackSize.y = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight; } return 0; case WM_ERASEBKGND: #if CYGDEBUG winDebug("winWindowProc - WM_ERASEBKGND\n"); #endif /* * Pretend that we did erase the background but we don't care, * the application uses the full window estate. This avoids some * flickering when resizing. */ return TRUE; case WM_PAINT: #if CYGDEBUG winDebug("winWindowProc - WM_PAINT\n"); #endif /* Only paint if we have privates and the server is enabled */ if (s_pScreenPriv == NULL || !s_pScreenPriv->fEnabled || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive) || s_pScreenPriv->fBadDepth) { /* We don't want to paint */ break; } /* Break out here if we don't have a valid paint routine */ if (s_pScreenPriv->pwinBltExposedRegions == NULL) break; /* Call the engine dependent repainter */ (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen); return 0; case WM_PALETTECHANGED: { #if CYGDEBUG winDebug("winWindowProc - WM_PALETTECHANGED\n"); #endif /* * Don't process if we don't have privates or a colormap, * or if we have an invalid depth. */ if (s_pScreenPriv == NULL || s_pScreenPriv->pcmapInstalled == NULL || s_pScreenPriv->fBadDepth) break; /* Return if we caused the palette to change */ if ((HWND) wParam == hwnd) { /* Redraw the screen */ (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen); return 0; } /* Reinstall the windows palette */ (*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen); /* Redraw the screen */ (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen); return 0; } case WM_MOUSEMOVE: /* We can't do anything without privates */ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* We can't do anything without g_pwinPointer */ if (g_pwinPointer == NULL) break; /* Has the mouse pointer crossed screens? */ if (s_pScreen != miPointerGetScreen(g_pwinPointer)) miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen, GET_X_LPARAM(lParam) - s_pScreenInfo->dwXOffset, GET_Y_LPARAM(lParam) - 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 (!TrackMouseEvent(&tme)) ErrorF("winWindowProc - TrackMouseEvent failed\n"); /* Flag that we are tracking now */ s_fTracking = TRUE; } /* Hide or show the Windows mouse cursor */ if (g_fSoftwareCursor && g_fCursor && (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer)) { /* Hide Windows cursor */ g_fCursor = FALSE; ShowCursor(FALSE); } else if (g_fSoftwareCursor && !g_fCursor && !s_pScreenPriv->fActive && !s_pScreenInfo->fLessPointer) { /* Show Windows cursor */ g_fCursor = TRUE; ShowCursor(TRUE); } /* Deliver absolute cursor position to X Server */ winEnqueueMotion(GET_X_LPARAM(lParam) - s_pScreenInfo->dwXOffset, GET_Y_LPARAM(lParam) - s_pScreenInfo->dwYOffset); 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 (g_fSoftwareCursor && !g_fCursor) { g_fCursor = TRUE; ShowCursor(TRUE); } 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 (g_fSoftwareCursor && !g_fCursor) { g_fCursor = TRUE; ShowCursor(TRUE); } return 0; case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam); case WM_LBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam); case WM_MBUTTONDBLCLK: case WM_MBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam); case WM_MBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam); case WM_RBUTTONDBLCLK: case WM_RBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam); case WM_RBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam); case WM_XBUTTONDBLCLK: case WM_XBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam); case WM_XBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM #endif ) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam); case WM_TIMER: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Branch on the timer id */ switch (wParam) { case WIN_E3B_TIMER_ID: /* Send delayed button press */ winMouseButtonsSendEvent(ButtonPress, s_pScreenPriv->iE3BCachedPress); /* Kill this timer */ KillTimer(s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID); /* Clear screen privates flags */ s_pScreenPriv->iE3BCachedPress = 0; break; case WIN_POLLING_MOUSE_TIMER_ID: { POINT point; WPARAM wL, wM, wR, wShift, wCtrl; LPARAM lPos; /* Get the current position of the mouse cursor */ GetCursorPos(&point); /* Map from screen (-X, -Y) to root (0, 0) */ point.x -= GetSystemMetrics(SM_XVIRTUALSCREEN); point.y -= GetSystemMetrics(SM_YVIRTUALSCREEN); /* Deliver absolute cursor position to X Server */ winEnqueueMotion(point.x, point.y); /* Check if a button was released but we didn't see it */ GetCursorPos(&point); wL = (GetKeyState(VK_LBUTTON) & 0x8000) ? MK_LBUTTON : 0; wM = (GetKeyState(VK_MBUTTON) & 0x8000) ? MK_MBUTTON : 0; wR = (GetKeyState(VK_RBUTTON) & 0x8000) ? MK_RBUTTON : 0; wShift = (GetKeyState(VK_SHIFT) & 0x8000) ? MK_SHIFT : 0; wCtrl = (GetKeyState(VK_CONTROL) & 0x8000) ? MK_CONTROL : 0; lPos = MAKELPARAM(point.x, point.y); if (g_fButton[0] & !wL) PostMessage(hwnd, WM_LBUTTONUP, wCtrl | wM | wR | wShift, lPos); if (g_fButton[1] & !wM) PostMessage(hwnd, WM_MBUTTONUP, wCtrl | wL | wR | wShift, lPos); if (g_fButton[2] & !wR) PostMessage(hwnd, WM_RBUTTONUP, wCtrl | wL | wM | wShift, lPos); } } return 0; case WM_CTLCOLORSCROLLBAR: FatalError("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not " "supposed to get this message. Exiting.\n"); return 0; case WM_MOUSEWHEEL: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; #if CYGDEBUG winDebug("winWindowProc - WM_MOUSEWHEEL\n"); #endif winMouseWheel(s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam)); break; case WM_SETFOCUS: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Restore the state of all mode keys */ winRestoreModeKeyStates(); /* Add the keyboard hook if possible */ if (g_fKeyboardHookLL) g_fKeyboardHookLL = winInstallKeyboardHookLL(); return 0; case WM_KILLFOCUS: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Release any pressed keys */ winKeybdReleaseKeys(); /* Remove our keyboard hook if it is installed */ winRemoveKeyboardHookLL(); return 0; case WM_SYSKEYDOWN: case WM_KEYDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* * FIXME: Catching Alt-F4 like this is really terrible. This should * be generalized to handle other Windows keyboard signals. Actually, * the list keys to catch and the actions to perform when caught should * be configurable; that way user's can customize the keys that they * need to have passed through to their window manager or apps, or they * can remap certain actions to new key codes that do not conflict * with the X apps that they are using. Yeah, that'll take awhile. */ if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000)) || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK && (GetKeyState(VK_MENU) & 0x8000) && (GetKeyState(VK_CONTROL) & 0x8000))) { /* * Better leave this message here, just in case some unsuspecting * user enters Alt + F4 and is surprised when the application * quits. */ ErrorF("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n"); /* Display Exit dialog */ winDisplayExitDialog(s_pScreenPriv); return 0; } /* * Don't do anything for the Windows keys, as focus will soon * be returned to Windows. We may be able to trap the Windows keys, * but we should determine if that is desirable before doing so. */ if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL) break; /* Discard fake Ctrl_L events that precede AltGR on non-US keyboards */ if (winIsFakeCtrl_L(message, wParam, lParam)) return 0; /* * Discard presses generated from Windows auto-repeat */ if (lParam & (1 << 30)) { switch (wParam) { /* ago: Pressing LControl while RControl is pressed is * Indicated as repeat. Fix this! */ case VK_CONTROL: case VK_SHIFT: if (winCheckKeyPressed(wParam, lParam)) return 0; break; default: return 0; } } /* Translate Windows key code to X scan code */ winTranslateKey(wParam, lParam, &iScanCode); /* Ignore repeats for CapsLock */ if (wParam == VK_CAPITAL) lParam = 1; /* Send the key event(s) */ for (i = 0; i < LOWORD(lParam); ++i) winSendKeyEvent(iScanCode, TRUE); return 0; case WM_SYSKEYUP: case WM_KEYUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* * Don't do anything for the Windows keys, as focus will soon * be returned to Windows. We may be able to trap the Windows keys, * but we should determine if that is desirable before doing so. */ if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL) break; /* Ignore the fake Ctrl_L that follows an AltGr release */ if (winIsFakeCtrl_L(message, wParam, lParam)) return 0; /* Enqueue a keyup event */ winTranslateKey(wParam, lParam, &iScanCode); winSendKeyEvent(iScanCode, FALSE); /* Release all pressed shift keys */ if (wParam == VK_SHIFT) winFixShiftKeys(iScanCode); return 0; case WM_HOTKEY: if (s_pScreenPriv == NULL) break; /* Call the engine-specific hot key handler */ (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen); return 0; case WM_ACTIVATE: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* TODO: Override display of window when we have a bad depth */ if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth) { ErrorF("winWindowProc - WM_ACTIVATE - Bad depth, trying " "to override window activation\n"); /* Minimize the window */ ShowWindow(hwnd, SW_MINIMIZE); /* Display dialog box */ if (g_hDlgDepthChange != NULL) { /* Make the existing dialog box active */ SetActiveWindow(g_hDlgDepthChange); } else { /* TODO: Recreate the dialog box and bring to the top */ ShowWindow(g_hDlgDepthChange, SW_SHOWDEFAULT); } /* Don't do any other processing of this message */ return 0; } #if CYGDEBUG winDebug("winWindowProc - WM_ACTIVATE\n"); #endif /* * Focus is being changed to another window. * The other window may or may not belong to * our process. */ /* Clear any lingering wheel delta */ s_pScreenPriv->iDeltaZ = 0; /* Reshow the Windows mouse cursor if we are being deactivated */ if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE && !g_fCursor) { /* Show Windows cursor */ g_fCursor = TRUE; ShowCursor(TRUE); } return 0; case WM_ACTIVATEAPP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; #if CYGDEBUG || TRUE winDebug("winWindowProc - WM_ACTIVATEAPP\n"); #endif /* Activate or deactivate */ s_pScreenPriv->fActive = wParam; /* Reshow the Windows mouse cursor if we are being deactivated */ if (g_fSoftwareCursor && !s_pScreenPriv->fActive && !g_fCursor) { /* Show Windows cursor */ g_fCursor = TRUE; ShowCursor(TRUE); } #ifdef XWIN_CLIPBOARD /* Make sure the clipboard chain is ok. */ winFixClipboardChain(); #endif /* Call engine specific screen activation/deactivation function */ (*s_pScreenPriv->pwinActivateApp) (s_pScreen); #ifdef XWIN_MULTIWINDOWEXTWM if (s_pScreenPriv->fActive) { /* Restack all window unless using built-in wm. */ if (s_pScreenInfo->fInternalWM && s_pScreenInfo->fAnotherWMRunning) winMWExtWMRestackWindows(s_pScreen); } #endif return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_APP_EXIT: /* Display Exit dialog */ winDisplayExitDialog(s_pScreenPriv); return 0; #ifdef XWIN_MULTIWINDOW case ID_APP_HIDE_ROOT: if (s_pScreenPriv->fRootWindowShown) ShowWindow(s_pScreenPriv->hwndScreen, SW_HIDE); else ShowWindow(s_pScreenPriv->hwndScreen, SW_SHOW); s_pScreenPriv->fRootWindowShown = !s_pScreenPriv->fRootWindowShown; return 0; #endif case ID_APP_ABOUT: /* Display the About box */ winDisplayAboutDialog(s_pScreenPriv); return 0; default: /* It's probably one of the custom menus... */ if (HandleCustomWM_COMMAND(0, LOWORD(wParam))) return 0; } break; case WM_ENDSESSION: case WM_GIVEUP: /* Tell X that we are giving up */ #ifdef XWIN_MULTIWINDOW if (s_pScreenInfo->fMultiWindow) winDeinitMultiWindowWM(); #endif GiveUp(0); return 0; case WM_CLOSE: /* Display Exit dialog */ winDisplayExitDialog(s_pScreenPriv); return 0; case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT) { if (!g_fSoftwareCursor) SetCursor(s_pScreenPriv->cursor.handle); return TRUE; } break; #ifdef XWIN_MULTIWINDOWEXTWM case WM_MANAGE: ErrorF("winWindowProc - WM_MANAGE\n"); s_pScreenInfo->fAnotherWMRunning = FALSE; if (s_pScreenInfo->fInternalWM) { EnumThreadWindows(g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0); //RootlessRepositionWindows (s_pScreen); } break; case WM_UNMANAGE: ErrorF("winWindowProc - WM_UNMANAGE\n"); s_pScreenInfo->fAnotherWMRunning = TRUE; if (s_pScreenInfo->fInternalWM) { EnumThreadWindows(g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0); winMWExtWMRestackWindows(s_pScreen); } break; #endif default: if (message == s_uTaskbarRestart) { winInitNotifyIcon(s_pScreenPriv); } break; } return DefWindowProc(hwnd, message, wParam, lParam); }
LRESULT CALLBACK winWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static winPrivScreenPtr s_pScreenPriv = NULL; static winScreenInfo *s_pScreenInfo = NULL; static ScreenPtr s_pScreen = NULL; static HWND s_hwndLastPrivates = NULL; static HINSTANCE s_hInstance; static Bool s_fTracking = FALSE; static unsigned long s_ulServerGeneration = 0; int iScanCode; int i; /* Watch for server regeneration */ if (g_ulServerGeneration != s_ulServerGeneration) { /* Store new server generation */ s_ulServerGeneration = g_ulServerGeneration; } /* Only retrieve new privates pointers if window handle is null or changed */ if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates) && (s_pScreenPriv = GetProp (hwnd, WIN_SCR_PROP)) != NULL) { #if CYGDEBUG ErrorF ("winWindowProc - Setting privates handle\n"); #endif s_pScreenInfo = s_pScreenPriv->pScreenInfo; s_pScreen = s_pScreenInfo->pScreen; s_hwndLastPrivates = hwnd; } else if (s_pScreenPriv == NULL) { /* For safety, handle case that should never happen */ s_pScreenInfo = NULL; s_pScreen = NULL; s_hwndLastPrivates = NULL; } /* Branch on message type */ switch (message) { case WM_TRAYICON: return winHandleIconMessage (hwnd, message, wParam, lParam, s_pScreenPriv); case WM_CREATE: #if CYGDEBUG ErrorF ("winWindowProc - WM_CREATE\n"); #endif /* * Add a property to our display window that references * this screens' privates. * * This allows the window procedure to refer to the * appropriate window DC and shadow DC for the window that * it is processing. We use this to repaint exposed * areas of our display window. */ s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams; s_hInstance = ((LPCREATESTRUCT) lParam)->hInstance; s_pScreenInfo = s_pScreenPriv->pScreenInfo; s_pScreen = s_pScreenInfo->pScreen; s_hwndLastPrivates = hwnd; SetProp (hwnd, WIN_SCR_PROP, s_pScreenPriv); /* Store the mode key states so restore doesn't try to restore them */ winStoreModeKeyStates (s_pScreen); /* Setup tray icon */ if (!s_pScreenInfo->fNoTrayIcon) { /* * NOTE: The WM_CREATE message is processed before CreateWindowEx * returns, so s_pScreenPriv->hwndScreen is invalid at this point. * We go ahead and copy our hwnd parameter over top of the screen * privates hwndScreen so that we have a valid value for * that member. Otherwise, the tray icon will disappear * the first time you move the mouse over top of it. */ s_pScreenPriv->hwndScreen = hwnd; winInitNotifyIcon (s_pScreenPriv); } return 0; case WM_DISPLAYCHANGE: /* We cannot handle a display mode change during initialization */ if (s_pScreenInfo == NULL) FatalError ("winWindowProc - WM_DISPLAYCHANGE - The display " "mode changed while we were intializing. This is " "very bad and unexpected. Exiting.\n"); /* * We do not care about display changes with * fullscreen DirectDraw engines, because those engines set * their own mode when they become active. */ if (s_pScreenInfo->fFullScreen && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD)) { /* * Store the new display dimensions and depth. * We do this here for future compatibility in case we * ever allow switching from fullscreen to windowed mode. */ s_pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXSCREEN); s_pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYSCREEN); s_pScreenPriv->dwLastWindowsBitsPixel = GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL); break; } ErrorF ("winWindowProc - WM_DISPLAYCHANGE - orig bpp: %d, last bpp: %d, " "new bpp: %d\n", s_pScreenInfo->dwBPP, s_pScreenPriv->dwLastWindowsBitsPixel, wParam); ErrorF ("winWindowProc - WM_DISPLAYCHANGE - new width: %d " "new height: %d\n", LOWORD (lParam), HIWORD (lParam)); /* * TrueColor --> TrueColor depth changes are disruptive for: * Windowed: * Shadow DirectDraw * Shadow DirectDraw Non-Locking * Primary DirectDraw * * TrueColor --> TrueColor depth changes are non-optimal for: * Windowed: * Shadow GDI * * FullScreen: * Shadow GDI * * TrueColor --> PseudoColor or vice versa are disruptive for: * Windowed: * Shadow DirectDraw * Shadow DirectDraw Non-Locking * Primary DirectDraw * Shadow GDI */ /* * Check for a disruptive change in depth. * We can only display a message for a disruptive depth change, * we cannot do anything to correct the situation. */ if ((s_pScreenInfo->dwBPP != wParam) && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD)) { /* Cannot display the visual until the depth is restored */ ErrorF ("winWindowProc - Disruptive change in depth\n"); /* Display Exit dialog */ winDisplayDepthChangeDialog (s_pScreenPriv); /* Flag that we have an invalid screen depth */ s_pScreenPriv->fBadDepth = TRUE; /* Minimize the display window */ ShowWindow (hwnd, SW_MINIMIZE); } else { /* Flag that we have a valid screen depth */ s_pScreenPriv->fBadDepth = FALSE; } /* * Check for a change in display dimensions. * We can simply recreate the same-sized primary surface when * the display dimensions change. */ if (s_pScreenPriv->dwLastWindowsWidth != LOWORD (lParam) || s_pScreenPriv->dwLastWindowsHeight != HIWORD (lParam)) { /* * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface * and CreatePrimarySurface function pointers to point * to the no operation function, NoopDDA. This allows us * to blindly call these functions, even if they are not * relevant to the current engine (e.g., Shadow GDI). */ #if CYGDEBUG ErrorF ("winWindowProc - WM_DISPLAYCHANGE - Dimensions changed\n"); #endif /* Release the old primary surface */ (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen); #if CYGDEBUG ErrorF ("winWindowProc - WM_DISPLAYCHANGE - Released " "primary surface\n"); #endif /* Create the new primary surface */ (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen); #if CYGDEBUG ErrorF ("winWindowProc - WM_DISPLAYCHANGE - Recreated " "primary surface\n"); #endif } else { #if CYGDEBUG ErrorF ("winWindowProc - WM_DISPLAYCHANGE - Dimensions did not " "change\n"); #endif } /* Store the new display dimensions and depth */ s_pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXSCREEN); s_pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYSCREEN); s_pScreenPriv->dwLastWindowsBitsPixel = GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL); break; case WM_SIZE: { SCROLLINFO si; RECT rcWindow; int iWidth, iHeight; #if CYGDEBUG ErrorF ("winWindowProc - WM_SIZE\n"); #endif /* Break if we do not use scrollbars */ if (!s_pScreenInfo->fScrollbars || !s_pScreenInfo->fDecoration || s_pScreenInfo->fRootless || s_pScreenInfo->fMultiWindow || s_pScreenInfo->fFullScreen) break; /* No need to resize if we get minimized */ if (wParam == SIZE_MINIMIZED) return 0; /* * Get the size of the whole window, including client area, * scrollbars, and non-client area decorations (caption, borders). * We do this because we need to check if the client area * without scrollbars is large enough to display the whole visual. * The new client area size passed by lParam already subtracts * the size of the scrollbars if they are currently displayed. * So checking is LOWORD(lParam) == visual_width and * HIWORD(lParam) == visual_height will never tell us to hide * the scrollbars because the client area would always be too small. * GetClientRect returns the same sizes given by lParam, so we * cannot use GetClientRect either. */ GetWindowRect (hwnd, &rcWindow); iWidth = rcWindow.right - rcWindow.left; iHeight = rcWindow.bottom - rcWindow.top; ErrorF ("winWindowProc - WM_SIZE - window w: %d h: %d, " "new client area w: %d h: %d\n", iWidth, iHeight, LOWORD (lParam), HIWORD (lParam)); /* Subtract the frame size from the window size. */ iWidth -= 2 * GetSystemMetrics (SM_CXSIZEFRAME); iHeight -= (2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION)); /* * Update scrollbar page sizes. * NOTE: If page size == range, then the scrollbar is * automatically hidden. */ /* Is the naked client area large enough to show the whole visual? */ if (iWidth < s_pScreenInfo->dwWidth || iHeight < s_pScreenInfo->dwHeight) { /* Client area too small to display visual, use scrollbars */ iWidth -= GetSystemMetrics (SM_CXVSCROLL); iHeight -= GetSystemMetrics (SM_CYHSCROLL); } /* Set the horizontal scrollbar page size */ si.cbSize = sizeof (si); si.fMask = SIF_PAGE | SIF_RANGE; si.nMin = 0; si.nMax = s_pScreenInfo->dwWidth - 1; si.nPage = iWidth; SetScrollInfo (hwnd, SB_HORZ, &si, TRUE); /* Set the vertical scrollbar page size */ si.cbSize = sizeof (si); si.fMask = SIF_PAGE | SIF_RANGE; si.nMin = 0; si.nMax = s_pScreenInfo->dwHeight - 1; si.nPage = iHeight; SetScrollInfo (hwnd, SB_VERT, &si, TRUE); /* * NOTE: Scrollbars may have moved if they were at the * far right/bottom, so we query their current position. */ /* Get the horizontal scrollbar position and set the offset */ si.cbSize = sizeof (si); si.fMask = SIF_POS; GetScrollInfo (hwnd, SB_HORZ, &si); s_pScreenInfo->dwXOffset = -si.nPos; /* Get the vertical scrollbar position and set the offset */ si.cbSize = sizeof (si); si.fMask = SIF_POS; GetScrollInfo (hwnd, SB_VERT, &si); s_pScreenInfo->dwYOffset = -si.nPos; } return 0; case WM_VSCROLL: { SCROLLINFO si; int iVertPos; #if CYGDEBUG ErrorF ("winWindowProc - WM_VSCROLL\n"); #endif /* Get vertical scroll bar info */ si.cbSize = sizeof (si); si.fMask = SIF_ALL; GetScrollInfo (hwnd, SB_VERT, &si); /* Save the vertical position for comparison later */ iVertPos = si.nPos; /* * Don't forget: * moving the scrollbar to the DOWN, scroll the content UP */ switch (LOWORD(wParam)) { case SB_TOP: si.nPos = si.nMin; break; case SB_BOTTOM: si.nPos = si.nMax - si.nPage + 1; break; case SB_LINEUP: si.nPos -= 1; break; case SB_LINEDOWN: si.nPos += 1; break; case SB_PAGEUP: si.nPos -= si.nPage; break; case SB_PAGEDOWN: si.nPos += si.nPage; break; case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; default: break; } /* * We retrieve the position after setting it, * because Windows may adjust it. */ si.fMask = SIF_POS; SetScrollInfo (hwnd, SB_VERT, &si, TRUE); GetScrollInfo (hwnd, SB_VERT, &si); /* Scroll the window if the position has changed */ if (si.nPos != iVertPos) { /* Save the new offset for bit block transfers, etc. */ s_pScreenInfo->dwYOffset = -si.nPos; /* Change displayed region in the window */ ScrollWindowEx (hwnd, 0, iVertPos - si.nPos, NULL, NULL, NULL, NULL, SW_INVALIDATE); /* Redraw the window contents */ UpdateWindow (hwnd); } } return 0; case WM_HSCROLL: { SCROLLINFO si; int iHorzPos; #if CYGDEBUG ErrorF ("winWindowProc - WM_HSCROLL\n"); #endif /* Get horizontal scroll bar info */ si.cbSize = sizeof (si); si.fMask = SIF_ALL; GetScrollInfo (hwnd, SB_HORZ, &si); /* Save the horizontal position for comparison later */ iHorzPos = si.nPos; /* * Don't forget: * moving the scrollbar to the RIGHT, scroll the content LEFT */ switch (LOWORD(wParam)) { case SB_LEFT: si.nPos = si.nMin; break; case SB_RIGHT: si.nPos = si.nMax - si.nPage + 1; break; case SB_LINELEFT: si.nPos -= 1; break; case SB_LINERIGHT: si.nPos += 1; break; case SB_PAGELEFT: si.nPos -= si.nPage; break; case SB_PAGERIGHT: si.nPos += si.nPage; break; case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; default: break; } /* * We retrieve the position after setting it, * because Windows may adjust it. */ si.fMask = SIF_POS; SetScrollInfo (hwnd, SB_HORZ, &si, TRUE); GetScrollInfo (hwnd, SB_HORZ, &si); /* Scroll the window if the position has changed */ if (si.nPos != iHorzPos) { /* Save the new offset for bit block transfers, etc. */ s_pScreenInfo->dwXOffset = -si.nPos; /* Change displayed region in the window */ ScrollWindowEx (hwnd, iHorzPos - si.nPos, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE); /* Redraw the window contents */ UpdateWindow (hwnd); } } return 0; case WM_GETMINMAXINFO: { MINMAXINFO *pMinMaxInfo = (MINMAXINFO *) lParam; int iCaptionHeight; int iBorderHeight, iBorderWidth; #if CYGDEBUG ErrorF ("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %08x\n", s_pScreenInfo); #endif /* Can't do anything without screen info */ if (s_pScreenInfo == NULL || !s_pScreenInfo->fScrollbars || s_pScreenInfo->fFullScreen || !s_pScreenInfo->fDecoration || s_pScreenInfo->fRootless || s_pScreenInfo->fMultiWindow) break; /* * Here we can override the maximum tracking size, which * is the largest size that can be assigned to our window * via the sizing border. */ /* * FIXME: Do we only need to do this once, since our visual size * does not change? Does Windows store this value statically * once we have set it once? */ /* Get the border and caption sizes */ iCaptionHeight = GetSystemMetrics (SM_CYCAPTION); iBorderWidth = 2 * GetSystemMetrics (SM_CXSIZEFRAME); iBorderHeight = 2 * GetSystemMetrics (SM_CYSIZEFRAME); /* Allow the full visual to be displayed */ pMinMaxInfo->ptMaxTrackSize.x = s_pScreenInfo->dwWidth + iBorderWidth; pMinMaxInfo->ptMaxTrackSize.y = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight; } return 0; case WM_ERASEBKGND: #if CYGDEBUG ErrorF ("winWindowProc - WM_ERASEBKGND\n"); #endif /* * Pretend that we did erase the background but we don't care, * the application uses the full window estate. This avoids some * flickering when resizing. */ return TRUE; case WM_PAINT: #if CYGDEBUG ErrorF ("winWindowProc - WM_PAINT\n"); #endif /* Only paint if we have privates and the server is enabled */ if (s_pScreenPriv == NULL || !s_pScreenPriv->fEnabled || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive) || s_pScreenPriv->fBadDepth) { /* We don't want to paint */ break; } /* Break out here if we don't have a valid paint routine */ if (s_pScreenPriv->pwinBltExposedRegions == NULL) break; /* Call the engine dependent repainter */ (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen); return 0; case WM_PALETTECHANGED: { #if CYGDEBUG ErrorF ("winWindowProc - WM_PALETTECHANGED\n"); #endif /* * Don't process if we don't have privates or a colormap, * or if we have an invalid depth. */ if (s_pScreenPriv == NULL || s_pScreenPriv->pcmapInstalled == NULL || s_pScreenPriv->fBadDepth) break; /* Return if we caused the palette to change */ if ((HWND) wParam == hwnd) { /* Redraw the screen */ (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen); return 0; } /* Reinstall the windows palette */ (*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen); /* Redraw the screen */ (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen); return 0; } case WM_MOUSEMOVE: /* 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, GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset, GET_Y_LPARAM(lParam)-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 ("winWindowProc - _TrackMouseEvent failed\n"); /* Flag that we are tracking now */ s_fTracking = TRUE; } /* Hide or show the Windows mouse cursor */ if (g_fCursor && (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer)) { /* Hide Windows cursor */ g_fCursor = FALSE; ShowCursor (FALSE); } else if (!g_fCursor && !s_pScreenPriv->fActive && !s_pScreenInfo->fLessPointer) { /* Show Windows cursor */ g_fCursor = TRUE; ShowCursor (TRUE); } /* Deliver absolute cursor position to X Server */ miPointerAbsoluteCursor (GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset, GET_Y_LPARAM(lParam)-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 (!g_fCursor) { g_fCursor = TRUE; ShowCursor (TRUE); } 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 (!g_fCursor) { g_fCursor = TRUE; ShowCursor (TRUE); } return 0; case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless) SetCapture (hwnd); return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam); case WM_LBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless) ReleaseCapture (); return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam); case WM_MBUTTONDBLCLK: case WM_MBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless) SetCapture (hwnd); return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam); case WM_MBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless) ReleaseCapture (); return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam); case WM_RBUTTONDBLCLK: case WM_RBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless) SetCapture (hwnd); return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam); case WM_RBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; if (s_pScreenInfo->fRootless) ReleaseCapture (); return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam); case WM_TIMER: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Branch on the timer id */ switch (wParam) { case WIN_E3B_TIMER_ID: /* Send delayed button press */ winMouseButtonsSendEvent (ButtonPress, s_pScreenPriv->iE3BCachedPress); /* Kill this timer */ KillTimer (s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID); /* Clear screen privates flags */ s_pScreenPriv->iE3BCachedPress = 0; break; case WIN_POLLING_MOUSE_TIMER_ID: { POINT point; /* Get the current position of the mouse cursor */ GetCursorPos (&point); /* Map from screen (-X, -Y) to root (0, 0) */ point.x -= GetSystemMetrics (SM_XVIRTUALSCREEN); point.y -= GetSystemMetrics (SM_YVIRTUALSCREEN); /* Deliver absolute cursor position to X Server */ miPointerAbsoluteCursor (point.x, point.y, g_c32LastInputEventTime = GetTickCount()); } } return 0; case WM_CTLCOLORSCROLLBAR: FatalError ("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not " "supposed to get this message. Exiting.\n"); return 0; case WM_MOUSEWHEEL: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; #if CYGDEBUG ErrorF ("winWindowProc - WM_MOUSEWHEEL\n"); #endif winMouseWheel (s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam)); break; case WM_SETFOCUS: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Restore the state of all mode keys */ winRestoreModeKeyStates (s_pScreen); return 0; case WM_KILLFOCUS: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Store the state of all mode keys */ winStoreModeKeyStates (s_pScreen); /* Release any pressed keys */ winKeybdReleaseKeys (); return 0; #if WIN_NEW_KEYBOARD_SUPPORT case WM_SYSKEYDOWN: case WM_KEYDOWN: case WM_SYSKEYUP: case WM_KEYUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Don't process keys if we are not active */ if (!s_pScreenPriv->fActive) return 0; winProcessKeyEvent ((DWORD)wParam, (DWORD) lParam); return 0; case WM_DEADCHAR: case WM_SYSDEADCHAR: return 0; #else /* WIN_NEW_KEYBOARD_SUPPORT */ case WM_SYSKEYDOWN: case WM_KEYDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* * FIXME: Catching Alt-F4 like this is really terrible. This should * be generalized to handle other Windows keyboard signals. Actually, * the list keys to catch and the actions to perform when caught should * be configurable; that way user's can customize the keys that they * need to have passed through to their window manager or apps, or they * can remap certain actions to new key codes that do not conflict * with the X apps that they are using. Yeah, that'll take awhile. */ if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000)) || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK && (GetKeyState (VK_MENU) & 0x8000) && (GetKeyState (VK_CONTROL) & 0x8000))) { /* * Better leave this message here, just in case some unsuspecting * user enters Alt + F4 and is surprised when the application * quits. */ ErrorF ("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n"); /* Display Exit dialog */ winDisplayExitDialog (s_pScreenPriv); return 0; } /* * Don't do anything for the Windows keys, as focus will soon * be returned to Windows. We may be able to trap the Windows keys, * but we should determine if that is desirable before doing so. */ if (wParam == VK_LWIN || wParam == VK_RWIN) break; /* Discard fake Ctrl_L presses that precede AltGR on non-US keyboards */ if (winIsFakeCtrl_L (message, wParam, lParam)) return 0; /* Send the key event(s) */ winTranslateKey (wParam, lParam, &iScanCode); for (i = 0; i < LOWORD(lParam); ++i) winSendKeyEvent (iScanCode, TRUE); return 0; case WM_SYSKEYUP: case WM_KEYUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* * Don't do anything for the Windows keys, as focus will soon * be returned to Windows. We may be able to trap the Windows keys, * but we should determine if that is desirable before doing so. */ if (wParam == VK_LWIN || wParam == VK_RWIN) break; /* Ignore the fake Ctrl_L that follows an AltGr release */ if (winIsFakeCtrl_L (message, wParam, lParam)) return 0; /* Enqueue a keyup event */ winTranslateKey (wParam, lParam, &iScanCode); winSendKeyEvent (iScanCode, FALSE); return 0; #endif /* WIN_NEW_KEYBOARD_SUPPORT */ case WM_HOTKEY: if (s_pScreenPriv == NULL) break; /* Call the engine-specific hot key handler */ (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen); return 0; case WM_ACTIVATE: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* TODO: Override display of window when we have a bad depth */ if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth) { ErrorF ("winWindowProc - WM_ACTIVATE - Bad depth, trying " "to override window activation\n"); /* Minimize the window */ ShowWindow (hwnd, SW_MINIMIZE); /* Display dialog box */ if (g_hDlgDepthChange != NULL) { /* Make the existing dialog box active */ SetActiveWindow (g_hDlgDepthChange); } else { /* TODO: Recreate the dialog box and bring to the top */ ShowWindow (g_hDlgDepthChange, SW_SHOWDEFAULT); } /* Don't do any other processing of this message */ return 0; } #if CYGDEBUG ErrorF ("winWindowProc - WM_ACTIVATE\n"); #endif /* * Focus is being changed to another window. * The other window may or may not belong to * our process. */ /* Clear any lingering wheel delta */ s_pScreenPriv->iDeltaZ = 0; /* Reshow the Windows mouse cursor if we are being deactivated */ if (LOWORD(wParam) == WA_INACTIVE && !g_fCursor) { /* Show Windows cursor */ g_fCursor = TRUE; ShowCursor (TRUE); } return 0; case WM_ACTIVATEAPP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; #if CYGDEBUG ErrorF ("winWindowProc - WM_ACTIVATEAPP\n"); #endif /* Activate or deactivate */ s_pScreenPriv->fActive = wParam; /* Reshow the Windows mouse cursor if we are being deactivated */ if (!s_pScreenPriv->fActive && !g_fCursor) { /* Show Windows cursor */ g_fCursor = TRUE; ShowCursor (TRUE); } /* Call engine specific screen activation/deactivation function */ (*s_pScreenPriv->pwinActivateApp) (s_pScreen); return 0; case WM_COMMAND: switch (LOWORD (wParam)) { case ID_APP_EXIT: /* Display Exit dialog */ winDisplayExitDialog (s_pScreenPriv); return 0; case ID_APP_HIDE_ROOT: ShowWindow (s_pScreenPriv->hwndScreen, SW_HIDE); s_pScreenPriv->fRootWindowShown = FALSE; return 0; case ID_APP_SHOW_ROOT: ShowWindow (s_pScreenPriv->hwndScreen, SW_SHOW); s_pScreenPriv->fRootWindowShown = TRUE; return 0; default: /* It's probably one of the custom menus... */ return HandleCustomWM_COMMAND (0, LOWORD (wParam)); } break; case WM_GIVEUP: /* Tell X that we are giving up */ winDeinitClipboard (); winDeinitMultiWindowWM (); GiveUp (0); return 0; case WM_CLOSE: /* Display Exit dialog */ winDisplayExitDialog (s_pScreenPriv); return 0; } return DefWindowProc (hwnd, message, wParam, lParam); }
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; winWMMessageRec wmMsg; Bool fWMMsgInitialized = FALSE; static Bool s_fTracking = FALSE; Bool needRestack = FALSE; LRESULT ret; static Bool hasEnteredSizeMove = FALSE; winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam, lParam); /* 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 */ hwndScreen = s_pScreenPriv->hwndScreen; /* */ wmMsg.msg = 0; wmMsg.hwndWindow = hwnd; wmMsg.iWindow = (Window) GetProp(hwnd, WIN_WID_PROP); wmMsg.iX = pDraw->x; wmMsg.iY = pDraw->y; wmMsg.iWidth = pDraw->width; wmMsg.iHeight = pDraw->height; fWMMsgInitialized = TRUE; } #ifdef _DEBUG else if (message!=WM_CREATE) { winDebug("Warning: message 0x%x received when WIN_WINDOW_PROP NULL\n",message); } #endif /* Branch on message type */ switch (message) { case WM_CREATE: /* */ SetProp(hwnd, WIN_WINDOW_PROP, (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams); /* */ SetProp(hwnd, WIN_WID_PROP, (HANDLE) winGetWindowID(((LPCREATESTRUCT) lParam)-> lpCreateParams)); /* * Make X windows' Z orders sync with Windows windows because * there can be AlwaysOnTop windows overlapped on the window * currently being created. */ winReorderWindowsMultiWindow(); /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */ { RECT rWindow; HRGN hRgnWindow; GetWindowRect(hwnd, &rWindow); hRgnWindow = CreateRectRgnIndirect(&rWindow); SetWindowRgn(hwnd, hRgnWindow, TRUE); } SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)VCXSRV_SIGNATURE); return 0; case WM_INIT_SYS_MENU: /* * Add whatever the setup file wants to for this window */ SetupSysMenu((unsigned long) hwnd); return 0; case WM_SYSCOMMAND: /* * Any window menu items go through here */ if (HandleCustomWM_COMMAND((unsigned long) hwnd, LOWORD(wParam))) { /* Don't pass customized menus to DefWindowProc */ return 0; } if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE) { WINDOWPLACEMENT wndpl; wndpl.length = sizeof(wndpl); if (GetWindowPlacement(hwnd, &wndpl) && wndpl.showCmd == SW_SHOWMINIMIZED) needRestack = TRUE; } break; case WM_INITMENU: /* Checks/Unchecks any menu items before they are displayed */ HandleCustomWM_INITMENU((unsigned long) hwnd, wParam); break; case WM_ERASEBKGND: /* * Pretend that we did erase the background but we don't care, * since we repaint the entire region anyhow * This avoids some flickering when resizing. */ return TRUE; 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); /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */ if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 && ps.rcPaint.left == 0 && ps.rcPaint.top == 0) { EndPaint(hwnd, &ps); return 0; } #ifdef XWIN_GLX_WINDOWS if (pWinPriv->fWglUsed) { /* For regions which are being drawn by GL, the shadow framebuffer doesn't have the correct bits, so don't bitblt from the shadow framebuffer XXX: For now, just leave it alone, but ideally we want to send an expose event to the window so it really redraws the affected region... */ ValidateRect(hwnd, &(ps.rcPaint)); } else #endif /* 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, s_pScreenPriv->hdcShadow, ps.rcPaint.left + pWin->drawable.x, ps.rcPaint.top + pWin->drawable.y, 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("winTopLevelWindowProc - BitBlt failed: %s\n", (LPSTR) lpMsgBuf); LocalFree(lpMsgBuf); } /* EndPaint frees the DC */ EndPaint(hwnd, &ps); return 0; 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); /* 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 (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Has the mouse pointer crossed screens? */ if (s_pScreen != miPointerGetScreen(g_pwinPointer)) miPointerSetScreen(g_pwinPointer, 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 (!TrackMouseEvent(&tme)) ErrorF("winTopLevelWindowProc - TrackMouseEvent failed\n"); /* Flag that we are tracking now */ s_fTracking = TRUE; } /* Hide or show the Windows mouse cursor */ if (g_fSoftwareCursor && g_fCursor) { /* Hide Windows cursor */ g_fCursor = FALSE; ShowCursor(FALSE); } /* Kill the timer used to poll mouse events */ if (g_uipMousePollingTimerID != 0) { KillTimer(s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID); g_uipMousePollingTimerID = 0; } /* Deliver absolute cursor position to X Server */ winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset, ptMouse.y - s_pScreenInfo->dwYOffset); 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 (g_fSoftwareCursor && !g_fCursor) { g_fCursor = TRUE; ShowCursor(TRUE); } winStartMousePolling(s_pScreenPriv); break; case WM_MOUSELEAVE: /* We can't do anything without privates */ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; /* Mouse has left our client area */ /* Flag that we are no longer tracking */ s_fTracking = FALSE; /* Show the mouse cursor, if necessary */ if (g_fSoftwareCursor && !g_fCursor) { g_fCursor = TRUE; ShowCursor(TRUE); } winStartMousePolling(s_pScreenPriv); return 0; case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; g_fButton[0] = TRUE; SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam); case WM_LBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; g_fButton[0] = FALSE; ReleaseCapture(); winStartMousePolling(s_pScreenPriv); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam); case WM_MBUTTONDBLCLK: case WM_MBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; g_fButton[1] = TRUE; SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam); case WM_MBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; g_fButton[1] = FALSE; ReleaseCapture(); winStartMousePolling(s_pScreenPriv); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam); case WM_RBUTTONDBLCLK: case WM_RBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; g_fButton[2] = TRUE; SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam); case WM_RBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; g_fButton[2] = FALSE; ReleaseCapture(); winStartMousePolling(s_pScreenPriv); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam); case WM_XBUTTONDBLCLK: case WM_XBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam); case WM_XBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; ReleaseCapture(); winStartMousePolling(s_pScreenPriv); return winMouseButtonsHandle(s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam); case WM_MOUSEWHEEL: if (SendMessage (hwnd, WM_NCHITTEST, 0, MAKELONG(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) == HTCLIENT) { /* Pass the message to the root window */ SendMessage(hwndScreen, message, wParam, lParam); return 0; } else break; case WM_SETFOCUS: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; { /* Get the parent window for transient handling */ HWND hParent = GetParent(hwnd); if (hParent && IsIconic(hParent)) ShowWindow(hParent, SW_RESTORE); } winRestoreModeKeyStates(); /* Add the keyboard hook if possible */ if (g_fKeyboardHookLL) g_fKeyboardHookLL = winInstallKeyboardHookLL(); return 0; case WM_KILLFOCUS: /* Pop any pressed keys since we are losing keyboard focus */ winKeybdReleaseKeys(); /* Remove our keyboard hook if it is installed */ winRemoveKeyboardHookLL(); /* Revert the X focus as well, but only if the Windows focus is going to another window */ if (!wParam && pWin) DeleteWindowFromAnyEvents(pWin, FALSE); 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: /* * 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; #ifdef WINDBG if (wParam == VK_ESCAPE) { /* Place for debug: put any tests and dumps here */ WINDOWPLACEMENT windPlace; RECT rc; LPRECT pRect; windPlace.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(hwnd, &windPlace); pRect = &windPlace.rcNormalPosition; winDebug ("\nCYGWINDOWING Dump:\n" "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x, pDraw->y, pDraw->width, pDraw->height); winDebug ("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); if (GetClientRect(hwnd, &rc)) { pRect = &rc; winDebug ("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); } if (GetWindowRect(hwnd, &rc)) { pRect = &rc; winDebug ("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); } winDebug ("\n"); } #endif /* Pass the message to the root window */ return winWindowProc(hwndScreen, message, wParam, lParam); case WM_SYSKEYUP: case WM_KEYUP: /* Pass the message to the root window */ return winWindowProc(hwndScreen, message, wParam, lParam); case WM_HOTKEY: /* Pass the message to the root window */ SendMessage(hwndScreen, message, wParam, lParam); return 0; case WM_ACTIVATE: /* Pass the message to the root window */ SendMessage(hwndScreen, message, wParam, lParam); if (LOWORD(wParam) != WA_INACTIVE) { /* Raise the window to the top in Z order */ /* ago: Activate does not mean putting it to front! */ /* wmMsg.msg = WM_WM_RAISE; if (fWMMsgInitialized) winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); */ /* Tell our Window Manager thread to activate the window */ wmMsg.msg = WM_WM_ACTIVATE; if (fWMMsgInitialized && pWin->realized && !pWin->overrideRedirect /* for OOo menus */) winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); } /* Prevent the mouse wheel from stalling when another window is minimized */ if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE && (HWND) lParam != NULL && (HWND) lParam != (HWND) GetParent(hwnd)) SetFocus(hwnd); return 0; case WM_ACTIVATEAPP: /* * This message is also sent to the root window * so we do nothing for individual multiwindow windows */ break; case WM_CLOSE: /* Removep AppUserModelID property */ winSetAppUserModelID(hwnd, NULL); /* 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; if (fWMMsgInitialized) winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); } return 0; case WM_DESTROY: /* Branch on if the window was killed in X already */ if (pWinPriv && !pWinPriv->fXKilled) { winDebug ("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n"); /* Tell our Window Manager thread to kill the window */ wmMsg.msg = WM_WM_KILL; if (fWMMsgInitialized) winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); } RemoveProp(hwnd, WIN_WINDOW_PROP); RemoveProp(hwnd, WIN_WID_PROP); RemoveProp(hwnd, WIN_NEEDMANAGE_PROP); break; case WM_MOVE: /* Adjust the X Window to the moved Windows window */ if (!hasEnteredSizeMove) winAdjustXWindow (pWin, hwnd); /* else: Wait for WM_EXITSIZEMOVE */ return 0; case WM_SHOWWINDOW: /* Bail out if the window is being hidden */ if (!wParam) return 0; /* */ if (!pWin->overrideRedirect) { HWND zstyle = HWND_NOTOPMOST; /* Flag that this window needs to be made active when clicked */ SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1); /* Set the transient style flags */ if (GetParent(hwnd)) SetWindowLongPtr(hwnd, GWL_STYLE, WS_POPUP | WS_OVERLAPPED | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); /* Set the window standard style flags */ else SetWindowLongPtr(hwnd, GWL_STYLE, (WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS) & ~WS_CAPTION & ~WS_SIZEBOX); winUpdateWindowPosition(hwnd, &zstyle); { WinXWMHints hints; if (winMultiWindowGetWMHints(pWin, &hints)) { /* Give the window focus, unless it has an InputHint which is FALSE (this is used by e.g. glean to avoid every test window grabbing the focus) */ if (!((hints.flags & InputHint) && (!hints.input))) { SetForegroundWindow(hwnd); } } } wmMsg.msg = WM_WM_MAP3; } else { /* It is an overridden window so make it top of Z stack */ HWND forHwnd = GetForegroundWindow(); winDebug ("overridden window is shown\n"); if (forHwnd != NULL) { if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR) VCXSRV_SIGNATURE) { if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); else SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } } wmMsg.msg = WM_WM_MAP2; } /* Tell our Window Manager thread to map the window */ if (fWMMsgInitialized) winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); winStartMousePolling(s_pScreenPriv); return 0; case WM_SIZING: /* Need to legalize the size according to WM_NORMAL_HINTS */ /* for applications like xterm */ return ValidateSizing(hwnd, pWin, wParam, lParam); case WM_WINDOWPOSCHANGING: { /* When window is moved or resized, force it to be redrawn, so that any OpenGL content is re-drawn correctly, rather than copying bits (which seem to be wrong, either because we are copying the wrong window in the window heirarchy, or because we don't have the bits drawn by OpenGL at all) XXX: really this should check if any child has fWglUsed set, but that might be expensive to check.... */ if (g_fNativeGl) { LPWINDOWPOS pWinPos = (LPWINDOWPOS)lParam; pWinPos->flags |= SWP_NOCOPYBITS; } } break; case WM_WINDOWPOSCHANGED: { LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam; if (!(pWinPos->flags & SWP_NOZORDER)) { #if CYGWINDOWING_DEBUG winDebug("\twindow z order was changed\n"); #endif if (pWinPos->hwndInsertAfter == HWND_TOP || pWinPos->hwndInsertAfter == HWND_TOPMOST || pWinPos->hwndInsertAfter == HWND_NOTOPMOST) { #if CYGWINDOWING_DEBUG winDebug("\traise to top\n"); #endif /* Raise the window to the top in Z order */ winRaiseWindow(pWin); } 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 CYGWINDOWING_DEBUG winDebug("\traise to top\n"); #endif winRaiseWindow(pWin); } } } } /* * Pass the message to DefWindowProc to let the function * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE. */ break; case WM_ENTERSIZEMOVE: hasEnteredSizeMove = TRUE; return 0; case WM_EXITSIZEMOVE: /* Adjust the X Window to the moved Windows window */ hasEnteredSizeMove = FALSE; winAdjustXWindow (pWin, hwnd); return 0; case WM_SIZE: /* see dix/window.c */ #ifdef WINDBG { char buf[64]; switch (wParam) { case SIZE_MINIMIZED: strcpy(buf, "SIZE_MINIMIZED"); break; case SIZE_MAXIMIZED: strcpy(buf, "SIZE_MAXIMIZED"); break; case SIZE_RESTORED: strcpy(buf, "SIZE_RESTORED"); break; default: strcpy(buf, "UNKNOWN_FLAG"); } winDebug ("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n", (int) LOWORD(lParam), (int) HIWORD(lParam), buf, (int) (GetTickCount())); } #endif if (!hasEnteredSizeMove) { /* Adjust the X Window to the moved Windows window */ winAdjustXWindow (pWin, hwnd); if (wParam == SIZE_MINIMIZED) winReorderWindowsMultiWindow(); } /* else: wait for WM_EXITSIZEMOVE */ return 0; /* end of WM_SIZE handler */ case WM_STYLECHANGED: /* when the style changes, adjust the window size so the client area remains the same */ { LONG x,y; DrawablePtr pDraw = &pWin->drawable; x = pDraw->x - wBorderWidth(pWin); y = pDraw->y - wBorderWidth(pWin); winPositionWindowMultiWindow(pWin, x, y); } return 0; case WM_MOUSEACTIVATE: /* Check if this window needs to be made active when clicked */ if (!GetProp(pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) { winDebug ("winTopLevelWindowProc - WM_MOUSEACTIVATE - " "MA_NOACTIVATE\n"); /* */ return MA_NOACTIVATE; } break; case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT) { if (!g_fSoftwareCursor) SetCursor(s_pScreenPriv->cursor.handle); return TRUE; } break; default: break; } ret = DefWindowProc(hwnd, message, wParam, lParam); /* * If the window was minized we get the stack change before the window is restored * and so it gets lost. Ensure there stacking order is correct. */ if (needRestack) winReorderWindowsMultiWindow(); return ret; }