KWaylandServer

output_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 Martin Gräßlin <[email protected]>
3  SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 #include "output_interface.h"
8 #include "display.h"
9 #include "display_p.h"
10 #include "utils.h"
11 
12 #include "qwayland-server-wayland.h"
13 
14 #include <QPointer>
15 #include <QVector>
16 
17 namespace KWaylandServer
18 {
19 static const int s_version = 3;
20 
21 class OutputInterfacePrivate : public QtWaylandServer::wl_output
22 {
23 public:
24  explicit OutputInterfacePrivate(Display *display, OutputInterface *q);
25 
26  void sendScale(Resource *resource);
27  void sendGeometry(Resource *resource);
28  void sendMode(Resource *resource);
29  void sendDone(Resource *resource);
30 
31  void broadcastGeometry();
32 
33  OutputInterface *q;
34  QPointer<Display> display;
35  QSize physicalSize;
36  QPoint globalPosition;
37  QString manufacturer = QStringLiteral("org.kde.kwin");
38  QString model = QStringLiteral("none");
39  int scale = 1;
40  OutputInterface::SubPixel subPixel = OutputInterface::SubPixel::Unknown;
41  OutputInterface::Transform transform = OutputInterface::Transform::Normal;
42  OutputInterface::Mode mode;
43  struct {
44  OutputInterface::DpmsMode mode = OutputInterface::DpmsMode::Off;
45  bool supported = false;
46  } dpms;
47 
48 private:
49  void output_destroy_global() override;
50  void output_bind_resource(Resource *resource) override;
51  void output_release(Resource *resource) override;
52 };
53 
54 OutputInterfacePrivate::OutputInterfacePrivate(Display *display, OutputInterface *q)
55  : QtWaylandServer::wl_output(*display, s_version)
56  , q(q)
57  , display(display)
58 {
59 }
60 
61 void OutputInterfacePrivate::sendMode(Resource *resource)
62 {
63  send_mode(resource->handle, mode_current, mode.size.width(), mode.size.height(), mode.refreshRate);
64 }
65 
66 void OutputInterfacePrivate::sendScale(Resource *resource)
67 {
68  if (resource->version() >= WL_OUTPUT_SCALE_SINCE_VERSION) {
69  send_scale(resource->handle, scale);
70  }
71 }
72 
73 static quint32 kwaylandServerTransformToWaylandTransform(OutputInterface::Transform transform)
74 {
75  switch (transform) {
76  case OutputInterface::Transform::Normal:
77  return OutputInterfacePrivate::transform_normal;
78  case OutputInterface::Transform::Rotated90:
79  return OutputInterfacePrivate::transform_90;
80  case OutputInterface::Transform::Rotated180:
81  return OutputInterfacePrivate::transform_180;
82  case OutputInterface::Transform::Rotated270:
83  return OutputInterfacePrivate::transform_270;
84  case OutputInterface::Transform::Flipped:
85  return OutputInterfacePrivate::transform_flipped;
86  case OutputInterface::Transform::Flipped90:
87  return OutputInterfacePrivate::transform_flipped_90;
88  case OutputInterface::Transform::Flipped180:
89  return OutputInterfacePrivate::transform_flipped_180;
90  case OutputInterface::Transform::Flipped270:
91  return OutputInterfacePrivate::transform_flipped_270;
92  default:
93  Q_UNREACHABLE();
94  }
95 }
96 
97 static quint32 kwaylandServerSubPixelToWaylandSubPixel(OutputInterface::SubPixel subPixel)
98 {
99  switch (subPixel) {
100  case OutputInterface::SubPixel::Unknown:
101  return OutputInterfacePrivate::subpixel_unknown;
102  case OutputInterface::SubPixel::None:
103  return OutputInterfacePrivate::subpixel_none;
104  case OutputInterface::SubPixel::HorizontalRGB:
105  return OutputInterfacePrivate::subpixel_horizontal_rgb;
106  case OutputInterface::SubPixel::HorizontalBGR:
107  return OutputInterfacePrivate::subpixel_horizontal_bgr;
108  case OutputInterface::SubPixel::VerticalRGB:
109  return OutputInterfacePrivate::subpixel_vertical_rgb;
110  case OutputInterface::SubPixel::VerticalBGR:
111  return OutputInterfacePrivate::subpixel_vertical_bgr;
112  default:
113  Q_UNREACHABLE();
114  }
115 }
116 
117 void OutputInterfacePrivate::sendGeometry(Resource *resource)
118 {
119  send_geometry(resource->handle,
120  globalPosition.x(),
121  globalPosition.y(),
122  physicalSize.width(),
123  physicalSize.height(),
124  kwaylandServerSubPixelToWaylandSubPixel(subPixel),
125  manufacturer,
126  model,
127  kwaylandServerTransformToWaylandTransform(transform));
128 }
129 
130 void OutputInterfacePrivate::sendDone(Resource *resource)
131 {
132  if (resource->version() >= WL_OUTPUT_DONE_SINCE_VERSION) {
133  send_done(resource->handle);
134  }
135 }
136 
137 void OutputInterfacePrivate::broadcastGeometry()
138 {
139  const auto outputResources = resourceMap();
140  for (Resource *resource : outputResources) {
141  sendGeometry(resource);
142  }
143 }
144 
145 void OutputInterfacePrivate::output_destroy_global()
146 {
147  delete q;
148 }
149 
150 void OutputInterfacePrivate::output_release(Resource *resource)
151 {
152  wl_resource_destroy(resource->handle);
153 }
154 
155 void OutputInterfacePrivate::output_bind_resource(Resource *resource)
156 {
157  if (isGlobalRemoved()) {
158  return; // We are waiting for the wl_output global to be destroyed.
159  }
160 
161  sendMode(resource);
162  sendScale(resource);
163  sendGeometry(resource);
164  sendDone(resource);
165 
166  Q_EMIT q->bound(display->getConnection(resource->client()), resource->handle);
167 }
168 
169 OutputInterface::OutputInterface(Display *display, QObject *parent)
170  : QObject(parent)
171  , d(new OutputInterfacePrivate(display, this))
172 {
173  DisplayPrivate *displayPrivate = DisplayPrivate::get(display);
174  displayPrivate->outputs.append(this);
175 }
176 
177 OutputInterface::~OutputInterface()
178 {
179  remove();
180 }
181 
182 void OutputInterface::remove()
183 {
184  if (d->isGlobalRemoved()) {
185  return;
186  }
187 
188  if (d->display) {
189  DisplayPrivate *displayPrivate = DisplayPrivate::get(d->display);
190  displayPrivate->outputs.removeOne(this);
191  }
192 
193  Q_EMIT removed();
194  d->globalRemove();
195 }
196 
197 QSize OutputInterface::pixelSize() const
198 {
199  return d->mode.size;
200 }
201 
202 int OutputInterface::refreshRate() const
203 {
204  return d->mode.refreshRate;
205 }
206 
207 OutputInterface::Mode OutputInterface::mode() const
208 {
209  return d->mode;
210 }
211 
212 void OutputInterface::setMode(const Mode &mode)
213 {
214  if (d->mode.size == mode.size && d->mode.refreshRate == mode.refreshRate) {
215  return;
216  }
217 
218  d->mode = mode;
219 
220  const auto outputResources = d->resourceMap();
221  for (OutputInterfacePrivate::Resource *resource : outputResources) {
222  d->sendMode(resource);
223  }
224 
225  Q_EMIT modeChanged();
226  Q_EMIT refreshRateChanged(mode.refreshRate);
227  Q_EMIT pixelSizeChanged(mode.size);
228 }
229 
230 void OutputInterface::setMode(const QSize &size, int refreshRate)
231 {
232  setMode({size, refreshRate});
233 }
234 
235 QSize OutputInterface::physicalSize() const
236 {
237  return d->physicalSize;
238 }
239 
240 void OutputInterface::setPhysicalSize(const QSize &physicalSize)
241 {
242  if (d->physicalSize == physicalSize) {
243  return;
244  }
245  d->physicalSize = physicalSize;
246  d->broadcastGeometry();
247  Q_EMIT physicalSizeChanged(d->physicalSize);
248 }
249 
250 QPoint OutputInterface::globalPosition() const
251 {
252  return d->globalPosition;
253 }
254 
255 void OutputInterface::setGlobalPosition(const QPoint &globalPos)
256 {
257  if (d->globalPosition == globalPos) {
258  return;
259  }
260  d->globalPosition = globalPos;
261  Q_EMIT globalPositionChanged(d->globalPosition);
262 }
263 
264 QString OutputInterface::manufacturer() const
265 {
266  return d->manufacturer;
267 }
268 
269 void OutputInterface::setManufacturer(const QString &manufacturer)
270 {
271  if (d->manufacturer == manufacturer) {
272  return;
273  }
274  d->manufacturer = manufacturer;
275  d->broadcastGeometry();
276  Q_EMIT manufacturerChanged(d->manufacturer);
277 }
278 
279 QString OutputInterface::model() const
280 {
281  return d->model;
282 }
283 
284 void OutputInterface::setModel(const QString &model)
285 {
286  if (d->model == model) {
287  return;
288  }
289  d->model = model;
290  d->broadcastGeometry();
291  Q_EMIT modelChanged(d->model);
292 }
293 
294 int OutputInterface::scale() const
295 {
296  return d->scale;
297 }
298 
299 void OutputInterface::setScale(int scale)
300 {
301  if (d->scale == scale) {
302  return;
303  }
304  d->scale = scale;
305 
306  const auto outputResources = d->resourceMap();
307  for (OutputInterfacePrivate::Resource *resource : outputResources) {
308  d->sendScale(resource);
309  }
310 
311  Q_EMIT scaleChanged(d->scale);
312 }
313 
314 OutputInterface::SubPixel OutputInterface::subPixel() const
315 {
316  return d->subPixel;
317 }
318 
319 void OutputInterface::setSubPixel(SubPixel subPixel)
320 {
321  if (d->subPixel == subPixel) {
322  return;
323  }
324  d->subPixel = subPixel;
325  d->broadcastGeometry();
326  Q_EMIT subPixelChanged(d->subPixel);
327 }
328 
329 OutputInterface::Transform OutputInterface::transform() const
330 {
331  return d->transform;
332 }
333 
334 void OutputInterface::setTransform(Transform transform)
335 {
336  if (d->transform == transform) {
337  return;
338  }
339  d->transform = transform;
340  d->broadcastGeometry();
341  Q_EMIT transformChanged(d->transform);
342 }
343 
344 void OutputInterface::setDpmsMode(OutputInterface::DpmsMode mode)
345 {
346  if (d->dpms.mode == mode) {
347  return;
348  }
349  d->dpms.mode = mode;
350  Q_EMIT dpmsModeChanged();
351 }
352 
354 {
355  if (d->dpms.supported == supported) {
356  return;
357  }
358  d->dpms.supported = supported;
359  Q_EMIT dpmsSupportedChanged();
360 }
361 
362 OutputInterface::DpmsMode OutputInterface::dpmsMode() const
363 {
364  return d->dpms.mode;
365 }
366 
367 bool OutputInterface::isDpmsSupported() const
368 {
369  return d->dpms.supported;
370 }
371 
373 {
374  const auto outputResources = d->resourceMap().values(client->client());
376  ret.reserve(outputResources.count());
377 
378  for (OutputInterfacePrivate::Resource *resource : outputResources) {
379  ret.append(resource->handle);
380  }
381 
382  return ret;
383 }
384 
386 {
387  if (!d->dpms.supported) {
388  return true;
389  }
390  return d->dpms.mode == DpmsMode::On;
391 }
392 
394 {
395  const auto outputResources = d->resourceMap();
396  for (OutputInterfacePrivate::Resource *resource : outputResources) {
397  d->sendDone(resource);
398  }
399 }
400 
401 OutputInterface *OutputInterface::get(wl_resource *native)
402 {
403  if (auto outputPrivate = resource_cast<OutputInterfacePrivate *>(native)) {
404  return outputPrivate->q;
405  }
406  return nullptr;
407 }
408 
409 } // namespace KWaylandServer
The OutputInterface class represents a screen.
void append(const T &value)
KDOCTOOLS_EXPORT QString transform(const QString &file, const QString &stylesheet, const QVector< const char * > &params=QVector< const char * >())
bool isEnabled() const
Returns true if the output is on; otherwise returns false.
void reserve(int size)
Convenient Class which represents a wl_client.
void done()
Submit changes to all clients.
QVector< wl_resource * > clientResources(ClientConnection *client) const
void setDpmsMode(DpmsMode mode)
Sets the currently used dpms mode.
void setDpmsSupported(bool supported)
Sets whether Dpms is supported for this output.
QObject * parent() const const
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 23 2021 23:08:27 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.