Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/seat/helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@
#include <woutputitem.h>
#include <woutputlayout.h>
#include <woutputmanagerv1.h>
#include <woutputrenderwindow.h>

Check warning on line 79 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <woutputrenderwindow.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <woutputviewport.h>

Check warning on line 80 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <woutputviewport.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wqmlcreator.h>

Check warning on line 81 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wqmlcreator.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wpointerconstraintsv1.h>

Check warning on line 82 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wpointerconstraintsv1.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wquickcursor.h>

Check warning on line 83 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wquickcursor.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wrelativepointermanagerv1.h>

Check warning on line 84 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wrelativepointermanagerv1.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wrenderhelper.h>

Check warning on line 85 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wrenderhelper.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wseat.h>

Check warning on line 86 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wseat.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wsecuritycontextmanager.h>

Check warning on line 87 in src/seat/helper.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wsecuritycontextmanager.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <wsocket.h>
#include <wtoplevelsurface.h>
#include <wxdgshell.h>
Expand Down Expand Up @@ -1324,6 +1326,8 @@

m_foreignToplevel = m_server->attach<WForeignToplevel>();
m_extForeignToplevelListV1 = m_server->attach<WExtForeignToplevelListV1>();
m_server->attach<WRelativePointerManagerV1>();
m_server->attach<WPointerConstraintsV1>();

