[server] Support sub-surfaces from PointerInterface
Summary: The idea behind this change is to make the existance of sub-surfaces an implementation detail for pointer events. The user of the library does not need to care about on which sub-surface the pointer is on. It only needs to care about the main surface and passes the focus to the main surface. Internally the PointerInterface takes care of sending the enter to the sub-surface at the current pointer position. Also whenever the pointer position changes, the PointerInterface evaluates whether it triggered a change for the focused sub-surface and sends enter/leave events accordingly. If the focused sub-surface does not change, it sends motion events as normally, but of course under consideration of the sub-surface position. Overall this means that from pointer usage perspective a user of the library doesn't need to care about the fact that there are sub-surfaces at all. The library does the correct thing for it. Reviewers: #plasma Subscribers: plasma-devel Projects: #plasma Differential Revision: https://phabricator.kde.org/D1329
This commit is contained in:
parent
37851e2e08
commit
84a1d5eadc
2 changed files with 184 additions and 11 deletions
|
@ -32,6 +32,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "../../src/client/registry.h"
|
#include "../../src/client/registry.h"
|
||||||
#include "../../src/client/seat.h"
|
#include "../../src/client/seat.h"
|
||||||
#include "../../src/client/shm_pool.h"
|
#include "../../src/client/shm_pool.h"
|
||||||
|
#include "../../src/client/subcompositor.h"
|
||||||
|
#include "../../src/client/subsurface.h"
|
||||||
#include "../../src/client/touch.h"
|
#include "../../src/client/touch.h"
|
||||||
#include "../../src/server/buffer_interface.h"
|
#include "../../src/server/buffer_interface.h"
|
||||||
#include "../../src/server/compositor_interface.h"
|
#include "../../src/server/compositor_interface.h"
|
||||||
|
@ -40,6 +42,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "../../src/server/keyboard_interface.h"
|
#include "../../src/server/keyboard_interface.h"
|
||||||
#include "../../src/server/pointer_interface.h"
|
#include "../../src/server/pointer_interface.h"
|
||||||
#include "../../src/server/seat_interface.h"
|
#include "../../src/server/seat_interface.h"
|
||||||
|
#include "../../src/server/subcompositor_interface.h"
|
||||||
#include "../../src/server/surface_interface.h"
|
#include "../../src/server/surface_interface.h"
|
||||||
// Wayland
|
// Wayland
|
||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
|
@ -63,6 +66,7 @@ private Q_SLOTS:
|
||||||
void testPointerTransformation();
|
void testPointerTransformation();
|
||||||
void testPointerButton_data();
|
void testPointerButton_data();
|
||||||
void testPointerButton();
|
void testPointerButton();
|
||||||
|
void testPointerSubSurfaceTree();
|
||||||
void testCursor();
|
void testCursor();
|
||||||
void testCursorDamage();
|
void testCursorDamage();
|
||||||
void testKeyboard();
|
void testKeyboard();
|
||||||
|
@ -76,10 +80,12 @@ private:
|
||||||
KWayland::Server::Display *m_display;
|
KWayland::Server::Display *m_display;
|
||||||
KWayland::Server::CompositorInterface *m_compositorInterface;
|
KWayland::Server::CompositorInterface *m_compositorInterface;
|
||||||
KWayland::Server::SeatInterface *m_seatInterface;
|
KWayland::Server::SeatInterface *m_seatInterface;
|
||||||
|
KWayland::Server::SubCompositorInterface *m_subCompositorInterface;
|
||||||
KWayland::Client::ConnectionThread *m_connection;
|
KWayland::Client::ConnectionThread *m_connection;
|
||||||
KWayland::Client::Compositor *m_compositor;
|
KWayland::Client::Compositor *m_compositor;
|
||||||
KWayland::Client::Seat *m_seat;
|
KWayland::Client::Seat *m_seat;
|
||||||
KWayland::Client::ShmPool *m_shm;
|
KWayland::Client::ShmPool *m_shm;
|
||||||
|
KWayland::Client::SubCompositor * m_subCompositor;
|
||||||
KWayland::Client::EventQueue *m_queue;
|
KWayland::Client::EventQueue *m_queue;
|
||||||
QThread *m_thread;
|
QThread *m_thread;
|
||||||
};
|
};
|
||||||
|
@ -91,10 +97,12 @@ TestWaylandSeat::TestWaylandSeat(QObject *parent)
|
||||||
, m_display(nullptr)
|
, m_display(nullptr)
|
||||||
, m_compositorInterface(nullptr)
|
, m_compositorInterface(nullptr)
|
||||||
, m_seatInterface(nullptr)
|
, m_seatInterface(nullptr)
|
||||||
|
, m_subCompositorInterface(nullptr)
|
||||||
, m_connection(nullptr)
|
, m_connection(nullptr)
|
||||||
, m_compositor(nullptr)
|
, m_compositor(nullptr)
|
||||||
, m_seat(nullptr)
|
, m_seat(nullptr)
|
||||||
, m_shm(nullptr)
|
, m_shm(nullptr)
|
||||||
|
, m_subCompositor(nullptr)
|
||||||
, m_queue(nullptr)
|
, m_queue(nullptr)
|
||||||
, m_thread(nullptr)
|
, m_thread(nullptr)
|
||||||
{
|
{
|
||||||
|
@ -115,6 +123,11 @@ void TestWaylandSeat::init()
|
||||||
m_compositorInterface->create();
|
m_compositorInterface->create();
|
||||||
QVERIFY(m_compositorInterface->isValid());
|
QVERIFY(m_compositorInterface->isValid());
|
||||||
|
|
||||||
|
m_subCompositorInterface = m_display->createSubCompositor(m_display);
|
||||||
|
QVERIFY(m_subCompositorInterface);
|
||||||
|
m_subCompositorInterface->create();
|
||||||
|
QVERIFY(m_subCompositorInterface->isValid());
|
||||||
|
|
||||||
// setup connection
|
// setup connection
|
||||||
m_connection = new KWayland::Client::ConnectionThread;
|
m_connection = new KWayland::Client::ConnectionThread;
|
||||||
QSignalSpy connectedSpy(m_connection, SIGNAL(connected()));
|
QSignalSpy connectedSpy(m_connection, SIGNAL(connected()));
|
||||||
|
@ -158,10 +171,19 @@ void TestWaylandSeat::init()
|
||||||
m_shm = new KWayland::Client::ShmPool(this);
|
m_shm = new KWayland::Client::ShmPool(this);
|
||||||
m_shm->setup(registry.bindShm(shmSpy.first().first().value<quint32>(), shmSpy.first().last().value<quint32>()));
|
m_shm->setup(registry.bindShm(shmSpy.first().first().value<quint32>(), shmSpy.first().last().value<quint32>()));
|
||||||
QVERIFY(m_shm->isValid());
|
QVERIFY(m_shm->isValid());
|
||||||
|
|
||||||
|
m_subCompositor = registry.createSubCompositor(registry.interface(KWayland::Client::Registry::Interface::SubCompositor).name,
|
||||||
|
registry.interface(KWayland::Client::Registry::Interface::SubCompositor).version,
|
||||||
|
this);
|
||||||
|
QVERIFY(m_subCompositor->isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestWaylandSeat::cleanup()
|
void TestWaylandSeat::cleanup()
|
||||||
{
|
{
|
||||||
|
if (m_subCompositor) {
|
||||||
|
delete m_subCompositor;
|
||||||
|
m_subCompositor = nullptr;
|
||||||
|
}
|
||||||
if (m_shm) {
|
if (m_shm) {
|
||||||
delete m_shm;
|
delete m_shm;
|
||||||
m_shm = nullptr;
|
m_shm = nullptr;
|
||||||
|
@ -195,6 +217,9 @@ void TestWaylandSeat::cleanup()
|
||||||
delete m_seatInterface;
|
delete m_seatInterface;
|
||||||
m_seatInterface = nullptr;
|
m_seatInterface = nullptr;
|
||||||
|
|
||||||
|
delete m_subCompositorInterface;
|
||||||
|
m_subCompositorInterface = nullptr;
|
||||||
|
|
||||||
delete m_display;
|
delete m_display;
|
||||||
m_display = nullptr;
|
m_display = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -643,6 +668,104 @@ void TestWaylandSeat::testPointerButton()
|
||||||
QCOMPARE(buttonChangedSpy.last().at(3).value<KWayland::Client::Pointer::ButtonState>(), Pointer::ButtonState::Released);
|
QCOMPARE(buttonChangedSpy.last().at(3).value<KWayland::Client::Pointer::ButtonState>(), Pointer::ButtonState::Released);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestWaylandSeat::testPointerSubSurfaceTree()
|
||||||
|
{
|
||||||
|
// this test verifies that pointer motion on a surface with sub-surfaces sends motion enter/leave to the sub-surface
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
using namespace KWayland::Server;
|
||||||
|
|
||||||
|
// first create the pointer
|
||||||
|
QSignalSpy hasPointerChangedSpy(m_seat, &Seat::hasPointerChanged);
|
||||||
|
QVERIFY(hasPointerChangedSpy.isValid());
|
||||||
|
m_seatInterface->setHasPointer(true);
|
||||||
|
QVERIFY(hasPointerChangedSpy.wait());
|
||||||
|
QScopedPointer<Pointer> pointer(m_seat->createPointer());
|
||||||
|
|
||||||
|
// create a sub surface tree
|
||||||
|
// parent surface (100, 100) with one sub surface taking the half of it's size (50, 100)
|
||||||
|
// which has two further children (50, 50) which are overlapping
|
||||||
|
QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
|
||||||
|
QVERIFY(surfaceCreatedSpy.isValid());
|
||||||
|
QScopedPointer<Surface> parentSurface(m_compositor->createSurface());
|
||||||
|
QScopedPointer<Surface> childSurface(m_compositor->createSurface());
|
||||||
|
QScopedPointer<Surface> grandChild1Surface(m_compositor->createSurface());
|
||||||
|
QScopedPointer<Surface> grandChild2Surface(m_compositor->createSurface());
|
||||||
|
QScopedPointer<SubSurface> childSubSurface(m_subCompositor->createSubSurface(childSurface.data(), parentSurface.data()));
|
||||||
|
QScopedPointer<SubSurface> grandChild1SubSurface(m_subCompositor->createSubSurface(grandChild1Surface.data(), childSurface.data()));
|
||||||
|
QScopedPointer<SubSurface> grandChild2SubSurface(m_subCompositor->createSubSurface(grandChild2Surface.data(), childSurface.data()));
|
||||||
|
grandChild2SubSurface->setPosition(QPoint(0, 25));
|
||||||
|
|
||||||
|
// let's map the surfaces
|
||||||
|
auto render = [this] (Surface *s, const QSize &size) {
|
||||||
|
QImage image(size, QImage::Format_ARGB32);
|
||||||
|
image.fill(Qt::black);
|
||||||
|
s->attachBuffer(m_shm->createBuffer(image));
|
||||||
|
s->damage(QRect(QPoint(0, 0), size));
|
||||||
|
s->commit(Surface::CommitFlag::None);
|
||||||
|
};
|
||||||
|
render(grandChild2Surface.data(), QSize(50, 50));
|
||||||
|
render(grandChild1Surface.data(), QSize(50, 50));
|
||||||
|
render(childSurface.data(), QSize(50, 100));
|
||||||
|
render(parentSurface.data(), QSize(100, 100));
|
||||||
|
|
||||||
|
QVERIFY(surfaceCreatedSpy.wait());
|
||||||
|
auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
|
||||||
|
QVERIFY(serverSurface->isMapped());
|
||||||
|
|
||||||
|
// send in pointer events
|
||||||
|
QSignalSpy enteredSpy(pointer.data(), &Pointer::entered);
|
||||||
|
QVERIFY(enteredSpy.isValid());
|
||||||
|
QSignalSpy leftSpy(pointer.data(), &Pointer::left);
|
||||||
|
QVERIFY(leftSpy.isValid());
|
||||||
|
QSignalSpy motionSpy(pointer.data(), &Pointer::motion);
|
||||||
|
QVERIFY(motionSpy.isValid());
|
||||||
|
// first to the grandChild2 in the overlapped area
|
||||||
|
quint32 timestamp = 1;
|
||||||
|
m_seatInterface->setTimestamp(timestamp++);
|
||||||
|
m_seatInterface->setPointerPos(QPointF(25, 50));
|
||||||
|
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||||
|
QVERIFY(enteredSpy.wait());
|
||||||
|
QCOMPARE(enteredSpy.count(), 1);
|
||||||
|
QCOMPARE(leftSpy.count(), 0);
|
||||||
|
QCOMPARE(motionSpy.count(), 0);
|
||||||
|
QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(25, 25));
|
||||||
|
QCOMPARE(pointer->enteredSurface(), grandChild2Surface.data());
|
||||||
|
// a motion on grandchild2
|
||||||
|
m_seatInterface->setTimestamp(timestamp++);
|
||||||
|
m_seatInterface->setPointerPos(QPointF(25, 60));
|
||||||
|
QVERIFY(motionSpy.wait());
|
||||||
|
QCOMPARE(enteredSpy.count(), 1);
|
||||||
|
QCOMPARE(leftSpy.count(), 0);
|
||||||
|
QCOMPARE(motionSpy.count(), 1);
|
||||||
|
QCOMPARE(motionSpy.last().first().toPointF(), QPointF(25, 35));
|
||||||
|
// motion which changes to childSurface
|
||||||
|
m_seatInterface->setTimestamp(timestamp++);
|
||||||
|
m_seatInterface->setPointerPos(QPointF(25, 80));
|
||||||
|
QVERIFY(enteredSpy.wait());
|
||||||
|
QCOMPARE(enteredSpy.count(), 2);
|
||||||
|
QCOMPARE(leftSpy.count(), 1);
|
||||||
|
QCOMPARE(motionSpy.count(), 1);
|
||||||
|
QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(25, 80));
|
||||||
|
QCOMPARE(pointer->enteredSurface(), childSurface.data());
|
||||||
|
// a leave for the whole surface
|
||||||
|
m_seatInterface->setTimestamp(timestamp++);
|
||||||
|
m_seatInterface->setFocusedPointerSurface(nullptr);
|
||||||
|
QVERIFY(leftSpy.wait());
|
||||||
|
QCOMPARE(enteredSpy.count(), 2);
|
||||||
|
QCOMPARE(leftSpy.count(), 2);
|
||||||
|
QCOMPARE(motionSpy.count(), 1);
|
||||||
|
// a new enter on the main surface
|
||||||
|
m_seatInterface->setTimestamp(timestamp++);
|
||||||
|
m_seatInterface->setPointerPos(QPointF(75, 50));
|
||||||
|
m_seatInterface->setFocusedPointerSurface(serverSurface);
|
||||||
|
QVERIFY(enteredSpy.wait());
|
||||||
|
QCOMPARE(enteredSpy.count(), 3);
|
||||||
|
QCOMPARE(leftSpy.count(), 2);
|
||||||
|
QCOMPARE(motionSpy.count(), 1);
|
||||||
|
QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(75, 50));
|
||||||
|
QCOMPARE(pointer->enteredSurface(), parentSurface.data());
|
||||||
|
}
|
||||||
|
|
||||||
void TestWaylandSeat::testCursor()
|
void TestWaylandSeat::testCursor()
|
||||||
{
|
{
|
||||||
using namespace KWayland::Client;
|
using namespace KWayland::Client;
|
||||||
|
@ -1019,6 +1142,7 @@ void TestWaylandSeat::testDestroy()
|
||||||
m_compositor = nullptr;
|
m_compositor = nullptr;
|
||||||
connect(m_connection, &ConnectionThread::connectionDied, m_seat, &Seat::destroy);
|
connect(m_connection, &ConnectionThread::connectionDied, m_seat, &Seat::destroy);
|
||||||
connect(m_connection, &ConnectionThread::connectionDied, m_shm, &ShmPool::destroy);
|
connect(m_connection, &ConnectionThread::connectionDied, m_shm, &ShmPool::destroy);
|
||||||
|
connect(m_connection, &ConnectionThread::connectionDied, m_subCompositor, &SubCompositor::destroy);
|
||||||
connect(m_connection, &ConnectionThread::connectionDied, m_queue, &EventQueue::destroy);
|
connect(m_connection, &ConnectionThread::connectionDied, m_queue, &EventQueue::destroy);
|
||||||
QVERIFY(m_seat->isValid());
|
QVERIFY(m_seat->isValid());
|
||||||
|
|
||||||
|
@ -1028,6 +1152,7 @@ void TestWaylandSeat::testDestroy()
|
||||||
m_display = nullptr;
|
m_display = nullptr;
|
||||||
m_compositorInterface = nullptr;
|
m_compositorInterface = nullptr;
|
||||||
m_seatInterface = nullptr;
|
m_seatInterface = nullptr;
|
||||||
|
m_subCompositorInterface = nullptr;
|
||||||
QVERIFY(connectionDiedSpy.wait());
|
QVERIFY(connectionDiedSpy.wait());
|
||||||
|
|
||||||
// now the seat should be destroyed;
|
// now the seat should be destroyed;
|
||||||
|
|
|
@ -21,6 +21,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "resource_p.h"
|
#include "resource_p.h"
|
||||||
#include "seat_interface.h"
|
#include "seat_interface.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "subcompositor_interface.h"
|
||||||
#include "surface_interface.h"
|
#include "surface_interface.h"
|
||||||
// Wayland
|
// Wayland
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
|
@ -38,9 +39,13 @@ public:
|
||||||
|
|
||||||
SeatInterface *seat;
|
SeatInterface *seat;
|
||||||
SurfaceInterface *focusedSurface = nullptr;
|
SurfaceInterface *focusedSurface = nullptr;
|
||||||
|
QPointer<SurfaceInterface> focusedChildSurface;
|
||||||
QMetaObject::Connection destroyConnection;
|
QMetaObject::Connection destroyConnection;
|
||||||
Cursor *cursor = nullptr;
|
Cursor *cursor = nullptr;
|
||||||
|
|
||||||
|
void sendLeave(SurfaceInterface *surface, quint32 serial);
|
||||||
|
void sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PointerInterface *q_func() {
|
PointerInterface *q_func() {
|
||||||
return reinterpret_cast<PointerInterface *>(q);
|
return reinterpret_cast<PointerInterface *>(q);
|
||||||
|
@ -89,6 +94,36 @@ void PointerInterface::Private::setCursor(quint32 serial, SurfaceInterface *surf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PointerInterface::Private::sendLeave(SurfaceInterface *surface, quint32 serial)
|
||||||
|
{
|
||||||
|
if (!surface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resource && surface->resource()) {
|
||||||
|
wl_pointer_send_leave(resource, serial, surface->resource());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static QPointF surfacePosition(SurfaceInterface *surface) {
|
||||||
|
if (surface && surface->subSurface()) {
|
||||||
|
return surface->subSurface()->position() + surfacePosition(surface->subSurface()->parentSurface().data());
|
||||||
|
}
|
||||||
|
return QPointF();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerInterface::Private::sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial)
|
||||||
|
{
|
||||||
|
if (!surface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QPointF adjustedPos = parentSurfacePosition - surfacePosition(surface);
|
||||||
|
wl_pointer_send_enter(resource, serial,
|
||||||
|
surface->resource(),
|
||||||
|
wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y()));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
const struct wl_pointer_interface PointerInterface::Private::s_interface = {
|
const struct wl_pointer_interface PointerInterface::Private::s_interface = {
|
||||||
setCursorCallback,
|
setCursorCallback,
|
||||||
|
@ -108,8 +143,21 @@ PointerInterface::PointerInterface(SeatInterface *parent, wl_resource *parentRes
|
||||||
}
|
}
|
||||||
if (d->focusedSurface && d->resource) {
|
if (d->focusedSurface && d->resource) {
|
||||||
const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
|
const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
|
||||||
|
auto targetSurface = d->focusedSurface->surfaceAt(pos);
|
||||||
|
if (!targetSurface) {
|
||||||
|
targetSurface = d->focusedSurface;
|
||||||
|
}
|
||||||
|
if (targetSurface != d->focusedChildSurface.data()) {
|
||||||
|
const quint32 serial = d->seat->display()->nextSerial();
|
||||||
|
d->sendLeave(d->focusedChildSurface.data(), serial);
|
||||||
|
d->focusedChildSurface = QPointer<SurfaceInterface>(targetSurface);
|
||||||
|
d->sendEnter(targetSurface, pos, serial);
|
||||||
|
d->client->flush();
|
||||||
|
} else {
|
||||||
|
const QPointF adjustedPos = pos - surfacePosition(d->focusedChildSurface);
|
||||||
wl_pointer_send_motion(d->resource, d->seat->timestamp(),
|
wl_pointer_send_motion(d->resource, d->seat->timestamp(),
|
||||||
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
|
wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -119,14 +167,11 @@ PointerInterface::~PointerInterface() = default;
|
||||||
void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
|
void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
|
||||||
{
|
{
|
||||||
Q_D();
|
Q_D();
|
||||||
if (d->focusedSurface) {
|
d->sendLeave(d->focusedChildSurface.data(), serial);
|
||||||
if (d->resource && d->focusedSurface->resource()) {
|
|
||||||
wl_pointer_send_leave(d->resource, serial, d->focusedSurface->resource());
|
|
||||||
}
|
|
||||||
disconnect(d->destroyConnection);
|
disconnect(d->destroyConnection);
|
||||||
}
|
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
d->focusedSurface = nullptr;
|
d->focusedSurface = nullptr;
|
||||||
|
d->focusedChildSurface.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->focusedSurface = surface;
|
d->focusedSurface = surface;
|
||||||
|
@ -134,13 +179,16 @@ void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 seri
|
||||||
[this] {
|
[this] {
|
||||||
Q_D();
|
Q_D();
|
||||||
d->focusedSurface = nullptr;
|
d->focusedSurface = nullptr;
|
||||||
|
d->focusedChildSurface.clear();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
|
const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
|
||||||
wl_pointer_send_enter(d->resource, serial,
|
d->focusedChildSurface = QPointer<SurfaceInterface>(d->focusedSurface->surfaceAt(pos));
|
||||||
d->focusedSurface->resource(),
|
if (!d->focusedChildSurface) {
|
||||||
wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
|
d->focusedChildSurface = QPointer<SurfaceInterface>(d->focusedSurface);
|
||||||
|
}
|
||||||
|
d->sendEnter(d->focusedChildSurface.data(), pos, serial);
|
||||||
d->client->flush();
|
d->client->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue