From 29122f1df6601f3606bd03c12e940973c6f8771e Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 22 May 2024 12:52:59 +0300 Subject: [PATCH] Improve integration of preferred buffer scale with xdg shell configure events With this change the preferred buffer scale, transform and color description properties will be latched to xdg shell configure events. This should ensure that the clients are told the preferred buffer scale before the first configure events. --- src/inputpanelv1window.cpp | 26 +++++++++++ src/inputpanelv1window.h | 3 ++ src/internalwindow.cpp | 2 + src/layershellv1window.cpp | 26 +++++++++++ src/layershellv1window.h | 3 ++ src/waylandwindow.cpp | 5 --- src/window.cpp | 89 ++++++++++++++++++++++++++++++++++++-- src/window.h | 23 +++++++++- src/x11window.cpp | 3 ++ src/xdgshellwindow.cpp | 74 ++++++++++++++++++++++++++++++- src/xdgshellwindow.h | 6 +++ 11 files changed, 250 insertions(+), 10 deletions(-) diff --git a/src/inputpanelv1window.cpp b/src/inputpanelv1window.cpp index 268bf7577b..d1114799c7 100644 --- a/src/inputpanelv1window.cpp +++ b/src/inputpanelv1window.cpp @@ -26,6 +26,8 @@ InputPanelV1Window::InputPanelV1Window(InputPanelSurfaceV1Interface *panelSurfac : WaylandWindow(panelSurface->surface()) , m_panelSurface(panelSurface) { + setOutput(workspace()->activeOutput()); + setMoveResizeOutput(workspace()->activeOutput()); setSkipSwitcher(true); setSkipPager(true); setSkipTaskbar(true); @@ -191,6 +193,30 @@ void InputPanelV1Window::moveResizeInternal(const QRectF &rect, MoveResizeMode m updateGeometry(rect); } +void InputPanelV1Window::doSetPreferredBufferScale() +{ + if (isDeleted()) { + return; + } + surface()->setPreferredBufferScale(preferredBufferScale()); +} + +void InputPanelV1Window::doSetPreferredBufferTransform() +{ + if (isDeleted()) { + return; + } + surface()->setPreferredBufferTransform(preferredBufferTransform()); +} + +void InputPanelV1Window::doSetPreferredColorDescription() +{ + if (isDeleted()) { + return; + } + surface()->setPreferredColorDescription(preferredColorDescription()); +} + void InputPanelV1Window::handleMapped() { maybeShow(); diff --git a/src/inputpanelv1window.h b/src/inputpanelv1window.h index 40c795323f..54c27eea12 100644 --- a/src/inputpanelv1window.h +++ b/src/inputpanelv1window.h @@ -83,6 +83,9 @@ public: protected: void moveResizeInternal(const QRectF &rect, MoveResizeMode mode) override; + void doSetPreferredBufferScale() override; + void doSetPreferredBufferTransform() override; + void doSetPreferredColorDescription() override; private: void showTopLevel(OutputInterface *output, InputPanelSurfaceV1Interface::Position position); diff --git a/src/internalwindow.cpp b/src/internalwindow.cpp index 04bb52133d..645905af9f 100644 --- a/src/internalwindow.cpp +++ b/src/internalwindow.cpp @@ -38,6 +38,8 @@ InternalWindow::InternalWindow(QWindow *handle) connect(m_handle, &QWindow::opacityChanged, this, &InternalWindow::setOpacity); connect(m_handle, &QWindow::destroyed, this, &InternalWindow::destroyWindow); + setOutput(workspace()->activeOutput()); + setMoveResizeOutput(workspace()->activeOutput()); setCaption(m_handle->title()); setIcon(QIcon::fromTheme(QStringLiteral("kwin"))); setOnAllDesktops(true); diff --git a/src/layershellv1window.cpp b/src/layershellv1window.cpp index 0b927185a5..1bfa71c70c 100644 --- a/src/layershellv1window.cpp +++ b/src/layershellv1window.cpp @@ -43,6 +43,8 @@ LayerShellV1Window::LayerShellV1Window(LayerSurfaceV1Interface *shellSurface, , m_shellSurface(shellSurface) , m_windowType(scopeToType(shellSurface->scope())) { + setOutput(output); + setMoveResizeOutput(output); setSkipSwitcher(!isDesktop()); setSkipPager(true); setSkipTaskbar(true); @@ -249,6 +251,30 @@ void LayerShellV1Window::moveResizeInternal(const QRectF &rect, MoveResizeMode m updateGeometry(updateRect); } +void LayerShellV1Window::doSetPreferredBufferScale() +{ + if (isDeleted()) { + return; + } + surface()->setPreferredBufferScale(preferredBufferScale()); +} + +void LayerShellV1Window::doSetPreferredBufferTransform() +{ + if (isDeleted()) { + return; + } + surface()->setPreferredBufferTransform(preferredBufferTransform()); +} + +void LayerShellV1Window::doSetPreferredColorDescription() +{ + if (isDeleted()) { + return; + } + surface()->setPreferredColorDescription(preferredColorDescription()); +} + void LayerShellV1Window::handleSizeChanged() { updateGeometry(QRectF(pos(), clientSizeToFrameSize(surface()->size()))); diff --git a/src/layershellv1window.h b/src/layershellv1window.h index 37620b7c4e..b188cdee2d 100644 --- a/src/layershellv1window.h +++ b/src/layershellv1window.h @@ -50,6 +50,9 @@ protected: Layer belongsToLayer() const override; bool acceptsFocus() const override; void moveResizeInternal(const QRectF &rect, MoveResizeMode mode) override; + void doSetPreferredBufferScale() override; + void doSetPreferredBufferTransform() override; + void doSetPreferredColorDescription() override; private: void handleSizeChanged(); diff --git a/src/waylandwindow.cpp b/src/waylandwindow.cpp index 614119bab3..2f9caf17c2 100644 --- a/src/waylandwindow.cpp +++ b/src/waylandwindow.cpp @@ -153,11 +153,6 @@ void WaylandWindow::updateClientOutputs() } surface()->setOutputs(waylandServer()->display()->outputsIntersecting(frameGeometry().toAlignedRect()), waylandServer()->display()->largestIntersectingOutput(frameGeometry().toAlignedRect())); - if (output()) { - surface()->setPreferredBufferScale(output()->scale()); - surface()->setPreferredBufferTransform(output()->transform()); - surface()->setPreferredColorDescription(output()->colorDescription()); - } } void WaylandWindow::updateIcon() diff --git a/src/window.cpp b/src/window.cpp index eeb14f0923..d65bf71756 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -59,13 +59,11 @@ QHash> Window::s_palettes; std::shared_ptr Window::s_defaultPalette; Window::Window() - : m_output(workspace()->activeOutput()) - , ready_for_painting(false) + : ready_for_painting(false) , m_internalId(QUuid::createUuid()) , m_clientMachine(new ClientMachine(this)) , m_skipCloseAnimation(false) , m_colorScheme(QStringLiteral("kdeglobals")) - , m_moveResizeOutput(workspace()->activeOutput()) { connect(this, &Window::bufferGeometryChanged, this, &Window::inputTransformationChanged); @@ -3322,7 +3320,26 @@ Output *Window::moveResizeOutput() const void Window::setMoveResizeOutput(Output *output) { + if (m_moveResizeOutput == output) { + return; + } + + if (m_moveResizeOutput) { + disconnect(m_moveResizeOutput, &Output::scaleChanged, this, &Window::updatePreferredBufferScale); + disconnect(m_moveResizeOutput, &Output::transformChanged, this, &Window::updatePreferredBufferTransform); + disconnect(m_moveResizeOutput, &Output::colorDescriptionChanged, this, &Window::updatePreferredColorDescription); + } + m_moveResizeOutput = output; + if (output) { + connect(output, &Output::scaleChanged, this, &Window::updatePreferredBufferScale); + connect(output, &Output::transformChanged, this, &Window::updatePreferredBufferTransform); + connect(output, &Output::colorDescriptionChanged, this, &Window::updatePreferredColorDescription); + } + + updatePreferredBufferScale(); + updatePreferredBufferTransform(); + updatePreferredColorDescription(); } void Window::move(const QPointF &point) @@ -4340,6 +4357,72 @@ void Window::doSetModal() { } +qreal Window::preferredBufferScale() const +{ + return m_preferredBufferScale; +} + +void Window::setPreferredBufferScale(qreal scale) +{ + if (m_preferredBufferScale != scale) { + m_preferredBufferScale = scale; + doSetPreferredBufferScale(); + } +} + +void Window::doSetPreferredBufferScale() +{ +} + +void Window::updatePreferredBufferScale() +{ + setPreferredBufferScale(m_moveResizeOutput->scale()); +} + +OutputTransform Window::preferredBufferTransform() const +{ + return m_preferredBufferTransform; +} + +void Window::setPreferredBufferTransform(OutputTransform transform) +{ + if (m_preferredBufferTransform != transform) { + m_preferredBufferTransform = transform; + doSetPreferredBufferTransform(); + } +} + +void Window::doSetPreferredBufferTransform() +{ +} + +void Window::updatePreferredBufferTransform() +{ + setPreferredBufferTransform(m_moveResizeOutput->transform()); +} + +const ColorDescription &Window::preferredColorDescription() const +{ + return m_preferredColorDescription; +} + +void Window::setPreferredColorDescription(const ColorDescription &description) +{ + if (m_preferredColorDescription != description) { + m_preferredColorDescription = description; + doSetPreferredColorDescription(); + } +} + +void Window::doSetPreferredColorDescription() +{ +} + +void Window::updatePreferredColorDescription() +{ + setPreferredColorDescription(m_moveResizeOutput->colorDescription()); +} + } // namespace KWin #include "moc_window.cpp" diff --git a/src/window.h b/src/window.h index d1216a9ba0..4d1d36e56d 100644 --- a/src/window.h +++ b/src/window.h @@ -9,6 +9,7 @@ */ #pragma once +#include "core/output.h" #include "cursor.h" #include "effect/globals.h" #include "options.h" @@ -1322,6 +1323,15 @@ public: void refOffscreenRendering(); void unrefOffscreenRendering(); + qreal preferredBufferScale() const; + void setPreferredBufferScale(qreal scale); + + OutputTransform preferredBufferTransform() const; + void setPreferredBufferTransform(OutputTransform transform); + + const ColorDescription &preferredColorDescription() const; + void setPreferredColorDescription(const ColorDescription &description); + public Q_SLOTS: virtual void closeWindow() = 0; @@ -1517,6 +1527,9 @@ protected: virtual void doSetHiddenByShowDesktop(); virtual void doSetSuspended(); virtual void doSetModal(); + virtual void doSetPreferredBufferScale(); + virtual void doSetPreferredBufferTransform(); + virtual void doSetPreferredColorDescription(); void setupWindowManagementInterface(); void destroyWindowManagementInterface(); @@ -1715,6 +1728,10 @@ protected: void cleanTabBox(); void maybeSendFrameCallback(); + void updatePreferredBufferScale(); + void updatePreferredBufferTransform(); + void updatePreferredColorDescription(); + Output *m_output = nullptr; QRectF m_frameGeometry; QRectF m_clientGeometry; @@ -1723,6 +1740,10 @@ protected: bool m_hidden = false; bool m_hiddenByShowDesktop = false; + qreal m_preferredBufferScale = 1; + OutputTransform m_preferredBufferTransform = OutputTransform::Normal; + ColorDescription m_preferredColorDescription = ColorDescription::sRGB; + int m_refCount = 1; QUuid m_internalId; std::unique_ptr m_windowItem; @@ -1781,7 +1802,7 @@ protected: QTimer *m_electricMaximizingDelay = nullptr; // geometry - Output *m_moveResizeOutput; + Output *m_moveResizeOutput = nullptr; QRectF m_moveResizeGeometry; QRectF m_keyboardGeometryRestore; QRectF m_maximizeGeometryRestore; diff --git a/src/x11window.cpp b/src/x11window.cpp index ec02c37457..0f539d1062 100644 --- a/src/x11window.cpp +++ b/src/x11window.cpp @@ -302,6 +302,9 @@ X11Window::X11Window() , m_decoInputExtent() , m_focusOutTimer(nullptr) { + setOutput(workspace()->activeOutput()); + setMoveResizeOutput(workspace()->activeOutput()); + // TODO: Do all as initialization m_syncRequest.counter = m_syncRequest.alarm = XCB_NONE; m_syncRequest.timeout = m_syncRequest.failsafeTimeout = nullptr; diff --git a/src/xdgshellwindow.cpp b/src/xdgshellwindow.cpp index 8f73a18dfa..4cc3800612 100644 --- a/src/xdgshellwindow.cpp +++ b/src/xdgshellwindow.cpp @@ -415,6 +415,8 @@ XdgToplevelWindow::XdgToplevelWindow(XdgToplevelInterface *shellSurface) : XdgSurfaceWindow(shellSurface->xdgSurface()) , m_shellSurface(shellSurface) { + setOutput(workspace()->activeOutput()); + setMoveResizeOutput(workspace()->activeOutput()); setDesktops({VirtualDesktopManager::self()->currentDesktop()}); #if KWIN_BUILD_ACTIVITIES if (auto a = Workspace::self()->activities()) { @@ -674,6 +676,10 @@ void XdgToplevelWindow::closeWindow() XdgSurfaceConfigure *XdgToplevelWindow::sendRoleConfigure() const { + surface()->setPreferredBufferScale(preferredBufferScale()); + surface()->setPreferredBufferTransform(preferredBufferTransform()); + surface()->setPreferredColorDescription(preferredColorDescription()); + QSize framePadding(0, 0); if (m_nextDecoration) { framePadding.setWidth(m_nextDecoration->borderLeft() + m_nextDecoration->borderRight()); @@ -870,6 +876,36 @@ void XdgToplevelWindow::doSetSuspended() scheduleConfigure(); } +void XdgToplevelWindow::doSetPreferredBufferScale() +{ + if (isDeleted()) { + return; + } + if (m_isInitialized) { + scheduleConfigure(); + } +} + +void XdgToplevelWindow::doSetPreferredBufferTransform() +{ + if (isDeleted()) { + return; + } + if (m_isInitialized) { + scheduleConfigure(); + } +} + +void XdgToplevelWindow::doSetPreferredColorDescription() +{ + if (isDeleted()) { + return; + } + if (m_isInitialized) { + scheduleConfigure(); + } +} + bool XdgToplevelWindow::takeFocus() { if (wantsInput()) { @@ -1261,7 +1297,6 @@ void XdgToplevelWindow::initialize() scheduleConfigure(); updateColorScheme(); updateCapabilities(); - updateClientOutputs(); setupWindowManagementInterface(); m_isInitialized = true; @@ -1623,6 +1658,9 @@ XdgPopupWindow::XdgPopupWindow(XdgPopupInterface *shellSurface) : XdgSurfaceWindow(shellSurface->xdgSurface()) , m_shellSurface(shellSurface) { + setOutput(workspace()->activeOutput()); + setMoveResizeOutput(workspace()->activeOutput()); + m_windowType = WindowType::Unknown; connect(shellSurface, &XdgPopupInterface::grabRequested, @@ -1749,6 +1787,10 @@ bool XdgPopupWindow::acceptsFocus() const XdgSurfaceConfigure *XdgPopupWindow::sendRoleConfigure() const { + surface()->setPreferredBufferScale(preferredBufferScale()); + surface()->setPreferredBufferTransform(preferredBufferTransform()); + surface()->setPreferredColorDescription(preferredColorDescription()); + const QPointF parentPosition = transientFor()->framePosToClientPos(transientFor()->pos()); const QPointF popupPosition = moveResizeGeometry().topLeft() - parentPosition; @@ -1783,6 +1825,36 @@ void XdgPopupWindow::initialize() scheduleConfigure(); } +void XdgPopupWindow::doSetPreferredBufferScale() +{ + if (isDeleted()) { + return; + } + if (m_shellSurface->isConfigured()) { + scheduleConfigure(); + } +} + +void XdgPopupWindow::doSetPreferredBufferTransform() +{ + if (isDeleted()) { + return; + } + if (m_shellSurface->isConfigured()) { + scheduleConfigure(); + } +} + +void XdgPopupWindow::doSetPreferredColorDescription() +{ + if (isDeleted()) { + return; + } + if (m_shellSurface->isConfigured()) { + scheduleConfigure(); + } +} + } // namespace KWin #include "moc_xdgshellwindow.cpp" diff --git a/src/xdgshellwindow.h b/src/xdgshellwindow.h index 796cea95fa..0a94886388 100644 --- a/src/xdgshellwindow.h +++ b/src/xdgshellwindow.h @@ -177,6 +177,9 @@ protected: bool acceptsFocus() const override; void doSetQuickTileMode() override; void doSetSuspended() override; + void doSetPreferredBufferScale() override; + void doSetPreferredBufferTransform() override; + void doSetPreferredColorDescription() override; private: void handleWindowTitleChanged(); @@ -260,6 +263,9 @@ protected: bool acceptsFocus() const override; XdgSurfaceConfigure *sendRoleConfigure() const override; void handleRoleDestroyed() override; + void doSetPreferredBufferScale() override; + void doSetPreferredBufferTransform() override; + void doSetPreferredColorDescription() override; private: void handleGrabRequested(SeatInterface *seat, quint32 serial);