diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-06-03 11:30:23 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-06-03 11:59:15 +0200 |
commit | 1f456b4cbb93e3fea699878d117900b703146213 (patch) | |
tree | ce33b7dc746a1ef1b6a044fbcf742755c0c5744b /src/widgets/kernel | |
parent | 7d9fcaccb1e6e056336b9ad1f7f89afac4699aee (diff) |
Add support for mouse and keyboard grab.
Reviewed-by: Samuel Rødal
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r-- | src/widgets/kernel/qapplication_qpa.cpp | 85 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_qpa.cpp | 38 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow_qpa.cpp | 10 |
4 files changed, 96 insertions, 39 deletions
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index ec67452543..65aca42cd3 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -71,8 +71,13 @@ QT_BEGIN_NAMESPACE static QString appName; static QString appFont; +static bool popupGrabOk; extern bool app_do_modal; extern QWidgetList *qt_modal_stack; +extern QWidget *qt_button_down; +extern QWidget *qt_popup_down; +extern bool qt_replay_popup_mouse_event; +int openPopupCount = 0; QString QApplicationPrivate::appName() const { @@ -160,6 +165,35 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous) q->setActiveWindow(tlw); } +static void ungrabKeyboardForPopup(QWidget *popup) +{ + if (QWidget::keyboardGrabber()) + qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true); + else + qt_widget_private(popup)->stealKeyboardGrab(false); +} + +static void ungrabMouseForPopup(QWidget *popup) +{ + if (QWidget::mouseGrabber()) + qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true); + else + qt_widget_private(popup)->stealMouseGrab(false); +} + +static void grabForPopup(QWidget *popup) +{ + Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); + popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true); + if (popupGrabOk) { + popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true); + if (!popupGrabOk) { + // transfer grab back to the keyboard grabber if any + ungrabKeyboardForPopup(popup); + } + } +} + void QApplicationPrivate::closePopup(QWidget *popup) { Q_Q(QApplication); @@ -167,23 +201,34 @@ void QApplicationPrivate::closePopup(QWidget *popup) return; popupWidgets->removeAll(popup); -//### -// if (popup == qt_popup_down) { -// qt_button_down = 0; -// qt_popup_down = 0; -// } + if (popup == qt_popup_down) { + qt_button_down = 0; + qt_popup_down = 0; + } - if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup + if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup delete QApplicationPrivate::popupWidgets; QApplicationPrivate::popupWidgets = 0; - //### replay mouse event? - - //### transfer/release mouse grab + if (popupGrabOk) { + popupGrabOk = false; + + if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX, + QGuiApplicationPrivate::mousePressY)) + || popup->testAttribute(Qt::WA_NoMouseReplay)) { + // mouse release event or inside + qt_replay_popup_mouse_event = false; + } else { // mouse press event + QGuiApplicationPrivate::mousePressTime -= 10000; // avoid double click + qt_replay_popup_mouse_event = true; + } - //### transfer/release keyboard grab + // transfer grab back to mouse grabber if any, otherwise release the grab + ungrabMouseForPopup(popup); - //give back focus + // transfer grab back to keyboard grabber if any, otherwise release the grab + ungrabKeyboardForPopup(popup); + } if (active_window) { if (QWidget *fw = active_window->focusWidget()) { @@ -198,31 +243,25 @@ void QApplicationPrivate::closePopup(QWidget *popup) } else { // A popup was closed, so the previous popup gets the focus. - QWidget* aw = QApplicationPrivate::popupWidgets->last(); if (QWidget *fw = aw->focusWidget()) fw->setFocus(Qt::PopupFocusReason); - //### regrab the keyboard and mouse in case 'popup' lost the grab - - + if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard + grabForPopup(aw); } } -int openPopupCount = 0; void QApplicationPrivate::openPopup(QWidget *popup) { openPopupCount++; - if (!popupWidgets) { // create list + if (!popupWidgets) // create list popupWidgets = new QWidgetList; + popupWidgets->append(popup); // add to end of list - /* only grab if you are the first/parent popup */ - //#### ->grabMouse(popup,true); - //#### ->grabKeyboard(popup,true); - //### popupGrabOk = true; - } - popupWidgets->append(popup); // add to end of list + if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard + grabForPopup(popup); // popups are not focus-handled by the window system (the first // popup grabbed the keyboard), so we have to do that manually: A diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 24047cbced..d39e318b36 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -901,6 +901,8 @@ public: #elif defined(Q_WS_QPA) // <--------------------------------------------------------- QPA void setMaxWindowState_helper(); void setFullScreenSize_helper(); + bool stealKeyboardGrab(bool grab); + bool stealMouseGrab(bool grab); #ifndef QT_NO_CURSOR void updateCursor() const; #endif diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index b8a7cb5463..8764f633f1 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -338,8 +338,8 @@ void QWidget::grabMouse() if (qt_mouseGrb) qt_mouseGrb->releaseMouse(); - // XXX - //qwsDisplay()->grabMouse(this,true); + if (windowHandle()) + windowHandle()->setMouseGrabEnabled(true); qt_mouseGrb = this; qt_pressGrab = 0; @@ -353,19 +353,27 @@ void QWidget::grabMouse(const QCursor &cursor) if (qt_mouseGrb) qt_mouseGrb->releaseMouse(); - // XXX - //qwsDisplay()->grabMouse(this,true); - //qwsDisplay()->selectCursor(this, cursor.handle()); + if (windowHandle()) + windowHandle()->setMouseGrabEnabled(true); + qt_mouseGrb = this; qt_pressGrab = 0; } #endif +bool QWidgetPrivate::stealMouseGrab(bool grab) +{ + // This is like a combination of grab/releaseMouse() but with error checking + // and it has no effect on the result of mouseGrabber(). + Q_Q(QWidget); + return q->windowHandle() ? q->windowHandle()->setMouseGrabEnabled(grab) : false; +} + void QWidget::releaseMouse() { if (qt_mouseGrb == this) { - // XXX - //qwsDisplay()->grabMouse(this,false); + if (windowHandle()) + windowHandle()->setMouseGrabEnabled(false); qt_mouseGrb = 0; } } @@ -374,16 +382,24 @@ void QWidget::grabKeyboard() { if (keyboardGrb) keyboardGrb->releaseKeyboard(); - // XXX - //qwsDisplay()->grabKeyboard(this, true); + if (windowHandle()) + windowHandle()->setKeyboardGrabEnabled(true); keyboardGrb = this; } +bool QWidgetPrivate::stealKeyboardGrab(bool grab) +{ + // This is like a combination of grab/releaseKeyboard() but with error + // checking and it has no effect on the result of keyboardGrabber(). + Q_Q(QWidget); + return q->windowHandle() ? q->windowHandle()->setKeyboardGrabEnabled(grab) : false; +} + void QWidget::releaseKeyboard() { if (keyboardGrb == this) { - // XXX - //qwsDisplay()->grabKeyboard(this, false); + if (windowHandle()) + windowHandle()->setKeyboardGrabEnabled(false); keyboardGrb = 0; } } diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp index 38156d30e0..dbb8112e43 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa.cpp +++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp @@ -49,9 +49,9 @@ QT_BEGIN_NAMESPACE QWidget *qt_button_down = 0; // widget got last button-down // popup control -static QWidget *qt_popup_down = 0; // popup that contains the pressed widget +QWidget *qt_popup_down = 0; // popup that contains the pressed widget extern int openPopupCount; -static bool replayPopupMouseEvent = false; +bool qt_replay_popup_mouse_event = false; extern bool qt_try_modal(QWidget *widget, QEvent::Type type); QWidgetWindow::QWidgetWindow(QWidget *widget) @@ -155,7 +155,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) if (popup->isEnabled()) { // deliver event - replayPopupMouseEvent = false; + qt_replay_popup_mouse_event = false; QWidget *receiver = popup; QPoint widgetPos = mapped; if (qt_button_down) @@ -181,10 +181,10 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) } if (qApp->activePopupWidget() != activePopupWidget - && replayPopupMouseEvent) { + && qt_replay_popup_mouse_event) { if (m_widget->windowType() != Qt::Popup) qt_button_down = 0; - replayPopupMouseEvent = false; + qt_replay_popup_mouse_event = false; } else if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { |