File indexing completed on 2024-11-10 04:57:30
0001 /* 0002 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0003 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "pointerconstraints_v1.h" 0009 #include "display.h" 0010 #include "pointer.h" 0011 #include "pointerconstraints_v1_p.h" 0012 #include "region_p.h" 0013 #include "surface_p.h" 0014 0015 namespace KWin 0016 { 0017 static const int s_version = 1; 0018 0019 static QRegion mapScaleOverride(const QRegion ®ion, qreal scaleOverride) 0020 { 0021 QRegion out; 0022 for (const QRect &rect : region) { 0023 out += QRect(rect.topLeft() / scaleOverride, rect.size() / scaleOverride); 0024 } 0025 return out; 0026 } 0027 0028 PointerConstraintsV1InterfacePrivate::PointerConstraintsV1InterfacePrivate(Display *display) 0029 : QtWaylandServer::zwp_pointer_constraints_v1(*display, s_version) 0030 { 0031 } 0032 0033 static QRegion regionFromResource(::wl_resource *resource) 0034 { 0035 const RegionInterface *region = RegionInterface::get(resource); 0036 return region ? region->region() : QRegion(); 0037 } 0038 0039 void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_lock_pointer(Resource *resource, 0040 uint32_t id, 0041 ::wl_resource *surface_resource, 0042 ::wl_resource *pointer_resource, 0043 ::wl_resource *region_resource, 0044 uint32_t lifetime) 0045 { 0046 PointerInterface *pointer = PointerInterface::get(pointer_resource); 0047 if (!pointer) { 0048 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid pointer"); 0049 return; 0050 } 0051 0052 SurfaceInterface *surface = SurfaceInterface::get(surface_resource); 0053 if (!surface) { 0054 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid surface"); 0055 return; 0056 } 0057 0058 if (surface->lockedPointer() || surface->confinedPointer()) { 0059 wl_resource_post_error(resource->handle, error_already_constrained, "the surface is already constrained"); 0060 return; 0061 } 0062 0063 if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) { 0064 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "unknown lifetime %d", lifetime); 0065 return; 0066 } 0067 0068 wl_resource *lockedPointerResource = wl_resource_create(resource->client(), &zwp_locked_pointer_v1_interface, resource->version(), id); 0069 if (!lockedPointerResource) { 0070 wl_resource_post_no_memory(resource->handle); 0071 return; 0072 } 0073 0074 new LockedPointerV1Interface(surface, LockedPointerV1Interface::LifeTime(lifetime), regionFromResource(region_resource), lockedPointerResource); 0075 } 0076 0077 void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_confine_pointer(Resource *resource, 0078 uint32_t id, 0079 ::wl_resource *surface_resource, 0080 ::wl_resource *pointer_resource, 0081 ::wl_resource *region_resource, 0082 uint32_t lifetime) 0083 { 0084 PointerInterface *pointer = PointerInterface::get(pointer_resource); 0085 if (!pointer) { 0086 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid pointer"); 0087 return; 0088 } 0089 0090 SurfaceInterface *surface = SurfaceInterface::get(surface_resource); 0091 if (!surface) { 0092 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "invalid surface"); 0093 return; 0094 } 0095 0096 if (lifetime != lifetime_oneshot && lifetime != lifetime_persistent) { 0097 wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "unknown lifetime %d", lifetime); 0098 return; 0099 } 0100 0101 if (surface->lockedPointer() || surface->confinedPointer()) { 0102 wl_resource_post_error(resource->handle, error_already_constrained, "the surface is already constrained"); 0103 return; 0104 } 0105 0106 wl_resource *confinedPointerResource = wl_resource_create(resource->client(), &zwp_confined_pointer_v1_interface, resource->version(), id); 0107 if (!confinedPointerResource) { 0108 wl_resource_post_no_memory(resource->handle); 0109 return; 0110 } 0111 0112 new ConfinedPointerV1Interface(surface, ConfinedPointerV1Interface::LifeTime(lifetime), regionFromResource(region_resource), confinedPointerResource); 0113 } 0114 0115 void PointerConstraintsV1InterfacePrivate::zwp_pointer_constraints_v1_destroy(Resource *resource) 0116 { 0117 wl_resource_destroy(resource->handle); 0118 } 0119 0120 PointerConstraintsV1Interface::PointerConstraintsV1Interface(Display *display, QObject *parent) 0121 : QObject(parent) 0122 , d(new PointerConstraintsV1InterfacePrivate(display)) 0123 { 0124 } 0125 0126 PointerConstraintsV1Interface::~PointerConstraintsV1Interface() 0127 { 0128 } 0129 0130 LockedPointerV1InterfacePrivate *LockedPointerV1InterfacePrivate::get(LockedPointerV1Interface *q) 0131 { 0132 return q->d.get(); 0133 } 0134 0135 LockedPointerV1InterfacePrivate::LockedPointerV1InterfacePrivate(LockedPointerV1Interface *q, 0136 SurfaceInterface *surface, 0137 LockedPointerV1Interface::LifeTime lifeTime, 0138 const QRegion ®ion, 0139 ::wl_resource *resource) 0140 : QtWaylandServer::zwp_locked_pointer_v1(resource) 0141 , SurfaceExtension(surface) 0142 , q(q) 0143 , surface(surface) 0144 , lifeTime(lifeTime) 0145 { 0146 pending.region = region; 0147 0148 apply(&pending); 0149 0150 pending = LockedPointerV1Commit{}; 0151 } 0152 0153 void LockedPointerV1InterfacePrivate::apply(LockedPointerV1Commit *commit) 0154 { 0155 const QRegion oldRegion = effectiveRegion; 0156 const QPointF oldHint = hint; 0157 0158 if (commit->region.has_value()) { 0159 region = mapScaleOverride(commit->region.value(), surface->scaleOverride()); 0160 } 0161 if (commit->hint.has_value()) { 0162 hint = commit->hint.value() / surface->scaleOverride(); 0163 } 0164 0165 effectiveRegion = surface->input(); 0166 if (!region.isEmpty()) { 0167 effectiveRegion &= region; 0168 } 0169 0170 if (oldRegion != effectiveRegion) { 0171 Q_EMIT q->regionChanged(); 0172 } 0173 if (oldHint != hint) { 0174 Q_EMIT q->cursorPositionHintChanged(); 0175 } 0176 } 0177 0178 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy_resource(Resource *resource) 0179 { 0180 Q_EMIT q->aboutToBeDestroyed(); 0181 delete q; 0182 } 0183 0184 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy(Resource *resource) 0185 { 0186 wl_resource_destroy(resource->handle); 0187 } 0188 0189 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y) 0190 { 0191 pending.hint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)); 0192 } 0193 0194 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource) 0195 { 0196 pending.region = regionFromResource(region_resource); 0197 } 0198 0199 LockedPointerV1Interface::LockedPointerV1Interface(SurfaceInterface *surface, 0200 LifeTime lifeTime, 0201 const QRegion ®ion, 0202 ::wl_resource *resource) 0203 : d(new LockedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource)) 0204 { 0205 SurfaceInterfacePrivate::get(surface)->installPointerConstraint(this); 0206 } 0207 0208 LockedPointerV1Interface::~LockedPointerV1Interface() 0209 { 0210 } 0211 0212 LockedPointerV1Interface::LifeTime LockedPointerV1Interface::lifeTime() const 0213 { 0214 return d->lifeTime; 0215 } 0216 0217 QRegion LockedPointerV1Interface::region() const 0218 { 0219 return d->effectiveRegion; 0220 } 0221 0222 QPointF LockedPointerV1Interface::cursorPositionHint() const 0223 { 0224 return d->hint; 0225 } 0226 0227 bool LockedPointerV1Interface::isLocked() const 0228 { 0229 return d->isLocked; 0230 } 0231 0232 void LockedPointerV1Interface::setLocked(bool locked) 0233 { 0234 if (d->isLocked == locked) { 0235 return; 0236 } 0237 if (!locked) { 0238 d->hint = QPointF(-1, -1); 0239 } 0240 d->isLocked = locked; 0241 if (d->isLocked) { 0242 d->send_locked(); 0243 } else { 0244 d->send_unlocked(); 0245 } 0246 Q_EMIT lockedChanged(); 0247 } 0248 0249 ConfinedPointerV1InterfacePrivate *ConfinedPointerV1InterfacePrivate::get(ConfinedPointerV1Interface *q) 0250 { 0251 return q->d.get(); 0252 } 0253 0254 ConfinedPointerV1InterfacePrivate::ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q, 0255 SurfaceInterface *surface, 0256 ConfinedPointerV1Interface::LifeTime lifeTime, 0257 const QRegion ®ion, 0258 ::wl_resource *resource) 0259 : QtWaylandServer::zwp_confined_pointer_v1(resource) 0260 , SurfaceExtension(surface) 0261 , q(q) 0262 , surface(surface) 0263 , lifeTime(lifeTime) 0264 { 0265 pending.region = region; 0266 0267 apply(&pending); 0268 0269 pending = ConfinedPointerV1Commit{}; 0270 } 0271 0272 void ConfinedPointerV1InterfacePrivate::apply(ConfinedPointerV1Commit *commit) 0273 { 0274 const QRegion oldRegion = effectiveRegion; 0275 0276 if (commit->region.has_value()) { 0277 region = mapScaleOverride(commit->region.value(), surface->scaleOverride()); 0278 } 0279 0280 effectiveRegion = surface->input(); 0281 if (!region.isEmpty()) { 0282 effectiveRegion &= region; 0283 } 0284 0285 if (oldRegion != effectiveRegion) { 0286 Q_EMIT q->regionChanged(); 0287 } 0288 } 0289 0290 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy_resource(Resource *resource) 0291 { 0292 delete q; 0293 } 0294 0295 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy(Resource *resource) 0296 { 0297 wl_resource_destroy(resource->handle); 0298 } 0299 0300 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource) 0301 { 0302 pending.region = regionFromResource(region_resource); 0303 } 0304 0305 ConfinedPointerV1Interface::ConfinedPointerV1Interface(SurfaceInterface *surface, 0306 LifeTime lifeTime, 0307 const QRegion ®ion, 0308 ::wl_resource *resource) 0309 : d(new ConfinedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource)) 0310 { 0311 SurfaceInterfacePrivate::get(surface)->installPointerConstraint(this); 0312 } 0313 0314 ConfinedPointerV1Interface::~ConfinedPointerV1Interface() 0315 { 0316 } 0317 0318 ConfinedPointerV1Interface::LifeTime ConfinedPointerV1Interface::lifeTime() const 0319 { 0320 return d->lifeTime; 0321 } 0322 0323 QRegion ConfinedPointerV1Interface::region() const 0324 { 0325 return d->effectiveRegion; 0326 } 0327 0328 bool ConfinedPointerV1Interface::isConfined() const 0329 { 0330 return d->isConfined; 0331 } 0332 0333 void ConfinedPointerV1Interface::setConfined(bool confined) 0334 { 0335 if (d->isConfined == confined) { 0336 return; 0337 } 0338 d->isConfined = confined; 0339 if (d->isConfined) { 0340 d->send_confined(); 0341 } else { 0342 d->send_unconfined(); 0343 } 0344 Q_EMIT confinedChanged(); 0345 } 0346 0347 } // namespace KWin 0348 0349 #include "moc_pointerconstraints_v1.cpp"