Fork of forge-ext/forge with additional CPU, memory and functionality bug fixes, plus a standalone build script. All changes are backward-compatible with GNOME 45-48 and verified against GNOME 50.1.
- Per-focus debug overhead -
movePointerWith()built debug strings and calledglobal.get_pointer()for every parent node on every focus/move/swap, even with logging disabled (JS evaluates log arguments eagerly, before the no-op log call). Now gated behind a cheapLogger.enabledcheck. - Logger settings reads - the
Loggerlevel getter now short-circuits in production before reading GSettings, so hot paths that log no longer pay for a settings read on every call. - Stale focus-follows-mouse timer - the hover-focus loop now clears its source id when it self-removes, avoiding
GLib.Source.remove()on an already-removed source (GLib criticals / removing an unrelated, id-recycled source).
- Quick-settings indicator leak -
FeatureIndicatorconnected achangedhandler to GSettings that was never disconnected, while the indicator is destroyed and recreated on every screen lock/unlock - leaking the indicator (and its handler) each cycle. It now disconnects on destroy. - WindowManager settings handler - now tracked and disconnected on disable, so a stale handler can't fire against a torn-down manager across enable/disable cycles.
- Focus-hint split border never appeared - a condition tested a function reference (
!maximized) instead of calling it (!maximized()). - Tabbed focus not updated on monitor/workspace moves -
!this.grabOp === Meta.GrabOp.WINDOW_BASEwas an operator-precedence bug (always false); corrected to!==. - Dangling parent after detaching a node -
Node.removeChild()clearedparentNodeon the array returned bysplice()rather than on the node, leaving a stale_parentthat could throwNodeNotFoundon a later re-parent (a likely source of intermittent tiling glitches). - Added a missing
breakin the tree_search()switch and fixed an off-by-one workspace loop infindWindowWith().
- Replaced the legacy
imports.byteArray.toString()withnew TextDecoder().decode()when reading the window-config/stylesheet files (the old API is deprecated and risks breaking on GNOME 50.x). - Guarded the pointer scan against window actors that have no
meta_window. - Verified GNOME 50.1 compatibility:
maximize()/unmaximize()/is_maximized()already use version-safe fallbacks,Mtk.Rectangleand Clutter event getters are used throughout, and no removed APIs remain.
A standalone build.sh is included (needs no make, npm or prettier - only the GNOME tools that ship with the desktop):
./build.sh # builds forge@jmmaranan.com.zip
./build.sh install # builds and installs via gnome-extensionsLog out and back in (Wayland requires a session restart), then enable:
gnome-extensions enable forge@jmmaranan.comForge is a GNOME Shell extension that provides tiling/window management AND is looking for a new owner or maintainer:
- Works on GNOME 45 through 50.1. X11 and Wayland
- Tree-based tiling with vertical and horizontal split containers similar to i3-wm and sway-wm
- Vim-like keybindings for navigation/swapping windows/moving windows in the containers
- Drag and drop tiling
- Support for floating windows, smart gaps and focus hint
- Customizable shortcuts in extension preferences
- Some support for multi-display
- Tiling support per workspace
- Update hint color scheme from preferences
- Stacked tiling layout
- Swap current window with the last active window
- Auto Split or Quarter Tiling
- Show/hide tab decoration via keybinding forge-ext#180
- Window resize using keyboard shortcuts
- Does not support dynamic workspaces
- Does not support vertical monitor setup
- Build it yourself via
make installormake dev. - Download from GNOME extensions website.
- AUR Package - thanks to @Radeox
- Fedora Package - thanks to @carlwgeorge
See the acceptable key combinations on the wiki
| Action | Shortcut |
|---|---|
| Increase active window size left | <Ctrl> + <Super> + y |
| Decrease active window size left | <Ctrl> + <Shift> + <Super> + o |
| Increase active window size bottom | <Ctrl> + <Super> + u |
| Decrease active window size bottom | <Ctrl> + <Shift> + <Super> + i |
| Increase active window size top | <Ctrl> + <Super> + i |
| Decrease active window size top | <Ctrl> + <Shift> + <Super> + u |
| Increase active window size right | <Ctrl> + <Super> + o |
| Decrease active window size right | <Ctrl> + <Shift> + <Super> + y |
| Open preferences | <Super> + period |
| Toggle tiling mode | <Super> + w |
| Focus left | <Super> + h |
| Focus right | <Super> + l |
| Focus up | <Super> + k |
| Focus down | <Super> + j |
| Swap current window with last active | <Super> + Return |
| Swap active window left | <Ctrl> + <Super> + h |
| Swap active window right | <Ctrl> + <Super> + l |
| Swap active window up | <Ctrl> + <Super> + k |
| Swap active window down | <Ctrl> + <Super> + j |
| Move active window left | <Shift> + <Super> + h |
| Move active window right | <Shift> + <Super> + l |
| Move active window up | <Shift> + <Super> + k |
| Move active window down | <Shift> + <Super> + j |
| Split container horizontally | <Super> + z |
| Split container vertically | <Super> + v |
| Toggle split container | <Super> + g |
| Gap increase | <Ctrl> + <Super> + Plus |
| Gap decrease | <Ctrl> + <Super> + Minus |
| Toggle focus hint | <Super> + x |
| Toggle active workspace tiling | <Shift> + <Super> + w |
| Toggle stacked layout | <Shift> + <Super> + s |
| Toggle tabbed layout | <Shift> + <Super> + t |
| Show/hide tab decoration | <Ctrl> + <Alt> + y |
| Activate tile drag-drop | Start dragging - Mod key configuration in prefs |
| Snap active window left two thirds | <Ctrl> + <Alt> + e |
| Snap active window right two thirds | <Ctrl> + <Alt> + t |
| Snap active window left third | <Ctrl> + <Alt> + d |
| Snap active window right third | <Ctrl> + <Alt> + g |
| Persist toggle floating for active window | <Super> + c |
| Persist toggle floating for active window and its window class | <Super><Shift> + c |
For any shortcut conflicts, the user has to manually configure those for now from the
GNOME Control Center > Keyboard > Customize Shortcuts. forge-ext#37
- Window Overrides:
$HOME/.config/forge/config/windows.json - Stylesheet Overrides:
$HOME/.config/forge/stylesheet/forge/stylesheet.css
GNOME Shell has built in support for workspace management and seems to work well - so Forge will not touch those.
User is encouraged to bind the following:
- Switching/moving windows to different workspaces
- Switching to numbered, previous or next workspace
- The
mainbranch contains gnome-4x code. - The
legacyandgnome-3-36are the same and is now the source for gnome-3x.
- Install NodeJS 16+
- Install
gettext - Run
npm install - Commands:
# Compile and override the gnome-shell update repo
make dev
# Or run below, and restart the shell manually
make build && make debug && make install
# X11 - build from source and restarts gnome-shell
make test-x
# Wayland - build from source and starts a wayland instance (no restart)
make test-wayland
# Formatting, when you do npm install,
# husky gets installed should force prettier formatting during commit
npm run format- Please be nice, friendly and welcoming on discussions/tickets.
- See existing Issues, or create a new Issue with the "Bug report" format if it doesn't exist.
Thank you to:
- Forge extension contributors
- Michael Stapelberg/contributors for i3
- System76/contributors for pop-shell
- ReworkCSS/contributors for css-parse/css-stringify
