File indexing completed on 2024-11-10 04:56:31

0001 /*
0002     SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "fakeinputbackend.h"
0008 #include "fakeinputdevice.h"
0009 #include "wayland/display.h"
0010 
0011 #include "wayland/qwayland-server-fake-input.h"
0012 
0013 namespace KWin
0014 {
0015 
0016 static const quint32 s_version = 5;
0017 
0018 class FakeInputBackendPrivate : public QtWaylandServer::org_kde_kwin_fake_input
0019 {
0020 public:
0021     FakeInputBackendPrivate(FakeInputBackend *q, Display *display);
0022 
0023     FakeInputDevice *findDevice(Resource *resource);
0024     std::chrono::microseconds currentTime() const;
0025 
0026     FakeInputBackend *q;
0027     Display *display;
0028     std::map<Resource *, std::unique_ptr<FakeInputDevice>> devices;
0029     static QList<quint32> touchIds;
0030 
0031 protected:
0032     void org_kde_kwin_fake_input_bind_resource(Resource *resource) override;
0033     void org_kde_kwin_fake_input_destroy_resource(Resource *resource) override;
0034     void org_kde_kwin_fake_input_authenticate(Resource *resource, const QString &application, const QString &reason) override;
0035     void org_kde_kwin_fake_input_pointer_motion(Resource *resource, wl_fixed_t delta_x, wl_fixed_t delta_y) override;
0036     void org_kde_kwin_fake_input_button(Resource *resource, uint32_t button, uint32_t state) override;
0037     void org_kde_kwin_fake_input_axis(Resource *resource, uint32_t axis, wl_fixed_t value) override;
0038     void org_kde_kwin_fake_input_touch_down(Resource *resource, uint32_t id, wl_fixed_t x, wl_fixed_t y) override;
0039     void org_kde_kwin_fake_input_touch_motion(Resource *resource, uint32_t id, wl_fixed_t x, wl_fixed_t y) override;
0040     void org_kde_kwin_fake_input_touch_up(Resource *resource, uint32_t id) override;
0041     void org_kde_kwin_fake_input_touch_cancel(Resource *resource) override;
0042     void org_kde_kwin_fake_input_touch_frame(Resource *resource) override;
0043     void org_kde_kwin_fake_input_pointer_motion_absolute(Resource *resource, wl_fixed_t x, wl_fixed_t y) override;
0044     void org_kde_kwin_fake_input_keyboard_key(Resource *resource, uint32_t button, uint32_t state) override;
0045     void org_kde_kwin_fake_input_destroy(Resource *resource) override;
0046 };
0047 
0048 QList<quint32> FakeInputBackendPrivate::touchIds = QList<quint32>();
0049 
0050 FakeInputBackendPrivate::FakeInputBackendPrivate(FakeInputBackend *q, Display *display)
0051     : q(q)
0052     , display(display)
0053 {
0054 }
0055 
0056 void FakeInputBackendPrivate::org_kde_kwin_fake_input_bind_resource(Resource *resource)
0057 {
0058     auto device = new FakeInputDevice(q);
0059     devices[resource] = std::unique_ptr<FakeInputDevice>(device);
0060     Q_EMIT q->deviceAdded(device);
0061 }
0062 
0063 void FakeInputBackendPrivate::org_kde_kwin_fake_input_destroy(Resource *resource)
0064 {
0065     wl_resource_destroy(resource->handle);
0066 }
0067 
0068 void FakeInputBackendPrivate::org_kde_kwin_fake_input_destroy_resource(Resource *resource)
0069 {
0070     auto it = devices.find(resource);
0071     if (it != devices.end()) {
0072         const auto [resource, device] = std::move(*it);
0073         devices.erase(it);
0074         Q_EMIT q->deviceRemoved(device.get());
0075     }
0076 }
0077 
0078 FakeInputDevice *FakeInputBackendPrivate::findDevice(Resource *resource)
0079 {
0080     return devices[resource].get();
0081 }
0082 
0083 std::chrono::microseconds FakeInputBackendPrivate::currentTime() const
0084 {
0085     return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
0086 }
0087 
0088 void FakeInputBackendPrivate::org_kde_kwin_fake_input_authenticate(Resource *resource, const QString &application, const QString &reason)
0089 {
0090     FakeInputDevice *device = findDevice(resource);
0091     if (device) {
0092         // TODO: make secure
0093         device->setAuthenticated(true);
0094     }
0095 }
0096 
0097 void FakeInputBackendPrivate::org_kde_kwin_fake_input_pointer_motion(Resource *resource, wl_fixed_t delta_x, wl_fixed_t delta_y)
0098 {
0099     FakeInputDevice *device = findDevice(resource);
0100     if (!device->isAuthenticated()) {
0101         return;
0102     }
0103     const QPointF delta(wl_fixed_to_double(delta_x), wl_fixed_to_double(delta_y));
0104 
0105     Q_EMIT device->pointerMotion(delta, delta, currentTime(), device);
0106     Q_EMIT device->pointerFrame(device);
0107 }
0108 
0109 void FakeInputBackendPrivate::org_kde_kwin_fake_input_button(Resource *resource, uint32_t button, uint32_t state)
0110 {
0111     FakeInputDevice *device = findDevice(resource);
0112     if (!device->isAuthenticated()) {
0113         return;
0114     }
0115 
0116     InputRedirection::PointerButtonState nativeState;
0117     switch (state) {
0118     case WL_POINTER_BUTTON_STATE_PRESSED:
0119         nativeState = InputRedirection::PointerButtonPressed;
0120         break;
0121     case WL_POINTER_BUTTON_STATE_RELEASED:
0122         nativeState = InputRedirection::PointerButtonReleased;
0123         break;
0124     default:
0125         return;
0126     }
0127 
0128     Q_EMIT device->pointerButtonChanged(button, nativeState, currentTime(), device);
0129     Q_EMIT device->pointerFrame(device);
0130 }
0131 
0132 void FakeInputBackendPrivate::org_kde_kwin_fake_input_axis(Resource *resource, uint32_t axis, wl_fixed_t value)
0133 {
0134     FakeInputDevice *device = findDevice(resource);
0135     if (!device->isAuthenticated()) {
0136         return;
0137     }
0138 
0139     InputRedirection::PointerAxis nativeAxis;
0140     switch (axis) {
0141     case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
0142         nativeAxis = InputRedirection::PointerAxisHorizontal;
0143         break;
0144 
0145     case WL_POINTER_AXIS_VERTICAL_SCROLL:
0146         nativeAxis = InputRedirection::PointerAxisVertical;
0147         break;
0148 
0149     default:
0150         return;
0151     }
0152 
0153     Q_EMIT device->pointerAxisChanged(nativeAxis, wl_fixed_to_double(value), 0, InputRedirection::PointerAxisSourceUnknown, currentTime(), device);
0154     Q_EMIT device->pointerFrame(device);
0155 }
0156 
0157 void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_down(Resource *resource, uint32_t id, wl_fixed_t x, wl_fixed_t y)
0158 {
0159     FakeInputDevice *device = findDevice(resource);
0160     if (!device->isAuthenticated()) {
0161         return;
0162     }
0163     if (touchIds.contains(id)) {
0164         return;
0165     }
0166     touchIds << id;
0167     Q_EMIT device->touchDown(id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), currentTime(), device);
0168 }
0169 
0170 void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_motion(Resource *resource, uint32_t id, wl_fixed_t x, wl_fixed_t y)
0171 {
0172     FakeInputDevice *device = findDevice(resource);
0173     if (!device->isAuthenticated()) {
0174         return;
0175     }
0176     if (!touchIds.contains(id)) {
0177         return;
0178     }
0179     Q_EMIT device->touchMotion(id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), currentTime(), device);
0180 }
0181 
0182 void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_up(Resource *resource, uint32_t id)
0183 {
0184     FakeInputDevice *device = findDevice(resource);
0185     if (!device->isAuthenticated()) {
0186         return;
0187     }
0188     if (!touchIds.contains(id)) {
0189         return;
0190     }
0191     touchIds.removeOne(id);
0192     Q_EMIT device->touchUp(id, currentTime(), device);
0193 }
0194 
0195 void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_cancel(Resource *resource)
0196 {
0197     FakeInputDevice *device = findDevice(resource);
0198     if (!device->isAuthenticated()) {
0199         return;
0200     }
0201     touchIds.clear();
0202     Q_EMIT device->touchCanceled(device);
0203 }
0204 
0205 void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_frame(Resource *resource)
0206 {
0207     FakeInputDevice *device = findDevice(resource);
0208     if (!device->isAuthenticated()) {
0209         return;
0210     }
0211     Q_EMIT device->touchFrame(device);
0212 }
0213 
0214 void FakeInputBackendPrivate::org_kde_kwin_fake_input_pointer_motion_absolute(Resource *resource, wl_fixed_t x, wl_fixed_t y)
0215 {
0216     FakeInputDevice *device = findDevice(resource);
0217     if (!device->isAuthenticated()) {
0218         return;
0219     }
0220 
0221     Q_EMIT device->pointerMotionAbsolute(QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), currentTime(), device);
0222     Q_EMIT device->pointerFrame(device);
0223 }
0224 
0225 void FakeInputBackendPrivate::org_kde_kwin_fake_input_keyboard_key(Resource *resource, uint32_t button, uint32_t state)
0226 {
0227     FakeInputDevice *device = findDevice(resource);
0228     if (!device->isAuthenticated()) {
0229         return;
0230     }
0231 
0232     InputRedirection::KeyboardKeyState nativeState;
0233     switch (state) {
0234     case WL_KEYBOARD_KEY_STATE_PRESSED:
0235         nativeState = InputRedirection::KeyboardKeyPressed;
0236         break;
0237 
0238     case WL_KEYBOARD_KEY_STATE_RELEASED:
0239         nativeState = InputRedirection::KeyboardKeyReleased;
0240         break;
0241 
0242     default:
0243         return;
0244     }
0245 
0246     Q_EMIT device->keyChanged(button, nativeState, currentTime(), device);
0247 }
0248 
0249 FakeInputBackend::FakeInputBackend(Display *display)
0250     : d(std::make_unique<FakeInputBackendPrivate>(this, display))
0251 {
0252 }
0253 
0254 FakeInputBackend::~FakeInputBackend() = default;
0255 
0256 void FakeInputBackend::initialize()
0257 {
0258     d->init(*d->display, s_version);
0259 }
0260 
0261 } // namespace KWin
0262 
0263 #include "moc_fakeinputbackend.cpp"