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

New layout: MonadThreeCol #2606

Merged
merged 1 commit into from Feb 7, 2022
Merged

Conversation

mbenford
Copy link
Contributor

@mbenford mbenford commented Jul 5, 2021

This PR introduces a new layout: MonadThreeCol. It's based on XMonad's ThreeColumns layout and it's useful for people using ultra wide displays. It behaves similarly to MonadTall with two key differences: the main window can be placed at the center of the screen and the secondary windows are divided into two columns:

image

Windows are distributed following XMonad's ThreeColumns behavior:

image
image

This is a working in progress and shouldn't be merged yet. It's functional - I've been using it myself - but there are some rough edges that need smoothing out. I wanted to share it as it stands to get some early feedback on both the code (Python isn't my strong suit) and the layout design. I tried to use as much as I could from MonadTall and only rewrote the parts that were too coupled to the way the tall layout works.

To-do list

  • Port XMonad's ThreeCol layout.
  • Port XMonad's ThreeColMid layout.
  • Fix double margins.
  • Fix resize of secondary windows.
  • Write tests.

@m-col
Copy link
Member

m-col commented Jul 5, 2021

Awesome! Looking at the code itself everything looks good. Do you have an example configuration that someone who hasn't used the Monad layouts (me) could use to test out the different functions and features?

@mbenford
Copy link
Contributor Author

mbenford commented Jul 5, 2021

There you go (default config file with custom key bindings for xmonad layout). To be honest, there are no new features besides the layout itself; most configuration options and public methods come from MonadTall.

from typing import List  # noqa: F401

from libqtile import bar, layout, widget
from libqtile.config import Click, Drag, Group, Key, Match, Screen
from libqtile.lazy import lazy
from libqtile.utils import guess_terminal

mod = "mod4"
terminal = guess_terminal()

keys = [
    Key([mod], "h", lazy.layout.left(), desc="Move focus to left"),
    Key([mod], "l", lazy.layout.right(), desc="Move focus to right"),
    Key([mod], "j", lazy.layout.down(), desc="Move focus down"),
    Key([mod], "k", lazy.layout.up(), desc="Move focus up"),
    Key([mod], "space", lazy.layout.next(), desc="Move window focus to other window"),

    Key([mod, "shift"], "h", lazy.layout.shuffle_left(), desc="Move window to the left"),
    Key([mod, "shift"], "l", lazy.layout.shuffle_right(), desc="Move window to the right"),
    Key([mod, "shift"], "j", lazy.layout.shuffle_down(), desc="Move window down"),
    Key([mod, "shift"], "k", lazy.layout.shuffle_up(), desc="Move window up"),

    Key([mod, "control"], "h", lazy.layout.shrink_main(), desc="Grow window to the left"),
    Key([mod, "control"], "l", lazy.layout.grow_main(), desc="Grow window to the right"),
    Key([mod, "control"], "j", lazy.layout.grow(), desc="Grow window down"),
    Key([mod, "control"], "k", lazy.layout.shrink(), desc="Grow window up"),
    Key([mod], "m", lazy.layout.normalize(), desc="Maximize window"),
    Key([mod], "n", lazy.layout.normalize(), desc="Reset all window sizes"),

    Key([mod], "Return", lazy.spawn(terminal), desc="Launch terminal"),

    Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"),
    Key([mod], "w", lazy.window.kill(), desc="Kill focused window"),

    Key([mod, "control"], "r", lazy.restart(), desc="Restart Qtile"),
    Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"),
    Key([mod], "r", lazy.spawncmd(), desc="Spawn a command using a prompt widget"),
]

groups = [Group(i) for i in "123456789"]

for i in groups:
    keys.extend([
        Key([mod], i.name, lazy.group[i.name].toscreen(), desc="Switch to group {}".format(i.name)),
        Key([mod, "shift"], i.name, lazy.window.togroup(i.name, switch_group=True), 
            desc="Switch to & move focused window to group {}".format(i.name)),
    ])

layouts = [
    layout.MonadThreeCol(main_centered=True),
    layout.MonadThreeCol(main_centered=False),
]

widget_defaults = dict(
    font='sans',
    fontsize=12,
    padding=3,
)
extension_defaults = widget_defaults.copy()

screens = [
    Screen(
        bottom=bar.Bar(
            [
                widget.CurrentLayout(),
                widget.GroupBox(),
                widget.Prompt(),
                widget.WindowName(),
                widget.Chord(
                    chords_colors={
                        'launch': ("#ff0000", "#ffffff"),
                    },
                    name_transform=lambda name: name.upper(),
                ),
                widget.TextBox("default config", name="default"),
                widget.TextBox("Press <M-r> to spawn", foreground="#d75f5f"),
                widget.Systray(),
                widget.Clock(format='%Y-%m-%d %a %I:%M %p'),
                widget.QuickExit(),
            ],
            24,
        ),
    ),
]

mouse = [
    Drag([mod], "Button1", lazy.window.set_position_floating(), start=lazy.window.get_position()),
    Drag([mod], "Button3", lazy.window.set_size_floating(), start=lazy.window.get_size()),
    Click([mod], "Button2", lazy.window.bring_to_front())
]

dgroups_key_binder = None
dgroups_app_rules = []  # type: List
follow_mouse_focus = True
bring_front_click = False
cursor_warp = False
floating_layout = layout.Floating(float_rules=[
    *layout.Floating.default_float_rules,
    Match(wm_class='confirmreset'),  # gitk
    Match(wm_class='makebranch'),  # gitk
    Match(wm_class='maketag'),  # gitk
    Match(wm_class='ssh-askpass'),  # ssh-askpass
    Match(title='branchdialog'),  # gitk
    Match(title='pinentry'),  # GPG key password entry
])
auto_fullscreen = True
focus_on_window_activation = "smart"
reconfigure_screens = True
auto_minimize = True
wmname = "LG3D"

