├── .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 =