aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Edmundson <[email protected]>2017-05-11 12:16:25 +0200
committerDavid Edmundson <[email protected]>2017-05-11 12:16:25 +0200
commitac9d4b9cd382996fbc7fbbf2736a15467e4356fc (patch)
tree7c591cfcb99c645f3fbdc7dc83583cc198749d31
parent7a7dfffba98d383821c39ac68de6e8aabe45b7ed (diff)
Move code on wayland surface being created.
Summary: We need to setup our attachments when the wl_surface is created. This gets recreated when a window is hidden and shown. QPlatformSurfaceCreated is emitted once, when the backing store is created, not when the wl_surface is created, despite it's similar sounding name. QEvent::Show is too soon, as this is before the platform gets setVisible We do however, always get an expose event. QEvent::Hide weirdly comes after the platform has done its thing. Expose is called whilst we are in QWaylandWindow::setVisible, so before the initial surface has been committed, so we still have perfect frames. Test Plan: See attached test Still has window decos after hide/show Ran on Qt 5.9 and Qt 5.7 Reviewers: #plasma, graesslin Reviewed By: #plasma, graesslin Subscribers: graesslin, plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D5746
-rw-r--r--src/platformtheme/kwaylandintegration.cpp100
-rw-r--r--src/platformtheme/kwaylandintegration.h3
-rw-r--r--tests/CMakeLists.txt3
-rw-r--r--tests/windowdecotest.cpp71
4 files changed, 131 insertions, 46 deletions
diff --git a/src/platformtheme/kwaylandintegration.cpp b/src/platformtheme/kwaylandintegration.cpp
index 10da7e5..b3a20e3 100644
--- a/src/platformtheme/kwaylandintegration.cpp
+++ b/src/platformtheme/kwaylandintegration.cpp
@@ -71,65 +71,71 @@ bool KWaylandIntegration::eventFilter(QObject *watched, QEvent *event)
{
if (!m_decoration) {
return false;
- }
- if (event->type() == QEvent::PlatformSurface) {
+ } else if (event->type() == QEvent::Expose) {
+ auto ee = static_cast<QExposeEvent*>(event);
+ if (ee->region().isNull()) {
+ return false;
+ }
QWindow *w = qobject_cast<QWindow*>(watched);
if (!w || w->parent()) {
return false;
}
- if (auto e = dynamic_cast<QPlatformSurfaceEvent*>(event)) {
- switch (e->surfaceEventType()) {
- case QPlatformSurfaceEvent::SurfaceCreated: {
- // set colorscheme hint
- if (qApp->property(s_schemePropertyName.constData()).isValid()) {
- installColorScheme(w);
- }
- const auto blurBehindProperty = w->property(s_blurBehindPropertyName.constData());
- if (blurBehindProperty.isValid()) {
- KWindowEffects::enableBlurBehind(w->winId(), blurBehindProperty.toBool());
- }
- // create deco
- Surface *s = Surface::fromWindow(w);
- if (!s) {
- return false;
- }
- auto deco = m_decoration->create(s, w);
- connect(deco, &ServerSideDecoration::modeChanged, w,
- [deco, w] {
- const auto flags = w->flags();
- const auto ourMode = (flags.testFlag(Qt::FramelessWindowHint) || flags.testFlag(Qt::Popup) || flags.testFlag(Qt::ToolTip)) ? ServerSideDecoration::Mode::None : ServerSideDecoration::Mode::Server;
- if (deco->mode() != ourMode) {
- deco->requestMode(ourMode);
- }
- }
- );
- const auto flags = w->flags();
- const auto ourMode = (flags.testFlag(Qt::FramelessWindowHint) || flags.testFlag(Qt::Popup) || flags.testFlag(Qt::ToolTip)) ? ServerSideDecoration::Mode::None : ServerSideDecoration::Mode::Server;
- if (deco->defaultMode() != ourMode) {
- deco->requestMode(ourMode);
- }
- w->setProperty("org.kde.plasma.integration.waylandserverdecoration", QVariant::fromValue(deco));
- break;
- }
- case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: {
- delete w->property("org.kde.plasma.integration.waylandserverdecoration").value<ServerSideDecoration*>();
- break;
- }
- default:
- // nothing
- break;
- }
+ shellSurfaceCreated(w);
+ } else if (event->type() == QEvent::Hide) {
+ QWindow *w = qobject_cast<QWindow*>(watched);
+ if (!w || w->parent()) {
+ return false;
}
- }
- if (event->type() == QEvent::ApplicationPaletteChange) {
+ shellSurfaceDestroyed(w);
+ } else if (event->type() == QEvent::ApplicationPaletteChange) {
const auto topLevelWindows = QGuiApplication::topLevelWindows();
for (QWindow *w : topLevelWindows) {
installColorScheme(w);
}
}
+
return false;
}
+void KWaylandIntegration::shellSurfaceCreated(QWindow *w)
+{
+ // set colorscheme hint
+ if (qApp->property(s_schemePropertyName.constData()).isValid()) {
+ installColorScheme(w);
+ }
+ const auto blurBehindProperty = w->property(s_blurBehindPropertyName.constData());
+ if (blurBehindProperty.isValid()) {
+ KWindowEffects::enableBlurBehind(w->winId(), blurBehindProperty.toBool());
+ }
+ // create deco
+ Surface *s = Surface::fromWindow(w);
+ if (!s) {
+ return;
+ }
+ auto deco = m_decoration->create(s, w);
+ connect(deco, &ServerSideDecoration::modeChanged, w,
+ [deco, w] {
+ const auto flags = w->flags();
+ const auto ourMode = (flags.testFlag(Qt::FramelessWindowHint) || flags.testFlag(Qt::Popup) || flags.testFlag(Qt::ToolTip)) ? ServerSideDecoration::Mode::None : ServerSideDecoration::Mode::Server;
+ if (deco->mode() != ourMode) {
+ deco->requestMode(ourMode);
+ }
+ }
+ );
+ const auto flags = w->flags();
+ const auto ourMode = (flags.testFlag(Qt::FramelessWindowHint) || flags.testFlag(Qt::Popup) || flags.testFlag(Qt::ToolTip)) ? ServerSideDecoration::Mode::None : ServerSideDecoration::Mode::Server;
+ if (deco->defaultMode() != ourMode) {
+ deco->requestMode(ourMode);
+ }
+ w->setProperty("org.kde.plasma.integration.waylandserverdecoration", QVariant::fromValue(deco));
+}
+
+void KWaylandIntegration::shellSurfaceDestroyed(QWindow *w)
+{
+ delete w->property("org.kde.plasma.integration.waylandserverdecoration").value<ServerSideDecoration*>();
+ w->setProperty("org.kde.plasma.integration.waylandserverdecoration", 0);
+}
+
void KWaylandIntegration::installColorScheme(QWindow *w)
{
if (QPlatformNativeInterface *native = qApp->platformNativeInterface()) {
@@ -147,3 +153,5 @@ void KWaylandIntegration::setWindowProperty(QWindow *window, const QByteArray &n
}
}
}
+
+#include "kwaylandintegration.moc"
diff --git a/src/platformtheme/kwaylandintegration.h b/src/platformtheme/kwaylandintegration.h
index 1ab11e7..46d8112 100644
--- a/src/platformtheme/kwaylandintegration.h
+++ b/src/platformtheme/kwaylandintegration.h
@@ -45,6 +45,9 @@ public:
bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE;
private:
+ void shellSurfaceCreated(QWindow *w);
+ void shellSurfaceDestroyed(QWindow *w);
+
void installColorScheme(QWindow *w);
KWayland::Client::ServerSideDecorationManager *m_decoration;
};
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 87beb05..ed5f8a6 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,2 +1,5 @@
add_executable(qfiledialogtest qfiledialogtest.cpp)
target_link_libraries(qfiledialogtest Qt5::Core Qt5::Widgets)
+
+add_executable(windowdecotest windowdecotest.cpp)
+target_link_libraries(windowdecotest Qt5::Core Qt5::Widgets)
diff --git a/tests/windowdecotest.cpp b/tests/windowdecotest.cpp
new file mode 100644
index 0000000..5d1253c
--- /dev/null
+++ b/tests/windowdecotest.cpp
@@ -0,0 +1,71 @@
+/* This file is part of the KDE libraries
+
+ Copyright 2017 David Edmundson <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * This class is for checking that wayland server side window decorations remain
+ * after a window is hidden and shown.
+ */
+
+#include <QApplication>
+#include <QWidget>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QTimer>
+
+class ATestWindow: public QWidget
+{
+ Q_OBJECT
+public:
+ ATestWindow();
+
+private:
+ QPushButton *mBtn;
+ QWidget *m_area;
+};
+
+ATestWindow::ATestWindow()
+{
+ mBtn = new QPushButton(QStringLiteral("Hide and Show"));
+
+ m_area = new QWidget;
+ m_area->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ connect(mBtn, &QPushButton::clicked, this, [this]() {
+ this->hide();
+ QTimer::singleShot(1000, this, [this](){this->show();});
+ });
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(mBtn);
+ setLayout(layout);
+}
+
+
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ ATestWindow wnd;
+ wnd.show();
+
+ return app.exec();
+}
+
+
+#include "windowdecotest.moc"