9 Commits

Author SHA1 Message Date
Dome 7aa9a30375 Update README.md 2025-07-23 23:43:48 +02:00
Dome ecfc739cc8 Update README.md 2025-07-23 23:42:27 +02:00
Dome 2a94a1c04f Update org.gnome.shell.extensions.simple-tiling.domoel.gschema.xml 2025-07-23 23:36:45 +02:00
Dome 8c1dce1644 Update extension.js 2025-07-23 23:36:27 +02:00
Dome 6a5f421fdf Update metadata.json 2025-07-23 23:36:08 +02:00
Dome 10e9faf528 Update prefs.js 2025-07-23 23:35:52 +02:00
Dome bf492ceeb3 Update README.md 2025-07-23 22:46:06 +02:00
Dome a5ba875df0 Update README.md 2025-07-23 22:45:09 +02:00
Dome 90b8dd952e Update README.md 2025-07-23 22:04:52 +02:00
5 changed files with 56 additions and 9 deletions
+10 -1
View File
@@ -5,7 +5,7 @@
A lightweight, opinionated, and automatic tiling window manager for GNOME Shell 3.38. A lightweight, opinionated, and automatic tiling window manager for GNOME Shell 3.38.
<img width="2560" height="1440" alt="Simple-Tiling" src="https://github.com/user-attachments/assets/bb776134-57e0-4fcc-93c8-0b43b616dd11" /> <img width="2560" height="1440" alt="Simple-Tiling-v3" src="https://github.com/user-attachments/assets/42c64902-baab-4c84-9857-470f7f1ff035" />
## Introduction ## Introduction
@@ -17,6 +17,7 @@ This extension was built from the ground up to be stable and performant on **GNO
* **Automatic Tiling:** Windows are automatically arranged into a master and stack layout without any manual intervention. * **Automatic Tiling:** Windows are automatically arranged into a master and stack layout without any manual intervention.
* **Master & Fibonacci Stack Layout:** The first window becomes the "master," occupying the left half of the screen. All subsequent windows form a "stack" on the right half, which is tiled using a space-efficient Fibonacci-style algorithm. * **Master & Fibonacci Stack Layout:** The first window becomes the "master," occupying the left half of the screen. All subsequent windows form a "stack" on the right half, which is tiled using a space-efficient Fibonacci-style algorithm.
* **Configurable New Window Behavior:** Choose whether new windows open as the new master or are appended to the end of the stack.
* **Tiling Lock:** The layout is strict by default. If you manually move a window with the mouse and drop it in an empty space, it will automatically "snap back" to its designated tile position, preserving the integrity of the layout. * **Tiling Lock:** The layout is strict by default. If you manually move a window with the mouse and drop it in an empty space, it will automatically "snap back" to its designated tile position, preserving the integrity of the layout.
* **Interactive Window Swapping:** * **Interactive Window Swapping:**
* **Drag & Drop:** Swap any two windows by simply dragging one and dropping it over the other. * **Drag & Drop:** Swap any two windows by simply dragging one and dropping it over the other.
@@ -84,6 +85,10 @@ You can adjust the window gap margins (inner gaps between windows, outer gaps ho
If you have race condition issues between mutter (Gnome WM) and the Simple Tiling extension, you can adjust the window delay settings (both for tiling windows as well as for centered application from the exceptions list) directly in the extensions.js (~/.local/share/gnome-shell/extensions/simple-tiling@domoel/extension.js). You will find the parameter at line 222 (commented). Defaults to "20" for General Tiling Window Delay and "5" for centered Apps on the Exception List. If you have race condition issues between mutter (Gnome WM) and the Simple Tiling extension, you can adjust the window delay settings (both for tiling windows as well as for centered application from the exceptions list) directly in the extensions.js (~/.local/share/gnome-shell/extensions/simple-tiling@domoel/extension.js). You will find the parameter at line 222 (commented). Defaults to "20" for General Tiling Window Delay and "5" for centered Apps on the Exception List.
#### Configurable New Window Behavior
A toogle setting allows you to control the behavior for newly opened windows. You can choose to either have them become the new master window (pushing the old master into the stack) or have them appended to the stack as the last window (Default).
## Future Development ## Future Development
This extension was built to solve a specific need. However, future enhancements could include: This extension was built to solve a specific need. However, future enhancements could include:
@@ -91,6 +96,10 @@ This extension was built to solve a specific need. However, future enhancements
* Additional layout algorithms. * Additional layout algorithms.
* A more detailed settings panel to configure other options via a GUI. * A more detailed settings panel to configure other options via a GUI.
## Misc
I recommend to add also [Focus Changer](https://github.com/martinhjartmyr/gnome-shell-extension-focus-changer) as an extension to make navigating between windows super easy. With Foocus Changer you can set keybindings (e.g. "Alt" + "Arrow-Keys") to change the selected / active window on a given workspace. Once selected you can now (with Simple Tiling) swap the selected window with any other window on your workspace (e.g. "Super" + "Arrow-Key"). Its super handy and really simple.
## License ## License
This project is licensed under the MIT License - see the `LICENSE` file for details. This project is licensed under the MIT License - see the `LICENSE` file for details.
+8 -2
View File
@@ -1,5 +1,5 @@
// ---------------------------------------------------- // // ---------------------------------------------------- //
// Simple-Tiling GNOME Shell 3.38 (X11) - Version 2 // // Simple-Tiling GNOME Shell 3.38 (X11) - Version 3 //
// © 2025 domoel MIT // // © 2025 domoel MIT //
// ---------------------------------------------------- // // ---------------------------------------------------- //
@@ -310,11 +310,17 @@ class Tiler {
} }
if (this._isTileable(win)) { if (this._isTileable(win)) {
this.windows.push(win); if (this._settings.get_string('new-window-behavior') === 'master') {
this.windows.unshift(win);
} else {
this.windows.push(win);
}
const id = win.get_id(); const id = win.get_id();
this._signalIds.set(`unmanaged-${id}`, { object: win, id: win.connect('unmanaged', () => this._onWindowRemoved(null, win)) }); this._signalIds.set(`unmanaged-${id}`, { object: win, id: win.connect('unmanaged', () => this._onWindowRemoved(null, win)) });
this._signalIds.set(`size-changed-${id}`, { object: win, id: win.connect('size-changed', () => { if (!this.grabbedWindow) this.queueTile(); }) }); this._signalIds.set(`size-changed-${id}`, { object: win, id: win.connect('size-changed', () => { if (!this.grabbedWindow) this.queueTile(); }) });
this._signalIds.set(`minimized-${id}`, { object: win, id: win.connect('notify::minimized', this._onWindowMinimizedStateChanged) }); this._signalIds.set(`minimized-${id}`, { object: win, id: win.connect('notify::minimized', this._onWindowMinimizedStateChanged) });
this.queueTile(); this.queueTile();
} }
} }
+1 -1
View File
@@ -2,7 +2,7 @@
"uuid": "simple-tiling@domoel", "uuid": "simple-tiling@domoel",
"name": "Simple Tiling", "name": "Simple Tiling",
"description": "A Simple Tiling Extension for Gnome Shell 3.38.", "description": "A Simple Tiling Extension for Gnome Shell 3.38.",
"version": 2, "version": 3,
"shell-version": [ "3.38" ], "shell-version": [ "3.38" ],
"settings-schema": "org.gnome.shell.extensions.simple-tiling.domoel", "settings-schema": "org.gnome.shell.extensions.simple-tiling.domoel",
"preferences_ui": "prefs.js", "preferences_ui": "prefs.js",
+31 -5
View File
@@ -48,10 +48,10 @@ function buildPrefsWidget() {
store.set_column_types([ GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_INT ]); store.set_column_types([ GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_INT ]);
addKeybinding(store, settings, 'swap-master-window', 'Master-Fenster tauschen'); addKeybinding(store, settings, 'swap-master-window', 'Master-Fenster tauschen');
addKeybinding(store, settings, 'swap-left-window', 'Fenster nach links tauschen'); addKeybinding(store, settings, 'swap-left-window', 'Nach links tauschen');
addKeybinding(store, settings, 'swap-right-window', 'Fenster nach rechts tauschen'); addKeybinding(store, settings, 'swap-right-window', 'Nach rechts tauschen');
addKeybinding(store, settings, 'swap-up-window', 'Fenster nach oben tauschen'); addKeybinding(store, settings, 'swap-up-window', 'Nach oben tauschen');
addKeybinding(store, settings, 'swap-down-window', 'Fenster nach unten tauschen'); addKeybinding(store, settings, 'swap-down-window', 'Nach unten tauschen');
let treeView = new Gtk.TreeView({ model: store, headers_visible: false, hexpand: true, visible: true }); let treeView = new Gtk.TreeView({ model: store, headers_visible: false, hexpand: true, visible: true });
keysBox.add(treeView); keysBox.add(treeView);
@@ -92,7 +92,7 @@ function buildPrefsWidget() {
// ---------------------------------------------------- // // ---------------------------------------------------- //
// Section for Window Gaps // // Section for Window Gaps //
// ---------------------------------------------------- // // ---------------------------------------------------- //
const gapsTitle = new Gtk.Label({ label: '<b>Fensterabstände (Gaps)</b>', use_markup: true, halign: Gtk.Align.START, visible: true }); const gapsTitle = new Gtk.Label({ label: '<b>Abstände (Gaps)</b>', use_markup: true, halign: Gtk.Align.START, visible: true });
const gapsFrame = new Gtk.Frame({ label_widget: gapsTitle, shadow_type: Gtk.ShadowType.NONE, visible: true }); const gapsFrame = new Gtk.Frame({ label_widget: gapsTitle, shadow_type: Gtk.ShadowType.NONE, visible: true });
const gapsGrid = new Gtk.Grid({ margin: 12, column_spacing: 12, row_spacing: 12, visible: true }); const gapsGrid = new Gtk.Grid({ margin: 12, column_spacing: 12, row_spacing: 12, visible: true });
gapsFrame.add(gapsGrid); gapsFrame.add(gapsGrid);
@@ -102,16 +102,42 @@ function buildPrefsWidget() {
addSpinButtonRow(gapsGrid, settings, "Äußerer Abstand (vertikal)", "outer-gap-vertical", 2); addSpinButtonRow(gapsGrid, settings, "Äußerer Abstand (vertikal)", "outer-gap-vertical", 2);
prefsWidget.add(gapsFrame); prefsWidget.add(gapsFrame);
// ---------------------------------------------------- //
// Section for Window Behavior (Master vs. Stack) //
// ---------------------------------------------------- //
const behaviorTitle = new Gtk.Label({ label: '<b>Verhalten</b>', use_markup: true, halign: Gtk.Align.START, visible: true });
const behaviorFrame = new Gtk.Frame({ label_widget: behaviorTitle, shadow_type: Gtk.ShadowType.NONE, visible: true });
const behaviorGrid = new Gtk.Grid({ margin: 12, column_spacing: 12, row_spacing: 12, visible: true });
behaviorFrame.add(behaviorGrid);
const comboLabel = new Gtk.Label({ label: "Neues Fenster öffnen als", halign: Gtk.Align.START, visible: true });
behaviorGrid.attach(comboLabel, 0, 0, 1, 1);
const comboBox = new Gtk.ComboBoxText({ visible: true, halign: Gtk.Align.END });
comboBox.append('stack', 'Stack-Fenster (Standard)');
comboBox.append('master', 'Master-Fenster');
comboBox.set_active_id(settings.get_string('new-window-behavior'));
comboBox.connect('changed', () => {
settings.set_string('new-window-behavior', comboBox.get_active_id());
});
behaviorGrid.attach(comboBox, 1, 0, 1, 1);
prefsWidget.add(behaviorFrame);
return prefsWidget; return prefsWidget;
} }
function addKeybinding(model, settings, id, description) { function addKeybinding(model, settings, id, description) {
let [key, mods] = [0, 0]; let [key, mods] = [0, 0];
const strv = settings.get_strv(id); const strv = settings.get_strv(id);
if (strv && strv.length > 0 && strv[0]) { if (strv && strv.length > 0 && strv[0]) {
[key, mods] = Gtk.accelerator_parse(strv[0]); [key, mods] = Gtk.accelerator_parse(strv[0]);
} }
let iter = model.append(); let iter = model.append();
model.set(iter, model.set(iter,
[COLUMN_ID, COLUMN_DESC, COLUMN_KEY, COLUMN_MODS], [COLUMN_ID, COLUMN_DESC, COLUMN_KEY, COLUMN_MODS],
@@ -35,6 +35,12 @@
<default>10</default> <default>10</default>
<summary>Der Abstand zum linken und rechten Bildschirmrand.</summary> <summary>Der Abstand zum linken und rechten Bildschirmrand.</summary>
</key> </key>
<key name="new-window-behavior" type="s">
<default>'stack'</default>
<summary>Verhalten für neu geöffnete Fenster.</summary>
<description>Legt fest, ob ein neues Fenster als Master oder als Teil des Stacks hinzugefügt wird.</description>
</key>
</schema> </schema>
</schemalist> </schemalist>