LRESULT CALLBACK winMWExtWMWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { WindowPtr pWin = NULL; win32RootlessWindowPtr pRLWinPriv = NULL; ScreenPtr pScreen = NULL; winPrivScreenPtr pScreenPriv = NULL; winScreenInfo *pScreenInfo = NULL; HWND hwndScreen = NULL; POINT ptMouse; static Bool s_fTracking = FALSE; HDC hdcUpdate; PAINTSTRUCT ps; LPWINDOWPOS pWinPos = NULL; RECT rcClient; winWMMessageRec wmMsg; Bool fWMMsgInitialized = FALSE; /* Check if the Windows window property for our X window pointer is valid */ if ((pRLWinPriv = (win32RootlessWindowPtr)GetProp (hwnd, WIN_WINDOW_PROP)) != NULL) { pWin = pRLWinPriv->pFrame->win; pScreen = pWin->drawable.pScreen; if (pScreen) pScreenPriv = winGetScreenPriv(pScreen); if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo; if (pScreenPriv) hwndScreen = pScreenPriv->hwndScreen; wmMsg.msg = 0; wmMsg.hwndWindow = hwnd; wmMsg.iWindow = (Window)pWin->drawable.id; wmMsg.iX = pRLWinPriv->pFrame->x; wmMsg.iY = pRLWinPriv->pFrame->y; wmMsg.iWidth = pRLWinPriv->pFrame->width; wmMsg.iHeight = pRLWinPriv->pFrame->height; fWMMsgInitialized = TRUE; #if CYGDEBUG winDebugWin32Message("winMWExtWMWindowProc", hwnd, message, wParam, lParam); winDebug ("\thWnd %08X\n", hwnd); winDebug ("\tpScreenPriv %08X\n", pScreenPriv); winDebug ("\tpScreenInfo %08X\n", pScreenInfo); winDebug ("\thwndScreen %08X\n", hwndScreen); winDebug ("winMWExtWMWindowProc (%08x) %08x %08x %08x\n", pRLWinPriv, message, wParam, lParam); #endif } /* Branch on message type */ switch (message) { case WM_CREATE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_CREATE\n"); #endif /* */ SetProp (hwnd, WIN_WINDOW_PROP, (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams); return 0; case WM_CLOSE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_CLOSE %d\n", pRLWinPriv->fClose); #endif /* Tell window-manager to close window */ if (pRLWinPriv->fClose) { DestroyWindow (hwnd); } else { if (winIsInternalWMRunning(pScreenInfo)) { /* Tell our Window Manager thread to kill the window */ wmMsg.msg = WM_WM_KILL; if (fWMMsgInitialized) winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); } winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMCloseWindow, pWin->drawable.id, 0, 0, 0, 0); } return 0; case WM_DESTROY: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_DESTROY\n"); #endif /* Free the shaodw DC; which allows the bitmap to be freed */ DeleteDC (pRLWinPriv->hdcShadow); pRLWinPriv->hdcShadow = NULL; /* Free the shadow bitmap */ DeleteObject (pRLWinPriv->hbmpShadow); pRLWinPriv->hbmpShadow = NULL; /* Free the screen DC */ ReleaseDC (pRLWinPriv->hWnd, pRLWinPriv->hdcScreen); pRLWinPriv->hdcScreen = NULL; /* Free shadow buffer info header */ free (pRLWinPriv->pbmihShadow); pRLWinPriv->pbmihShadow = NULL; pRLWinPriv->fResized = FALSE; pRLWinPriv->pfb = NULL; free (pRLWinPriv); RemoveProp (hwnd, WIN_WINDOW_PROP); break; case WM_MOUSEMOVE: #if CYGMULTIWINDOW_DEBUG && 0 winDebug ("winMWExtWMWindowProc - WM_MOUSEMOVE\n"); #endif /* Unpack the client area mouse coordinates */ ptMouse.x = GET_X_LPARAM(lParam); ptMouse.y = GET_Y_LPARAM(lParam); /* Translate the client area mouse coordinates to screen coordinates */ ClientToScreen (hwnd, &ptMouse); /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */ ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN); ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN); /* We can't do anything without privates */ if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; /* Has the mouse pointer crossed screens? */ if (pScreen != miPointerCurrentScreen ()) miPointerSetNewScreen (pScreenInfo->dwScreen, ptMouse.x - pScreenInfo->dwXOffset, ptMouse.y - pScreenInfo->dwYOffset); /* Are we tracking yet? */ if (!s_fTracking) { TRACKMOUSEEVENT tme; /* Setup data structure */ ZeroMemory (&tme, sizeof (tme)); tme.cbSize = sizeof (tme); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hwnd; /* Call the tracking function */ if (!(*g_fpTrackMouseEvent) (&tme)) ErrorF ("winMWExtWMWindowProc - _TrackMouseEvent failed\n"); /* Flag that we are tracking now */ s_fTracking = TRUE; } /* Kill the timer used to poll mouse events */ if (g_uipMousePollingTimerID != 0) { KillTimer (pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID); g_uipMousePollingTimerID = 0; } /* Deliver absolute cursor position to X Server */ miPointerAbsoluteCursor (ptMouse.x - pScreenInfo->dwXOffset, ptMouse.y - pScreenInfo->dwYOffset, g_c32LastInputEventTime = GetTickCount ()); return 0; case WM_NCMOUSEMOVE: #if CYGMULTIWINDOW_DEBUG && 0 winDebug ("winMWExtWMWindowProc - WM_NCMOUSEMOVE\n"); #endif /* * We break instead of returning 0 since we need to call * DefWindowProc to get the mouse cursor changes * and min/max/close button highlighting in Windows XP. * The Platform SDK says that you should return 0 if you * process this message, but it fails to mention that you * will give up any default functionality if you do return 0. */ /* We can't do anything without privates */ if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; /* * Timer to poll mouse events. This is needed to make * programs like xeyes follow the mouse properly. */ if (g_uipMousePollingTimerID == 0) g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID, MOUSE_POLLING_INTERVAL, NULL); break; case WM_MOUSELEAVE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MOUSELEAVE\n"); #endif /* Mouse has left our client area */ /* Flag that we are no longer tracking */ s_fTracking = FALSE; /* * Timer to poll mouse events. This is needed to make * programs like xeyes follow the mouse properly. */ if (g_uipMousePollingTimerID == 0) g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID, MOUSE_POLLING_INTERVAL, NULL); return 0; case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_LBUTTONDBLCLK\n"); #endif if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; SetCapture (hwnd); return winMouseButtonsHandle (pScreen, ButtonPress, Button1, wParam); case WM_LBUTTONUP: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_LBUTTONUP\n"); #endif if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; ReleaseCapture (); return winMouseButtonsHandle (pScreen, ButtonRelease, Button1, wParam); case WM_MBUTTONDBLCLK: case WM_MBUTTONDOWN: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MBUTTONDBLCLK\n"); #endif if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; SetCapture (hwnd); return winMouseButtonsHandle (pScreen, ButtonPress, Button2, wParam); case WM_MBUTTONUP: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MBUTTONUP\n"); #endif if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; ReleaseCapture (); return winMouseButtonsHandle (pScreen, ButtonRelease, Button2, wParam); case WM_RBUTTONDBLCLK: case WM_RBUTTONDOWN: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_RBUTTONDBLCLK\n"); #endif if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; SetCapture (hwnd); return winMouseButtonsHandle (pScreen, ButtonPress, Button3, wParam); case WM_RBUTTONUP: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_RBUTTONUP\n"); #endif if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; ReleaseCapture (); return winMouseButtonsHandle (pScreen, ButtonRelease, Button3, wParam); case WM_XBUTTONDBLCLK: case WM_XBUTTONDOWN: if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; SetCapture (hwnd); return winMouseButtonsHandle (pScreen, ButtonPress, HIWORD(wParam) + 5, wParam); case WM_XBUTTONUP: if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; ReleaseCapture (); return winMouseButtonsHandle (pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam); case WM_MOUSEWHEEL: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MOUSEWHEEL\n"); #endif /* Pass the message to the root window */ SendMessage (hwndScreen, message, wParam, lParam); return 0; case WM_MOUSEACTIVATE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n"); #endif #if 1 /* Check if this window needs to be made active when clicked */ if (winIsInternalWMRunning(pScreenInfo) && pWin->overrideRedirect) { #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE - " "MA_NOACTIVATE\n"); #endif /* */ return MA_NOACTIVATE; } #endif if (!winIsInternalWMRunning(pScreenInfo) && !IsMouseActive (pWin)) return MA_NOACTIVATE; break; case WM_KILLFOCUS: /* Pop any pressed keys since we are losing keyboard focus */ winKeybdReleaseKeys (); return 0; case WM_SYSDEADCHAR: case WM_DEADCHAR: /* * NOTE: We do nothing with WM_*CHAR messages, * nor does the root window, so we can just toss these messages. */ return 0; case WM_SYSKEYDOWN: case WM_KEYDOWN: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_*KEYDOWN\n"); #endif /* * Don't pass Alt-F4 key combo to root window, * let Windows translate to WM_CLOSE and close this top-level window. * * NOTE: We purposely don't check the fUseWinKillKey setting because * it should only apply to the key handling for the root window, * not for top-level window-manager windows. * * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window * because that is a key combo that no X app should be expecting to * receive, since it has historically been used to shutdown the X server. * Passing Ctrl-Alt-Backspace to the root window preserves that * behavior, assuming that -unixkill has been passed as a parameter. */ if (wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000)) break; /* Pass the message to the root window */ SendMessage (hwndScreen, message, wParam, lParam); return 0; case WM_SYSKEYUP: case WM_KEYUP: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_*KEYUP\n"); #endif /* Pass the message to the root window */ SendMessage (hwndScreen, message, wParam, lParam); return 0; case WM_HOTKEY: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_HOTKEY\n"); #endif /* Pass the message to the root window */ SendMessage (hwndScreen, message, wParam, lParam); return 0; case WM_PAINT: /* BeginPaint gives us an hdc that clips to the invalidated region */ hdcUpdate = BeginPaint (hwnd, &ps); /* Try to copy from the shadow buffer */ if (!BitBlt (hdcUpdate, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, pRLWinPriv->hdcShadow, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY)) { LPVOID lpMsgBuf; /* Display a fancy error message */ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError (), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); ErrorF ("winMWExtWMWindowProc - BitBlt failed: %s\n", (LPSTR)lpMsgBuf); LocalFree (lpMsgBuf); } /* EndPaint frees the DC */ EndPaint (hwnd, &ps); break; case WM_ACTIVATE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_ACTIVATE\n"); #endif if (LOWORD(wParam) != WA_INACTIVE) { if (winIsInternalWMRunning(pScreenInfo)) { #if 0 /* Raise the window to the top in Z order */ wmMsg.msg = WM_WM_RAISE; if (fWMMsgInitialized) winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); #endif /* Tell our Window Manager thread to activate the window */ wmMsg.msg = WM_WM_ACTIVATE; if (fWMMsgInitialized) if (!pWin || !pWin->overrideRedirect) /* for OOo menus */ winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); } winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMActivateWindow, pWin->drawable.id, 0, 0, 0, 0); } return 0; #if 1 case WM_WINDOWPOSCHANGING: pWinPos = (LPWINDOWPOS)lParam; if (!(pWinPos->flags & SWP_NOZORDER)) { if (pRLWinPriv->fRestackingNow || pScreenPriv->fRestacking) { #if CYGMULTIWINDOW_DEBUG winDebug ("Win %08x is now restacking.\n", (unsigned int)pRLWinPriv); #endif break; } if (winIsInternalWMRunning(pScreenInfo) || IsRaiseOnClick (pWin)) { #if CYGMULTIWINDOW_DEBUG winDebug ("Win %08x has WINDOWSWM_RAISE_ON_CLICK.\n", (unsigned int)pRLWinPriv); #endif break; } #if CYGMULTIWINDOW_DEBUG winDebug ("Win %08x forbid to change z order (%08x).\n", (unsigned int)pRLWinPriv, (unsigned int)pWinPos->hwndInsertAfter); #endif pWinPos->flags |= SWP_NOZORDER; } break; #endif case WM_MOVE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_MOVE - %d ms\n", (unsigned int)GetTickCount ()); #endif if (g_fNoConfigureWindow) break; #if 0 /* Bail if Windows window is not actually moving */ if (pRLWinPriv->dwX == (short) LOWORD(lParam) && pRLWinPriv->dwY == (short) HIWORD(lParam)) break; /* Also bail if we're maximizing, we'll do the whole thing in WM_SIZE */ { WINDOWPLACEMENT windPlace; windPlace.length = sizeof (WINDOWPLACEMENT); /* Get current window placement */ GetWindowPlacement (hwnd, &windPlace); /* Bail if maximizing */ if (windPlace.showCmd == SW_MAXIMIZE || windPlace.showCmd == SW_SHOWMAXIMIZED) break; } #endif #if CYGMULTIWINDOW_DEBUG winDebug ("\t(%d, %d)\n", (short) LOWORD(lParam), (short) HIWORD(lParam)); #endif if (!pRLWinPriv->fMovingOrSizing) { if (winIsInternalWMRunning(pScreenInfo)) winAdjustXWindow (pWin, hwnd); winMWExtWMMoveXWindow (pWin, (LOWORD(lParam) - wBorderWidth (pWin) - GetSystemMetrics (SM_XVIRTUALSCREEN)), (HIWORD(lParam) - wBorderWidth (pWin) - GetSystemMetrics (SM_YVIRTUALSCREEN))); } return 0; case WM_SHOWWINDOW: #if CYGMULTIWINDOW_DEBUG || TRUE winDebug ("winMWExtWMWindowProc - WM_SHOWWINDOW - %d ms\n", (unsigned int)GetTickCount ()); #endif /* Bail out if the window is being hidden */ if (!wParam) return 0; if (!pScreenInfo->fInternalWM)//XXXX return 0; winMWExtWMUpdateWindowDecoration (pRLWinPriv, pScreenInfo); if (winIsInternalWMRunning(pScreenInfo)) { #if CYGMULTIWINDOW_DEBUG || TRUE winDebug ("\tMapWindow\n"); #endif /* Tell X to map the window */ MapWindow (pWin, wClient(pWin)); if (!pRLWinPriv->pFrame->win->overrideRedirect) /* Bring the Windows window to the foreground */ SetForegroundWindow (hwnd); /* Setup the Window Manager message */ wmMsg.msg = WM_WM_MAP; wmMsg.iWidth = pRLWinPriv->pFrame->width; wmMsg.iHeight = pRLWinPriv->pFrame->height; /* Tell our Window Manager thread to map the window */ if (fWMMsgInitialized) winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); } break; case WM_SIZING: /* Need to legalize the size according to WM_NORMAL_HINTS */ /* for applications like xterm */ return ValidateSizing (hwnd, pWin, wParam, lParam); case WM_WINDOWPOSCHANGED: { pWinPos = (LPWINDOWPOS) lParam; #if CYGMULTIWINDOW_DEBUG winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n"); winDebug("\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n", (pWinPos->flags & SWP_DRAWFRAME)?"SWP_DRAWFRAME ":"", (pWinPos->flags & SWP_FRAMECHANGED)?"SWP_FRAMECHANGED ":"", (pWinPos->flags & SWP_HIDEWINDOW)?"SWP_HIDEWINDOW ":"", (pWinPos->flags & SWP_NOACTIVATE)?"SWP_NOACTIVATE ":"", (pWinPos->flags & SWP_NOCOPYBITS)?"SWP_NOCOPYBITS ":"", (pWinPos->flags & SWP_NOMOVE)?"SWP_NOMOVE ":"", (pWinPos->flags & SWP_NOOWNERZORDER)?"SWP_NOOWNERZORDER ":"", (pWinPos->flags & SWP_NOSIZE)?"SWP_NOSIZE ":"", (pWinPos->flags & SWP_NOREDRAW)?"SWP_NOREDRAW ":"", (pWinPos->flags & SWP_NOSENDCHANGING)?"SWP_NOSENDCHANGING ":"", (pWinPos->flags & SWP_NOZORDER)?"SWP_NOZORDER ":"", (pWinPos->flags & SWP_SHOWWINDOW)?"SWP_SHOWWINDOW ":""); winDebug("\tno_configure: %s\n", (g_fNoConfigureWindow?"Yes":"No")); winDebug("\textend: (%d, %d, %d, %d)\n", pWinPos->x, pWinPos->y, pWinPos->cx, pWinPos->cy); #endif if (pWinPos->flags & SWP_HIDEWINDOW) break; /* Reorder if window z order was changed */ if ((pScreenPriv != NULL) && !(pWinPos->flags & SWP_NOZORDER) && !(pWinPos->flags & SWP_SHOWWINDOW) && winIsInternalWMRunning(pScreenInfo)) { #if CYGMULTIWINDOW_DEBUG winDebug ("\twindow z order was changed\n"); #endif if (pWinPos->hwndInsertAfter == HWND_TOP ||pWinPos->hwndInsertAfter == HWND_TOPMOST ||pWinPos->hwndInsertAfter == HWND_NOTOPMOST) { #if CYGMULTIWINDOW_DEBUG winDebug ("\traise to top\n"); #endif /* Raise the window to the top in Z order */ wmMsg.msg = WM_WM_RAISE; if (fWMMsgInitialized) winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); } #if 1 else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) { } else { /* Check if this window is top of X windows. */ HWND hWndAbove = NULL; DWORD dwCurrentProcessID = GetCurrentProcessId (); DWORD dwWindowProcessID = 0; for (hWndAbove = pWinPos->hwndInsertAfter; hWndAbove != NULL; hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV)) { /* Ignore other XWin process's window */ GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID); if ((dwWindowProcessID == dwCurrentProcessID) && GetProp (hWndAbove, WIN_WINDOW_PROP) && !IsWindowVisible (hWndAbove) && !IsIconic (hWndAbove) ) /* ignore minimized windows */ break; } /* If this is top of X windows in Windows stack, raise it in X stack. */ if (hWndAbove == NULL) { #if CYGMULTIWINDOW_DEBUG winDebug ("\traise to top\n"); #endif /* Raise the window to the top in Z order */ wmMsg.msg = WM_WM_RAISE; if (fWMMsgInitialized) winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); } } #endif } if (!(pWinPos->flags & SWP_NOSIZE)) { if (IsIconic(hwnd)){ #if CYGMULTIWINDOW_DEBUG winDebug ("\tIconic -> MINIMIZED\n"); #endif if (winIsInternalWMRunning(pScreenInfo)) { /* Raise the window to the top in Z order */ wmMsg.msg = WM_WM_LOWER; if (fWMMsgInitialized) winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); } winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMMinimizeWindow, pWin->drawable.id, 0, 0, 0, 0); } else if (IsZoomed(hwnd)){ #if CYGMULTIWINDOW_DEBUG winDebug ("\tZoomed -> MAXIMIZED\n"); #endif winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMMaximizeWindow, pWin->drawable.id, 0, 0, 0, 0); } else { #if CYGMULTIWINDOW_DEBUG winDebug ("\tnone -> RESTORED\n"); #endif winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMRestoreWindow, pWin->drawable.id, 0, 0, 0, 0); } } if (!g_fNoConfigureWindow ) { if (!pRLWinPriv->fMovingOrSizing /*&& (pWinPos->flags & SWP_SHOWWINDOW)*/) { GetClientRect (hwnd, &rcClient); MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2); if (!(pWinPos->flags & SWP_NOMOVE) &&!(pWinPos->flags & SWP_NOSIZE)) { #if CYGMULTIWINDOW_DEBUG winDebug ("\tmove & resize\n"); #endif if (winIsInternalWMRunning(pScreenInfo)) winAdjustXWindow (pWin, hwnd); winMWExtWMMoveResizeXWindow (pWin, rcClient.left - wBorderWidth (pWin) - GetSystemMetrics (SM_XVIRTUALSCREEN), rcClient.top - wBorderWidth (pWin) - GetSystemMetrics (SM_YVIRTUALSCREEN), rcClient.right - rcClient.left - wBorderWidth (pWin)*2, rcClient.bottom - rcClient.top - wBorderWidth (pWin)*2); } else if (!(pWinPos->flags & SWP_NOMOVE)) { #if CYGMULTIWINDOW_DEBUG winDebug ("\tmove\n"); #endif if (winIsInternalWMRunning(pScreenInfo)) winAdjustXWindow (pWin, hwnd); winMWExtWMMoveResizeXWindow (pWin, rcClient.left - wBorderWidth (pWin) - GetSystemMetrics (SM_XVIRTUALSCREEN), rcClient.top - wBorderWidth (pWin) - GetSystemMetrics (SM_YVIRTUALSCREEN), rcClient.right - rcClient.left - wBorderWidth (pWin)*2, rcClient.bottom - rcClient.top - wBorderWidth (pWin)*2); } else if (!(pWinPos->flags & SWP_NOMOVE)) { #if CYGMULTIWINDOW_DEBUG winDebug ("\tmove\n"); #endif if (winIsInternalWMRunning(pScreenInfo)) winAdjustXWindow (pWin, hwnd); winMWExtWMMoveXWindow (pWin, rcClient.left - wBorderWidth (pWin) - GetSystemMetrics (SM_XVIRTUALSCREEN), rcClient.top - wBorderWidth (pWin) - GetSystemMetrics (SM_YVIRTUALSCREEN)); } else if (!(pWinPos->flags & SWP_NOSIZE)) { #if CYGMULTIWINDOW_DEBUG winDebug ("\tresize\n"); #endif if (winIsInternalWMRunning(pScreenInfo)) winAdjustXWindow (pWin, hwnd); winMWExtWMResizeXWindow (pWin, rcClient.right - rcClient.left - wBorderWidth (pWin)*2, rcClient.bottom - rcClient.top - wBorderWidth (pWin)*2); } } } } #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED - done.\n"); #endif return 0; case WM_SIZE: /* see dix/window.c */ /* FIXME: Maximize/Restore? */ #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_SIZE - %d ms\n", (unsigned int)GetTickCount ()); #endif #if CYGMULTIWINDOW_DEBUG winDebug ("\t(%d, %d) %d\n", (short) LOWORD(lParam), (short) HIWORD(lParam), g_fNoConfigureWindow); #endif if (g_fNoConfigureWindow) break; /* Branch on type of resizing occurring */ switch (wParam) { case SIZE_MINIMIZED: #if CYGMULTIWINDOW_DEBUG winDebug ("\tSIZE_MINIMIZED\n"); #endif if (winIsInternalWMRunning(pScreenInfo)) { /* Raise the window to the top in Z order */ wmMsg.msg = WM_WM_LOWER; if (fWMMsgInitialized) winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg); } winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMMinimizeWindow, pWin->drawable.id, 0, 0, LOWORD(lParam), HIWORD(lParam)); break; case SIZE_RESTORED: #if CYGMULTIWINDOW_DEBUG winDebug ("\tSIZE_RESTORED\n"); #endif winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMRestoreWindow, pWin->drawable.id, 0, 0, LOWORD(lParam), HIWORD(lParam)); break; case SIZE_MAXIMIZED: #if CYGMULTIWINDOW_DEBUG winDebug ("\tSIZE_MAXIMIZED\n"); #endif winWindowsWMSendEvent(WindowsWMControllerNotify, WindowsWMControllerNotifyMask, 1, WindowsWMMaximizeWindow, pWin->drawable.id, 0, 0, LOWORD(lParam), HIWORD(lParam)); break; } /* Perform the resize and notify the X client */ if (!pRLWinPriv->fMovingOrSizing) { if (winIsInternalWMRunning(pScreenInfo)) winAdjustXWindow (pWin, hwnd); winMWExtWMResizeXWindow (pWin, (short) LOWORD(lParam) - wBorderWidth (pWin)*2, (short) HIWORD(lParam) - wBorderWidth (pWin)*2); } break; case WM_ACTIVATEAPP: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_ACTIVATEAPP - %d ms\n", (unsigned int)GetTickCount ()); #endif if (wParam) { if (winIsInternalWMRunning(pScreenInfo)) { } else { } winWindowsWMSendEvent(WindowsWMActivationNotify, WindowsWMActivationNotifyMask, 1, WindowsWMIsActive, pWin->drawable.id, 0, 0, 0, 0); } else { winWindowsWMSendEvent(WindowsWMActivationNotify, WindowsWMActivationNotifyMask, 1, WindowsWMIsInactive, pWin->drawable.id, 0, 0, 0, 0); } break; case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT) { if (!g_fSoftwareCursor) SetCursor (pScreenPriv->cursor.handle); return TRUE; } break; case WM_ENTERSIZEMOVE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_ENTERSIZEMOVE - %d ms\n", (unsigned int)GetTickCount ()); #endif pRLWinPriv->fMovingOrSizing = TRUE; break; case WM_EXITSIZEMOVE: #if CYGMULTIWINDOW_DEBUG winDebug ("winMWExtWMWindowProc - WM_EXITSIZEMOVE - %d ms\n", (unsigned int)GetTickCount ()); #endif pRLWinPriv->fMovingOrSizing = FALSE; GetClientRect (hwnd, &rcClient); MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2); if (winIsInternalWMRunning(pScreenInfo)) winAdjustXWindow (pWin, hwnd); winMWExtWMMoveResizeXWindow (pWin, rcClient.left - wBorderWidth (pWin) - GetSystemMetrics (SM_XVIRTUALSCREEN), rcClient.top - wBorderWidth (pWin) - GetSystemMetrics (SM_YVIRTUALSCREEN), rcClient.right - rcClient.left - wBorderWidth (pWin)*2, rcClient.bottom - rcClient.top - wBorderWidth (pWin)*2); break; case WM_MANAGE: ErrorF ("winMWExtWMWindowProc - WM_MANAGE\n"); break; case WM_UNMANAGE: ErrorF ("winMWExtWMWindowProc - WM_UNMANAGE\n"); break; default: break; } return DefWindowProc (hwnd, message, wParam, lParam); }
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); }