Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwaylandxdgshell.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// Copyright (C) 2017 Eurogiciel, author: <philippe.coval@eurogiciel.fr>
3// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org>
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
7
10
11#include <QtWaylandClient/private/qwaylanddisplay_p.h>
12#include <QtWaylandClient/private/qwaylandwindow_p.h>
13#include <QtWaylandClient/private/qwaylandinputdevice_p.h>
14#include <QtWaylandClient/private/qwaylandscreen_p.h>
15#include <QtWaylandClient/private/qwaylandcursor_p.h>
16#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
17
18#include <QtGui/QGuiApplication>
19#include <QtGui/private/qwindow_p.h>
20
22
23namespace QtWaylandClient {
24
25QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface)
26 : QtWayland::xdg_toplevel(xdgSurface->get_toplevel())
27 , m_xdgSurface(xdgSurface)
28{
29 QWindow *window = xdgSurface->window()->window();
30 if (auto *decorationManager = m_xdgSurface->m_shell->decorationManager()) {
31 if (!(window->flags() & Qt::FramelessWindowHint))
32 m_decoration = decorationManager->createToplevelDecoration(object());
33 }
34 requestWindowStates(window->windowStates());
35 requestWindowFlags(window->flags());
36 if (auto transientParent = xdgSurface->window()->transientParent()) {
37 if (auto parentSurface =
38 qobject_cast<QWaylandXdgSurface *>(transientParent->shellSurface())) {
39 set_parent(parentSurface->m_toplevel->object());
40 if (window->modality() != Qt::NonModal && m_xdgSurface->m_shell->m_xdgDialogWm) {
41 m_xdgDialog.reset(m_xdgSurface->m_shell->m_xdgDialogWm->getDialog(object()));
42 m_xdgDialog->set_modal();
43 }
44 }
45 }
46}
47
48QWaylandXdgSurface::Toplevel::~Toplevel()
49{
50 // The protocol spec requires that the decoration object is deleted before xdg_toplevel.
51 delete m_decoration;
52 m_decoration = nullptr;
53
54 if (isInitialized())
55 destroy();
56}
57
58void QWaylandXdgSurface::Toplevel::applyConfigure()
59{
60 if (!(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen)))
61 m_normalSize = m_xdgSurface->m_window->windowContentGeometry().size();
62
63 if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive)
64 && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
65 m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window);
66
67 if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive)
68 && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
69 m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);
70
71 m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates);
72 m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);
73
74 // If the width or height is zero, the client should decide the size on its own.
75 QSize surfaceSize;
76
77 if (m_pending.size.width() > 0) {
78 surfaceSize.setWidth(m_pending.size.width());
79 } else {
80 if (Q_UNLIKELY(m_pending.states & (Qt::WindowMaximized | Qt::WindowFullScreen))) {
81 qCWarning(lcQpaWayland) << "Configure event with maximized or fullscreen state contains invalid width:" << m_pending.size.width();
82 } else {
83 int width = m_normalSize.width();
84 if (!m_pending.bounds.isEmpty())
85 width = std::min(width, m_pending.bounds.width());
86 surfaceSize.setWidth(width);
87 }
88 }
89
90 if (m_pending.size.height() > 0) {
91 surfaceSize.setHeight(m_pending.size.height());
92 } else {
93 if (Q_UNLIKELY(m_pending.states & (Qt::WindowMaximized | Qt::WindowFullScreen))) {
94 qCWarning(lcQpaWayland) << "Configure event with maximized or fullscreen state contains invalid height:" << m_pending.size.height();
95 } else {
96 int height = m_normalSize.height();
97 if (!m_pending.bounds.isEmpty())
98 height = std::min(height, m_pending.bounds.height());
99 surfaceSize.setHeight(height);
100 }
101 }
102
103 m_applied = m_pending;
104
105 if (!surfaceSize.isEmpty())
106 m_xdgSurface->m_window->resizeFromApplyConfigure(surfaceSize.grownBy(m_xdgSurface->m_window->windowContentMargins()));
107
108 qCDebug(lcQpaWayland) << "Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states;
109}
110
111bool QWaylandXdgSurface::Toplevel::wantsDecorations()
112{
113 if (m_decoration && (m_decoration->pending() == QWaylandXdgToplevelDecorationV1::mode_server_side
114 || !m_decoration->isConfigured()))
115 return false;
116
117 return !(m_pending.states & Qt::WindowFullScreen);
118}
119
120void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure_bounds(int32_t width, int32_t height)
121{
122 m_pending.bounds = QSize(width, height);
123}
124
125void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states)
126{
127 m_pending.size = QSize(width, height);
128
129 auto *xdgStates = static_cast<uint32_t *>(states->data);
130 size_t numStates = states->size / sizeof(uint32_t);
131
132 m_pending.suspended = false;
133 m_pending.states = Qt::WindowNoState;
134 m_toplevelStates = QWaylandWindow::WindowNoState;
135
136 for (size_t i = 0; i < numStates; i++) {
137 switch (xdgStates[i]) {
138 case XDG_TOPLEVEL_STATE_ACTIVATED:
139 m_pending.states |= Qt::WindowActive;
140 break;
141 case XDG_TOPLEVEL_STATE_MAXIMIZED:
142 m_pending.states |= Qt::WindowMaximized;
143 break;
144 case XDG_TOPLEVEL_STATE_FULLSCREEN:
145 m_pending.states |= Qt::WindowFullScreen;
146 break;
147 case XDG_TOPLEVEL_STATE_TILED_LEFT:
148 m_toplevelStates |= QWaylandWindow::WindowTiledLeft;
149 break;
150 case XDG_TOPLEVEL_STATE_TILED_RIGHT:
151 m_toplevelStates |= QWaylandWindow::WindowTiledRight;
152 break;
153 case XDG_TOPLEVEL_STATE_TILED_TOP:
154 m_toplevelStates |= QWaylandWindow::WindowTiledTop;
155 break;
156 case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
157 m_toplevelStates |= QWaylandWindow::WindowTiledBottom;
158 break;
159 case XDG_TOPLEVEL_STATE_SUSPENDED:
160 m_pending.suspended = true;
161 break;
162 default:
163 break;
164 }
165 }
166 qCDebug(lcQpaWayland) << "Received xdg_toplevel.configure with" << m_pending.size
167 << "and" << m_pending.states;
168}
169
170void QWaylandXdgSurface::Toplevel::xdg_toplevel_close()
171{
172 QWindowSystemInterface::handleCloseEvent(m_xdgSurface->m_window->window());
173}
174
175void QWaylandXdgSurface::Toplevel::requestWindowFlags(Qt::WindowFlags flags)
176{
177 if (m_decoration) {
179 delete m_decoration;
180 m_decoration = nullptr;
181 } else {
182 m_decoration->unsetMode();
183 }
184 }
185}
186
187void QWaylandXdgSurface::Toplevel::requestWindowStates(Qt::WindowStates states)
188{
189 // Re-send what's different from the applied state
190 Qt::WindowStates changedStates = m_applied.states ^ states;
191
192 // Minimized state is not reported by the protocol, so always send it
194 set_minimized();
195 m_xdgSurface->window()->handleWindowStatesChanged(states & ~Qt::WindowMinimized);
196 // The internal window state whilst minimized is not maximised or fullscreen, but we don't want to
197 // update the compositors cached version of this state
198 return;
199 }
200
201 if (changedStates & Qt::WindowMaximized) {
203 set_maximized();
204 else
205 unset_maximized();
206 }
207
208 if (changedStates & Qt::WindowFullScreen) {
210 auto screen = m_xdgSurface->window()->waylandScreen();
211 if (screen) {
212 set_fullscreen(screen->output());
213 }
214 } else
215 unset_fullscreen();
216 }
217
218
219}
220
221QtWayland::xdg_toplevel::resize_edge QWaylandXdgSurface::Toplevel::convertToResizeEdges(Qt::Edges edges)
222{
223 return static_cast<enum resize_edge>(
224 ((edges & Qt::TopEdge) ? resize_edge_top : 0)
225 | ((edges & Qt::BottomEdge) ? resize_edge_bottom : 0)
226 | ((edges & Qt::LeftEdge) ? resize_edge_left : 0)
227 | ((edges & Qt::RightEdge) ? resize_edge_right : 0));
228}
229
230QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent,
231 QtWayland::xdg_positioner *positioner)
232 : m_xdgSurface(xdgSurface)
233 , m_parentXdgSurface(qobject_cast<QWaylandXdgSurface *>(parent->shellSurface()))
234 , m_parent(parent)
235{
236
237 init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() : nullptr,
238 positioner->object()));
239}
240
241QWaylandXdgSurface::Popup::~Popup()
242{
243 if (isInitialized())
244 destroy();
245
246 if (m_grabbing) {
247 m_grabbing = false;
248
249 // Synthesize Qt enter/leave events for popup
250 QWindow *leave = nullptr;
251 if (m_xdgSurface && m_xdgSurface->window())
252 leave = m_xdgSurface->window()->window();
254
255 QWindow *enter = nullptr;
256 if (m_parentXdgSurface && m_parentXdgSurface->window()) {
257 enter = m_parentXdgSurface->window()->window();
258 const auto pos = m_xdgSurface->window()->display()->waylandCursor()->pos();
260 }
261 }
262}
263
264void QWaylandXdgSurface::Popup::applyConfigure()
265{
266 if (m_pendingGeometry.isValid()) {
267 QRect geometryWithMargins = m_pendingGeometry.marginsAdded(m_xdgSurface->m_window->windowContentMargins());
268 QMargins parentMargins = m_parent->windowContentMargins() - m_parent->clientSideMargins();
269 QRect globalGeometry = geometryWithMargins.translated(m_parent->geometry().topLeft() + QPoint(parentMargins.left(), parentMargins.top()));
270 m_xdgSurface->setGeometryFromApplyConfigure(globalGeometry.topLeft(), globalGeometry.size());
271 }
272 resetConfiguration();
273}
274
275void QWaylandXdgSurface::Popup::resetConfiguration()
276{
277 m_pendingGeometry = QRect();
278}
279
280void QWaylandXdgSurface::Popup::grab(QWaylandInputDevice *seat, uint serial)
281{
282 xdg_popup::grab(seat->wl_seat(), serial);
283 m_grabbing = true;
284}
285
286void QWaylandXdgSurface::Popup::xdg_popup_configure(int32_t x, int32_t y, int32_t width, int32_t height)
287{
288 m_pendingGeometry = QRect(x, y, width, height);
289}
290
291void QWaylandXdgSurface::Popup::xdg_popup_popup_done()
292{
293 QWindowSystemInterface::handleCloseEvent(m_xdgSurface->m_window->window());
294}
295
298 , xdg_surface(surface)
299 , m_shell(shell)
300 , m_window(window)
301{
303 Qt::WindowType type = window->window()->type();
304 auto *transientParent = window->transientParent();
305
306 if (type == Qt::ToolTip && transientParent) {
307 setPopup(transientParent);
308 } else if (type == Qt::Popup && transientParent && display->lastInputDevice()) {
309 setGrabPopup(transientParent, display->lastInputDevice(), display->lastInputSerial());
310 } else {
311 setToplevel();
312 }
313 setSizeHints();
314}
315
317{
318 if (m_toplevel) {
319 delete m_toplevel;
320 m_toplevel = nullptr;
321 }
322 if (m_popup) {
323 delete m_popup;
324 m_popup = nullptr;
325 }
326 destroy();
327}
328
329bool QWaylandXdgSurface::resize(QWaylandInputDevice *inputDevice, Qt::Edges edges)
330{
331 if (!m_toplevel || !m_toplevel->isInitialized())
332 return false;
333
334 auto resizeEdges = Toplevel::convertToResizeEdges(edges);
335 m_toplevel->resize(inputDevice->wl_seat(), inputDevice->serial(), resizeEdges);
336 return true;
337}
338
340{
341 if (m_toplevel && m_toplevel->isInitialized()) {
342 m_toplevel->move(inputDevice->wl_seat(), inputDevice->serial());
343 return true;
344 }
345 return false;
346}
347
349{
350 if (m_toplevel && m_toplevel->isInitialized()) {
352 m_toplevel->show_window_menu(seat->wl_seat(), seat->serial(), position.x(), position.y());
353 return true;
354 }
355 return false;
356}
357
359{
360 if (m_toplevel)
361 m_toplevel->set_title(title);
362}
363
365{
366 if (m_toplevel)
367 m_toplevel->set_app_id(appId);
368
369 m_appId = appId;
370}
371
373{
374 if (m_toplevel)
375 m_toplevel->requestWindowFlags(flags);
376}
377
379{
380 if (m_toplevel && m_toplevel->m_applied.suspended)
381 return false;
382
383 return m_configured || m_pendingConfigureSerial;
384}
385
387{
388 if (!isExposed() && !region.isEmpty()) {
389 return true;
390 }
391 return false;
392}
393
395{
396 // It is a redundant ack_configure, so skipped.
397 if (m_pendingConfigureSerial == m_appliedConfigureSerial)
398 return;
399
400 if (m_toplevel)
401 m_toplevel->applyConfigure();
402 if (m_popup)
403 m_popup->applyConfigure();
404 m_appliedConfigureSerial = m_pendingConfigureSerial;
405
406 m_configured = true;
407 ack_configure(m_appliedConfigureSerial);
408}
409
411{
412 return m_toplevel && m_toplevel->wantsDecorations();
413}
414
419
421{
422 if (window()->isExposed())
423 set_window_geometry(rect.x(), rect.y(), rect.width(), rect.height());
424}
425
427{
428 if (m_toplevel && m_window) {
429 const QMargins margins = m_window->windowContentMargins() - m_window->clientSideMargins();
430 const QSize minSize = m_window->windowMinimumSize().shrunkBy(margins);
431 const QSize maxSize = m_window->windowMaximumSize().shrunkBy(margins);
432 const int minWidth = qMax(0, minSize.width());
433 const int minHeight = qMax(0, minSize.height());
434 int maxWidth = qMax(0, maxSize.width());
435 int maxHeight = qMax(0, maxSize.height());
436
437 // It will not change min/max sizes if invalid.
438 if (minWidth > maxWidth || minHeight > maxHeight)
439 return;
440
441 if (maxWidth == QWINDOWSIZE_MAX)
442 maxWidth = 0;
443 if (maxHeight == QWINDOWSIZE_MAX)
444 maxHeight = 0;
445
446 m_toplevel->set_min_size(minWidth, minHeight);
447 m_toplevel->set_max_size(maxWidth, maxHeight);
448 }
449}
450
452{
453 QByteArray lowerCaseResource = resource.toLower();
454 if (lowerCaseResource == "xdg_surface")
455 return object();
456 else if (lowerCaseResource == "xdg_toplevel" && m_toplevel)
457 return m_toplevel->object();
458 else if (lowerCaseResource == "xdg_popup" && m_popup)
459 return m_popup->object();
460 return nullptr;
461}
462
464{
465 if (m_toplevel)
466 return m_toplevel->object();
467 if (m_popup)
468 return m_popup->object();
469 return {};
470}
471
473{
474 if (m_toplevel)
475 m_toplevel->requestWindowStates(states);
476 else
477 qCDebug(lcQpaWayland) << "Ignoring window states requested by non-toplevel zxdg_surface_v6.";
478}
479
480void QWaylandXdgSurface::setToplevel()
481{
482 Q_ASSERT(!m_toplevel && !m_popup);
483 m_toplevel = new Toplevel(this);
484}
485
486void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
487{
488 Q_ASSERT(!m_toplevel && !m_popup);
489
490 auto positioner = new QtWayland::xdg_positioner(m_shell->m_xdgWmBase->create_positioner());
491 // set_popup expects a position relative to the parent
492 QRect windowGeometry = m_window->windowContentGeometry();
493 QMargins windowMargins = m_window->windowContentMargins() - m_window->clientSideMargins();
494 QMargins parentMargins = parent->windowContentMargins() - parent->clientSideMargins();
495
496 // These property overrides may be removed when public API becomes available
497 QRect placementAnchor = m_window->window()->property("_q_waylandPopupAnchorRect").toRect();
498 if (!placementAnchor.isValid()) {
499 placementAnchor = QRect(m_window->geometry().topLeft() - parent->geometry().topLeft(), QSize(1,1));
500 }
501 placementAnchor.translate(windowMargins.left(), windowMargins.top());
502 placementAnchor.translate(-parentMargins.left(), -parentMargins.top());
503
504 uint32_t anchor = QtWayland::xdg_positioner::anchor_top_right;
505 const QVariant anchorVariant = m_window->window()->property("_q_waylandPopupAnchor");
506 if (anchorVariant.isValid()) {
507 switch (anchorVariant.value<Qt::Edges>()) {
508 case Qt::Edges():
509 anchor = QtWayland::xdg_positioner::anchor_none;
510 break;
511 case Qt::TopEdge:
512 anchor = QtWayland::xdg_positioner::anchor_top;
513 break;
515 anchor = QtWayland::xdg_positioner::anchor_top_right;
516 break;
517 case Qt::RightEdge:
518 anchor = QtWayland::xdg_positioner::anchor_right;
519 break;
521 anchor = QtWayland::xdg_positioner::anchor_bottom_right;
522 break;
523 case Qt::BottomEdge:
524 anchor = QtWayland::xdg_positioner::anchor_bottom;
525 break;
527 anchor = QtWayland::xdg_positioner::anchor_bottom_left;
528 break;
529 case Qt::LeftEdge:
530 anchor = QtWayland::xdg_positioner::anchor_left;
531 break;
533 anchor = QtWayland::xdg_positioner::anchor_top_left;
534 break;
535 }
536 }
537
538 uint32_t gravity = QtWayland::xdg_positioner::gravity_bottom_right;
539 const QVariant popupGravityVariant = m_window->window()->property("_q_waylandPopupGravity");
540 if (popupGravityVariant.isValid()) {
541 switch (popupGravityVariant.value<Qt::Edges>()) {
542 case Qt::Edges():
543 gravity = QtWayland::xdg_positioner::gravity_none;
544 break;
545 case Qt::TopEdge:
546 gravity = QtWayland::xdg_positioner::gravity_top;
547 break;
549 gravity = QtWayland::xdg_positioner::gravity_top_right;
550 break;
551 case Qt::RightEdge:
552 gravity = QtWayland::xdg_positioner::gravity_right;
553 break;
555 gravity = QtWayland::xdg_positioner::gravity_bottom_right;
556 break;
557 case Qt::BottomEdge:
558 gravity = QtWayland::xdg_positioner::gravity_bottom;
559 break;
561 gravity = QtWayland::xdg_positioner::gravity_bottom_left;
562 break;
563 case Qt::LeftEdge:
564 gravity = QtWayland::xdg_positioner::gravity_left;
565 break;
567 gravity = QtWayland::xdg_positioner::gravity_top_left;
568 break;
569 }
570 }
571
572 uint32_t constraintAdjustment = QtWayland::xdg_positioner::constraint_adjustment_slide_x | QtWayland::xdg_positioner::constraint_adjustment_slide_y;
573 const QVariant constraintAdjustmentVariant = m_window->window()->property("_q_waylandPopupConstraintAdjustment");
574 if (constraintAdjustmentVariant.isValid()) {
575 constraintAdjustment = constraintAdjustmentVariant.toUInt();
576 }
577
578 positioner->set_anchor_rect(placementAnchor.x(),
579 placementAnchor.y(),
580 placementAnchor.width(),
581 placementAnchor.height());
582 positioner->set_anchor(anchor);
583 positioner->set_gravity(gravity);
584 positioner->set_size(windowGeometry.width(), windowGeometry.height());
585 positioner->set_constraint_adjustment(constraintAdjustment);
586 m_popup = new Popup(this, parent, positioner);
587 positioner->destroy();
588
589 delete positioner;
590}
591
592void QWaylandXdgSurface::setGrabPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial)
593{
594 setPopup(parent);
595 m_popup->grab(device, serial);
596
597 // Synthesize Qt enter/leave events for popup
598 if (!parent)
599 return;
600 QWindow *leave = parent->window();
602
603 QWindow *enter = nullptr;
604 if (m_popup && m_popup->m_xdgSurface && m_popup->m_xdgSurface->window())
605 enter = m_popup->m_xdgSurface->window()->window();
606
607 if (enter) {
608 const auto pos = m_popup->m_xdgSurface->window()->display()->waylandCursor()->pos();
610 }
611}
612
614{
615 m_pendingConfigureSerial = serial;
616 if (!m_configured) {
617 // We have to do the initial applyConfigure() immediately, since that is the expose.
619 if (isExposed())
620 m_window->sendRecursiveExposeEvent();
621 } else {
622 // Later configures are probably resizes, so we have to queue them up for a time when we
623 // are not painting to the window.
624 m_window->applyConfigureWhenPossible();
625 }
626}
627
629{
630 if (auto *activation = m_shell->activation()) {
631 if (!m_activationToken.isEmpty()) {
632 activation->activate(m_activationToken, window()->wlSurface());
633 m_activationToken = {};
634 return true;
635 } else if (const auto token = qEnvironmentVariable("XDG_ACTIVATION_TOKEN"); !token.isEmpty()) {
636 activation->activate(token, window()->wlSurface());
637 qunsetenv("XDG_ACTIVATION_TOKEN");
638 return true;
639 } else {
640 const auto focusWindow = QGuiApplication::focusWindow();
641 // At least GNOME requires to request the token in order to get the
642 // focus stealing prevention indication, so requestXdgActivationToken call
643 // is still necessary in that case.
644 const auto wlWindow = focusWindow ? static_cast<QWaylandWindow*>(focusWindow->handle()) : m_window;
645
646 QString appId;
647 if (const auto xdgSurface = qobject_cast<QWaylandXdgSurface *>(wlWindow->shellSurface()))
648 appId = xdgSurface->m_appId;
649
650 if (const auto seat = wlWindow->display()->lastInputDevice()) {
651 const auto tokenProvider = activation->requestXdgActivationToken(
652 wlWindow->display(), wlWindow->wlSurface(), seat->serial(), appId);
653 connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this,
654 [this, tokenProvider](const QString &token) {
655 m_shell->activation()->activate(token, window()->wlSurface());
656 tokenProvider->deleteLater();
657 });
658 return true;
659 }
660 }
661 }
662 return false;
663}
664
666{
667 const Qt::WindowType type = m_window->window()->type();
669 return false;
670
671 if (m_window->window()->property("_q_showWithoutActivating").toBool())
672 return false;
673
674 return requestActivate();
675}
676
678{
679 if (auto *activation = m_shell->activation()) {
680 auto tokenProvider = activation->requestXdgActivationToken(
681 m_shell->m_display, m_window->wlSurface(), serial, m_appId);
682 connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this,
683 [this, tokenProvider](const QString &token) {
684 Q_EMIT m_window->xdgActivationTokenCreated(token);
685 tokenProvider->deleteLater();
686 });
687 } else {
689 }
690}
691
693{
694 if (m_shell->activation()) {
695 m_activationToken = token;
696 } else {
697 qCWarning(lcQpaWayland) << "zxdg_activation_v1 not available";
698 }
699}
700
702{
703 if (m_alertState == enabled)
704 return;
705
706 m_alertState = enabled;
707
708 if (!m_alertState)
709 return;
710
711 auto *activation = m_shell->activation();
712 if (!activation)
713 return;
714
715 const auto tokenProvider = activation->requestXdgActivationToken(
716 m_shell->m_display, m_window->wlSurface(), std::nullopt, m_appId);
717 connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this,
718 [this, tokenProvider](const QString &token) {
719 m_shell->activation()->activate(token, m_window->wlSurface());
720 tokenProvider->deleteLater();
721 });
722}
723
725{
726 if (!m_toplevel || !m_shell->exporter()) {
727 return QString();
728 }
729 if (!m_toplevel->m_exported) {
730 auto *exporterWrapper = static_cast<zxdg_exporter_v2 *>(
731 wl_proxy_create_wrapper(m_shell->exporter()->object()));
732 auto exportQueue = wl_display_create_queue(m_shell->display()->wl_display());
733 wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(exporterWrapper), exportQueue);
734 m_toplevel->m_exported.reset(new QWaylandXdgExportedV2(
735 zxdg_exporter_v2_export_toplevel(exporterWrapper, m_window->wlSurface())));
736 // handle events is sent immediately
737 wl_display_roundtrip_queue(m_shell->display()->wl_display(), exportQueue);
738
739 wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(m_toplevel->m_exported->object()), nullptr);
740 wl_proxy_wrapper_destroy(exporterWrapper);
741 wl_event_queue_destroy(exportQueue);
742 }
743 return m_toplevel->m_exported->handle();
744}
745
747 : m_display(display), m_xdgWmBase(xdgWmBase)
748{
749 display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal, this);
750}
751
753{
754 m_display->removeListener(&QWaylandXdgShell::handleRegistryGlobal, this);
755}
756
757void QWaylandXdgShell::handleRegistryGlobal(void *data, wl_registry *registry, uint id,
758 const QString &interface, uint version)
759{
760 QWaylandXdgShell *xdgShell = static_cast<QWaylandXdgShell *>(data);
762 xdgShell->m_xdgDecorationManager.reset(new QWaylandXdgDecorationManagerV1(registry, id, version));
763
764 if (interface == QLatin1String(QWaylandXdgActivationV1::interface()->name)) {
765 xdgShell->m_xdgActivation.reset(new QWaylandXdgActivationV1(registry, id, version));
766 }
767
768 if (interface == QLatin1String(QWaylandXdgExporterV2::interface()->name)) {
769 xdgShell->m_xdgExporter.reset(new QWaylandXdgExporterV2(registry, id, version));
770 }
771
772 if (interface == QLatin1String(QWaylandXdgDialogWmV1::interface()->name)) {
773 xdgShell->m_xdgDialogWm.reset(new QWaylandXdgDialogWmV1(registry, id, version));
774 }
775}
776
777}
778
780
781#include "moc_qwaylandxdgshell_p.cpp"
IOBluetoothDevice * device
\inmodule QtCore
Definition qbytearray.h:57
QByteArray toLower() const &
Definition qbytearray.h:254
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
\inmodule QtCore
Definition qmargins.h:24
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4323
virtual QPoint mapFromGlobal(const QPoint &pos) const
Translates the global screen coordinate pos to window coordinates using native methods.
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
QSize windowMinimumSize() const
Returns the QWindow minimum size.
virtual QRect geometry() const
Returns the current geometry of a window.
QSize windowMaximumSize() const
Returns the QWindow maximum size.
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr QRect marginsAdded(const QMargins &margins) const noexcept
Returns a rectangle grown by the margins.
Definition qrect.h:448
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:261
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr QSize grownBy(QMargins m) const noexcept
Definition qsize.h:49
constexpr QSize shrunkBy(QMargins m) const noexcept
Definition qsize.h:51
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:124
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
Definition qvariant.h:65
uint toUInt(bool *ok=nullptr) const
Returns the variant as an unsigned int if the variant has userType() \l QMetaType::UInt,...
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
QRect toRect() const
Returns the variant as a QRect if the variant has userType() \l QMetaType::QRect; otherwise returns a...
static const struct wl_interface * interface()
Returns the Wayland interface for the QWaylandXdgDecorationManagerV1.
QWaylandXdgShell()
Constructs a QWaylandXdgShell object.
\qmltype XdgSurface \instantiates QWaylandXdgSurface \inqmlmodule QtWayland.Compositor....
QWaylandXdgSurface()
Constructs a QWaylandXdgSurface.
static void handleLeaveEvent(QWindow *window)
static bool handleCloseEvent(QWindow *window)
static void handleEnterEvent(QWindow *window, const QPointF &local=QPointF(), const QPointF &global=QPointF())
\inmodule QtGui
Definition qwindow.h:63
void removeListener(RegistryListener listener, void *data)
struct wl_display * wl_display() const
virtual void requestXdgActivationToken(quint32 serial)
QWaylandWindow * transientParent() const
QWaylandDisplay * display() const
::wl_surface * wlSurface() const
QRect windowContentGeometry() const
Window geometry as defined by the xdg-shell spec (in wl_surface coordinates) topLeft is where the sha...
QWaylandXdgActivationTokenV1 * requestXdgActivationToken(QWaylandDisplay *display, struct ::wl_surface *surface, std::optional< uint32_t > serial, const QString &app_id)
QWaylandDisplay * display() const
QWaylandXdgActivationV1 * activation() const
QWaylandXdgExporterV2 * exporter() const
std::any surfaceRole() const override
void setWindowGeometry(const QRect &rect) override
void * nativeResource(const QByteArray &resource)
void setTitle(const QString &title) override
void setXdgActivationToken(const QString &token) override
bool handleExpose(const QRegion &) override
void setAlertState(bool enabled) override
bool resize(QWaylandInputDevice *inputDevice, Qt::Edges edges) override
void requestWindowStates(Qt::WindowStates states) override
bool move(QWaylandInputDevice *inputDevice) override
void xdg_surface_configure(uint32_t serial) override
void setWindowFlags(Qt::WindowFlags flags) override
void setAppId(const QString &appId) override
void requestXdgActivationToken(quint32 serial) override
bool showWindowMenu(QWaylandInputDevice *seat) override
rect
[4]
Token token
Definition keywords.cpp:444
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
Definition qcompare.h:63
@ WindowFullScreen
Definition qnamespace.h:255
@ WindowNoState
Definition qnamespace.h:252
@ WindowMinimized
Definition qnamespace.h:253
@ WindowMaximized
Definition qnamespace.h:254
@ WindowActive
Definition qnamespace.h:256
@ NonModal
@ RightEdge
@ TopEdge
@ BottomEdge
@ LeftEdge
WindowType
Definition qnamespace.h:205
@ FramelessWindowHint
Definition qnamespace.h:225
@ ToolTip
Definition qnamespace.h:213
@ Popup
Definition qnamespace.h:211
@ SplashScreen
Definition qnamespace.h:214
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
T qobject_cast(QObject *object)
\variable QObject::staticMetaObject
Definition qobject.h:419
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei width
GLenum type
GLbitfield flags
GLuint name
GLint y
GLuint * states
#define QWINDOWSIZE_MAX
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
QScreen * screen
[1]
Definition main.cpp:29
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
Q_CORE_EXPORT bool qunsetenv(const char *varName)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define Q_EMIT
unsigned int quint32
Definition qtypes.h:50
unsigned int uint
Definition qtypes.h:34
#define leave(x)
#define enabled
QObject::connect nullptr
QString title
[35]
aWidget window() -> setWindowTitle("New Window Title")
[2]