wayland: Send wl_pointer leave before data_device enter
SeatInterface currently has a separation of kwin's focus scope to pointer input with early return guards in notifyPointerEnter and notifyPointerLeave where clients don't get pointer events. However we don't update the initial state when a drag is started, this patch notifies sends a pointer leave to the new drag target before the data_device enter so things are consistent. This also brings it in line with Weston and Mutter. notifyPointerLeave has it's early return removed as for wayland windows as we know nothing will have pointer focus.
This commit is contained in:
parent
8a9cb06b41
commit
5386360928
3 changed files with 27 additions and 18 deletions
|
@ -274,8 +274,6 @@ void TestDragAndDrop::testPointerDragAndDrop()
|
|||
|
||||
// verify that we did not get any further input events
|
||||
QVERIFY(pointerMotionSpy.isEmpty());
|
||||
// the release event is sent primarily for xwayland
|
||||
QCOMPARE(buttonPressSpy.count(), 2);
|
||||
}
|
||||
|
||||
void TestDragAndDrop::testTouchDragAndDrop()
|
||||
|
@ -390,6 +388,8 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
QVERIFY(buttonPressSpy.wait());
|
||||
QCOMPARE(buttonPressSpy.first().at(1).value<quint32>(), quint32(2));
|
||||
|
||||
QSignalSpy pointerLeftSpy(m_pointer, &KWayland::Client::Pointer::left);
|
||||
|
||||
// add some signal spies for client side
|
||||
QSignalSpy dragEnteredSpy(m_dataDevice, &KWayland::Client::DataDevice::dragEntered);
|
||||
QSignalSpy dragMotionSpy(m_dataDevice, &KWayland::Client::DataDevice::dragMotion);
|
||||
|
@ -401,11 +401,13 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
m_dataSource->setDragAndDropActions(KWayland::Client::DataDeviceManager::DnDAction::Copy | KWayland::Client::DataDeviceManager::DnDAction::Move);
|
||||
m_dataDevice->startDrag(buttonPressSpy.first().first().value<quint32>(), m_dataSource, s.get());
|
||||
QVERIFY(dragStartedSpy.wait());
|
||||
|
||||
QCOMPARE(m_seatInterface->dragSurface(), serverSurface);
|
||||
QCOMPARE(m_seatInterface->dragSurfaceTransformation(), QMatrix4x4());
|
||||
QVERIFY(!m_seatInterface->dragIcon());
|
||||
QCOMPARE(SeatInterfacePrivate::get(m_seatInterface)->drag.dragImplicitGrabSerial, buttonPressSpy.first().first().value<quint32>());
|
||||
QVERIFY(dragEnteredSpy.wait());
|
||||
QVERIFY(pointerLeftSpy.wait());
|
||||
QVERIFY(dragEnteredSpy.count() || dragEnteredSpy.wait());
|
||||
QCOMPARE(dragEnteredSpy.count(), 1);
|
||||
QCOMPARE(dragEnteredSpy.first().first().value<quint32>(), m_display->serial());
|
||||
QCOMPARE(dragEnteredSpy.first().last().toPointF(), QPointF(0, 0));
|
||||
|
@ -452,7 +454,6 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
|
||||
// verify that we did not get any further input events
|
||||
QVERIFY(pointerMotionSpy.isEmpty());
|
||||
QCOMPARE(buttonPressSpy.count(), 2);
|
||||
}
|
||||
|
||||
void TestDragAndDrop::testPointerEventsIgnored()
|
||||
|
@ -533,9 +534,7 @@ void TestDragAndDrop::testPointerEventsIgnored()
|
|||
QCOMPARE(axisSpy.count(), 1);
|
||||
QCOMPARE(pointerMotionSpy.count(), 1);
|
||||
QCOMPARE(pointerEnteredSpy.count(), 1);
|
||||
QVERIFY(pointerLeftSpy.isEmpty());
|
||||
// the release event is sent primary for xwayland, see BUG 465444
|
||||
QCOMPARE(buttonSpy.count(), 2);
|
||||
QCOMPARE(pointerLeftSpy.count(), 1);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestDragAndDrop)
|
||||
|
|
|
@ -268,6 +268,15 @@ void SeatInterfacePrivate::cancelDrag()
|
|||
Q_EMIT q->dragEnded();
|
||||
}
|
||||
|
||||
bool SeatInterfacePrivate::dragInhibitsPointer(SurfaceInterface *surface) const
|
||||
{
|
||||
if (drag.mode != SeatInterfacePrivate::Drag::Mode::Pointer) {
|
||||
return false;
|
||||
}
|
||||
const bool targetHasDataDevice = !dataDevicesForSurface(surface).isEmpty();
|
||||
return targetHasDataDevice;
|
||||
}
|
||||
|
||||
void SeatInterfacePrivate::endDrag()
|
||||
{
|
||||
QObject::disconnect(drag.dragSourceDestroyConnection);
|
||||
|
@ -445,11 +454,8 @@ void SeatInterface::notifyPointerMotion(const QPointF &pos)
|
|||
if (!focusedSurface) {
|
||||
return;
|
||||
}
|
||||
if (isDragPointer()) {
|
||||
// data device will handle it directly
|
||||
// for xwayland cases we still want to send pointer events
|
||||
if (!d->dataDevicesForSurface(focusedSurface).isEmpty())
|
||||
return;
|
||||
if (d->dragInhibitsPointer(focusedSurface)) {
|
||||
return;
|
||||
}
|
||||
if (focusedSurface->lockedPointer() && focusedSurface->lockedPointer()->isLocked()) {
|
||||
return;
|
||||
|
@ -520,6 +526,9 @@ void SeatInterface::setDragTarget(AbstractDropHandler *dropTarget,
|
|||
surfaceInputTransformation.scale(surface->scaleOverride());
|
||||
d->drag.surface = surface;
|
||||
d->drag.transformation = surfaceInputTransformation;
|
||||
if (d->dragInhibitsPointer(surface)) {
|
||||
notifyPointerLeave();
|
||||
}
|
||||
d->drag.target->updateDragTarget(surface, serial);
|
||||
} else {
|
||||
d->drag.surface = nullptr;
|
||||
|
@ -558,7 +567,7 @@ void SeatInterface::notifyPointerEnter(SurfaceInterface *surface, const QPointF
|
|||
if (!d->pointer) {
|
||||
return;
|
||||
}
|
||||
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
|
||||
if (d->dragInhibitsPointer(surface)) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
@ -597,10 +606,6 @@ void SeatInterface::notifyPointerLeave()
|
|||
if (!d->pointer) {
|
||||
return;
|
||||
}
|
||||
if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->globalPointer.focus.surface) {
|
||||
disconnect(d->globalPointer.focus.destroyConnection);
|
||||
|
@ -1352,6 +1357,7 @@ void SeatInterface::startDrag(AbstractDataSource *dragSource, SurfaceInterface *
|
|||
// no implicit grab, abort drag
|
||||
return;
|
||||
}
|
||||
|
||||
d->drag.dragImplicitGrabSerial = dragSerial;
|
||||
|
||||
// set initial drag target to ourself
|
||||
|
@ -1369,7 +1375,10 @@ void SeatInterface::startDrag(AbstractDataSource *dragSource, SurfaceInterface *
|
|||
d->drag.target = d->dataDevicesForSurface(originSurface)[0];
|
||||
}
|
||||
if (d->drag.target) {
|
||||
d->drag.target->updateDragTarget(originSurface, dragSerial);
|
||||
if (d->dragInhibitsPointer(originSurface)) {
|
||||
notifyPointerLeave();
|
||||
}
|
||||
d->drag.target->updateDragTarget(originSurface, display()->nextSerial());
|
||||
}
|
||||
Q_EMIT dragStarted();
|
||||
Q_EMIT dragSurfaceChanged();
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
void registerDataControlDevice(DataControlDeviceV1Interface *dataDevice);
|
||||
void endDrag();
|
||||
void cancelDrag();
|
||||
bool dragInhibitsPointer(SurfaceInterface *surface) const;
|
||||
|
||||
SeatInterface *q;
|
||||
QPointer<Display> display;
|
||||
|
|
Loading…
Reference in a new issue