Commit e83e8779 authored by Alvin Wong's avatar Alvin Wong

Fix fullscreen mode on Windows with OpenGL

A previous attempt was made in D1977 [1] but it didn't work properly.
The patch `0003-Hack-for-fullscreen-workaround.patch` only partly hid
the issue and the issue has resurfaced since this patch was removed.

This commit actually enables Qt's workaround with an additional patch
from Qt 5.13 [2]. The workaround adds a 1px border around the window. An
additional hack is added to hide three of the borders, though we can't
hide all four borders since the bug will return. This currently leaves
the bottom border visible as a compromise.

This workaround is not active when ANGLE is being used. If anyone is
annoyed by the 1px border, they may consider switching to ANGLE.

[1]: https://phabricator.kde.org/D1977
[2]: https://codereview.qt-project.org/246155

Differential Revision: https://phabricator.kde.org/D20657
parent 24479fd3
...@@ -57,6 +57,10 @@ if (WIN32) ...@@ -57,6 +57,10 @@ if (WIN32)
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0027-Switch-stylus-pointer-type-when-the-tablet-is-in-the.patch COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0027-Switch-stylus-pointer-type-when-the-tablet-is-in-the.patch
) )
endif() endif()
set(ext_qt_PATCH_COMMAND ${ext_qt_PATCH_COMMAND}
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/set-has-border-in-full-screen-default.patch
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/remove-fullscreen-border-hack.patch
)
ExternalProject_Add( ExternalProject_Add(
ext_qt ext_qt
......
From e9b40ddf98af52f1c1866c766c9add6245e66a92 Mon Sep 17 00:00:00 2001
From: Alvin Wong <alvin@alvinhc.com>
Date: Thu, 18 Apr 2019 18:59:58 +0800
Subject: [PATCH] Hack to hide 1px border with OpenGL fullscreen hack
Unfortunately can't hide all four sides because the bug returns. Now we
leave the bottom border visible, which is probably the most we can do.
Ref: https://bugreports.qt.io/browse/QTBUG-41309
---
src/plugins/platforms/windows/qwindowswindow.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 9705eb7293..08c743aaae 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1995,7 +1995,7 @@ bool QWindowsWindow::isFullScreen_sys() const
return false;
QRect geometry = geometry_sys();
if (testFlag(HasBorderInFullScreen))
- geometry += QMargins(1, 1, 1, 1);
+ geometry += QMargins(0, 0, 0, 1);
QPlatformScreen *screen = screenForGeometry(geometry);
return screen && geometry == screen->geometry();
}
@@ -2066,7 +2066,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
- SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
+ SetWindowPos(m_data.hwnd, HWND_TOP, r.left() - 1, r.top() - 1, r.width() + 2, r.height() + 1, swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
clearFlag(MaximizeToFullScreen);
--
2.18.0.windows.1
From f377ab8da1acb279e5b23ab1d2ef4afabe5f481c Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@qt.io>
Date: Wed, 21 Nov 2018 09:06:50 +0100
Subject: [PATCH] Windows: Add a default setting for hasBorderInFullScreen
The hasBorderInFullScreen only has an effect when set before
the window is shown or switched to fullscreen. This is currently
not possible in the QML case since the window is only accessible
after all properties (including visibility) have been set.
Add a function to set a default value.
[ChangeLog][QtPlatformHeaders][QWindowsWindowFunctions] Add a default
setting for hasBorderInFullScreen
Task-number: QTBUG-47247
Task-number: QTBUG-71855
Change-Id: I3952e3f34bc4eb134cf1c5265b4489fc74112688
Reviewed-by: Andre de la Rocha <andre.rocha@qt.io>
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
(cherry picked from commit 7264bf19dbc47b805bb7af5df584ce1aae081962)
---
.../qwindowswindowfunctions.h | 9 +++++
.../qwindowswindowfunctions.qdoc | 33 +++++++++++++++++++
.../windows/qwindowsnativeinterface.cpp | 2 ++
.../platforms/windows/qwindowswindow.cpp | 8 ++++-
.../platforms/windows/qwindowswindow.h | 2 ++
5 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
index e51c2fde67..032dcafa6e 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
@@ -81,6 +81,15 @@ public:
func(window, border);
}
+ typedef void (*SetHasBorderInFullScreenDefault)(bool border);
+ static const QByteArray setHasBorderInFullScreenDefaultIdentifier() { return QByteArrayLiteral("WindowsSetHasBorderInFullScreenDefault"); }
+ static void setHasBorderInFullScreenDefault(bool border)
+ {
+ auto func = reinterpret_cast<SetHasBorderInFullScreenDefault>(QGuiApplication::platformFunction(setHasBorderInFullScreenDefaultIdentifier()));
+ if (func)
+ func(border);
+ }
+
typedef void (*SetWindowActivationBehaviorType)(WindowActivationBehavior);
static const QByteArray setWindowActivationBehaviorIdentifier() { return QByteArrayLiteral("WindowsSetWindowActivationBehavior"); }
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
index a52bbe061b..0c52cde753 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
@@ -93,7 +93,40 @@
is true then it will enable the WS_BORDER flag in full screen mode to enable other top level windows
inside the application to appear on top when required.
+ \note The setting must be applied before showing the window or switching it
+ to full screen. For QML, setHasBorderInFullScreenDefault() can be used to
+ set a default value.
+
+ See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
+*/
+
+/*!
+ \typedef QWindowsWindowFunctions::SetHasBorderInFullScreenDefault
+ \since 5.13
+
+ This is the typedef for the function returned by QGuiApplication::platformFunction
+ when passed setHasBorderInFullScreenDefaultIdentifier.
+*/
+
+/*!
+ \fn QByteArray QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier()
+ \since 5.13
+
+ This function returns the bytearray that can be used to query
+ QGuiApplication::platformFunction to retrieve the SetHasBorderInFullScreen function.
+*/
+
+/*!
+ \fn void QWindowsWindowFunctions::setHasBorderInFullScreenDefault(bool border)
+ \since 5.13
+
+ This is a convenience function that can be used directly instead of resolving
+ the function pointer. \a border will be relayed to the function retrieved by
+ QGuiApplication. When \a border is true, the WS_BORDER flag will be set
+ in full screen mode for all windows by default.
+
See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
+ \sa setHasBorderInFullScreen()
*/
/*!
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 05d6ac9201..eeb1aa58a3 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -293,6 +293,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
+ if (function == QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier())
+ return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenDefault);
if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier())
return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior);
if (function == QWindowsWindowFunctions::isTabletModeIdentifier())
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 910d8dd209..9705eb7293 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1180,6 +1180,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle";
const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen";
+bool QWindowsWindow::m_borderInFullScreenDefault = false;
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) :
QWindowsBaseWindow(aWindow),
@@ -1217,7 +1218,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
if (aWindow->isTopLevel())
setWindowIcon(aWindow->icon());
- if (aWindow->property(hasBorderInFullScreenProperty).toBool())
+ if (m_borderInFullScreenDefault || aWindow->property(hasBorderInFullScreenProperty).toBool())
setFlag(HasBorderInFullScreen);
clearFlag(WithinCreate);
}
@@ -2820,6 +2821,11 @@ void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border
window->setProperty(hasBorderInFullScreenProperty, QVariant(border));
}
+void QWindowsWindow::setHasBorderInFullScreenDefault(bool border)
+{
+ m_borderInFullScreenDefault = border;
+}
+
void QWindowsWindow::setHasBorderInFullScreen(bool border)
{
if (testFlag(HasBorderInFullScreen) == border)
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index b9b398b67b..b07bd15d2a 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -341,6 +341,7 @@ public:
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
+ static void setHasBorderInFullScreenDefault(bool border);
void setHasBorderInFullScreen(bool border);
static QString formatWindowTitle(const QString &title);
@@ -386,6 +387,7 @@ private:
// note: intentionally not using void * in order to avoid breaking x86
VkSurfaceKHR m_vkSurface = 0;
#endif
+ static bool m_borderInFullScreenDefault;
};
#ifndef QT_NO_DEBUG_STREAM
--
2.18.0.windows.1
...@@ -339,6 +339,18 @@ HAVE_HDR ...@@ -339,6 +339,18 @@ HAVE_HDR
) )
configure_file(config-hdr.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-hdr.h) configure_file(config-hdr.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-hdr.h)
if (WIN32)
CHECK_CXX_SOURCE_COMPILES("
#include <QtPlatformHeaders/QWindowsWindowFunctions>
int main(int argc, char *argv[]) {
QWindowsWindowFunctions::setHasBorderInFullScreenDefault(true);
}
"
HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT
)
configure_file(config-set-has-border-in-full-screen-default.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-set-has-border-in-full-screen-default.h)
endif (WIN32)
unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES) unset(CMAKE_REQUIRED_LIBRARIES)
......
/* config-hdr.h. Generated by cmake from config-set-has-border-in-full-screen-default.h.in */
/* Define if QWindowsWindowFunctions::setHasBorderInFullScreenDefault is available */
#cmakedefine HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT 1
...@@ -67,6 +67,10 @@ ...@@ -67,6 +67,10 @@
#else #else
#include <dialogs/KisDlgCustomTabletResolution.h> #include <dialogs/KisDlgCustomTabletResolution.h>
#endif #endif
#include "config-set-has-border-in-full-screen-default.h"
#ifdef HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT
#include <QtPlatformHeaders/QWindowsWindowFunctions>
#endif
#include <QLibrary> #include <QLibrary>
#endif #endif
...@@ -324,6 +328,12 @@ extern "C" int main(int argc, char **argv) ...@@ -324,6 +328,12 @@ extern "C" int main(int argc, char **argv)
// first create the application so we can create a pixmap // first create the application so we can create a pixmap
KisApplication app(key, argc, argv); KisApplication app(key, argc, argv);
#ifdef HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT
if (QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL)) {
QWindowsWindowFunctions::setHasBorderInFullScreenDefault(true);
}
#endif
KisUsageLogger::writeHeader(); KisUsageLogger::writeHeader();
if (!language.isEmpty()) { if (!language.isEmpty()) {
......
...@@ -148,10 +148,6 @@ ...@@ -148,10 +148,6 @@
#include <kritaversion.h> #include <kritaversion.h>
#include <mutex> #include <mutex>
#ifdef Q_OS_WIN
#include <QtPlatformHeaders/QWindowsWindowFunctions>
#endif
class ToolDockerFactory : public KoDockFactoryBase class ToolDockerFactory : public KoDockFactoryBase
{ {
public: public:
...@@ -508,11 +504,6 @@ KisMainWindow::KisMainWindow(QUuid uuid) ...@@ -508,11 +504,6 @@ KisMainWindow::KisMainWindow(QUuid uuid)
d->viewManager->updateGUI(); d->viewManager->updateGUI();
d->viewManager->updateIcons(); d->viewManager->updateIcons();
#ifdef Q_OS_WIN
auto w = qApp->activeWindow();
if (w) QWindowsWindowFunctions::setHasBorderInFullScreen(w->windowHandle(), true);
#endif
QTimer::singleShot(1000, this, SLOT(checkSanity())); QTimer::singleShot(1000, this, SLOT(checkSanity()));
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment