Alt+Tab window switcher for Hyprland, written in C with GTK4.
- C 93.7%
- CMake 5%
- Shell 1.3%
Calling hyprctl_focuswindow after gtk_window_destroy is a Wayland timing hazard: Hyprland may pick a fallback focus target when the popup surface disappears, racing with the focuswindow dispatch. On a quick Alt+Tab tap the popup can vanish before Hyprland has given it keyboard focus, making the race more likely to lose. Swapping the order also eliminates a potential dangling-pointer read of addr_str, which is freed as part of the widget teardown. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .gdbinit | ||
| .gitignore | ||
| CLAUDE.md | ||
| clean.sh | ||
| CMakeLists.txt | ||
| config.def.h | ||
| debug.sh | ||
| go | ||
| ipc.c | ||
| ipc.h | ||
| LICENSE | ||
| main.c | ||
| README.md | ||
| release.sh | ||
| test_ipc.c | ||
hyprtab
Alt+Tab window switcher for Hyprland, written in C with GTK4.
How it works
hyprtab runs as a small resident GTK4 window. It listens to Hyprland's IPC event socket to maintain a most-recently-used (MRU) window list. When Alt+Tab is pressed, a popup appears showing all tracked windows with the selection starting at the previous window. Repeated presses cycle forward. Releasing Alt confirms the selection and focuses the chosen window via hyprctl.
Dependencies
- GTK4
- Hyprland
- CMake ≥ 3.10
Build
cp config.def.h config.h # create your local config (edit as needed)
./debug.sh # clean + cmake (Debug) + make
# or
./release.sh # clean + cmake (Release) + make
The binary is placed in the build directory as hyprtab.
Configuration
Edit config.h before building to customize keybindings:
| Define | Default | Meaning |
|---|---|---|
TAB_STATE |
GDK_ALT_MASK |
Modifier required to trigger |
TAB_KEYVAL |
GDK_KEY_Tab |
Key to cycle windows |
TAB_RELEASE_KEYVAL |
GDK_KEY_Alt_L |
Key release that confirms selection |
Hyprland setup
Add the following to your Hyprland configuration file ~/.config/hypr/hyprland.conf
bind = ALT, Tab, pass, class:fr.kanis.hyprtab
windowrule {
name = hyprtab-main
match:class = fr.kanis.hyprtab
workspace = name:h
no_initial_focus = true
}
windowrule {
name = hyprtab-list
match:title = hyprtab.list
float = true
}
Then launch hyprtab at startup, for example:
exec-once = /path/to/hyprtab
License
BSD 3-Clause — see LICENSE. Copyright (c) 2026, Ivan Kanis.