Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new Input Capture protocol #7919

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
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
3 changes: 2 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[submodule "subprojects/hyprland-protocols"]
path = subprojects/hyprland-protocols
url = https://github.com/hyprwm/hyprland-protocols
url = https://github.com/3l0w/hyprland-protocols
branch = feat/input-capture-impl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

marking this one as a blocker until this is removed so we dont forget (don't resolve)

[submodule "subprojects/udis86"]
path = subprojects/udis86
url = https://github.com/canihavesomecoffee/udis86
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
protocolnew("staging/security-context" "security-context-v1" false)

protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-input-capture-v1"
3l0w marked this conversation as resolved.
Show resolved Hide resolved
true)
protocolwayland()

# tools
Expand Down
6 changes: 3 additions & 3 deletions hyprpm/src/core/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ bool CPluginManager::updateHeaders(bool force) {
return false;
}

progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning https://github.com/hyprwm/Hyprland, this might take a moment."));
progress.printMessageAbove(statusString("!", Colors::YELLOW, "Cloning https://github.com/3l0w/Hyprland, this might take a moment."));

const bool bShallow = (HLVER.branch == "main") && !m_bNoShallow;

Expand All @@ -474,12 +474,12 @@ bool CPluginManager::updateHeaders(bool force) {
if (m_bVerbose && bShallow)
progress.printMessageAbove(verboseString("will shallow since: {}", SHALLOW_DATE));

std::string ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/Hyprland hyprland-{}{}", getTempRoot(), USERNAME,
std::string ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/3l0w/Hyprland hyprland-{}{}", getTempRoot(), USERNAME,
(bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : "")));

if (!std::filesystem::exists(WORKINGDIR)) {
progress.printMessageAbove(failureString("Clone failed. Retrying without shallow."));
ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/hyprwm/hyprland hyprland-{}", getTempRoot(), USERNAME));
ret = execAndGet(std::format("cd {} && git clone --recursive https://github.com/3l0w/hyprland hyprland-{}", getTempRoot(), USERNAME));
}

if (!std::filesystem::exists(WORKINGDIR + "/.git")) {
Expand Down
1 change: 1 addition & 0 deletions protocols/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ protocols = [
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-input-capture-v1.xml',
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
Expand Down
112 changes: 112 additions & 0 deletions protocols/meson.build.orig
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
wayland_protos = dependency(
'wayland-protocols',
version: '>=1.32',
fallback: 'wayland-protocols',
default_options: ['tests=false'],
)

hyprland_protos = dependency(
'hyprland-protocols',
version: '>=0.4',
fallback: 'hyprland-protocols',
)

wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir')
hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir')

hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true)
hyprwayland_scanner = find_program(
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
native: true,
)

protocols = [
'wlr-gamma-control-unstable-v1.xml',
'wlr-foreign-toplevel-management-unstable-v1.xml',
'wlr-output-power-management-unstable-v1.xml',
'input-method-unstable-v2.xml',
'virtual-keyboard-unstable-v1.xml',
'wlr-virtual-pointer-unstable-v1.xml',
'wlr-output-management-unstable-v1.xml',
'kde-server-decoration.xml',
'wlr-layer-shell-unstable-v1.xml',
'wayland-drm.xml',
'wlr-data-control-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml',
'xx-color-management-v4.xml',
'frog-color-management-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml',
<<<<<<< HEAD
hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml',
=======
hyprland_protocol_dir / 'protocols/hyprland-input-capture-v1.xml',
>>>>>>> c8b8ec02 (input-capture: add protocol to meson.build)
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml',
wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml',
wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml',
wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml',
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml',
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml',
wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml',
wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
wayland_protocol_dir / 'stable/tablet/tablet-v2.xml',
wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml',
wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml',
wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
wayland_protocol_dir / 'stable/viewporter/viewporter.xml',
wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml',
wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',
wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
wayland_protocol_dir / 'staging/security-context/security-context-v1.xml',
]

wl_protocols = []
foreach protocol : protocols
wl_protocols += custom_target(
protocol.underscorify(),
input: protocol,
install: true,
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
output: ['@[email protected]', '@[email protected]'],
command: [hyprwayland_scanner, '@INPUT@', '@OUTDIR@'],
)
endforeach

# wayland.xml generation
wayland_scanner = dependency('wayland-scanner')
wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir')

wayland_xml = wayland_scanner_datadir / 'wayland.xml'
wayland_protocol = custom_target(
wayland_xml.underscorify(),
input: wayland_xml,
install: true,
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
output: ['@[email protected]', '@[email protected]'],
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
)

lib_server_protos = static_library(
'server_protos',
wl_protocols + wayland_protocol,
)

server_protos = declare_dependency(
link_with: lib_server_protos,
sources: wl_protocols + wayland_protocol,
)
15 changes: 15 additions & 0 deletions src/managers/KeybindManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../protocols/ShortcutsInhibit.hpp"
#include "../protocols/GlobalShortcuts.hpp"
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
#include "../devices/IKeyboard.hpp"
#include "KeybindManager.hpp"
#include "PointerManager.hpp"
#include "Compositor.hpp"
Expand All @@ -13,6 +14,7 @@
#include "debug/Log.hpp"
#include "helpers/varlist/VarList.hpp"
#include "../helpers/signal/Signal.hpp"
#include "protocols/InputCapture.hpp"

#include <optional>
#include <iterator>
Expand Down Expand Up @@ -131,6 +133,7 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["event"] = event;
m_mDispatchers["global"] = global;
m_mDispatchers["setprop"] = setProp;
m_mDispatchers["releaseinputcapture"] = releaseInputCapture;

m_tScrollTimer.reset();

Expand Down Expand Up @@ -748,6 +751,14 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP

m_iPassPressed = (int)pressed;

// We only process the releaseinputcapture dispatcher when input capture is active
if (PROTO::inputCapture->isCaptured()) {
if (k->handler == "releaseinputcapture")
res = DISPATCHER->second(k->arg);
else
break;
}

// if the dispatchers says to pass event then we will
if (k->handler == "mouse")
res = DISPATCHER->second((pressed ? "1" : "0") + k->arg);
Expand Down Expand Up @@ -3160,3 +3171,7 @@ SDispatchResult CKeybindManager::setProp(std::string args) {

return {};
}
SDispatchResult CKeybindManager::releaseInputCapture(std::string args) {
PROTO::inputCapture->forceRelease();
return {};
}
1 change: 1 addition & 0 deletions src/managers/KeybindManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ class CKeybindManager {
static SDispatchResult global(std::string);
static SDispatchResult event(std::string);
static SDispatchResult setProp(std::string);
static SDispatchResult releaseInputCapture(std::string);

friend class CCompositor;
friend class CInputManager;
Expand Down
17 changes: 9 additions & 8 deletions src/managers/PointerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "eventLoop/EventLoopManager.hpp"
#include "../render/pass/TexPassElement.hpp"
#include "SeatManager.hpp"
#include "protocols/InputCapture.hpp"
#include <cstring>
#include <gbm.h>

Expand Down Expand Up @@ -701,6 +702,13 @@ void CPointerManager::move(const Vector2D& deltaLogical) {
const auto oldPos = pointerPos;
auto newPos = oldPos + Vector2D{std::isnan(deltaLogical.x) ? 0.0 : deltaLogical.x, std::isnan(deltaLogical.y) ? 0.0 : deltaLogical.y};


if (!g_pInputManager->isLocked())
PROTO::inputCapture->sendMotion(newPos, deltaLogical);

if (PROTO::inputCapture->isCaptured())
return;

warpTo(newPos);
}

Expand Down Expand Up @@ -872,14 +880,7 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) {
});

listener->frame = pointer->pointerEvents.frame.registerListener([] (std::any e) {
bool shouldSkip = false;
if (!g_pSeatManager->mouse.expired() && g_pInputManager->isLocked()) {
auto PMONITOR = g_pCompositor->m_pLastMonitor.get();
shouldSkip = PMONITOR && PMONITOR->shouldSkipScheduleFrameOnMouseEvent();
}
g_pSeatManager->isPointerFrameSkipped = shouldSkip;
if (!g_pSeatManager->isPointerFrameSkipped)
g_pSeatManager->sendPointerFrame();
g_pInputManager->onMouseFrame();
});

listener->swipeBegin = pointer->pointerEvents.swipeBegin.registerListener([] (std::any e) {
Expand Down
3 changes: 3 additions & 0 deletions src/managers/ProtocolManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "../protocols/SinglePixel.hpp"
#include "../protocols/SecurityContext.hpp"
#include "../protocols/CTMControl.hpp"
#include "../protocols/InputCapture.hpp"
#include "../protocols/HyprlandSurface.hpp"

#include "../protocols/core/Seat.hpp"
Expand Down Expand Up @@ -166,6 +167,7 @@ CProtocolManager::CProtocolManager() {
PROTO::singlePixel = std::make_unique<CSinglePixelProtocol>(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel");
PROTO::securityContext = std::make_unique<CSecurityContextProtocol>(&wp_security_context_manager_v1_interface, 1, "SecurityContext");
PROTO::ctm = std::make_unique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl");
PROTO::inputCapture = std::make_unique<CInputCaptureProtocol>(&hyprland_input_capture_manager_v1_interface, 1, "InputCapture");
PROTO::hyprlandSurface = std::make_unique<CHyprlandSurfaceProtocol>(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface");

if (*PENABLEXXCM) {
Expand Down Expand Up @@ -245,6 +247,7 @@ CProtocolManager::~CProtocolManager() {
PROTO::singlePixel.reset();
PROTO::securityContext.reset();
PROTO::ctm.reset();
PROTO::inputCapture.reset();
PROTO::hyprlandSurface.reset();

PROTO::lease.reset();
Expand Down
2 changes: 2 additions & 0 deletions src/managers/SeatManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../protocols/DataDeviceWlr.hpp"
#include "../protocols/PrimarySelection.hpp"
#include "../protocols/core/Compositor.hpp"
#include "../protocols/InputCapture.hpp"
#include "../Compositor.hpp"
#include "../devices/IKeyboard.hpp"
#include "wlr-layer-shell-unstable-v1.hpp"
Expand Down Expand Up @@ -97,6 +98,7 @@ void CSeatManager::updateActiveKeyboardData() {
if (keyboard)
PROTO::seat->updateRepeatInfo(keyboard->repeatRate, keyboard->repeatDelay);
PROTO::seat->updateKeymap();
PROTO::inputCapture->updateKeymap();
}

void CSeatManager::setKeyboardFocus(SP<CWLSurfaceResource> surf) {
Expand Down
42 changes: 40 additions & 2 deletions src/managers/input/InputManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "../../protocols/core/DataDevice.hpp"
#include "../../protocols/core/Compositor.hpp"
#include "../../protocols/XDGShell.hpp"
#include "../../protocols/InputCapture.hpp"

#include "../../devices/Mouse.hpp"
#include "../../devices/VirtualPointer.hpp"
Expand Down Expand Up @@ -99,6 +100,9 @@ void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {

g_pPointerManager->move(DELTA);

if (PROTO::inputCapture->isCaptured())
return;

mouseMoveUnified(e.timeMs, false, e.mouse);

m_tmrLastCursorMovement.reset();
Expand Down Expand Up @@ -545,6 +549,11 @@ void CInputManager::onMouseButton(IPointer::SButtonEvent e) {
if (e.mouse)
recheckMouseWarpOnMouseInput();

PROTO::inputCapture->sendButton(e.button, (hyprlandInputCaptureManagerV1ButtonState)e.state);

if (PROTO::inputCapture->isCaptured())
return;

m_tmrLastCursorMovement.reset();

if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
Expand Down Expand Up @@ -782,7 +791,13 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) {
if (e.mouse)
recheckMouseWarpOnMouseInput();

bool passEvent = g_pKeybindManager->onAxisEvent(e);
PROTO::inputCapture->sendAxis((hyprlandInputCaptureManagerV1Axis)e.axis, e.delta);
if (e.source == 0)
PROTO::inputCapture->sendAxisValue120((hyprlandInputCaptureManagerV1Axis)e.axis, e.delta);
else if (e.delta == 0)
PROTO::inputCapture->sendAxisStop((hyprlandInputCaptureManagerV1Axis)e.axis);

bool passEvent = !PROTO::inputCapture->isCaptured() && g_pKeybindManager->onAxisEvent(e);

if (!passEvent)
return;
Expand Down Expand Up @@ -862,6 +877,22 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e) {
g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL);
}

void CInputManager::onMouseFrame() {
PROTO::inputCapture->sendFrame();

if (PROTO::inputCapture->isCaptured())
return;

bool shouldSkip = false;
if (!g_pSeatManager->mouse.expired() && g_pInputManager->isLocked()) {
auto PMONITOR = g_pCompositor->m_pLastMonitor.get();
shouldSkip = PMONITOR && PMONITOR->shouldSkipScheduleFrameOnMouseEvent();
}
g_pSeatManager->isPointerFrameSkipped = shouldSkip;
if (!g_pSeatManager->isPointerFrameSkipped)
g_pSeatManager->sendPointerFrame();
}

Vector2D CInputManager::getMouseCoordsInternal() {
return g_pPointerManager->position();
}
Expand Down Expand Up @@ -1321,10 +1352,12 @@ void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
const auto EMAP = std::unordered_map<std::string, std::any>{{"keyboard", pKeyboard}, {"event", event}};
EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP);

bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard);
bool passEvent = (DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard)) && !PROTO::inputCapture->isCaptured();

auto e = std::any_cast<IKeyboard::SKeyEvent>(event);

PROTO::inputCapture->sendKey(e.keycode, (hyprlandInputCaptureManagerV1KeyState)e.state);

if (passEvent) {
const auto IME = m_sIMERelay.m_pIME.lock();

Expand All @@ -1351,6 +1384,11 @@ void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) {
auto MODS = pKeyboard->modifiersState;
MODS.depressed = ALLMODS;

PROTO::inputCapture->sendModifiers(MODS.depressed,MODS.latched, MODS.locked, MODS.group);

if (PROTO::inputCapture->isCaptured())
return;

const auto IME = m_sIMERelay.m_pIME.lock();

if (IME && IME->hasGrab() && !DISALLOWACTION) {
Expand Down
1 change: 1 addition & 0 deletions src/managers/input/InputManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class CInputManager {
void onMouseWarp(IPointer::SMotionAbsoluteEvent);
void onMouseButton(IPointer::SButtonEvent);
void onMouseWheel(IPointer::SAxisEvent);
void onMouseFrame();
void onKeyboardKey(std::any, SP<IKeyboard>);
void onKeyboardMod(SP<IKeyboard>);

Expand Down
Loading
Loading