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: Dakshinamurthy Karra 29 * Suhaib M Siddiqi 30 * Peter Busch 31 * Harold L Hunt II 32 * MATSUZAKI Kensuke 33 */ 34 35#ifdef HAVE_XWIN_CONFIG_H 36#include <xwin-config.h> 37#endif 38#include "win.h" 39#include <commctrl.h> 40#include "winprefs.h" 41#include "winconfig.h" 42#include "winmsg.h" 43#include "winmonitors.h" 44#include "inputstr.h" 45 46/* 47 * Global variables 48 */ 49 50Bool g_fCursor = TRUE; 51Bool g_fButton[3] = { FALSE, FALSE, FALSE }; 52 53 54/* 55 * Called by winWakeupHandler 56 * Processes current Windows message 57 */ 58 59LRESULT CALLBACK 60winWindowProc (HWND hwnd, UINT message, 61 WPARAM wParam, LPARAM lParam) 62{ 63 static winPrivScreenPtr s_pScreenPriv = NULL; 64 static winScreenInfo *s_pScreenInfo = NULL; 65 static ScreenPtr s_pScreen = NULL; 66 static HWND s_hwndLastPrivates = NULL; 67 static HINSTANCE s_hInstance; 68 static Bool s_fTracking = FALSE; 69 static unsigned long s_ulServerGeneration = 0; 70 static UINT s_uTaskbarRestart = 0; 71 int iScanCode; 72 int i; 73 74#if CYGDEBUG 75 winDebugWin32Message("winWindowProc", hwnd, message, wParam, lParam); 76#endif 77 78 /* Watch for server regeneration */ 79 if (g_ulServerGeneration != s_ulServerGeneration) 80 { 81 /* Store new server generation */ 82 s_ulServerGeneration = g_ulServerGeneration; 83 } 84 85 /* Only retrieve new privates pointers if window handle is null or changed */ 86 if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates) 87 && (s_pScreenPriv = GetProp (hwnd, WIN_SCR_PROP)) != NULL) 88 { 89#if CYGDEBUG 90 winDebug ("winWindowProc - Setting privates handle\n"); 91#endif 92 s_pScreenInfo = s_pScreenPriv->pScreenInfo; 93 s_pScreen = s_pScreenInfo->pScreen; 94 s_hwndLastPrivates = hwnd; 95 } 96 else if (s_pScreenPriv == NULL) 97 { 98 /* For safety, handle case that should never happen */ 99 s_pScreenInfo = NULL; 100 s_pScreen = NULL; 101 s_hwndLastPrivates = NULL; 102 } 103 104 /* Branch on message type */ 105 switch (message) 106 { 107 case WM_TRAYICON: 108 return winHandleIconMessage (hwnd, message, wParam, lParam, 109 s_pScreenPriv); 110 111 case WM_CREATE: 112#if CYGDEBUG 113 winDebug ("winWindowProc - WM_CREATE\n"); 114#endif 115 116 /* 117 * Add a property to our display window that references 118 * this screens' privates. 119 * 120 * This allows the window procedure to refer to the 121 * appropriate window DC and shadow DC for the window that 122 * it is processing. We use this to repaint exposed 123 * areas of our display window. 124 */ 125 s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams; 126 s_hInstance = ((LPCREATESTRUCT) lParam)->hInstance; 127 s_pScreenInfo = s_pScreenPriv->pScreenInfo; 128 s_pScreen = s_pScreenInfo->pScreen; 129 s_hwndLastPrivates = hwnd; 130 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); 131 SetProp (hwnd, WIN_SCR_PROP, s_pScreenPriv); 132 133 /* Setup tray icon */ 134 if (!s_pScreenInfo->fNoTrayIcon) 135 { 136 /* 137 * NOTE: The WM_CREATE message is processed before CreateWindowEx 138 * returns, so s_pScreenPriv->hwndScreen is invalid at this point. 139 * We go ahead and copy our hwnd parameter over top of the screen 140 * privates hwndScreen so that we have a valid value for 141 * that member. Otherwise, the tray icon will disappear 142 * the first time you move the mouse over top of it. 143 */ 144 145 s_pScreenPriv->hwndScreen = hwnd; 146 147 winInitNotifyIcon (s_pScreenPriv); 148 } 149 return 0; 150 151 case WM_DISPLAYCHANGE: 152 /* 153 WM_DISPLAYCHANGE seems to be sent when the monitor layout or 154 any monitor's resolution or depth changes, but it's lParam and 155 wParam always indicate the resolution and bpp for the primary 156 monitor (so ignore that as we could be on any monitor...) 157 */ 158 159 /* We cannot handle a display mode change during initialization */ 160 if (s_pScreenInfo == NULL) 161 FatalError ("winWindowProc - WM_DISPLAYCHANGE - The display " 162 "mode changed while we were intializing. This is " 163 "very bad and unexpected. Exiting.\n"); 164 165 /* 166 * We do not care about display changes with 167 * fullscreen DirectDraw engines, because those engines set 168 * their own mode when they become active. 169 */ 170 if (s_pScreenInfo->fFullScreen 171 && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD 172 || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL 173#ifdef XWIN_PRIMARYFB 174 || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD 175#endif 176 )) 177 { 178 break; 179 } 180 181 ErrorF ("winWindowProc - WM_DISPLAYCHANGE - new width: %d " 182 "new height: %d new bpp: %d\n", 183 LOWORD (lParam), HIWORD (lParam), wParam); 184 185 /* 186 * Check for a disruptive change in depth. 187 * We can only display a message for a disruptive depth change, 188 * we cannot do anything to correct the situation. 189 */ 190 /* 191 XXX: maybe we need to check if GetSystemMetrics(SM_SAMEDISPLAYFORMAT) 192 has changed as well... 193 */ 194 if (s_pScreenInfo->dwBPP != GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL)) 195 { 196 if ((s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD 197 || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL 198#ifdef XWIN_PRIMARYFB 199 || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD 200#endif 201 )) 202 { 203 /* Cannot display the visual until the depth is restored */ 204 ErrorF ("winWindowProc - Disruptive change in depth\n"); 205 206 /* Display depth change dialog */ 207 winDisplayDepthChangeDialog (s_pScreenPriv); 208 209 /* Flag that we have an invalid screen depth */ 210 s_pScreenPriv->fBadDepth = TRUE; 211 212 /* Minimize the display window */ 213 ShowWindow (hwnd, SW_MINIMIZE); 214 } 215 else 216 { 217 /* For GDI, performance may suffer until original depth is restored */ 218 ErrorF ("winWindowProc - Performance may be non-optimal after change in depth\n"); 219 } 220 } 221 else 222 { 223 /* Flag that we have a valid screen depth */ 224 s_pScreenPriv->fBadDepth = FALSE; 225 } 226 227 /* 228 If we could cheaply check if this WM_DISPLAYCHANGE change 229 affects the monitor(s) which this X screen is displayed on 230 then we should do so here. For the moment, assume it does. 231 (this is probably usually the case so that might be an 232 overoptimization) 233 */ 234 { 235 /* 236 In rootless modes which are monitor or virtual desktop size 237 use RandR to resize the X screen 238 */ 239 if ((!s_pScreenInfo->fUserGaveHeightAndWidth) && 240 (s_pScreenInfo->iResizeMode == resizeWithRandr) && 241 (FALSE 242#ifdef XWIN_MULTIWINDOWEXTWM 243 || s_pScreenInfo->fMWExtWM 244#endif 245 || s_pScreenInfo->fRootless 246#ifdef XWIN_MULTIWINDOW 247 || s_pScreenInfo->fMultiWindow 248#endif 249 )) 250 { 251 DWORD dwWidth, dwHeight; 252 253 if (s_pScreenInfo->fMultipleMonitors) 254 { 255 /* resize to new virtual desktop size */ 256 dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); 257 dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); 258 } 259 else 260 { 261 /* resize to new size of specified monitor */ 262 struct GetMonitorInfoData data; 263 if (QueryMonitor(s_pScreenInfo->iMonitor, &data)) 264 { 265 if (data.bMonitorSpecifiedExists == TRUE) 266 { 267 dwWidth = data.monitorWidth; 268 dwHeight = data.monitorHeight; 269 /* 270 XXX: monitor may have changed position, 271 so we might need to update xinerama data 272 */ 273 } 274 else 275 { 276 ErrorF ("Monitor number %d no longer exists!\n", s_pScreenInfo->iMonitor); 277 } 278 } 279 } 280 281 /* 282 XXX: probably a small bug here: we don't compute the work area 283 and allow for task bar 284 285 XXX: generally, we don't allow for the task bar being moved after 286 the server is started 287 */ 288 289 /* Set screen size to match new size, if it is different to current */ 290 if ((s_pScreenInfo->dwWidth != dwWidth) || 291 (s_pScreenInfo->dwHeight != dwHeight)) 292 { 293 winDoRandRScreenSetSize(s_pScreen, 294 dwWidth, 295 dwHeight, 296 (dwWidth * 25.4) / monitorResolution, 297 (dwHeight * 25.4) / monitorResolution); 298 } 299 } 300 else 301 { 302 /* 303 * We can simply recreate the same-sized primary surface when 304 * the display dimensions change. 305 */ 306 307 /* 308 * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface 309 * and CreatePrimarySurface function pointers to point 310 * to the no operation function, NoopDDA. This allows us 311 * to blindly call these functions, even if they are not 312 * relevant to the current engine (e.g., Shadow GDI). 313 */ 314 315 winDebug ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n"); 316 317 /* Release the old primary surface */ 318 (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen); 319 320 /* Create the new primary surface */ 321 (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen); 322 } 323 } 324 325 break; 326 327 case WM_SIZE: 328 { 329 SCROLLINFO si; 330 RECT rcWindow; 331 int iWidth, iHeight; 332 333#if CYGDEBUG 334 winDebug ("winWindowProc - WM_SIZE\n"); 335#endif 336 337 /* Break if we do not allow resizing */ 338 if ((s_pScreenInfo->iResizeMode == notAllowed) 339 || !s_pScreenInfo->fDecoration 340#ifdef XWIN_MULTIWINDOWEXTWM 341 || s_pScreenInfo->fMWExtWM 342#endif 343 || s_pScreenInfo->fRootless 344#ifdef XWIN_MULTIWINDOW 345 || s_pScreenInfo->fMultiWindow 346#endif 347 || s_pScreenInfo->fFullScreen) 348 break; 349 350 /* No need to resize if we get minimized */ 351 if (wParam == SIZE_MINIMIZED) 352 return 0; 353 354 ErrorF ("winWindowProc - WM_SIZE - new client area w: %d h: %d\n", 355 LOWORD (lParam), HIWORD (lParam)); 356 357 if (s_pScreenInfo->iResizeMode == resizeWithRandr) 358 { 359 /* Actual resizing is done on WM_EXITSIZEMOVE */ 360 return 0; 361 } 362 363 /* Otherwise iResizeMode == resizeWithScrollbars */ 364 365 /* 366 * Get the size of the whole window, including client area, 367 * scrollbars, and non-client area decorations (caption, borders). 368 * We do this because we need to check if the client area 369 * without scrollbars is large enough to display the whole visual. 370 * The new client area size passed by lParam already subtracts 371 * the size of the scrollbars if they are currently displayed. 372 * So checking is LOWORD(lParam) == visual_width and 373 * HIWORD(lParam) == visual_height will never tell us to hide 374 * the scrollbars because the client area would always be too small. 375 * GetClientRect returns the same sizes given by lParam, so we 376 * cannot use GetClientRect either. 377 */ 378 GetWindowRect (hwnd, &rcWindow); 379 iWidth = rcWindow.right - rcWindow.left; 380 iHeight = rcWindow.bottom - rcWindow.top; 381 382 /* Subtract the frame size from the window size. */ 383 iWidth -= 2 * GetSystemMetrics (SM_CXSIZEFRAME); 384 iHeight -= (2 * GetSystemMetrics (SM_CYSIZEFRAME) 385 + GetSystemMetrics (SM_CYCAPTION)); 386 387 /* 388 * Update scrollbar page sizes. 389 * NOTE: If page size == range, then the scrollbar is 390 * automatically hidden. 391 */ 392 393 /* Is the naked client area large enough to show the whole visual? */ 394 if (iWidth < s_pScreenInfo->dwWidth 395 || iHeight < s_pScreenInfo->dwHeight) 396 { 397 /* Client area too small to display visual, use scrollbars */ 398 iWidth -= GetSystemMetrics (SM_CXVSCROLL); 399 iHeight -= GetSystemMetrics (SM_CYHSCROLL); 400 } 401 402 /* Set the horizontal scrollbar page size */ 403 si.cbSize = sizeof (si); 404 si.fMask = SIF_PAGE | SIF_RANGE; 405 si.nMin = 0; 406 si.nMax = s_pScreenInfo->dwWidth - 1; 407 si.nPage = iWidth; 408 SetScrollInfo (hwnd, SB_HORZ, &si, TRUE); 409 410 /* Set the vertical scrollbar page size */ 411 si.cbSize = sizeof (si); 412 si.fMask = SIF_PAGE | SIF_RANGE; 413 si.nMin = 0; 414 si.nMax = s_pScreenInfo->dwHeight - 1; 415 si.nPage = iHeight; 416 SetScrollInfo (hwnd, SB_VERT, &si, TRUE); 417 418 /* 419 * NOTE: Scrollbars may have moved if they were at the 420 * far right/bottom, so we query their current position. 421 */ 422 423 /* Get the horizontal scrollbar position and set the offset */ 424 si.cbSize = sizeof (si); 425 si.fMask = SIF_POS; 426 GetScrollInfo (hwnd, SB_HORZ, &si); 427 s_pScreenInfo->dwXOffset = -si.nPos; 428 429 /* Get the vertical scrollbar position and set the offset */ 430 si.cbSize = sizeof (si); 431 si.fMask = SIF_POS; 432 GetScrollInfo (hwnd, SB_VERT, &si); 433 s_pScreenInfo->dwYOffset = -si.nPos; 434 } 435 return 0; 436 437 case WM_ENTERSIZEMOVE: 438 ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n"); 439 break; 440 441 case WM_EXITSIZEMOVE: 442 ErrorF("winWindowProc - WM_EXITSIZEMOVE\n"); 443 444 if (s_pScreenInfo->iResizeMode == resizeWithRandr) 445 { 446 /* Set screen size to match new client area, if it is different to current */ 447 RECT rcClient; 448 DWORD dwWidth, dwHeight; 449 450 GetClientRect (hwnd, &rcClient); 451 dwWidth = rcClient.right - rcClient.left; 452 dwHeight = rcClient.bottom - rcClient.top; 453 454 if ((s_pScreenInfo->dwWidth != dwWidth) || 455 (s_pScreenInfo->dwHeight != dwHeight)) 456 { 457 /* mm = dots * (25.4 mm / inch) / (dots / inch) */ 458 winDoRandRScreenSetSize(s_pScreen, 459 dwWidth, 460 dwHeight, 461 (dwWidth * 25.4) / monitorResolution, 462 (dwHeight * 25.4) / monitorResolution); 463 } 464 } 465 466 break; 467 468 case WM_VSCROLL: 469 { 470 SCROLLINFO si; 471 int iVertPos; 472 473#if CYGDEBUG 474 winDebug ("winWindowProc - WM_VSCROLL\n"); 475#endif 476 477 /* Get vertical scroll bar info */ 478 si.cbSize = sizeof (si); 479 si.fMask = SIF_ALL; 480 GetScrollInfo (hwnd, SB_VERT, &si); 481 482 /* Save the vertical position for comparison later */ 483 iVertPos = si.nPos; 484 485 /* 486 * Don't forget: 487 * moving the scrollbar to the DOWN, scroll the content UP 488 */ 489 switch (LOWORD(wParam)) 490 { 491 case SB_TOP: 492 si.nPos = si.nMin; 493 break; 494 495 case SB_BOTTOM: 496 si.nPos = si.nMax - si.nPage + 1; 497 break; 498 499 case SB_LINEUP: 500 si.nPos -= 1; 501 break; 502 503 case SB_LINEDOWN: 504 si.nPos += 1; 505 break; 506 507 case SB_PAGEUP: 508 si.nPos -= si.nPage; 509 break; 510 511 case SB_PAGEDOWN: 512 si.nPos += si.nPage; 513 break; 514 515 case SB_THUMBTRACK: 516 si.nPos = si.nTrackPos; 517 break; 518 519 default: 520 break; 521 } 522 523 /* 524 * We retrieve the position after setting it, 525 * because Windows may adjust it. 526 */ 527 si.fMask = SIF_POS; 528 SetScrollInfo (hwnd, SB_VERT, &si, TRUE); 529 GetScrollInfo (hwnd, SB_VERT, &si); 530 531 /* Scroll the window if the position has changed */ 532 if (si.nPos != iVertPos) 533 { 534 /* Save the new offset for bit block transfers, etc. */ 535 s_pScreenInfo->dwYOffset = -si.nPos; 536 537 /* Change displayed region in the window */ 538 ScrollWindowEx (hwnd, 539 0, 540 iVertPos - si.nPos, 541 NULL, 542 NULL, 543 NULL, 544 NULL, 545 SW_INVALIDATE); 546 547 /* Redraw the window contents */ 548 UpdateWindow (hwnd); 549 } 550 } 551 return 0; 552 553 case WM_HSCROLL: 554 { 555 SCROLLINFO si; 556 int iHorzPos; 557 558#if CYGDEBUG 559 winDebug ("winWindowProc - WM_HSCROLL\n"); 560#endif 561 562 /* Get horizontal scroll bar info */ 563 si.cbSize = sizeof (si); 564 si.fMask = SIF_ALL; 565 GetScrollInfo (hwnd, SB_HORZ, &si); 566 567 /* Save the horizontal position for comparison later */ 568 iHorzPos = si.nPos; 569 570 /* 571 * Don't forget: 572 * moving the scrollbar to the RIGHT, scroll the content LEFT 573 */ 574 switch (LOWORD(wParam)) 575 { 576 case SB_LEFT: 577 si.nPos = si.nMin; 578 break; 579 580 case SB_RIGHT: 581 si.nPos = si.nMax - si.nPage + 1; 582 break; 583 584 case SB_LINELEFT: 585 si.nPos -= 1; 586 break; 587 588 case SB_LINERIGHT: 589 si.nPos += 1; 590 break; 591 592 case SB_PAGELEFT: 593 si.nPos -= si.nPage; 594 break; 595 596 case SB_PAGERIGHT: 597 si.nPos += si.nPage; 598 break; 599 600 case SB_THUMBTRACK: 601 si.nPos = si.nTrackPos; 602 break; 603 604 default: 605 break; 606 } 607 608 /* 609 * We retrieve the position after setting it, 610 * because Windows may adjust it. 611 */ 612 si.fMask = SIF_POS; 613 SetScrollInfo (hwnd, SB_HORZ, &si, TRUE); 614 GetScrollInfo (hwnd, SB_HORZ, &si); 615 616 /* Scroll the window if the position has changed */ 617 if (si.nPos != iHorzPos) 618 { 619 /* Save the new offset for bit block transfers, etc. */ 620 s_pScreenInfo->dwXOffset = -si.nPos; 621 622 /* Change displayed region in the window */ 623 ScrollWindowEx (hwnd, 624 iHorzPos - si.nPos, 625 0, 626 NULL, 627 NULL, 628 NULL, 629 NULL, 630 SW_INVALIDATE); 631 632 /* Redraw the window contents */ 633 UpdateWindow (hwnd); 634 } 635 } 636 return 0; 637 638 case WM_GETMINMAXINFO: 639 { 640 MINMAXINFO *pMinMaxInfo = (MINMAXINFO *) lParam; 641 int iCaptionHeight; 642 int iBorderHeight, iBorderWidth; 643 644#if CYGDEBUG 645 winDebug ("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %08x\n", 646 s_pScreenInfo); 647#endif 648 649 /* Can't do anything without screen info */ 650 if (s_pScreenInfo == NULL 651 || (s_pScreenInfo->iResizeMode != resizeWithScrollbars) 652 || s_pScreenInfo->fFullScreen 653 || !s_pScreenInfo->fDecoration 654#ifdef XWIN_MULTIWINDOWEXTWM 655 || s_pScreenInfo->fMWExtWM 656#endif 657 || s_pScreenInfo->fRootless 658#ifdef XWIN_MULTIWINDOW 659 || s_pScreenInfo->fMultiWindow 660#endif 661 ) 662 break; 663 664 /* 665 * Here we can override the maximum tracking size, which 666 * is the largest size that can be assigned to our window 667 * via the sizing border. 668 */ 669 670 /* 671 * FIXME: Do we only need to do this once, since our visual size 672 * does not change? Does Windows store this value statically 673 * once we have set it once? 674 */ 675 676 /* Get the border and caption sizes */ 677 iCaptionHeight = GetSystemMetrics (SM_CYCAPTION); 678 iBorderWidth = 2 * GetSystemMetrics (SM_CXSIZEFRAME); 679 iBorderHeight = 2 * GetSystemMetrics (SM_CYSIZEFRAME); 680 681 /* Allow the full visual to be displayed */ 682 pMinMaxInfo->ptMaxTrackSize.x 683 = s_pScreenInfo->dwWidth + iBorderWidth; 684 pMinMaxInfo->ptMaxTrackSize.y 685 = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight; 686 } 687 return 0; 688 689 case WM_ERASEBKGND: 690#if CYGDEBUG 691 winDebug ("winWindowProc - WM_ERASEBKGND\n"); 692#endif 693 /* 694 * Pretend that we did erase the background but we don't care, 695 * the application uses the full window estate. This avoids some 696 * flickering when resizing. 697 */ 698 return TRUE; 699 700 case WM_PAINT: 701#if CYGDEBUG 702 winDebug ("winWindowProc - WM_PAINT\n"); 703#endif 704 /* Only paint if we have privates and the server is enabled */ 705 if (s_pScreenPriv == NULL 706 || !s_pScreenPriv->fEnabled 707 || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive) 708 || s_pScreenPriv->fBadDepth) 709 { 710 /* We don't want to paint */ 711 break; 712 } 713 714 /* Break out here if we don't have a valid paint routine */ 715 if (s_pScreenPriv->pwinBltExposedRegions == NULL) 716 break; 717 718 /* Call the engine dependent repainter */ 719 (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen); 720 return 0; 721 722 case WM_PALETTECHANGED: 723 { 724#if CYGDEBUG 725 winDebug ("winWindowProc - WM_PALETTECHANGED\n"); 726#endif 727 /* 728 * Don't process if we don't have privates or a colormap, 729 * or if we have an invalid depth. 730 */ 731 if (s_pScreenPriv == NULL 732 || s_pScreenPriv->pcmapInstalled == NULL 733 || s_pScreenPriv->fBadDepth) 734 break; 735 736 /* Return if we caused the palette to change */ 737 if ((HWND) wParam == hwnd) 738 { 739 /* Redraw the screen */ 740 (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen); 741 return 0; 742 } 743 744 /* Reinstall the windows palette */ 745 (*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen); 746 747 /* Redraw the screen */ 748 (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen); 749 return 0; 750 } 751 752 case WM_MOUSEMOVE: 753 /* We can't do anything without privates */ 754 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 755 break; 756 757 /* We can't do anything without g_pwinPointer */ 758 if (g_pwinPointer == NULL) 759 break; 760 761 /* Has the mouse pointer crossed screens? */ 762 if (s_pScreen != miPointerGetScreen(g_pwinPointer)) 763 miPointerSetScreen (g_pwinPointer, s_pScreenInfo->dwScreen, 764 GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset, 765 GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset); 766 767 /* Are we tracking yet? */ 768 if (!s_fTracking) 769 { 770 TRACKMOUSEEVENT tme; 771 772 /* Setup data structure */ 773 ZeroMemory (&tme, sizeof (tme)); 774 tme.cbSize = sizeof (tme); 775 tme.dwFlags = TME_LEAVE; 776 tme.hwndTrack = hwnd; 777 778 /* Call the tracking function */ 779 if (!(*g_fpTrackMouseEvent) (&tme)) 780 ErrorF ("winWindowProc - _TrackMouseEvent failed\n"); 781 782 /* Flag that we are tracking now */ 783 s_fTracking = TRUE; 784 } 785 786 /* Hide or show the Windows mouse cursor */ 787 if (g_fSoftwareCursor && g_fCursor && (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer)) 788 { 789 /* Hide Windows cursor */ 790 g_fCursor = FALSE; 791 ShowCursor (FALSE); 792 } 793 else if (g_fSoftwareCursor && !g_fCursor && !s_pScreenPriv->fActive 794 && !s_pScreenInfo->fLessPointer) 795 { 796 /* Show Windows cursor */ 797 g_fCursor = TRUE; 798 ShowCursor (TRUE); 799 } 800 801 /* Deliver absolute cursor position to X Server */ 802 winEnqueueMotion(GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset, 803 GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset); 804 return 0; 805 806 case WM_NCMOUSEMOVE: 807 /* 808 * We break instead of returning 0 since we need to call 809 * DefWindowProc to get the mouse cursor changes 810 * and min/max/close button highlighting in Windows XP. 811 * The Platform SDK says that you should return 0 if you 812 * process this message, but it fails to mention that you 813 * will give up any default functionality if you do return 0. 814 */ 815 816 /* We can't do anything without privates */ 817 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 818 break; 819 820 /* Non-client mouse movement, show Windows cursor */ 821 if (g_fSoftwareCursor && !g_fCursor) 822 { 823 g_fCursor = TRUE; 824 ShowCursor (TRUE); 825 } 826 break; 827 828 case WM_MOUSELEAVE: 829 /* Mouse has left our client area */ 830 831 /* Flag that we are no longer tracking */ 832 s_fTracking = FALSE; 833 834 /* Show the mouse cursor, if necessary */ 835 if (g_fSoftwareCursor && !g_fCursor) 836 { 837 g_fCursor = TRUE; 838 ShowCursor (TRUE); 839 } 840 return 0; 841 842 case WM_LBUTTONDBLCLK: 843 case WM_LBUTTONDOWN: 844 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 845 break; 846 if (s_pScreenInfo->fRootless 847#ifdef XWIN_MULTIWINDOWEXTWM 848 || s_pScreenInfo->fMWExtWM 849#endif 850 ) 851 SetCapture (hwnd); 852 return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam); 853 854 case WM_LBUTTONUP: 855 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 856 break; 857 if (s_pScreenInfo->fRootless 858#ifdef XWIN_MULTIWINDOWEXTWM 859 || s_pScreenInfo->fMWExtWM 860#endif 861 ) 862 ReleaseCapture (); 863 return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam); 864 865 case WM_MBUTTONDBLCLK: 866 case WM_MBUTTONDOWN: 867 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 868 break; 869 if (s_pScreenInfo->fRootless 870#ifdef XWIN_MULTIWINDOWEXTWM 871 || s_pScreenInfo->fMWExtWM 872#endif 873 ) 874 SetCapture (hwnd); 875 return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam); 876 877 case WM_MBUTTONUP: 878 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 879 break; 880 if (s_pScreenInfo->fRootless 881#ifdef XWIN_MULTIWINDOWEXTWM 882 || s_pScreenInfo->fMWExtWM 883#endif 884 ) 885 ReleaseCapture (); 886 return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam); 887 888 case WM_RBUTTONDBLCLK: 889 case WM_RBUTTONDOWN: 890 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 891 break; 892 if (s_pScreenInfo->fRootless 893#ifdef XWIN_MULTIWINDOWEXTWM 894 || s_pScreenInfo->fMWExtWM 895#endif 896 ) 897 SetCapture (hwnd); 898 return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam); 899 900 case WM_RBUTTONUP: 901 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 902 break; 903 if (s_pScreenInfo->fRootless 904#ifdef XWIN_MULTIWINDOWEXTWM 905 || s_pScreenInfo->fMWExtWM 906#endif 907 ) 908 ReleaseCapture (); 909 return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam); 910 911 case WM_XBUTTONDBLCLK: 912 case WM_XBUTTONDOWN: 913 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 914 break; 915 if (s_pScreenInfo->fRootless 916#ifdef XWIN_MULTIWINDOWEXTWM 917 || s_pScreenInfo->fMWExtWM 918#endif 919 ) 920 SetCapture (hwnd); 921 return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam); 922 case WM_XBUTTONUP: 923 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 924 break; 925 if (s_pScreenInfo->fRootless 926#ifdef XWIN_MULTIWINDOWEXTWM 927 || s_pScreenInfo->fMWExtWM 928#endif 929 ) 930 ReleaseCapture (); 931 return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam); 932 933 case WM_TIMER: 934 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 935 break; 936 937 /* Branch on the timer id */ 938 switch (wParam) 939 { 940 case WIN_E3B_TIMER_ID: 941 /* Send delayed button press */ 942 winMouseButtonsSendEvent (ButtonPress, 943 s_pScreenPriv->iE3BCachedPress); 944 945 /* Kill this timer */ 946 KillTimer (s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID); 947 948 /* Clear screen privates flags */ 949 s_pScreenPriv->iE3BCachedPress = 0; 950 break; 951 952 case WIN_POLLING_MOUSE_TIMER_ID: 953 { 954 POINT point; 955 WPARAM wL, wM, wR, wShift, wCtrl; 956 LPARAM lPos; 957 958 /* Get the current position of the mouse cursor */ 959 GetCursorPos (&point); 960 961 /* Map from screen (-X, -Y) to root (0, 0) */ 962 point.x -= GetSystemMetrics (SM_XVIRTUALSCREEN); 963 point.y -= GetSystemMetrics (SM_YVIRTUALSCREEN); 964 965 /* Deliver absolute cursor position to X Server */ 966 winEnqueueMotion(point.x , point.y); 967 968 /* Check if a button was released but we didn't see it */ 969 GetCursorPos (&point); 970 wL = (GetKeyState (VK_LBUTTON) & 0x8000)?MK_LBUTTON:0; 971 wM = (GetKeyState (VK_MBUTTON) & 0x8000)?MK_MBUTTON:0; 972 wR = (GetKeyState (VK_RBUTTON) & 0x8000)?MK_RBUTTON:0; 973 wShift = (GetKeyState (VK_SHIFT) & 0x8000)?MK_SHIFT:0; 974 wCtrl = (GetKeyState (VK_CONTROL) & 0x8000)?MK_CONTROL:0; 975 lPos = MAKELPARAM(point.x, point.y); 976 if (g_fButton[0] & !wL) 977 PostMessage (hwnd, WM_LBUTTONUP, wCtrl|wM|wR|wShift, lPos); 978 if (g_fButton[1] & !wM) 979 PostMessage (hwnd, WM_MBUTTONUP, wCtrl|wL|wR|wShift, lPos); 980 if (g_fButton[2] & !wR) 981 PostMessage (hwnd, WM_RBUTTONUP, wCtrl|wL|wM|wShift, lPos); 982 } 983 } 984 return 0; 985 986 case WM_CTLCOLORSCROLLBAR: 987 FatalError ("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not " 988 "supposed to get this message. Exiting.\n"); 989 return 0; 990 991 case WM_MOUSEWHEEL: 992 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 993 break; 994#if CYGDEBUG 995 winDebug ("winWindowProc - WM_MOUSEWHEEL\n"); 996#endif 997 winMouseWheel (s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam)); 998 break; 999 1000 case WM_SETFOCUS: 1001 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 1002 break; 1003 1004 /* Restore the state of all mode keys */ 1005 winRestoreModeKeyStates (); 1006 1007 /* Add the keyboard hook if possible */ 1008 if (g_fKeyboardHookLL) 1009 g_fKeyboardHookLL = winInstallKeyboardHookLL (); 1010 return 0; 1011 1012 case WM_KILLFOCUS: 1013 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 1014 break; 1015 1016 /* Release any pressed keys */ 1017 winKeybdReleaseKeys (); 1018 1019 /* Remove our keyboard hook if it is installed */ 1020 winRemoveKeyboardHookLL (); 1021 return 0; 1022 1023 case WM_SYSKEYDOWN: 1024 case WM_KEYDOWN: 1025 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 1026 break; 1027 1028 /* 1029 * FIXME: Catching Alt-F4 like this is really terrible. This should 1030 * be generalized to handle other Windows keyboard signals. Actually, 1031 * the list keys to catch and the actions to perform when caught should 1032 * be configurable; that way user's can customize the keys that they 1033 * need to have passed through to their window manager or apps, or they 1034 * can remap certain actions to new key codes that do not conflict 1035 * with the X apps that they are using. Yeah, that'll take awhile. 1036 */ 1037 if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4 1038 && (GetKeyState (VK_MENU) & 0x8000)) 1039 || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK 1040 && (GetKeyState (VK_MENU) & 0x8000) 1041 && (GetKeyState (VK_CONTROL) & 0x8000))) 1042 { 1043 /* 1044 * Better leave this message here, just in case some unsuspecting 1045 * user enters Alt + F4 and is surprised when the application 1046 * quits. 1047 */ 1048 ErrorF ("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n"); 1049 1050 /* Display Exit dialog */ 1051 winDisplayExitDialog (s_pScreenPriv); 1052 return 0; 1053 } 1054 1055 /* 1056 * Don't do anything for the Windows keys, as focus will soon 1057 * be returned to Windows. We may be able to trap the Windows keys, 1058 * but we should determine if that is desirable before doing so. 1059 */ 1060 if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL) 1061 break; 1062 1063 /* 1064 * Discard presses generated from Windows auto-repeat 1065 */ 1066 if (lParam & (1<<30)) 1067 { 1068 switch (wParam) 1069 { 1070 /* ago: Pressing LControl while RControl is pressed is 1071 * Indicated as repeat. Fix this! 1072 */ 1073 case VK_CONTROL: 1074 case VK_SHIFT: 1075 if (winCheckKeyPressed(wParam, lParam)) 1076 return 0; 1077 break; 1078 default: 1079 return 0; 1080 } 1081 } 1082 1083 /* Discard fake Ctrl_L presses that precede AltGR on non-US keyboards */ 1084 if (winIsFakeCtrl_L (message, wParam, lParam)) 1085 return 0; 1086 1087 /* Translate Windows key code to X scan code */ 1088 winTranslateKey (wParam, lParam, &iScanCode); 1089 1090 /* Ignore repeats for CapsLock */ 1091 if (wParam == VK_CAPITAL) 1092 lParam = 1; 1093 1094 /* Send the key event(s) */ 1095 for (i = 0; i < LOWORD(lParam); ++i) 1096 winSendKeyEvent (iScanCode, TRUE); 1097 return 0; 1098 1099 case WM_SYSKEYUP: 1100 case WM_KEYUP: 1101 if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) 1102 break; 1103 1104 /* 1105 * Don't do anything for the Windows keys, as focus will soon 1106 * be returned to Windows. We may be able to trap the Windows keys, 1107 * but we should determine if that is desirable before doing so. 1108 */ 1109 if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL) 1110 break; 1111 1112 /* Ignore the fake Ctrl_L that follows an AltGr release */ 1113 if (winIsFakeCtrl_L (message, wParam, lParam)) 1114 return 0; 1115 1116 /* Enqueue a keyup event */ 1117 winTranslateKey (wParam, lParam, &iScanCode); 1118 winSendKeyEvent (iScanCode, FALSE); 1119 1120 /* Release all pressed shift keys */ 1121 if (wParam == VK_SHIFT) 1122 winFixShiftKeys (iScanCode); 1123 return 0; 1124 1125 case WM_HOTKEY: 1126 if (s_pScreenPriv == NULL) 1127 break; 1128 1129 /* Call the engine-specific hot key handler */ 1130 (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen); 1131 return 0; 1132 1133 case WM_ACTIVATE: 1134 if (s_pScreenPriv == NULL 1135 || s_pScreenInfo->fIgnoreInput) 1136 break; 1137 1138 /* TODO: Override display of window when we have a bad depth */ 1139 if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth) 1140 { 1141 ErrorF ("winWindowProc - WM_ACTIVATE - Bad depth, trying " 1142 "to override window activation\n"); 1143 1144 /* Minimize the window */ 1145 ShowWindow (hwnd, SW_MINIMIZE); 1146 1147 /* Display dialog box */ 1148 if (g_hDlgDepthChange != NULL) 1149 { 1150 /* Make the existing dialog box active */ 1151 SetActiveWindow (g_hDlgDepthChange); 1152 } 1153 else 1154 { 1155 /* TODO: Recreate the dialog box and bring to the top */ 1156 ShowWindow (g_hDlgDepthChange, SW_SHOWDEFAULT); 1157 } 1158 1159 /* Don't do any other processing of this message */ 1160 return 0; 1161 } 1162 1163#if CYGDEBUG 1164 winDebug ("winWindowProc - WM_ACTIVATE\n"); 1165#endif 1166 1167 /* 1168 * Focus is being changed to another window. 1169 * The other window may or may not belong to 1170 * our process. 1171 */ 1172 1173 /* Clear any lingering wheel delta */ 1174 s_pScreenPriv->iDeltaZ = 0; 1175 1176 /* Reshow the Windows mouse cursor if we are being deactivated */ 1177 if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE 1178 && !g_fCursor) 1179 { 1180 /* Show Windows cursor */ 1181 g_fCursor = TRUE; 1182 ShowCursor (TRUE); 1183 } 1184 return 0; 1185 1186 case WM_ACTIVATEAPP: 1187 if (s_pScreenPriv == NULL 1188 || s_pScreenInfo->fIgnoreInput) 1189 break; 1190 1191#if CYGDEBUG || TRUE 1192 winDebug ("winWindowProc - WM_ACTIVATEAPP\n"); 1193#endif 1194 1195 /* Activate or deactivate */ 1196 s_pScreenPriv->fActive = wParam; 1197 1198 /* Reshow the Windows mouse cursor if we are being deactivated */ 1199 if (g_fSoftwareCursor && !s_pScreenPriv->fActive 1200 && !g_fCursor) 1201 { 1202 /* Show Windows cursor */ 1203 g_fCursor = TRUE; 1204 ShowCursor (TRUE); 1205 } 1206 1207#ifdef XWIN_CLIPBOARD 1208 /* Make sure the clipboard chain is ok. */ 1209 winFixClipboardChain (); 1210#endif 1211 1212 /* Call engine specific screen activation/deactivation function */ 1213 (*s_pScreenPriv->pwinActivateApp) (s_pScreen); 1214 1215#ifdef XWIN_MULTIWINDOWEXTWM 1216 if (s_pScreenPriv->fActive) 1217 { 1218 /* Restack all window unless using built-in wm. */ 1219 if (s_pScreenInfo->fInternalWM && s_pScreenInfo->fAnotherWMRunning) 1220 winMWExtWMRestackWindows (s_pScreen); 1221 } 1222#endif 1223 1224 return 0; 1225 1226 case WM_COMMAND: 1227 switch (LOWORD (wParam)) 1228 { 1229 case ID_APP_EXIT: 1230 /* Display Exit dialog */ 1231 winDisplayExitDialog (s_pScreenPriv); 1232 return 0; 1233 1234#ifdef XWIN_MULTIWINDOW 1235 case ID_APP_HIDE_ROOT: 1236 if (s_pScreenPriv->fRootWindowShown) 1237 ShowWindow (s_pScreenPriv->hwndScreen, SW_HIDE); 1238 else 1239 ShowWindow (s_pScreenPriv->hwndScreen, SW_SHOW); 1240 s_pScreenPriv->fRootWindowShown = !s_pScreenPriv->fRootWindowShown; 1241 return 0; 1242#endif 1243 1244 case ID_APP_ABOUT: 1245 /* Display the About box */ 1246 winDisplayAboutDialog (s_pScreenPriv); 1247 return 0; 1248 1249 default: 1250 /* It's probably one of the custom menus... */ 1251 if (HandleCustomWM_COMMAND (0, LOWORD (wParam))) 1252 return 0; 1253 } 1254 break; 1255 1256 case WM_ENDSESSION: 1257 case WM_GIVEUP: 1258 /* Tell X that we are giving up */ 1259#ifdef XWIN_MULTIWINDOW 1260 if (s_pScreenInfo->fMultiWindow) 1261 winDeinitMultiWindowWM (); 1262#endif 1263 GiveUp (0); 1264 return 0; 1265 1266 case WM_CLOSE: 1267 /* Display Exit dialog */ 1268 winDisplayExitDialog (s_pScreenPriv); 1269 return 0; 1270 1271 case WM_SETCURSOR: 1272 if (LOWORD(lParam) == HTCLIENT) 1273 { 1274 if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle); 1275 return TRUE; 1276 } 1277 break; 1278 1279#ifdef XWIN_MULTIWINDOWEXTWM 1280 case WM_MANAGE: 1281 ErrorF ("winWindowProc - WM_MANAGE\n"); 1282 s_pScreenInfo->fAnotherWMRunning = FALSE; 1283 1284 if (s_pScreenInfo->fInternalWM) 1285 { 1286 EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0); 1287 //RootlessRepositionWindows (s_pScreen); 1288 } 1289 break; 1290 1291 case WM_UNMANAGE: 1292 ErrorF ("winWindowProc - WM_UNMANAGE\n"); 1293 s_pScreenInfo->fAnotherWMRunning = TRUE; 1294 1295 if (s_pScreenInfo->fInternalWM) 1296 { 1297 EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0); 1298 winMWExtWMRestackWindows (s_pScreen); 1299 } 1300 break; 1301#endif 1302 1303 default: 1304 if(message == s_uTaskbarRestart) 1305 { 1306 winInitNotifyIcon (s_pScreenPriv); 1307 } 1308 break; 1309 } 1310 1311 return DefWindowProc (hwnd, message, wParam, lParam); 1312} 1313