KWayland

output.cpp
1 /*
2  SPDX-FileCopyrightText: 2013 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "output.h"
7 #include "wayland_pointer_p.h"
8 // Qt
9 #include <QPoint>
10 #include <QRect>
11 #include <QVector>
12 // wayland
13 #include <wayland-client-protocol.h>
14 
15 namespace KWayland
16 {
17 namespace Client
18 {
19 namespace
20 {
21 typedef QList<Output::Mode> Modes;
22 }
23 
24 class Q_DECL_HIDDEN Output::Private
25 {
26 public:
27  Private(Output *q);
28  ~Private();
29  void setup(wl_output *o);
30 
31  WaylandPointer<wl_output, wl_output_release> output;
32  EventQueue *queue = nullptr;
33  QSize physicalSize;
34  QPoint globalPosition;
35  QString manufacturer;
36  QString model;
37  int scale = 1;
38  SubPixel subPixel = SubPixel::Unknown;
39  Transform transform = Transform::Normal;
40  Modes modes;
41  Modes::iterator currentMode = modes.end();
42  QString name;
43  QString description;
44 
45  static Output *get(wl_output *o);
46 
47 private:
48  static void geometryCallback(void *data,
49  wl_output *output,
50  int32_t x,
51  int32_t y,
52  int32_t physicalWidth,
53  int32_t physicalHeight,
54  int32_t subPixel,
55  const char *make,
56  const char *model,
57  int32_t transform);
58  static void modeCallback(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh);
59  static void doneCallback(void *data, wl_output *output);
60  static void scaleCallback(void *data, wl_output *output, int32_t scale);
61  static void nameCallback(void *data, struct wl_output *wl_output, const char *name);
62  static void descriptionCallback(void *data, struct wl_output *wl_output, const char *description);
63  void setPhysicalSize(const QSize &size);
64  void setGlobalPosition(const QPoint &pos);
65  void setManufacturer(const QString &manufacturer);
66  void setModel(const QString &model);
67  void setScale(int scale);
68  void setSubPixel(SubPixel subPixel);
69  void setTransform(Transform transform);
70  void addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh);
71 
72  Output *q;
73  static struct wl_output_listener s_outputListener;
74 
75  static QVector<Private *> s_allOutputs;
76 };
77 
78 QVector<Output::Private *> Output::Private::s_allOutputs;
79 
80 Output::Private::Private(Output *q)
81  : q(q)
82 {
83  s_allOutputs << this;
84 }
85 
86 Output::Private::~Private()
87 {
88  s_allOutputs.removeOne(this);
89 }
90 
91 Output *Output::Private::get(wl_output *o)
92 {
93  auto it = std::find_if(s_allOutputs.constBegin(), s_allOutputs.constEnd(), [o](Private *p) {
94  const wl_output *reference = p->output;
95  return reference == o;
96  });
97  if (it != s_allOutputs.constEnd()) {
98  return (*it)->q;
99  }
100  return nullptr;
101 }
102 
103 void Output::Private::setup(wl_output *o)
104 {
105  Q_ASSERT(o);
106  Q_ASSERT(!output);
107  output.setup(o);
108  wl_output_add_listener(output, &s_outputListener, this);
109 }
110 
111 bool Output::Mode::operator==(const Output::Mode &m) const
112 {
113  return size == m.size && refreshRate == m.refreshRate && flags == m.flags && output == m.output;
114 }
115 
116 Output::Output(QObject *parent)
117  : QObject(parent)
118  , d(new Private(this))
119 {
120 }
121 
122 Output::~Output()
123 {
124  d->output.release();
125 }
126 
127 wl_output_listener Output::Private::s_outputListener = {
128  geometryCallback, modeCallback, doneCallback, scaleCallback,
129 #ifdef WL_OUTPUT_NAME_SINCE_VERSION
130  nameCallback,
131 #endif
132 #ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
133  descriptionCallback,
134 #endif
135 };
136 
137 void Output::Private::geometryCallback(void *data,
138  wl_output *output,
139  int32_t x,
140  int32_t y,
141  int32_t physicalWidth,
142  int32_t physicalHeight,
143  int32_t subPixel,
144  const char *make,
145  const char *model,
146  int32_t transform)
147 {
148  Q_UNUSED(transform)
149  auto o = reinterpret_cast<Output::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 Output::Private::modeCallback(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
198 {
199  auto o = reinterpret_cast<Output::Private *>(data);
200  Q_ASSERT(o->output == output);
201  o->addMode(flags, width, height, refresh);
202 }
203 
204 void Output::Private::addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh)
205 {
206  Mode mode;
207  mode.output = QPointer<Output>(q);
208  mode.refreshRate = refresh;
209  mode.size = QSize(width, height);
210  if (flags & WL_OUTPUT_MODE_CURRENT) {
211  mode.flags |= Mode::Flag::Current;
212  }
213  if (flags & WL_OUTPUT_MODE_PREFERRED) {
214  mode.flags |= Mode::Flag::Preferred;
215  }
216  auto currentIt = modes.insert(modes.end(), mode);
217  bool existing = false;
218  if (flags & WL_OUTPUT_MODE_CURRENT) {
219  auto it = modes.begin();
220  while (it != currentIt) {
221  auto &m = (*it);
222  if (m.flags.testFlag(Mode::Flag::Current)) {
223  m.flags &= ~Mode::Flags(Mode::Flag::Current);
224  Q_EMIT q->modeChanged(m);
225  }
226  if (m.refreshRate == mode.refreshRate && m.size == mode.size) {
227  it = modes.erase(it);
228  existing = true;
229  } else {
230  it++;
231  }
232  }
233  currentMode = currentIt;
234  }
235  if (existing) {
236  Q_EMIT q->modeChanged(mode);
237  } else {
238  Q_EMIT q->modeAdded(mode);
239  }
240 }
241 
242 void Output::Private::scaleCallback(void *data, wl_output *output, int32_t scale)
243 {
244  auto o = reinterpret_cast<Output::Private *>(data);
245  Q_ASSERT(o->output == output);
246  o->setScale(scale);
247 }
248 
249 void Output::Private::nameCallback(void *data, struct wl_output *wl_output, const char *name)
250 {
251  auto o = reinterpret_cast<Output::Private *>(data);
252  Q_ASSERT(o->output == wl_output);
253  o->name = QString::fromUtf8(name);
254 }
255 
256 void Output::Private::descriptionCallback(void *data, struct wl_output *wl_output, const char *description)
257 {
258  auto o = reinterpret_cast<Output::Private *>(data);
259  Q_ASSERT(o->output == wl_output);
260  o->description = QString::fromUtf8(description);
261 }
262 
263 void Output::Private::doneCallback(void *data, wl_output *output)
264 {
265  auto o = reinterpret_cast<Output::Private *>(data);
266  Q_ASSERT(o->output == output);
267  Q_EMIT o->q->changed();
268 }
269 
270 void Output::setup(wl_output *output)
271 {
272  d->setup(output);
273 }
274 
275 EventQueue *Output::eventQueue() const
276 {
277  return d->queue;
278 }
279 
280 void Output::setEventQueue(EventQueue *queue)
281 {
282  d->queue = queue;
283 }
284 
285 void Output::Private::setGlobalPosition(const QPoint &pos)
286 {
287  globalPosition = pos;
288 }
289 
290 void Output::Private::setManufacturer(const QString &m)
291 {
292  manufacturer = m;
293 }
294 
295 void Output::Private::setModel(const QString &m)
296 {
297  model = m;
298 }
299 
300 void Output::Private::setPhysicalSize(const QSize &size)
301 {
302  physicalSize = size;
303 }
304 
305 void Output::Private::setScale(int s)
306 {
307  scale = s;
308 }
309 
310 QRect Output::geometry() const
311 {
312  if (d->currentMode == d->modes.end()) {
313  return QRect();
314  }
315  return QRect(d->globalPosition, pixelSize());
316 }
317 
318 void Output::Private::setSubPixel(Output::SubPixel s)
319 {
320  subPixel = s;
321 }
322 
323 void Output::Private::setTransform(Output::Transform t)
324 {
325  transform = t;
326 }
327 
328 QPoint Output::globalPosition() const
329 {
330  return d->globalPosition;
331 }
332 
333 QString Output::manufacturer() const
334 {
335  return d->manufacturer;
336 }
337 
338 QString Output::model() const
339 {
340  return d->model;
341 }
342 
343 wl_output *Output::output()
344 {
345  return d->output;
346 }
347 
348 QSize Output::physicalSize() const
349 {
350  return d->physicalSize;
351 }
352 
353 QSize Output::pixelSize() const
354 {
355  if (d->currentMode == d->modes.end()) {
356  return QSize();
357  }
358  return (*d->currentMode).size;
359 }
360 
361 int Output::refreshRate() const
362 {
363  if (d->currentMode == d->modes.end()) {
364  return 0;
365  }
366  return (*d->currentMode).refreshRate;
367 }
368 
369 int Output::scale() const
370 {
371  return d->scale;
372 }
373 
374 bool Output::isValid() const
375 {
376  return d->output.isValid();
377 }
378 
379 Output::SubPixel Output::subPixel() const
380 {
381  return d->subPixel;
382 }
383 
384 Output::Transform Output::transform() const
385 {
386  return d->transform;
387 }
388 
389 QList<Output::Mode> Output::modes() const
390 {
391  return d->modes;
392 }
393 
394 QString Output::name() const
395 {
396  return d->name;
397 }
398 
399 QString Output::description() const
400 {
401  return d->description;
402 }
403 
404 Output::operator wl_output *()
405 {
406  return d->output;
407 }
408 
409 Output::operator wl_output *() const
410 {
411  return d->output;
412 }
413 
414 Output *Output::get(wl_output *o)
415 {
416  return Private::get(o);
417 }
418 
419 void Output::destroy()
420 {
421  d->output.destroy();
422 }
423 
424 }
425 }
KDOCTOOLS_EXPORT QString transform(const QString &file, const QString &stylesheet, const QVector< const char * > &params=QVector< const char * >())
Wrapper for the wl_output interface.
Definition: output.h:54
QString fromUtf8(const char *str, int size)
Q_EMITQ_EMIT
Wrapper class for wl_event_queue interface.
Definition: event_queue.h:54
QList::iterator end()
QObject * parent() const const
virtual QVariant get(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Jan 30 2023 03:56:24 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.