Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xwin / winwin32rootlesswndproc.c
blob859aafd290792049eed46aa68419f9aba61ed30d
1 /*
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
30 * Harold L Hunt II
32 #ifdef HAVE_XWIN_CONFIG_H
33 #include <xwin-config.h>
34 #endif
35 #include "win.h"
36 #include <winuser.h>
37 #define _WINDOWSWM_SERVER_
38 #include "windowswmstr.h"
39 #include "dixevents.h"
40 #include "propertyst.h"
41 #include <X11/Xatom.h>
42 #include "winmultiwindowclass.h"
43 #include "winmsg.h"
44 #include "inputstr.h"
48 * Constant defines
51 #define MOUSE_POLLING_INTERVAL 500
52 #define MOUSE_ACTIVATE_DEFAULT TRUE
53 #define RAISE_ON_CLICK_DEFAULT FALSE
57 * Global variables
60 extern Bool g_fNoConfigureWindow;
61 extern Bool g_fSoftwareCursor;
65 * Local globals
68 static UINT_PTR g_uipMousePollingTimerID = 0;
72 * Local function
75 DEFINE_ATOM_HELPER(AtmWindowsWmRaiseOnClick, WINDOWSWM_RAISE_ON_CLICK)
76 DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate, WINDOWSWM_MOUSE_ACTIVATE)
77 /* DEFINE_ATOM_HELPER(AtmWindowsWMClientWindow, WINDOWSWM_CLIENT_WINDOW) */
80 * ConstrainSize - Taken from TWM sources - Respects hints for sizing
82 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
83 static void
84 ConstrainSize (WinXSizeHints hints, int *widthp, int *heightp)
86 int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
87 int baseWidth, baseHeight;
88 int dwidth = *widthp, dheight = *heightp;
90 if (hints.flags & PMinSize)
92 minWidth = hints.min_width;
93 minHeight = hints.min_height;
95 else if (hints.flags & PBaseSize)
97 minWidth = hints.base_width;
98 minHeight = hints.base_height;
100 else
101 minWidth = minHeight = 1;
103 if (hints.flags & PBaseSize)
105 baseWidth = hints.base_width;
106 baseHeight = hints.base_height;
108 else if (hints.flags & PMinSize)
110 baseWidth = hints.min_width;
111 baseHeight = hints.min_height;
113 else
114 baseWidth = baseHeight = 0;
116 if (hints.flags & PMaxSize)
118 maxWidth = hints.max_width;
119 maxHeight = hints.max_height;
121 else
123 maxWidth = MAXINT;
124 maxHeight = MAXINT;
127 if (hints.flags & PResizeInc)
129 xinc = hints.width_inc;
130 yinc = hints.height_inc;
132 else
133 xinc = yinc = 1;
136 * First, clamp to min and max values
138 if (dwidth < minWidth)
139 dwidth = minWidth;
140 if (dheight < minHeight)
141 dheight = minHeight;
143 if (dwidth > maxWidth)
144 dwidth = maxWidth;
145 if (dheight > maxHeight)
146 dheight = maxHeight;
149 * Second, fit to base + N * inc
151 dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
152 dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
155 * Third, adjust for aspect ratio
159 * The math looks like this:
161 * minAspectX dwidth maxAspectX
162 * ---------- <= ------- <= ----------
163 * minAspectY dheight maxAspectY
165 * If that is multiplied out, then the width and height are
166 * invalid in the following situations:
168 * minAspectX * dheight > minAspectY * dwidth
169 * maxAspectX * dheight < maxAspectY * dwidth
173 if (hints.flags & PAspect)
175 if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth)
177 delta = makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - dwidth, xinc);
178 if (dwidth + delta <= maxWidth)
179 dwidth += delta;
180 else
182 delta = makemult(dheight - dwidth*hints.min_aspect.y/hints.min_aspect.x, yinc);
183 if (dheight - delta >= minHeight)
184 dheight -= delta;
188 if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth)
190 delta = makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - dheight, yinc);
191 if (dheight + delta <= maxHeight)
192 dheight += delta;
193 else
195 delta = makemult(dwidth - hints.max_aspect.x*dheight/hints.max_aspect.y, xinc);
196 if (dwidth - delta >= minWidth)
197 dwidth -= delta;
202 /* Return computed values */
203 *widthp = dwidth;
204 *heightp = dheight;
206 #undef makemult
211 * ValidateSizing - Ensures size request respects hints
213 static int
214 ValidateSizing (HWND hwnd, WindowPtr pWin,
215 WPARAM wParam, LPARAM lParam)
217 WinXSizeHints sizeHints;
218 RECT *rect;
219 int iWidth, iHeight, iTopBorder;
220 POINT pt;
222 /* Invalid input checking */
223 if (pWin==NULL || lParam==0)
225 ErrorF ("Invalid input checking\n");
226 return FALSE;
229 /* No size hints, no checking */
230 if (!winMultiWindowGetWMNormalHints (pWin, &sizeHints))
232 ErrorF ("No size hints, no checking\n");
233 return FALSE;
236 /* Avoid divide-by-zero */
237 if (sizeHints.flags & PResizeInc)
239 if (sizeHints.width_inc == 0) sizeHints.width_inc = 1;
240 if (sizeHints.height_inc == 0) sizeHints.height_inc = 1;
243 rect = (RECT*)lParam;
245 iWidth = rect->right - rect->left;
246 iHeight = rect->bottom - rect->top;
248 /* Get title bar height, there must be an easier way?! */
249 pt.x = pt.y = 0;
250 ClientToScreen(hwnd, &pt);
251 iTopBorder = pt.y - rect->top;
253 /* Now remove size of any borders */
254 iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME);
255 iHeight -= GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
257 /* Constrain the size to legal values */
258 ConstrainSize (sizeHints, &iWidth, &iHeight);
260 /* Add back the borders */
261 iWidth += 2 * GetSystemMetrics(SM_CXSIZEFRAME);
262 iHeight += GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
264 /* Adjust size according to where we're dragging from */
265 switch(wParam) {
266 case WMSZ_TOP:
267 case WMSZ_TOPRIGHT:
268 case WMSZ_BOTTOM:
269 case WMSZ_BOTTOMRIGHT:
270 case WMSZ_RIGHT:
271 rect->right = rect->left + iWidth;
272 break;
273 default:
274 rect->left = rect->right - iWidth;
275 break;
277 switch(wParam) {
278 case WMSZ_BOTTOM:
279 case WMSZ_BOTTOMRIGHT:
280 case WMSZ_BOTTOMLEFT:
281 case WMSZ_RIGHT:
282 case WMSZ_LEFT:
283 rect->bottom = rect->top + iHeight;
284 break;
285 default:
286 rect->top = rect->bottom - iHeight;
287 break;
289 return TRUE;
294 * IsRaiseOnClick
297 static Bool
298 IsRaiseOnClick (WindowPtr pWin)
301 struct _Window *pwin;
302 struct _Property *prop;
303 WindowPtr pRoot = GetCurrentRootWindow ();
305 if (!pWin)
307 ErrorF ("IsRaiseOnClick - no prop use default value:%d\n",
308 RAISE_ON_CLICK_DEFAULT);
309 return RAISE_ON_CLICK_DEFAULT;
312 pwin = (struct _Window*) pWin;
314 if (pwin->optional)
315 prop = (struct _Property *) pwin->optional->userProps;
316 else
317 prop = NULL;
319 while (prop)
321 if (prop->propertyName == AtmWindowsWmRaiseOnClick ()
322 && prop->type == XA_INTEGER
323 && prop->format == 32)
325 return *(int*)prop->data;
327 else
328 prop = prop->next;
331 if (pWin != pRoot)
333 return IsRaiseOnClick (pRoot);
335 else
337 #if CYGMULTIWINDOW_DEBUG
338 winDebug ("IsRaiseOnClick - no prop use default value:%d\n",
339 RAISE_ON_CLICK_DEFAULT);
340 #endif
341 return RAISE_ON_CLICK_DEFAULT;
347 * IsMouseActive
350 static Bool
351 IsMouseActive (WindowPtr pWin)
354 struct _Window *pwin;
355 struct _Property *prop;
356 WindowPtr pRoot = GetCurrentRootWindow ();
358 if (!pWin)
360 ErrorF ("IsMouseActive - pWin was NULL use default value:%d\n",
361 MOUSE_ACTIVATE_DEFAULT);
362 return MOUSE_ACTIVATE_DEFAULT;
365 pwin = (struct _Window*) pWin;
367 if (pwin->optional)
368 prop = (struct _Property *) pwin->optional->userProps;
369 else
370 prop = NULL;
372 while (prop)
374 if (prop->propertyName == AtmWindowsWMMouseActivate ()
375 && prop->type == XA_INTEGER
376 && prop->format == 32)
378 return *(int*)prop->data;
380 else
381 prop = prop->next;
384 if (pWin != pRoot)
386 return IsMouseActive (pRoot);
388 else
390 #if CYGMULTIWINDOW_DEBUG
391 winDebug ("IsMouseActive - no prop use default value:%d\n",
392 MOUSE_ACTIVATE_DEFAULT);
393 #endif
394 return MOUSE_ACTIVATE_DEFAULT;
400 * winMWExtWMWindowProc - Window procedure
403 LRESULT CALLBACK
404 winMWExtWMWindowProc (HWND hwnd, UINT message,
405 WPARAM wParam, LPARAM lParam)
407 WindowPtr pWin = NULL;
408 win32RootlessWindowPtr pRLWinPriv = NULL;
409 ScreenPtr pScreen = NULL;
410 winPrivScreenPtr pScreenPriv = NULL;
411 winScreenInfo *pScreenInfo = NULL;
412 HWND hwndScreen = NULL;
413 POINT ptMouse;
414 static Bool s_fTracking = FALSE;
415 HDC hdcUpdate;
416 PAINTSTRUCT ps;
417 LPWINDOWPOS pWinPos = NULL;
418 RECT rcClient;
419 winWMMessageRec wmMsg;
420 Bool fWMMsgInitialized = FALSE;
422 /* Check if the Windows window property for our X window pointer is valid */
423 if ((pRLWinPriv = (win32RootlessWindowPtr)GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
425 pWin = pRLWinPriv->pFrame->win;
426 pScreen = pWin->drawable.pScreen;
427 if (pScreen) pScreenPriv = winGetScreenPriv(pScreen);
428 if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
429 if (pScreenPriv) hwndScreen = pScreenPriv->hwndScreen;
431 wmMsg.msg = 0;
432 wmMsg.hwndWindow = hwnd;
433 wmMsg.iWindow = (Window)pWin->drawable.id;
435 wmMsg.iX = pRLWinPriv->pFrame->x;
436 wmMsg.iY = pRLWinPriv->pFrame->y;
437 wmMsg.iWidth = pRLWinPriv->pFrame->width;
438 wmMsg.iHeight = pRLWinPriv->pFrame->height;
440 fWMMsgInitialized = TRUE;
441 #if CYGDEBUG
442 winDebugWin32Message("winMWExtWMWindowProc", hwnd, message, wParam, lParam);
444 winDebug ("\thWnd %08X\n", hwnd);
445 winDebug ("\tpScreenPriv %08X\n", pScreenPriv);
446 winDebug ("\tpScreenInfo %08X\n", pScreenInfo);
447 winDebug ("\thwndScreen %08X\n", hwndScreen);
448 winDebug ("winMWExtWMWindowProc (%08x) %08x %08x %08x\n",
449 pRLWinPriv, message, wParam, lParam);
450 #endif
452 /* Branch on message type */
453 switch (message)
455 case WM_CREATE:
456 #if CYGMULTIWINDOW_DEBUG
457 winDebug ("winMWExtWMWindowProc - WM_CREATE\n");
458 #endif
459 /* */
460 SetProp (hwnd,
461 WIN_WINDOW_PROP,
462 (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams);
463 return 0;
465 case WM_CLOSE:
466 #if CYGMULTIWINDOW_DEBUG
467 winDebug ("winMWExtWMWindowProc - WM_CLOSE %d\n", pRLWinPriv->fClose);
468 #endif
469 /* Tell window-manager to close window */
470 if (pRLWinPriv->fClose)
472 DestroyWindow (hwnd);
474 else
476 if (winIsInternalWMRunning(pScreenInfo))
478 /* Tell our Window Manager thread to kill the window */
479 wmMsg.msg = WM_WM_KILL;
480 if (fWMMsgInitialized)
481 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
483 winWindowsWMSendEvent(WindowsWMControllerNotify,
484 WindowsWMControllerNotifyMask,
486 WindowsWMCloseWindow,
487 pWin->drawable.id,
488 0, 0, 0, 0);
490 return 0;
492 case WM_DESTROY:
493 #if CYGMULTIWINDOW_DEBUG
494 winDebug ("winMWExtWMWindowProc - WM_DESTROY\n");
495 #endif
496 /* Free the shaodw DC; which allows the bitmap to be freed */
497 DeleteDC (pRLWinPriv->hdcShadow);
498 pRLWinPriv->hdcShadow = NULL;
500 /* Free the shadow bitmap */
501 DeleteObject (pRLWinPriv->hbmpShadow);
502 pRLWinPriv->hbmpShadow = NULL;
504 /* Free the screen DC */
505 ReleaseDC (pRLWinPriv->hWnd, pRLWinPriv->hdcScreen);
506 pRLWinPriv->hdcScreen = NULL;
508 /* Free shadow buffer info header */
509 free (pRLWinPriv->pbmihShadow);
510 pRLWinPriv->pbmihShadow = NULL;
512 pRLWinPriv->fResized = FALSE;
513 pRLWinPriv->pfb = NULL;
514 free (pRLWinPriv);
515 RemoveProp (hwnd, WIN_WINDOW_PROP);
516 break;
518 case WM_MOUSEMOVE:
519 #if CYGMULTIWINDOW_DEBUG && 0
520 winDebug ("winMWExtWMWindowProc - WM_MOUSEMOVE\n");
521 #endif
522 /* Unpack the client area mouse coordinates */
523 ptMouse.x = GET_X_LPARAM(lParam);
524 ptMouse.y = GET_Y_LPARAM(lParam);
526 /* Translate the client area mouse coordinates to screen coordinates */
527 ClientToScreen (hwnd, &ptMouse);
529 /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
530 ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
531 ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
533 /* We can't do anything without privates */
534 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
535 break;
537 /* Has the mouse pointer crossed screens? */
538 if (pScreen != miPointerGetScreen(inputInfo.pointer))
539 miPointerSetScreen (inputInfo.pointer, pScreenInfo->dwScreen,
540 ptMouse.x - pScreenInfo->dwXOffset,
541 ptMouse.y - pScreenInfo->dwYOffset);
543 /* Are we tracking yet? */
544 if (!s_fTracking)
546 TRACKMOUSEEVENT tme;
548 /* Setup data structure */
549 ZeroMemory (&tme, sizeof (tme));
550 tme.cbSize = sizeof (tme);
551 tme.dwFlags = TME_LEAVE;
552 tme.hwndTrack = hwnd;
554 /* Call the tracking function */
555 if (!(*g_fpTrackMouseEvent) (&tme))
556 ErrorF ("winMWExtWMWindowProc - _TrackMouseEvent failed\n");
558 /* Flag that we are tracking now */
559 s_fTracking = TRUE;
562 /* Kill the timer used to poll mouse events */
563 if (g_uipMousePollingTimerID != 0)
565 KillTimer (pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
566 g_uipMousePollingTimerID = 0;
569 /* Deliver absolute cursor position to X Server */
570 miPointerAbsoluteCursor (ptMouse.x - pScreenInfo->dwXOffset,
571 ptMouse.y - pScreenInfo->dwYOffset,
572 g_c32LastInputEventTime = GetTickCount ());
573 return 0;
575 case WM_NCMOUSEMOVE:
576 #if CYGMULTIWINDOW_DEBUG && 0
577 winDebug ("winMWExtWMWindowProc - WM_NCMOUSEMOVE\n");
578 #endif
580 * We break instead of returning 0 since we need to call
581 * DefWindowProc to get the mouse cursor changes
582 * and min/max/close button highlighting in Windows XP.
583 * The Platform SDK says that you should return 0 if you
584 * process this message, but it fails to mention that you
585 * will give up any default functionality if you do return 0.
588 /* We can't do anything without privates */
589 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
590 break;
593 * Timer to poll mouse events. This is needed to make
594 * programs like xeyes follow the mouse properly.
596 if (g_uipMousePollingTimerID == 0)
597 g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen,
598 WIN_POLLING_MOUSE_TIMER_ID,
599 MOUSE_POLLING_INTERVAL,
600 NULL);
601 break;
603 case WM_MOUSELEAVE:
604 #if CYGMULTIWINDOW_DEBUG
605 winDebug ("winMWExtWMWindowProc - WM_MOUSELEAVE\n");
606 #endif
607 /* Mouse has left our client area */
609 /* Flag that we are no longer tracking */
610 s_fTracking = FALSE;
613 * Timer to poll mouse events. This is needed to make
614 * programs like xeyes follow the mouse properly.
616 if (g_uipMousePollingTimerID == 0)
617 g_uipMousePollingTimerID = SetTimer (pScreenPriv->hwndScreen,
618 WIN_POLLING_MOUSE_TIMER_ID,
619 MOUSE_POLLING_INTERVAL,
620 NULL);
621 return 0;
623 case WM_LBUTTONDBLCLK:
624 case WM_LBUTTONDOWN:
625 #if CYGMULTIWINDOW_DEBUG
626 winDebug ("winMWExtWMWindowProc - WM_LBUTTONDBLCLK\n");
627 #endif
628 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
629 break;
630 SetCapture (hwnd);
631 return winMouseButtonsHandle (pScreen, ButtonPress, Button1, wParam);
633 case WM_LBUTTONUP:
634 #if CYGMULTIWINDOW_DEBUG
635 winDebug ("winMWExtWMWindowProc - WM_LBUTTONUP\n");
636 #endif
637 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
638 break;
639 ReleaseCapture ();
640 return winMouseButtonsHandle (pScreen, ButtonRelease, Button1, wParam);
642 case WM_MBUTTONDBLCLK:
643 case WM_MBUTTONDOWN:
644 #if CYGMULTIWINDOW_DEBUG
645 winDebug ("winMWExtWMWindowProc - WM_MBUTTONDBLCLK\n");
646 #endif
647 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
648 break;
649 SetCapture (hwnd);
650 return winMouseButtonsHandle (pScreen, ButtonPress, Button2, wParam);
652 case WM_MBUTTONUP:
653 #if CYGMULTIWINDOW_DEBUG
654 winDebug ("winMWExtWMWindowProc - WM_MBUTTONUP\n");
655 #endif
656 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
657 break;
658 ReleaseCapture ();
659 return winMouseButtonsHandle (pScreen, ButtonRelease, Button2, wParam);
661 case WM_RBUTTONDBLCLK:
662 case WM_RBUTTONDOWN:
663 #if CYGMULTIWINDOW_DEBUG
664 winDebug ("winMWExtWMWindowProc - WM_RBUTTONDBLCLK\n");
665 #endif
666 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
667 break;
668 SetCapture (hwnd);
669 return winMouseButtonsHandle (pScreen, ButtonPress, Button3, wParam);
671 case WM_RBUTTONUP:
672 #if CYGMULTIWINDOW_DEBUG
673 winDebug ("winMWExtWMWindowProc - WM_RBUTTONUP\n");
674 #endif
675 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
676 break;
677 ReleaseCapture ();
678 return winMouseButtonsHandle (pScreen, ButtonRelease, Button3, wParam);
680 case WM_XBUTTONDBLCLK:
681 case WM_XBUTTONDOWN:
682 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
683 break;
684 SetCapture (hwnd);
685 return winMouseButtonsHandle (pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
686 case WM_XBUTTONUP:
687 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
688 break;
689 ReleaseCapture ();
690 return winMouseButtonsHandle (pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
692 case WM_MOUSEWHEEL:
693 #if CYGMULTIWINDOW_DEBUG
694 winDebug ("winMWExtWMWindowProc - WM_MOUSEWHEEL\n");
695 #endif
697 /* Pass the message to the root window */
698 SendMessage (hwndScreen, message, wParam, lParam);
699 return 0;
701 case WM_MOUSEACTIVATE:
702 #if CYGMULTIWINDOW_DEBUG
703 winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n");
704 #endif
705 #if 1
706 /* Check if this window needs to be made active when clicked */
707 if (winIsInternalWMRunning(pScreenInfo) && pWin->overrideRedirect)
709 #if CYGMULTIWINDOW_DEBUG
710 winDebug ("winMWExtWMWindowProc - WM_MOUSEACTIVATE - "
711 "MA_NOACTIVATE\n");
712 #endif
714 /* */
715 return MA_NOACTIVATE;
717 #endif
718 if (!winIsInternalWMRunning(pScreenInfo) && !IsMouseActive (pWin))
719 return MA_NOACTIVATE;
721 break;
723 case WM_KILLFOCUS:
724 /* Pop any pressed keys since we are losing keyboard focus */
725 winKeybdReleaseKeys ();
726 return 0;
728 case WM_SYSDEADCHAR:
729 case WM_DEADCHAR:
731 * NOTE: We do nothing with WM_*CHAR messages,
732 * nor does the root window, so we can just toss these messages.
734 return 0;
736 case WM_SYSKEYDOWN:
737 case WM_KEYDOWN:
738 #if CYGMULTIWINDOW_DEBUG
739 winDebug ("winMWExtWMWindowProc - WM_*KEYDOWN\n");
740 #endif
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))
757 break;
759 /* Pass the message to the root window */
760 SendMessage (hwndScreen, message, wParam, lParam);
761 return 0;
763 case WM_SYSKEYUP:
764 case WM_KEYUP:
766 #if CYGMULTIWINDOW_DEBUG
767 winDebug ("winMWExtWMWindowProc - WM_*KEYUP\n");
768 #endif
770 /* Pass the message to the root window */
771 SendMessage (hwndScreen, message, wParam, lParam);
772 return 0;
774 case WM_HOTKEY:
775 #if CYGMULTIWINDOW_DEBUG
776 winDebug ("winMWExtWMWindowProc - WM_HOTKEY\n");
777 #endif
779 /* Pass the message to the root window */
780 SendMessage (hwndScreen, message, wParam, lParam);
781 return 0;
783 case WM_PAINT:
785 /* BeginPaint gives us an hdc that clips to the invalidated region */
786 hdcUpdate = BeginPaint (hwnd, &ps);
788 /* Try to copy from the shadow buffer */
789 if (!BitBlt (hdcUpdate,
790 ps.rcPaint.left, ps.rcPaint.top,
791 ps.rcPaint.right - ps.rcPaint.left,
792 ps.rcPaint.bottom - ps.rcPaint.top,
793 pRLWinPriv->hdcShadow,
794 ps.rcPaint.left, ps.rcPaint.top,
795 SRCCOPY))
797 LPVOID lpMsgBuf;
799 /* Display a fancy error message */
800 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
801 FORMAT_MESSAGE_FROM_SYSTEM |
802 FORMAT_MESSAGE_IGNORE_INSERTS,
803 NULL,
804 GetLastError (),
805 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
806 (LPTSTR) &lpMsgBuf,
807 0, NULL);
809 ErrorF ("winMWExtWMWindowProc - BitBlt failed: %s\n",
810 (LPSTR)lpMsgBuf);
811 LocalFree (lpMsgBuf);
814 /* EndPaint frees the DC */
815 EndPaint (hwnd, &ps);
816 break;
818 case WM_ACTIVATE:
819 #if CYGMULTIWINDOW_DEBUG
820 winDebug ("winMWExtWMWindowProc - WM_ACTIVATE\n");
821 #endif
822 if (LOWORD(wParam) != WA_INACTIVE)
824 if (winIsInternalWMRunning(pScreenInfo))
826 #if 0
827 /* Raise the window to the top in Z order */
828 wmMsg.msg = WM_WM_RAISE;
829 if (fWMMsgInitialized)
830 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
831 #endif
832 /* Tell our Window Manager thread to activate the window */
833 wmMsg.msg = WM_WM_ACTIVATE;
834 if (fWMMsgInitialized)
835 if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
836 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
838 winWindowsWMSendEvent(WindowsWMControllerNotify,
839 WindowsWMControllerNotifyMask,
841 WindowsWMActivateWindow,
842 pWin->drawable.id,
843 0, 0,
844 0, 0);
846 return 0;
848 #if 1
849 case WM_WINDOWPOSCHANGING:
850 pWinPos = (LPWINDOWPOS)lParam;
851 if (!(pWinPos->flags & SWP_NOZORDER))
853 if (pRLWinPriv->fRestackingNow || pScreenPriv->fRestacking)
855 #if CYGMULTIWINDOW_DEBUG
856 winDebug ("Win %08x is now restacking.\n", (unsigned int)pRLWinPriv);
857 #endif
858 break;
861 if (winIsInternalWMRunning(pScreenInfo) || IsRaiseOnClick (pWin))
863 #if CYGMULTIWINDOW_DEBUG
864 winDebug ("Win %08x has WINDOWSWM_RAISE_ON_CLICK.\n", (unsigned int)pRLWinPriv);
865 #endif
866 break;
869 #if CYGMULTIWINDOW_DEBUG
870 winDebug ("Win %08x forbid to change z order (%08x).\n",
871 (unsigned int)pRLWinPriv, (unsigned int)pWinPos->hwndInsertAfter);
872 #endif
873 pWinPos->flags |= SWP_NOZORDER;
875 break;
876 #endif
878 case WM_MOVE:
879 #if CYGMULTIWINDOW_DEBUG
880 winDebug ("winMWExtWMWindowProc - WM_MOVE - %d ms\n",
881 (unsigned int)GetTickCount ());
882 #endif
883 if (g_fNoConfigureWindow) break;
884 #if 0
885 /* Bail if Windows window is not actually moving */
886 if (pRLWinPriv->dwX == (short) LOWORD(lParam)
887 && pRLWinPriv->dwY == (short) HIWORD(lParam))
888 break;
890 /* Also bail if we're maximizing, we'll do the whole thing in WM_SIZE */
892 WINDOWPLACEMENT windPlace;
893 windPlace.length = sizeof (WINDOWPLACEMENT);
895 /* Get current window placement */
896 GetWindowPlacement (hwnd, &windPlace);
898 /* Bail if maximizing */
899 if (windPlace.showCmd == SW_MAXIMIZE
900 || windPlace.showCmd == SW_SHOWMAXIMIZED)
901 break;
903 #endif
905 #if CYGMULTIWINDOW_DEBUG
906 winDebug ("\t(%d, %d)\n", (short) LOWORD(lParam), (short) HIWORD(lParam));
907 #endif
908 if (!pRLWinPriv->fMovingOrSizing)
910 if (winIsInternalWMRunning(pScreenInfo))
911 winAdjustXWindow (pWin, hwnd);
913 winMWExtWMMoveXWindow (pWin,
914 (LOWORD(lParam) - wBorderWidth (pWin)
915 - GetSystemMetrics (SM_XVIRTUALSCREEN)),
916 (HIWORD(lParam) - wBorderWidth (pWin)
917 - GetSystemMetrics (SM_YVIRTUALSCREEN)));
919 return 0;
921 case WM_SHOWWINDOW:
922 #if CYGMULTIWINDOW_DEBUG || TRUE
923 winDebug ("winMWExtWMWindowProc - WM_SHOWWINDOW - %d ms\n",
924 (unsigned int)GetTickCount ());
925 #endif
926 /* Bail out if the window is being hidden */
927 if (!wParam)
928 return 0;
930 if (!pScreenInfo->fInternalWM)//XXXX
931 return 0;
933 winMWExtWMUpdateWindowDecoration (pRLWinPriv, pScreenInfo);
935 if (winIsInternalWMRunning(pScreenInfo))
937 #if CYGMULTIWINDOW_DEBUG || TRUE
938 winDebug ("\tMapWindow\n");
939 #endif
940 /* Tell X to map the window */
941 MapWindow (pWin, wClient(pWin));
943 if (!pRLWinPriv->pFrame->win->overrideRedirect)
944 /* Bring the Windows window to the foreground */
945 SetForegroundWindow (hwnd);
947 /* Setup the Window Manager message */
948 wmMsg.msg = WM_WM_MAP;
949 wmMsg.iWidth = pRLWinPriv->pFrame->width;
950 wmMsg.iHeight = pRLWinPriv->pFrame->height;
952 /* Tell our Window Manager thread to map the window */
953 if (fWMMsgInitialized)
954 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
956 break;
958 case WM_SIZING:
959 /* Need to legalize the size according to WM_NORMAL_HINTS */
960 /* for applications like xterm */
961 return ValidateSizing (hwnd, pWin, wParam, lParam);
963 case WM_WINDOWPOSCHANGED:
965 pWinPos = (LPWINDOWPOS) lParam;
966 #if CYGMULTIWINDOW_DEBUG
967 winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n");
968 winDebug("\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n",
969 (pWinPos->flags & SWP_DRAWFRAME)?"SWP_DRAWFRAME ":"",
970 (pWinPos->flags & SWP_FRAMECHANGED)?"SWP_FRAMECHANGED ":"",
971 (pWinPos->flags & SWP_HIDEWINDOW)?"SWP_HIDEWINDOW ":"",
972 (pWinPos->flags & SWP_NOACTIVATE)?"SWP_NOACTIVATE ":"",
973 (pWinPos->flags & SWP_NOCOPYBITS)?"SWP_NOCOPYBITS ":"",
974 (pWinPos->flags & SWP_NOMOVE)?"SWP_NOMOVE ":"",
975 (pWinPos->flags & SWP_NOOWNERZORDER)?"SWP_NOOWNERZORDER ":"",
976 (pWinPos->flags & SWP_NOSIZE)?"SWP_NOSIZE ":"",
977 (pWinPos->flags & SWP_NOREDRAW)?"SWP_NOREDRAW ":"",
978 (pWinPos->flags & SWP_NOSENDCHANGING)?"SWP_NOSENDCHANGING ":"",
979 (pWinPos->flags & SWP_NOZORDER)?"SWP_NOZORDER ":"",
980 (pWinPos->flags & SWP_SHOWWINDOW)?"SWP_SHOWWINDOW ":"");
981 winDebug("\tno_configure: %s\n", (g_fNoConfigureWindow?"Yes":"No"));
982 winDebug("\textend: (%d, %d, %d, %d)\n",
983 pWinPos->x, pWinPos->y, pWinPos->cx, pWinPos->cy);
985 #endif
986 if (pWinPos->flags & SWP_HIDEWINDOW) break;
988 /* Reorder if window z order was changed */
989 if ((pScreenPriv != NULL)
990 && !(pWinPos->flags & SWP_NOZORDER)
991 && !(pWinPos->flags & SWP_SHOWWINDOW)
992 && winIsInternalWMRunning(pScreenInfo))
994 #if CYGMULTIWINDOW_DEBUG
995 winDebug ("\twindow z order was changed\n");
996 #endif
997 if (pWinPos->hwndInsertAfter == HWND_TOP
998 ||pWinPos->hwndInsertAfter == HWND_TOPMOST
999 ||pWinPos->hwndInsertAfter == HWND_NOTOPMOST)
1001 #if CYGMULTIWINDOW_DEBUG
1002 winDebug ("\traise to top\n");
1003 #endif
1004 /* Raise the window to the top in Z order */
1005 wmMsg.msg = WM_WM_RAISE;
1006 if (fWMMsgInitialized)
1007 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1009 #if 1
1010 else if (pWinPos->hwndInsertAfter == HWND_BOTTOM)
1013 else
1015 /* Check if this window is top of X windows. */
1016 HWND hWndAbove = NULL;
1017 DWORD dwCurrentProcessID = GetCurrentProcessId ();
1018 DWORD dwWindowProcessID = 0;
1020 for (hWndAbove = pWinPos->hwndInsertAfter;
1021 hWndAbove != NULL;
1022 hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV))
1024 /* Ignore other XWin process's window */
1025 GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID);
1027 if ((dwWindowProcessID == dwCurrentProcessID)
1028 && GetProp (hWndAbove, WIN_WINDOW_PROP)
1029 && !IsWindowVisible (hWndAbove)
1030 && !IsIconic (hWndAbove) ) /* ignore minimized windows */
1031 break;
1033 /* If this is top of X windows in Windows stack,
1034 raise it in X stack. */
1035 if (hWndAbove == NULL)
1037 #if CYGMULTIWINDOW_DEBUG
1038 winDebug ("\traise to top\n");
1039 #endif
1040 /* Raise the window to the top in Z order */
1041 wmMsg.msg = WM_WM_RAISE;
1042 if (fWMMsgInitialized)
1043 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1046 #endif
1049 if (!(pWinPos->flags & SWP_NOSIZE)) {
1050 if (IsIconic(hwnd)){
1051 #if CYGMULTIWINDOW_DEBUG
1052 winDebug ("\tIconic -> MINIMIZED\n");
1053 #endif
1054 if (winIsInternalWMRunning(pScreenInfo))
1056 /* Raise the window to the top in Z order */
1057 wmMsg.msg = WM_WM_LOWER;
1058 if (fWMMsgInitialized)
1059 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1061 winWindowsWMSendEvent(WindowsWMControllerNotify,
1062 WindowsWMControllerNotifyMask,
1064 WindowsWMMinimizeWindow,
1065 pWin->drawable.id,
1066 0, 0, 0, 0);
1067 } else if (IsZoomed(hwnd)){
1068 #if CYGMULTIWINDOW_DEBUG
1069 winDebug ("\tZoomed -> MAXIMIZED\n");
1070 #endif
1071 winWindowsWMSendEvent(WindowsWMControllerNotify,
1072 WindowsWMControllerNotifyMask,
1074 WindowsWMMaximizeWindow,
1075 pWin->drawable.id,
1076 0, 0, 0, 0);
1077 } else {
1078 #if CYGMULTIWINDOW_DEBUG
1079 winDebug ("\tnone -> RESTORED\n");
1080 #endif
1081 winWindowsWMSendEvent(WindowsWMControllerNotify,
1082 WindowsWMControllerNotifyMask,
1084 WindowsWMRestoreWindow,
1085 pWin->drawable.id,
1086 0, 0, 0, 0);
1089 if (!g_fNoConfigureWindow ) {
1091 if (!pRLWinPriv->fMovingOrSizing
1092 /*&& (pWinPos->flags & SWP_SHOWWINDOW)*/) {
1093 GetClientRect (hwnd, &rcClient);
1094 MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2);
1096 if (!(pWinPos->flags & SWP_NOMOVE)
1097 &&!(pWinPos->flags & SWP_NOSIZE)) {
1098 #if CYGMULTIWINDOW_DEBUG
1099 winDebug ("\tmove & resize\n");
1100 #endif
1101 if (winIsInternalWMRunning(pScreenInfo))
1102 winAdjustXWindow (pWin, hwnd);
1104 winMWExtWMMoveResizeXWindow (pWin,
1105 rcClient.left - wBorderWidth (pWin)
1106 - GetSystemMetrics (SM_XVIRTUALSCREEN),
1107 rcClient.top - wBorderWidth (pWin)
1108 - GetSystemMetrics (SM_YVIRTUALSCREEN),
1109 rcClient.right - rcClient.left
1110 - wBorderWidth (pWin)*2,
1111 rcClient.bottom - rcClient.top
1112 - wBorderWidth (pWin)*2);
1113 } else if (!(pWinPos->flags & SWP_NOMOVE)) {
1114 #if CYGMULTIWINDOW_DEBUG
1115 winDebug ("\tmove\n");
1116 #endif
1117 if (winIsInternalWMRunning(pScreenInfo))
1118 winAdjustXWindow (pWin, hwnd);
1120 winMWExtWMMoveResizeXWindow (pWin,
1121 rcClient.left - wBorderWidth (pWin)
1122 - GetSystemMetrics (SM_XVIRTUALSCREEN),
1123 rcClient.top - wBorderWidth (pWin)
1124 - GetSystemMetrics (SM_YVIRTUALSCREEN),
1125 rcClient.right - rcClient.left
1126 - wBorderWidth (pWin)*2,
1127 rcClient.bottom - rcClient.top
1128 - wBorderWidth (pWin)*2);
1129 } else if (!(pWinPos->flags & SWP_NOMOVE)) {
1130 #if CYGMULTIWINDOW_DEBUG
1131 winDebug ("\tmove\n");
1132 #endif
1133 if (winIsInternalWMRunning(pScreenInfo))
1134 winAdjustXWindow (pWin, hwnd);
1136 winMWExtWMMoveXWindow (pWin,
1137 rcClient.left - wBorderWidth (pWin)
1138 - GetSystemMetrics (SM_XVIRTUALSCREEN),
1139 rcClient.top - wBorderWidth (pWin)
1140 - GetSystemMetrics (SM_YVIRTUALSCREEN));
1141 } else if (!(pWinPos->flags & SWP_NOSIZE)) {
1142 #if CYGMULTIWINDOW_DEBUG
1143 winDebug ("\tresize\n");
1144 #endif
1145 if (winIsInternalWMRunning(pScreenInfo))
1146 winAdjustXWindow (pWin, hwnd);
1148 winMWExtWMResizeXWindow (pWin,
1149 rcClient.right - rcClient.left
1150 - wBorderWidth (pWin)*2,
1151 rcClient.bottom - rcClient.top
1152 - wBorderWidth (pWin)*2);
1157 #if CYGMULTIWINDOW_DEBUG
1158 winDebug ("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED - done.\n");
1159 #endif
1160 return 0;
1162 case WM_SIZE:
1163 /* see dix/window.c */
1164 /* FIXME: Maximize/Restore? */
1165 #if CYGMULTIWINDOW_DEBUG
1166 winDebug ("winMWExtWMWindowProc - WM_SIZE - %d ms\n",
1167 (unsigned int)GetTickCount ());
1168 #endif
1169 #if CYGMULTIWINDOW_DEBUG
1170 winDebug ("\t(%d, %d) %d\n", (short) LOWORD(lParam), (short) HIWORD(lParam), g_fNoConfigureWindow);
1171 #endif
1172 if (g_fNoConfigureWindow) break;
1174 /* Branch on type of resizing occurring */
1175 switch (wParam)
1177 case SIZE_MINIMIZED:
1178 #if CYGMULTIWINDOW_DEBUG
1179 winDebug ("\tSIZE_MINIMIZED\n");
1180 #endif
1181 if (winIsInternalWMRunning(pScreenInfo))
1183 /* Raise the window to the top in Z order */
1184 wmMsg.msg = WM_WM_LOWER;
1185 if (fWMMsgInitialized)
1186 winSendMessageToWM (pScreenPriv->pWMInfo, &wmMsg);
1188 winWindowsWMSendEvent(WindowsWMControllerNotify,
1189 WindowsWMControllerNotifyMask,
1191 WindowsWMMinimizeWindow,
1192 pWin->drawable.id,
1193 0, 0,
1194 LOWORD(lParam), HIWORD(lParam));
1195 break;
1197 case SIZE_RESTORED:
1198 #if CYGMULTIWINDOW_DEBUG
1199 winDebug ("\tSIZE_RESTORED\n");
1200 #endif
1201 winWindowsWMSendEvent(WindowsWMControllerNotify,
1202 WindowsWMControllerNotifyMask,
1204 WindowsWMRestoreWindow,
1205 pWin->drawable.id,
1206 0, 0,
1207 LOWORD(lParam), HIWORD(lParam));
1208 break;
1210 case SIZE_MAXIMIZED:
1211 #if CYGMULTIWINDOW_DEBUG
1212 winDebug ("\tSIZE_MAXIMIZED\n");
1213 #endif
1214 winWindowsWMSendEvent(WindowsWMControllerNotify,
1215 WindowsWMControllerNotifyMask,
1217 WindowsWMMaximizeWindow,
1218 pWin->drawable.id,
1219 0, 0,
1220 LOWORD(lParam), HIWORD(lParam));
1221 break;
1224 /* Perform the resize and notify the X client */
1225 if (!pRLWinPriv->fMovingOrSizing)
1227 if (winIsInternalWMRunning(pScreenInfo))
1228 winAdjustXWindow (pWin, hwnd);
1230 winMWExtWMResizeXWindow (pWin,
1231 (short) LOWORD(lParam)
1232 - wBorderWidth (pWin)*2,
1233 (short) HIWORD(lParam)
1234 - wBorderWidth (pWin)*2);
1236 break;
1238 case WM_ACTIVATEAPP:
1239 #if CYGMULTIWINDOW_DEBUG
1240 winDebug ("winMWExtWMWindowProc - WM_ACTIVATEAPP - %d ms\n",
1241 (unsigned int)GetTickCount ());
1242 #endif
1243 if (wParam)
1245 if (winIsInternalWMRunning(pScreenInfo))
1248 else
1251 winWindowsWMSendEvent(WindowsWMActivationNotify,
1252 WindowsWMActivationNotifyMask,
1254 WindowsWMIsActive,
1255 pWin->drawable.id,
1256 0, 0,
1257 0, 0);
1259 else
1261 winWindowsWMSendEvent(WindowsWMActivationNotify,
1262 WindowsWMActivationNotifyMask,
1264 WindowsWMIsInactive,
1265 pWin->drawable.id,
1266 0, 0,
1267 0, 0);
1269 break;
1271 case WM_SETCURSOR:
1272 if (LOWORD(lParam) == HTCLIENT)
1274 if (!g_fSoftwareCursor) SetCursor (pScreenPriv->cursor.handle);
1275 return TRUE;
1277 break;
1279 case WM_ENTERSIZEMOVE:
1280 #if CYGMULTIWINDOW_DEBUG
1281 winDebug ("winMWExtWMWindowProc - WM_ENTERSIZEMOVE - %d ms\n",
1282 (unsigned int)GetTickCount ());
1283 #endif
1284 pRLWinPriv->fMovingOrSizing = TRUE;
1285 break;
1287 case WM_EXITSIZEMOVE:
1288 #if CYGMULTIWINDOW_DEBUG
1289 winDebug ("winMWExtWMWindowProc - WM_EXITSIZEMOVE - %d ms\n",
1290 (unsigned int)GetTickCount ());
1291 #endif
1292 pRLWinPriv->fMovingOrSizing = FALSE;
1294 GetClientRect (hwnd, &rcClient);
1296 MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rcClient, 2);
1298 if (winIsInternalWMRunning(pScreenInfo))
1299 winAdjustXWindow (pWin, hwnd);
1301 winMWExtWMMoveResizeXWindow (pWin,
1302 rcClient.left - wBorderWidth (pWin)
1303 - GetSystemMetrics (SM_XVIRTUALSCREEN),
1304 rcClient.top - wBorderWidth (pWin)
1305 - GetSystemMetrics (SM_YVIRTUALSCREEN),
1306 rcClient.right - rcClient.left
1307 - wBorderWidth (pWin)*2,
1308 rcClient.bottom - rcClient.top
1309 - wBorderWidth (pWin)*2);
1310 break;
1312 case WM_MANAGE:
1313 ErrorF ("winMWExtWMWindowProc - WM_MANAGE\n");
1314 break;
1316 case WM_UNMANAGE:
1317 ErrorF ("winMWExtWMWindowProc - WM_UNMANAGE\n");
1318 break;
1320 default:
1321 break;
1324 return DefWindowProc (hwnd, message, wParam, lParam);