diff options
author | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-09-03 14:36:15 (GMT) |
---|---|---|
committer | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-09-03 14:36:15 (GMT) |
commit | f0844f9da7a834c282f6f04b2676f28de444e9dc (patch) | |
tree | 8e121429e25959043cc04c4364adbe8239e44a67 /src/gui/kernel | |
parent | fe763ef6cd255ccb54d0de1894c1a772f959585e (diff) | |
parent | f360180890298618ef3284c08789c2a243e1ba9d (diff) | |
download | Qt-f0844f9da7a834c282f6f04b2676f28de444e9dc.zip Qt-f0844f9da7a834c282f6f04b2676f28de444e9dc.tar.gz Qt-f0844f9da7a834c282f6f04b2676f28de444e9dc.tar.bz2 |
Merge commit 'qt/4.6' into kinetic-declarativeui
Diffstat (limited to 'src/gui/kernel')
-rw-r--r-- | src/gui/kernel/qaction.cpp | 20 | ||||
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 1 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 98 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_win.cpp | 17 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_x11.cpp | 7 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaapplication_mac.mm | 3 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaapplicationdelegate_mac.mm | 3 | ||||
-rw-r--r-- | src/gui/kernel/qcocoamenuloader_mac.mm | 3 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaview_mac.mm | 11 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaview_mac_p.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qcocoawindow_mac.mm | 3 | ||||
-rw-r--r-- | src/gui/kernel/qcocoawindowdelegate_mac.mm | 3 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.cpp | 30 | ||||
-rw-r--r-- | src/gui/kernel/qgesture_p.h | 5 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures.cpp | 204 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures.h | 28 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures_p.h | 18 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_win.cpp | 28 |
19 files changed, 341 insertions, 144 deletions
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index d2a25fd..2a28c71 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -269,6 +269,26 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) MenuRole for the actions in that submenu have no effect. They will never be moved. */ +/*! \enum QAction::SoftKeyRole + \value OptionsSoftKey + \value SelectSoftKey + \value BackSoftKey + \value NextSoftKey + \value PreviousSoftKey + \value OkSoftKey + \value CancelSoftKey + \value EditSoftKey + \value ViewSoftKey + \value BackSpaceSoftKey + \value EndEditSoftKey + \value RevertEditSoftKey + \value DeselectSoftKey + \value FinishSoftKey + \value MenuSoftKey + \value ContextMenuSoftKey + \value ExitSoftKey + */ + /*! Constructs an action with \a parent. If \a parent is an action group the action will be automatically inserted into the group. diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index f049a58..511c797 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3625,6 +3625,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: d->toolTipFallAsleep.stop(); + // fall-through case QEvent::Leave: d->toolTipWakeUp.stop(); default: diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 1bbf332..8561045 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); + } } } @@ -972,11 +997,14 @@ void QApplication::beep() beep=NULL; } -/*! \fn int QApplication::s60ProcessEvent(TWsEvent *event) - This function does the core processing of individual s60 - \a{event}s. It returns 1 if the event was handled, 0 if +/*! + \warning This function is only available on Symbian. + + This function processes an individual Symbian window server + \a event. It returns 1 if the event was handled, 0 if the \a event was not handled, and -1 if the event was - not handled because the event handle was not in the map. + not handled because the event handle (\c{TWsEvent::Handle()}) + is not known to Qt. */ int QApplication::s60ProcessEvent(TWsEvent *event) { @@ -1065,7 +1093,16 @@ int QApplication::s60ProcessEvent(TWsEvent *event) } /*! - Returns false. Does nothing with the TWsEvent \a aEvent. + \warning This virtual function is only available on Symbian. + + If you create an application that inherits QApplication and reimplement + this function, you get direct access to events that the are received + from the Symbian window server. The events are passed in the TWsEvent + \a aEvent parameter. + + Return true if you want to stop the event from being processed. Return + false for normal event dispatching. The default implementation + false, and does nothing with \a aEvent. */ bool QApplication::s60EventFilter(TWsEvent * /* aEvent */) { @@ -1073,9 +1110,11 @@ bool QApplication::s60EventFilter(TWsEvent * /* aEvent */) } /*! + \warning This function is only available on Symbian. + Handles \a{command}s which are typically handled by CAknAppUi::HandleCommandL(). Qts Ui integration into Symbian is - partially achieved by deriving from CAknAppUi. Currently, exit, + partially achieved by deriving from CAknAppUi. Currently, exit, menu and softkey commands are handled. \sa s60EventFilter(), s60ProcessEvent() @@ -1107,7 +1146,12 @@ void QApplication::symbianHandleCommand(int command) } /*! + \warning This function is only available on Symbian. + Handles the resource change specified by \a type. + + Currently, KEikDynamicLayoutVariantSwitch and + KAknsMessageSkinChange are handled. */ void QApplication::symbianResourceChange(int type) { diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index a3de120..84edf1f 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -1903,11 +1903,9 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam QHideEvent e; qt_sendSpontaneousEvent(widget, &e); widget->hideChildren(true); -#ifndef Q_WS_WINCE const QString title = widget->windowIconText(); if (!title.isEmpty()) widget->setWindowTitle_helper(title); -#endif } result = false; break; @@ -1926,11 +1924,9 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam widget->showChildren(true); QShowEvent e; qt_sendSpontaneousEvent(widget, &e); -#ifndef Q_WS_WINCE const QString title = widget->windowTitle(); if (!title.isEmpty()) widget->setWindowTitle_helper(title); -#endif } result = false; break; @@ -1943,7 +1939,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam QWindowStateChangeEvent e(oldstate); qt_sendSpontaneousEvent(widget, &e); } -#endif +#endif // #ifndef Q_OS_WINCE break; } @@ -2030,13 +2026,16 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam // WM_ACTIVATEAPP handles the "true" false case, as this is only when the application // loses focus. Doing it here would result in the widget getting focus to not know // where it got it from; it would simply get a 0 value as the old focus widget. -#ifndef Q_WS_WINCE_WM - if (!(widget->windowState() & Qt::WindowMinimized)) { - // Ignore the activate message send by WindowsXP to a minimized window -#else +#ifdef Q_WS_WINCE { if (widget->windowState() & Qt::WindowMinimized) widget->dataPtr()->window_state &= ~Qt::WindowMinimized; +#else + if (!(widget->windowState() & Qt::WindowMinimized)) { +#endif + // Ignore the activate message send by WindowsXP to a minimized window +#ifdef Q_WS_WINCE_WM + { if (widget->windowState() & Qt::WindowFullScreen) qt_wince_hide_taskbar(widget->winId()); #endif diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 0056b9e..a7a6504 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -79,6 +79,7 @@ #include <private/qcolor_p.h> #include <private/qcursor_p.h> #include <private/qiconloader_p.h> +#include <private/gtksymbols_p.h> #include "qstyle.h" #include "qmetaobject.h" #include "qtimer.h" @@ -2287,6 +2288,12 @@ void qt_init(QApplicationPrivate *priv, int, if (X11->desktopEnvironment == DE_KDE) X11->desktopVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt(); +#if !defined(QT_NO_STYLE_GTK) + if (X11->desktopEnvironment == DE_GNOME) { + static bool menusHaveIcons = QGtk::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true); + QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !menusHaveIcons); + } +#endif qt_set_input_encoding(); qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol); diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm index ed62d02..2f1d88d 100644 --- a/src/gui/kernel/qcocoaapplication_mac.mm +++ b/src/gui/kernel/qcocoaapplication_mac.mm @@ -37,9 +37,6 @@ ** ** $QT_END_LICENSE$ ** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** ****************************************************************************/ /**************************************************************************** diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index cbf5cb6..b6aa454 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -37,9 +37,6 @@ ** ** $QT_END_LICENSE$ ** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** ****************************************************************************/ /**************************************************************************** diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm index 1bdb123..14e4510 100644 --- a/src/gui/kernel/qcocoamenuloader_mac.mm +++ b/src/gui/kernel/qcocoamenuloader_mac.mm @@ -37,9 +37,6 @@ ** ** $QT_END_LICENSE$ ** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** ****************************************************************************/ #include "qmacdefines_mac.h" diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index bc32078..59494a7 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -201,7 +201,6 @@ extern "C" { composingText = new QString(); composing = false; sendKeyEvents = true; - inKeyDown = false; currentCustomTypes = 0; [self setHidden:YES]; return self; @@ -1037,7 +1036,6 @@ extern "C" { - (void)keyDown:(NSEvent *)theEvent { - inKeyDown = true; sendKeyEvents = true; QWidget *widgetToGetKey = qwidget; @@ -1057,7 +1055,6 @@ extern "C" { if (!keyOK && !sendToPopup) [super keyDown:theEvent]; } - inKeyDown = false; } @@ -1104,13 +1101,7 @@ extern "C" { }; } - if ([aString length] && !inKeyDown) { - // Handle the case where insertText is called from somewhere else than the keyDown - // implementation, for example when inserting text from the character palette. - QInputMethodEvent e; - e.setCommitString(commitText); - qt_sendSpontaneousEvent(qwidget, &e); - } else if ([aString length] && composing) { + if ([aString length] && composing) { // Send the commit string to the widget. composing = false; sendKeyEvents = false; diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index 9d4e3d0..3810a2b 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -86,7 +86,6 @@ Q_GUI_EXPORT bool composing; int composingLength; bool sendKeyEvents; - bool inKeyDown; QString *composingText; QStringList *currentCustomTypes; NSInteger dragEnterSequence; diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index 59e8254..57dca6d 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -37,9 +37,6 @@ ** ** $QT_END_LICENSE$ ** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** ****************************************************************************/ #include "qmacdefines_mac.h" diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 0a7a00f..6704fda 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -37,9 +37,6 @@ ** ** $QT_END_LICENSE$ ** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** ****************************************************************************/ #import "private/qcocoawindowdelegate_mac_p.h" diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index d5e7167..7831893 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -133,21 +133,22 @@ private: /*! \fn void QGesture::cancelled() - The signal is emitted when the gesture is cancelled, for example the reset() - function is called while the gesture was in the process of emitting a - triggered() signal. Extended information about the gesture is contained in - the sender object. + The signal is emitted when the gesture is cancelled, for example the + reset() function is called while the gesture was in the process of + emitting a triggered() signal. Extended information about the + gesture is contained in the sender object. */ - /*! - Creates a new gesture handler object and marks it as a child of \a parent. + Creates a new gesture handler object and marks it as a child of \a + parent. \a gestureTarget is the object that the gesture will watch + for events. - The \a parent object is also the default event source for the gesture, - meaning that the gesture installs itself as an event filter for the \a - parent. + The \a parent object is also the default event source for the + gesture, meaning that the gesture installs itself as an event filter + for the \a parent. - \sa setGraphicsItem() + \sa setGraphicsItem() */ QGesture::QGesture(QObject *gestureTarget, QObject *parent) : QObject(*new QGesturePrivate, parent) @@ -173,7 +174,7 @@ QGesture::~QGesture() /*! \property QGesture::gestureTarget - Gesture target is the object that the gesture will observe for events. + Gesture target is the object that the gesture will watch for events. Typically this means that the gesture installs an event filter on the target object. */ @@ -240,15 +241,18 @@ void QGesture::updateState(Qt::GestureState state) return; } const Qt::GestureState oldState = d->state; - d->state = state; if (state != Qt::NoGesture && oldState > state) { // comparing the state as ints: state should only be changed from // started to (optionally) updated and to finished. + d->state = state; qWarning("QGesture::updateState: incorrect new state"); return; } - if (oldState == Qt::NoGesture) + if (oldState == Qt::NoGesture) { + d->state = Qt::GestureStarted; emit started(); + } + d->state = state; if (state == Qt::GestureUpdated) emit triggered(); else if (state == Qt::GestureFinished) diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 2cfabef..ddca79e 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -70,7 +70,7 @@ class QGesturePrivate : public QObjectPrivate public: QGesturePrivate() : gestureTarget(0), graphicsItem(0), eventFilterProxyGraphicsItem(0), - state(Qt::NoGesture) + state(Qt::NoGesture), implicitGesture(false) { } @@ -81,6 +81,9 @@ public: QGraphicsItem *eventFilterProxyGraphicsItem; Qt::GestureState state; + + // the flag specifies if the gesture was created implicitely by Qt. + bool implicitGesture; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index cc30049..8e76715 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -47,6 +47,7 @@ #include <private/qapplication_p.h> #include <private/qevent_p.h> #include <private/qwidget_p.h> +#include <qmath.h> QT_BEGIN_NAMESPACE @@ -90,9 +91,12 @@ QPanGesture::QPanGesture(QWidget *gestureTarget, QObject *parent) void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget) { Q_Q(QPanGesture); + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + if (gestureTarget && gestureTarget->isWidgetType()) { QWidget *w = static_cast<QWidget*>(gestureTarget.data()); - QApplicationPrivate::instance()->widgetGestures[w].pan = 0; + if (qAppPriv->widgetGestures[w].pan == q) + qAppPriv->widgetGestures[w].pan = 0; #if defined(Q_WS_WIN) qt_widget_private(w)->winSetupGestures(); #elif defined(Q_WS_MAC) @@ -103,7 +107,7 @@ void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget) if (newGestureTarget && newGestureTarget->isWidgetType()) { QWidget *w = static_cast<QWidget*>(newGestureTarget); - QApplicationPrivate::instance()->widgetGestures[w].pan = q; + qAppPriv->widgetGestures[w].pan = q; #if defined(Q_WS_WIN) qt_widget_private(w)->winSetupGestures(); #elif defined(Q_WS_MAC) @@ -133,8 +137,13 @@ bool QPanGesture::event(QEvent *event) bool QPanGesture::eventFilter(QObject *receiver, QEvent *event) { -#ifdef Q_WS_WIN Q_D(QPanGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + +#ifdef Q_WS_WIN if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) { QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); @@ -164,11 +173,12 @@ bool QPanGesture::eventFilter(QObject *receiver, QEvent *event) return false; } if (state() == Qt::NoGesture) { - d->lastOffset = d->totalOffset = QSize(); + d->lastOffset = d->totalOffset = d->offset = QSize(); } else { - d->lastOffset = QSize(ev->position.x() - d->lastPosition.x(), - ev->position.y() - d->lastPosition.y()); - d->totalOffset += d->lastOffset; + d->lastOffset = d->offset; + d->offset = QSize(ev->position.x() - d->lastPosition.x(), + ev->position.y() - d->lastPosition.y()); + d->totalOffset += d->offset; } d->lastPosition = ev->position; updateState(nextState); @@ -181,23 +191,29 @@ bool QPanGesture::eventFilter(QObject *receiver, QEvent *event) /*! \internal */ bool QPanGesture::filterEvent(QEvent *event) { -#if defined(Q_WS_WIN) Q_D(QPanGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + +#if defined(Q_WS_WIN) const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); if (event->type() == QEvent::TouchBegin) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); d->lastPosition = p.pos().toPoint(); - d->lastOffset = d->totalOffset = QSize(); + d->lastOffset = d->totalOffset = d->offset = QSize(); } else if (event->type() == QEvent::TouchEnd) { if (state() != Qt::NoGesture) { if (ev->touchPoints().size() == 2) { QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); - d->lastOffset = + d->lastOffset = d->offset; + d->offset = QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; - d->totalOffset += d->lastOffset; + d->totalOffset += d->offset; } updateState(Qt::GestureFinished); } @@ -206,10 +222,11 @@ bool QPanGesture::filterEvent(QEvent *event) if (ev->touchPoints().size() == 2) { QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); - d->lastOffset = + d->lastOffset = d->offset; + d->offset = QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; - d->totalOffset += d->lastOffset; + d->totalOffset += d->offset; if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { updateState(Qt::GestureUpdated); @@ -219,7 +236,6 @@ bool QPanGesture::filterEvent(QEvent *event) #elif defined(QT_MAC_USE_COCOA) // The following implements single touch // panning on Mac: - Q_D(QPanGesture); const int panBeginDelay = 300; const int panBeginRadius = 3; const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); @@ -252,8 +268,9 @@ bool QPanGesture::filterEvent(QEvent *event) QPointF mousePos = QCursor::pos(); QPointF dist = mousePos - d->lastPosition; d->lastPosition = mousePos; - d->lastOffset = QSizeF(dist.x(), dist.y()); - d->totalOffset += d->lastOffset; + d->lastOffset = d->offset; + d->offset = QSizeF(dist.x(), dist.y()); + d->totalOffset += d->offset; updateState(Qt::GestureUpdated); } } else if (state() == Qt::NoGesture) { @@ -273,7 +290,7 @@ bool QPanGesture::filterEvent(QEvent *event) void QPanGesture::reset() { Q_D(QPanGesture); - d->lastOffset = d->totalOffset = QSize(0, 0); + d->lastOffset = d->totalOffset = d->offset = QSize(0, 0); d->lastPosition = QPoint(0, 0); #if defined(QT_MAC_USE_COCOA) @@ -298,8 +315,7 @@ QSizeF QPanGesture::totalOffset() const /*! \property QPanGesture::lastOffset - Specifies a pan offset since the last time the gesture was - triggered. + Specifies a pan offset the last time the gesture was triggered. */ QSizeF QPanGesture::lastOffset() const { @@ -307,6 +323,18 @@ QSizeF QPanGesture::lastOffset() const return d->lastOffset; } +/*! + \property QPanGesture::offset + + Specifies the current pan offset since the last time the gesture was + triggered. +*/ +QSizeF QPanGesture::offset() const +{ + Q_D(const QPanGesture); + return d->offset; +} + ////////////////////////////////////////////////////////////////////////////// /*! @@ -360,8 +388,13 @@ bool QPinchGesture::event(QEvent *event) bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) { -#if defined(Q_WS_WIN) || defined(Q_WS_MAC) Q_D(QPinchGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) { QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); #if defined(Q_WS_WIN) @@ -380,39 +413,80 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) // next we might receive the first gesture update event, so we // prepare for it. d->state = Qt::NoGesture; - d->scaleFactor = d->lastScaleFactor = 1; - d->rotationAngle = d->lastRotationAngle = 0; + d->changes = 0; + d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.; + d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.; d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF(); #if defined(Q_WS_WIN) d->initialDistance = 0; + d->lastSequenceId = ev->sequenceId; #endif return false; - case QNativeGestureEvent::Rotate: - d->scaleFactor = 0; + case QNativeGestureEvent::Rotate: { + d->lastScaleFactor = d->scaleFactor; d->lastRotationAngle = d->rotationAngle; -#if defined(Q_WS_WIN) - d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument); -#elif defined(Q_WS_MAC) - d->rotationAngle = ev->percentage; -#endif +#if defined(Q_WS_MAC) + d->rotationAngle += ev->percentage; nextState = Qt::GestureUpdated; +#elif defined(Q_WS_WIN) + // This is a workaround for an issue with the native rotation + // gesture on Windows 7. For some reason the rotation angle in the + // first WM_GESTURE message in a sequence contains value that is + // off a little bit and causes the rotating item to "jump", so + // we just ignore the first WM_GESTURE in every sequence. + bool windowsRotateWorkaround = false; + if (!d->lastSequenceId) { + windowsRotateWorkaround = true; + d->lastSequenceId = ev->sequenceId; + } + if (d->lastSequenceId > 0 && d->lastSequenceId != (ulong)-1 && ev->sequenceId != d->lastSequenceId) { + // this is the first WM_GESTURE message in a sequence. + d->totalRotationAngle += d->rotationAngle; + windowsRotateWorkaround = true; + // a magic value to mark that the next WM_GESTURE message is + // the second message in a sequence and we should clear the + // lastRotationAngle + d->lastSequenceId = (ulong)-1; + } + if (!windowsRotateWorkaround) { + d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument) * 180. / M_PI; + if (d->lastSequenceId == (ulong)-1) { + // a special case since we need to set the lastRotationAngle to + // rotationAngle when the first WM_GESTURE is received in each + // sequence. + d->lastRotationAngle = d->rotationAngle; + } + d->lastSequenceId = ev->sequenceId; + } + if (!windowsRotateWorkaround) + nextState = Qt::GestureUpdated; +#endif + d->changes = QPinchGesture::RotationAngleChanged; event->accept(); break; + } case QNativeGestureEvent::Zoom: - d->rotationAngle = 0; + d->lastRotationAngle = d->rotationAngle; + d->lastScaleFactor = d->scaleFactor; #if defined(Q_WS_WIN) if (d->initialDistance != 0) { - d->lastScaleFactor = d->scaleFactor; int distance = int(qint64(ev->argument)); - d->scaleFactor = (qreal) distance / d->initialDistance; + if (d->lastSequenceId && ev->sequenceId != d->lastSequenceId) { + d->totalScaleFactor *= d->scaleFactor; + d->initialDistance = int(qint64(ev->argument)); + d->lastScaleFactor = d->scaleFactor = (qreal) distance / d->initialDistance; + } else { + d->scaleFactor = (qreal) distance / d->initialDistance; + } + d->lastSequenceId = ev->sequenceId; } else { d->initialDistance = int(qint64(ev->argument)); } #elif defined(Q_WS_MAC) - d->lastScaleFactor = d->scaleFactor; - d->scaleFactor = ev->percentage; + d->scaleFactor += ev->percentage; #endif nextState = Qt::GestureUpdated; + d->changes = QPinchGesture::ScaleFactorChanged; event->accept(); break; case QNativeGestureEvent::GestureEnd: @@ -427,6 +501,8 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) d->startCenterPoint = d->centerPoint; d->lastCenterPoint = d->centerPoint; d->centerPoint = static_cast<QWidget*>(receiver)->mapFromGlobal(ev->position); + if (d->lastCenterPoint != d->centerPoint) + d->changes |= QPinchGesture::CenterPointChanged; updateState(nextState); return true; } @@ -438,6 +514,12 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) /*! \internal */ bool QPinchGesture::filterEvent(QEvent *event) { + Q_D(QPinchGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + Q_UNUSED(event); return false; } @@ -446,16 +528,44 @@ bool QPinchGesture::filterEvent(QEvent *event) void QPinchGesture::reset() { Q_D(QPinchGesture); - d->scaleFactor = d->lastScaleFactor = 0; - d->rotationAngle = d->lastRotationAngle = 0; + d->changes = 0; + d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.; + d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.; d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF(); QGesture::reset(); } /*! + \property QPinchGesture::whatChanged + + Specifies which values were changed in the gesture. +*/ +QPinchGesture::WhatChanged QPinchGesture::whatChanged() const +{ + return d_func()->changes; +} + +/*! + \property QPinchGesture::totalScaleFactor + + Specifies a total scale factor of the pinch gesture since the gesture + started. +*/ +qreal QPinchGesture::totalScaleFactor() const +{ + Q_D(const QPinchGesture); + return d->totalScaleFactor * d->scaleFactor; +} + +/*! \property QPinchGesture::scaleFactor Specifies a scale factor of the pinch gesture. + + If the gesture consists of several pinch sequences (i.e. zoom and rotate + sequences), then this property specifies the scale factor in the current + sequence. When pinching changes the rotation angle only, the value of this + property is 1. */ qreal QPinchGesture::scaleFactor() const { @@ -473,9 +583,29 @@ qreal QPinchGesture::lastScaleFactor() const } /*! + \property QPinchGesture::totalRotationAngle + + Specifies a total rotation angle of the gesture since the gesture started. + + The angle is specified in degrees. +*/ +qreal QPinchGesture::totalRotationAngle() const +{ + Q_D(const QPinchGesture); + return d->totalRotationAngle + d->rotationAngle; +} + +/*! \property QPinchGesture::rotationAngle Specifies a rotation angle of the gesture. + + If the gesture consists of several pinch sequences (i.e. zoom and rotate + sequences), then this property specifies the rotation angle in the current + sequence. When pinching changes the scale factor only, the value of this + property is 0. + + The angle is specified in degrees. */ qreal QPinchGesture::rotationAngle() const { @@ -486,6 +616,8 @@ qreal QPinchGesture::rotationAngle() const \property QPinchGesture::lastRotationAngle Specifies a previous rotation angle of the gesture. + + The angle is specified in degrees. */ qreal QPinchGesture::lastRotationAngle() const { diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h index bb6f3b6..53c4416 100644 --- a/src/gui/kernel/qstandardgestures.h +++ b/src/gui/kernel/qstandardgestures.h @@ -61,6 +61,7 @@ class Q_GUI_EXPORT QPanGesture : public QGesture Q_PROPERTY(QSizeF totalOffset READ totalOffset) Q_PROPERTY(QSizeF lastOffset READ lastOffset) + Q_PROPERTY(QSizeF offset READ offset) public: QPanGesture(QWidget *gestureTarget, QObject *parent = 0); @@ -69,6 +70,7 @@ public: QSizeF totalOffset() const; QSizeF lastOffset() const; + QSizeF offset() const; protected: void reset(); @@ -78,6 +80,7 @@ private: bool eventFilter(QObject *receiver, QEvent *event); friend class QWidget; + friend class QAbstractScrollAreaPrivate; }; class QPinchGesturePrivate; @@ -86,31 +89,48 @@ class Q_GUI_EXPORT QPinchGesture : public QGesture Q_OBJECT Q_DECLARE_PRIVATE(QPinchGesture) - Q_PROPERTY(qreal scaleFactor READ scaleFactor) +public: + enum WhatChange { + ScaleFactorChanged = 0x1, + RotationAngleChanged = 0x2, + CenterPointChanged = 0x4 + }; + Q_DECLARE_FLAGS(WhatChanged, WhatChange) + + Q_PROPERTY(WhatChanged whatChanged READ whatChanged) + + Q_PROPERTY(qreal totalScaleFactor READ totalScaleFactor) Q_PROPERTY(qreal lastScaleFactor READ lastScaleFactor) + Q_PROPERTY(qreal scaleFactor READ scaleFactor) - Q_PROPERTY(qreal rotationAngle READ rotationAngle) + Q_PROPERTY(qreal totalRotationAngle READ totalRotationAngle) Q_PROPERTY(qreal lastRotationAngle READ lastRotationAngle) + Q_PROPERTY(qreal rotationAngle READ rotationAngle) Q_PROPERTY(QPointF startCenterPoint READ startCenterPoint) Q_PROPERTY(QPointF lastCenterPoint READ lastCenterPoint) Q_PROPERTY(QPointF centerPoint READ centerPoint) public: + QPinchGesture(QWidget *gestureTarget, QObject *parent = 0); bool filterEvent(QEvent *event); void reset(); + WhatChanged whatChanged() const; + QPointF startCenterPoint() const; QPointF lastCenterPoint() const; QPointF centerPoint() const; - qreal scaleFactor() const; + qreal totalScaleFactor() const; qreal lastScaleFactor() const; + qreal scaleFactor() const; - qreal rotationAngle() const; + qreal totalRotationAngle() const; qreal lastRotationAngle() const; + qreal rotationAngle() const; private: bool event(QEvent *event); diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h index 270f307..354ebee 100644 --- a/src/gui/kernel/qstandardgestures_p.h +++ b/src/gui/kernel/qstandardgestures_p.h @@ -74,6 +74,7 @@ public: QSizeF totalOffset; QSizeF lastOffset; + QSizeF offset; QPointF lastPosition; #if defined(QT_MAC_USE_COCOA) @@ -88,25 +89,32 @@ class QPinchGesturePrivate : public QGesturePrivate public: QPinchGesturePrivate() - : scaleFactor(0), lastScaleFactor(0), - rotationAngle(0), lastRotationAngle(0) + : changes(0), totalScaleFactor(0.), lastScaleFactor(0.), scaleFactor(0.), + totalRotationAngle(0.), lastRotationAngle(0.), rotationAngle(0.) #ifdef Q_WS_WIN - ,initialDistance(0) + ,initialDistance(0), lastSequenceId(0) #endif { } void setupGestureTarget(QObject *o); - qreal scaleFactor; + QPinchGesture::WhatChanged changes; + + qreal totalScaleFactor; // total scale factor, excluding the current sequence. qreal lastScaleFactor; - qreal rotationAngle; + qreal scaleFactor; // scale factor in the current sequence. + + qreal totalRotationAngle; // total rotation angle, excluding the current sequence. qreal lastRotationAngle; + qreal rotationAngle; // rotation angle in the current sequence. + QPointF startCenterPoint; QPointF lastCenterPoint; QPointF centerPoint; #ifdef Q_WS_WIN int initialDistance; + ulong lastSequenceId; #endif }; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 863c43e..44f9db1 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -82,8 +82,6 @@ #include "private/qstyle_p.h" #include "private/qinputcontext_p.h" #include "qfileinfo.h" -#include "qstandardgestures.h" -#include "qstandardgestures_p.h" #if defined (Q_WS_WIN) # include <private/qwininputcontext_p.h> diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 8e60fb3..0ec7e7e 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -2062,29 +2062,21 @@ void QWidgetPrivate::registerTouchWindow() void QWidgetPrivate::winSetupGestures() { Q_Q(QWidget); - if (!q) - return; - if (!q->isVisible()) + if (!q || !q->isVisible()) return; QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - bool needh = false; - bool needv = false; - bool singleFingerPanEnabled = false; QApplicationPrivate::WidgetStandardGesturesMap::const_iterator it = qAppPriv->widgetGestures.find(q); if (it == qAppPriv->widgetGestures.end()) return; const QStandardGestures &gestures = it.value(); - WId winid = 0; + WId winid = q->effectiveWinId(); - if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q)) { - winid = asa->viewport()->internalWinId(); - if (!winid) { - QWidget *nativeParent = asa->viewport()->nativeParentWidget(); - if (!nativeParent) - return; - winid = nativeParent->internalWinId(); - } + bool needh = false; + bool needv = false; + bool singleFingerPanEnabled = false; + + if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q->parent())) { QScrollBar *hbar = asa->horizontalScrollBar(); QScrollBar *vbar = asa->verticalScrollBar(); Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy(); @@ -2094,12 +2086,6 @@ void QWidgetPrivate::winSetupGestures() needv = (vbarpolicy == Qt::ScrollBarAlwaysOn || (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum())); singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled; - } else { - winid = q->internalWinId(); - if (!winid) { - if (QWidget *nativeParent = q->nativeParentWidget()) - winid = nativeParent->internalWinId(); - } } if (winid && qAppPriv->SetGestureConfig) { GESTURECONFIG gc[3]; |