1/*
2 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6#ifndef KWAYLAND_CLIENT_XDG_SHELL_H
7#define KWAYLAND_CLIENT_XDG_SHELL_H
8
9#include "KWayland/Client/kwaylandclient_export.h"
10#include <QObject>
11#include <QRect>
12#include <QSize>
13
14// This is a mix of structs for both xdgshell unstable v5 AND xdg wm base stable
15struct xdg_wm_base;
16struct xdg_shell;
17struct xdg_surface;
18struct xdg_popup;
19struct xdg_toplevel;
20
21struct zxdg_shell_v6;
22struct zxdg_toplevel_v6;
23struct zxdg_surface_v6;
24struct zxdg_popup_v6;
25struct zxdg_position_v6;
26
27namespace KWayland
28{
29namespace Client
30{
31class EventQueue;
32class Output;
33class Surface;
34class Seat;
35class XdgShellPopup;
36class XdgShellSurface;
37
38/**
39 * Builder class describing how a popup should be positioned
40 * when created
41 *
42 * @since 5.39
43 */
44class KWAYLANDCLIENT_EXPORT XdgPositioner
45{
46public:
47 /*
48 * Flags describing how a popup should be reposition if constrained
49 */
50 enum class Constraint {
51 /*
52 * Slide the popup on the X axis until there is room
53 */
54 SlideX = 1 << 0,
55 /*
56 * Slide the popup on the Y axis until there is room
57 */
58 SlideY = 1 << 1,
59 /*
60 * Invert the anchor and gravity on the X axis
61 */
62 FlipX = 1 << 2,
63 /*
64 * Invert the anchor and gravity on the Y axis
65 */
66 FlipY = 1 << 3,
67 /*
68 * Resize the popup in the X axis
69 */
70 ResizeX = 1 << 4,
71 /*
72 * Resize the popup in the Y axis
73 */
74 ResizeY = 1 << 5,
75 };
76
77 Q_DECLARE_FLAGS(Constraints, Constraint)
78
79 XdgPositioner(const QSize &initialSize = QSize(), const QRect &anchor = QRect());
80 XdgPositioner(const XdgPositioner &other);
81 ~XdgPositioner();
82
83 /**
84 * Which edge of the anchor should the popup be positioned around
85 */
86 // KF6 TODO use a better data type (enum of 8 options) rather than flags which allow invalid values
87 Qt::Edges anchorEdge() const;
88 void setAnchorEdge(Qt::Edges edge);
89
90 /**
91 * Specifies in what direction the popup should be positioned around the anchor
92 * i.e if the gravity is "bottom", then then the top of top of the popup will be at the anchor edge
93 * if the gravity is top, then the bottom of the popup will be at the anchor edge
94 *
95 */
96 // KF6 TODO use a better data type (enum of 8 options) rather than flags which allow invalid values
97 Qt::Edges gravity() const;
98 void setGravity(Qt::Edges edge);
99
100 /**
101 * The area this popup should be positioned around
102 */
103 QRect anchorRect() const;
104 void setAnchorRect(const QRect &anchor);
105
106 /**
107 * The size of the surface that is to be positioned.
108 */
109 QSize initialSize() const;
110 void setInitialSize(const QSize &size);
111
112 /**
113 * Specifies how the compositor should position the popup if it does not fit in the requested position
114 */
115 Constraints constraints() const;
116 void setConstraints(Constraints constraints);
117
118 /**
119 * An additional offset that should be applied from the anchor.
120 */
121 QPoint anchorOffset() const;
122 void setAnchorOffset(const QPoint &offset);
123
124private:
125 class Private;
126 QScopedPointer<Private> d;
127};
128
129Q_DECLARE_OPERATORS_FOR_FLAGS(XdgPositioner::Constraints)
130
131/**
132 * @short Wrapper for the xdg_shell interface.
133 *
134 * This class provides a convenient wrapper for the xdg_shell interface.
135 *
136 * To use this class one needs to interact with the Registry. There are two
137 * possible ways to create the XdgShell interface:
138 * @code
139 * XdgShell *c = registry->createXdgShell(name, version);
140 * @endcode
141 *
142 * This creates the XdgShell and sets it up directly. As an alternative this
143 * can also be done in a more low level way:
144 * @code
145 * XdgShell *c = new XdgShell;
146 * c->setup(registry->bindXdgShell(name, version));
147 * @endcode
148 *
149 * The XdgShell can be used as a drop-in replacement for any xdg_shell
150 * pointer as it provides matching cast operators.
151 *
152 * @see Registry
153 * @since 5.25
154 **/
155class KWAYLANDCLIENT_EXPORT XdgShell : public QObject
156{
157 Q_OBJECT
158public:
159 ~XdgShell() override;
160
161 /**
162 * Setup this XdgShell to manage the @p xdgshellv5.
163 * When using Registry::createXdgShell there is no need to call this
164 * method.
165 **/
166 void setup(xdg_shell *xdgshellv5);
167
168 /**
169 * Setup this XdgShell to manage the @p xdgshellv6.
170 * When using Registry::createXdgShell there is no need to call this
171 * method.
172 **/
173 void setup(zxdg_shell_v6 *xdgshellv6);
174
175 /**
176 * Setup this XdgShell to manage the @p xdg_wm_base.
177 * When using Registry::createXdgShell there is no need to call this
178 * method.
179 **/
180 void setup(xdg_wm_base *xdg_wm_base);
181 /**
182 * @returns @c true if managing a xdg_shell.
183 **/
184 bool isValid() const;
185 /**
186 * Releases the xdg_shell interface.
187 * After the interface has been released the XdgShell instance is no
188 * longer valid and can be setup with another xdg_shell interface.
189 **/
190 void release();
191 /**
192 * Destroys the data held by this XdgShell.
193 * This method is supposed to be used when the connection to the Wayland
194 * server goes away. If the connection is not valid anymore, it's not
195 * possible to call release anymore as that calls into the Wayland
196 * connection and the call would fail. This method cleans up the data, so
197 * that the instance can be deleted or set up to a new xdg_shell interface
198 * once there is a new connection available.
199 *
200 * This method is automatically invoked when the Registry which created this
201 * XdgShell gets destroyed.
202 *
203 * @see release
204 **/
205 void destroy();
206
207 /**
208 * Sets the @p queue to use for creating objects with this XdgShell.
209 **/
210 void setEventQueue(EventQueue *queue);
211 /**
212 * @returns The event queue to use for creating objects with this XdgShell.
213 **/
214 EventQueue *eventQueue();
215
216 /**
217 * Creates a new XdgShellSurface for the given @p surface.
218 **/
219 XdgShellSurface *createSurface(Surface *surface, QObject *parent = nullptr);
220
221 /**
222 * Creates a new XdgShellPopup for the given @p surface on top of @p parentSurface.
223 * This method is only valid for Xdgv5
224 **/
225 XdgShellPopup *createPopup(Surface *surface, Surface *parentSurface, Seat *seat, quint32 serial, const QPoint &parentPos, QObject *parent = nullptr);
226
227 /**
228 * Creates a new XdgShellPopup for the given @p surface on top of @p parentSurface with the given @p positioner.
229 * This method is only valid for Xdgv6 onwards.
230 * @since 5.39
231 **/
232 XdgShellPopup *createPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent = nullptr);
233
234 /**
235 * Creates a new XdgShellPopup for the given @p surface on top of @p parentSurface with the given @p positioner.
236 * @since 5.39
237 **/
238 XdgShellPopup *createPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent = nullptr);
239
240 operator xdg_wm_base *();
241 operator xdg_wm_base *() const;
242 operator xdg_shell *();
243 operator xdg_shell *() const;
244 operator zxdg_shell_v6 *();
245 operator zxdg_shell_v6 *() const;
246
247Q_SIGNALS:
248 /**
249 * The corresponding global for this interface on the Registry got removed.
250 *
251 * This signal gets only emitted if the XdgShell got created by
252 * Registry::createXdgShell
253 **/
254 void removed();
255
256protected:
257 /**
258 * Creates a new XdgShell.
259 * Note: after constructing the XdgShell it is not yet valid and one needs
260 * to call setup. In order to get a ready to use XdgShell prefer using
261 * Registry::createXdgShell.
262 **/
263 class Private;
264 explicit XdgShell(Private *p, QObject *parent = nullptr);
265
266private:
267 QScopedPointer<Private> d;
268};
269
270/**
271 *
272 * @since 5.25
273 **/
274class KWAYLANDCLIENT_EXPORT XdgShellSurface : public QObject
275{
276 Q_OBJECT
277public:
278 ~XdgShellSurface() override;
279 /**
280 * States the Surface can be in
281 **/
282 enum class State {
283 /**
284 * The Surface is maximized.
285 **/
286 Maximized = 1 << 0,
287 /**
288 * The Surface is fullscreen.
289 **/
290 Fullscreen = 1 << 1,
291 /**
292 * The Surface is currently being resized by the Compositor.
293 **/
294 Resizing = 1 << 2,
295 /**
296 * The Surface is considered active. Does not imply keyboard focus.
297 **/
298 Activated = 1 << 3
299 };
300 Q_DECLARE_FLAGS(States, State)
301
302 /**
303 * Setup this XdgShellSurface to manage the @p xdgsurfacev5.
304 * When using XdgShell::createXdgShellSurface there is no need to call this
305 * method.
306 **/
307 void setup(xdg_surface *xdgsurfacev5);
308
309 /**
310 * Setup this XdgShellSurface to manage the @p toplevel on the relevant @p xdgsurfacev6
311 * When using XdgShell::createXdgShellSurface there is no need to call this
312 * method.
313 **/
314 void setup(zxdg_surface_v6 *xdgsurfacev6, zxdg_toplevel_v6 *toplevel);
315
316 /**
317 * Setup this XdgShellSurface to manage the @p toplevel on the relevant @p xdgsurface
318 * When using XdgShell::createXdgShellSurface there is no need to call this
319 * method.
320 **/
321 void setup(xdg_surface *xdgsurface, xdg_toplevel *toplevel);
322
323 /**
324 * @returns @c true if managing a xdg_surface.
325 **/
326 bool isValid() const;
327 /**
328 * Releases the xdg_surface interface.
329 * After the interface has been released the XdgShellSurface instance is no
330 * longer valid and can be setup with another xdg_surface interface.
331 **/
332 void release();
333 /**
334 * Destroys the data held by this XdgShellSurface.
335 * This method is supposed to be used when the connection to the Wayland
336 * server goes away. If the connection is not valid anymore, it's not
337 * possible to call release anymore as that calls into the Wayland
338 * connection and the call would fail. This method cleans up the data, so
339 * that the instance can be deleted or set up to a new xdg_surface interface
340 * once there is a new connection available.
341 *
342 * It is suggested to connect this method to ConnectionThread::connectionDied:
343 * @code
344 * connect(connection, &ConnectionThread::connectionDied, xdgsurfacev5, &XdgShellSurface::destroy);
345 * @endcode
346 *
347 * @see release
348 **/
349 void destroy();
350 /**
351 * Sets the @p queue to use for bound proxies.
352 **/
353 void setEventQueue(EventQueue *queue);
354 /**
355 * @returns The event queue to use for bound proxies.
356 **/
357 EventQueue *eventQueue();
358
359 /**
360 * The currently configured size.
361 * @see sizeChanged
362 * @see setSize
363 **/
364 QSize size() const;
365
366 /**
367 * Sets the size for the XdgShellSurface to @p size.
368 * This is mostly an internal information. The actual size of the XdgShellSurface is
369 * determined by the size of the Buffer attached to the XdgShellSurface's Surface.
370 *
371 * @param size The new size to be used for the XdgShellSurface
372 * @see size
373 * @see sizeChanged
374 **/
375 void setSize(const QSize &size);
376
377 /**
378 * Set this XdgShellSurface as transient for @p parent.
379 **/
380 void setTransientFor(XdgShellSurface *parent);
381
382 /**
383 * Sets the window title of this XdgShellSurface to @p title.
384 **/
385 void setTitle(const QString &title);
386
387 /**
388 * Set an application identifier for the surface.
389 **/
390 void setAppId(const QByteArray &appId);
391
392 /**
393 * Requests to show the window menu at @p pos in surface coordinates.
394 **/
395 void requestShowWindowMenu(Seat *seat, quint32 serial, const QPoint &pos);
396
397 /**
398 * Requests a move on the given @p seat after the pointer button press with the given @p serial.
399 *
400 * @param seat The seat on which to move the window
401 * @param serial The serial of the pointer button press which should trigger the move
402 **/
403 void requestMove(Seat *seat, quint32 serial);
404
405 /**
406 * Requests a resize on the given @p seat after the pointer button press with the given @p serial.
407 *
408 * @param seat The seat on which to resize the window
409 * @param serial The serial of the pointer button press which should trigger the resize
410 * @param edges A hint for the compositor to set e.g. an appropriate cursor image
411 **/
412 void requestResize(Seat *seat, quint32 serial, Qt::Edges edges);
413
414 /**
415 * When a configure event is received, if a client commits the
416 * Surface in response to the configure event, then the client
417 * must make an ackConfigure request sometime before the commit
418 * request, passing along the @p serial of the configure event.
419 * @see configureRequested
420 **/
421 void ackConfigure(quint32 serial);
422
423 /**
424 * Request to set this XdgShellSurface to be maximized if @p set is @c true.
425 * If @p set is @c false it requests to unset the maximized state - if set.
426 *
427 * @param set Whether the XdgShellSurface should be maximized
428 **/
429 void setMaximized(bool set);
430
431 /**
432 * Request to set this XdgShellSurface as fullscreen on @p output.
433 * If @p set is @c true the Surface should be set to fullscreen, otherwise restore
434 * from fullscreen state.
435 *
436 * @param set Whether the Surface should be fullscreen or not
437 * @param output Optional output as hint to the compositor where the Surface should be put
438 **/
439 void setFullscreen(bool set, Output *output = nullptr);
440
441 /**
442 * Request to the compositor to minimize this XdgShellSurface.
443 **/
444 void requestMinimize();
445
446 /**
447 * Set this surface to have a given maximum size
448 * @since 5.39
449 */
450 void setMaxSize(const QSize &size);
451
452 /**
453 * Set this surface to have a given minimum size
454 * @since 5.39
455 */
456 void setMinSize(const QSize &size);
457
458 /**
459 * Sets the position of the window contents within the buffer
460 * @since 5.59
461 */
462 void setWindowGeometry(const QRect &windowGeometry);
463
464 operator xdg_surface *();
465 operator xdg_surface *() const;
466 operator xdg_toplevel *();
467 operator xdg_toplevel *() const;
468 operator zxdg_surface_v6 *();
469 operator zxdg_surface_v6 *() const;
470 operator zxdg_toplevel_v6 *();
471 operator zxdg_toplevel_v6 *() const;
472
473Q_SIGNALS:
474 /**
475 * The compositor requested to close this window.
476 **/
477 void closeRequested();
478 /**
479 * The compositor sent a configure with the new @p size and the @p states.
480 * Before the next commit of the surface the @p serial needs to be passed to ackConfigure.
481 **/
482 void configureRequested(const QSize &size, KWayland::Client::XdgShellSurface::States states, quint32 serial);
483
484 /**
485 * Emitted whenever the size of the XdgShellSurface changes by e.g. receiving a configure request.
486 *
487 * @see configureRequested
488 * @see size
489 * @see setSize
490 **/
491 void sizeChanged(const QSize &);
492
493protected:
494 class Private;
495 explicit XdgShellSurface(Private *p, QObject *parent = nullptr);
496
497private:
498 QScopedPointer<Private> d;
499};
500
501Q_DECLARE_OPERATORS_FOR_FLAGS(XdgShellSurface::States)
502
503/**
504 * A XdgShellPopup is a short-lived, temporary surface that can be
505 * used to implement menus. It takes an explicit grab on the surface
506 * that will be dismissed when the user dismisses the popup. This can
507 * be done by the user clicking outside the surface, using the keyboard,
508 * or even locking the screen through closing the lid or a timeout.
509 * @since 5.25
510 **/
511class KWAYLANDCLIENT_EXPORT XdgShellPopup : public QObject
512{
513 Q_OBJECT
514public:
515 ~XdgShellPopup() override;
516
517 /**
518 * Setup this XdgShellPopup to manage the @p xdgpopupv5.
519 * When using XdgShell::createXdgShellPopup there is no need to call this
520 * method.
521 *
522 * @deprecated Since 5.49. This was for XDGShellV5, this is now deprecated
523 **/
524 // KWAYLANDCLIENT_DEPRECATED_VERSION(5, 49, "Use XDGShell version >5") // TODO KF6 remove internal usage
525 void setup(xdg_popup *xdgpopupv5);
526
527 /**
528 * Setup this XdgShellPopup to manage the @p xdgpopupv6 on associated @p xdgsurfacev6
529 * When using XdgShell::createXdgShellPopup there is no need to call this
530 * method.
531 * @since 5.39
532 **/
533 void setup(zxdg_surface_v6 *xdgsurfacev6, zxdg_popup_v6 *xdgpopup6);
534
535 /**
536 * Setup this XdgShellPopup to manage the @p xdgpopupv on associated @p xdgsurface
537 * When using XdgShell::createXdgShellPopup there is no need to call this
538 * method.
539 * @since 5.XDGSTABLE
540 **/
541 void setup(xdg_surface *xdgsurface, xdg_popup *xdgpopup);
542
543 /**
544 * @returns @c true if managing an xdg_popup.
545 **/
546 bool isValid() const;
547 /**
548 * Releases the xdg_popup interface.
549 * After the interface has been released the XdgShellPopup instance is no
550 * longer valid and can be setup with another xdg_popup interface.
551 **/
552 void release();
553 /**
554 * Destroys the data held by this XdgShellPopup.
555 * This method is supposed to be used when the connection to the Wayland
556 * server goes away. If the connection is not valid anymore, it's not
557 * possible to call release anymore as that calls into the Wayland
558 * connection and the call would fail. This method cleans up the data, so
559 * that the instance can be deleted or set up to a new xdg_popup interface
560 * once there is a new connection available.
561 *
562 * It is suggested to connect this method to ConnectionThread::connectionDied:
563 * @code
564 * connect(connection, &ConnectionThread::connectionDied, xdgpopupv5, &XdgShellPopup::destroy);
565 * @endcode
566 *
567 * @see release
568 **/
569 void destroy();
570 /**
571 * Sets the @p queue to use for bound proxies.
572 **/
573 void setEventQueue(EventQueue *queue);
574 /**
575 * @returns The event queue to use for bound proxies.
576 **/
577 EventQueue *eventQueue();
578
579 /**
580 * Requests a grab on this popup
581 * @since 5.39
582 */
583 void requestGrab(Seat *seat, quint32 serial);
584
585 /**
586 * When a configure event is received, if a client commits the
587 * Surface in response to the configure event, then the client
588 * must make an ackConfigure request sometime before the commit
589 * request, passing along the @p serial of the configure event.
590 * @see configureRequested
591 * @since 5.56
592 **/
593 void ackConfigure(quint32 serial);
594
595 /**
596 * Sets the position of the window contents within the buffer
597 * @since 5.59
598 */
599 void setWindowGeometry(const QRect &windowGeometry);
600
601 operator xdg_surface *();
602 operator xdg_surface *() const;
603 operator xdg_popup *();
604 operator xdg_popup *() const;
605 operator zxdg_surface_v6 *();
606 operator zxdg_surface_v6 *() const;
607 operator zxdg_popup_v6 *();
608 operator zxdg_popup_v6 *() const;
609
610Q_SIGNALS:
611 /**
612 * This signal is emitted when a XdgShellPopup is dismissed by the
613 * compositor. The user should delete this instance at this point.
614 **/
615 void popupDone();
616
617 /**
618 * Emitted when the server has configured the popup with the final location of @p relativePosition
619 * This is emitted for V6 surfaces only
620 * @since 5.39
621 **/
622 void configureRequested(const QRect &relativePosition, quint32 serial);
623
624protected:
625 class Private;
626 explicit XdgShellPopup(Private *p, QObject *parent = nullptr);
627
628private:
629 QScopedPointer<Private> d;
630};
631
632/**
633 * Wrapper class for xdg_wm_base interface.
634 *
635 * @since 5.101
636 */
637class KWAYLANDCLIENT_EXPORT XdgShellStable : public XdgShell
638{
639 Q_OBJECT
640public:
641 explicit XdgShellStable(QObject *parent = nullptr);
642 ~XdgShellStable() override;
643
644private:
645 class Private;
646};
647
648/**
649 * Wrapper class for xdg_toplevel interface.
650 *
651 * @since 5.101
652 */
653class KWAYLANDCLIENT_EXPORT XdgTopLevelStable : public XdgShellSurface
654{
655 Q_OBJECT
656public:
657 explicit XdgTopLevelStable(QObject *parent = nullptr);
658 ~XdgTopLevelStable() override;
659
660private:
661 friend class XdgShellStable;
662 class Private;
663};
664
665/**
666 * Wrapper class for xdg_popup interface.
667 *
668 * @since 5.101
669 */
670class KWAYLANDCLIENT_EXPORT XdgShellPopupStable : public XdgShellPopup
671{
672public:
673 explicit XdgShellPopupStable(QObject *parent = nullptr);
674 ~XdgShellPopupStable() override;
675
676private:
677 friend class XdgShellStable;
678 class Private;
679};
680
681}
682}
683
684Q_DECLARE_METATYPE(KWayland::Client::XdgPositioner)
685Q_DECLARE_METATYPE(KWayland::Client::XdgShellSurface::State)
686Q_DECLARE_METATYPE(KWayland::Client::XdgShellSurface::States)
687Q_DECLARE_METATYPE(KWayland::Client::XdgPositioner::Constraint)
688Q_DECLARE_METATYPE(KWayland::Client::XdgPositioner::Constraints)
689
690#endif
691

source code of kwayland/src/client/xdgshell.h