backends/wayland: Merge WaylandOutput and XdgShellOutput
This commit is contained in:
parent
d4676cceb3
commit
6951d662d6
4 changed files with 77 additions and 146 deletions
|
@ -13,7 +13,6 @@
|
|||
#include "wayland_egl_backend.h"
|
||||
#include <gbm.h>
|
||||
#endif
|
||||
#include "core/renderloop_p.h"
|
||||
#include "wayland_display.h"
|
||||
#include "wayland_logging.h"
|
||||
#include "wayland_output.h"
|
||||
|
@ -35,7 +34,6 @@
|
|||
#include <KWayland/Client/pointergestures.h>
|
||||
#include <KWayland/Client/relativepointer.h>
|
||||
#include <KWayland/Client/seat.h>
|
||||
#include <KWayland/Client/server_decoration.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
#include <KWayland/Client/subcompositor.h>
|
||||
#include <KWayland/Client/subsurface.h>
|
||||
|
@ -631,27 +629,7 @@ void WaylandBackend::createOutputs()
|
|||
|
||||
WaylandOutput *WaylandBackend::createOutput(const QString &name, const QSize &size)
|
||||
{
|
||||
std::unique_ptr<KWayland::Client::Surface> surface{m_display->compositor()->createSurface()};
|
||||
if (!surface || !surface->isValid()) {
|
||||
qCCritical(KWIN_WAYLAND_BACKEND) << "Creating Wayland Surface failed";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (KWayland::Client::ServerSideDecorationManager *ssdManager = m_display->serverSideDecorationManager()) {
|
||||
auto decoration = ssdManager->create(surface.get(), surface.get());
|
||||
connect(decoration, &ServerSideDecoration::modeChanged, this, [decoration] {
|
||||
if (decoration->mode() != ServerSideDecoration::Mode::Server) {
|
||||
decoration->requestMode(ServerSideDecoration::Mode::Server);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
XdgShellOutput *waylandOutput = waylandOutput = new XdgShellOutput(name, std::move(surface), m_display->xdgShell(), this, m_nextId++);
|
||||
if (!waylandOutput) {
|
||||
qCCritical(KWIN_WAYLAND_BACKEND) << "Binding to all shell interfaces failed for output";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WaylandOutput *waylandOutput = new WaylandOutput(name, this);
|
||||
waylandOutput->init(size);
|
||||
|
||||
// Wait until the output window is configured by the host compositor.
|
||||
|
@ -659,14 +637,6 @@ WaylandOutput *WaylandBackend::createOutput(const QString &name, const QSize &si
|
|||
wl_display_roundtrip(m_display->nativeDisplay());
|
||||
}
|
||||
|
||||
connect(waylandOutput, &WaylandOutput::frameRendered, this, [waylandOutput]() {
|
||||
// The current time of the monotonic clock is a pretty good estimate when the frame
|
||||
// has been presented, however it will be much better if we check whether the host
|
||||
// compositor supports the wp_presentation protocol.
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(waylandOutput->renderLoop());
|
||||
renderLoopPrivate->notifyFrameCompleted(std::chrono::steady_clock::now().time_since_epoch());
|
||||
});
|
||||
|
||||
return waylandOutput;
|
||||
}
|
||||
|
||||
|
@ -752,16 +722,6 @@ void WaylandBackend::togglePointerLock()
|
|||
flush();
|
||||
}
|
||||
|
||||
bool WaylandBackend::pointerIsLocked()
|
||||
{
|
||||
for (auto *output : std::as_const(m_outputs)) {
|
||||
if (output->pointerIsLocked()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVector<CompositingType> WaylandBackend::supportedCompositors() const
|
||||
{
|
||||
#if HAVE_WAYLAND_EGL
|
||||
|
|
|
@ -252,7 +252,6 @@ public:
|
|||
|
||||
bool supportsPointerLock();
|
||||
void togglePointerLock();
|
||||
bool pointerIsLocked();
|
||||
|
||||
QVector<CompositingType> supportedCompositors() const override;
|
||||
|
||||
|
@ -298,7 +297,6 @@ private:
|
|||
std::unique_ptr<WaylandCursor> m_waylandCursor;
|
||||
std::unique_ptr<DpmsInputEventFilter> m_dpmsFilter;
|
||||
bool m_pointerLockRequested = false;
|
||||
int m_nextId = 0;
|
||||
#if HAVE_WAYLAND_EGL
|
||||
FileDescriptor m_drmFileDescriptor;
|
||||
gbm_device *m_gbmDevice;
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "wayland_output.h"
|
||||
#include "core/renderloop.h"
|
||||
#include "core/renderloop_p.h"
|
||||
#include "wayland_backend.h"
|
||||
#include "wayland_display.h"
|
||||
#include "wayland_server.h"
|
||||
|
||||
#include <KWayland/Client/compositor.h>
|
||||
#include <KWayland/Client/pointerconstraints.h>
|
||||
#include <KWayland/Client/server_decoration.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
@ -25,31 +27,80 @@ namespace Wayland
|
|||
using namespace KWayland::Client;
|
||||
static const int s_refreshRate = 60000; // TODO: can we get refresh rate data from Wayland host?
|
||||
|
||||
WaylandOutput::WaylandOutput(const QString &name, std::unique_ptr<Surface> &&surface, WaylandBackend *backend)
|
||||
WaylandOutput::WaylandOutput(const QString &name, WaylandBackend *backend)
|
||||
: Output(backend)
|
||||
, m_renderLoop(std::make_unique<RenderLoop>())
|
||||
, m_surface(std::move(surface))
|
||||
, m_surface(backend->display()->compositor()->createSurface())
|
||||
, m_xdgShellSurface(backend->display()->xdgShell()->createSurface(m_surface.get()))
|
||||
, m_backend(backend)
|
||||
{
|
||||
if (KWayland::Client::ServerSideDecorationManager *ssdManager = backend->display()->serverSideDecorationManager()) {
|
||||
m_serverDecoration.reset(ssdManager->create(m_surface.get()));
|
||||
connect(m_serverDecoration.get(), &KWayland::Client::ServerSideDecoration::modeChanged, this, [this] {
|
||||
if (m_serverDecoration->mode() != KWayland::Client::ServerSideDecoration::Mode::Server) {
|
||||
m_serverDecoration->requestMode(KWayland::Client::ServerSideDecoration::Mode::Server);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setInformation(Information{
|
||||
.name = name,
|
||||
.model = name,
|
||||
.capabilities = Capability::Dpms,
|
||||
});
|
||||
|
||||
connect(m_surface.get(), &Surface::frameRendered, this, &WaylandOutput::frameRendered);
|
||||
m_turnOffTimer.setSingleShot(true);
|
||||
m_turnOffTimer.setInterval(dimAnimationTime());
|
||||
connect(&m_turnOffTimer, &QTimer::timeout, this, [this] {
|
||||
updateDpmsMode(DpmsMode::Off);
|
||||
});
|
||||
|
||||
connect(m_surface.get(), &KWayland::Client::Surface::frameRendered, this, [this]() {
|
||||
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(renderLoop());
|
||||
renderLoopPrivate->notifyFrameCompleted(std::chrono::steady_clock::now().time_since_epoch());
|
||||
});
|
||||
|
||||
updateWindowTitle();
|
||||
|
||||
connect(m_xdgShellSurface.get(), &XdgShellSurface::configureRequested, this, &WaylandOutput::handleConfigure);
|
||||
connect(m_xdgShellSurface.get(), &XdgShellSurface::closeRequested, qApp, &QCoreApplication::quit);
|
||||
connect(this, &WaylandOutput::enabledChanged, this, &WaylandOutput::updateWindowTitle);
|
||||
connect(this, &WaylandOutput::dpmsModeChanged, this, &WaylandOutput::updateWindowTitle);
|
||||
|
||||
connect(backend, &WaylandBackend::pointerLockSupportedChanged, this, &WaylandOutput::updateWindowTitle);
|
||||
connect(backend, &WaylandBackend::pointerLockChanged, this, [this](bool locked) {
|
||||
if (locked) {
|
||||
if (!m_hasPointerLock) {
|
||||
// some other output has locked the pointer
|
||||
// this surface can stop trying to lock the pointer
|
||||
lockPointer(nullptr, false);
|
||||
// set it true for the other surface
|
||||
m_hasPointerLock = true;
|
||||
}
|
||||
} else {
|
||||
// just try unlocking
|
||||
lockPointer(nullptr, false);
|
||||
}
|
||||
updateWindowTitle();
|
||||
});
|
||||
}
|
||||
|
||||
WaylandOutput::~WaylandOutput()
|
||||
{
|
||||
m_xdgShellSurface->destroy();
|
||||
m_surface->destroy();
|
||||
}
|
||||
|
||||
bool WaylandOutput::isReady() const
|
||||
{
|
||||
return m_ready;
|
||||
}
|
||||
|
||||
KWayland::Client::Surface *WaylandOutput::surface() const
|
||||
{
|
||||
return m_surface.get();
|
||||
}
|
||||
|
||||
RenderLoop *WaylandOutput::renderLoop() const
|
||||
{
|
||||
return m_renderLoop.get();
|
||||
|
@ -66,6 +117,8 @@ void WaylandOutput::init(const QSize &pixelSize)
|
|||
initialState.currentMode = mode;
|
||||
initialState.scale = m_backend->initialOutputScale();
|
||||
setState(initialState);
|
||||
|
||||
m_surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
}
|
||||
|
||||
void WaylandOutput::resize(const QSize &pixelSize)
|
||||
|
@ -113,49 +166,7 @@ void WaylandOutput::updateEnabled(bool enabled)
|
|||
setState(next);
|
||||
}
|
||||
|
||||
XdgShellOutput::XdgShellOutput(const QString &name, std::unique_ptr<Surface> &&waylandSurface, XdgShell *xdgShell, WaylandBackend *backend, int number)
|
||||
: WaylandOutput(name, std::move(waylandSurface), backend)
|
||||
, m_xdgShellSurface(xdgShell->createSurface(surface()))
|
||||
, m_number(number)
|
||||
{
|
||||
updateWindowTitle();
|
||||
|
||||
connect(m_xdgShellSurface.get(), &XdgShellSurface::configureRequested, this, &XdgShellOutput::handleConfigure);
|
||||
connect(m_xdgShellSurface.get(), &XdgShellSurface::closeRequested, qApp, &QCoreApplication::quit);
|
||||
connect(this, &WaylandOutput::enabledChanged, this, &XdgShellOutput::updateWindowTitle);
|
||||
connect(this, &WaylandOutput::dpmsModeChanged, this, &XdgShellOutput::updateWindowTitle);
|
||||
|
||||
connect(backend, &WaylandBackend::pointerLockSupportedChanged, this, &XdgShellOutput::updateWindowTitle);
|
||||
connect(backend, &WaylandBackend::pointerLockChanged, this, [this](bool locked) {
|
||||
if (locked) {
|
||||
if (!m_hasPointerLock) {
|
||||
// some other output has locked the pointer
|
||||
// this surface can stop trying to lock the pointer
|
||||
lockPointer(nullptr, false);
|
||||
// set it true for the other surface
|
||||
m_hasPointerLock = true;
|
||||
}
|
||||
} else {
|
||||
// just try unlocking
|
||||
lockPointer(nullptr, false);
|
||||
}
|
||||
updateWindowTitle();
|
||||
});
|
||||
|
||||
surface()->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
}
|
||||
|
||||
XdgShellOutput::~XdgShellOutput()
|
||||
{
|
||||
m_xdgShellSurface->destroy();
|
||||
}
|
||||
|
||||
bool XdgShellOutput::isReady() const
|
||||
{
|
||||
return m_ready;
|
||||
}
|
||||
|
||||
void XdgShellOutput::handleConfigure(const QSize &size, XdgShellSurface::States states, quint32 serial)
|
||||
void WaylandOutput::handleConfigure(const QSize &size, XdgShellSurface::States states, quint32 serial)
|
||||
{
|
||||
m_xdgShellSurface->ackConfigure(serial);
|
||||
if (size.width() > 0 && size.height() > 0) {
|
||||
|
@ -168,17 +179,17 @@ void XdgShellOutput::handleConfigure(const QSize &size, XdgShellSurface::States
|
|||
m_ready = true;
|
||||
}
|
||||
|
||||
void XdgShellOutput::updateWindowTitle()
|
||||
void WaylandOutput::updateWindowTitle()
|
||||
{
|
||||
QString grab;
|
||||
if (m_hasPointerLock) {
|
||||
grab = i18n("Press right control to ungrab pointer");
|
||||
} else if (backend()->display()->pointerConstraints()) {
|
||||
} else if (m_backend->display()->pointerConstraints()) {
|
||||
grab = i18n("Press right control key to grab pointer");
|
||||
}
|
||||
|
||||
QString title = i18nc("Title of nested KWin Wayland with Wayland socket identifier as argument",
|
||||
"KDE Wayland Compositor #%1 (%2)", m_number, waylandServer()->socketName());
|
||||
"KDE Wayland Compositor %1 (%2)", name(), waylandServer()->socketName());
|
||||
|
||||
if (!isEnabled()) {
|
||||
title += i18n("- Output disabled");
|
||||
|
@ -190,32 +201,32 @@ void XdgShellOutput::updateWindowTitle()
|
|||
m_xdgShellSurface->setTitle(title);
|
||||
}
|
||||
|
||||
void XdgShellOutput::lockPointer(Pointer *pointer, bool lock)
|
||||
void WaylandOutput::lockPointer(Pointer *pointer, bool lock)
|
||||
{
|
||||
if (!lock) {
|
||||
const bool surfaceWasLocked = m_pointerLock && m_hasPointerLock;
|
||||
m_pointerLock.reset();
|
||||
m_hasPointerLock = false;
|
||||
if (surfaceWasLocked) {
|
||||
Q_EMIT backend()->pointerLockChanged(false);
|
||||
Q_EMIT m_backend->pointerLockChanged(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Q_ASSERT(!m_pointerLock);
|
||||
m_pointerLock.reset(backend()->display()->pointerConstraints()->lockPointer(surface(), pointer, nullptr, PointerConstraints::LifeTime::OneShot));
|
||||
m_pointerLock.reset(m_backend->display()->pointerConstraints()->lockPointer(surface(), pointer, nullptr, PointerConstraints::LifeTime::OneShot));
|
||||
if (!m_pointerLock->isValid()) {
|
||||
m_pointerLock.reset();
|
||||
return;
|
||||
}
|
||||
connect(m_pointerLock.get(), &LockedPointer::locked, this, [this]() {
|
||||
m_hasPointerLock = true;
|
||||
Q_EMIT backend()->pointerLockChanged(true);
|
||||
Q_EMIT m_backend->pointerLockChanged(true);
|
||||
});
|
||||
connect(m_pointerLock.get(), &LockedPointer::unlocked, this, [this]() {
|
||||
m_pointerLock.reset();
|
||||
m_hasPointerLock = false;
|
||||
Q_EMIT backend()->pointerLockChanged(false);
|
||||
Q_EMIT m_backend->pointerLockChanged(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,9 @@ namespace KWayland
|
|||
namespace Client
|
||||
{
|
||||
class Surface;
|
||||
|
||||
class Shell;
|
||||
class ShellSurface;
|
||||
|
||||
class Pointer;
|
||||
class LockedPointer;
|
||||
class ServerSideDecoration;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,71 +36,36 @@ class WaylandOutput : public Output
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WaylandOutput(const QString &name, std::unique_ptr<KWayland::Client::Surface> &&surface, WaylandBackend *backend);
|
||||
WaylandOutput(const QString &name, WaylandBackend *backend);
|
||||
~WaylandOutput() override;
|
||||
|
||||
RenderLoop *renderLoop() const override;
|
||||
|
||||
void init(const QSize &pixelSize);
|
||||
|
||||
virtual void lockPointer(KWayland::Client::Pointer *pointer, bool lock)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool pointerIsLocked()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool isReady() const;
|
||||
KWayland::Client::Surface *surface() const;
|
||||
|
||||
void lockPointer(KWayland::Client::Pointer *pointer, bool lock);
|
||||
void resize(const QSize &pixelSize);
|
||||
|
||||
KWayland::Client::Surface *surface() const
|
||||
{
|
||||
return m_surface.get();
|
||||
}
|
||||
|
||||
void setDpmsMode(DpmsMode mode) override;
|
||||
|
||||
void updateDpmsMode(DpmsMode dpmsMode);
|
||||
void updateEnabled(bool enabled);
|
||||
|
||||
Q_SIGNALS:
|
||||
void sizeChanged(const QSize &size);
|
||||
void frameRendered();
|
||||
|
||||
protected:
|
||||
WaylandBackend *backend()
|
||||
{
|
||||
return m_backend;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<RenderLoop> m_renderLoop;
|
||||
std::unique_ptr<KWayland::Client::Surface> m_surface;
|
||||
WaylandBackend *m_backend;
|
||||
QTimer m_turnOffTimer;
|
||||
};
|
||||
|
||||
class XdgShellOutput : public WaylandOutput
|
||||
{
|
||||
public:
|
||||
XdgShellOutput(const QString &name,
|
||||
std::unique_ptr<KWayland::Client::Surface> &&surface,
|
||||
KWayland::Client::XdgShell *xdgShell,
|
||||
WaylandBackend *backend, int number);
|
||||
~XdgShellOutput() override;
|
||||
|
||||
void lockPointer(KWayland::Client::Pointer *pointer, bool lock) override;
|
||||
|
||||
bool isReady() const;
|
||||
|
||||
private:
|
||||
void handleConfigure(const QSize &size, KWayland::Client::XdgShellSurface::States states, quint32 serial);
|
||||
void updateWindowTitle();
|
||||
|
||||
std::unique_ptr<RenderLoop> m_renderLoop;
|
||||
std::unique_ptr<KWayland::Client::Surface> m_surface;
|
||||
std::unique_ptr<KWayland::Client::XdgShellSurface> m_xdgShellSurface;
|
||||
int m_number;
|
||||
std::unique_ptr<KWayland::Client::LockedPointer> m_pointerLock;
|
||||
std::unique_ptr<KWayland::Client::ServerSideDecoration> m_serverDecoration;
|
||||
WaylandBackend *const m_backend;
|
||||
QTimer m_turnOffTimer;
|
||||
bool m_hasPointerLock = false;
|
||||
bool m_ready = false;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue