keybinds: simulate mouse movement after bringing active window to top (#12703)

Fixes https://github.com/hyprwm/Hyprland/discussions/12702
This commit is contained in:
Aditya Singh 2025-12-28 01:57:59 +05:30 committed by GitHub
parent 5faa66d297
commit e5d20b56bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 66 additions and 0 deletions

View file

@ -224,6 +224,28 @@ static SDispatchResult scroll(std::string in) {
return {};
}
static SDispatchResult click(std::string in) {
CVarList2 data(std::move(in));
uint32_t button;
bool pressed;
try {
button = std::stoul(std::string{data[0]});
pressed = std::stoul(std::string{data[1]}) == 1;
} catch (...) { return {.success = false, .error = "invalid input"}; }
Log::logger->log(Log::DEBUG, "tester: mouse button {} state {}", button, pressed);
g_mouse->m_pointerEvents.button.emit(IPointer::SButtonEvent{
.timeMs = sc<uint32_t>(Time::millis(Time::steadyNow())),
.button = button,
.state = pressed ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED,
.mouse = true,
});
return {};
}
static SDispatchResult keybind(std::string in) {
CVarList2 data(std::move(in));
// 0 = release, 1 = press
@ -283,6 +305,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:alt", ::pressAlt);
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:gesture", ::simulateGesture);
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:scroll", ::scroll);
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:click", ::click);
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:keybind", ::keybind);
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:add_rule", ::addRule);
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:check_rule", ::checkRule);

View file

@ -373,6 +373,45 @@ static void testMaximizeSize() {
EXPECT(Tests::windowCount(), 0);
}
static void testBringActiveToTopMouseMovement() {
NLog::log("{}Testing bringactivetotop mouse movement", Colors::GREEN);
Tests::killAllWindows();
OK(getFromSocket("/keyword input:follow_mouse 2"));
OK(getFromSocket("/keyword input:float_switch_override_focus 0"));
EXPECT(spawnKitty("a"), true);
OK(getFromSocket("/dispatch setfloating"));
OK(getFromSocket("/dispatch movewindowpixel exact 500 300,activewindow"));
OK(getFromSocket("/dispatch resizewindowpixel exact 400 400,activewindow"));
EXPECT(spawnKitty("b"), true);
OK(getFromSocket("/dispatch setfloating"));
OK(getFromSocket("/dispatch movewindowpixel exact 500 300,activewindow"));
OK(getFromSocket("/dispatch resizewindowpixel exact 400 400,activewindow"));
auto getTopWindow = []() -> std::string {
auto clients = getFromSocket("/clients");
return (clients.rfind("class: a") > clients.rfind("class: b")) ? "a" : "b";
};
EXPECT(getTopWindow(), std::string("b"));
OK(getFromSocket("/dispatch movecursor 700 500"));
OK(getFromSocket("/dispatch focuswindow class:a"));
EXPECT_CONTAINS(getFromSocket("/activewindow"), "class: a");
OK(getFromSocket("/dispatch bringactivetotop"));
EXPECT(getTopWindow(), std::string("a"));
OK(getFromSocket("/dispatch plugin:test:click 272,1"));
OK(getFromSocket("/dispatch plugin:test:click 272,0"));
EXPECT(getTopWindow(), std::string("a"));
Tests::killAllWindows();
}
static bool test() {
NLog::log("{}Testing windows", Colors::GREEN);
@ -806,6 +845,8 @@ static bool test() {
testMaximizeSize();
testBringActiveToTopMouseMovement();
NLog::log("{}Reloading config", Colors::YELLOW);
OK(getFromSocket("/reload"));

View file

@ -2793,6 +2793,8 @@ SDispatchResult CKeybindManager::bringActiveToTop(std::string args) {
if (Desktop::focusState()->window() && Desktop::focusState()->window()->m_isFloating)
g_pCompositor->changeWindowZOrder(Desktop::focusState()->window(), true);
g_pInputManager->simulateMouseMovement();
return {};
}