├── .github
└── ISSUE_TEMPLATE
├── .gitignore
├── .xinitrc
├── LICENSE
├── Makefile
├── README.md
├── _clang-format
├── docs
└── img
│ ├── img1.png
│ ├── img2.png
│ └── img3.png
├── run.sh
├── src
├── config_parser.c
├── config_parser.h
├── helper.h
├── logger.c
├── logger.h
├── queue.c
├── queue.h
├── tree.c
├── tree.h
├── type.h
├── zwm.c
└── zwm.h
├── zwm.1
└── zwm.conf
/.github/ISSUE_TEMPLATE:
--------------------------------------------------------------------------------
1 | ## Issue Type
2 | - [ ] Bug Report
3 | - [ ] Feature Request
4 | - [ ] Enhancement
5 |
6 | ## Description
7 | Provide a brief description of the issue or feature request.
8 |
9 | ## Steps to Reproduce (for Bug Reports)
10 | 1.
11 | 2.
12 | 3.
13 |
14 | ## Expected Behavior
15 | Describe what you expected to happen.
16 |
17 | ## Actual Behavior
18 | Describe what actually happened. Include any error messages or logs.
19 |
20 | ## Configuration
21 | - **WN Version**:
22 | - **Operating System**:
23 | - **Compiler Version**:
24 | - **Configuration File**:
25 |
26 | ## Environment
27 | - **Compositor** (if applicable):
28 | - **Desktop Environment** (if applicable):
29 | - **Other Relevant Software**:
30 |
31 | ## Logs and Screenshots
32 | Attach any relevant logs or screenshots that might help in diagnosing the issue.
33 |
34 | ## Additional Information
35 | Add any other context about the problem here.
36 |
37 | ## Checklist
38 | - [ ] I have searched for duplicate issues to ensure this is not a duplicate.
39 | ---
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 | .idea/*
4 | zwm
5 | # Object files
6 | *.o
7 | *.ko
8 | *.obj
9 | *.elf
10 |
11 | # Linker output
12 | *.ilk
13 | *.map
14 | *.exp
15 |
16 | # Precompiled Headers
17 | *.gch
18 | *.pch
19 |
20 | # Libraries
21 | *.lib
22 | *.a
23 | *.la
24 | *.lo
25 |
26 | # Shared objects (inc. Windows DLLs)
27 | *.dll
28 | *.so
29 | *.so.*
30 | *.dylib
31 |
32 | # Executables
33 | *.exe
34 | *.out
35 | *.app
36 | *.i*86
37 | *.x86_64
38 | *.hex
39 |
40 | # Debug files
41 | *.dSYM/
42 | *.su
43 | *.idb
44 | *.pdb
45 |
46 | # Kernel Module Compile Results
47 | *.mod*
48 | *.cmd
49 | .tmp_versions/
50 | modules.order
51 | Module.symvers
52 | Mkfile.old
53 | dkms.conf
--------------------------------------------------------------------------------
/.xinitrc:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | userresources=$HOME/.Xresources
3 | usermodmap=$HOME/.Xmodmap
4 | sysresources=/etc/X11/xinit/.Xresources
5 | sysmodmap=/etc/X11/xinit/.Xmodmap
6 |
7 | # merge in defaults and keymaps
8 | if [ -f $sysresources ]; then
9 | xrdb -merge $sysresources
10 | fi
11 |
12 | if [ -f $sysmodmap ]; then
13 | xmodmap $sysmodmap
14 | fi
15 |
16 | if [ -f "$userresources" ]; then
17 | xrdb -merge "$userresources"
18 | fi
19 |
20 | if [ -f "$usermodmap" ]; then
21 | xmodmap "$usermodmap"
22 | fi
23 |
24 | # start some nice programs
25 | if [ -d /etc/X11/xinit/xinitrc.d ]; then
26 | for f in /etc/X11/xinit/xinitrc.d/?*.sh; do
27 | [ -x "$f" ] && . "$f"
28 | done
29 | unset f
30 | fi
31 |
32 | setxkbmap us &
33 | nitrogen --restore &
34 | xsetroot -cursor_name left_ptr &
35 |
36 | exec zwm
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 2-Clause License
2 |
3 | Copyright (c) 2024, Yazeed Alharthi
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CC = gcc
2 | CFLAGS = -Wextra -Wshadow -Wunreachable-code -Wcast-align -Wuninitialized -finline-functions -finline-small-functions
3 |
4 | LDFLAGS = -lxcb -lxcb-util -lxcb-keysyms -lxcb-ewmh -lxcb-icccm -lxcb-randr -lxcb-xinerama -lxcb-cursor
5 | SRC_FILES = ./src/zwm.c ./src/logger.c ./src/tree.c ./src/config_parser.c ./src/queue.c
6 | HEADER_FILES = ./src/logger.h ./src/tree.h ./src/type.h ./src/zwm.h ./src/config_parser.h ./src/helper.h ./src/queue.h
7 | OBJ_FILES = $(SRC_FILES:.c=.o)
8 | DEBUG_FLAGS = -g -D_DEBUG__=1
9 | GDB_FLAGS = -ggdb3
10 | LOCAL_TEST = -D__LTEST__=1
11 | TARGET = zwm
12 | PREFIX = /usr
13 | BINDIR = $(PREFIX)/bin
14 | MANDIR = $(PREFIX)/share/man/man1
15 | MANPAGE = zwm.1
16 |
17 | $(TARGET): $(OBJ_FILES)
18 | $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
19 |
20 | %.o: %.c $(HEADER_FILES)
21 | $(CC) $(CFLAGS) -c $< -o $@
22 |
23 | clean:
24 | rm -f $(TARGET) $(OBJ_FILES)
25 |
26 | install: $(TARGET)
27 | mkdir -p "$(DESTDIR)$(BINDIR)"
28 | cp -pf $(TARGET) "$(DESTDIR)$(BINDIR)"
29 | mkdir -p "$(DESTDIR)$(MANDIR)"
30 | cp -pf $(MANPAGE) "$(DESTDIR)$(MANDIR)"
31 |
32 | uninstall:
33 | rm -f "$(DESTDIR)$(BINDIR)/$(TARGET)"
34 | rm -f "$(DESTDIR)$(MANDIR)/$(MANPAGE)"
35 |
36 | debug: CFLAGS += $(DEBUG_FLAGS)
37 | debug: clean $(TARGET)
38 |
39 | for_gdb: CFLAGS += $(GDB_FLAGS)
40 | for_gdb: clean $(TARGET)
41 |
42 | test: CFLAGS += $(LOCAL_TEST)
43 | test: clean $(TARGET)
44 |
45 | all: clean $(TARGET)
46 |
47 | .PHONY: all clean install uninstall debug
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### zwm
2 |
3 | ## Table of Contents
4 |
5 | - [About ZWM](#about-zwm)
6 | - [Motivation](#motivation)
7 | - [Goals](#goals)
8 | - [Features](#features)
9 | - [The underlying data structure](#the-underlying-data-structure)
10 | - [Screenshots](#screenshots)
11 | - [Installation](#installation)
12 | - [Configuration](#configuration)
13 | - [Default Keybindings](#default-keybindings)
14 | - [ewmh specific settings for polyabr](#ewmh-specific-settings-for-polyabr)
15 | - [Contributing](#contributing)
16 |
17 | ## About ZWM
18 |
19 | zwm is a minimalistic and opinionated tiling window manager for X11. It uses XCB instead of Xlib to communicate with the X server. The underlying data structure for managing windows is a customized BSP tree.
20 |
21 | ## Motivation
22 |
23 | The motivation behind zwm stems from a desire to create a window manager that is both lightweight and highly efficient, yet tailored to how I like to work. Sure, there are other great tiling window managers that perform well and offer robust features, but zwm was developed primarily as a learning exercise in creating a window manager from scratch.
24 |
25 | ## Goals
26 |
27 | - Minimalism
28 | - Efficiency
29 | - Performance
30 |
31 | ## Features
32 |
33 | - Compliance with a subset of [ewmh](https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html) and [icccm](https://www.x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html)
34 | - Multiple Layouts (default, master, stack, grid).
35 | - Multiple virtual desktops.
36 | - Multi-monitor support.
37 | - Independent workspaces for each monitor by default.
38 | - Low memory footprint, runs within ~2MB of memory
39 | - Resize, flip, and swap windows or partitions.
40 | - Layouts apply to individual desktops.
41 | - Customizable settings.
42 | - Customizable window rules.
43 | - Keyboard-Driven, fully controlled via keyboard shortcuts.
44 | - Can be integrated with any status bar.
45 | - Config reload on the fly.
46 |
47 | ## The underlying data structure:
48 |
49 | ZWM uses **binary space partitioning tree** ([BSP-tree](https://en.wikipedia.org/wiki/Binary_space_partitioning)) to store and manage windows. This allows for more flexible layouts.
50 |
51 | - Each desktop has its own pointer to a bsp-tree
52 | - The tree is a partition of a monitor's rectangle into smaller rectangular regions.
53 | - Each leaf node holds exactly one window.
54 | - Each node in a bsp-tree either has zero or two children.
55 | - Each internal node is responsible for splitting a rectangle in half.
56 |
57 | #### The following should illustrate how bsp-tree is used to achive window managment:
58 |
59 | ```
60 | Window and Partition Structure in a BSP-tree:
61 |
62 | The layout of windows in BSPWM follows a binary tree structure:
63 |
64 | I ROOT (root is an INTERNAL NODE, unless it is a leaf by definition)
65 | / \
66 | I I INTERNAL NODES (screen sections/partitions)
67 | / \ / \
68 | E E E E EXTERNAL NODES (windows/leaves)
69 |
70 | - Internal Nodes (I) represent screen sections where windows can be displayed.
71 | - External Nodes (E) represent the actual windows within those sections.
72 | - Windows (E nodes) share the width, height, and coordinates (x, y) of their parent sections (I nodes).
73 |
74 | Example Structure:
75 |
76 | I
77 | / \
78 | I I
79 | / \ / \
80 | E E E I
81 | / \
82 | E E
83 |
84 | Partition Behavior:
85 | - Internal nodes (I) can contain other partitions or be contained within other partitions.
86 | - External nodes (E) are the leaves (actual windows).
87 |
88 | Example of tree:
89 | - 1, 2, 3 are leaves/windows (EXTERNAL_NODE).
90 | - a, b are internal nodes (INTERNAL_NODE), or screen sections/partitions.
91 |
92 | 1 a a
93 | / \ / \
94 | ---> 1 2 ---> 1 b
95 | / \
96 | 2 3
97 | Visualization of Screen Layout:
98 |
99 | +-----------------------+ +-----------------------+ +-----------------------+
100 | | | | | | | | |
101 | | | | | | | | 2 |
102 | | | | | | | | |
103 | | 1 | | 1 | 2 | | 1 |-----------|
104 | | | | | | | | |
105 | | | | | | | | 3 |
106 | | | | | | | | |
107 | +-----------------------+ +-----------------------+ +-----------------------+
108 |
109 | Another Example:
110 | - Numbers are the are leaves/windows (EXTERNAL_NODE).
111 | - Letters are internal nodes (INTERNAL_NODE), or screen sections/partitions.
112 |
113 | a a a
114 | / \ / \ / \
115 | 1 b ---> c b ---> c b
116 | / \ / \ / \ / \ / \
117 | 2 3 1 4 2 3 1 d 2 3
118 | / \
119 | 4 5
120 |
121 | +-----------------------+ +-----------------------+ +-----------------------+
122 | | | | | | | | | |
123 | | | 2 | | 1 | 2 | | 1 | 2 |
124 | | | | | | | | | |
125 | | 1 |-----------| |-----------|-----------| |-----------|-----------|
126 | | | | | | | | | | |
127 | | | 3 | | 4 | 3 | | 4 | 5 | 3 |
128 | | | | | | | | | | |
129 | +-----------------------+ +-----------------------+ +-----------------------+
130 |
131 | ```
132 |
133 | ## Screenshots:
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | ## Installation
146 |
147 | #### Arch Linux (AUR)
148 |
149 | ```bash
150 | yay -S zwm
151 | ```
152 |
153 | #### Void Linux (XBPS-SRC)
154 |
155 | Assuming you have [void-packages](https://github.com/void-linux/void-packages)
156 |
157 | ```bash
158 | git clone https://github.com/elbachir-one/void-templates
159 | cp void-templates/zwm/ void-packages/srcpkgs/ # Copying the zwm/ directory that has the template
160 | cd void-packages/
161 | ./xbps-src pkg zwm
162 | sudo xbps-install -R hostdir/binpkgs zwm
163 | ```
164 |
165 | #### Build from source
166 |
167 | ##### Dependencies
168 |
169 | - gcc
170 | - libxcb
171 | - xcb-util
172 | - xcb-util-keysyms
173 | - xcb-util-wm (ewmh,icccm)
174 | - lxcb-randr
175 | - lxcb-xinerama
176 | - lxcb-cursor
177 |
178 | ```bash
179 | git clone https://github.com/Yazeed1s/zwm.git
180 | cd zwm && sudo make install
181 | ```
182 |
183 | ## Configuration
184 |
185 | ##### A config file will be generated when you first start `zwm`. The file can be found in the following location:
186 |
187 | - ~/.config/zwm/zwm.conf
188 |
189 | ###### As of now, the following configs are offered:
190 |
191 | ### 1- Config variables
192 |
193 | ```ini
194 | border_width = 2
195 | active_border_color = 0x4a4a48
196 | normal_border_color = 0x30302f
197 | window_gap = 10
198 | virtual_desktops = 7
199 | focus_follow_pointer = true
200 | ```
201 |
202 | ##### Available Variables:
203 |
204 | - **border_width**: Defines the width of the window borders in pixels.
205 | - **active_border_color**: Specifies the color of the border for the active (focused) window.
206 | - **normal_border_color**: Specifies the color of the border for inactive (unfocused) windows.
207 | - **window_gap**: Sets the gap between windows in pixels.
208 | - **virtual_desktops**: sets the number of virtual desktops.
209 | - **focus_follow_pointer**: If false, the window is focused on click; if true, the window is focused when the cursor enters it.
210 |
211 | ### 2- Commands to run on startup
212 |
213 | ##### Use the `exec` directive to specify programs that should be started when ZWM is launched.
214 |
215 | - For a single command:
216 |
217 | ```ini
218 | exec = "polybar"
219 | ```
220 |
221 | - To specify additional arguments as a list:
222 |
223 | ```ini
224 | exec = ["polybar", "-c", ".config/polybar/config.ini"]
225 | ```
226 |
227 | ### 3- Custom window rules
228 |
229 | ##### Custom window rules allow you to define specific behaviors for windows based on their window class.
230 |
231 | ##### Syntax:
232 |
233 | ```ini
234 | rule = wm_class("window class name"), state(tiled|floated), desktop(1..N)
235 | ```
236 |
237 | ##### Explanation:
238 |
239 | - **wm_class**: The window class name used to identify the window.
240 | - Use the **`xprop`** tool to find the wm_class of a window.
241 | - **state**: Specifies whether the window should be tiled or floated.
242 | - **tiled**: The window will be tiled... clearly.
243 | - **floated**: The window will be floated... clearly.
244 | - **desktop**: The virtual desktop number where the window should be placed.
245 | - Use **-1** if you do not want to set it to a specific desktop.
246 |
247 | ```ini
248 | ; Example:
249 | rule = wm_class("firefox"), state(tiled), desktop(-1)
250 | ; This rule sets "firefox" window to be tiled and does not change its virtual desktop.
251 | ```
252 |
253 | ### 4- Key bindings
254 |
255 | - The format for defining key bindings is: `bind = modifier + key -> action`
256 | - If two modifiers are used, combine them with a pipe (|). For example, alt + shift is written as `alt|shift`.
257 | - Note: Some functions require additional arguments to specify details of the action.
258 | - These arguments are provided using a colon syntax, where the function and its argument are separated by a colon.
259 | - Example: `func(switch_desktop:1)` means "switch to desktop 1".
260 | - Example: `func(resize:grow)` means "grow the size of the window".
261 | - Example: `func(layout:master)` means "toggle master layout".
262 |
263 | #### Available modifires:
264 |
265 | - **super (meta)**, **alt**, **shift**, **ctrl**
266 |
267 | #### Available Actions:
268 |
269 | - run(...): Executes a specified process.
270 |
271 | - Example: `bind = super + return -> run("alacritty")`
272 | - To run a process with arguments, use a list:
273 | Example: `bind = super + p -> run(["rofi", "-show", "drun"])`
274 |
275 | - func(...): Calls a predefined function. The following functions are available:
276 |
277 | - **kill**: Kills the focused window.
278 | - **switch_desktop**: Switches to a specified virtual desktop.
279 | - **fullscreen**: Toggles fullscreen mode for the focused window.
280 | - **swap**: Swaps the focused window with its sibling.
281 | - **transfer_node**: Moves the focused window to another virtual desktop.
282 | - **layout**: Toggles the specified layout (master, deafult, stack).
283 | - **traverse**: (In stack layout only) Moves focus to the window above or below.
284 | - **flip**: Changes the window's orientation; if the window is primarily vertical, it becomes horizontal, and vice versa.
285 | - **cycle_window**: Moves focus to the window in the specified direction (up, down, left, right).
286 | - **cycle_desktop**: Cycles through the virtual desktops (left, right).
287 | - **resize**: Adjusts the size of the focused window (grow, shrink).
288 | - **reload_config**: Reloads the configuration file without restarting ZWM.
289 | - **shift_window**: Shift the floating window's position to the specified direction by 10px (up, down, left, right).
290 | - **gap_handler**: Increase or decrease window gaps (GROW, SHRINK).
291 | - **change_state**: Set window state (FLAOTING, TILED).
292 | - **grow_floating_window**: Grow floating window (horizontally or vertically).
293 | - **shrink_floating_window**: Shrink floating window (horizontally or vertically).
294 | - **cycle_monitors**: Cycle between monitors (left or right, relative to the linked-list order not the physical positioning).
295 |
296 | - Default keys
297 |
298 | ```ini
299 | bind = super + return -> run("alacritty")
300 | bind = super + space -> run("dmenu_run")
301 | bind = super + p -> run(["rofi","-show", "drun"])
302 | bind = super + w -> func(kill)
303 | bind = super + 1 -> func(switch_desktop:1)
304 | bind = super + 2 -> func(switch_desktop:2)
305 | bind = super + 3 -> func(switch_desktop:3)
306 | bind = super + 4 -> func(switch_desktop:4)
307 | bind = super + 5 -> func(switch_desktop:5)
308 | bind = super + 6 -> func(switch_desktop:6)
309 | bind = super + 7 -> func(switch_desktop:7)
310 | bind = super + l -> func(resize:grow)
311 | bind = super + h -> func(resize:shrink)
312 | bind = super + i -> func(gap_handler:grow)
313 | bind = super + d -> func(gap_handler:shrink)
314 | bind = super + f -> func(fullscreen)
315 | bind = super + s -> func(swap)
316 | bind = super + up -> func(cycle_window:up)
317 | bind = super + right -> func(cycle_window:right)
318 | bind = super + left -> func(cycle_window:left)
319 | bind = super + down -> func(cycle_window:down)
320 | bind = shift + up -> func(shift_window:up)
321 | bind = shift + right -> func(shift_window:right)
322 | bind = shift + left -> func(shift_window:left)
323 | bind = shift + down -> func(shift_window:down)
324 | bind = shift + f -> func(change_state:float)
325 | bind = shift + t -> func(change_state:tile)
326 | bind = super|shift + t -> func(shrink_floating_window:horizontal)
327 | bind = super|shift + g -> func(shrink_floating_window:vertical)
328 | bind = super|shift + y -> func(grow_floating_window:horizontal)
329 | bind = super|shift + h -> func(grow_floating_window:vertical)
330 | bind = super|shift + left -> func(cycle_desktop:left)
331 | bind = super|shift + right -> func(cycle_desktop:right)
332 | bind = super|ctrl + right -> func(cycle_monitors:next)
333 | bind = super|ctrl + left -> func(cycle_monitors:prev)
334 | bind = super|shift + 1 -> func(transfer_node:1)
335 | bind = super|shift + 2 -> func(transfer_node:2)
336 | bind = super|shift + 3 -> func(transfer_node:3)
337 | bind = super|shift + 4 -> func(transfer_node:4)
338 | bind = super|shift + 5 -> func(transfer_node:5)
339 | bind = super|shift + 6 -> func(transfer_node:6)
340 | bind = super|shift + 7 -> func(transfer_node:7)
341 | bind = super|shift + m -> func(layout:master)
342 | bind = super|shift + s -> func(layout:stack)
343 | bind = super|shift + d -> func(layout:default)
344 | bind = super|shift + k -> func(traverse:up)
345 | bind = super|shift + j -> func(traverse:down)
346 | bind = super|shift + f -> func(flip)
347 | bind = super|shift + r -> func(reload_config)
348 | ```
349 |
350 | More options will be added in the future as development progresses.
351 |
352 | ## Default Keybindings
353 |
354 | | Key | Description |
355 | | ------------------------ | ------------------------------------ |
356 | | `super + w` | kill/close window |
357 | | `super + return` | launch a terminal (alacritty) |
358 | | `super + space` | launch dmenu |
359 | | `super + p ` | launch rofi |
360 | | `super + [1..N]` | switch to desktop |
361 | | `super + l` | resize window (grow/expand) |
362 | | `super + h` | resize window (shrink) |
363 | | `super + f` | toggle fullscreen |
364 | | `super + shift + [1..N]` | transfer window to a diff desktop |
365 | | `super + shift + m` | toggle master layout |
366 | | `super + shift + s` | toggle stack layout |
367 | | `super + shift + d` | toggle default layout |
368 | | `super + shift + j/k` | traverse the stack |
369 | | `super + shift + f` | flip the window/partion |
370 | | `super + shift + r` | hot-reload |
371 | | `super + shift + y` | grow floating windows horizontally |
372 | | `super + shift + h` | grow floating windows vertically |
373 | | `super + shift + t` | shrink floating windows horizontally |
374 | | `super + shift + g` | shrink floating windows vertically |
375 | | `super + ctrl + →` | focus/change monitor right |
376 | | `super + ctrl + ←` | focus/change monitor left |
377 | | `super + s` | swap window's orientation |
378 | | `super + ←` | focus window on the left |
379 | | `super + ↑` | focus window above |
380 | | `super + →` | focus window on the right |
381 | | `super + ↓` | focus window below |
382 | | `super + shift + →` | cycle desktop right |
383 | | `super + shift + ←` | cycle desktop left |
384 | | `shift + ←` | shift window to the left by 10px |
385 | | `shift + ↑` | shift window up by 10px |
386 | | `shift + →` | shift window to the right by 10px |
387 | | `shift + ↓` | shift window down by 10px |
388 | | `super + i` | increase window gaps by 5px |
389 | | `super + d` | decrease window gaps by 5px |
390 | | `super + t` | tile window |
391 | | `super + f` | float window |
392 |
393 | ## ewmh specific settings for polyabr
394 |
395 | ### To display the window name (CLASS_NAME):
396 |
397 | ```ini
398 | [module/xwindow]
399 | type = internal/xwindow
400 | format =