KWayland

outputconfiguration_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 Martin Gräßlin <[email protected]>
3  SPDX-FileCopyrightText: 2015 Sebastian Kügler <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 #include "outputconfiguration_interface.h"
8 #include "outputdevice_interface.h"
9 #include "logging.h"
10 #include "resource_p.h"
11 #include "display.h"
12 #include "outputchangeset_p.h"
13 
14 #include <wayland-server.h>
15 #include "wayland-output-management-server-protocol.h"
16 #include "wayland-org_kde_kwin_outputdevice-server-protocol.h"
17 
18 #include <QDebug>
19 #include <QSize>
20 
21 namespace KWayland
22 {
23 namespace Server
24 {
25 
26 
27 class OutputConfigurationInterface::Private : public Resource::Private
28 {
29 public:
30  Private(OutputConfigurationInterface *q, OutputManagementInterface *c, wl_resource *parentResource);
31  ~Private();
32 
33  void sendApplied();
34  void sendFailed();
35  void emitConfigurationChangeRequested() const;
36  void clearPendingChanges();
37 
38  bool hasPendingChanges(OutputDeviceInterface *outputdevice) const;
39  OutputChangeSet* pendingChanges(OutputDeviceInterface *outputdevice);
40 
41  OutputManagementInterface *outputManagement;
43 
44  static const quint32 s_version = 2;
45 
46 private:
47  static void enableCallback(wl_client *client, wl_resource *resource,
48  wl_resource * outputdevice, int32_t enable);
49  static void modeCallback(wl_client *client, wl_resource *resource,
50  wl_resource * outputdevice, int32_t mode_id);
51  static void transformCallback(wl_client *client, wl_resource *resource,
52  wl_resource * outputdevice, int32_t transform);
53  static void positionCallback(wl_client *client, wl_resource *resource,
54  wl_resource * outputdevice, int32_t x, int32_t y);
55  static void scaleCallback(wl_client *client, wl_resource *resource,
56  wl_resource * outputdevice, int32_t scale);
57  static void applyCallback(wl_client *client, wl_resource *resource);
58  static void scaleFCallback(wl_client *client, wl_resource *resource,
59  wl_resource * outputdevice, wl_fixed_t scale);
60  static void colorcurvesCallback(wl_client *client, wl_resource *resource,
61  wl_resource * outputdevice,
62  wl_array *red, wl_array *green, wl_array *blue);
63 
64  OutputConfigurationInterface *q_func() {
65  return reinterpret_cast<OutputConfigurationInterface *>(q);
66  }
67 
68  static const struct org_kde_kwin_outputconfiguration_interface s_interface;
69 };
70 
71 const struct org_kde_kwin_outputconfiguration_interface OutputConfigurationInterface::Private::s_interface = {
72  enableCallback,
73  modeCallback,
74  transformCallback,
75  positionCallback,
76  scaleCallback,
77  applyCallback,
78  scaleFCallback,
79  colorcurvesCallback,
80  resourceDestroyedCallback
81 };
82 
83 OutputConfigurationInterface::OutputConfigurationInterface(OutputManagementInterface* parent, wl_resource* parentResource): Resource(new Private(this, parent, parentResource))
84 {
85  Q_D();
86  d->outputManagement = parent;
87 }
88 
89 OutputConfigurationInterface::~OutputConfigurationInterface()
90 {
91  Q_D();
92  d->clearPendingChanges();
93 }
94 
95 void OutputConfigurationInterface::Private::enableCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, int32_t enable)
96 {
97  Q_UNUSED(client);
98  auto s = cast<Private>(resource);
99  Q_ASSERT(s);
100  auto _enable = (enable == ORG_KDE_KWIN_OUTPUTDEVICE_ENABLEMENT_ENABLED) ?
101  OutputDeviceInterface::Enablement::Enabled :
102  OutputDeviceInterface::Enablement::Disabled;
103  OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
104  s->pendingChanges(o)->d_func()->enabled = _enable;
105 }
106 
107 void OutputConfigurationInterface::Private::modeCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, int32_t mode_id)
108 {
109  Q_UNUSED(client);
110  OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
111 
112  bool modeValid = false;
113  for (const auto &m: o->modes()) {
114  if (m.id == mode_id) {
115  modeValid = true;
116  break;
117  }
118  }
119  if (!modeValid) {
120  qCWarning(KWAYLAND_SERVER) << "Set invalid mode id:" << mode_id;
121  return;
122  }
123  auto s = cast<Private>(resource);
124  Q_ASSERT(s);
125  s->pendingChanges(o)->d_func()->modeId = mode_id;
126 }
127 
128 void OutputConfigurationInterface::Private::transformCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, int32_t transform)
129 {
130  Q_UNUSED(client);
131  auto toTransform = [transform]() {
132  switch (transform) {
133  case WL_OUTPUT_TRANSFORM_90:
134  return OutputDeviceInterface::Transform::Rotated90;
135  case WL_OUTPUT_TRANSFORM_180:
136  return OutputDeviceInterface::Transform::Rotated180;
137  case WL_OUTPUT_TRANSFORM_270:
138  return OutputDeviceInterface::Transform::Rotated270;
139  case WL_OUTPUT_TRANSFORM_FLIPPED:
140  return OutputDeviceInterface::Transform::Flipped;
141  case WL_OUTPUT_TRANSFORM_FLIPPED_90:
142  return OutputDeviceInterface::Transform::Flipped90;
143  case WL_OUTPUT_TRANSFORM_FLIPPED_180:
144  return OutputDeviceInterface::Transform::Flipped180;
145  case WL_OUTPUT_TRANSFORM_FLIPPED_270:
146  return OutputDeviceInterface::Transform::Flipped270;
147  case WL_OUTPUT_TRANSFORM_NORMAL:
148  default:
149  return OutputDeviceInterface::Transform::Normal;
150  }
151  };
152  auto _transform = toTransform();
153  OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
154  auto s = cast<Private>(resource);
155  Q_ASSERT(s);
156  s->pendingChanges(o)->d_func()->transform = _transform;
157 }
158 
159 void OutputConfigurationInterface::Private::positionCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, int32_t x, int32_t y)
160 {
161  Q_UNUSED(client);
162  auto _pos = QPoint(x, y);
163  OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
164  auto s = cast<Private>(resource);
165  Q_ASSERT(s);
166  s->pendingChanges(o)->d_func()->position = _pos;
167 }
168 
169 void OutputConfigurationInterface::Private::scaleCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, int32_t scale)
170 {
171  Q_UNUSED(client);
172  if (scale <= 0) {
173  qCWarning(KWAYLAND_SERVER) << "Requested to scale output device to" << scale << ", but I can't do that.";
174  return;
175  }
176  OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
177  auto s = cast<Private>(resource);
178  Q_ASSERT(s);
179  s->pendingChanges(o)->d_func()->scale = scale;
180 }
181 
182 void OutputConfigurationInterface::Private::scaleFCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, wl_fixed_t scale_fixed)
183 {
184  Q_UNUSED(client);
185  const qreal scale = wl_fixed_to_double(scale_fixed);
186 
187  if (scale <= 0) {
188  qCWarning(KWAYLAND_SERVER) << "Requested to scale output device to" << scale << ", but I can't do that.";
189  return;
190  }
191  OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
192  auto s = cast<Private>(resource);
193  Q_ASSERT(s);
194 
195  s->pendingChanges(o)->d_func()->scale = scale;
196 }
197 
198 void OutputConfigurationInterface::Private::applyCallback(wl_client *client, wl_resource *resource)
199 {
200  Q_UNUSED(client);
201  auto s = cast<Private>(resource);
202  Q_ASSERT(s);
203  s->emitConfigurationChangeRequested();
204 }
205 
206 void OutputConfigurationInterface::Private::colorcurvesCallback(wl_client *client, wl_resource *resource,
207  wl_resource * outputdevice,
208  wl_array *red, wl_array *green, wl_array *blue)
209 {
210  Q_UNUSED(client);
211  OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
212  OutputDeviceInterface::ColorCurves oldCc = o->colorCurves();
213 
214  auto checkArg = [](const wl_array *newColor, const QVector<quint16> &oldColor) {
215  return (newColor->size % sizeof(uint16_t) == 0) &&
216  (newColor->size / sizeof(uint16_t) == static_cast<size_t>(oldColor.size()));
217  };
218  if (!checkArg(red, oldCc.red) || !checkArg(green, oldCc.green) || !checkArg(blue, oldCc.blue)) {
219  qCWarning(KWAYLAND_SERVER) << "Requested to change color curves, but have wrong size.";
220  return;
221  }
222 
223  auto s = cast<Private>(resource);
224  Q_ASSERT(s);
225  OutputDeviceInterface::ColorCurves cc;
226 
227  auto fillVector = [](const wl_array *array, QVector<quint16> *v) {
228  const uint16_t *pos = (uint16_t*)array->data;
229 
230  while((char*)pos < (char*)array->data + array->size) {
231  v->append(*pos);
232  pos++;
233  }
234  };
235  fillVector(red, &cc.red);
236  fillVector(green, &cc.green);
237  fillVector(blue, &cc.blue);
238 
239  s->pendingChanges(o)->d_func()->colorCurves = cc;
240 }
241 
242 void OutputConfigurationInterface::Private::emitConfigurationChangeRequested() const
243 {
244  auto configinterface = reinterpret_cast<OutputConfigurationInterface *>(q);
245  emit outputManagement->configurationChangeRequested(configinterface);
246 }
247 
248 
249 OutputConfigurationInterface::Private::Private(OutputConfigurationInterface *q, OutputManagementInterface *c, wl_resource *parentResource)
250 : Resource::Private(q, c, parentResource, &org_kde_kwin_outputconfiguration_interface, &s_interface)
251 {
252 }
253 
254 OutputConfigurationInterface::Private::~Private() = default;
255 
256 OutputConfigurationInterface::Private *OutputConfigurationInterface::d_func() const
257 {
258  return reinterpret_cast<Private*>(d.data());
259 }
260 
261 QHash<OutputDeviceInterface*, OutputChangeSet*> OutputConfigurationInterface::changes() const
262 {
263  Q_D();
264  return d->changes;
265 }
266 
267 void OutputConfigurationInterface::setApplied()
268 {
269  Q_D();
270  d->clearPendingChanges();
271  d->sendApplied();
272 }
273 
274 void OutputConfigurationInterface::Private::sendApplied()
275 {
276  if (!resource) {
277  return;
278  }
279  org_kde_kwin_outputconfiguration_send_applied(resource);
280 }
281 
282 void OutputConfigurationInterface::setFailed()
283 {
284  Q_D();
285  d->clearPendingChanges();
286  d->sendFailed();
287 }
288 
289 void OutputConfigurationInterface::Private::sendFailed()
290 {
291  if (!resource) {
292  return;
293  }
294  org_kde_kwin_outputconfiguration_send_failed(resource);
295 }
296 
297 OutputChangeSet* OutputConfigurationInterface::Private::pendingChanges(OutputDeviceInterface *outputdevice)
298 {
299  if (!changes.keys().contains(outputdevice)) {
300  changes[outputdevice] = new OutputChangeSet(outputdevice, q);
301  }
302  return changes[outputdevice];
303 }
304 
305 bool OutputConfigurationInterface::Private::hasPendingChanges(OutputDeviceInterface *outputdevice) const
306 {
307  if (!changes.keys().contains(outputdevice)) {
308  return false;
309  }
310  auto c = changes[outputdevice];
311  return c->enabledChanged() ||
312  c->modeChanged() ||
313  c->transformChanged() ||
314  c->positionChanged() ||
315  c->scaleChanged();
316 }
317 
318 void OutputConfigurationInterface::Private::clearPendingChanges()
319 {
320  qDeleteAll(changes.begin(), changes.end());
321  changes.clear();
322 }
323 
324 
325 }
326 }
T * data() const const
QObject * parent() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 7 2020 22:48:18 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.