kwin/plugins/platforms/wayland/wayland_output.cpp
Vlad Zahorodnii 1fb9f6f13a Switch to SPDX license markers
The main advantage of SPDX license identifiers over the traditional
license headers is that it's more difficult to overlook inappropriate
licenses for kwin, for example GPL 3. We also don't have to copy a
lot of boilerplate text.

In order to create this change, I ran licensedigger -r -c from the
toplevel source directory.
2020-08-07 19:57:56 +00:00

172 lines
5.2 KiB
C++

/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*********************************************************************/
#include "wayland_output.h"
#include "wayland_backend.h"
#include "wayland_server.h"
#include <KWayland/Client/pointerconstraints.h>
#include <KWayland/Client/surface.h>
#include <KWaylandServer/display.h>
#include <KLocalizedString>
namespace KWin
{
namespace Wayland
{
using namespace KWayland::Client;
WaylandOutput::WaylandOutput(Surface *surface, WaylandBackend *backend)
: AbstractWaylandOutput(backend)
, m_surface(surface)
, m_backend(backend)
{
static int identifier = -1;
identifier++;
setName("WL-" + QString::number(identifier));
connect(surface, &Surface::frameRendered, [this] {
m_rendered = true;
emit frameRendered();
});
}
WaylandOutput::~WaylandOutput()
{
m_surface->destroy();
delete m_surface;
}
void WaylandOutput::init(const QPoint &logicalPosition, const QSize &pixelSize)
{
KWaylandServer::OutputDeviceInterface::Mode mode;
mode.id = 0;
mode.size = pixelSize;
mode.flags = KWaylandServer::OutputDeviceInterface::ModeFlag::Current;
mode.refreshRate = 60000; // TODO: can we get refresh rate data from Wayland host?
initInterfaces("model_TODO", "manufacturer_TODO", "UUID_TODO", pixelSize, { mode });
setGeometry(logicalPosition, pixelSize);
setScale(backend()->initialOutputScale());
}
void WaylandOutput::setGeometry(const QPoint &logicalPosition, const QSize &pixelSize)
{
// TODO: set mode to have updated pixelSize
Q_UNUSED(pixelSize)
setGlobalPos(logicalPosition);
}
XdgShellOutput::XdgShellOutput(Surface *surface, XdgShell *xdgShell, WaylandBackend *backend, int number)
: WaylandOutput(surface, backend)
, m_number(number)
{
m_xdgShellSurface = xdgShell->createSurface(surface, this);
updateWindowTitle();
connect(m_xdgShellSurface, &XdgShellSurface::configureRequested, this, &XdgShellOutput::handleConfigure);
connect(m_xdgShellSurface, &XdgShellSurface::closeRequested, qApp, &QCoreApplication::quit);
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(Surface::CommitFlag::None);
}
XdgShellOutput::~XdgShellOutput()
{
m_xdgShellSurface->destroy();
delete m_xdgShellSurface;
}
void XdgShellOutput::handleConfigure(const QSize &size, XdgShellSurface::States states, quint32 serial)
{
Q_UNUSED(states);
if (size.width() > 0 && size.height() > 0) {
setGeometry(geometry().topLeft(), size);
emit sizeChanged(size);
}
m_xdgShellSurface->ackConfigure(serial);
}
void XdgShellOutput::updateWindowTitle()
{
QString grab;
if (m_hasPointerLock) {
grab = i18n("Press right control to ungrab pointer");
} else if (backend()->pointerConstraints()) {
grab = i18n("Press right control key to grab pointer");
}
const QString title = i18nc("Title of nested KWin Wayland with Wayland socket identifier as argument",
"KDE Wayland Compositor #%1 (%2)", m_number, waylandServer()->display()->socketName());
if (grab.isEmpty()) {
m_xdgShellSurface->setTitle(title);
} else {
m_xdgShellSurface->setTitle(title + QStringLiteral("") + grab);
}
}
void XdgShellOutput::lockPointer(Pointer *pointer, bool lock)
{
if (!lock) {
const bool surfaceWasLocked = m_pointerLock && m_hasPointerLock;
delete m_pointerLock;
m_pointerLock = nullptr;
m_hasPointerLock = false;
if (surfaceWasLocked) {
emit backend()->pointerLockChanged(false);
}
return;
}
Q_ASSERT(!m_pointerLock);
m_pointerLock = backend()->pointerConstraints()->lockPointer(surface(), pointer, nullptr,
PointerConstraints::LifeTime::OneShot,
this);
if (!m_pointerLock->isValid()) {
delete m_pointerLock;
m_pointerLock = nullptr;
return;
}
connect(m_pointerLock, &LockedPointer::locked, this,
[this] {
m_hasPointerLock = true;
emit backend()->pointerLockChanged(true);
}
);
connect(m_pointerLock, &LockedPointer::unlocked, this,
[this] {
delete m_pointerLock;
m_pointerLock = nullptr;
m_hasPointerLock = false;
emit backend()->pointerLockChanged(false);
}
);
}
}
}