xdgshellclient: Support set_fullscreen argument

xdgshell allows clients to specify which output should we fill on
set_fullscreen. This change takes this request into consideration
instead of ignoring it.
This commit is contained in:
Aleix Pol 2020-11-23 19:24:37 +01:00 committed by Aleix Pol Gonzalez
parent f04fa44f34
commit 91064cb26a
3 changed files with 65 additions and 2 deletions

View file

@ -9,6 +9,7 @@
*/ */
#include "kwin_wayland_test.h" #include "kwin_wayland_test.h"
#include "abstract_client.h" #include "abstract_client.h"
#include "abstract_wayland_output.h"
#include "cursor.h" #include "cursor.h"
#include "decorations/decorationbridge.h" #include "decorations/decorationbridge.h"
#include "decorations/settings.h" #include "decorations/settings.h"
@ -73,6 +74,7 @@ private Q_SLOTS:
void testMaximizedToFullscreen_data(); void testMaximizedToFullscreen_data();
void testMaximizedToFullscreen(); void testMaximizedToFullscreen();
void testFullscreenMultipleOutputs();
void testWindowOpensLargerThanScreen(); void testWindowOpensLargerThanScreen();
void testHidden(); void testHidden();
void testDesktopFileName(); void testDesktopFileName();
@ -626,6 +628,59 @@ void TestXdgShellClient::testMaximizedToFullscreen()
QVERIFY(Test::waitForWindowDestroyed(client)); QVERIFY(Test::waitForWindowDestroyed(client));
} }
void TestXdgShellClient::testFullscreenMultipleOutputs()
{
// this test verifies that kwin will place fullscreen windows in the outputs its instructed to
for (int i = 0; i < screens()->count(); ++i) {
XdgShellSurface::States states;
QSharedPointer<Surface> surface(Test::createSurface());
QSharedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
QVERIFY(surface);
QVERIFY(shellSurface);
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
QVERIFY(client);
QVERIFY(client->isActive());
QVERIFY(!client->isFullScreen());
QCOMPARE(client->clientSize(), QSize(100, 50));
QVERIFY(!client->isDecorated());
QSignalSpy fullscreenChangedSpy(client, &AbstractClient::fullScreenChanged);
QVERIFY(fullscreenChangedSpy.isValid());
QSignalSpy frameGeometryChangedSpy(client, &AbstractClient::frameGeometryChanged);
QVERIFY(frameGeometryChangedSpy.isValid());
QSignalSpy configureRequestedSpy(shellSurface.data(), &XdgShellSurface::configureRequested);
QVERIFY(configureRequestedSpy.isValid());
// Wait for the compositor to send a configure event with the Activated state.
QVERIFY(configureRequestedSpy.wait());
QCOMPARE(configureRequestedSpy.count(), 1);
states = configureRequestedSpy.last().at(1).value<XdgShellSurface::States>();
QVERIFY(states & XdgShellSurface::State::Activated);
// Ask the compositor to show the window in full screen mode.
shellSurface->setFullscreen(true, Test::waylandOutputs()[i]);
QVERIFY(configureRequestedSpy.wait());
QCOMPARE(configureRequestedSpy.count(), 2);
QCOMPARE(configureRequestedSpy.last().at(0).value<QSize>(), screens()->size(i));
shellSurface->ackConfigure(configureRequestedSpy.last().at(2).value<quint32>());
Test::render(surface.data(), configureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
QVERIFY(!fullscreenChangedSpy.isEmpty() || fullscreenChangedSpy.wait());
QCOMPARE(fullscreenChangedSpy.count(), 1);
QVERIFY(!frameGeometryChangedSpy.isEmpty() || frameGeometryChangedSpy.wait());
QVERIFY(client->isFullScreen());
QCOMPARE(client->frameGeometry(), screens()->geometry(i));
}
}
void TestXdgShellClient::testWindowOpensLargerThanScreen() void TestXdgShellClient::testWindowOpensLargerThanScreen()
{ {
// this test creates a window which is as large as the screen, but is decorated // this test creates a window which is as large as the screen, but is decorated

View file

@ -9,7 +9,9 @@
SPDX-License-Identifier: GPL-2.0-or-later SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include "xdgshellclient.h" #include "xdgshellclient.h"
#include "abstract_wayland_output.h"
#include "deleted.h" #include "deleted.h"
#include "platform.h"
#include "screenedge.h" #include "screenedge.h"
#include "screens.h" #include "screens.h"
#include "subsurfacemonitor.h" #include "subsurfacemonitor.h"
@ -1060,7 +1062,8 @@ void XdgToplevelClient::handleUnmaximizeRequested()
void XdgToplevelClient::handleFullscreenRequested(OutputInterface *output) void XdgToplevelClient::handleFullscreenRequested(OutputInterface *output)
{ {
Q_UNUSED(output) m_fullScreenRequestedOutput = waylandServer()->findOutput(output);
if (m_isInitialized) { if (m_isInitialized) {
setFullScreen(/* set */ true, /* user */ false); setFullScreen(/* set */ true, /* user */ false);
scheduleConfigure(ConfigureRequired); scheduleConfigure(ConfigureRequired);
@ -1071,6 +1074,7 @@ void XdgToplevelClient::handleFullscreenRequested(OutputInterface *output)
void XdgToplevelClient::handleUnfullscreenRequested() void XdgToplevelClient::handleUnfullscreenRequested()
{ {
m_fullScreenRequestedOutput.clear();
if (m_isInitialized) { if (m_isInitialized) {
setFullScreen(/* set */ false, /* user */ false); setFullScreen(/* set */ false, /* user */ false);
scheduleConfigure(ConfigureRequired); scheduleConfigure(ConfigureRequired);
@ -1560,8 +1564,10 @@ void XdgToplevelClient::setFullScreen(bool set, bool user)
updateDecoration(false, false); updateDecoration(false, false);
if (set) { if (set) {
setFrameGeometry(workspace()->clientArea(FullScreenArea, this)); const int screen = m_fullScreenRequestedOutput ? kwinApp()->platform()->enabledOutputs().indexOf(m_fullScreenRequestedOutput) : screens()->number(frameGeometry().center());
setFrameGeometry(workspace()->clientArea(FullScreenArea, screen, desktop()));
} else { } else {
m_fullScreenRequestedOutput.clear();
if (m_fullScreenGeometryRestore.isValid()) { if (m_fullScreenGeometryRestore.isValid()) {
int currentScreen = screen(); int currentScreen = screen();
setFrameGeometry(QRect(m_fullScreenGeometryRestore.topLeft(), setFrameGeometry(QRect(m_fullScreenGeometryRestore.topLeft(),

View file

@ -29,6 +29,7 @@ class XdgToplevelDecorationV1Interface;
namespace KWin namespace KWin
{ {
class AbstractOutput;
class XdgSurfaceConfigure class XdgSurfaceConfigure
{ {
@ -216,6 +217,7 @@ private:
bool m_isInitialized = false; bool m_isInitialized = false;
bool m_userNoBorder = false; bool m_userNoBorder = false;
bool m_isTransient = false; bool m_isTransient = false;
QPointer<AbstractOutput> m_fullScreenRequestedOutput;
}; };
class XdgPopupClient final : public XdgSurfaceClient class XdgPopupClient final : public XdgSurfaceClient