KWayland

outputdevice.cpp
1 /*
2  SPDX-FileCopyrightText: 2013 Martin Gräßlin <[email protected]>
3  SPDX-FileCopyrightText: 2018 Roman Gilg <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 #include "outputdevice.h"
8 #include "logging.h"
9 #include "wayland_pointer_p.h"
10 // Qt
11 #include <QDebug>
12 #include <QPoint>
13 #include <QRect>
14 // wayland
15 #include "wayland-org_kde_kwin_outputdevice-client-protocol.h"
16 #include <wayland-client-protocol.h>
17 
18 namespace KWayland
19 {
20 namespace Client
21 {
22 typedef QList<OutputDevice::Mode> Modes;
23 
24 class Q_DECL_HIDDEN OutputDevice::Private
25 {
26 public:
27  Private(OutputDevice *q);
28  void setup(org_kde_kwin_outputdevice *o);
29 
30  WaylandPointer<org_kde_kwin_outputdevice, org_kde_kwin_outputdevice_destroy> output;
31  EventQueue *queue = nullptr;
32  QSize physicalSize;
33  QPoint globalPosition;
34  QString manufacturer;
35  QString model;
36  qreal scale = 1.0;
37  QString serialNumber;
38  QString eisaId;
39  SubPixel subPixel = SubPixel::Unknown;
40  Transform transform = Transform::Normal;
41  Modes modes;
42  Modes::iterator currentMode = modes.end();
43 
44  QByteArray edid;
45  OutputDevice::Enablement enabled = OutputDevice::Enablement::Enabled;
46  QByteArray uuid;
47 
48  ColorCurves colorCurves;
49 
51  uint32_t overscan = 0;
52  VrrPolicy vrrPolicy = VrrPolicy::Automatic;
53 
54  bool done = false;
55 
56 private:
57  static void geometryCallback(void *data,
58  org_kde_kwin_outputdevice *output,
59  int32_t x,
60  int32_t y,
61  int32_t physicalWidth,
62  int32_t physicalHeight,
63  int32_t subPixel,
64  const char *make,
65  const char *model,
66  int32_t transform);
67  static void modeCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh, int32_t mode_id);
68  static void doneCallback(void *data, org_kde_kwin_outputdevice *output);
69  static void scaleCallback(void *data, org_kde_kwin_outputdevice *output, int32_t scale);
70  static void scaleFCallback(void *data, org_kde_kwin_outputdevice *output, wl_fixed_t scale);
71 
72  static void edidCallback(void *data, org_kde_kwin_outputdevice *output, const char *raw);
73  static void enabledCallback(void *data, org_kde_kwin_outputdevice *output, int32_t enabled);
74  static void uuidCallback(void *data, org_kde_kwin_outputdevice *output, const char *uuid);
75 
76  static void colorcurvesCallback(void *data, org_kde_kwin_outputdevice *output, wl_array *red, wl_array *green, wl_array *blue);
77 
78  static void serialNumberCallback(void *data, org_kde_kwin_outputdevice *output, const char *serialNumber);
79  static void eisaIdCallback(void *data, org_kde_kwin_outputdevice *output, const char *eisa);
80  static void capabilitiesCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t capabilities);
81  static void overscanCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t overscan);
82  static void vrrPolicyCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t vrrPolicy);
83 
84  void setPhysicalSize(const QSize &size);
85  void setGlobalPosition(const QPoint &pos);
86  void setManufacturer(const QString &manufacturer);
87  void setModel(const QString &model);
88  void setScale(qreal scale);
89  void setSerialNumber(const QString &serialNumber);
90  void setEisaId(const QString &eisaId);
91  void setSubPixel(SubPixel subPixel);
92  void setTransform(Transform transform);
93  void addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh, int32_t mode_id);
94 
95  OutputDevice *q;
96  static struct org_kde_kwin_outputdevice_listener s_outputListener;
97 };
98 
99 OutputDevice::Private::Private(OutputDevice *q)
100  : q(q)
101 {
102 }
103 
104 void OutputDevice::Private::setup(org_kde_kwin_outputdevice *o)
105 {
106  Q_ASSERT(o);
107  Q_ASSERT(!output);
108  output.setup(o);
109  org_kde_kwin_outputdevice_add_listener(output, &s_outputListener, this);
110 }
111 
112 bool OutputDevice::Mode::operator==(const OutputDevice::Mode &m) const
113 {
114  return size == m.size && refreshRate == m.refreshRate && flags == m.flags && output == m.output;
115 }
116 
117 bool OutputDevice::ColorCurves::operator==(const OutputDevice::ColorCurves &cc) const
118 {
119  return red == cc.red && green == cc.green && blue == cc.blue;
120 }
121 bool OutputDevice::ColorCurves::operator!=(const ColorCurves &cc) const
122 {
123  return !operator==(cc);
124 }
125 
126 OutputDevice::OutputDevice(QObject *parent)
127  : QObject(parent)
128  , d(new Private(this))
129 {
130 }
131 
132 OutputDevice::~OutputDevice()
133 {
134  d->output.release();
135 }
136 
137 org_kde_kwin_outputdevice_listener OutputDevice::Private::s_outputListener = {
138  geometryCallback,
139  modeCallback,
140  doneCallback,
141  scaleCallback,
142  edidCallback,
143  enabledCallback,
144  uuidCallback,
145  scaleFCallback,
146  colorcurvesCallback,
147  serialNumberCallback,
148  eisaIdCallback,
149  capabilitiesCallback,
150  overscanCallback,
151  vrrPolicyCallback
152 };
153 
154 void OutputDevice::Private::geometryCallback(void *data,
155  org_kde_kwin_outputdevice *output,
156  int32_t x,
157  int32_t y,
158  int32_t physicalWidth,
159  int32_t physicalHeight,
160  int32_t subPixel,
161  const char *make,
162  const char *model,
163  int32_t transform)
164 {
165  Q_UNUSED(transform)
166  auto o = reinterpret_cast<OutputDevice::Private *>(data);
167  Q_ASSERT(o->output == output);
168  o->setGlobalPosition(QPoint(x, y));
169  o->setManufacturer(make);
170  o->setModel(model);
171  o->setPhysicalSize(QSize(physicalWidth, physicalHeight));
172  auto toSubPixel = [subPixel]() {
173  switch (subPixel) {
174  case WL_OUTPUT_SUBPIXEL_NONE:
175  return SubPixel::None;
176  case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
177  return SubPixel::HorizontalRGB;
178  case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
179  return SubPixel::HorizontalBGR;
180  case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
181  return SubPixel::VerticalRGB;
182  case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
183  return SubPixel::VerticalBGR;
184  case WL_OUTPUT_SUBPIXEL_UNKNOWN:
185  default:
186  return SubPixel::Unknown;
187  }
188  };
189  o->setSubPixel(toSubPixel());
190  auto toTransform = [transform]() {
191  switch (transform) {
192  case WL_OUTPUT_TRANSFORM_90:
193  return Transform::Rotated90;
194  case WL_OUTPUT_TRANSFORM_180:
195  return Transform::Rotated180;
196  case WL_OUTPUT_TRANSFORM_270:
197  return Transform::Rotated270;
198  case WL_OUTPUT_TRANSFORM_FLIPPED:
199  return Transform::Flipped;
200  case WL_OUTPUT_TRANSFORM_FLIPPED_90:
201  return Transform::Flipped90;
202  case WL_OUTPUT_TRANSFORM_FLIPPED_180:
203  return Transform::Flipped180;
204  case WL_OUTPUT_TRANSFORM_FLIPPED_270:
205  return Transform::Flipped270;
206  case WL_OUTPUT_TRANSFORM_NORMAL:
207  default:
208  return Transform::Normal;
209  }
210  };
211  o->setTransform(toTransform());
212 }
213 
214 void OutputDevice::Private::modeCallback(void *data,
215  org_kde_kwin_outputdevice *output,
216  uint32_t flags,
217  int32_t width,
218  int32_t height,
219  int32_t refresh,
220  int32_t mode_id)
221 {
222  auto o = reinterpret_cast<OutputDevice::Private *>(data);
223  Q_ASSERT(o->output == output);
224  o->addMode(flags, width, height, refresh, mode_id);
225 }
226 
227 void OutputDevice::Private::addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh, int32_t mode_id)
228 {
229  Mode mode;
230  mode.output = QPointer<OutputDevice>(q);
231  mode.refreshRate = refresh;
232  mode.size = QSize(width, height);
233  mode.id = mode_id;
234  if (flags & WL_OUTPUT_MODE_CURRENT) {
235  mode.flags |= Mode::Flag::Current;
236  }
237  if (flags & WL_OUTPUT_MODE_PREFERRED) {
238  mode.flags |= Mode::Flag::Preferred;
239  }
240 
241  bool existing = false;
242  if (flags & WL_OUTPUT_MODE_CURRENT) {
243  auto it = modes.begin();
244  while (it != modes.end()) {
245  auto &m = (*it);
246  if (m.flags.testFlag(Mode::Flag::Current)) {
247  m.flags &= ~Mode::Flags(Mode::Flag::Current);
248  Q_EMIT q->modeChanged(m);
249  }
250  if (m.refreshRate == mode.refreshRate && m.size == mode.size) {
251  it = modes.erase(it);
252  existing = true;
253  } else {
254  it++;
255  }
256  }
257  }
258 
259  // insert new mode after erase all repeat old mode
260  const auto last = modes.insert(modes.end(), mode);
261  if (flags & WL_OUTPUT_MODE_CURRENT) {
262  currentMode = last;
263  }
264 
265  if (existing) {
266  Q_EMIT q->modeChanged(mode);
267  } else {
268  Q_EMIT q->modeAdded(mode);
269  }
270 }
271 
272 KWayland::Client::OutputDevice::Mode OutputDevice::currentMode() const
273 {
274  for (const auto &m : modes()) {
275  if (m.flags.testFlag(KWayland::Client::OutputDevice::Mode::Flag::Current)) {
276  return m;
277  }
278  }
279  qCWarning(KWAYLAND_CLIENT) << "current mode not found";
280  return Mode();
281 }
282 
283 void OutputDevice::Private::scaleCallback(void *data, org_kde_kwin_outputdevice *output, int32_t scale)
284 {
285  auto o = reinterpret_cast<OutputDevice::Private *>(data);
286  Q_ASSERT(o->output == output);
287  o->setScale(scale);
288 }
289 
290 void OutputDevice::Private::scaleFCallback(void *data, org_kde_kwin_outputdevice *output, wl_fixed_t scale_fixed)
291 {
292  auto o = reinterpret_cast<OutputDevice::Private *>(data);
293  Q_ASSERT(o->output == output);
294  o->setScale(wl_fixed_to_double(scale_fixed));
295 }
296 
297 void OutputDevice::Private::doneCallback(void *data, org_kde_kwin_outputdevice *output)
298 {
299  auto o = reinterpret_cast<OutputDevice::Private *>(data);
300  Q_ASSERT(o->output == output);
301  o->done = true;
302  Q_EMIT o->q->changed();
303  Q_EMIT o->q->done();
304 }
305 
306 void OutputDevice::Private::edidCallback(void *data, org_kde_kwin_outputdevice *output, const char *raw)
307 {
308  Q_UNUSED(output);
309  auto o = reinterpret_cast<OutputDevice::Private *>(data);
310  o->edid = QByteArray::fromBase64(raw);
311 }
312 
313 void OutputDevice::Private::enabledCallback(void *data, org_kde_kwin_outputdevice *output, int32_t enabled)
314 {
315  Q_UNUSED(output);
316  auto o = reinterpret_cast<OutputDevice::Private *>(data);
317 
318  OutputDevice::Enablement _enabled = OutputDevice::Enablement::Disabled;
319  if (enabled == ORG_KDE_KWIN_OUTPUTDEVICE_ENABLEMENT_ENABLED) {
320  _enabled = OutputDevice::Enablement::Enabled;
321  }
322  if (o->enabled != _enabled) {
323  o->enabled = _enabled;
324  Q_EMIT o->q->enabledChanged(o->enabled);
325  if (o->done) {
326  Q_EMIT o->q->changed();
327  }
328  }
329 }
330 
331 void OutputDevice::Private::uuidCallback(void *data, org_kde_kwin_outputdevice *output, const char *uuid)
332 {
333  Q_UNUSED(output);
334  auto o = reinterpret_cast<OutputDevice::Private *>(data);
335  if (o->uuid != uuid) {
336  o->uuid = uuid;
337  Q_EMIT o->q->uuidChanged(o->uuid);
338  if (o->done) {
339  Q_EMIT o->q->changed();
340  }
341  }
342 }
343 
344 void OutputDevice::Private::colorcurvesCallback(void *data, org_kde_kwin_outputdevice *output, wl_array *red, wl_array *green, wl_array *blue)
345 {
346  Q_UNUSED(output);
347  auto o = reinterpret_cast<OutputDevice::Private *>(data);
348 
349  auto cc = ColorCurves();
350 
351  auto setCurve = [](const wl_array *curve, QVector<quint16> *destination) {
352  destination->resize(curve->size / sizeof(uint16_t));
353  memcpy(destination->data(), curve->data, curve->size);
354  };
355  setCurve(red, &cc.red);
356  setCurve(green, &cc.green);
357  setCurve(blue, &cc.blue);
358 
359  if (o->colorCurves != cc) {
360  o->colorCurves = cc;
361  Q_EMIT o->q->colorCurvesChanged();
362  if (o->done) {
363  Q_EMIT o->q->changed();
364  }
365  }
366 }
367 
368 void OutputDevice::Private::serialNumberCallback(void *data, org_kde_kwin_outputdevice *output, const char *raw)
369 {
370  auto o = reinterpret_cast<OutputDevice::Private *>(data);
371  Q_UNUSED(output);
372  o->setSerialNumber(raw);
373 }
374 
375 void OutputDevice::Private::eisaIdCallback(void *data, org_kde_kwin_outputdevice *output, const char *raw)
376 {
377  auto o = reinterpret_cast<OutputDevice::Private *>(data);
378  Q_UNUSED(output);
379  o->setEisaId(raw);
380 }
381 
382 void OutputDevice::Private::capabilitiesCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t capabilities)
383 {
384  auto o = reinterpret_cast<OutputDevice::Private *>(data);
385  Q_UNUSED(output);
386  auto caps = static_cast<Capabilities>(capabilities);
387  if (o->capabilities != caps) {
388  o->capabilities = caps;
389  Q_EMIT o->q->capabilitiesChanged(caps);
390  if (o->done) {
391  Q_EMIT o->q->changed();
392  }
393  }
394 }
395 
396 void OutputDevice::Private::overscanCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t overscan)
397 {
398  auto o = reinterpret_cast<OutputDevice::Private *>(data);
399  Q_UNUSED(output);
400  if (o->overscan != overscan) {
401  o->overscan = overscan;
402  Q_EMIT o->q->overscanChanged(overscan);
403  if (o->done) {
404  Q_EMIT o->q->changed();
405  }
406  }
407 }
408 
409 void OutputDevice::Private::vrrPolicyCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t vrr_policy)
410 {
411  auto o = reinterpret_cast<OutputDevice::Private*>(data);
412  Q_UNUSED(output);
413  auto vrrPolicy = static_cast<VrrPolicy>(vrr_policy);
414  if (o->vrrPolicy != vrrPolicy) {
415  o->vrrPolicy = vrrPolicy;
416  Q_EMIT o->q->vrrPolicyChanged(vrrPolicy);
417  if (o->done) {
418  Q_EMIT o->q->changed();
419  }
420  }
421 }
422 
423 void OutputDevice::setup(org_kde_kwin_outputdevice *output)
424 {
425  d->setup(output);
426 }
427 
429 {
430  return d->queue;
431 }
432 
434 {
435  d->queue = queue;
436 }
437 
438 void OutputDevice::Private::setGlobalPosition(const QPoint &pos)
439 {
440  globalPosition = pos;
441 }
442 
443 void OutputDevice::Private::setManufacturer(const QString &m)
444 {
445  manufacturer = m;
446 }
447 
448 void OutputDevice::Private::setModel(const QString &m)
449 {
450  model = m;
451 }
452 
453 void OutputDevice::Private::setSerialNumber(const QString &sn)
454 {
455  serialNumber = sn;
456 }
457 
458 void OutputDevice::Private::setEisaId(const QString &e)
459 {
460  eisaId = e;
461 }
462 
463 void OutputDevice::Private::setPhysicalSize(const QSize &size)
464 {
465  physicalSize = size;
466 }
467 
468 void OutputDevice::Private::setScale(qreal s)
469 {
470  scale = s;
471 }
472 
474 {
475  if (d->currentMode == d->modes.end()) {
476  return QRect();
477  }
478  return QRect(d->globalPosition, pixelSize());
479 }
480 
481 void OutputDevice::Private::setSubPixel(OutputDevice::SubPixel s)
482 {
483  subPixel = s;
484 }
485 
486 void OutputDevice::Private::setTransform(OutputDevice::Transform t)
487 {
488  transform = t;
489 }
490 
492 {
493  return d->globalPosition;
494 }
495 
497 {
498  return d->manufacturer;
499 }
500 
502 {
503  return d->model;
504 }
505 
507 {
508  return d->serialNumber;
509 }
510 
512 {
513  return d->eisaId;
514 }
515 
516 org_kde_kwin_outputdevice *OutputDevice::output()
517 {
518  return d->output;
519 }
520 
522 {
523  return d->physicalSize;
524 }
525 
527 {
528  if (d->currentMode == d->modes.end()) {
529  return QSize();
530  }
531  return (*d->currentMode).size;
532 }
533 
535 {
536  if (d->currentMode == d->modes.end()) {
537  return 0;
538  }
539  return (*d->currentMode).refreshRate;
540 }
541 
542 #if KWAYLANDCLIENT_BUILD_DEPRECATED_SINCE(5, 50)
544 {
545  return qRound(d->scale);
546 }
547 #endif
548 
549 qreal OutputDevice::scaleF() const
550 {
551  return d->scale;
552 }
553 
555 {
556  return d->output.isValid();
557 }
558 
559 OutputDevice::SubPixel OutputDevice::subPixel() const
560 {
561  return d->subPixel;
562 }
563 
564 OutputDevice::Transform OutputDevice::transform() const
565 {
566  return d->transform;
567 }
568 
570 {
571  return d->modes;
572 }
573 
574 OutputDevice::operator org_kde_kwin_outputdevice *()
575 {
576  return d->output;
577 }
578 
579 OutputDevice::operator org_kde_kwin_outputdevice *() const
580 {
581  return d->output;
582 }
583 
585 {
586  return d->edid;
587 }
588 
589 OutputDevice::Enablement OutputDevice::enabled() const
590 {
591  return d->enabled;
592 }
593 
595 {
596  return d->uuid;
597 }
598 
599 OutputDevice::ColorCurves OutputDevice::colorCurves() const
600 {
601  return d->colorCurves;
602 }
603 
605 {
606  return d->capabilities;
607 }
608 
609 uint32_t OutputDevice::overscan() const
610 {
611  return d->overscan;
612 }
613 
614 OutputDevice::VrrPolicy OutputDevice::vrrPolicy() const
615 {
616  return d->vrrPolicy;
617 }
618 
620 {
621  d->output.destroy();
622 }
623 
624 }
625 }
KDOCTOOLS_EXPORT QString transform(const QString &file, const QString &stylesheet, const QVector< const char * > &params=QVector< const char * >())
Transform transform() const
Transform that maps framebuffer to OutputDevice.
ColorCurves colorCurves() const
Color curves.
QFlags< Capability > Capabilities
void setEventQueue(EventQueue *queue)
Sets the queue to use for bound proxies.
void destroy()
Destroys the data hold by this OutputDevice.
QString model() const
Textual description of the model.
QString manufacturer() const
Textual description of the manufacturer.
QString eisaId() const
Textual representation of EISA identifier.
Capabilities capabilities() const
OutputDevice::Enablement enabled() const
QPoint globalPosition() const
Position within the global compositor space.
void setup(org_kde_kwin_outputdevice *output)
Setup this Compositor to manage the output.
bool operator==(const Qt3DRender::QGraphicsApiFilter &reference, const Qt3DRender::QGraphicsApiFilter &sample)
Wrapper class for wl_event_queue interface.
Definition: event_queue.h:54
QList< Mode > modes() const
QByteArray fromBase64(const QByteArray &base64, QByteArray::Base64Options options)
int refreshRate() const
Refresh rate in mHz of the current mode.
SubPixel subPixel() const
Subpixel orientation of this OutputDevice.
QSize physicalSize() const
Size in millimeters.
Capabilities capabilities()
qreal scaleF() const
Scaling factor of this output.
int scale() const
Scaling factor of this output.
QString serialNumber() const
Textual representation of serial number.
EventQueue * eventQueue() const
QRect geometry() const
The geometry of this OutputDevice in pixels.
QList::iterator end()
QSize pixelSize() const
Size in the current mode.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Feb 8 2023 03:59:21 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.