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

KDE's Doxygen guidelines are available online.