1 /*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
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:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
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.
22 *
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.
27 *
28 * Authors: Kensuke Matsuzaki
29 * Earle F. Philhower, III
30 * Harold L Hunt II
31 */
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 <X11/extensions/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"
45
46 /*
47 * Constant defines
48 */
49
50 #define MOUSE_ACTIVATE_DEFAULT TRUE
51 #define RAISE_ON_CLICK_DEFAULT FALSE
52
53 /*
54 * Local globals
55 */
56
57 static UINT_PTR g_uipMousePollingTimerID = 0;
58
59 /*
60 * Local function
61 */
62
DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate,WINDOWSWM_MOUSE_ACTIVATE)63 DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate, WINDOWSWM_MOUSE_ACTIVATE)
64 /* DEFINE_ATOM_HELPER(AtmWindowsWMClientWindow, WINDOWSWM_CLIENT_WINDOW) */
65
66 /*
67 * ConstrainSize - Taken from TWM sources - Respects hints for sizing
68 */
69 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
70 static void
71 ConstrainSize(WinXSizeHints hints, int *widthp, int *heightp)
72 {
73 int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
74 int baseWidth, baseHeight;
75 int dwidth = *widthp, dheight = *heightp;
76
77 if (hints.flags & PMinSize) {
78 minWidth = hints.min_width;
79 minHeight = hints.min_height;
80 }
81 else if (hints.flags & PBaseSize) {
82 minWidth = hints.base_width;
83 minHeight = hints.base_height;
84 }
85 else
86 minWidth = minHeight = 1;
87
88 if (hints.flags & PBaseSize) {
89 baseWidth = hints.base_width;
90 baseHeight = hints.base_height;
91 }
92 else if (hints.flags & PMinSize) {
93 baseWidth = hints.min_width;
94 baseHeight = hints.min_height;
95 }
96 else
97 baseWidth = baseHeight = 0;
98
99 if (hints.flags & PMaxSize) {
100 maxWidth = hints.max_width;
101 maxHeight = hints.max_height;
102 }
103 else {
104 maxWidth = MAXINT;
105 maxHeight = MAXINT;
106 }
107
108 if (hints.flags & PResizeInc) {
109 xinc = hints.width_inc;
110 yinc = hints.height_inc;
111 }
112 else
113 xinc = yinc = 1;
114
115 /*
116 * First, clamp to min and max values
117 */
118 if (dwidth < minWidth)
119 dwidth = minWidth;
120 if (dheight < minHeight)
121 dheight = minHeight;
122
123 if (dwidth > maxWidth)
124 dwidth = maxWidth;
125 if (dheight > maxHeight)
126 dheight = maxHeight;
127
128 /*
129 * Second, fit to base + N * inc
130 */
131 dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
132 dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
133
134 /*
135 * Third, adjust for aspect ratio
136 */
137
138 /*
139 * The math looks like this:
140 *
141 * minAspectX dwidth maxAspectX
142 * ---------- <= ------- <= ----------
143 * minAspectY dheight maxAspectY
144 *
145 * If that is multiplied out, then the width and height are
146 * invalid in the following situations:
147 *
148 * minAspectX * dheight > minAspectY * dwidth
149 * maxAspectX * dheight < maxAspectY * dwidth
150 *
151 */
152
153 if (hints.flags & PAspect) {
154 if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth) {
155 delta =
156 makemult(hints.min_aspect.x * dheight / hints.min_aspect.y -
157 dwidth, xinc);
158 if (dwidth + delta <= maxWidth)
159 dwidth += delta;
160 else {
161 delta =
162 makemult(dheight -
163 dwidth * hints.min_aspect.y / hints.min_aspect.x,
164 yinc);
165 if (dheight - delta >= minHeight)
166 dheight -= delta;
167 }
168 }
169
170 if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth) {
171 delta =
172 makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x -
173 dheight, yinc);
174 if (dheight + delta <= maxHeight)
175 dheight += delta;
176 else {
177 delta =
178 makemult(dwidth -
179 hints.max_aspect.x * dheight / hints.max_aspect.y,
180 xinc);
181 if (dwidth - delta >= minWidth)
182 dwidth -= delta;
183 }
184 }
185 }
186
187 /* Return computed values */
188 *widthp = dwidth;
189 *heightp = dheight;
190 }
191
192 #undef makemult
193
194 /*
195 * ValidateSizing - Ensures size request respects hints
196 */
197 static int
ValidateSizing(HWND hwnd,WindowPtr pWin,WPARAM wParam,LPARAM lParam)198 ValidateSizing(HWND hwnd, WindowPtr pWin, WPARAM wParam, LPARAM lParam)
199 {
200 WinXSizeHints sizeHints;
201 RECT *rect;
202 int iWidth, iHeight, iTopBorder;
203 POINT pt;
204
205 /* Invalid input checking */
206 if (pWin == NULL || lParam == 0) {
207 ErrorF("Invalid input checking\n");
208 return FALSE;
209 }
210
211 /* No size hints, no checking */
212 if (!winMultiWindowGetWMNormalHints(pWin, &sizeHints)) {
213 ErrorF("No size hints, no checking\n");
214 return FALSE;
215 }
216
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;
223 }
224
225 rect = (RECT *) lParam;
226
227 iWidth = rect->right - rect->left;
228 iHeight = rect->bottom - rect->top;
229
230 /* Get title bar height, there must be an easier way?! */
231 pt.x = pt.y = 0;
232 ClientToScreen(hwnd, &pt);
233 iTopBorder = pt.y - rect->top;
234
235 /* Now remove size of any borders */
236 iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME);
237 iHeight -= GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
238
239 /* Constrain the size to legal values */
240 ConstrainSize(sizeHints, &iWidth, &iHeight);
241
242 /* Add back the borders */
243 iWidth += 2 * GetSystemMetrics(SM_CXSIZEFRAME);
244 iHeight += GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder;
245
246 /* Adjust size according to where we're dragging from */
247 switch (wParam) {
248 case WMSZ_TOP:
249 case WMSZ_TOPRIGHT:
250 case WMSZ_BOTTOM:
251 case WMSZ_BOTTOMRIGHT:
252 case WMSZ_RIGHT:
253 rect->right = rect->left + iWidth;
254 break;
255 default:
256 rect->left = rect->right - iWidth;
257 break;
258 }
259 switch (wParam) {
260 case WMSZ_BOTTOM:
261 case WMSZ_BOTTOMRIGHT:
262 case WMSZ_BOTTOMLEFT:
263 case WMSZ_RIGHT:
264 case WMSZ_LEFT:
265 rect->bottom = rect->top + iHeight;
266 break;
267 default:
268 rect->top = rect->bottom - iHeight;
269 break;
270 }
271 return TRUE;
272 }
273
274 /*
275 * IsMouseActive
276 */
277
278 static Bool
IsMouseActive(WindowPtr pWin)279 IsMouseActive(WindowPtr pWin)
280 {
281
282 struct _Window *pwin;
283 struct _Property *prop;
284
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);
288
289 if (!pWin) {
290 ErrorF("IsMouseActive - pWin was NULL use default value:%d\n",
291 MOUSE_ACTIVATE_DEFAULT);
292 return MOUSE_ACTIVATE_DEFAULT;
293 }
294
295 pwin = (struct _Window *) pWin;
296
297 if (pwin->optional)
298 prop = (struct _Property *) pwin->optional->userProps;
299 else
300 prop = NULL;
301
302 while (prop) {
303 if (prop->propertyName == AtmWindowsWMMouseActivate()
304 && prop->type == XA_INTEGER && prop->format == 32) {
305 return *(int *) prop->data;
306 }
307 else
308 prop = prop->next;
309 }
310
311 if (pWin != pRoot) {
312 return IsMouseActive(pRoot);
313 }
314 else {
315 #if CYGMULTIWINDOW_DEBUG
316 winDebug("IsMouseActive - no prop use default value:%d\n",
317 MOUSE_ACTIVATE_DEFAULT);
318 #endif
319 return MOUSE_ACTIVATE_DEFAULT;
320 }
321 }
322
323 /*
324 * winMWExtWMWindowProc - Window procedure
325 */
326
327 LRESULT CALLBACK
winMWExtWMWindowProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)328 winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
329 {
330 WindowPtr pWin = NULL;
331 win32RootlessWindowPtr pRLWinPriv = NULL;
332 ScreenPtr pScreen = NULL;
333 winPrivScreenPtr pScreenPriv = NULL;
334 winScreenInfo *pScreenInfo = NULL;
335 HWND hwndScreen = NULL;
336 POINT ptMouse;
337 static Bool s_fTracking = FALSE;
338 HDC hdcUpdate;
339 PAINTSTRUCT ps;
340 LPWINDOWPOS pWinPos = NULL;
341 RECT rcClient;
342
343 /* Check if the Windows window property for our X window pointer is valid */
344 if ((pRLWinPriv =
345 (win32RootlessWindowPtr) GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) {
346 pWin = pRLWinPriv->pFrame->win;
347 pScreen = pWin->drawable.pScreen;
348 if (pScreen)
349 pScreenPriv = winGetScreenPriv(pScreen);
350 if (pScreenPriv)
351 pScreenInfo = pScreenPriv->pScreenInfo;
352 if (pScreenPriv)
353 hwndScreen = pScreenPriv->hwndScreen;
354
355 #if CYGDEBUG
356 winDebugWin32Message("winMWExtWMWindowProc", hwnd, message, wParam,
357 lParam);
358
359 winDebug("\thWnd %p\n", hwnd);
360 winDebug("\tpScreenPriv %p\n", pScreenPriv);
361 winDebug("\tpScreenInfo %p\n", pScreenInfo);
362 winDebug("\thwndScreen %p\n", hwndScreen);
363 winDebug("winMWExtWMWindowProc (%p) %08x %08x %08x\n",
364 pRLWinPriv, message, (int)wParam, (int)lParam);
365 #endif
366 }
367 /* Branch on message type */
368 switch (message) {
369 case WM_CREATE:
370 #if CYGMULTIWINDOW_DEBUG
371 winDebug("winMWExtWMWindowProc - WM_CREATE\n");
372 #endif
373 /* */
374 SetProp(hwnd,
375 WIN_WINDOW_PROP,
376 (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams);
377 return 0;
378
379 case WM_CLOSE:
380 #if CYGMULTIWINDOW_DEBUG
381 winDebug("winMWExtWMWindowProc - WM_CLOSE %d\n", pRLWinPriv->fClose);
382 #endif
383 /* Tell window-manager to close window */
384 if (pRLWinPriv->fClose) {
385 DestroyWindow(hwnd);
386 }
387 else {
388 winWindowsWMSendEvent(WindowsWMControllerNotify,
389 WindowsWMControllerNotifyMask,
390 1,
391 WindowsWMCloseWindow,
392 pWin->drawable.id, 0, 0, 0, 0);
393 }
394 return 0;
395
396 case WM_DESTROY:
397 #if CYGMULTIWINDOW_DEBUG
398 winDebug("winMWExtWMWindowProc - WM_DESTROY\n");
399 #endif
400 /* Free the shaodw DC; which allows the bitmap to be freed */
401 DeleteDC(pRLWinPriv->hdcShadow);
402 pRLWinPriv->hdcShadow = NULL;
403
404 /* Free the shadow bitmap */
405 DeleteObject(pRLWinPriv->hbmpShadow);
406 pRLWinPriv->hbmpShadow = NULL;
407
408 /* Free the screen DC */
409 ReleaseDC(pRLWinPriv->hWnd, pRLWinPriv->hdcScreen);
410 pRLWinPriv->hdcScreen = NULL;
411
412 /* Free shadow buffer info header */
413 free(pRLWinPriv->pbmihShadow);
414 pRLWinPriv->pbmihShadow = NULL;
415
416 pRLWinPriv->fResized = FALSE;
417 pRLWinPriv->pfb = NULL;
418 free(pRLWinPriv);
419 RemoveProp(hwnd, WIN_WINDOW_PROP);
420 break;
421
422 case WM_MOUSEMOVE:
423 #if CYGMULTIWINDOW_DEBUG && 0
424 winDebug("winMWExtWMWindowProc - WM_MOUSEMOVE\n");
425 #endif
426 /* Unpack the client area mouse coordinates */
427 ptMouse.x = GET_X_LPARAM(lParam);
428 ptMouse.y = GET_Y_LPARAM(lParam);
429
430 /* Translate the client area mouse coordinates to screen coordinates */
431 ClientToScreen(hwnd, &ptMouse);
432
433 /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
434 ptMouse.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
435 ptMouse.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
436
437 /* We can't do anything without privates */
438 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
439 break;
440
441 /* Has the mouse pointer crossed screens? */
442 if (pScreen != miPointerGetScreen(inputInfo.pointer))
443 miPointerSetScreen(inputInfo.pointer, pScreenInfo->dwScreen,
444 ptMouse.x - pScreenInfo->dwXOffset,
445 ptMouse.y - pScreenInfo->dwYOffset);
446
447 /* Are we tracking yet? */
448 if (!s_fTracking) {
449 TRACKMOUSEEVENT tme;
450
451 /* Setup data structure */
452 ZeroMemory(&tme, sizeof(tme));
453 tme.cbSize = sizeof(tme);
454 tme.dwFlags = TME_LEAVE;
455 tme.hwndTrack = hwnd;
456
457 /* Call the tracking function */
458 if (!TrackMouseEvent(&tme))
459 ErrorF("winMWExtWMWindowProc - TrackMouseEvent failed\n");
460
461 /* Flag that we are tracking now */
462 s_fTracking = TRUE;
463 }
464
465 /* Kill the timer used to poll mouse events */
466 if (g_uipMousePollingTimerID != 0) {
467 KillTimer(pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
468 g_uipMousePollingTimerID = 0;
469 }
470
471 /* Deliver absolute cursor position to X Server */
472 winEnqueueMotion(ptMouse.x - pScreenInfo->dwXOffset,
473 ptMouse.y - pScreenInfo->dwYOffset);
474
475 return 0;
476
477 case WM_NCMOUSEMOVE:
478 #if CYGMULTIWINDOW_DEBUG && 0
479 winDebug("winMWExtWMWindowProc - WM_NCMOUSEMOVE\n");
480 #endif
481 /*
482 * We break instead of returning 0 since we need to call
483 * DefWindowProc to get the mouse cursor changes
484 * and min/max/close button highlighting in Windows XP.
485 * The Platform SDK says that you should return 0 if you
486 * process this message, but it fails to mention that you
487 * will give up any default functionality if you do return 0.
488 */
489
490 /* We can't do anything without privates */
491 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
492 break;
493
494 /*
495 * Timer to poll mouse events. This is needed to make
496 * programs like xeyes follow the mouse properly.
497 */
498 if (g_uipMousePollingTimerID == 0)
499 g_uipMousePollingTimerID = SetTimer(pScreenPriv->hwndScreen,
500 WIN_POLLING_MOUSE_TIMER_ID,
501 MOUSE_POLLING_INTERVAL, NULL);
502 break;
503
504 case WM_MOUSELEAVE:
505 #if CYGMULTIWINDOW_DEBUG
506 winDebug("winMWExtWMWindowProc - WM_MOUSELEAVE\n");
507 #endif
508 /* Mouse has left our client area */
509
510 /* Flag that we are no longer tracking */
511 s_fTracking = FALSE;
512
513 /*
514 * Timer to poll mouse events. This is needed to make
515 * programs like xeyes follow the mouse properly.
516 */
517 if (g_uipMousePollingTimerID == 0)
518 g_uipMousePollingTimerID = SetTimer(pScreenPriv->hwndScreen,
519 WIN_POLLING_MOUSE_TIMER_ID,
520 MOUSE_POLLING_INTERVAL, NULL);
521 return 0;
522
523 case WM_LBUTTONDBLCLK:
524 case WM_LBUTTONDOWN:
525 #if CYGMULTIWINDOW_DEBUG
526 winDebug("winMWExtWMWindowProc - WM_LBUTTONDBLCLK\n");
527 #endif
528 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
529 break;
530 SetCapture(hwnd);
531 return winMouseButtonsHandle(pScreen, ButtonPress, Button1, wParam);
532
533 case WM_LBUTTONUP:
534 #if CYGMULTIWINDOW_DEBUG
535 winDebug("winMWExtWMWindowProc - WM_LBUTTONUP\n");
536 #endif
537 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
538 break;
539 ReleaseCapture();
540 return winMouseButtonsHandle(pScreen, ButtonRelease, Button1, wParam);
541
542 case WM_MBUTTONDBLCLK:
543 case WM_MBUTTONDOWN:
544 #if CYGMULTIWINDOW_DEBUG
545 winDebug("winMWExtWMWindowProc - WM_MBUTTONDBLCLK\n");
546 #endif
547 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
548 break;
549 SetCapture(hwnd);
550 return winMouseButtonsHandle(pScreen, ButtonPress, Button2, wParam);
551
552 case WM_MBUTTONUP:
553 #if CYGMULTIWINDOW_DEBUG
554 winDebug("winMWExtWMWindowProc - WM_MBUTTONUP\n");
555 #endif
556 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
557 break;
558 ReleaseCapture();
559 return winMouseButtonsHandle(pScreen, ButtonRelease, Button2, wParam);
560
561 case WM_RBUTTONDBLCLK:
562 case WM_RBUTTONDOWN:
563 #if CYGMULTIWINDOW_DEBUG
564 winDebug("winMWExtWMWindowProc - WM_RBUTTONDBLCLK\n");
565 #endif
566 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
567 break;
568 SetCapture(hwnd);
569 return winMouseButtonsHandle(pScreen, ButtonPress, Button3, wParam);
570
571 case WM_RBUTTONUP:
572 #if CYGMULTIWINDOW_DEBUG
573 winDebug("winMWExtWMWindowProc - WM_RBUTTONUP\n");
574 #endif
575 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
576 break;
577 ReleaseCapture();
578 return winMouseButtonsHandle(pScreen, ButtonRelease, Button3, wParam);
579
580 case WM_XBUTTONDBLCLK:
581 case WM_XBUTTONDOWN:
582 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
583 break;
584 SetCapture(hwnd);
585 return winMouseButtonsHandle(pScreen, ButtonPress, HIWORD(wParam) + 7,
586 wParam);
587 case WM_XBUTTONUP:
588 if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput)
589 break;
590 ReleaseCapture();
591 return winMouseButtonsHandle(pScreen, ButtonRelease, HIWORD(wParam) + 7,
592 wParam);
593
594 case WM_MOUSEWHEEL:
595 #if CYGMULTIWINDOW_DEBUG
596 winDebug("winMWExtWMWindowProc - WM_MOUSEWHEEL\n");
597 #endif
598
599 /* Pass the message to the root window */
600 SendMessage(hwndScreen, message, wParam, lParam);
601 return 0;
602
603 case WM_MOUSEHWHEEL:
604 #if CYGMULTIWINDOW_DEBUG
605 winDebug("winMWExtWMWindowProc - WM_MOUSEHWHEEL\n");
606 #endif
607
608 /* Pass the message to the root window */
609 SendMessage(hwndScreen, message, wParam, lParam);
610 return 0;
611
612 case WM_MOUSEACTIVATE:
613 #if CYGMULTIWINDOW_DEBUG
614 winDebug("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n");
615 #endif
616 if (!IsMouseActive(pWin))
617 return MA_NOACTIVATE;
618
619 break;
620
621 case WM_KILLFOCUS:
622 /* Pop any pressed keys since we are losing keyboard focus */
623 winKeybdReleaseKeys();
624 return 0;
625
626 case WM_SYSDEADCHAR:
627 case WM_DEADCHAR:
628 /*
629 * NOTE: We do nothing with WM_*CHAR messages,
630 * nor does the root window, so we can just toss these messages.
631 */
632 return 0;
633
634 case WM_SYSKEYDOWN:
635 case WM_KEYDOWN:
636 #if CYGMULTIWINDOW_DEBUG
637 winDebug("winMWExtWMWindowProc - WM_*KEYDOWN\n");
638 #endif
639
640 /*
641 * Don't pass Alt-F4 key combo to root window,
642 * let Windows translate to WM_CLOSE and close this top-level window.
643 *
644 * NOTE: We purposely don't check the fUseWinKillKey setting because
645 * it should only apply to the key handling for the root window,
646 * not for top-level window-manager windows.
647 *
648 * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
649 * because that is a key combo that no X app should be expecting to
650 * receive, since it has historically been used to shutdown the X server.
651 * Passing Ctrl-Alt-Backspace to the root window preserves that
652 * behavior, assuming that -unixkill has been passed as a parameter.
653 */
654 if (wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000))
655 break;
656
657 /* Pass the message to the root window */
658 SendMessage(hwndScreen, message, wParam, lParam);
659 return 0;
660
661 case WM_SYSKEYUP:
662 case WM_KEYUP:
663
664 #if CYGMULTIWINDOW_DEBUG
665 winDebug("winMWExtWMWindowProc - WM_*KEYUP\n");
666 #endif
667
668 /* Pass the message to the root window */
669 SendMessage(hwndScreen, message, wParam, lParam);
670 return 0;
671
672 case WM_HOTKEY:
673 #if CYGMULTIWINDOW_DEBUG
674 winDebug("winMWExtWMWindowProc - WM_HOTKEY\n");
675 #endif
676
677 /* Pass the message to the root window */
678 SendMessage(hwndScreen, message, wParam, lParam);
679 return 0;
680
681 case WM_ERASEBKGND:
682 #if CYGDEBUG
683 winDebug("winMWExtWMWindowProc - WM_ERASEBKGND\n");
684 #endif
685 /*
686 * Pretend that we did erase the background but we don't care,
687 * since we repaint the entire region anyhow
688 * This avoids some flickering when resizing.
689 */
690 return TRUE;
691
692 case WM_PAINT:
693
694 /* BeginPaint gives us an hdc that clips to the invalidated region */
695 hdcUpdate = BeginPaint(hwnd, &ps);
696
697 /* Try to copy from the shadow buffer */
698 if (!BitBlt(hdcUpdate,
699 ps.rcPaint.left, ps.rcPaint.top,
700 ps.rcPaint.right - ps.rcPaint.left,
701 ps.rcPaint.bottom - ps.rcPaint.top,
702 pRLWinPriv->hdcShadow,
703 ps.rcPaint.left, ps.rcPaint.top, SRCCOPY)) {
704 LPVOID lpMsgBuf;
705
706 /* Display a fancy error message */
707 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
708 FORMAT_MESSAGE_FROM_SYSTEM |
709 FORMAT_MESSAGE_IGNORE_INSERTS,
710 NULL,
711 GetLastError(),
712 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
713 (LPTSTR) &lpMsgBuf, 0, NULL);
714
715 ErrorF("winMWExtWMWindowProc - BitBlt failed: %s\n",
716 (LPSTR) lpMsgBuf);
717 LocalFree(lpMsgBuf);
718 }
719
720 /* EndPaint frees the DC */
721 EndPaint(hwnd, &ps);
722 break;
723
724 case WM_ACTIVATE:
725 #if CYGMULTIWINDOW_DEBUG
726 winDebug("winMWExtWMWindowProc - WM_ACTIVATE\n");
727 #endif
728 if (LOWORD(wParam) != WA_INACTIVE) {
729 winWindowsWMSendEvent(WindowsWMControllerNotify,
730 WindowsWMControllerNotifyMask,
731 1,
732 WindowsWMActivateWindow,
733 pWin->drawable.id, 0, 0, 0, 0);
734 }
735 return 0;
736
737 #if 1
738 case WM_WINDOWPOSCHANGING:
739 pWinPos = (LPWINDOWPOS) lParam;
740 if (!(pWinPos->flags & SWP_NOZORDER)) {
741 if (pRLWinPriv->fRestackingNow || pScreenPriv->fRestacking) {
742 #if CYGMULTIWINDOW_DEBUG
743 winDebug("Win %p is now restacking.\n",
744 pRLWinPriv);
745 #endif
746 break;
747 }
748
749 #if CYGMULTIWINDOW_DEBUG
750 winDebug("Win %p forbid to change z order (%p).\n",
751 pRLWinPriv,
752 pWinPos->hwndInsertAfter);
753 #endif
754 pWinPos->flags |= SWP_NOZORDER;
755 }
756 break;
757 #endif
758
759 case WM_MOVE:
760 #if CYGMULTIWINDOW_DEBUG
761 winDebug("winMWExtWMWindowProc - WM_MOVE\n");
762 #endif
763 if (g_fNoConfigureWindow)
764 break;
765 #if 0
766 /* Bail if Windows window is not actually moving */
767 if (pRLWinPriv->dwX == (short) LOWORD(lParam)
768 && pRLWinPriv->dwY == (short) HIWORD(lParam))
769 break;
770
771 /* Also bail if we're maximizing, we'll do the whole thing in WM_SIZE */
772 {
773 WINDOWPLACEMENT windPlace;
774
775 windPlace.length = sizeof(WINDOWPLACEMENT);
776
777 /* Get current window placement */
778 GetWindowPlacement(hwnd, &windPlace);
779
780 /* Bail if maximizing */
781 if (windPlace.showCmd == SW_MAXIMIZE
782 || windPlace.showCmd == SW_SHOWMAXIMIZED)
783 break;
784 }
785 #endif
786
787 #if CYGMULTIWINDOW_DEBUG
788 winDebug("\t(%d, %d)\n", (short) LOWORD(lParam),
789 (short) HIWORD(lParam));
790 #endif
791 if (!pRLWinPriv->fMovingOrSizing) {
792 winMWExtWMMoveXWindow(pWin, (LOWORD(lParam) - wBorderWidth(pWin)
793 - GetSystemMetrics(SM_XVIRTUALSCREEN)),
794 (HIWORD(lParam) - wBorderWidth(pWin)
795 - GetSystemMetrics(SM_YVIRTUALSCREEN)));
796 }
797 return 0;
798
799 case WM_SHOWWINDOW:
800 #if CYGMULTIWINDOW_DEBUG || TRUE
801 winDebug("winMWExtWMWindowProc - WM_SHOWWINDOW\n");
802 #endif
803 /* Bail out if the window is being hidden */
804 if (!wParam)
805 return 0;
806
807 winMWExtWMUpdateWindowDecoration(pRLWinPriv, pScreenInfo);
808
809 break;
810
811 case WM_SIZING:
812 /* Need to legalize the size according to WM_NORMAL_HINTS */
813 /* for applications like xterm */
814 return ValidateSizing(hwnd, pWin, wParam, lParam);
815
816 case WM_WINDOWPOSCHANGED:
817 {
818 pWinPos = (LPWINDOWPOS) lParam;
819 #if CYGMULTIWINDOW_DEBUG
820 winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n");
821 winDebug("\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n",
822 (pWinPos->flags & SWP_DRAWFRAME) ? "SWP_DRAWFRAME " : "",
823 (pWinPos->flags & SWP_FRAMECHANGED) ? "SWP_FRAMECHANGED " : "",
824 (pWinPos->flags & SWP_HIDEWINDOW) ? "SWP_HIDEWINDOW " : "",
825 (pWinPos->flags & SWP_NOACTIVATE) ? "SWP_NOACTIVATE " : "",
826 (pWinPos->flags & SWP_NOCOPYBITS) ? "SWP_NOCOPYBITS " : "",
827 (pWinPos->flags & SWP_NOMOVE) ? "SWP_NOMOVE " : "",
828 (pWinPos->
829 flags & SWP_NOOWNERZORDER) ? "SWP_NOOWNERZORDER " : "",
830 (pWinPos->flags & SWP_NOSIZE) ? "SWP_NOSIZE " : "",
831 (pWinPos->flags & SWP_NOREDRAW) ? "SWP_NOREDRAW " : "",
832 (pWinPos->
833 flags & SWP_NOSENDCHANGING) ? "SWP_NOSENDCHANGING " : "",
834 (pWinPos->flags & SWP_NOZORDER) ? "SWP_NOZORDER " : "",
835 (pWinPos->flags & SWP_SHOWWINDOW) ? "SWP_SHOWWINDOW " : "");
836 winDebug("\tno_configure: %s\n", (g_fNoConfigureWindow ? "Yes" : "No"));
837 winDebug("\textend: (%d, %d, %d, %d)\n",
838 pWinPos->x, pWinPos->y, pWinPos->cx, pWinPos->cy);
839
840 #endif
841 if (pWinPos->flags & SWP_HIDEWINDOW)
842 break;
843
844 if (!(pWinPos->flags & SWP_NOSIZE)) {
845 if (IsIconic(hwnd)) {
846 #if CYGMULTIWINDOW_DEBUG
847 winDebug("\tIconic -> MINIMIZED\n");
848 #endif
849
850 winWindowsWMSendEvent(WindowsWMControllerNotify,
851 WindowsWMControllerNotifyMask,
852 1,
853 WindowsWMMinimizeWindow,
854 pWin->drawable.id, 0, 0, 0, 0);
855 }
856 else if (IsZoomed(hwnd)) {
857 #if CYGMULTIWINDOW_DEBUG
858 winDebug("\tZoomed -> MAXIMIZED\n");
859 #endif
860 winWindowsWMSendEvent(WindowsWMControllerNotify,
861 WindowsWMControllerNotifyMask,
862 1,
863 WindowsWMMaximizeWindow,
864 pWin->drawable.id, 0, 0, 0, 0);
865 }
866 else {
867 #if CYGMULTIWINDOW_DEBUG
868 winDebug("\tnone -> RESTORED\n");
869 #endif
870 winWindowsWMSendEvent(WindowsWMControllerNotify,
871 WindowsWMControllerNotifyMask,
872 1,
873 WindowsWMRestoreWindow,
874 pWin->drawable.id, 0, 0, 0, 0);
875 }
876 }
877 if (!g_fNoConfigureWindow) {
878
879 if (!pRLWinPriv->fMovingOrSizing
880 /*&& (pWinPos->flags & SWP_SHOWWINDOW) */ ) {
881 GetClientRect(hwnd, &rcClient);
882 MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT) &rcClient, 2);
883
884 if (!(pWinPos->flags & SWP_NOMOVE)
885 && !(pWinPos->flags & SWP_NOSIZE)) {
886 #if CYGMULTIWINDOW_DEBUG
887 winDebug("\tmove & resize\n");
888 #endif
889
890 winMWExtWMMoveResizeXWindow(pWin,
891 rcClient.left -
892 wBorderWidth(pWin)
893 -
894 GetSystemMetrics
895 (SM_XVIRTUALSCREEN),
896 rcClient.top -
897 wBorderWidth(pWin)
898 -
899 GetSystemMetrics
900 (SM_YVIRTUALSCREEN),
901 rcClient.right - rcClient.left -
902 wBorderWidth(pWin) * 2,
903 rcClient.bottom - rcClient.top -
904 wBorderWidth(pWin) * 2);
905 }
906 else if (!(pWinPos->flags & SWP_NOMOVE)) {
907 #if CYGMULTIWINDOW_DEBUG
908 winDebug("\tmove\n");
909 #endif
910
911 winMWExtWMMoveResizeXWindow(pWin,
912 rcClient.left -
913 wBorderWidth(pWin)
914 -
915 GetSystemMetrics
916 (SM_XVIRTUALSCREEN),
917 rcClient.top -
918 wBorderWidth(pWin)
919 -
920 GetSystemMetrics
921 (SM_YVIRTUALSCREEN),
922 rcClient.right - rcClient.left -
923 wBorderWidth(pWin) * 2,
924 rcClient.bottom - rcClient.top -
925 wBorderWidth(pWin) * 2);
926 }
927 else if (!(pWinPos->flags & SWP_NOMOVE)) {
928 #if CYGMULTIWINDOW_DEBUG
929 winDebug("\tmove\n");
930 #endif
931
932 winMWExtWMMoveXWindow(pWin,
933 rcClient.left - wBorderWidth(pWin)
934 - GetSystemMetrics(SM_XVIRTUALSCREEN),
935 rcClient.top - wBorderWidth(pWin)
936 -
937 GetSystemMetrics(SM_YVIRTUALSCREEN));
938 }
939 else if (!(pWinPos->flags & SWP_NOSIZE)) {
940 #if CYGMULTIWINDOW_DEBUG
941 winDebug("\tresize\n");
942 #endif
943
944 winMWExtWMResizeXWindow(pWin,
945 rcClient.right - rcClient.left
946 - wBorderWidth(pWin) * 2,
947 rcClient.bottom - rcClient.top
948 - wBorderWidth(pWin) * 2);
949 }
950 }
951 }
952 }
953 #if CYGMULTIWINDOW_DEBUG
954 winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED - done.\n");
955 #endif
956 return 0;
957
958 case WM_SIZE:
959 /* see dix/window.c */
960 /* FIXME: Maximize/Restore? */
961 #if CYGMULTIWINDOW_DEBUG
962 winDebug("winMWExtWMWindowProc - WM_SIZE\n");
963 #endif
964 #if CYGMULTIWINDOW_DEBUG
965 winDebug("\t(%d, %d) %d\n", (short) LOWORD(lParam),
966 (short) HIWORD(lParam), g_fNoConfigureWindow);
967 #endif
968 if (g_fNoConfigureWindow)
969 break;
970
971 /* Branch on type of resizing occurring */
972 switch (wParam) {
973 case SIZE_MINIMIZED:
974 #if CYGMULTIWINDOW_DEBUG
975 winDebug("\tSIZE_MINIMIZED\n");
976 #endif
977
978 winWindowsWMSendEvent(WindowsWMControllerNotify,
979 WindowsWMControllerNotifyMask,
980 1,
981 WindowsWMMinimizeWindow,
982 pWin->drawable.id,
983 0, 0, LOWORD(lParam), HIWORD(lParam));
984 break;
985
986 case SIZE_RESTORED:
987 #if CYGMULTIWINDOW_DEBUG
988 winDebug("\tSIZE_RESTORED\n");
989 #endif
990 winWindowsWMSendEvent(WindowsWMControllerNotify,
991 WindowsWMControllerNotifyMask,
992 1,
993 WindowsWMRestoreWindow,
994 pWin->drawable.id,
995 0, 0, LOWORD(lParam), HIWORD(lParam));
996 break;
997
998 case SIZE_MAXIMIZED:
999 #if CYGMULTIWINDOW_DEBUG
1000 winDebug("\tSIZE_MAXIMIZED\n");
1001 #endif
1002 winWindowsWMSendEvent(WindowsWMControllerNotify,
1003 WindowsWMControllerNotifyMask,
1004 1,
1005 WindowsWMMaximizeWindow,
1006 pWin->drawable.id,
1007 0, 0, LOWORD(lParam), HIWORD(lParam));
1008 break;
1009 }
1010
1011 /* Perform the resize and notify the X client */
1012 if (!pRLWinPriv->fMovingOrSizing) {
1013 winMWExtWMResizeXWindow(pWin, (short) LOWORD(lParam)
1014 - wBorderWidth(pWin) * 2,
1015 (short) HIWORD(lParam)
1016 - wBorderWidth(pWin) * 2);
1017 }
1018 break;
1019
1020 case WM_ACTIVATEAPP:
1021 #if CYGMULTIWINDOW_DEBUG
1022 winDebug("winMWExtWMWindowProc - WM_ACTIVATEAPP\n");
1023 #endif
1024 if (wParam) {
1025 winWindowsWMSendEvent(WindowsWMActivationNotify,
1026 WindowsWMActivationNotifyMask,
1027 1,
1028 WindowsWMIsActive,
1029 pWin->drawable.id, 0, 0, 0, 0);
1030 }
1031 else {
1032 winWindowsWMSendEvent(WindowsWMActivationNotify,
1033 WindowsWMActivationNotifyMask,
1034 1,
1035 WindowsWMIsInactive,
1036 pWin->drawable.id, 0, 0, 0, 0);
1037 }
1038 break;
1039
1040 case WM_SETCURSOR:
1041 if (LOWORD(lParam) == HTCLIENT) {
1042 if (!g_fSoftwareCursor)
1043 SetCursor(pScreenPriv->cursor.handle);
1044 return TRUE;
1045 }
1046 break;
1047
1048 case WM_ENTERSIZEMOVE:
1049 #if CYGMULTIWINDOW_DEBUG
1050 winDebug("winMWExtWMWindowProc - WM_ENTERSIZEMOVE\n");
1051 #endif
1052 pRLWinPriv->fMovingOrSizing = TRUE;
1053 break;
1054
1055 case WM_EXITSIZEMOVE:
1056 #if CYGMULTIWINDOW_DEBUG
1057 winDebug("winMWExtWMWindowProc - WM_EXITSIZEMOVE\n");
1058 #endif
1059 pRLWinPriv->fMovingOrSizing = FALSE;
1060
1061 GetClientRect(hwnd, &rcClient);
1062
1063 MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT) &rcClient, 2);
1064
1065 winMWExtWMMoveResizeXWindow(pWin, rcClient.left - wBorderWidth(pWin)
1066 - GetSystemMetrics(SM_XVIRTUALSCREEN),
1067 rcClient.top - wBorderWidth(pWin)
1068 - GetSystemMetrics(SM_YVIRTUALSCREEN),
1069 rcClient.right - rcClient.left
1070 - wBorderWidth(pWin) * 2,
1071 rcClient.bottom - rcClient.top
1072 - wBorderWidth(pWin) * 2);
1073 break;
1074
1075 default:
1076 break;
1077 }
1078
1079 return DefWindowProc(hwnd, message, wParam, lParam);
1080 }
1081