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 
50  Capabilities capabilities;
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 
543 {
544  return qRound(d->scale);
545 }
546 
547 qreal OutputDevice::scaleF() const
548 {
549  return d->scale;
550 }
551 
553 {
554  return d->output.isValid();
555 }
556 
557 OutputDevice::SubPixel OutputDevice::subPixel() const
558 {
559  return d->subPixel;
560 }
561 
562 OutputDevice::Transform OutputDevice::transform() const
563 {
564  return d->transform;
565 }
566 
568 {
569  return d->modes;
570 }
571 
572 OutputDevice::operator org_kde_kwin_outputdevice *()
573 {
574  return d->output;
575 }
576 
577 OutputDevice::operator org_kde_kwin_outputdevice *() const
578 {
579  return d->output;
580 }
581 
583 {
584  return d->edid;
585 }
586 
587 OutputDevice::Enablement OutputDevice::enabled() const
588 {
589  return d->enabled;
590 }
591 
593 {
594  return d->uuid;
595 }
596 
597 OutputDevice::ColorCurves OutputDevice::colorCurves() const
598 {
599  return d->colorCurves;
600 }
601 
603 {
604  return d->capabilities;
605 }
606 
607 uint32_t OutputDevice::overscan() const
608 {
609  return d->overscan;
610 }
611 
612 OutputDevice::VrrPolicy OutputDevice::vrrPolicy() const
613 {
614  return d->vrrPolicy;
615 }
616 
618 {
619  d->output.destroy();
620 }
621 
622 }
623 }
QList< Mode > modes() const
QSize physicalSize() const
Size in millimeters.
QString::iterator end()
Wrapper class for wl_event_queue interface.
Definition: event_queue.h:54
int scale() const
Scaling factor of this output.
QRect geometry() const
The geometry of this OutputDevice in pixels.
QString serialNumber() const
Textual representation of serial number.
Transform transform() const
Transform that maps framebuffer to OutputDevice.
KDOCTOOLS_EXPORT QString transform(const QString &file, const QString &stylesheet, const QVector< const char * > &params=QVector< const char * >())
bool operator==(const Qt3DRender::QGraphicsApiFilter &reference, const Qt3DRender::QGraphicsApiFilter &sample)
QString manufacturer() const
Textual description of the manufacturer.
QString eisaId() const
Textual representation of EISA identifier.
void destroy()
Destroys the data hold by this OutputDevice.
void setEventQueue(EventQueue *queue)
Sets the queue to use for bound proxies.
SubPixel subPixel() const
Subpixel orientation of this OutputDevice.
Capabilities capabilities() const
QByteArray fromBase64(const QByteArray &base64, QByteArray::Base64Options options)
Capabilities capabilities()
EventQueue * eventQueue() const
QSize pixelSize() const
Size in the current mode.
int refreshRate() const
Refresh rate in mHz of the current mode.
QPoint globalPosition() const
Position within the global compositor space.
qreal scaleF() const
Scaling factor of this output.
QObject * parent() const const
ColorCurves colorCurves() const
Color curves.
OutputDevice::Enablement enabled() const
void setup(org_kde_kwin_outputdevice *output)
Setup this Compositor to manage the output.
QString model() const
Textual description of the model.
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Sep 26 2021 22:51:13 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.