diff options
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r-- | src/widgets/kernel/kernel.pri | 56 | ||||
-rw-r--r-- | src/widgets/kernel/qgesture_p.h | 35 | ||||
-rw-r--r-- | src/widgets/kernel/qgesturemanager.cpp | 6 | ||||
-rw-r--r-- | src/widgets/kernel/qmacgesturerecognizer.cpp | 275 | ||||
-rw-r--r-- | src/widgets/kernel/qmacgesturerecognizer_p.h | 102 | ||||
-rw-r--r-- | src/widgets/kernel/qsizepolicy.qdoc | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 16 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 33 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow_qpa_p.h | 4 | ||||
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 173 | ||||
-rw-r--r-- | src/widgets/kernel/qwindowcontainer_p.h | 5 |
12 files changed, 594 insertions, 114 deletions
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri index 533b696faa..444b9b687f 100644 --- a/src/widgets/kernel/kernel.pri +++ b/src/widgets/kernel/kernel.pri @@ -66,59 +66,9 @@ SOURCES += \ kernel/qwidgetwindow.cpp \ kernel/qwindowcontainer.cpp - -# TODO -false:!x11:mac { - SOURCES += \ - kernel/qclipboard_mac.cpp \ - kernel/qmime_mac.cpp \ - kernel/qt_mac.cpp \ - kernel/qkeymapper_mac.cpp - - OBJECTIVE_HEADERS += \ - qcocoawindow_mac_p.h \ - qcocoapanel_mac_p.h \ - qcocoawindowdelegate_mac_p.h \ - qcocoaview_mac_p.h \ - qcocoaapplication_mac_p.h \ - qcocoaapplicationdelegate_mac_p.h \ - qmacgesturerecognizer_mac_p.h \ - qmultitouch_mac_p.h \ - qcocoasharedwindowmethods_mac_p.h \ - qcocoaintrospection_p.h - - OBJECTIVE_SOURCES += \ - kernel/qcursor_mac.mm \ - kernel/qdnd_mac.mm \ - kernel/qapplication_mac.mm \ - kernel/qwidget_mac.mm \ - kernel/qcocoapanel_mac.mm \ - kernel/qcocoaview_mac.mm \ - kernel/qcocoawindow_mac.mm \ - kernel/qcocoawindowdelegate_mac.mm \ - kernel/qcocoaapplication_mac.mm \ - kernel/qcocoaapplicationdelegate_mac.mm \ - kernel/qt_cocoa_helpers_mac.mm \ - kernel/qdesktopwidget_mac.mm \ - kernel/qeventdispatcher_mac.mm \ - kernel/qcocoawindowcustomthemeframe_mac.mm \ - kernel/qmacgesturerecognizer_mac.mm \ - kernel/qmultitouch_mac.mm \ - kernel/qcocoaintrospection_mac.mm - - HEADERS += \ - kernel/qt_cocoa_helpers_mac_p.h \ - kernel/qcocoaapplication_mac_p.h \ - kernel/qcocoaapplicationdelegate_mac_p.h \ - kernel/qeventdispatcher_mac_p.h - - MENU_NIB.files = mac/qt_menu.nib - MENU_NIB.path = Resources - MENU_NIB.version = Versions - QMAKE_BUNDLE_DATA += MENU_NIB - RESOURCES += mac/macresources.qrc - - LIBS_PRIVATE += -framework AppKit +macx: { + HEADERS += kernel/qmacgesturerecognizer_p.h + SOURCES += kernel/qmacgesturerecognizer.cpp } wince*: { diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h index c041af7317..ae203d2819 100644 --- a/src/widgets/kernel/qgesture_p.h +++ b/src/widgets/kernel/qgesture_p.h @@ -190,41 +190,6 @@ public: static int Timeout; }; -#ifndef QT_NO_GESTURES -class QNativeGestureEvent : public QEvent -{ -public: - enum Type { - None, - GestureBegin, - GestureEnd, - Pan, - Zoom, - Rotate, - Swipe - }; - - QNativeGestureEvent() - : QEvent(QEvent::NativeGesture), gestureType(None), percentage(0) -#ifdef Q_WS_WIN - , sequenceId(0), argument(0) -#endif - { - } - - Type gestureType; - float percentage; - QPoint position; - float angle; -#ifdef Q_WS_WIN - ulong sequenceId; - quint64 argument; -#endif -}; - -#endif // QT_NO_GESTURES - - QT_END_NAMESPACE #endif // QT_NO_GESTURES diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index d90b187bf0..18abad4b40 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -51,8 +51,8 @@ #include "qevent.h" #include "qgraphicsitem.h" -#ifdef Q_WS_MAC -#include "qmacgesturerecognizer_mac_p.h" +#ifdef Q_OS_OSX +#include "qmacgesturerecognizer_p.h" #endif #if defined(Q_WS_WIN) && !defined(QT_NO_NATIVE_GESTURES) #include "qwinnativepangesturerecognizer_win_p.h" @@ -76,7 +76,7 @@ QGestureManager::QGestureManager(QObject *parent) { qRegisterMetaType<Qt::GestureState>(); -#if defined(Q_WS_MAC) +#if defined(Q_OS_OSX) registerGestureRecognizer(new QMacSwipeGestureRecognizer); registerGestureRecognizer(new QMacPinchGestureRecognizer); registerGestureRecognizer(new QMacPanGestureRecognizer); diff --git a/src/widgets/kernel/qmacgesturerecognizer.cpp b/src/widgets/kernel/qmacgesturerecognizer.cpp new file mode 100644 index 0000000000..feb779e53f --- /dev/null +++ b/src/widgets/kernel/qmacgesturerecognizer.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmacgesturerecognizer_p.h" +#include "qgesture.h" +#include "qgesture_p.h" +#include "qevent.h" +#include "qwidget.h" +#include "qdebug.h" + +#ifndef QT_NO_GESTURES + +QT_BEGIN_NAMESPACE + +QMacSwipeGestureRecognizer::QMacSwipeGestureRecognizer() +{ +} + +QGesture *QMacSwipeGestureRecognizer::create(QObject * /*target*/) +{ + return new QSwipeGesture; +} + +QGestureRecognizer::Result +QMacSwipeGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) { + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + switch (ev->gestureType()) { + case Qt::SwipeNativeGesture: { + QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); + g->setSwipeAngle(ev->value()); + g->setHotSpot(ev->screenPos()); + return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; + break; } + default: + break; + } + } + + return QGestureRecognizer::Ignore; +} + +void QMacSwipeGestureRecognizer::reset(QGesture *gesture) +{ + QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); + g->setSwipeAngle(0); + QGestureRecognizer::reset(gesture); +} + +//////////////////////////////////////////////////////////////////////// + +QMacPinchGestureRecognizer::QMacPinchGestureRecognizer() +{ +} + +QGesture *QMacPinchGestureRecognizer::create(QObject * /*target*/) +{ + return new QPinchGesture; +} + +QGestureRecognizer::Result +QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) { + QPinchGesture *g = static_cast<QPinchGesture *>(gesture); + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + switch (ev->gestureType()) { + case Qt::BeginNativeGesture: + reset(gesture); + g->setStartCenterPoint(static_cast<QWidget*>(obj)->mapFromGlobal(ev->screenPos().toPoint())); + g->setCenterPoint(g->startCenterPoint()); + g->setChangeFlags(QPinchGesture::CenterPointChanged); + g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); + g->setHotSpot(ev->screenPos()); + return QGestureRecognizer::MayBeGesture | QGestureRecognizer::ConsumeEventHint; + case Qt::RotateNativeGesture: + g->setLastScaleFactor(g->scaleFactor()); + g->setLastRotationAngle(g->rotationAngle()); + g->setRotationAngle(g->rotationAngle() + ev->value()); + g->setChangeFlags(QPinchGesture::RotationAngleChanged); + g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); + g->setHotSpot(ev->screenPos()); + return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; + case Qt::ZoomNativeGesture: + g->setLastScaleFactor(g->scaleFactor()); + g->setLastRotationAngle(g->rotationAngle()); + g->setScaleFactor(g->scaleFactor() * (1 + ev->value())); + g->setChangeFlags(QPinchGesture::ScaleFactorChanged); + g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); + g->setHotSpot(ev->screenPos()); + return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; + case Qt::SmartZoomNativeGesture: + g->setLastScaleFactor(g->scaleFactor()); + g->setLastRotationAngle(g->rotationAngle()); + g->setScaleFactor(ev->value() ? 1.7f : 1.0f); + g->setChangeFlags(QPinchGesture::ScaleFactorChanged); + g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); + g->setHotSpot(ev->screenPos()); + return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; + case Qt::EndNativeGesture: + return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; + default: + break; + } + } + + return QGestureRecognizer::Ignore; +} + +void QMacPinchGestureRecognizer::reset(QGesture *gesture) +{ + QPinchGesture *g = static_cast<QPinchGesture *>(gesture); + g->setChangeFlags(0); + g->setTotalChangeFlags(0); + g->setScaleFactor(1.0f); + g->setTotalScaleFactor(1.0f); + g->setLastScaleFactor(1.0f); + g->setRotationAngle(0.0f); + g->setTotalRotationAngle(0.0f); + g->setLastRotationAngle(0.0f); + g->setCenterPoint(QPointF()); + g->setStartCenterPoint(QPointF()); + g->setLastCenterPoint(QPointF()); + QGestureRecognizer::reset(gesture); +} + +//////////////////////////////////////////////////////////////////////// + +QMacPanGestureRecognizer::QMacPanGestureRecognizer() : _panCanceled(true) +{ +} + +QGesture *QMacPanGestureRecognizer::create(QObject *target) +{ + if (!target) + return new QPanGesture; + + if (QWidget *w = qobject_cast<QWidget *>(target)) { + w->setAttribute(Qt::WA_AcceptTouchEvents); + w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); + return new QPanGesture; + } + return 0; +} + +QGestureRecognizer::Result +QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent *event) +{ + const int panBeginDelay = 300; + const int panBeginRadius = 3; + + QPanGesture *g = static_cast<QPanGesture *>(gesture); + + switch (event->type()) { + case QEvent::TouchBegin: { + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + if (ev->touchPoints().size() == 1) { + reset(gesture); + _startPos = QCursor::pos(); + _panTimer.start(panBeginDelay, target); + _panCanceled = false; + return QGestureRecognizer::MayBeGesture; + } + break;} + case QEvent::TouchEnd: { + if (_panCanceled) + break; + + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + if (ev->touchPoints().size() == 1) + return QGestureRecognizer::FinishGesture; + break;} + case QEvent::TouchUpdate: { + if (_panCanceled) + break; + + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + if (ev->touchPoints().size() == 1) { + if (_panTimer.isActive()) { + // INVARIANT: Still in maybeGesture. Check if the user + // moved his finger so much that it makes sense to cancel the pan: + const QPointF p = QCursor::pos(); + if ((p - _startPos).manhattanLength() > panBeginRadius) { + _panCanceled = true; + _panTimer.stop(); + return QGestureRecognizer::CancelGesture; + } + } else { + const QPointF p = QCursor::pos(); + const QPointF posOffset = p - _startPos; + g->setLastOffset(g->offset()); + g->setOffset(QPointF(posOffset.x(), posOffset.y())); + g->setHotSpot(_startPos); + return QGestureRecognizer::TriggerGesture; + } + } else if (_panTimer.isActive()) { + // I only want to cancel the pan if the user is pressing + // more than one finger, and the pan hasn't started yet: + _panCanceled = true; + _panTimer.stop(); + return QGestureRecognizer::CancelGesture; + } + break;} + case QEvent::Timer: { + QTimerEvent *ev = static_cast<QTimerEvent *>(event); + if (ev->timerId() == _panTimer.timerId()) { + _panTimer.stop(); + if (_panCanceled) + break; + // Begin new pan session! + _startPos = QCursor::pos(); + g->setHotSpot(_startPos); + return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; + } + break; } + default: + break; + } + + return QGestureRecognizer::Ignore; +} + +void QMacPanGestureRecognizer::reset(QGesture *gesture) +{ + QPanGesture *g = static_cast<QPanGesture *>(gesture); + _startPos = QPointF(); + _panCanceled = true; + g->setOffset(QPointF(0, 0)); + g->setLastOffset(QPointF(0, 0)); + g->setAcceleration(qreal(1)); + QGestureRecognizer::reset(gesture); +} + +QT_END_NAMESPACE + +#endif // QT_NO_GESTURES diff --git a/src/widgets/kernel/qmacgesturerecognizer_p.h b/src/widgets/kernel/qmacgesturerecognizer_p.h new file mode 100644 index 0000000000..02f836b3f7 --- /dev/null +++ b/src/widgets/kernel/qmacgesturerecognizer_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMACSWIPEGESTURERECOGNIZER_MAC_P_H +#define QMACSWIPEGESTURERECOGNIZER_MAC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtimer.h" +#include "qpoint.h" +#include "qgesturerecognizer.h" + +#ifndef QT_NO_GESTURES + +QT_BEGIN_NAMESPACE + +class QMacSwipeGestureRecognizer : public QGestureRecognizer +{ +public: + QMacSwipeGestureRecognizer(); + + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); + void reset(QGesture *gesture); +}; + +class QMacPinchGestureRecognizer : public QGestureRecognizer +{ +public: + QMacPinchGestureRecognizer(); + + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); + void reset(QGesture *gesture); +}; + +class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer +{ +public: + QMacPanGestureRecognizer(); + + QGesture *create(QObject *target); + QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); + void reset(QGesture *gesture); +private: + QPointF _startPos; + QBasicTimer _panTimer; + bool _panCanceled; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GESTURES + +#endif // QMACSWIPEGESTURERECOGNIZER_MAC_P_H diff --git a/src/widgets/kernel/qsizepolicy.qdoc b/src/widgets/kernel/qsizepolicy.qdoc index 1c99131bc4..d82f3837f2 100644 --- a/src/widgets/kernel/qsizepolicy.qdoc +++ b/src/widgets/kernel/qsizepolicy.qdoc @@ -342,6 +342,7 @@ /*! \fn void QSizePolicy::retainSizeWhenHidden() const + \since 5.2 Returns if the layout should retain the widgets size when it is hidden. This is by default false. @@ -350,6 +351,7 @@ /*! \fn void QSizePolicy::setRetainSizeWhenHidden(bool retainSize) + \since 5.2 Set if a layout should retain the widgets size when it is hidden. If \a retainSize is true the layout will not be changed by hiding the widget. diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 72e3a56702..55459ac1ac 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1594,6 +1594,7 @@ void QWidgetPrivate::createExtra() extra->autoFillBackground = 0; extra->nativeChildrenForced = 0; extra->inRenderWithPainter = 0; + extra->hasWindowContainer = false; extra->hasMask = 0; createSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG @@ -6543,6 +6544,9 @@ void QWidget::move(const QPoint &p) data->crect.moveTopLeft(p); // no frame yet setAttribute(Qt::WA_PendingMoveEvent); } + + if (d->extra && d->extra->hasWindowContainer) + QWindowContainer::parentWasMoved(this); } /*! \fn void QWidget::resize(int w, int h) @@ -6581,6 +6585,9 @@ void QWidget::setGeometry(const QRect &r) setAttribute(Qt::WA_PendingMoveEvent); setAttribute(Qt::WA_PendingResizeEvent); } + + if (d->extra && d->extra->hasWindowContainer) + QWindowContainer::parentWasMoved(this); } /*! @@ -9715,6 +9722,9 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) ancestorProxy->d_func()->embedSubWindow(this); } #endif + + if (d->extra && d->extra->hasWindowContainer) + QWindowContainer::parentWasChanged(this); } /*! @@ -10747,6 +10757,9 @@ void QWidget::raise() if (testAttribute(Qt::WA_WState_Created)) d->raise_sys(); + if (d->extra && d->extra->hasWindowContainer) + QWindowContainer::parentWasRaised(this); + QEvent e(QEvent::ZOrderChange); QApplication::sendEvent(this, &e); } @@ -10781,6 +10794,9 @@ void QWidget::lower() if (testAttribute(Qt::WA_WState_Created)) d->lower_sys(); + if (d->extra && d->extra->hasWindowContainer) + QWindowContainer::parentWasLowered(this); + QEvent e(QEvent::ZOrderChange); QApplication::sendEvent(this, &e); } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index cc740034fc..df40908c00 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -254,6 +254,7 @@ struct QWExtra { uint nativeChildrenForced : 1; uint inRenderWithPainter : 1; uint hasMask : 1; + uint hasWindowContainer : 1; // *************************** Platform specific values (bit fields first) ********** #if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index f2bd389769..51a0eb7d72 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -49,6 +49,7 @@ #endif #include <private/qwidgetbackingstore_p.h> #include <qpa/qwindowsysteminterface_p.h> +#include <private/qgesturemanager_p.h> QT_BEGIN_NAMESPACE @@ -85,6 +86,12 @@ QWidgetWindow::QWidgetWindow(QWidget *widget) connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); } +QWidgetWindow::~QWidgetWindow() +{ + if (m_widget == qt_tablet_target) + qt_tablet_target = 0; +} + #ifndef QT_NO_ACCESSIBILITY QAccessibleInterface *QWidgetWindow::accessibleRoot() const { @@ -220,6 +227,13 @@ bool QWidgetWindow::event(QEvent *event) handleTabletEvent(static_cast<QTabletEvent *>(event)); return true; #endif + +#ifndef QT_NO_GESTURES + case QEvent::NativeGesture: + handleGestureEvent(static_cast<QNativeGestureEvent *>(event)); + return true; +#endif + #ifndef QT_NO_CONTEXTMENU case QEvent::ContextMenu: handleContextMenuEvent(static_cast<QContextMenuEvent *>(event)); @@ -732,6 +746,25 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event) } #endif // QT_NO_TABLETEVENT +#ifndef QT_NO_GESTURES +void QWidgetWindow::handleGestureEvent(QNativeGestureEvent *e) +{ + // copy-pasted code to find correct widget follows: + QObject *receiver = 0; + if (QApplicationPrivate::inPopupMode()) { + QWidget *popup = QApplication::activePopupWidget(); + QWidget *popupFocusWidget = popup->focusWidget(); + receiver = popupFocusWidget ? popupFocusWidget : popup; + } + if (!receiver) + receiver = QApplication::widgetAt(e->globalPos()); + if (!receiver) + receiver = m_widget; // last resort + + QApplication::sendSpontaneousEvent(receiver, e); +} +#endif // QT_NO_GESTURES + #ifndef QT_NO_CONTEXTMENU void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e) { diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h index cb7bef8f3e..ffde44dd27 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa_p.h +++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h @@ -58,6 +58,7 @@ class QWidgetWindow : public QWindow Q_OBJECT public: QWidgetWindow(QWidget *widget); + ~QWidgetWindow(); QWidget *widget() const { return m_widget; } #ifndef QT_NO_ACCESSIBILITY @@ -91,6 +92,9 @@ protected: #ifndef QT_NO_TABLETEVENT void handleTabletEvent(QTabletEvent *); #endif +#ifndef QT_NO_GESTURES + void handleGestureEvent(QNativeGestureEvent *); +#endif #ifndef QT_NO_CONTEXTMENU void handleContextMenuEvent(QContextMenuEvent *); #endif diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index b02b05552f..6914f64f8e 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -42,6 +42,10 @@ #include "qwindowcontainer_p.h" #include "qwidget_p.h" #include <QtGui/qwindow.h> +#include <QDebug> + +#include <QMdiSubWindow> +#include <QAbstractScrollArea> QT_BEGIN_NAMESPACE @@ -50,11 +54,67 @@ class QWindowContainerPrivate : public QWidgetPrivate public: Q_DECLARE_PUBLIC(QWindowContainer) - QWindowContainerPrivate() : window(0), oldFocusWindow(0) { } + QWindowContainerPrivate() + : window(0) + , oldFocusWindow(0) + , usesNativeWidgets(false) + { + } + ~QWindowContainerPrivate() { } + static QWindowContainerPrivate *get(QWidget *w) { + QWindowContainer *wc = qobject_cast<QWindowContainer *>(w); + if (wc) + return wc->d_func(); + return 0; + } + + void updateGeometry() { + Q_Q(QWindowContainer); + if (usesNativeWidgets) + window->setGeometry(q->rect()); + else + window->setGeometry(QRect(q->mapTo(q->window(), QPoint()), q->size())); + } + + void updateUsesNativeWidgets() + { + if (usesNativeWidgets || window->parent() == 0) + return; + Q_Q(QWindowContainer); + QWidget *p = q->parentWidget(); + while (p) { + if (qobject_cast<QMdiSubWindow *>(p) != 0 + || qobject_cast<QAbstractScrollArea *>(p) != 0) { + q->winId(); + usesNativeWidgets = true; + break; + } + p = p->parentWidget(); + } + } + + void markParentChain() { + Q_Q(QWindowContainer); + QWidget *p = q; + while (p) { + QWidgetPrivate *d = static_cast<QWidgetPrivate *>(QWidgetPrivate::get(p)); + d->createExtra(); + d->extra->hasWindowContainer = true; + p = p->parentWidget(); + } + } + + bool isStillAnOrphan() const { + return window->parent() == &fakeParent; + } + QPointer<QWindow> window; QWindow *oldFocusWindow; + QWindow fakeParent; + + uint usesNativeWidgets : 1; }; @@ -78,6 +138,14 @@ public: be removed from the window container with a call to QWindow::setParent(). + The window container is attached as a native child window to the + toplevel window it is a child of. When a window container is used + as a child of a QAbstractScrollArea or QMdiArea, it will + create a \l {Native Widgets vs Alien Widgets} {native window} for + every widget in its parent chain to allow for proper stacking and + clipping in this use case. Applications with many native child + windows may suffer from performance issues. + The window container has a number of known limitations: \list @@ -86,11 +154,6 @@ public: widget hierarchy as an opaque box. The stacking order of multiple overlapping window container instances is undefined. - \li Window Handles; The window container will explicitly invoke - winId() which will force the use of native window handles - inside the application. See \l {Native Widgets vs Alien Widgets} - {QWidget documentation} for more details. - \li Rendering Integration; The window container does not interoperate with QGraphicsProxyWidget, QWidget::render() or similar functionality. @@ -132,13 +195,7 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: } d->window = embeddedWindow; - - // We force this window to become a native window and reparent the - // window directly to it. This is done so that the order in which - // the QWindowContainer is added to a QWidget tree and when it - // gets a window does not matter. - winId(); - d->window->setParent(windowHandle()); + d->window->setParent(&d->fakeParent); connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow *)), this, SLOT(focusWindowChanged(QWindow *))); } @@ -167,8 +224,6 @@ void QWindowContainer::focusWindowChanged(QWindow *focusWindow) d->oldFocusWindow = focusWindow; } - - /*! \internal */ @@ -190,22 +245,38 @@ bool QWindowContainer::event(QEvent *e) // The only thing we are interested in is making sure our sizes stay // in sync, so do a catch-all case. case QEvent::Resize: + d->updateGeometry(); + break; case QEvent::Move: + d->updateGeometry(); + break; case QEvent::PolishRequest: - d->window->setGeometry(0, 0, width(), height()); + d->updateGeometry(); break; case QEvent::Show: - d->window->show(); + d->updateUsesNativeWidgets(); + if (d->isStillAnOrphan()) { + d->window->setParent(d->usesNativeWidgets + ? windowHandle() + : window()->windowHandle()); + } + if (d->window->parent()) { + d->markParentChain(); + d->window->show(); + } break; case QEvent::Hide: - d->window->hide(); + if (d->window->parent()) + d->window->hide(); break; case QEvent::FocusIn: - if (d->oldFocusWindow != d->window) { - d->window->requestActivate(); - } else { - QWidget *next = nextInFocusChain(); - next->setFocus(); + if (d->window->parent()) { + if (d->oldFocusWindow != d->window) { + d->window->requestActivate(); + } else { + QWidget *next = nextInFocusChain(); + next->setFocus(); + } } break; default: @@ -215,4 +286,60 @@ bool QWindowContainer::event(QEvent *e) return QWidget::event(e); } +typedef void (*qwindowcontainer_traverse_callback)(QWidget *parent); +static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse_callback callback) +{ + const QObjectList &children = parent->children(); + for (int i=0; i<children.size(); ++i) { + QWidget *w = qobject_cast<QWidget *>(children.at(i)); + if (w) { + QWidgetPrivate *wd = static_cast<QWidgetPrivate *>(QWidgetPrivate::get(w)); + if (wd->extra && wd->extra->hasWindowContainer) + callback(w); + } + } +} + +void QWindowContainer::parentWasChanged(QWidget *parent) +{ + if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { + if (d->window->parent()) { + d->updateUsesNativeWidgets(); + d->markParentChain(); + d->window->setParent(d->usesNativeWidgets + ? parent->windowHandle() + : parent->window()->windowHandle()); + d->updateGeometry(); + } + } + qwindowcontainer_traverse(parent, parentWasChanged); +} + +void QWindowContainer::parentWasMoved(QWidget *parent) +{ + if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { + if (d->window->parent()) + d->updateGeometry(); + } + qwindowcontainer_traverse(parent, parentWasMoved); +} + +void QWindowContainer::parentWasRaised(QWidget *parent) +{ + if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { + if (d->window->parent()) + d->window->raise(); + } + qwindowcontainer_traverse(parent, parentWasRaised); +} + +void QWindowContainer::parentWasLowered(QWidget *parent) +{ + if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { + if (d->window->parent()) + d->window->lower(); + } + qwindowcontainer_traverse(parent, parentWasLowered); +} + QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h index 37c023fc1d..e2446bef42 100644 --- a/src/widgets/kernel/qwindowcontainer_p.h +++ b/src/widgets/kernel/qwindowcontainer_p.h @@ -57,6 +57,11 @@ public: explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = 0, Qt::WindowFlags f = 0); ~QWindowContainer(); + static void parentWasChanged(QWidget *parent); + static void parentWasMoved(QWidget *parent); + static void parentWasRaised(QWidget *parent); + static void parentWasLowered(QWidget *parent); + protected: bool event(QEvent *ev); |