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

KDE's Doxygen guidelines are available online.