diff options
Diffstat (limited to 'src/compositor/extensions/qwaylandxdgshell.cpp')
-rw-r--r-- | src/compositor/extensions/qwaylandxdgshell.cpp | 217 |
1 files changed, 173 insertions, 44 deletions
diff --git a/src/compositor/extensions/qwaylandxdgshell.cpp b/src/compositor/extensions/qwaylandxdgshell.cpp index b5346036a..ab2c60ecc 100644 --- a/src/compositor/extensions/qwaylandxdgshell.cpp +++ b/src/compositor/extensions/qwaylandxdgshell.cpp @@ -36,13 +36,16 @@ #include "qwaylandxdgshell.h" #include "qwaylandxdgshell_p.h" + +#ifdef QT_WAYLAND_COMPOSITOR_QUICK #include "qwaylandxdgshellintegration_p.h" +#endif #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandSurface> #include <QtWaylandCompositor/QWaylandSurfaceRole> #include <QtWaylandCompositor/QWaylandResource> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include <QtCore/QObject> @@ -147,11 +150,11 @@ void QWaylandXdgShellPrivate::xdg_shell_get_xdg_surface(Resource *resource, uint QWaylandResource xdgSurfaceResource(wl_resource_create(resource->client(), &xdg_surface_interface, wl_resource_get_version(resource->handle), id)); - emit q->createXdgSurface(surface, xdgSurfaceResource); + emit q->xdgSurfaceRequested(surface, xdgSurfaceResource); QWaylandXdgSurface *xdgSurface = QWaylandXdgSurface::fromResource(xdgSurfaceResource.resource()); if (!xdgSurface) { - // A QWaylandXdgSurface was not created in response to the createXdgSurface signal, so we + // A QWaylandXdgSurface was not created in response to the xdgSurfaceRequested signal, so we // create one as fallback here instead. xdgSurface = new QWaylandXdgSurface(q, surface, xdgSurfaceResource); } @@ -171,7 +174,7 @@ void QWaylandXdgShellPrivate::xdg_shell_use_unstable_version(Resource *resource, void QWaylandXdgShellPrivate::xdg_shell_get_xdg_popup(Resource *resource, uint32_t id, wl_resource *surface_res, wl_resource *parent, - wl_resource *seat, uint32_t serial, + wl_resource *seatResource, uint32_t serial, int32_t x, int32_t y) { Q_UNUSED(serial); @@ -191,15 +194,15 @@ void QWaylandXdgShellPrivate::xdg_shell_get_xdg_popup(Resource *resource, uint32 QWaylandResource xdgPopupResource (wl_resource_create(resource->client(), &xdg_popup_interface, wl_resource_get_version(resource->handle), id)); - QWaylandInputDevice *inputDevice = QWaylandInputDevice::fromSeatResource(seat); + QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource); QPoint position(x, y); - emit q->createXdgPopup(surface, parentSurface, inputDevice, position, xdgPopupResource); + emit q->xdgPopupRequested(surface, parentSurface, seat, position, xdgPopupResource); QWaylandXdgPopup *xdgPopup = QWaylandXdgPopup::fromResource(xdgPopupResource.resource()); if (!xdgPopup) { - // A QWaylandXdgPopup was not created in response to the createXdgPopup signal, so we + // A QWaylandXdgPopup was not created in response to the xdgPopupRequested signal, so we // create one as fallback here instead. - xdgPopup = new QWaylandXdgPopup(q, surface, parentSurface, xdgPopupResource); + xdgPopup = new QWaylandXdgPopup(q, surface, parentSurface, position, xdgPopupResource); } registerXdgPopup(xdgPopup); @@ -221,6 +224,7 @@ QWaylandXdgSurfacePrivate::QWaylandXdgSurfacePrivate() , xdg_surface() , m_surface(nullptr) , m_parentSurface(nullptr) + , m_windowType(UnknownWindowType) , m_unsetWindowGeometry(true) , m_lastAckedConfigure({{}, QSize(0, 0), 0}) { @@ -246,6 +250,27 @@ void QWaylandXdgSurfacePrivate::handleFocusReceived() q->sendConfigure(current.size, current.states); } +QRect QWaylandXdgSurfacePrivate::calculateFallbackWindowGeometry() const +{ + // TODO: The unset window geometry should include subsurfaces as well, so this solution + // won't work too well on those kinds of clients. + return QRect(QPoint(0, 0), m_surface->size() / m_surface->bufferScale()); +} + +void QWaylandXdgSurfacePrivate::updateFallbackWindowGeometry() +{ + Q_Q(QWaylandXdgSurface); + if (!m_unsetWindowGeometry) + return; + + const QRect unsetGeometry = calculateFallbackWindowGeometry(); + if (unsetGeometry == m_windowGeometry) + return; + + m_windowGeometry = unsetGeometry; + emit q->windowGeometryChanged(); +} + void QWaylandXdgSurfacePrivate::xdg_surface_destroy_resource(Resource *resource) { Q_UNUSED(resource); @@ -265,7 +290,7 @@ void QWaylandXdgSurfacePrivate::xdg_surface_move(Resource *resource, wl_resource Q_UNUSED(serial); Q_Q(QWaylandXdgSurface); - QWaylandInputDevice *input_device = QWaylandInputDevice::fromSeatResource(seat); + QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(seat); emit q->startMove(input_device); } @@ -276,7 +301,7 @@ void QWaylandXdgSurfacePrivate::xdg_surface_resize(Resource *resource, wl_resour Q_UNUSED(serial); Q_Q(QWaylandXdgSurface); - QWaylandInputDevice *input_device = QWaylandInputDevice::fromSeatResource(seat); + QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(seat); emit q->startResize(input_device, QWaylandXdgSurface::ResizeEdge(edges)); } @@ -325,12 +350,22 @@ void QWaylandXdgSurfacePrivate::xdg_surface_set_parent(Resource *resource, wl_re QWaylandXdgSurfacePrivate::Resource::fromResource(parent)->xdg_surface_object)->q_func(); } - if (m_parentSurface == parentSurface) - return; - Q_Q(QWaylandXdgSurface); - m_parentSurface = parentSurface; - emit q->parentSurfaceChanged(); + + if (m_parentSurface != parentSurface) { + m_parentSurface = parentSurface; + emit q->parentSurfaceChanged(); + } + + if (m_parentSurface && m_windowType != TransientWindowType) { + // There's a parent now, which means the surface is transient + m_windowType = TransientWindowType; + emit q->setTransient(); + } else if (!m_parentSurface && m_windowType != TopLevelWindowType) { + // When the surface has no parent it is toplevel + m_windowType = TopLevelWindowType; + emit q->setTopLevel(); + } } void QWaylandXdgSurfacePrivate::xdg_surface_set_app_id(Resource *resource, const QString &app_id) @@ -343,15 +378,15 @@ void QWaylandXdgSurfacePrivate::xdg_surface_set_app_id(Resource *resource, const emit q->appIdChanged(); } -void QWaylandXdgSurfacePrivate::xdg_surface_show_window_menu(Resource *resource, wl_resource *seat, +void QWaylandXdgSurfacePrivate::xdg_surface_show_window_menu(Resource *resource, wl_resource *seatResource, uint32_t serial, int32_t x, int32_t y) { Q_UNUSED(resource); Q_UNUSED(serial); QPoint position(x, y); - auto inputDevice = QWaylandInputDevice::fromSeatResource(seat); + auto seat = QWaylandSeat::fromSeatResource(seatResource); Q_Q(QWaylandXdgSurface); - emit q->showWindowMenu(inputDevice, position); + emit q->showWindowMenu(seat, position); } void QWaylandXdgSurfacePrivate::xdg_surface_ack_configure(Resource *resource, uint32_t serial) @@ -490,10 +525,10 @@ void QWaylandXdgShell::initialize() } d->init(compositor->display(), 1); - handleDefaultInputDeviceChanged(compositor->defaultInputDevice(), nullptr); + handleSeatChanged(compositor->defaultSeat(), nullptr); - connect(compositor, &QWaylandCompositor::defaultInputDeviceChanged, - this, &QWaylandXdgShell::handleDefaultInputDeviceChanged); + connect(compositor, &QWaylandCompositor::defaultSeatChanged, + this, &QWaylandXdgShell::handleSeatChanged); } /*! @@ -548,15 +583,15 @@ void QWaylandXdgShell::closeAllPopups() } } -void QWaylandXdgShell::handleDefaultInputDeviceChanged(QWaylandInputDevice *newDevice, QWaylandInputDevice *oldDevice) +void QWaylandXdgShell::handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat) { - if (oldDevice != nullptr) { - disconnect(oldDevice, &QWaylandInputDevice::keyboardFocusChanged, + if (oldSeat != nullptr) { + disconnect(oldSeat, &QWaylandSeat::keyboardFocusChanged, this, &QWaylandXdgShell::handleFocusChanged); } - if (newDevice != nullptr) { - connect(newDevice, &QWaylandInputDevice::keyboardFocusChanged, + if (newSeat != nullptr) { + connect(newSeat, &QWaylandSeat::keyboardFocusChanged, this, &QWaylandXdgShell::handleFocusChanged); } } @@ -590,6 +625,20 @@ void QWaylandXdgShell::handleFocusChanged(QWaylandSurface *newSurface, QWaylandS */ /*! + * \qmlsignal QtWaylandCompositor::XdgSurface::setTopLevel() + * + * This signal is emitted when the parent surface is unset, effectively + * making the window top level. + */ + +/*! + * \qmlsignal QtWaylandCompositor::XdgSurface::setTransient() + * + * This signal is emitted when the parent surface is set, effectively + * making the window transient. + */ + +/*! * Constructs a QWaylandXdgSurface. */ QWaylandXdgSurface::QWaylandXdgSurface() @@ -625,8 +674,10 @@ void QWaylandXdgSurface::initialize(QWaylandXdgShell *xdgShell, QWaylandSurface d->m_surface = surface; d->init(resource.resource()); setExtensionContainer(surface); - d->m_windowGeometry = QRect(QPoint(0,0), surface->size()); + d->m_windowGeometry = d->calculateFallbackWindowGeometry(); connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandXdgSurface::handleSurfaceSizeChanged); + connect(surface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandXdgSurface::handleBufferScaleChanged); + emit shellChanged(); emit surfaceChanged(); emit windowGeometryChanged(); QWaylandCompositorExtension::initialize(); @@ -652,12 +703,30 @@ QList<int> QWaylandXdgSurface::statesAsInts() const void QWaylandXdgSurface::handleSurfaceSizeChanged() { Q_D(QWaylandXdgSurface); - if (d->m_unsetWindowGeometry && d->m_windowGeometry.size() != surface()->size()) { - // TODO: The unset window geometry should include subsurfaces as well, so this solution - // won't work too well on those kinds of clients. - d->m_windowGeometry.setSize(surface()->size()); - emit windowGeometryChanged(); - } + d->updateFallbackWindowGeometry(); +} + +void QWaylandXdgSurface::handleBufferScaleChanged() +{ + Q_D(QWaylandXdgSurface); + d->updateFallbackWindowGeometry(); +} + +/*! + * \qmlproperty object QtWaylandCompositor::XdgSurface::shell + * + * This property holds the shell associated with this XdgSurface. + */ + +/*! + * \property QWaylandXdgSurface::shell + * + * This property holds the shell associated with this QWaylandXdgSurface. + */ +QWaylandXdgShell *QWaylandXdgSurface::shell() const +{ + Q_D(const QWaylandXdgSurface); + return d->m_xdgShell; } /*! @@ -681,12 +750,22 @@ QWaylandSurface *QWaylandXdgSurface::surface() const * \qmlproperty object QtWaylandCompositor::XdgSurface::parentSurface * * This property holds the XdgSurface parent of this XdgSurface. + * When a parent surface is set, the parentSurfaceChanged() signal + * is guaranteed to be emitted before setTopLevel() and setTransient(). + * + * \sa QtWaylandCompositor::XdgSurface::setTopLevel() + * \sa QtWaylandCompositor::XdgSurface::setTransient() */ /*! * \property QWaylandXdgSurface::parentSurface * * This property holds the XdgSurface parent of this XdgSurface. + * When a parent surface is set, the parentSurfaceChanged() signal + * is guaranteed to be emitted before setTopLevel() and setTransient(). + * + * \sa QWaylandXdgSurface::setTopLevel() + * \sa QWaylandXdgSurface::setTransient() */ QWaylandXdgSurface *QWaylandXdgSurface::parentSurface() const { @@ -867,7 +946,7 @@ void QWaylandXdgSurface::sendClose() d->send_close(); } -uint QWaylandXdgSurface::requestMaximized(const QSize &size) +uint QWaylandXdgSurface::sendMaximized(const QSize &size) { Q_D(QWaylandXdgSurface); QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); @@ -880,7 +959,7 @@ uint QWaylandXdgSurface::requestMaximized(const QSize &size) return sendConfigure(size, conf.states); } -uint QWaylandXdgSurface::requestUnMaximized(const QSize &size) +uint QWaylandXdgSurface::sendUnmaximized(const QSize &size) { Q_D(QWaylandXdgSurface); QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); @@ -892,7 +971,7 @@ uint QWaylandXdgSurface::requestUnMaximized(const QSize &size) return sendConfigure(size, conf.states); } -uint QWaylandXdgSurface::requestFullscreen(const QSize &size) +uint QWaylandXdgSurface::sendFullscreen(const QSize &size) { Q_D(QWaylandXdgSurface); QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); @@ -905,7 +984,7 @@ uint QWaylandXdgSurface::requestFullscreen(const QSize &size) return sendConfigure(size, conf.states); } -uint QWaylandXdgSurface::requestResizing(const QSize &maxSize) +uint QWaylandXdgSurface::sendResizing(const QSize &maxSize) { Q_D(QWaylandXdgSurface); QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); @@ -918,10 +997,12 @@ uint QWaylandXdgSurface::requestResizing(const QSize &maxSize) return sendConfigure(maxSize, conf.states); } +#ifdef QT_WAYLAND_COMPOSITOR_QUICK QWaylandQuickShellIntegration *QWaylandXdgSurface::createIntegration(QWaylandQuickShellSurfaceItem *item) { return new QtWayland::XdgShellIntegration(item); } +#endif /*! * \class QWaylandXdgPopup @@ -940,7 +1021,7 @@ QWaylandQuickShellIntegration *QWaylandXdgSurface::createIntegration(QWaylandQui * Constructs a QWaylandXdgPopup. */ QWaylandXdgPopup::QWaylandXdgPopup() - : QWaylandCompositorExtensionTemplate<QWaylandXdgPopup>(*new QWaylandXdgPopupPrivate) + : QWaylandShellSurfaceTemplate<QWaylandXdgPopup>(*new QWaylandXdgPopupPrivate) { } @@ -949,10 +1030,10 @@ QWaylandXdgPopup::QWaylandXdgPopup() * given \a parentSurface and \a resource. */ QWaylandXdgPopup::QWaylandXdgPopup(QWaylandXdgShell *xdgShell, QWaylandSurface *surface, - QWaylandSurface *parentSurface, const QWaylandResource &resource) - : QWaylandCompositorExtensionTemplate<QWaylandXdgPopup>(*new QWaylandXdgPopupPrivate) + QWaylandSurface *parentSurface, const QPoint &position, const QWaylandResource &resource) + : QWaylandShellSurfaceTemplate<QWaylandXdgPopup>(*new QWaylandXdgPopupPrivate) { - initialize(xdgShell, surface, parentSurface, resource); + initialize(xdgShell, surface, parentSurface, position, resource); } /*! @@ -966,21 +1047,40 @@ QWaylandXdgPopup::QWaylandXdgPopup(QWaylandXdgShell *xdgShell, QWaylandSurface * * Initializes the QWaylandXdgPopup, associating it with the given \a shell \a surface, * \a parentSurface and \a resource. */ -void QWaylandXdgPopup::initialize(QWaylandXdgShell *shell, QWaylandSurface *surface, - QWaylandSurface *parentSurface, const QWaylandResource &resource) +void QWaylandXdgPopup::initialize(QWaylandXdgShell *shell, QWaylandSurface *surface, QWaylandSurface *parentSurface, + const QPoint& position, const QWaylandResource &resource) { Q_D(QWaylandXdgPopup); d->m_surface = surface; d->m_parentSurface = parentSurface; d->m_xdgShell = shell; + d->m_position = position; d->init(resource.resource()); setExtensionContainer(surface); + emit shellChanged(); emit surfaceChanged(); emit parentSurfaceChanged(); QWaylandCompositorExtension::initialize(); } /*! + * \qmlproperty object QtWaylandCompositor::XdgPopup::shell + * + * This property holds the shell associated with this XdgPopup. + */ + +/*! + * \property QWaylandXdgPopup::shell + * + * This property holds the shell associated with this QWaylandXdgPopup. + */ +QWaylandXdgShell *QWaylandXdgPopup::shell() const +{ + Q_D(const QWaylandXdgPopup); + return d->m_xdgShell; +} + +/*! * \qmlproperty object QtWaylandCompositor::XdgPopup::surface * * This property holds the surface associated with this XdgPopup. @@ -1015,12 +1115,34 @@ QWaylandSurface *QWaylandXdgPopup::parentSurface() const return d->m_parentSurface; } + +/*! + * \qmlproperty object QtWaylandCompositor::XdgPopup::position + * + * This property holds the location of the upper left corner of the surface + * relative to the upper left corner of the parent surface, in surface local + * coordinates. + */ + +/*! + * \property QWaylandXdgPopup::position + * + * This property holds the location of the upper left corner of the surface + * relative to the upper left corner of the parent surface, in surface local + * coordinates. + */ +QPoint QWaylandXdgPopup::position() const +{ + Q_D(const QWaylandXdgPopup); + return d->m_position; +} + /*! * \internal */ void QWaylandXdgPopup::initialize() { - QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositorExtension::initialize(); } /*! @@ -1058,4 +1180,11 @@ void QWaylandXdgPopup::sendPopupDone() d->send_popup_done(); } +#ifdef QT_WAYLAND_COMPOSITOR_QUICK +QWaylandQuickShellIntegration *QWaylandXdgPopup::createIntegration(QWaylandQuickShellSurfaceItem *item) +{ + return new QtWayland::XdgPopupIntegration(item); +} +#endif + QT_END_NAMESPACE |