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 #include <QSize>
15 // wayland
16 #include "wayland-org_kde_kwin_outputdevice-client-protocol.h"
17 #include <wayland-client-protocol.h>
18 
19 namespace KWayland
20 {
21 
22 namespace Client
23 {
24 
25 typedef QList<OutputDevice::Mode> Modes;
26 
27 class Q_DECL_HIDDEN OutputDevice::Private
28 {
29 public:
30  Private(OutputDevice *q);
31  void setup(org_kde_kwin_outputdevice *o);
32 
33  WaylandPointer<org_kde_kwin_outputdevice, org_kde_kwin_outputdevice_destroy> output;
34  EventQueue *queue = nullptr;
35  QSize physicalSize;
36  QPoint globalPosition;
37  QString manufacturer;
38  QString model;
39  qreal scale = 1.0;
40  QString serialNumber;
41  QString eisaId;
42  SubPixel subPixel = SubPixel::Unknown;
43  Transform transform = Transform::Normal;
44  Modes modes;
45  Modes::iterator currentMode = modes.end();
46 
47  QByteArray edid;
48  OutputDevice::Enablement enabled = OutputDevice::Enablement::Enabled;
49  QByteArray uuid;
50 
51  ColorCurves colorCurves;
52 
53  bool done = false;
54 
55 private:
56  static void geometryCallback(void *data, org_kde_kwin_outputdevice *output, int32_t x, int32_t y,
57  int32_t physicalWidth, int32_t physicalHeight, int32_t subPixel,
58  const char *make, const char *model, int32_t transform);
59  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);
60  static void doneCallback(void *data, org_kde_kwin_outputdevice *output);
61  static void scaleCallback(void *data, org_kde_kwin_outputdevice *output, int32_t scale);
62  static void scaleFCallback(void *data, org_kde_kwin_outputdevice *output, wl_fixed_t scale);
63 
64  static void edidCallback(void *data, org_kde_kwin_outputdevice *output, const char *raw);
65  static void enabledCallback(void *data, org_kde_kwin_outputdevice *output, int32_t enabled);
66  static void uuidCallback(void *data, org_kde_kwin_outputdevice *output, const char *uuid);
67 
68  static void colorcurvesCallback(void *data, org_kde_kwin_outputdevice *output,
69  wl_array *red, wl_array *green, wl_array *blue);
70 
71  static void serialNumberCallback(void *data, org_kde_kwin_outputdevice *output, const char *serialNumber);
72  static void eisaIdCallback(void *data, org_kde_kwin_outputdevice *output, const char *eisa);
73 
74  void setPhysicalSize(const QSize &size);
75  void setGlobalPosition(const QPoint &pos);
76  void setManufacturer(const QString &manufacturer);
77  void setModel(const QString &model);
78  void setScale(qreal scale);
79  void setSerialNumber(const QString &serialNumber);
80  void setEisaId(const QString &eisaId);
81  void setSubPixel(SubPixel subPixel);
82  void setTransform(Transform transform);
83  void addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh, int32_t mode_id);
84 
85  OutputDevice *q;
86  static struct org_kde_kwin_outputdevice_listener s_outputListener;
87 };
88 
89 OutputDevice::Private::Private(OutputDevice *q)
90  : q(q)
91 {
92 }
93 
94 void OutputDevice::Private::setup(org_kde_kwin_outputdevice *o)
95 {
96  Q_ASSERT(o);
97  Q_ASSERT(!output);
98  output.setup(o);
99  org_kde_kwin_outputdevice_add_listener(output, &s_outputListener, this);
100 }
101 
102 bool OutputDevice::Mode::operator==(const OutputDevice::Mode &m) const
103 {
104  return size == m.size
105  && refreshRate == m.refreshRate
106  && flags == m.flags
107  && output == m.output;
108 }
109 
110 bool OutputDevice::ColorCurves::operator==(const OutputDevice::ColorCurves &cc) const
111 {
112  return red == cc.red && green == cc.green && blue == cc.blue;
113 }
114 bool OutputDevice::ColorCurves::operator!=(const ColorCurves &cc) const {
115  return !operator==(cc);
116 }
117 
118 OutputDevice::OutputDevice(QObject *parent)
119  : QObject(parent)
120  , d(new Private(this))
121 {
122 }
123 
124 OutputDevice::~OutputDevice()
125 {
126  d->output.release();
127 }
128 
129 org_kde_kwin_outputdevice_listener OutputDevice::Private::s_outputListener = {
130  geometryCallback,
131  modeCallback,
132  doneCallback,
133  scaleCallback,
134  edidCallback,
135  enabledCallback,
136  uuidCallback,
137  scaleFCallback,
138  colorcurvesCallback,
139  serialNumberCallback,
140  eisaIdCallback
141 };
142 
143 void OutputDevice::Private::geometryCallback(void *data, org_kde_kwin_outputdevice *output,
144  int32_t x, int32_t y,
145  int32_t physicalWidth, int32_t physicalHeight,
146  int32_t subPixel, const char *make, const char *model, int32_t transform)
147 {
148  Q_UNUSED(transform)
149  auto o = reinterpret_cast<OutputDevice::Private*>(data);
150  Q_ASSERT(o->output == output);
151  o->setGlobalPosition(QPoint(x, y));
152  o->setManufacturer(make);
153  o->setModel(model);
154  o->setPhysicalSize(QSize(physicalWidth, physicalHeight));
155  auto toSubPixel = [subPixel]() {
156  switch (subPixel) {
157  case WL_OUTPUT_SUBPIXEL_NONE:
158  return SubPixel::None;
159  case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
160  return SubPixel::HorizontalRGB;
161  case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
162  return SubPixel::HorizontalBGR;
163  case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
164  return SubPixel::VerticalRGB;
165  case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
166  return SubPixel::VerticalBGR;
167  case WL_OUTPUT_SUBPIXEL_UNKNOWN:
168  default:
169  return SubPixel::Unknown;
170  }
171  };
172  o->setSubPixel(toSubPixel());
173  auto toTransform = [transform]() {
174  switch (transform) {
175  case WL_OUTPUT_TRANSFORM_90:
176  return Transform::Rotated90;
177  case WL_OUTPUT_TRANSFORM_180:
178  return Transform::Rotated180;
179  case WL_OUTPUT_TRANSFORM_270:
180  return Transform::Rotated270;
181  case WL_OUTPUT_TRANSFORM_FLIPPED:
182  return Transform::Flipped;
183  case WL_OUTPUT_TRANSFORM_FLIPPED_90:
184  return Transform::Flipped90;
185  case WL_OUTPUT_TRANSFORM_FLIPPED_180:
186  return Transform::Flipped180;
187  case WL_OUTPUT_TRANSFORM_FLIPPED_270:
188  return Transform::Flipped270;
189  case WL_OUTPUT_TRANSFORM_NORMAL:
190  default:
191  return Transform::Normal;
192  }
193  };
194  o->setTransform(toTransform());
195 }
196 
197 void OutputDevice::Private::modeCallback(void *data, org_kde_kwin_outputdevice *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh, int32_t mode_id)
198 {
199  auto o = reinterpret_cast<OutputDevice::Private*>(data);
200  Q_ASSERT(o->output == output);
201  o->addMode(flags, width, height, refresh, mode_id);
202 }
203 
204 void OutputDevice::Private::addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh, int32_t mode_id)
205 {
206  Mode mode;
207  mode.output = QPointer<OutputDevice>(q);
208  mode.refreshRate = refresh;
209  mode.size = QSize(width, height);
210  mode.id = mode_id;
211  if (flags & WL_OUTPUT_MODE_CURRENT) {
212  mode.flags |= Mode::Flag::Current;
213  }
214  if (flags & WL_OUTPUT_MODE_PREFERRED) {
215  mode.flags |= Mode::Flag::Preferred;
216  }
217  auto currentIt = modes.insert(modes.end(), mode);
218  bool existing = false;
219  if (flags & WL_OUTPUT_MODE_CURRENT) {
220  auto it = modes.begin();
221  while (it != currentIt) {
222  auto &m = (*it);
223  if (m.flags.testFlag(Mode::Flag::Current)) {
224  m.flags &= ~Mode::Flags(Mode::Flag::Current);
225  emit q->modeChanged(m);
226  }
227  if (m.refreshRate == mode.refreshRate && m.size == mode.size) {
228  it = modes.erase(it);
229  existing = true;
230  } else {
231  it++;
232  }
233  }
234  currentMode = currentIt;
235  }
236  if (existing) {
237  emit q->modeChanged(mode);
238  } else {
239  emit q->modeAdded(mode);
240  }
241 }
242 
243 KWayland::Client::OutputDevice::Mode OutputDevice::currentMode() const
244 {
245  for (const auto &m: modes()) {
246  if (m.flags.testFlag(KWayland::Client::OutputDevice::Mode::Flag::Current)) {
247  return m;
248  }
249  }
250  qCWarning(KWAYLAND_CLIENT) << "current mode not found";
251  return Mode();
252 }
253 
254 void OutputDevice::Private::scaleCallback(void *data, org_kde_kwin_outputdevice *output, int32_t scale)
255 {
256  auto o = reinterpret_cast<OutputDevice::Private*>(data);
257  Q_ASSERT(o->output == output);
258  o->setScale(scale);
259 }
260 
261 void OutputDevice::Private::scaleFCallback(void *data, org_kde_kwin_outputdevice *output, wl_fixed_t scale_fixed)
262 {
263  auto o = reinterpret_cast<OutputDevice::Private*>(data);
264  Q_ASSERT(o->output == output);
265  o->setScale(wl_fixed_to_double(scale_fixed));
266 }
267 
268 void OutputDevice::Private::doneCallback(void *data, org_kde_kwin_outputdevice *output)
269 {
270  auto o = reinterpret_cast<OutputDevice::Private*>(data);
271  Q_ASSERT(o->output == output);
272  o->done = true;
273  emit o->q->changed();
274  emit o->q->done();
275 }
276 
277 void OutputDevice::Private::edidCallback(void* data, org_kde_kwin_outputdevice* output, const char* raw)
278 {
279  Q_UNUSED(output);
280  auto o = reinterpret_cast<OutputDevice::Private*>(data);
281  o->edid = QByteArray::fromBase64(raw);
282 }
283 
284 void OutputDevice::Private::enabledCallback(void* data, org_kde_kwin_outputdevice* output, int32_t enabled)
285 {
286  Q_UNUSED(output);
287  auto o = reinterpret_cast<OutputDevice::Private*>(data);
288 
289  OutputDevice::Enablement _enabled = OutputDevice::Enablement::Disabled;
290  if (enabled == ORG_KDE_KWIN_OUTPUTDEVICE_ENABLEMENT_ENABLED) {
291  _enabled = OutputDevice::Enablement::Enabled;
292  }
293  if (o->enabled != _enabled) {
294  o->enabled = _enabled;
295  emit o->q->enabledChanged(o->enabled);
296  if (o->done) {
297  emit o->q->changed();
298  }
299  }
300 }
301 
302 void OutputDevice::Private::uuidCallback(void* data, org_kde_kwin_outputdevice* output, const char *uuid)
303 {
304  Q_UNUSED(output);
305  auto o = reinterpret_cast<OutputDevice::Private*>(data);
306  if (o->uuid != uuid) {
307  o->uuid = uuid;
308  emit o->q->uuidChanged(o->uuid);
309  if (o->done) {
310  emit o->q->changed();
311  }
312  }
313 }
314 
315 void OutputDevice::Private::colorcurvesCallback(void *data, org_kde_kwin_outputdevice *output,
316  wl_array *red,
317  wl_array *green,
318  wl_array *blue)
319 {
320  Q_UNUSED(output);
321  auto o = reinterpret_cast<OutputDevice::Private*>(data);
322 
323  auto cc = ColorCurves();
324 
325  auto setCurve = [](const wl_array *curve, QVector<quint16> *destination) {
326  destination->resize(curve->size / sizeof(uint16_t));
327  memcpy(destination->data(), curve->data, curve->size);
328  };
329  setCurve(red, &cc.red);
330  setCurve(green, &cc.green);
331  setCurve(blue, &cc.blue);
332 
333  if (o->colorCurves != cc) {
334  o->colorCurves = cc;
335  emit o->q->colorCurvesChanged();
336  if (o->done) {
337  emit o->q->changed();
338  }
339  }
340 }
341 
342 void OutputDevice::Private::serialNumberCallback(void *data, org_kde_kwin_outputdevice *output, const char *raw)
343 {
344  auto o = reinterpret_cast<OutputDevice::Private*>(data);
345  Q_UNUSED(output);
346  o->setSerialNumber(raw);
347 }
348 
349 void OutputDevice::Private::eisaIdCallback(void *data, org_kde_kwin_outputdevice *output, const char *raw)
350 {
351  auto o = reinterpret_cast<OutputDevice::Private*>(data);
352  Q_UNUSED(output);
353  o->setEisaId(raw);
354 }
355 
356 void OutputDevice::setup(org_kde_kwin_outputdevice *output)
357 {
358  d->setup(output);
359 }
360 
362 {
363  return d->queue;
364 }
365 
367 {
368  d->queue = queue;
369 }
370 
371 void OutputDevice::Private::setGlobalPosition(const QPoint &pos)
372 {
373  globalPosition = pos;
374 }
375 
376 void OutputDevice::Private::setManufacturer(const QString &m)
377 {
378  manufacturer = m;
379 }
380 
381 void OutputDevice::Private::setModel(const QString &m)
382 {
383  model = m;
384 }
385 
386 void OutputDevice::Private::setSerialNumber(const QString &sn)
387 {
388  serialNumber = sn;
389 }
390 
391 void OutputDevice::Private::setEisaId(const QString &e)
392 {
393  eisaId = e;
394 }
395 
396 void OutputDevice::Private::setPhysicalSize(const QSize &size)
397 {
398  physicalSize = size;
399 }
400 
401 void OutputDevice::Private::setScale(qreal s)
402 {
403  scale = s;
404 }
405 
407 {
408  if (d->currentMode == d->modes.end()) {
409  return QRect();
410  }
411  return QRect(d->globalPosition, pixelSize());
412 }
413 
414 void OutputDevice::Private::setSubPixel(OutputDevice::SubPixel s)
415 {
416  subPixel = s;
417 }
418 
419 void OutputDevice::Private::setTransform(OutputDevice::Transform t)
420 {
421  transform = t;
422 }
423 
425 {
426  return d->globalPosition;
427 }
428 
430 {
431  return d->manufacturer;
432 }
433 
435 {
436  return d->model;
437 }
438 
440 {
441  return d->serialNumber;
442 }
443 
445 {
446  return d->eisaId;
447 }
448 
449 org_kde_kwin_outputdevice *OutputDevice::output()
450 {
451  return d->output;
452 }
453 
455 {
456  return d->physicalSize;
457 }
458 
460 {
461  if (d->currentMode == d->modes.end()) {
462  return QSize();
463  }
464  return (*d->currentMode).size;
465 }
466 
468 {
469  if (d->currentMode == d->modes.end()) {
470  return 0;
471  }
472  return (*d->currentMode).refreshRate;
473 }
474 
476 {
477  return qRound(d->scale);
478 }
479 
480 qreal OutputDevice::scaleF() const
481 {
482  return d->scale;
483 }
484 
485 
487 {
488  return d->output.isValid();
489 }
490 
491 OutputDevice::SubPixel OutputDevice::subPixel() const
492 {
493  return d->subPixel;
494 }
495 
496 OutputDevice::Transform OutputDevice::transform() const
497 {
498  return d->transform;
499 }
500 
502 {
503  return d->modes;
504 }
505 
506 OutputDevice::operator org_kde_kwin_outputdevice*() {
507  return d->output;
508 }
509 
510 OutputDevice::operator org_kde_kwin_outputdevice*() const {
511  return d->output;
512 }
513 
515 {
516  return d->edid;
517 }
518 
519 OutputDevice::Enablement OutputDevice::enabled() const
520 {
521  return d->enabled;
522 }
523 
525 {
526  return d->uuid;
527 }
528 
529 OutputDevice::ColorCurves OutputDevice::colorCurves() const
530 {
531  return d->colorCurves;
532 }
533 
535 {
536  d->output.destroy();
537 
538 }
539 
540 }
541 }
QList< Mode > modes() const
QSize physicalSize() const
Size in millimeters.
QString::iterator end()
Wrapper class for wl_event_queue interface.
Definition: event_queue.h:55
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.
QByteArray fromBase64(const QByteArray &base64, QByteArray::Base64Options options)
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.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Jul 9 2020 22:49:30 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.