@mbenford mbenford marked this pull request as draft July 5, 2021 17:41
@mbenford mbenford changed the title WIP: New layout: MonadThreeCol New layout: MonadThreeCol Jul 5, 2021
@mbenford
Copy link
Contributor Author

I updated the PR and fixed both double margins and resize of secondary windows. I thought I'd share how I did it because my approaches were different than the ones in MonadTall.

Double margins

MonadTall deals with double margins by adjusting both the y position and the height of all secondary clients other than the first one. Since this new layout can have two columns I tried to fix the problem in a more general way: rightmost and bottommost clients will have all four margins set while other clients will have only north and west margins. This prevents margins of adjacent clients from adding up and all distances among clients will honor the margin option. Clients are considered rightmost and/or bottommost when they touch the screen_rect edges (at first I thought this wouldn't work due the position of bars, but qtile takes care of that by providing a corrected screen_rect).

Resize of secondary windows

I couldn't use MonadTalls resize implementation because it (reasonably) assumes a single column for secondary windows, and I would have to re-implement several methods in MonadThreeCol. So I created a single method that handles all resizing cases (grow and shrink) by iterating over all secondary clients in the same column and change their heights accordingly. A single pass should be enough for most cases, and even on edge cases two or three passes will eventually resize everything.

If anyone sees any problems with these approaches, please let me know.

@github-actions
Copy link

This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 30 days.

@mbenford
Copy link
Contributor Author

mbenford commented Nov 2, 2021

I have started working on the tests and I hope I can get them done soon.

@github-actions github-actions bot closed this Dec 2, 2021
@jeffzi
Copy link

jeffzi commented Dec 28, 2021

Hi @mbenford, thanks for this layout 🎉 . I've been using it for a couple of months without issues. It's now my default layout on my ultrawide 38"!

I'm not familiar with qtile development but can help with testing if needed.

@m-col m-col reopened this Dec 28, 2021
@jwijenbergh jwijenbergh mentioned this pull request Dec 30, 2021
5 tasks
@m-col
Copy link
Member

m-col commented Jan 16, 2022

Is this PR finished? Just asking because I see you've added a test for it, but the PR is still marked as a draft.

@mbenford
Copy link
Contributor Author

@m-col I've added a single test so far that ensures windows are correctly placed on the screen. I'd like to write a few more to cover other behaviors as well. But I guess the draft status can be changed at this point since the new layout is 100% done.

@jeffzi I'm glad it's been useful to you. :)

@mbenford mbenford marked this pull request as ready for review January 16, 2022 22:35
@m-col
Copy link
Member

m-col commented Jan 16, 2022

OK, no problem. It looks like you'll need to rebase as there is a conflict. Let me know if you'd prefer to merge and add more tests in a future PR, or to hold on merging until then.

Please could you add an entry to the changelog too? Then others can appreciate your work!

libqtile/layout/xmonad.py Outdated Show resolved Hide resolved
libqtile/layout/xmonad.py Outdated Show resolved Hide resolved
libqtile/layout/xmonad.py Outdated Show resolved Hide resolved
@mbenford mbenford force-pushed the xmonad-three-columns branch 4 times, most recently from f67bc47 to 7e3eb69 Compare January 18, 2022 02:24
@mbenford
Copy link
Contributor Author

OK, no problem. It looks like you'll need to rebase as there is a conflict. Let me know if you'd prefer to merge and add more tests in a future PR, or to hold on merging until then.

@m-col I'll add a few more tests later this week so we can merge this PR more confidently.

@keslerm
Copy link

keslerm commented Jan 24, 2022

Just some noise but I am actively looking forward to this PR!

@mbenford mbenford force-pushed the xmonad-three-columns branch 3 times, most recently from b2cd597 to ee72a0f Compare January 28, 2022 02:38
@mbenford
Copy link
Contributor Author

@m-col I've added a few more tests and I think this PR is good to be merged now. There are still some areas that I want to cover but I can do it later, if that's ok with you.

Also, I'm not sure why the Python 3.10 action failed. Let me know if I need to fix anything on my end.

@elParaguayo
Copy link
Member

The tests failed the formatting check. You need to run blackon your modified files to fix this.

@mbenford
Copy link
Contributor Author

@elParaguayo done!

@mbenford
Copy link
Contributor Author

mbenford commented Feb 6, 2022

@m-col Do you want me to rebase my branch so there's no merge commit from master?

@m-col
Copy link
Member

m-col commented Feb 6, 2022

I was just trying to rebase it through github but oddly it says I can't. Not sure why. But yes, that would be great, thanks!

Introduce a new layout: MonadThreeCol. It's based on XMonad's
ThreeColumns layout and it's useful for people using ultra wide
displays. It behaves similarly to MonadTall with two key differences:
the main window can be placed at the center of the screen and the
secondary windows are divided into two columns.
@m-col
Copy link
Member

m-col commented Feb 7, 2022

Amazing, thank you @mbenford!

@m-col m-col merged commit 26bc987 into qtile:master Feb 7, 2022
@davidbudzynski
Copy link

Not sure if this is the place to post this, but I think we're missing an icon for this layout in the CurrentLayoutIcon widget. I'm on a qtile-git version on Arch Linux and it currently looks like this.

@m-col
Copy link
Member

m-col commented Mar 12, 2022

Good catch. Would one of you like to put one together @mbenford, or @elParaguayo as you made one recently for Spiral?

@elParaguayo
Copy link
Member

Yeah. I can do it.

@elParaguayo
Copy link
Member

#3422

@mbenford mbenford deleted the xmonad-three-columns branch March 12, 2022 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants