1 /****************************************************************************
2 **
3 ** Copyright (C) 2017-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
4 ** Copyright (C) 2017 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30
31 #include "qwaylandsurface.h"
32 #include "qwaylandsurface_p.h"
33
34 #include "wayland_wrapper/qwlbuffermanager_p.h"
35 #include "wayland_wrapper/qwlregion_p.h"
36 #include <QtWaylandCompositor/private/qtwaylandcompositorglobal_p.h>
37 #if QT_CONFIG(wayland_datadevice)
38 #include "wayland_wrapper/qwldatadevice_p.h"
39 #include "wayland_wrapper/qwldatadevicemanager_p.h"
40 #endif
41
42 #include "qwaylandinputmethodcontrol_p.h"
43
44 #include <QtWaylandCompositor/QWaylandCompositor>
45 #include <QtWaylandCompositor/QWaylandClient>
46 #include <QtWaylandCompositor/QWaylandView>
47 #include <QtWaylandCompositor/QWaylandBufferRef>
48
49 #include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
50 #include <QtWaylandCompositor/private/qwaylandview_p.h>
51 #include <QtWaylandCompositor/private/qwaylandseat_p.h>
52 #include <QtWaylandCompositor/private/qwaylandutils_p.h>
53
54 #include <QtCore/private/qobject_p.h>
55
56 #include <QtGui/QGuiApplication>
57 #include <QtGui/QScreen>
58
59 #include <QtCore/QDebug>
60 #include <QtCore/QtMath>
61
62 QT_BEGIN_NAMESPACE
63
64 namespace QtWayland {
65 class FrameCallback {
66 public:
FrameCallback(QWaylandSurface * surf,wl_resource * res)67 FrameCallback(QWaylandSurface *surf, wl_resource *res)
68 : surface(surf)
69 , resource(res)
70 {
71 wl_resource_set_implementation(res, nullptr, this, destroyCallback);
72 }
~FrameCallback()73 ~FrameCallback()
74 {
75 }
destroy()76 void destroy()
77 {
78 if (resource)
79 wl_resource_destroy(resource);
80 else
81 delete this;
82 }
send(uint time)83 void send(uint time)
84 {
85 wl_callback_send_done(resource, time);
86 wl_resource_destroy(resource);
87 }
destroyCallback(wl_resource * res)88 static void destroyCallback(wl_resource *res)
89 {
90 FrameCallback *_this = static_cast<FrameCallback *>(wl_resource_get_user_data(res));
91 if (_this->surface)
92 QWaylandSurfacePrivate::get(_this->surface)->removeFrameCallback(_this);
93 delete _this;
94 }
95 QWaylandSurface *surface = nullptr;
96 wl_resource *resource = nullptr;
97 bool canSend = false;
98 };
99 }
infiniteRegion()100 static QRegion infiniteRegion() {
101 return QRegion(QRect(QPoint(std::numeric_limits<int>::min(), std::numeric_limits<int>::min()),
102 QPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::max())));
103 }
104
105 #ifndef QT_NO_DEBUG
106 QList<QWaylandSurfacePrivate *> QWaylandSurfacePrivate::uninitializedSurfaces;
107 #endif
108
QWaylandSurfacePrivate()109 QWaylandSurfacePrivate::QWaylandSurfacePrivate()
110 : inputRegion(infiniteRegion())
111 {
112 pending.buffer = QWaylandBufferRef();
113 pending.newlyAttached = false;
114 pending.inputRegion = infiniteRegion();
115 pending.bufferScale = 1;
116 #ifndef QT_NO_DEBUG
117 addUninitializedSurface(this);
118 #endif
119 }
120
~QWaylandSurfacePrivate()121 QWaylandSurfacePrivate::~QWaylandSurfacePrivate()
122 {
123 for (int i = 0; i < views.size(); i++) {
124 QWaylandViewPrivate::get(views.at(i))->markSurfaceAsDestroyed(q_func());
125 }
126 views.clear();
127
128 bufferRef = QWaylandBufferRef();
129
130 for (QtWayland::FrameCallback *c : qAsConst(pendingFrameCallbacks))
131 c->destroy();
132 for (QtWayland::FrameCallback *c : qAsConst(frameCallbacks))
133 c->destroy();
134 }
135
removeFrameCallback(QtWayland::FrameCallback * callback)136 void QWaylandSurfacePrivate::removeFrameCallback(QtWayland::FrameCallback *callback)
137 {
138 pendingFrameCallbacks.removeOne(callback);
139 frameCallbacks.removeOne(callback);
140 }
141
notifyViewsAboutDestruction()142 void QWaylandSurfacePrivate::notifyViewsAboutDestruction()
143 {
144 Q_Q(QWaylandSurface);
145 const auto viewsCopy = views; // Views will be removed from the list when marked as destroyed
146 for (QWaylandView *view : viewsCopy) {
147 QWaylandViewPrivate::get(view)->markSurfaceAsDestroyed(q);
148 }
149 if (hasContent) {
150 hasContent = false;
151 emit q->hasContentChanged();
152 }
153 }
154
155 #ifndef QT_NO_DEBUG
addUninitializedSurface(QWaylandSurfacePrivate * surface)156 void QWaylandSurfacePrivate::addUninitializedSurface(QWaylandSurfacePrivate *surface)
157 {
158 Q_ASSERT(!surface->isInitialized);
159 Q_ASSERT(!uninitializedSurfaces.contains(surface));
160 uninitializedSurfaces.append(surface);
161 }
162
removeUninitializedSurface(QWaylandSurfacePrivate * surface)163 void QWaylandSurfacePrivate::removeUninitializedSurface(QWaylandSurfacePrivate *surface)
164 {
165 Q_ASSERT(surface->isInitialized);
166 bool removed = uninitializedSurfaces.removeOne(surface);
167 Q_ASSERT(removed);
168 }
169
hasUninitializedSurface()170 bool QWaylandSurfacePrivate::hasUninitializedSurface()
171 {
172 return uninitializedSurfaces.size();
173 }
174 #endif
175
surface_destroy_resource(Resource *)176 void QWaylandSurfacePrivate::surface_destroy_resource(Resource *)
177 {
178 Q_Q(QWaylandSurface);
179 notifyViewsAboutDestruction();
180
181 destroyed = true;
182 emit q->surfaceDestroyed();
183 q->destroy();
184 }
185
surface_destroy(Resource * resource)186 void QWaylandSurfacePrivate::surface_destroy(Resource *resource)
187 {
188 wl_resource_destroy(resource->handle);
189 }
190
surface_attach(Resource *,struct wl_resource * buffer,int x,int y)191 void QWaylandSurfacePrivate::surface_attach(Resource *, struct wl_resource *buffer, int x, int y)
192 {
193 pending.buffer = QWaylandBufferRef(getBuffer(buffer));
194 pending.offset = QPoint(x, y);
195 pending.newlyAttached = true;
196 }
197
surface_damage(Resource *,int32_t x,int32_t y,int32_t width,int32_t height)198 void QWaylandSurfacePrivate::surface_damage(Resource *, int32_t x, int32_t y, int32_t width, int32_t height)
199 {
200 pending.damage = pending.damage.united(QRect(x, y, width, height));
201 }
202
surface_frame(Resource * resource,uint32_t callback)203 void QWaylandSurfacePrivate::surface_frame(Resource *resource, uint32_t callback)
204 {
205 Q_Q(QWaylandSurface);
206 struct wl_resource *frame_callback = wl_resource_create(resource->client(), &wl_callback_interface, wl_callback_interface.version, callback);
207 pendingFrameCallbacks << new QtWayland::FrameCallback(q, frame_callback);
208 }
209
surface_set_opaque_region(Resource *,struct wl_resource * region)210 void QWaylandSurfacePrivate::surface_set_opaque_region(Resource *, struct wl_resource *region)
211 {
212 pending.opaqueRegion = region ? QtWayland::Region::fromResource(region)->region() : QRegion();
213 }
214
surface_set_input_region(Resource *,struct wl_resource * region)215 void QWaylandSurfacePrivate::surface_set_input_region(Resource *, struct wl_resource *region)
216 {
217 if (region) {
218 pending.inputRegion = QtWayland::Region::fromResource(region)->region();
219 } else {
220 pending.inputRegion = infiniteRegion();
221 }
222 }
223
surface_commit(Resource *)224 void QWaylandSurfacePrivate::surface_commit(Resource *)
225 {
226 Q_Q(QWaylandSurface);
227
228 // Needed in order to know whether we want to emit signals later
229 QSize oldBufferSize = bufferSize;
230 QRectF oldSourceGeometry = sourceGeometry;
231 QSize oldDestinationSize = destinationSize;
232 bool oldHasContent = hasContent;
233 int oldBufferScale = bufferScale;
234
235 // Update all internal state
236 if (pending.buffer.hasBuffer() || pending.newlyAttached)
237 bufferRef = pending.buffer;
238 bufferScale = pending.bufferScale;
239 bufferSize = bufferRef.size();
240 QSize surfaceSize = bufferSize / bufferScale;
241 sourceGeometry = !pending.sourceGeometry.isValid() ? QRect(QPoint(), surfaceSize) : pending.sourceGeometry;
242 destinationSize = pending.destinationSize.isEmpty() ? sourceGeometry.size().toSize() : pending.destinationSize;
243 damage = pending.damage.intersected(QRect(QPoint(), destinationSize));
244 hasContent = bufferRef.hasContent();
245 frameCallbacks << pendingFrameCallbacks;
246 inputRegion = pending.inputRegion.intersected(QRect(QPoint(), destinationSize));
247 opaqueRegion = pending.opaqueRegion.intersected(QRect(QPoint(), destinationSize));
248 QPoint offsetForNextFrame = pending.offset;
249
250 if (viewport)
251 viewport->checkCommittedState();
252
253 // Clear per-commit state
254 pending.buffer = QWaylandBufferRef();
255 pending.offset = QPoint();
256 pending.newlyAttached = false;
257 pending.damage = QRegion();
258 pendingFrameCallbacks.clear();
259
260 // Notify buffers and views
261 if (auto *buffer = bufferRef.buffer())
262 buffer->setCommitted(damage);
263 for (auto *view : qAsConst(views))
264 view->bufferCommitted(bufferRef, damage);
265
266 // Now all double-buffered state has been applied so it's safe to emit general signals
267 // i.e. we won't have inconsistensies such as mismatched surface size and buffer scale in
268 // signal handlers.
269
270 emit q->damaged(damage);
271
272 if (oldBufferSize != bufferSize) {
273 emit q->bufferSizeChanged();
274 #if QT_DEPRECATED_SINCE(5, 13)
275 QT_WARNING_PUSH
276 QT_WARNING_DISABLE_DEPRECATED
277 emit q->sizeChanged();
278 QT_WARNING_POP
279 #endif
280 }
281
282 if (oldBufferScale != bufferScale)
283 emit q->bufferScaleChanged();
284
285 if (oldDestinationSize != destinationSize)
286 emit q->destinationSizeChanged();
287
288 if (oldSourceGeometry != sourceGeometry)
289 emit q->sourceGeometryChanged();
290
291 if (oldHasContent != hasContent)
292 emit q->hasContentChanged();
293
294 if (!offsetForNextFrame.isNull())
295 emit q->offsetForNextFrame(offsetForNextFrame);
296
297 emit q->redraw();
298 }
299
surface_set_buffer_transform(Resource * resource,int32_t orientation)300 void QWaylandSurfacePrivate::surface_set_buffer_transform(Resource *resource, int32_t orientation)
301 {
302 Q_UNUSED(resource);
303 Q_Q(QWaylandSurface);
304 QScreen *screen = QGuiApplication::primaryScreen();
305 bool isPortrait = screen->primaryOrientation() == Qt::PortraitOrientation;
306 Qt::ScreenOrientation oldOrientation = contentOrientation;
307 switch (orientation) {
308 case WL_OUTPUT_TRANSFORM_90:
309 contentOrientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation;
310 break;
311 case WL_OUTPUT_TRANSFORM_180:
312 contentOrientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation;
313 break;
314 case WL_OUTPUT_TRANSFORM_270:
315 contentOrientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation;
316 break;
317 default:
318 contentOrientation = Qt::PrimaryOrientation;
319 }
320 if (contentOrientation != oldOrientation)
321 emit q->contentOrientationChanged();
322 }
323
surface_set_buffer_scale(QtWaylandServer::wl_surface::Resource * resource,int32_t scale)324 void QWaylandSurfacePrivate::surface_set_buffer_scale(QtWaylandServer::wl_surface::Resource *resource, int32_t scale)
325 {
326 Q_UNUSED(resource);
327 pending.bufferScale = scale;
328 }
329
getBuffer(struct::wl_resource * buffer)330 QtWayland::ClientBuffer *QWaylandSurfacePrivate::getBuffer(struct ::wl_resource *buffer)
331 {
332 QtWayland::BufferManager *bufMan = QWaylandCompositorPrivate::get(compositor)->bufferManager();
333 return bufMan->getBuffer(buffer);
334 }
335
336 /*!
337 * \qmltype WaylandSurface
338 * \inqmlmodule QtWayland.Compositor
339 * \since 5.8
340 * \brief Represents a rectangular area on an output device.
341 *
342 * This type encapsulates a rectangular area of pixels that is displayed on an output device. It
343 * corresponds to the interface \c wl_surface in the Wayland protocol.
344 */
345
346 /*!
347 * \class QWaylandSurface
348 * \inmodule QtWaylandCompositor
349 * \since 5.8
350 * \brief The QWaylandSurface class represents a rectangular area on an output device.
351 *
352 * This class encapsulates a rectangular area of pixels that is displayed on an output device. It
353 * corresponds to the interface \c wl_surface in the Wayland protocol.
354 */
355
356 /*!
357 * Constructs a an uninitialized QWaylandSurface.
358 */
QWaylandSurface()359 QWaylandSurface::QWaylandSurface()
360 : QWaylandObject(*new QWaylandSurfacePrivate())
361 {
362 }
363
364 /*!
365 * Constructs and initializes a QWaylandSurface for the given \a compositor and \a client, and with the given \a id
366 * and \a version.
367 */
QWaylandSurface(QWaylandCompositor * compositor,QWaylandClient * client,uint id,int version)368 QWaylandSurface::QWaylandSurface(QWaylandCompositor *compositor, QWaylandClient *client, uint id, int version)
369 : QWaylandObject(*new QWaylandSurfacePrivate())
370 {
371 initialize(compositor, client, id, version);
372 }
373
374 /*!
375 * \internal
376 */
QWaylandSurface(QWaylandSurfacePrivate & dptr)377 QWaylandSurface::QWaylandSurface(QWaylandSurfacePrivate &dptr)
378 : QWaylandObject(dptr)
379 {
380 }
381
382 /*!
383 * Destroys the QWaylandSurface.
384 */
~QWaylandSurface()385 QWaylandSurface::~QWaylandSurface()
386 {
387 Q_D(QWaylandSurface);
388 if (d->compositor)
389 QWaylandCompositorPrivate::get(d->compositor)->unregisterSurface(this);
390 d->notifyViewsAboutDestruction();
391 }
392
393 /*!
394 * \qmlmethod void QtWaylandCompositor::WaylandSurface::initialize(WaylandCompositor compositor, WaylandClient client, int id, int version)
395 *
396 * Initializes the WaylandSurface with the given \a compositor and \a client, and with the given \a id
397 * and \a version.
398 */
399
400 /*!
401 * Initializes the QWaylandSurface with the given \a compositor and \a client, and with the given \a id
402 * and \a version.
403 */
initialize(QWaylandCompositor * compositor,QWaylandClient * client,uint id,int version)404 void QWaylandSurface::initialize(QWaylandCompositor *compositor, QWaylandClient *client, uint id, int version)
405 {
406 Q_D(QWaylandSurface);
407 d->compositor = compositor;
408 d->client = client;
409 d->init(client->client(), id, version);
410 d->isInitialized = true;
411 #if QT_CONFIG(im)
412 d->inputMethodControl = new QWaylandInputMethodControl(this);
413 #endif
414 #ifndef QT_NO_DEBUG
415 QWaylandSurfacePrivate::removeUninitializedSurface(d);
416 #endif
417 }
418
419 /*!
420 * Returns true if the QWaylandSurface has been initialized.
421 */
isInitialized() const422 bool QWaylandSurface::isInitialized() const
423 {
424 Q_D(const QWaylandSurface);
425 return d->isInitialized;
426 }
427
428 /*!
429 * \qmlproperty WaylandClient QtWaylandCompositor::WaylandSurface::client
430 *
431 * This property holds the client using this WaylandSurface.
432 */
433
434 /*!
435 * \property QWaylandSurface::client
436 *
437 * This property holds the client using this QWaylandSurface.
438 */
client() const439 QWaylandClient *QWaylandSurface::client() const
440 {
441 Q_D(const QWaylandSurface);
442 if (isDestroyed() || !compositor() || !compositor()->clients().contains(d->client))
443 return nullptr;
444
445 return d->client;
446 }
447
448 /*!
449 * Holds the \c wl_client using this QWaylandSurface.
450 */
waylandClient() const451 ::wl_client *QWaylandSurface::waylandClient() const
452 {
453 if (auto *c = client())
454 return c->client();
455
456 return nullptr;
457 }
458
459 /*!
460 * \qmlproperty bool QtWaylandCompositor::WaylandSurface::hasContent
461 *
462 * This property holds whether the WaylandSurface has content.
463 */
464
465 /*!
466 * \property QWaylandSurface::hasContent
467 *
468 * This property holds whether the QWaylandSurface has content.
469 */
hasContent() const470 bool QWaylandSurface::hasContent() const
471 {
472 Q_D(const QWaylandSurface);
473 return d->hasContent;
474 }
475
476 /*!
477 * \qmlproperty rect QtWaylandCompositor::WaylandSurface::sourceGeometry
478 * \since 5.13
479 *
480 * This property describes the portion of the attached Wayland buffer that should
481 * be drawn on the screen. The coordinates are from the corner of the buffer and are
482 * scaled by \l bufferScale.
483 *
484 * \sa bufferScale
485 * \sa bufferSize
486 * \sa destinationSize
487 */
488
489 /*!
490 * \property QWaylandSurface::sourceGeometry
491 * \since 5.13
492 *
493 * This property describes the portion of the attached QWaylandBuffer that should
494 * be drawn on the screen. The coordinates are from the corner of the buffer and are
495 * scaled by \l bufferScale.
496 *
497 * \sa bufferScale
498 * \sa bufferSize
499 * \sa destinationSize
500 */
sourceGeometry() const501 QRectF QWaylandSurface::sourceGeometry() const
502 {
503 Q_D(const QWaylandSurface);
504 return d->sourceGeometry;
505 }
506
507 /*!
508 * \qmlproperty size QtWaylandCompositor::WaylandSurface::destinationSize
509 * \since 5.13
510 *
511 * This property holds the size of this WaylandSurface in surface coordinates.
512 *
513 * \sa bufferScale
514 * \sa bufferSize
515 */
516
517 /*!
518 * \property QWaylandSurface::destinationSize
519 * \since 5.13
520 *
521 * This property holds the size of this WaylandSurface in surface coordinates.
522 *
523 * \sa bufferScale
524 * \sa bufferSize
525 */
destinationSize() const526 QSize QWaylandSurface::destinationSize() const
527 {
528 Q_D(const QWaylandSurface);
529 return d->destinationSize;
530 }
531
532 /*!
533 * \qmlproperty size QtWaylandCompositor::WaylandSurface::bufferSize
534 *
535 * This property holds the size of the current buffer of this WaylandSurface in pixels,
536 * not in surface coordinates.
537 *
538 * For the size in surface coordinates, use \l destinationSize instead.
539 *
540 * \sa destinationSize
541 * \sa bufferScale
542 */
543
544 /*!
545 * \property QWaylandSurface::bufferSize
546 *
547 * This property holds the size of the current buffer of this QWaylandSurface in pixels,
548 * not in surface coordinates.
549 *
550 * For the size in surface coordinates, use \l destinationSize instead.
551 *
552 * \sa destinationSize
553 * \sa bufferScale
554 */
bufferSize() const555 QSize QWaylandSurface::bufferSize() const
556 {
557 Q_D(const QWaylandSurface);
558 return d->bufferSize;
559 }
560
561 #if QT_DEPRECATED_SINCE(5, 13)
562 /*!
563 * \qmlproperty size QtWaylandCompositor::WaylandSurface::size
564 * \obsolete use bufferSize or destinationSize instead
565 *
566 * This property has been deprecated, use \l bufferSize or \l destinationSize instead.
567 */
568
569 /*!
570 * \property QWaylandSurface::size
571 * \obsolete use bufferSize or destinationSize instead
572 *
573 * This property has been deprecated, use \l bufferSize or \l destinationSize instead.
574 */
size() const575 QSize QWaylandSurface::size() const
576 {
577 return bufferSize();
578 }
579 #endif
580
581 /*!
582 * \qmlproperty size QtWaylandCompositor::WaylandSurface::bufferScale
583 *
584 * This property holds the WaylandSurface's buffer scale. The buffer scale lets
585 * a client supply higher resolution buffer data for use on high resolution
586 * outputs.
587 */
588
589 /*!
590 * \property QWaylandSurface::bufferScale
591 *
592 * This property holds the QWaylandSurface's buffer scale. The buffer scale
593 * lets a client supply higher resolution buffer data for use on high
594 * resolution outputs.
595 */
bufferScale() const596 int QWaylandSurface::bufferScale() const
597 {
598 Q_D(const QWaylandSurface);
599 return d->bufferScale;
600 }
601
602 /*!
603 * \qmlproperty enum QtWaylandCompositor::WaylandSurface::contentOrientation
604 *
605 * This property holds the orientation of the WaylandSurface's contents.
606 *
607 * \sa {WaylandOutput::transform}{WaylandOutput.transform}
608 */
609
610 /*!
611 * \property QWaylandSurface::contentOrientation
612 *
613 * This property holds the orientation of the QWaylandSurface's contents.
614 *
615 * \sa QWaylandOutput::transform
616 */
contentOrientation() const617 Qt::ScreenOrientation QWaylandSurface::contentOrientation() const
618 {
619 Q_D(const QWaylandSurface);
620 return d->contentOrientation;
621 }
622
623 /*!
624 * \enum QWaylandSurface::Origin
625 *
626 * This enum type is used to specify the origin of a QWaylandSurface's buffer.
627 *
628 * \value OriginTopLeft The origin is the top left corner of the buffer.
629 * \value OriginBottomLeft The origin is the bottom left corner of the buffer.
630 */
631
632 /*!
633 * \qmlproperty enum QtWaylandCompositor::WaylandSurface::origin
634 *
635 * This property holds the origin of the WaylandSurface's buffer, or
636 * WaylandSurface.OriginTopLeft if the surface has no buffer.
637 *
638 * It can have the following values:
639 * \list
640 * \li WaylandSurface.OriginTopLeft The origin is the top left corner of the buffer.
641 * \li WaylandSurface.OriginBottomLeft The origin is the bottom left corner of the buffer.
642 * \endlist
643 */
644
645 /*!
646 * \property QWaylandSurface::origin
647 *
648 * This property holds the origin of the QWaylandSurface's buffer, or
649 * QWaylandSurface::OriginTopLeft if the surface has no buffer.
650 */
origin() const651 QWaylandSurface::Origin QWaylandSurface::origin() const
652 {
653 Q_D(const QWaylandSurface);
654 return d->bufferRef.origin();
655 }
656
657 /*!
658 * Returns the compositor for this QWaylandSurface.
659 */
compositor() const660 QWaylandCompositor *QWaylandSurface::compositor() const
661 {
662 Q_D(const QWaylandSurface);
663 return d->compositor;
664 }
665
666 /*!
667 * Prepares all frame callbacks for sending.
668 */
frameStarted()669 void QWaylandSurface::frameStarted()
670 {
671 Q_D(QWaylandSurface);
672 for (QtWayland::FrameCallback *c : qAsConst(d->frameCallbacks))
673 c->canSend = true;
674 }
675
676 /*!
677 * Sends pending frame callbacks.
678 */
sendFrameCallbacks()679 void QWaylandSurface::sendFrameCallbacks()
680 {
681 Q_D(QWaylandSurface);
682 uint time = d->compositor->currentTimeMsecs();
683 int i = 0;
684 while (i < d->frameCallbacks.size()) {
685 if (d->frameCallbacks.at(i)->canSend) {
686 d->frameCallbacks.at(i)->surface = nullptr;
687 d->frameCallbacks.at(i)->send(time);
688 d->frameCallbacks.removeAt(i);
689 } else {
690 i++;
691 }
692 }
693 }
694
695 /*!
696 * Returns \c true if the QWaylandSurface's input region contains the point \a p.
697 * Otherwise returns \c false.
698 */
inputRegionContains(const QPoint & p) const699 bool QWaylandSurface::inputRegionContains(const QPoint &p) const
700 {
701 Q_D(const QWaylandSurface);
702 return d->inputRegion.contains(p);
703 }
704
705 /*!
706 * Returns \c true if the QWaylandSurface's input region contains the point \a position.
707 * Otherwise returns \c false.
708 *
709 * \since 5.14
710 */
inputRegionContains(const QPointF & position) const711 bool QWaylandSurface::inputRegionContains(const QPointF &position) const
712 {
713 Q_D(const QWaylandSurface);
714 // QRegion::contains operates in integers. If a region has a rect (0,0,10,10), (0,0) is
715 // inside while (10,10) is outside. Therefore, we can't use QPoint::toPoint(), which will
716 // round upwards, meaning the point (-0.25,-0.25) would be rounded to (0,0) and count as
717 // being inside the region, and similarly, a point (9.75,9.75) inside the region would be
718 // rounded upwards and count as being outside the region.
719 const QPoint floored(qFloor(position.x()), qFloor(position.y()));
720 return d->inputRegion.contains(floored);
721 }
722
723 /*!
724 * \qmlmethod void QtWaylandCompositor::WaylandSurface::destroy()
725 *
726 * Destroys the WaylandSurface.
727 */
728
729 /*!
730 * Destroys the QWaylandSurface.
731 */
destroy()732 void QWaylandSurface::destroy()
733 {
734 Q_D(QWaylandSurface);
735 d->deref();
736 }
737
738 /*!
739 * \qmlmethod bool QtWaylandCompositor::WaylandSurface::isDestroyed()
740 *
741 * Returns \c true if the WaylandSurface has been destroyed. Otherwise returns \c false.
742 */
743
744 /*!
745 * Returns true if the QWaylandSurface has been destroyed. Otherwise returns false.
746 */
isDestroyed() const747 bool QWaylandSurface::isDestroyed() const
748 {
749 Q_D(const QWaylandSurface);
750 return d->destroyed;
751 }
752
753 /*!
754 * \qmlproperty bool QtWaylandCompositor::WaylandSurface::cursorSurface
755 *
756 * This property holds whether the WaylandSurface is a cursor surface.
757 */
758
759 /*!
760 * \property QWaylandSurface::cursorSurface
761 *
762 * This property holds whether the QWaylandSurface is a cursor surface.
763 */
markAsCursorSurface(bool cursorSurface)764 void QWaylandSurface::markAsCursorSurface(bool cursorSurface)
765 {
766 Q_D(QWaylandSurface);
767 if (d->isCursorSurface == cursorSurface)
768 return;
769
770 d->isCursorSurface = cursorSurface;
771 emit cursorSurfaceChanged();
772 }
773
isCursorSurface() const774 bool QWaylandSurface::isCursorSurface() const
775 {
776 Q_D(const QWaylandSurface);
777 return d->isCursorSurface;
778 }
779
780 /*!
781 * \qmlproperty bool QtWaylandCompositor::WaylandSurface::inhibitsIdle
782 * \since 5.14
783 *
784 * This property holds whether this surface is intended to inhibit the idle
785 * behavior of the compositor such as screen blanking, locking and screen saving.
786 *
787 * \sa IdleInhibitManagerV1
788 */
789
790 /*!
791 * \property QWaylandSurface::inhibitsIdle
792 * \since 5.14
793 *
794 * This property holds whether this surface is intended to inhibit the idle
795 * behavior of the compositor such as screen blanking, locking and screen saving.
796 *
797 * \sa QWaylandIdleInhibitManagerV1
798 */
inhibitsIdle() const799 bool QWaylandSurface::inhibitsIdle() const
800 {
801 Q_D(const QWaylandSurface);
802 return !d->idleInhibitors.isEmpty();
803 }
804
805 #if QT_CONFIG(im)
inputMethodControl() const806 QWaylandInputMethodControl *QWaylandSurface::inputMethodControl() const
807 {
808 Q_D(const QWaylandSurface);
809 return d->inputMethodControl;
810 }
811 #endif
812
813 /*!
814 * Updates the surface with the compositor's retained clipboard selection. Although
815 * this is done automatically when the surface receives keyboard focus, this
816 * function is useful for updating clients which do not have keyboard focus.
817 */
818 #if QT_CONFIG(clipboard)
updateSelection()819 void QWaylandSurface::updateSelection()
820 {
821 Q_D(QWaylandSurface);
822 QWaylandSeat *seat = d->compositor->defaultSeat();
823 if (seat) {
824 const QtWayland::DataDevice *dataDevice = QWaylandSeatPrivate::get(seat)->dataDevice();
825 if (dataDevice) {
826 QWaylandCompositorPrivate::get(d->compositor)->dataDeviceManager()->offerRetainedSelection(
827 dataDevice->resourceMap().value(d->resource()->client())->handle);
828 }
829 }
830 }
831 #endif
832
833 /*!
834 * Returns this QWaylandSurface's primary view.
835 *
836 * \sa QWaylandView::advance(), QWaylandSurface::setPrimaryView()
837 */
primaryView() const838 QWaylandView *QWaylandSurface::primaryView() const
839 {
840 Q_D(const QWaylandSurface);
841 if (d->views.isEmpty())
842 return nullptr;
843 return d->views.first();
844 }
845
846 /*!
847 * Sets this QWaylandSurface's primary view to \a view, in case there are
848 * multiple views of this surface. The primary view is the view that
849 * governs the client's refresh rate. It takes care of discarding buffer
850 * references when QWaylandView::advance() is called. See the documentation
851 * for QWaylandView::advance() for more details.
852 *
853 * In shell surface integrations, such as QWaylandWlShellIntegration and
854 * QWaylandXdgShellV5Integration, maximize and fullscreen requests from the
855 * client will only have an effect if the integration has the primary view
856 * of the surface.
857 *
858 * \sa QWaylandView::advance()
859 */
setPrimaryView(QWaylandView * view)860 void QWaylandSurface::setPrimaryView(QWaylandView *view)
861 {
862 Q_D(QWaylandSurface);
863
864 if (!view)
865 return;
866
867 int index = d->views.indexOf(view);
868
869 if (index < 0) {
870 view->setSurface(this);
871 index = d->views.indexOf(view);
872 }
873
874 d->views.move(index, 0);
875 }
876
877 /*!
878 * Returns the views for this QWaylandSurface.
879 */
views() const880 QList<QWaylandView *> QWaylandSurface::views() const
881 {
882 Q_D(const QWaylandSurface);
883 return d->views;
884 }
885
886 /*!
887 * Returns the QWaylandSurface corresponding to the Wayland resource \a resource.
888 */
fromResource(::wl_resource * resource)889 QWaylandSurface *QWaylandSurface::fromResource(::wl_resource *resource)
890 {
891 if (auto p = QtWayland::fromResource<QWaylandSurfacePrivate *>(resource))
892 return p->q_func();
893 return nullptr;
894 }
895
896 /*!
897 * Returns the Wayland resource corresponding to this QWaylandSurface.
898 */
resource() const899 struct wl_resource *QWaylandSurface::resource() const
900 {
901 Q_D(const QWaylandSurface);
902 return d->resource()->handle;
903 }
904
905 /*!
906 * Sets a \a role on the surface. A role defines how a surface will be mapped on screen; without a role
907 * a surface is supposed to be hidden. Only one role can be set on a surface, at all times. Although
908 * setting the same role many times is allowed, attempting to change the role of a surface will trigger
909 * a protocol error to the \a errorResource and send an \a errorCode to the client.
910 *
911 * Returns true if a role can be assigned; false otherwise.
912 */
setRole(QWaylandSurfaceRole * role,wl_resource * errorResource,uint32_t errorCode)913 bool QWaylandSurface::setRole(QWaylandSurfaceRole *role, wl_resource *errorResource, uint32_t errorCode)
914 {
915 Q_D(QWaylandSurface);
916
917 if (d->role && d->role != role) {
918 wl_resource_post_error(errorResource, errorCode,
919 "Cannot assign role %s to wl_surface@%d, already has role %s\n",
920 role->name().constData(), wl_resource_get_id(resource()),
921 d->role->name().constData());
922 return false;
923 }
924
925 d->role = role;
926 return true;
927 }
928
role() const929 QWaylandSurfaceRole *QWaylandSurface::role() const
930 {
931 Q_D(const QWaylandSurface);
932 return d->role;
933 }
934
get(QWaylandSurface * surface)935 QWaylandSurfacePrivate *QWaylandSurfacePrivate::get(QWaylandSurface *surface)
936 {
937 return surface ? surface->d_func() : nullptr;
938 }
939
ref()940 void QWaylandSurfacePrivate::ref()
941 {
942 ++refCount;
943 }
944
deref()945 void QWaylandSurfacePrivate::deref()
946 {
947 if (--refCount == 0)
948 QWaylandCompositorPrivate::get(compositor)->destroySurface(q_func());
949 }
950
refView(QWaylandView * view)951 void QWaylandSurfacePrivate::refView(QWaylandView *view)
952 {
953 if (views.contains(view))
954 return;
955
956 views.append(view);
957 ref();
958 view->bufferCommitted(bufferRef, QRect(QPoint(0,0), bufferRef.size()));
959 }
960
derefView(QWaylandView * view)961 void QWaylandSurfacePrivate::derefView(QWaylandView *view)
962 {
963 int nViews = views.removeAll(view);
964
965 for (int i = 0; i < nViews && refCount > 0; i++) {
966 deref();
967 }
968 }
969
initSubsurface(QWaylandSurface * parent,wl_client * client,int id,int version)970 void QWaylandSurfacePrivate::initSubsurface(QWaylandSurface *parent, wl_client *client, int id, int version)
971 {
972 Q_Q(QWaylandSurface);
973 QWaylandSurface *oldParent = nullptr; // TODO: implement support for switching parents
974
975 subsurface = new Subsurface(this);
976 subsurface->init(client, id, version);
977 subsurface->parentSurface = parent->d_func();
978 emit q->parentChanged(parent, oldParent);
979 emit parent->childAdded(q);
980 }
981
subsurface_set_position(wl_subsurface::Resource * resource,int32_t x,int32_t y)982 void QWaylandSurfacePrivate::Subsurface::subsurface_set_position(wl_subsurface::Resource *resource, int32_t x, int32_t y)
983 {
984 Q_UNUSED(resource);
985 position = QPoint(x,y);
986 emit surface->q_func()->subsurfacePositionChanged(position);
987
988 }
989
subsurface_place_above(wl_subsurface::Resource * resource,struct wl_resource * sibling)990 void QWaylandSurfacePrivate::Subsurface::subsurface_place_above(wl_subsurface::Resource *resource, struct wl_resource *sibling)
991 {
992 Q_UNUSED(resource);
993 emit surface->q_func()->subsurfacePlaceAbove(QWaylandSurface::fromResource(sibling));
994 }
995
subsurface_place_below(wl_subsurface::Resource * resource,struct wl_resource * sibling)996 void QWaylandSurfacePrivate::Subsurface::subsurface_place_below(wl_subsurface::Resource *resource, struct wl_resource *sibling)
997 {
998 Q_UNUSED(resource);
999 emit surface->q_func()->subsurfacePlaceBelow(QWaylandSurface::fromResource(sibling));
1000 }
1001
subsurface_set_sync(wl_subsurface::Resource * resource)1002 void QWaylandSurfacePrivate::Subsurface::subsurface_set_sync(wl_subsurface::Resource *resource)
1003 {
1004 Q_UNUSED(resource);
1005 // TODO: sync/desync implementation
1006 qDebug() << Q_FUNC_INFO;
1007 }
1008
subsurface_set_desync(wl_subsurface::Resource * resource)1009 void QWaylandSurfacePrivate::Subsurface::subsurface_set_desync(wl_subsurface::Resource *resource)
1010 {
1011 Q_UNUSED(resource);
1012 // TODO: sync/desync implementation
1013 qDebug() << Q_FUNC_INFO;
1014 }
1015
1016 /*!
1017 * \qmlsignal QtWaylandCompositor::WaylandSurface::childAdded(WaylandSurface child)
1018 *
1019 * This signal is emitted when a wl_subsurface, \a child, has been added to the surface.
1020 */
1021
1022 /*!
1023 * \fn void QWaylandSurface::childAdded(QWaylandSurface *child)
1024 *
1025 * This signal is emitted when a wl_subsurface, \a child, has been added to the surface.
1026 */
1027
1028 /*!
1029 * \qmlsignal QtWaylandCompositor::WaylandSurface::surfaceDestroyed()
1030 *
1031 * This signal is emitted when the corresponding wl_surface is destroyed.
1032 */
1033
1034 /*!
1035 * \fn void QWaylandSurface::surfaceDestroyed()
1036 *
1037 * This signal is emitted when the corresponing wl_surface is destroyed.
1038 */
1039
1040 /*!
1041 * \qmlsignal void QtWaylandCompositor::WaylandSurface::dragStarted(WaylandDrag drag)
1042 *
1043 * This signal is emitted when a \a drag has started from this surface.
1044 */
1045
1046 /*!
1047 * \fn void QWaylandSurface::dragStarted(QWaylandDrag *drag)
1048 *
1049 * This signal is emitted when a \a drag has started from this surface.
1050 */
1051
1052 /*!
1053 * \fn void damaged(const QRegion &rect)
1054 *
1055 * This signal is emitted when the client tells the compositor that a particular part of, or
1056 * possibly the entire surface has been updated, so the compositor can redraw that part.
1057 *
1058 * While the compositor APIs take care of redrawing automatically, this function may be useful
1059 * if you require a specific, custom behavior.
1060 */
1061
1062 /*!
1063 * \fn void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
1064 *
1065 * This signal is emitted when the client has requested that this surface should be a
1066 * subsurface of \a newParent.
1067 */
1068
1069 QT_END_NAMESPACE
1070