diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bedacd75b..8be1ae43e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") if ("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.8") message(SEND_ERROR "Version ${CMAKE_CXX_COMPILER_VERSION} of the ${CMAKE_CXX_COMPILER_ID} C++ compiler is not supported. Please use version 4.8 or later.") endif() + # adjusting CMAKE_C_FLAGS to get wayland protocols to compile + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") endif() find_package(Qt5Multimedia QUIET) @@ -134,6 +136,36 @@ set_package_properties(Wayland PROPERTIES add_feature_info("Wayland-Client" Wayland_Client_FOUND "Required for building the Wayland backend in KWin") add_feature_info("Wayland-EGL" Wayland_Egl_FOUND "Required for building the Wayland EGL compositing backend in KWin") +find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) +add_feature_info("wayland-scanner" WAYLAND_SCANNER_EXECUTABLE "Required for generating Wayland protocols") + +if(WAYLAND_SCANNER_EXECUTABLE) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/wayland_protocols/) + add_custom_command( + OUTPUT + ${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.h + COMMAND + ${WAYLAND_SCANNER_EXECUTABLE} client-header <${KWIN_SOURCE_DIR}/wayland_client/protocols/fullscreen-shell.xml >${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.h + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/wayland_protocols/ + WORKING_DIRECTORY + ${CMAKE_BINARY_DIR}/wayland_protocols + ) + add_custom_command( + OUTPUT + ${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c + COMMAND + ${WAYLAND_SCANNER_EXECUTABLE} code <${KWIN_SOURCE_DIR}/wayland_client/protocols/fullscreen-shell.xml >${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c + DEPENDS ${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.h + WORKING_DIRECTORY + ${CMAKE_BINARY_DIR}/wayland_protocols + ) + add_custom_target(wayland-client-fullscreen-shell DEPENDS ${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c) + include_directories(${CMAKE_BINARY_DIR}/wayland_protocols/) + set_source_files_properties(${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c GENERATED) +else() + set(Wayland_Client_FOUND FALSE) +endif() + find_package(XKB 0.4.1) set_package_properties(XKB PROPERTIES TYPE OPTIONAL @@ -396,6 +428,8 @@ if(Wayland_Client_FOUND AND XKB_FOUND) wayland_backend.cpp wayland_client/connection_thread.cpp wayland_client/registry.cpp + wayland_client/fullscreen_shell.cpp + ${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c ) if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND) set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} egl_wayland_backend.cpp) diff --git a/autotests/wayland_client/CMakeLists.txt b/autotests/wayland_client/CMakeLists.txt index 020ff068e3..c8fff047bf 100644 --- a/autotests/wayland_client/CMakeLists.txt +++ b/autotests/wayland_client/CMakeLists.txt @@ -1,3 +1,5 @@ +include_directories(${CMAKE_BINARY_DIR}/wayland_protocols/) +set_source_files_properties(${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c GENERATED) ######################################################## # Test WaylandConnectionThread ######################################################## @@ -14,8 +16,26 @@ set( testWaylandRegistry_SRCS test_wayland_registry.cpp ${KWIN_SOURCE_DIR}/wayland_client/connection_thread.cpp ${KWIN_SOURCE_DIR}/wayland_client/registry.cpp + ${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c ) add_executable(testWaylandRegistry ${testWaylandRegistry_SRCS}) +add_dependencies(testWaylandRegistry wayland-client-fullscreen-shell) target_link_libraries( testWaylandRegistry Qt5::Test Wayland::Client) add_test(kwin-testWaylandRegistry testWaylandRegistry) ecm_mark_as_test(testWaylandRegistry) + +######################################################## +# Test WaylandFullscreenShell +######################################################## +set( testWaylandFullscreenShell_SRCS + test_wayland_fullscreen_shell.cpp + ${KWIN_SOURCE_DIR}/wayland_client/connection_thread.cpp + ${KWIN_SOURCE_DIR}/wayland_client/registry.cpp + ${KWIN_SOURCE_DIR}/wayland_client/fullscreen_shell.cpp + ${CMAKE_BINARY_DIR}/wayland_protocols/wayland-client-fullscreen-shell.c + ) +add_executable(testWaylandFullscreenShell ${testWaylandFullscreenShell_SRCS}) +add_dependencies(testWaylandFullscreenShell wayland-client-fullscreen-shell) +target_link_libraries( testWaylandFullscreenShell Qt5::Test Wayland::Client) +add_test(kwin-testWaylandFullscreenShell testWaylandFullscreenShell) +ecm_mark_as_test(testWaylandFullscreenShell) diff --git a/autotests/wayland_client/test_wayland_fullscreen_shell.cpp b/autotests/wayland_client/test_wayland_fullscreen_shell.cpp new file mode 100644 index 0000000000..f0257a0217 --- /dev/null +++ b/autotests/wayland_client/test_wayland_fullscreen_shell.cpp @@ -0,0 +1,123 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright (C) 2014 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +// Qt +#include +// KWin +#include "../../wayland_client/connection_thread.h" +#include "../../wayland_client/registry.h" +#include "../../wayland_client/fullscreen_shell.h" +// Wayland +#include + +class TestWaylandFullscreenShell : public QObject +{ + Q_OBJECT +public: + explicit TestWaylandFullscreenShell(QObject *parent = nullptr); +private Q_SLOTS: + void init(); + void cleanup(); + + void testRegistry(); + + // TODO: add tests for removal - requires more control over the compositor + +private: + QProcess *m_westonProcess; +}; + +static const QString s_socketName = QStringLiteral("kwin-test-wayland-fullscreen-shell-0"); + +TestWaylandFullscreenShell::TestWaylandFullscreenShell(QObject *parent) + : QObject(parent) + , m_westonProcess(nullptr) +{ +} + +void TestWaylandFullscreenShell::init() +{ + QVERIFY(!m_westonProcess); + // starts weston + m_westonProcess = new QProcess(this); + m_westonProcess->setProgram(QStringLiteral("weston")); + + m_westonProcess->setArguments(QStringList({QStringLiteral("--socket=%1").arg(s_socketName), + QStringLiteral("--use-pixman"), + QStringLiteral("--shell=fullscreen-shell.so")})); + m_westonProcess->start(); + QVERIFY(m_westonProcess->waitForStarted()); + + // wait for the socket to appear + QDir runtimeDir(qgetenv("XDG_RUNTIME_DIR")); + if (runtimeDir.exists(s_socketName)) { + return; + } + QFileSystemWatcher *socketWatcher = new QFileSystemWatcher(QStringList({runtimeDir.absolutePath()}), this); + QSignalSpy socketSpy(socketWatcher, SIGNAL(directoryChanged(QString))); + + // limit to maximum of 10 waits + for (int i = 0; i < 10; ++i) { + QVERIFY(socketSpy.wait()); + if (runtimeDir.exists(s_socketName)) { + delete socketWatcher; + return; + } + } +} + +void TestWaylandFullscreenShell::cleanup() +{ + // terminates weston + m_westonProcess->terminate(); + QVERIFY(m_westonProcess->waitForFinished()); + delete m_westonProcess; + m_westonProcess = nullptr; +} + +void TestWaylandFullscreenShell::testRegistry() +{ + if (m_westonProcess->state() != QProcess::Running) { + QSKIP("This test requires a running wayland server"); + } + KWin::Wayland::ConnectionThread connection; + QSignalSpy connectedSpy(&connection, SIGNAL(connected())); + connection.setSocketName(s_socketName); + connection.initConnection(); + QVERIFY(connectedSpy.wait()); + + KWin::Wayland::Registry registry; + QSignalSpy announced(®istry, SIGNAL(fullscreenShellAnnounced(quint32,quint32))); + registry.create(connection.display()); + QVERIFY(registry.isValid()); + registry.setup(); + wl_display_flush(connection.display()); + QVERIFY(announced.wait()); + + KWin::Wayland::FullscreenShell fullscreenShell; + QVERIFY(!fullscreenShell.isValid()); + QVERIFY(!fullscreenShell.hasCapabilityArbitraryModes()); + QVERIFY(!fullscreenShell.hasCapabilityCursorPlane()); + + fullscreenShell.setup(registry.bindFullscreenShell(announced.first().first().value(), 1)); + QVERIFY(fullscreenShell.isValid()); +} + +QTEST_MAIN(TestWaylandFullscreenShell) +#include "test_wayland_fullscreen_shell.moc" diff --git a/wayland_backend.cpp b/wayland_backend.cpp index c2686e9f8d..9321f74bf1 100644 --- a/wayland_backend.cpp +++ b/wayland_backend.cpp @@ -23,6 +23,7 @@ along with this program. If not, see . #include "cursor.h" #include "input.h" #include "wayland_client/connection_thread.h" +#include "wayland_client/fullscreen_shell.h" #include "wayland_client/registry.h" // Qt #include @@ -705,6 +706,7 @@ WaylandBackend::WaylandBackend(QObject *parent) , m_shm() , m_connectionThreadObject(nullptr) , m_connectionThread(nullptr) + , m_fullscreenShell(new FullscreenShell(this)) { connect(m_registry, &Registry::compositorAnnounced, this, [this](quint32 name) { @@ -723,6 +725,12 @@ WaylandBackend::WaylandBackend(QObject *parent) ); connect(m_registry, &Registry::seatAnnounced, this, &WaylandBackend::createSeat); connect(m_registry, &Registry::shmAnnounced, this, &WaylandBackend::createShm); + connect(m_registry, &Registry::fullscreenShellAnnounced, this, + [this](quint32 name, quint32 version) { + m_fullscreenShell->setup(m_registry->bindFullscreenShell(name, version)); + createSurface(); + } + ); initConnection(); } @@ -732,6 +740,7 @@ WaylandBackend::~WaylandBackend() if (m_shellSurface) { wl_shell_surface_destroy(m_shellSurface); } + m_fullscreenShell->release(); if (m_surface) { wl_surface_destroy(m_surface); } @@ -793,6 +802,7 @@ void WaylandBackend::initConnection() free(m_shellSurface); m_shellSurface = nullptr; } + m_fullscreenShell->destroy(); if (m_surface) { free(m_surface); m_surface = nullptr; @@ -840,10 +850,25 @@ void WaylandBackend::createSurface() qCritical() << "Creating Wayland Surface failed"; return; } - // map the surface as fullscreen - m_shellSurface = wl_shell_get_shell_surface(m_shell, m_surface); - wl_shell_surface_add_listener(m_shellSurface, &s_shellSurfaceListener, this); - wl_shell_surface_set_fullscreen(m_shellSurface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); + if (m_fullscreenShell->isValid()) { + Output *o = m_outputs.first(); + if (o->pixelSize().isValid()) { + setShellSurfaceSize(o->pixelSize()); + } + connect(o, &Output::changed, this, + [this, o]() { + if (o->pixelSize().isValid()) { + setShellSurfaceSize(o->pixelSize()); + } + } + ); + m_fullscreenShell->present(m_surface, o->output()); + } else { + // map the surface as fullscreen + m_shellSurface = wl_shell_get_shell_surface(m_shell, m_surface); + wl_shell_surface_add_listener(m_shellSurface, &s_shellSurfaceListener, this); + wl_shell_surface_set_fullscreen(m_shellSurface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); + } emit backendReady(); } diff --git a/wayland_backend.h b/wayland_backend.h index 9fbaff944e..46cf86b4f1 100644 --- a/wayland_backend.h +++ b/wayland_backend.h @@ -47,6 +47,7 @@ class ShmPool; class WaylandBackend; class WaylandSeat; class ConnectionThread; +class FullscreenShell; class Registry; class CursorData @@ -253,6 +254,7 @@ private: QList m_outputs; ConnectionThread *m_connectionThreadObject; QThread *m_connectionThread; + FullscreenShell *m_fullscreenShell; KWIN_SINGLETON(WaylandBackend) }; diff --git a/wayland_client/fullscreen_shell.cpp b/wayland_client/fullscreen_shell.cpp new file mode 100644 index 0000000000..be3c795059 --- /dev/null +++ b/wayland_client/fullscreen_shell.cpp @@ -0,0 +1,96 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2014 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "fullscreen_shell.h" + +#include + +namespace KWin +{ +namespace Wayland +{ + +FullscreenShell::FullscreenShell(QObject *parent) + : QObject(parent) + , m_shell(nullptr) + , m_capabilityArbitraryModes(false) + , m_capabilityCursorPlane(false) +{ +} + +FullscreenShell::~FullscreenShell() +{ + release(); +} + +void FullscreenShell::release() +{ + if (m_shell) { + _wl_fullscreen_shell_release(m_shell); + m_shell = nullptr; + } +} + +void FullscreenShell::destroy() +{ + if (m_shell) { + free(m_shell); + m_shell = nullptr; + } +} + +_wl_fullscreen_shell_listener FullscreenShell::s_fullscreenShellListener = { + FullscreenShell::capabilitiesAnnounce +}; + +void FullscreenShell::setup(_wl_fullscreen_shell *shell) +{ + Q_ASSERT(!m_shell); + Q_ASSERT(shell); + m_shell = shell; + _wl_fullscreen_shell_add_listener(m_shell, &s_fullscreenShellListener, this); +} + +void FullscreenShell::capabilitiesAnnounce(void *data, _wl_fullscreen_shell *shell, uint32_t capability) +{ + FullscreenShell *s = reinterpret_cast(data); + Q_ASSERT(shell == s->m_shell); + s->handleCapabilities(capability); +} + +void FullscreenShell::handleCapabilities(uint32_t capability) +{ + if (capability & _WL_FULLSCREEN_SHELL_CAPABILITY_ARBITRARY_MODES) { + m_capabilityArbitraryModes = true; + emit capabilityArbitraryModesChanged(m_capabilityArbitraryModes); + } + if (capability & _WL_FULLSCREEN_SHELL_CAPABILITY_CURSOR_PLANE) { + m_capabilityCursorPlane = true; + emit capabilityCursorPlaneChanged(m_capabilityCursorPlane); + } +} + +void FullscreenShell::present(wl_surface *surface, wl_output *output) +{ + Q_ASSERT(m_shell); + _wl_fullscreen_shell_present_surface(m_shell, surface, _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT, output); +} + +} +} diff --git a/wayland_client/fullscreen_shell.h b/wayland_client/fullscreen_shell.h new file mode 100644 index 0000000000..11aa91c5d4 --- /dev/null +++ b/wayland_client/fullscreen_shell.h @@ -0,0 +1,73 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2014 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWIN_WAYLAND_FULLSCREEN_SHELL_H +#define KWIN_WAYLAND_FULLSCREEN_SHELL_H + +#include + +#include +#include + +namespace KWin +{ +namespace Wayland +{ + +class FullscreenShell : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool capabilityArbitraryModes READ hasCapabilityArbitraryModes NOTIFY capabilityArbitraryModesChanged) + Q_PROPERTY(bool capabilityCursorPlane READ hasCapabilityCursorPlane NOTIFY capabilityCursorPlaneChanged) +public: + explicit FullscreenShell(QObject *parent = nullptr); + virtual ~FullscreenShell(); + + bool isValid() const { + return m_shell != nullptr; + } + void release(); + void destroy(); + bool hasCapabilityArbitraryModes() const { + return m_capabilityArbitraryModes; + } + bool hasCapabilityCursorPlane() const { + return m_capabilityCursorPlane; + } + void setup(_wl_fullscreen_shell *shell); + void present(wl_surface *surface, wl_output *output); + + static void capabilitiesAnnounce(void *data, struct _wl_fullscreen_shell *shell, uint32_t capability); + +Q_SIGNALS: + void capabilityArbitraryModesChanged(bool); + void capabilityCursorPlaneChanged(bool); + +private: + void handleCapabilities(uint32_t capability); + _wl_fullscreen_shell *m_shell; + bool m_capabilityArbitraryModes; + bool m_capabilityCursorPlane; + static _wl_fullscreen_shell_listener s_fullscreenShellListener; +}; + +} +} + +#endif diff --git a/wayland_client/protocols/fullscreen-shell.xml b/wayland_client/protocols/fullscreen-shell.xml new file mode 100644 index 0000000000..939c2ba187 --- /dev/null +++ b/wayland_client/protocols/fullscreen-shell.xml @@ -0,0 +1,206 @@ + + + + Displays a single surface per output. + + This interface provides a mechanism for a single client to display + simple full-screen surfaces. While there technically may be multiple + clients bound to this interface, only one of those clients should be + shown at a time. + + To present a surface, the client uses either the present_surface or + present_surface_for_mode requests. Presenting a surface takes effect + on the next wl_surface.commit. See the individual requests for + details about scaling and mode switches. + + The client can have at most one surface per output at any time. + Requesting a surface be presented on an output that already has a + surface replaces the previously presented surface. Presenting a null + surface removes its content and effectively disables the output. + Exactly what happens when an output is "disabled" is + compositor-specific. The same surface may be presented on multiple + outputs simultaneously. + + Once a surface is presented on an output, it stays on that output + until either the client removes it or the compositor destroys the + output. This way, the client can update the output's contents by + simply attaching a new buffer. + + + + + Release the binding from the wl_fullscreen_shell interface + + This destroys the server-side object and frees this binding. If + the client binds to wl_fullscreen_shell multiple times, it may wish + to free some of those bindings. + + + + + + Various capabilities that can be advertised by the compositor. They + are advertised one-at-a-time when the wl_fullscreen_shell interface is + bound. See the wl_fullscreen_shell.capability event for more details. + + ARBITRARY_MODE: + This is a hint to the client that indicates that the compositor is + capable of setting practially any mode on its outputs. If this + capability is provided, wl_fullscreen_shell.present_surface_for_mode + will almost never fail and clients should feel free to set whatever + mode they like. If the compositor does not advertise this, it may + still support some modes that are not advertised through wl_global.mode + but it is less likely. + + CURSOR_PLANE: + This is a hint to the client that indicates that the compositor can + handle a cursor surface from the client without actually compositing. + This may be because of a hardware cursor plane or some other mechanism. + If the compositor does not advertise this capability then setting + wl_pointer.cursor may degrade performance or be ignored entirely. If + CURSOR_PLANE is not advertised, it is recommended that the client draw + its own cursor and set wl_pointer.cursor(NULL). + + + + + + + + Advertises a single capability of the compositor. + + When the wl_fullscreen_shell interface is bound, this event is emitted + once for each capability advertised. Valid capabilities are given by + the wl_fullscreen_shell.capability enum. If clients want to take + advantage of any of these capabilities, they sould use a + wl_display.sync request immediatly after binding to ensure that they + recieve all the capability events. + + + + + + + Hints to indicate to the compositor how to deal with a conflict + between the dimensions of the surface and the dimensions of the + output. The compositor is free to ignore this parameter. + + + + + + + + + + + Present a surface on the given output. + + If the output is null, the compositor will present the surface on + whatever display (or displays) it thinks best. In particular, this + may replace any or all surfaces currently presented so it should + not be used in combination with placing surfaces on specific + outputs. + + The method parameter is a hint to the compositor for how the surface + is to be presented. In particular, it tells the compostior how to + handle a size mismatch between the presented surface and the + output. The compositor is free to ignore this parameter. + + The "zoom", "zoom_crop", and "stretch" methods imply a scaling + operation on the surface. This will override any kind of output + scaling, so the buffer_scale property of the surface is effectively + ignored. + + + + + + + + + Presents a surface on the given output for a particular mode. + + If the current size of the output differs from that of the surface, + the compositor will attempt to change the size of the output to + match the surface. The result of the mode-switch operation will be + returned via the provided wl_fullscreen_shell_mode_feedback object. + + If the current output mode matches the one requested or if the + compositor successfully switches the mode to match the surface, + then the mode_successful event will be sent and the output will + contain the contents of the given surface. If the compositor + cannot match the output size to the surface size, the mode_failed + will be sent and the output will contain the contents of the + previously presented surface (if any). If another surface is + presented on the given output before either of these has a chance + to happen, the present_cancelled event will be sent. + + Due to race conditions and other issues unknown to the client, no + mode-switch operation is guaranteed to succeed. However, if the + mode is one advertised by wl_output.mode or if the compositor + advertises the ARBITRARY_MODES capability, then the client should + expect that the mode-switch operation will usually succeed. + + If the size of the presented surface changes, the resulting output + is undefined. The compositor may attempt to change the output mode + to compensate. However, there is no guarantee that a suitable mode + will be found and the client has no way to be notified of success + or failure. + + The framerate parameter specifies the desired framerate for the + output in mHz. The compositor is free to ignore this parameter. A + value of 0 indicates that the client has no preference. + + If the value of wl_output.scale differs from wl_surface.buffer_scale, + then the compositor may choose a mode that matches either the buffer + size or the surface size. In either case, the surface will fill the + output. + + + + + + + + + + These errors can be emitted in response to wl_fullscreen_shell requests + + + + + + + + + This event indicates that the attempted mode switch operation was + successful. A surface of the size requested in the mode switch + will fill the output without scaling. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + + This event indicates that the attempted mode switch operation + failed. This may be because the requested output mode is not + possible or it may mean that the compositor does not want to allow it. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + + This event indicates that the attempted mode switch operation was + cancelled. Most likely this is because the client requested a + second mode switch before the first one completed. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + diff --git a/wayland_client/registry.cpp b/wayland_client/registry.cpp index d03e747f28..d97fc88dfa 100644 --- a/wayland_client/registry.cpp +++ b/wayland_client/registry.cpp @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "registry.h" +#include #include @@ -97,6 +98,8 @@ static Registry::Interface nameToInterface(const char *interface) return Registry::Interface::Shm; } else if (strcmp(interface, "wl_output") == 0) { return Registry::Interface::Output; + } else if (strcmp(interface, "_wl_fullscreen_shell") == 0) { + return Registry::Interface::FullscreenShell; } return Registry::Interface::Unknown; } @@ -126,6 +129,9 @@ void Registry::handleAnnounce(uint32_t name, const char *interface, uint32_t ver case Interface::Shm: emit shmAnnounced(name, version); break; + case Interface::FullscreenShell: + emit fullscreenShellAnnounced(name, version); + break; case Interface::Unknown: default: // nothing @@ -159,6 +165,9 @@ void Registry::handleRemove(uint32_t name) case Interface::Shm: emit shmRemoved(data.name); break; + case Interface::FullscreenShell: + emit fullscreenShellRemoved(data.name); + break; case Interface::Unknown: default: // nothing @@ -202,6 +211,11 @@ wl_shm *Registry::bindShm(uint32_t name, uint32_t version) const return reinterpret_cast(bind(Interface::Shm, name, version)); } +_wl_fullscreen_shell *Registry::bindFullscreenShell(uint32_t name, uint32_t version) const +{ + return reinterpret_cast<_wl_fullscreen_shell*>(bind(Interface::FullscreenShell, name, version)); +} + static const wl_interface *wlInterface(Registry::Interface interface) { switch (interface) { @@ -215,6 +229,8 @@ static const wl_interface *wlInterface(Registry::Interface interface) return &wl_shell_interface; case Registry::Interface::Shm: return &wl_shm_interface; + case Registry::Interface::FullscreenShell: + return &_wl_fullscreen_shell_interface; case Registry::Interface::Unknown: default: return nullptr; diff --git a/wayland_client/registry.h b/wayland_client/registry.h index a9f16d83bd..2856657b89 100644 --- a/wayland_client/registry.h +++ b/wayland_client/registry.h @@ -25,6 +25,8 @@ along with this program. If not, see . #include +struct _wl_fullscreen_shell; + namespace KWin { namespace Wayland @@ -40,6 +42,7 @@ public: Seat, // wl_seat Shm, // wl_shm Output, // wl_output + FullscreenShell, // _wl_fullscreen_shell Unknown }; explicit Registry(QObject *parent = nullptr); @@ -60,6 +63,7 @@ public: wl_seat *bindSeat(uint32_t name, uint32_t version) const; wl_shm *bindShm(uint32_t name, uint32_t version) const; wl_output *bindOutput(uint32_t name, uint32_t version) const; + _wl_fullscreen_shell *bindFullscreenShell(uint32_t name, uint32_t version) const; operator wl_registry*() { return m_registry; @@ -80,11 +84,13 @@ Q_SIGNALS: void seatAnnounced(quint32 name, quint32 version); void shmAnnounced(quint32 name, quint32 version); void outputAnnounced(quint32 name, quint32 version); + void fullscreenShellAnnounced(quint32 name, quint32 version); void compositorRemoved(quint32 name); void shellRemoved(quint32 name); void seatRemoved(quint32 name); void shmRemoved(quint32 name); void outputRemoved(quint32 name); + void fullscreenShellRemoved(quint32 name); private: static const struct wl_registry_listener s_registryListener;