connect(m_shellHandler,
&ShellHandler::surfaceWrapperAdded,
Expand Down
6 changes: 6 additions & 0 deletions waylib/src/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ set(SOURCES
protocols/private/wvirtualkeyboardv1.cpp
protocols/ext_foreign_toplevel_image_capture_source.c #TODO: Remove after wlroots 0.20
protocols/wcursorshapemanagerv1.cpp
protocols/wrelativepointermanagerv1.cpp
protocols/wpointerconstraintsv1.cpp
protocols/woutputmanagerv1.cpp
protocols/wextforeigntoplevellistv1.cpp
protocols/wsecuritycontextmanager.cpp
Expand Down Expand Up @@ -287,6 +289,10 @@ set(HEADERS
protocols/WInputPopupSurface
protocols/wcursorshapemanagerv1.h
protocols/WCursorShapeManagerV1
protocols/wrelativepointermanagerv1.h
protocols/WRelativePointerManagerV1
protocols/wpointerconstraintsv1.h
protocols/WPointerConstraintsV1
protocols/woutputmanagerv1.h
protocols/WOutputManagerV1
protocols/wlayershell.h
Expand Down
11 changes: 11 additions & 0 deletions waylib/src/server/kernel/wcursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ void WCursorPrivate::sendLeaveEvent(WInputDevice *device)
void WCursorPrivate::on_motion(wlr_pointer_motion_event *event)
{
auto device = qw_pointer::from(event->pointer);
if (auto inputDevice = WInputDevice::fromHandle(device)) {
if (auto deviceSeat = inputDevice->seat()) {
deviceSeat->refreshPointerConstraint();
deviceSeat->notifyRelativeMotion(event->time_msec,
QPointF(event->delta_x, event->delta_y),
QPointF(event->unaccel_dx, event->unaccel_dy));
if (deviceSeat->pointerMotionLocked())
return;
}
}

q_func()->move(device, QPointF(event->delta_x, event->delta_y));
processCursorMotion(device, event->time_msec);
}
Expand Down
137 changes: 137 additions & 0 deletions waylib/src/server/kernel/wseat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "wcursor.h"
#include "winputdevice.h"
#include "woutput.h"
#include "wpointerconstraintsv1.h"

Check warning on line 8 in waylib/src/server/kernel/wseat.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "wpointerconstraintsv1.h" not found.
#include "wrelativepointermanagerv1.h"
#include "wsurface.h"
#include "wxdgsurface.h"
#include "platformplugin/qwlrootsintegration.h"
Expand All @@ -15,6 +17,7 @@
#include <qwcursor.h>
#include <qwcompositor.h>
#include <qwdatadevice.h>
#include <qwpointerconstraintsv1.h>
#include <qwpointergesturesv1.h>
#include <qwcompositor.h>
#include <qwdisplay.h>
Expand All @@ -27,6 +30,8 @@
#include <QDebug>
#include <QTimer>

#include <cmath>

#include <qpa/qwindowsysteminterface.h>
#include <private/qxkbcommon_p.h>
#include <private/qquickwindow_p.h>
Expand Down Expand Up @@ -137,6 +142,104 @@
return nativeHandle()->keyboard_state.focused_surface;
}

inline WPointerConstraintsV1 *pointerConstraints() const {
const auto *server = q_func()->server();
return server ? server->findInterface<WPointerConstraintsV1>() : nullptr;
}

inline qw_pointer_constraint_v1 *constraintForSurface(WSurface *surface) const {
auto *constraints = pointerConstraints();
return constraints ? constraints->constraintForSurface(surface, q_func()) : nullptr;
}

inline bool pointerConstraintContains(qw_pointer_constraint_v1 *constraint,
const QPointF &surfacePos) const {
if (!constraint || !constraint->handle())
return false;

pixman_box32_t box;
return pixman_region32_contains_point(&constraint->handle()->region,
std::floor(surfacePos.x()),
std::floor(surfacePos.y()),
&box);
}

inline bool pointerMotionLocked() const {
return activePointerConstraint
&& activePointerConstraint->handle()
&& activePointerConstraint->handle()->type == WLR_POINTER_CONSTRAINT_V1_LOCKED;
}

inline void deactivatePointerConstraint() {
auto *constraint = activePointerConstraint.data();

activePointerConstraint.clear();
QObject::disconnect(activePointerConstraintDestroyConnection);
QObject::disconnect(activePointerConstraintRegionConnection);
activePointerConstraintDestroyConnection = {};
activePointerConstraintRegionConnection = {};

if (constraint && constraint->handle())
constraint->send_deactivated();
}

inline void updatePointerConstraint(WSurface *surface, const QPointF &surfacePos) {
auto *constraint = constraintForSurface(surface);
if (!constraint) {
if (activePointerConstraint)
deactivatePointerConstraint();
return;
}

if (activePointerConstraint && activePointerConstraint->handle() == constraint->handle()) {
if (!pointerConstraintContains(constraint, surfacePos))
deactivatePointerConstraint();
return;
}

if (activePointerConstraint)
deactivatePointerConstraint();

if (!pointerConstraintContains(constraint, surfacePos))
return;

activePointerConstraint = constraint;
activePointerConstraintDestroyConnection =
QObject::connect(constraint, &qw_pointer_constraint_v1::before_destroy,
q_func(), [this] {
activePointerConstraint.clear();
QObject::disconnect(activePointerConstraintDestroyConnection);
QObject::disconnect(activePointerConstraintRegionConnection);
activePointerConstraintDestroyConnection = {};
activePointerConstraintRegionConnection = {};
});
activePointerConstraintRegionConnection =
QObject::connect(constraint, &qw_pointer_constraint_v1::notify_set_region,
q_func(), [this] {
updatePointerConstraint();
});
constraint->send_activated();
}

inline void updatePointerConstraint() {
auto *focus = pointerFocusSurface();
if (!focus) {
if (activePointerConstraint)
deactivatePointerConstraint();
return;
}

auto *surface = WSurface::fromHandle(focus);
if (!surface) {
if (activePointerConstraint)
deactivatePointerConstraint();
return;
}

const auto &pointerState = nativeHandle()->pointer_state;
updatePointerConstraint(surface, QPointF(pointerState.sx, pointerState.sy));
}

inline bool doNotifyMotion(WSurface *target, QObject *eventObject, QPointF localPos, uint32_t timestamp) {
if (target) {
if (pointerFocusSurface()) {
Expand All @@ -148,8 +251,13 @@
// take pointer focus for this surface.
doEnter(target, eventObject, localPos);
}

updatePointerConstraint(target, localPos);
}

if (pointerMotionLocked())
return true;

handle()->pointer_notify_motion(timestamp, localPos.x(), localPos.y());
return true;
}
Expand Down Expand Up @@ -183,6 +291,9 @@
}
auto tmp = oldPointerFocusSurface;
oldPointerFocusSurface = handle()->handle()->pointer_state.focused_surface;
if (activePointerConstraint && activePointerConstraint->handle()->surface != surface->handle()->handle())
deactivatePointerConstraint();

handle()->pointer_notify_enter(surface->handle()->handle(), position.x(), position.y());
if (!pointerFocusSurface()) {
// Because if the last pointer focus surface is a popup, the 'pointerNotifyEnter'
Expand All @@ -207,9 +318,13 @@
});
}

updatePointerConstraint(surface, position);

return true;
}
inline void doClearPointerFocus() {
if (activePointerConstraint)
deactivatePointerConstraint();
pointerFocusEventObject.clear();
handle()->pointer_notify_clear_focus();
Q_ASSERT(!handle()->handle()->pointer_state.focused_surface);
Expand Down Expand Up @@ -370,7 +485,10 @@
QPointer<QWindow> focusWindow;
QPointer<QObject> pointerFocusEventObject;
QPointer<WSurface> m_keyboardFocusSurface;
QPointer<qw_pointer_constraint_v1> activePointerConstraint;
QMetaObject::Connection onEventObjectDestroy;
QMetaObject::Connection activePointerConstraintDestroyConnection;
QMetaObject::Connection activePointerConstraintRegionConnection;
wlr_surface *oldPointerFocusSurface = nullptr;

bool gestureActive = false;
Expand Down Expand Up @@ -1168,6 +1286,25 @@
Q_EMIT alwaysUpdateHoverTargetChanged();
}

