diff options
author | Janne Anttila <janne.anttila@digia.com> | 2009-09-02 08:49:03 (GMT) |
---|---|---|
committer | Janne Anttila <janne.anttila@digia.com> | 2009-09-02 08:49:03 (GMT) |
commit | cd84cbc19df1f6ea02119ca89107645803e9c630 (patch) | |
tree | 4fe1b6eaafc116d5391819c76e3f96d7922f5de1 | |
parent | c0358c891d91b7fe78f439eefc706d87099e2634 (diff) | |
download | Qt-cd84cbc19df1f6ea02119ca89107645803e9c630.zip Qt-cd84cbc19df1f6ea02119ca89107645803e9c630.tar.gz Qt-cd84cbc19df1f6ea02119ca89107645803e9c630.tar.bz2 |
Fixes pointer events when using popups and/or modal dialogs.
This commit also adds initial support for fading behind modal dialogs.
Avoid unnecessary local/global capturing since when having global
capture enabled we cannot for example tap icons on statusbar.
The logic how pointer events for popups and modal dialogs shall work:
- Modal dialogs:
* Shall not close when outside dlg is clicked
* Shall not allow usage or underlying control with mouse
* Achieved with SetGloballyCapturing and SetPointerCapture
in enterModal_sys / leaveModal_sys
- Popups
* Shall close when the outside popup is clicked
* Achieved with enabling the SetPointerCapture only for topmost
popup and canceling it for all underlyuing ones.
* In addition long tap timer needs to be canceled for underlying
widgets when opening a pop-up. Otherwise theu get longtap event
whcih causes unexpected behaviour.
TODOs:
- Fading does not work correctly when more than two levels of modal
dialogs are opened.
- Fading does not work correctly when switching away from app and
back to it with fast swap window (using menu works)
- Check if fading should be implemented with MAknFadedComponent and
TAknPopupFader, in order to support cross-application fading
- Should popups closes when application loses the focus?
Reviewed-by: Janne Koskinen
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 1bbf332..4260fd9 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -347,21 +347,21 @@ void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, cons QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton; QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos, Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier); - + bool res = sendMouseEvent(alienWidget, &mEvent); #if !defined(QT_NO_CONTEXTMENU) QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, mEvent.modifiers()); qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent); -#endif - +#endif + m_previousEventLongTap = true; } void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) { m_longTapDetector->PointerEventL(pEvent); - QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); + QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); } void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) @@ -396,15 +396,6 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) if (!alienWidget) alienWidget = qwidget; S60->mousePressTarget = alienWidget; - //pointer grab - SetGloballyCapturing(ETrue); - SetPointerCapture(ETrue); - } - else if (type == QEvent::MouseButtonRelease) - { - //release pointer grab - SetGloballyCapturing(EFalse); - SetPointerCapture(EFalse); } alienWidget = S60->mousePressTarget; @@ -801,14 +792,27 @@ bool QApplicationPrivate::modalState() void QApplicationPrivate::enterModal_sys(QWidget *widget) { + if (widget) { + widget->effectiveWinId()->DrawableWindow()->FadeBehind(ETrue); + // Modal partial screen dialogs (like queries) capture pointer events. + // ### FixMe: Add specialized behaviour for fullscreen modal dialogs + widget->effectiveWinId()->SetGloballyCapturing(ETrue); + widget->effectiveWinId()->SetPointerCapture(ETrue); + } if (!qt_modal_stack) qt_modal_stack = new QWidgetList; qt_modal_stack->insert(0, widget); - app_do_modal = true; + app_do_modal = true; } void QApplicationPrivate::leaveModal_sys(QWidget *widget) { + if (widget) { + widget->effectiveWinId()->DrawableWindow()->FadeBehind(EFalse); + // ### FixMe: Add specialized behaviour for fullscreen modal dialogs + widget->effectiveWinId()->SetGloballyCapturing(EFalse); + widget->effectiveWinId()->SetPointerCapture(EFalse); + } if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { if (qt_modal_stack->isEmpty()) { delete qt_modal_stack; @@ -824,18 +828,31 @@ void QApplicationPrivate::openPopup(QWidget *popup) QApplicationPrivate::popupWidgets = new QWidgetList; QApplicationPrivate::popupWidgets->append(popup); - if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()) { + + // Cancel focus widget pointer capture and long tap timer + if (QApplication::focusWidget()) { + static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer(); + QApplication::focusWidget()->effectiveWinId()->SetPointerCapture(false); + } + + if (!qt_nograb()) { + // Cancel pointer capture and long tap timer for earlier popup + int popupCount = QApplicationPrivate::popupWidgets->count(); + if (popupCount > 1) { + QWidget* prevPopup = QApplicationPrivate::popupWidgets->at(popupCount-2); + static_cast<QSymbianControl*>(prevPopup->effectiveWinId())->CancelLongTapTimer(); + prevPopup->effectiveWinId()->SetPointerCapture(false); + } + + // Enable pointer capture for this (topmost) popup Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); WId id = popup->effectiveWinId(); id->SetPointerCapture(true); - id->SetGloballyCapturing(true); } // popups are not focus-handled by the window system (the first // popup grabbed the keyboard), so we have to do that manually: A // new popup gets the focus - if (QApplication::focusWidget()) - static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer(); QWidget *fw = popup->focusWidget(); if (fw) { fw->setFocus(Qt::PopupFocusReason); @@ -854,14 +871,16 @@ void QApplicationPrivate::closePopup(QWidget *popup) return; QApplicationPrivate::popupWidgets->removeAll(popup); + // Cancel pointer capture and long tap for this popup + WId id = popup->effectiveWinId(); + id->SetPointerCapture(false); + static_cast<QSymbianControl*>(id)->CancelLongTapTimer(); + if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup delete QApplicationPrivate::popupWidgets; QApplicationPrivate::popupWidgets = 0; if (!qt_nograb()) { // grabbing not disabled Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); - WId id = popup->effectiveWinId(); - id->SetPointerCapture(false); - id->SetGloballyCapturing(false); if (QWidgetPrivate::mouseGrabber != 0) QWidgetPrivate::mouseGrabber->grabMouse(); @@ -880,6 +899,7 @@ void QApplicationPrivate::closePopup(QWidget *popup) } } } else { + // popups are not focus-handled by the window system (the // first popup grabbed the keyboard), so we have to do that // manually: A popup was closed, so the previous popup gets @@ -889,6 +909,11 @@ void QApplicationPrivate::closePopup(QWidget *popup) QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); q_func()->sendEvent(fw, &e); } + + // Enable pointer capture for previous popup + if (aw) { + aw->effectiveWinId()->SetPointerCapture(true); + } } } |