scroll is a Wayland compositor forked from sway. It creates a window layout similar to PaperWM.
Consult the README for more details beyond this quick tutorial.
This tutorial uses the default key bindings you can find in
/etc/scroll/config or in this repo in
config.in.
scroll supports multiple workspaces per monitor. Each workspace is a row: a scrollable set of columns, where each column may contain one or more windows.
Your workspace is not limited by the size of the monitor; windows will have a standard size and will scroll in and out of the view as they gain or lose focus. This is an important difference with respect to other tiling window managers, you always control the size of your windows, and if they are too big and not in focus, they will just scroll out of view. There are ways to view all windows at the same time, through overview mode, but more on that later.
There are two working modes that can be changed at any time:
- horizontal: it is the default. For each new window you open, it creates a new column containing only that window.
- vertical: a new window will be placed in the current column, right below the active window.
bindsym $mod+bracketleft set_mode h
bindsym $mod+bracketright set_mode v
If your monitor is in landscape mode (the usual one), you will probably work mostly in horizontal mode. If you are using a monitor in portrait mode, scroll will adapt and instead of having a row with columns of windows, you will have a column with rows of windows. You can configure each monitor independently through available options.
If you have an ultra-wide display, you can also show two workspaces at the
same time using workspace split. It will split the current workspace in two,
and both will be shown at the same time.
rows-columns.mp4
There are options to define the default width and height of windows. These
sizes are usually a fraction of the available monitor space so it is easier to
fit an integer number of windows fully on screen at a time. If you use a regular
monitor, you may use fractions like 0.5 or 0.333333 to fit 2 or 3
windows. If you have an ultra-wide monitor, you may decide to use smaller
fractions to fit more windows in the viewport at a time.
It is convenient to define complementary fractions like 0.6666667, 0.75 etc.,
so for example you can fit a 0.333333 and a 0.666667 window for the full
size of the monitor. Depending on the size and resolution of your monitor you
can decide which fractions are best suited for you, and configure them
through options.
You can toggle different window widths and heights in real-time using
cycle_size. It will go through your list of selected fractions defined in the
configuration, and resize the active window accordingly.
bindsym $mod+minus cycle_size h prev
bindsym $mod+equal cycle_size h next
bindsym $mod+Shift+minus cycle_size v prev
bindsym $mod+Shift+equal cycle_size v next
Of course you can also manually define exactly the size of a window with
resize or use set_size to directly choose a fraction without having to
cycle through them.
mode "setsizeh" {
bindsym 1 set_size h 0.125; mode default
bindsym 2 set_size h 0.1666666667; mode default
bindsym 3 set_size h 0.25; mode default
bindsym 4 set_size h 0.333333333; mode default
bindsym 5 set_size h 0.375; mode default
bindsym 6 set_size h 0.5; mode default
bindsym 7 set_size h 0.625; mode default
bindsym 8 set_size h 0.6666666667; mode default
bindsym 9 set_size h 0.75; mode default
bindsym 0 set_size h 0.833333333; mode default
bindsym minus set_size h 0.875; mode default
bindsym equal set_size h 1.0; mode default
# Return to default mode
#bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+b mode "setsizeh"
mode "setsizev" {
bindsym 1 set_size v 0.125; mode default
bindsym 2 set_size v 0.1666666667; mode default
bindsym 3 set_size v 0.25; mode default
bindsym 4 set_size v 0.333333333; mode default
bindsym 5 set_size v 0.375; mode default
bindsym 6 set_size v 0.5; mode default
bindsym 7 set_size v 0.625; mode default
bindsym 8 set_size v 0.6666666667; mode default
bindsym 9 set_size v 0.75; mode default
bindsym 0 set_size v 0.833333333; mode default
bindsym minus set_size v 0.875; mode default
bindsym equal set_size v 1.0; mode default
# Return to default mode
#bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+Shift+b mode "setsizev"
mode "resize" {
# left will shrink the containers width
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
bindsym $left resize shrink width 100px
bindsym $down resize grow height 100px
bindsym $up resize shrink height 100px
bindsym $right resize grow width 100px
# Return to default mode
#bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+Shift+r mode "resize"
If you want to quickly fit a series of windows in a column or columns in a
row, you can use fit_size. It will ignore fractions, and re-scale all the
affected windows to fit in the screen.
cyclesize-fitview.mp4
mode "fit_size" {
bindsym w fit_size h visible proportional; mode default
bindsym Shift+w fit_size v visible proportional; mode default
bindsym Ctrl+w fit_size h visible equal; mode default
bindsym Ctrl+Shift+w fit_size v visible equal; mode default
bindsym $right fit_size h toend proportional; mode default
bindsym Shift+$right fit_size v toend proportional; mode default
bindsym Ctrl+$right fit_size h toend equal; mode default
bindsym Ctrl+Shift+$right fit_size v toend equal; mode default
bindsym $left fit_size h tobeg proportional; mode default
bindsym Shift+$left fit_size v tobeg proportional; mode default
bindsym Ctrl+$left fit_size h tobeg equal; mode default
bindsym Ctrl+Shift+$left fit_size v tobeg equal; mode default
bindsym $up fit_size h active proportional; mode default
bindsym Shift+$up fit_size v active proportional; mode default
#bindsym Ctrl+$up fit_size h active equal; mode default
#bindsym Ctrl+Shift+$up fit_size v active equal; mode default
bindsym $down fit_size h all proportional; mode default
bindsym Shift+$down fit_size v all proportional; mode default
bindsym Ctrl+$down fit_size h all equal; mode default
bindsym Ctrl+Shift+$down fit_size v all equal; mode default
}
bindsym $mod+w mode "fit_size"
When you change window focus, scroll will always show the active
(focused) window on screen, and intelligently try to fit another adjacent
window if it can. However, in some cases you may want to decide to align a
window manually; align does exactly that.
alignwindow.mp4
mode "align" {
bindsym c align center; mode default
bindsym m align middle; mode default
bindsym r align reset; mode default
bindsym $left align left; mode default
bindsym $right align right; mode default
bindsym $up align up; mode default
bindsym $down align down; mode default
bindsym Escape mode "default"
}
bindsym $mod+c mode "align"
There are several ways to move windows and columns:
bindsym $mod+Ctrl+$left move left
bindsym $mod+Ctrl+$down move down
bindsym $mod+Ctrl+$up move up
bindsym $mod+Ctrl+$right move right
bindsym $mod+Ctrl+home move beginning
bindsym $mod+Ctrl+end move end
# nomode
bindsym $mod+Alt+$left move left nomode
bindsym $mod+Alt+$down move down nomode
bindsym $mod+Alt+$up move up nomode
bindsym $mod+Alt+$right move right nomode
bindsym $mod+Alt+home move beginning nomode
bindsym $mod+Alt+end move end nomode
When using mod+Ctrl+cursor_keys you move a window, a row or a column
depending on which mode you are on. Instead, mod+Alt+cursor_keys uses
nomode, which bypasses the mode, and moves individual windows, extracting
them from the row/column or inserting them when needed.
movement-1280.mp4
To be able to re-organize windows and columns more easily, you can use
selection toggle to select and deselect windows. Those windows can be in
any workspace, and can also be selected from overview mode. After you are
done with your selection, go to the place where you want to move them (same
or different workspace), and call selection move. All the selected
windows/containers will move to your current location. If you want to select
a full workspace, use selection workspace, or selection reset to undo a
multiple selection. You can control more precisely where the selection will
end up by changing mode modifiers (after, before, end,...)
# Selection
bindsym --no-repeat $mod+Insert selection toggle
bindsym --no-repeat $mod+Ctrl+Insert selection reset
bindsym --no-repeat $mod+Shift+Insert selection move
bindsym --no-repeat $mod+Ctrl+Shift+Insert selection workspace
bindsym --no-repeat $mod+Alt+Insert selection to_trail
When you have too many windows in a workspace, it can be hard to know where
things are. scale_workspace overview helps with that by creating a bird's eye view
of the whole workspace.
scale_workspaces toggle creates an overview mode where scroll renders
all the workspaces for each monitor.
You can work normally when in either overview mode, and drag windows between workspaces too.
bindsym --no-repeat $mod+tab scale_workspace overview
bindsym --no-repeat $mod+Shift+tab scale_workspaces toggle
overview-mode.mp4
Jump mode takes advantage of overview mode to provide a very quick way to focus on
any window or workspace on your monitors. Similar to vim-easymotion,
it overlays a label on each window (or workspace if you use jump workspaces.
Pressing all the numbers of a label, changes focus to the selected window or
workspace.
- Assign key bindings to
jump, for this tutorial:
mode "jump" {
bindsym slash jump; mode default
bindsym c jump container; mode default
bindsym w jump workspaces; mode default
bindsym f jump floating; mode default
bindsym a jump all; mode default
bindsym s scratchpad jump; mode default
bindsym t trailmark jump; mode default
# Return to default mode
bindsym Escape mode "default"
}
bindsym $mod+slash mode "jump"
- Pressing your
modkey and/followed by/will show an overview of your windows on each monitor. - Now press the numbers shown on the overlay for the window you want to change focus to, or click on it.
jumpwill exit, and the focus will be on the window you selected.
If instead you press mod, / and w, you will see a bird's eye view of
all your workspaces. Pressing a combination of keys, like in the example
above, will take you to the chosen workspace.
If your focus is on a column with more than one window, you can press mod,
/ and c, and you will get a jump overview of only all the windows in that
column instead.
If you use floating windows, mod+/ followed by f will show you an overview of
all your floating windows without overlaps, so you can select one even if it
was hidden behind.
jump.mp4
A space is a configuration of existing windows. You can set your workspace and save a named "space" with that configuration. You can later on recall that configuration on the same or any other workspace. scroll will gather the windows from their location and set them up as they were when you saved the space.
mode "spaces" {
bindsym 1 space load 1; mode default
bindsym 2 space load 2; mode default
bindsym 3 space load 3; mode default
bindsym 4 space load 4; mode default
bindsym 5 space load 5; mode default
bindsym 6 space load 6; mode default
bindsym 7 space load 7; mode default
bindsym 8 space load 8; mode default
bindsym 9 space load 9; mode default
bindsym 0 space load 0; mode default
bindsym Shift+1 space save 1; mode default
bindsym Shift+2 space save 2; mode default
bindsym Shift+3 space save 3; mode default
bindsym Shift+4 space save 4; mode default
bindsym Shift+5 space save 5; mode default
bindsym Shift+6 space save 6; mode default
bindsym Shift+7 space save 7; mode default
bindsym Shift+8 space save 8; mode default
bindsym Shift+9 space save 9; mode default
bindsym Shift+0 space save 0; mode default
bindsym Ctrl+1 space restore 1; mode default
bindsym Ctrl+2 space restore 2; mode default
bindsym Ctrl+3 space restore 3; mode default
bindsym Ctrl+4 space restore 4; mode default
bindsym Ctrl+5 space restore 5; mode default
bindsym Ctrl+6 space restore 6; mode default
bindsym Ctrl+7 space restore 7; mode default
bindsym Ctrl+8 space restore 8; mode default
bindsym Ctrl+9 space restore 9; mode default
bindsym Ctrl+0 space restore 0; mode default
bindsym Escape mode "default"
}
bindsym $mod+g mode "spaces"
space-1280.mp4
scroll adds some functionality to sway's scratchpad. By using scratchpad jump
you will see an overview similar to jump floating for your scratchpad windows.
You can use this to quickly select one of them instead of having to cycle.
# Move the currently focused window to the scratchpad
bindsym $mod+Shift+z move scratchpad
# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+z scratchpad show
# Show all the scratchpad windows to quickly change focus to one of them
bindsym --no-repeat $mod+Alt+z scratchpad jump
You can set the scale of the content of any window independently. Add these bindings and pressing Mod and moving the scroll wheel of you mouse will scale the content of the active window.
bindsym --whole-window $mod+button4 scale_content incr -0.05
bindsym --whole-window $mod+button5 scale_content incr 0.05
Apart from overview and jump, you can scale your workspace to an arbitrary scale value. Add these bindings to your configuration, and pressing Mod + Shift and moving the scroll wheel of your mouse will scale the workspace.
bindsym --whole-window $mod+Shift+button4 scale_workspace incr -0.05
bindsym --whole-window $mod+Shift+button5 scale_workspace incr 0.05
scale-1280.mp4
Sometimes you want to keep one window static at all times, for example an editor with a file you are working on, while letting other windows scroll in the rest of the available space. These windows may include terminals or documentation browser windows. You can pin a column to the right or left (top or bottom) of the monitor, and it will stay at that location until you call pin again.
# Toggle pin
bindsym --no-repeat $mod+a pin beginning
bindsym --no-repeat $mod+Shift+a pin end
pin.mp4
Aside from sway's marks, scroll supports a special kind of anonymous mark called a trailmark. You can create trails and trailmarks and use them to navigate your favorite windows. See the README and the man page for more details.
mode "trailmark" {
bindsym bracketright trailmark next
bindsym bracketleft trailmark prev
bindsym semicolon trailmark toggle; mode default
bindsym --no-repeat slash trailmark jump; mode default
bindsym Escape mode "default"
}
bindsym $mod+semicolon mode "trailmark"
mode "trail" {
bindsym bracketright trail next
bindsym bracketleft trail prev
bindsym semicolon trail new; mode default
bindsym d trail delete; mode default
bindsym c trail clear; mode default
bindsym insert trail to_selection; mode default
bindsym Escape mode "default"
}
bindsym $mod+Shift+semicolon mode "trail"
You can create selections from trails, and a new trail for the current
selection. This also provides memory for selections, and a way to quickly
navigate favorite windows by using trailmark jump.
trailmarks.mp4
Overview and jump can be very helpful when you work in fullscreen mode. You can keep all your windows maximized or in full screen mode, and toggle overview on/off to see your full desktop, and quickly focus or change the position to a different application.
fullscreen-1280.mp4
You can also use fullscreen application to toggle a full screen UI for any
application, while still having its content fit in the assigned container.
With different combinations of fullscreen and fullscreen application you
can have several "fake" full screen modes, like full screen YouTube videos
within a container, full screen UI within a container, or a regular UI in a
full screen container.
fullscreen layout applies a special full screen mode to the active tiled
window. The window becomes full screen but it is still part of the tiling
layout, so you can scroll it like the rest. You can have as many of these
full screen windows as you want at the same time.
scroll also supports a maximize mode, through the toggle_size command.
This command lets you toggle back and forth any size for the active window in
the current workspace, or all of them. See the manual for details.
bindsym $mod+f fullscreen
bindsym $mod+Ctrl+f fullscreen layout
bindsym $mod+Alt+f fullscreen application
bindsym $mod+Ctrl+Alt+f fullscreen global
# Toggle Size (and maximize)
bindsym $mod+t toggle_size this 1.0 1.0
bindsym $mod+Shift+t toggle_size active 1.0 1.0
mode "togglesizeh" {
bindsym 1 toggle_size all 0.125 1.0; mode default
bindsym 2 toggle_size all 0.1666666667 1.0; mode default
bindsym 3 toggle_size all 0.25 1.0; mode default
bindsym 4 toggle_size all 0.333333333 1.0; mode default
bindsym 5 toggle_size all 0.375 1.0; mode default
bindsym 6 toggle_size all 0.5 1.0; mode default
bindsym 7 toggle_size all 0.625 1.0; mode default
bindsym 8 toggle_size all 0.6666666667 1.0; mode default
bindsym 9 toggle_size all 0.75 1.0; mode default
bindsym 0 toggle_size all 0.833333333 1.0; mode default
bindsym minus toggle_size all 0.875 1.0; mode default
bindsym equal toggle_size all 1.0 1.0; mode default
bindsym r toggle_size reset; mode default
# Return to default mode
bindsym Escape mode "default"
}
bindsym $mod+Ctrl+t mode "togglesizeh"
mode "togglesizev" {
bindsym 1 toggle_size all 1.0 0.125; mode default
bindsym 2 toggle_size all 1.0 0.1666666667; mode default
bindsym 3 toggle_size all 1.0 0.25; mode default
bindsym 4 toggle_size all 1.0 0.333333333; mode default
bindsym 5 toggle_size all 1.0 0.375; mode default
bindsym 6 toggle_size all 1.0 0.5; mode default
bindsym 7 toggle_size all 1.0 0.625; mode default
bindsym 8 toggle_size all 1.0 0.6666666667; mode default
bindsym 9 toggle_size all 1.0 0.75; mode default
bindsym 0 toggle_size all 1.0 0.833333333; mode default
bindsym minus toggle_size all 1.0 0.875; mode default
bindsym equal toggle_size all 1.0 1.0; mode default
bindsym r toggle_size reset; mode default
# Return to default mode
bindsym Escape mode "default"
}
bindsym $mod+Ctrl+Shift+t mode "togglesizev"
By default, scroll supports three and four finger touchpad swipe gestures to scroll windows, call overview and switch workspaces.
You can also scroll windows with the mouse. Press mod and the middle mouse
button, and you can drag/scroll columns and windows.
scroll is programmable through an exposed Lua API. You can write scripts that access the internals of the window manager, listen to events and execute commands. Follow this link for examples and requests.
local function candidate(view)
local app_id = scroll.view_get_app_id(view)
if app_id == "mpv" then
local pview = scroll.view_get_parent_view(view)
if pview ~= nil and pview ~= view then
local papp_id = scroll.view_get_app_id(pview)
if papp_id == "kitty" then
return scroll.view_get_container(pview)
end
end
end
return nil
end
local function on_create(view, _)
local parent = candidate(view)
if parent ~= nil then
scroll.command(parent, "move scratchpad")
end
end
local function on_destroy(view, _)
local parent = candidate(view)
if parent ~= nil then
scroll.command(nil, "scratchpad show; floating toggle")
end
end
scroll.add_callback("view_map", on_create, nil)
scroll.add_callback("view_unmap", on_destroy, nil)scroll includes an example configuration with most of the key bindings recommended for a standard setup.