summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r--src/widgets/kernel/kernel.pri56
-rw-r--r--src/widgets/kernel/qgesture_p.h35
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp6
-rw-r--r--src/widgets/kernel/qmacgesturerecognizer.cpp275
-rw-r--r--src/widgets/kernel/qmacgesturerecognizer_p.h102
-rw-r--r--src/widgets/kernel/qsizepolicy.qdoc2
-rw-r--r--src/widgets/kernel/qwidget.cpp16
-rw-r--r--src/widgets/kernel/qwidget_p.h1
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp33
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h4
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp173
-rw-r--r--src/widgets/kernel/qwindowcontainer_p.h5
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);