Skip to content

Commit

Permalink
Support default movefocus and movewindow
Browse files Browse the repository at this point in the history
  • Loading branch information
dawsers committed Oct 30, 2024
1 parent ed725c5 commit af5cebc
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 65 deletions.
41 changes: 20 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ The plugin adds the following dispatchers:

| Dispatcher | Description |
|---------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| `scroller:movefocus` | A replacement for `movefocus`, takes a direction as argument. |
| `scroller:movewindow` | A replacement for `movewindow`, takes a direction as argument. |
| `scroller:movefocus` | An optional replacement for `movefocus`, takes a direction as argument. |
| `scroller:movewindow` | An optional replacement for `movewindow`, takes a direction as argument. |
| `scroller:setmode` | Set mode: `r/row` (default), `c/col/column`. Sets the working mode. Affects most dispatchers and new window creation. |
| `scroller:cyclesize` | Resize the focused column width (*row* mode), or the active window height (*column* mode). |
| `scroller:alignwindow` | Align window on the screen, `l/left`, `c/center`, `r/right` (*row* mode), `c/center`, `u/up`, `d/down` (*col* mode) |
Expand Down Expand Up @@ -153,13 +153,12 @@ The plugin adds the following dispatchers:

## Window/Column Focus and Movement

If you want to use *Hyprscroller* you will need to map your key bindings from
the default `movefocus`/`movewindow` to
`scroller:movefocus`/`scroller:movewindow`. The reason is *Hyprland* doesn't
have the concept (yet) of a workspace that spans more than the space of a
monitor, and when focusing directionally, it doesn't look for windows that are
"outside" of that region. If this changes in the future, these two dispatchers
may become obsolete.
*Hyprscroller* is now compatible with *Hyprland's* default `movefocus`/`movewindow`
dispatchers and key bindings. But you can also add *Hyprscroller's* own
`scroller:movefocus`/`scroller:movewindow` for cases unsupported by Hyprland,
like `beginning` and `end`. Supporting the default dispatcher allows for
better switching of layouts without needing to modify the configuration, which
was the case in the past.

`movefocus` and `movewindow` accept the following directional arguments:
`l` or `left`, `r` or `right`, `u` or `up`, `d` or `dn` or `down`, `b` or
Expand Down Expand Up @@ -629,18 +628,18 @@ As an example, you could set some key bindings in your `hyprland.conf` like this

