summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2017-07-21 12:06:50 +0200
committerJohan Helsing <johan.helsing@qt.io>2017-08-24 07:28:54 +0000
commitfe99464d6057a1a8d3db2389c65079a9564ac8d3 (patch)
tree4e7642793a7730cc517c9ea07ff99f2e05caf178
parent25cde2cc337740823b28898a54c05ec95b82d119 (diff)
Send pointer events to all bound resources
Previously we would send events to just one of the bound resources. An example of this, is the breeze Qt style, which would bind to the pointer resource a second time, which resulted in the original resource not receiving any events, which in turn resulted in an unresponsive client. Change-Id: Iac0ffe5d9ef0dfb95db89796515d7eb4a0b38227 Reviewed-by: Giulio Camuffo <giulio.camuffo@kdab.com>
-rw-r--r--src/compositor/compositor_api/qwaylandpointer.cpp90
-rw-r--r--src/compositor/compositor_api/qwaylandpointer_p.h6
2 files changed, 60 insertions, 36 deletions
diff --git a/src/compositor/compositor_api/qwaylandpointer.cpp b/src/compositor/compositor_api/qwaylandpointer.cpp
index 267b5d980..d1ca174db 100644
--- a/src/compositor/compositor_api/qwaylandpointer.cpp
+++ b/src/compositor/compositor_api/qwaylandpointer.cpp
@@ -51,17 +51,29 @@ QWaylandPointerPrivate::QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylan
, wl_pointer()
, seat(seat)
, output()
- , focusResource()
, hasSentEnter(false)
+ , enterSerial(0)
, buttonCount()
{
Q_UNUSED(pointer);
}
-void QWaylandPointerPrivate::pointer_destroy_resource(wl_pointer::Resource *resource)
+const QList<QtWaylandServer::wl_pointer::Resource *> QWaylandPointerPrivate::pointerResourcesForFocusedSurface() const
{
- if (focusResource == resource->handle)
- focusResource = 0;
+ if (!seat->mouseFocus())
+ return {};
+
+ return resourceMap().values(seat->mouseFocus()->surfaceResource()->client);
+}
+
+uint QWaylandPointerPrivate::sendButton(Qt::MouseButton button, uint32_t state)
+{
+ Q_Q(QWaylandPointer);
+ uint32_t time = compositor()->currentTimeMsecs();
+ uint32_t serial = compositor()->nextSerial();
+ for (auto resource : pointerResourcesForFocusedSurface())
+ send_button(resource->handle, serial, time, q->toWaylandButton(button), state);
+ return serial;
}
void QWaylandPointerPrivate::pointer_release(wl_pointer::Resource *resource)
@@ -160,12 +172,11 @@ void QWaylandPointer::setOutput(QWaylandOutput *output)
uint QWaylandPointer::sendMousePressEvent(Qt::MouseButton button)
{
Q_D(QWaylandPointer);
- uint32_t time = d->compositor()->currentTimeMsecs();
d->buttonCount++;
uint serial = 0;
- if (d->focusResource)
- serial = sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_PRESSED);
+ if (d->seat->mouseFocus())
+ serial = d->sendButton(button, WL_POINTER_BUTTON_STATE_PRESSED);
if (d->buttonCount == 1) {
emit buttonPressedChanged();
@@ -182,12 +193,11 @@ uint QWaylandPointer::sendMousePressEvent(Qt::MouseButton button)
uint QWaylandPointer::sendMouseReleaseEvent(Qt::MouseButton button)
{
Q_D(QWaylandPointer);
- uint32_t time = d->compositor()->currentTimeMsecs();
d->buttonCount--;
uint serial = 0;
- if (d->focusResource)
- serial = sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_RELEASED);
+ if (d->seat->mouseFocus())
+ serial = d->sendButton(button, WL_POINTER_BUTTON_STATE_RELEASED);
if (d->buttonCount == 0)
emit buttonPressedChanged();
@@ -219,31 +229,30 @@ void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &loca
d->localPosition.ry() -= 0.01;
}
- QWaylandPointerPrivate::Resource *resource = view ? d->resourceMap().value(view->surface()->waylandClient()) : 0;
- if (resource && !d->hasSentEnter) {
- uint32_t serial = d->compositor()->nextSerial();
+ if (!d->hasSentEnter) {
+ d->enterSerial = d->compositor()->nextSerial();
QWaylandKeyboard *keyboard = d->seat->keyboard();
- if (keyboard) {
- keyboard->sendKeyModifiers(view->surface()->client(), serial);
+ 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->send_enter(resource->handle, serial, 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;
}
- d->focusResource = resource ? resource->handle : 0;
-
if (view && view->output())
setOutput(view->output());
uint32_t time = d->compositor()->currentTimeMsecs();
- if (d->focusResource) {
+ if (d->seat->mouseFocus()) {
wl_fixed_t x = wl_fixed_from_double(currentLocalPosition().x());
wl_fixed_t y = wl_fixed_from_double(currentLocalPosition().y());
- wl_pointer_send_motion(d->focusResource, time, x, y);
+ for (auto resource : d->pointerResourcesForFocusedSurface())
+ wl_pointer_send_motion(resource->handle, time, x, y);
}
}
@@ -253,13 +262,15 @@ void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &loca
void QWaylandPointer::sendMouseWheelEvent(Qt::Orientation orientation, int delta)
{
Q_D(QWaylandPointer);
- if (!d->focusResource)
+ if (!d->seat->mouseFocus())
return;
uint32_t time = d->compositor()->currentTimeMsecs();
uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL
: WL_POINTER_AXIS_VERTICAL_SCROLL;
- d->send_axis(d->focusResource, time, axis, wl_fixed_from_int(-delta / 12));
+
+ for (auto resource : d->pointerResourcesForFocusedSurface())
+ d->send_axis(resource->handle, time, axis, wl_fixed_from_int(-delta / 12));
}
/*!
@@ -304,19 +315,30 @@ bool QWaylandPointer::isButtonPressed() const
void QWaylandPointer::addClient(QWaylandClient *client, uint32_t id, uint32_t version)
{
Q_D(QWaylandPointer);
- d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_pointer::interfaceVersion(), version));
+ 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(),
+ wl_fixed_from_double(d->localPosition.x()),
+ wl_fixed_from_double(d->localPosition.y()));
+ }
}
/*!
- * Returns the Wayland resource for this QWaylandPointer.
+ * Returns a Wayland resource for this QWaylandPointer.
+ *
+ * This API doesn't actually make sense, since there may be many pointer resources per client
+ * It's here for compatibility reasons.
*/
struct wl_resource *QWaylandPointer::focusResource() const
{
Q_D(const QWaylandPointer);
- if (!d->focusResource)
- return Q_NULLPTR;
+ QWaylandView *focus = d->seat->mouseFocus();
+ if (!focus)
+ return nullptr;
- return d->focusResource;
+ // Just return the first resource we can find.
+ return d->resourceMap().value(focus->surface()->waylandClient())->handle;
}
/*!
@@ -324,6 +346,8 @@ struct wl_resource *QWaylandPointer::focusResource() const
*/
uint QWaylandPointer::sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state)
{
+ // This method is here for compatibility reasons only, since it usually doesn't make sense to
+ // send button events to just one of the pointer resources for a client.
Q_D(QWaylandPointer);
uint32_t serial = d->compositor()->nextSerial();
d->send_button(resource, serial, time, toWaylandButton(button), state);
@@ -372,7 +396,6 @@ void QWaylandPointer::focusDestroyed(void *data)
d->focusDestroyListener.reset();
d->seat->setMouseFocus(Q_NULLPTR);
- d->focusResource = 0;
d->buttonCount = 0;
}
@@ -385,13 +408,12 @@ void QWaylandPointer::pointerFocusChanged(QWaylandView *newFocus, QWaylandView *
Q_D(QWaylandPointer);
d->localPosition = QPointF();
d->hasSentEnter = false;
- if (d->focusResource && oldFocus) {
+ if (oldFocus) {
uint32_t serial = d->compositor()->nextSerial();
- d->send_leave(d->focusResource, serial, oldFocus->surfaceResource());
+ for (auto resource : d->resourceMap().values(oldFocus->surfaceResource()->client))
+ d->send_leave(resource->handle, serial, oldFocus->surfaceResource());
d->focusDestroyListener.reset();
- d->focusResource = 0;
}
-
}
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandpointer_p.h b/src/compositor/compositor_api/qwaylandpointer_p.h
index f9c247896..0a9ef2329 100644
--- a/src/compositor/compositor_api/qwaylandpointer_p.h
+++ b/src/compositor/compositor_api/qwaylandpointer_p.h
@@ -84,17 +84,19 @@ public:
protected:
void pointer_set_cursor(Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) override;
void pointer_release(Resource *resource) override;
- void pointer_destroy_resource(Resource *resource) override;
private:
+ const QList<Resource *> pointerResourcesForFocusedSurface() const;
+ uint sendButton(Qt::MouseButton button, uint32_t state);
+
QWaylandSeat *seat;
QWaylandOutput *output;
QPointF localPosition;
QPointF spacePosition;
- struct ::wl_resource *focusResource;
bool hasSentEnter;
+ uint enterSerial;
int buttonCount;