summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@digia.com>2014-02-19 10:06:25 +0100
committerOswald Buddenhagen <oswald.buddenhagen@digia.com>2014-02-19 10:06:25 +0100
commit30fd22b9574def54726e7b193127cc0c901c1b4c (patch)
tree96dfc923044db0515064ba39d052d9ed577e3e40 /src/widgets/kernel
parentd7b0581c1c2ef60c08d238dae39298af6904918f (diff)
parent6aa09bbce59828d028f6d1e81d2bfc6ba537aae1 (diff)
Merge remote-tracking branch 'origin/dev' into stable
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r--src/widgets/kernel/kernel.pri5
-rw-r--r--src/widgets/kernel/qapplication.cpp124
-rw-r--r--src/widgets/kernel/qapplication.h4
-rw-r--r--src/widgets/kernel/qapplication_p.h7
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp4
-rw-r--r--src/widgets/kernel/qformlayout.h2
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp183
-rw-r--r--src/widgets/kernel/qopenglwidget_p.h135
-rw-r--r--src/widgets/kernel/qwidget.cpp114
-rw-r--r--src/widgets/kernel/qwidget_p.h33
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp5
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp138
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h27
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp59
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h1
-rw-r--r--src/widgets/kernel/win.pri2
16 files changed, 731 insertions, 112 deletions
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index 444b9b687f..857fe4ac91 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -79,3 +79,8 @@ wince*: {
SOURCES += \
kernel/qwidgetsfunctions_wince.cpp
}
+
+contains(QT_CONFIG, opengl) {
+ HEADERS += kernel/qopenglwidget_p.h
+ SOURCES += kernel/qopenglwidget.cpp
+}
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index c9d6593662..9bc1576dc6 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -377,7 +377,6 @@ QPalette *QApplicationPrivate::set_pal = 0; // default palette set by pro
QFont *QApplicationPrivate::sys_font = 0; // default system font
QFont *QApplicationPrivate::set_font = 0; // default font set by programmer
-QIcon *QApplicationPrivate::app_icon = 0;
QWidget *QApplicationPrivate::main_widget = 0; // main application widget
QWidget *QApplicationPrivate::focus_widget = 0; // has keyboard input focus
QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard input focus after show()
@@ -446,7 +445,8 @@ void QApplicationPrivate::process_cmdline()
continue;
}
QByteArray arg = argv[i];
- arg = arg;
+ if (arg.startsWith("--"))
+ arg.remove(0, 1);
QString s;
if (arg == "-qdevel" || arg == "-qdebug") {
// obsolete argument
@@ -729,8 +729,6 @@ QApplication::~QApplication()
delete QApplicationPrivate::app_style;
QApplicationPrivate::app_style = 0;
- delete QApplicationPrivate::app_icon;
- QApplicationPrivate::app_icon = 0;
#ifndef QT_NO_DRAGANDDROP
if (qt_is_gui_used)
@@ -1560,6 +1558,7 @@ QString QApplicationPrivate::desktopStyleKey()
return QString();
}
+#if QT_VERSION < 0x060000 // remove these forwarders in Qt 6
/*!
\property QApplication::windowIcon
\brief the default window icon
@@ -1568,23 +1567,32 @@ QString QApplicationPrivate::desktopStyleKey()
*/
QIcon QApplication::windowIcon()
{
- return QApplicationPrivate::app_icon ? *QApplicationPrivate::app_icon : QIcon();
+ return QGuiApplication::windowIcon();
}
void QApplication::setWindowIcon(const QIcon &icon)
{
- if (!QApplicationPrivate::app_icon)
- QApplicationPrivate::app_icon = new QIcon();
- *QApplicationPrivate::app_icon = icon;
- if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
- QEvent e(QEvent::ApplicationWindowIconChange);
- QWidgetList all = QApplication::allWidgets();
- for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
- QWidget *w = *it;
- if (w->isWindow())
- sendEvent(w, &e);
- }
+ QGuiApplication::setWindowIcon(icon);
+}
+#endif
+
+void QApplicationPrivate::notifyWindowIconChanged()
+{
+ QEvent ev(QEvent::ApplicationWindowIconChange);
+ const QWidgetList list = QApplication::topLevelWidgets();
+ QWindowList windowList = QGuiApplication::topLevelWindows();
+
+ // send to all top-level QWidgets
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ windowList.removeOne(w->windowHandle());
+ QCoreApplication::sendEvent(w, &ev);
}
+
+ // in case there are any plain QWindows in this QApplication-using
+ // application, also send the notification to them
+ for (int i = 0; i < windowList.size(); ++i)
+ QCoreApplication::sendEvent(windowList.at(i), &ev);
}
/*!
@@ -1725,6 +1733,41 @@ QFontMetrics QApplication::fontMetrics()
return desktop()->fontMetrics();
}
+bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows)
+{
+ Q_ASSERT(processedWindows);
+ while (QWidget *w = QApplication::activeModalWidget()) {
+ if (!w->isVisible() || w->data->is_closing)
+ break;
+ QWindow *window = w->windowHandle();
+ if (!w->close()) // Qt::WA_DeleteOnClose may cause deletion.
+ return false;
+ if (window)
+ processedWindows->append(window);
+ }
+
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ if (w->isVisible() && w->windowType() != Qt::Desktop && !w->data->is_closing) {
+ QWindow *window = w->windowHandle();
+ if (!w->close()) // Qt::WA_DeleteOnClose may cause deletion.
+ return false;
+ if (window)
+ processedWindows->append(window);
+ list = QApplication::topLevelWidgets();
+ i = -1;
+ }
+ }
+ return true;
+}
+
+bool QApplicationPrivate::tryCloseAllWindows()
+{
+ QWindowList processedWindows;
+ return QApplicationPrivate::tryCloseAllWidgetWindows(&processedWindows)
+ && QGuiApplicationPrivate::tryCloseRemainingWindows(processedWindows);
+}
/*!
Closes all top-level windows.
@@ -1746,24 +1789,8 @@ QFontMetrics QApplication::fontMetrics()
*/
void QApplication::closeAllWindows()
{
- bool did_close = true;
- QWidget *w;
- while ((w = activeModalWidget()) && did_close) {
- if (!w->isVisible() || w->data->is_closing)
- break;
- did_close = w->close();
- }
- QWidgetList list = QApplication::topLevelWidgets();
- for (int i = 0; did_close && i < list.size(); ++i) {
- w = list.at(i);
- if (w->isVisible()
- && w->windowType() != Qt::Desktop
- && !w->data->is_closing) {
- did_close = w->close();
- list = QApplication::topLevelWidgets();
- i = -1;
- }
- }
+ QWindowList processedWindows;
+ QApplicationPrivate::tryCloseAllWidgetWindows(&processedWindows);
}
/*!
@@ -2611,7 +2638,7 @@ QDesktopWidget *QApplication::desktop()
void QApplication::setStartDragTime(int ms)
{
- Q_UNUSED(ms)
+ QGuiApplication::styleHints()->setStartDragTime(ms);
}
/*!
@@ -2644,7 +2671,7 @@ int QApplication::startDragTime()
void QApplication::setStartDragDistance(int l)
{
- Q_UNUSED(l);
+ QGuiApplication::styleHints()->setStartDragDistance(l);
}
/*!
@@ -2716,9 +2743,11 @@ bool QApplicationPrivate::shouldQuit()
QWindowList processedWindows;
for (int i = 0; i < list.size(); ++i) {
QWidget *w = list.at(i);
- processedWindows.push_back(w->windowHandle());
- if (w->isVisible() && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose))
- return false;
+ if (QWindow *window = w->windowHandle()) { // Menus, popup widgets may not have a QWindow
+ processedWindows.push_back(window);
+ if (w->isVisible() && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose))
+ return false;
+ }
}
return QGuiApplicationPrivate::shouldQuitInternal(processedWindows);
}
@@ -2767,6 +2796,13 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QApplicationPrivate::mouse_buttons |= me->button();
break;
}
+ case QEvent::MouseButtonDblClick:
+ {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ QApplicationPrivate::modifier_buttons = me->modifiers();
+ QApplicationPrivate::mouse_buttons |= me->button();
+ break;
+ }
case QEvent::MouseButtonRelease:
{
QMouseEvent *me = static_cast<QMouseEvent*>(e);
@@ -2995,6 +3031,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
mouse->modifiers());
me.spont = mouse->spontaneous();
me.setTimestamp(mouse->timestamp());
+ QGuiApplicationPrivate::setMouseEventFlags(&me, mouse->flags());
// throw away any mouse-tracking-only mouse events
if (!w->hasMouseTracking()
&& mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {
@@ -3611,7 +3648,7 @@ bool QApplication::keypadNavigationEnabled()
*/
void QApplication::setCursorFlashTime(int msecs)
{
- Q_UNUSED(msecs);
+ QGuiApplication::styleHints()->setCursorFlashTime(msecs);
}
int QApplication::cursorFlashTime()
@@ -3626,12 +3663,10 @@ int QApplication::cursorFlashTime()
The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
operating system's value is used.
-
- Setting the interval is not supported anymore in Qt 5.
*/
void QApplication::setDoubleClickInterval(int ms)
{
- Q_UNUSED(ms);
+ QGuiApplication::styleHints()->setMouseDoubleClickInterval(ms);
}
int QApplication::doubleClickInterval()
@@ -3659,7 +3694,7 @@ int QApplication::doubleClickInterval()
*/
void QApplication::setKeyboardInputInterval(int ms)
{
- Q_UNUSED(ms);
+ QGuiApplication::styleHints()->setKeyboardInputInterval(ms);
}
int QApplication::keyboardInputInterval()
@@ -3750,6 +3785,7 @@ void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEven
switch (event->type()) {
case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
case QEvent::TouchBegin:
if (setFocusOnRelease)
return;
diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h
index 83673eef4e..9cd18d5cd9 100644
--- a/src/widgets/kernel/qapplication.h
+++ b/src/widgets/kernel/qapplication.h
@@ -126,10 +126,10 @@ public:
static void setFont(const QFont &, const char* className = 0);
static QFontMetrics fontMetrics();
+#if QT_VERSION < 0x060000 // remove these forwarders in Qt 6
static void setWindowIcon(const QIcon &icon);
static QIcon windowIcon();
-
-
+#endif
static QWidgetList allWidgets();
static QWidgetList topLevelWidgets();
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 29c6902c78..93c9ffe002 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -120,6 +120,7 @@ public:
virtual void notifyActiveWindowChange(QWindow *);
virtual bool shouldQuit();
+ bool tryCloseAllWindows() Q_DECL_OVERRIDE;
#if defined(Q_WS_X11)
#ifndef QT_NO_SETTINGS
@@ -137,6 +138,8 @@ public:
void createEventDispatcher();
static void dispatchEnterLeave(QWidget *enter, QWidget *leave, const QPointF &globalPosF);
+ void notifyWindowIconChanged() Q_DECL_OVERRIDE;
+
//modality
bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = 0) const Q_DECL_OVERRIDE;
static bool isBlockedByModal(QWidget *widget);
@@ -144,7 +147,7 @@ public:
static bool tryModalHelper(QWidget *widget, QWidget **rettop = 0);
#ifdef Q_WS_MAC
static QWidget *tryModalHelper_sys(QWidget *top);
- bool canQuit();
+ bool canQuit();
#endif
bool notify_helper(QObject *receiver, QEvent * e);
@@ -198,7 +201,6 @@ public:
static QWidget *focus_widget;
static QWidget *hidden_focus_widget;
static QWidget *active_window;
- static QIcon *app_icon;
#ifndef QT_NO_WHEELEVENT
static int wheel_scroll_lines;
#endif
@@ -293,6 +295,7 @@ public:
QPixmap applyQIconStyleHelper(QIcon::Mode mode, const QPixmap& base) const;
private:
static QApplicationPrivate *self;
+ static bool tryCloseAllWidgetWindows(QWindowList *processedWindows);
static void giveFocusAccordingToFocusPolicy(QWidget *w, QEvent *event, QPoint localPos);
static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
index 1f8e950d00..7977ae3528 100644
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ b/src/widgets/kernel/qapplication_qpa.cpp
@@ -451,7 +451,7 @@ void qt_init(QApplicationPrivate *priv, int type)
QApplicationPrivate::initializeWidgetFontHash();
}
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// #fixme: Remove.
static HDC displayDC = 0; // display device context
@@ -470,7 +470,7 @@ void qt_cleanup()
QColormap::cleanup();
QApplicationPrivate::active_window = 0; //### this should not be necessary
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
if (displayDC) {
ReleaseDC(0, displayDC);
displayDC = 0;
diff --git a/src/widgets/kernel/qformlayout.h b/src/widgets/kernel/qformlayout.h
index a1356c734f..0b8fd65a3f 100644
--- a/src/widgets/kernel/qformlayout.h
+++ b/src/widgets/kernel/qformlayout.h
@@ -143,7 +143,7 @@ public:
int rowCount() const;
#if 0
- void dump() const;
+ void dump() const;
#endif
private:
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
new file mode 100644
index 0000000000..a5f81a9df8
--- /dev/null
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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 "qopenglwidget_p.h"
+#include <QOpenGLContext>
+#include <QtWidgets/private/qwidget_p.h>
+
+#include <QOpenGLFramebufferObject>
+#include <QWindow>
+#include <qpa/qplatformwindow.h>
+#include <QDebug>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLWidgetPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLWidget)
+public:
+ QOpenGLWidgetPrivate()
+ : fbo(0), uninitialized(true)
+ {
+ setRenderToTexture();
+ }
+ GLuint textureId() const { return fbo ? fbo->texture() : 0; }
+
+ const QSurface *surface() const { return q_func()->window()->windowHandle(); }
+ QSurface *surface() { return q_func()->window()->windowHandle(); }
+ void initialize();
+
+ QOpenGLContext context;
+ QOpenGLFramebufferObject *fbo;
+ bool uninitialized;
+
+ int w,h;
+};
+
+void QOpenGLWidgetPrivate::initialize()
+{
+ Q_Q(QOpenGLWidget);
+ if (!uninitialized)
+ return;
+ context.setShareContext(get(q->window())->shareContext());
+ context.setFormat(surface()->format());
+ context.create();
+ context.makeCurrent(surface());
+ q->initializeGL();
+ uninitialized = false;
+}
+
+QOpenGLWidget::QOpenGLWidget(QWidget *parent, Qt::WindowFlags f)
+ : QWidget(*(new QOpenGLWidgetPrivate), parent, f)
+{
+}
+
+QOpenGLWidget::~QOpenGLWidget()
+{
+}
+
+bool QOpenGLWidget::isValid() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->context.isValid();
+}
+
+void QOpenGLWidget::makeCurrent()
+{
+ Q_D(QOpenGLWidget);
+ d->context.makeCurrent(d->surface());
+ d->fbo->bind();
+}
+
+void QOpenGLWidget::doneCurrent()
+{
+ Q_D(QOpenGLWidget);
+ d->context.doneCurrent();
+}
+
+QSurfaceFormat QOpenGLWidget::format() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->surface()->format();
+}
+
+GLuint QOpenGLWidget::defaultFramebufferObject() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->fbo ? d->fbo->handle() : 0;
+}
+
+void QOpenGLWidget::initializeGL()
+{
+
+}
+
+void QOpenGLWidget::resizeGL(int w, int h)
+{
+ Q_UNUSED(w);
+ Q_UNUSED(h);
+}
+
+void QOpenGLWidget::paintGL()
+{
+}
+
+void QOpenGLWidget::updateGL()
+{
+ makeCurrent();
+ paintGL();
+ glFlush();
+ doneCurrent();
+ update();
+}
+
+
+void QOpenGLWidget::resizeEvent(QResizeEvent *)
+{
+ Q_D(QOpenGLWidget);
+ d->w = width();
+ d->h = height();
+ d->initialize();
+
+ d->context.makeCurrent(d->surface());
+ delete d->fbo; // recreate when resized
+ d->fbo = new QOpenGLFramebufferObject(size());
+ d->fbo->bind();
+ glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ resizeGL(width(), height());
+ paintGL();
+ glFlush();
+}
+
+void QOpenGLWidget::paintEvent(QPaintEvent *)
+{
+ qWarning("QOpenGLWidget does not support paintEvent() yet.");
+ return;
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qopenglwidget_p.h b/src/widgets/kernel/qopenglwidget_p.h
new file mode 100644
index 0000000000..1c7f0bfeec
--- /dev/null
+++ b/src/widgets/kernel/qopenglwidget_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+#ifndef QOPENGLWIDGET_H
+#define QOPENGLWIDGET_H
+
+#include <QWidget>
+#include <QSurfaceFormat>
+
+#include <QtGui/qopengl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLWidgetPrivate;
+
+class Q_WIDGETS_EXPORT QOpenGLWidget : public QWidget
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QOpenGLWidget)
+
+public:
+ explicit QOpenGLWidget(QWidget* parent=0,
+ Qt::WindowFlags f=0);
+
+// This API is not finalized yet. The commented-out functions below are
+// QGLWidget functions that have not been implemented for QOpenGLWidget.
+// Some of them may not end up in the final version (which is planned for a
+// future release of Qt).
+
+// explicit QOpenGLWidget(const QSurfaceFormat& format, QWidget* parent=0,
+// Qt::WindowFlags f=0);
+ ~QOpenGLWidget();
+
+// void qglClearColor(const QColor& c) const;
+
+ bool isValid() const;
+// bool isSharing() const;
+
+ void makeCurrent();
+ void doneCurrent();
+
+// void swapBuffers();
+
+ QSurfaceFormat format() const;
+ GLuint defaultFramebufferObject() const;
+
+// QPixmap renderPixmap(int w = 0, int h = 0, bool useContext = false);
+ QImage grabFrameBuffer(bool withAlpha = false);
+
+// static QImage convertToGLFormat(const QImage& img);
+
+// QPaintEngine *paintEngine() const;
+
+// void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
+// void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
+
+public Q_SLOTS:
+ void updateGL();
+
+protected:
+// bool event(QEvent *);
+ virtual void initializeGL();
+ virtual void resizeGL(int w, int h);
+ virtual void paintGL();
+
+// void setAutoBufferSwap(bool on);
+// bool autoBufferSwap() const;
+
+ void paintEvent(QPaintEvent*);
+ void resizeEvent(QResizeEvent*);
+
+// virtual void glInit();
+// virtual void glDraw();
+
+// QOpenGLWidget(QOpenGLWidgetPrivate &dd,
+// const QGLFormat &format = QGLFormat(),
+// QWidget *parent = 0,
+// const QOpenGLWidget* shareWidget = 0,
+// Qt::WindowFlags f = 0);
+private:
+ Q_DISABLE_COPY(QOpenGLWidget)
+
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENGLWIDGET_H
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index ee7f779a3a..46aa93fe48 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -78,6 +78,7 @@
#include "private/qstyle_p.h"
#include "qfileinfo.h"
#include <QtGui/qinputmethod.h>
+#include <QtGui/qopenglcontext.h>
#include <private/qgraphicseffect_p.h>
#include <qbackingstore.h>
@@ -270,6 +271,8 @@ QWidgetPrivate::QWidgetPrivate(int version)
, isMoved(0)
, usesDoubleBufferedGLContext(0)
, mustHaveWindowHandle(0)
+ , renderToTexture(0)
+ , textureChildSeen(0)
#ifndef QT_NO_IM
, inheritsInputMethodHints(0)
#endif
@@ -353,10 +356,10 @@ void QWidgetPrivate::scrollChildren(int dx, int dy)
}
}
-void QWidgetPrivate::updateWidgetTransform()
+void QWidgetPrivate::updateWidgetTransform(QEvent *event)
{
Q_Q(QWidget);
- if (q == qGuiApp->focusObject()) {
+ if (q == qGuiApp->focusObject() || event->type() == QEvent::FocusIn) {
QTransform t;
QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
t.translate(p.x(), p.y());
@@ -1188,7 +1191,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
- if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation))
+ if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation)) // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
q->create();
QEvent e(QEvent::Create);
@@ -1558,6 +1561,7 @@ void QWidgetPrivate::createTLExtra()
x->inRepaint = false;
x->embedded = 0;
x->window = 0;
+ x->shareContext = 0;
x->screenIndex = 0;
#ifdef Q_WS_MAC
x->wasMaximized = false;
@@ -4178,7 +4182,7 @@ const QPalette &QWidget::palette() const
if (!isEnabled()) {
data->pal.setCurrentColorGroup(QPalette::Disabled);
} else if ((!isVisible() || isActiveWindow())
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
&& !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
#endif
) {
@@ -5133,9 +5137,17 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
<< "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
#endif
- //actually send the paint event
- QPaintEvent e(toBePainted);
- QCoreApplication::sendSpontaneousEvent(q, &e);
+ if (renderToTexture) {
+ // This widget renders into a texture which is composed later. We just need to
+ // punch a hole in the backingstore, so the texture will be visible.
+ QPainter p(q);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(q->rect(), Qt::transparent);
+ } else {
+ //actually send the paint event
+ QPaintEvent e(toBePainted);
+ QCoreApplication::sendSpontaneousEvent(q, &e);
+ }
// Native widgets need to be marked dirty on screen so painting will be done in correct context
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
@@ -6747,12 +6759,25 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
if (maximized || fullScreen) {
// set geometry before setting the window state to make
// sure the window is maximized to the right screen.
- // Skip on windows: the window is restored into a broken
- // half-maximized state.
+ Qt::WindowStates ws = windowState();
#ifndef Q_OS_WIN
setGeometry(restoredNormalGeometry);
-#endif
- Qt::WindowStates ws = windowState();
+#else
+ if (ws & Qt::WindowFullScreen) {
+ // Full screen is not a real window state on Windows.
+ move(availableGeometry.topLeft());
+ } else if (ws & Qt::WindowMaximized) {
+ // Setting a geometry on an already maximized window causes this to be
+ // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
+ // Move the window in normal state if needed.
+ if (restoredScreenNumber != desktop->screenNumber(this)) {
+ setWindowState(Qt::WindowNoState);
+ setGeometry(restoredNormalGeometry);
+ }
+ } else {
+ setGeometry(restoredNormalGeometry);
+ }
+#endif // Q_OS_WIN
if (maximized)
ws |= Qt::WindowMaximized;
if (fullScreen)
@@ -8058,7 +8083,7 @@ bool QWidget::event(QEvent *event)
break;
case QEvent::FocusIn:
focusInEvent((QFocusEvent*)event);
- d->updateWidgetTransform();
+ d->updateWidgetTransform(event);
break;
case QEvent::FocusOut:
@@ -8100,12 +8125,12 @@ bool QWidget::event(QEvent *event)
case QEvent::Move:
moveEvent((QMoveEvent*)event);
- d->updateWidgetTransform();
+ d->updateWidgetTransform(event);
break;
case QEvent::Resize:
resizeEvent((QResizeEvent*)event);
- d->updateWidgetTransform();
+ d->updateWidgetTransform(event);
break;
case QEvent::Close:
@@ -9479,27 +9504,36 @@ void QWidget::updateGeometry()
*/
void QWidget::setWindowFlags(Qt::WindowFlags flags)
{
- if (data->window_flags == flags)
- return;
-
Q_D(QWidget);
+ d->setWindowFlags(flags);
+}
+
+/*! \internal
+
+ Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
+*/
+void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
+{
+ Q_Q(QWidget);
+ if (q->data->window_flags == flags)
+ return;
- if ((data->window_flags | flags) & Qt::Window) {
+ if ((q->data->window_flags | flags) & Qt::Window) {
// the old type was a window and/or the new type is a window
- QPoint oldPos = pos();
- bool visible = isVisible();
- setParent(parentWidget(), flags);
+ QPoint oldPos = q->pos();
+ bool visible = q->isVisible();
+ q->setParent(q->parentWidget(), flags);
// if both types are windows or neither of them are, we restore
// the old position
- if (!((data->window_flags ^ flags) & Qt::Window)
- && (visible || testAttribute(Qt::WA_Moved))) {
- move(oldPos);
+ if (!((q->data->window_flags ^ flags) & Qt::Window)
+ && (visible || q->testAttribute(Qt::WA_Moved))) {
+ q->move(oldPos);
}
// for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
- d->adjustQuitOnCloseAttribute();
+ adjustQuitOnCloseAttribute();
} else {
- data->window_flags = flags;
+ q->data->window_flags = flags;
}
}
@@ -9615,6 +9649,13 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
if (desktopWidget)
parent = 0;
+#ifndef QT_NO_OPENGL
+ if (d->textureChildSeen && parent) {
+ // set the textureChildSeen flag up the whole parent chain
+ QWidgetPrivate::get(parent)->setTextureChildSeen();
+ }
+#endif
+
if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
if (newParent)
oldBs->removeDirtyWidget(this);
@@ -9623,6 +9664,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
oldBs->moveStaticWidgets(this);
}
+ // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation) && !testAttribute(Qt::WA_WState_Created))
create();
@@ -11085,7 +11127,25 @@ void QWidgetPrivate::adjustQuitOnCloseAttribute()
}
}
-
+QOpenGLContext *QWidgetPrivate::shareContext() const
+{
+#ifdef QT_NO_OPENGL
+ return 0;
+#else
+ if (!extra || !extra->topextra || !extra->topextra->window) {
+ qWarning() << "Asking for share context for widget that does not have a window handle";
+ return 0;
+ }
+ QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this);
+ if (!extra->topextra->shareContext) {
+ QOpenGLContext *ctx = new QOpenGLContext();
+ ctx->setFormat(extra->topextra->window->format());
+ ctx->create();
+ that->extra->topextra->shareContext = ctx;
+ }
+ return that->extra->topextra->shareContext;
+#endif // QT_NO_OPENGL
+}
Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
{
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 943b7057b5..bdfc57f7c3 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -60,6 +60,7 @@
#include "QtCore/qset.h"
#include "QtGui/qregion.h"
#include "QtGui/qinputmethod.h"
+#include "QtGui/qopengl.h"
#include "QtWidgets/qsizepolicy.h"
#include "QtWidgets/qstyle.h"
#include "QtWidgets/qapplication.h"
@@ -80,6 +81,7 @@ class QPixmap;
class QWidgetBackingStore;
class QGraphicsProxyWidget;
class QWidgetItemV2;
+class QOpenGLContext;
class QStyle;
@@ -216,6 +218,7 @@ struct QTLWExtra {
bool wasMaximized;
#endif
QWidgetWindow *window;
+ QOpenGLContext *shareContext;
quint32 screenIndex; // index in qplatformscreenlist
};
@@ -324,6 +327,8 @@ public:
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
~QWidgetPrivate();
+ static QWidgetPrivate *get(QWidget *w) { return w->d_func(); }
+
QWExtra *extraData() const;
QTLWExtra *topData() const;
QTLWExtra *maybeTopData() const;
@@ -438,7 +443,7 @@ public:
void syncBackingStore(const QRegion &region);
// tells the input method about the widgets transform
- void updateWidgetTransform();
+ void updateWidgetTransform(QEvent *event);
void reparentFocusWidgets(QWidget *oldtlw);
@@ -489,6 +494,7 @@ public:
void setWindowTitle_helper(const QString &cap);
void setWindowFilePath_helper(const QString &filePath);
void setWindowModified_helper();
+ virtual void setWindowFlags(Qt::WindowFlags windowFlags);
bool setMinimumSize_helper(int &minw, int &minh);
bool setMaximumSize_helper(int &maxw, int &maxh);
@@ -537,6 +543,8 @@ public:
}
}
}
+#else
+ Q_UNUSED(widget);
#endif
return screen;
}
@@ -615,6 +623,27 @@ public:
inline QRect mapFromWS(const QRect &r) const
{ QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+ QOpenGLContext *shareContext() const;
+
+#ifndef QT_NO_OPENGL
+ virtual GLuint textureId() const { return 0; }
+
+ void setRenderToTexture() { renderToTexture = true; textureChildSeen = true; }
+ void setTextureChildSeen()
+ {
+ Q_Q(QWidget);
+ if (textureChildSeen)
+ return;
+ textureChildSeen = 1;
+
+ if (!q->isWindow()) {
+ QWidget *parent = q->parentWidget();
+ if (parent)
+ get(parent)->setTextureChildSeen();
+ }
+ }
+#endif
+
// Variables.
// Regular pointers (keep them together to avoid gaps on 64 bit architectures).
QWExtra *extra;
@@ -695,6 +724,8 @@ public:
uint isMoved : 1;
uint usesDoubleBufferedGLContext : 1;
uint mustHaveWindowHandle : 1;
+ uint renderToTexture : 1;
+ uint textureChildSeen : 1;
#ifndef QT_NO_IM
uint inheritsInputMethodHints : 1;
#endif
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index 0a4bc990e6..c2260b6e7d 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -49,6 +49,7 @@
#include "QtWidgets/qdesktopwidget.h"
#include <qpa/qplatformwindow.h>
#include "QtGui/qsurfaceformat.h"
+#include <QtGui/qopenglcontext.h>
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformintegration.h>
#include "QtGui/private/qwindow_p.h"
@@ -953,6 +954,10 @@ void QWidgetPrivate::deleteTLSysExtra()
delete extra->topextra->backingStore;
extra->topextra->backingStore = 0;
+#ifndef QT_NO_OPENGL
+ delete extra->topextra->shareContext;
+ extra->topextra->shareContext = 0;
+#endif
}
}
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 4a94cd6cb8..dc918657b4 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -57,6 +57,8 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qgraphicseffect_p.h>
+#include <qpa/qplatformbackingstore.h>
+
#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG)
# include <QtCore/qt_windows.h>
# include <qpa/qplatformnativeinterface.h>
@@ -72,10 +74,15 @@ extern QRegion qt_dirtyRegion(QWidget *);
* \a region is the region to be updated in \a widget coordinates.
*/
static inline void qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
- QWidget *tlw, const QPoint &tlwOffset)
+ QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures = 0,
+ QOpenGLContext *context = 0)
{
+#ifdef QT_NO_OPENGL
+ Q_UNUSED(widgetTextures);
+ Q_UNUSED(context);
+#endif
Q_ASSERT(widget);
- Q_ASSERT(!region.isEmpty());
+ Q_ASSERT(!region.isEmpty() || (context && widgetTextures && widgetTextures->count()));
Q_ASSERT(backingStore);
Q_ASSERT(tlw);
@@ -104,14 +111,20 @@ static inline void qt_flush(QWidget *widget, const QRegion &region, QBackingStor
if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))
return;
+ QPoint offset = tlwOffset;
if (widget != tlw)
- backingStore->flush(region, widget->windowHandle(), tlwOffset + widget->mapTo(tlw, QPoint()));
+ offset += widget->mapTo(tlw, QPoint());
+
+#ifndef QT_NO_OPENGL
+ if (widgetTextures)
+ backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, context);
else
- backingStore->flush(region, widget->windowHandle(), tlwOffset);
+#endif
+ backingStore->flush(region, widget->windowHandle(), offset);
}
#ifndef QT_NO_PAINT_DEBUG
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
static void showYellowThing_win(QWidget *widget, const QRegion &region, int msec)
{
@@ -151,7 +164,7 @@ static void showYellowThing_win(QWidget *widget, const QRegion &region, int msec
QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), nativeWindow);
::Sleep(msec);
}
-#endif // Q_OS_WIN
+#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped)
{
@@ -166,7 +179,7 @@ void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePa
widget = nativeParent;
}
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
Q_UNUSED(unclipped);
showYellowThing_win(widget, paintRegion, msec);
#else
@@ -430,7 +443,7 @@ QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &within
return region;
}
-static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately)
+void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, bool updateImmediately)
{
if (!widget)
return;
@@ -439,6 +452,7 @@ static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately)
QEvent event(QEvent::UpdateRequest);
QApplication::sendEvent(widget, &event);
} else {
+ updateRequestSent = true;
QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
}
}
@@ -488,6 +502,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
return;
}
+ //### FIXME fullUpdatePending seems to be always false????
if (fullUpdatePending) {
if (updateImmediately)
sendUpdateRequest(tlw, updateImmediately);
@@ -495,6 +510,13 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
}
const QPoint offset = widget->mapTo(tlw, QPoint());
+
+ if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!updateRequestSent || updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
if (updateImmediately)
@@ -503,7 +525,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
}
if (invalidateBuffer) {
- const bool eventAlreadyPosted = !dirty.isEmpty();
+ const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent;
#ifndef QT_NO_GRAPHICSEFFECT
if (widget->d_func()->graphicsEffect)
dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
@@ -583,6 +605,13 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
return;
}
+ if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!updateRequestSent || updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
if (qt_region_strictContains(dirty, translatedRect)) {
@@ -703,7 +732,12 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
}
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
- : tlw(topLevel), dirtyOnScreenWidgets(0), fullUpdatePending(0)
+ : tlw(topLevel),
+ dirtyOnScreenWidgets(0),
+ widgetTextures(0),
+ fullUpdatePending(0),
+ updateRequestSent(0),
+ textureListWatcher(0)
{
store = tlw->backingStore();
Q_ASSERT(store);
@@ -892,17 +926,17 @@ static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedRegion)
{
QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
- if (discardSyncRequest(tlw, tlwExtra) || tlwExtra->inTopLevelResize)
+ if (!tlw->isVisible() || !tlwExtra || tlwExtra->inTopLevelResize)
return;
- if (!exposedWidget || !exposedWidget->internalWinId() || !exposedWidget->isVisible()
+ if (!exposedWidget || !exposedWidget->internalWinId() || !exposedWidget->isVisible() || !exposedWidget->testAttribute(Qt::WA_Mapped)
|| !exposedWidget->updatesEnabled() || exposedRegion.isEmpty()) {
return;
}
// Nothing to repaint.
if (!isDirty()) {
- qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset);
+ qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
return;
}
@@ -910,7 +944,42 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
markDirtyOnScreen(exposedRegion, exposedWidget, exposedWidget->mapTo(tlw, QPoint()));
else
markDirtyOnScreen(exposedRegion, exposedWidget, QPoint());
- sync();
+
+ doSync();
+}
+
+#ifndef QT_NO_OPENGL
+static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures)
+{
+ QWidgetPrivate *wd = QWidgetPrivate::get(widget);
+ if (wd->renderToTexture)
+ widgetTextures->appendTexture(wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size()));
+
+ for (int i = 0; i < wd->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(wd->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
+ findTextureWidgetsRecursively(tlw, w, widgetTextures);
+ }
+}
+#endif
+
+QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore)
+ : m_locked(false),
+ m_backingStore(backingStore)
+{
+}
+
+void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList)
+{
+ connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool)));
+ m_locked = textureList->isLocked();
+}
+
+void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)
+{
+ m_locked = locked;
+ if (!locked)
+ m_backingStore->sync();
}
/*!
@@ -918,6 +987,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
*/
void QWidgetBackingStore::sync()
{
+ updateRequestSent = false;
QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
if (discardSyncRequest(tlw, tlwExtra)) {
// If the top-level is minimized, it's not visible on the screen so we can delay the
@@ -935,10 +1005,26 @@ void QWidgetBackingStore::sync()
return;
}
+ if (textureListWatcher && !textureListWatcher->isLocked()) {
+ textureListWatcher->deleteLater();
+ textureListWatcher = 0;
+ } else if (widgetTextures && widgetTextures->isLocked()) {
+ if (!textureListWatcher)
+ textureListWatcher = new QPlatformTextureListWatcher(this);
+ if (!textureListWatcher->isLocked())
+ textureListWatcher->watch(widgetTextures);
+ return;
+ }
+
+ doSync();
+}
+
+void QWidgetBackingStore::doSync()
+{
const bool updatesDisabled = !tlw->updatesEnabled();
bool repaintAllWidgets = false;
- const bool inTopLevelResize = tlwExtra->inTopLevelResize;
+ const bool inTopLevelResize = tlw->d_func()->maybeTopData()->inTopLevelResize;
const QRect tlwRect(topLevelRect());
const QRect surfaceGeometry(tlwRect.topLeft(), store->size());
if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
@@ -1018,7 +1104,15 @@ void QWidgetBackingStore::sync()
}
dirtyWidgets.clear();
+#ifndef QT_NO_OPENGL
+ delete widgetTextures;
+ widgetTextures = 0;
+ if (tlw->d_func()->textureChildSeen) {
+ widgetTextures = new QPlatformTextureList;
+ findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
+ }
fullUpdatePending = false;
+#endif
if (toClean.isEmpty()) {
// Nothing to repaint. However, we might have newly exposed areas on the
@@ -1032,6 +1126,7 @@ void QWidgetBackingStore::sync()
if (tlw->d_func()->extra->proxyWidget) {
updateStaticContentsSize();
dirty = QRegion();
+ updateRequestSent = false;
const QVector<QRect> rects(toClean.rects());
for (int i = 0; i < rects.size(); ++i)
tlw->d_func()->extra->proxyWidget->update(rects.at(i));
@@ -1045,6 +1140,7 @@ void QWidgetBackingStore::sync()
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
resetWidget(opaqueNonOverlappedWidgets[i]);
dirty = QRegion();
+ updateRequestSent = false;
return;
}
@@ -1053,6 +1149,7 @@ void QWidgetBackingStore::sync()
updateStaticContentsSize();
const QRegion dirtyCopy(dirty);
dirty = QRegion();
+ updateRequestSent = false;
// Paint opaque non overlapped widgets.
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {
@@ -1093,12 +1190,19 @@ void QWidgetBackingStore::flush(QWidget *widget)
{
if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset);
+ qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
dirtyOnScreen = QRegion();
}
- if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty())
+ if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) {
+#ifndef QT_NO_OPENGL
+ if (widgetTextures && widgetTextures->count()) {
+ QWidget *target = widget ? widget : tlw;
+ qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
+ }
+#endif
return;
+ }
for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
QWidget *w = dirtyOnScreenWidgets->at(i);
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index b6c3e13cb0..2fe58fa4a7 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -60,6 +60,9 @@
QT_BEGIN_NAMESPACE
+class QPlatformTextureList;
+class QWidgetBackingStore;
+
struct BeginPaintInfo {
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {}
uint wasFlushed : 1;
@@ -67,6 +70,23 @@ struct BeginPaintInfo {
uint backingStoreRecreated : 1;
};
+class QPlatformTextureListWatcher : public QObject
+{
+ Q_OBJECT
+
+public:
+ QPlatformTextureListWatcher(QWidgetBackingStore *backingStore);
+ void watch(QPlatformTextureList *textureList);
+ bool isLocked() const { return m_locked; }
+
+private slots:
+ void onLockStatusChanged(bool locked);
+
+private:
+ bool m_locked;
+ QWidgetBackingStore *m_backingStore;
+};
+
class Q_AUTOTEST_EXPORT QWidgetBackingStore
{
public:
@@ -102,14 +122,21 @@ private:
QVector<QWidget *> dirtyWidgets;
QVector<QWidget *> *dirtyOnScreenWidgets;
QList<QWidget *> staticWidgets;
+ QPlatformTextureList *widgetTextures;
QBackingStore *store;
uint fullUpdatePending : 1;
+ uint updateRequestSent : 1;
QPoint tlwOffset;
+ QPlatformTextureListWatcher *textureListWatcher;
+
+ void sendUpdateRequest(QWidget *widget, bool updateImmediately);
+
static bool flushPaint(QWidget *widget, const QRegion &rgn);
static void unflushPaint(QWidget *widget, const QRegion &rgn);
+ void doSync();
bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget);
void releaseBuffer();
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 167102c633..0e40dd866f 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -50,6 +50,7 @@
#include <private/qwidgetbackingstore_p.h>
#include <qpa/qwindowsysteminterface_p.h>
#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformwindow.h>
#include <private/qgesturemanager_p.h>
QT_BEGIN_NAMESPACE
@@ -91,6 +92,12 @@ QWidgetWindow::QWidgetWindow(QWidget *widget)
, m_widget(widget)
{
updateObjectName();
+ // Enable QOpenGLWidget/QQuickWidget children if the platform plugin supports it,
+ // and the application developer has not explicitly disabled it.
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface)
+ && !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
+ setSurfaceType(QSurface::RasterGLSurface);
+ }
connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
}
@@ -473,7 +480,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
if (!widget)
widget = m_widget;
- if (event->type() == QEvent::MouseButtonPress)
+ if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
qt_button_down = widget;
QWidget *receiver = QApplicationPrivate::pickMouseReceiver(m_widget, event->windowPos().toPoint(), &mapped, event->type(), event->buttons(),
@@ -484,12 +491,17 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
QApplicationPrivate::mouse_buttons &= ~event->button();
return;
}
-
- QMouseEvent translated(event->type(), mapped, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers());
- translated.setTimestamp(event->timestamp());
- QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget, &qt_button_down,
- qt_last_mouse_receiver);
-
+ if ((event->type() != QEvent::MouseButtonPress)
+ || !(event->flags().testFlag(Qt::MouseEventCreatedDoubleClick))) {
+
+ // The preceding statement excludes MouseButtonPress events which caused
+ // creation of a MouseButtonDblClick event. QTBUG-25831
+ QMouseEvent translated(event->type(), mapped, event->windowPos(), event->screenPos(),
+ event->button(), event->buttons(), event->modifiers());
+ translated.setTimestamp(event->timestamp());
+ QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget,
+ &qt_button_down, qt_last_mouse_receiver);
+ }
#ifndef QT_NO_CONTEXTMENU
if (event->type() == contextMenuTrigger && event->button() == Qt::RightButton) {
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
@@ -542,6 +554,24 @@ void QWidgetWindow::updateGeometry()
m_widget->data->fstrut_dirty = false;
}
+Qt::WindowState effectiveState(Qt::WindowStates state);
+
+// Store normal geometry used for saving application settings.
+void QWidgetWindow::updateNormalGeometry()
+{
+ QTLWExtra *tle = m_widget->d_func()->maybeTopData();
+ if (!tle)
+ return;
+ // Ask platform window, default to widget geometry.
+ QRect normalGeometry;
+ if (const QPlatformWindow *pw = handle())
+ normalGeometry = pw->normalGeometry();
+ if (!normalGeometry.isValid() && effectiveState(m_widget->windowState()) == Qt::WindowNoState)
+ normalGeometry = m_widget->geometry();
+ if (normalGeometry.isValid())
+ tle->normalGeometry = normalGeometry;
+}
+
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
updateGeometry();
@@ -654,6 +684,11 @@ void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
void QWidgetWindow::handleDropEvent(QDropEvent *event)
{
+ if (m_dragTarget.isNull()) {
+ qWarning() << Q_FUNC_INFO << m_widget << ": No drag target set.";
+ event->ignore();
+ return;
+ }
const QPoint mapped = m_dragTarget.data()->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &translated);
@@ -682,8 +717,6 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
}
}
-Qt::WindowState effectiveState(Qt::WindowStates state);
-
void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
{
// QWindow does currently not know 'active'.
@@ -702,16 +735,12 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
widgetState |= Qt::WindowMinimized;
break;
case Qt::WindowMaximized:
- if (effectiveState(widgetState) == Qt::WindowNoState)
- if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
- tle->normalGeometry = m_widget->geometry();
+ updateNormalGeometry();
widgetState |= Qt::WindowMaximized;
widgetState &= ~(Qt::WindowMinimized | Qt::WindowFullScreen);
break;
case Qt::WindowFullScreen:
- if (effectiveState(widgetState) == Qt::WindowNoState)
- if (QTLWExtra *tle = m_widget->d_func()->maybeTopData())
- tle->normalGeometry = m_widget->geometry();
+ updateNormalGeometry();
widgetState |= Qt::WindowFullScreen;
widgetState &= ~(Qt::WindowMinimized);
break;
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h
index ffde44dd27..8d6f14a669 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa_p.h
+++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h
@@ -104,6 +104,7 @@ private slots:
private:
void updateGeometry();
+ void updateNormalGeometry();
enum FocusWidgets {
FirstFocusWidget,
diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri
index d5cba740d1..76bb709e2b 100644
--- a/src/widgets/kernel/win.pri
+++ b/src/widgets/kernel/win.pri
@@ -2,6 +2,6 @@
# --------------------------------------------------------------------
INCLUDEPATH += ../3rdparty/wintab
-!wince* {
+!wince*:!winrt {
LIBS_PRIVATE *= -lshell32
}