hy3
hy3 copied to clipboard
Shift focus to monitor if at the edge of the screen
Closes #2
Not sure if this is the idiomatic way of doing this, but it does seem to work. The only problem I've seen is that if there are no windows on a monitor, there is no indication that that monitor is focused
Oops, this seems to cause some random freezes, don't merge until I figure that one out :sweat:
How does this interact with multiple monitors in a given direction? Also I would prefer it to be implemented in shiftOrGetFocus, probably between the breakout and breakin code.
How does this interact with multiple monitors in a given direction?
Just like focusing windows, each dispatch of the movefocus command moves one monitor in that direction.
Also I would prefer it to be implemented in shiftOrGetFocus, probably between the breakout and breakin code.
So after the while loop on line 1300?
How do you want that to work with the return value though? It seems like the current code computes a node which should be focused and which is returned. Should it focus the monitor, then continue with the execution?
Also, the crash I was talking about was not caused by me, it was a bug in hyprland with X11 windows, so this is safe to merge
I also made a change to make the mouse cursor follow the monitor (though not windows individually as seems to be what dwindle does). This is what I'm used to from bspwm, but I could also change it
How does this interact with multiple monitors in a given direction?
Just like focusing windows, each dispatch of the movefocus command moves one monitor in that direction.
What happens if two monitors border the same monitor though? Ideally focus would move to the monitor that borders more of the window.
Also I would prefer it to be implemented in shiftOrGetFocus, probably between the breakout and breakin code.
So after the while loop on line 1300?
How do you want that to work with the return value though? It seems like the current code computes a node which should be focused and which is returned. Should it focus the monitor, then continue with the execution?
shiftOrGetFocus either changes window focus or returns a window to select given a direction. Implementing the monitor finding logic in that function will make it work for both window shifting and window focus at the same time. The best place I can see to implement this logic would be in this if block, as at this point we've reached the root node of the workspace:
https://github.com/outfoxxed/hy3/blob/90f36e3b0033e39dbb86417a81acca201b8a0b92/src/Hy3Layout.cpp#L1405
Note that you'll have to account for the once option.
I also made a change to make the mouse cursor follow the monitor (though not windows individually as seems to be what dwindle does). This is what I'm used to from bspwm, but I could also change it
Make an option for it and its fine.
@TheZoq2 Any news on this?
No sorry, it has worked well enough for locally me to not bother updating it yet. I might get around to it eventually, but feel free to pick it up and finish what I started if you feel like it
I reapplied the changes to v0.31.0 and created a patch for Nix, if anyone else wants to hack it together I'll put it below. I wish I knew more C++, I'd try to pick this up. I wanted to add basic support for shifting between monitors, but I couldn't figure out how.
plugins = [
(hy3.packages.${pkgs.system}.hy3.overrideAttrs (old: {
patches = (old.patches or []) ++ [
./patches/0001-Allow-shiftFocus-to-move-between-monitors.patch
];
}))
];
--- a/src/Hy3Layout.cpp
+++ b/src/Hy3Layout.cpp
@@ -926,14 +926,53 @@ void Hy3Layout::shiftWindow(int workspace, ShiftDirection direction, bool once,
void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction, bool visible) {
auto* node = this->getWorkspaceFocusedNode(workspace);
- if (node == nullptr) return;
+ if (node == nullptr) {
+ shiftFocusMonitor(direction);
+ return;
+ }
- Hy3Node* target;
- if ((target = this->shiftOrGetFocus(*node, direction, false, false, visible))) {
+ Hy3Node* target = this->shiftOrGetFocus(*node, direction, false, false, visible);
+ if (target != nullptr) {
target->focus();
while (target->parent != nullptr) target = target->parent;
target->recalcSizePosRecursive();
}
+ else {
+ shiftFocusMonitor(direction);
+ }
+}
+
+void Hy3Layout::shiftFocusMonitor(ShiftDirection direction) {
+ char direction_str;
+ switch (direction) {
+ case ShiftDirection::Up:
+ direction_str = 'u';
+ break;
+ case ShiftDirection::Left:
+ direction_str = 'l';
+ break;
+ case ShiftDirection::Down:
+ direction_str = 'd';
+ break;
+ case ShiftDirection::Right:
+ direction_str = 'r';
+ break;
+ }
+
+ auto target = g_pCompositor->getMonitorInDirection(direction_str);
+
+ if(target != nullptr) {
+ g_pCompositor->setActiveMonitor(target);
+
+ auto target_center = target->vecPosition + target->vecSize / 2;
+ g_pCompositor->warpCursorTo(target_center);
+
+ // Focus
+ auto* target_node = getWorkspaceFocusedNode(target->activeWorkspace);
+ if (target_node != nullptr) {
+ target_node->focus();
+ }
+ }
}
void Hy3Layout::changeFocus(int workspace, FocusShift shift) {
diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp
index 5aef41a..d970e02 100644
--- a/src/Hy3Layout.hpp
+++ b/src/Hy3Layout.hpp
@@ -108,6 +108,7 @@ public:
void shiftNode(Hy3Node&, ShiftDirection, bool once, bool visible);
void shiftWindow(int workspace, ShiftDirection, bool once, bool visible);
void shiftFocus(int workspace, ShiftDirection, bool visible);
+ void shiftFocusMonitor(ShiftDirection direction);
void changeFocus(int workspace, FocusShift);
void focusTab(int workspace, TabFocus target, TabFocusMousePriority, bool wrap_scroll, int index);
void setNodeSwallow(int workspace, SetSwallowOption);
--
2.42.0