2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *Copyright (C) Colin Harrison 2005-2008
5 *Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 *"Software"), to deal in the Software without restriction, including
8 *without limitation the rights to use, copy, modify, merge, publish,
9 *distribute, sublicense, and/or sell copies of the Software, and to
10 *permit persons to whom the Software is furnished to do so, subject to
11 *the following conditions:
13 *The above copyright notice and this permission notice shall be
14 *included in all copies or substantial portions of the Software.
16 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *Except as contained in this notice, the name of the XFree86 Project
25 *shall not be used in advertising or otherwise to promote the sale, use
26 *or other dealings in this Software without prior written authorization
27 *from the XFree86 Project.
29 * Authors: Kensuke Matsuzaki
30 * Earle F. Philhower, III
35 #ifdef HAVE_XWIN_CONFIG_H
36 #include <xwin-config.h>
39 #include "dixevents.h"
40 #include "winmultiwindowclass.h"
45 extern void winUpdateWindowPosition(HWND hWnd, Bool reshape, HWND * zstyle);
51 static UINT_PTR g_uipMousePollingTimerID = 0;
57 #define WIN_MULTIWINDOW_SHAPE YES
60 * ConstrainSize - Taken from TWM sources - Respects hints for sizing
62 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
64 ConstrainSize(WinXSizeHints hints, int *widthp, int *heightp)
66 int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
67 int baseWidth, baseHeight;
68 int dwidth = *widthp, dheight = *heightp;
70 if (hints.flags & PMinSize) {
71 minWidth = hints.min_width;
72 minHeight = hints.min_height;
74 else if (hints.flags & PBaseSize) {
75 minWidth = hints.base_width;
76 minHeight = hints.base_height;
79 minWidth = minHeight = 1;
81 if (hints.flags & PBaseSize) {
82 baseWidth = hints.base_width;
83 baseHeight = hints.base_height;
85 else if (hints.flags & PMinSize) {
86 baseWidth = hints.min_width;
87 baseHeight = hints.min_height;
90 baseWidth = baseHeight = 0;
92 if (hints.flags & PMaxSize) {
93 maxWidth = hints.max_width;
94 maxHeight = hints.max_height;
101 if (hints.flags & PResizeInc) {
102 xinc = hints.width_inc;
103 yinc = hints.height_inc;
109 * First, clamp to min and max values
111 if (dwidth < minWidth)
113 if (dheight < minHeight)
116 if (dwidth > maxWidth)
118 if (dheight > maxHeight)
122 * Second, fit to base + N * inc
124 dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
125 dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
128 * Third, adjust for aspect ratio
132 * The math looks like this:
134 * minAspectX dwidth maxAspectX
135 * ---------- <= ------- <= ----------
136 * minAspectY dheight maxAspectY
138 * If that is multiplied out, then the width and height are
139 * invalid in the following situations:
141 * minAspectX * dheight > minAspectY * dwidth
142 * maxAspectX * dheight < maxAspectY * dwidth
146 if (hints.flags & PAspect) {
147 if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth) {
149 makemult(hints.min_aspect.x * dheight / hints.min_aspect.y -
151 if (dwidth + delta <= maxWidth)
156 dwidth * hints.min_aspect.y / hints.min_aspect.x,
158 if (dheight - delta >= minHeight)
163 if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth) {
165 makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x -
167 if (dheight + delta <= maxHeight)
172 hints.max_aspect.x * dheight / hints.max_aspect.y,
174 if (dwidth - delta >= minWidth)
180 /* Return computed values */
188 * ValidateSizing - Ensures size request respects hints
191 ValidateSizing(HWND hwnd, WindowPtr pWin, WPARAM wParam, LPARAM lParam)
193 WinXSizeHints sizeHints;
196 RECT rcClient, rcWindow;
197 int iBorderWidthX, iBorderWidthY;
199 /* Invalid input checking */
200 if (pWin == NULL || lParam == 0)
203 /* No size hints, no checking */
204 if (!winMultiWindowGetWMNormalHints(pWin, &sizeHints))
207 /* Avoid divide-by-zero */
208 if (sizeHints.flags & PResizeInc) {
209 if (sizeHints.width_inc == 0)
210 sizeHints.width_inc = 1;
211 if (sizeHints.height_inc == 0)
212 sizeHints.height_inc = 1;
215 rect = (RECT *) lParam;
217 iWidth = rect->right - rect->left;
218 iHeight = rect->bottom - rect->top;
220 /* Now remove size of any borders and title bar */
221 GetClientRect(hwnd, &rcClient);
222 GetWindowRect(hwnd, &rcWindow);
224 (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
226 (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
227 iWidth -= iBorderWidthX;
228 iHeight -= iBorderWidthY;
230 /* Constrain the size to legal values */
231 ConstrainSize(sizeHints, &iWidth, &iHeight);
233 /* Add back the size of borders and title bar */
234 iWidth += iBorderWidthX;
235 iHeight += iBorderWidthY;
237 /* Adjust size according to where we're dragging from */
242 case WMSZ_BOTTOMRIGHT:
244 rect->right = rect->left + iWidth;
247 rect->left = rect->right - iWidth;
252 case WMSZ_BOTTOMRIGHT:
253 case WMSZ_BOTTOMLEFT:
256 rect->bottom = rect->top + iHeight;
259 rect->top = rect->bottom - iHeight;
265 extern Bool winInDestroyWindowsWindow;
266 static Bool winInRaiseWindow = FALSE;
268 winRaiseWindow(WindowPtr pWin)
270 if (!winInDestroyWindowsWindow && !winInRaiseWindow) {
271 BOOL oldstate = winInRaiseWindow;
272 XID vlist[1] = { 0 };
273 winInRaiseWindow = TRUE;
274 /* Call configure window directly to make sure it gets processed
277 ConfigureWindow(pWin, CWStackMode, vlist, serverClient);
278 winInRaiseWindow = oldstate;
284 winStartMousePolling(winPrivScreenPtr s_pScreenPriv)
287 * Timer to poll mouse position. This is needed to make
288 * programs like xeyes follow the mouse properly when the
289 * mouse pointer is outside of any X window.
291 if (g_uipMousePollingTimerID == 0)
292 g_uipMousePollingTimerID = SetTimer(s_pScreenPriv->hwndScreen,
293 WIN_POLLING_MOUSE_TIMER_ID,
294 MOUSE_POLLING_INTERVAL, NULL);
298 * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
302 winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
307 WindowPtr pWin = NULL;
308 winPrivWinPtr pWinPriv = NULL;
309 ScreenPtr s_pScreen = NULL;
310 winPrivScreenPtr s_pScreenPriv = NULL;
311 winScreenInfo *s_pScreenInfo = NULL;
312 HWND hwndScreen = NULL;
313 DrawablePtr pDraw = NULL;
314 winWMMessageRec wmMsg;
315 Bool fWMMsgInitialized = FALSE;
316 static Bool s_fTracking = FALSE;
317 Bool needRestack = FALSE;
321 winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam,
325 /* Check if the Windows window property for our X window pointer is valid */
326 if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) {
327 /* Our X window pointer is valid */
329 /* Get pointers to the drawable and the screen */
330 pDraw = &pWin->drawable;
331 s_pScreen = pWin->drawable.pScreen;
333 /* Get a pointer to our window privates */
334 pWinPriv = winGetWindowPriv(pWin);
336 /* Get pointers to our screen privates and screen info */
337 s_pScreenPriv = pWinPriv->pScreenPriv;
338 s_pScreenInfo = s_pScreenPriv->pScreenInfo;
340 /* Get the handle for our screen-sized window */
341 hwndScreen = s_pScreenPriv->hwndScreen;
345 wmMsg.hwndWindow = hwnd;
346 wmMsg.iWindow = (Window) GetProp(hwnd, WIN_WID_PROP);
350 wmMsg.iWidth = pDraw->width;
351 wmMsg.iHeight = pDraw->height;
353 fWMMsgInitialized = TRUE;
357 * Print some debugging information
360 ErrorF("hWnd %08X\n", hwnd);
361 ErrorF("pWin %08X\n", pWin);
362 ErrorF("pDraw %08X\n", pDraw);
363 ErrorF("\ttype %08X\n", pWin->drawable.type);
364 ErrorF("\tclass %08X\n", pWin->drawable.class);
365 ErrorF("\tdepth %08X\n", pWin->drawable.depth);
366 ErrorF("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
367 ErrorF("\tid %08X\n", pWin->drawable.id);
368 ErrorF("\tx %08X\n", pWin->drawable.x);
369 ErrorF("\ty %08X\n", pWin->drawable.y);
370 ErrorF("\twidth %08X\n", pWin->drawable.width);
371 ErrorF("\thenght %08X\n", pWin->drawable.height);
372 ErrorF("\tpScreen %08X\n", pWin->drawable.pScreen);
373 ErrorF("\tserialNumber %08X\n", pWin->drawable.serialNumber);
374 ErrorF("g_iWindowPrivateKey %p\n", g_iWindowPrivateKey);
375 ErrorF("pWinPriv %08X\n", pWinPriv);
376 ErrorF("s_pScreenPriv %08X\n", s_pScreenPriv);
377 ErrorF("s_pScreenInfo %08X\n", s_pScreenInfo);
378 ErrorF("hwndScreen %08X\n", hwndScreen);
382 /* Branch on message type */
389 (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams);
394 (HANDLE) winGetWindowID(((LPCREATESTRUCT) lParam)->
398 * Make X windows' Z orders sync with Windows windows because
399 * there can be AlwaysOnTop windows overlapped on the window
400 * currently being created.
402 winReorderWindowsMultiWindow();
404 /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
409 GetWindowRect(hwnd, &rWindow);
410 hRgnWindow = CreateRectRgnIndirect(&rWindow);
411 SetWindowRgn(hwnd, hRgnWindow, TRUE);
412 DeleteObject(hRgnWindow);
415 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) XMING_SIGNATURE);
419 case WM_INIT_SYS_MENU:
421 * Add whatever the setup file wants to for this window
423 SetupSysMenu((unsigned long) hwnd);
428 * Any window menu items go through here
430 if (HandleCustomWM_COMMAND((unsigned long) hwnd, LOWORD(wParam))) {
431 /* Don't pass customized menus to DefWindowProc */
434 if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE) {
435 WINDOWPLACEMENT wndpl;
437 wndpl.length = sizeof(wndpl);
438 if (GetWindowPlacement(hwnd, &wndpl) &&
439 wndpl.showCmd == SW_SHOWMINIMIZED)
445 /* Checks/Unchecks any menu items before they are displayed */
446 HandleCustomWM_INITMENU((unsigned long) hwnd, wParam);
451 * Pretend that we did erase the background but we don't care,
452 * since we repaint the entire region anyhow
453 * This avoids some flickering when resizing.
458 /* Only paint if our window handle is valid */
459 if (hwndScreen == NULL)
462 /* BeginPaint gives us an hdc that clips to the invalidated region */
463 hdcUpdate = BeginPaint(hwnd, &ps);
464 /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
465 if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
466 ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
471 #ifdef XWIN_GLX_WINDOWS
472 if (pWinPriv->fWglUsed) {
474 For regions which are being drawn by GL, the shadow framebuffer doesn't have the
475 correct bits, so don't bitblt from the shadow framebuffer
477 XXX: For now, just leave it alone, but ideally we want to send an expose event to
478 the window so it really redraws the affected region...
480 ValidateRect(hwnd, &(ps.rcPaint));
484 /* Try to copy from the shadow buffer */
485 if (!BitBlt(hdcUpdate,
486 ps.rcPaint.left, ps.rcPaint.top,
487 ps.rcPaint.right - ps.rcPaint.left,
488 ps.rcPaint.bottom - ps.rcPaint.top,
489 s_pScreenPriv->hdcShadow,
490 ps.rcPaint.left + pWin->drawable.x,
491 ps.rcPaint.top + pWin->drawable.y, SRCCOPY)) {
494 /* Display a fancy error message */
495 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
496 FORMAT_MESSAGE_FROM_SYSTEM |
497 FORMAT_MESSAGE_IGNORE_INSERTS,
500 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
501 (LPTSTR) & lpMsgBuf, 0, NULL);
503 ErrorF("winTopLevelWindowProc - BitBlt failed: %s\n",
508 /* EndPaint frees the DC */
513 /* Unpack the client area mouse coordinates */
514 ptMouse.x = GET_X_LPARAM(lParam);
515 ptMouse.y = GET_Y_LPARAM(lParam);
517 /* Translate the client area mouse coordinates to screen coordinates */
518 ClientToScreen(hwnd, &ptMouse);
520 /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
521 ptMouse.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
522 ptMouse.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
524 /* We can't do anything without privates */
525 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
528 /* Has the mouse pointer crossed screens? */
529 if (s_pScreen != miPointerGetScreen(g_pwinPointer))
530 miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen,
531 ptMouse.x - s_pScreenInfo->dwXOffset,
532 ptMouse.y - s_pScreenInfo->dwYOffset);
534 /* Are we tracking yet? */
538 /* Setup data structure */
539 ZeroMemory(&tme, sizeof(tme));
540 tme.cbSize = sizeof(tme);
541 tme.dwFlags = TME_LEAVE;
542 tme.hwndTrack = hwnd;
544 /* Call the tracking function */
545 if (!TrackMouseEvent(&tme))
546 ErrorF("winTopLevelWindowProc - TrackMouseEvent failed\n");
548 /* Flag that we are tracking now */
552 /* Hide or show the Windows mouse cursor */
553 if (g_fSoftwareCursor && g_fCursor) {
554 /* Hide Windows cursor */
559 /* Kill the timer used to poll mouse events */
560 if (g_uipMousePollingTimerID != 0) {
561 KillTimer(s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
562 g_uipMousePollingTimerID = 0;
565 /* Deliver absolute cursor position to X Server */
566 winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset,
567 ptMouse.y - s_pScreenInfo->dwYOffset);
573 * We break instead of returning 0 since we need to call
574 * DefWindowProc to get the mouse cursor changes
575 * and min/max/close button highlighting in Windows XP.
576 * The Platform SDK says that you should return 0 if you
577 * process this message, but it fails to mention that you
578 * will give up any default functionality if you do return 0.
581 /* We can't do anything without privates */
582 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
585 /* Non-client mouse movement, show Windows cursor */
586 if (g_fSoftwareCursor && !g_fCursor) {
591 winStartMousePolling(s_pScreenPriv);
596 /* Mouse has left our client area */
598 /* Flag that we are no longer tracking */
601 /* Show the mouse cursor, if necessary */
602 if (g_fSoftwareCursor && !g_fCursor) {
607 winStartMousePolling(s_pScreenPriv);
611 case WM_LBUTTONDBLCLK:
613 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
617 return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam);
620 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
622 g_fButton[0] = FALSE;
624 winStartMousePolling(s_pScreenPriv);
625 return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam);
627 case WM_MBUTTONDBLCLK:
629 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
633 return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam);
636 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
638 g_fButton[1] = FALSE;
640 winStartMousePolling(s_pScreenPriv);
641 return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam);
643 case WM_RBUTTONDBLCLK:
645 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
649 return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam);
652 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
654 g_fButton[2] = FALSE;
656 winStartMousePolling(s_pScreenPriv);
657 return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam);
659 case WM_XBUTTONDBLCLK:
661 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
664 return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 5,
668 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
671 winStartMousePolling(s_pScreenPriv);
672 return winMouseButtonsHandle(s_pScreen, ButtonRelease,
673 HIWORD(wParam) + 5, wParam);
677 (hwnd, WM_NCHITTEST, 0,
678 MAKELONG(GET_X_LPARAM(lParam),
679 GET_Y_LPARAM(lParam))) == HTCLIENT) {
680 /* Pass the message to the root window */
681 SendMessage(hwndScreen, message, wParam, lParam);
688 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
692 /* Get the parent window for transient handling */
693 HWND hParent = GetParent(hwnd);
695 if (hParent && IsIconic(hParent))
696 ShowWindow(hParent, SW_RESTORE);
699 winRestoreModeKeyStates();
701 /* Add the keyboard hook if possible */
702 if (g_fKeyboardHookLL)
703 g_fKeyboardHookLL = winInstallKeyboardHookLL();
707 /* Pop any pressed keys since we are losing keyboard focus */
708 winKeybdReleaseKeys();
710 /* Remove our keyboard hook if it is installed */
711 winRemoveKeyboardHookLL();
713 /* Revert the X focus as well, but only if the Windows focus is going to another window */
715 DeleteWindowFromAnyEvents(pWin, FALSE);
722 * NOTE: We do nothing with WM_*CHAR messages,
723 * nor does the root window, so we can just toss these messages.
731 * Don't pass Alt-F4 key combo to root window,
732 * let Windows translate to WM_CLOSE and close this top-level window.
734 * NOTE: We purposely don't check the fUseWinKillKey setting because
735 * it should only apply to the key handling for the root window,
736 * not for top-level window-manager windows.
738 * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
739 * because that is a key combo that no X app should be expecting to
740 * receive, since it has historically been used to shutdown the X server.
741 * Passing Ctrl-Alt-Backspace to the root window preserves that
742 * behavior, assuming that -unixkill has been passed as a parameter.
744 if (wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000))
747 #if CYGWINDOWING_DEBUG
748 if (wParam == VK_ESCAPE) {
749 /* Place for debug: put any tests and dumps here */
750 WINDOWPLACEMENT windPlace;
754 windPlace.length = sizeof(WINDOWPLACEMENT);
755 GetWindowPlacement(hwnd, &windPlace);
756 pRect = &windPlace.rcNormalPosition;
757 ErrorF("\nCYGWINDOWING Dump:\n"
758 "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
759 pDraw->y, pDraw->width, pDraw->height);
760 ErrorF("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left,
761 pRect->top, pRect->right - pRect->left,
762 pRect->bottom - pRect->top);
763 if (GetClientRect(hwnd, &rc)) {
765 ErrorF("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
766 pRect->top, pRect->right - pRect->left,
767 pRect->bottom - pRect->top);
769 if (GetWindowRect(hwnd, &rc)) {
771 ErrorF("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
772 pRect->top, pRect->right - pRect->left,
773 pRect->bottom - pRect->top);
779 /* Pass the message to the root window */
780 return winWindowProc(hwndScreen, message, wParam, lParam);
785 /* Pass the message to the root window */
786 return winWindowProc(hwndScreen, message, wParam, lParam);
790 /* Pass the message to the root window */
791 SendMessage(hwndScreen, message, wParam, lParam);
796 /* Pass the message to the root window */
797 SendMessage(hwndScreen, message, wParam, lParam);
799 if (LOWORD(wParam) != WA_INACTIVE) {
800 /* Raise the window to the top in Z order */
801 /* ago: Activate does not mean putting it to front! */
803 wmMsg.msg = WM_WM_RAISE;
804 if (fWMMsgInitialized)
805 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
808 /* Tell our Window Manager thread to activate the window */
809 wmMsg.msg = WM_WM_ACTIVATE;
810 if (fWMMsgInitialized)
811 if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
812 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
814 /* Prevent the mouse wheel from stalling when another window is minimized */
815 if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE &&
816 (HWND) lParam != NULL && (HWND) lParam != (HWND) GetParent(hwnd))
822 * This message is also sent to the root window
823 * so we do nothing for individual multiwindow windows
828 /* Branch on if the window was killed in X already */
829 if (pWinPriv->fXKilled) {
830 /* Window was killed, go ahead and destroy the window */
834 /* Tell our Window Manager thread to kill the window */
835 wmMsg.msg = WM_WM_KILL;
836 if (fWMMsgInitialized)
837 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
843 /* Branch on if the window was killed in X already */
844 if (pWinPriv && !pWinPriv->fXKilled) {
845 ErrorF("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
847 /* Tell our Window Manager thread to kill the window */
848 wmMsg.msg = WM_WM_KILL;
849 if (fWMMsgInitialized)
850 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
853 RemoveProp(hwnd, WIN_WINDOW_PROP);
854 RemoveProp(hwnd, WIN_WID_PROP);
855 RemoveProp(hwnd, WIN_NEEDMANAGE_PROP);
860 /* Adjust the X Window to the moved Windows window */
861 winAdjustXWindow(pWin, hwnd);
865 /* Bail out if the window is being hidden */
870 if (!pWin->overrideRedirect) {
871 /* Flag that this window needs to be made active when clicked */
872 SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
874 if (!(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_APPWINDOW)) {
875 HWND zstyle = HWND_NOTOPMOST;
877 /* Set the window extended style flags */
878 SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
880 /* Set the transient style flags */
882 SetWindowLongPtr(hwnd, GWL_STYLE,
883 WS_POPUP | WS_OVERLAPPED | WS_SYSMENU |
884 WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
885 /* Set the window standard style flags */
887 SetWindowLongPtr(hwnd, GWL_STYLE,
888 (WS_POPUP | WS_OVERLAPPEDWINDOW |
889 WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
890 & ~WS_CAPTION & ~WS_SIZEBOX);
892 winUpdateWindowPosition(hwnd, FALSE, &zstyle);
897 if (winMultiWindowGetWMHints(pWin, &hints)) {
899 Give the window focus, unless it has an InputHint
900 which is FALSE (this is used by e.g. glean to
901 avoid every test window grabbing the focus)
903 if (!((hints.flags & InputHint) && (!hints.input))) {
904 SetForegroundWindow(hwnd);
909 wmMsg.msg = WM_WM_MAP3;
911 else { /* It is an overridden window so make it top of Z stack */
913 HWND forHwnd = GetForegroundWindow();
915 #if CYGWINDOWING_DEBUG
916 ErrorF("overridden window is shown\n");
918 if (forHwnd != NULL) {
919 if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)
921 if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
922 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
923 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
925 SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
926 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
929 wmMsg.msg = WM_WM_MAP2;
932 /* Tell our Window Manager thread to map the window */
933 if (fWMMsgInitialized)
934 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
936 winStartMousePolling(s_pScreenPriv);
941 /* Need to legalize the size according to WM_NORMAL_HINTS */
942 /* for applications like xterm */
943 return ValidateSizing(hwnd, pWin, wParam, lParam);
945 case WM_WINDOWPOSCHANGED:
947 LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
949 if (!(pWinPos->flags & SWP_NOZORDER)) {
950 #if CYGWINDOWING_DEBUG
951 winDebug("\twindow z order was changed\n");
953 if (pWinPos->hwndInsertAfter == HWND_TOP
954 || pWinPos->hwndInsertAfter == HWND_TOPMOST
955 || pWinPos->hwndInsertAfter == HWND_NOTOPMOST) {
956 #if CYGWINDOWING_DEBUG
957 winDebug("\traise to top\n");
959 /* Raise the window to the top in Z order */
960 winRaiseWindow(pWin);
962 else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) {
965 /* Check if this window is top of X windows. */
966 HWND hWndAbove = NULL;
967 DWORD dwCurrentProcessID = GetCurrentProcessId();
968 DWORD dwWindowProcessID = 0;
970 for (hWndAbove = pWinPos->hwndInsertAfter;
972 hWndAbove = GetNextWindow(hWndAbove, GW_HWNDPREV)) {
973 /* Ignore other XWin process's window */
974 GetWindowThreadProcessId(hWndAbove, &dwWindowProcessID);
976 if ((dwWindowProcessID == dwCurrentProcessID)
977 && GetProp(hWndAbove, WIN_WINDOW_PROP)
978 && !IsWindowVisible(hWndAbove)
979 && !IsIconic(hWndAbove)) /* ignore minimized windows */
982 /* If this is top of X windows in Windows stack,
983 raise it in X stack. */
984 if (hWndAbove == NULL) {
985 #if CYGWINDOWING_DEBUG
986 winDebug("\traise to top\n");
988 winRaiseWindow(pWin);
994 * Pass the message to DefWindowProc to let the function
995 * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
1000 /* see dix/window.c */
1001 #if CYGWINDOWING_DEBUG
1006 case SIZE_MINIMIZED:
1007 strcpy(buf, "SIZE_MINIMIZED");
1009 case SIZE_MAXIMIZED:
1010 strcpy(buf, "SIZE_MAXIMIZED");
1013 strcpy(buf, "SIZE_RESTORED");
1016 strcpy(buf, "UNKNOWN_FLAG");
1018 ErrorF("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n",
1019 (int) LOWORD(lParam), (int) HIWORD(lParam), buf,
1020 (int) (GetTickCount()));
1023 /* Adjust the X Window to the moved Windows window */
1024 winAdjustXWindow(pWin, hwnd);
1025 return 0; /* end of WM_SIZE handler */
1027 case WM_STYLECHANGING:
1029 When the style changes, adjust the Windows window size so the client area remains the same size,
1030 and adjust the Windows window position so that the client area remains in the same place.
1036 DWORD newStyle = ((STYLESTRUCT *) lParam)->styleNew;
1039 dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
1040 dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
1042 winDebug("winTopLevelWindowProc - WM_STYLECHANGING from %08x %08x\n",
1043 dwStyle, dwExStyle);
1045 if (wParam == GWL_EXSTYLE)
1046 dwExStyle = newStyle;
1048 if (wParam == GWL_STYLE)
1051 winDebug("winTopLevelWindowProc - WM_STYLECHANGING to %08x %08x\n",
1052 dwStyle, dwExStyle);
1054 /* Get client rect in screen coordinates */
1055 wi.cbSize = sizeof(WINDOWINFO);
1056 GetWindowInfo(hwnd, &wi);
1059 ("winTopLevelWindowProc - WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n",
1060 wi.rcClient.left, wi.rcClient.top, wi.rcClient.right,
1061 wi.rcClient.bottom, wi.rcClient.right - wi.rcClient.left,
1062 wi.rcClient.bottom - wi.rcClient.top);
1064 newWinRect = wi.rcClient;
1065 if (!AdjustWindowRectEx(&newWinRect, dwStyle, FALSE, dwExStyle))
1067 ("winTopLevelWindowProc - WM_STYLECHANGING AdjustWindowRectEx failed\n");
1070 ("winTopLevelWindowProc - WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n",
1071 newWinRect.left, newWinRect.top, newWinRect.right,
1072 newWinRect.bottom, newWinRect.right - newWinRect.left,
1073 newWinRect.bottom - newWinRect.top);
1076 Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow()
1077 which WM_SIZE does will use the current (unchanged) style. Instead make a note to change it when
1078 WM_STYLECHANGED is received...
1080 pWinPriv->hDwp = BeginDeferWindowPos(1);
1082 DeferWindowPos(pWinPriv->hDwp, hwnd, NULL, newWinRect.left,
1083 newWinRect.top, newWinRect.right - newWinRect.left,
1084 newWinRect.bottom - newWinRect.top,
1085 SWP_NOACTIVATE | SWP_NOZORDER);
1089 case WM_STYLECHANGED:
1091 if (pWinPriv->hDwp) {
1092 EndDeferWindowPos(pWinPriv->hDwp);
1093 pWinPriv->hDwp = NULL;
1095 winDebug("winTopLevelWindowProc - WM_STYLECHANGED done\n");
1099 case WM_MOUSEACTIVATE:
1101 /* Check if this window needs to be made active when clicked */
1102 if (!GetProp(pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) {
1103 #if CYGMULTIWINDOW_DEBUG
1104 ErrorF("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
1109 return MA_NOACTIVATE;
1114 if (LOWORD(lParam) == HTCLIENT) {
1115 if (!g_fSoftwareCursor)
1116 SetCursor(s_pScreenPriv->cursor.handle);
1125 ret = DefWindowProc(hwnd, message, wParam, lParam);
1127 * If the window was minized we get the stack change before the window is restored
1128 * and so it gets lost. Ensure there stacking order is correct.
1131 winReorderWindowsMultiWindow();