GlazeWM is a tiling window manager for Windows inspired by i3 and Polybar.
Why use a tiling window manager? A tiling WM lets you easily organize windows and adjust their layout on the fly by using keyboard-driven commands.
- Simple YAML configuration
- Multi-monitor support
- Customizable bar window
- Customizable rules for specific windows
- Easy one-click installation
Showcase GIF by @HolbyFPV
Under the hood, GlazeWM adds functionality to the built-in window manager and uses the Windows API via P/Invoke to position windows.
The latest runnable executable can be downloaded via releases. No installation necessary, simply run the .exe
file.
GlazeWM can be downloaded via Winget package manager:
winget install GlazeWM
Winget installs portable packages in %LOCALAPPDATA%\Microsoft\Winget\Packages\
by default. This can be overrided with the flag --location \path\to\folder
.
GlazeWM can be download via Scoop in the Extras bucket:
scoop bucket add extras # Ensure bucket is added first
scoop install glazewm
Alternatively, to build from source, use the following .NET CLI command:
dotnet publish ./GlazeWM.App/GlazeWM.App.csproj --configuration=Release --runtime=win-x64 --output=. --self-contained -p:PublishSingleFile=true -p:IncludeAllContentForSelfExtract=true
To build for other runtimes than Windows x64, see here.
- Improve handling of fullscreen and maximized windows.
- More bar components.
The configuration file for GlazeWM can be found at C:\Users\<YOUR_USER>\.glaze-wm\config.yaml
. If this file doesn't exist, the default config can optionally be generated on launch.
To use a different config file location, you can launch the GlazeWM executable with the CLI argument --config="..."
, like so:
./GlazeWM.exe --config="C:\<PATH_TO_CONFIG>\config.yaml"
general:
# Whether to automatically focus windows underneath the cursor.
focus_follows_cursor: false
# Whether to jump the cursor between windows focused by the WM.
cursor_follows_focus: false
# Whether to switch back and forth between the previously focused workspace
# when focusing the current workspace.
toggle_workspace_on_refocus: true
# Whether to show floating windows as always on top.
show_floating_on_top: false
# Amount to move floating windows by (eg. when using `alt+<hjkl>` on a floating window)
floating_window_move_amount: "5%"
# Whether to globally enable/disable window transition animations (on minimize, close,
# etc). Set to 'unchanged' to make no setting changes.
window_animations: "unchanged"
The available keybindings can be customized via the keybindings
property in the config file. A keybinding consists of one or more key combinations and one or more commands to run when pressed.
A full list of keys that can be used for keybindings can be found here. Numbers can be used in keybindings with and without a D
prefix (eg. either D1
or 1
works).
It's recommended to use the alt key for keybindings. The windows key is unfortunately a pain to remap, since certain keybindings (eg. LWin+L
) are reserved by the OS.
keybindings:
# Command to run.
- command: "focus workspace 1"
# Key combination to trigger the keybinding.
binding: "Alt+1"
# To run multiple commands in a sequence, use the `commands` property (eg. to move a window to a
# workspace + focus workspace).
- commands: ["move to workspace 1", "focus workspace 1"]
binding: "Alt+Shift+1"
- command: "focus left"
# To have multiple key combinations that can trigger a command, use the `bindings` property.
bindings: ["Alt+H", "Alt+Left"]
Keybindings with Alt pressed:
Keybindings with Alt+Shift pressed:
Apart from the Alt+Shift+E
binding for exiting GlazeWM, it's also possibly to safely exit via the system tray icon.
The focused and unfocused window border color can be configured via the focus_borders
property.
Requires minimum of Windows 11 Build 22000.51.
focus_borders:
active:
enabled: true
color: "#ff0000"
inactive:
enabled: false
color: "#0000ff"
The gaps between windows can be changed via the gaps
property in the config file. Inner and outer gaps are set separately.
gaps:
# Gap between adjacent windows.
inner_gap: "20px"
# Gap between windows and the screen edge. See "Shorthand properties" for more info.
outer_gap: "20px 0 20px 0"
Workspaces need to be predefined via the workspaces
property in the config file. A workspace is automatically assigned to each monitor on startup.
workspaces:
# Uniquely identifies the workspace and is used as the label for the workspace in the bar if
# `display_name` is not provided.
- name: "1"
# Optional override for the workspace label in the bar. Does not need to be unique.
display_name: "Work"
# Optionally force the workspace on a specific monitor if it exists. Use the monitor's number
# as shown in the Windows display settings (eg. 1, 2, 3...).
bind_to_monitor: 1
# Optionally prevent workspace from being deactivated when empty.
keep_alive: false
The appearance of the bar can be changed via the bar
property in the config file.
bar:
# The option to enable/disable the bar.
enabled: true
# Height of the bar in pixels.
height: "30px"
# The position of the bar on the screen. Can be either "top" or "bottom".
position: "top"
# Whether to show the bar above other windows
always_on_top: false
# Opacity value between 0.0 and 1.0.
opacity: 1.0
# Background color of the bar.
background: "#101010"
# Default font color. Can be overriden by setting `foreground` in a component's config.
foreground: "white"
# Default font family. Can be overriden by setting `font_family` in a component's config.
font_family: "Segoe UI"
# Default font size. Can be overriden by setting `font_size` in a component's config.
font_size: "13px"
# Default font weight. Typically ranges from 100 to 950, where a higher value is thicker. Can
# be overriden by setting `font_weight` in a component's config.
font_weight: "400"
# Horizontal and vertical borders in pixels. Borders are inside the dimensions of the bar and do
# not affect bar height. See "Shorthand properties" for more info.
border_width: "0"
# Color of the border.
border_color: "blue"
# Horizontal and vertical spacing between components within the bar and the edges of the bar. See
# "Shorthand properties" for more info.
padding: "4px 6px 4px 6px"
# Separator between components within the bar. `label` is used for each section
# of the bar unless `label_{left,center,right}` is explictly set, in which case
# they are preferred over default.
component_separator:
label: " | "
# Components to display on the left side of the bar.
components_left:
- type: "workspaces"
# Components to display on the right side of the bar.
components_right:
- type: "clock"
The appearance of bar components can also be customized. The following properties can change the styling of a component, regardless of the component type.
# Type of component to display. Currently 7 component types exist: "workspaces", "clock", "text", "battery", "window title", "binding mode" and "tiling direction".
type: <COMPONENT_TYPE>
# Horizontal and vertical margins. See "Shorthand properties" for more info.
margin: "0 10px 0 0"
# Horizontal and vertical padding. See "Shorthand properties" for more info.
padding: "0"
# Opacity value between 0.0 and 1.0.
opacity: 1.0
# Background color of the component.
background: "#101010"
# Font color used within the component.
foreground: "white"
# Font family used within the component.
font_family: "Segoe UI"
# Font size used within the component.
font_size: "13px"
# Font weight used within the component. Typically ranges from 100 to 950, where a higher value is
# thicker.
font_weight: "400"
# Horizontal and vertical borders in pixels. Borders are inside the dimensions of the component.
# See "Shorthand properties" for more info.
border_width: "0"
# Color of the border.
border_color: "blue"
Properties related to the edges of the bar or a component, like padding
, margin
, and border_width
, use a 1-to-4 value syntax. This is the same convention that's common in CSS.
Using the example of padding:
- When one value is specified, it applies the same padding to all four sides.
- When two values are specified, the first padding applies to the top and bottom, the second to the left and right.
- When three values are specified, the first padding applies to the top, the second to the right and left, the third to the bottom.
- When four values are specified, the paddings apply to the top, right, bottom, and left in that order (clockwise).
The text shown in the clock component is specified via time_formatting
. The supported time format specifiers are defined by .NET's time/date string formatting.
Additionally supported format specifiers:
Specifier | Description | Example |
---|---|---|
"w" | Week of year: 1..53 | 'HH:mm dd.MM.yyyy (ww)' => 13:05 21.12.2022 (51) |
"ww" | Week of year 01..53 | 'HH:mm dd.MM.yyyy (ww)' => 13:05 02.01.2022 (02) |
Example usage:
- type: "clock"
time_formatting: "hh:mm tt ddd MMM d"
The battery component displays the system's battery level in percent. There are three labels available that can be customized:
label_draining
: used when the system is draining battery power(i.e. not charging).label_power_saver
: used when the system is on power saving mode.label_charging
: used when the system is connected to power.
{battery_level}
is a variable which is replaced by the actual battery level when the label is displayed.
Example usage:
- type: "battery"
label_draining: "{battery_level}% remaining"
label_power_saver: "{battery_level}% (power saver)"
label_charging: "{battery_level}% (charging)"
Displays the current CPU usage.
- type: "cpu"
label: "CPU: {percent_usage}%"
# How often this counter is refreshed.
refresh_interval_ms: 1000
This component has high CPU requirement (compared to others); due to no efficient way to pull data from Windows API. Avoid using low refresh intervals.
- type: "gpu"
label: "GPU: {percent_usage}%"
# How often this counter is refreshed.
refresh_interval_ms: 1000
Displays the current Memory usage.
- type: "memory"
label: "RAM: {percent_usage}%"
# How often this counter is refreshed.
refresh_interval_ms: 1000
Displays the type and signal strength of the active network connection.
- type: "network"
label_no_internet: "NC"
label_ethernet: "Eth"
label_wifi_strength_0: "WiFi: 0%"
label_wifi_strength_25: "WiFi: 25%"
label_wifi_strength_50: "WiFi: 50%"
label_wifi_strength_75: "WiFi: 75%"
label_wifi_strength_100: "WiFi: 100%"
Displays volume level.
- type: "volume"
label_low: "🔊{volume_level}%"
label_medium: "🔊{volume_level}%"
label_high: "🔊{volume_level}%"
label_mute: "🔊{volume_level}%"
For displaying any content without a native integrated widget; updates in real time.
- type: "text file"
# Path to file.
file_path: "PATH_HERE"
Uses Open-Meteo API, refreshes every hour.
- type: "weather"
latitude: 40.6892
longitude: 74.0445
label: "{temperature_celsius}°C"
label_sun: "☀️ {temperature_celsius}°C"
label_moon: "🌙 {temperature_celsius}°C"
label_cloud_moon: "🌙☁️ {temperature_celsius}°C"
label_cloud_sun: "⛅ {temperature_celsius}°C"
label_cloud_moon_rain: "🌙🌧️ {temperature_celsius}°C"
label_cloud_sun_rain: "🌦️ {temperature_celsius}°C"
label_cloud_rain: "🌧️ {temperature_celsius}°C"
label_snow_flake: "❄️ {temperature_celsius}°C"
label_thunderstorm: "⚡ {temperature_celsius}°C"
label_cloud: "☁️ {temperature_celsius}°C"
Supports .png
and .jpg
formats.
- type: "image"
source: "C:\\Folder\\AnotherFolder\\image.png"
Use Alt+Click
to pin and un-pin an icon.
- type: "system tray"
label_expand_text: "<"
label_collapse_text: ">"
Font family, font weight, font size, and foreground color can be changed within parts of a label. This means that icons and text fonts can be used together in a label. To customize a part of the label, wrap it in an tag:
bar:
components_left:
- type: "cpu"
# Change font family (ie. ff) to Comic Sans for part of the label:
label: "<attr ff='Comic Sans'>CPU:</attr> {percent_usage}%"
- type: "battery"
# Show an icon by using an icon font:
label_draining: "<attr ff='Material Icons'></attr> {battery_level}%"
# Multiple attributes can be changed at once:
label_charging: "{battery_level}% <attr ff='Arial' fg='#228B22' fw='400' fs='13px'>(charging)</attr>"
It's common to use icons as the label
in bar components by assigning a font family that contains glyphs. A popular option is Nerd Font which comes with a cheat sheet for easily finding a desired glyph.
Commands can be run when a window is initially launched. This can be used to assign an app to a specific workspace or to always start an app in floating mode.
Multiple matching criteria can be used together to target a window more precisely. Regex syntax can also be used by wrapping the pattern with /
(eg. /notepad|chrome/
)
window_rules:
# Command to run. Use `commands` to specify an array of commands to run in sequence.
- command: "move to workspace 2"
# Process name to match exactly.
match_process_name: "chrome"
# Window title to match exactly.
match_title: "/.*/"
# Class name to match exactly.
match_class_name: "Chrome_WidgetWin_1"
# To prevent the WM from managing an app, use the "ignore" command.
- command: "ignore"
match_process_name: "notepad"
- focus <left | right | up | down>
- focus workspace <prev | next | recent>
- focus workspace <workspace name>
- move <left | right | up | down>
- move to workspace <workspace name>
- resize <height | width> <amount in px | amount in %> (eg.
resize height 3%
orresize width 20px
) - resize borders <shorthand property> (eg.
resize borders 0px -7px -7px -7px
) - set <floating | tiling | minimized | maximized>
- set <width | height> <amount in px | amount in %> (eg.
set height 30%
orset width 200px
) - toggle <floating | maximized>
- focus mode toggle
- tiling direction <vertical | horizontal | toggle>
- exit wm
- reload config
- close
- exec <process name | path to executable> (eg.
exec chrome
orexec 'C:/Program Files/Google/Chrome/Application/chrome'
) - ignore
An app called "Sonic Studio", which is installed by default on ASUS ROG machines can cause rendering issues with WPF apps. This can be resolved by disabling NahimicService
in Windows Services Manager.
Most keyboard layouts treat the right-side Alt key the same as the left, while others (eg. US International and German) treat it as AltGr and generate both Ctrl and Alt when it is pressed. For these keyboard layouts, keybindings with the AltGr key need to specify both RMenu
and Control
(eg. RMenu+Control+A
).
Example:
Run the following autohotkey v1 script as administrator
; https://superuser.com/a/1819950/881662
#InstallKeybdHook
; Disable win + l key locking (This line must come before any hotkey assignments in the .ahk file)
RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 1
; Optional: Remap winKey + <someKey> here:
#space::return
#s::return
#h::
Send, ^{F9} ; It's important to chose some random intermediary hotkey, I choose ctrl + F9
return
#j::
Send, ^{F10}
return
#k::
Send, ^{F11}
return
#l::
Send, ^{F12}
return
;CTRL+WIN+L
^F12::
RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 0
DllCall("LockWorkStation")
;after locking workstation force a reload of this script which effectively disables Win + L locking the computer again
Reload
Next, amend the keybindings section in config.yaml:
keybindings:
# Shift focus in a given direction.
- command: "focus left"
bindings: ["Ctrl+F9"] ; Notice I am using the intermediary hotkeys here
- command: "focus right"
bindings: ["Ctrl+F12"]
- command: "focus up"
bindings: ["Ctrl+F11"]
- command: "focus down"
bindings: ["Ctrl+F10"]
That's it, now you can use LWin + l
to focus right and LWin + h
to focus left, etc.