6 #include "outputdevice_interface.h"
11 #include "wayland-org_kde_kwin_outputdevice-server-protocol.h"
13 #include <wayland-server.h>
19 class OutputDeviceInterface::Private :
public Global::Private
23 wl_resource *resource;
26 Private(OutputDeviceInterface *q, Display *d);
29 void updateGeometry();
34 void updateColorCurves();
36 void updateSerialNumber();
38 void sendGeometry(wl_resource *resource);
39 void sendMode(wl_resource *resource,
const Mode &mode);
40 void sendDone(
const ResourceData &data);
41 void sendUuid(
const ResourceData &data);
42 void sendEdid(
const ResourceData &data);
43 void sendEnabled(
const ResourceData &data);
44 void sendScale(
const ResourceData &data);
45 void sendColorCurves(
const ResourceData &data);
46 void sendEisaId(
const ResourceData &data);
47 void sendSerialNumber(
const ResourceData &data);
51 QString manufacturer = QStringLiteral(
"org.kde.kwin");
52 QString model = QStringLiteral(
"none");
56 SubPixel subPixel = SubPixel::Unknown;
58 ColorCurves colorCurves;
64 Enablement enabled = Enablement::Enabled;
67 static OutputDeviceInterface *
get(wl_resource *native);
70 static Private *cast(wl_resource *native);
71 static void unbind(wl_resource *resource);
72 void bind(wl_client *client, uint32_t version, uint32_t
id)
override;
73 int32_t toTransform()
const;
74 int32_t toSubPixel()
const;
76 static const quint32 s_version;
77 OutputDeviceInterface *q;
81 const quint32 OutputDeviceInterface::Private::s_version = 2;
85 OutputDeviceInterface::Private::Private(OutputDeviceInterface *q, Display *d)
86 : Global::Private(d, &org_kde_kwin_outputdevice_interface, s_version)
92 OutputDeviceInterface::Private::~Private()
94 s_privates.removeAll(
this);
99 if (Private *p = cast(native)) {
105 OutputDeviceInterface::Private *OutputDeviceInterface::Private::cast(wl_resource *native)
107 for (
auto it = s_privates.constBegin(); it != s_privates.constEnd(); ++it) {
108 const auto &resources = (*it)->resources;
109 auto rit = std::find_if(resources.begin(), resources.end(), [native](
const ResourceData &data) {
110 return data.resource == native;
112 if (rit != resources.end()) {
119 OutputDeviceInterface::OutputDeviceInterface(Display *display,
QObject *parent)
120 : Global(new Private(this, display), parent)
123 connect(
this, &OutputDeviceInterface::currentModeChanged,
this, [d] {
124 Q_ASSERT(d->currentMode.id >= 0);
125 for (
auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
126 d->sendMode((*it).resource, d->currentMode);
129 wl_display_flush_clients(*(d->display));
131 connect(
this, &OutputDeviceInterface::subPixelChanged,
this, [d] {
134 connect(
this, &OutputDeviceInterface::transformChanged,
this, [d] {
137 connect(
this, &OutputDeviceInterface::globalPositionChanged,
this, [d] {
140 connect(
this, &OutputDeviceInterface::modelChanged,
this, [d] {
143 connect(
this, &OutputDeviceInterface::manufacturerChanged,
this, [d] {
146 connect(
this, &OutputDeviceInterface::scaleFChanged,
this, [d] {
149 connect(
this, &OutputDeviceInterface::scaleChanged,
this, [d] {
152 connect(
this, &OutputDeviceInterface::colorCurvesChanged,
this, [d] {
153 d->updateColorCurves();
157 OutputDeviceInterface::~OutputDeviceInterface() =
default;
159 QSize OutputDeviceInterface::pixelSize()
const
163 if (d->currentMode.id == -1) {
166 return d->currentMode.size;
174 int OutputDeviceInterface::refreshRate()
const
178 if (d->currentMode.id == -1) {
181 return d->currentMode.refreshRate;
184 void OutputDeviceInterface::addMode(Mode &mode)
186 Q_ASSERT(!isValid());
187 Q_ASSERT(mode.id >= 0);
188 Q_ASSERT(mode.size.isValid());
191 auto currentModeIt = std::find_if(d->modes.begin(), d->modes.end(), [](
const Mode &mode) {
192 return mode.flags.testFlag(ModeFlag::Current);
194 if (currentModeIt == d->modes.end() && !mode.flags.testFlag(ModeFlag::Current)) {
196 mode.flags |= ModeFlag::Current;
198 if (currentModeIt != d->modes.end() && mode.flags.testFlag(ModeFlag::Current)) {
200 (*currentModeIt).flags &= ~uint(ModeFlag::Current);
203 if (mode.flags.testFlag(ModeFlag::Preferred)) {
205 auto preferredIt = std::find_if(d->modes.begin(), d->modes.end(), [](
const Mode &mode) {
206 return mode.flags.testFlag(ModeFlag::Preferred);
208 if (preferredIt != d->modes.end()) {
209 (*preferredIt).flags &= ~uint(ModeFlag::Preferred);
213 auto existingModeIt = std::find_if(d->modes.begin(), d->modes.end(), [mode](
const Mode &mode_it) {
214 return mode.size == mode_it.size && mode.refreshRate == mode_it.refreshRate && mode.id == mode_it.id;
216 auto emitChanges = [
this, d, mode] {
217 Q_EMIT modesChanged();
218 if (mode.flags.testFlag(ModeFlag::Current)) {
219 d->currentMode = mode;
220 Q_EMIT refreshRateChanged(mode.refreshRate);
221 Q_EMIT pixelSizeChanged(mode.size);
222 Q_EMIT currentModeChanged();
225 if (existingModeIt != d->modes.end()) {
226 if ((*existingModeIt).flags == mode.flags) {
230 (*existingModeIt).flags = mode.flags;
234 auto idIt = std::find_if(d->modes.constBegin(), d->modes.constEnd(), [mode](
const Mode &mode_it) {
235 return mode.id == mode_it.id;
237 if (idIt != d->modes.constEnd()) {
238 qCWarning(KWAYLAND_SERVER) <<
"Duplicate Mode id" << mode.id <<
": not adding mode" << mode.size << mode.refreshRate;
246 void OutputDeviceInterface::setCurrentMode(
const int modeId)
249 auto currentModeIt = std::find_if(d->modes.begin(), d->modes.end(), [](
const Mode &mode) {
250 return mode.flags.testFlag(ModeFlag::Current);
252 if (currentModeIt != d->modes.end()) {
254 (*currentModeIt).flags &= ~uint(ModeFlag::Current);
257 auto existingModeIt = std::find_if(d->modes.begin(), d->modes.end(), [modeId](
const Mode &mode) {
258 return mode.id == modeId;
261 Q_ASSERT(existingModeIt != d->modes.end());
262 (*existingModeIt).flags |= ModeFlag::Current;
263 d->currentMode = *existingModeIt;
264 Q_EMIT modesChanged();
265 Q_EMIT refreshRateChanged((*existingModeIt).refreshRate);
266 Q_EMIT pixelSizeChanged((*existingModeIt).size);
267 Q_EMIT currentModeChanged();
270 int32_t OutputDeviceInterface::Private::toTransform()
const
273 case Transform::Normal:
274 return WL_OUTPUT_TRANSFORM_NORMAL;
275 case Transform::Rotated90:
276 return WL_OUTPUT_TRANSFORM_90;
277 case Transform::Rotated180:
278 return WL_OUTPUT_TRANSFORM_180;
279 case Transform::Rotated270:
280 return WL_OUTPUT_TRANSFORM_270;
281 case Transform::Flipped:
282 return WL_OUTPUT_TRANSFORM_FLIPPED;
283 case Transform::Flipped90:
284 return WL_OUTPUT_TRANSFORM_FLIPPED_90;
285 case Transform::Flipped180:
286 return WL_OUTPUT_TRANSFORM_FLIPPED_180;
287 case Transform::Flipped270:
288 return WL_OUTPUT_TRANSFORM_FLIPPED_270;
293 int32_t OutputDeviceInterface::Private::toSubPixel()
const
296 case SubPixel::Unknown:
297 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
299 return WL_OUTPUT_SUBPIXEL_NONE;
300 case SubPixel::HorizontalRGB:
301 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
302 case SubPixel::HorizontalBGR:
303 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
304 case SubPixel::VerticalRGB:
305 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
306 case SubPixel::VerticalBGR:
307 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
312 void OutputDeviceInterface::Private::bind(wl_client *client, uint32_t version, uint32_t
id)
314 auto c = display->getConnection(client);
315 wl_resource *resource = c->createResource(&org_kde_kwin_outputdevice_interface, qMin(version, s_version),
id);
317 wl_client_post_no_memory(client);
320 wl_resource_set_user_data(resource,
this);
321 wl_resource_set_destructor(resource, unbind);
323 r.resource = resource;
327 sendGeometry(resource);
333 auto currentModeIt = modes.constEnd();
334 for (
auto it = modes.constBegin(); it != modes.constEnd(); ++it) {
335 const Mode &mode = *it;
336 if (mode.flags.testFlag(ModeFlag::Current)) {
341 sendMode(resource, mode);
344 if (currentModeIt != modes.constEnd()) {
345 sendMode(resource, *currentModeIt);
356 void OutputDeviceInterface::Private::unbind(wl_resource *resource)
358 Private *o = cast(resource);
362 auto it = std::find_if(o->resources.begin(), o->resources.end(), [resource](
const ResourceData &r) {
363 return r.resource == resource;
365 if (it != o->resources.end()) {
366 o->resources.erase(it);
370 void OutputDeviceInterface::Private::sendMode(wl_resource *resource,
const Mode &mode)
373 if (mode.flags.testFlag(ModeFlag::Current)) {
374 flags |= WL_OUTPUT_MODE_CURRENT;
376 if (mode.flags.testFlag(ModeFlag::Preferred)) {
377 flags |= WL_OUTPUT_MODE_PREFERRED;
379 org_kde_kwin_outputdevice_send_mode(resource, flags, mode.size.width(), mode.size.height(), mode.refreshRate, mode.id);
382 void OutputDeviceInterface::Private::sendGeometry(wl_resource *resource)
384 org_kde_kwin_outputdevice_send_geometry(resource,
387 physicalSize.width(),
388 physicalSize.height(),
390 qPrintable(manufacturer),
395 void OutputDeviceInterface::Private::sendScale(
const ResourceData &data)
397 if (wl_resource_get_version(data.resource) < ORG_KDE_KWIN_OUTPUTDEVICE_SCALEF_SINCE_VERSION) {
398 org_kde_kwin_outputdevice_send_scale(data.resource, qRound(scale));
400 org_kde_kwin_outputdevice_send_scalef(data.resource, wl_fixed_from_double(scale));
404 void OutputDeviceInterface::Private::sendColorCurves(
const ResourceData &data)
406 if (data.version < ORG_KDE_KWIN_OUTPUTDEVICE_COLORCURVES_SINCE_VERSION) {
416 const size_t memLength =
sizeof(uint16_t) * origin.
size();
417 void *s = wl_array_add(dest, memLength);
418 memcpy(s, origin.
data(), memLength);
420 fillArray(colorCurves.red, &wlRed);
421 fillArray(colorCurves.green, &wlGreen);
422 fillArray(colorCurves.blue, &wlBlue);
424 org_kde_kwin_outputdevice_send_colorcurves(data.resource, &wlRed, &wlGreen, &wlBlue);
426 wl_array_release(&wlRed);
427 wl_array_release(&wlGreen);
428 wl_array_release(&wlBlue);
431 void KWayland::Server::OutputDeviceInterface::Private::sendSerialNumber(
const ResourceData &data)
433 if (wl_resource_get_version(data.resource) >= ORG_KDE_KWIN_OUTPUTDEVICE_SERIAL_NUMBER_SINCE_VERSION) {
434 org_kde_kwin_outputdevice_send_serial_number(data.resource, qPrintable(serialNumber));
438 void KWayland::Server::OutputDeviceInterface::Private::sendEisaId(
const ResourceData &data)
440 if (wl_resource_get_version(data.resource) >= ORG_KDE_KWIN_OUTPUTDEVICE_EISA_ID_SINCE_VERSION) {
441 org_kde_kwin_outputdevice_send_eisa_id(data.resource, qPrintable(eisaId));
445 void OutputDeviceInterface::Private::sendDone(
const ResourceData &data)
447 org_kde_kwin_outputdevice_send_done(data.resource);
450 void OutputDeviceInterface::Private::updateGeometry()
452 for (
auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
453 sendGeometry((*it).resource);
458 void OutputDeviceInterface::Private::updateScale()
460 for (
auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
466 void OutputDeviceInterface::Private::updateColorCurves()
468 for (
auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
469 sendColorCurves(*it);
474 bool OutputDeviceInterface::ColorCurves::operator==(
const ColorCurves &cc)
const
476 return red == cc.red &&
green == cc.green &&
blue == cc.blue;
478 bool OutputDeviceInterface::ColorCurves::operator!=(
const ColorCurves &cc)
const
484 #define SETTER(setterName, type, argumentName) \
485 void OutputDeviceInterface::setterName(type arg) \
488 if (d->argumentName == arg) { \
491 d->argumentName = arg; \
492 Q_EMIT argumentName##Changed(d->argumentName); \
496 SETTER(setPhysicalSize,
const QSize &, physicalSize)
497 SETTER(setGlobalPosition,
const QPoint &, globalPosition)
498 SETTER(setManufacturer,
const QString &, manufacturer)
499 SETTER(setModel,
const QString &, model)
500 SETTER(setSerialNumber,
const QString &, serialNumber)
501 SETTER(setEisaId,
const QString &, eisaId)
502 SETTER(setSubPixel, SubPixel, subPixel)
503 SETTER(setTransform, Transform, transform)
507 void OutputDeviceInterface::setScale(
int scale)
510 if (d->scale == scale) {
514 Q_EMIT scaleChanged(d->scale);
515 Q_EMIT scaleFChanged(d->scale);
518 void OutputDeviceInterface::setScaleF(qreal scale)
521 if (qFuzzyCompare(d->scale, scale)) {
525 Q_EMIT scaleChanged(qRound(d->scale));
526 Q_EMIT scaleFChanged(d->scale);
529 QSize OutputDeviceInterface::physicalSize()
const
532 return d->physicalSize;
535 QPoint OutputDeviceInterface::globalPosition()
const
538 return d->globalPosition;
541 QString OutputDeviceInterface::manufacturer()
const
544 return d->manufacturer;
547 QString OutputDeviceInterface::model()
const
553 QString OutputDeviceInterface::serialNumber()
const
556 return d->serialNumber;
559 QString OutputDeviceInterface::eisaId()
const
565 int OutputDeviceInterface::scale()
const
568 return qRound(d->scale);
571 qreal OutputDeviceInterface::scaleF()
const
577 OutputDeviceInterface::SubPixel OutputDeviceInterface::subPixel()
const
583 OutputDeviceInterface::Transform OutputDeviceInterface::transform()
const
589 OutputDeviceInterface::ColorCurves OutputDeviceInterface::colorCurves()
const
592 return d->colorCurves;
601 int OutputDeviceInterface::currentModeId()
const
604 for (
const Mode &m : d->modes) {
605 if (m.flags.testFlag(OutputDeviceInterface::ModeFlag::Current)) {
612 OutputDeviceInterface::Private *OutputDeviceInterface::d_func()
const
614 return reinterpret_cast<Private *
>(d.data());
617 void OutputDeviceInterface::setColorCurves(
const ColorCurves &colorCurves)
621 if (d->colorCurves == colorCurves) {
624 d->colorCurves = colorCurves;
625 Q_EMIT colorCurvesChanged(d->colorCurves);
628 void OutputDeviceInterface::setEdid(
const QByteArray &edid)
633 Q_EMIT edidChanged();
636 QByteArray OutputDeviceInterface::edid()
const
642 void OutputDeviceInterface::setEnabled(OutputDeviceInterface::Enablement enabled)
645 if (d->enabled != enabled) {
646 d->enabled = enabled;
648 Q_EMIT enabledChanged();
652 OutputDeviceInterface::Enablement OutputDeviceInterface::enabled()
const
658 void OutputDeviceInterface::setUuid(
const QByteArray &uuid)
661 if (d->uuid != uuid) {
664 Q_EMIT uuidChanged();
668 QByteArray OutputDeviceInterface::uuid()
const
674 void KWayland::Server::OutputDeviceInterface::Private::sendEdid(
const ResourceData &data)
679 void KWayland::Server::OutputDeviceInterface::Private::sendEnabled(
const ResourceData &data)
682 if (enabled == OutputDeviceInterface::Enablement::Enabled) {
685 org_kde_kwin_outputdevice_send_enabled(data.resource, _enabled);
688 void OutputDeviceInterface::Private::sendUuid(
const ResourceData &data)
690 org_kde_kwin_outputdevice_send_uuid(data.resource, uuid.
constData());
693 void KWayland::Server::OutputDeviceInterface::Private::updateEnabled()
695 for (
auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
700 void KWayland::Server::OutputDeviceInterface::Private::updateEdid()
702 for (
auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
707 void KWayland::Server::OutputDeviceInterface::Private::updateUuid()
709 for (
auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
714 void KWayland::Server::OutputDeviceInterface::Private::updateEisaId()
716 for (
auto it = resources.constBegin(); it != resources.constEnd(); ++it) {