Extract tile position computation into tilePosForID() helper to provide
a single source of truth for centering logic. The close, open, swipe,
and damage-reporting animations were using a simple grid formula that
ignored partial-row centering and vertical grid centering offsets,
causing the zoom to target the wrong position for tiles in incomplete
rows (e.g. the 3rd workspace in a 2x2 grid).
Instead of fitting tiles inside oversized grid cells (which created
uneven padding that looked like double-gaps), compute the aspect-correct
tile size upfront and lay out tiles with uniform gaps. The entire grid
is centered on screen. No visual change for square grids (cols == rows).
New features for the overview:
- Active workspace and hover highlight borders (configurable color/width)
- Keyboard navigation with arrow keys, Enter, Escape, and 1-9 quick jump
- Drag-to-move windows between workspaces (opt-in)
- Configurable label position, size, and color
- Workspace name labels (opt-in)
- Fill gaps between active workspaces in dynamic grid (opt-in)
- MRU sorting to put current workspace first (opt-in)
- Staggered fade-in animation on entry (opt-in)
When cols ≠ rows, grid cells have a different aspect ratio than the
monitor, causing workspace textures to stretch. Fit each tile within
its cell while preserving the monitor aspect ratio, centering with
letterbox/pillarbox padding. No-op when cols == rows (square grid).
- Added labelTex texture field to SWorkspaceImage for rendering workspace numbers
- Added renderLabel() method to generate circular labels with workspace IDs
- Integrated Cairo/Pango text rendering for high-quality label generation
- Labels display at top-right corner of each tile with dark background and white text
- Improves visual identification of workspaces in overview mode
This makes it easy to identify which workspace each tile represents at a glance.
- Add horizontal centering for tiles in incomplete last row
- Add vertical centering when tiles don't fill all grid rows
- Ensure minimum 2x2 grid for better aspect ratio with 2+ workspaces
- Fix mouse hit detection to use actual tile boxes
When dynamic_grid=1, the overview grid automatically sizes itself based
on the number of active (non-empty) workspaces instead of always showing
a fixed columns×columns grid.
For example:
- 2 active workspaces → 2×1 grid (fills screen width)
- 3 active workspaces → 2×2 grid (3 tiles)
- 4 active workspaces → 2×2 grid (4 tiles)
- 5-6 active workspaces → 3×2 grid
This provides a cleaner overview when working with fewer workspaces,
as tiles fill the available screen space rather than showing many
empty slots.
The feature works in combination with skip_empty=1 to only show
workspaces that contain windows.
Configuration:
plugin {
hyprexpo {
dynamic_grid = 1
skip_empty = 1
}
}
* hyprexpo: Fixes for 40d8fa8
* csgo-vulkan-fix: Fixes for 40d8fa8
* hyprbars: Fixes for 40d8fa8
I am not entirely sure whether I was supposed to use fullWindowFocus()
or rawWindowFocus() in hyprbars/barDeco.cpp at line 220
* xtra-dispatchers: Fixes for 40d8fa8
I am not entirely sure whether I was supposed to use fullWindowFocus()
or rawWindowFocus() in xtra-dispatchers/main.cpp at lines 47 and 106
* hyprscrolling: Fixes for 40d8fa8
A lot of repeated code can be removed if it's safe to store
`Desktop::focusState()`, `Desktop::focusState()->monitor()` and
`Desktop::focusState()->window()` at the top of the
`CScrollingLayout::findBestNeighbor` function.
This change requires further review as I don't know if any of those
change during this function so I didn't wanna introduce any unexpected
issues.
I am not entirely sure whether I was supposed to use fullWindowFocus()
or rawWindowFocus() in xtra-dispatchers/main.cpp at lines 786, 789 and
1344