First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xwin / winmultiwindowwndproc.c
blob0a7579b6198570869fa5cdf31a979744afd3a77d
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
33 #ifdef HAVE_XWIN_CONFIG_H
34 #include <xwin-config.h>
35 #endif
36 #include "win.h"
37 #include "dixevents.h"
38 #include "winmultiwindowclass.h"
39 #include "winprefs.h"
40 #include "winmsg.h"
41 #include "inputstr.h"
44 * External global variables
47 extern Bool g_fCursor;
48 extern Bool g_fKeyboardHookLL;
49 extern Bool g_fSoftwareCursor;
50 extern Bool g_fButton[3];
54 * Local globals
57 static UINT_PTR g_uipMousePollingTimerID = 0;
61 * Constant defines
64 #define MOUSE_POLLING_INTERVAL 500
65 #define WIN_MULTIWINDOW_SHAPE YES
69 * ConstrainSize - Taken from TWM sources - Respects hints for sizing
71 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
72 static void
73 ConstrainSize (WinXSizeHints hints, int *widthp, int *heightp)
75 int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
76 int baseWidth, baseHeight;
77 int dwidth = *widthp, dheight = *heightp;
79 if (hints.flags & PMinSize)
81 minWidth = hints.min_width;
82 minHeight = hints.min_height;
84 else if (hints.flags & PBaseSize)
86 minWidth = hints.base_width;
87 minHeight = hints.base_height;
89 else
90 minWidth = minHeight = 1;
92 if (hints.flags & PBaseSize)
94 baseWidth = hints.base_width;
95 baseHeight = hints.base_height;
97 else if (hints.flags & PMinSize)
99 baseWidth = hints.min_width;
100 baseHeight = hints.min_height;
102 else
103 baseWidth = baseHeight = 0;
105 if (hints.flags & PMaxSize)
107 maxWidth = hints.max_width;
108 maxHeight = hints.max_height;
110 else
112 maxWidth = MAXINT;
113 maxHeight = MAXINT;
116 if (hints.flags & PResizeInc)
118 xinc = hints.width_inc;
119 yinc = hints.height_inc;
121 else
122 xinc = yinc = 1;
125 * First, clamp to min and max values
127 if (dwidth < minWidth)
128 dwidth = minWidth;
129 if (dheight < minHeight)
130 dheight = minHeight;
132 if (dwidth > maxWidth)
133 dwidth = maxWidth;
134 if (dheight > maxHeight)
135 dheight = maxHeight;
138 * Second, fit to base + N * inc
140 dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
141 dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
144 * Third, adjust for aspect ratio
148 * The math looks like this:
150 * minAspectX dwidth maxAspectX
151 * ---------- <= ------- <= ----------
152 * minAspectY dheight maxAspectY
154 * If that is multiplied out, then the width and height are
155 * invalid in the following situations:
157 * minAspectX * dheight > minAspectY * dwidth
158 * maxAspectX * dheight < maxAspectY * dwidth
162 if (hints.flags & PAspect)
164 if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth)
166 delta = makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - dwidth, xinc);
167 if (dwidth + delta <= maxWidth)
168 dwidth += delta;
169 else
171 delta = makemult(dheight - dwidth*hints.min_aspect.y/hints.min_aspect.x, yinc);
172 if (dheight - delta >= minHeight)
173 dheight -= delta;
177 if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth)
179 delta = makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - dheight, yinc);
180 if (dheight + delta <= maxHeight)
181 dheight += delta;
182 else
184 delta = makemult(dwidth - hints.max_aspect.x*dheight/hints.max_aspect.y, xinc);
185 if (dwidth - delta >= minWidth)
186 dwidth -= delta;
191 /* Return computed values */
192 *widthp = dwidth;
193 *heightp = dheight;
195 #undef makemult
200 * ValidateSizing - Ensures size request respects hints
202 static int
203 ValidateSizing (HWND hwnd, WindowPtr pWin,
204 WPARAM wParam, LPARAM lParam)
206 WinXSizeHints sizeHints;
207 RECT *rect;
208 int iWidth, iHeight;
210 /* Invalid input checking */
211 if (pWin==NULL || lParam==0)
212 return FALSE;
214 /* No size hints, no checking */
215 if (!winMultiWindowGetWMNormalHints (pWin, &sizeHints))
216 return FALSE;
218 /* Avoid divide-by-zero */
219 if (sizeHints.flags & PResizeInc)
221 if (sizeHints.width_inc == 0) sizeHints.width_inc = 1;
222 if (sizeHints.height_inc == 0) sizeHints.height_inc = 1;
225 rect = (RECT*)lParam;
227 iWidth = rect->right - rect->left;
228 iHeight = rect->bottom - rect->top;
230 /* Now remove size of any borders */
231 iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME);
232 iHeight -= (GetSystemMetrics(SM_CYCAPTION)
233 + 2 * GetSystemMetrics(SM_CYSIZEFRAME));
236 /* Constrain the size to legal values */
237 ConstrainSize (sizeHints, &iWidth, &iHeight);
239 /* Add back the borders */
240 iWidth += 2 * GetSystemMetrics(SM_CXSIZEFRAME);
241 iHeight += (GetSystemMetrics(SM_CYCAPTION)
242 + 2 * GetSystemMetrics(SM_CYSIZEFRAME));
244 /* Adjust size according to where we're dragging from */
245 switch(wParam) {
246 case WMSZ_TOP:
247 case WMSZ_TOPRIGHT:
248 case WMSZ_BOTTOM:
249 case WMSZ_BOTTOMRIGHT:
250 case WMSZ_RIGHT:
251 rect->right = rect->left + iWidth;
252 break;
253 default:
254 rect->left = rect->right - iWidth;
255 break;
257 switch(wParam) {
258 case WMSZ_BOTTOM:
259 case WMSZ_BOTTOMRIGHT:
260 case WMSZ_BOTTOMLEFT:
261 case WMSZ_RIGHT:
262 case WMSZ_LEFT:
263 rect->bottom = rect->top + iHeight;
264 break;
265 default:
266 rect->top = rect->bottom - iHeight;
267 break;
269 return TRUE;
272 extern Bool winInDestroyWindowsWindow;
273 static Bool winInRaiseWindow = FALSE;
274 static void winRaiseWindow(WindowPtr pWin)
276 if (!winInDestroyWindowsWindow && !winInRaiseWindow)
278 BOOL oldstate = winInRaiseWindow;
279 winInRaiseWindow = TRUE;
280 /* Call configure window directly to make sure it gets processed
281 * in time
283 XID vlist[1] = { 0 };
284 ConfigureWindow(pWin, CWStackMode, vlist, serverClient);
285 winInRaiseWindow = oldstate;
291 * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
294 LRESULT CALLBACK
295 winTopLevelWindowProc (HWND hwnd, UINT message,
296 WPARAM wParam, LPARAM lParam)
298 POINT ptMouse;
299 HDC hdcUpdate;
300 PAINTSTRUCT ps;
301 WindowPtr pWin = NULL;
302 winPrivWinPtr pWinPriv = NULL;
303 ScreenPtr s_pScreen = NULL;
304 winPrivScreenPtr s_pScreenPriv = NULL;
305 winScreenInfo *s_pScreenInfo = NULL;
306 HWND hwndScreen = NULL;
307 DrawablePtr pDraw = NULL;
308 winWMMessageRec wmMsg;
309 Bool fWMMsgInitialized = FALSE;
310 static Bool s_fTracking = FALSE;
311 Bool needRestack = FALSE;
312 LRESULT ret;
314 #if CYGDEBUG
315 winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam, lParam);
316 #endif
318 /* Check if the Windows window property for our X window pointer is valid */
319 if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
321 /* Our X window pointer is valid */
323 /* Get pointers to the drawable and the screen */
324 pDraw = &pWin->drawable;
325 s_pScreen = pWin->drawable.pScreen;
327 /* Get a pointer to our window privates */
328 pWinPriv = winGetWindowPriv(pWin);
330 /* Get pointers to our screen privates and screen info */
331 s_pScreenPriv = pWinPriv->pScreenPriv;
332 s_pScreenInfo = s_pScreenPriv->pScreenInfo;
334 /* Get the handle for our screen-sized window */
335 hwndScreen = s_pScreenPriv->hwndScreen;
337 /* */
338 wmMsg.msg = 0;
339 wmMsg.hwndWindow = hwnd;
340 wmMsg.iWindow = (Window)GetProp (hwnd, WIN_WID_PROP);
342 wmMsg.iX = pDraw->x;
343 wmMsg.iY = pDraw->y;
344 wmMsg.iWidth = pDraw->width;
345 wmMsg.iHeight = pDraw->height;
347 fWMMsgInitialized = TRUE;
349 #if 0
351 * Print some debugging information
354 ErrorF ("hWnd %08X\n", hwnd);
355 ErrorF ("pWin %08X\n", pWin);
356 ErrorF ("pDraw %08X\n", pDraw);
357 ErrorF ("\ttype %08X\n", pWin->drawable.type);
358 ErrorF ("\tclass %08X\n", pWin->drawable.class);
359 ErrorF ("\tdepth %08X\n", pWin->drawable.depth);
360 ErrorF ("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
361 ErrorF ("\tid %08X\n", pWin->drawable.id);
362 ErrorF ("\tx %08X\n", pWin->drawable.x);
363 ErrorF ("\ty %08X\n", pWin->drawable.y);
364 ErrorF ("\twidth %08X\n", pWin->drawable.width);
365 ErrorF ("\thenght %08X\n", pWin->drawable.height);
366 ErrorF ("\tpScreen %08X\n", pWin->drawable.pScreen);
367 ErrorF ("\tserialNumber %08X\n", pWin->drawable.serialNumber);
368 ErrorF ("g_iWindowPrivateIndex %d\n", g_iWindowPrivateIndex);
369 ErrorF ("pWinPriv %08X\n", pWinPriv);
370 ErrorF ("s_pScreenPriv %08X\n", s_pScreenPriv);
371 ErrorF ("s_pScreenInfo %08X\n", s_pScreenInfo);
372 ErrorF ("hwndScreen %08X\n", hwndScreen);
373 #endif
376 /* Branch on message type */
377 switch (message)
379 case WM_CREATE:
381 /* */
382 SetProp (hwnd,
383 WIN_WINDOW_PROP,
384 (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams);
386 /* */
387 SetProp (hwnd,
388 WIN_WID_PROP,
389 (HANDLE)winGetWindowID (((LPCREATESTRUCT) lParam)->lpCreateParams));
392 * Make X windows' Z orders sync with Windows windows because
393 * there can be AlwaysOnTop windows overlapped on the window
394 * currently being created.
396 winReorderWindowsMultiWindow ();
398 /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
399 RECT rWindow;
400 HRGN hRgnWindow;
401 GetWindowRect(hwnd, &rWindow);
402 hRgnWindow = CreateRectRgnIndirect(&rWindow);
403 SetWindowRgn (hwnd, hRgnWindow, TRUE);
404 DeleteObject(hRgnWindow);
406 return 0;
408 case WM_INIT_SYS_MENU:
410 * Add whatever the setup file wants to for this window
412 SetupSysMenu ((unsigned long)hwnd);
413 return 0;
415 case WM_SYSCOMMAND:
417 * Any window menu items go through here
419 if (HandleCustomWM_COMMAND ((unsigned long)hwnd, LOWORD(wParam)))
421 /* Don't pass customized menus to DefWindowProc */
422 return 0;
424 if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE)
426 WINDOWPLACEMENT wndpl;
427 wndpl.length = sizeof(wndpl);
428 if (GetWindowPlacement(hwnd, &wndpl) && wndpl.showCmd == SW_SHOWMINIMIZED)
429 needRestack = TRUE;
431 break;
433 case WM_INITMENU:
434 /* Checks/Unchecks any menu items before they are displayed */
435 HandleCustomWM_INITMENU ((unsigned long)hwnd, wParam);
436 break;
438 case WM_PAINT:
439 /* Only paint if our window handle is valid */
440 if (hwndScreen == NULL)
441 break;
443 /* BeginPaint gives us an hdc that clips to the invalidated region */
444 hdcUpdate = BeginPaint (hwnd, &ps);
445 /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
446 if (ps.rcPaint.right==0 && ps.rcPaint.bottom==0 && ps.rcPaint.left==0 && ps.rcPaint.top==0)
448 EndPaint (hwnd, &ps);
449 return 0;
452 /* Try to copy from the shadow buffer */
453 if (!BitBlt (hdcUpdate,
454 ps.rcPaint.left, ps.rcPaint.top,
455 ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
456 s_pScreenPriv->hdcShadow,
457 ps.rcPaint.left + pWin->drawable.x, ps.rcPaint.top + pWin->drawable.y,
458 SRCCOPY))
460 LPVOID lpMsgBuf;
462 /* Display a fancy error message */
463 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
464 FORMAT_MESSAGE_FROM_SYSTEM |
465 FORMAT_MESSAGE_IGNORE_INSERTS,
466 NULL,
467 GetLastError (),
468 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
469 (LPTSTR) &lpMsgBuf,
470 0, NULL);
472 ErrorF ("winTopLevelWindowProc - BitBlt failed: %s\n",
473 (LPSTR)lpMsgBuf);
474 LocalFree (lpMsgBuf);
477 /* EndPaint frees the DC */
478 EndPaint (hwnd, &ps);
479 return 0;
481 case WM_MOUSEMOVE:
482 /* Unpack the client area mouse coordinates */
483 ptMouse.x = GET_X_LPARAM(lParam);
484 ptMouse.y = GET_Y_LPARAM(lParam);
486 /* Translate the client area mouse coordinates to screen coordinates */
487 ClientToScreen (hwnd, &ptMouse);
489 /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
490 ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
491 ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
493 /* We can't do anything without privates */
494 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
495 break;
497 /* Has the mouse pointer crossed screens? */
498 if (s_pScreen != miPointerGetScreen(inputInfo.pointer))
499 miPointerSetScreen (inputInfo.pointer, s_pScreenInfo->dwScreen,
500 ptMouse.x - s_pScreenInfo->dwXOffset,
501 ptMouse.y - s_pScreenInfo->dwYOffset);
503 /* Are we tracking yet? */
504 if (!s_fTracking)
506 TRACKMOUSEEVENT tme;
508 /* Setup data structure */
509 ZeroMemory (&tme, sizeof (tme));
510 tme.cbSize = sizeof (tme);
511 tme.dwFlags = TME_LEAVE;
512 tme.hwndTrack = hwnd;
514 /* Call the tracking function */
515 if (!(*g_fpTrackMouseEvent) (&tme))
516 ErrorF ("winTopLevelWindowProc - _TrackMouseEvent failed\n");
518 /* Flag that we are tracking now */
519 s_fTracking = TRUE;
522 /* Hide or show the Windows mouse cursor */
523 if (g_fSoftwareCursor && g_fCursor)
525 /* Hide Windows cursor */
526 g_fCursor = FALSE;
527 ShowCursor (FALSE);
530 /* Kill the timer used to poll mouse events */
531 if (g_uipMousePollingTimerID != 0)
533 KillTimer (s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
534 g_uipMousePollingTimerID = 0;
537 /* Deliver absolute cursor position to X Server */
538 miPointerAbsoluteCursor (ptMouse.x - s_pScreenInfo->dwXOffset,
539 ptMouse.y - s_pScreenInfo->dwYOffset,
540 g_c32LastInputEventTime = GetTickCount ());
541 return 0;
543 case WM_NCMOUSEMOVE:
545 * We break instead of returning 0 since we need to call
546 * DefWindowProc to get the mouse cursor changes
547 * and min/max/close button highlighting in Windows XP.
548 * The Platform SDK says that you should return 0 if you
549 * process this message, but it fails to mention that you
550 * will give up any default functionality if you do return 0.
553 /* We can't do anything without privates */
554 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
555 break;
557 /* Non-client mouse movement, show Windows cursor */
558 if (g_fSoftwareCursor && !g_fCursor)
560 g_fCursor = TRUE;
561 ShowCursor (TRUE);
565 * Timer to poll mouse events. This is needed to make
566 * programs like xeyes follow the mouse properly.
568 if (g_uipMousePollingTimerID == 0)
569 g_uipMousePollingTimerID = SetTimer (s_pScreenPriv->hwndScreen,
570 WIN_POLLING_MOUSE_TIMER_ID,
571 MOUSE_POLLING_INTERVAL,
572 NULL);
573 break;
575 case WM_MOUSELEAVE:
576 /* Mouse has left our client area */
578 /* Flag that we are no longer tracking */
579 s_fTracking = FALSE;
581 /* Show the mouse cursor, if necessary */
582 if (g_fSoftwareCursor && !g_fCursor)
584 g_fCursor = TRUE;
585 ShowCursor (TRUE);
589 * Timer to poll mouse events. This is needed to make
590 * programs like xeyes follow the mouse properly.
592 if (g_uipMousePollingTimerID == 0)
593 g_uipMousePollingTimerID = SetTimer (s_pScreenPriv->hwndScreen,
594 WIN_POLLING_MOUSE_TIMER_ID,
595 MOUSE_POLLING_INTERVAL,
596 NULL);
597 return 0;
599 case WM_LBUTTONDBLCLK:
600 case WM_LBUTTONDOWN:
601 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
602 break;
603 g_fButton[0] = TRUE;
604 return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam);
606 case WM_LBUTTONUP:
607 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
608 break;
609 g_fButton[0] = FALSE;
610 return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam);
612 case WM_MBUTTONDBLCLK:
613 case WM_MBUTTONDOWN:
614 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
615 break;
616 g_fButton[1] = TRUE;
617 return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam);
619 case WM_MBUTTONUP:
620 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
621 break;
622 g_fButton[1] = FALSE;
623 return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam);
625 case WM_RBUTTONDBLCLK:
626 case WM_RBUTTONDOWN:
627 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
628 break;
629 g_fButton[2] = TRUE;
630 return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam);
632 case WM_RBUTTONUP:
633 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
634 break;
635 g_fButton[2] = FALSE;
636 return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam);
638 case WM_XBUTTONDBLCLK:
639 case WM_XBUTTONDOWN:
640 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
641 break;
642 return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
643 case WM_XBUTTONUP:
644 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
645 break;
646 return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
648 case WM_MOUSEWHEEL:
650 /* Pass the message to the root window */
651 SendMessage (hwndScreen, message, wParam, lParam);
652 return 0;
654 case WM_SETFOCUS:
655 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
656 break;
658 winRestoreModeKeyStates ();
660 /* Add the keyboard hook if possible */
661 if (g_fKeyboardHookLL)
662 g_fKeyboardHookLL = winInstallKeyboardHookLL ();
663 return 0;
665 case WM_KILLFOCUS:
666 /* Pop any pressed keys since we are losing keyboard focus */
667 winKeybdReleaseKeys ();
669 /* Remove our keyboard hook if it is installed */
670 winRemoveKeyboardHookLL ();
671 return 0;
673 case WM_SYSDEADCHAR:
674 case WM_DEADCHAR:
676 * NOTE: We do nothing with WM_*CHAR messages,
677 * nor does the root window, so we can just toss these messages.
679 return 0;
681 case WM_SYSKEYDOWN:
682 case WM_KEYDOWN:
685 * Don't pass Alt-F4 key combo to root window,
686 * let Windows translate to WM_CLOSE and close this top-level window.
688 * NOTE: We purposely don't check the fUseWinKillKey setting because
689 * it should only apply to the key handling for the root window,
690 * not for top-level window-manager windows.
692 * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
693 * because that is a key combo that no X app should be expecting to
694 * receive, since it has historically been used to shutdown the X server.
695 * Passing Ctrl-Alt-Backspace to the root window preserves that
696 * behavior, assuming that -unixkill has been passed as a parameter.
698 if (wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000))
699 break;
701 #if CYGWINDOWING_DEBUG
702 if (wParam == VK_ESCAPE)
704 /* Place for debug: put any tests and dumps here */
705 WINDOWPLACEMENT windPlace;
706 RECT rc;
707 LPRECT pRect;
709 windPlace.length = sizeof (WINDOWPLACEMENT);
710 GetWindowPlacement (hwnd, &windPlace);
711 pRect = &windPlace.rcNormalPosition;
712 ErrorF ("\nCYGWINDOWING Dump:\n"
713 "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
714 pDraw->y, pDraw->width, pDraw->height);
715 ErrorF ("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left,
716 pRect->top, pRect->right - pRect->left,
717 pRect->bottom - pRect->top);
718 if (GetClientRect (hwnd, &rc))
720 pRect = &rc;
721 ErrorF ("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
722 pRect->top, pRect->right - pRect->left,
723 pRect->bottom - pRect->top);
725 if (GetWindowRect (hwnd, &rc))
727 pRect = &rc;
728 ErrorF ("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
729 pRect->top, pRect->right - pRect->left,
730 pRect->bottom - pRect->top);
732 ErrorF ("\n");
734 #endif
736 /* Pass the message to the root window */
737 return winWindowProc(hwndScreen, message, wParam, lParam);
739 case WM_SYSKEYUP:
740 case WM_KEYUP:
743 /* Pass the message to the root window */
744 return winWindowProc(hwndScreen, message, wParam, lParam);
746 case WM_HOTKEY:
748 /* Pass the message to the root window */
749 SendMessage (hwndScreen, message, wParam, lParam);
750 return 0;
752 case WM_ACTIVATE:
754 /* Pass the message to the root window */
755 SendMessage (hwndScreen, message, wParam, lParam);
757 if (LOWORD(wParam) != WA_INACTIVE)
759 /* Raise the window to the top in Z order */
760 /* ago: Activate does not mean putting it to front! */
762 wmMsg.msg = WM_WM_RAISE;
763 if (fWMMsgInitialized)
764 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
767 /* Tell our Window Manager thread to activate the window */
768 wmMsg.msg = WM_WM_ACTIVATE;
769 if (fWMMsgInitialized)
770 if (!pWin || !pWin->overrideRedirect) /* for OOo menus */
771 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
773 return 0;
775 case WM_ACTIVATEAPP:
777 * This message is also sent to the root window
778 * so we do nothing for individual multiwindow windows
780 break;
782 case WM_CLOSE:
783 /* Branch on if the window was killed in X already */
784 if (pWinPriv->fXKilled)
786 /* Window was killed, go ahead and destroy the window */
787 DestroyWindow (hwnd);
789 else
791 /* Tell our Window Manager thread to kill the window */
792 wmMsg.msg = WM_WM_KILL;
793 if (fWMMsgInitialized)
794 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
796 return 0;
798 case WM_DESTROY:
800 /* Branch on if the window was killed in X already */
801 if (pWinPriv && !pWinPriv->fXKilled)
803 ErrorF ("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
805 /* Tell our Window Manager thread to kill the window */
806 wmMsg.msg = WM_WM_KILL;
807 if (fWMMsgInitialized)
808 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
811 RemoveProp (hwnd, WIN_WINDOW_PROP);
812 RemoveProp (hwnd, WIN_WID_PROP);
813 RemoveProp (hwnd, WIN_NEEDMANAGE_PROP);
815 break;
817 case WM_MOVE:
818 /* Adjust the X Window to the moved Windows window */
819 winAdjustXWindow (pWin, hwnd);
820 return 0;
822 case WM_SHOWWINDOW:
823 /* Bail out if the window is being hidden */
824 if (!wParam)
825 return 0;
827 /* Tell X to map the window */
828 MapWindow (pWin, wClient(pWin));
830 /* */
831 if (!pWin->overrideRedirect)
833 DWORD dwExStyle;
834 DWORD dwStyle;
835 RECT rcNew;
836 int iDx, iDy;
838 /* Flag that this window needs to be made active when clicked */
839 SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
841 /* Get the standard and extended window style information */
842 dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE);
843 dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE);
845 /* */
846 if (dwExStyle != WS_EX_APPWINDOW)
848 /* Setup a rectangle with the X window position and size */
849 SetRect (&rcNew,
850 pDraw->x,
851 pDraw->y,
852 pDraw->x + pDraw->width,
853 pDraw->y + pDraw->height);
855 #if 0
856 ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n",
857 rcNew.left, rcNew.top,
858 rcNew.right, rcNew.bottom);
859 #endif
861 /* */
862 AdjustWindowRectEx (&rcNew,
863 WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW,
864 FALSE,
865 WS_EX_APPWINDOW);
867 /* Calculate position deltas */
868 iDx = pDraw->x - rcNew.left;
869 iDy = pDraw->y - rcNew.top;
871 /* Calculate new rectangle */
872 rcNew.left += iDx;
873 rcNew.right += iDx;
874 rcNew.top += iDy;
875 rcNew.bottom += iDy;
877 #if 0
878 ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n",
879 rcNew.left, rcNew.top,
880 rcNew.right, rcNew.bottom);
881 #endif
883 /* Set the window extended style flags */
884 SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
886 /* Set the window standard style flags */
887 SetWindowLongPtr (hwnd, GWL_STYLE,
888 WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW);
890 /* Position the Windows window */
891 SetWindowPos (hwnd, HWND_TOP,
892 rcNew.left, rcNew.top,
893 rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
894 SWP_NOMOVE | SWP_FRAMECHANGED
895 | SWP_SHOWWINDOW | SWP_NOACTIVATE);
897 /* Bring the Windows window to the foreground */
898 SetForegroundWindow (hwnd);
901 else /* It is an overridden window so make it top of Z stack */
903 #if CYGWINDOWING_DEBUG
904 ErrorF ("overridden window is shown\n");
905 #endif
906 SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
907 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
910 /* Setup the Window Manager message */
911 wmMsg.msg = WM_WM_MAP;
912 wmMsg.iWidth = pDraw->width;
913 wmMsg.iHeight = pDraw->height;
915 /* Tell our Window Manager thread to map the window */
916 if (fWMMsgInitialized)
917 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
919 return 0;
921 case WM_SIZING:
922 /* Need to legalize the size according to WM_NORMAL_HINTS */
923 /* for applications like xterm */
924 return ValidateSizing (hwnd, pWin, wParam, lParam);
926 case WM_WINDOWPOSCHANGED:
928 LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
930 if (!(pWinPos->flags & SWP_NOZORDER))
932 #if CYGWINDOWING_DEBUG
933 winDebug ("\twindow z order was changed\n");
934 #endif
935 if (pWinPos->hwndInsertAfter == HWND_TOP
936 ||pWinPos->hwndInsertAfter == HWND_TOPMOST
937 ||pWinPos->hwndInsertAfter == HWND_NOTOPMOST)
939 #if CYGWINDOWING_DEBUG
940 winDebug ("\traise to top\n");
941 #endif
942 /* Raise the window to the top in Z order */
943 winRaiseWindow(pWin);
945 else if (pWinPos->hwndInsertAfter == HWND_BOTTOM)
948 else
950 /* Check if this window is top of X windows. */
951 HWND hWndAbove = NULL;
952 DWORD dwCurrentProcessID = GetCurrentProcessId ();
953 DWORD dwWindowProcessID = 0;
955 for (hWndAbove = pWinPos->hwndInsertAfter;
956 hWndAbove != NULL;
957 hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV))
959 /* Ignore other XWin process's window */
960 GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID);
962 if ((dwWindowProcessID == dwCurrentProcessID)
963 && GetProp (hWndAbove, WIN_WINDOW_PROP)
964 && !IsWindowVisible (hWndAbove)
965 && !IsIconic (hWndAbove) ) /* ignore minimized windows */
966 break;
968 /* If this is top of X windows in Windows stack,
969 raise it in X stack. */
970 if (hWndAbove == NULL)
972 #if CYGWINDOWING_DEBUG
973 winDebug ("\traise to top\n");
974 #endif
975 winRaiseWindow(pWin);
981 * Pass the message to DefWindowProc to let the function
982 * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
984 break;
986 case WM_SIZE:
987 /* see dix/window.c */
988 #if CYGWINDOWING_DEBUG
990 char buf[64];
991 switch (wParam)
993 case SIZE_MINIMIZED:
994 strcpy(buf, "SIZE_MINIMIZED");
995 break;
996 case SIZE_MAXIMIZED:
997 strcpy(buf, "SIZE_MAXIMIZED");
998 break;
999 case SIZE_RESTORED:
1000 strcpy(buf, "SIZE_RESTORED");
1001 break;
1002 default:
1003 strcpy(buf, "UNKNOWN_FLAG");
1005 ErrorF ("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n",
1006 (int)LOWORD(lParam), (int)HIWORD(lParam), buf,
1007 (int)(GetTickCount ()));
1009 #endif
1010 /* Adjust the X Window to the moved Windows window */
1011 winAdjustXWindow (pWin, hwnd);
1012 return 0; /* end of WM_SIZE handler */
1014 case WM_MOUSEACTIVATE:
1016 /* Check if this window needs to be made active when clicked */
1017 if (!GetProp (pWinPriv->hWnd, WIN_NEEDMANAGE_PROP))
1019 #if CYGMULTIWINDOW_DEBUG
1020 ErrorF ("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
1021 "MA_NOACTIVATE\n");
1022 #endif
1024 /* */
1025 return MA_NOACTIVATE;
1027 break;
1029 case WM_SETCURSOR:
1030 if (LOWORD(lParam) == HTCLIENT)
1032 if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle);
1033 return TRUE;
1035 break;
1037 default:
1038 break;
1041 ret = DefWindowProc (hwnd, message, wParam, lParam);
1043 * If the window was minized we get the stack change before the window is restored
1044 * and so it gets lost. Ensure there stacking order is correct.
1046 if (needRestack)
1047 winReorderWindowsMultiWindow();
1048 return ret;