9#include <QtWaylandClient/private/qwaylanddisplay_p.h>
10#include <QtWaylandClient/private/qwaylandwindow_p.h>
11#include <QtWaylandClient/private/qwaylandinputdevice_p.h>
12#include <QtWaylandClient/private/qwaylandscreen_p.h>
13#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
15#include <QtGui/QGuiApplication>
16#include <QtGui/private/qwindow_p.h>
23 :
QtWayland::xdg_toplevel(xdgSurface->get_toplevel())
24 , m_xdgSurface(xdgSurface)
27 if (
auto *decorationManager = m_xdgSurface->m_shell->decorationManager()) {
29 m_decoration = decorationManager->createToplevelDecoration(
object());
31 requestWindowStates(
window->windowStates());
32 requestWindowFlags(
window->flags());
35QWaylandXdgSurface::Toplevel::~Toplevel()
39 m_decoration =
nullptr;
45void QWaylandXdgSurface::Toplevel::applyConfigure()
48 m_normalSize = m_xdgSurface->m_window->windowContentGeometry().size();
51 && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
52 m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window);
55 && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
56 m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);
58 m_xdgSurface->m_window->handleToplevelWindowTilingStatesChanged(m_toplevelStates);
59 m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);
64 if (m_pending.size.width() > 0) {
65 surfaceSize.
setWidth(m_pending.size.width());
68 qCWarning(lcQpaWayland) <<
"Configure event with maximized or fullscreen state contains invalid width:" << m_pending.size.width();
70 int width = m_normalSize.width();
71 if (!m_pending.bounds.isEmpty())
72 width = std::min(
width, m_pending.bounds.width());
77 if (m_pending.size.height() > 0) {
78 surfaceSize.
setHeight(m_pending.size.height());
81 qCWarning(lcQpaWayland) <<
"Configure event with maximized or fullscreen state contains invalid height:" << m_pending.size.height();
83 int height = m_normalSize.height();
84 if (!m_pending.bounds.isEmpty())
91 m_xdgSurface->m_window->resizeFromApplyConfigure(surfaceSize.
grownBy(m_xdgSurface->m_window->windowContentMargins()));
93 m_applied = m_pending;
94 qCDebug(lcQpaWayland) <<
"Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states;
97bool QWaylandXdgSurface::Toplevel::wantsDecorations()
99 if (m_decoration && (m_decoration->pending() == QWaylandXdgToplevelDecorationV1::mode_server_side
100 || !m_decoration->isConfigured()))
106void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure_bounds(int32_t
width, int32_t
height)
111void QWaylandXdgSurface::Toplevel::xdg_toplevel_configure(int32_t
width, int32_t
height, wl_array *
states)
115 auto *xdgStates =
static_cast<uint32_t *
>(
states->data);
116 size_t numStates =
states->size /
sizeof(uint32_t);
119 m_toplevelStates = QWaylandWindow::WindowNoState;
121 for (
size_t i = 0;
i < numStates;
i++) {
122 switch (xdgStates[
i]) {
123 case XDG_TOPLEVEL_STATE_ACTIVATED:
126 case XDG_TOPLEVEL_STATE_MAXIMIZED:
129 case XDG_TOPLEVEL_STATE_FULLSCREEN:
132 case XDG_TOPLEVEL_STATE_TILED_LEFT:
133 m_toplevelStates |= QWaylandWindow::WindowTiledLeft;
135 case XDG_TOPLEVEL_STATE_TILED_RIGHT:
136 m_toplevelStates |= QWaylandWindow::WindowTiledRight;
138 case XDG_TOPLEVEL_STATE_TILED_TOP:
139 m_toplevelStates |= QWaylandWindow::WindowTiledTop;
141 case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
142 m_toplevelStates |= QWaylandWindow::WindowTiledBottom;
148 qCDebug(lcQpaWayland) <<
"Received xdg_toplevel.configure with" << m_pending.size
149 <<
"and" << m_pending.states;
152void QWaylandXdgSurface::Toplevel::xdg_toplevel_close()
154 m_xdgSurface->m_window->window()->close();
157void QWaylandXdgSurface::Toplevel::requestWindowFlags(Qt::WindowFlags
flags)
162 m_decoration =
nullptr;
164 m_decoration->unsetMode();
169void QWaylandXdgSurface::Toplevel::requestWindowStates(Qt::WindowStates
states)
172 Qt::WindowStates changedStates = m_applied.states ^
states;
183 auto screen = m_xdgSurface->window()->waylandScreen();
185 set_fullscreen(
screen->output());
198QtWayland::xdg_toplevel::resize_edge QWaylandXdgSurface::Toplevel::convertToResizeEdges(Qt::Edges edges)
200 return static_cast<enum resize_edge
>(
203 | ((edges &
Qt::
LeftEdge) ? resize_edge_left : 0)
204 | ((edges &
Qt::
RightEdge) ? resize_edge_right : 0));
208 QtWayland::xdg_positioner *positioner)
209 : m_xdgSurface(xdgSurface)
214 init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() :
nullptr,
218QWaylandXdgSurface::Popup::~Popup()
224 auto *shell = m_xdgSurface->m_shell;
225 Q_ASSERT(shell->m_topmostGrabbingPopup ==
this);
226 shell->m_topmostGrabbingPopup = m_parentXdgSurface ? m_parentXdgSurface->m_popup :
nullptr;
231 if (m_xdgSurface && m_xdgSurface->window())
232 leave = m_xdgSurface->window()->window();
240void QWaylandXdgSurface::Popup::applyConfigure()
242 if (m_pendingGeometry.isValid()) {
243 QRect geometryWithMargins = m_pendingGeometry.
marginsAdded(m_xdgSurface->m_window->windowContentMargins());
244 QMargins parentMargins = m_parent->windowContentMargins() - m_parent->clientSideMargins();
245 QRect globalGeometry = geometryWithMargins.
translated(m_parent->geometry().topLeft() +
QPoint(parentMargins.
left(), parentMargins.
top()));
246 m_xdgSurface->setGeometryFromApplyConfigure(globalGeometry.
topLeft(), globalGeometry.
size());
248 resetConfiguration();
251void QWaylandXdgSurface::Popup::resetConfiguration()
253 m_pendingGeometry =
QRect();
256void QWaylandXdgSurface::Popup::grab(QWaylandInputDevice *seat,
uint serial)
258 m_xdgSurface->m_shell->m_topmostGrabbingPopup =
this;
259 xdg_popup::grab(seat->wl_seat(), serial);
263void QWaylandXdgSurface::Popup::xdg_popup_configure(int32_t
x, int32_t
y, int32_t
width, int32_t
height)
268void QWaylandXdgSurface::Popup::xdg_popup_popup_done()
270 m_xdgSurface->m_window->window()->close();
275 , xdg_surface(surface)
284 setPopup(transientParent);
286 setGrabPopup(transientParent,
display->lastInputDevice(),
display->lastInputSerial());
289 if (transientParent) {
290 auto parentXdgSurface = qobject_cast<QWaylandXdgSurface *>(transientParent->shellSurface());
291 if (parentXdgSurface)
292 m_toplevel->set_parent(parentXdgSurface->m_toplevel->object());
302 m_toplevel =
nullptr;
313 if (!m_toplevel || !m_toplevel->isInitialized())
316 auto resizeEdges = Toplevel::convertToResizeEdges(edges);
317 m_toplevel->resize(inputDevice->
wl_seat(), inputDevice->
serial(), resizeEdges);
323 if (m_toplevel && m_toplevel->isInitialized()) {
324 m_toplevel->move(inputDevice->
wl_seat(), inputDevice->
serial());
332 if (m_toplevel && m_toplevel->isInitialized()) {
343 m_toplevel->set_title(
title);
349 m_toplevel->set_app_id(appId);
357 m_toplevel->requestWindowFlags(
flags);
362 return m_configured || m_pendingConfigureSerial;
368 m_exposeRegion = region;
377 if (m_pendingConfigureSerial == m_appliedConfigureSerial)
381 m_toplevel->applyConfigure();
383 m_popup->applyConfigure();
384 m_appliedConfigureSerial = m_pendingConfigureSerial;
387 ack_configure(m_appliedConfigureSerial);
392 return m_toplevel && m_toplevel->wantsDecorations();
399 if (m_toplevel && m_window)
410 if (m_toplevel && m_window) {
421 if (minWidth > maxWidth || minHeight > maxHeight)
424 m_toplevel->set_min_size(minWidth, minHeight);
425 m_toplevel->set_max_size(maxWidth, maxHeight);
432 if (lowerCaseResource ==
"xdg_surface")
434 else if (lowerCaseResource ==
"xdg_toplevel" && m_toplevel)
435 return m_toplevel->object();
436 else if (lowerCaseResource ==
"xdg_popup" && m_popup)
437 return m_popup->object();
444 return m_toplevel->object();
446 return m_popup->object();
453 m_toplevel->requestWindowStates(
states);
455 qCDebug(lcQpaWayland) <<
"Ignoring window states requested by non-toplevel zxdg_surface_v6.";
458void QWaylandXdgSurface::setToplevel()
461 m_toplevel =
new Toplevel(
this);
464void QWaylandXdgSurface::setPopup(QWaylandWindow *
parent)
468 auto positioner =
new QtWayland::xdg_positioner(m_shell->m_xdgWmBase->create_positioner());
474 transientPos +=
QPoint(windowMargins.
left(), windowMargins.
top());
475 transientPos -=
parent->geometry().topLeft();
476 transientPos -=
QPoint(parentMargins.
left(), parentMargins.
top());
477 positioner->set_anchor_rect(transientPos.
x(), transientPos.
y(), 1, 1);
478 positioner->set_anchor(QtWayland::xdg_positioner::anchor_top_left);
479 positioner->set_gravity(QtWayland::xdg_positioner::gravity_bottom_right);
480 positioner->set_size(windowGeometry.
width(), windowGeometry.
height());
481 positioner->set_constraint_adjustment(QtWayland::xdg_positioner::constraint_adjustment_slide_x
482 | QtWayland::xdg_positioner::constraint_adjustment_slide_y);
483 m_popup =
new Popup(
this,
parent, positioner);
484 positioner->destroy();
489void QWaylandXdgSurface::setGrabPopup(QWaylandWindow *
parent, QWaylandInputDevice *
device,
int serial)
491 auto parentXdgSurface = qobject_cast<QWaylandXdgSurface *>(
parent->shellSurface());
492 auto *
top = m_shell->m_topmostGrabbingPopup;
494 if (
top &&
top->m_xdgSurface != parentXdgSurface) {
495 qCWarning(lcQpaWayland) <<
"setGrabPopup called with a parent," << parentXdgSurface
496 <<
"which does not match the current topmost grabbing popup,"
497 <<
top->m_xdgSurface <<
"According to the xdg-shell protocol, this"
498 <<
"is not allowed. The wayland QPA plugin is currently handling"
499 <<
"it by setting the parent to the topmost grabbing popup."
500 <<
"Note, however, that this may cause positioning errors and"
501 <<
"popups closing unxpectedly because xdg-shell mandate that child"
502 <<
"popups close before parents";
506 m_popup->grab(
device, serial);
513 if (current !=
leave)
519 if (m_popup && m_popup->m_xdgSurface && m_popup->m_xdgSurface->window())
520 enter = m_popup->m_xdgSurface->window()->window();
528 m_pendingConfigureSerial = serial;
539 if (!m_exposeRegion.
isEmpty()) {
547 if (
auto *activation = m_shell->
activation()) {
548 if (!m_activationToken.
isEmpty()) {
550 m_activationToken = {};
561 const auto wlWindow = focusWindow ?
static_cast<QWaylandWindow*
>(focusWindow->handle()) : m_window;
562 if (
const auto xdgSurface = qobject_cast<QWaylandXdgSurface *>(wlWindow->shellSurface())) {
563 if (
const auto seat = wlWindow->display()->lastInputDevice()) {
565 wlWindow->display(), wlWindow->wlSurface(), seat->serial(), xdgSurface->m_appId);
569 tokenProvider->deleteLater();
581 if (
auto *activation = m_shell->
activation()) {
582 auto tokenProvider = activation->requestXdgActivationToken(
583 m_shell->m_display, m_window->
wlSurface(), serial, m_appId);
587 tokenProvider->deleteLater();
597 m_activationToken =
token;
599 qCWarning(lcQpaWayland) <<
"zxdg_activation_v1 not available";
618 m_shell->m_display, m_window->
wlSurface(), std::nullopt, m_appId);
622 tokenProvider->deleteLater();
628 if (!m_toplevel || !m_shell->
exporter()) {
631 if (!m_toplevel->m_exported) {
636 return m_toplevel->m_exported->handle();
640 : m_display(
display), m_xdgWmBase(xdgWmBase)
642 display->addRegistryListener(&QWaylandXdgShell::handleRegistryGlobal,
this);
647 m_display->
removeListener(&QWaylandXdgShell::handleRegistryGlobal,
this);
650void QWaylandXdgShell::handleRegistryGlobal(
void *
data, wl_registry *registry,
uint id,
662 xdgShell->m_xdgExporter.reset(
new QWaylandXdgExporterV2(registry,
id, version));
670#include "moc_qwaylandxdgshell_p.cpp"
IOBluetoothDevice * device
QByteArray toLower() const &
static QPoint pos()
Returns the position of the cursor (hot spot) of the primary screen in global screen coordinates.
static QWindow * topLevelAt(const QPoint &pos)
Returns the top level window at the given position pos, if any.
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
constexpr int left() const noexcept
Returns the left margin.
constexpr int top() const noexcept
Returns the top margin.
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
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
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
\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 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
Returns true if the string has no characters; otherwise returns false.
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 void handleEnterEvent(QWindow *window, const QPointF &local=QPointF(), const QPointF &global=QPointF())
void removeListener(RegistryListener listener, void *data)
virtual void requestXdgActivationToken(quint32 serial)
QWaylandWindow * window()
struct wl_surface * wlSurface()
QMargins windowContentMargins() const
QMargins clientSideMargins() const
::wl_surface * wlSurface()
void commit(QWaylandBuffer *buffer, const QRegion &damage)
QWaylandWindow * transientParent() const
void applyConfigureWhenPossible()
QWaylandDisplay * display() const
void requestXdgActivationToken(uint serial) override
QRect windowContentGeometry() const
Window geometry as defined by the xdg-shell spec (in wl_surface coordinates) topLeft is where the sha...
void handleExpose(const QRegion ®ion)
void done(const QString &token)
QWaylandXdgActivationTokenV1 * requestXdgActivationToken(QWaylandDisplay *display, struct ::wl_surface *surface, std::optional< uint32_t > serial, const QString &app_id)
QWaylandXdgExportedV2 * exportToplevel(wl_surface *surface)
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
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
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
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)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent