-
Notifications
You must be signed in to change notification settings - Fork 195
Add 'max_window_width' feature #482
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
Conversation
…eds the max_window_width * window_count, update all layouts to use the new method on workspace
This is great! And also the commit message is awesome 😎, thanks! I indeed think that the Besides that and my in-line question, this looks really good. Regarding that inline comment: maybe at some point we might consider refactoring these matches into its own function? But this might very well be its own PR. |
I agree we could use a lot better code documentation, I think the wiki should be more for user documentation (but could also use a bit more love, although it's not too bad lately, I guess). |
Could also be useful to time that around the PR that pushes us to Rust 2021. |
I initially had something like Well, instead of having to find a good name for that method, we could also simply get rid of it. It's only used in the window-snap feature right now, mainly because I didn't have access to the
Maybe one of those is already possible by accessing the value through some existing properties (?), or maybe those are bad ideas... As I've said, I don't understand most of the code/project structure yet.
What do you mean with in-line question? Do you mean a direct comment on the code? If so, I can't find that. I think you have to submit a PR review before others can see those comments. |
src/layouts/center_main.rs
Outdated
@@ -64,39 +64,41 @@ pub fn update(workspace: &Workspace, windows: &mut Vec<&mut Window>, tags: &mut | |||
return; | |||
} | |||
|
|||
let workspace_width = workspace.width(window_count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I liked it better with keeping the function call in the match arms, since it is more clear when reading the code the width is calculated based on the number of windows.
But this is just a personal preference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I extracted this to a variable for two reasons:
- If I didn't extract this the line gets a bit long and
fmt
would force me to add a line break like here. - At most places where I replaced it, declaring this variable also prevents multiple unnecessary calls to the
width()
method. While I don't think that the method is particularly expensive, it's still a performance improvement. Which admittedly might be very small. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that I was a bit inconsistent about doing that, if there is a general preference of the maintainer(s) whether to create those variables or not, I can further adapt the code in the layouts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I get that.
The fmt
suggestion is a bit odd. I would have expected more something like this (note: am on mobile again, so the actual amount of indentation might not be fmt compliant):
_ => (workspace
.width(window_count) as f32 / 100.0 * workspace
.main_width(tags)).floor() as i32,
I guess we leave this as you suggested and with the layout-handler coming at some point there is quite a bunch of refactoring coming ahead anyways.
I think we could move almost all these matches to a dedicated function then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @hertg mostly with reducing calls as .width now has more overhead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, then.
@@ -11,6 +11,7 @@ pub fn process(manager: &mut Manager, screen: Screen) -> bool { | |||
screen.bbox, | |||
manager.tags.clone(), | |||
manager.layouts.clone(), | |||
screen.max_window_width.or(manager.max_window_width), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thing:
If we could try to calculate this from workspace sizes in the config would be really good to be more consistent from the users view.
Can't we get the actual workspace size anywhere we have the workspace by workspace.xyhw
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if this is a general comment or if it is directed at me.
Unfortunately, I couldn't wrap my head around what xyhw
and bbox
exactly stand for, so I don't fully understand the comment. I'll try to dig into that the next time I work on the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, totally missed to come back to this one.
But at the point I commented on this I hadn't understood yet, you are actually changing the workspace size, so I guess this should be good.
Yeah, I didn't like
That might work as well 😬
I totally feel you here. There are still parts of the code I am having a hard time figuring out whats going on. (to be fair though, I am by no means a seasoned developer and started learning Rust basically the same time I started getting onto this project 🤷♂️)
Oh, right, sry. I was writing this on mobile and missed to send the review. |
That sounds like a pretty good idea to me. I can look into this snap thing and change the |
The code seems good, I find it a bit weird as you are less limiting the size of the window but its container (the workspace). Because of this we would need clear code documentation (comments) to help new contributors. (Idk how possible or easy it would be to make it an actual limit on the window, which could allow in the future per app sizes and to limit the size of floating windows. If this is a bit much don't worry). Another note would be to give the user the option to set a percentage of the workspace width (This could be set as a float for easier differentiation). With the method naming, I feel keeping the original the same as it was and change the new method to something like PS I should have time soon to actually start #448, or should I wait for #472 now to save @cecton extra work. |
I totally agree, and it felt weird doing so. The reason why I did was because of the
Do you mean for the
Yeah that naming sounds pretty self-explanatory, I can change it to something like that. |
You could use a different key or you could use an enum, e.g.
Similar to margins. Where the pixels can be calculated and set in the same place in screen_create_handler. |
Sure. I'll address some feedback I got from the other people and then resolve the conflicts. I'll probably have some time for that tomorrow. :) |
Ooh, so much for reading on mobile. I totally missed the point, that you are actually limiting workspace width. Regarding the snap rework: thanks for volunteering, I'll open an issue for this later, to better keep track of the ideas. |
So I'm working on the PR right now, and I found a possible solution to also fix the weird flickering in the snap feature. A pretty easy solution for this would be to always check the windows float position, even if it isn't floating. Because we don't really care about the windows current tile position to check whether it should snap. My problem is that I don't know how to get the windows floating position when it's currently not floating. There is the To get this PR moving, I can stash the changes I made to the snap code and address them later, as it is a pre-existing issue and not a regression introduced here. Btw. As was asked for here, it would be great if there was a community discord or something. Having such a place to ask questions about the code or to share knowledge would be great. It seems a bit awkward to ask quick questions via Github. What do you think about that? |
…es instead of multiple method calls in layouts
I don't mind making and setting up a server, however @lex148 would you prefer to set it up? Shall we create an issue for suggestions for it, or shall we wing it and see what everyone feels once added. |
Alright, so I've updated the code and addressed your feedback:
That's all for now. We can address the snap issue in a future PR :) |
Wow, this is looking super great now! I'll open an issue to keep track of the snap-rework ideas right away. |
I like this feature a lot and the code looks great. Conceptually though this seems like a different set of layouts rather than a setting for a window or workspace. Would it be feasible to create additional layouts that take the max_width setting from config.toml? This would make it easy to sort of toggle the feature on off by having both Monocle and MonocleMaxWidth enabled. |
But as shown in one of the comments by @hertg this feature actually mixes very well with several layouts, especially when viewing more windows then a single one as monocle would. |
Sorry, I should have clarified, Monocle was simply an example. It would mean adding layout enum variants for each layout you want a max_width option enabled. |
I'm not sure if creating completely separate layouts for this is better than applying the config to the existing ones, it would lead to a lot of duplicate code. If toggling the max-width feature is something people want in the future, there probably is a more user-friendly approach to achieve that than having to switch layouts. Edit: Sorry, I sent the comment too early You did remind me of something I missed though. I developed this feature, mainly with the The same goes for two column layouts, if the specified max-width is smaller than half of the workspace width. Or any vertical stack layout I should probably patch that, but I need some feedback on how the layouts should behave when the
Personally, I'd probably prefer the second option, the only "drawback" of that is the following:
I don't think that's e big issue though, if you have an ultra-wide monitor and set a Do you guys have any opinion or other ideas? I would really appreciate hearing from people that also use ultra-wide monitors (34' / 49'). When should I address that? Personally I never use anything different than the If this PR blocks other contributions from moving on, it's probably better to merge it as is and patch that later. If it doesn't, I can patch it directly here after considering the feedback. |
I would say the second option, as if the user doesn't want wasted space they would be best splitting the monitor into multiple workspaces. If this option becomes togglable per layout used, this would also solve the issue (as a note to this we may want to expand and/or rewrite the layout code to allow for the expanding options). Thanks. |
Fair enough. I don't think it would have to be duplicate code necessarily. The max_width variants could call the regular variants but passing different dimension parameters based on the max width setting. In any case it looks like this is going to work in the paradigm you've already started so I won't belabor the issue. Cool feature. |
You've got a point though, being able to dynamically toggle the width limitation might be cool. But I would personally prefer that to be toggleable dynamically per tag or something, rather than having to change layouts to toggle it. Being able to dynamically increase or decrease the But for the time being, it's probably better to go forward with this in the current state and let people use the feature in its basic form. If any pain-points arise or such additional feature-requests are wished for after people used it, I'll be happy to extend the functionality of this new feature in a future PR :) |
Personally I'd say this is ready to merge and these minor issues can be patched later on. But to be fair I only use a 14" Laptop 😛 and if I had a external monitor with the above aspect ratio I'd probably configure two square workspaces left and right and the rest in the center. This reminds me, that at some point we had a feature request or discussion in the comments of one issue, about a 'fullscreen over all workspaces'. Which would also be nice, and might not being too far fetched as this PR proves, that we are actually capable of dynamic workspace sizes, which is awesome, and I believe quite unique. Another idea that came to mind while reading this, was if it might be useful to have an optional config field |
Ok, you all rocketed past me, while I was writing my last comment on the subway 😂 And I was just about to write if we might want to toggle this feature, but thought maybe keep this for a later discussion. I believe with gathering more and more dynamic and togglable features we are at a point where an actually soft reload or |
/// an absolute pixel value or a relative percentage value | ||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Copy)] | ||
#[serde(untagged)] | ||
pub enum Size { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In retrospect, I think it is a bit weird that any int is automatically assumed to be a pixel value, and any float is assumed to be a percentage... Maybe in the long run, it would be cleaner to allow setting a unit and parse from that, similar to CSS. Where an absent unit would default to pixel.
250
=> Pixel(250)
250px
=> Pixel(250)
250%
=> Percentage(250)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe keep the float with 2.5
=> Fraction(2.5)
?
I Actually like the distinction of absolute sizes in int and relative sizes in float.
All in all, the size
model is a really great achievement of this PR and I can see use of it in many other config options, like margins, gutters, scratch pad dimensions and position, default floating dimensions etc.
🥳
FWIW the ability to define workspaces already makes leftwm a good tool for ultra wide monitors. This feature does make it more flexible and user friendly, though. |
I added some documentation for this feature to the wiki: |
This PR addresses my feature request #475.
It allows setting a
max_window_width
in the configuration file.As suggested by @VuiMuich in #475 (comment), the max width can be set globally or on a per-workspace level. A per workspace configuration takes presedence over the global configuration.
Setting this configuration is optional, if it isn't configured, layouts will behave as they did before, by filling the complete workspace width.
The max width will be applied to every layout, as I've updated the code of
workspace.width()
to account for this configuration. Because of that, the method now requires a parameter ofwindow_count: usize
so it can calculate the correct width.Example

In this example, a global configuration of
max_window_width = 2100
has been configured. The monitor has a resolution of5120x1440
.I would appreciate some feedback on the code, and am happy to change anything if it goes against the projects architecture or best-practices. As I have only worked in smaller scale Rust projects, it was a bit hard to navigate the code at first. Is there some form of documentation about the project architecture available anywhere? I wasn't able to find a summary anywhere in the markdown files or the Github Wiki. Such a document would be pretty helpful for first-time contributors.
I tested the feature with a single and with multiple workspaces and it works as intended. I also ran all the tests, fmt, and clippy successfully. However there are some things I was unsure if I did them correctly:
max_window_width
variable to thescreen
struct, because I can't access the workspace configuration in thescreen_create_handler.rs
where the workspace gets created, so I have to get the workspace's max_window_width value directly from the screen.workspace.x()
andworkspace.width()
asworkspace.x_without_window()
andworkspace.width_without_window()
respectively (I can rename those if you have a better alternative). The only place where I still call those is from the snap feature inwindow_move_handler.rs
, because I (think) I don't have access to the workspace's window-count there.This has the side effect that the window snap feature still snaps to the edge of the original workspace, and not to the edge of the outer windows. But maybe that's something you'd expect? I'm unsure because I never use the snap feature... I think it is a bit hard to use, because the window always jumps around if I don't hit the exact pixels where it snaps.
I will provide documentation for the feature in the Github Wiki after the PR is merged. Please let me know if this needs documentation anywhere else :)