winmultiwindowwndproc.c revision 4642e01f
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 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" 42 43/* 44 * External global variables 45 */ 46 47extern Bool g_fCursor; 48extern Bool g_fKeyboardHookLL; 49extern Bool g_fSoftwareCursor; 50extern Bool g_fButton[3]; 51 52 53/* 54 * Local globals 55 */ 56 57static UINT_PTR g_uipMousePollingTimerID = 0; 58 59 60/* 61 * Constant defines 62 */ 63 64#define MOUSE_POLLING_INTERVAL 500 65#define WIN_MULTIWINDOW_SHAPE YES 66 67 68/* 69 * ConstrainSize - Taken from TWM sources - Respects hints for sizing 70 */ 71#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) 72static void 73ConstrainSize (WinXSizeHints hints, int *widthp, int *heightp) 74{ 75 int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta; 76 int baseWidth, baseHeight; 77 int dwidth = *widthp, dheight = *heightp; 78 79 if (hints.flags & PMinSize) 80 { 81 minWidth = hints.min_width; 82 minHeight = hints.min_height; 83 } 84 else if (hints.flags & PBaseSize) 85 { 86 minWidth = hints.base_width; 87 minHeight = hints.base_height; 88 } 89 else 90 minWidth = minHeight = 1; 91 92 if (hints.flags & PBaseSize) 93 { 94 baseWidth = hints.base_width; 95 baseHeight = hints.base_height; 96 } 97 else if (hints.flags & PMinSize) 98 { 99 baseWidth = hints.min_width; 100 baseHeight = hints.min_height; 101 } 102 else 103 baseWidth = baseHeight = 0; 104 105 if (hints.flags & PMaxSize) 106 { 107 maxWidth = hints.max_width; 108 maxHeight = hints.max_height; 109 } 110 else 111 { 112 maxWidth = MAXINT; 113 maxHeight = MAXINT; 114 } 115 116 if (hints.flags & PResizeInc) 117 { 118 xinc = hints.width_inc; 119 yinc = hints.height_inc; 120 } 121 else 122 xinc = yinc = 1; 123 124 /* 125 * First, clamp to min and max values 126 */ 127 if (dwidth < minWidth) 128 dwidth = minWidth; 129 if (dheight < minHeight) 130 dheight = minHeight; 131 132 if (dwidth > maxWidth) 133 dwidth = maxWidth; 134 if (dheight > maxHeight) 135 dheight = maxHeight; 136 137 /* 138 * Second, fit to base + N * inc 139 */ 140 dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth; 141 dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight; 142 143 /* 144 * Third, adjust for aspect ratio 145 */ 146 147 /* 148 * The math looks like this: 149 * 150 * minAspectX dwidth maxAspectX 151 * ---------- <= ------- <= ---------- 152 * minAspectY dheight maxAspectY 153 * 154 * If that is multiplied out, then the width and height are 155 * invalid in the following situations: 156 * 157 * minAspectX * dheight > minAspectY * dwidth 158 * maxAspectX * dheight < maxAspectY * dwidth 159 * 160 */ 161 162 if (hints.flags & PAspect) 163 { 164 if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth) 165 { 166 delta = makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - dwidth, xinc); 167 if (dwidth + delta <= maxWidth) 168 dwidth += delta; 169 else 170 { 171 delta = makemult(dheight - dwidth*hints.min_aspect.y/hints.min_aspect.x, yinc); 172 if (dheight - delta >= minHeight) 173 dheight -= delta; 174 } 175 } 176 177 if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth) 178 { 179 delta = makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - dheight, yinc); 180 if (dheight + delta <= maxHeight) 181 dheight += delta; 182 else 183 { 184 delta = makemult(dwidth - hints.max_aspect.x*dheight/hints.max_aspect.y, xinc); 185 if (dwidth - delta >= minWidth) 186 dwidth -= delta; 187 } 188 } 189 } 190 191 /* Return computed values */ 192 *widthp = dwidth; 193 *heightp = dheight; 194} 195#undef makemult 196 197 198 199/* 200 * ValidateSizing - Ensures size request respects hints 201 */ 202static int 203ValidateSizing (HWND hwnd, WindowPtr pWin, 204 WPARAM wParam, LPARAM lParam) 205{ 206 WinXSizeHints sizeHints; 207 RECT *rect; 208 int iWidth, iHeight; 209 210 /* Invalid input checking */ 211 if (pWin==NULL || lParam==0) 212 return FALSE; 213 214 /* No size hints, no checking */ 215 if (!winMultiWindowGetWMNormalHints (pWin, &sizeHints)) 216 return FALSE; 217 218 /* Avoid divide-by-zero */ 219 if (sizeHints.flags & PResizeInc) 220 { 221 if (sizeHints.width_inc == 0) sizeHints.width_inc = 1; 222 if (sizeHints.height_inc == 0) 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 /* Now remove size of any borders */ 231 iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME); 232 iHeight -= (GetSystemMetrics(SM_CYCAPTION) 233 + 2 * GetSystemMetrics(SM_CYSIZEFRAME)); 234 235 236 /* Constrain the size to legal values */ 237 ConstrainSize (sizeHints, &iWidth, &iHeight); 238 239 /* Add back the borders */ 240 iWidth += 2 * GetSystemMetrics(SM_CXSIZEFRAME); 241 iHeight += (GetSystemMetrics(SM_CYCAPTION) 242 + 2 * GetSystemMetrics(SM_CYSIZEFRAME)); 243 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; 256 } 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; 268 } 269 return TRUE; 270} 271 272extern Bool winInDestroyWindowsWindow; 273static Bool winInRaiseWindow = FALSE; 274static void winRaiseWindow(WindowPtr pWin) 275{ 276 if (!winInDestroyWindowsWindow && !winInRaiseWindow) 277 { 278 BOOL oldstate = winInRaiseWindow; 279 winInRaiseWindow = TRUE; 280 /* Call configure window directly to make sure it gets processed 281 * in time 282 */ 283 XID vlist[1] = { 0 }; 284 ConfigureWindow(pWin, CWStackMode, vlist, serverClient); 285 winInRaiseWindow = oldstate; 286 } 287} 288 289 290/* 291 * winTopLevelWindowProc - Window procedure for all top-level Windows windows. 292 */ 293 294LRESULT CALLBACK 295winTopLevelWindowProc (HWND hwnd, UINT message, 296 WPARAM wParam, LPARAM lParam) 297{ 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; 313 314#if CYGDEBUG 315 winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam, lParam); 316#endif 317 318 /* Check if the Windows window property for our X window pointer is valid */ 319 if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL) 320 { 321 /* Our X window pointer is valid */ 322 323 /* Get pointers to the drawable and the screen */ 324 pDraw = &pWin->drawable; 325 s_pScreen = pWin->drawable.pScreen; 326 327 /* Get a pointer to our window privates */ 328 pWinPriv = winGetWindowPriv(pWin); 329 330 /* Get pointers to our screen privates and screen info */ 331 s_pScreenPriv = pWinPriv->pScreenPriv; 332 s_pScreenInfo = s_pScreenPriv->pScreenInfo; 333 334 /* Get the handle for our screen-sized window */ 335 hwndScreen = s_pScreenPriv->hwndScreen; 336 337 /* */ 338 wmMsg.msg = 0; 339 wmMsg.hwndWindow = hwnd; 340 wmMsg.iWindow = (Window)GetProp (hwnd, WIN_WID_PROP); 341 342 wmMsg.iX = pDraw->x; 343 wmMsg.iY = pDraw->y; 344 wmMsg.iWidth = pDraw->width; 345 wmMsg.iHeight = pDraw->height; 346 347 fWMMsgInitialized = TRUE; 348 349#if 0 350 /* 351 * Print some debugging information 352 */ 353 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_iWindowPrivateKey %p\n", g_iWindowPrivateKey); 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 374 } 375 376 /* Branch on message type */ 377 switch (message) 378 { 379 case WM_CREATE: 380 381 /* */ 382 SetProp (hwnd, 383 WIN_WINDOW_PROP, 384 (HANDLE)((LPCREATESTRUCT) lParam)->lpCreateParams); 385 386 /* */ 387 SetProp (hwnd, 388 WIN_WID_PROP, 389 (HANDLE)winGetWindowID (((LPCREATESTRUCT) lParam)->lpCreateParams)); 390 391 /* 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. 395 */ 396 winReorderWindowsMultiWindow (); 397 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); 405 406 return 0; 407 408 case WM_INIT_SYS_MENU: 409 /* 410 * Add whatever the setup file wants to for this window 411 */ 412 SetupSysMenu ((unsigned long)hwnd); 413 return 0; 414 415 case WM_SYSCOMMAND: 416 /* 417 * Any window menu items go through here 418 */ 419 if (HandleCustomWM_COMMAND ((unsigned long)hwnd, LOWORD(wParam))) 420 { 421 /* Don't pass customized menus to DefWindowProc */ 422 return 0; 423 } 424 if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE) 425 { 426 WINDOWPLACEMENT wndpl; 427 wndpl.length = sizeof(wndpl); 428 if (GetWindowPlacement(hwnd, &wndpl) && wndpl.showCmd == SW_SHOWMINIMIZED) 429 needRestack = TRUE; 430 } 431 break; 432 433 case WM_INITMENU: 434 /* Checks/Unchecks any menu items before they are displayed */ 435 HandleCustomWM_INITMENU ((unsigned long)hwnd, wParam); 436 break; 437 438 case WM_PAINT: 439 /* Only paint if our window handle is valid */ 440 if (hwndScreen == NULL) 441 break; 442 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) 447 { 448 EndPaint (hwnd, &ps); 449 return 0; 450 } 451 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)) 459 { 460 LPVOID lpMsgBuf; 461 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); 471 472 ErrorF ("winTopLevelWindowProc - BitBlt failed: %s\n", 473 (LPSTR)lpMsgBuf); 474 LocalFree (lpMsgBuf); 475 } 476 477 /* EndPaint frees the DC */ 478 EndPaint (hwnd, &ps); 479 return 0; 480 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); 485 486 /* Translate the client area mouse coordinates to screen coordinates */ 487 ClientToScreen (hwnd, &ptMouse); 488 489 /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */ 490 ptMouse.x -= GetSystemMetrics (SM_XVIRTUALSCREEN); 491 ptMouse.y -= GetSystemMetrics (SM_YVIRTUALSCREEN); 492 493 /* We can't do anything without privates */ 494 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 495 break; 496 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); 502 503 /* Are we tracking yet? */ 504 if (!s_fTracking) 505 { 506 TRACKMOUSEEVENT tme; 507 508 /* Setup data structure */ 509 ZeroMemory (&tme, sizeof (tme)); 510 tme.cbSize = sizeof (tme); 511 tme.dwFlags = TME_LEAVE; 512 tme.hwndTrack = hwnd; 513 514 /* Call the tracking function */ 515 if (!(*g_fpTrackMouseEvent) (&tme)) 516 ErrorF ("winTopLevelWindowProc - _TrackMouseEvent failed\n"); 517 518 /* Flag that we are tracking now */ 519 s_fTracking = TRUE; 520 } 521 522 /* Hide or show the Windows mouse cursor */ 523 if (g_fSoftwareCursor && g_fCursor) 524 { 525 /* Hide Windows cursor */ 526 g_fCursor = FALSE; 527 ShowCursor (FALSE); 528 } 529 530 /* Kill the timer used to poll mouse events */ 531 if (g_uipMousePollingTimerID != 0) 532 { 533 KillTimer (s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID); 534 g_uipMousePollingTimerID = 0; 535 } 536 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; 542 543 case WM_NCMOUSEMOVE: 544 /* 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. 551 */ 552 553 /* We can't do anything without privates */ 554 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 555 break; 556 557 /* Non-client mouse movement, show Windows cursor */ 558 if (g_fSoftwareCursor && !g_fCursor) 559 { 560 g_fCursor = TRUE; 561 ShowCursor (TRUE); 562 } 563 564 /* 565 * Timer to poll mouse events. This is needed to make 566 * programs like xeyes follow the mouse properly. 567 */ 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; 574 575 case WM_MOUSELEAVE: 576 /* Mouse has left our client area */ 577 578 /* Flag that we are no longer tracking */ 579 s_fTracking = FALSE; 580 581 /* Show the mouse cursor, if necessary */ 582 if (g_fSoftwareCursor && !g_fCursor) 583 { 584 g_fCursor = TRUE; 585 ShowCursor (TRUE); 586 } 587 588 /* 589 * Timer to poll mouse events. This is needed to make 590 * programs like xeyes follow the mouse properly. 591 */ 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; 598 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); 605 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); 611 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); 618 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); 624 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); 631 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); 637 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); 647 648 case WM_MOUSEWHEEL: 649 650 /* Pass the message to the root window */ 651 SendMessage (hwndScreen, message, wParam, lParam); 652 return 0; 653 654 case WM_SETFOCUS: 655 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 656 break; 657 658 winRestoreModeKeyStates (); 659 660 /* Add the keyboard hook if possible */ 661 if (g_fKeyboardHookLL) 662 g_fKeyboardHookLL = winInstallKeyboardHookLL (); 663 return 0; 664 665 case WM_KILLFOCUS: 666 /* Pop any pressed keys since we are losing keyboard focus */ 667 winKeybdReleaseKeys (); 668 669 /* Remove our keyboard hook if it is installed */ 670 winRemoveKeyboardHookLL (); 671 return 0; 672 673 case WM_SYSDEADCHAR: 674 case WM_DEADCHAR: 675 /* 676 * NOTE: We do nothing with WM_*CHAR messages, 677 * nor does the root window, so we can just toss these messages. 678 */ 679 return 0; 680 681 case WM_SYSKEYDOWN: 682 case WM_KEYDOWN: 683 684 /* 685 * Don't pass Alt-F4 key combo to root window, 686 * let Windows translate to WM_CLOSE and close this top-level window. 687 * 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. 691 * 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. 697 */ 698 if (wParam == VK_F4 && (GetKeyState (VK_MENU) & 0x8000)) 699 break; 700 701#if CYGWINDOWING_DEBUG 702 if (wParam == VK_ESCAPE) 703 { 704 /* Place for debug: put any tests and dumps here */ 705 WINDOWPLACEMENT windPlace; 706 RECT rc; 707 LPRECT pRect; 708 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)) 719 { 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); 724 } 725 if (GetWindowRect (hwnd, &rc)) 726 { 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); 731 } 732 ErrorF ("\n"); 733 } 734#endif 735 736 /* Pass the message to the root window */ 737 return winWindowProc(hwndScreen, message, wParam, lParam); 738 739 case WM_SYSKEYUP: 740 case WM_KEYUP: 741 742 743 /* Pass the message to the root window */ 744 return winWindowProc(hwndScreen, message, wParam, lParam); 745 746 case WM_HOTKEY: 747 748 /* Pass the message to the root window */ 749 SendMessage (hwndScreen, message, wParam, lParam); 750 return 0; 751 752 case WM_ACTIVATE: 753 754 /* Pass the message to the root window */ 755 SendMessage (hwndScreen, message, wParam, lParam); 756 757 if (LOWORD(wParam) != WA_INACTIVE) 758 { 759 /* Raise the window to the top in Z order */ 760 /* ago: Activate does not mean putting it to front! */ 761 /* 762 wmMsg.msg = WM_WM_RAISE; 763 if (fWMMsgInitialized) 764 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); 765 */ 766 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); 772 } 773 return 0; 774 775 case WM_ACTIVATEAPP: 776 /* 777 * This message is also sent to the root window 778 * so we do nothing for individual multiwindow windows 779 */ 780 break; 781 782 case WM_CLOSE: 783 /* Branch on if the window was killed in X already */ 784 if (pWinPriv->fXKilled) 785 { 786 /* Window was killed, go ahead and destroy the window */ 787 DestroyWindow (hwnd); 788 } 789 else 790 { 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); 795 } 796 return 0; 797 798 case WM_DESTROY: 799 800 /* Branch on if the window was killed in X already */ 801 if (pWinPriv && !pWinPriv->fXKilled) 802 { 803 ErrorF ("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n"); 804 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); 809 } 810 811 RemoveProp (hwnd, WIN_WINDOW_PROP); 812 RemoveProp (hwnd, WIN_WID_PROP); 813 RemoveProp (hwnd, WIN_NEEDMANAGE_PROP); 814 815 break; 816 817 case WM_MOVE: 818 /* Adjust the X Window to the moved Windows window */ 819 winAdjustXWindow (pWin, hwnd); 820 return 0; 821 822 case WM_SHOWWINDOW: 823 /* Bail out if the window is being hidden */ 824 if (!wParam) 825 return 0; 826 827 /* Tell X to map the window */ 828 MapWindow (pWin, wClient(pWin)); 829 830 /* */ 831 if (!pWin->overrideRedirect) 832 { 833 DWORD dwExStyle; 834 DWORD dwStyle; 835 RECT rcNew; 836 int iDx, iDy; 837 838 /* Flag that this window needs to be made active when clicked */ 839 SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1); 840 841 /* Get the standard and extended window style information */ 842 dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE); 843 dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE); 844 845 /* */ 846 if (dwExStyle != WS_EX_APPWINDOW) 847 { 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); 854 855#if 0 856 ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n", 857 rcNew.left, rcNew.top, 858 rcNew.right, rcNew.bottom); 859#endif 860 861 /* */ 862 AdjustWindowRectEx (&rcNew, 863 WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW, 864 FALSE, 865 WS_EX_APPWINDOW); 866 867 /* Calculate position deltas */ 868 iDx = pDraw->x - rcNew.left; 869 iDy = pDraw->y - rcNew.top; 870 871 /* Calculate new rectangle */ 872 rcNew.left += iDx; 873 rcNew.right += iDx; 874 rcNew.top += iDy; 875 rcNew.bottom += iDy; 876 877#if 0 878 ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n", 879 rcNew.left, rcNew.top, 880 rcNew.right, rcNew.bottom); 881#endif 882 883 /* Set the window extended style flags */ 884 SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW); 885 886 /* Set the window standard style flags */ 887 SetWindowLongPtr (hwnd, GWL_STYLE, 888 WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW); 889 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); 896 897 /* Bring the Windows window to the foreground */ 898 SetForegroundWindow (hwnd); 899 } 900 } 901 else /* It is an overridden window so make it top of Z stack */ 902 { 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); 908 } 909 910 /* Setup the Window Manager message */ 911 wmMsg.msg = WM_WM_MAP; 912 wmMsg.iWidth = pDraw->width; 913 wmMsg.iHeight = pDraw->height; 914 915 /* Tell our Window Manager thread to map the window */ 916 if (fWMMsgInitialized) 917 winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); 918 919 return 0; 920 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); 925 926 case WM_WINDOWPOSCHANGED: 927 { 928 LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam; 929 930 if (!(pWinPos->flags & SWP_NOZORDER)) 931 { 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) 938 { 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); 944 } 945 else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) 946 { 947 } 948 else 949 { 950 /* Check if this window is top of X windows. */ 951 HWND hWndAbove = NULL; 952 DWORD dwCurrentProcessID = GetCurrentProcessId (); 953 DWORD dwWindowProcessID = 0; 954 955 for (hWndAbove = pWinPos->hwndInsertAfter; 956 hWndAbove != NULL; 957 hWndAbove = GetNextWindow (hWndAbove, GW_HWNDPREV)) 958 { 959 /* Ignore other XWin process's window */ 960 GetWindowThreadProcessId (hWndAbove, &dwWindowProcessID); 961 962 if ((dwWindowProcessID == dwCurrentProcessID) 963 && GetProp (hWndAbove, WIN_WINDOW_PROP) 964 && !IsWindowVisible (hWndAbove) 965 && !IsIconic (hWndAbove) ) /* ignore minimized windows */ 966 break; 967 } 968 /* If this is top of X windows in Windows stack, 969 raise it in X stack. */ 970 if (hWndAbove == NULL) 971 { 972#if CYGWINDOWING_DEBUG 973 winDebug ("\traise to top\n"); 974#endif 975 winRaiseWindow(pWin); 976 } 977 } 978 } 979 } 980 /* 981 * Pass the message to DefWindowProc to let the function 982 * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE. 983 */ 984 break; 985 986 case WM_SIZE: 987 /* see dix/window.c */ 988#if CYGWINDOWING_DEBUG 989 { 990 char buf[64]; 991 switch (wParam) 992 { 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"); 1004 } 1005 ErrorF ("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n", 1006 (int)LOWORD(lParam), (int)HIWORD(lParam), buf, 1007 (int)(GetTickCount ())); 1008 } 1009#endif 1010 /* Adjust the X Window to the moved Windows window */ 1011 winAdjustXWindow (pWin, hwnd); 1012 return 0; /* end of WM_SIZE handler */ 1013 1014 case WM_MOUSEACTIVATE: 1015 1016 /* Check if this window needs to be made active when clicked */ 1017 if (!GetProp (pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) 1018 { 1019#if CYGMULTIWINDOW_DEBUG 1020 ErrorF ("winTopLevelWindowProc - WM_MOUSEACTIVATE - " 1021 "MA_NOACTIVATE\n"); 1022#endif 1023 1024 /* */ 1025 return MA_NOACTIVATE; 1026 } 1027 break; 1028 1029 case WM_SETCURSOR: 1030 if (LOWORD(lParam) == HTCLIENT) 1031 { 1032 if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle); 1033 return TRUE; 1034 } 1035 break; 1036 1037 default: 1038 break; 1039 } 1040 1041 ret = DefWindowProc (hwnd, message, wParam, lParam); 1042 /* 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. 1045 */ 1046 if (needRestack) 1047 winReorderWindowsMultiWindow(); 1048 return ret; 1049} 1050