File indexing completed on 2024-05-19 16:33:53

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0006     SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 #pragma once
0011 
0012 #include <config-kwin.h>
0013 // KWin
0014 #include "core/inputbackend.h"
0015 #include "core/inputdevice.h"
0016 #include "core/outputbackend.h"
0017 #include "utils/filedescriptor.h"
0018 #include <kwinglobals.h>
0019 // Qt
0020 #include <QHash>
0021 #include <QImage>
0022 #include <QObject>
0023 #include <QPoint>
0024 #include <QSize>
0025 
0026 struct wl_display;
0027 struct gbm_device;
0028 struct gbm_bo;
0029 
0030 namespace KWayland
0031 {
0032 namespace Client
0033 {
0034 class Keyboard;
0035 class Pointer;
0036 class PointerSwipeGesture;
0037 class PointerPinchGesture;
0038 class RelativePointer;
0039 class Seat;
0040 class Surface;
0041 class Touch;
0042 }
0043 }
0044 
0045 namespace KWin
0046 {
0047 class DpmsInputEventFilter;
0048 
0049 namespace Wayland
0050 {
0051 
0052 class WaylandBackend;
0053 class WaylandSeat;
0054 class WaylandOutput;
0055 class WaylandEglBackend;
0056 class WaylandDisplay;
0057 
0058 class WaylandInputDevice : public InputDevice
0059 {
0060     Q_OBJECT
0061 
0062 public:
0063     WaylandInputDevice(KWayland::Client::Touch *touch, WaylandSeat *seat);
0064     WaylandInputDevice(KWayland::Client::Keyboard *keyboard, WaylandSeat *seat);
0065     WaylandInputDevice(KWayland::Client::RelativePointer *relativePointer, WaylandSeat *seat);
0066     WaylandInputDevice(KWayland::Client::Pointer *pointer, WaylandSeat *seat);
0067     ~WaylandInputDevice() override;
0068 
0069     QString sysName() const override;
0070     QString name() const override;
0071 
0072     bool isEnabled() const override;
0073     void setEnabled(bool enabled) override;
0074 
0075     LEDs leds() const override;
0076     void setLeds(LEDs leds) override;
0077 
0078     bool isKeyboard() const override;
0079     bool isAlphaNumericKeyboard() const override;
0080     bool isPointer() const override;
0081     bool isTouchpad() const override;
0082     bool isTouch() const override;
0083     bool isTabletTool() const override;
0084     bool isTabletPad() const override;
0085     bool isTabletModeSwitch() const override;
0086     bool isLidSwitch() const override;
0087 
0088     KWayland::Client::Pointer *nativePointer() const;
0089 
0090 private:
0091     WaylandSeat *const m_seat;
0092 
0093     std::unique_ptr<KWayland::Client::Keyboard> m_keyboard;
0094     std::unique_ptr<KWayland::Client::Touch> m_touch;
0095     std::unique_ptr<KWayland::Client::RelativePointer> m_relativePointer;
0096     std::unique_ptr<KWayland::Client::Pointer> m_pointer;
0097     std::unique_ptr<KWayland::Client::PointerPinchGesture> m_pinchGesture;
0098     std::unique_ptr<KWayland::Client::PointerSwipeGesture> m_swipeGesture;
0099 };
0100 
0101 class WaylandInputBackend : public InputBackend
0102 {
0103     Q_OBJECT
0104 
0105 public:
0106     explicit WaylandInputBackend(WaylandBackend *backend, QObject *parent = nullptr);
0107 
0108     void initialize() override;
0109 
0110 private:
0111     WaylandBackend *m_backend;
0112 };
0113 
0114 class WaylandSeat : public QObject
0115 {
0116     Q_OBJECT
0117 public:
0118     WaylandSeat(KWayland::Client::Seat *nativeSeat, WaylandBackend *backend);
0119     ~WaylandSeat() override;
0120 
0121     WaylandBackend *backend() const
0122     {
0123         return m_backend;
0124     }
0125 
0126     WaylandInputDevice *pointerDevice() const
0127     {
0128         return m_pointerDevice.get();
0129     }
0130     WaylandInputDevice *relativePointerDevice() const
0131     {
0132         return m_relativePointerDevice.get();
0133     }
0134     WaylandInputDevice *keyboardDevice() const
0135     {
0136         return m_keyboardDevice.get();
0137     }
0138     WaylandInputDevice *touchDevice() const
0139     {
0140         return m_touchDevice.get();
0141     }
0142 
0143     void createRelativePointer();
0144     void destroyRelativePointer();
0145 
0146 Q_SIGNALS:
0147     void deviceAdded(WaylandInputDevice *device);
0148     void deviceRemoved(WaylandInputDevice *device);
0149 
0150 private:
0151     void createPointerDevice();
0152     void destroyPointerDevice();
0153     void createKeyboardDevice();
0154     void destroyKeyboardDevice();
0155     void createTouchDevice();
0156     void destroyTouchDevice();
0157 
0158     KWayland::Client::Seat *m_seat;
0159     WaylandBackend *m_backend;
0160 
0161     std::unique_ptr<WaylandInputDevice> m_pointerDevice;
0162     std::unique_ptr<WaylandInputDevice> m_relativePointerDevice;
0163     std::unique_ptr<WaylandInputDevice> m_keyboardDevice;
0164     std::unique_ptr<WaylandInputDevice> m_touchDevice;
0165 };
0166 
0167 struct WaylandBackendOptions
0168 {
0169     QString socketName;
0170     int outputCount = 1;
0171     qreal outputScale = 1;
0172     QSize outputSize = QSize(1024, 768);
0173 };
0174 
0175 /**
0176  * @brief Class encapsulating all Wayland data structures needed by the Egl backend.
0177  *
0178  * It creates the connection to the Wayland Compositor, sets up the registry and creates
0179  * the Wayland output surfaces and its shell mappings.
0180  */
0181 class KWIN_EXPORT WaylandBackend : public OutputBackend
0182 {
0183     Q_OBJECT
0184 
0185 public:
0186     explicit WaylandBackend(const WaylandBackendOptions &options, QObject *parent = nullptr);
0187     ~WaylandBackend() override;
0188     bool initialize() override;
0189 
0190     std::unique_ptr<InputBackend> createInputBackend() override;
0191     std::unique_ptr<OpenGLBackend> createOpenGLBackend() override;
0192     std::unique_ptr<QPainterBackend> createQPainterBackend() override;
0193 
0194     WaylandDisplay *display() const
0195     {
0196         return m_display.get();
0197     }
0198     WaylandSeat *seat() const
0199     {
0200         return m_seat.get();
0201     }
0202 
0203     bool supportsPointerLock();
0204     void togglePointerLock();
0205 
0206     QVector<CompositingType> supportedCompositors() const override;
0207 
0208     WaylandOutput *findOutput(KWayland::Client::Surface *nativeSurface) const;
0209     Outputs outputs() const override;
0210     QVector<WaylandOutput *> waylandOutputs() const
0211     {
0212         return m_outputs;
0213     }
0214     void createDpmsFilter();
0215     void clearDpmsFilter();
0216 
0217     Output *createVirtualOutput(const QString &name, const QSize &size, double scale) override;
0218     void removeVirtualOutput(Output *output) override;
0219 
0220     std::optional<DmaBufParams> testCreateDmaBuf(const QSize &size, quint32 format, const QVector<uint64_t> &modifiers) override;
0221     std::shared_ptr<DmaBufTexture> createDmaBufTexture(const QSize &size, quint32 format, uint64_t modifier) override;
0222 
0223     gbm_device *gbmDevice() const
0224     {
0225         return m_gbmDevice;
0226     }
0227 
0228     void setEglBackend(WaylandEglBackend *eglBackend)
0229     {
0230         m_eglBackend = eglBackend;
0231     }
0232 
0233 Q_SIGNALS:
0234     void pointerLockChanged(bool locked);
0235 
0236 private:
0237     void createOutputs();
0238     void destroyOutputs();
0239     WaylandOutput *createOutput(const QString &name, const QSize &size, qreal scale);
0240 
0241     WaylandBackendOptions m_options;
0242     std::unique_ptr<WaylandDisplay> m_display;
0243     std::unique_ptr<WaylandSeat> m_seat;
0244     WaylandEglBackend *m_eglBackend = nullptr;
0245     QVector<WaylandOutput *> m_outputs;
0246     std::unique_ptr<DpmsInputEventFilter> m_dpmsFilter;
0247     bool m_pointerLockRequested = false;
0248     FileDescriptor m_drmFileDescriptor;
0249     gbm_device *m_gbmDevice;
0250 };
0251 
0252 } // namespace Wayland
0253 } // namespace KWin