Changeset 108
- Timestamp:
- Aug 12, 2009, 10:18:10 PM (16 years ago)
- Location:
- trunk/src/gui/kernel
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/src/gui/kernel/qapplication_pm.cpp ¶
r100 r108 51 51 #include "qcolormap.h" 52 52 #include "qpixmapcache.h" 53 #include "qdesktopwidget.h" 53 54 54 55 #include "qset.h" … … 68 69 static HWND curWin = 0; // current window 69 70 static HPS displayPS = 0; // display presentation space 71 72 #if !defined (QT_NO_SESSIONMANAGER) 73 74 // Session management 75 static bool sm_blockUserInput = FALSE; 76 77 //#define DEBUG_SESSIONMANAGER 78 79 #endif 70 80 71 81 static bool replayPopupMouseEvent = false; // replay handling when popups close … … 82 92 extern QDesktopWidget *qt_desktopWidget; 83 93 static QPointer<QWidget> popupButtonFocus; 84 static bool qt_try_modal(QWidget *, QMSG *, int& ret);94 static bool qt_try_modal(QWidget*, QMSG*, MRESULT&); 85 95 86 96 QWidget *qt_button_down = 0; // widget got last button-down … … 88 98 89 99 static HWND autoCaptureWnd = NULLHANDLE; 100 static bool autoCaptureReleased = FALSE; 90 101 static void setAutoCapture(HWND); // automatic capture 91 102 static void releaseAutoCapture(); … … 107 118 // QWidgetPrivate *dptr() { return d_func(); } 108 119 // QRect frameStrut() const { return d_func()->frameStrut(); } 109 // bool winEvent(QMSG *m, long *r) { return QWidget::winEvent(m, r); }120 bool pmEvent(QMSG *m, MRESULT *r) { return QWidget::pmEvent(m, r); } 110 121 // void markFrameStrutDirty() { data->fstrut_dirty = 1; } 111 // bool translateMouseEvent(const MSG &msg); 112 // bool translateWheelEvent(const MSG &msg); 113 // bool translatePaintEvent(const MSG &msg); 122 bool translateMouseEvent(const QMSG &qmsg); 123 #ifndef QT_NO_WHEELEVENT 124 bool translateWheelEvent(const QMSG &qmsg); 125 #endif 126 bool translatePaintEvent(const QMSG &qmsg); 114 127 // bool translateConfigEvent(const MSG &msg); 115 128 // bool translateCloseEvent(const MSG &msg); … … 254 267 class QGuiEventDispatcherPM : public QEventDispatcherPM 255 268 { 256 Q_DECLARE_PRIVATE(QEventDispatcherPM)257 269 public: 258 270 QGuiEventDispatcherPM(QObject *parent = 0); … … 424 436 MRESULT EXPENTRY QtWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 425 437 { 426 // message handling indicators: if handled is true at the end of message427 // processing, no default window proc is called but rc is returned.428 bool handled = false;429 MRESULT rc = (MRESULT) FALSE;430 QETWidget *widget = 0;431 HWND hwndC = NULLHANDLE;432 433 438 do { 439 if (!qApp) // unstable app state 440 break; 441 #if 0 442 // make sure we show widgets (e.g. scrollbars) when the user resizes 443 if (qApp->loopLevel()) 444 qApp->sendPostedEvents(0, QEvent::ShowWindowRequest); 445 #endif 446 447 MRESULT rc = (MRESULT) FALSE; 448 QETWidget *widget = 0; 449 450 bool isTranslatableMouseEvent = 451 (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) || 452 (msg >= WM_EXTMOUSEFIRST && msg <= WM_EXTMOUSELAST); 453 454 QMSG qmsg; // create QMSG structure 455 qmsg.hwnd = hwnd; 456 qmsg.msg = msg; 457 qmsg.mp1 = mp1; 458 qmsg.mp2 = mp2; 459 qmsg.time = WinQueryMsgTime(0); 460 461 if (isTranslatableMouseEvent || msg == WM_CONTEXTMENU) { 462 qmsg.ptl.x = (short)SHORT1FROMMP(mp1); 463 qmsg.ptl.y = (short)SHORT2FROMMP(mp1); 464 WinMapWindowPoints(qmsg.hwnd, HWND_DESKTOP, &qmsg.ptl, 1); 465 } else { 466 WinQueryMsgPos(0, &qmsg.ptl); 467 } 468 // flip y coordinate 469 qmsg.ptl.y = QApplication::desktop()->height() - (qmsg.ptl.y + 1); 470 471 // send through app filter 472 if (qApp->filterEvent(&qmsg, reinterpret_cast<long *>(&rc))) 473 return rc; 474 475 switch(msg) { 476 477 case WM_BUTTON1DOWN: 478 case WM_BUTTON2DOWN: 479 case WM_BUTTON3DOWN: 480 if (ignoreNextMouseReleaseEvent) 481 ignoreNextMouseReleaseEvent = false; 482 break; 483 case WM_BUTTON1UP: 484 case WM_BUTTON2UP: 485 case WM_BUTTON3UP: 486 if (ignoreNextMouseReleaseEvent) { 487 ignoreNextMouseReleaseEvent = false; 488 if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) { 489 releaseAutoCapture(); 490 qt_button_down = 0; 491 } 492 return (MRESULT)TRUE; 493 } 494 break; 495 496 default: 497 break; 498 } 499 500 if (!widget) 501 widget = (QETWidget*)QWidget::find(hwnd); 502 if (!widget) // don't know this widget 503 break; 504 505 if (app_do_modal) { // modal event handling 506 if (!qt_try_modal(widget, &qmsg, rc)) 507 return rc; 508 } 509 510 if (widget->pmEvent(&qmsg, &rc)) // send through widget filter 511 return rc; 512 513 if (isTranslatableMouseEvent) { 514 if (qApp->activePopupWidget() != 0) { // in popup mode 515 QWidget *w = QApplication::widgetAt(qmsg.ptl.x, qmsg.ptl.y); 516 if (w) { 517 POINTL ptl = { SHORT1FROMMP(qmsg.mp1), SHORT2FROMMP(qmsg.mp1) }; 518 WinMapWindowPoints(qmsg.hwnd, w->winId(), &ptl, 1); 519 qmsg.mp1 = MPFROM2SHORT(ptl.x, ptl.y); 520 widget = (QETWidget*)w; 521 } 522 } 523 if (widget->translateMouseEvent(qmsg)) // mouse event 524 return (MRESULT)TRUE; 525 #ifndef QT_NO_WHEELEVENT 526 } else if (msg == WM_VSCROLL || msg == WM_HSCROLL) { 527 if (widget->translateWheelEvent(qmsg)) 528 return (MRESULT)TRUE; 529 #endif 530 #ifndef QT_NO_DRAGANDDROP 531 } else if (msg >= WM_DRAGFIRST && msg <= WM_DRAGLAST) { 532 return qt_dispatchDragAndDrop(widget, qmsg); 533 #endif 534 } else { 535 switch(msg) { 536 537 case WM_SHOW: { 538 // @todo there is some more processing in Qt4, see 539 // WM_SHOWWINDOW in Win32 sources 540 if (!SHORT1FROMMP(mp1) && autoCaptureWnd == widget->internalWinId()) 541 releaseAutoCapture(); 542 break; 543 } 544 545 #ifndef QT_NO_CONTEXTMENU 546 case WM_CONTEXTMENU: { 547 if (SHORT2FROMMP(mp2)) { 548 // keyboard event 549 QWidget *fw = qApp->focusWidget(); 550 if (fw && fw->isEnabled()) { 551 QContextMenuEvent e(QContextMenuEvent::Keyboard, 552 QPoint(5, 5), 553 fw->mapToGlobal(QPoint(5, 5)), 0); 554 if (qt_sendSpontaneousEvent(fw, &e)) 555 return (MRESULT)TRUE; 556 } 557 } else { 558 // mouse event 559 if (widget->translateMouseEvent(qmsg)) 560 return (MRESULT)TRUE; 561 } 562 break; 563 } 564 #endif 565 566 default: 567 break; 568 } 569 } 570 571 } while(0); 572 573 return WinDefWindowProc(hwnd, msg, mp1, mp2); 574 } 575 576 PFNWP QtOldFrameProc = 0; 577 578 MRESULT EXPENTRY QtFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 579 { 580 do { 581 if (!qApp) // unstable app state 582 break; 583 #if 0 584 // make sure we show widgets (e.g. scrollbars) when the user resizes 585 if (qApp->loopLevel()) 586 qApp->sendPostedEvents(0, QEvent::ShowWindowRequest); 587 #endif 588 589 HWND hwndC = WinWindowFromID(hwnd, FID_CLIENT); 590 QETWidget *widget = (QETWidget*)QWidget::find(hwndC); 591 if (!widget) // don't know this widget 592 break; 593 434 594 switch(msg) { 435 595 default: 436 596 break; 437 597 } 438 if (handled)439 return rc;440 } while(0);441 442 return WinDefWindowProc(hwnd, msg, mp1, mp2);443 }444 445 PFNWP QtOldFrameProc = 0;446 447 MRESULT EXPENTRY QtFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)448 {449 // message handling indicators: if handled is true at the end of message450 // processing, no default window proc is called but rc is returned.451 bool handled = false;452 MRESULT rc = (MRESULT) FALSE;453 QETWidget *widget = 0;454 HWND hwndC = NULLHANDLE;455 456 do {457 switch(msg) {458 default:459 break;460 }461 if (handled)462 return rc;463 598 } while(0); 464 599 … … 499 634 } 500 635 636 bool qt_try_modal(QWidget *widget, QMSG *qmsg, MRESULT& rc) 637 { 638 // @todo implement 639 return false; 640 } 641 501 642 /***************************************************************************** 502 643 Popup widget mechanism … … 527 668 *****************************************************************************/ 528 669 670 // State holder for LWIN/RWIN and ALTGr keys 671 // (ALTGr is also necessary since OS/2 doesn't report ALTGr as KC_ALT) 672 static int qt_extraKeyState = 0; 673 674 static int mouseButtonState() 675 { 676 int state = 0; 677 678 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) 679 state |= Qt::LeftButton; 680 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) 681 state |= Qt::RightButton; 682 if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) 683 state |= Qt::MidButton; 684 685 return state; 686 } 687 688 // 689 // Auto-capturing for mouse press and mouse release 690 // 691 692 static void setAutoCapture(HWND h) 693 { 694 if (autoCaptureWnd) 695 releaseAutoCapture(); 696 autoCaptureWnd = h; 697 698 if (!mouseButtonState()) { 699 // all buttons released, we don't actually capture the mouse 700 // (see QWidget::translateMouseEvent()) 701 autoCaptureReleased = true; 702 } else { 703 autoCaptureReleased = false; 704 WinSetCapture(HWND_DESKTOP, h); 705 } 706 } 707 708 static void releaseAutoCapture() 709 { 710 if (autoCaptureWnd) { 711 if (!autoCaptureReleased) { 712 WinSetCapture(HWND_DESKTOP, NULLHANDLE); 713 autoCaptureReleased = true; 714 } 715 autoCaptureWnd = NULLHANDLE; 716 } 717 } 718 719 // 720 // Mouse event translation 721 // 722 723 static ushort mouseTbl[] = { 724 WM_MOUSEMOVE, QEvent::MouseMove, 0, 725 WM_BUTTON1DOWN, QEvent::MouseButtonPress, Qt::LeftButton, 726 WM_BUTTON1UP, QEvent::MouseButtonRelease, Qt::LeftButton, 727 WM_BUTTON1DBLCLK, QEvent::MouseButtonDblClick, Qt::LeftButton, 728 WM_BUTTON2DOWN, QEvent::MouseButtonPress, Qt::RightButton, 729 WM_BUTTON2UP, QEvent::MouseButtonRelease, Qt::RightButton, 730 WM_BUTTON2DBLCLK, QEvent::MouseButtonDblClick, Qt::RightButton, 731 WM_BUTTON3DOWN, QEvent::MouseButtonPress, Qt::MidButton, 732 WM_BUTTON3UP, QEvent::MouseButtonRelease, Qt::MidButton, 733 WM_BUTTON3DBLCLK, QEvent::MouseButtonDblClick, Qt::MidButton, 734 WM_CONTEXTMENU, QEvent::ContextMenu, 0, 735 0, 0, 0 736 }; 737 738 static int translateButtonState(USHORT s, int type, int button) 739 { 740 Q_UNUSED(button); 741 742 int bst = mouseButtonState(); 743 744 if (type == QEvent::ContextMenu) { 745 if (WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000) 746 bst |= Qt::ShiftModifier; 747 if (WinGetKeyState(HWND_DESKTOP, VK_ALT) & 0x8000) 748 bst |= Qt::AltModifier; 749 if (WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000) 750 bst |= Qt::ControlModifier; 751 } else { 752 if (s & KC_SHIFT) 753 bst |= Qt::ShiftModifier; 754 if ((s & KC_ALT)) 755 bst |= Qt::AltModifier; 756 if (s & KC_CTRL) 757 bst |= Qt::ControlModifier; 758 } 759 if ((qt_extraKeyState & Qt::AltModifier)) 760 bst |= Qt::AltModifier; 761 if (qt_extraKeyState & Qt::MetaModifier) 762 bst |= Qt::MetaModifier; 763 764 return bst; 765 } 766 767 bool QETWidget::translateMouseEvent(const QMSG &qmsg) 768 { 769 #if 0 770 static const char *msgNames[] = { // 11 items 771 "WM_MOUSEMOVE", 772 "WM_BUTTON1DOWN", "WM_BUTTON1UP", "WM_BUTTON1DBLCLK", 773 "WM_BUTTON2DOWN", "WM_BUTTON2UP", "WM_BUTTON2DBLCLK", 774 "WM_BUTTON3DOWN", "WM_BUTTON3UP", "WM_BUTTON3DBLCLK", 775 "WM_???" 776 }; 777 int msgIdx = qmsg.msg - WM_MOUSEMOVE; 778 if (msgIdx < 0 || msgIdx > 9) 779 msgIdx = 10; 780 qDebug("%s (%04lX): [%08lX/%p:%s] %04hd,%04hd hit=%04hX fl=%04hX", 781 msgNames[msgIdx], qmsg.msg, qmsg.hwnd, this, widgetName(this), 782 SHORT1FROMMP(qmsg.mp1), SHORT2FROMMP(qmsg.mp1), 783 SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2)); 784 #endif 785 786 if (!isWindow() && testAttribute(Qt::WA_NativeWindow)) 787 Q_ASSERT(internalWinId() != NULLHANDLE); 788 789 static QPoint pos; // window pos (y flipped) 790 static POINTL gpos = { -1, -1 }; // global pos (y flipped) 791 QEvent::Type type; // event parameters 792 int button; 793 int state; 794 int i; 795 796 // candidate for the double click event 797 static HWND dblClickCandidateWin = 0; 798 799 #if !defined (QT_NO_SESSIONMANAGER) 800 if (sm_blockUserInput) //block user interaction during session management 801 return true; 802 #endif 803 804 // Compress mouse move events 805 if (qmsg.msg == WM_MOUSEMOVE) { 806 QMSG mouseMsg; 807 mouseMsg.msg = WM_NULL; 808 while (WinPeekMsg(0, &mouseMsg, qmsg.hwnd, WM_MOUSEMOVE, 809 WM_MOUSEMOVE, PM_NOREMOVE)) { 810 if (mouseMsg.mp2 != qmsg.mp2) 811 break; // leave the message in the queue because 812 // the key state has changed 813 // Remove the mouse move message 814 WinPeekMsg(0, &mouseMsg, qmsg.hwnd, WM_MOUSEMOVE, 815 WM_MOUSEMOVE, PM_REMOVE); 816 } 817 // Update the passed in QMSG structure with the 818 // most recent one. 819 if (mouseMsg.msg != WM_NULL) { 820 PQMSG pqmsg = (PQMSG)&qmsg; 821 pqmsg->mp1 = mouseMsg.mp1; 822 pqmsg->mp2 = mouseMsg.mp2; 823 pqmsg->time = mouseMsg.time; 824 pqmsg->ptl.x = (short)SHORT1FROMMP(mouseMsg.mp1); 825 pqmsg->ptl.y = (short)SHORT2FROMMP(mouseMsg.mp1); 826 WinMapWindowPoints(pqmsg->hwnd, HWND_DESKTOP, &pqmsg->ptl, 1); 827 // flip y coordinate 828 pqmsg->ptl.y = QApplication::desktop()->height() - (pqmsg->ptl.y + 1); 829 } 830 } 831 832 for (i = 0; mouseTbl[i] && (ULONG)mouseTbl[i] != qmsg.msg; i += 3) 833 ; 834 if (!mouseTbl[i]) 835 return true; 836 837 type = (QEvent::Type)mouseTbl[++i]; // event type 838 button = mouseTbl[++i]; // which button 839 state = translateButtonState(SHORT2FROMMP(qmsg.mp2), type, button); // button state 840 841 // It seems, that PM remembers only the WM_BUTTONxDOWN message (instead of 842 // the WM_BUTTONxDOWN + WM_BUTTONxUP pair) to detect whether the next button 843 // press should be converted to WM_BUTTONxDBLCLK or not. As a result, the 844 // window gets WM_BUTTONxDBLCLK even if it didn't receive the preceeding 845 // WM_BUTTONxUP (this happens if we issue WinSetCapture() on the first 846 // WM_BUTTONxDOWN), which is obviously wrong and makes problems for QWorkspace 847 // and QTitleBar system menu handlers that don't expect a double click after 848 // they opened a popup menu. dblClickCandidateWin is reset to 0 (see a *** 849 // remmark below) when WinSetCapture is issued that directs messages 850 // to a window other than one received the first WM_BUTTONxDOWN, 851 // so we can fix it here. Note that if there is more than one popup window, 852 // WinSetCapture is issued only for the first of them, so this code doesn't 853 // prevent MouseButtonDblClick from being delivered to a popup when another 854 // popup gets closed on the first WM_BUTTONxDOWN (Qt/Win32 behaves in the 855 // same way, so it's left for compatibility). 856 if (type == QEvent::MouseButtonPress) { 857 dblClickCandidateWin = qmsg.hwnd; 858 } else if (type == QEvent::MouseButtonDblClick) { 859 if (dblClickCandidateWin != qmsg.hwnd) 860 type = QEvent::MouseButtonPress; 861 dblClickCandidateWin = 0; 862 } 863 864 const QPoint widgetPos = mapFromGlobal(QPoint(qmsg.ptl.x, qmsg.ptl.y)); 865 866 QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); 867 if (alienWidget && alienWidget->internalWinId()) 868 alienWidget = 0; 869 870 if (type == QEvent::MouseMove) { 871 if (!(state & Qt::MouseButtonMask)) 872 qt_button_down = 0; 873 #ifndef QT_NO_CURSOR 874 QCursor *c = qt_grab_cursor(); 875 if (!c) 876 c = QApplication::overrideCursor(); 877 if (c) // application cursor defined 878 WinSetPointer(HWND_DESKTOP, c->handle()); 879 else if (!qt_button_down) { 880 QWidget *w = alienWidget ? alienWidget : this; 881 while (!w->isWindow() && !w->isEnabled()) 882 w = w->parentWidget(); 883 WinSetPointer(HWND_DESKTOP, w->cursor().handle()); 884 } 885 #else 886 // pass the msg to the default proc to let it change the pointer shape 887 WinDefWindowProc(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); 888 #endif 889 890 HWND id = effectiveWinId(); 891 QWidget *mouseGrabber = QWidget::mouseGrabber(); 892 QWidget *activePopupWidget = qApp->activePopupWidget(); 893 if (mouseGrabber) { 894 if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos))) 895 id = mouseGrabber->effectiveWinId(); 896 } else if (type == QEvent::NonClientAreaMouseMove) { 897 id = 0; 898 } 899 900 if (curWin != id) { // new current window 901 // @todo 902 // add CS_HITTEST to our window classes and handle WM_HITTEST, 903 // otherwise disabled windows will not get mouse events? 904 if (id == 0) { 905 QWidget *leave = qt_last_mouse_receiver; 906 if (!leave) 907 leave = QWidget::find(curWin); 908 QApplicationPrivate::dispatchEnterLeave(0, leave); 909 qt_last_mouse_receiver = 0; 910 curWin = 0; 911 } else { 912 QWidget *leave = 0; 913 if (curWin && qt_last_mouse_receiver) 914 leave = qt_last_mouse_receiver; 915 else 916 leave = QWidget::find(curWin); 917 QWidget *enter = alienWidget ? alienWidget : this; 918 if (mouseGrabber && activePopupWidget) { 919 if (leave != mouseGrabber) 920 enter = mouseGrabber; 921 else 922 enter = activePopupWidget == this ? this : mouseGrabber; 923 } 924 QApplicationPrivate::dispatchEnterLeave(enter, leave); 925 qt_last_mouse_receiver = enter; 926 curWin = enter ? enter->effectiveWinId() : 0; 927 } 928 } 929 930 // *** PM posts a dummy WM_MOUSEMOVE message (with the same, uncahnged 931 // pointer coordinates) after every WinSetCapture that actually changes 932 // the capture target. I.e., if the argument of WinSetCapture is 933 // NULLHANDLE, a window under the mouse pointer gets this message, 934 // otherwise the specified window gets it unless it is already under the 935 // pointer. We use this info to check whether the window can be a double 936 // click candidate (see above). 937 if (qmsg.ptl.x == gpos.x && qmsg.ptl.y == gpos.y) { 938 if (dblClickCandidateWin != qmsg.hwnd) 939 dblClickCandidateWin = 0; 940 return true; 941 } 942 943 gpos = qmsg.ptl; 944 945 Q_ASSERT(testAttribute(Qt::WA_WState_Created)); 946 947 POINTL curPos = gpos; 948 WinMapWindowPoints(internalWinId(), HWND_DESKTOP, &gpos, 1); 949 950 pos.rx() = curPos.x; 951 pos.ry() = curPos.y; 952 pos = d_func()->mapFromWS(pos); 953 } else { 954 if (type == QEvent::MouseButtonPress && !isActiveWindow()) 955 setActiveWindow(); 956 957 gpos = qmsg.ptl; 958 pos = mapFromGlobal(QPoint(gpos.x, gpos.y)); 959 960 // mouse button pressed 961 if (!qt_button_down && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick)) { 962 QWidget *tlw = window(); 963 if (QWidget *child = tlw->childAt(mapTo(tlw, pos))) 964 qt_button_down = child; 965 else 966 qt_button_down = this; 967 } 968 } 969 970 // detect special button states 971 enum { Other, SinglePressed, AllReleased } btnState = Other; 972 int bs = state & Qt::MouseButtonMask; 973 if ((type == QEvent::MouseButtonPress || 974 type == QEvent::MouseButtonDblClick) && bs == 0) { 975 btnState = SinglePressed; 976 } else if (type == QEvent::MouseButtonRelease && bs == button) { 977 btnState = AllReleased; 978 } 979 980 bool res = false; 981 982 if (qApp->d_func()->inPopupMode()) { // in popup mode 983 if (!autoCaptureReleased && btnState == AllReleased) { 984 // in order to give non-Qt windows the opportunity to see mouse 985 // messages while our popups are active we need to release the 986 // mouse capture which is absolute in OS/2. we do it directly 987 // (not through releaseAutoCapture()) in order to keep 988 // autoCaptureWnd nonzero to keep forwarding mouse move events 989 // (actually sent to one of Qt widgets) to the active popup. 990 autoCaptureReleased = true; 991 WinSetCapture(HWND_DESKTOP, 0); 992 } else if (autoCaptureReleased && btnState == SinglePressed) { 993 // set the mouse capture back if a button is pressed. 994 if ( autoCaptureWnd ) { 995 autoCaptureReleased = false; 996 WinSetCapture(HWND_DESKTOP, autoCaptureWnd); 997 } 998 } 999 1000 replayPopupMouseEvent = false; 1001 QWidget* activePopupWidget = qApp->activePopupWidget(); 1002 QWidget *target = activePopupWidget; 1003 const QPoint globalPos(gpos.x, gpos.y); 1004 1005 if (target != this) { 1006 if ((windowType() == Qt::Popup) && rect().contains(pos) && 0) 1007 target = this; 1008 else // send to last popup 1009 pos = target->mapFromGlobal(globalPos); 1010 } 1011 QWidget *popupChild = target->childAt(pos); 1012 bool releaseAfter = false; 1013 switch (type) { 1014 case QEvent::MouseButtonPress: 1015 case QEvent::MouseButtonDblClick: 1016 popupButtonFocus = popupChild; 1017 break; 1018 case QEvent::MouseButtonRelease: 1019 releaseAfter = true; 1020 break; 1021 default: 1022 break; // nothing for mouse move 1023 } 1024 1025 if (target->isEnabled()) { 1026 if (popupButtonFocus) { 1027 target = popupButtonFocus; 1028 } else if (popupChild) { 1029 // forward mouse events to the popup child. mouse move events 1030 // are only forwarded to popup children that enable mouse tracking. 1031 if (type != QEvent::MouseMove || popupChild->hasMouseTracking()) 1032 target = popupChild; 1033 } 1034 1035 pos = target->mapFromGlobal(globalPos); 1036 #ifndef QT_NO_CONTEXTMENU 1037 if (type == QEvent::ContextMenu) { 1038 QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, state); 1039 res = QApplication::sendSpontaneousEvent(target, &e); 1040 res = res && e.isAccepted(); 1041 } 1042 else 1043 #endif 1044 { 1045 QMouseEvent e(type, pos, globalPos, 1046 Qt::MouseButton(button), 1047 Qt::MouseButtons(state & Qt::MouseButtonMask), 1048 Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask)); 1049 res = QApplicationPrivate::sendMouseEvent(target, &e, alienWidget, this, &qt_button_down, 1050 qt_last_mouse_receiver); 1051 res = res && e.isAccepted(); 1052 } 1053 } else { 1054 // close disabled popups when a mouse button is pressed or released 1055 switch (type) { 1056 case QEvent::MouseButtonPress: 1057 case QEvent::MouseButtonDblClick: 1058 case QEvent::MouseButtonRelease: 1059 target->close(); 1060 break; 1061 default: 1062 break; 1063 } 1064 } 1065 1066 if (releaseAfter) { 1067 popupButtonFocus = 0; 1068 qt_button_down = 0; 1069 } 1070 1071 if (type == QEvent::MouseButtonPress 1072 && qApp->activePopupWidget() != activePopupWidget 1073 && replayPopupMouseEvent) { 1074 // the popup dissappeared. Replay the event 1075 QWidget* w = QApplication::widgetAt(gpos.x, gpos.y); 1076 if (w && !QApplicationPrivate::isBlockedByModal(w)) { 1077 Q_ASSERT(w->testAttribute(Qt::WA_WState_Created)); 1078 HWND hwndTarget = w->effectiveWinId(); 1079 if (QWidget::mouseGrabber() == 0) 1080 setAutoCapture(hwndTarget); 1081 if (!w->isActiveWindow()) 1082 w->activateWindow(); 1083 POINTL pt = gpos; 1084 WinMapWindowPoints(HWND_DESKTOP, hwndTarget, &pt, 1); 1085 // flip y coordinate 1086 pt.y = w->height() - (pt.y + 1); 1087 WinPostMsg(hwndTarget, qmsg.msg, 1088 MPFROM2SHORT(pt.x, pt.y), qmsg.mp2); 1089 } 1090 } 1091 } else { // not popup mode 1092 if (btnState == SinglePressed && QWidget::mouseGrabber() == 0) { 1093 Q_ASSERT(testAttribute(Qt::WA_WState_Created)); 1094 setAutoCapture(internalWinId()); 1095 } else if (btnState == AllReleased && QWidget::mouseGrabber() == 0) { 1096 releaseAutoCapture(); 1097 } 1098 1099 const QPoint globalPos(gpos.x,gpos.y); 1100 QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type, 1101 Qt::MouseButtons(bs), 1102 qt_button_down, alienWidget); 1103 if (!widget) 1104 return false; // don't send event 1105 1106 #ifndef QT_NO_CONTEXTMENU 1107 if (type == QEvent::ContextMenu) { 1108 QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, state); 1109 res = QApplication::sendSpontaneousEvent(widget, &e); 1110 res = res && e.isAccepted(); 1111 } else 1112 #endif 1113 { 1114 QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), 1115 Qt::MouseButtons(state & Qt::MouseButtonMask), 1116 Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask)); 1117 1118 res = QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down, 1119 qt_last_mouse_receiver); 1120 res = res && e.isAccepted(); 1121 } 1122 1123 if (type != QEvent::MouseMove) 1124 pos.rx() = pos.ry() = -9999; // init for move compression 1125 } 1126 1127 return res; 1128 } 1129 1130 #ifndef QT_NO_WHEELEVENT 1131 bool QETWidget::translateWheelEvent(const QMSG &qmsg) 1132 { 1133 enum { WHEEL_DELTA = 120 }; 1134 1135 #ifndef QT_NO_SESSIONMANAGER 1136 if (sm_blockUserInput) // block user interaction during session management 1137 return true; 1138 #endif 1139 1140 // consume duplicate wheel events sent by the AMouse driver to emulate 1141 // multiline scrolls. we need this since currently Qt (QScrollBar, for 1142 // instance) maintains the number of lines to scroll per wheel rotation 1143 // (including the special handling of CTRL and SHIFT modifiers) on its own 1144 // and doesn't have a setting to tell it to be aware of system settings 1145 // for the mouse wheel. if we had processed events as they are, we would 1146 // get a confusing behavior (too many lines scrolled etc.). 1147 { 1148 int devh = QApplication::desktop()->height(); 1149 QMSG wheelMsg; 1150 while (WinPeekMsg(0, &wheelMsg, qmsg.hwnd, qmsg.msg, qmsg.msg, PM_NOREMOVE)) { 1151 // PM bug: ptl contains SHORT coordinates although fields are LONG 1152 wheelMsg.ptl.x = (short) wheelMsg.ptl.x; 1153 wheelMsg.ptl.y = (short) wheelMsg.ptl.y; 1154 // flip y coordinate 1155 wheelMsg.ptl.y = devh - (wheelMsg.ptl.y + 1); 1156 if (wheelMsg.mp1 != qmsg.mp1 || 1157 wheelMsg.mp2 != qmsg.mp2 || 1158 wheelMsg.ptl.x != qmsg.ptl.x || 1159 wheelMsg.ptl.y != qmsg.ptl.y) 1160 break; 1161 WinPeekMsg(0, &wheelMsg, qmsg.hwnd, qmsg.msg, qmsg.msg, PM_REMOVE); 1162 } 1163 } 1164 1165 int delta; 1166 USHORT cmd = SHORT2FROMMP(qmsg.mp2); 1167 switch (cmd) { 1168 case SB_LINEUP: 1169 case SB_PAGEUP: 1170 delta = WHEEL_DELTA; 1171 break; 1172 case SB_LINEDOWN: 1173 case SB_PAGEDOWN: 1174 delta = -WHEEL_DELTA; 1175 break; 1176 default: 1177 return false; 1178 } 1179 1180 int state = 0; 1181 if (WinGetKeyState(HWND_DESKTOP, VK_SHIFT ) & 0x8000) 1182 state |= Qt::ShiftModifier; 1183 if (WinGetKeyState(HWND_DESKTOP, VK_ALT) & 0x8000 || 1184 (qt_extraKeyState & Qt::AltModifier)) 1185 state |= Qt::AltModifier; 1186 if (WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000) 1187 state |= Qt::ControlModifier; 1188 if (qt_extraKeyState & Qt::MetaModifier) 1189 state |= Qt::MetaModifier; 1190 1191 Qt::Orientation orient; 1192 // Alt inverts scroll orientation (Qt/Win32 behavior) 1193 if (state & Qt::AltModifier) 1194 orient = qmsg.msg == WM_VSCROLL ? Qt::Horizontal : Qt::Vertical; 1195 else 1196 orient = qmsg.msg == WM_VSCROLL ? Qt::Vertical : Qt::Horizontal; 1197 1198 QPoint globalPos(qmsg.ptl.x, qmsg.ptl.y); 1199 1200 // if there is a widget under the mouse and it is not shadowed 1201 // by modality, we send the event to it first 1202 MRESULT rc = FALSE; 1203 QWidget* w = QApplication::widgetAt(globalPos); 1204 if (!w || !qt_try_modal(w, (QMSG*)&qmsg, rc)) { 1205 //synaptics touchpad shows its own widget at this position 1206 //so widgetAt() will fail with that HWND, try child of this widget 1207 w = this->childAt(this->mapFromGlobal(globalPos)); 1208 if (!w) 1209 w = this; 1210 } 1211 1212 // send the event to the widget or its ancestors 1213 { 1214 QWidget* popup = qApp->activePopupWidget(); 1215 if (popup && w->window() != popup) 1216 popup->close(); 1217 #ifndef QT_NO_WHEELEVENT 1218 QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta, 1219 Qt::MouseButtons(state & Qt::MouseButtonMask), 1220 Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient); 1221 1222 if (QApplication::sendSpontaneousEvent(w, &e)) 1223 #else 1224 Q_UNUSED(orient); 1225 #endif //QT_NO_WHEELEVENT 1226 return true; 1227 } 1228 1229 // send the event to the widget that has the focus or its ancestors, if different 1230 if (w != qApp->focusWidget() && (w = qApp->focusWidget())) { 1231 QWidget* popup = qApp->activePopupWidget(); 1232 if (popup && w->window() != popup) 1233 popup->close(); 1234 #ifndef QT_NO_WHEELEVENT 1235 QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta, 1236 Qt::MouseButtons(state & Qt::MouseButtonMask), 1237 Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient); 1238 if (QApplication::sendSpontaneousEvent(w, &e)) 1239 #endif //QT_NO_WHEELEVENT 1240 return true; 1241 } 1242 1243 return false; 1244 } 1245 #endif 1246 529 1247 QT_END_NAMESPACE -
TabularUnified trunk/src/gui/kernel/qcursor.h ¶
r2 r108 115 115 HCURSOR handle() const; 116 116 QCursor(HCURSOR cursor); 117 #elif defined(Q_WS_PM) 118 HPOINTER handle() const; 119 QCursor(HPOINTER handle); 117 120 #elif defined(Q_WS_X11) 118 121 Qt::HANDLE handle() const; -
TabularUnified trunk/src/gui/kernel/qcursor_p.h ¶
r2 r108 93 93 #if defined (Q_WS_WIN) 94 94 HCURSOR hcurs; 95 #elif defined (Q_WS_PM) 96 HPOINTER hcurs; 95 97 #elif defined (Q_WS_X11) 96 98 XColor fg, bg; -
TabularUnified trunk/src/gui/kernel/qcursor_pm.cpp ¶
r95 r108 60 60 61 61 QCursorData::QCursorData(Qt::CursorShape s) 62 : cshape(s), bm(0), bmm(0), hx(0), hy(0) // @todo, hcurs(0)62 : cshape(s), bm(0), bmm(0), hx(0), hy(0), hcurs(NULLHANDLE) 63 63 { 64 64 ref = 1; … … 79 79 // @todo implement 80 80 return 0; 81 } 82 83 HPOINTER QCursor::handle() const 84 { 85 if (!QCursorData::initialized) 86 QCursorData::initialize(); 87 if (!d->hcurs) 88 d->update(); 89 return d->hcurs; 90 } 91 92 QCursor::QCursor(HPOINTER handle) 93 { 94 d = new QCursorData(Qt::CustomCursor); 95 d->hcurs = handle; 81 96 } 82 97 -
TabularUnified trunk/src/gui/kernel/qwidget_pm.cpp ¶
r106 r108 857 857 858 858 if (flags & Qt::WindowTitleHint) { 859 title = topLevel ? qAppName().toLocal8Bit() : q->objectName().toLocal8Bit(); 859 QString t = topLevel ? qAppName() : q->objectName(); 860 t = t.left(1).toUpper() + t.mid(1).toLower(); 861 title = t.toLocal8Bit(); 860 862 } 861 863 … … 1186 1188 } 1187 1189 1190 QCursor *qt_grab_cursor() 1191 { 1192 return mouseGrbCur; 1193 } 1194 1188 1195 void QWidget::grabMouse() 1189 1196 { -
TabularUnified trunk/src/gui/kernel/qwindowdefs_pm.h ¶
r100 r108 59 59 typedef LHANDLE HWND; 60 60 typedef LHANDLE HPS; 61 typedef LHANDLE HPOINTER; 61 62 typedef struct _QMSG QMSG; 62 63 typedef void *MRESULT;
Note:
See TracChangeset
for help on using the changeset viewer.