1 /* 2 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 3 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 4 5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 6 */ 7 8 #pragma once 9 10 #include <KWaylandServer/kwaylandserver_export.h> 11 12 #include <QObject> 13 #include <QRegion> 14 15 struct wl_resource; 16 17 namespace KWaylandServer 18 { 19 class ConfinedPointerV1InterfacePrivate; 20 class Display; 21 class LockedPointerV1InterfacePrivate; 22 class PointerConstraintsV1InterfacePrivate; 23 class SurfaceInterface; 24 25 /** 26 * Manager object to create pointer constraints. 27 * 28 * To create this manager use {@link Display::createPointerConstraintsV1} 29 * 30 * @see ConfinedPointerV1Interface 31 * @see LockedPointerV1Interface 32 */ 33 class KWAYLANDSERVER_EXPORT PointerConstraintsV1Interface : public QObject 34 { 35 Q_OBJECT 36 37 public: 38 explicit PointerConstraintsV1Interface(Display *display, QObject *parent = nullptr); 39 ~PointerConstraintsV1Interface() override; 40 41 private: 42 QScopedPointer<PointerConstraintsV1InterfacePrivate> d; 43 }; 44 45 /** 46 * The LockedPointerV1Interface lets the client request to disable movements of 47 * the virtual pointer (i.e. the cursor), effectively locking the pointer 48 * to a position. 49 * 50 * It is up to the compositor whether the lock gets activated. 51 * To activate it needs to use {@link LockedPointerV1Interface::setLocked}. 52 * The compositor needs to ensure that the SurfaceInterface has pointer focus 53 * and that the pointer is inside the {@link LockedPointerV1Interface::region} when 54 * it activates the lock. 55 * 56 * While the lock is active the PointerInterface does no longer Q_EMIT pointer motion 57 * events, but still emits relative pointer motion events. 58 */ 59 class KWAYLANDSERVER_EXPORT LockedPointerV1Interface : public QObject 60 { 61 Q_OBJECT 62 63 public: 64 ~LockedPointerV1Interface() override; 65 66 enum class LifeTime : uint { 67 OneShot = 1, 68 Persistent = 2, 69 }; 70 71 LifeTime lifeTime() const; 72 73 /** 74 * The intersection of this region and the input region of the SurfaceInterface is used 75 * to determine where the pointer must be in order for the lock to activate. 76 * It is up to the compositor whether to warp the pointer or require some kind of 77 * user interaction for the lock to activate. 78 * 79 * If the region is empty the SurfaceInterface input region is used. 80 * 81 * @see regionChanged 82 * @see SurfaceInterface::input 83 */ 84 QRegion region() const; 85 86 /** 87 * Indicates where the mouse cursor should be positioned after it has been unlocked again. 88 * The compositor can warp the cursor at this moment to the position. For that it 89 * will not Q_EMIT any relative motion events. The hint is relative to the top-left 90 * corner of the surface the lock was applied to. Only non-negative x and y values 91 * are allowed. Otherwise the hint is invalid and should be ignored by the compositor. 92 * 93 * In case the client never set the hint, an invalid one will be returned. 94 * 95 * This function should be called when the compositor decides to break the lock or the 96 * client unbinds the resource. To set the position in this case the compositor should 97 * call this function when the aboutToBeUnbound signal has been emitted. 98 * 99 * @see cursorPositionHintChanged 100 */ 101 QPointF cursorPositionHint() const; 102 103 /** 104 * Whether the Compositor set this pointer lock to be active. 105 * @see setLocked 106 * @see lockedChanged 107 */ 108 bool isLocked() const; 109 110 /** 111 * Activates or deactivates the lock. 112 * 113 * A pointer lock can only be activated if the SurfaceInterface 114 * this LockedPointerV1Interface was created for has pointer focus 115 * and the pointer is inside the {@link region}. 116 * 117 * Unlocking resets the cursor position hint. 118 * 119 * @param locked Whether the lock should be active 120 * @see isLocked 121 * @see lockedChanged 122 */ 123 void setLocked(bool locked); 124 125 Q_SIGNALS: 126 /** 127 * This is signal is emitted when the locked pointer is about to be destroyed. 128 */ 129 void aboutToBeDestroyed(); 130 131 /** 132 * Emitted whenever the region changes. 133 * This happens when the parent SurfaceInterface gets committed 134 * @see region 135 */ 136 void regionChanged(); 137 138 /** 139 * Emitted whenever the cursor position hint changes. 140 * This happens when the parent SurfaceInterface gets committed 141 * @see cursorPositionHint 142 */ 143 void cursorPositionHintChanged(); 144 145 /** 146 * Emitted whenever the {@link isLocked} state changes. 147 * @see isLocked 148 * @see setLocked 149 */ 150 void lockedChanged(); 151 152 private: 153 LockedPointerV1Interface(LifeTime lifeTime, const QRegion ®ion, ::wl_resource *resource); 154 QScopedPointer<LockedPointerV1InterfacePrivate> d; 155 friend class LockedPointerV1InterfacePrivate; 156 friend class PointerConstraintsV1InterfacePrivate; 157 }; 158 159 /** 160 * 161 * The ConfinedPointerV1Interface gets installed on a SurfaceInterface. 162 * The confinement indicates that the SurfaceInterface wants to confine the 163 * pointer to a region of the SurfaceInterface. 164 * 165 * It is up to the compositor whether the confinement gets activated. 166 * To activate it needs to use {@link ConfinedPointerV1Interface::setConfined}. 167 * The compositor needs to ensure that the SurfaceInterface has pointer focus 168 * and that the pointer is inside the {@link ConfinedPointerV1Interface::region} when 169 * it activates the confinement. 170 * 171 * From client side the confinement gets deactivated by destroying the ConfinedPointerV1Interface. 172 * From compositor side the confinement can be deactivated by setting 173 * {@link ConfinedPointerV1Interface::setConfined} to @c false. 174 */ 175 class KWAYLANDSERVER_EXPORT ConfinedPointerV1Interface : public QObject 176 { 177 Q_OBJECT 178 179 public: 180 ~ConfinedPointerV1Interface() override; 181 182 enum class LifeTime : uint { 183 OneShot = 1, 184 Persistent = 2, 185 }; 186 187 LifeTime lifeTime() const; 188 189 /** 190 * The intersection of this region and the input region of the SurfaceInterface is used 191 * to determine where the pointer must be in order for the confinement to activate. 192 * It is up to the compositor whether to warp the pointer or require some kind of 193 * user interaction for the confinement to activate. 194 * 195 * If the region is empty the SurfaceInterface input region is used. 196 * 197 * @see regionChanged 198 * @see SurfaceInterface::input 199 */ 200 QRegion region() const; 201 202 /** 203 * Whether the Compositor set this pointer confinement to be active. 204 * @see setConfined 205 * @see confinedChanged 206 */ 207 bool isConfined() const; 208 209 /** 210 * Activates or deactivates the confinement. 211 * 212 * A pointer confinement can only be activated if the SurfaceInterface 213 * this ConfinedPointerV1Interface was created for has pointer focus 214 * and the pointer is inside the {@link region}. 215 * 216 * @param confined Whether the confinement should be active 217 * @see isConfined 218 * @see confinedChanged 219 */ 220 void setConfined(bool confined); 221 222 Q_SIGNALS: 223 /** 224 * Emitted whenever the region changes. 225 * This happens when the parent SurfaceInterface gets committed 226 * @see region 227 */ 228 void regionChanged(); 229 230 /** 231 * Emitted whenever the {@link isConfined} state changes. 232 * @see isConfined 233 * @see setConfined 234 */ 235 void confinedChanged(); 236 237 private: 238 ConfinedPointerV1Interface(LifeTime lifeTime, const QRegion ®ion, ::wl_resource *resource); 239 QScopedPointer<ConfinedPointerV1InterfacePrivate> d; 240 friend class ConfinedPointerV1InterfacePrivate; 241 friend class PointerConstraintsV1InterfacePrivate; 242 }; 243 244 } // namespace KWaylandServer 245