diff --git a/src/server/seat_interface.cpp b/src/server/seat_interface.cpp --- a/src/server/seat_interface.cpp +++ b/src/server/seat_interface.cpp @@ -209,9 +209,9 @@ } } -PointerInterface *SeatInterface::Private::pointerForSurface(SurfaceInterface *surface) const +QVector SeatInterface::Private::pointersForSurface(SurfaceInterface *surface) const { - return interfaceForSurface(surface, pointers); + return interfacesForSurface(surface, pointers); } QVector SeatInterface::Private::keyboardsForSurface(SurfaceInterface *surface) const @@ -433,18 +433,20 @@ 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 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ 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 @@ 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 @@ 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())); - - wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); + 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((*it)->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); + } #endif } @@ -1160,14 +1179,16 @@ 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 @@ } 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); diff --git a/src/server/seat_interface_p.h b/src/server/seat_interface_p.h --- a/src/server/seat_interface_p.h +++ b/src/server/seat_interface_p.h @@ -43,7 +43,7 @@ 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 pointersForSurface(SurfaceInterface *surface) const; QVector keyboardsForSurface(SurfaceInterface *surface) const; TouchInterface *touchForSurface(SurfaceInterface *surface) const; DataDeviceInterface *dataDeviceForSurface(SurfaceInterface *surface) const; @@ -77,7 +77,7 @@ QPointF pos; struct Focus { SurfaceInterface *surface = nullptr; - PointerInterface *pointer = nullptr; + QVector pointers; QMetaObject::Connection destroyConnection; QPointF offset = QPointF(); QMatrix4x4 transformation;