2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
28 * Authors: Kensuke Matsuzaki
29 * Earle F. Philhower, III
32 #ifdef HAVE_XWIN_CONFIG_H
33 #include <xwin-config.h>
37 #define _WINDOWSWM_SERVER_
38 #include <X11/extensions/windowswmstr.h>
39 #include "dixevents.h"
40 #include "propertyst.h"
41 #include <X11/Xatom.h>
42 #include "winmultiwindowclass.h"
50 #define MOUSE_ACTIVATE_DEFAULT TRUE
51 #define RAISE_ON_CLICK_DEFAULT FALSE
57 static UINT_PTR g_uipMousePollingTimerID
= 0;
63 DEFINE_ATOM_HELPER(AtmWindowsWmRaiseOnClick
, WINDOWSWM_RAISE_ON_CLICK
)
64 DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate
, WINDOWSWM_MOUSE_ACTIVATE
)
65 /* DEFINE_ATOM_HELPER(AtmWindowsWMClientWindow, WINDOWSWM_CLIENT_WINDOW) */
67 * ConstrainSize - Taken from TWM sources - Respects hints for sizing
69 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
71 ConstrainSize(WinXSizeHints hints
, int *widthp
, int *heightp
)
73 int minWidth
, minHeight
, maxWidth
, maxHeight
, xinc
, yinc
, delta
;
74 int baseWidth
, baseHeight
;
75 int dwidth
= *widthp
, dheight
= *heightp
;
77 if (hints
.flags
& PMinSize
) {
78 minWidth
= hints
.min_width
;
79 minHeight
= hints
.min_height
;
81 else if (hints
.flags
& PBaseSize
) {
82 minWidth
= hints
.base_width
;
83 minHeight
= hints
.base_height
;
86 minWidth
= minHeight
= 1;
88 if (hints
.flags
& PBaseSize
) {
89 baseWidth
= hints
.base_width
;
90 baseHeight
= hints
.base_height
;
92 else if (hints
.flags
& PMinSize
) {
93 baseWidth
= hints
.min_width
;
94 baseHeight
= hints
.min_height
;
97 baseWidth
= baseHeight
= 0;
99 if (hints
.flags
& PMaxSize
) {
100 maxWidth
= hints
.max_width
;
101 maxHeight
= hints
.max_height
;
108 if (hints
.flags
& PResizeInc
) {
109 xinc
= hints
.width_inc
;
110 yinc
= hints
.height_inc
;
116 * First, clamp to min and max values
118 if (dwidth
< minWidth
)
120 if (dheight
< minHeight
)
123 if (dwidth
> maxWidth
)
125 if (dheight
> maxHeight
)
129 * Second, fit to base + N * inc
131 dwidth
= ((dwidth
- baseWidth
) / xinc
* xinc
) + baseWidth
;
132 dheight
= ((dheight
- baseHeight
) / yinc
* yinc
) + baseHeight
;
135 * Third, adjust for aspect ratio
139 * The math looks like this:
141 * minAspectX dwidth maxAspectX
142 * ---------- <= ------- <= ----------
143 * minAspectY dheight maxAspectY
145 * If that is multiplied out, then the width and height are
146 * invalid in the following situations:
148 * minAspectX * dheight > minAspectY * dwidth
149 * maxAspectX * dheight < maxAspectY * dwidth
153 if (hints
.flags
& PAspect
) {
154 if (hints
.min_aspect
.x
* dheight
> hints
.min_aspect
.y
* dwidth
) {
156 makemult(hints
.min_aspect
.x
* dheight
/ hints
.min_aspect
.y
-
158 if (dwidth
+ delta
<= maxWidth
)
163 dwidth
* hints
.min_aspect
.y
/ hints
.min_aspect
.x
,
165 if (dheight
- delta
>= minHeight
)
170 if (hints
.max_aspect
.x
* dheight
< hints
.max_aspect
.y
* dwidth
) {
172 makemult(dwidth
* hints
.max_aspect
.y
/ hints
.max_aspect
.x
-
174 if (dheight
+ delta
<= maxHeight
)
179 hints
.max_aspect
.x
* dheight
/ hints
.max_aspect
.y
,
181 if (dwidth
- delta
>= minWidth
)
187 /* Return computed values */
195 * ValidateSizing - Ensures size request respects hints
198 ValidateSizing(HWND hwnd
, WindowPtr pWin
, WPARAM wParam
, LPARAM lParam
)
200 WinXSizeHints sizeHints
;
202 int iWidth
, iHeight
, iTopBorder
;
205 /* Invalid input checking */
206 if (pWin
== NULL
|| lParam
== 0) {
207 ErrorF("Invalid input checking\n");
211 /* No size hints, no checking */
212 if (!winMultiWindowGetWMNormalHints(pWin
, &sizeHints
)) {
213 ErrorF("No size hints, no checking\n");
217 /* Avoid divide-by-zero */
218 if (sizeHints
.flags
& PResizeInc
) {
219 if (sizeHints
.width_inc
== 0)
220 sizeHints
.width_inc
= 1;
221 if (sizeHints
.height_inc
== 0)
222 sizeHints
.height_inc
= 1;
225 rect
= (RECT
*) lParam
;
227 iWidth
= rect
->right
- rect
->left
;
228 iHeight
= rect
->bottom
- rect
->top
;
230 /* Get title bar height, there must be an easier way?! */
232 ClientToScreen(hwnd
, &pt
);
233 iTopBorder
= pt
.y
- rect
->top
;
235 /* Now remove size of any borders */
236 iWidth
-= 2 * GetSystemMetrics(SM_CXSIZEFRAME
);
237 iHeight
-= GetSystemMetrics(SM_CYSIZEFRAME
) + iTopBorder
;
239 /* Constrain the size to legal values */
240 ConstrainSize(sizeHints
, &iWidth
, &iHeight
);
242 /* Add back the borders */
243 iWidth
+= 2 * GetSystemMetrics(SM_CXSIZEFRAME
);
244 iHeight
+= GetSystemMetrics(SM_CYSIZEFRAME
) + iTopBorder
;
246 /* Adjust size according to where we're dragging from */
251 case WMSZ_BOTTOMRIGHT
:
253 rect
->right
= rect
->left
+ iWidth
;
256 rect
->left
= rect
->right
- iWidth
;
261 case WMSZ_BOTTOMRIGHT
:
262 case WMSZ_BOTTOMLEFT
:
265 rect
->bottom
= rect
->top
+ iHeight
;
268 rect
->top
= rect
->bottom
- iHeight
;
279 IsRaiseOnClick(WindowPtr pWin
)
282 struct _Window
*pwin
;
283 struct _Property
*prop
;
285 /* XXX We're getting inputInfo.poniter here, but this might be really wrong.
286 * Which pointer's current window do we want? */
287 WindowPtr pRoot
= GetCurrentRootWindow(inputInfo
.pointer
);
290 ErrorF("IsRaiseOnClick - no prop use default value:%d\n",
291 RAISE_ON_CLICK_DEFAULT
);
292 return RAISE_ON_CLICK_DEFAULT
;
295 pwin
= (struct _Window
*) pWin
;
298 prop
= (struct _Property
*) pwin
->optional
->userProps
;
303 if (prop
->propertyName
== AtmWindowsWmRaiseOnClick()
304 && prop
->type
== XA_INTEGER
&& prop
->format
== 32) {
305 return *(int *) prop
->data
;
312 return IsRaiseOnClick(pRoot
);
315 #if CYGMULTIWINDOW_DEBUG
316 winDebug("IsRaiseOnClick - no prop use default value:%d\n",
317 RAISE_ON_CLICK_DEFAULT
);
319 return RAISE_ON_CLICK_DEFAULT
;
328 IsMouseActive(WindowPtr pWin
)
331 struct _Window
*pwin
;
332 struct _Property
*prop
;
334 /* XXX We're getting inputInfo.poniter here, but this might be really wrong.
335 * Which pointer's current window do we want? */
336 WindowPtr pRoot
= GetCurrentRootWindow(inputInfo
.pointer
);
339 ErrorF("IsMouseActive - pWin was NULL use default value:%d\n",
340 MOUSE_ACTIVATE_DEFAULT
);
341 return MOUSE_ACTIVATE_DEFAULT
;
344 pwin
= (struct _Window
*) pWin
;
347 prop
= (struct _Property
*) pwin
->optional
->userProps
;
352 if (prop
->propertyName
== AtmWindowsWMMouseActivate()
353 && prop
->type
== XA_INTEGER
&& prop
->format
== 32) {
354 return *(int *) prop
->data
;
361 return IsMouseActive(pRoot
);
364 #if CYGMULTIWINDOW_DEBUG
365 winDebug("IsMouseActive - no prop use default value:%d\n",
366 MOUSE_ACTIVATE_DEFAULT
);
368 return MOUSE_ACTIVATE_DEFAULT
;
373 * winMWExtWMWindowProc - Window procedure
377 winMWExtWMWindowProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
379 WindowPtr pWin
= NULL
;
380 win32RootlessWindowPtr pRLWinPriv
= NULL
;
381 ScreenPtr pScreen
= NULL
;
382 winPrivScreenPtr pScreenPriv
= NULL
;
383 winScreenInfo
*pScreenInfo
= NULL
;
384 HWND hwndScreen
= NULL
;
386 static Bool s_fTracking
= FALSE
;
389 LPWINDOWPOS pWinPos
= NULL
;
391 winWMMessageRec wmMsg
;
392 Bool fWMMsgInitialized
= FALSE
;
394 /* Check if the Windows window property for our X window pointer is valid */
396 (win32RootlessWindowPtr
) GetProp(hwnd
, WIN_WINDOW_PROP
)) != NULL
) {
397 pWin
= pRLWinPriv
->pFrame
->win
;
398 pScreen
= pWin
->drawable
.pScreen
;
400 pScreenPriv
= winGetScreenPriv(pScreen
);
402 pScreenInfo
= pScreenPriv
->pScreenInfo
;
404 hwndScreen
= pScreenPriv
->hwndScreen
;
407 wmMsg
.hwndWindow
= hwnd
;
408 wmMsg
.iWindow
= (Window
) pWin
->drawable
.id
;
410 wmMsg
.iX
= pRLWinPriv
->pFrame
->x
;
411 wmMsg
.iY
= pRLWinPriv
->pFrame
->y
;
412 wmMsg
.iWidth
= pRLWinPriv
->pFrame
->width
;
413 wmMsg
.iHeight
= pRLWinPriv
->pFrame
->height
;
415 fWMMsgInitialized
= TRUE
;
417 winDebugWin32Message("winMWExtWMWindowProc", hwnd
, message
, wParam
,
420 winDebug("\thWnd %08X\n", hwnd
);
421 winDebug("\tpScreenPriv %08X\n", pScreenPriv
);
422 winDebug("\tpScreenInfo %08X\n", pScreenInfo
);
423 winDebug("\thwndScreen %08X\n", hwndScreen
);
424 winDebug("winMWExtWMWindowProc (%08x) %08x %08x %08x\n",
425 pRLWinPriv
, message
, wParam
, lParam
);
428 /* Branch on message type */
431 #if CYGMULTIWINDOW_DEBUG
432 winDebug("winMWExtWMWindowProc - WM_CREATE\n");
437 (HANDLE
) ((LPCREATESTRUCT
) lParam
)->lpCreateParams
);
441 #if CYGMULTIWINDOW_DEBUG
442 winDebug("winMWExtWMWindowProc - WM_CLOSE %d\n", pRLWinPriv
->fClose
);
444 /* Tell window-manager to close window */
445 if (pRLWinPriv
->fClose
) {
449 if (winIsInternalWMRunning(pScreenInfo
)) {
450 /* Tell our Window Manager thread to kill the window */
451 wmMsg
.msg
= WM_WM_KILL
;
452 if (fWMMsgInitialized
)
453 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
455 winWindowsWMSendEvent(WindowsWMControllerNotify
,
456 WindowsWMControllerNotifyMask
,
458 WindowsWMCloseWindow
,
459 pWin
->drawable
.id
, 0, 0, 0, 0);
464 #if CYGMULTIWINDOW_DEBUG
465 winDebug("winMWExtWMWindowProc - WM_DESTROY\n");
467 /* Free the shaodw DC; which allows the bitmap to be freed */
468 DeleteDC(pRLWinPriv
->hdcShadow
);
469 pRLWinPriv
->hdcShadow
= NULL
;
471 /* Free the shadow bitmap */
472 DeleteObject(pRLWinPriv
->hbmpShadow
);
473 pRLWinPriv
->hbmpShadow
= NULL
;
475 /* Free the screen DC */
476 ReleaseDC(pRLWinPriv
->hWnd
, pRLWinPriv
->hdcScreen
);
477 pRLWinPriv
->hdcScreen
= NULL
;
479 /* Free shadow buffer info header */
480 free(pRLWinPriv
->pbmihShadow
);
481 pRLWinPriv
->pbmihShadow
= NULL
;
483 pRLWinPriv
->fResized
= FALSE
;
484 pRLWinPriv
->pfb
= NULL
;
486 RemoveProp(hwnd
, WIN_WINDOW_PROP
);
490 #if CYGMULTIWINDOW_DEBUG && 0
491 winDebug("winMWExtWMWindowProc - WM_MOUSEMOVE\n");
493 /* Unpack the client area mouse coordinates */
494 ptMouse
.x
= GET_X_LPARAM(lParam
);
495 ptMouse
.y
= GET_Y_LPARAM(lParam
);
497 /* Translate the client area mouse coordinates to screen coordinates */
498 ClientToScreen(hwnd
, &ptMouse
);
500 /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
501 ptMouse
.x
-= GetSystemMetrics(SM_XVIRTUALSCREEN
);
502 ptMouse
.y
-= GetSystemMetrics(SM_YVIRTUALSCREEN
);
504 /* We can't do anything without privates */
505 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
508 /* Has the mouse pointer crossed screens? */
509 if (pScreen
!= miPointerGetScreen(inputInfo
.pointer
))
510 miPointerSetScreen(inputInfo
.pointer
, pScreenInfo
->dwScreen
,
511 ptMouse
.x
- pScreenInfo
->dwXOffset
,
512 ptMouse
.y
- pScreenInfo
->dwYOffset
);
514 /* Are we tracking yet? */
518 /* Setup data structure */
519 ZeroMemory(&tme
, sizeof(tme
));
520 tme
.cbSize
= sizeof(tme
);
521 tme
.dwFlags
= TME_LEAVE
;
522 tme
.hwndTrack
= hwnd
;
524 /* Call the tracking function */
525 if (!TrackMouseEvent(&tme
))
526 ErrorF("winMWExtWMWindowProc - TrackMouseEvent failed\n");
528 /* Flag that we are tracking now */
532 /* Kill the timer used to poll mouse events */
533 if (g_uipMousePollingTimerID
!= 0) {
534 KillTimer(pScreenPriv
->hwndScreen
, WIN_POLLING_MOUSE_TIMER_ID
);
535 g_uipMousePollingTimerID
= 0;
538 /* Deliver absolute cursor position to X Server */
539 winEnqueueMotion(ptMouse
.x
- pScreenInfo
->dwXOffset
,
540 ptMouse
.y
- pScreenInfo
->dwYOffset
);
545 #if CYGMULTIWINDOW_DEBUG && 0
546 winDebug("winMWExtWMWindowProc - WM_NCMOUSEMOVE\n");
549 * We break instead of returning 0 since we need to call
550 * DefWindowProc to get the mouse cursor changes
551 * and min/max/close button highlighting in Windows XP.
552 * The Platform SDK says that you should return 0 if you
553 * process this message, but it fails to mention that you
554 * will give up any default functionality if you do return 0.
557 /* We can't do anything without privates */
558 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
562 * Timer to poll mouse events. This is needed to make
563 * programs like xeyes follow the mouse properly.
565 if (g_uipMousePollingTimerID
== 0)
566 g_uipMousePollingTimerID
= SetTimer(pScreenPriv
->hwndScreen
,
567 WIN_POLLING_MOUSE_TIMER_ID
,
568 MOUSE_POLLING_INTERVAL
, NULL
);
572 #if CYGMULTIWINDOW_DEBUG
573 winDebug("winMWExtWMWindowProc - WM_MOUSELEAVE\n");
575 /* Mouse has left our client area */
577 /* Flag that we are no longer tracking */
581 * Timer to poll mouse events. This is needed to make
582 * programs like xeyes follow the mouse properly.
584 if (g_uipMousePollingTimerID
== 0)
585 g_uipMousePollingTimerID
= SetTimer(pScreenPriv
->hwndScreen
,
586 WIN_POLLING_MOUSE_TIMER_ID
,
587 MOUSE_POLLING_INTERVAL
, NULL
);
590 case WM_LBUTTONDBLCLK
:
592 #if CYGMULTIWINDOW_DEBUG
593 winDebug("winMWExtWMWindowProc - WM_LBUTTONDBLCLK\n");
595 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
598 return winMouseButtonsHandle(pScreen
, ButtonPress
, Button1
, wParam
);
601 #if CYGMULTIWINDOW_DEBUG
602 winDebug("winMWExtWMWindowProc - WM_LBUTTONUP\n");
604 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
607 return winMouseButtonsHandle(pScreen
, ButtonRelease
, Button1
, wParam
);
609 case WM_MBUTTONDBLCLK
:
611 #if CYGMULTIWINDOW_DEBUG
612 winDebug("winMWExtWMWindowProc - WM_MBUTTONDBLCLK\n");
614 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
617 return winMouseButtonsHandle(pScreen
, ButtonPress
, Button2
, wParam
);
620 #if CYGMULTIWINDOW_DEBUG
621 winDebug("winMWExtWMWindowProc - WM_MBUTTONUP\n");
623 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
626 return winMouseButtonsHandle(pScreen
, ButtonRelease
, Button2
, wParam
);
628 case WM_RBUTTONDBLCLK
:
630 #if CYGMULTIWINDOW_DEBUG
631 winDebug("winMWExtWMWindowProc - WM_RBUTTONDBLCLK\n");
633 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
636 return winMouseButtonsHandle(pScreen
, ButtonPress
, Button3
, wParam
);
639 #if CYGMULTIWINDOW_DEBUG
640 winDebug("winMWExtWMWindowProc - WM_RBUTTONUP\n");
642 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
645 return winMouseButtonsHandle(pScreen
, ButtonRelease
, Button3
, wParam
);
647 case WM_XBUTTONDBLCLK
:
649 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
652 return winMouseButtonsHandle(pScreen
, ButtonPress
, HIWORD(wParam
) + 7,
655 if (pScreenPriv
== NULL
|| pScreenInfo
->fIgnoreInput
)
658 return winMouseButtonsHandle(pScreen
, ButtonRelease
, HIWORD(wParam
) + 7,
662 #if CYGMULTIWINDOW_DEBUG
663 winDebug("winMWExtWMWindowProc - WM_MOUSEWHEEL\n");
666 /* Pass the message to the root window */
667 SendMessage(hwndScreen
, message
, wParam
, lParam
);
671 #if CYGMULTIWINDOW_DEBUG
672 winDebug("winMWExtWMWindowProc - WM_MOUSEHWHEEL\n");
675 /* Pass the message to the root window */
676 SendMessage(hwndScreen
, message
, wParam
, lParam
);
679 case WM_MOUSEACTIVATE
:
680 #if CYGMULTIWINDOW_DEBUG
681 winDebug("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n");
684 /* Check if this window needs to be made active when clicked */
685 if (winIsInternalWMRunning(pScreenInfo
) && pWin
->overrideRedirect
) {
686 #if CYGMULTIWINDOW_DEBUG
687 winDebug("winMWExtWMWindowProc - WM_MOUSEACTIVATE - "
692 return MA_NOACTIVATE
;
695 if (!winIsInternalWMRunning(pScreenInfo
) && !IsMouseActive(pWin
))
696 return MA_NOACTIVATE
;
701 /* Pop any pressed keys since we are losing keyboard focus */
702 winKeybdReleaseKeys();
708 * NOTE: We do nothing with WM_*CHAR messages,
709 * nor does the root window, so we can just toss these messages.
715 #if CYGMULTIWINDOW_DEBUG
716 winDebug("winMWExtWMWindowProc - WM_*KEYDOWN\n");
720 * Don't pass Alt-F4 key combo to root window,
721 * let Windows translate to WM_CLOSE and close this top-level window.
723 * NOTE: We purposely don't check the fUseWinKillKey setting because
724 * it should only apply to the key handling for the root window,
725 * not for top-level window-manager windows.
727 * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
728 * because that is a key combo that no X app should be expecting to
729 * receive, since it has historically been used to shutdown the X server.
730 * Passing Ctrl-Alt-Backspace to the root window preserves that
731 * behavior, assuming that -unixkill has been passed as a parameter.
733 if (wParam
== VK_F4
&& (GetKeyState(VK_MENU
) & 0x8000))
736 /* Pass the message to the root window */
737 SendMessage(hwndScreen
, message
, wParam
, lParam
);
743 #if CYGMULTIWINDOW_DEBUG
744 winDebug("winMWExtWMWindowProc - WM_*KEYUP\n");
747 /* Pass the message to the root window */
748 SendMessage(hwndScreen
, message
, wParam
, lParam
);
752 #if CYGMULTIWINDOW_DEBUG
753 winDebug("winMWExtWMWindowProc - WM_HOTKEY\n");
756 /* Pass the message to the root window */
757 SendMessage(hwndScreen
, message
, wParam
, lParam
);
762 winDebug("winMWExtWMWindowProc - WM_ERASEBKGND\n");
765 * Pretend that we did erase the background but we don't care,
766 * since we repaint the entire region anyhow
767 * This avoids some flickering when resizing.
773 /* BeginPaint gives us an hdc that clips to the invalidated region */
774 hdcUpdate
= BeginPaint(hwnd
, &ps
);
776 /* Try to copy from the shadow buffer */
777 if (!BitBlt(hdcUpdate
,
778 ps
.rcPaint
.left
, ps
.rcPaint
.top
,
779 ps
.rcPaint
.right
- ps
.rcPaint
.left
,
780 ps
.rcPaint
.bottom
- ps
.rcPaint
.top
,
781 pRLWinPriv
->hdcShadow
,
782 ps
.rcPaint
.left
, ps
.rcPaint
.top
, SRCCOPY
)) {
785 /* Display a fancy error message */
786 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
787 FORMAT_MESSAGE_FROM_SYSTEM
|
788 FORMAT_MESSAGE_IGNORE_INSERTS
,
791 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
792 (LPTSTR
) &lpMsgBuf
, 0, NULL
);
794 ErrorF("winMWExtWMWindowProc - BitBlt failed: %s\n",
799 /* EndPaint frees the DC */
804 #if CYGMULTIWINDOW_DEBUG
805 winDebug("winMWExtWMWindowProc - WM_ACTIVATE\n");
807 if (LOWORD(wParam
) != WA_INACTIVE
) {
808 if (winIsInternalWMRunning(pScreenInfo
)) {
810 /* Raise the window to the top in Z order */
811 wmMsg
.msg
= WM_WM_RAISE
;
812 if (fWMMsgInitialized
)
813 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
815 /* Tell our Window Manager thread to activate the window */
816 wmMsg
.msg
= WM_WM_ACTIVATE
;
817 if (fWMMsgInitialized
)
818 if (!pWin
|| !pWin
->overrideRedirect
) /* for OOo menus */
819 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
821 winWindowsWMSendEvent(WindowsWMControllerNotify
,
822 WindowsWMControllerNotifyMask
,
824 WindowsWMActivateWindow
,
825 pWin
->drawable
.id
, 0, 0, 0, 0);
830 case WM_WINDOWPOSCHANGING
:
831 pWinPos
= (LPWINDOWPOS
) lParam
;
832 if (!(pWinPos
->flags
& SWP_NOZORDER
)) {
833 if (pRLWinPriv
->fRestackingNow
|| pScreenPriv
->fRestacking
) {
834 #if CYGMULTIWINDOW_DEBUG
835 winDebug("Win %p is now restacking.\n",
841 if (winIsInternalWMRunning(pScreenInfo
) || IsRaiseOnClick(pWin
)) {
842 #if CYGMULTIWINDOW_DEBUG
843 winDebug("Win %p has WINDOWSWM_RAISE_ON_CLICK.\n",
849 #if CYGMULTIWINDOW_DEBUG
850 winDebug("Win %p forbid to change z order (%p).\n",
852 pWinPos
->hwndInsertAfter
);
854 pWinPos
->flags
|= SWP_NOZORDER
;
860 #if CYGMULTIWINDOW_DEBUG
861 winDebug("winMWExtWMWindowProc - WM_MOVE - %d ms\n",
862 (unsigned int) GetTickCount());
864 if (g_fNoConfigureWindow
)
867 /* Bail if Windows window is not actually moving */
868 if (pRLWinPriv
->dwX
== (short) LOWORD(lParam
)
869 && pRLWinPriv
->dwY
== (short) HIWORD(lParam
))
872 /* Also bail if we're maximizing, we'll do the whole thing in WM_SIZE */
874 WINDOWPLACEMENT windPlace
;
876 windPlace
.length
= sizeof(WINDOWPLACEMENT
);
878 /* Get current window placement */
879 GetWindowPlacement(hwnd
, &windPlace
);
881 /* Bail if maximizing */
882 if (windPlace
.showCmd
== SW_MAXIMIZE
883 || windPlace
.showCmd
== SW_SHOWMAXIMIZED
)
888 #if CYGMULTIWINDOW_DEBUG
889 winDebug("\t(%d, %d)\n", (short) LOWORD(lParam
),
890 (short) HIWORD(lParam
));
892 if (!pRLWinPriv
->fMovingOrSizing
) {
893 if (winIsInternalWMRunning(pScreenInfo
))
894 winAdjustXWindow(pWin
, hwnd
);
896 winMWExtWMMoveXWindow(pWin
, (LOWORD(lParam
) - wBorderWidth(pWin
)
897 - GetSystemMetrics(SM_XVIRTUALSCREEN
)),
898 (HIWORD(lParam
) - wBorderWidth(pWin
)
899 - GetSystemMetrics(SM_YVIRTUALSCREEN
)));
904 #if CYGMULTIWINDOW_DEBUG || TRUE
905 winDebug("winMWExtWMWindowProc - WM_SHOWWINDOW - %d ms\n",
906 (unsigned int) GetTickCount());
908 /* Bail out if the window is being hidden */
912 if (!pScreenInfo
->fInternalWM
) //XXXX
915 winMWExtWMUpdateWindowDecoration(pRLWinPriv
, pScreenInfo
);
917 if (winIsInternalWMRunning(pScreenInfo
)) {
918 #if CYGMULTIWINDOW_DEBUG || TRUE
919 winDebug("\tMapWindow\n");
921 /* Tell X to map the window */
922 MapWindow(pWin
, wClient(pWin
));
924 if (!pRLWinPriv
->pFrame
->win
->overrideRedirect
)
925 /* Bring the Windows window to the foreground */
926 SetForegroundWindow(hwnd
);
928 /* Setup the Window Manager message */
929 wmMsg
.msg
= WM_WM_MAP
;
930 wmMsg
.iWidth
= pRLWinPriv
->pFrame
->width
;
931 wmMsg
.iHeight
= pRLWinPriv
->pFrame
->height
;
933 /* Tell our Window Manager thread to map the window */
934 if (fWMMsgInitialized
)
935 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
940 /* Need to legalize the size according to WM_NORMAL_HINTS */
941 /* for applications like xterm */
942 return ValidateSizing(hwnd
, pWin
, wParam
, lParam
);
944 case WM_WINDOWPOSCHANGED
:
946 pWinPos
= (LPWINDOWPOS
) lParam
;
947 #if CYGMULTIWINDOW_DEBUG
948 winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n");
949 winDebug("\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n",
950 (pWinPos
->flags
& SWP_DRAWFRAME
) ? "SWP_DRAWFRAME " : "",
951 (pWinPos
->flags
& SWP_FRAMECHANGED
) ? "SWP_FRAMECHANGED " : "",
952 (pWinPos
->flags
& SWP_HIDEWINDOW
) ? "SWP_HIDEWINDOW " : "",
953 (pWinPos
->flags
& SWP_NOACTIVATE
) ? "SWP_NOACTIVATE " : "",
954 (pWinPos
->flags
& SWP_NOCOPYBITS
) ? "SWP_NOCOPYBITS " : "",
955 (pWinPos
->flags
& SWP_NOMOVE
) ? "SWP_NOMOVE " : "",
957 flags
& SWP_NOOWNERZORDER
) ? "SWP_NOOWNERZORDER " : "",
958 (pWinPos
->flags
& SWP_NOSIZE
) ? "SWP_NOSIZE " : "",
959 (pWinPos
->flags
& SWP_NOREDRAW
) ? "SWP_NOREDRAW " : "",
961 flags
& SWP_NOSENDCHANGING
) ? "SWP_NOSENDCHANGING " : "",
962 (pWinPos
->flags
& SWP_NOZORDER
) ? "SWP_NOZORDER " : "",
963 (pWinPos
->flags
& SWP_SHOWWINDOW
) ? "SWP_SHOWWINDOW " : "");
964 winDebug("\tno_configure: %s\n", (g_fNoConfigureWindow
? "Yes" : "No"));
965 winDebug("\textend: (%d, %d, %d, %d)\n",
966 pWinPos
->x
, pWinPos
->y
, pWinPos
->cx
, pWinPos
->cy
);
969 if (pWinPos
->flags
& SWP_HIDEWINDOW
)
972 /* Reorder if window z order was changed */
973 if ((pScreenPriv
!= NULL
)
974 && !(pWinPos
->flags
& SWP_NOZORDER
)
975 && !(pWinPos
->flags
& SWP_SHOWWINDOW
)
976 && winIsInternalWMRunning(pScreenInfo
)) {
977 #if CYGMULTIWINDOW_DEBUG
978 winDebug("\twindow z order was changed\n");
980 if (pWinPos
->hwndInsertAfter
== HWND_TOP
981 || pWinPos
->hwndInsertAfter
== HWND_TOPMOST
982 || pWinPos
->hwndInsertAfter
== HWND_NOTOPMOST
) {
983 #if CYGMULTIWINDOW_DEBUG
984 winDebug("\traise to top\n");
986 /* Raise the window to the top in Z order */
987 wmMsg
.msg
= WM_WM_RAISE
;
988 if (fWMMsgInitialized
)
989 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
992 else if (pWinPos
->hwndInsertAfter
== HWND_BOTTOM
) {
995 /* Check if this window is top of X windows. */
996 HWND hWndAbove
= NULL
;
997 DWORD dwCurrentProcessID
= GetCurrentProcessId();
998 DWORD dwWindowProcessID
= 0;
1000 for (hWndAbove
= pWinPos
->hwndInsertAfter
;
1002 hWndAbove
= GetNextWindow(hWndAbove
, GW_HWNDPREV
)) {
1003 /* Ignore other XWin process's window */
1004 GetWindowThreadProcessId(hWndAbove
, &dwWindowProcessID
);
1006 if ((dwWindowProcessID
== dwCurrentProcessID
)
1007 && GetProp(hWndAbove
, WIN_WINDOW_PROP
)
1008 && !IsWindowVisible(hWndAbove
)
1009 && !IsIconic(hWndAbove
)) /* ignore minimized windows */
1012 /* If this is top of X windows in Windows stack,
1013 raise it in X stack. */
1014 if (hWndAbove
== NULL
) {
1015 #if CYGMULTIWINDOW_DEBUG
1016 winDebug("\traise to top\n");
1018 /* Raise the window to the top in Z order */
1019 wmMsg
.msg
= WM_WM_RAISE
;
1020 if (fWMMsgInitialized
)
1021 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
1027 if (!(pWinPos
->flags
& SWP_NOSIZE
)) {
1028 if (IsIconic(hwnd
)) {
1029 #if CYGMULTIWINDOW_DEBUG
1030 winDebug("\tIconic -> MINIMIZED\n");
1032 if (winIsInternalWMRunning(pScreenInfo
)) {
1033 /* Raise the window to the top in Z order */
1034 wmMsg
.msg
= WM_WM_LOWER
;
1035 if (fWMMsgInitialized
)
1036 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
1038 winWindowsWMSendEvent(WindowsWMControllerNotify
,
1039 WindowsWMControllerNotifyMask
,
1041 WindowsWMMinimizeWindow
,
1042 pWin
->drawable
.id
, 0, 0, 0, 0);
1044 else if (IsZoomed(hwnd
)) {
1045 #if CYGMULTIWINDOW_DEBUG
1046 winDebug("\tZoomed -> MAXIMIZED\n");
1048 winWindowsWMSendEvent(WindowsWMControllerNotify
,
1049 WindowsWMControllerNotifyMask
,
1051 WindowsWMMaximizeWindow
,
1052 pWin
->drawable
.id
, 0, 0, 0, 0);
1055 #if CYGMULTIWINDOW_DEBUG
1056 winDebug("\tnone -> RESTORED\n");
1058 winWindowsWMSendEvent(WindowsWMControllerNotify
,
1059 WindowsWMControllerNotifyMask
,
1061 WindowsWMRestoreWindow
,
1062 pWin
->drawable
.id
, 0, 0, 0, 0);
1065 if (!g_fNoConfigureWindow
) {
1067 if (!pRLWinPriv
->fMovingOrSizing
1068 /*&& (pWinPos->flags & SWP_SHOWWINDOW) */ ) {
1069 GetClientRect(hwnd
, &rcClient
);
1070 MapWindowPoints(hwnd
, HWND_DESKTOP
, (LPPOINT
) &rcClient
, 2);
1072 if (!(pWinPos
->flags
& SWP_NOMOVE
)
1073 && !(pWinPos
->flags
& SWP_NOSIZE
)) {
1074 #if CYGMULTIWINDOW_DEBUG
1075 winDebug("\tmove & resize\n");
1077 if (winIsInternalWMRunning(pScreenInfo
))
1078 winAdjustXWindow(pWin
, hwnd
);
1080 winMWExtWMMoveResizeXWindow(pWin
,
1085 (SM_XVIRTUALSCREEN
),
1090 (SM_YVIRTUALSCREEN
),
1091 rcClient
.right
- rcClient
.left
-
1092 wBorderWidth(pWin
) * 2,
1093 rcClient
.bottom
- rcClient
.top
-
1094 wBorderWidth(pWin
) * 2);
1096 else if (!(pWinPos
->flags
& SWP_NOMOVE
)) {
1097 #if CYGMULTIWINDOW_DEBUG
1098 winDebug("\tmove\n");
1100 if (winIsInternalWMRunning(pScreenInfo
))
1101 winAdjustXWindow(pWin
, hwnd
);
1103 winMWExtWMMoveResizeXWindow(pWin
,
1108 (SM_XVIRTUALSCREEN
),
1113 (SM_YVIRTUALSCREEN
),
1114 rcClient
.right
- rcClient
.left
-
1115 wBorderWidth(pWin
) * 2,
1116 rcClient
.bottom
- rcClient
.top
-
1117 wBorderWidth(pWin
) * 2);
1119 else if (!(pWinPos
->flags
& SWP_NOMOVE
)) {
1120 #if CYGMULTIWINDOW_DEBUG
1121 winDebug("\tmove\n");
1123 if (winIsInternalWMRunning(pScreenInfo
))
1124 winAdjustXWindow(pWin
, hwnd
);
1126 winMWExtWMMoveXWindow(pWin
,
1127 rcClient
.left
- wBorderWidth(pWin
)
1128 - GetSystemMetrics(SM_XVIRTUALSCREEN
),
1129 rcClient
.top
- wBorderWidth(pWin
)
1131 GetSystemMetrics(SM_YVIRTUALSCREEN
));
1133 else if (!(pWinPos
->flags
& SWP_NOSIZE
)) {
1134 #if CYGMULTIWINDOW_DEBUG
1135 winDebug("\tresize\n");
1137 if (winIsInternalWMRunning(pScreenInfo
))
1138 winAdjustXWindow(pWin
, hwnd
);
1140 winMWExtWMResizeXWindow(pWin
,
1141 rcClient
.right
- rcClient
.left
1142 - wBorderWidth(pWin
) * 2,
1143 rcClient
.bottom
- rcClient
.top
1144 - wBorderWidth(pWin
) * 2);
1149 #if CYGMULTIWINDOW_DEBUG
1150 winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED - done.\n");
1155 /* see dix/window.c */
1156 /* FIXME: Maximize/Restore? */
1157 #if CYGMULTIWINDOW_DEBUG
1158 winDebug("winMWExtWMWindowProc - WM_SIZE - %d ms\n",
1159 (unsigned int) GetTickCount());
1161 #if CYGMULTIWINDOW_DEBUG
1162 winDebug("\t(%d, %d) %d\n", (short) LOWORD(lParam
),
1163 (short) HIWORD(lParam
), g_fNoConfigureWindow
);
1165 if (g_fNoConfigureWindow
)
1168 /* Branch on type of resizing occurring */
1170 case SIZE_MINIMIZED
:
1171 #if CYGMULTIWINDOW_DEBUG
1172 winDebug("\tSIZE_MINIMIZED\n");
1174 if (winIsInternalWMRunning(pScreenInfo
)) {
1175 /* Raise the window to the top in Z order */
1176 wmMsg
.msg
= WM_WM_LOWER
;
1177 if (fWMMsgInitialized
)
1178 winSendMessageToWM(pScreenPriv
->pWMInfo
, &wmMsg
);
1180 winWindowsWMSendEvent(WindowsWMControllerNotify
,
1181 WindowsWMControllerNotifyMask
,
1183 WindowsWMMinimizeWindow
,
1185 0, 0, LOWORD(lParam
), HIWORD(lParam
));
1189 #if CYGMULTIWINDOW_DEBUG
1190 winDebug("\tSIZE_RESTORED\n");
1192 winWindowsWMSendEvent(WindowsWMControllerNotify
,
1193 WindowsWMControllerNotifyMask
,
1195 WindowsWMRestoreWindow
,
1197 0, 0, LOWORD(lParam
), HIWORD(lParam
));
1200 case SIZE_MAXIMIZED
:
1201 #if CYGMULTIWINDOW_DEBUG
1202 winDebug("\tSIZE_MAXIMIZED\n");
1204 winWindowsWMSendEvent(WindowsWMControllerNotify
,
1205 WindowsWMControllerNotifyMask
,
1207 WindowsWMMaximizeWindow
,
1209 0, 0, LOWORD(lParam
), HIWORD(lParam
));
1213 /* Perform the resize and notify the X client */
1214 if (!pRLWinPriv
->fMovingOrSizing
) {
1215 if (winIsInternalWMRunning(pScreenInfo
))
1216 winAdjustXWindow(pWin
, hwnd
);
1218 winMWExtWMResizeXWindow(pWin
, (short) LOWORD(lParam
)
1219 - wBorderWidth(pWin
) * 2,
1220 (short) HIWORD(lParam
)
1221 - wBorderWidth(pWin
) * 2);
1225 case WM_ACTIVATEAPP
:
1226 #if CYGMULTIWINDOW_DEBUG
1227 winDebug("winMWExtWMWindowProc - WM_ACTIVATEAPP - %d ms\n",
1228 (unsigned int) GetTickCount());
1231 if (winIsInternalWMRunning(pScreenInfo
)) {
1235 winWindowsWMSendEvent(WindowsWMActivationNotify
,
1236 WindowsWMActivationNotifyMask
,
1239 pWin
->drawable
.id
, 0, 0, 0, 0);
1242 winWindowsWMSendEvent(WindowsWMActivationNotify
,
1243 WindowsWMActivationNotifyMask
,
1245 WindowsWMIsInactive
,
1246 pWin
->drawable
.id
, 0, 0, 0, 0);
1251 if (LOWORD(lParam
) == HTCLIENT
) {
1252 if (!g_fSoftwareCursor
)
1253 SetCursor(pScreenPriv
->cursor
.handle
);
1258 case WM_ENTERSIZEMOVE
:
1259 #if CYGMULTIWINDOW_DEBUG
1260 winDebug("winMWExtWMWindowProc - WM_ENTERSIZEMOVE - %d ms\n",
1261 (unsigned int) GetTickCount());
1263 pRLWinPriv
->fMovingOrSizing
= TRUE
;
1266 case WM_EXITSIZEMOVE
:
1267 #if CYGMULTIWINDOW_DEBUG
1268 winDebug("winMWExtWMWindowProc - WM_EXITSIZEMOVE - %d ms\n",
1269 (unsigned int) GetTickCount());
1271 pRLWinPriv
->fMovingOrSizing
= FALSE
;
1273 GetClientRect(hwnd
, &rcClient
);
1275 MapWindowPoints(hwnd
, HWND_DESKTOP
, (LPPOINT
) &rcClient
, 2);
1277 if (winIsInternalWMRunning(pScreenInfo
))
1278 winAdjustXWindow(pWin
, hwnd
);
1280 winMWExtWMMoveResizeXWindow(pWin
, rcClient
.left
- wBorderWidth(pWin
)
1281 - GetSystemMetrics(SM_XVIRTUALSCREEN
),
1282 rcClient
.top
- wBorderWidth(pWin
)
1283 - GetSystemMetrics(SM_YVIRTUALSCREEN
),
1284 rcClient
.right
- rcClient
.left
1285 - wBorderWidth(pWin
) * 2,
1286 rcClient
.bottom
- rcClient
.top
1287 - wBorderWidth(pWin
) * 2);
1291 ErrorF("winMWExtWMWindowProc - WM_MANAGE\n");
1295 ErrorF("winMWExtWMWindowProc - WM_UNMANAGE\n");
1302 return DefWindowProc(hwnd
, message
, wParam
, lParam
);