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, 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;
319 static Bool hasEnteredSizeMove = FALSE;
322 winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam,
326 /* Check if the Windows window property for our X window pointer is valid */
327 if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) {
328 /* Our X window pointer is valid */
330 /* Get pointers to the drawable and the screen */
331 pDraw = &pWin->drawable;
332 s_pScreen = pWin->drawable.pScreen;
334 /* Get a pointer to our window privates */
335 pWinPriv = winGetWindowPriv(pWin);
337 /* Get pointers to our screen privates and screen info */
338 s_pScreenPriv = pWinPriv->pScreenPriv;
339 s_pScreenInfo = s_pScreenPriv->pScreenInfo;
341 /* Get the handle for our screen-sized window */
342 hwndScreen = s_pScreenPriv->hwndScreen;
346 wmMsg.hwndWindow = hwnd;
347 wmMsg.iWindow = (Window) (INT_PTR) GetProp(hwnd, WIN_WID_PROP);
351 wmMsg.iWidth = pDraw->width;
352 wmMsg.iHeight = pDraw->height;
354 fWMMsgInitialized = TRUE;
358 * Print some debugging information
361 ErrorF("hWnd %08X\n", hwnd);
362 ErrorF("pWin %08X\n", pWin);
363 ErrorF("pDraw %08X\n", pDraw);
364 ErrorF("\ttype %08X\n", pWin->drawable.type);
365 ErrorF("\tclass %08X\n", pWin->drawable.class);
366 ErrorF("\tdepth %08X\n", pWin->drawable.depth);
367 ErrorF("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
368 ErrorF("\tid %08X\n", pWin->drawable.id);
369 ErrorF("\tx %08X\n", pWin->drawable.x);
370 ErrorF("\ty %08X\n", pWin->drawable.y);
371 ErrorF("\twidth %08X\n", pWin->drawable.width);
372 ErrorF("\thenght %08X\n", pWin->drawable.height);
373 ErrorF("\tpScreen %08X\n", pWin->drawable.pScreen);
374 ErrorF("\tserialNumber %08X\n", pWin->drawable.serialNumber);
375 ErrorF("g_iWindowPrivateKey %p\n", g_iWindowPrivateKey);
376 ErrorF("pWinPriv %08X\n", pWinPriv);
377 ErrorF("s_pScreenPriv %08X\n", s_pScreenPriv);
378 ErrorF("s_pScreenInfo %08X\n", s_pScreenInfo);
379 ErrorF("hwndScreen %08X\n", hwndScreen);
383 /* Branch on message type */
390 (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams);
395 (HANDLE) (INT_PTR) winGetWindowID(((LPCREATESTRUCT) lParam)->
399 * Make X windows' Z orders sync with Windows windows because
400 * there can be AlwaysOnTop windows overlapped on the window
401 * currently being created.
403 winReorderWindowsMultiWindow();
405 /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
410 GetWindowRect(hwnd, &rWindow);
411 hRgnWindow = CreateRectRgnIndirect(&rWindow);
412 SetWindowRgn(hwnd, hRgnWindow, TRUE);
413 DeleteObject(hRgnWindow);
416 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) XMING_SIGNATURE);
420 case WM_INIT_SYS_MENU:
422 * Add whatever the setup file wants to for this window
429 * Any window menu items go through here
431 if (HandleCustomWM_COMMAND(hwnd, LOWORD(wParam))) {
432 /* Don't pass customized menus to DefWindowProc */
435 if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE) {
436 WINDOWPLACEMENT wndpl;
438 wndpl.length = sizeof(wndpl);
439 if (GetWindowPlacement(hwnd, &wndpl) &&
440 wndpl.showCmd == SW_SHOWMINIMIZED)
446 /* Checks/Unchecks any menu items before they are displayed */
447 HandleCustomWM_INITMENU(hwnd, (HMENU)wParam);
452 * Pretend that we did erase the background but we don't care,
453 * since we repaint the entire region anyhow
454 * This avoids some flickering when resizing.
459 /* Only paint if our window handle is valid */
460 if (hwndScreen == NULL)
463 /* BeginPaint gives us an hdc that clips to the invalidated region */
464 hdcUpdate = BeginPaint(hwnd, &ps);
465 /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
466 if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
467 ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
472 #ifdef XWIN_GLX_WINDOWS
473 if (pWinPriv->fWglUsed) {
475 For regions which are being drawn by GL, the shadow framebuffer doesn't have the
476 correct bits, so don't bitblt from the shadow framebuffer
478 XXX: For now, just leave it alone, but ideally we want to send an expose event to
479 the window so it really redraws the affected region...
481 ValidateRect(hwnd, &(ps.rcPaint));
485 /* Try to copy from the shadow buffer */
486 if (!BitBlt(hdcUpdate,
487 ps.rcPaint.left, ps.rcPaint.top,
488 ps.rcPaint.right - ps.rcPaint.left,
489 ps.rcPaint.bottom - ps.rcPaint.top,
490 s_pScreenPriv->hdcShadow,
491 ps.rcPaint.left + pWin->drawable.x,
492 ps.rcPaint.top + pWin->drawable.y, SRCCOPY)) {
495 /* Display a fancy error message */
496 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
497 FORMAT_MESSAGE_FROM_SYSTEM |
498 FORMAT_MESSAGE_IGNORE_INSERTS,
501 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
502 (LPTSTR) &lpMsgBuf, 0, NULL);
504 ErrorF("winTopLevelWindowProc - BitBlt failed: %s\n",
509 /* EndPaint frees the DC */
514 /* Unpack the client area mouse coordinates */
515 ptMouse.x = GET_X_LPARAM(lParam);
516 ptMouse.y = GET_Y_LPARAM(lParam);
518 /* Translate the client area mouse coordinates to screen coordinates */
519 ClientToScreen(hwnd, &ptMouse);
521 /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
522 ptMouse.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
523 ptMouse.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
525 /* We can't do anything without privates */
526 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
529 /* Has the mouse pointer crossed screens? */
530 if (s_pScreen != miPointerGetScreen(g_pwinPointer))
531 miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen,
532 ptMouse.x - s_pScreenInfo->dwXOffset,
533 ptMouse.y - s_pScreenInfo->dwYOffset);
535 /* Are we tracking yet? */
539 /* Setup data structure */
540 ZeroMemory(&tme, sizeof(tme));
541 tme.cbSize = sizeof(tme);
542 tme.dwFlags = TME_LEAVE;
543 tme.hwndTrack = hwnd;
545 /* Call the tracking function */
546 if (!TrackMouseEvent(&tme))
547 ErrorF("winTopLevelWindowProc - TrackMouseEvent failed\n");
549 /* Flag that we are tracking now */
553 /* Hide or show the Windows mouse cursor */
554 if (g_fSoftwareCursor && g_fCursor) {
555 /* Hide Windows cursor */
560 /* Kill the timer used to poll mouse events */
561 if (g_uipMousePollingTimerID != 0) {
562 KillTimer(s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
563 g_uipMousePollingTimerID = 0;
566 /* Deliver absolute cursor position to X Server */
567 winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset,
568 ptMouse.y - s_pScreenInfo->dwYOffset);
574 * We break instead of returning 0 since we need to call
575 * DefWindowProc to get the mouse cursor changes
576 * and min/max/close button highlighting in Windows XP.
577 * The Platform SDK says that you should return 0 if you
578 * process this message, but it fails to mention that you
579 * will give up any default functionality if you do return 0.
582 /* We can't do anything without privates */
583 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
586 /* Non-client mouse movement, show Windows cursor */
587 if (g_fSoftwareCursor && !g_fCursor) {
592 winStartMousePolling(s_pScreenPriv);
597 /* Mouse has left our client area */
599 /* Flag that we are no longer tracking */
602 /* Show the mouse cursor, if necessary */
603 if (g_fSoftwareCursor && !g_fCursor) {
608 winStartMousePolling(s_pScreenPriv);
612 case WM_LBUTTONDBLCLK:
614 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
618 return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam);
621 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
623 g_fButton[0] = FALSE;
625 winStartMousePolling(s_pScreenPriv);
626 return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam);
628 case WM_MBUTTONDBLCLK:
630 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
634 return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam);
637 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
639 g_fButton[1] = FALSE;
641 winStartMousePolling(s_pScreenPriv);
642 return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam);
644 case WM_RBUTTONDBLCLK:
646 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
650 return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam);
653 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
655 g_fButton[2] = FALSE;
657 winStartMousePolling(s_pScreenPriv);
658 return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam);
660 case WM_XBUTTONDBLCLK:
662 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
665 return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
669 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
672 winStartMousePolling(s_pScreenPriv);
673 return winMouseButtonsHandle(s_pScreen, ButtonRelease,
674 HIWORD(wParam) + 7, wParam);
678 (hwnd, WM_NCHITTEST, 0,
679 MAKELONG(GET_X_LPARAM(lParam),
680 GET_Y_LPARAM(lParam))) == HTCLIENT) {
681 /* Pass the message to the root window */
682 SendMessage(hwndScreen, message, wParam, lParam);
690 (hwnd, WM_NCHITTEST, 0,
691 MAKELONG(GET_X_LPARAM(lParam),
692 GET_Y_LPARAM(lParam))) == HTCLIENT) {
693 /* Pass the message to the root window */
694 SendMessage(hwndScreen, message, wParam, lParam);
701 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
705 /* Get the parent window for transient handling */
706 HWND hParent = GetParent(hwnd);
708 if (hParent && IsIconic(hParent))
709 ShowWindow(hParent, SW_RESTORE);
712 winRestoreModeKeyStates();
714 /* Add the keyboard hook if possible */
715 if (g_fKeyboardHookLL)
716 g_fKeyboardHookLL = winInstallKeyboardHookLL();
720 /* Pop any pressed keys since we are losing keyboard focus */
721 winKeybdReleaseKeys();
723 /* Remove our keyboard hook if it is installed */
724 winRemoveKeyboardHookLL();
726 /* Revert the X focus as well, but only if the Windows focus is going to another window */
728 DeleteWindowFromAnyEvents(pWin, FALSE);
735 * NOTE: We do nothing with WM_*CHAR messages,
736 * nor does the root window, so we can just toss these messages.
744 * Don't pass Alt-F4 key combo to root window,
745 * let Windows translate to WM_CLOSE and close this top-level window.
747 * NOTE: We purposely don't check the fUseWinKillKey setting because
748 * it should only apply to the key handling for the root window,
749 * not for top-level window-manager windows.
751 * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
752 * because that is a key combo that no X app should be expecting to
753 * receive, since it has historically been used to shutdown the X server.
754 * Passing Ctrl-Alt-Backspace to the root window preserves that
755 * behavior, assuming that -unixkill has been passed as a parameter.
757 if (wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000))
760 #if CYGWINDOWING_DEBUG
761 if (wParam == VK_ESCAPE) {
762 /* Place for debug: put any tests and dumps here */
763 WINDOWPLACEMENT windPlace;
767 windPlace.length = sizeof(WINDOWPLACEMENT);
768 GetWindowPlacement(hwnd, &windPlace);
769 pRect = &windPlace.rcNormalPosition;
770 ErrorF("\nCYGWINDOWING Dump:\n"
771 "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
772 pDraw->y, pDraw->width, pDraw->height);
773 ErrorF("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left,
774 pRect->top, pRect->right - pRect->left,
775 pRect->bottom - pRect->top);
776 if (GetClientRect(hwnd, &rc)) {
778 ErrorF("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
779 pRect->top, pRect->right - pRect->left,
780 pRect->bottom - pRect->top);
782 if (GetWindowRect(hwnd, &rc)) {
784 ErrorF("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
785 pRect->top, pRect->right - pRect->left,
786 pRect->bottom - pRect->top);
792 /* Pass the message to the root window */
793 return winWindowProc(hwndScreen, message, wParam, lParam);
798 /* Pass the message to the root window */
799 return winWindowProc(hwndScreen, message, wParam, lParam);
803 /* Pass the message to the root window */
804 SendMessage(hwndScreen, message, wParam, lParam);
809 /* Pass the message to the root window */
810 SendMessage(hwndScreen, message, wParam, lParam);
812 if (LOWORD(wParam) != WA_INACTIVE) {
813 /* Raise the window to the top in Z order */
814 /* ago: Activate does not mean putting it to front! */
816 wmMsg.msg = WM_WM_RAISE;
817 if (fWMMsgInitialized)
818 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
821 /* Tell our Window Manager thread to activate the window */
822 wmMsg.msg = WM_WM_ACTIVATE;
823 if (fWMMsgInitialized)
824 if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
825 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
827 /* Prevent the mouse wheel from stalling when another window is minimized */
828 if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE &&
829 (HWND) lParam != NULL && (HWND) lParam != GetParent(hwnd))
835 * This message is also sent to the root window
836 * so we do nothing for individual multiwindow windows
841 /* Remove AppUserModelID property */
842 winSetAppUserModelID(hwnd, NULL);
843 /* Branch on if the window was killed in X already */
844 if (pWinPriv->fXKilled) {
845 /* Window was killed, go ahead and destroy the window */
849 /* Tell our Window Manager thread to kill the window */
850 wmMsg.msg = WM_WM_KILL;
851 if (fWMMsgInitialized)
852 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
858 /* Branch on if the window was killed in X already */
859 if (pWinPriv && !pWinPriv->fXKilled) {
860 ErrorF("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
862 /* Tell our Window Manager thread to kill the window */
863 wmMsg.msg = WM_WM_KILL;
864 if (fWMMsgInitialized)
865 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
868 RemoveProp(hwnd, WIN_WINDOW_PROP);
869 RemoveProp(hwnd, WIN_WID_PROP);
870 RemoveProp(hwnd, WIN_NEEDMANAGE_PROP);
875 /* Adjust the X Window to the moved Windows window */
876 if (!hasEnteredSizeMove)
877 winAdjustXWindow(pWin, hwnd);
878 /* else: Wait for WM_EXITSIZEMOVE */
882 /* Bail out if the window is being hidden */
887 if (!pWin->overrideRedirect) {
888 HWND zstyle = HWND_NOTOPMOST;
890 /* Flag that this window needs to be made active when clicked */
891 SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
893 /* Set the transient style flags */
895 SetWindowLongPtr(hwnd, GWL_STYLE,
896 WS_POPUP | WS_OVERLAPPED | WS_SYSMENU |
897 WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
898 /* Set the window standard style flags */
900 SetWindowLongPtr(hwnd, GWL_STYLE,
901 (WS_POPUP | WS_OVERLAPPEDWINDOW |
902 WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
903 & ~WS_CAPTION & ~WS_SIZEBOX);
905 winUpdateWindowPosition(hwnd, &zstyle);
910 if (winMultiWindowGetWMHints(pWin, &hints)) {
912 Give the window focus, unless it has an InputHint
913 which is FALSE (this is used by e.g. glean to
914 avoid every test window grabbing the focus)
916 if (!((hints.flags & InputHint) && (!hints.input))) {
917 SetForegroundWindow(hwnd);
921 wmMsg.msg = WM_WM_MAP3;
923 else { /* It is an overridden window so make it top of Z stack */
925 HWND forHwnd = GetForegroundWindow();
927 #if CYGWINDOWING_DEBUG
928 ErrorF("overridden window is shown\n");
930 if (forHwnd != NULL) {
931 if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)
933 if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
934 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
935 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
937 SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
938 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
941 wmMsg.msg = WM_WM_MAP2;
944 /* Tell our Window Manager thread to map the window */
945 if (fWMMsgInitialized)
946 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
948 winStartMousePolling(s_pScreenPriv);
953 /* Need to legalize the size according to WM_NORMAL_HINTS */
954 /* for applications like xterm */
955 return ValidateSizing(hwnd, pWin, wParam, lParam);
957 case WM_WINDOWPOSCHANGED:
959 LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
961 if (!(pWinPos->flags & SWP_NOZORDER)) {
962 #if CYGWINDOWING_DEBUG
963 winDebug("\twindow z order was changed\n");
965 if (pWinPos->hwndInsertAfter == HWND_TOP
966 || pWinPos->hwndInsertAfter == HWND_TOPMOST
967 || pWinPos->hwndInsertAfter == HWND_NOTOPMOST) {
968 #if CYGWINDOWING_DEBUG
969 winDebug("\traise to top\n");
971 /* Raise the window to the top in Z order */
972 winRaiseWindow(pWin);
974 else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) {
977 /* Check if this window is top of X windows. */
978 HWND hWndAbove = NULL;
979 DWORD dwCurrentProcessID = GetCurrentProcessId();
980 DWORD dwWindowProcessID = 0;
982 for (hWndAbove = pWinPos->hwndInsertAfter;
984 hWndAbove = GetNextWindow(hWndAbove, GW_HWNDPREV)) {
985 /* Ignore other XWin process's window */
986 GetWindowThreadProcessId(hWndAbove, &dwWindowProcessID);
988 if ((dwWindowProcessID == dwCurrentProcessID)
989 && GetProp(hWndAbove, WIN_WINDOW_PROP)
990 && !IsWindowVisible(hWndAbove)
991 && !IsIconic(hWndAbove)) /* ignore minimized windows */
994 /* If this is top of X windows in Windows stack,
995 raise it in X stack. */
996 if (hWndAbove == NULL) {
997 #if CYGWINDOWING_DEBUG
998 winDebug("\traise to top\n");
1000 winRaiseWindow(pWin);
1006 * Pass the message to DefWindowProc to let the function
1007 * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
1011 case WM_ENTERSIZEMOVE:
1012 hasEnteredSizeMove = TRUE;
1015 case WM_EXITSIZEMOVE:
1016 /* Adjust the X Window to the moved Windows window */
1017 hasEnteredSizeMove = FALSE;
1018 winAdjustXWindow(pWin, hwnd);
1022 /* see dix/window.c */
1023 #if CYGWINDOWING_DEBUG
1028 case SIZE_MINIMIZED:
1029 strcpy(buf, "SIZE_MINIMIZED");
1031 case SIZE_MAXIMIZED:
1032 strcpy(buf, "SIZE_MAXIMIZED");
1035 strcpy(buf, "SIZE_RESTORED");
1038 strcpy(buf, "UNKNOWN_FLAG");
1040 ErrorF("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n",
1041 (int) LOWORD(lParam), (int) HIWORD(lParam), buf,
1042 (int) (GetTickCount()));
1045 if (!hasEnteredSizeMove) {
1046 /* Adjust the X Window to the moved Windows window */
1047 winAdjustXWindow(pWin, hwnd);
1049 /* else: wait for WM_EXITSIZEMOVE */
1050 return 0; /* end of WM_SIZE handler */
1052 case WM_STYLECHANGING:
1054 When the style changes, adjust the Windows window size so the client area remains the same size,
1055 and adjust the Windows window position so that the client area remains in the same place.
1061 DWORD newStyle = ((STYLESTRUCT *) lParam)->styleNew;
1064 dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
1065 dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
1067 winDebug("winTopLevelWindowProc - WM_STYLECHANGING from %08x %08x\n",
1068 dwStyle, dwExStyle);
1070 if (wParam == GWL_EXSTYLE)
1071 dwExStyle = newStyle;
1073 if (wParam == GWL_STYLE)
1076 winDebug("winTopLevelWindowProc - WM_STYLECHANGING to %08x %08x\n",
1077 dwStyle, dwExStyle);
1079 /* Get client rect in screen coordinates */
1080 wi.cbSize = sizeof(WINDOWINFO);
1081 GetWindowInfo(hwnd, &wi);
1084 ("winTopLevelWindowProc - WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n",
1085 wi.rcClient.left, wi.rcClient.top, wi.rcClient.right,
1086 wi.rcClient.bottom, wi.rcClient.right - wi.rcClient.left,
1087 wi.rcClient.bottom - wi.rcClient.top);
1089 newWinRect = wi.rcClient;
1090 if (!AdjustWindowRectEx(&newWinRect, dwStyle, FALSE, dwExStyle))
1092 ("winTopLevelWindowProc - WM_STYLECHANGING AdjustWindowRectEx failed\n");
1095 ("winTopLevelWindowProc - WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n",
1096 newWinRect.left, newWinRect.top, newWinRect.right,
1097 newWinRect.bottom, newWinRect.right - newWinRect.left,
1098 newWinRect.bottom - newWinRect.top);
1101 Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow()
1102 which WM_SIZE does will use the current (unchanged) style. Instead make a note to change it when
1103 WM_STYLECHANGED is received...
1105 pWinPriv->hDwp = BeginDeferWindowPos(1);
1107 DeferWindowPos(pWinPriv->hDwp, hwnd, NULL, newWinRect.left,
1108 newWinRect.top, newWinRect.right - newWinRect.left,
1109 newWinRect.bottom - newWinRect.top,
1110 SWP_NOACTIVATE | SWP_NOZORDER);
1114 case WM_STYLECHANGED:
1116 if (pWinPriv->hDwp) {
1117 EndDeferWindowPos(pWinPriv->hDwp);
1118 pWinPriv->hDwp = NULL;
1120 winDebug("winTopLevelWindowProc - WM_STYLECHANGED done\n");
1124 case WM_MOUSEACTIVATE:
1126 /* Check if this window needs to be made active when clicked */
1127 if (!GetProp(pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) {
1128 #if CYGMULTIWINDOW_DEBUG
1129 ErrorF("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
1134 return MA_NOACTIVATE;
1139 if (LOWORD(lParam) == HTCLIENT) {
1140 if (!g_fSoftwareCursor)
1141 SetCursor(s_pScreenPriv->cursor.handle);
1150 ret = DefWindowProc(hwnd, message, wParam, lParam);
1152 * If the window was minized we get the stack change before the window is restored
1153 * and so it gets lost. Ensure there stacking order is correct.
1156 winReorderWindowsMultiWindow();