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

Multi-Monitor Operation #7

Open
crackulator opened this issue May 8, 2024 · 38 comments · May be fixed by #14
Open

Multi-Monitor Operation #7

crackulator opened this issue May 8, 2024 · 38 comments · May be fixed by #14

Comments

@crackulator
Copy link

When using in a multi-monitor setup, it only plays activities and workspaces on the primary monitor; the other monitors remain static. Would it be difficult to have it include all monitors in the desktop-switching?

@thrombe
Copy link
Owner

thrombe commented May 8, 2024

hyprkool does not have multi-monitor support only because i don't have multiple monitors and thus i cannot test it. i don't think it will be super hard to add multi-montor support.

if someone with multiple monitors were to help me test the plugin or make a PR, I'd be happy to support this feature.

@crackulator
Copy link
Author

I can certainly test it for you. I could probably code it up and make a PR but that's a ways away, I'd be starting from scratch and I don't have much free time at the moment.

@thrombe
Copy link
Owner

thrombe commented May 10, 2024

I can certainly test it for you

we can plan out a schedule for testing the feature. It would be great to have a few hours of quick exchanges back and forth to get it done efficiently. having to wait several hours between messages would be frustrating and inconvenient for both of us.

@crackulator
Copy link
Author

Sure, what time zone are you in? I'm USA/Pacific.

@thrombe
Copy link
Owner

thrombe commented May 13, 2024

I'm in Indian Standard Time (IST). UTC+05:30.

are you on the hyprland discord server by any chance?

@Nero-Study-Hat
Copy link

Hardware setup for context.
left monitor: 1680x1050 rotated by hyprland settings 90 degrees
right monitor: 3440x1440
ps. hardware inputs are inverse of their final direction as those were what I could reach on my gpu with my cables
they were then given their right left positioning with the monitor settings in my hyprland config


Bug: mouse switching on edge activation triggers incorrectly with empty hyprkool.toml file

  • triggers around a quarter or third of the ultrawide monitor size from the right
  • no triggering at all on the left

Suspected reasons:

  • default scaling applying without taking into account non-standard monitor aspect ratios
  • second monitor is completely ignored and nullified edge system

Bug: missing edge detection with filled in hyprkool.toml file

  • no triggering at all on the left
  • ps. right side edge detection works correctly

Suspected reasons: I got nothing


Bug: toggle-overview incorrect highlighting and on-click behavior

Intended behavior:

  • this feature is supposed to separate activity into set number of desktops and highlight edge of each desktop with some color
  • on-click send the user to the associated desktop of the area clicked on

What happens:

  • lines are displaced over windows and area for clicking does not clearly match visual area of each desktop

I will try to get screenshots for this bug to better demonstrate it tomorrow but for now I hope this can help.

@thrombe
Copy link
Owner

thrombe commented Aug 17, 2024

triggers around a quarter or third of the ultrawide monitor size from the right

this is probably cuz i only fetch the current monitor once when structs are initialized here. and dimensions for this monitor are used for every monitor. fixing it seems easy. I' might make a separate branch for testing multi-monitor setups and ask users for feedback as i don't have multiple monitors to test this.

with empty hyprkool.toml file

empty config file probably has nothing to do with this. any unspecified values are initialized with default values.

lines are displaced over windows and area for clicking does not clearly match visual area of each desktop

does this happen when some windows are in fullscreen?

@Nero-Study-Hat
Copy link

Here is a screenshot of my right monitor (ultrawide) in overview mode with a brave window open in fullscreen mode on one activity.
image
If I try to toggle overview with my mouse over my left monitor I just get this error
[hyprkool] can't display overview when not in a hyprkool activity
Now here is a screenshot with a window in every activity (not full-screened)
image
I then checked the overview with every window full-screened and the result was the same. There also is a displaced blue border if I hover over certain areas but I can'st screenshot those areas because the clicking part of it chooses an activity for me and I lose the shot.

I improved my config so switching between my custom stuff and hyprkool is a much nicer process for me now.

@thrombe
Copy link
Owner

thrombe commented Aug 24, 2024

thanks for the info. i suspect all of this behavior is also because hyprkool is using dimensions of one monitor for every monitor, which is incorrect.

@crackulator
Copy link
Author

I'm still really interested, but unable to test right now. I'll report back as soon as I have it back up and running.

@crackulator
Copy link
Author

