mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-22 15:25:58 +01:00
Implemented mouse constraints
has some todos but mostly works
This commit is contained in:
parent
b0f5e4ab56
commit
7b1eaca840
10 changed files with 531 additions and 4 deletions
12
Makefile
12
Makefile
|
@ -49,6 +49,16 @@ ext-workspace-unstable-v1-protocol.c:
|
||||||
|
|
||||||
ext-workspace-unstable-v1-protocol.o: ext-workspace-unstable-v1-protocol.h
|
ext-workspace-unstable-v1-protocol.o: ext-workspace-unstable-v1-protocol.h
|
||||||
|
|
||||||
|
pointer-constraints-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/pointer-constraints-unstable-v1.xml $@
|
||||||
|
|
||||||
|
pointer-constraints-unstable-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/pointer-constraints-unstable-v1.xml $@
|
||||||
|
|
||||||
|
pointer-constraints-unstable-v1-protocol.o: pointer-constraints-unstable-v1-protocol.h
|
||||||
|
|
||||||
idle-protocol.h:
|
idle-protocol.h:
|
||||||
$(WAYLAND_SCANNER) server-header \
|
$(WAYLAND_SCANNER) server-header \
|
||||||
protocols/idle.xml $@
|
protocols/idle.xml $@
|
||||||
|
@ -102,4 +112,4 @@ uninstall:
|
||||||
rm -f /usr/bin/hyprctl
|
rm -f /usr/bin/hyprctl
|
||||||
rm -rf /usr/share/hyprland
|
rm -rf /usr/share/hyprland
|
||||||
|
|
||||||
config: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o
|
config: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o
|
||||||
|
|
339
protocols/pointer-constraints-unstable-v1.xml
Normal file
339
protocols/pointer-constraints-unstable-v1.xml
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="pointer_constraints_unstable_v1">
|
||||||
|
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2014 Jonas Ådahl
|
||||||
|
Copyright © 2015 Red Hat Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<description summary="protocol for constraining pointer motions">
|
||||||
|
This protocol specifies a set of interfaces used for adding constraints to
|
||||||
|
the motion of a pointer. Possible constraints include confining pointer
|
||||||
|
motions to a given region, or locking it to its current position.
|
||||||
|
|
||||||
|
In order to constrain the pointer, a client must first bind the global
|
||||||
|
interface "wp_pointer_constraints" which, if a compositor supports pointer
|
||||||
|
constraints, is exposed by the registry. Using the bound global object, the
|
||||||
|
client uses the request that corresponds to the type of constraint it wants
|
||||||
|
to make. See wp_pointer_constraints for more details.
|
||||||
|
|
||||||
|
Warning! The protocol described in this file is experimental and backward
|
||||||
|
incompatible changes may be made. Backward compatible changes may be added
|
||||||
|
together with the corresponding interface version bump. Backward
|
||||||
|
incompatible changes are done by bumping the version number in the protocol
|
||||||
|
and interface names and resetting the interface version. Once the protocol
|
||||||
|
is to be declared stable, the 'z' prefix and the version number in the
|
||||||
|
protocol and interface names are removed and the interface version number is
|
||||||
|
reset.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<interface name="zwp_pointer_constraints_v1" version="1">
|
||||||
|
<description summary="constrain the movement of a pointer">
|
||||||
|
The global interface exposing pointer constraining functionality. It
|
||||||
|
exposes two requests: lock_pointer for locking the pointer to its
|
||||||
|
position, and confine_pointer for locking the pointer to a region.
|
||||||
|
|
||||||
|
The lock_pointer and confine_pointer requests create the objects
|
||||||
|
wp_locked_pointer and wp_confined_pointer respectively, and the client can
|
||||||
|
use these objects to interact with the lock.
|
||||||
|
|
||||||
|
For any surface, only one lock or confinement may be active across all
|
||||||
|
wl_pointer objects of the same seat. If a lock or confinement is requested
|
||||||
|
when another lock or confinement is active or requested on the same surface
|
||||||
|
and with any of the wl_pointer objects of the same seat, an
|
||||||
|
'already_constrained' error will be raised.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<description summary="wp_pointer_constraints error values">
|
||||||
|
These errors can be emitted in response to wp_pointer_constraints
|
||||||
|
requests.
|
||||||
|
</description>
|
||||||
|
<entry name="already_constrained" value="1"
|
||||||
|
summary="pointer constraint already requested on that surface"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="lifetime">
|
||||||
|
<description summary="constraint lifetime">
|
||||||
|
These values represent different lifetime semantics. They are passed
|
||||||
|
as arguments to the factory requests to specify how the constraint
|
||||||
|
lifetimes should be managed.
|
||||||
|
</description>
|
||||||
|
<entry name="oneshot" value="1">
|
||||||
|
<description summary="the pointer constraint is defunct once deactivated">
|
||||||
|
A oneshot pointer constraint will never reactivate once it has been
|
||||||
|
deactivated. See the corresponding deactivation event
|
||||||
|
(wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
|
||||||
|
details.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="persistent" value="2">
|
||||||
|
<description summary="the pointer constraint may reactivate">
|
||||||
|
A persistent pointer constraint may again reactivate once it has
|
||||||
|
been deactivated. See the corresponding deactivation event
|
||||||
|
(wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
|
||||||
|
details.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the pointer constraints manager object">
|
||||||
|
Used by the client to notify the server that it will no longer use this
|
||||||
|
pointer constraints object.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="lock_pointer">
|
||||||
|
<description summary="lock pointer to a position">
|
||||||
|
The lock_pointer request lets the client request to disable movements of
|
||||||
|
the virtual pointer (i.e. the cursor), effectively locking the pointer
|
||||||
|
to a position. This request may not take effect immediately; in the
|
||||||
|
future, when the compositor deems implementation-specific constraints
|
||||||
|
are satisfied, the pointer lock will be activated and the compositor
|
||||||
|
sends a locked event.
|
||||||
|
|
||||||
|
The protocol provides no guarantee that the constraints are ever
|
||||||
|
satisfied, and does not require the compositor to send an error if the
|
||||||
|
constraints cannot ever be satisfied. It is thus possible to request a
|
||||||
|
lock that will never activate.
|
||||||
|
|
||||||
|
There may not be another pointer constraint of any kind requested or
|
||||||
|
active on the surface for any of the wl_pointer objects of the seat of
|
||||||
|
the passed pointer when requesting a lock. If there is, an error will be
|
||||||
|
raised. See general pointer lock documentation for more details.
|
||||||
|
|
||||||
|
The intersection of the region passed with this request and the input
|
||||||
|
region of the surface is used to determine where the pointer must be
|
||||||
|
in order for the lock to activate. It is up to the compositor whether to
|
||||||
|
warp the pointer or require some kind of user interaction for the lock
|
||||||
|
to activate. If the region is null the surface input region is used.
|
||||||
|
|
||||||
|
A surface may receive pointer focus without the lock being activated.
|
||||||
|
|
||||||
|
The request creates a new object wp_locked_pointer which is used to
|
||||||
|
interact with the lock as well as receive updates about its state. See
|
||||||
|
the the description of wp_locked_pointer for further information.
|
||||||
|
|
||||||
|
Note that while a pointer is locked, the wl_pointer objects of the
|
||||||
|
corresponding seat will not emit any wl_pointer.motion events, but
|
||||||
|
relative motion events will still be emitted via wp_relative_pointer
|
||||||
|
objects of the same seat. wl_pointer.axis and wl_pointer.button events
|
||||||
|
are unaffected.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="zwp_locked_pointer_v1"/>
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"
|
||||||
|
summary="surface to lock pointer to"/>
|
||||||
|
<arg name="pointer" type="object" interface="wl_pointer"
|
||||||
|
summary="the pointer that should be locked"/>
|
||||||
|
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||||
|
summary="region of surface"/>
|
||||||
|
<arg name="lifetime" type="uint" enum="lifetime" summary="lock lifetime"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="confine_pointer">
|
||||||
|
<description summary="confine pointer to a region">
|
||||||
|
The confine_pointer request lets the client request to confine the
|
||||||
|
pointer cursor to a given region. This request may not take effect
|
||||||
|
immediately; in the future, when the compositor deems implementation-
|
||||||
|
specific constraints are satisfied, the pointer confinement will be
|
||||||
|
activated and the compositor sends a confined event.
|
||||||
|
|
||||||
|
The intersection of the region passed with this request and the input
|
||||||
|
region of the surface is used to determine where the pointer must be
|
||||||
|
in order for the confinement to activate. It is up to the compositor
|
||||||
|
whether to warp the pointer or require some kind of user interaction for
|
||||||
|
the confinement to activate. If the region is null the surface input
|
||||||
|
region is used.
|
||||||
|
|
||||||
|
The request will create a new object wp_confined_pointer which is used
|
||||||
|
to interact with the confinement as well as receive updates about its
|
||||||
|
state. See the the description of wp_confined_pointer for further
|
||||||
|
information.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="zwp_confined_pointer_v1"/>
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"
|
||||||
|
summary="surface to lock pointer to"/>
|
||||||
|
<arg name="pointer" type="object" interface="wl_pointer"
|
||||||
|
summary="the pointer that should be confined"/>
|
||||||
|
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||||
|
summary="region of surface"/>
|
||||||
|
<arg name="lifetime" type="uint" enum="lifetime" summary="confinement lifetime"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_locked_pointer_v1" version="1">
|
||||||
|
<description summary="receive relative pointer motion events">
|
||||||
|
The wp_locked_pointer interface represents a locked pointer state.
|
||||||
|
|
||||||
|
While the lock of this object is active, the wl_pointer objects of the
|
||||||
|
associated seat will not emit any wl_pointer.motion events.
|
||||||
|
|
||||||
|
This object will send the event 'locked' when the lock is activated.
|
||||||
|
Whenever the lock is activated, it is guaranteed that the locked surface
|
||||||
|
will already have received pointer focus and that the pointer will be
|
||||||
|
within the region passed to the request creating this object.
|
||||||
|
|
||||||
|
To unlock the pointer, send the destroy request. This will also destroy
|
||||||
|
the wp_locked_pointer object.
|
||||||
|
|
||||||
|
If the compositor decides to unlock the pointer the unlocked event is
|
||||||
|
sent. See wp_locked_pointer.unlock for details.
|
||||||
|
|
||||||
|
When unlocking, the compositor may warp the cursor position to the set
|
||||||
|
cursor position hint. If it does, it will not result in any relative
|
||||||
|
motion events emitted via wp_relative_pointer.
|
||||||
|
|
||||||
|
If the surface the lock was requested on is destroyed and the lock is not
|
||||||
|
yet activated, the wp_locked_pointer object is now defunct and must be
|
||||||
|
destroyed.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the locked pointer object">
|
||||||
|
Destroy the locked pointer object. If applicable, the compositor will
|
||||||
|
unlock the pointer.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_cursor_position_hint">
|
||||||
|
<description summary="set the pointer cursor position hint">
|
||||||
|
Set the cursor position hint relative to the top left corner of the
|
||||||
|
surface.
|
||||||
|
|
||||||
|
If the client is drawing its own cursor, it should update the position
|
||||||
|
hint to the position of its own cursor. A compositor may use this
|
||||||
|
information to warp the pointer upon unlock in order to avoid pointer
|
||||||
|
jumps.
|
||||||
|
|
||||||
|
The cursor position hint is double buffered. The new hint will only take
|
||||||
|
effect when the associated surface gets it pending state applied. See
|
||||||
|
wl_surface.commit for details.
|
||||||
|
</description>
|
||||||
|
<arg name="surface_x" type="fixed"
|
||||||
|
summary="surface-local x coordinate"/>
|
||||||
|
<arg name="surface_y" type="fixed"
|
||||||
|
summary="surface-local y coordinate"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_region">
|
||||||
|
<description summary="set a new lock region">
|
||||||
|
Set a new region used to lock the pointer.
|
||||||
|
|
||||||
|
The new lock region is double-buffered. The new lock region will
|
||||||
|
only take effect when the associated surface gets its pending state
|
||||||
|
applied. See wl_surface.commit for details.
|
||||||
|
|
||||||
|
For details about the lock region, see wp_locked_pointer.
|
||||||
|
</description>
|
||||||
|
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||||
|
summary="region of surface"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="locked">
|
||||||
|
<description summary="lock activation event">
|
||||||
|
Notification that the pointer lock of the seat's pointer is activated.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="unlocked">
|
||||||
|
<description summary="lock deactivation event">
|
||||||
|
Notification that the pointer lock of the seat's pointer is no longer
|
||||||
|
active. If this is a oneshot pointer lock (see
|
||||||
|
wp_pointer_constraints.lifetime) this object is now defunct and should
|
||||||
|
be destroyed. If this is a persistent pointer lock (see
|
||||||
|
wp_pointer_constraints.lifetime) this pointer lock may again
|
||||||
|
reactivate in the future.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_confined_pointer_v1" version="1">
|
||||||
|
<description summary="confined pointer object">
|
||||||
|
The wp_confined_pointer interface represents a confined pointer state.
|
||||||
|
|
||||||
|
This object will send the event 'confined' when the confinement is
|
||||||
|
activated. Whenever the confinement is activated, it is guaranteed that
|
||||||
|
the surface the pointer is confined to will already have received pointer
|
||||||
|
focus and that the pointer will be within the region passed to the request
|
||||||
|
creating this object. It is up to the compositor to decide whether this
|
||||||
|
requires some user interaction and if the pointer will warp to within the
|
||||||
|
passed region if outside.
|
||||||
|
|
||||||
|
To unconfine the pointer, send the destroy request. This will also destroy
|
||||||
|
the wp_confined_pointer object.
|
||||||
|
|
||||||
|
If the compositor decides to unconfine the pointer the unconfined event is
|
||||||
|
sent. The wp_confined_pointer object is at this point defunct and should
|
||||||
|
be destroyed.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the confined pointer object">
|
||||||
|
Destroy the confined pointer object. If applicable, the compositor will
|
||||||
|
unconfine the pointer.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_region">
|
||||||
|
<description summary="set a new confine region">
|
||||||
|
Set a new region used to confine the pointer.
|
||||||
|
|
||||||
|
The new confine region is double-buffered. The new confine region will
|
||||||
|
only take effect when the associated surface gets its pending state
|
||||||
|
applied. See wl_surface.commit for details.
|
||||||
|
|
||||||
|
If the confinement is active when the new confinement region is applied
|
||||||
|
and the pointer ends up outside of newly applied region, the pointer may
|
||||||
|
warped to a position within the new confinement region. If warped, a
|
||||||
|
wl_pointer.motion event will be emitted, but no
|
||||||
|
wp_relative_pointer.relative_motion event.
|
||||||
|
|
||||||
|
The compositor may also, instead of using the new region, unconfine the
|
||||||
|
pointer.
|
||||||
|
|
||||||
|
For details about the confine region, see wp_confined_pointer.
|
||||||
|
</description>
|
||||||
|
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||||
|
summary="region of surface"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="confined">
|
||||||
|
<description summary="pointer confined">
|
||||||
|
Notification that the pointer confinement of the seat's pointer is
|
||||||
|
activated.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="unconfined">
|
||||||
|
<description summary="pointer unconfined">
|
||||||
|
Notification that the pointer confinement of the seat's pointer is no
|
||||||
|
longer active. If this is a oneshot pointer confinement (see
|
||||||
|
wp_pointer_constraints.lifetime) this object is now defunct and should
|
||||||
|
be destroyed. If this is a persistent pointer confinement (see
|
||||||
|
wp_pointer_constraints.lifetime) this pointer confinement may again
|
||||||
|
reactivate in the future.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
</protocol>
|
|
@ -93,6 +93,10 @@ CCompositor::CCompositor() {
|
||||||
m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay);
|
m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
m_sWLREXTWorkspaceMgr = wlr_ext_workspace_manager_v1_create(m_sWLDisplay);
|
m_sWLREXTWorkspaceMgr = wlr_ext_workspace_manager_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
|
m_sWLRPointerConstraints = wlr_pointer_constraints_v1_create(m_sWLDisplay);
|
||||||
|
|
||||||
|
m_sWLRRelPointerMgr = wlr_relative_pointer_manager_v1_create(m_sWLDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCompositor::~CCompositor() {
|
CCompositor::~CCompositor() {
|
||||||
|
@ -118,6 +122,7 @@ void CCompositor::initAllSignals() {
|
||||||
addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr");
|
addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr");
|
||||||
addWLSignal(&m_sWLRInhibitMgr->events.activate, &Events::listen_InhibitActivate, m_sWLRInhibitMgr, "InhibitMgr");
|
addWLSignal(&m_sWLRInhibitMgr->events.activate, &Events::listen_InhibitActivate, m_sWLRInhibitMgr, "InhibitMgr");
|
||||||
addWLSignal(&m_sWLRInhibitMgr->events.deactivate, &Events::listen_InhibitDeactivate, m_sWLRInhibitMgr, "InhibitMgr");
|
addWLSignal(&m_sWLRInhibitMgr->events.deactivate, &Events::listen_InhibitDeactivate, m_sWLRInhibitMgr, "InhibitMgr");
|
||||||
|
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::startCompositor() {
|
void CCompositor::startCompositor() {
|
||||||
|
|
|
@ -51,6 +51,8 @@ public:
|
||||||
int m_iDRMFD;
|
int m_iDRMFD;
|
||||||
wlr_ext_workspace_manager_v1* m_sWLREXTWorkspaceMgr;
|
wlr_ext_workspace_manager_v1* m_sWLREXTWorkspaceMgr;
|
||||||
wlr_linux_dmabuf_v1* m_sWLRDmabuf;
|
wlr_linux_dmabuf_v1* m_sWLRDmabuf;
|
||||||
|
wlr_pointer_constraints_v1* m_sWLRPointerConstraints;
|
||||||
|
wlr_relative_pointer_manager_v1* m_sWLRRelPointerMgr;
|
||||||
// ------------------------------------------------- //
|
// ------------------------------------------------- //
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,3 +81,39 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
|
||||||
|
|
||||||
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, capabilities);
|
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
||||||
|
const auto PCONSTRAINT = (wlr_pointer_constraint_v1*)data;
|
||||||
|
|
||||||
|
Debug::log(LOG, "New mouse constraint at %x", PCONSTRAINT);
|
||||||
|
|
||||||
|
g_pInputManager->m_lConstraints.emplace_back();
|
||||||
|
const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
|
||||||
|
|
||||||
|
CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
|
||||||
|
CONSTRAINT->constraint = PCONSTRAINT;
|
||||||
|
|
||||||
|
CONSTRAINT->hyprListener_destroyConstraint.initCallback(&PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint, CONSTRAINT, "Constraint");
|
||||||
|
CONSTRAINT->hyprListener_setConstraintRegion.initCallback(&PCONSTRAINT->events.set_region, &Events::listener_setConstraintRegion, CONSTRAINT, "Constraint");
|
||||||
|
|
||||||
|
if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
|
||||||
|
g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::listener_destroyConstraint(void* owner, void* data) {
|
||||||
|
const auto PCONSTRAINT = (SConstraint*)owner;
|
||||||
|
|
||||||
|
if (PCONSTRAINT->pMouse->currentConstraint == PCONSTRAINT->constraint) {
|
||||||
|
PCONSTRAINT->pMouse->hyprListener_commitConstraint.removeCallback();
|
||||||
|
PCONSTRAINT->pMouse->currentConstraint = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Unconstrained mouse from %x", PCONSTRAINT->constraint);
|
||||||
|
|
||||||
|
g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::listener_setConstraintRegion(void* owner, void* data) {
|
||||||
|
// no
|
||||||
|
}
|
|
@ -66,6 +66,11 @@ namespace Events {
|
||||||
DYNLISTENFUNC(keyboardMod);
|
DYNLISTENFUNC(keyboardMod);
|
||||||
DYNLISTENFUNC(keyboardDestroy);
|
DYNLISTENFUNC(keyboardDestroy);
|
||||||
|
|
||||||
|
DYNLISTENFUNC(commitConstraint);
|
||||||
|
LISTENER(newConstraint);
|
||||||
|
DYNLISTENFUNC(setConstraintRegion);
|
||||||
|
DYNLISTENFUNC(destroyConstraint);
|
||||||
|
|
||||||
// Various
|
// Various
|
||||||
LISTENER(requestMouse);
|
LISTENER(requestMouse);
|
||||||
LISTENER(requestSetSel);
|
LISTENER(requestSetSel);
|
||||||
|
|
|
@ -60,6 +60,32 @@ struct SKeyboard {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SMouse {
|
||||||
|
wlr_input_device* mouse = nullptr;
|
||||||
|
|
||||||
|
wlr_pointer_constraint_v1* currentConstraint = nullptr;
|
||||||
|
|
||||||
|
pixman_region32_t confinedTo;
|
||||||
|
|
||||||
|
DYNLISTENER(commitConstraint);
|
||||||
|
|
||||||
|
bool operator==(const SMouse& b) {
|
||||||
|
return mouse == b.mouse;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SConstraint {
|
||||||
|
SMouse* pMouse = nullptr;
|
||||||
|
wlr_pointer_constraint_v1* constraint = nullptr;
|
||||||
|
|
||||||
|
DYNLISTENER(setConstraintRegion);
|
||||||
|
DYNLISTENER(destroyConstraint);
|
||||||
|
|
||||||
|
bool operator==(const SConstraint& b) {
|
||||||
|
return constraint == b.constraint;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SMonitor;
|
struct SMonitor;
|
||||||
|
|
||||||
struct SXDGPopup {
|
struct SXDGPopup {
|
||||||
|
@ -87,6 +113,8 @@ struct SXDGPopup {
|
||||||
struct SSeat {
|
struct SSeat {
|
||||||
wlr_seat* seat = nullptr;
|
wlr_seat* seat = nullptr;
|
||||||
wl_client* exclusiveClient = nullptr;
|
wl_client* exclusiveClient = nullptr;
|
||||||
|
|
||||||
|
SMouse* mouse = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDrag {
|
struct SDrag {
|
||||||
|
|
|
@ -79,6 +79,8 @@ extern "C" {
|
||||||
#include <X11/Xproto.h>
|
#include <X11/Xproto.h>
|
||||||
#include <wlr/render/gles2.h>
|
#include <wlr/render/gles2.h>
|
||||||
#include <wlr/render/wlr_texture.h>
|
#include <wlr/render/wlr_texture.h>
|
||||||
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||||
|
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef class
|
#undef class
|
||||||
|
|
|
@ -5,6 +5,8 @@ void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
||||||
|
|
||||||
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
|
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
|
||||||
|
|
||||||
|
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, e->delta_x, e->delta_y, e->unaccel_dx, e->unaccel_dy);
|
||||||
|
|
||||||
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->delta_x * sensitivity, e->delta_y * sensitivity);
|
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, e->delta_x * sensitivity, e->delta_y * sensitivity);
|
||||||
|
|
||||||
mouseMoveUnified(e->time_msec);
|
mouseMoveUnified(e->time_msec);
|
||||||
|
@ -129,6 +131,19 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||||
|
|
||||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||||
|
|
||||||
|
// constraints
|
||||||
|
// All constraints TODO: multiple mice?
|
||||||
|
if (g_pCompositor->m_sSeat.mouse->currentConstraint) {
|
||||||
|
const auto CONSTRAINTWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_sSeat.mouse->currentConstraint->surface);
|
||||||
|
|
||||||
|
if (g_pCompositor->m_pLastWindow == CONSTRAINTWINDOW) {
|
||||||
|
// todo: this is incorrect, but it will work in most cases for now
|
||||||
|
// i made this cuz i wanna play minecraft lol
|
||||||
|
Vector2D deltaToMiddle = (CONSTRAINTWINDOW->m_vRealPosition + CONSTRAINTWINDOW->m_vRealSize / 2.f) - mouseCoords;
|
||||||
|
wlr_cursor_move(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, deltaToMiddle.x, deltaToMiddle.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||||
|
@ -239,6 +254,11 @@ void CInputManager::setKeyboardLayout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::newMouse(wlr_input_device* mouse) {
|
void CInputManager::newMouse(wlr_input_device* mouse) {
|
||||||
|
m_lMice.emplace_back();
|
||||||
|
const auto PMOUSE = &m_lMice.back();
|
||||||
|
|
||||||
|
PMOUSE->mouse = mouse;
|
||||||
|
|
||||||
if (wlr_input_device_is_libinput(mouse)) {
|
if (wlr_input_device_is_libinput(mouse)) {
|
||||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
|
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
|
||||||
|
|
||||||
|
@ -251,6 +271,8 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
|
||||||
|
|
||||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
|
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
|
||||||
|
|
||||||
|
g_pCompositor->m_sSeat.mouse = PMOUSE;
|
||||||
|
|
||||||
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
|
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +285,14 @@ void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::destroyMouse(wlr_input_device* mouse) {
|
void CInputManager::destroyMouse(wlr_input_device* mouse) {
|
||||||
//
|
for (auto& m : m_lMice) {
|
||||||
|
if (m.mouse == mouse) {
|
||||||
|
m_lMice.remove(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pCompositor->m_sSeat.mouse = m_lMice.size() > 0 ? &m_lMice.front() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||||
|
@ -315,3 +344,69 @@ void CInputManager::updateDragIcon() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInputManager::recheckConstraint(SMouse* pMouse) {
|
||||||
|
if (!pMouse->currentConstraint)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto MOUSECOORDS = getMouseCoordsInternal();
|
||||||
|
const auto PWINDOW = g_pCompositor->getWindowFromSurface(pMouse->currentConstraint->surface);
|
||||||
|
const auto PREGION = &pMouse->currentConstraint->region;
|
||||||
|
|
||||||
|
if (pMouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED) {
|
||||||
|
pixman_region32_copy(&pMouse->confinedTo, PREGION);
|
||||||
|
} else {
|
||||||
|
pixman_region32_clear(&pMouse->confinedTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Constraint rechecked: %i, %i to %i, %i", PREGION->extents.x1, PREGION->extents.y1, PREGION->extents.x2, PREGION->extents.y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* constraint) {
|
||||||
|
|
||||||
|
if (pMouse->currentConstraint == constraint)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto PWINDOW = g_pCompositor->getWindowFromSurface(constraint->surface);
|
||||||
|
const auto MOUSECOORDS = getMouseCoordsInternal();
|
||||||
|
|
||||||
|
pMouse->hyprListener_commitConstraint.removeCallback();
|
||||||
|
|
||||||
|
if (pMouse->currentConstraint) {
|
||||||
|
if (!constraint) {
|
||||||
|
// warpe to hint
|
||||||
|
|
||||||
|
if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
|
||||||
|
if (PWINDOW) {
|
||||||
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
|
||||||
|
constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.x, constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.y);
|
||||||
|
|
||||||
|
wlr_seat_pointer_warp(constraint->seat, constraint->current.cursor_hint.x, constraint->current.cursor_hint.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
pMouse->currentConstraint = constraint;
|
||||||
|
|
||||||
|
if (pixman_region32_not_empty(&constraint->current.region)) {
|
||||||
|
pixman_region32_intersect(&constraint->region, &constraint->surface->input_region, &constraint->current.region);
|
||||||
|
} else {
|
||||||
|
pixman_region32_copy(&constraint->region, &constraint->surface->input_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
// warp to the constraint
|
||||||
|
recheckConstraint(pMouse);
|
||||||
|
|
||||||
|
wlr_pointer_constraint_v1_send_activated(pMouse->currentConstraint);
|
||||||
|
|
||||||
|
pMouse->hyprListener_commitConstraint.initCallback(&pMouse->currentConstraint->surface->events.commit, &Events::listener_commitConstraint, pMouse, "Mouse constraint commit");
|
||||||
|
|
||||||
|
Debug::log(LOG, "Constrained mouse to %x", pMouse->currentConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::listener_commitConstraint(void* owner, void* data) {
|
||||||
|
//g_pInputManager->recheckConstraint((SMouse*)owner);
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ public:
|
||||||
void destroyKeyboard(SKeyboard*);
|
void destroyKeyboard(SKeyboard*);
|
||||||
void destroyMouse(wlr_input_device*);
|
void destroyMouse(wlr_input_device*);
|
||||||
|
|
||||||
|
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
|
||||||
|
void recheckConstraint(SMouse*);
|
||||||
|
|
||||||
Vector2D getMouseCoordsInternal();
|
Vector2D getMouseCoordsInternal();
|
||||||
void refocus();
|
void refocus();
|
||||||
|
|
||||||
|
@ -33,12 +36,14 @@ public:
|
||||||
|
|
||||||
SDrag m_sDrag;
|
SDrag m_sDrag;
|
||||||
|
|
||||||
|
std::list<SConstraint> m_lConstraints;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::list<SKeyboard> m_lKeyboards;
|
std::list<SKeyboard> m_lKeyboards;
|
||||||
|
std::list<SMouse> m_lMice;
|
||||||
|
|
||||||
void mouseMoveUnified(uint32_t, bool refocus = false);
|
void mouseMoveUnified(uint32_t, bool refocus = false);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
inline std::unique_ptr<CInputManager> g_pInputManager;
|
Loading…
Reference in a new issue