AutoTile is a GNOME Shell extension that brings **automatic tiling window management** to GNOME. It is heavily inspired by **[Omarchy](https://omarchy.org) 4.0** and the window layouters of **[Hyprland](https://hyprland.org)**: that is why we forked the excellent **[Tiling Shell](https://github.com/domferr/tilingshell)** project (many thanks to its original author [Domenico Ferraro](https://github.com/domferr)) and extended it, so that GNOME users can enjoy an auto-tiling experience that comes close to **Omarchy Linux** — huge thanks to DHH and the Omarchy developers for their aesthetics, inspiration, philosophy and outstanding code contributions.
Note: Binary files aren't shown on the web site. To see all files, please download the extension zipfile.
EGO-X-004 warning
extensions should avoid synchronous file IO in shell code
Shell code should avoid synchronous file IO APIs like `GLib.file_get_contents()` and `Gio.File.load_contents()`.
translations.js:19
Gio.File.new_for_path(
`${extensionPath}/locale/${catalogName}/LC_MESSAGES/${domain}.mo`
).load_contents(null)
EGO-C49-003 error
extensions targeting GNOME 49 must not call maximize or unmaximize with Meta.MaximizeFlags
This extension explicitly targets GNOME Shell 49 but still passes `Meta.MaximizeFlags` to `maximize()` or `unmaximize()`.
utils/gnomesupport.js:29
window.maximize(Meta.MaximizeFlags.BOTH)
utils/gnomesupport.js:33
window.unmaximize(Meta.MaximizeFlags.BOTH)
EGO-L-002 warning
objects created by extension should be destroyed in disable()
Objects assigned in `enable()` are missing matching `.destroy()` calls in `disable()` or its helper methods.
components/altTab/MultipleWindowsIcon.js:41
this._label = new St.Label({
text: t("Tiled windows")
})
components/altTab/tilePreviewWithWindow.js:12
this._gaps = new Clutter.Margin()
components/editor/editorDialog.js:42
this._layoutsBoxLayout = new St.BoxLayout({
styleClass: "layouts-box-layout",
xAlign: Clutter.ActorAlign.CENTER
})
components/windowsSuggestions/suggestionsTilePreview.js:30
this.layout_manager = new Clutter.BinLayout()
indicator/defaultMenu.js:134
this._container = new St.BoxLayout({
xAlign: Clutter.ActorAlign.CENTER,
yAlign: Clutter.ActorAlign.CENTER,
xExpand: true,
yExpand: true,
styleClass: "default-menu-container",
...widgetOrientation(true)
})
EGO-L-005 warning
owned object references should be released in disable()
Owned references that are cleaned up in `disable()` should also be released with `null` or `undefined`.
components/altTab/MultipleWindowsIcon.js:41
this._label = new St.Label({
text: t("Tiled windows")
})
components/altTab/tilePreviewWithWindow.js:12
this._gaps = new Clutter.Margin()
components/editor/editorDialog.js:42
this._layoutsBoxLayout = new St.BoxLayout({
styleClass: "layouts-box-layout",
xAlign: Clutter.ActorAlign.CENTER
})
components/windowBorder/windowBorderManager.js:15
this._interfaceSettings = new Gio.Settings({
schema_id: "org.gnome.desktop.interface"
})
components/windowsSuggestions/suggestionsTilePreview.js:30
this.layout_manager = new Clutter.BinLayout()
indicator/defaultMenu.js:134
this._container = new St.BoxLayout({
xAlign: Clutter.ActorAlign.CENTER,
yAlign: Clutter.ActorAlign.CENTER,
xExpand: true,
yExpand: true,
styleClass: "default-menu-container",
...widgetOrientation(true)
})
EGO-L-003 warning
signals connected by extension should be disconnected in disable()
Signals assigned in `enable()` are missing matching disconnect calls in `disable()` or its helper methods.
components/editor/editorDialog.js:284
btn.connect("clicked", () => {
params.onSelectLayout(btnInd, lay);
this._makeLegendDialog({
onClose: params.onClose,
path: params.path
});
})
components/editor/editorDialog.js:317
newLayoutBtn.connect("clicked", () => {
params.onNewLayout();
this._makeLegendDialog({
onClose: params.onClose,
path: params.path
});
})
components/editor/layoutEditor.js:158
editableTile.connect("clicked", (_, clicked_button) => {
if (clicked_button === St.ButtonMask.ONE)
this.splitTile(editableTile);
else if (clicked_button === 3) this.deleteTile(editableTile);
})
components/editor/layoutEditor.js:163
editableTile.connect("motion-event", (_, event) => {
const [stageX, stageY] = getEventCoords(event);
this._hoverWidget.handleMouseMove(
editableTile,
stageX - this.x,
stageY - this.y
);
return Clutter.EVENT_PROPAGATE;
})
components/editor/layoutEditor.js:172
editableTile.connect("notify::hover", () => {
const [stageX, stageY] = Shell.Global.get().get_pointer();
this._hoverWidget.handleMouseMove(
editableTile,
stageX - this.x,
stageY - this.y
);
})
components/raiseTogether/raiseTogetherManager.js:54
window.connect("unmanaged", () => {
delete this._raiseId[window.get_id()];
})
components/snapassist/snapAssist.js:69
this._signals.connect(
St.ThemeContext.get_for_stage(global.get_stage()),
"changed",
() => {
this._applyStyle();
}
)
components/windowBorder/windowBorder.js:100
this._signals.connect(global.display, "restacked", () => {
this.queue_repaint();
global.windowGroup.set_child_above_sibling(this, null);
})
components/windowBorder/windowBorderManager.js:49
this._interfaceSettings.connect(
"changed::accent-color",
() => this._border?.updateStyle()
)
components/windowManager/autoTileWindowManager.js:56
this._signals.connect(
global.display,
"window-created",
(_, window) => {
window.__ts_cached = new CachedWindowProperties(window, this);
this._trackWindowSignals(window);
}
)
indicator/defaultMenu.js:62
btn.connect(
"clicked",
() => !btn.checked && this.emit("selected-layout", lay.id)
)
indicator/defaultMenu.js:349
row.connect(
"selected-layout",
(r, layoutId) => {
this._indicator.selectLayoutOnClick(
monitor.index,
layoutId
);
}
)
keybindings.js:29
this._signals.connect(
Settings,
Settings.KEY_ENABLE_MOVE_KEYBINDINGS,
() => {
this._setupKeyBindings(extensionSettings);
}
)
utils/globalState.js:46
this._signals.connect(
Settings,
Settings.KEY_SETTING_LAYOUTS_JSON,
() => {
this._layouts = Settings.get_layouts_json();
this.emit(_GlobalState.SIGNAL_LAYOUTS_CHANGED);
}
)
EGO-L-004 warning
main loop sources should be removed in disable()
Main loop sources assigned in `enable()` are missing matching removals in `disable()` or its helper methods.
components/tilingsystem/tilingManager.js:1269
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
if (window.minimized || window.maximizedHorizontally || window.maximizedVertically || window.get_transient_for() !== null || window.is_attached_dialog())
return GLib.SOURCE_REMOVE;
if (!Settings.ENABLE_AUTO_TIL
components/tilingsystem/tilingManager.js:1476
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
try {
this._executeInsertionPlan(window, plan, anchorWs);
return GLib.SOURCE_REMOVE;
} finally {
_insertionShiftInProgress = false;
}
})
components/tilingsystem/tilingManager.js:1624
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250 * attempt, () => {
if (window.get_compositor_private() === null)
return GLib.SOURCE_REMOVE;
const movedOk = window.get_frame_rect().overlap(tileRect);
if (!movedOk && attempt < 3) {
this._auditInsertionMoveLater(
components/windowBorder/windowBorder.js:161
this._timeout = setTimeout(() => {
this._computeBorderRadius(winActor).then(() => this.updateStyle());
if (this._timeout) clearTimeout(this._timeout);
this._timeout = void 0;
}, SMART_BORDER_RADIUS_FIRST_FRAME_DELAY)
| Version | Status |
|---|---|
| 18.0 (2) | Unreviewed |
| 17.3 (1) | Rejected |