How's it going? I've got my system all rebuilt (on Fedora this time) and hyprkool installed and working as I had it before, and updated hyprkool to 0.7.2. From the comments here it seemed like you might have done something for multi-monitor, but for me it is doing the same as it was before, just switching the one monitor. I'm available if you want me to do some testing, we can coordinate. I'm not on discord but I can be.

@thrombe
Copy link
Owner

thrombe commented Sep 19, 2024

okay so i just pushed to the multi_monitor branch.

switch_workspace_on_edge should respect the current monitor. just make sure to switch to a hyprkool activity on both of your monitors (hyprkool next-activity -c should do it)

you can test it by installing the cli from this branch again. (don't forget to restart hyprkool daemon).

i have a few questions tho. i need to understand how multiple monitors behave with hyprland.

  1. how do you take your cursor from one monitor to another? is it just by dragging it across the edge? if yes - you should probably turn off the switch_workspace_on_edge as it will conflict with that behavior.
  2. when you switch workspaces, does hyprland only switch workspaces on the monitor where the cursor is? or can you do so without having the cursor on that monitor?
  3. do all monitors show the same set of workspaces?

@thrombe
Copy link
Owner

thrombe commented Sep 19, 2024

i also updated the plugin. don't forget to unload the older plugin (if active) and then load the newer one. it should hopefully render overview without bugs now. let me know if it works, and what behavior you observe.

there are still a few bugs in this implementation - but overview should work on one monitor at a time right now. if that works fine, i'll work on fixing the known bugs.

@crackulator
Copy link
Author

From what I can tell, nothing has changed. It still changes workspaces only on the primary monitor, and then only if the mouse is on that monitor. I'm just shifting workspaces and activities using hyprland binds to "hyprkool prev-activity", etc.

Looks like the version number hasn't changed (0.7.2 on both master and multi_monitor) so I can't use that to verify that I'm running the right code. But I did get from multi_monitor, rebuild with that and install the bin, and restart the system, so I'm pretty sure I am.

I don't have the plugin loaded on my new install. I had it on the old one but it didn't seem necessary at least for the moment. I don't use the workspace edge-switching, I guess I'm too clumsy with the mouse and I was always flipping pages accidentally - which requires traversing all the way to the other edge of the screen to get back. I much prefer just using function keys.

You are asking how hyprland normally handles workspaces on multiple monitors, like without mods? It has separate workspaces for each monitor, like for my three monitors it will set them up by default as workspaces 1, 2, and 3. If you open a new workspace, it opens it on the monitor that is currently selected, and gives it the next available number, say 4. So then I might have workspaces 1:4 on the first monitor. Then I might go to the third monitor and open another workspace, and then I will have 1:4, 2, and 3:5. When you select a workspace with the function keys it switches to that monitor and workspace. This behavior is inherited from i3 and is ok for up to 10 workspaces (total across all monitors), but quite inferior to other workspace/activity models for multiple monitors imho.

What I would prefer is that all three monitors are treated as one workspace, as regards to changing activities and workspaces. Such that when I hit the bind key to move to another activity or workspace, it just changes them all simultaneously. That's what most multi-desktop multi-monitor implementations do these days, including Plasma. It's simple and works pretty well for most cases.

(Even better, perhaps, would be that within an activity, the three monitors could switch independently. But changing activities would switch all the monitors to the last-selected workspaces of that activity. That seems cool but probably complicated to code and maybe hard to drive.)

I have a feeling as I'm talking through this that multi-monitors may be much trickier for hyprkool than single monitor, maybe impossible to do blind.

@thrombe
Copy link
Owner

thrombe commented Sep 20, 2024

Looks like the version number hasn't changed (0.7.2 on both master and multi_monitor)

oops. i pushed a version number change on that branch.

I have a feeling as I'm talking through this that multi-monitors may be much trickier for hyprkool than single monitor, maybe impossible to do blind.

yeah doing it blind is the main issue. i didn't even know how hyprland behaved with multiple monitors - and i don't know what commands you need to send to hyprland (hyprctl commands) to switch monitors and workspaces within a monotor.

@thrombe
Copy link
Owner

thrombe commented Sep 20, 2024

and then only if the mouse is on that monitor

that is what i intended. as long as both monitors are on valid hyprkool activities ("activity:(x y)" workspace) - atleast switching workspaces on the active monitor should work.

from now on - could you try to use hyprkool commands instead of keybinds? if there is any error - hyprkool commands on cli will show an error which you would miss if you use keybinds. also use the --force-no-daemon flag just to make sure a daemon from different version of hyprkool isn't used.

Even better, perhaps, would be that within an activity, the three monitors could switch independently. But changing activities would switch all the monitors to the last-selected workspaces of that activity.

yes i would prefer this too. i'll try the activity thing once basic things like switching workspaces works fine.

to be clear, currently when you run hyprkool move-right -c it should move that monitor to the workspace to the right of it.
similarly - hyprkool next-activity -c should move that active monitor to the next activity.

@thrombe
Copy link
Owner

thrombe commented Sep 20, 2024

moreover - can you tell me the exact hyprctl commands you may use to change workspaces on your monitors?
that will help me check if the correct commands are being sent from hyprkool

from what i can see - there isn't a separate hyprctl command for switching workspaces if you happen to have multiple monitors.
hyprctl dispatch workspace "activity:(x y)" should work as i understand it.

also - can you check if you can switch to a different hyprkool workspace manually by running hyprctl dispatch workspace command on more than 1 monitor?

@crackulator
Copy link
Author

crackulator commented Sep 22, 2024

I set up a default hyprland install to get a handle on the multi-monitor behavior without hyprkool, and did a bunch of experiments with the dispatches.

"hyprctl dispatch workspace [N]" does not allow you to specify which monitor. If that workspace already exists on a monitor, it will switch focus to that monitor, and also select that workspace on that monitor. If the workspace does not already exist on a monitor, it will create it on the currently selected monitor and select it.

So you use "dispatch focusmonitor N" to focus on each monitor (this is a number starting with 0, enumerating the available monitors, so with my three-monitor setup it's 0, 1, 2) and then select a workspace for that monitor using "dispatch workspace N". You don't have to worry about whether or not the workspace already exists, as long as you always assign a given workspace to the same monitor (it would come into play if the workspace existed on a different monitor from where you wanted it).

So I believe, compared to the 1-monitor implementation, you need to allocate T times as many workspaces, where T is the total number of monitors. Then after the calculations you're doing accounting for the activities and workspaces within the activity, multiply by T (lets call that WxT). Then loop through the monitors, for each one do focusmonitor N, and assign it to workspace WxT+N where N is the enumeration of the monitors from 0 to (T-1).

Does that make sense? The math appears to be the same for 1 monitor or multiple monitors, so at least you can test it in the 1-monitor case :)

If that doesn't pretty much nail it down, let me know, I can probably try adding it to the project code. I haven't looked at the code at all, but it looks like the algorithm boils down fairly easily.

@thrombe
Copy link
Owner

thrombe commented Sep 22, 2024

Thanks for the info!

If that workspace already exists on a monitor, it will switch focus to that monitor

this is not what i expected. luckily there's a dispatcher called focusworkspaceoncurrentmonitor which does what we expect here.

if i understand this correctly -
say you have 3 workspaces w1, w2, w3. and 2 monitors m1, m2
w:m -> m currently focuses w
f:w -> cursor is currently on monitor w

f:w1, m1:w1, m2:w2
hyprctl dispatch workspace w3
f:w1, m1:w3, m2:w2
hyprctl dispatch workspace w2
f:w2, m1:w3, m2:w2
hyprctl dispatch workspace w1
f:w2, m1:w3, m2:w1

if this is correct - simply replacing workspace dispatcher with focusworkspaceoncurrentmonitor in hyprkool should just work.

@thrombe
Copy link
Owner

thrombe commented Sep 22, 2024

Does that make sense?

it does make sense, but luckily hyprkool does not do much tracking of workspaces. neither does hyprland require explicit allocation of workspaces.

all info hyprkool needs is present in the name of the workspace itself. so i can just provide a toggle to add another dimension to the workspace name. activity:(x y m) (m being the monitor number).
this way user can choose to keep separate workspaces for each monitor, or use the same set of workspaces for all monitors.

@thrombe thrombe linked a pull request Sep 22, 2024 that will close this issue
@thrombe
Copy link
Owner

thrombe commented Sep 22, 2024

added a new config option.

# ~/.config/hypr/hyprkool.toml
multi_monitor_strategy = "SharedWorkspacesUnsyncActivities"

possible options:

// all monitors share a common hyprkool workspace (same x y) acitvity:(x y w)
SeparateWorkspaces

// activity:(x y)
SharedWorkspacesSyncActivities // m1:a1w1 m2:a2w2 -> m1:a2w1 m2:a2w2 when switching activities
SharedWorkspacesUnsyncActivities

let me know how these behave.

@crackulator
Copy link
Author

Ah, I see. I didn't understand when you were talking about "activity: (x y)", that's the name/identifier of the workspace (without multi-monitor support). I had assumed you were just resolving that to a number, since by default the workspaces are numbers (though of course you can name them too). Anyway I think I get it now, yeah, it needs to be "activity: (x y M)", where M is the monitor.

Whether you use "dispatch workspace" or "dispatch focusworkspaceoncurrentmonitor" I don't think matters, because you wouldn't ever be moving a workspace from one monitor to another, a given workspace would always be on one monitor, so the behavior would be the same.

Anyway I tried the latest (it calls itself hyprkool 0.7.2-multi-monitor), and it's all kinda messed up. I think it's because the workspaces are named like "activity:(1 1$)".

When I first start up, "hyprctl monitors" it tells me that monitor 0 is on workspace "home:(1 1$)", monitor 1 is on workspace "2", and monitor 2 is on workspace "3". (home is the name of my first activity). The 2 and 3 correlate to the default workspaces that would be selected with no hyprkool So maybe there is some code that sets up the monitor to a certain workspace on initialization, which does only the first monitor?

If I then do "hyprkool next-activity", in a terminal on the first monitor, only the first monitor is affected. The terminal disappears off the screen as if I have gone to another activity. If I then do "hyprctl monitors" it says my monitors are on the same workspaces they were before ("home: (1 1$)", 2, 3). "hyprkool prev-activity" doesn't bring it back, it just does the same thing again: the terminal disappears, and "hyprctl monitors" still reports I'm in the same workspaces.

move-up and move-down exhibit the same behavior. The terminal disappears, but the workspaces don't change. That is, if I do them on the first monitor. If I do them on either of the other monitors, it reports "Error: not in a valid activity workspace" (which makes some sense because it's on workspace "2" or whatever).

