From b1c715f8214233f5b573ed58fc89c9dd70beabb4 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 24 Jan 2011 10:02:51 +0100 Subject: Add support for disabling touch on to enhance scrolling in Cocoa On Mac/Cocoa, enabling touch on a widget slows down the scrolling performance of the whole application. It seems Cocoa spends some time in the background figuring out what to do with the touch events, and whether or not it should convert them to scroll/wheel events. Therefore, it makes sense to no subscribe for touch when the mouse is not over the widget, This patch implements that strategy, and the effect is huge when tested agains creator. Rev-By: brad --- src/gui/kernel/qapplication.cpp | 16 ++++++++++++++++ src/gui/kernel/qcocoaview_mac.mm | 2 ++ src/gui/kernel/qcocoaview_mac_p.h | 1 + src/gui/kernel/qwidget.cpp | 1 + src/gui/kernel/qwidget_mac.mm | 31 +++++++++++++++++++++++-------- src/gui/kernel/qwidget_p.h | 3 ++- src/gui/kernel/qwidget_s60.cpp | 3 ++- src/gui/kernel/qwidget_win.cpp | 3 ++- 8 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 8545d63..af4a258 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4423,6 +4423,22 @@ bool QApplication::notify(QObject *receiver, QEvent *e) break; } #endif // QT_NO_GESTURES +#ifdef QT_MAC_USE_COCOA + case QEvent::Enter: + if (receiver->isWidgetType()) { + QWidget *w = static_cast(receiver); + if (w->testAttribute(Qt::WA_AcceptTouchEvents)) + qt_widget_private(w)->registerTouchWindow(true); + } + break; + case QEvent::Leave: + if (receiver->isWidgetType()) { + QWidget *w = static_cast(receiver); + if (w->testAttribute(Qt::WA_AcceptTouchEvents)) + qt_widget_private(w)->registerTouchWindow(false); + } + break; +#endif default: res = d->notify_helper(receiver, e); break; diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 575343f..18a2be1 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -153,6 +153,8 @@ static int qCocoaViewCount = 0; composing = false; sendKeyEvents = true; fromKeyDownEvent = false; + alienTouchCount = 0; + [self setHidden:YES]; return self; } diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index fc14285..cc79b67 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -71,6 +71,7 @@ Q_GUI_EXPORT bool sendKeyEvents; bool fromKeyDownEvent; QString *composingText; + @public int alienTouchCount; } - (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; - (void) finishInitWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index f7d7d43..d3ccfd1 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -327,6 +327,7 @@ QWidgetPrivate::QWidgetPrivate(int version) hasOwnContext = false; isInUnifiedToolbar = false; unifiedSurface = 0; + touchEventsEnabled = false; #endif // QT_MAC_USE_COCOA #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index f8254ec..b3450ab 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2697,8 +2697,6 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO setWSGeometry(); if (destroyid) qt_mac_destructView(destroyid); - if (q->testAttribute(Qt::WA_AcceptTouchEvents)) - registerTouchWindow(); } /*! @@ -4981,19 +4979,36 @@ void QWidgetPrivate::registerDropSite(bool on) #endif } -void QWidgetPrivate::registerTouchWindow() +void QWidgetPrivate::registerTouchWindow(bool enable) { +#ifdef QT_MAC_USE_COCOA #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6) return; + Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) + if (enable == touchEventsEnabled) return; -#ifndef QT_MAC_USE_COCOA - // Needs implementation! + + QCocoaView *view = static_cast(qt_mac_effectiveview_for(q)); + if (!view) + return; + + if (enable) { + ++view->alienTouchCount; + if (view->alienTouchCount == 1) { + touchEventsEnabled = true; + [view setAcceptsTouchEvents:YES]; + } + } else { + --view->alienTouchCount; + if (view->alienTouchCount == 0) { + touchEventsEnabled = false; + [view setAcceptsTouchEvents:NO]; + } + } #else - NSView *view = qt_mac_effectiveview_for(q); - [view setAcceptsTouchEvents:YES]; + Q_UNUSED(on); #endif #endif } diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index bfaf91a..ecfd85f 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -859,6 +859,7 @@ public: bool isInUnifiedToolbar; QWindowSurface *unifiedSurface; QPoint toolbar_offset; + bool touchEventsEnabled; #endif void determineWindowClass(); void transferChildren(); @@ -871,7 +872,7 @@ public: static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); - void registerTouchWindow(); + void registerTouchWindow(bool enable = true); #elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS void setMaxWindowState_helper(); void setFullScreenSize_helper(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index cb72800..7547bec 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -990,8 +990,9 @@ void QWidgetPrivate::setMask_sys(const QRegion& /* region */) } -void QWidgetPrivate::registerTouchWindow() +void QWidgetPrivate::registerTouchWindow(bool enable) { + Q_UNUSED(enable); #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER Q_Q(QWidget); if (q->testAttribute(Qt::WA_WState_Created) && q->windowType() != Qt::Desktop) { diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index a02c5ba..54784a2 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -2064,8 +2064,9 @@ void QWidgetPrivate::setModal_sys() { } -void QWidgetPrivate::registerTouchWindow() +void QWidgetPrivate::registerTouchWindow(bool enable) { + Q_UNUSED(enable); Q_Q(QWidget); // enable WM_TOUCH* messages on our window -- cgit v0.12