-
-
Notifications
You must be signed in to change notification settings - Fork 698
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
Add ScreenSplit layout #3793
Add ScreenSplit layout #3793
Conversation
c167204
to
4c0afab
Compare
@nazar-pc - copying your question from the discussion here:
At the moment, each split takes a single layout object. It should be possible to allow a list of layouts if that's useful (but I'd need to block nested |
Another thing that could be useful is to be able to resize after instantiation like in Column and other layouts. But even without those changes should be useful and usable, I'll try to test it over the weekend. |
Unlikely to happen. The logic would get pretty complicated if you had more than 2 splits. The idea is really to break the screen down into smaller, fixed-size screen areas. |
Another difference this has compared to re fullscreening, we could add a command to fullscreen a window across the entire output layout rather than a single screen (could also useful even when using multiple physical outputs). And for bars, it appears you can give bars a large negative margin in one direction and they will extend beyond the screen it 'belongs' to. E.g. if you wanted to vertically split a 3840 pixel wide window into two 1920 wide virtual screens, giving the left 'screen' a bar with margin |
I don't think lack of groups is an issue for me personally, the way it is done with static config for one group is perfectly fine for what I have in mind, but moving windows across nested layouts is generally desirable (though may be non-critical for the very initial implementation. |
I had assumed "no" to this question as, otherwise, people should use
A combination of |
I haven't implemented moving windows between nested layouts yet. |
318ba9b
to
64307e4
Compare
@nazar-pc I think this is in fairly good shape now. Would be great to get some feedback. |
Will do once I am a bit less busy, thank you! |
Initial feedback:
I see why resizing is extremely challenging to implement. Maybe one day we'll just have ability to nest any layout in any layout and this will be solved 🙄 |
Pretty hard to do. That's why I added the
Interesting. Let me check this. EDIT: Found the bug. Fixed.
Are you saying you'd like a match rule for each split to put windows in specific splits straightaway? I can look at that.
It's good to have dreams 😉 |
f0ee66f
to
99f559f
Compare
I'm not using any widgets though, I just have tint2 that is hidden 95.5% of the time and no other panels anywhere.
Exactly. Or else it takes quite a bit of effort to move things around manually every time. |
Another idea would be to write a function that's hooked to
Ok. Can add this. |
Added matches - see the docs for how to use it (basically just add |
5aad2f3
to
d8cfafc
Compare
Tested latest version, no issues with moving windows around splits and I think borders and having split where mouse is "active" (even if there is no window there, at least for indicating where to spawn new windows) are the two things I have on my mind right now. The "active" part will be less critical if borders are added. |
One slightly annoying thing: I'm going to use this layout with Plasm inside of splits (numirias/qtile-plasma#25 is necessary if you're planning to do the same) as the main setup going forward. |
Sorry - that was a silly mistake by me. Yes, we can fix it so matches are only applied when windows are opened. Not when we're moving them. |
Hm, last commit doesn't seem to match windows anymore |
And docs have failed... I must have mucked up the commit! |
753573f
to
57fb798
Compare
Please DM me with USDC wallet address, I'd like to send you a few bucks as a thank you 🙂 |
Thanks for the offer but really not needed. I do this for the fun of it, learning new stuff and generally trying to make things better. |
Unless I'm doing something wrong I don't think prev/next_split methods actually work. Moving does work, just switching doesn't seem to. I have |
Hmm. I suspect |
We've got a big PR to merge first and then we'll look at getting others merged. I'm also dealing with an issue with our test suite at the moment too. |
I found a bug that I think might be related to this PR or to the Plasma layout, not sure yet. Here is my config: from libqtile.command import lazy
from libqtile.config import EzDrag, EzKey, EzClick, Screen, Group, Match
from libqtile.layout import Columns, Floating, Matrix, Max, ScreenSplit, Tile
from libqtile import hook
from plasma import Plasma
from xcffib.xproto import StackMode
import subprocess
import os
@hook.subscribe.startup
def dbus_register():
id = os.environ.get('DESKTOP_AUTOSTART_ID')
if not id:
return
subprocess.Popen([
'dbus-send',
'--session',
'--print-reply',
'--dest=org.gnome.SessionManager',
'/org/gnome/SessionManager',
'org.gnome.SessionManager.RegisterClient',
'string:qtile',
'string:' id
])
tint2_instance = None
@hook.subscribe.client_managed
def register_and_bring_to_front_tint2_instance(window):
global tint2_instance
if window.name == 'tint2':
tint2_instance = window
elif tint2_instance is not None:
tint2_instance.window.configure(stackmode=StackMode.Above)
@hook.subscribe.client_killed
def unregister_tint2_instance(window):
global tint2_instance
if window.name == 'tint2':
tint2_instance = None
mod = 'mod4'
keymap = {
'M-<Left>': lazy.layout.left(),
'M-<Down>': lazy.layout.down(),
'M-<Up>': lazy.layout.up(),
'M-<Right>': lazy.layout.right(),
'M-S-<Left>': [lazy.layout.integrate_left(), lazy.layout.shuffle_left()],
'M-S-<Down>': [lazy.layout.integrate_down(), lazy.layout.shuffle_down()],
'M-S-<Up>': [lazy.layout.integrate_up(), lazy.layout.shuffle_up()],
'M-S-<Right>': [lazy.layout.integrate_right(), lazy.layout.shuffle_right()],
'M-C-<Left>': [lazy.layout.move_left(), lazy.layout.swap_column_left()],
'M-C-<Down>': lazy.layout.move_down(),
'M-C-<Up>': lazy.layout.move_up(),
'M-C-<Right>': [lazy.layout.move_right(), lazy.layout.swap_column_right()],
'M-A-<Left>': [lazy.layout.previous_split()],
'M-A-<Down>': [lazy.layout.next_split()],
'M-A-<Up>': [lazy.layout.previous_split()],
'M-A-<Right>': [lazy.layout.next_split()],
'M-A-S-<Left>': [lazy.layout.move_window_to_previous_split()],
'M-A-S-<Down>': [lazy.layout.move_window_to_next_split()],
'M-A-S-<Up>': [lazy.layout.move_window_to_previous_split()],
'M-A-S-<Right>': [lazy.layout.move_window_to_next_split()],
'A-S-<Tab>': lazy.layout.previous(),
'A-<Tab>': lazy.layout.next(),
'M-h': lazy.layout.mode_horizontal(),
'M-v': lazy.layout.mode_vertical(),
'M-S-h': lazy.layout.mode_horizontal_split(),
'M-S-v': lazy.layout.mode_vertical_split(),
'M-<End>': [lazy.layout.increase_ratio(), lazy.layout.grow_width(100), lazy.layout.grow_right()],
'M-<Home>': [lazy.layout.decrease_ratio(), lazy.layout.grow_width(-100), lazy.layout.grow_left()],
'M-<equal>': lazy.layout.increase_nmaster(),
'M-<minus>': lazy.layout.decrease_nmaster(),
'M-<KP_Add>': lazy.layout.increase_nmaster(),
'M-<KP_Subtract>': lazy.layout.decrease_nmaster(),
'M-<Page_Up>': [lazy.layout.grow_height(100), lazy.layout.grow_up()],
'M-<Page_Down>': [lazy.layout.grow_height(-100), lazy.layout.grow_down()],
'M-<Tab>': lazy.next_layout(),
'C-A-<Up>': lazy.screen.prev_group(),
'C-A-<Down>': lazy.screen.next_group(),
'M-r': lazy.layout.reset_size(),
'M-w': lazy.window.kill(),
'C-A-t': lazy.spawn('terminator'),
'C-A-c': lazy.spawn('gnome-calculator'),
'C-A-s': lazy.spawn('env XDG_CURRENT_DESKTOP=GNOME gnome-system-monitor'),
'M-f': lazy.spawn('spacefm'),
'M-s': lazy.spawn('synapse'),
'<XF86Tools>': lazy.spawn('clementine'),
'<Print>': lazy.spawn('gnome-screenshot'),
'A-<Print>': lazy.spawn('gnome-screenshot --window'),
'S-<Print>': lazy.spawn('gnome-screenshot --area'),
'M-l': [lazy.group['0'].toscreen(), lazy.spawn('i3lock -c 000000')],
'M-S-l': [lazy.group['0'].toscreen(), lazy.spawn('sh -c "i3lock -c 000000; systemctl suspend"')],
'M-C-r': lazy.restart(),
'M-a': lazy.spawn('xrandr --auto'),
'M-c': lazy.spawn('autorandr --load 8k@30'),
'M-S-c': lazy.spawn('autorandr --load off'),
'M-<space>': lazy.window.toggle_floating(),
'M-S-<space>': lazy.window.toggle_fullscreen(),
}
mouse = [
EzDrag('M-1', lazy.window.set_position_floating(), start=lazy.window.get_position()),
EzDrag('M-3', lazy.window.set_size_floating(), start=lazy.window.get_size()),
EzClick('M-2', lazy.window.bring_to_front()),
EzClick('9', lazy.screen.prev_group()),
EzClick('8', lazy.screen.next_group()),
]
borders = {
'border_width': 1,
'border_width_single': 0,
'border_normal': '#000000',
'border_focus': '#318d00',
# For Plasm layout
'border_normal_fixed': '#000000',
'border_focus_fixed': '#318d00',
}
primary_match = [
Match(wm_class='thunderbird-beta'),
Match(wm_class='firefox-nightly'),
Match(wm_class='jetbrains-idea'),
Match(wm_class='jetbrains-clion'),
Match(wm_class='clementine'),
Match(wm_class='smplayer'),
]
email_layout = ScreenSplit(
name="Email",
splits=[
{
"name": "top",
"rect": (0, 0, 0.7, 0.4),
"layout": Plasma(**borders),
},
{
"name": "bottom",
"rect": (0, 0.4, 0.7, 0.6),
"layout": Plasma(**borders),
"matches": primary_match,
},
{
"name": "right",
"rect": (0.7, 0, 0.3, 1),
"layout": Plasma(**borders),
"matches": [Match(wm_class='xpad')],
},
],
**borders
)
plasma_layout = Plasma(name='Plasma', **borders)
main_layout = ScreenSplit(
name="Main",
splits=[
{
"name": "left",
"rect": (0, 0, 0.15, 1),
"layout": Plasma(
insert_position=1,
**borders
),
"matches": [
Match(wm_class='pavucontrol'),
],
},
{
"name": "top",
"rect": (0.15, 0, 0.6, 0.4),
"layout": Plasma(
insert_position=1,
**borders
),
},
{
"name": "bottom",
"rect": (0.15, 0.4, 0.6, 0.6),
"layout": Plasma(
insert_position=1,
**borders
),
"matches": primary_match,
},
{
"name": "right",
"rect": (0.75, 0, 0.25, 1),
"layout": Plasma(
insert_position=1,
**borders
),
"matches": [
Match(wm_class='qbittorrent'),
Match(wm_class='keepassxc'),
Match(wm_class='synaptic'),
],
},
],
**borders
)
layouts = [
main_layout,
plasma_layout,
# Tile(
# name='Tile',
# expand=False,
# add_after_last=True,
# shift_windows=True,
# ratio=0.5,
# master_match=primary_match,
# **borders
# ),
# Columns(
# name='Columns',
# insert_position=1,
# **borders
# ),
]
floating_layout = Floating(
# no_reposition_match = Match(wm_class = 'Synapse'),
**borders
)
groups = [
Group(
'1',
layout='Email',
layouts=[email_layout, main_layout, plasma_layout],
matches=[
Match(wm_class='thunderbird-beta'),
Match(wm_class='xpad'),
],
),
Group(
'2',
layout='Main',
matches=[Match(wm_class='firefox-nightly'), Match(wm_class='qbittorrent'), Match(wm_class='keepassxc')],
),
Group(
'3',
layout='Main',
matches=[Match(wm_class='jetbrains-idea'), Match(wm_class='jetbrains-clion')],
),
Group(
'4',
layout='Main',
matches=[Match(wm_class='clementine'), Match(wm_class='pavucontrol'), Match(wm_class='synaptic')],
),
Group(
'5',
layout='Main',
),
Group(
'6',
layout='Plasma',
),
Group(
'7',
layout='Plasma',
),
Group(
'8',
layout='Plasma',
),
Group(
'9',
layout='Plasma',
),
Group(
'0',
layout='Plasma',
),
]
for i in groups:
keymap['M-' i.name] = [
lazy.group[i.name].toscreen()
]
keymap['M-S-' i.name] = [
lazy.window.togroup(i.name),
lazy.group[i.name].toscreen()
]
keys = []
for k, v in keymap.items():
if type(v) is list:
keys.append(EzKey(k, *v))
else:
keys.append(EzKey(k, v))
screens = [Screen()]
follow_mouse_focus = True
bring_front_click = False
cursor_warp = False
auto_fullscreen = True
focus_on_window_activation = 'smart'
wmname = 'LG3D' I open Firefox Nightly, it gets opened in the second group, bottom part (the biggest), then I open private window of the same Nightly, move regular window into another split, which makes private window occupy the whole split and close private window. I end up in a situation where:
I hit it a few times before, but only now I figured out how to reproduce it reliably. For Plasma layout to work within ScreenSplit numirias/qtile-plasma#25 is needed. |
Can you recreate this without using the Plasma layout? |
4eda85a
to
48f8266
Compare
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. |
Please don't close, I'm using it and looking forward for it to be merged 🙏 |
Can someone reopen this? I'd hate it to be forgotten, this is an extremely useful layout! |
I wonder if i need to put this in qtile-extras... |
48f8266
to
18ed957
Compare
It sounds quite interesting for large monitors. |
Regardless of where it goes, I just hope it gets merged and maintained. I don't think Qtile will be usable for me on 8k screen without this. |
I think we'd like to include this in the main repo. I'll put this back on my to do list so I can tidy up the code and get the tests passing. |
Yes 1 this sounds like a must have for ultrawide monitor users |
1 |
18ed957
to
5a2a646
Compare
OK. I've rebased but I suspect there'll be some test failures for me to work on ;) |
64665cd
to
3c68ff7
Compare
Everything's passing now so squashed into a single commit. |
3c68ff7
to
4aff29e
Compare
Adds a new layout which allows users to split screen into sub areas and assign a layout to each area, while retaining the ability for fullscreen windows to occupy the whole screen.
4aff29e
to
84ce6e1
Compare
Tests are pretty happy ;) |
Adds a new layout which allows users to split screen into sub areas and assign a layout to each area, while retaining the ability for fullscreen windows to occupy the whole screen.
This is draft for now as I'm interested in people's thoughts.
This could easily go in qtile-extras if it's not wanted here.
Also, I've not looked at tests yet...
Screenshot (
Max
on top,Columns
on bottom):