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>
18#include <QtGui/QGuiApplication>
19#include <QtGui/private/qwindow_p.h>
26 :
QtWayland::xdg_toplevel(xdgSurface->get_toplevel())
27 , m_xdgSurface(xdgSurface)
30 if (
auto *decorationManager = m_xdgSurface->m_shell->decorationManager()) {
32 m_decoration = decorationManager->createToplevelDecoration(
object());
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());
41 m_xdgDialog.reset(m_xdgSurface->m_shell->m_xdgDialogWm->getDialog(
object()));
42 m_xdgDialog->set_modal();
48QWaylandXdgSurface::Toplevel::~Toplevel()
52 m_decoration =
nullptr;
58void QWaylandXdgSurface::Toplevel::applyConfigure()
61 m_normalSize = m_xdgSurface->m_window->windowContentGeometry().size();
64 && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
65 m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window);
68 && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
69 m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);
71 m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates);
72 m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);
77 if (m_pending.size.width() > 0) {
78 surfaceSize.
setWidth(m_pending.size.width());
81 qCWarning(lcQpaWayland) <<
"Configure event with maximized or fullscreen state contains invalid width:" << m_pending.size.width();
83 int width = m_normalSize.width();
84 if (!m_pending.bounds.isEmpty())
85 width = std::min(
width, m_pending.bounds.width());
90 if (m_pending.size.height() > 0) {
91 surfaceSize.
setHeight(m_pending.size.height());
94 qCWarning(lcQpaWayland) <<
"Configure event with maximized or fullscreen state contains invalid height:" << m_pending.size.height();
96 int height = m_normalSize.height();
97 if (!m_pending.bounds.isEmpty())
103 m_applied = m_pending;
106 m_xdgSurface->m_window->resizeFromApplyConfigure(surfaceSize.
grownBy(m_xdgSurface->m_window->windowContentMargins()));
108 qCDebug(lcQpaWayland) <<
"Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states;
111bool QWaylandXdgSurface::Toplevel::wantsDecorations()
113 if (m_decoration && (m_decoration->pending() == QWaylandXdgToplevelDecorationV1::mode_server_side
114 || !m_decoration->isConfigured()))
120void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure_bounds(int32_t
width, int32_t
height)
125void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t
width, int32_t
height, wl_array *
states)
129 auto *xdgStates =
static_cast<uint32_t *
>(
states->data);
130 size_t numStates =
states->size /
sizeof(uint32_t);
132 m_pending.suspended =
false;
134 m_toplevelStates = QWaylandWindow::WindowNoState;
136 for (
size_t i = 0;
i < numStates;
i++) {
137 switch (xdgStates[
i]) {
138 case XDG_TOPLEVEL_STATE_ACTIVATED:
141 case XDG_TOPLEVEL_STATE_MAXIMIZED:
144 case XDG_TOPLEVEL_STATE_FULLSCREEN:
147 case XDG_TOPLEVEL_STATE_TILED_LEFT:
148 m_toplevelStates |= QWaylandWindow::WindowTiledLeft;
150 case XDG_TOPLEVEL_STATE_TILED_RIGHT:
151 m_toplevelStates |= QWaylandWindow::WindowTiledRight;
153 case XDG_TOPLEVEL_STATE_TILED_TOP:
154 m_toplevelStates |= QWaylandWindow::WindowTiledTop;
156 case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
157 m_toplevelStates |= QWaylandWindow::WindowTiledBottom;
159 case XDG_TOPLEVEL_STATE_SUSPENDED:
160 m_pending.suspended =
true;
166 qCDebug(lcQpaWayland) <<
"Received xdg_toplevel.configure with" << m_pending.size
167 <<
"and" << m_pending.states;
170void QWaylandXdgSurface::Toplevel::xdg_toplevel_close()
175void QWaylandXdgSurface::Toplevel::requestWindowFlags(Qt::WindowFlags
flags)
180 m_decoration =
nullptr;
182 m_decoration->unsetMode();
187void QWaylandXdgSurface::Toplevel::requestWindowStates(Qt::WindowStates
states)
190 Qt::WindowStates changedStates = m_applied.states ^
states;
210 auto screen = m_xdgSurface->window()->waylandScreen();
212 set_fullscreen(
screen->output());
221QtWayland::xdg_toplevel::resize_edge QWaylandXdgSurface::Toplevel::convertToResizeEdges(Qt::Edges edges)
223 return static_cast<enum resize_edge
>(
226 | ((edges &
Qt::
LeftEdge) ? resize_edge_left : 0)
227 | ((edges &
Qt::
RightEdge) ? resize_edge_right : 0));
230QWaylandXdgSurface::Popup::Popup(
QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent,
231 QtWayland::xdg_positioner *positioner)
232 : m_xdgSurface(xdgSurface)
237 init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() :
nullptr,
241QWaylandXdgSurface::Popup::~Popup()
251 if (m_xdgSurface && m_xdgSurface->window())
252 leave = m_xdgSurface->window()->window();
256 if (m_parentXdgSurface && m_parentXdgSurface->window()) {
257 enter = m_parentXdgSurface->window()->window();
258 const auto pos = m_xdgSurface->window()->display()->waylandCursor()->pos();
264void QWaylandXdgSurface::Popup::applyConfigure()
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());
272 resetConfiguration();
275void QWaylandXdgSurface::Popup::resetConfiguration()
277 m_pendingGeometry =
QRect();
280void QWaylandXdgSurface::Popup::grab(QWaylandInputDevice *seat,
uint serial)
282 xdg_popup::grab(seat->wl_seat(), serial);
286void QWaylandXdgSurface::Popup::xdg_popup_configure(int32_t
x, int32_t
y, int32_t
width, int32_t
height)
291void QWaylandXdgSurface::Popup::xdg_popup_popup_done()
298 , xdg_surface(surface)
307 setPopup(transientParent);
309 setGrabPopup(transientParent,
display->lastInputDevice(),
display->lastInputSerial());
320 m_toplevel =
nullptr;
331 if (!m_toplevel || !m_toplevel->isInitialized())
334 auto resizeEdges = Toplevel::convertToResizeEdges(edges);
335 m_toplevel->resize(inputDevice->wl_seat(), inputDevice->serial(), resizeEdges);
341 if (m_toplevel && m_toplevel->isInitialized()) {
342 m_toplevel->move(inputDevice->wl_seat(), inputDevice->serial());
350 if (m_toplevel && m_toplevel->isInitialized()) {
361 m_toplevel->set_title(
title);
367 m_toplevel->set_app_id(appId);
375 m_toplevel->requestWindowFlags(
flags);
380 if (m_toplevel && m_toplevel->m_applied.suspended)
383 return m_configured || m_pendingConfigureSerial;
397 if (m_pendingConfigureSerial == m_appliedConfigureSerial)
401 m_toplevel->applyConfigure();
403 m_popup->applyConfigure();
404 m_appliedConfigureSerial = m_pendingConfigureSerial;
407 ack_configure(m_appliedConfigureSerial);
412 return m_toplevel && m_toplevel->wantsDecorations();
428 if (m_toplevel && m_window) {
432 const int minWidth =
qMax(0, minSize.
width());
433 const int minHeight =
qMax(0, minSize.
height());
438 if (minWidth > maxWidth || minHeight > maxHeight)
446 m_toplevel->set_min_size(minWidth, minHeight);
447 m_toplevel->set_max_size(maxWidth, maxHeight);
454 if (lowerCaseResource ==
"xdg_surface")
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();
466 return m_toplevel->object();
468 return m_popup->object();
475 m_toplevel->requestWindowStates(
states);
477 qCDebug(lcQpaWayland) <<
"Ignoring window states requested by non-toplevel zxdg_surface_v6.";
480void QWaylandXdgSurface::setToplevel()
483 m_toplevel =
new Toplevel(
this);
486void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
490 auto positioner =
new QtWayland::xdg_positioner(m_shell->m_xdgWmBase->create_positioner());
498 if (!placementAnchor.isValid()) {
501 placementAnchor.translate(windowMargins.left(), windowMargins.top());
502 placementAnchor.translate(-parentMargins.left(), -parentMargins.top());
504 uint32_t anchor = QtWayland::xdg_positioner::anchor_top_right;
506 if (anchorVariant.isValid()) {
507 switch (anchorVariant.value<Qt::Edges>()) {
509 anchor =
QtWayland::xdg_positioner::anchor_none;
512 anchor = QtWayland::xdg_positioner::anchor_top;
515 anchor = QtWayland::xdg_positioner::anchor_top_right;
518 anchor = QtWayland::xdg_positioner::anchor_right;
521 anchor = QtWayland::xdg_positioner::anchor_bottom_right;
524 anchor = QtWayland::xdg_positioner::anchor_bottom;
527 anchor = QtWayland::xdg_positioner::anchor_bottom_left;
530 anchor = QtWayland::xdg_positioner::anchor_left;
533 anchor = QtWayland::xdg_positioner::anchor_top_left;
538 uint32_t gravity = QtWayland::xdg_positioner::gravity_bottom_right;
540 if (popupGravityVariant.isValid()) {
541 switch (popupGravityVariant.value<Qt::Edges>()) {
543 gravity =
QtWayland::xdg_positioner::gravity_none;
546 gravity = QtWayland::xdg_positioner::gravity_top;
549 gravity = QtWayland::xdg_positioner::gravity_top_right;
552 gravity = QtWayland::xdg_positioner::gravity_right;
555 gravity = QtWayland::xdg_positioner::gravity_bottom_right;
558 gravity = QtWayland::xdg_positioner::gravity_bottom;
561 gravity = QtWayland::xdg_positioner::gravity_bottom_left;
564 gravity = QtWayland::xdg_positioner::gravity_left;
567 gravity = QtWayland::xdg_positioner::gravity_top_left;
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();
578 positioner->set_anchor_rect(placementAnchor.x(),
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);
587 positioner->destroy();
592void QWaylandXdgSurface::setGrabPopup(QWaylandWindow *parent, QWaylandInputDevice *
device,
int serial)
595 m_popup->grab(
device, serial);
604 if (m_popup && m_popup->m_xdgSurface && m_popup->m_xdgSurface->
window())
608 const auto pos = m_popup->m_xdgSurface->
window()->
display()->waylandCursor()->pos();
615 m_pendingConfigureSerial = serial;
630 if (
auto *activation = m_shell->
activation()) {
631 if (!m_activationToken.
isEmpty()) {
633 m_activationToken = {};
644 const auto wlWindow = focusWindow ?
static_cast<QWaylandWindow*
>(focusWindow->handle()) : m_window;
647 if (
const auto xdgSurface = qobject_cast<QWaylandXdgSurface *>(wlWindow->shellSurface()))
648 appId = xdgSurface->m_appId;
650 if (
const auto seat = wlWindow->display()->lastInputDevice()) {
651 const auto tokenProvider = activation->requestXdgActivationToken(
652 wlWindow->display(), wlWindow->wlSurface(), seat->serial(), appId);
656 tokenProvider->deleteLater();
679 if (
auto *activation = m_shell->
activation()) {
680 auto tokenProvider = activation->requestXdgActivationToken(
681 m_shell->m_display, m_window->
wlSurface(), serial, m_appId);
685 tokenProvider->deleteLater();
695 m_activationToken =
token;
697 qCWarning(lcQpaWayland) <<
"zxdg_activation_v1 not available";
716 m_shell->m_display, m_window->
wlSurface(), std::nullopt, m_appId);
720 tokenProvider->deleteLater();
726 if (!m_toplevel || !m_shell->
exporter()) {
729 if (!m_toplevel->m_exported) {
730 auto *exporterWrapper =
static_cast<zxdg_exporter_v2 *
>(
731 wl_proxy_create_wrapper(m_shell->
exporter()->object()));
733 wl_proxy_set_queue(
reinterpret_cast<wl_proxy *
>(exporterWrapper), exportQueue);
735 zxdg_exporter_v2_export_toplevel(exporterWrapper, m_window->
wlSurface())));
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);
743 return m_toplevel->m_exported->handle();
747 : m_display(
display), m_xdgWmBase(xdgWmBase)
749 display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal,
this);
754 m_display->
removeListener(&QWaylandXdgShell::handleRegistryGlobal,
this);
757void QWaylandXdgShell::handleRegistryGlobal(
void *
data, wl_registry *registry,
uint id,
769 xdgShell->m_xdgExporter.reset(
new QWaylandXdgExporterV2(registry,
id, version));
773 xdgShell->m_xdgDialogWm.reset(
new QWaylandXdgDialogWmV1(registry,
id, version));
781#include "moc_qwaylandxdgshell_p.cpp"
IOBluetoothDevice * device
QByteArray toLower() const &
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
QObject * parent() const
Returns a pointer to the parent object.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
QVariant property(const char *name) const
Returns the value of the object's name property.
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
constexpr QRect marginsAdded(const QMargins &margins) const noexcept
Returns a rectangle grown by the margins.
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr QSize size() const noexcept
Returns the size of the rectangle.
constexpr int width() const noexcept
Returns the width of the rectangle.
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,...
The QRegion class specifies a clip region for a painter.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
constexpr int height() const noexcept
Returns the height.
constexpr QSize grownBy(QMargins m) const noexcept
constexpr QSize shrunkBy(QMargins m) const noexcept
constexpr int width() const noexcept
Returns the width.
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
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())
void removeListener(RegistryListener listener, void *data)
struct wl_display * wl_display() const
virtual void requestXdgActivationToken(quint32 serial)
QWaylandWindow * window()
struct wl_surface * wlSurface()
QMargins windowContentMargins() const
QMargins clientSideMargins() const
QWaylandWindow * transientParent() const
void applyConfigureWhenPossible()
QWaylandDisplay * display() const
::wl_surface * wlSurface() const
void sendRecursiveExposeEvent()
QRect windowContentGeometry() const
Window geometry as defined by the xdg-shell spec (in wl_surface coordinates) topLeft is where the sha...
void done(const QString &token)
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
QString externWindowHandle() override
bool requestActivate() override
void setWindowGeometry(const QRect &rect) override
void * nativeResource(const QByteArray &resource)
bool wantsDecorations() const override
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 isExposed() const override
void propagateSizeHints() override
bool move(QWaylandInputDevice *inputDevice) override
void applyConfigure() override
~QWaylandXdgSurface() override
void xdg_surface_configure(uint32_t serial) override
bool requestActivateOnShow() override
void setWindowFlags(Qt::WindowFlags flags) override
void setAppId(const QString &appId) override
void requestXdgActivationToken(quint32 serial) override
bool showWindowMenu(QWaylandInputDevice *seat) override
struct wl_display * display
Combined button and popup list for selecting options.
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)
T qobject_cast(QObject *object)
\variable QObject::staticMetaObject
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
QLatin1StringView QLatin1String
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)