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

Shift focus to monitor if at the edge of the screen #5

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

TheZoq2
Copy link

@TheZoq2 TheZoq2 commented Jun 4, 2023

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

@TheZoq2
Copy link
Author

TheZoq2 commented Jun 4, 2023

Oops, this seems to cause some random freezes, don't merge until I figure that one out 😓

@outfoxxed
Copy link
Owner

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.

@TheZoq2
Copy link
Author

TheZoq2 commented Jun 6, 2023

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

@outfoxxed
Copy link
Owner

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:

if (break_parent->parent == nullptr) {

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.

@sekhat
Copy link
Contributor

sekhat commented Aug 15, 2023

@TheZoq2 Any news on this?

@TheZoq2
Copy link
Author

TheZoq2 commented Aug 16, 2023

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

@jess-sol
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

hy3:movefocus doesn't change monitor
4 participants