I don't understand the three options for multi_monitor_strategy, but I believe I'm seeing the behavior described above with no entry in the toml file and with multi_monitor+strategy = "SharedWorkspacesSyncActivities".

@thrombe
Copy link
Owner

thrombe commented Sep 23, 2024

home:(1 1$)

oh no. silly bugs. :(

So maybe there is some code that sets up the monitor to a certain workspace on initialization

yes. it should have set it on all the monitors on the latest commit, but clearly it was more buggy than i thought.
it appears you are still running the daemon on boot?
could you disable the daemon for now and use the commands in this fashion for testing?

I believe I'm seeing the behavior described above with no entry in the toml file and with multi_monitor+strategy = "SharedWorkspacesSyncActivities".

the home:(1 1$) ruined everything here.

i'll try to fix the bugs with a little more testing this time :(

@thrombe
Copy link
Owner

thrombe commented Sep 23, 2024

okay, so i managed to create a virtual machine setup with 2 monitors which mostly works.

hyprland only moves already existing workspaces with moveworkspacetomonitor dispatcher, which makes working with multiple monitors much harder.

correctly handling multiple monitors will be more work than i originally thought.

@crackulator
Copy link
Author

Why would you use moveworkspacetomonitor? It seems like activity:(x y 1) would always be on monitor 1 - if you always set M to the currently focused monitor, "dispatch workspace", will always bring it up on the correct monitor.

@crackulator
Copy link
Author

Do you want me to work on this? It'll take some time, but I'm willing to tackle it.

@thrombe
Copy link
Owner

thrombe commented Sep 24, 2024

It seems like activity:(x y 1) would always be on monitor 1

there're three different modes in the config. so not always.

@thrombe
Copy link
Owner

thrombe commented Sep 24, 2024

It'll take some time, but I'm willing to tackle it.

if you want to do it and have the time, sure.

@crackulator
Copy link
Author

Hehe, well I would estimate my enthusiasm 8, competence 6, free time 1. And if activity:(x y 1) would not always be on monitor 1, then I don't really get where you're going with it...

I'll peruse the code and see what I can figure out.

@crackulator
Copy link
Author

Ok, I got it working at least for some cases, and I think it's a template for all cases. I could probably give you a PR but that's another hurdle and the changes are pretty isolated, so here is the relevant code in state.rs:

use regex::Regex;
                    .map(|(x, y)| format!("{name}:({x} {y} $)"))
	let re = Regex::new(r"\d+\)").unwrap();
	let name = re.replace(name,"$)");
        match self.config.multi_monitor_strategy {

            MultiMonitorStrategy::SeparateWorkspaces => {
                // get x y for current monitor and switch all monitors to x y w
                let monitors = Monitors::get_async().await?;
                let mut monitors = monitors.into_iter().collect::<Vec<_>>();
                monitors.sort_by(|a, b| {
                   if a.focused {
                        Ordering::Greater
                    } else if b.focused {
                        Ordering::Less
                    } else {
                        Ordering::Equal
                    }
                });
                for m in monitors.iter() {
                    let wsname = name.replace("$", &m.id.to_string());
                    Dispatch::call_async(DispatchType::Custom(
                        "focusmonitor",
                        &m.id.to_string()
                    ))
                    .await?;
                    Dispatch::call_async(DispatchType::Custom(
                        "workspace",
                        &format!("name:{}", wsname)
                    ))
                    .await?;
                }
            }

With these changes, I am able to use next-activity, prev-activity, and switch-to-activity, with the multi_monitor_strategy = SeparateWorkspaces. move commands don't work, they complain that it's not a valid activity workspace. I haven't looked into it.

I still don't understand where you are going with multi-monitor-strategy; is this just sort of a debug option for you to play with different algorithms, or are you intending a user feature? I worked on SeparateWorkspaces just because it looked the closest to working; the other cases all start with "let name = name.replace("$", "");" which will never work out. Hyprkool's workspace model won't allow you to have the same name of workspace on different monitors simultaneously.

@crackulator
Copy link
Author

Well I have everything working, at least the features that I use. Which is basically moving among activities and workspaces with keybinds, also moving windows around, and interacting with the eww buttons.

I'll try to get github straightened out and submit a PR to your multi-monitor branch. But ultimately I think we should do this a different way. I believe the "$" wildcard for the monitor dimension is doing more harm than good, in the long run we will find that it will cause a lot of bugs and workarounds. So I may try to recode some bits with another idea.

As far as multi-monitor-strategy for users, I would suggest that we write two cases: monitors Linked, or monitors Independent (affecting both workspaces and activities). The default would be Linked, it's simplest and what most DEs do. That's what works so far. Independent would allow the user to switch monitors independently to different activities and workspaces.

I'd also like to add something to "info" that would let eww indicate whether there are windows active on a workspace; I think that would be helpful in searching for lost windows.

Thoughts?

@thrombe
Copy link
Owner

thrombe commented Sep 29, 2024

I believe the "$" wildcard for the monitor dimension is doing more harm than good

yes i agree. i did that just to see if things work. i was going to rewrite it later if it all worked out.

I would suggest that we write two cases: monitors Linked, or monitors Independent

that was what i was trying to do with the options i mentioned earlier.
as i understand it, monitors Linked should be equivalent to SeparateWorkspaces (as in, each monitor uses it's own set of workspaces. therefore it has 3 dimentional coords)
and monitors Unlinked should be equivalent to SharedWorkspacesUnsyncActivities. all workspaces can be used on all monitors. switching workspaces on one monitor does not switch on other monitors.
and the third option SharedWorkspaceSyncActivities would be where all monitors switch workspaces when you switch activities.
these option names were temporary. if you have better names, just use those.

I'd also like to add something to "info"

that should be fine

@crackulator
Copy link
Author

Not sure where to go with it from here. It is working well with my PR to the multi-monitor branch, I'm using it daily driving, though not flexing all the features. Ultimately it should probably be merged with the main branch, no? It would need to be decided how you want to handle the monitor designation in the workspace name. Seems like there are a number of options and considerations there.

@thrombe
Copy link
Owner

thrombe commented Nov 25, 2024

yeah. i can't merge it without testing all the features. either i'll have to do that work when i have access to a second monitor, or someone else will.

i might be getting a second monitor sometime not too distant in the future tho. and i'll def want to support multiple monitors when that happens.

it's good to know your PR is working for you. i'll check it out again when i have some free time.

@crackulator
Copy link
Author

can I sponsor you for another monitor?

@thrombe
Copy link
Owner

thrombe commented Nov 26, 2024

Sure, if you're sure about it, I'd really appreciate it!

It honestly makes me happy to know that you like my work enough to sponsor me with a monitor. Just to be upfront, though, I can't promise many new features since I'll be starting my first job soon and my time will be a bit more limited.

That said, multi-monitor support is something I definitely still want to add, especially since I'd love to use it myself!

@crackulator
Copy link
Author

Where can I send funds?

I really appreciate all your work on this project, I'm using it every day and it's my favorite desktop environment right now.

@thrombe
Copy link
Owner

thrombe commented Dec 7, 2024

thank you for the kind words! that made my day.

i have just set up a github sponsors account. you can use that.
https://github.com/sponsors/thrombe

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 a pull request may close this issue.

3 participants