summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/qwaylandbuffer.cpp2
-rw-r--r--src/client/qwaylandbuffer_p.h6
-rw-r--r--src/client/qwaylandwindow.cpp29
-rw-r--r--src/client/qwaylandwlshellsurface.cpp6
-rw-r--r--src/compositor/compositor_api/qwaylandclient.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp4
-rw-r--r--src/compositor/compositor_api/qwaylandoutput.cpp3
-rw-r--r--src/compositor/compositor_api/qwaylandpointer.cpp155
-rw-r--r--src/compositor/compositor_api/qwaylandpointer.h2
-rw-r--r--src/compositor/compositor_api/qwaylandpointer_p.h8
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.cpp4
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp6
-rw-r--r--src/compositor/compositor_api/qwaylandseat.cpp17
-rw-r--r--src/compositor/compositor_api/qwaylandseat.h3
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandview.cpp8
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-cpp.qdoc10
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-examples.qdoc10
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-overview.qdoc10
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc10
-rw-r--r--src/compositor/extensions/qwaylandivisurface.cpp2
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp2
-rw-r--r--src/compositor/extensions/qwaylandwlshell.cpp37
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv5.cpp236
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp119
25 files changed, 505 insertions, 188 deletions
diff --git a/src/client/qwaylandbuffer.cpp b/src/client/qwaylandbuffer.cpp
index a0fcc532f..076a0d57d 100644
--- a/src/client/qwaylandbuffer.cpp
+++ b/src/client/qwaylandbuffer.cpp
@@ -66,7 +66,7 @@ void QWaylandBuffer::init(wl_buffer *buf)
void QWaylandBuffer::release(void *data, wl_buffer *)
{
- static_cast<QWaylandBuffer *>(data)->mBusy = false;
+ static_cast<QWaylandBuffer *>(data)->mBusy--;
}
const wl_buffer_listener QWaylandBuffer::listener = {
diff --git a/src/client/qwaylandbuffer_p.h b/src/client/qwaylandbuffer_p.h
index 9e8cba2e4..b3513d151 100644
--- a/src/client/qwaylandbuffer_p.h
+++ b/src/client/qwaylandbuffer_p.h
@@ -73,14 +73,14 @@ public:
virtual QSize size() const = 0;
virtual int scale() const { return 1; }
- void setBusy() { mBusy = true; }
- bool busy() const { return mBusy; }
+ void setBusy() { mBusy++; }
+ bool busy() const { return mBusy > 0; }
protected:
struct wl_buffer *mBuffer;
private:
- bool mBusy;
+ int mBusy;
static void release(void *data, wl_buffer *);
static const wl_buffer_listener listener;
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index cac92a7e1..cff380e8f 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -261,6 +261,8 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
wl_callback_destroy(mFrameCallback);
mFrameCallback = nullptr;
}
+
+ mMask = QRegion();
}
QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
@@ -790,22 +792,27 @@ QWaylandAbstractDecoration *QWaylandWindow::decoration() const
return mWindowDecoration;
}
-static QWindow *topLevelWindow(QWindow *window)
+static QWaylandWindow *closestShellSurfaceWindow(QWindow *window)
{
- while (QWindow *parent = window->parent())
- window = parent;
- return window;
+ while (window) {
+ auto w = static_cast<QWaylandWindow *>(window->handle());
+ if (w->shellSurface())
+ return w;
+ window = window->transientParent() ? window->transientParent() : window->parent();
+ }
+ return nullptr;
}
QWaylandWindow *QWaylandWindow::transientParent() const
{
- // Take the top level window here, since the transient parent may be a QWidgetWindow
- // or some other window without a shell surface, which is then not able to get mouse
- // events.
- if (auto transientParent = window()->transientParent())
- return static_cast<QWaylandWindow *>(topLevelWindow(transientParent)->handle());
- else if (QGuiApplication::focusWindow() && (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup))
- return static_cast<QWaylandWindow *>(topLevelWindow(QGuiApplication::focusWindow())->handle());
+ // Take the closest window with a shell surface, since the transient parent may be a
+ // QWidgetWindow or some other window without a shell surface, which is then not able to
+ // get mouse events.
+ if (auto transientParent = closestShellSurfaceWindow(window()->transientParent()))
+ return transientParent;
+
+ if (QGuiApplication::focusWindow() && (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup))
+ return closestShellSurfaceWindow(QGuiApplication::focusWindow());
return nullptr;
}
diff --git a/src/client/qwaylandwlshellsurface.cpp b/src/client/qwaylandwlshellsurface.cpp
index 77434e98b..92223f45e 100644
--- a/src/client/qwaylandwlshellsurface.cpp
+++ b/src/client/qwaylandwlshellsurface.cpp
@@ -185,6 +185,7 @@ void QWaylandWlShellSurface::updateTransientParent(QWindow *parent)
|| testShowWithoutActivating(m_window->window()))
flags |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
+ Q_ASSERT(parent_wayland_window->object());
set_transient(parent_wayland_window->object(),
transientPos.x(),
transientPos.y(),
@@ -211,15 +212,16 @@ void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevic
transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
}
+ Q_ASSERT(parent_wayland_window->object());
set_popup(device->wl_seat(), serial, parent_wayland_window->object(),
transientPos.x(), transientPos.y(), 0);
}
void QWaylandWlShellSurface::setType(Qt::WindowType type, QWaylandWindow *transientParent)
{
- if (type == Qt::Popup && transientParent)
+ if (type == Qt::Popup && transientParent && transientParent->object())
setPopup(transientParent, m_window->display()->lastInputDevice(), m_window->display()->lastInputSerial());
- else if (transientParent)
+ else if (transientParent && transientParent->object())
updateTransientParent(transientParent->window());
else
setTopLevel();
diff --git a/src/compositor/compositor_api/qwaylandclient.cpp b/src/compositor/compositor_api/qwaylandclient.cpp
index 48675c495..f6b5564b8 100644
--- a/src/compositor/compositor_api/qwaylandclient.cpp
+++ b/src/compositor/compositor_api/qwaylandclient.cpp
@@ -167,7 +167,7 @@ QWaylandClient *QWaylandClient::fromWlClient(QWaylandCompositor *compositor, wl_
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandClient::compositor
+ * \qmlproperty WaylandCompositor QtWaylandCompositor::WaylandClient::compositor
*
* This property holds the compositor of this WaylandClient.
*/
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 522ef0413..00f3d83f0 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -660,7 +660,7 @@ QWaylandOutput *QWaylandCompositor::outputFor(QWindow *window) const
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultOutput
+ * \qmlproperty WaylandOutput QtWaylandCompositor::WaylandCompositor::defaultOutput
*
* This property contains the first in the list of outputs added to the
* WaylandCompositor, or null if no outputs have been added.
@@ -805,7 +805,7 @@ void QWaylandCompositor::overrideSelection(const QMimeData *data)
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultSeat
+ * \qmlproperty WaylandSeat QtWaylandCompositor::WaylandCompositor::defaultSeat
*
* This property contains the default seat for this
* WaylandCompositor.
diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp
index cbd7fe776..522de08e8 100644
--- a/src/compositor/compositor_api/qwaylandoutput.cpp
+++ b/src/compositor/compositor_api/qwaylandoutput.cpp
@@ -336,7 +336,7 @@ void QWaylandOutput::update()
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandOutput::compositor
+ * \qmlproperty WaylandCompositor QtWaylandCompositor::WaylandOutput::compositor
*
* This property holds the compositor displaying content on this WaylandOutput.
*
@@ -990,6 +990,7 @@ void QWaylandOutput::handleWindowDestroyed()
{
Q_D(QWaylandOutput);
d->window = Q_NULLPTR;
+ emit windowChanged();
emit windowDestroyed();
}
diff --git a/src/compositor/compositor_api/qwaylandpointer.cpp b/src/compositor/compositor_api/qwaylandpointer.cpp
index d1ca174db..bf4bf547d 100644
--- a/src/compositor/compositor_api/qwaylandpointer.cpp
+++ b/src/compositor/compositor_api/qwaylandpointer.cpp
@@ -51,31 +51,77 @@ QWaylandPointerPrivate::QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylan
, wl_pointer()
, seat(seat)
, output()
- , hasSentEnter(false)
, enterSerial(0)
, buttonCount()
{
Q_UNUSED(pointer);
}
-const QList<QtWaylandServer::wl_pointer::Resource *> QWaylandPointerPrivate::pointerResourcesForFocusedSurface() const
-{
- if (!seat->mouseFocus())
- return {};
-
- return resourceMap().values(seat->mouseFocus()->surfaceResource()->client);
-}
-
uint QWaylandPointerPrivate::sendButton(Qt::MouseButton button, uint32_t state)
{
Q_Q(QWaylandPointer);
+ if (!q->mouseFocus() || !q->mouseFocus()->surface())
+ return 0;
+
+ wl_client *client = q->mouseFocus()->surface()->waylandClient();
uint32_t time = compositor()->currentTimeMsecs();
uint32_t serial = compositor()->nextSerial();
- for (auto resource : pointerResourcesForFocusedSurface())
+ for (auto resource : resourceMap().values(client))
send_button(resource->handle, serial, time, q->toWaylandButton(button), state);
return serial;
}
+void QWaylandPointerPrivate::sendMotion()
+{
+ Q_ASSERT(enteredSurface);
+ uint32_t time = compositor()->currentTimeMsecs();
+ wl_fixed_t x = wl_fixed_from_double(localPosition.x());
+ wl_fixed_t y = wl_fixed_from_double(localPosition.y());
+ for (auto resource : resourceMap().values(enteredSurface->waylandClient()))
+ wl_pointer_send_motion(resource->handle, time, x, y);
+}
+
+void QWaylandPointerPrivate::sendEnter(QWaylandSurface *surface)
+{
+ Q_ASSERT(surface && !enteredSurface);
+ enterSerial = compositor()->nextSerial();
+
+ QWaylandKeyboard *keyboard = seat->keyboard();
+ if (keyboard)
+ keyboard->sendKeyModifiers(surface->client(), enterSerial);
+
+ wl_fixed_t x = wl_fixed_from_double(localPosition.x());
+ wl_fixed_t y = wl_fixed_from_double(localPosition.y());
+ for (auto resource : resourceMap().values(surface->waylandClient()))
+ send_enter(resource->handle, enterSerial, surface->resource(), x, y);
+
+ enteredSurface = surface;
+ enteredSurfaceDestroyListener.listenForDestruction(surface->resource());
+}
+
+void QWaylandPointerPrivate::sendLeave()
+{
+ Q_ASSERT(enteredSurface);
+ uint32_t serial = compositor()->nextSerial();
+ for (auto resource : resourceMap().values(enteredSurface->waylandClient()))
+ send_leave(resource->handle, serial, enteredSurface->resource());
+ enteredSurface = nullptr;
+ localPosition = QPointF();
+ enteredSurfaceDestroyListener.reset();
+}
+
+void QWaylandPointerPrivate::ensureEntered(QWaylandSurface *surface)
+{
+ if (enteredSurface == surface)
+ return;
+
+ if (enteredSurface)
+ sendLeave();
+
+ if (surface)
+ sendEnter(surface);
+}
+
void QWaylandPointerPrivate::pointer_release(wl_pointer::Resource *resource)
{
wl_resource_destroy(resource->handle);
@@ -122,7 +168,7 @@ void QWaylandPointerPrivate::pointer_set_cursor(wl_pointer::Resource *resource,
QWaylandPointer::QWaylandPointer(QWaylandSeat *seat, QObject *parent)
: QWaylandObject(* new QWaylandPointerPrivate(this, seat), parent)
{
- connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandPointer::focusDestroyed);
+ connect(&d_func()->enteredSurfaceDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandPointer::enteredSurfaceDestroyed);
connect(seat, &QWaylandSeat::mouseFocusChanged, this, &QWaylandPointer::pointerFocusChanged);
}
@@ -173,16 +219,11 @@ uint QWaylandPointer::sendMousePressEvent(Qt::MouseButton button)
{
Q_D(QWaylandPointer);
d->buttonCount++;
- uint serial = 0;
-
- if (d->seat->mouseFocus())
- serial = d->sendButton(button, WL_POINTER_BUTTON_STATE_PRESSED);
- if (d->buttonCount == 1) {
+ if (d->buttonCount == 1)
emit buttonPressedChanged();
- }
- return serial;
+ return d->sendButton(button, WL_POINTER_BUTTON_STATE_PRESSED);
}
/*!
@@ -194,15 +235,11 @@ uint QWaylandPointer::sendMouseReleaseEvent(Qt::MouseButton button)
{
Q_D(QWaylandPointer);
d->buttonCount--;
- uint serial = 0;
-
- if (d->seat->mouseFocus())
- serial = d->sendButton(button, WL_POINTER_BUTTON_STATE_RELEASED);
if (d->buttonCount == 0)
emit buttonPressedChanged();
- return serial;
+ return d->sendButton(button, WL_POINTER_BUTTON_STATE_RELEASED);
}
/*!
@@ -218,41 +255,20 @@ void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &loca
d->localPosition = localPos;
d->spacePosition = outputSpacePos;
- //we adjust if the mouse position is on the edge
- //to work around Qt's event propagation
- if (view && view->surface()) {
+ if (view) {
+ // We adjust if the mouse position is on the edge
+ // to work around Qt's event propagation
QSizeF size(view->surface()->size());
- if (d->localPosition.x() == size.width())
+ if (d->localPosition.x() == size.width())
d->localPosition.rx() -= 0.01;
-
if (d->localPosition.y() == size.height())
d->localPosition.ry() -= 0.01;
- }
-
- if (!d->hasSentEnter) {
- d->enterSerial = d->compositor()->nextSerial();
- QWaylandKeyboard *keyboard = d->seat->keyboard();
- if (keyboard)
- keyboard->sendKeyModifiers(view->surface()->client(), d->enterSerial);
- for (auto resource : d->pointerResourcesForFocusedSurface()) {
- d->send_enter(resource->handle, d->enterSerial, view->surface()->resource(),
- wl_fixed_from_double(d->localPosition.x()),
- wl_fixed_from_double(d->localPosition.y()));
- }
- d->focusDestroyListener.listenForDestruction(view->surface()->resource());
- d->hasSentEnter = true;
- }
- if (view && view->output())
- setOutput(view->output());
-
- uint32_t time = d->compositor()->currentTimeMsecs();
+ d->ensureEntered(view->surface());
+ d->sendMotion();
- if (d->seat->mouseFocus()) {
- wl_fixed_t x = wl_fixed_from_double(currentLocalPosition().x());
- wl_fixed_t y = wl_fixed_from_double(currentLocalPosition().y());
- for (auto resource : d->pointerResourcesForFocusedSurface())
- wl_pointer_send_motion(resource->handle, time, x, y);
+ if (view->output())
+ setOutput(view->output());
}
}
@@ -262,14 +278,14 @@ void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &loca
void QWaylandPointer::sendMouseWheelEvent(Qt::Orientation orientation, int delta)
{
Q_D(QWaylandPointer);
- if (!d->seat->mouseFocus())
+ if (!d->enteredSurface)
return;
uint32_t time = d->compositor()->currentTimeMsecs();
uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL
: WL_POINTER_AXIS_VERTICAL_SCROLL;
- for (auto resource : d->pointerResourcesForFocusedSurface())
+ for (auto resource : d->resourceMap().values(d->enteredSurface->waylandClient()))
d->send_axis(resource->handle, time, axis, wl_fixed_from_int(-delta / 12));
}
@@ -316,9 +332,8 @@ void QWaylandPointer::addClient(QWaylandClient *client, uint32_t id, uint32_t ve
{
Q_D(QWaylandPointer);
wl_resource *resource = d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_pointer::interfaceVersion(), version))->handle;
- QWaylandView *focus = d->seat->mouseFocus();
- if (focus && client == focus->surface()->client()) {
- d->send_enter(resource, d->enterSerial, focus->surfaceResource(),
+ if (d->enteredSurface && client == d->enteredSurface->client()) {
+ d->send_enter(resource, d->enterSerial, d->enteredSurface->resource(),
wl_fixed_from_double(d->localPosition.x()),
wl_fixed_from_double(d->localPosition.y()));
}
@@ -389,14 +404,19 @@ uint32_t QWaylandPointer::toWaylandButton(Qt::MouseButton button)
/*!
* \internal
*/
-void QWaylandPointer::focusDestroyed(void *data)
+void QWaylandPointer::enteredSurfaceDestroyed(void *data)
{
Q_D(QWaylandPointer);
Q_UNUSED(data)
- d->focusDestroyListener.reset();
+ d->enteredSurfaceDestroyListener.reset();
+ d->enteredSurface = nullptr;
+
+ d->seat->setMouseFocus(nullptr);
- d->seat->setMouseFocus(Q_NULLPTR);
- d->buttonCount = 0;
+ if (d->buttonCount != 0) {
+ d->buttonCount = 0;
+ emit buttonPressedChanged();
+ }
}
/*!
@@ -404,16 +424,11 @@ void QWaylandPointer::focusDestroyed(void *data)
*/
void QWaylandPointer::pointerFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus)
{
- Q_UNUSED(newFocus);
Q_D(QWaylandPointer);
- d->localPosition = QPointF();
- d->hasSentEnter = false;
- if (oldFocus) {
- uint32_t serial = d->compositor()->nextSerial();
- for (auto resource : d->resourceMap().values(oldFocus->surfaceResource()->client))
- d->send_leave(resource->handle, serial, oldFocus->surfaceResource());
- d->focusDestroyListener.reset();
- }
+ Q_UNUSED(oldFocus);
+ bool wasSameSurface = newFocus && newFocus->surface() == d->enteredSurface;
+ if (d->enteredSurface && !wasSameSurface)
+ d->sendLeave();
}
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandpointer.h b/src/compositor/compositor_api/qwaylandpointer.h
index bcba1d6a3..409bcc83a 100644
--- a/src/compositor/compositor_api/qwaylandpointer.h
+++ b/src/compositor/compositor_api/qwaylandpointer.h
@@ -89,7 +89,7 @@ Q_SIGNALS:
void buttonPressedChanged();
private:
- void focusDestroyed(void *data);
+ void enteredSurfaceDestroyed(void *data);
void pointerFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus);
};
diff --git a/src/compositor/compositor_api/qwaylandpointer_p.h b/src/compositor/compositor_api/qwaylandpointer_p.h
index 0a9ef2329..11076f34b 100644
--- a/src/compositor/compositor_api/qwaylandpointer_p.h
+++ b/src/compositor/compositor_api/qwaylandpointer_p.h
@@ -86,11 +86,15 @@ protected:
void pointer_release(Resource *resource) override;
private:
- const QList<Resource *> pointerResourcesForFocusedSurface() const;
uint sendButton(Qt::MouseButton button, uint32_t state);
+ void sendMotion();
+ void sendEnter(QWaylandSurface *surface);
+ void sendLeave();
+ void ensureEntered(QWaylandSurface *surface);
QWaylandSeat *seat;
QWaylandOutput *output;
+ QPointer<QWaylandSurface> enteredSurface;
QPointF localPosition;
QPointF spacePosition;
@@ -100,7 +104,7 @@ private:
int buttonCount;
- QWaylandDestroyListener focusDestroyListener;
+ QWaylandDestroyListener enteredSurfaceDestroyListener;
static QWaylandSurfaceRole s_role;
};
diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
index dccb8a151..35cd49228 100644
--- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
@@ -90,9 +90,9 @@ QWaylandQuickCompositor::QWaylandQuickCompositor(QObject *parent)
* import QtWayland.Compositor 1.0
*
* WaylandCompositor {
- * extensions: [ WlShell {
+ * WlShell {
* // ...
- * } ]
+ * }
* }
* \endcode
*/
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index bfd252753..a993467ac 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -371,7 +371,7 @@ QWaylandQuickItem::~QWaylandQuickItem()
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandQuickItem::compositor
+ * \qmlproperty WaylandCompositor QtWaylandCompositor::WaylandQuickItem::compositor
*
* This property holds the compositor for the surface rendered by this WaylandQuickItem.
*/
@@ -388,7 +388,7 @@ QWaylandCompositor *QWaylandQuickItem::compositor() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandQuickItem::view
+ * \qmlproperty WaylandView QtWaylandCompositor::WaylandQuickItem::view
*
* This property holds the view rendered by this WaylandQuickItem.
*/
@@ -405,7 +405,7 @@ QWaylandView *QWaylandQuickItem::view() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandQuickItem::surface
+ * \qmlproperty WaylandSurface QtWaylandCompositor::WaylandQuickItem::surface
*
* This property holds the surface rendered by this WaylandQuickItem.
*/
diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp
index 80b75d617..b4b45392c 100644
--- a/src/compositor/compositor_api/qwaylandseat.cpp
+++ b/src/compositor/compositor_api/qwaylandseat.cpp
@@ -456,6 +456,12 @@ void QWaylandSeat::setMouseFocus(QWaylandView *view)
QWaylandView *oldFocus = d->mouseFocus;
d->mouseFocus = view;
+
+ if (oldFocus)
+ disconnect(oldFocus, &QObject::destroyed, this, &QWaylandSeat::handleMouseFocusDestroyed);
+ if (d->mouseFocus)
+ connect(d->mouseFocus, &QObject::destroyed, this, &QWaylandSeat::handleMouseFocusDestroyed);
+
emit mouseFocusChanged(d->mouseFocus, oldFocus);
}
@@ -512,4 +518,15 @@ QWaylandSeat *QWaylandSeat::fromSeatResource(struct ::wl_resource *resource)
* This signal is emitted when the mouse focus has changed from \a oldFocus to \a newFocus.
*/
+void QWaylandSeat::handleMouseFocusDestroyed()
+{
+ // This is triggered when the QWaylandView is destroyed, NOT the surface.
+ // ... so this is for the rare case when the view that currently holds the mouse focus is
+ // destroyed before its surface
+ Q_D(QWaylandSeat);
+ d->mouseFocus = nullptr;
+ QWaylandView *oldFocus = nullptr; // we have to send nullptr because the old focus is already destroyed at this point
+ emit mouseFocusChanged(d->mouseFocus, oldFocus);
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandseat.h b/src/compositor/compositor_api/qwaylandseat.h
index 86cf250a6..e5ef46dc6 100644
--- a/src/compositor/compositor_api/qwaylandseat.h
+++ b/src/compositor/compositor_api/qwaylandseat.h
@@ -133,6 +133,9 @@ Q_SIGNALS:
void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus);
void keyboardFocusChanged(QWaylandSurface *newFocus, QWaylandSurface *oldFocus);
void cursorSurfaceRequest(QWaylandSurface *surface, int hotspotX, int hotspotY);
+
+private:
+ void handleMouseFocusDestroyed();
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandSeat::CapabilityFlags)
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index 6f277dd96..945d68827 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -445,7 +445,7 @@ bool QWaylandSurface::isInitialized() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandSurface::client
+ * \qmlproperty WaylandClient QtWaylandCompositor::WaylandSurface::client
*
* This property holds the client using this WaylandSurface.
*/
diff --git a/src/compositor/compositor_api/qwaylandview.cpp b/src/compositor/compositor_api/qwaylandview.cpp
index f56cb0b8e..9e8297574 100644
--- a/src/compositor/compositor_api/qwaylandview.cpp
+++ b/src/compositor/compositor_api/qwaylandview.cpp
@@ -99,9 +99,6 @@ QWaylandView::~QWaylandView()
if (d->surface) {
if (d->output)
QWaylandOutputPrivate::get(d->output)->removeView(this, d->surface);
- QWaylandSeat *i = d->surface->compositor()->defaultSeat();
- if (i->mouseFocus() == this)
- i->setMouseFocus(Q_NULLPTR);
QWaylandSurfacePrivate::get(d->surface)->derefView(this);
}
@@ -117,8 +114,9 @@ QObject *QWaylandView::renderObject() const
Q_D(const QWaylandView);
return d->renderObject;
}
+
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandView::surface
+ * \qmlproperty WaylandSurface QtWaylandCompositor::WaylandView::surface
*
* This property holds the surface viewed by this WaylandView.
*/
@@ -169,7 +167,7 @@ void QWaylandView::setSurface(QWaylandSurface *newSurface)
}
/*!
- * \qmlproperty object QtWaylandCompositor::WaylandView::output
+ * \qmlproperty WaylandOutput QtWaylandCompositor::WaylandView::output
*
* This property holds the output on which this view displays its surface.
*/
diff --git a/src/compositor/doc/src/qtwaylandcompositor-cpp.qdoc b/src/compositor/doc/src/qtwaylandcompositor-cpp.qdoc
index 4b38c8613..c406b81e1 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-cpp.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-cpp.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/compositor/doc/src/qtwaylandcompositor-examples.qdoc b/src/compositor/doc/src/qtwaylandcompositor-examples.qdoc
index 2b8511281..560844242 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-examples.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-examples.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
index d2fb6a27d..6be6444cc 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
index 1f1f58286..1dadb7102 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
@@ -11,8 +11,8 @@
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
@@ -20,7 +20,7 @@
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
-** will be met: http://www.gnu.org/copyleft/fdl.html.
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/compositor/extensions/qwaylandivisurface.cpp b/src/compositor/extensions/qwaylandivisurface.cpp
index 0bb2a6158..08b95b3b5 100644
--- a/src/compositor/extensions/qwaylandivisurface.cpp
+++ b/src/compositor/extensions/qwaylandivisurface.cpp
@@ -121,7 +121,7 @@ void QWaylandIviSurface::initialize(QWaylandIviApplication *iviApplication, QWay
}
/*!
- * \qmlproperty object QtWaylandCompositor::IviSurface::surface
+ * \qmlproperty WaylandSurface QtWaylandCompositor::IviSurface::surface
*
* This property holds the surface associated with this IviSurface.
*/
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
index e52bb4852..2b603099b 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
@@ -93,7 +93,7 @@ QWaylandQuickShellSurfaceItem::QWaylandQuickShellSurfaceItem(QWaylandQuickShellS
}
/*!
- * \qmlproperty object QtWaylandCompositor::ShellSurfaceItem::shellSurface
+ * \qmlproperty ShellSurface QtWaylandCompositor::ShellSurfaceItem::shellSurface
*
* This property holds the ShellSurface rendered by this ShellSurfaceItem.
* It may either be an XdgSurfaceV5, WlShellSurface or IviSurface depending on which shell protocol
diff --git a/src/compositor/extensions/qwaylandwlshell.cpp b/src/compositor/extensions/qwaylandwlshell.cpp
index 038e41b1f..96dbd3dc1 100644
--- a/src/compositor/extensions/qwaylandwlshell.cpp
+++ b/src/compositor/extensions/qwaylandwlshell.cpp
@@ -277,7 +277,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_class(Resource *resource,
* import QtWayland.Compositor 1.0
*
* WaylandCompositor {
- * extensions: WlShell {
+ * WlShell {
* // ...
* }
* }
@@ -384,18 +384,37 @@ const struct wl_interface *QWaylandWlShell::interface()
}
/*!
- * \qmlsignal void QtWaylandCompositor::WlShell::wlShellSurfaceRequested(object surface, object client, int id)
+ * \qmlsignal void QtWaylandCompositor::WlShell::wlShellSurfaceRequested(WaylandSurface surface, WaylandResource resource)
*
- * This signal is emitted when the \a client has requested a \c wl_shell_surface to be associated
- * with \a surface, which is identified by \a id. The handler for this signal is
- * expected to create the shell surface and initialize it within the scope of the
- * signal emission.
+ * This signal is emitted when the client has requested a \c wl_shell_surface to be associated with
+ * \a surface. The handler for this signal may create a shell surface for \a resource and initialize
+ * it within the scope of the signal emission. Otherwise a WlShellSurface will be created
+ * automatically.
*/
/*!
* \fn void QWaylandWlShell::wlShellSurfaceRequested(QWaylandSurface *surface, const QWaylandResource &resource)
*
- * Constructs a QWaylandSurface, assigns it to \a surface and initializes it with the given \a resource.
+ * This signal is emitted when the client has requested a \c wl_shell_surface to be associated with
+ * \a surface. The handler for this signal may create a shell surface for \a resource and initialize
+ * it within the scope of the signal emission. Otherwise a QWaylandWlShellSurface will be created
+ * automatically.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::WlShell::wlShellSurfaceCreated(WlShellSurface shellSurface)
+ *
+ * This signal is emitted when the client has created a \c wl_shell_surface.
+ * A common use case is to let the handler of this signal instantiate a ShellSurfaceItem or
+ * WaylandQuickItem for displaying \a shellSurface in a QtQuick scene.
+ */
+
+/*!
+ * \fn void QWaylandWlShell::wlShellSurfaceCreated(QWaylandWlShellSurface *shellSurface)
+ *
+ * This signal is emitted when the client has created a \c wl_shell_surface.
+ * A common use case is to let the handler of this signal instantiate a QWaylandShellSurfaceItem or
+ * QWaylandQuickItem for displaying \a shellSurface in a QtQuick scene.
*/
/*!
@@ -575,7 +594,7 @@ QWaylandQuickShellIntegration *QWaylandWlShellSurface::createIntegration(QWaylan
#endif
/*!
- * \qmlproperty object QtWaylandCompositor::WlShellSurface::surface
+ * \qmlproperty WaylandSurface QtWaylandCompositor::WlShellSurface::surface
*
* This property holds the \c wl_surface associated with this WlShellSurface.
*/
@@ -592,7 +611,7 @@ QWaylandSurface *QWaylandWlShellSurface::surface() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::WlShellSurface::shell
+ * \qmlproperty WlShell QtWaylandCompositor::WlShellSurface::shell
*
* This property holds the shell associated with this WlShellSurface.
*/
diff --git a/src/compositor/extensions/qwaylandxdgshellv5.cpp b/src/compositor/extensions/qwaylandxdgshellv5.cpp
index 8f1164260..c0cb4f8e4 100644
--- a/src/compositor/extensions/qwaylandxdgshellv5.cpp
+++ b/src/compositor/extensions/qwaylandxdgshellv5.cpp
@@ -646,6 +646,98 @@ void QWaylandXdgShellV5::closeAllPopups()
}
}
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgShellV5::xdgSurfaceRequested(WaylandSurface surface, WaylandResource resource)
+ *
+ * This signal is emitted when the client has requested an \c xdg_surface to be associated
+ * with \a surface. The handler for this signal may create the shell surface for \a resource
+ * and initialize it within the scope of the signal emission. Otherwise an XdgSurfaceV5 will
+ * be created automatically.
+ */
+
+/*!
+ * \fn void QWaylandXdgShellV5::xdgSurfaceRequested(QWaylandSurface *surface, const QWaylandResource &resource)
+ *
+ * This signal is emitted when the client has requested an \c xdg_surface to be associated
+ * with \a surface. The handler for this signal may create the shell surface for \a resource
+ * and initialize it within the scope of the signal emission. Otherwise a QWaylandXdgSurfaceV5
+ * will be created automatically.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgShellV5::xdgSurfaceCreated(XdgSurfaceV5 xdgSurface)
+ *
+ * This signal is emitted when the client has created an \c xdg_surface.
+ * A common use case is to let the handler of this signal instantiate a ShellSurfaceItem or
+ * WaylandQuickItem for displaying \a xdgSurface in a QtQuick scene.
+ */
+
+/*!
+ * \fn void QWaylandXdgShellV5::xdgSurfaceCreated(QWaylandXdgSurfaceV5 *xdgSurface)
+ *
+ * This signal is emitted when the client has created an \c xdg_surface.
+ * A common use case is to let the handler of this signal instantiate a QWaylandShellSurfaceItem or
+ * QWaylandQuickItem for displaying \a xdgSurface in a QtQuick scene.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgShellV5::xdgPopupRequested(WaylandSurface surface, WaylandSurface parent, WaylandSeat seat, point position, WaylandResource resource)
+ *
+ * This signal is emitted when the client has requested an \c xdg_popup to be associated
+ * with \a surface. The handler for this signal may create the xdg popup for \a resource and
+ * initialize it within the scope of the signal emission. Otherwise an XdgPopupV5 will be
+ * created automatically.
+ *
+ * The \a seat is the \c wl_seat that caused the popup to be opened.
+ *
+ * \a position is the desired position of the popup, relative to the \a parent.
+ */
+
+/*!
+ * \fn void QWaylandXdgShellV5::xdgPopupRequested(QWaylandSurface *surface, QWaylandSurface *parent, QWaylandSeat *seat, const QPoint &position, const QWaylandResource &resource)
+ *
+ * This signal is emitted when the client has requested an \c xdg_surface to be associated
+ * with \a surface. The handler for this signal may create the xdg poup for \a resource and
+ * initialize it within the scope of the signal emission. Otherwise a QWaylandXdgPopupV5 will be
+ * created automatically.
+ *
+ * The \a seat is the \c wl_seat that caused the popup to be opened.
+ *
+ * \a position is the desired position of the popup, relative to the \a parent.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgShellV5::xdgPopupCreated(XdgPopupV5 xdgPopup)
+ *
+ * This signal is emitted when the client has created an \c xdg_popup.
+ * A common use case is to let the handler of this signal instantiate a ShellSurfaceItem or
+ * WaylandQuickItem for displaying \a xdgPopup in a QtQuick scene.
+ */
+
+/*!
+ * \fn void QWaylandXdgShellV5::xdgPopupCreated(QWaylandXdgPopupV5 *xdgPopup)
+ *
+ * This signal is emitted when the client has created an \c xdg_popup.
+ * A common use case is to let the handler of this signal instantiate a QWaylandShellSurfaceItem or
+ * QWaylandQuickItem for displaying \a xdgPopup in a QtQuick scene.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgShellV5::pong(int serial)
+ *
+ * This signal is emitted when the client has responded to a ping event with serial \a serial.
+ *
+ * \sa QtWaylandCompositor::XdgShellV5::ping()
+ */
+
+/*!
+ * \fn void QWaylandXdgShellV5::pong(uint serial)
+ *
+ * This signal is emitted when the client has responded to a ping event with serial \a serial.
+ *
+ * \sa QWaylandXdgShellV5::ping()
+ */
+
void QWaylandXdgShellV5::handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat)
{
if (oldSeat != nullptr) {
@@ -760,6 +852,134 @@ void QWaylandXdgSurfaceV5::initialize(QWaylandXdgShellV5 *xdgShell, QWaylandSurf
}
/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::showWindowMenu(WaylandSeat seat, point localSurfacePosition)
+ *
+ * This signal is emitted when the client wants to show a context menu at \a localSurfacePosition,
+ * using the Wayland seat \a seat. It's typically emitted in response to the user right-clicking
+ * the window decorations.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::showWindowMenu(QWaylandSeat *seat, const QPoint &localSurfacePosition)
+ *
+ * This signal is emitted when the client wants to show a context menu at \a localSurfacePosition,
+ * using the Wayland seat \a seat. It's typically emitted in response to the user right-clicking
+ * the window decorations.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::startMove(WaylandSeat seat)
+ *
+ * This signal is emitted when the client wants to start an interactive move of the XdgSurfaceV5,
+ * typically in response to the window decorations being dragged by \a seat.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::startMove(QWaylandSeat *seat)
+ *
+ * This signal is emitted when the client wants to start an interactive move of the
+ * QWaylandXdgSurfaceV5, typically in response to the window decorations being dragged by \a seat.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::startResize(WaylandSeat seat, enumeration edges)
+ *
+ * This signal is emitted when the client wants to start an interactive resize of the XdgSurfaceV5,
+ * typically in response to the window decorations being dragged by \a seat on the window borders
+ * given by \a edges.
+ *
+ * \sa QWaylandXdgSurfaceV5::ResizeEdges
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::startResize(QWaylandSeat *seat, ResizeEdges edges)
+ *
+ * This signal is emitted when the client wants to start an interactive resize of the
+ * QWaylandXdgSurfaceV5, typically in response to the window decorations being dragged by
+ * \a seat on the window borders given by \a edges.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::setMaximized()
+ *
+ * This signal is emitted when the client wants the \c xdg_surface to be maximized.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::setMaximized()
+ *
+ * This signal is emitted when the client wants the \c xdg_surface to be maximized.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::unsetMaximized()
+ *
+ * This signal is emitted when the client doesn't want the \c xdg_surface to be maximized anymore.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::unsetMaximized()
+ *
+ * This signal is emitted when the client doesn't want the \c xdg_surface to be maximized anymore.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::setFullscreen(WaylandOutput output)
+ *
+ * This signal is emitted when the client wants the \c xdg_surface to be in full screen mode.
+ * The client may specify an \a output it wishes the \c xdg_surface to be shown on.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::setFullscreen(QWaylandOutput *output)
+ *
+ * This signal is emitted when the client wants the \c xdg_surface to be in full screen mode.
+ * The client may specify an \a output it wishes the \c xdg_surface to be shown on.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::unsetFullscreen()
+ *
+ * This signal is emitted when the client doesn't want the \c xdg_surface to be in full screen mode
+ * anymore.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::unsetFullscreen()
+ *
+ * This signal is emitted when the client doesn't want the \c xdg_surface to be in full screen mode
+ * anymore.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::setMinimized()
+ *
+ * This signal is emitted when the client wants the \c xdg_surface to be minimized.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::setMinimized()
+ *
+ * This signal is emitted when the client wants the \c xdg_surface to be minimized.
+ */
+
+/*!
+ * \qmlsignal void QtWaylandCompositor::XdgSurfaceV5::ackConfigure(int serial)
+ *
+ * This signal is emitted when the client has received configure events up to and including the
+ * configure event with serial \a serial and will draw its surface accordingly in the next committed
+ * buffer.
+ */
+
+/*!
+ * \fn void QWaylandXdgSurfaceV5::ackConfigure(uint serial)
+ *
+ * This signal is emitted when the client has received configure events up to and including the
+ * configure event with serial \a serial and will draw its surface accordingly in the next committed
+ * buffer.
+ */
+
+/*!
* \internal
*/
void QWaylandXdgSurfaceV5::initialize()
@@ -789,7 +1009,7 @@ void QWaylandXdgSurfaceV5::handleBufferScaleChanged()
}
/*!
- * \qmlproperty object QtWaylandCompositor::XdgSurfaceV5::shell
+ * \qmlproperty XdgShellV5 QtWaylandCompositor::XdgSurfaceV5::shell
*
* This property holds the shell associated with this XdgSurfaceV5.
*/
@@ -806,7 +1026,7 @@ QWaylandXdgShellV5 *QWaylandXdgSurfaceV5::shell() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::XdgSurfaceV5::surface
+ * \qmlproperty WaylandSurface QtWaylandCompositor::XdgSurfaceV5::surface
*
* This property holds the surface associated with this XdgSurfaceV5.
*/
@@ -823,7 +1043,7 @@ QWaylandSurface *QWaylandXdgSurfaceV5::surface() const
}
/*!
- * \qmlproperty enum QtWaylandCompositor::XdgSurfaceV5::windowType
+ * \qmlproperty enumeration QtWaylandCompositor::XdgSurfaceV5::windowType
*
* This property holds the window type of the XdgSurfaceV5.
*/
@@ -840,7 +1060,7 @@ Qt::WindowType QWaylandXdgSurfaceV5::windowType() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::XdgSurfaceV5::parentSurface
+ * \qmlproperty XdgSurfaceV5 QtWaylandCompositor::XdgSurfaceV5::parentSurface
*
* This property holds the XdgSurfaceV5 parent of this XdgSurfaceV5.
* When a parent surface is set, the parentSurfaceChanged() signal
@@ -1175,7 +1395,7 @@ void QWaylandXdgPopupV5::initialize(QWaylandXdgShellV5 *shell, QWaylandSurface *
}
/*!
- * \qmlproperty object QtWaylandCompositor::XdgPopupV5::shell
+ * \qmlproperty XdgShellV5 QtWaylandCompositor::XdgPopupV5::shell
*
* This property holds the shell associated with this XdgPopupV5.
*/
@@ -1192,7 +1412,7 @@ QWaylandXdgShellV5 *QWaylandXdgPopupV5::shell() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::XdgPopupV5::surface
+ * \qmlproperty WaylandSurface QtWaylandCompositor::XdgPopupV5::surface
*
* This property holds the surface associated with this XdgPopupV5.
*/
@@ -1209,7 +1429,7 @@ QWaylandSurface *QWaylandXdgPopupV5::surface() const
}
/*!
- * \qmlproperty object QtWaylandCompositor::XdgPopupV5::parentSurface
+ * \qmlproperty WaylandSurface QtWaylandCompositor::XdgPopupV5::parentSurface
*
* This property holds the surface associated with the parent of this XdgPopupV5.
*/
@@ -1228,7 +1448,7 @@ QWaylandSurface *QWaylandXdgPopupV5::parentSurface() const
/*!
- * \qmlproperty object QtWaylandCompositor::XdgPopupV5::position
+ * \qmlproperty point QtWaylandCompositor::XdgPopupV5::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
diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
index c9133a227..453800c18 100644
--- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
@@ -44,6 +44,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLTexture>
+#include <QtGui/QOffscreenSurface>
#include <qpa/qplatformscreen.h>
#include <QtGui/QWindow>
#include <QtCore/QPointer>
@@ -153,14 +154,14 @@ struct BufferState
BufferState();
enum EglMode {
- ModeNone,
+ ModeUninitialized,
ModeEGLImage,
ModeEGLStream
};
EGLint egl_format;
QVarLengthArray<EGLImageKHR, 3> egl_images;
- QOpenGLTexture *textures[3];
+ QOpenGLTexture *textures[3] = {};
EGLStreamKHR egl_stream;
bool isYInverted;
@@ -174,13 +175,17 @@ public:
WaylandEglClientBufferIntegrationPrivate();
void initBuffer(WaylandEglClientBuffer *buffer);
- void init_egl_texture(WaylandEglClientBuffer *buffer, EGLint format);
- void init_egl_fd_texture(WaylandEglClientBuffer *buffer, wl_resource *bufferHandle);
- void register_buffer(struct ::wl_resource *buffer, BufferState state);
+ void initEglTexture(WaylandEglClientBuffer *buffer, EGLint format);
+ bool ensureContext();
+ bool initEglStream(WaylandEglClientBuffer *buffer, struct ::wl_resource *bufferHandle);
+ void handleEglstreamTexture(WaylandEglClientBuffer *buffer, wl_resource *bufferHandle);
+ void registerBuffer(struct ::wl_resource *buffer, BufferState state);
EGLDisplay egl_display;
bool valid;
bool display_bound;
+ QOffscreenSurface *offscreenSurface = nullptr;
+ QOpenGLContext *localContext = nullptr;
PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display;
PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display;
@@ -201,7 +206,7 @@ BufferState::BufferState()
: egl_format(EGL_TEXTURE_RGBA)
, egl_stream(EGL_NO_STREAM_KHR)
, isYInverted(true)
- , eglMode(ModeNone)
+ , eglMode(ModeUninitialized)
{}
WaylandEglClientBufferIntegrationPrivate::WaylandEglClientBufferIntegrationPrivate()
@@ -223,10 +228,10 @@ void WaylandEglClientBufferIntegrationPrivate::initBuffer(WaylandEglClientBuffer
EGLint format;
if (egl_query_wayland_buffer(egl_display, buffer->waylandBufferHandle(), EGL_TEXTURE_FORMAT, &format))
- init_egl_texture(buffer, format);
+ initEglTexture(buffer, format);
}
-void WaylandEglClientBufferIntegrationPrivate::init_egl_texture(WaylandEglClientBuffer *buffer, EGLint format)
+void WaylandEglClientBufferIntegrationPrivate::initEglTexture(WaylandEglClientBuffer *buffer, EGLint format)
{
// Non-streaming case
@@ -288,11 +293,31 @@ void WaylandEglClientBufferIntegrationPrivate::init_egl_texture(WaylandEglClient
}
}
-void WaylandEglClientBufferIntegrationPrivate::init_egl_fd_texture(WaylandEglClientBuffer *buffer, struct ::wl_resource *bufferHandle)
+bool WaylandEglClientBufferIntegrationPrivate::ensureContext()
{
-//EglStreams case
- BufferState &state = *buffer->d;
+ bool localContextNeeded = false;
+ if (!QOpenGLContext::currentContext()) {
+ if (!localContext && QOpenGLContext::globalShareContext()) {
+ localContext = new QOpenGLContext;
+ localContext->setShareContext(QOpenGLContext::globalShareContext());
+ localContext->create();
+ }
+ if (localContext) {
+ if (!offscreenSurface) {
+ offscreenSurface = new QOffscreenSurface;
+ offscreenSurface->setFormat(localContext->format());
+ offscreenSurface->create();
+ }
+ localContext->makeCurrent(offscreenSurface);
+ localContextNeeded = true;
+ }
+ }
+ return localContextNeeded;
+}
+bool WaylandEglClientBufferIntegrationPrivate::initEglStream(WaylandEglClientBuffer *buffer, wl_resource *bufferHandle)
+{
+ BufferState &state = *buffer->d;
state.egl_format = EGL_TEXTURE_EXTERNAL_WL;
state.isYInverted = false;
@@ -311,39 +336,57 @@ void WaylandEglClientBufferIntegrationPrivate::init_egl_fd_texture(WaylandEglCli
if (state.egl_stream == EGL_NO_STREAM_KHR) {
qWarning("%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
- return;
+ return false;
}
state.eglMode = BufferState::ModeEGLStream;
if (!QOpenGLContext::currentContext()) {
qWarning("EglClientBufferIntegration: creating texture with no current context");
- return;
+ return false;
}
- //TODO This texture might end up in a different context than the quick item which wants to use it, this needs to be fixed somehow.
-
auto texture = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(GL_TEXTURE_EXTERNAL_OES));
texture->create();
state.textures[0] = texture; // TODO: support multiple planes for the streaming case
- glActiveTexture(GL_TEXTURE0);
- texture->create();
texture->bind();
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->textureId());
-
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
auto newStream = funcs->stream_consumer_gltexture(egl_display, state.egl_stream);
-
if (!newStream) {
EGLint code = eglGetError();
qWarning() << "Could not initialize EGLStream:" << egl_error_string(code) << hex << (long)code;
funcs->destroy_stream(egl_display, state.egl_stream);
state.egl_stream = EGL_NO_STREAM_KHR;
+ return false;
+ }
+ return true;
+}
+
+void WaylandEglClientBufferIntegrationPrivate::handleEglstreamTexture(WaylandEglClientBuffer *buffer, struct ::wl_resource *bufferHandle)
+{
+ bool usingLocalContext = ensureContext();
+
+ if (buffer->d->eglMode == BufferState::ModeUninitialized) {
+ bool streamOK = initEglStream(buffer, bufferHandle);
+ if (!streamOK)
+ return;
}
+
+ BufferState &state = *buffer->d;
+ auto texture = state.textures[0];
+
+ // EGLStream requires calling acquire on every frame.
+ texture->bind();
+ EGLint stream_state;
+ funcs->query_stream(egl_display, state.egl_stream, EGL_STREAM_STATE_KHR, &stream_state);
+
+ if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) {
+ if (funcs->stream_consumer_acquire(egl_display, state.egl_stream) != EGL_TRUE)
+ qWarning("%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
+ }
+
+ if (usingLocalContext)
+ localContext->doneCurrent();
}
WaylandEglClientBufferIntegration::WaylandEglClientBufferIntegration()
@@ -477,9 +520,12 @@ QOpenGLTexture *WaylandEglClientBuffer::toOpenGlTexture(int plane)
if (!m_buffer)
return nullptr;
- auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
auto texture = d->textures[plane];
- const auto target = static_cast<QOpenGLTexture::Target>((d->eglMode == BufferState::ModeEGLStream || d->egl_format == EGL_TEXTURE_EXTERNAL_WL) ? GL_TEXTURE_EXTERNAL_OES
+ if (d->eglMode == BufferState::ModeEGLStream)
+ return texture; // EGLStreams texture is maintained by handle_eglstream_texture()
+
+ auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
+ const auto target = static_cast<QOpenGLTexture::Target>(d->egl_format == EGL_TEXTURE_EXTERNAL_WL ? GL_TEXTURE_EXTERNAL_OES
: GL_TEXTURE_2D);
if (!texture) {
texture = new QOpenGLTexture(target);
@@ -489,22 +535,7 @@ QOpenGLTexture *WaylandEglClientBuffer::toOpenGlTexture(int plane)
d->textures[plane] = texture;
}
-
- if (d->eglMode == BufferState::ModeEGLStream) {
- // EGLStream requires calling acquire on every frame.
- if (d->egl_stream != EGL_NO_STREAM_KHR) {
-
- texture->bind();
-
- EGLint stream_state;
- p->funcs->query_stream(p->egl_display, d->egl_stream, EGL_STREAM_STATE_KHR, &stream_state);
-
- if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) {
- if (p->funcs->stream_consumer_acquire(p->egl_display, d->egl_stream) != EGL_TRUE)
- qWarning("%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
- }
- }
- } else if (m_textureDirty) {
+ if (m_textureDirty) {
texture->bind();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
p->gl_egl_image_target_texture_2d(target, d->egl_images[plane]);
@@ -515,9 +546,9 @@ QOpenGLTexture *WaylandEglClientBuffer::toOpenGlTexture(int plane)
void WaylandEglClientBuffer::setCommitted(QRegion &damage)
{
ClientBuffer::setCommitted(damage);
- if (d->eglMode == BufferState::ModeNone) {
+ if (d->eglMode == BufferState::ModeEGLStream || d->eglMode == BufferState::ModeUninitialized) {
auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
- p->init_egl_fd_texture(this, waylandBufferHandle());
+ p->handleEglstreamTexture(this, waylandBufferHandle());
}
}