void WSeat::notifyRelativeMotion(uint32_t timestamp, const QPointF &delta,
const QPointF &unacceleratedDelta)
{
if (auto *manager = server() ? server()->findInterface<WRelativePointerManagerV1>() : nullptr)
manager->sendRelativeMotion(this, timestamp, delta, unacceleratedDelta);
}

void WSeat::refreshPointerConstraint()
{
W_D(WSeat);
d->updatePointerConstraint();
}

bool WSeat::pointerMotionLocked() const
{
W_DC(WSeat);
return d->pointerMotionLocked();
}

void WSeat::notifyMotion(WCursor *cursor, WInputDevice *device, uint32_t timestamp)
{
W_D(WSeat);
Expand Down
4 changes: 4 additions & 0 deletions waylib/src/server/kernel/wseat.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ class WAYLIB_SERVER_EXPORT WSeat : public WWrapObject, public WServerInterface
bool filterUnacceptedEvent(QWindow *targetWindow, QInputEvent *event);

// pointer
void notifyRelativeMotion(uint32_t timestamp, const QPointF &delta,
const QPointF &unacceleratedDelta);
void refreshPointerConstraint();
bool pointerMotionLocked() const;
void notifyMotion(WCursor *cursor, WInputDevice *device, uint32_t timestamp);
void notifyButton(WCursor *cursor, WInputDevice *device,
Qt::MouseButton button, wl_pointer_button_state_t state,
Expand Down
1 change: 1 addition & 0 deletions waylib/src/server/protocols/WPointerConstraintsV1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "wpointerconstraintsv1.h"
1 change: 1 addition & 0 deletions waylib/src/server/protocols/WRelativePointerManagerV1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "wrelativepointermanagerv1.h"
72 changes: 72 additions & 0 deletions waylib/src/server/protocols/wpointerconstraintsv1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (C) 2026 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "wpointerconstraintsv1.h"

#include "wseat.h"
#include "wsurface.h"

#include "private/wglobal_p.h"

#include <qwcompositor.h>
#include <qwdisplay.h>
#include <qwpointerconstraintsv1.h>

QW_USE_NAMESPACE
WAYLIB_SERVER_BEGIN_NAMESPACE

class Q_DECL_HIDDEN WPointerConstraintsV1Private : public WObjectPrivate
{
public:
explicit WPointerConstraintsV1Private(WPointerConstraintsV1 *qq)
: WObjectPrivate(qq)
{
}
};

WPointerConstraintsV1::WPointerConstraintsV1()
: WObject(*new WPointerConstraintsV1Private(this))
{
}

qw_pointer_constraints_v1 *WPointerConstraintsV1::handle() const
{
return nativeInterface<qw_pointer_constraints_v1>();
}

qw_pointer_constraint_v1 *WPointerConstraintsV1::constraintForSurface(WSurface *surface,
const WSeat *seat) const
{
if (!handle() || !surface || !seat)
return nullptr;

return qw_pointer_constraint_v1::from(
handle()->constraint_for_surface(surface->handle()->handle(), seat->nativeHandle()));
}

QByteArrayView WPointerConstraintsV1::interfaceName() const
{
return "zwp_pointer_constraints_v1";
}

void WPointerConstraintsV1::create(WServer *server)
{
if (m_handle)
return;

m_handle = qw_pointer_constraints_v1::create(*server->handle());
QObject::connect(handle(), &qw_pointer_constraints_v1::notify_new_constraint,
this, [this](wlr_pointer_constraint_v1 *constraint) {
Q_EMIT newConstraint(qw_pointer_constraint_v1::from(constraint));
});
}

wl_global *WPointerConstraintsV1::global() const
{
if (!handle())
return nullptr;

return handle()->handle()->global;
}

WAYLIB_SERVER_END_NAMESPACE
42 changes: 42 additions & 0 deletions waylib/src/server/protocols/wpointerconstraintsv1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (C) 2026 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#pragma once

#include <WServer>

#include <QObject>

QW_BEGIN_NAMESPACE
class qw_pointer_constraint_v1;
class qw_pointer_constraints_v1;
QW_END_NAMESPACE

struct wlr_pointer_constraint_v1;

WAYLIB_SERVER_BEGIN_NAMESPACE

class WSeat;
class WSurface;

class WAYLIB_SERVER_EXPORT WPointerConstraintsV1 : public QObject, public WObject, public WServerInterface
{
Q_OBJECT

public:
explicit WPointerConstraintsV1();

QW_NAMESPACE::qw_pointer_constraints_v1 *handle() const;
QW_NAMESPACE::qw_pointer_constraint_v1 *constraintForSurface(WSurface *surface, const WSeat *seat) const;

QByteArrayView interfaceName() const override;

Q_SIGNALS:
void newConstraint(QW_NAMESPACE::qw_pointer_constraint_v1 *constraint);

protected:
void create(WServer *server) override;
wl_global *global() const override;
};

WAYLIB_SERVER_END_NAMESPACE
Loading
Loading