Files
RedBear-OS/local/recipes/kde/kf6-kwayland/source/src/client/pointer.cpp
T
2026-04-14 10:51:06 +01:00

246 lines
6.8 KiB
C++

/*
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "pointer.h"
#include "surface.h"
#include "wayland_pointer_p.h"
// Qt
#include <QPointF>
#include <QPointer>
// wayland
#include <wayland-client-protocol.h>
namespace KWayland
{
namespace Client
{
static Pointer::Axis wlAxisToPointerAxis(uint32_t axis)
{
switch (axis) {
case WL_POINTER_AXIS_VERTICAL_SCROLL:
return Pointer::Axis::Vertical;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
return Pointer::Axis::Horizontal;
}
Q_UNREACHABLE();
}
class Q_DECL_HIDDEN Pointer::Private
{
public:
Private(Pointer *q);
void setup(wl_pointer *p);
WaylandPointer<wl_pointer, wl_pointer_release> pointer;
QPointer<Surface> enteredSurface;
quint32 enteredSerial = 0;
private:
void enter(uint32_t serial, wl_surface *surface, const QPointF &relativeToSurface);
void leave(uint32_t serial);
static void enterCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy);
static void leaveCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface);
static void motionCallback(void *data, wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy);
static void buttonCallback(void *data, wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
static void axisCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value);
static void frameCallback(void *data, wl_pointer *pointer);
static void axisSourceCallback(void *data, wl_pointer *pointer, uint32_t axis_source);
static void axisStopCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis);
static void axisDiscreteCallback(void *data, wl_pointer *pointer, uint32_t axis, int32_t discrete);
Pointer *q;
static const wl_pointer_listener s_listener;
};
Pointer::Private::Private(Pointer *q)
: q(q)
{
}
void Pointer::Private::setup(wl_pointer *p)
{
Q_ASSERT(p);
Q_ASSERT(!pointer);
pointer.setup(p);
wl_pointer_add_listener(pointer, &s_listener, this);
}
const wl_pointer_listener Pointer::Private::s_listener =
{enterCallback, leaveCallback, motionCallback, buttonCallback, axisCallback, frameCallback, axisSourceCallback, axisStopCallback, axisDiscreteCallback};
Pointer::Pointer(QObject *parent)
: QObject(parent)
, d(new Private(this))
{
}
Pointer::~Pointer()
{
release();
}
void Pointer::release()
{
d->pointer.release();
}
void Pointer::destroy()
{
d->pointer.destroy();
}
void Pointer::setup(wl_pointer *pointer)
{
d->setup(pointer);
}
void Pointer::Private::enterCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
p->enter(serial, surface, QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy)));
}
void Pointer::Private::enter(uint32_t serial, wl_surface *surface, const QPointF &relativeToSurface)
{
enteredSurface = QPointer<Surface>(Surface::get(surface));
enteredSerial = serial;
Q_EMIT q->entered(serial, relativeToSurface);
}
void Pointer::Private::leaveCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
Q_UNUSED(surface)
p->leave(serial);
}
void Pointer::Private::leave(uint32_t serial)
{
enteredSurface.clear();
Q_EMIT q->left(serial);
}
void Pointer::Private::motionCallback(void *data, wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
Q_EMIT p->q->motion(QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy)), time);
}
void Pointer::Private::buttonCallback(void *data, wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
auto toState = [state] {
if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
return ButtonState::Released;
} else {
return ButtonState::Pressed;
}
};
Q_EMIT p->q->buttonStateChanged(serial, time, button, toState());
}
void Pointer::Private::axisCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
Q_EMIT p->q->axisChanged(time, wlAxisToPointerAxis(axis), wl_fixed_to_double(value));
}
void Pointer::Private::frameCallback(void *data, wl_pointer *pointer)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
Q_EMIT p->q->frame();
}
void Pointer::Private::axisSourceCallback(void *data, wl_pointer *pointer, uint32_t axis_source)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
AxisSource source;
switch (axis_source) {
case WL_POINTER_AXIS_SOURCE_WHEEL:
source = AxisSource::Wheel;
break;
case WL_POINTER_AXIS_SOURCE_FINGER:
source = AxisSource::Finger;
break;
case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
source = AxisSource::Continuous;
break;
case WL_POINTER_AXIS_SOURCE_WHEEL_TILT:
source = AxisSource::WheelTilt;
break;
default:
Q_UNREACHABLE();
break;
}
Q_EMIT p->q->axisSourceChanged(source);
}
void Pointer::Private::axisStopCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
Q_EMIT p->q->axisStopped(time, wlAxisToPointerAxis(axis));
}
void Pointer::Private::axisDiscreteCallback(void *data, wl_pointer *pointer, uint32_t axis, int32_t discrete)
{
auto p = reinterpret_cast<Pointer::Private *>(data);
Q_ASSERT(p->pointer == pointer);
Q_EMIT p->q->axisDiscreteChanged(wlAxisToPointerAxis(axis), discrete);
}
void Pointer::setCursor(Surface *surface, const QPoint &hotspot)
{
Q_ASSERT(isValid());
wl_surface *s = nullptr;
if (surface) {
s = *surface;
}
wl_pointer_set_cursor(d->pointer, d->enteredSerial, s, hotspot.x(), hotspot.y());
}
void Pointer::hideCursor()
{
setCursor(nullptr);
}
Surface *Pointer::enteredSurface()
{
return d->enteredSurface.data();
}
Surface *Pointer::enteredSurface() const
{
return d->enteredSurface.data();
}
bool Pointer::isValid() const
{
return d->pointer.isValid();
}
Pointer::operator wl_pointer *() const
{
return d->pointer;
}
Pointer::operator wl_pointer *()
{
return d->pointer;
}
}
}
#include "moc_pointer.cpp"