cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
246 lines
6.8 KiB
C++
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"
|