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
;
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
) (INT_PTR
) 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
) (INT_PTR
) 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
428 * Any window menu items go through here
430 if (HandleCustomWM_COMMAND(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(hwnd
, (HMENU
)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
) + 7,
668 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
671 winStartMousePolling(s_pScreenPriv
);
672 return winMouseButtonsHandle(s_pScreen
, ButtonRelease
,
673 HIWORD(wParam
) + 7, 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
);
689 (hwnd
, WM_NCHITTEST
, 0,
690 MAKELONG(GET_X_LPARAM(lParam
),
691 GET_Y_LPARAM(lParam
))) == HTCLIENT
) {
692 /* Pass the message to the root window */
693 SendMessage(hwndScreen
, message
, wParam
, lParam
);
700 if (s_pScreenPriv
== NULL
|| s_pScreenInfo
->fIgnoreInput
)
704 /* Get the parent window for transient handling */
705 HWND hParent
= GetParent(hwnd
);
707 if (hParent
&& IsIconic(hParent
))
708 ShowWindow(hParent
, SW_RESTORE
);
711 winRestoreModeKeyStates();
713 /* Add the keyboard hook if possible */
714 if (g_fKeyboardHookLL
)
715 g_fKeyboardHookLL
= winInstallKeyboardHookLL();
719 /* Pop any pressed keys since we are losing keyboard focus */
720 winKeybdReleaseKeys();
722 /* Remove our keyboard hook if it is installed */
723 winRemoveKeyboardHookLL();
725 /* Revert the X focus as well, but only if the Windows focus is going to another window */
727 DeleteWindowFromAnyEvents(pWin
, FALSE
);
734 * NOTE: We do nothing with WM_*CHAR messages,
735 * nor does the root window, so we can just toss these messages.
743 * Don't pass Alt-F4 key combo to root window,
744 * let Windows translate to WM_CLOSE and close this top-level window.
746 * NOTE: We purposely don't check the fUseWinKillKey setting because
747 * it should only apply to the key handling for the root window,
748 * not for top-level window-manager windows.
750 * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
751 * because that is a key combo that no X app should be expecting to
752 * receive, since it has historically been used to shutdown the X server.
753 * Passing Ctrl-Alt-Backspace to the root window preserves that
754 * behavior, assuming that -unixkill has been passed as a parameter.
756 if (wParam
== VK_F4
&& (GetKeyState(VK_MENU
) & 0x8000))
759 #if CYGWINDOWING_DEBUG
760 if (wParam
== VK_ESCAPE
) {
761 /* Place for debug: put any tests and dumps here */
762 WINDOWPLACEMENT windPlace
;
766 windPlace
.length
= sizeof(WINDOWPLACEMENT
);
767 GetWindowPlacement(hwnd
, &windPlace
);
768 pRect
= &windPlace
.rcNormalPosition
;
769 ErrorF("\nCYGWINDOWING Dump:\n"
770 "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw
->x
,
771 pDraw
->y
, pDraw
->width
, pDraw
->height
);
772 ErrorF("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect
->left
,
773 pRect
->top
, pRect
->right
- pRect
->left
,
774 pRect
->bottom
- pRect
->top
);
775 if (GetClientRect(hwnd
, &rc
)) {
777 ErrorF("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect
->left
,
778 pRect
->top
, pRect
->right
- pRect
->left
,
779 pRect
->bottom
- pRect
->top
);
781 if (GetWindowRect(hwnd
, &rc
)) {
783 ErrorF("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect
->left
,
784 pRect
->top
, pRect
->right
- pRect
->left
,
785 pRect
->bottom
- pRect
->top
);
791 /* Pass the message to the root window */
792 return winWindowProc(hwndScreen
, message
, wParam
, lParam
);
797 /* Pass the message to the root window */
798 return winWindowProc(hwndScreen
, message
, wParam
, lParam
);
802 /* Pass the message to the root window */
803 SendMessage(hwndScreen
, message
, wParam
, lParam
);
808 /* Pass the message to the root window */
809 SendMessage(hwndScreen
, message
, wParam
, lParam
);
811 if (LOWORD(wParam
) != WA_INACTIVE
) {
812 /* Raise the window to the top in Z order */
813 /* ago: Activate does not mean putting it to front! */
815 wmMsg.msg = WM_WM_RAISE;
816 if (fWMMsgInitialized)
817 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
820 /* Tell our Window Manager thread to activate the window */
821 wmMsg
.msg
= WM_WM_ACTIVATE
;
822 if (fWMMsgInitialized
)
823 if (!pWin
|| !pWin
->overrideRedirect
) /* for OOo menus */
824 winSendMessageToWM(s_pScreenPriv
->pWMInfo
, &wmMsg
);
826 /* Prevent the mouse wheel from stalling when another window is minimized */
827 if (HIWORD(wParam
) == 0 && LOWORD(wParam
) == WA_ACTIVE
&&
828 (HWND
) lParam
!= NULL
&& (HWND
) lParam
!= GetParent(hwnd
))
834 * This message is also sent to the root window
835 * so we do nothing for individual multiwindow windows
840 /* Removep AppUserModelID property */
841 winSetAppUserModelID(hwnd
, NULL
);
842 /* Branch on if the window was killed in X already */
843 if (pWinPriv
->fXKilled
) {
844 /* Window was killed, go ahead and destroy the window */
848 /* Tell our Window Manager thread to kill the window */
849 wmMsg
.msg
= WM_WM_KILL
;
850 if (fWMMsgInitialized
)
851 winSendMessageToWM(s_pScreenPriv
->pWMInfo
, &wmMsg
);
857 /* Branch on if the window was killed in X already */
858 if (pWinPriv
&& !pWinPriv
->fXKilled
) {
859 ErrorF("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
861 /* Tell our Window Manager thread to kill the window */
862 wmMsg
.msg
= WM_WM_KILL
;
863 if (fWMMsgInitialized
)
864 winSendMessageToWM(s_pScreenPriv
->pWMInfo
, &wmMsg
);
867 RemoveProp(hwnd
, WIN_WINDOW_PROP
);
868 RemoveProp(hwnd
, WIN_WID_PROP
);
869 RemoveProp(hwnd
, WIN_NEEDMANAGE_PROP
);
874 /* Adjust the X Window to the moved Windows window */
875 winAdjustXWindow(pWin
, hwnd
);
879 /* Bail out if the window is being hidden */
884 if (!pWin
->overrideRedirect
) {
885 HWND zstyle
= HWND_NOTOPMOST
;
887 /* Flag that this window needs to be made active when clicked */
888 SetProp(hwnd
, WIN_NEEDMANAGE_PROP
, (HANDLE
) 1);
890 /* Set the transient style flags */
892 SetWindowLongPtr(hwnd
, GWL_STYLE
,
893 WS_POPUP
| WS_OVERLAPPED
| WS_SYSMENU
|
894 WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
);
895 /* Set the window standard style flags */
897 SetWindowLongPtr(hwnd
, GWL_STYLE
,
898 (WS_POPUP
| WS_OVERLAPPEDWINDOW
|
899 WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
)
900 & ~WS_CAPTION
& ~WS_SIZEBOX
);
902 winUpdateWindowPosition(hwnd
, &zstyle
);
907 if (winMultiWindowGetWMHints(pWin
, &hints
)) {
909 Give the window focus, unless it has an InputHint
910 which is FALSE (this is used by e.g. glean to
911 avoid every test window grabbing the focus)
913 if (!((hints
.flags
& InputHint
) && (!hints
.input
))) {
914 SetForegroundWindow(hwnd
);
918 wmMsg
.msg
= WM_WM_MAP3
;
920 else { /* It is an overridden window so make it top of Z stack */
922 HWND forHwnd
= GetForegroundWindow();
924 #if CYGWINDOWING_DEBUG
925 ErrorF("overridden window is shown\n");
927 if (forHwnd
!= NULL
) {
928 if (GetWindowLongPtr(forHwnd
, GWLP_USERDATA
) & (LONG_PTR
)
930 if (GetWindowLongPtr(forHwnd
, GWL_EXSTYLE
) & WS_EX_TOPMOST
)
931 SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, 0, 0,
932 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
934 SetWindowPos(hwnd
, HWND_NOTOPMOST
, 0, 0, 0, 0,
935 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
938 wmMsg
.msg
= WM_WM_MAP2
;
941 /* Tell our Window Manager thread to map the window */
942 if (fWMMsgInitialized
)
943 winSendMessageToWM(s_pScreenPriv
->pWMInfo
, &wmMsg
);
945 winStartMousePolling(s_pScreenPriv
);
950 /* Need to legalize the size according to WM_NORMAL_HINTS */
951 /* for applications like xterm */
952 return ValidateSizing(hwnd
, pWin
, wParam
, lParam
);
954 case WM_WINDOWPOSCHANGED
:
956 LPWINDOWPOS pWinPos
= (LPWINDOWPOS
) lParam
;
958 if (!(pWinPos
->flags
& SWP_NOZORDER
)) {
959 #if CYGWINDOWING_DEBUG
960 winDebug("\twindow z order was changed\n");
962 if (pWinPos
->hwndInsertAfter
== HWND_TOP
963 || pWinPos
->hwndInsertAfter
== HWND_TOPMOST
964 || pWinPos
->hwndInsertAfter
== HWND_NOTOPMOST
) {
965 #if CYGWINDOWING_DEBUG
966 winDebug("\traise to top\n");
968 /* Raise the window to the top in Z order */
969 winRaiseWindow(pWin
);
971 else if (pWinPos
->hwndInsertAfter
== HWND_BOTTOM
) {
974 /* Check if this window is top of X windows. */
975 HWND hWndAbove
= NULL
;
976 DWORD dwCurrentProcessID
= GetCurrentProcessId();
977 DWORD dwWindowProcessID
= 0;
979 for (hWndAbove
= pWinPos
->hwndInsertAfter
;
981 hWndAbove
= GetNextWindow(hWndAbove
, GW_HWNDPREV
)) {
982 /* Ignore other XWin process's window */
983 GetWindowThreadProcessId(hWndAbove
, &dwWindowProcessID
);
985 if ((dwWindowProcessID
== dwCurrentProcessID
)
986 && GetProp(hWndAbove
, WIN_WINDOW_PROP
)
987 && !IsWindowVisible(hWndAbove
)
988 && !IsIconic(hWndAbove
)) /* ignore minimized windows */
991 /* If this is top of X windows in Windows stack,
992 raise it in X stack. */
993 if (hWndAbove
== NULL
) {
994 #if CYGWINDOWING_DEBUG
995 winDebug("\traise to top\n");
997 winRaiseWindow(pWin
);
1003 * Pass the message to DefWindowProc to let the function
1004 * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
1009 /* see dix/window.c */
1010 #if CYGWINDOWING_DEBUG
1015 case SIZE_MINIMIZED
:
1016 strcpy(buf
, "SIZE_MINIMIZED");
1018 case SIZE_MAXIMIZED
:
1019 strcpy(buf
, "SIZE_MAXIMIZED");
1022 strcpy(buf
, "SIZE_RESTORED");
1025 strcpy(buf
, "UNKNOWN_FLAG");
1027 ErrorF("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n",
1028 (int) LOWORD(lParam
), (int) HIWORD(lParam
), buf
,
1029 (int) (GetTickCount()));
1032 /* Adjust the X Window to the moved Windows window */
1033 winAdjustXWindow(pWin
, hwnd
);
1034 return 0; /* end of WM_SIZE handler */
1036 case WM_STYLECHANGING
:
1038 When the style changes, adjust the Windows window size so the client area remains the same size,
1039 and adjust the Windows window position so that the client area remains in the same place.
1045 DWORD newStyle
= ((STYLESTRUCT
*) lParam
)->styleNew
;
1048 dwExStyle
= GetWindowLongPtr(hwnd
, GWL_EXSTYLE
);
1049 dwStyle
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
1051 winDebug("winTopLevelWindowProc - WM_STYLECHANGING from %08x %08x\n",
1052 dwStyle
, dwExStyle
);
1054 if (wParam
== GWL_EXSTYLE
)
1055 dwExStyle
= newStyle
;
1057 if (wParam
== GWL_STYLE
)
1060 winDebug("winTopLevelWindowProc - WM_STYLECHANGING to %08x %08x\n",
1061 dwStyle
, dwExStyle
);
1063 /* Get client rect in screen coordinates */
1064 wi
.cbSize
= sizeof(WINDOWINFO
);
1065 GetWindowInfo(hwnd
, &wi
);
1068 ("winTopLevelWindowProc - WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n",
1069 wi
.rcClient
.left
, wi
.rcClient
.top
, wi
.rcClient
.right
,
1070 wi
.rcClient
.bottom
, wi
.rcClient
.right
- wi
.rcClient
.left
,
1071 wi
.rcClient
.bottom
- wi
.rcClient
.top
);
1073 newWinRect
= wi
.rcClient
;
1074 if (!AdjustWindowRectEx(&newWinRect
, dwStyle
, FALSE
, dwExStyle
))
1076 ("winTopLevelWindowProc - WM_STYLECHANGING AdjustWindowRectEx failed\n");
1079 ("winTopLevelWindowProc - WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n",
1080 newWinRect
.left
, newWinRect
.top
, newWinRect
.right
,
1081 newWinRect
.bottom
, newWinRect
.right
- newWinRect
.left
,
1082 newWinRect
.bottom
- newWinRect
.top
);
1085 Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow()
1086 which WM_SIZE does will use the current (unchanged) style. Instead make a note to change it when
1087 WM_STYLECHANGED is received...
1089 pWinPriv
->hDwp
= BeginDeferWindowPos(1);
1091 DeferWindowPos(pWinPriv
->hDwp
, hwnd
, NULL
, newWinRect
.left
,
1092 newWinRect
.top
, newWinRect
.right
- newWinRect
.left
,
1093 newWinRect
.bottom
- newWinRect
.top
,
1094 SWP_NOACTIVATE
| SWP_NOZORDER
);
1098 case WM_STYLECHANGED
:
1100 if (pWinPriv
->hDwp
) {
1101 EndDeferWindowPos(pWinPriv
->hDwp
);
1102 pWinPriv
->hDwp
= NULL
;
1104 winDebug("winTopLevelWindowProc - WM_STYLECHANGED done\n");
1108 case WM_MOUSEACTIVATE
:
1110 /* Check if this window needs to be made active when clicked */
1111 if (!GetProp(pWinPriv
->hWnd
, WIN_NEEDMANAGE_PROP
)) {
1112 #if CYGMULTIWINDOW_DEBUG
1113 ErrorF("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
1118 return MA_NOACTIVATE
;
1123 if (LOWORD(lParam
) == HTCLIENT
) {
1124 if (!g_fSoftwareCursor
)
1125 SetCursor(s_pScreenPriv
->cursor
.handle
);
1134 ret
= DefWindowProc(hwnd
, message
, wParam
, lParam
);
1136 * If the window was minized we get the stack change before the window is restored
1137 * and so it gets lost. Ensure there stacking order is correct.
1140 winReorderWindowsMultiWindow();