[server] Send pointer events to all wl_pointer resources of a client

Summary:
This is what Weston does. With this change clients can create
multiple wl_pointer instances and thus get events reported to all of them.
This will be needed to e.g. support drag on empty area in Breeze on Wayland.

A similar change was done for wl_keyboard already in 25dbc84d.

Test Plan: Seat auto test still passes

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3016
This commit is contained in:
Martin Gräßlin 2016-10-11 08:04:27 +02:00
parent 9e5177cb36
commit 97afd2658d
2 changed files with 69 additions and 46 deletions

View file

@ -209,9 +209,9 @@ QVector<T *> interfacesForSurface(SurfaceInterface *surface, const QVector<T*> &
}
}
PointerInterface *SeatInterface::Private::pointerForSurface(SurfaceInterface *surface) const
QVector<PointerInterface *> SeatInterface::Private::pointersForSurface(SurfaceInterface *surface) const
{
return interfaceForSurface(surface, pointers);
return interfacesForSurface(surface, pointers);
}
QVector<KeyboardInterface *> SeatInterface::Private::keyboardsForSurface(SurfaceInterface *surface) const
@ -433,18 +433,20 @@ void SeatInterface::Private::getPointer(wl_client *client, wl_resource *resource
pointers << pointer;
if (globalPointer.focus.surface && globalPointer.focus.surface->client() == clientConnection) {
// this is a pointer for the currently focused pointer surface
if (!globalPointer.focus.pointer) {
globalPointer.focus.pointer = pointer;
pointer->setFocusedSurface(globalPointer.focus.surface, globalPointer.focus.serial);
globalPointer.focus.pointers << pointer;
pointer->setFocusedSurface(globalPointer.focus.surface, globalPointer.focus.serial);
if (globalPointer.focus.pointers.count() == 1) {
// got a new pointer
emit q->focusedPointerChanged(pointer);
}
}
QObject::connect(pointer, &QObject::destroyed, q,
[pointer,this] {
pointers.removeAt(pointers.indexOf(pointer));
if (globalPointer.focus.pointer == pointer) {
globalPointer.focus.pointer = nullptr;
emit q->focusedPointerChanged(nullptr);
if (globalPointer.focus.pointers.removeOne(pointer)) {
if (globalPointer.focus.pointers.isEmpty()) {
emit q->focusedPointerChanged(nullptr);
}
}
}
);
@ -647,19 +649,16 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM
return;
}
const quint32 serial = d->display->nextSerial();
if (d->globalPointer.focus.pointer) {
d->globalPointer.focus.pointer->setFocusedSurface(nullptr, serial);
for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
(*it)->setFocusedSurface(nullptr, serial);
}
if (d->globalPointer.focus.surface) {
disconnect(d->globalPointer.focus.destroyConnection);
}
d->globalPointer.focus = Private::Pointer::Focus();
d->globalPointer.focus.surface = surface;
PointerInterface *p = d->pointerForSurface(surface);
if (p && !p->resource()) {
p = nullptr;
}
d->globalPointer.focus.pointer = p;
auto p = d->pointersForSurface(surface);
d->globalPointer.focus.pointers = p;
if (d->globalPointer.focus.surface) {
d->globalPointer.focus.destroyConnection = connect(surface, &QObject::destroyed, this,
[this] {
@ -672,17 +671,24 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM
d->globalPointer.focus.transformation = transformation;
d->globalPointer.focus.serial = serial;
}
emit focusedPointerChanged(p);
if (!p) {
if (p.isEmpty()) {
emit focusedPointerChanged(nullptr);
return;
}
p->setFocusedSurface(surface, serial);
// TODO: signal with all pointers
emit focusedPointerChanged(p.first());
for (auto it = p.constBegin(), end = p.constEnd(); it != end; ++it) {
(*it)->setFocusedSurface(surface, serial);
}
}
PointerInterface *SeatInterface::focusedPointer() const
{
Q_D();
return d->globalPointer.focus.pointer;
if (d->globalPointer.focus.pointers.isEmpty()) {
return nullptr;
}
return d->globalPointer.focus.pointers.first();
}
void SeatInterface::setFocusedPointerSurfacePosition(const QPointF &surfacePosition)
@ -767,8 +773,10 @@ void SeatInterface::pointerAxis(Qt::Orientation orientation, quint32 delta)
// ignore
return;
}
if (d->globalPointer.focus.pointer && d->globalPointer.focus.surface) {
d->globalPointer.focus.pointer->axis(orientation, delta);
if (d->globalPointer.focus.surface) {
for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
(*it)->axis(orientation, delta);
}
}
}
@ -791,12 +799,17 @@ void SeatInterface::pointerButtonPressed(quint32 button)
// ignore
return;
}
if (d->globalPointer.focus.pointer && d->globalPointer.focus.surface) {
d->globalPointer.focus.pointer->buttonPressed(button, serial);
if (d->globalPointer.focus.surface) {
for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
(*it)->buttonPressed(button, serial);
}
if (d->globalPointer.focus.surface == d->keys.focus.surface) {
// update the focused child surface
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->d_func()->focusChildSurface(d->globalPointer.focus.pointer->d_func()->focusedChildSurface, serial);
auto p = focusedPointer();
if (p) {
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->d_func()->focusChildSurface(p->d_func()->focusedChildSurface, serial);
}
}
}
}
@ -826,8 +839,10 @@ void SeatInterface::pointerButtonReleased(quint32 button)
d->endDrag(serial);
return;
}
if (d->globalPointer.focus.pointer && d->globalPointer.focus.surface) {
d->globalPointer.focus.pointer->buttonReleased(button, serial);
if (d->globalPointer.focus.surface) {
for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
(*it)->buttonReleased(button, serial);
}
}
}
@ -849,8 +864,10 @@ quint32 SeatInterface::pointerButtonSerial(quint32 button) const
void SeatInterface::relativePointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds)
{
Q_D();
if (d->globalPointer.focus.pointer && d->globalPointer.focus.surface) {
d->globalPointer.focus.pointer->relativeMotion(delta, deltaNonAccelerated, microseconds);
if (d->globalPointer.focus.surface) {
for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
(*it)->relativeMotion(delta, deltaNonAccelerated, microseconds);
}
}
}
@ -1135,18 +1152,20 @@ qint32 SeatInterface::touchDown(const QPointF &globalPosition)
d->touchInterface.focus.touch->down(id, serial, globalPosition - d->touchInterface.focus.offset);
} else if (id == 0 && focusedTouchSurface()) {
#if HAVE_LINUX_INPUT_H
auto p = d->pointerForSurface(focusedTouchSurface());
if (!p) {
auto p = d->pointersForSurface(focusedTouchSurface());
if (p.isEmpty()) {
return id;
}
const QPointF pos = globalPosition - d->touchInterface.focus.offset;
wl_pointer_send_enter(p->resource(), serial,
focusedTouchSurface()->resource(),
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
wl_pointer_send_motion(p->resource(), timestamp(),
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
for (auto it = p.constBegin(), end = p.constEnd(); it != end; ++it) {
wl_pointer_send_enter((*it)->resource(), serial,
focusedTouchSurface()->resource(),
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
wl_pointer_send_motion((*it)->resource(), timestamp(),
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
wl_pointer_send_button((*it)->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
}
#endif
}
@ -1160,14 +1179,16 @@ void SeatInterface::touchMove(qint32 id, const QPointF &globalPosition)
if (d->touchInterface.focus.touch && d->touchInterface.focus.surface) {
d->touchInterface.focus.touch->move(id, globalPosition - d->touchInterface.focus.offset);
} else if (id == 0 && focusedTouchSurface()) {
auto p = d->pointerForSurface(focusedTouchSurface());
if (!p) {
auto p = d->pointersForSurface(focusedTouchSurface());
if (p.isEmpty()) {
return;
}
const QPointF pos = globalPosition - d->touchInterface.focus.offset;
wl_pointer_send_motion(p->resource(), timestamp(),
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
for (auto it = p.constBegin(), end = p.constEnd(); it != end; ++it) {
wl_pointer_send_motion((*it)->resource(), timestamp(),
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
}
}
}
@ -1180,12 +1201,14 @@ void SeatInterface::touchUp(qint32 id)
} else if (id == 0 && focusedTouchSurface()) {
#if HAVE_LINUX_INPUT_H
const quint32 serial = display()->nextSerial();
auto p = d->pointerForSurface(focusedTouchSurface());
if (!p) {
auto p = d->pointersForSurface(focusedTouchSurface());
if (p.isEmpty()) {
return;
}
wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
for (auto it = p.constBegin(), end = p.constEnd(); it != end; ++it) {
wl_pointer_send_button((*it)->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
}
#endif
}
d->touchInterface.ids.removeAll(id);

View file

@ -43,7 +43,7 @@ public:
void bind(wl_client *client, uint32_t version, uint32_t id) override;
void sendCapabilities(wl_resource *r);
void sendName(wl_resource *r);
PointerInterface *pointerForSurface(SurfaceInterface *surface) const;
QVector<PointerInterface *> pointersForSurface(SurfaceInterface *surface) const;
QVector<KeyboardInterface *> keyboardsForSurface(SurfaceInterface *surface) const;
TouchInterface *touchForSurface(SurfaceInterface *surface) const;
DataDeviceInterface *dataDeviceForSurface(SurfaceInterface *surface) const;
@ -77,7 +77,7 @@ public:
QPointF pos;
struct Focus {
SurfaceInterface *surface = nullptr;
PointerInterface *pointer = nullptr;
QVector<PointerInterface *> pointers;
QMetaObject::Connection destroyConnection;
QPointF offset = QPointF();
QMatrix4x4 transformation;