TimUntersberger / nog

A tiling window manager for Windows
MIT License
698 stars 20 forks source link

Resizing Tiles #93

Closed ramirezmike closed 4 years ago

ramirezmike commented 4 years ago

A feature should be added that lets you bind keycommands to changing the size of a focused tile. It could be something with modifier keys + a direction (configurable so users can do hjkl, wasd, ijkl or combinations of [] {}) or an axis?

For example, given you had 3 tiles displaying next to each other as columns and you wanted to alter the width of the center tile..

Same for decreasing the tile size but in the opposite directions (adjacent tiles would expand).

Additionally, the amount that the tiles expand/shrink should be configurable as either a pixel-based amount or a percentage size of the display the tiles are currently displaying on.

Might also want to consider what happens when a user has several tiles that have been resized on one grid and then they unmanage or move a tile onto a different workspace, although it may just be as simple as have the adjacent tiles split the difference between them.

TimUntersberger commented 4 years ago

Additionally, the amount that the tiles expand/shrink should be configurable as either a pixel-based amount or a percentage size of the display the tiles are currently displaying on.

I don't really think that supporting pixel based expansion is really important. I don't really see a valid use case for this, can you please tell me a few examples? This will probably increase the difficulty by a bit.

ramirezmike commented 4 years ago

Ah, the only reason I suggested pixel-based as an option was because the existing sizing code looks like it's calculating widths/heights and x/y positions in pixels. But, I suspect having a increment/decrement set to one pixel count value would cause issues between monitors of different resolutions, i.e., changing by 5 pixels may work on a user's small screen but take forever on their large screen.

I do think it'd be simpler as just one system and I suspect it'd be easier and more compatible if it was percentage-based. Not sure if there's a flaw in that approach that I'm unaware of.

Oh, also another thing I forgot to mention is what to do if the amount it's changing ends up as an odd number split between two adjacent tiles. I figured in that scenario though you'd just default to giving the extra pixel or whatever to the left/up or right/down tile.

TimUntersberger commented 4 years ago

Oh, also another thing I forgot to mention is what to do if the amount it's changing ends up as an odd number split between two adjacent tiles. I figured in that scenario though you'd just default to giving the extra pixel or whatever to the left/up or right/down tile.

We will see what feels best when it is implemented.

TimUntersberger commented 4 years ago

Note to self: this will include a small refactor from pixel based to percentage based alignment.

0b01 commented 4 years ago

Ideally also support auto resize all tiles when dragging on the border of one window

TimUntersberger commented 4 years ago

I will try to implement this in the following order:

  1. Keybindings for basic resizing
  2. Resize mode (use movement keys for resizing until you leave the resize mode)
  3. Mouse support

Whenever I'm done with one part I'll push it to dev.

TimUntersberger commented 4 years ago

I pushed my current progress to the resize branch.

Keybindings I used:

  - type: Resize
    key: Alt+Shift+H
    direction: Left
    amount: 2
  - type: Resize
    key: Alt+Control+Shift+H
    direction: Left
    amount: -2
  - type: Resize
    key: Alt+Shift+J
    direction: Down
    amount: 2
  - type: Resize
    key: Alt+Control+Shift+J
    direction: Down
    amount: -2
  - type: Resize
    key: Alt+Shift+K
    direction: Up
    amount: 2
  - type: Resize
    key: Alt+Control+Shift+K
    direction: Up
    amount: -2
  - type: Resize
    key: Alt+Shift+L
    direction: Right
    amount: 2
  - type: Resize
    key: Alt+Control+Shift+L
    direction: Right
    amount: -2

I got the basic stuff to work, but there are still some edge cases I'll have to fix, but it would be nice if some of you could try out the resizing and give me some feedback on how the resizing feels.

The direction based resizing feels really bad for me to be honest.

I'm currently thinking about just providing keybindings for resizing by changing the height/width of a tile.

ramirezmike commented 4 years ago

I fetched from the resize branch but ran into borrow errors when compiling. I'll try to get it running sometime later today, but I looked over the changes and...

The direction based resizing feels really bad for me to be honest.

Can you describe what you mean? From the code it looks like it just expands/contracts in the direction you pick. Should it have some momentum while you resize or do you feel like it's too imprecise?

TimUntersberger commented 4 years ago

Can you describe what you mean?

There isn't really any keybinding combination that feels good to use, because you need 8 for 4 directions.

I probably just need to get used to it before I can be really sure.

I fetched from the resize branch but ran into borrow errors when compiling

Hmm interesting. I am not getting any borrow errors. Can you please tell me what the problem was once you fixed it?

ramirezmike commented 4 years ago

Can you please tell me what the problem was once you fixed it?

Did another reset on the commit and re-compiled and everything worked, so it probably was just a conflict with my working directory or something.

Anyway, I played around with it a bit. Obviously I realize this is a wip, but I was a bit confused as to whether you're planning on having the tiles all react to resizes or just the one tile you're resizing. At some points it did start modifying the sizes of multiple tiles simultaneously and got a bit confusing.

There isn't really any keybinding combination that feels good to use, because you need 8 for 4 directions.

Another approach could be to have a keybinding that puts the user in "resize mode" and then use hjkl/modifier + hjkl but.. that might still be technically 8 bindings although it could at least overlap with existing keybindings in that case.

The direction based resizing feels really bad for me to be honest.

I don't think the keybindings themselves are that bad, but because of the nature of the tiling windows, depending on what tile is focused some of they keybindings won't make sense: "what does it mean to shrink/expand up/down on a tile that fills a column?", "expanding a tile to the left when it's already on the left border of the screen" and that kind of stuff.

I did get tripped up a bit because of these things which made it feel tedious-ish: 1) expanding a tile to the left when it's already as left as it can go makes it expand right, which I'm assuming is just because it's a wip 2) other tiles don't react to focused tile's size changes 3) gaps that can be created

Screenshot from 2020-08-01 11-58-58

Like here, I shifted B window -Left a bit. Should C window follow with it? Should A expand to the right? Or in the following two pictures where I've -Left and -Right window A and then expanded window A past the other tiles.

Screenshot from 2020-08-01 12-00-12

Screenshot from 2020-08-01 11-59-29

Personally, if I'm resizing I'm doing so with the goal of making use of the entire screen, trying to eliminate any gaps (ignoring configurable margin/padding) and avoid overlapping, so if the controls were more context-sensitive it may make it feel better in that regard.

Given a setup like this assuming the hotkeys are just hjkl for ResizeLeft, ResizeDown, ResizeUp, ResizeRight:

Screenshot from 2020-08-01 11-58-34

Focused on Tile A: Left - Doesn't do anything OR shrinks the right side of A in the LEFT direction UP/Down - Not applicable Right - Expands to the right

Focused on Tile B: Left - Expands B and C tiles to the left and shrinks A Right - Shrinks B and C tiles to the right and expands A Up - Shrinks B upward and expands C and D upward Down - Expands B downward and shrinks C and D downward

Focused on Tile C: Left - Expands B and C tiles to the left and shrinks A Right - Expands C tile to the right and shrinks D Up - Shrinks B upward and expands C and D upward Down - Expands B downward and shrinks C and D downward

I realize that's a lot of context-sensitive coding and might be un-intuitive with questionable edge-cases, but I hope that somewhat shows an approach of resizing with assumptions about what the user is trying to achieve in order to speed up the process.

All that said, I want to also stress that I'd really like other people to share their thoughts too as I don't want to be the only other voice in the room here throwing out crazy ideas that no one actually wants. I definitely think there's room for discussion here.

TimUntersberger commented 4 years ago

Thanks to your examples I changed my way of thinking about this problem and I believe I can now implement this a LOT easier. Before I set some data on each tile when resizing which results in a massive amount of edge cases which have to be handled, but now I will just think about resizing a column/row instead of an indiviual tile. This is pretty obvious when I think about it in hindsight since it is a grid.

TimUntersberger commented 4 years ago

Resizing is now implemented in the resize branch

Right now I am thinking about how a resize mode could make the experience better.

There need to be keybindings for setting a column/row back to there normal size.

Some questions that I am thinking about now:

TimUntersberger commented 4 years ago

Update: I looked for ways on how to make the keybinding system a lot more flexible and I should now be able to add the concept of a "mode".

This means that I no longer use the RegisterHotKey function, but instead listen for every keypress and use custom logic to know which keybinding to use.

Concept for a resize mode:

  1. Press a shortcut for toggling resize mode (Example: Alt+R)
  2. Use h/j/k/l to increase in a direction (Shift for decreasing)
  3. Press the shortcut again
  4. h/j/k/l are no longer used for resizing

This can be leveraged to make it possible to define custom modes.

I am still thinking about how to support modes in the config, but this is how I am currently imagining it:

modes:
  resize:
    key: Control+R
    keybindings:
      - type: Resize
        key: H
        direction: Left
        amount: 2

Everything besides the key field gets only loaded when you are inside a mode.

This could be expanded for modifying the gaps for example.

modes:
  gap:
    key: Control+G
    keybindings:
      - type: IncrementConfig
        key: Plus
        field: padding
        value: 2
      - type: DecrementConfig
        key: Minus
        field: padding
        value: 2
      - type: IncrementConfig
        key: Shift+Plus
        field: margin
        value: 2
      - type: DecrementConfig
        key: Shift+Minus
        field: margin
        value: 2

One thing I am not to sure about is whether to swallow the keypress when in a custom mode or to let them go through.

I am very excited for the future of this feature!

Branch

ramirezmike commented 4 years ago

I tried out the resize branch and it's definitely feeling a lot better for me although there were still moments where I hit key commands expecting something to move but nothing did, and I think that's more of like what I was saying above.

I definitely like the way it reacts as a grid more though, but I was still able to make situations like this:

Screenshot from 2020-08-02 19-24-09

Although, honestly I don't think I'd really setup windows this way anyway and it may be a contrived example. I'm not really sure what should happen there.

As far as the modes, that definitely sounds useful. One thing I thought of at some point was putting some sort of visual indicator on the app_bar when you have an app fullscreened because sometimes I'd forget or switch to a workspace and try un-fullscreening only to realize it was the only app on that workspace. I think that... while that may or may not deserve an indicator, I think switching modes should show some indicator of what mode you're in.

TimUntersberger commented 4 years ago

@ramirezmike I can't really reproduce your screenshot. In what sequence did you create the tiles?

I tried out the resize branch and it's definitely feeling a lot better for me although there were still moments where I hit key commands expecting something to move but nothing did, and I think that's more of like what I was saying above.

Could you please give me some examples?

ramirezmike commented 4 years ago

In what sequence did you create the tiles?

For something like this:

Screenshot from 2020-08-03 08-55-10

(Assuming "open window" is just like... opening a new application that automatically gets managed)

1) Open window (A) 2) Open window with vertical split (B) 3) Switch to horizontal split and open window (C) 4) Switch back to vertical split and open window (D)

I don't really have a use case for this, it feels like a contrived situation I came across playing around with this but I can't expand B individually width-wise without affecting C.

Also, I did run into this afterward while closing windows I had opened and resized:

thread 'main' panicked at 'attempt to divide by zero', src/tile_grid.rs:491:30

But I'm having trouble reproducing that.

Could you please give me some examples?

After playing with it some more, I think it's just I thinking of it as moving the split rather than expanding/shrinking the window in a specific direction. Like, in the picture above if I do Alt+Shift+J to expand B window downward, if I go to far and want to "go back" my instinct is to hit Alt+Shift+K rather than Alt+Ctrl+Shift+J. Switching into the resize mode may make this easier for me though.

ramirezmike commented 4 years ago

Also, another quick thought: while in "resize mode" hjkl can resize the focused tile and something like wasd can be used to change which tile is focused?

TimUntersberger commented 4 years ago

The goal is that you can do whatever you want when in a mode.

example

modes:
  resize:
    key: Control+R
    keybindings:
      - type: resize
        key: H
        direction: Left
        amount: 2
      - type: focus
        key: A
        direction: Left

The resize keybinding type can also be assigned to when not in a custom mode.

example

keybindings:
  - type: resize
    key: Alt+Shift+H
    direction: Left
    amount: 2

Note: Every keybinding that doesn't belong to the current mode gets ignored.

TimUntersberger commented 4 years ago

The mode feature is now almost complete. The only remaining part is a visual indicator in the appbar. The problem is that I don't really know what the best way to display an active mode in the appbar is.

My plan right now is to just support a letter (which can be a unicode character if you want a nice icon like 👁).

You will be able to configure the letter somehow like this

modes:
  resize:
    icon: 👁
    key: Alt+R

The letter would be visible somewhere in the area of the red square in the following picture image

If someone wants to try out the mode feature you can checkout this branch.

Config I used to test this (modes are at the bottom)

```yaml app_bar_font: Cascadia Mono app_bar_font_size: 17 min_width: 200 min_height: 200 work_mode: false multi_monitor: true launch_on_startup: true display_app_bar: true remove_title_bar: true remove_task_bar: true rules: - pattern: ^(File Explorer|Task Manager)$ manage: false - pattern: ^.*- Mozilla Firefox|Mozilla Firefox$ has_custom_titlebar: true workspace: 2 firefox: true - pattern: ^.*- Discord|Discord$ has_custom_titlebar: true - pattern: ^Spotify Premium$ has_custom_titlebar: true - pattern: ^.*- Google Chrome$ has_custom_titlebar: true workspace: 2 chromium: true - pattern: ^.*- Visual Studio Code$ has_custom_titlebar: true keybindings: - type: Launch key: Alt+Enter cmd: wt.exe - type: Launch key: Alt+B cmd: C:\\Program Files\\Mozilla Firefox\\firefox.exe - type: CloseTile key: Alt+Q - type: Quit key: Alt+X - type: Focus key: Alt+H direction: Left - type: Focus key: Alt+J direction: Down - type: Focus key: Alt+K direction: Up - type: Focus key: Alt+L direction: Right - type: Swap key: Alt+Control+H direction: Left - type: Swap key: Alt+Control+J direction: Down - type: Swap key: Alt+Control+K direction: Up - type: Swap key: Alt+Control+L direction: Right - type: Split key: Alt+Plus direction: Vertical - type: Split key: Alt+Minus direction: Horizontal - type: ToggleFloatingMode key: Alt+Control+F - type: ToggleFullscreen key: Alt+F - type: ToggleWorkMode key: Alt+Control+W - type: MoveToWorkspace key: Alt+Shift+1 id: 1 - type: MoveToWorkspace key: Alt+Shift+2 id: 2 - type: MoveToWorkspace key: Alt+Shift+3 id: 3 - type: MoveToWorkspace key: Alt+Shift+4 id: 4 - type: MoveWorkspaceToMonitor key: Alt+Control+1 monitor: 1 - type: MoveWorkspaceToMonitor key: Alt+Control+2 monitor: 2 - type: ChangeWorkspace key: Alt+1 id: 1 - type: ChangeWorkspace key: Alt+2 id: 2 - type: ChangeWorkspace key: Alt+3 id: 3 - type: ChangeWorkspace key: Alt+4 id: 4 - type: ChangeWorkspace key: Alt+5 id: 5 modes: resize: key: Alt+R keybindings: - type: Resize key: H direction: Left amount: 2 - type: Resize key: Shift+H direction: Left amount: -2 - type: Focus key: A direction: Left - type: Focus key: D direction: Right - type: Focus key: W direction: Up - type: Focus key: S direction: Down ```

ramirezmike commented 4 years ago

My plan right now is to just support a letter (which can be a unicode character if you want a nice icon like eye).

I actually like this idea a lot.

TimUntersberger commented 4 years ago

@ramirezmike have you noticed any problems with the resize feature, else I'll merge this into development today.

ramirezmike commented 4 years ago

I haven't used it extensively, but aside from the tiles work that the other issue was created for, I'm not really seeing any issues and it hasn't paniced on me yet aside from that one time I got

thread 'main' panicked at 'attempt to divide by zero', src/tile_grid.rs:491:30

that I mentioned above, but I still haven't managed to reproduce it.

I think it will definitely be a lot more fun once the modes and config changes are merged too.

keepitsane commented 4 years ago

I saw this branch and was interested in testing it. Are you still planning to merge it with development or should I build it myself?

TimUntersberger commented 4 years ago

I am actually thinking about merging this together with the new config format and modes.

I will be doing this later today.

TimUntersberger commented 4 years ago

resize, modes and rhai are now merged into development. I will be creating a new issue for visual indicator when mode is active and after this is done I will be merging everything into master.