``` conf
# Move focus with mainMod + arrow keys
bind = $mainMod, left, scroller:movefocus, l
bind = $mainMod, right, scroller:movefocus, r
bind = $mainMod, up, scroller:movefocus, u
bind = $mainMod, down, scroller:movefocus, d
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
bind = $mainMod, home, scroller:movefocus, begin
bind = $mainMod, end, scroller:movefocus, end
# Movement
bind = $mainMod CTRL, left, scroller:movewindow, l
bind = $mainMod CTRL, right, scroller:movewindow, r
bind = $mainMod CTRL, up, scroller:movewindow, u
bind = $mainMod CTRL, down, scroller:movewindow, d
bind = $mainMod CTRL, left, movewindow, l
bind = $mainMod CTRL, right, movewindow, r
bind = $mainMod CTRL, up, movewindow, u
bind = $mainMod CTRL, down, movewindow, d
bind = $mainMod CTRL, home, scroller:movewindow, begin
bind = $mainMod CTRL, end, scroller:movewindow, end
Expand Down Expand Up @@ -721,10 +720,10 @@ bind = $mainMod, tab, scroller:toggleoverview
bind = $mainMod, tab, submap, overview
# will start a submap called "overview"
submap = overview
bind = , right, scroller:movefocus, right
bind = , left, scroller:movefocus, left
bind = , up, scroller:movefocus, up
bind = , down, scroller:movefocus, down
bind = , right, movefocus, right
bind = , left, movefocus, left
bind = , up, movefocus, up
bind = , down, movefocus, down
# use reset to go back to the global submap
bind = , escape, scroller:toggleoverview,
bind = , escape, submap, reset
Expand Down
24 changes: 12 additions & 12 deletions hypr.conf
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ bind = $mainMod, Return, exec, kitty
bind = $mainMod SHIFT, X, exit,

# focus
bind = $mainMod, left, scroller:movefocus, l
bind = $mainMod, right, scroller:movefocus, r
bind = $mainMod, up, scroller:movefocus, u
bind = $mainMod, down, scroller:movefocus, d
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
bind = $mainMod, home, scroller:movefocus, begin
bind = $mainMod, end, scroller:movefocus, end
bind = $mainMod CTRL, left, scroller:movewindow, l
bind = $mainMod CTRL, right, scroller:movewindow, r
bind = $mainMod CTRL, up, scroller:movewindow, u
bind = $mainMod CTRL, down, scroller:movewindow, d
bind = $mainMod CTRL, left, movewindow, l
bind = $mainMod CTRL, right, movewindow, r
bind = $mainMod CTRL, up, movewindow, u
bind = $mainMod CTRL, down, movewindow, d
bind = $mainMod CTRL, home, scroller:movewindow, begin
bind = $mainMod CTRL, end, scroller:movewindow, end

Expand Down Expand Up @@ -189,10 +189,10 @@ bind = $mainMod, tab, scroller:toggleoverview
bind = $mainMod, tab, submap, overview
# will start a submap called "overview"
submap = overview
bind = , right, scroller:movefocus, right
bind = , left, scroller:movefocus, left
bind = , up, scroller:movefocus, up
bind = , down, scroller:movefocus, down
bind = , right, movefocus, right
bind = , left, movefocus, left
bind = , up, movefocus, up
bind = , down, movefocus, down
# use reset to go back to the global submap
bind = , escape, scroller:toggleoverview,
bind = , escape, submap, reset
Expand Down
37 changes: 18 additions & 19 deletions src/dispatchers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern HANDLE PHANDLE;
extern std::unique_ptr<ScrollerLayout> g_ScrollerLayout;


namespace {
namespace dispatchers {
std::optional<Direction> parse_move_arg(std::string arg) {
if (arg == "l" || arg == "left")
return Direction::Left;
Expand Down Expand Up @@ -199,22 +199,21 @@ namespace {

g_ScrollerLayout->unpin(workspace);
}
}

void dispatchers::addDispatchers() {
HyprlandAPI::addDispatcher(PHANDLE, "scroller:cyclesize", dispatch_cyclesize);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:movefocus", dispatch_movefocus);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:movewindow", dispatch_movewindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:alignwindow", dispatch_alignwindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:admitwindow", dispatch_admitwindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:expelwindow", dispatch_expelwindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:setmode", dispatch_setmode);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:fitsize", dispatch_fitsize);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:toggleoverview", dispatch_toggleoverview);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksadd", dispatch_marksadd);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksdelete", dispatch_marksdelete);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksvisit", dispatch_marksvisit);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksreset", dispatch_marksreset);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:pin", dispatch_pin);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:unpin", dispatch_unpin);
void addDispatchers() {
HyprlandAPI::addDispatcher(PHANDLE, "scroller:cyclesize", dispatch_cyclesize);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:movefocus", dispatch_movefocus);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:movewindow", dispatch_movewindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:alignwindow", dispatch_alignwindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:admitwindow", dispatch_admitwindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:expelwindow", dispatch_expelwindow);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:setmode", dispatch_setmode);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:fitsize", dispatch_fitsize);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:toggleoverview", dispatch_toggleoverview);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksadd", dispatch_marksadd);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksdelete", dispatch_marksdelete);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksvisit", dispatch_marksvisit);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:marksreset", dispatch_marksreset);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:pin", dispatch_pin);
HyprlandAPI::addDispatcher(PHANDLE, "scroller:unpin", dispatch_unpin);
}
}
4 changes: 4 additions & 0 deletions src/dispatchers.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#pragma once

#include <string>

namespace dispatchers {
void addDispatchers();
void dispatch_movefocus(std::string arg);
void dispatch_movewindow(std::string arg);
}
10 changes: 5 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,36 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
dispatchers::addDispatchers();

static auto P1 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "workspace", [](void* self, SCallbackInfo& info, std::any param) {
if (!g_ScrollerLayout)
if (!g_ScrollerLayout || !g_ScrollerLayout->is_enabled())
return;
auto WORKSPACE = std::any_cast<PHLWORKSPACE>(param);
g_ScrollerLayout->post_event(WORKSPACE->m_iID, "mode");
g_ScrollerLayout->post_event(WORKSPACE->m_iID, "overview");
});
static auto P2 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "focusedMon", [](void* self, SCallbackInfo& info, std::any param) {
if (!g_ScrollerLayout)
if (!g_ScrollerLayout || !g_ScrollerLayout->is_enabled())
return;
auto monitor = std::any_cast<CMonitor *>(param);
g_ScrollerLayout->post_event(monitor->activeWorkspaceID(), "mode");
g_ScrollerLayout->post_event(monitor->activeWorkspaceID(), "overview");
});

static auto P3 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "swipeBegin", [](void* self, SCallbackInfo& info, std::any param) {
if (!g_ScrollerLayout)
if (!g_ScrollerLayout || !g_ScrollerLayout->is_enabled())
return;
auto swipe_event = std::any_cast<IPointer::SSwipeBeginEvent>(param);
g_ScrollerLayout->swipe_begin(swipe_event);
});

static auto P4 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "swipeUpdate", [](void* self, SCallbackInfo& info, std::any param) {
if (!g_ScrollerLayout)
if (!g_ScrollerLayout || !g_ScrollerLayout->is_enabled())
return;
auto swipe_event = std::any_cast<IPointer::SSwipeUpdateEvent>(param);
g_ScrollerLayout->swipe_update(info, swipe_event);
});

static auto P5 = HyprlandAPI::registerCallbackDynamic(PHANDLE, "swipeEnd", [](void* self, SCallbackInfo& info, std::any param) {
if (!g_ScrollerLayout)
if (!g_ScrollerLayout || !g_ScrollerLayout->is_enabled())
return;
auto swipe_event = std::any_cast<IPointer::SSwipeEndEvent>(param);
g_ScrollerLayout->swipe_end(info, swipe_event);
Expand Down
43 changes: 35 additions & 8 deletions src/scroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <hyprland/src/managers/EventManager.hpp>
#endif

#include "dispatchers.h"
#include "scroller.h"
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -375,6 +376,20 @@ class Marks {

static Marks marks;

static std::function<SDispatchResult(std::string)> orig_moveFocusTo;

SDispatchResult this_moveFocusTo(std::string args) {
dispatchers::dispatch_movefocus(args);
return {};
}

static std::function<SDispatchResult(std::string)> orig_moveActiveTo;

SDispatchResult this_moveActiveTo(std::string args) {
dispatchers::dispatch_movewindow(args);
return {};
}

class Window {
public:
Window(PHLWINDOW window, double box_h) : window(window) {
Expand Down Expand Up @@ -778,7 +793,7 @@ class Column {
return true;
}
// use default dispatch for movefocus (change monitor)
g_pKeybindManager->m_mDispatchers["movefocus"]("u");
orig_moveFocusTo("u");
return false;
}
reorder = Reorder::Auto;
Expand All @@ -794,7 +809,7 @@ class Column {
return true;
}
// use default dispatch for movefocus (change monitor)
g_pKeybindManager->m_mDispatchers["movefocus"]("d");
orig_moveFocusTo("d");
return false;
}
reorder = Reorder::Auto;
Expand Down Expand Up @@ -1219,7 +1234,7 @@ class Row {
return true;
}

g_pKeybindManager->m_mDispatchers["movefocus"]("l");
orig_moveFocusTo("l");
return false;
}
active = active->prev();
Expand All @@ -1234,7 +1249,7 @@ class Row {
return true;
}

g_pKeybindManager->m_mDispatchers["movefocus"]("r");
orig_moveFocusTo("r");
return false;
}
active = active->next();
Expand Down Expand Up @@ -2253,6 +2268,13 @@ void ScrollerLayout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to)
}

void ScrollerLayout::onEnable() {
// Hijack Hyprland's default dispatchers
orig_moveFocusTo = g_pKeybindManager->m_mDispatchers["movefocus"];
orig_moveActiveTo = g_pKeybindManager->m_mDispatchers["movewindow"];
g_pKeybindManager->m_mDispatchers["movefocus"] = this_moveFocusTo;
g_pKeybindManager->m_mDispatchers["movewindow"] = this_moveActiveTo;

enabled = true;
marks.reset();
for (auto& window : g_pCompositor->m_vWindows) {
if (window->m_bIsFloating || !window->m_bIsMapped || window->isHidden())
Expand All @@ -2264,6 +2286,11 @@ void ScrollerLayout::onEnable() {
}

void ScrollerLayout::onDisable() {
// Restore Hyprland's default dispatchers
g_pKeybindManager->m_mDispatchers["movefocus"] = orig_moveFocusTo;
g_pKeybindManager->m_mDispatchers["movewindow"] = orig_moveActiveTo;

enabled = false;
for (auto row = rows.first(); row != nullptr; row = row->next()) {
delete row->data();
}
Expand Down Expand Up @@ -2323,16 +2350,16 @@ void ScrollerLayout::move_focus(WORKSPACEID workspace, Direction direction)
// is "move to another monitor" (pass the direction)
switch (direction) {
case Direction::Left:
g_pKeybindManager->m_mDispatchers["movefocus"]("l");
orig_moveFocusTo("l");
break;
case Direction::Right:
g_pKeybindManager->m_mDispatchers["movefocus"]("r");
orig_moveFocusTo("r");
break;
case Direction::Up:
g_pKeybindManager->m_mDispatchers["movefocus"]("u");
orig_moveFocusTo("u");
break;
case Direction::Down:
g_pKeybindManager->m_mDispatchers["movefocus"]("d");
orig_moveFocusTo("d");
break;
default:
break;
Expand Down
3 changes: 3 additions & 0 deletions src/scroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,15 @@ class ScrollerLayout : public IHyprLayout {
void swipe_update(SCallbackInfo& info, IPointer::SSwipeUpdateEvent);
void swipe_end(SCallbackInfo& info, IPointer::SSwipeEndEvent);

bool is_enabled() const { return enabled; }

private:
Row *getRowForWorkspace(WORKSPACEID workspace);
Row *getRowForWindow(PHLWINDOW window);

List<Row *> rows;

bool enabled;
Vector2D gesture_delta;
bool swipe_active;
Direction swipe_direction;
Expand Down

0 comments on commit af5cebc

Please sign in to comment.