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 
18 namespace Client
19 {
20 
21 namespace {
22 typedef QList<Output::Mode> Modes;
23 }
24 
25 class Q_DECL_HIDDEN Output::Private
26 {
27 public:
28  Private(Output *q);
29  ~Private();
30  void setup(wl_output *o);
31 
32  WaylandPointer<wl_output, wl_output_release> output;
33  EventQueue *queue = nullptr;
34  QSize physicalSize;
35  QPoint globalPosition;
36  QString manufacturer;
37  QString model;
38  int scale = 1;
39  SubPixel subPixel = SubPixel::Unknown;
40  Transform transform = Transform::Normal;
41  Modes modes;
42  Modes::iterator currentMode = modes.end();
43 
44  static Output *get(wl_output *o);
45 
46 private:
47  static void geometryCallback(void *data, wl_output *output, int32_t x, int32_t y,
48  int32_t physicalWidth, int32_t physicalHeight, int32_t subPixel,
49  const char *make, const char *model, int32_t transform);
50  static void modeCallback(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh);
51  static void doneCallback(void *data, wl_output *output);
52  static void scaleCallback(void *data, wl_output *output, int32_t scale);
53  void setPhysicalSize(const QSize &size);
54  void setGlobalPosition(const QPoint &pos);
55  void setManufacturer(const QString &manufacturer);
56  void setModel(const QString &model);
57  void setScale(int scale);
58  void setSubPixel(SubPixel subPixel);
59  void setTransform(Transform transform);
60  void addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh);
61 
62  Output *q;
63  static struct wl_output_listener s_outputListener;
64 
65  static QVector<Private*> s_allOutputs;
66 };
67 
68 QVector<Output::Private*> Output::Private::s_allOutputs;
69 
70 Output::Private::Private(Output *q)
71  : q(q)
72 {
73  s_allOutputs << this;
74 }
75 
76 Output::Private::~Private()
77 {
78  s_allOutputs.removeOne(this);
79 }
80 
81 Output *Output::Private::get(wl_output *o)
82 {
83  auto it = std::find_if(s_allOutputs.constBegin(), s_allOutputs.constEnd(),
84  [o] (Private *p) {
85  const wl_output *reference = p->output;
86  return reference == o;
87  }
88  );
89  if (it != s_allOutputs.constEnd()) {
90  return (*it)->q;
91  }
92  return nullptr;
93 }
94 
95 void Output::Private::setup(wl_output *o)
96 {
97  Q_ASSERT(o);
98  Q_ASSERT(!output);
99  output.setup(o);
100  wl_output_add_listener(output, &s_outputListener, this);
101 }
102 
103 bool Output::Mode::operator==(const Output::Mode &m) const
104 {
105  return size == m.size
106  && refreshRate == m.refreshRate
107  && flags == m.flags
108  && output == m.output;
109 }
110 
111 Output::Output(QObject *parent)
112  : QObject(parent)
113  , d(new Private(this))
114 {
115 }
116 
117 Output::~Output()
118 {
119  d->output.release();
120 }
121 
122 wl_output_listener Output::Private::s_outputListener = {
123  geometryCallback,
124  modeCallback,
125  doneCallback,
126  scaleCallback
127 };
128 
129 void Output::Private::geometryCallback(void *data, wl_output *output,
130  int32_t x, int32_t y,
131  int32_t physicalWidth, int32_t physicalHeight,
132  int32_t subPixel, const char *make, const char *model, int32_t transform)
133 {
134  Q_UNUSED(transform)
135  auto o = reinterpret_cast<Output::Private*>(data);
136  Q_ASSERT(o->output == output);
137  o->setGlobalPosition(QPoint(x, y));
138  o->setManufacturer(make);
139  o->setModel(model);
140  o->setPhysicalSize(QSize(physicalWidth, physicalHeight));
141  auto toSubPixel = [subPixel]() {
142  switch (subPixel) {
143  case WL_OUTPUT_SUBPIXEL_NONE:
144  return SubPixel::None;
145  case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
146  return SubPixel::HorizontalRGB;
147  case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
148  return SubPixel::HorizontalBGR;
149  case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
150  return SubPixel::VerticalRGB;
151  case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
152  return SubPixel::VerticalBGR;
153  case WL_OUTPUT_SUBPIXEL_UNKNOWN:
154  default:
155  return SubPixel::Unknown;
156  }
157  };
158  o->setSubPixel(toSubPixel());
159  auto toTransform = [transform]() {
160  switch (transform) {
161  case WL_OUTPUT_TRANSFORM_90:
162  return Transform::Rotated90;
163  case WL_OUTPUT_TRANSFORM_180:
164  return Transform::Rotated180;
165  case WL_OUTPUT_TRANSFORM_270:
166  return Transform::Rotated270;
167  case WL_OUTPUT_TRANSFORM_FLIPPED:
168  return Transform::Flipped;
169  case WL_OUTPUT_TRANSFORM_FLIPPED_90:
170  return Transform::Flipped90;
171  case WL_OUTPUT_TRANSFORM_FLIPPED_180:
172  return Transform::Flipped180;
173  case WL_OUTPUT_TRANSFORM_FLIPPED_270:
174  return Transform::Flipped270;
175  case WL_OUTPUT_TRANSFORM_NORMAL:
176  default:
177  return Transform::Normal;
178  }
179  };
180  o->setTransform(toTransform());
181 }
182 
183 void Output::Private::modeCallback(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
184 {
185  auto o = reinterpret_cast<Output::Private*>(data);
186  Q_ASSERT(o->output == output);
187  o->addMode(flags, width, height, refresh);
188 }
189 
190 void Output::Private::addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh)
191 {
192  Mode mode;
193  mode.output = QPointer<Output>(q);
194  mode.refreshRate = refresh;
195  mode.size = QSize(width, height);
196  if (flags & WL_OUTPUT_MODE_CURRENT) {
197  mode.flags |= Mode::Flag::Current;
198  }
199  if (flags & WL_OUTPUT_MODE_PREFERRED) {
200  mode.flags |= Mode::Flag::Preferred;
201  }
202  auto currentIt = modes.insert(modes.end(), mode);
203  bool existing = false;
204  if (flags & WL_OUTPUT_MODE_CURRENT) {
205  auto it = modes.begin();
206  while (it != currentIt) {
207  auto &m = (*it);
208  if (m.flags.testFlag(Mode::Flag::Current)) {
209  m.flags &= ~Mode::Flags(Mode::Flag::Current);
210  emit q->modeChanged(m);
211  }
212  if (m.refreshRate == mode.refreshRate && m.size == mode.size) {
213  it = modes.erase(it);
214  existing = true;
215  } else {
216  it++;
217  }
218  }
219  currentMode = currentIt;
220  }
221  if (existing) {
222  emit q->modeChanged(mode);
223  } else {
224  emit q->modeAdded(mode);
225  }
226 }
227 
228 void Output::Private::scaleCallback(void *data, wl_output *output, int32_t scale)
229 {
230  auto o = reinterpret_cast<Output::Private*>(data);
231  Q_ASSERT(o->output == output);
232  o->setScale(scale);
233 }
234 
235 void Output::Private::doneCallback(void *data, wl_output *output)
236 {
237  auto o = reinterpret_cast<Output::Private*>(data);
238  Q_ASSERT(o->output == output);
239  emit o->q->changed();
240 }
241 
242 void Output::setup(wl_output *output)
243 {
244  d->setup(output);
245 }
246 
247 EventQueue *Output::eventQueue() const
248 {
249  return d->queue;
250 }
251 
252 void Output::setEventQueue(EventQueue *queue)
253 {
254  d->queue = queue;
255 }
256 
257 void Output::Private::setGlobalPosition(const QPoint &pos)
258 {
259  globalPosition = pos;
260 }
261 
262 void Output::Private::setManufacturer(const QString &m)
263 {
264  manufacturer = m;
265 }
266 
267 void Output::Private::setModel(const QString &m)
268 {
269  model = m;
270 }
271 
272 void Output::Private::setPhysicalSize(const QSize &size)
273 {
274  physicalSize = size;
275 }
276 
277 void Output::Private::setScale(int s)
278 {
279  scale = s;
280 }
281 
282 QRect Output::geometry() const
283 {
284  if (d->currentMode == d->modes.end()) {
285  return QRect();
286  }
287  return QRect(d->globalPosition, pixelSize());
288 }
289 
290 void Output::Private::setSubPixel(Output::SubPixel s)
291 {
292  subPixel = s;
293 }
294 
295 void Output::Private::setTransform(Output::Transform t)
296 {
297  transform = t;
298 }
299 
300 QPoint Output::globalPosition() const
301 {
302  return d->globalPosition;
303 }
304 
305 QString Output::manufacturer() const
306 {
307  return d->manufacturer;
308 }
309 
310 QString Output::model() const
311 {
312  return d->model;
313 }
314 
315 wl_output *Output::output()
316 {
317  return d->output;
318 }
319 
320 QSize Output::physicalSize() const
321 {
322  return d->physicalSize;
323 }
324 
325 QSize Output::pixelSize() const
326 {
327  if (d->currentMode == d->modes.end()) {
328  return QSize();
329  }
330  return (*d->currentMode).size;
331 }
332 
333 int Output::refreshRate() const
334 {
335  if (d->currentMode == d->modes.end()) {
336  return 0;
337  }
338  return (*d->currentMode).refreshRate;
339 }
340 
341 int Output::scale() const
342 {
343  return d->scale;
344 }
345 
346 bool Output::isValid() const
347 {
348  return d->output.isValid();
349 }
350 
351 Output::SubPixel Output::subPixel() const
352 {
353  return d->subPixel;
354 }
355 
356 Output::Transform Output::transform() const
357 {
358  return d->transform;
359 }
360 
361 QList< Output::Mode > Output::modes() const
362 {
363  return d->modes;
364 }
365 
366 Output::operator wl_output*() {
367  return d->output;
368 }
369 
370 Output::operator wl_output*() const {
371  return d->output;
372 }
373 
374 Output *Output::get(wl_output *o)
375 {
376  return Private::get(o);
377 }
378 
379 void Output::destroy()
380 {
381  d->output.destroy();
382 }
383 
384 }
385 }
Wrapper class for wl_event_queue interface.
Definition: event_queue.h:55
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:55
QList::iterator end()
QObject * parent() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Jan 16 2021 22:52:08 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.