summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r--src/widgets/kernel/qaction.cpp45
-rw-r--r--src/widgets/kernel/qaction.h3
-rw-r--r--src/widgets/kernel/qaction_p.h3
-rw-r--r--src/widgets/kernel/qapplication.cpp21
-rw-r--r--src/widgets/kernel/qapplication_p.h2
-rw-r--r--src/widgets/kernel/qboxlayout.cpp28
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp87
-rw-r--r--src/widgets/kernel/qdesktopwidget.qdoc2
-rw-r--r--src/widgets/kernel/qdesktopwidget_p.h23
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp10
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp134
-rw-r--r--src/widgets/kernel/qopenglwidget.h3
-rw-r--r--src/widgets/kernel/qtooltip.cpp13
-rw-r--r--src/widgets/kernel/qwhatsthis.cpp9
-rw-r--r--src/widgets/kernel/qwidget.cpp261
-rw-r--r--src/widgets/kernel/qwidget_p.h22
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp32
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h6
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp125
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h3
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp13
-rw-r--r--src/widgets/kernel/win.pri2
22 files changed, 542 insertions, 305 deletions
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 7754defaac..853e27cd6e 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -45,6 +45,7 @@
#include "qapplication.h"
#include "qevent.h"
#include "qlist.h"
+#include "qstylehints.h"
#include <private/qshortcutmap_p.h>
#include <private/qapplication_p.h>
#if QT_CONFIG(menu)
@@ -77,6 +78,7 @@ static QString qt_strippedText(QString s)
QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false),
iconVisibleInMenu(-1),
+ shortcutVisibleInContextMenu(-1),
menuRole(QAction::TextHeuristicRole),
priority(QAction::NormalPriority)
{
@@ -1282,8 +1284,7 @@ void QAction::setIconVisibleInMenu(bool visible)
d->iconVisibleInMenu = visible;
// Only send data changed if we really need to.
if (oldValue != -1
- || (oldValue == -1
- && visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus))) {
+ || visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus)) {
d->sendDataChanged();
}
}
@@ -1298,6 +1299,46 @@ bool QAction::isIconVisibleInMenu() const
return d->iconVisibleInMenu;
}
+/*!
+ \property QAction::shortcutVisibleInContextMenu
+ \brief Whether or not an action should show a shortcut in a context menu
+ \since 5.10
+
+ In some applications, it may make sense to have actions with shortcuts in
+ context menus. If true, the shortcut (if valid) is shown when the action is
+ shown via a context menu, when it is false, it is not shown.
+
+ The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute
+ is set for the application, falling back to the widget style hint.
+ Explicitly setting this property overrides the presence (or abscence) of the attribute.
+
+ \sa QAction::shortcut, QCoreApplication::setAttribute()
+*/
+void QAction::setShortcutVisibleInContextMenu(bool visible)
+{
+ Q_D(QAction);
+ if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) {
+ int oldValue = d->shortcutVisibleInContextMenu;
+ d->shortcutVisibleInContextMenu = visible;
+ // Only send data changed if we really need to.
+ if (oldValue != -1
+ || visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) {
+ d->sendDataChanged();
+ }
+ }
+}
+
+bool QAction::isShortcutVisibleInContextMenu() const
+{
+ Q_D(const QAction);
+ if (d->shortcutVisibleInContextMenu == -1) {
+ if (QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus))
+ return false;
+ return qApp->styleHints()->showShortcutsInContextMenus();
+ }
+ return d->shortcutVisibleInContextMenu;
+}
+
#ifndef QT_NO_DEBUG_STREAM
Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QAction *action)
{
diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h
index 41e29e6ab9..e1d431100e 100644
--- a/src/widgets/kernel/qaction.h
+++ b/src/widgets/kernel/qaction.h
@@ -80,6 +80,7 @@ class Q_WIDGETS_EXPORT QAction : public QObject
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
+ Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed)
Q_PROPERTY(Priority priority READ priority WRITE setPriority)
public:
@@ -168,6 +169,8 @@ public:
void setIconVisibleInMenu(bool visible);
bool isIconVisibleInMenu() const;
+ void setShortcutVisibleInContextMenu(bool show);
+ bool isShortcutVisibleInContextMenu() const;
QWidget *parentWidget() const;
diff --git a/src/widgets/kernel/qaction_p.h b/src/widgets/kernel/qaction_p.h
index 992323f308..19ae47c7b9 100644
--- a/src/widgets/kernel/qaction_p.h
+++ b/src/widgets/kernel/qaction_p.h
@@ -109,7 +109,8 @@ public:
uint separator : 1;
uint fontSet : 1;
- int iconVisibleInMenu : 3; // Only has values -1, 0, and 1
+ int iconVisibleInMenu : 2; // Only has values -1, 0, and 1
+ int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1
QAction::MenuRole menuRole;
QAction::Priority priority;
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 26e9ffbbf0..943aeaa2d9 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1236,7 +1236,7 @@ void QApplication::setStyle(QStyle *style)
Requests a QStyle object for \a style from the QStyleFactory.
The string must be one of the QStyleFactory::keys(), typically one of
- "windows", "fusion", "windowsxp", or "macintosh". Style
+ "windows", "windowsvista", "fusion", or "macintosh". Style
names are case insensitive.
Returns 0 if an unknown \a style is passed, otherwise the QStyle object
@@ -1479,8 +1479,8 @@ void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char*
"selection-background-color" and "alternate-background-color".
\note Some styles do not use the palette for all drawing, for instance, if
- they make use of native theme engines. This is the case for the Windows XP,
- Windows Vista, and \macos styles.
+ they make use of native theme engines. This is the case for the
+ Windows Vista and \macos styles.
\sa QWidget::setPalette(), palette(), QStyle::polish()
*/
@@ -2228,8 +2228,15 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
if (test->isWindow())
seenWindow = true;
+ // If the next focus widget has a focus proxy, we need to check to ensure
+ // that the proxy is in the correct parent-child direction (according to
+ // \a next). This is to ensure that we can tab in and out of compound widgets
+ // without getting stuck in a tab-loop between parent and child.
+ QWidget *focusProxy = test->d_func()->deepestFocusProxy();
+
if ((test->focusPolicy() & focus_flag) == focus_flag
- && !(test->d_func()->extra && test->d_func()->extra->focus_proxy)
+ && !(next && focusProxy && focusProxy->isAncestorOf(test))
+ && !(!next && focusProxy && test->isAncestorOf(focusProxy))
&& test->isVisibleTo(toplevel) && test->isEnabled()
&& !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test))
&& (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))) {
@@ -2735,7 +2742,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
case enter/leave events are genereated by the underlying windowing system.
*/
extern QPointer<QWidget> qt_last_mouse_receiver;
-extern QWidget *qt_button_down;
+extern Q_WIDGETS_EXPORT QWidget *qt_button_down;
void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
{
#ifndef QT_NO_CURSOR
@@ -2964,6 +2971,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
// required in order to support Qt Test synthesized events. Real mouse
// and keyboard state updates from the platform plugin are managed by
// QGuiApplicationPrivate::process(Mouse|Wheel|Key|Touch|Tablet)Event();
+ // ### FIXME: Qt Test should not call qapp->notify(), but rather route
+ // the events through the proper QPA interface. This is required to
+ // properly generate all other events such as enter/leave etc.
switch (e->type()) {
case QEvent::MouseButtonPress:
{
@@ -3760,7 +3770,6 @@ static void grabForPopup(QWidget *popup)
}
}
-extern QWidget *qt_button_down;
extern QWidget *qt_popup_down;
extern bool qt_replay_popup_mouse_event;
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 36de3cacaa..5dca2e85f1 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -92,7 +92,7 @@ extern QClipboard *qt_clipboard;
#endif
typedef QHash<QByteArray, QFont> FontHash;
-FontHash *qt_app_fonts_hash();
+Q_WIDGETS_EXPORT FontHash *qt_app_fonts_hash();
typedef QHash<QByteArray, QPalette> PaletteHash;
PaletteHash *qt_app_palettes_hash();
diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp
index f2e3df5314..588cec2b95 100644
--- a/src/widgets/kernel/qboxlayout.cpp
+++ b/src/widgets/kernel/qboxlayout.cpp
@@ -873,15 +873,9 @@ void QBoxLayout::insertSpacing(int index, int size)
else
b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Minimum, QSizePolicy::Fixed);
- QT_TRY {
- QBoxLayoutItem *it = new QBoxLayoutItem(b);
- it->magic = true;
- d->list.insert(index, it);
-
- } QT_CATCH(...) {
- delete b;
- QT_RETHROW;
- }
+ QBoxLayoutItem *it = new QBoxLayoutItem(b);
+ it->magic = true;
+ d->list.insert(index, it);
invalidate();
}
@@ -985,20 +979,8 @@ void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch,
QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
b->setAlignment(alignment);
- QBoxLayoutItem *it;
- QT_TRY{
- it = new QBoxLayoutItem(b, stretch);
- } QT_CATCH(...) {
- delete b;
- QT_RETHROW;
- }
-
- QT_TRY{
- d->list.insert(index, it);
- } QT_CATCH(...) {
- delete it;
- QT_RETHROW;
- }
+ QBoxLayoutItem *it = new QBoxLayoutItem(b, stretch);
+ d->list.insert(index, it);
invalidate();
}
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index 1e6fbfd239..1b9cf88efe 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -73,6 +73,11 @@ int QDesktopScreenWidget::screenNumber() const
const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const
{
+ return QDesktopWidgetPrivate::screenGeometry(widget);
+}
+
+const QRect QDesktopWidgetPrivate::screenGeometry(const QWidget *widget)
+{
if (Q_UNLIKELY(!widget)) {
qWarning("QDesktopWidget::screenGeometry(): Attempt "
"to get the screen geometry of a null widget");
@@ -86,6 +91,11 @@ const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const
const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
{
+ return QDesktopWidgetPrivate::availableGeometry(widget);
+}
+
+const QRect QDesktopWidgetPrivate::availableGeometry(const QWidget *widget)
+{
if (Q_UNLIKELY(!widget)) {
qWarning("QDesktopWidget::availableGeometry(): Attempt "
"to get the available geometry of a null widget");
@@ -195,16 +205,51 @@ QDesktopWidget::~QDesktopWidget()
bool QDesktopWidget::isVirtualDesktop() const
{
+ return QDesktopWidgetPrivate::isVirtualDesktop();
+}
+
+bool QDesktopWidgetPrivate::isVirtualDesktop()
+{
return QGuiApplication::primaryScreen()->virtualSiblings().size() > 1;
}
+QRect QDesktopWidgetPrivate::geometry()
+{
+ return QGuiApplication::primaryScreen()->virtualGeometry();
+}
+
+QSize QDesktopWidgetPrivate::size()
+{
+ return geometry().size();
+}
+
+int QDesktopWidgetPrivate::width()
+{
+ return geometry().width();
+}
+
+int QDesktopWidgetPrivate::height()
+{
+ return geometry().height();
+}
+
int QDesktopWidget::primaryScreen() const
{
+ return QDesktopWidgetPrivate::primaryScreen();
+}
+
+int QDesktopWidgetPrivate::primaryScreen()
+{
return 0;
}
int QDesktopWidget::numScreens() const
{
+ return QDesktopWidgetPrivate::numScreens();
+}
+
+int QDesktopWidgetPrivate::numScreens()
+{
return qMax(QGuiApplication::screens().size(), 1);
}
@@ -218,6 +263,11 @@ QWidget *QDesktopWidget::screen(int screen)
const QRect QDesktopWidget::availableGeometry(int screenNo) const
{
+ return QDesktopWidgetPrivate::availableGeometry(screenNo);
+}
+
+const QRect QDesktopWidgetPrivate::availableGeometry(int screenNo)
+{
QList<QScreen *> screens = QGuiApplication::screens();
if (screenNo == -1)
screenNo = 0;
@@ -229,6 +279,11 @@ const QRect QDesktopWidget::availableGeometry(int screenNo) const
const QRect QDesktopWidget::screenGeometry(int screenNo) const
{
+ return QDesktopWidgetPrivate::screenGeometry(screenNo);
+}
+
+const QRect QDesktopWidgetPrivate::screenGeometry(int screenNo)
+{
QList<QScreen *> screens = QGuiApplication::screens();
if (screenNo == -1)
screenNo = 0;
@@ -240,6 +295,11 @@ const QRect QDesktopWidget::screenGeometry(int screenNo) const
int QDesktopWidget::screenNumber(const QWidget *w) const
{
+ return QDesktopWidgetPrivate::screenNumber(w);
+}
+
+int QDesktopWidgetPrivate::screenNumber(const QWidget *w)
+{
if (!w)
return primaryScreen();
@@ -287,26 +347,13 @@ int QDesktopWidget::screenNumber(const QWidget *w) const
int QDesktopWidget::screenNumber(const QPoint &p) const
{
- const QList<QScreen *> screens = QGuiApplication::screens();
- if (!screens.isEmpty()) {
- const QList<QScreen *> primaryScreens = screens.first()->virtualSiblings();
- // Find the screen index on the primary virtual desktop first
- foreach (QScreen *screen, primaryScreens) {
- if (screen->geometry().contains(p))
- return screens.indexOf(screen);
- }
- // If the screen index is not found on primary virtual desktop, find
- // the screen index on all screens except the first which was for
- // sure in the previous loop. Some other screens may repeat. Find
- // only when there is more than one virtual desktop.
- if (screens.count() != primaryScreens.count()) {
- for (int i = 1; i < screens.size(); ++i) {
- if (screens[i]->geometry().contains(p))
- return i;
- }
- }
- }
- return primaryScreen(); //even better would be closest screen
+ return QDesktopWidgetPrivate::screenNumber(p);
+}
+
+int QDesktopWidgetPrivate::screenNumber(const QPoint &p)
+{
+ QScreen *screen = QGuiApplication::screenAt(p);
+ return screen ? QGuiApplication::screens().indexOf(screen) : primaryScreen();
}
void QDesktopWidget::resizeEvent(QResizeEvent *)
diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc
index 27d05ece8c..fdf6a27597 100644
--- a/src/widgets/kernel/qdesktopwidget.qdoc
+++ b/src/widgets/kernel/qdesktopwidget.qdoc
@@ -152,7 +152,7 @@
on \macos, or the task bar on Windows). The default screen is used if
\a screen is -1.
- \sa screenNumber(), screenGeometry()
+ \sa screenNumber(), screenGeometry(), QScreen::availableGeometry()
*/
/*!
diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h
index dade4fe45e..7a66661771 100644
--- a/src/widgets/kernel/qdesktopwidget_p.h
+++ b/src/widgets/kernel/qdesktopwidget_p.h
@@ -87,6 +87,29 @@ public:
void _q_availableGeometryChanged();
QDesktopScreenWidget *widgetForScreen(QScreen *qScreen) const;
+ static bool isVirtualDesktop();
+
+ static QRect geometry();
+ static QSize size();
+ static int width();
+ static int height();
+
+ static int numScreens();
+ static int primaryScreen();
+
+ static int screenNumber(const QWidget *widget = nullptr);
+ static int screenNumber(const QPoint &);
+
+ static const QRect screenGeometry(int screen = -1);
+ static const QRect screenGeometry(const QWidget *widget);
+ static const QRect screenGeometry(const QPoint &point)
+ { return screenGeometry(screenNumber(point)); }
+
+ static const QRect availableGeometry(int screen = -1);
+ static const QRect availableGeometry(const QWidget *widget);
+ static const QRect availableGeometry(const QPoint &point)
+ { return availableGeometry(screenNumber(point)); }
+
QList<QDesktopScreenWidget *> screens;
};
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index f27961b817..5bf66d68e3 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -124,7 +124,7 @@ QGestureManager::~QGestureManager()
Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer)
{
- QGesture *dummy = recognizer->create(0);
+ const QScopedPointer<QGesture> dummy(recognizer->create(nullptr));
if (Q_UNLIKELY(!dummy)) {
qWarning("QGestureManager::registerGestureRecognizer: "
"the recognizer fails to create a gesture object, skipping registration.");
@@ -137,7 +137,6 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r
type = Qt::GestureType(m_lastCustomGestureId);
}
m_recognizers.insertMulti(type, recognizer);
- delete dummy;
return type;
}
@@ -145,10 +144,9 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
{
QList<QGestureRecognizer *> list = m_recognizers.values(type);
while (QGestureRecognizer *recognizer = m_recognizers.take(type)) {
- if (!m_obsoleteGestures.contains(recognizer)) {
- // inserting even an empty QSet will cause the recognizer to be deleted on destruction of the manager
- m_obsoleteGestures.insert(recognizer, QSet<QGesture *>());
- }
+ // ensuring an entry exists causes the recognizer to be deleted on destruction of the manager
+ auto &gestures = m_obsoleteGestures[recognizer];
+ Q_UNUSED(gestures);
}
foreach (QGesture *g, m_gestureToRecognizer.keys()) {
QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 218d3c4a46..5bc408a8cd 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -567,7 +567,8 @@ public:
paintDevice(0),
updateBehavior(QOpenGLWidget::NoPartialUpdate),
requestedSamples(0),
- inPaintGL(false)
+ inPaintGL(false),
+ textureFormat(0)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
@@ -576,6 +577,7 @@ public:
void recreateFbo();
GLuint textureId() const Q_DECL_OVERRIDE;
+ QPlatformTextureList::Flags textureListFlags() Q_DECL_OVERRIDE;
void initialize();
void invokeUserPaint();
@@ -606,6 +608,7 @@ public:
QOpenGLWidget::UpdateBehavior updateBehavior;
int requestedSamples;
bool inPaintGL;
+ GLenum textureFormat;
};
void QOpenGLWidgetPaintDevicePrivate::beginPaint()
@@ -663,6 +666,35 @@ GLuint QOpenGLWidgetPrivate::textureId() const
return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0);
}
+#ifndef GL_SRGB
+#define GL_SRGB 0x8C40
+#endif
+#ifndef GL_SRGB8
+#define GL_SRGB8 0x8C41
+#endif
+#ifndef GL_SRGB_ALPHA
+#define GL_SRGB_ALPHA 0x8C42
+#endif
+#ifndef GL_SRGB8_ALPHA8
+#define GL_SRGB8_ALPHA8 0x8C43
+#endif
+
+QPlatformTextureList::Flags QOpenGLWidgetPrivate::textureListFlags()
+{
+ QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags();
+ switch (textureFormat) {
+ case GL_SRGB:
+ case GL_SRGB8:
+ case GL_SRGB_ALPHA:
+ case GL_SRGB8_ALPHA8:
+ flags |= QPlatformTextureList::TextureIsSrgb;
+ break;
+ default:
+ break;
+ }
+ return flags;
+}
+
void QOpenGLWidgetPrivate::reset()
{
Q_Q(QOpenGLWidget);
@@ -712,12 +744,16 @@ void QOpenGLWidgetPrivate::recreateFbo()
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setSamples(samples);
+ if (textureFormat)
+ format.setInternalTextureFormat(textureFormat);
const QSize deviceSize = q->size() * q->devicePixelRatioF();
fbo = new QOpenGLFramebufferObject(deviceSize, format);
if (samples > 0)
resolvedFbo = new QOpenGLFramebufferObject(deviceSize);
+ textureFormat = fbo->format().internalTextureFormat();
+
fbo->bind();
context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -755,10 +791,8 @@ void QOpenGLWidgetPrivate::initialize()
// texture usable by the underlying window's backingstore.
QWidget *tlw = q->window();
QOpenGLContext *shareContext = get(tlw)->shareContext();
- if (Q_UNLIKELY(!shareContext)) {
- qWarning("QOpenGLWidget: Cannot be used without a context shared with the toplevel.");
- return;
- }
+ // If shareContext is null, showing content on-screen will not work.
+ // However, offscreen rendering and grabFramebuffer() will stay fully functional.
// Do not include the sample count. Requesting a multisampled context is not necessary
// since we render into an FBO, never to an actual surface. What's more, attempting to
@@ -768,25 +802,31 @@ void QOpenGLWidgetPrivate::initialize()
requestedFormat.setSamples(0);
QScopedPointer<QOpenGLContext> ctx(new QOpenGLContext);
- ctx->setShareContext(shareContext);
ctx->setFormat(requestedFormat);
- ctx->setScreen(shareContext->screen());
+ if (shareContext) {
+ ctx->setShareContext(shareContext);
+ ctx->setScreen(shareContext->screen());
+ }
if (Q_UNLIKELY(!ctx->create())) {
qWarning("QOpenGLWidget: Failed to create context");
return;
}
- // Propagate settings that make sense only for the tlw.
- QSurfaceFormat tlwFormat = tlw->windowHandle()->format();
- if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
- // Most platforms will pick up the changed swap interval on the next
- // makeCurrent or swapBuffers.
- tlwFormat.setSwapInterval(requestedFormat.swapInterval());
- tlw->windowHandle()->setFormat(tlwFormat);
- }
- if (requestedFormat.swapBehavior() != tlwFormat.swapBehavior()) {
- tlwFormat.setSwapBehavior(requestedFormat.swapBehavior());
- tlw->windowHandle()->setFormat(tlwFormat);
+ // Propagate settings that make sense only for the tlw. Note that this only
+ // makes sense for properties that get picked up even after the native
+ // window is created.
+ if (tlw->windowHandle()) {
+ QSurfaceFormat tlwFormat = tlw->windowHandle()->format();
+ if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
+ // Most platforms will pick up the changed swap interval on the next
+ // makeCurrent or swapBuffers.
+ tlwFormat.setSwapInterval(requestedFormat.swapInterval());
+ tlw->windowHandle()->setFormat(tlwFormat);
+ }
+ if (requestedFormat.swapBehavior() != tlwFormat.swapBehavior()) {
+ tlwFormat.setSwapBehavior(requestedFormat.swapBehavior());
+ tlw->windowHandle()->setFormat(tlwFormat);
+ }
}
// The top-level window's surface is not good enough since it causes way too
@@ -880,9 +920,14 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_
QImage QOpenGLWidgetPrivate::grabFramebuffer()
{
Q_Q(QOpenGLWidget);
+
+ initialize();
if (!initialized)
return QImage();
+ if (!fbo) // could be completely offscreen, without ever getting a resize event
+ recreateFbo();
+
if (!inPaintGL)
render();
@@ -1000,7 +1045,6 @@ QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const
*/
void QOpenGLWidget::setFormat(const QSurfaceFormat &format)
{
- Q_UNUSED(format);
Q_D(QOpenGLWidget);
if (Q_UNLIKELY(d->initialized)) {
qWarning("QOpenGLWidget: Already initialized, setting the format has no effect");
@@ -1033,6 +1077,47 @@ QSurfaceFormat QOpenGLWidget::format() const
}
/*!
+ Sets a custom internal texture format of \a texFormat.
+
+ When working with sRGB framebuffers, it will be necessary to specify a
+ format like \c{GL_SRGB8_ALPHA8}. This can be achieved by calling this
+ function.
+
+ \note This function has no effect if called after the widget has already
+ been shown and thus it performed initialization.
+
+ \note This function will typically have to be used in combination with a
+ QSurfaceFormat::setDefaultFormat() call that sets the color space to
+ QSurfaceFormat::sRGBColorSpace.
+
+ \since 5.10
+ */
+void QOpenGLWidget::setTextureFormat(GLenum texFormat)
+{
+ Q_D(QOpenGLWidget);
+ if (Q_UNLIKELY(d->initialized)) {
+ qWarning("QOpenGLWidget: Already initialized, setting the internal texture format has no effect");
+ return;
+ }
+
+ d->textureFormat = texFormat;
+}
+
+/*!
+ \return the active internal texture format if the widget has already
+ initialized, the requested format if one was set but the widget has not yet
+ been made visible, or 0 if setTextureFormat() was not called and the widget
+ has not yet been made visible.
+
+ \since 5.10
+ */
+GLenum QOpenGLWidget::textureFormat() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->textureFormat;
+}
+
+/*!
\return \e true if the widget and OpenGL resources, like the context, have
been successfully initialized. Note that the return value is always false
until the widget is shown.
@@ -1293,7 +1378,7 @@ int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const
if (window)
return int(window->devicePixelRatio() * devicePixelRatioFScale());
else
- return 1.0;
+ return int(devicePixelRatioFScale());
default:
qWarning("QOpenGLWidget::metric(): unknown metric %d", metric);
return 0;
@@ -1346,7 +1431,14 @@ bool QOpenGLWidget::event(QEvent *e)
break;
// FALLTHROUGH
case QEvent::Show: // reparenting may not lead to a resize so reinitalize on Show too
- if (!d->initialized && !size().isEmpty() && window() && window()->windowHandle()) {
+ if (d->initialized && window()->windowHandle()
+ && d->context->shareContext() != QWidgetPrivate::get(window())->shareContext())
+ {
+ // Special case: did grabFramebuffer() for a hidden widget that then became visible.
+ // Recreate all resources since the context now needs to share with the TLW's.
+ d->reset();
+ }
+ if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
d->initialize();
if (d->initialized)
d->recreateFbo();
diff --git a/src/widgets/kernel/qopenglwidget.h b/src/widgets/kernel/qopenglwidget.h
index b60d79bedb..c0a6e41522 100644
--- a/src/widgets/kernel/qopenglwidget.h
+++ b/src/widgets/kernel/qopenglwidget.h
@@ -72,6 +72,9 @@ public:
void setFormat(const QSurfaceFormat &format);
QSurfaceFormat format() const;
+ GLenum textureFormat() const;
+ void setTextureFormat(GLenum texFormat);
+
bool isValid() const;
void makeCurrent();
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index c2610131f3..80dc65e2d2 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -44,6 +44,7 @@
#include <qapplication.h>
#include <qdesktopwidget.h>
+#include <private/qdesktopwidget_p.h>
#include <qevent.h>
#include <qpointer.h>
#include <qstyle.h>
@@ -366,10 +367,10 @@ bool QTipLabel::eventFilter(QObject *o, QEvent *e)
int QTipLabel::getTipScreen(const QPoint &pos, QWidget *w)
{
- if (QApplication::desktop()->isVirtualDesktop())
- return QApplication::desktop()->screenNumber(pos);
+ if (QDesktopWidgetPrivate::isVirtualDesktop())
+ return QDesktopWidgetPrivate::screenNumber(pos);
else
- return QApplication::desktop()->screenNumber(w);
+ return QDesktopWidgetPrivate::screenNumber(w);
}
void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
@@ -399,11 +400,11 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
QRect screen;
if(qt_mac_app_fullscreen)
- screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w));
+ screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w));
else
- screen = QApplication::desktop()->availableGeometry(getTipScreen(pos, w));
+ screen = QDesktopWidgetPrivate::availableGeometry(getTipScreen(pos, w));
#else
- QRect screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w));
+ QRect screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w));
#endif
QPoint p = pos;
diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp
index e2cfebb8a1..91d2b503e0 100644
--- a/src/widgets/kernel/qwhatsthis.cpp
+++ b/src/widgets/kernel/qwhatsthis.cpp
@@ -42,6 +42,7 @@
#include "qapplication.h"
#include <private/qguiapplication_p.h>
#include "qdesktopwidget.h"
+#include <private/qdesktopwidget_p.h>
#include "qevent.h"
#include "qpixmap.h"
#include "qscreen.h"
@@ -209,7 +210,7 @@ QWhatsThat::QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor
}
else
{
- int sw = QApplication::desktop()->width() / 3;
+ int sw = QDesktopWidgetPrivate::width() / 3;
if (sw < 200)
sw = 200;
else if (sw > 300)
@@ -582,14 +583,14 @@ void QWhatsThisPrivate::say(QWidget * widget, const QString &text, int x, int y)
// okay, now to find a suitable location
int scr = (widget ?
- QApplication::desktop()->screenNumber(widget) :
+ QDesktopWidgetPrivate::screenNumber(widget) :
#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ && !defined(QT_NO_CURSOR)
QCursor::x11Screen()
#else
- QApplication::desktop()->screenNumber(QPoint(x,y))
+ QDesktopWidgetPrivate::screenNumber(QPoint(x,y))
#endif
);
- QRect screen = QApplication::desktop()->screenGeometry(scr);
+ QRect screen = QDesktopWidgetPrivate::screenGeometry(scr);
int w = whatsThat->width();
int h = whatsThat->height();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index de734b6f51..2ee9d307c9 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -69,7 +69,6 @@
# include <private/qmainwindowlayout_p.h>
#endif
#include <qpa/qplatformwindow.h>
-#include <qpa/qplatformbackingstore.h>
#include "private/qwidgetwindow_p.h"
#include "qpainter.h"
#include "qtooltip.h"
@@ -1120,9 +1119,12 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
}
if (customize)
; // don't modify window flags if the user explicitly set them.
- else if (type == Qt::Dialog || type == Qt::Sheet)
- flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;
- else if (type == Qt::Tool)
+ else if (type == Qt::Dialog || type == Qt::Sheet) {
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+ // ### fixme: Qt 6: Never set Qt::WindowContextHelpButtonHint flag automatically
+ if (!QApplicationPrivate::testAttribute(Qt::AA_DisableWindowContextHelpButton))
+ flags |= Qt::WindowContextHelpButtonHint;
+ } else if (type == Qt::Tool)
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
else
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint |
@@ -1428,7 +1430,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
return; // we only care about real toplevels
- QWindow *win = topData()->window;
+ QWidgetWindow *win = topData()->window;
// topData() ensures the extra is created but does not ensure 'window' is non-null
// in case the extra was already valid.
if (!win) {
@@ -1445,7 +1447,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (q->testAttribute(Qt::WA_ShowWithoutActivating))
win->setProperty("_q_showWithoutActivating", QVariant(true));
if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
- win->setProperty("_q_macAlwaysShowToolWindow", QVariant::fromValue(QVariant(true)));
+ win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
win->setFlags(data.window_flags);
fixPosIncludesFrame();
@@ -1459,7 +1461,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
topData()->initialScreenIndex = -1;
if (screenNumber < 0) {
screenNumber = q->windowType() != Qt::Desktop
- ? QApplication::desktop()->screenNumber(q) : 0;
+ ? QDesktopWidgetPrivate::screenNumber(q) : 0;
}
win->setScreen(QGuiApplication::screens().value(screenNumber, Q_NULLPTR));
}
@@ -1529,7 +1531,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
q->setAttribute(Qt::WA_OutsideWSRange, true);
} else if (q->isVisible()) {
// If widget is already shown, set window visible, too
- win->setVisible(true);
+ win->setNativeWindowVisibility(true);
}
}
@@ -1876,39 +1878,15 @@ static void deleteBackingStore(QWidgetPrivate *d)
{
QTLWExtra *topData = d->topData();
- // The context must be current when destroying the backing store as it may attempt to
- // release resources like textures and shader programs. The window may not be suitable
- // anymore as there will often not be a platform window underneath at this stage. Fall
- // back to a QOffscreenSurface in this case.
- QScopedPointer<QOffscreenSurface> tempSurface;
-#ifndef QT_NO_OPENGL
- if (d->textureChildSeen && topData->shareContext) {
- if (topData->window->handle()) {
- topData->shareContext->makeCurrent(topData->window);
- } else {
- tempSurface.reset(new QOffscreenSurface);
- tempSurface->setFormat(topData->shareContext->format());
- tempSurface->create();
- topData->shareContext->makeCurrent(tempSurface.data());
- }
- }
-#endif
-
delete topData->backingStore;
topData->backingStore = 0;
-
-#ifndef QT_NO_OPENGL
- if (d->textureChildSeen && topData->shareContext)
- topData->shareContext->doneCurrent();
-#endif
}
void QWidgetPrivate::deleteTLSysExtra()
{
if (extra && extra->topextra) {
//the qplatformbackingstore may hold a reference to the window, so the backingstore
- //needs to be deleted first. If the backingstore holds GL resources, we need to
- // make the context current here. This is taken care of by deleteBackingStore().
+ //needs to be deleted first.
extra->topextra->backingStoreTracker.destroy();
deleteBackingStore(this);
@@ -2115,14 +2093,15 @@ QRegion QWidgetPrivate::clipRegion() const
return r;
}
-void QWidgetPrivate::setSystemClip(QPaintDevice *paintDevice, const QRegion &region)
+void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
{
// Transform the system clip region from device-independent pixels to device pixels
- QPaintEngine *paintEngine = paintDevice->paintEngine();
QTransform scaleTransform;
- const qreal devicePixelRatio = paintDevice->devicePixelRatioF();
scaleTransform.scale(devicePixelRatio, devicePixelRatio);
- paintEngine->d_func()->systemClip = scaleTransform.map(region);
+
+ paintEngine->d_func()->baseSystemClip = region;
+ paintEngine->d_func()->setSystemTransform(scaleTransform);
+
}
#if QT_CONFIG(graphicseffect)
@@ -2651,11 +2630,7 @@ WId QWidget::effectiveWinId() const
QWindow *QWidget::windowHandle() const
{
Q_D(const QWidget);
- QTLWExtra *extra = d->maybeTopData();
- if (extra)
- return extra->window;
-
- return 0;
+ return d->windowHandle();
}
#ifndef QT_NO_STYLE_STYLESHEET
@@ -3050,17 +3025,6 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate)
QApplication::sendEvent(this, &e);
}
-Qt::WindowState effectiveState(Qt::WindowStates state)
-{
- if (state & Qt::WindowMinimized)
- return Qt::WindowMinimized;
- else if (state & Qt::WindowFullScreen)
- return Qt::WindowFullScreen;
- else if (state & Qt::WindowMaximized)
- return Qt::WindowMaximized;
- return Qt::WindowNoState;
-}
-
/*!
\fn void QWidget::setWindowState(Qt::WindowStates windowState)
@@ -3102,19 +3066,17 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
data->window_state = newstate;
data->in_set_window_state = 1;
- Qt::WindowState newEffectiveState = effectiveState(newstate);
- Qt::WindowState oldEffectiveState = effectiveState(oldstate);
- if (isWindow() && newEffectiveState != oldEffectiveState) {
+ if (isWindow()) {
// Ensure the initial size is valid, since we store it as normalGeometry below.
if (!testAttribute(Qt::WA_Resized) && !isVisible())
adjustSize();
d->createTLExtra();
- if (oldEffectiveState == Qt::WindowNoState)
+ if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
d->topData()->normalGeometry = geometry();
Q_ASSERT(windowHandle());
- windowHandle()->setWindowState(newEffectiveState);
+ windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
}
data->in_set_window_state = 0;
@@ -4535,7 +4497,7 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
The default depends on the system environment. QApplication maintains a
system/theme palette which serves as a default for all widgets. There may
also be special palette defaults for certain types of widgets (e.g., on
- Windows XP and Vista, all classes that derive from QMenuBar have a special
+ Windows Vista, all classes that derive from QMenuBar have a special
default palette). You can also define default palettes for widgets
yourself by passing a custom palette and the name of a widget to
QApplication::setPalette(). Finally, the style always has the option of
@@ -4553,8 +4515,8 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
The current style, which is used to render the content of all standard Qt
widgets, is free to choose colors and brushes from the widget palette, or
in some cases, to ignore the palette (partially, or completely). In
- particular, certain styles like GTK style, Mac style, Windows XP, and
- Vista style, depend on third party APIs to render the content of widgets,
+ particular, certain styles like GTK style, Mac style, and Windows Vista
+ style, depend on third party APIs to render the content of widgets,
and these styles typically do not follow the palette. Because of this,
assigning roles to a widget's palette is not guaranteed to change the
appearance of the widget. Instead, you may choose to apply a \l
@@ -4716,7 +4678,7 @@ void QWidgetPrivate::updateSystemBackground()
The current style, which is used to render the content of all standard Qt
widgets, is free to choose to use the widget font, or in some cases, to
ignore it (partially, or completely). In particular, certain styles like
- GTK style, Mac style, Windows XP, and Vista style, apply special
+ GTK style, Mac style, and Windows Vista style, apply special
modifications to the widget font to match the platform's native look and
feel. Because of this, assigning properties to a widget's font is not
guaranteed to change the appearance of the widget. Instead, you may choose
@@ -5218,6 +5180,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
// Save current system clip, viewport and transform,
const QTransform oldTransform = enginePriv->systemTransform;
const QRegion oldSystemClip = enginePriv->systemClip;
+ const QRegion oldBaseClip = enginePriv->baseSystemClip;
const QRegion oldSystemViewport = enginePriv->systemViewport;
// This ensures that all painting triggered by render() is clipped to the current engine clip.
@@ -5231,9 +5194,8 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
d->render(target, targetOffset, toBePainted, renderFlags);
// Restore system clip, viewport and transform.
- enginePriv->setSystemViewport(oldSystemViewport);
- enginePriv->setSystemTransform(oldTransform);
- enginePriv->systemClip = oldSystemClip;
+ enginePriv->baseSystemClip = oldBaseClip;
+ enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
enginePriv->systemStateChanged();
// Restore shared painter.
@@ -5525,12 +5487,12 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
sourced->context = &context;
if (!sharedPainter) {
- setSystemClip(pdev, rgn.translated(offset));
+ setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset));
QPainter p(pdev);
p.translate(offset);
context.painter = &p;
graphicsEffect->draw(&p);
- setSystemClip(pdev, QRegion());
+ setSystemClip(pdev->paintEngine(), 1, QRegion());
} else {
context.painter = sharedPainter;
if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
@@ -5539,7 +5501,9 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
sharedPainter->save();
sharedPainter->translate(offset);
+ setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatioF(), rgn.translated(offset));
graphicsEffect->draw(sharedPainter);
+ setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
sharedPainter->restore();
}
sourced->context = 0;
@@ -5591,7 +5555,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
#endif
if (sharedPainter)
- setSystemClip(pdev, toBePainted);
+ setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted);
else
paintEngine->d_func()->systemRect = q->data->crect;
@@ -5609,7 +5573,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
if (!sharedPainter)
- setSystemClip(pdev, toBePainted.translated(offset));
+ setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted.translated(offset));
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
#ifndef QT_NO_OPENGL
@@ -5679,7 +5643,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
else
paintEngine->d_func()->currentClipDevice = 0;
- setSystemClip(pdev, QRegion());
+ setSystemClip(pdev->paintEngine(), 1, QRegion());
}
q->setAttribute(Qt::WA_WState_InPaintEvent, false);
if (Q_UNLIKELY(q->paintingActive()))
@@ -6537,9 +6501,9 @@ void QWidget::setFocus(Qt::FocusReason reason)
if (!isEnabled())
return;
- QWidget *f = this;
- while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
- f = f->d_func()->extra->focus_proxy;
+ QWidget *f = d_func()->deepestFocusProxy();
+ if (!f)
+ f = this;
if (QApplication::focusWidget() == f
#if 0 // Used to be included in Qt4 for Q_WS_WIN
@@ -6636,6 +6600,27 @@ void QWidget::setFocus(Qt::FocusReason reason)
}
}
+
+/*!\internal
+ * A focus proxy can have its own focus proxy, which can have its own
+ * proxy, and so on. This helper function returns the widget that sits
+ * at the bottom of the proxy chain, and therefore the one that should
+ * normally get focus if this widget receives a focus request.
+ */
+QWidget *QWidgetPrivate::deepestFocusProxy() const
+{
+ Q_Q(const QWidget);
+
+ QWidget *focusProxy = q->focusProxy();
+ if (!focusProxy)
+ return nullptr;
+
+ while (QWidget *nextFocusProxy = focusProxy->focusProxy())
+ focusProxy = nextFocusProxy;
+
+ return focusProxy;
+}
+
void QWidgetPrivate::setFocus_sys()
{
Q_Q(QWidget);
@@ -6938,6 +6923,9 @@ bool QWidget::isActiveWindow() const
/*!
Puts the \a second widget after the \a first widget in the focus order.
+ It effectively removes the \a second widget from its focus chain and
+ inserts it after the \a first widget.
+
Note that since the tab order of the \a second widget is changed, you
should order a chain like this:
@@ -6950,11 +6938,19 @@ bool QWidget::isActiveWindow() const
If \a first or \a second has a focus proxy, setTabOrder()
correctly substitutes the proxy.
+ \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
+ a compound widget. When setting a tab order between one or two compound widgets, the
+ local tab order inside each will be preserved. This means that if both widgets are
+ compound widgets, the resulting tab order will be from the last child inside
+ \a first, to the first child inside \a second.
+
\sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
*/
void QWidget::setTabOrder(QWidget* first, QWidget *second)
{
- if (!first || !second || first->focusPolicy() == Qt::NoFocus || second->focusPolicy() == Qt::NoFocus)
+ if (!first || !second || first == second
+ || first->focusPolicy() == Qt::NoFocus
+ || second->focusPolicy() == Qt::NoFocus)
return;
if (Q_UNLIKELY(first->window() != second->window())) {
@@ -6962,54 +6958,56 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
return;
}
- QWidget *fp = first->focusProxy();
- if (fp) {
- // If first is redirected, set first to the last child of first
- // that can take keyboard focus so that second is inserted after
- // that last child, and the focus order within first is (more
- // likely to be) preserved.
- QList<QWidget *> l = first->findChildren<QWidget *>();
- for (int i = l.size()-1; i >= 0; --i) {
- QWidget * next = l.at(i);
- if (next->window() == fp->window()) {
- fp = next;
- if (fp->focusPolicy() != Qt::NoFocus)
- break;
- }
- }
- first = fp;
- }
+ auto determineLastFocusChild = [](QWidget *target, QWidget *&lastFocusChild)
+ {
+ // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
+ // determines the last focus child for a widget, taking proxies and compound widgets into account.
+ // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
+ // 'lastFocusChild' will be set to the target itself.
+ lastFocusChild = target;
+
+ QWidget *focusProxy = target->d_func()->deepestFocusProxy();
+ if (!focusProxy || !target->isAncestorOf(focusProxy))
+ return;
- if (fp == second)
- return;
+ lastFocusChild = focusProxy;
- if (QWidget *sp = second->focusProxy())
- second = sp;
+ for (QWidget *focusNext = lastFocusChild->d_func()->focus_next;
+ focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
+ focusNext = focusNext->d_func()->focus_next) {
+ if (focusNext->focusPolicy() != Qt::NoFocus)
+ lastFocusChild = focusNext;
+ }
+ };
-// QWidget *fp = first->d_func()->focus_prev;
- QWidget *fn = first->d_func()->focus_next;
+ QWidget *lastFocusChildOfFirst, *lastFocusChildOfSecond;
+ determineLastFocusChild(first, lastFocusChildOfFirst);
+ determineLastFocusChild(second, lastFocusChildOfSecond);
- if (fn == second || first == second)
+ // If the tab order is already correct, exit early
+ if (lastFocusChildOfFirst->d_func()->focus_next == second)
return;
- QWidget *sp = second->d_func()->focus_prev;
- QWidget *sn = second->d_func()->focus_next;
-
- fn->d_func()->focus_prev = second;
- first->d_func()->focus_next = second;
+ // Note that we need to handle two different sections in the tab chain; The section
+ // that 'first' belongs to (firstSection), where we are about to insert 'second', and
+ // the section that 'second' used be a part of (secondSection). When we pull 'second'
+ // out of the second section and insert it into the first, we also need to ensure
+ // that we leave the second section in a connected state.
+ QWidget *firstChainOldSecond = lastFocusChildOfFirst->d_func()->focus_next;
+ QWidget *secondChainNewFirst = second->d_func()->focus_prev;
+ QWidget *secondChainNewSecond = lastFocusChildOfSecond->d_func()->focus_next;
- second->d_func()->focus_next = fn;
- second->d_func()->focus_prev = first;
+ // Insert 'second' after 'first'
+ lastFocusChildOfFirst->d_func()->focus_next = second;
+ second->d_func()->focus_prev = lastFocusChildOfFirst;
- sp->d_func()->focus_next = sn;
- sn->d_func()->focus_prev = sp;
+ // The widget that used to be 'second' in the first section, should now become 'third'
+ lastFocusChildOfSecond->d_func()->focus_next = firstChainOldSecond;
+ firstChainOldSecond->d_func()->focus_prev = lastFocusChildOfSecond;
-
- Q_ASSERT(first->d_func()->focus_next->d_func()->focus_prev == first);
- Q_ASSERT(first->d_func()->focus_prev->d_func()->focus_next == first);
-
- Q_ASSERT(second->d_func()->focus_next->d_func()->focus_prev == second);
- Q_ASSERT(second->d_func()->focus_prev->d_func()->focus_next == second);
+ // Repair the second section after we pulled 'second' out of it
+ secondChainNewFirst->d_func()->focus_next = secondChainNewSecond;
+ secondChainNewSecond->d_func()->focus_prev = secondChainNewFirst;
}
/*!\internal
@@ -7181,7 +7179,7 @@ void QWidgetPrivate::fixPosIncludesFrame()
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
te->posIncludesFrame = 0;
} else {
- if (q->windowHandle()) {
+ if (q->windowHandle() && q->windowHandle()->handle()) {
updateFrameStrut();
if (!q->data->fstrut_dirty) {
data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
@@ -7383,7 +7381,7 @@ QByteArray QWidget::saveGeometry() const
// - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
quint16 majorVersion = 2;
quint16 minorVersion = 0;
- const int screenNumber = QApplication::desktop()->screenNumber(this);
+ const int screenNumber = QDesktopWidgetPrivate::screenNumber(this);
stream << magicNumber
<< majorVersion
<< minorVersion
@@ -7397,7 +7395,7 @@ QByteArray QWidget::saveGeometry() const
<< qint32(screenNumber)
<< quint8(windowState() & Qt::WindowMaximized)
<< quint8(windowState() & Qt::WindowFullScreen)
- << qint32(QApplication::desktop()->screenGeometry(screenNumber).width()); // 1.1 onwards
+ << qint32(QDesktopWidgetPrivate::screenGeometry(screenNumber).width()); // 1.1 onwards
return array;
}
@@ -7463,10 +7461,9 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
if (majorVersion > 1)
stream >> restoredScreenWidth;
- const QDesktopWidget * const desktop = QApplication::desktop();
- if (restoredScreenNumber >= desktop->numScreens())
- restoredScreenNumber = desktop->primaryScreen();
- const qreal screenWidthF = qreal(desktop->screenGeometry(restoredScreenNumber).width());
+ if (restoredScreenNumber >= QDesktopWidgetPrivate::numScreens())
+ restoredScreenNumber = QDesktopWidgetPrivate::primaryScreen();
+ const qreal screenWidthF = qreal(QDesktopWidgetPrivate::screenGeometry(restoredScreenNumber).width());
// Sanity check bailing out when large variations of screen sizes occur due to
// high DPI scaling or different levels of DPI awareness.
if (restoredScreenWidth) {
@@ -7493,7 +7490,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
.expandedTo(d_func()->adjustedSize()));
}
- const QRect availableGeometry = desktop->availableGeometry(restoredScreenNumber);
+ const QRect availableGeometry = QDesktopWidgetPrivate::availableGeometry(restoredScreenNumber);
// Modify the restored geometry if we are about to restore to coordinates
// that would make the window "lost". This happens if:
@@ -7534,7 +7531,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
// 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)) {
+ if (restoredScreenNumber != QDesktopWidgetPrivate::screenNumber(this)) {
setWindowState(Qt::WindowNoState);
setGeometry(restoredNormalGeometry);
}
@@ -7987,7 +7984,7 @@ void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
- QWindow *window = q->windowHandle();
+ QWidgetWindow *window = windowHandle();
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
invalidateBuffer(q->rect());
@@ -8034,7 +8031,7 @@ void QWidgetPrivate::show_sys()
qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
#endif
invalidateBuffer(q->rect());
- window->setVisible(true);
+ window->setNativeWindowVisibility(true);
// Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
if (window->isTopLevel()) {
const QPoint crectTopLeft = q->data->crect.topLeft();
@@ -8126,7 +8123,7 @@ void QWidgetPrivate::hide_sys()
{
Q_Q(QWidget);
- QWindow *window = q->windowHandle();
+ QWidgetWindow *window = windowHandle();
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
q->setAttribute(Qt::WA_Mapped, false);
@@ -8156,7 +8153,7 @@ void QWidgetPrivate::hide_sys()
}
if (window)
- window->setVisible(false);
+ window->setNativeWindowVisibility(false);
}
/*!
@@ -8598,9 +8595,9 @@ QSize QWidgetPrivate::adjustedSize() const
if (exp & Qt::Vertical)
s.setHeight(qMax(s.height(), 100));
#if 0 // Used to be included in Qt4 for Q_WS_X11
- QRect screen = QApplication::desktop()->screenGeometry(q->x11Info().screen());
+ QRect screen = QDesktopWidgetPrivate::screenGeometry(q->x11Info().screen());
#else // all others
- QRect screen = QApplication::desktop()->screenGeometry(q->pos());
+ QRect screen = QDesktopWidgetPrivate::screenGeometry(q->pos());
#endif
s.setWidth(qMin(s.width(), screen.width()*2/3));
s.setHeight(qMin(s.height(), screen.height()*2/3));
@@ -10033,6 +10030,7 @@ void QWidget::hideEvent(QHideEvent *)
\table
\header \li Platform \li Event Type Identifier \li Message Type \li Result Type
\row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
+ \row \li macOS \li "NSEvent" \li NSEvent * \li
\endtable
*/
@@ -10743,7 +10741,7 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
f |= Qt::Window;
if (targetScreen == -1) {
if (parent)
- targetScreen = QApplication::desktop()->screenNumber(q->parentWidget()->window());
+ targetScreen = QDesktopWidgetPrivate::screenNumber(q->parentWidget()->window());
}
}
@@ -12264,10 +12262,9 @@ QOpenGLContext *QWidgetPrivate::shareContext() const
#ifdef QT_NO_OPENGL
return 0;
#else
- if (Q_UNLIKELY(!extra || !extra->topextra || !extra->topextra->window)) {
- qWarning("Asking for share context for widget that does not have a window handle");
+ if (Q_UNLIKELY(!extra || !extra->topextra || !extra->topextra->window))
return 0;
- }
+
QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this);
if (!extra->topextra->shareContext) {
QOpenGLContext *ctx = new QOpenGLContext;
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index a24d13e0e1..4a86f87c71 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -73,19 +73,20 @@
#include "QtWidgets/qgraphicsview.h"
#endif
#include <private/qgesture_p.h>
+#include <qpa/qplatformbackingstore.h>
QT_BEGIN_NAMESPACE
// Extra QWidget data
// - to minimize memory usage for members that are seldom used.
// - top-level widgets have extra extra data to reduce cost further
+class QWidgetWindow;
class QPaintEngine;
class QPixmap;
class QWidgetBackingStore;
class QGraphicsProxyWidget;
class QWidgetItemV2;
class QOpenGLContext;
-class QPlatformTextureList;
class QStyle;
@@ -164,7 +165,7 @@ struct QTLWExtra {
QWidgetBackingStoreTracker backingStoreTracker;
QBackingStore *backingStore;
QPainter *sharedPainter;
- QWindow *window;
+ QWidgetWindow *window;
QOpenGLContext *shareContext;
// Implicit pointers (shared_null).
@@ -342,6 +343,7 @@ public:
QPainter *sharedPainter() const;
void setSharedPainter(QPainter *painter);
QWidgetBackingStore *maybeBackingStore() const;
+ QWidgetWindow *windowHandle() const;
void init(QWidget *desktopWidget, Qt::WindowFlags f);
void create_sys(WId window, bool initializeWindow, bool destroyOldWindow);
void createRecursively();
@@ -367,6 +369,7 @@ public:
void lower_sys();
void stackUnder_sys(QWidget *);
+ QWidget *deepestFocusProxy() const;
void setFocus_sys();
void updateFocusChild();
@@ -413,7 +416,7 @@ public:
QRect clipRect() const;
QRegion clipRegion() const;
- void setSystemClip(QPaintDevice *paintDevice, const QRegion &region);
+ void setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region);
void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
bool alsoNonOpaque = false) const;
@@ -634,6 +637,12 @@ public:
#ifndef QT_NO_OPENGL
virtual GLuint textureId() const { return 0; }
+ virtual QPlatformTextureList::Flags textureListFlags() {
+ Q_Q(QWidget);
+ return q->testAttribute(Qt::WA_AlwaysStackOnTop)
+ ? QPlatformTextureList::StacksOnTop
+ : QPlatformTextureList::Flags(0);
+ }
virtual QImage grabFramebuffer() { return QImage(); }
virtual void beginBackingStorePainting() { }
virtual void endBackingStorePainting() { }
@@ -985,6 +994,13 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const
return x ? x->backingStoreTracker.data() : 0;
}
+inline QWidgetWindow *QWidgetPrivate::windowHandle() const
+{
+ if (QTLWExtra *x = maybeTopData())
+ return x->window;
+ return nullptr;
+}
+
QT_END_NAMESPACE
#endif // QWIDGET_P_H
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 57564ce477..52080fe05f 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -77,11 +77,10 @@ Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList)
/**
* Flushes the contents of the \a backingStore into the screen area of \a widget.
- * \a tlwOffset is the position of the top level widget relative to the window surface.
* \a region is the region to be updated in \a widget coordinates.
*/
void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
- QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures,
+ QWidget *tlw, QPlatformTextureList *widgetTextures,
QWidgetBackingStore *widgetBackingStore)
{
#ifdef QT_NO_OPENGL
@@ -112,7 +111,7 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
}
}
- QPoint offset = tlwOffset;
+ QPoint offset;
if (widget != tlw)
offset += widget->mapTo(tlw, QPoint());
@@ -144,10 +143,8 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
// WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends
// to rely on translucency, in order to decide if it should clear to transparent or opaque.
const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground);
- // Use the tlw's context, not widget's. The difference is important with native child
- // widgets where tlw != widget.
- backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, widgetTextures,
- tlw->d_func()->shareContext(), translucentBackground);
+ backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset,
+ widgetTextures, translucentBackground);
widget->window()->d_func()->sendComposeStatus(widget->window(), true);
} else
#endif
@@ -288,8 +285,7 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
if (!tlwExtra)
return;
- const QPoint offset = widget->mapTo(tlw, QPoint());
- qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, offset, 0, tlw->d_func()->maybeBackingStore());
+ qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, 0, tlw->d_func()->maybeBackingStore());
}
#endif // QT_NO_PAINT_DEBUG
@@ -299,7 +295,7 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
*/
bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget)
{
- const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft()));
+ const QPoint pos(widget->mapTo(tlw, rect.topLeft()));
const QRect tlwRect(QRect(pos, rect.size()));
if (dirty.intersects(tlwRect))
return false; // We don't want to scroll junk.
@@ -949,9 +945,7 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo
{
QWidgetPrivate *wd = QWidgetPrivate::get(widget);
if (wd->renderToTexture) {
- QPlatformTextureList::Flags flags = 0;
- if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
- flags |= QPlatformTextureList::StacksOnTop;
+ QPlatformTextureList::Flags flags = wd->textureListFlags();
const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
}
@@ -1123,7 +1117,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
// Nothing to repaint.
if (!isDirty() && store->size().isValid()) {
QPlatformTextureList *tl = widgetTexturesFor(tlw, exposedWidget);
- qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tlwOffset, tl, this);
+ qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tl, this);
return;
}
@@ -1369,7 +1363,7 @@ void QWidgetBackingStore::doSync()
QRegion toBePainted(wd->dirty);
resetWidget(w);
- QPoint offset(tlwOffset);
+ QPoint offset;
if (w != tlw)
offset += w->mapTo(tlw, QPoint());
wd->drawWidget(store->paintDevice(), toBePainted, offset, flags, 0, this);
@@ -1378,7 +1372,7 @@ void QWidgetBackingStore::doSync()
// Paint the rest with composition.
if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
- tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);
+ tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, 0, this);
}
endPaint(toClean, store, &beginPaintInfo);
@@ -1397,7 +1391,7 @@ void QWidgetBackingStore::flush(QWidget *widget)
// Flush the region in dirtyOnScreen.
if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this);
+ qt_flush(target, dirtyOnScreen, store, tlw, widgetTexturesFor(tlw, tlw), this);
dirtyOnScreen = QRegion();
flushed = true;
}
@@ -1409,7 +1403,7 @@ void QWidgetBackingStore::flush(QWidget *widget)
QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw);
if (tl) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, QRegion(), store, tlw, tlwOffset, tl, this);
+ qt_flush(target, QRegion(), store, tlw, tl, this);
}
}
#endif
@@ -1423,7 +1417,7 @@ void QWidgetBackingStore::flush(QWidget *widget)
QWidgetPrivate *wd = w->d_func();
Q_ASSERT(wd->needsFlush);
QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : 0;
- qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, widgetTexturesForNative, this);
+ qt_flush(w, *wd->needsFlush, store, tlw, widgetTexturesForNative, this);
*wd->needsFlush = QRegion();
}
dirtyOnScreenWidgets->clear();
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index fa51cb71de..53ccda850a 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -111,8 +111,6 @@ public:
void sync();
void flush(QWidget *widget = 0);
- inline QPoint topLevelOffset() const { return tlwOffset; }
-
QBackingStore *backingStore() const { return store; }
inline bool isDirty() const
@@ -138,8 +136,6 @@ private:
QBackingStore *store;
uint updateRequestSent : 1;
- QPoint tlwOffset;
-
QPlatformTextureListWatcher *textureListWatcher;
QElapsedTimer perfTime;
int perfFrames;
@@ -149,7 +145,7 @@ private:
static bool flushPaint(QWidget *widget, const QRegion &rgn);
static void unflushPaint(QWidget *widget, const QRegion &rgn);
static void qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
- QWidget *tlw, const QPoint &tlwOffset,
+ QWidget *tlw,
QPlatformTextureList *widgetTextures,
QWidgetBackingStore *widgetBackingStore);
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index abaebad821..d8d6eab7b1 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();
-QWidget *qt_button_down = 0; // widget got last button-down
+Q_WIDGETS_EXPORT QWidget *qt_button_down = 0; // widget got last button-down
// popup control
QWidget *qt_popup_down = 0; // popup that contains the pressed widget
@@ -69,6 +69,15 @@ class QWidgetWindowPrivate : public QWindowPrivate
{
Q_DECLARE_PUBLIC(QWidgetWindow)
public:
+ void setVisible(bool visible) override
+ {
+ Q_Q(QWidgetWindow);
+ if (QWidget *widget = q->widget())
+ widget->setVisible(visible);
+ else
+ QWindowPrivate::setVisible(visible);
+ }
+
QWindow *eventReceiver() Q_DECL_OVERRIDE {
Q_Q(QWidgetWindow);
QWindow *w = q;
@@ -87,6 +96,9 @@ public:
}
QRectF closestAcceptableGeometry(const QRectF &rect) const Q_DECL_OVERRIDE;
+#if QT_CONFIG(opengl)
+ QOpenGLContext *shareContext() const override;
+#endif
};
QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
@@ -118,6 +130,15 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
return result;
}
+#if QT_CONFIG(opengl)
+QOpenGLContext *QWidgetWindowPrivate::shareContext() const
+{
+ Q_Q(const QWidgetWindow);
+ const QWidgetPrivate *widgetPrivate = QWidgetPrivate::get(q->widget());
+ return widgetPrivate->shareContext();
+}
+#endif // opengl
+
QWidgetWindow::QWidgetWindow(QWidget *widget)
: QWindow(*new QWidgetWindowPrivate(), 0)
, m_widget(widget)
@@ -168,6 +189,15 @@ QObject *QWidgetWindow::focusObject() const
return widget;
}
+void QWidgetWindow::setNativeWindowVisibility(bool visible)
+{
+ Q_D(QWidgetWindow);
+ // Call base class setVisible() implementation to run the QWindow
+ // visibility logic. Don't call QWidgetWindowPrivate::setVisible()
+ // since that will recurse back into QWidget code.
+ d->QWindowPrivate::setVisible(visible);
+}
+
static inline bool shouldBePropagatedToWidget(QEvent *event)
{
switch (event->type()) {
@@ -194,7 +224,7 @@ bool QWidgetWindow::event(QEvent *event)
// generated before WA_DontShowOnScreen was set
if (!shouldBePropagatedToWidget(event))
return true;
- return QCoreApplication::sendEvent(m_widget, event);
+ return QCoreApplication::forwardEvent(m_widget, event);
}
switch (event->type()) {
@@ -226,7 +256,7 @@ bool QWidgetWindow::event(QEvent *event)
if (QApplicationPrivate::focus_widget->testAttribute(Qt::WA_InputMethodEnabled))
QGuiApplication::inputMethod()->commit();
- QGuiApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, event);
+ QGuiApplication::forwardEvent(QApplicationPrivate::focus_widget, event);
}
return true;
@@ -295,7 +325,7 @@ bool QWidgetWindow::event(QEvent *event)
case QEvent::ThemeChange: {
QEvent widgetEvent(QEvent::ThemeChange);
- QGuiApplication::sendSpontaneousEvent(m_widget, &widgetEvent);
+ QCoreApplication::forwardEvent(m_widget, &widgetEvent, event);
}
return true;
@@ -333,7 +363,7 @@ bool QWidgetWindow::event(QEvent *event)
break;
}
- if (shouldBePropagatedToWidget(event) && QCoreApplication::sendEvent(m_widget, event))
+ if (shouldBePropagatedToWidget(event) && QCoreApplication::forwardEvent(m_widget, event))
return true;
return QWindow::event(event);
@@ -442,7 +472,7 @@ void QWidgetWindow::handleFocusInEvent(QFocusEvent *e)
void QWidgetWindow::handleNonClientAreaMouseEvent(QMouseEvent *e)
{
- QApplication::sendSpontaneousEvent(m_widget, e);
+ QApplication::forwardEvent(m_widget, e);
}
void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
@@ -509,12 +539,15 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
}
}
#endif
-
- QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(),
- event->button(), event->buttons(), event->modifiers(), event->source());
- e.setTimestamp(event->timestamp());
- QApplicationPrivate::sendMouseEvent(receiver, &e, receiver, receiver->window(), &qt_button_down, qt_last_mouse_receiver);
- qt_last_mouse_receiver = receiver;
+ if ((event->type() != QEvent::MouseButtonPress)
+ || !(event->flags().testFlag(Qt::MouseEventCreatedDoubleClick))) {
+
+ QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(),
+ event->button(), event->buttons(), event->modifiers(), event->source());
+ e.setTimestamp(event->timestamp());
+ QApplicationPrivate::sendMouseEvent(receiver, &e, receiver, receiver->window(), &qt_button_down, qt_last_mouse_receiver);
+ qt_last_mouse_receiver = receiver;
+ }
} else {
// close disabled popups when a mouse button is pressed or released
switch (event->type()) {
@@ -567,13 +600,13 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
} else if (event->type() == contextMenuTrigger
&& event->button() == Qt::RightButton
&& (openPopupCount == oldOpenPopupCount)) {
- QWidget *popupEvent = activePopupWidget;
+ QWidget *receiver = activePopupWidget;
if (qt_button_down)
- popupEvent = qt_button_down;
+ receiver = qt_button_down;
else if(popupChild)
- popupEvent = popupChild;
+ receiver = popupChild;
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
- QApplication::sendSpontaneousEvent(popupEvent, &e);
+ QApplication::forwardEvent(receiver, &e, event);
}
#else
Q_UNUSED(contextMenuTrigger)
@@ -626,7 +659,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
if (event->type() == contextMenuTrigger && event->button() == Qt::RightButton
&& m_widget->rect().contains(event->pos())) {
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
- QGuiApplication::sendSpontaneousEvent(receiver, &e);
+ QGuiApplication::forwardEvent(receiver, &e, event);
}
#endif
}
@@ -658,7 +691,7 @@ void QWidgetWindow::handleKeyEvent(QKeyEvent *event)
}
if (!receiver)
receiver = focusObject();
- QGuiApplication::sendSpontaneousEvent(receiver, event);
+ QGuiApplication::forwardEvent(receiver, event);
}
bool QWidgetWindow::updateSize()
@@ -730,8 +763,6 @@ void QWidgetWindow::repaintWindow()
QWidgetBackingStore::UpdateNow, QWidgetBackingStore::BufferInvalid);
}
-Qt::WindowState effectiveState(Qt::WindowStates state);
-
// Store normal geometry used for saving application settings.
void QWidgetWindow::updateNormalGeometry()
{
@@ -742,7 +773,7 @@ void QWidgetWindow::updateNormalGeometry()
QRect normalGeometry;
if (const QPlatformWindow *pw = handle())
normalGeometry = QHighDpi::fromNativePixels(pw->normalGeometry(), this);
- if (!normalGeometry.isValid() && effectiveState(m_widget->windowState()) == Qt::WindowNoState)
+ if (!normalGeometry.isValid() && !(m_widget->windowState() & ~Qt::WindowActive))
normalGeometry = m_widget->geometry();
if (normalGeometry.isValid())
tle->normalGeometry = normalGeometry;
@@ -751,7 +782,7 @@ void QWidgetWindow::updateNormalGeometry()
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
if (updatePos())
- QGuiApplication::sendSpontaneousEvent(m_widget, event);
+ QGuiApplication::forwardEvent(m_widget, event);
}
void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
@@ -759,7 +790,7 @@ void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
QSize oldSize = m_widget->data->crect.size();
if (updateSize()) {
- QGuiApplication::sendSpontaneousEvent(m_widget, event);
+ QGuiApplication::forwardEvent(m_widget, event);
if (m_widget->d_func()->paintOnScreen()) {
QRegion updateRegion(geometry());
@@ -805,7 +836,7 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
QPoint mapped = widget->mapFrom(rootWidget, pos);
QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted());
- QGuiApplication::sendSpontaneousEvent(widget, &translated);
+ QGuiApplication::forwardEvent(widget, &translated, event);
}
#endif // QT_CONFIG(wheelevent)
@@ -832,7 +863,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
translated.accept();
translated.setDropAction(event->dropAction());
}
- QGuiApplication::sendSpontaneousEvent(widget, &translated);
+ QGuiApplication::forwardEvent(widget, &translated, event);
if (translated.isAccepted()) {
event->accept();
} else {
@@ -844,7 +875,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
// Target widget changed: Send DragLeave to previous, DragEnter to new if there is any
if (m_dragTarget.data()) {
QDragLeaveEvent le;
- QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &le);
+ QGuiApplication::forwardEvent(m_dragTarget.data(), &le, event);
m_dragTarget = 0;
}
if (!widget) {
@@ -854,7 +885,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
m_dragTarget = widget;
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
- QGuiApplication::sendSpontaneousEvent(widget, &translated);
+ QGuiApplication::forwardEvent(widget, &translated, event);
if (translated.isAccepted()) {
event->accept();
} else {
@@ -866,7 +897,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
{
if (m_dragTarget)
- QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), event);
+ QGuiApplication::forwardEvent(m_dragTarget.data(), event);
m_dragTarget = 0;
}
@@ -879,7 +910,7 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event)
}
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);
+ QGuiApplication::forwardEvent(m_dragTarget.data(), &translated, event);
if (translated.isAccepted())
event->accept();
event->setDropAction(translated.dropAction());
@@ -902,7 +933,7 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
// ... and they haven't been shown by this function yet - show it.
wPriv->showChildren(true);
QShowEvent showEvent;
- QCoreApplication::sendSpontaneousEvent(m_widget, &showEvent);
+ QCoreApplication::forwardEvent(m_widget, &showEvent, event);
wPriv->childrenShownByExpose = true;
}
} else {
@@ -914,7 +945,7 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
// and then, the QPA can send next expose event with null exposed region (not exposed).
wPriv->hideChildren(true);
QHideEvent hideEvent;
- QCoreApplication::sendSpontaneousEvent(m_widget, &hideEvent);
+ QCoreApplication::forwardEvent(m_widget, &hideEvent, event);
wPriv->childrenShownByExpose = false;
}
}
@@ -934,30 +965,18 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
// QWindow does currently not know 'active'.
Qt::WindowStates eventState = event->oldState();
Qt::WindowStates widgetState = m_widget->windowState();
+ Qt::WindowStates windowState = windowStates();
if (widgetState & Qt::WindowActive)
eventState |= Qt::WindowActive;
// Determine the new widget state, remember maximized/full screen
// during minimized.
- switch (windowState()) {
- case Qt::WindowNoState:
- widgetState &= ~(Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen);
- break;
- case Qt::WindowMinimized:
+ if (windowState & Qt::WindowMinimized) {
widgetState |= Qt::WindowMinimized;
- break;
- case Qt::WindowMaximized:
- updateNormalGeometry();
- widgetState |= Qt::WindowMaximized;
- widgetState &= ~(Qt::WindowMinimized | Qt::WindowFullScreen);
- break;
- case Qt::WindowFullScreen:
- updateNormalGeometry();
- widgetState |= Qt::WindowFullScreen;
- widgetState &= ~(Qt::WindowMinimized);
- break;
- case Qt::WindowActive: // Not handled by QWindow
- break;
+ } else {
+ widgetState = windowState | (widgetState & Qt::WindowActive);
+ if (windowState) // Maximized or FullScreen
+ updateNormalGeometry();
}
// Sent event if the state changed (that is, it is not triggered by
@@ -965,7 +984,7 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
if (widgetState != Qt::WindowStates::Int(m_widget->data->window_state)) {
m_widget->data->window_state = uint(widgetState);
QWindowStateChangeEvent widgetEvent(eventState);
- QGuiApplication::sendSpontaneousEvent(m_widget, &widgetEvent);
+ QGuiApplication::forwardEvent(m_widget, &widgetEvent, event);
}
}
@@ -997,7 +1016,7 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
event->pressure(), event->xTilt(), event->yTilt(), event->tangentialPressure(),
event->rotation(), event->z(), event->modifiers(), event->uniqueId(), event->button(), event->buttons());
ev.setTimestamp(event->timestamp());
- QGuiApplication::sendSpontaneousEvent(widget, &ev);
+ QGuiApplication::forwardEvent(widget, &ev, event);
event->setAccepted(ev.isAccepted());
}
@@ -1021,7 +1040,7 @@ void QWidgetWindow::handleGestureEvent(QNativeGestureEvent *e)
if (!receiver)
receiver = m_widget; // last resort
- QApplication::sendSpontaneousEvent(receiver, e);
+ QApplication::forwardEvent(receiver, e);
}
#endif // QT_NO_GESTURES
@@ -1049,7 +1068,7 @@ void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center();
QContextMenuEvent widgetEvent(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
e->modifiers());
- QGuiApplication::sendSpontaneousEvent(fw, &widgetEvent);
+ QGuiApplication::forwardEvent(fw, &widgetEvent, e);
}
}
#endif // QT_NO_CONTEXTMENU
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 50a2cfd57c..be3f808a22 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -63,10 +63,12 @@ QT_BEGIN_NAMESPACE
class QCloseEvent;
class QMoveEvent;
+class QWidgetWindowPrivate;
class QWidgetWindow : public QWindow
{
Q_OBJECT
+ Q_DECLARE_PRIVATE(QWidgetWindow)
public:
QWidgetWindow(QWidget *widget);
~QWidgetWindow();
@@ -77,6 +79,7 @@ public:
#endif
QObject *focusObject() const Q_DECL_OVERRIDE;
+ void setNativeWindowVisibility(bool visible);
protected:
bool event(QEvent *) Q_DECL_OVERRIDE;
diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp
index 56114350d2..d388327687 100644
--- a/src/widgets/kernel/qwindowcontainer.cpp
+++ b/src/widgets/kernel/qwindowcontainer.cpp
@@ -341,6 +341,19 @@ bool QWindowContainer::event(QEvent *e)
e->accept();
return true;
#endif
+
+ case QEvent::Paint:
+ {
+ static bool needsPunch = !QGuiApplicationPrivate::platformIntegration()->hasCapability(
+ QPlatformIntegration::TopStackedNativeChildWindows);
+ if (needsPunch) {
+ QPainter p(this);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(rect(), Qt::transparent);
+ }
+ break;
+ }
+
default:
break;
}
diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri
index 7cef2d14a8..f6877b02db 100644
--- a/src/widgets/kernel/win.pri
+++ b/src/widgets/kernel/win.pri
@@ -3,5 +3,3 @@
INCLUDEPATH += ../3rdparty/wintab
!winrt: LIBS_PRIVATE *= -lshell32 -luxtheme -ldwmapi
-# Override MinGW's definition in _mingw.h
-mingw: DEFINES += WINVER=0x600 _WIN32_WINNT=0x0600