mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-02 09:05:59 +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
|
||||
|
||||
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:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
protocols/idle.xml $@
|
||||
|
@ -102,4 +112,4 @@ uninstall:
|
|||
rm -f /usr/bin/hyprctl
|
||||
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_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() {
|
||||
|
@ -118,6 +122,7 @@ void CCompositor::initAllSignals() {
|
|||
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.deactivate, &Events::listen_InhibitDeactivate, m_sWLRInhibitMgr, "InhibitMgr");
|
||||
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
|
||||
}
|
||||
|
||||
void CCompositor::startCompositor() {
|
||||
|
|
|
@ -51,6 +51,8 @@ public:
|
|||
int m_iDRMFD;
|
||||
wlr_ext_workspace_manager_v1* m_sWLREXTWorkspaceMgr;
|
||||
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);
|
||||
}
|
||||
|
||||
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(keyboardDestroy);
|
||||
|
||||
DYNLISTENFUNC(commitConstraint);
|
||||
LISTENER(newConstraint);
|
||||
DYNLISTENFUNC(setConstraintRegion);
|
||||
DYNLISTENFUNC(destroyConstraint);
|
||||
|
||||
// Various
|
||||
LISTENER(requestMouse);
|
||||
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 SXDGPopup {
|
||||
|
@ -87,6 +113,8 @@ struct SXDGPopup {
|
|||
struct SSeat {
|
||||
wlr_seat* seat = nullptr;
|
||||
wl_client* exclusiveClient = nullptr;
|
||||
|
||||
SMouse* mouse = nullptr;
|
||||
};
|
||||
|
||||
struct SDrag {
|
||||
|
|
|
@ -79,6 +79,8 @@ extern "C" {
|
|||
#include <X11/Xproto.h>
|
||||
#include <wlr/render/gles2.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
|
||||
|
|
|
@ -5,6 +5,8 @@ void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
|||
|
||||
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);
|
||||
|
||||
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_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) {
|
||||
|
@ -239,6 +254,11 @@ void CInputManager::setKeyboardLayout() {
|
|||
}
|
||||
|
||||
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)) {
|
||||
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);
|
||||
|
||||
g_pCompositor->m_sSeat.mouse = PMOUSE;
|
||||
|
||||
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) {
|
||||
//
|
||||
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) {
|
||||
|
@ -315,3 +344,69 @@ void CInputManager::updateDragIcon() {
|
|||
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 destroyMouse(wlr_input_device*);
|
||||
|
||||
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
|
||||
void recheckConstraint(SMouse*);
|
||||
|
||||
Vector2D getMouseCoordsInternal();
|
||||
void refocus();
|
||||
|
||||
|
@ -33,12 +36,14 @@ public:
|
|||
|
||||
SDrag m_sDrag;
|
||||
|
||||
std::list<SConstraint> m_lConstraints;
|
||||
|
||||
private:
|
||||
|
||||
std::list<SKeyboard> m_lKeyboards;
|
||||
std::list<SMouse> m_lMice;
|
||||
|
||||
void mouseMoveUnified(uint32_t, bool refocus = false);
|
||||
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
Loading…
Reference in a new issue