File indexing completed on 2024-05-19 16:35:24

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_interface.h"
0009 #include "display.h"
0010 #include "pointer_interface.h"
0011 #include "pointerconstraints_v1_interface_p.h"
0012 #include "region_interface_p.h"
0013 #include "surface_interface_p.h"
0014 
0015 namespace KWaylandServer
0016 {
0017 static const int s_version = 1;
0018 
0019 static QRegion mapScaleOverride(const QRegion &region, 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 &region,
0139                                                                  ::wl_resource *resource)
0140     : QtWaylandServer::zwp_locked_pointer_v1(resource)
0141     , q(q)
0142     , surface(surface)
0143     , lifeTime(lifeTime)
0144     , region(region)
0145 {
0146 }
0147 
0148 void LockedPointerV1InterfacePrivate::commit()
0149 {
0150     qreal scaleOverride = surface->scaleOverride();
0151     if (hasPendingRegion) {
0152         region = mapScaleOverride(pendingRegion, scaleOverride);
0153         hasPendingRegion = false;
0154         Q_EMIT q->regionChanged();
0155     }
0156     if (hasPendingHint) {
0157         hint = pendingHint / scaleOverride;
0158         hasPendingHint = false;
0159         Q_EMIT q->cursorPositionHintChanged();
0160     }
0161 }
0162 
0163 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy_resource(Resource *resource)
0164 {
0165     Q_EMIT q->aboutToBeDestroyed();
0166     delete q;
0167 }
0168 
0169 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_destroy(Resource *resource)
0170 {
0171     wl_resource_destroy(resource->handle);
0172 }
0173 
0174 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_cursor_position_hint(Resource *resource, wl_fixed_t surface_x, wl_fixed_t surface_y)
0175 {
0176     pendingHint = QPointF(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
0177     hasPendingHint = true;
0178 }
0179 
0180 void LockedPointerV1InterfacePrivate::zwp_locked_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
0181 {
0182     pendingRegion = regionFromResource(region_resource);
0183     hasPendingRegion = true;
0184 }
0185 
0186 LockedPointerV1Interface::LockedPointerV1Interface(SurfaceInterface *surface, LifeTime lifeTime, const QRegion &region, ::wl_resource *resource)
0187     : d(new LockedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource))
0188 {
0189     SurfaceInterfacePrivate::get(surface)->installPointerConstraint(this);
0190 }
0191 
0192 LockedPointerV1Interface::~LockedPointerV1Interface()
0193 {
0194 }
0195 
0196 LockedPointerV1Interface::LifeTime LockedPointerV1Interface::lifeTime() const
0197 {
0198     return d->lifeTime;
0199 }
0200 
0201 QRegion LockedPointerV1Interface::region() const
0202 {
0203     return d->region;
0204 }
0205 
0206 QPointF LockedPointerV1Interface::cursorPositionHint() const
0207 {
0208     return d->hint;
0209 }
0210 
0211 bool LockedPointerV1Interface::isLocked() const
0212 {
0213     return d->isLocked;
0214 }
0215 
0216 void LockedPointerV1Interface::setLocked(bool locked)
0217 {
0218     if (d->isLocked == locked) {
0219         return;
0220     }
0221     if (!locked) {
0222         d->hint = QPointF(-1, -1);
0223     }
0224     d->isLocked = locked;
0225     if (d->isLocked) {
0226         d->send_locked();
0227     } else {
0228         d->send_unlocked();
0229     }
0230     Q_EMIT lockedChanged();
0231 }
0232 
0233 ConfinedPointerV1InterfacePrivate *ConfinedPointerV1InterfacePrivate::get(ConfinedPointerV1Interface *q)
0234 {
0235     return q->d.get();
0236 }
0237 
0238 ConfinedPointerV1InterfacePrivate::ConfinedPointerV1InterfacePrivate(ConfinedPointerV1Interface *q,
0239                                                                      SurfaceInterface *surface,
0240                                                                      ConfinedPointerV1Interface::LifeTime lifeTime,
0241                                                                      const QRegion &region,
0242                                                                      ::wl_resource *resource)
0243     : QtWaylandServer::zwp_confined_pointer_v1(resource)
0244     , q(q)
0245     , surface(surface)
0246     , lifeTime(lifeTime)
0247     , region(region)
0248 {
0249 }
0250 
0251 void ConfinedPointerV1InterfacePrivate::commit()
0252 {
0253     qreal scaleOverride = surface->scaleOverride();
0254     if (hasPendingRegion) {
0255         region = mapScaleOverride(pendingRegion, scaleOverride);
0256         hasPendingRegion = false;
0257         Q_EMIT q->regionChanged();
0258     }
0259 }
0260 
0261 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy_resource(Resource *resource)
0262 {
0263     delete q;
0264 }
0265 
0266 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_destroy(Resource *resource)
0267 {
0268     wl_resource_destroy(resource->handle);
0269 }
0270 
0271 void ConfinedPointerV1InterfacePrivate::zwp_confined_pointer_v1_set_region(Resource *resource, ::wl_resource *region_resource)
0272 {
0273     pendingRegion = regionFromResource(region_resource);
0274     hasPendingRegion = true;
0275 }
0276 
0277 ConfinedPointerV1Interface::ConfinedPointerV1Interface(SurfaceInterface *surface, LifeTime lifeTime, const QRegion &region, ::wl_resource *resource)
0278     : d(new ConfinedPointerV1InterfacePrivate(this, surface, lifeTime, region, resource))
0279 {
0280     SurfaceInterfacePrivate::get(surface)->installPointerConstraint(this);
0281 }
0282 
0283 ConfinedPointerV1Interface::~ConfinedPointerV1Interface()
0284 {
0285 }
0286 
0287 ConfinedPointerV1Interface::LifeTime ConfinedPointerV1Interface::lifeTime() const
0288 {
0289     return d->lifeTime;
0290 }
0291 
0292 QRegion ConfinedPointerV1Interface::region() const
0293 {
0294     return d->region;
0295 }
0296 
0297 bool ConfinedPointerV1Interface::isConfined() const
0298 {
0299     return d->isConfined;
0300 }
0301 
0302 void ConfinedPointerV1Interface::setConfined(bool confined)
0303 {
0304     if (d->isConfined == confined) {
0305         return;
0306     }
0307     d->isConfined = confined;
0308     if (d->isConfined) {
0309         d->send_confined();
0310     } else {
0311         d->send_unconfined();
0312     }
0313     Q_EMIT confinedChanged();
0314 }
0315 
0316 } // namespace KWaylandServer