c27230719c
Currently, output properties are looked up either on the wl_output object or the output device object. This puts a hard dependency on the wayland server in the platforms. This change intends to fix some flaws in the current output abstractions, and allow creating/destroying wayland-specific globals as we wish. With the work done in this patch, the need for the AbstractWaylandOutput class is unclear, and it might be a good idea to merge it with the base AbstractOutput class.
161 lines
6.3 KiB
C++
161 lines
6.3 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "waylandoutput.h"
|
|
#include "wayland_server.h"
|
|
|
|
#include <cmath>
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
static KWaylandServer::OutputInterface::Transform kwinTransformToOutputTransform(AbstractWaylandOutput::Transform transform)
|
|
{
|
|
switch (transform) {
|
|
case AbstractWaylandOutput::Transform::Normal:
|
|
return KWaylandServer::OutputInterface::Transform::Normal;
|
|
case AbstractWaylandOutput::Transform::Rotated90:
|
|
return KWaylandServer::OutputInterface::Transform::Rotated90;
|
|
case AbstractWaylandOutput::Transform::Rotated180:
|
|
return KWaylandServer::OutputInterface::Transform::Rotated180;
|
|
case AbstractWaylandOutput::Transform::Rotated270:
|
|
return KWaylandServer::OutputInterface::Transform::Rotated270;
|
|
case AbstractWaylandOutput::Transform::Flipped:
|
|
return KWaylandServer::OutputInterface::Transform::Flipped;
|
|
case AbstractWaylandOutput::Transform::Flipped90:
|
|
return KWaylandServer::OutputInterface::Transform::Flipped90;
|
|
case AbstractWaylandOutput::Transform::Flipped180:
|
|
return KWaylandServer::OutputInterface::Transform::Flipped180;
|
|
case AbstractWaylandOutput::Transform::Flipped270:
|
|
return KWaylandServer::OutputInterface::Transform::Flipped270;
|
|
default:
|
|
Q_UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
static KWaylandServer::OutputInterface::DpmsMode kwinDpmsModeToOutputDpmsMode(AbstractWaylandOutput::DpmsMode dpmsMode)
|
|
{
|
|
switch (dpmsMode) {
|
|
case AbstractWaylandOutput::DpmsMode::Off:
|
|
return KWaylandServer::OutputInterface::DpmsMode::Off;
|
|
case AbstractWaylandOutput::DpmsMode::On:
|
|
return KWaylandServer::OutputInterface::DpmsMode::On;
|
|
case AbstractWaylandOutput::DpmsMode::Standby:
|
|
return KWaylandServer::OutputInterface::DpmsMode::Standby;
|
|
case AbstractWaylandOutput::DpmsMode::Suspend:
|
|
return KWaylandServer::OutputInterface::DpmsMode::Suspend;
|
|
default:
|
|
Q_UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
static AbstractWaylandOutput::DpmsMode outputDpmsModeToKWinDpmsMode(KWaylandServer::OutputInterface::DpmsMode dpmsMode)
|
|
{
|
|
switch (dpmsMode) {
|
|
case KWaylandServer::OutputInterface::DpmsMode::Off:
|
|
return AbstractWaylandOutput::DpmsMode::Off;
|
|
case KWaylandServer::OutputInterface::DpmsMode::On:
|
|
return AbstractWaylandOutput::DpmsMode::On;
|
|
case KWaylandServer::OutputInterface::DpmsMode::Standby:
|
|
return AbstractWaylandOutput::DpmsMode::Standby;
|
|
case KWaylandServer::OutputInterface::DpmsMode::Suspend:
|
|
return AbstractWaylandOutput::DpmsMode::Suspend;
|
|
default:
|
|
Q_UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
WaylandOutput::WaylandOutput(AbstractWaylandOutput *output, QObject *parent)
|
|
: QObject(parent)
|
|
, m_platformOutput(output)
|
|
, m_waylandOutput(new KWaylandServer::OutputInterface(waylandServer()->display(), this))
|
|
, m_xdgOutputV1(waylandServer()->xdgOutputManagerV1()->createXdgOutput(m_waylandOutput, this))
|
|
{
|
|
const QRect geometry = m_platformOutput->geometry();
|
|
|
|
m_waylandOutput->setTransform(kwinTransformToOutputTransform(output->transform()));
|
|
m_waylandOutput->setManufacturer(output->manufacturer());
|
|
m_waylandOutput->setModel(output->model());
|
|
m_waylandOutput->setPhysicalSize(output->physicalSize());
|
|
m_waylandOutput->setDpmsMode(kwinDpmsModeToOutputDpmsMode(output->dpmsMode()));
|
|
m_waylandOutput->setDpmsSupported(output->capabilities() & AbstractWaylandOutput::Capability::Dpms);
|
|
m_waylandOutput->setGlobalPosition(geometry.topLeft());
|
|
m_waylandOutput->setScale(std::ceil(output->scale()));
|
|
|
|
m_xdgOutputV1->setName(output->name());
|
|
m_xdgOutputV1->setDescription(output->description());
|
|
m_xdgOutputV1->setLogicalPosition(geometry.topLeft());
|
|
m_xdgOutputV1->setLogicalSize(geometry.size());
|
|
|
|
const auto modes = output->modes();
|
|
for (const AbstractWaylandOutput::Mode &mode : modes) {
|
|
KWaylandServer::OutputInterface::ModeFlags flags;
|
|
if (mode.flags & AbstractWaylandOutput::ModeFlag::Current) {
|
|
flags |= KWaylandServer::OutputInterface::ModeFlag::Current;
|
|
}
|
|
if (mode.flags & AbstractWaylandOutput::ModeFlag::Preferred) {
|
|
flags |= KWaylandServer::OutputInterface::ModeFlag::Preferred;
|
|
}
|
|
|
|
m_waylandOutput->addMode(mode.size, flags, mode.refreshRate);
|
|
}
|
|
|
|
m_waylandOutput->create();
|
|
m_waylandOutput->done();
|
|
m_xdgOutputV1->done();
|
|
|
|
// The dpms functionality is not part of the wl_output interface, but org_kde_kwin_dpms.
|
|
connect(output, &AbstractWaylandOutput::dpmsModeChanged,
|
|
this, &WaylandOutput::handleDpmsModeChanged);
|
|
connect(m_waylandOutput, &KWaylandServer::OutputInterface::dpmsModeRequested,
|
|
this, &WaylandOutput::handleDpmsModeRequested);
|
|
|
|
// The timer is used to compress output updates so the wayland clients are not spammed.
|
|
m_updateTimer.setSingleShot(true);
|
|
connect(&m_updateTimer, &QTimer::timeout, this, &WaylandOutput::update);
|
|
|
|
connect(output, &AbstractWaylandOutput::geometryChanged, this, &WaylandOutput::scheduleUpdate);
|
|
connect(output, &AbstractWaylandOutput::transformChanged, this, &WaylandOutput::scheduleUpdate);
|
|
connect(output, &AbstractWaylandOutput::scaleChanged, this, &WaylandOutput::scheduleUpdate);
|
|
}
|
|
|
|
KWaylandServer::OutputInterface *WaylandOutput::waylandOutput() const
|
|
{
|
|
return m_waylandOutput;
|
|
}
|
|
|
|
void WaylandOutput::scheduleUpdate()
|
|
{
|
|
m_updateTimer.start();
|
|
}
|
|
|
|
void WaylandOutput::update()
|
|
{
|
|
const QRect geometry = m_platformOutput->geometry();
|
|
|
|
m_waylandOutput->setGlobalPosition(geometry.topLeft());
|
|
m_waylandOutput->setScale(std::ceil(m_platformOutput->scale()));
|
|
m_waylandOutput->setTransform(kwinTransformToOutputTransform(m_platformOutput->transform()));
|
|
m_waylandOutput->setCurrentMode(m_platformOutput->modeSize(), m_platformOutput->refreshRate());
|
|
|
|
m_xdgOutputV1->setLogicalPosition(geometry.topLeft());
|
|
m_xdgOutputV1->setLogicalSize(geometry.size());
|
|
|
|
m_waylandOutput->done();
|
|
m_xdgOutputV1->done();
|
|
}
|
|
|
|
void WaylandOutput::handleDpmsModeChanged()
|
|
{
|
|
m_waylandOutput->setDpmsMode(kwinDpmsModeToOutputDpmsMode(m_platformOutput->dpmsMode()));
|
|
}
|
|
|
|
void WaylandOutput::handleDpmsModeRequested(KWaylandServer::OutputInterface::DpmsMode dpmsMode)
|
|
{
|
|
m_platformOutput->setDpmsMode(outputDpmsModeToKWinDpmsMode(dpmsMode));
|
|
}
|
|
|
|
} // namespace KWin
|