summaryrefslogtreecommitdiffstats
path: root/src/compositor/extensions/qwaylandxdgshell.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor/extensions/qwaylandxdgshell.cpp')
-rw-r--r--src/compositor/extensions/qwaylandxdgshell.cpp217
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