54 Commits

Author SHA1 Message Date
Dome e6c8ef7f34 Update README.md 2026-04-21 11:59:34 +02:00
Dome 5b975187ba Update README.md 2026-04-12 22:13:25 +02:00
Dome fed6486932 Update README.md 2026-04-12 22:12:58 +02:00
Dome a7994f6742 Update README.md 2026-04-12 22:12:18 +02:00
Dome efd6bef0c4 Update README.md 2026-04-12 21:40:57 +02:00
Dome c9cbb56805 Update README.md 2026-04-12 21:40:04 +02:00
Dome d3fafa15ff add Zeitfresser Matrix Community Badge to readme.md 2026-04-12 21:32:51 +02:00
Dome 8db89fc155 Update Makefile 2025-10-11 22:22:35 +02:00
Dome 39e8a3541b Update enterprise.js 2025-10-11 22:12:59 +02:00
Dome 47f5a734be Update interim.js 2025-10-11 22:12:33 +02:00
Dome 1d5cdf480c Update modern.js 2025-10-11 22:12:13 +02:00
Dome 5f09053e06 Update enterprise.js 2025-10-01 16:44:20 +02:00
Dome 2295756f19 Update enterprise.js 2025-10-01 16:28:43 +02:00
Dome 58b4e746b6 Update interim.js 2025-10-01 16:28:03 +02:00
Dome e37cc5f8f4 Update legacy.js 2025-10-01 16:26:50 +02:00
Dome f10d3f0adf Update prefs_enterprise.js 2025-10-01 16:26:28 +02:00
Dome 528bf11371 Update prefs_interim.js 2025-10-01 16:26:02 +02:00
Dome 0598fa615d Update prefs_legacy.js 2025-10-01 16:25:45 +02:00
Dome 2e61ade64f Update prefs_modern.js 2025-10-01 16:25:02 +02:00
Dome 37e8a149f1 Update Makefile 2025-10-01 09:56:42 +02:00
Dome ef67c2d187 Update README.md 2025-10-01 09:47:02 +02:00
Dome 56ad942f24 Create prefs_enterprise.js 2025-10-01 09:43:12 +02:00
Dome ba04453c65 Create metadata_enterprise.json.in 2025-10-01 09:42:47 +02:00
Dome fd174e084e Create enterprise.js 2025-10-01 09:42:14 +02:00
Dome 6ade2e1520 Update Makefile 2025-10-01 09:41:35 +02:00
Dome b2099a6c1e Update metadata_interim.json.in 2025-09-30 17:10:30 +02:00
Dome 034bdcb05b Update Makefile 2025-09-29 20:08:56 +02:00
Dome 6d7acefed9 Update interim.js 2025-09-29 20:06:10 +02:00
Dome ef098d8986 Update modern.js 2025-09-29 09:39:12 +02:00
Dome 18d698cf7e Update interim.js 2025-09-29 09:15:19 +02:00
Dome 0aa80fda6a Update interim.js 2025-09-29 09:13:23 +02:00
Dome 7e51b5ff62 Update modern.js 2025-09-29 09:00:15 +02:00
Dome fe41ea8312 Update modern.js
fixes error "Fails on GNOME Shell 48.3 with TypeError get_session not a function" on modern.,js
2025-09-29 08:56:34 +02:00
Dome 5020250699 Update README.md 2025-09-28 23:33:32 +02:00
Dome 16688d6996 Update README.md 2025-09-28 23:17:24 +02:00
Dome 6b8ac746aa Update modern.js 2025-09-28 23:16:42 +02:00
Dome bcc5044cf8 Update prefs_modern.js 2025-09-28 23:15:56 +02:00
Dome e2df9fb038 Delete metadata_gnome45-48.json.in 2025-09-28 23:11:46 +02:00
Dome 5e23390911 Delete prefs_gnome45-48.js 2025-09-28 23:11:27 +02:00
Dome 7ba8dd1b0f Delete gnome45-48.js 2025-09-28 23:11:18 +02:00
Dome 849e2dc177 Update metadata_modern.json.in 2025-09-28 23:11:03 +02:00
Dome 982ca71642 Update modern.js 2025-09-28 23:10:43 +02:00
Dome a62c2307f9 Merge pull request #13 from ValerioCataldo/gnome49-comp
Gnome 49 compatibility
2025-09-28 20:21:56 +00:00
Dome b1c4924276 Rename metadata_modern,json.in to metadata_modern.json.in 2025-09-28 22:20:56 +02:00
Dome 73874fbd4b Rename prefs.interim.js to prefs_interim.js 2025-09-28 22:19:08 +02:00
valerio cataldo e4af31cb90 updating metadata 2025-09-27 13:26:15 +02:00
valerio cataldo b400189b4f split files 2025-09-27 13:23:26 +02:00
ValerioCataldo 568ceb7823 Merge branch 'Domoel:main' into gnome49-comp 2025-09-27 13:12:59 +02:00
valerio cataldo 138701a33d fixed for gnome49 2025-09-27 13:03:24 +02:00
Dome bbe09af89b Update interim.js 2025-08-22 12:37:08 +02:00
Dome 3331c84f31 Update Makefile 2025-08-22 12:34:32 +02:00
Dome 6591690c69 Update interim.js 2025-08-22 12:27:05 +02:00
Dome 40bea7a937 Update prefs_modern.js 2025-08-22 12:25:30 +02:00
Dome 4ea80d27bf Update README.md 2025-08-13 03:33:25 +00:00
13 changed files with 847 additions and 63 deletions
+39 -12
View File
@@ -1,22 +1,25 @@
############################################################################### ###############################################################################
# Simple-Tiling Makefile # Simple-Tiling Makefile
# #
# make build → Erzeugt alle drei Versionen als Archivdatei # make build → Erzeugt alle vier Versionen als Archivdatei
# make build-legacy → Erzeugt Legacy-ZIP (Shell 3.38) # make build-legacy → Erzeugt Legacy-ZIP (Shell 3.38)
# make build-interim → Erzeugt Interim-ZIP (Shell 40-44) # make build-enterprise → Erzeugt Enterprise-ZIP (Shell 40)
# make build-interim → Erzeugt Interim-ZIP (Shell 41-44)
# make build-modern → Erzeugt Modern-ZIP (Shell 45+) # make build-modern → Erzeugt Modern-ZIP (Shell 45+)
# make install-legacy → Installiert Legacy Extension # make install-legacy → Installiert Legacy Extension
# make install-enterprise → Installiert Enterprise Extension
# make install-interim → Installiert Interim Extension # make install-interim → Installiert Interim Extension
# make install-modern → Installiert Modern Extension # make install-modern → Installiert Modern Extension
# make clean → Bereinigt das Ausgangsverzeichnis # make clean → Bereinigt das Ausgangsverzeichnis
############################################################################### ###############################################################################
UUID := simple-tiling@domoel UUID := simple-tiling@domoel
VERSION := 7.1 VERSION := 7.6
EXTDIR := $(HOME)/.local/share/gnome-shell/extensions EXTDIR := $(HOME)/.local/share/gnome-shell/extensions
COMMON_FILES := prefs.js schemas exceptions.txt locale *.css README.md LICENSE COMMON_FILES := schemas exceptions.txt locale *.css README.md LICENSE
LEGACY_PREFS := prefs_legacy.js LEGACY_PREFS := prefs_legacy.js
ENTERPRISE_PREFS := prefs_enterprise.js
INTERIM_PREFS := prefs_interim.js INTERIM_PREFS := prefs_interim.js
MODERN_PREFS := prefs_modern.js MODERN_PREFS := prefs_modern.js
@@ -31,10 +34,10 @@ define copies
done done
endef endef
.PHONY: build build-legacy build-interim build-modern \ .PHONY: build build-legacy build-enterprise build-interim build-modern \
install-legacy install-interim install-modern clean install-legacy install-enterprise install-interim install-modern clean
build: build-legacy build-interim build-modern build: build-legacy build-enterprise build-interim build-modern
############################################################################### ###############################################################################
# Erzeugt Legacy-ZIP (Shell 3.38) # Erzeugt Legacy-ZIP (Shell 3.38)
@@ -54,10 +57,27 @@ build-legacy:
@echo "$(UUID)-legacy-v$(VERSION).zip created" @echo "$(UUID)-legacy-v$(VERSION).zip created"
############################################################################### ###############################################################################
# Erzeugt Interim-ZIP (Shell 40-44) # Erzeugt Enterprise-ZIP (Shell 40)
###############################################################################
build-enterprise:
@echo "==> Building ENTERPRISE zip (for GNOME 40)..."
@rm -rf build && mkdir -p build/$(UUID)
$(call copies,$(COMMON_FILES),build/$(UUID))
@glib-compile-schemas build/$(UUID)/schemas
@cp enterprise.js build/$(UUID)/extension.js
@cp $(ENTERPRISE_PREFS) build/$(UUID)/prefs.js
@sed -e "s/__UUID__/$(UUID)/g" \
-e "s/__VERSION__/$(VERSION)/g" \
metadata_enterprise.json.in > build/$(UUID)/metadata.json
@cd build && zip -qr ../$(UUID)-enterprise-v$(VERSION).zip .
@rm -rf build
@echo "$(UUID)-enterprise-v$(VERSION).zip created"
###############################################################################
# Erzeugt Interim-ZIP (Shell 41-44)
############################################################################### ###############################################################################
build-interim: build-interim:
@echo "==> Building INTERIM zip (for GNOME 40-44)..." @echo "==> Building INTERIM zip (for GNOME 41-44)..."
@rm -rf build && mkdir -p build/$(UUID) @rm -rf build && mkdir -p build/$(UUID)
$(call copies,$(COMMON_FILES),build/$(UUID)) $(call copies,$(COMMON_FILES),build/$(UUID))
@glib-compile-schemas build/$(UUID)/schemas @glib-compile-schemas build/$(UUID)/schemas
@@ -93,21 +113,28 @@ build-modern:
install-legacy: build-legacy install-legacy: build-legacy
@echo "==> Installing LEGACY Extension..." @echo "==> Installing LEGACY Extension..."
@rm -rf $(EXTDIR)/$(UUID) @rm -rf $(EXTDIR)/$(UUID)
@unzip -q $(UUID)-legacy-v$(VERSION).zip -d $(EXTDIR) @unzip -q $(UUID)-legacy-v$(VERSION).zip -d $(EXTDIR)/$(UUID)
@rm -f $(UUID)-legacy-v$(VERSION).zip @rm -f $(UUID)-legacy-v$(VERSION).zip
@echo "✓ Legacy Extension installed to $(EXTDIR)/$(UUID). Restart GNOME Shell to apply." @echo "✓ Legacy Extension installed to $(EXTDIR)/$(UUID). Restart GNOME Shell to apply."
install-enterprise: build-enterprise
@echo "==> Installing ENTERPRISE Extension..."
@rm -rf $(EXTDIR)/$(UUID)
@unzip -q $(UUID)-enterprise-v$(VERSION).zip -d $(EXTDIR)/$(UUID)
@rm -f $(UUID)-enterprise-v$(VERSION).zip
@echo "✓ Enterprise Extension installed to $(EXTDIR)/$(UUID). Restart GNOME Shell to apply."
install-interim: build-interim install-interim: build-interim
@echo "==> Installing INTERIM Extension..." @echo "==> Installing INTERIM Extension..."
@rm -rf $(EXTDIR)/$(UUID) @rm -rf $(EXTDIR)/$(UUID)
@unzip -q $(UUID)-interim-v$(VERSION).zip -d $(EXTDIR) @unzip -q $(UUID)-interim-v$(VERSION).zip -d $(EXTDIR)/$(UUID)
@rm -f $(UUID)-interim-v$(VERSION).zip @rm -f $(UUID)-interim-v$(VERSION).zip
@echo "✓ Interim Extension installed to $(EXTDIR)/$(UUID). Restart GNOME Shell to apply." @echo "✓ Interim Extension installed to $(EXTDIR)/$(UUID). Restart GNOME Shell to apply."
install-modern: build-modern install-modern: build-modern
@echo "==> Installing MODERN Extension..." @echo "==> Installing MODERN Extension..."
@rm -rf $(EXTDIR)/$(UUID) @rm -rf $(EXTDIR)/$(UUID)
@unzip -q $(UUID)-modern-v$(VERSION).zip -d $(EXTDIR) @unzip -q $(UUID)-modern-v$(VERSION).zip -d $(EXTDIR)/$(UUID)
@rm -f $(UUID)-modern-v$(VERSION).zip @rm -f $(UUID)-modern-v$(VERSION).zip
@echo "✓ Modern Extension installed to $(EXTDIR)/$(UUID). Restart GNOME Shell to apply." @echo "✓ Modern Extension installed to $(EXTDIR)/$(UUID). Restart GNOME Shell to apply."
+25 -7
View File
@@ -1,3 +1,8 @@
<p align="center">
<a href="https://ztfr.eu/matrix">
<img src="assets/community-badge.png" alt="Join Zeitfresser Matrix Community" height="70" />
</a>
</p>
<h1 align="center"> <h1 align="center">
Simple Tiling Simple Tiling
@@ -8,7 +13,16 @@ A lightweight, opinionated, and automatic tiling window manager for GNOME Shell
</span> </span>
<p> <p>
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) <h6 align="center">
<a href="https://ztfr.eu">🏰 Website</a>
·
<a href="https://ztfr.eu/matrix">📰 Zeitfresser Matrix Community</a>
·
<a href="https://social.ztfr.eu/@dome">🐘 Mastodon</a>
·
<a href="https://look.ztfr.eu/#/#support:ztfr.eu">💬 Supportchat</a>
</h6>
<br>
<img width="2560" height="1440" alt="Simple-Tiling-v6" src="https://github.com/user-attachments/assets/eb0f7cc3-6a5a-4036-8a1e-8f945c52e55c" /> <img width="2560" height="1440" alt="Simple-Tiling-v6" src="https://github.com/user-attachments/assets/eb0f7cc3-6a5a-4036-8a1e-8f945c52e55c" />
@@ -16,7 +30,7 @@ A lightweight, opinionated, and automatic tiling window manager for GNOME Shell
Simple Tiling is a GNOME Shell extension created for users who want a clean, predictable, and automatic tiling layout without the complexity of larger, more feature-heavy tiling extensions. It is designed to be simple to configure and intuitive to use, focusing on a core set of essential tiling features. Simple Tiling is a GNOME Shell extension created for users who want a clean, predictable, and automatic tiling layout without the complexity of larger, more feature-heavy tiling extensions. It is designed to be simple to configure and intuitive to use, focusing on a core set of essential tiling features.
This extension was built from the ground up to be stable and performant on **GNOME Shell 3.38**. However it is now also supporting modern gnome shells up to **version 48**. This extension was built from the ground up to be stable and performant on **GNOME Shell 3.38**. However it is now also supporting modern gnome shells up to **version 49**.
## Features ## Features
@@ -37,7 +51,7 @@ This extension was built from the ground up to be stable and performant on **GNO
Please note that this extension has been developed for a very specific environment. However, with the latest updates, I have ensured that modern Gnome Shells and Wayland are also supported. Please note that this extension has been developed for a very specific environment. However, with the latest updates, I have ensured that modern Gnome Shells and Wayland are also supported.
* **GNOME Shell Version:** **3.38 - 48** * **GNOME Shell Version:** **3.38 - 49**
* **Session Type:** **X11** (Wayland is still in beta but should be fine!). * **Session Type:** **X11** (Wayland is still in beta but should be fine!).
* **Monitor Setup:** **Single monitor only.** Multi-monitor support is not yet implemented. * **Monitor Setup:** **Single monitor only.** Multi-monitor support is not yet implemented.
@@ -49,7 +63,7 @@ Use the [GNOME Shell Extensions website](https://extensions.gnome.org/extension/
#### Manual Installation #### Manual Installation
The repository includes a Makefile that produces readytoinstall ZIP packages for the three supported GnomeShell lines (a legacy build for Gnome-Shell 3.38, an interim build for Gnome-Shell 40 - 44 and a modern build for Gnome-Shell 45+). The repository includes a Makefile that produces readytoinstall ZIP packages for the three supported GnomeShell lines (a legacy build for Gnome-Shell 3.38, an enterprise build for Gnome-Shell 40, an interim build for Gnome-Shell 41 - 44 and a modern build for Gnome-Shell 45+).
1. **Clone the Source** 1. **Clone the Source**
```bash ```bash
@@ -62,10 +76,11 @@ The repository includes a Makefile that produces readytoinstall ZIP packag
Open the Terminal within the Simple-Tiling directory and run Open the Terminal within the Simple-Tiling directory and run
```bash ```bash
make install-legacy # Installs Legacy Extension (Gnome-Shell 3.38) make install-legacy # Installs Legacy Extension (Gnome-Shell 3.38)
make install-interim # Installs Interim Extension (Gnome-Shell 40 - 44) make install-enterprise # Installs Enterprise Extension (Gnome-Shell 40)
make install-interim # Installs Interim Extension (Gnome-Shell 41 - 44)
make install-modern # Installs Modern Extension (Gnome-Shell 45+) make install-modern # Installs Modern Extension (Gnome-Shell 45+)
``` ```
**Note:** This command will directly install the extension in the choosen variant (legacy, interim or modern). If you want to manually create and upload the extension to your gnome extensions directory `(~/.local/share/gnome-shell/extensions)` you can just run `make build` to create all versions as .zip or `make build-legacy`, `make build-interim` or `make build-modern` to create them seperately as .zip. To enable them you need to unzip these archives and put them into your extensions directory. **Note:** This command will directly install the extension in the choosen variant (legacy, interim or modern). If you want to manually create and upload the extension to your gnome extensions directory `(~/.local/share/gnome-shell/extensions)` you can just run `make build` to create all versions as .zip or `make build-legacy`, `make build-enterprise`, `make build-interim` or `make build-modern` to create them seperately as .zip. To enable them you need to unzip these archives and put them into your extensions directory.
4. **Reload the shell** 4. **Reload the shell**
```bash ```bash
@@ -119,7 +134,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.
## Development & Support
If you need to get support or want to participate in the active development of this software, you can <a href="https://ztfr.eu/matrix">join our Zeitfresser Matrix Community</a> or the <a href="https://look.ztfr.eu/#/#support:ztfr.eu">Development & Support Channel</a> on Matrix.
## 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.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

+604
View File
@@ -0,0 +1,604 @@
////////////////////////////////////////////////////////////////
// Simple-Tiling ENTERPRISE (GNOME Shell 40 non-ESM) //
// © 2025 domoel MIT //
////////////////////////////////////////////////////////////////
// ── GLOBAL IMPORTS ───────────────────────────
const { Meta, Shell, Gio, GLib, Clutter } = imports.gi;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
// ── CONST ────────────────────────────────────────────
const WM_SCHEMA = 'org.gnome.desktop.wm.keybindings';
const TILING_DELAY_MS = 20; // Change Tiling Window Delay
const CENTERING_DELAY_MS = 5; // Change Centered Window Delay
const KEYBINDINGS = {
'swap-master-window': (self) => self._swapWithMaster(),
'swap-left-window': (self) => self._swapInDirection('left'),
'swap-right-window': (self) => self._swapInDirection('right'),
'swap-up-window': (self) => self._swapInDirection('up'),
'swap-down-window': (self) => self._swapInDirection('down'),
'focus-left': (self) => self._focusInDirection('left'),
'focus-right': (self) => self._focusInDirection('right'),
'focus-up': (self) => self._focusInDirection('up'),
'focus-down': (self) => self._focusInDirection('down'),
};
// ── HELPERFUNCTION ────────────────────────────────────────
function getPointerXY() {
if (global.get_pointer) {
const [x, y] = global.get_pointer();
return [x, y];
}
const ev = Clutter.get_current_event();
if (ev) {
const coords = ev.get_coords();
if (Array.isArray(coords))
return coords;
}
const device = Clutter.get_default_backend()
.get_default_seat()
.get_pointer();
return device ? device.get_position() : [0, 0];
}
// ── INTERACTIONHANDLER ───────────────────────────────────
class InteractionHandler {
constructor(tiler) {
this.tiler = tiler;
this._settings = this.tiler.settings;
this._wmSettings = new Gio.Settings({ schema: WM_SCHEMA });
this._wmKeysToDisable = [];
this._savedWmShortcuts = {};
this._grabOpIds = [];
this._settingsChangedId = null;
}
enable() {
this._prepareWmShortcuts();
if (this._wmKeysToDisable.length)
this._wmKeysToDisable.forEach(k =>
this._wmSettings.set_value(k, new GLib.Variant('as', [])));
this._bindAllShortcuts();
this._settingsChangedId =
this._settings.connect('changed', () => this._onSettingsChanged());
this._grabOpIds.push(
global.display.connect('grab-op-begin',
(_, __, win) => { if (this.tiler.windows.includes(win))
this.tiler.grabbedWindow = win; })
);
this._grabOpIds.push(
global.display.connect('grab-op-end', () => this._onGrabEnd())
);
}
disable() {
if (this._wmKeysToDisable.length)
this._wmKeysToDisable.forEach(k =>
this._wmSettings.set_value(k, this._savedWmShortcuts[k]));
this._unbindAllShortcuts();
if (this._settingsChangedId) {
this._settings.disconnect(this._settingsChangedId);
this._settingsChangedId = null;
}
this._grabOpIds.forEach(id => global.display.disconnect(id));
this._grabOpIds = [];
}
_bind(key, handler) {
Main.wm.addKeybinding(
key,
this._settings,
Meta.KeyBindingFlags.NONE,
Shell.ActionMode.NORMAL,
(..._args) => handler(this)
);
}
_bindAllShortcuts() { for (const [k,h] of Object.entries(KEYBINDINGS)) this._bind(k, h); }
_unbindAllShortcuts(){ for (const k in KEYBINDINGS) Main.wm.removeKeybinding(k); }
_onSettingsChanged() {
this._unbindAllShortcuts();
this._bindAllShortcuts();
}
_prepareWmShortcuts() {
const schema = this._wmSettings.settings_schema;
if (!schema) return;
const keys = [];
const add = key => { if (schema.has_key(key)) keys.push(key); };
if (schema.has_key('toggle-tiled-left'))
keys.push('toggle-tiled-left', 'toggle-tiled-right');
else {
add('tile-left'); add('tile-right');
}
if (schema.has_key('toggle-maximized'))
keys.push('toggle-maximized');
else {
add('maximize'); add('unmaximize');
}
if (keys.length) {
this._wmKeysToDisable = keys;
keys.forEach(k => this._savedWmShortcuts[k] =
this._wmSettings.get_value(k));
}
}
_focusInDirection(direction) {
const src = global.display.get_focus_window();
if (!src || !this.tiler.windows.includes(src)) return;
const tgt = this._findTargetInDirection(src, direction);
if (tgt) tgt.activate(global.get_current_time());
}
_swapWithMaster() {
const w = this.tiler.windows;
if (w.length < 2) return;
const foc = global.display.get_focus_window();
if (!foc || !w.includes(foc)) return;
const idx = w.indexOf(foc);
if (idx > 0) [w[0], w[idx]] = [w[idx], w[0]];
else [w[0], w[1]] = [w[1], w[0]];
this.tiler.tileNow();
w[0]?.activate(global.get_current_time());
}
_swapInDirection(direction) {
const src = global.display.get_focus_window();
if (!src || !this.tiler.windows.includes(src)) return;
let tgt = null;
const idx = this.tiler.windows.indexOf(src);
if (idx === 0 && direction==='right' && this.tiler.windows.length>1)
tgt = this.tiler.windows[1];
else
tgt = this._findTargetInDirection(src, direction);
if (!tgt) return;
const tidx = this.tiler.windows.indexOf(tgt);
[this.tiler.windows[idx], this.tiler.windows[tidx]] =
[this.tiler.windows[tidx], this.tiler.windows[idx]];
this.tiler.tileNow();
src.activate(global.get_current_time());
}
_findTargetInDirection(src, dir) {
const sRect = src.get_frame_rect(), cand=[];
for (const win of this.tiler.windows) {
if (win===src) continue;
const r=win.get_frame_rect();
if (dir==='left' && r.x<sRect.x) cand.push(win);
if (dir==='right'&& r.x>sRect.x) cand.push(win);
if (dir==='up' && r.y<sRect.y) cand.push(win);
if (dir==='down' && r.y>sRect.y) cand.push(win);
}
if (!cand.length) return null;
let best=null, min=Infinity;
for (const w of cand) {
const r=w.get_frame_rect();
const dev = (dir==='left'||dir==='right')
? Math.abs(sRect.y - r.y)
: Math.abs(sRect.x - r.x);
if (dev<min){min=dev; best=w;}
}
return best;
}
_onGrabEnd() {
const grabbed = this.tiler.grabbedWindow;
if (!grabbed) return;
const tgt = this._findTargetUnderPointer(grabbed);
if (tgt) {
const a = this.tiler.windows.indexOf(grabbed);
const b = this.tiler.windows.indexOf(tgt);
[this.tiler.windows[a], this.tiler.windows[b]] =
[this.tiler.windows[b], this.tiler.windows[a]];
}
this.tiler.queueTile();
this.tiler.grabbedWindow = null;
}
_findTargetUnderPointer(exclude) {
const [x,y] = getPointerXY();
const wins = global.get_window_actors()
.map(a=>a.meta_window)
.filter(w=>w && w!==exclude &&
this.tiler.windows.includes(w) && (()=>{const f=w.get_frame_rect();
return x>=f.x && x<f.x+f.width &&
y>=f.y && y<f.y+f.height;})());
if (wins.length) return wins[wins.length-1];
let best=null, max=0, sRect=exclude.get_frame_rect();
for (const w of this.tiler.windows) {
if (w===exclude) continue;
const r=w.get_frame_rect();
const ovX=Math.max(0, Math.min(sRect.x+sRect.width, r.x+r.width)-Math.max(sRect.x,r.x));
const ovY=Math.max(0, Math.min(sRect.y+sRect.height,r.y+r.height)-Math.max(sRect.y,r.y));
const area=ovX*ovY;
if (area>max){max=area; best=w;}
}
return best;
}
}
// ── TILER ────────────────────────────────────────────────
class Tiler {
constructor(extension) {
this._extension = extension;
this.settings = this._extension.getSettings();
this.windows = [];
this.grabbedWindow = null;
this._signalIds = new Map();
this._tileInProgress = false;
this._innerGap = this.settings.get_int('inner-gap');
this._outerGapVertical= this.settings.get_int('outer-gap-vertical');
this._outerGapHorizontal = this.settings.get_int('outer-gap-horizontal');
this._tilingDelay = TILING_DELAY_MS;
this._centeringDelay = CENTERING_DELAY_MS;
this._exceptions = [];
this._interactionHandler = new InteractionHandler(this);
this._tileTimeoutId = null;
this._centerTimeoutIds= [];
}
enable() {
this._loadExceptions();
this._workspaceManager = global.workspace_manager;
this._signalIds.set('workspace-changed', {
object: this._workspaceManager,
id: this._workspaceManager.connect('active-workspace-changed',
()=>this._onActiveWorkspaceChanged())
});
this._connectToWorkspace();
this._interactionHandler.enable();
this._signalIds.set('settings-changed', {
object: this.settings,
id: this.settings.connect('changed', ()=>this._onSettingsChanged())
});
}
disable() {
if (this._tileTimeoutId) {
GLib.source_remove(this._tileTimeoutId);
this._tileTimeoutId = null;
}
this._centerTimeoutIds.forEach(id=>GLib.source_remove(id));
this._centerTimeoutIds = [];
this._interactionHandler.disable();
this._disconnectFromWorkspace();
for (const [,sig] of this._signalIds) {
try { sig.object.disconnect(sig.id); } catch {}
}
this._signalIds.clear();
this.windows = [];
}
_onSettingsChanged() {
this._innerGap = this.settings.get_int('inner-gap');
this._outerGapVertical = this.settings.get_int('outer-gap-vertical');
this._outerGapHorizontal= this.settings.get_int('outer-gap-horizontal');
this.queueTile();
}
_loadExceptions() {
const file = Gio.File.new_for_path(this._extension.path + '/exceptions.txt');
if (!file.query_exists(null)) { this._exceptions=[]; return; }
const [ok,data] = file.load_contents(null);
if (!ok) { this._exceptions=[]; return; }
const txt = new TextDecoder('utf-8').decode(data);
this._exceptions = txt.split('\n')
.map(l=>l.trim())
.filter(l=>l && !l.startsWith('#'))
.map(l=>l.toLowerCase());
}
_isException(win) {
if (!win) return false;
const wmClass = (win.get_wm_class() || "").toLowerCase();
const appId = (win.get_gtk_application_id() || "").toLowerCase();
return this._exceptions.includes(wmClass) || this._exceptions.includes(appId);
}
_isTileable(win) {
return (
win &&
!win.minimized &&
!this._isException(win) &&
win.get_window_type() === Meta.WindowType.NORMAL
);
}
_centerWindow(win) {
const timeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
this._centeringDelay,
() => {
const index = this._centerTimeoutIds.indexOf(timeoutId);
if (index > -1) this._centerTimeoutIds.splice(index, 1);
if (!win || !win.get_display()) return GLib.SOURCE_REMOVE;
if (win.get_maximized())
win.unmaximize(Meta.MaximizeFlags.BOTH);
const monitorIndex = win.get_monitor();
const workspace = this._workspaceManager.get_active_workspace();
const workArea = workspace.get_work_area_for_monitor(
monitorIndex
);
const frame = win.get_frame_rect();
win.move_frame(
true,
workArea.x + Math.floor((workArea.width - frame.width) / 2),
workArea.y +
Math.floor((workArea.height - frame.height) / 2)
);
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
if (win.get_display()) {
if (typeof win.set_keep_above === "function")
win.set_keep_above(true);
else if (typeof win.make_above === "function")
win.make_above();
}
return GLib.SOURCE_REMOVE;
});
return GLib.SOURCE_REMOVE;
}
);
this._centerTimeoutIds.push(timeoutId);
}
_onWindowMinimizedStateChanged() {
this.queueTile();
}
_onWindowAdded(workspace, win) {
if (this.windows.includes(win)) return;
if (this._isException(win)) {
this._centerWindow(win);
return;
}
if (this._isTileable(win)) {
if (this.settings.get_string("new-window-behavior") === "master") {
this.windows.unshift(win);
} else {
this.windows.push(win);
}
const id = win.get_id();
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(`minimized-${id}`, {
object: win,
id: win.connect("notify::minimized", () =>
this._onWindowMinimizedStateChanged()
),
});
this.queueTile();
}
}
_onWindowRemoved(workspace, win) {
const index = this.windows.indexOf(win);
if (index > -1) this.windows.splice(index, 1);
["unmanaged", "size-changed", "minimized"].forEach((prefix) => {
const key = `${prefix}-${win.get_id()}`;
if (this._signalIds.has(key)) {
const { object, id } = this._signalIds.get(key);
try {
object.disconnect(id);
} catch (e) {}
this._signalIds.delete(key);
}
});
this.queueTile();
}
_onActiveWorkspaceChanged() {
this._disconnectFromWorkspace();
this._connectToWorkspace();
}
_connectToWorkspace() {
const workspace = this._workspaceManager.get_active_workspace();
workspace
.list_windows()
.forEach((win) => this._onWindowAdded(workspace, win));
this._signalIds.set("window-added", {
object: workspace,
id: workspace.connect("window-added", (ws, win) =>
this._onWindowAdded(ws, win)
),
});
this._signalIds.set("window-removed", {
object: workspace,
id: workspace.connect("window-removed", (ws, win) =>
this._onWindowRemoved(ws, win)
),
});
this.queueTile();
}
_disconnectFromWorkspace() {
this.windows.slice().forEach((win) => this._onWindowRemoved(null, win));
["window-added", "window-removed"].forEach((key) => {
if (this._signalIds.has(key)) {
const { object, id } = this._signalIds.get(key);
try {
object.disconnect(id);
} catch (e) {}
this._signalIds.delete(key);
}
});
}
queueTile() {
if (this._tileInProgress || this._tileTimeoutId) return;
this._tileInProgress = true;
this._tileTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
this._tilingDelay,
() => {
this._tileWindows();
this._tileInProgress = false;
this._tileTimeoutId = null;
return GLib.SOURCE_REMOVE;
}
);
}
tileNow() {
if (!this._tileInProgress) {
this._tileWindows();
}
}
_splitLayout(windows, area) {
if (windows.length === 0) return;
if (windows.length === 1) {
windows[0].move_resize_frame(
true,
area.x,
area.y,
area.width,
area.height
);
return;
}
const gap = Math.floor(this._innerGap / 2);
const primaryWindows = [windows[0]];
const secondaryWindows = windows.slice(1);
let primaryArea, secondaryArea;
if (area.width > area.height) {
const primaryWidth = Math.floor(area.width / 2) - gap;
primaryArea = {
x: area.x,
y: area.y,
width: primaryWidth,
height: area.height,
};
secondaryArea = {
x: area.x + primaryWidth + this._innerGap,
y: area.y,
width: area.width - primaryWidth - this._innerGap,
height: area.height,
};
} else {
const primaryHeight = Math.floor(area.height / 2) - gap;
primaryArea = {
x: area.x,
y: area.y,
width: area.width,
height: primaryHeight,
};
secondaryArea = {
x: area.x,
y: area.y + primaryHeight + this._innerGap,
width: area.width,
height: area.height - primaryHeight - this._innerGap,
};
}
this._splitLayout(primaryWindows, primaryArea);
this._splitLayout(secondaryWindows, secondaryArea);
}
_tileWindows() {
const windowsToTile = this.windows.filter((win) => !win.minimized);
if (windowsToTile.length === 0) return;
const monitor = Main.layoutManager.primaryMonitor;
const workspace = this._workspaceManager.get_active_workspace();
const workArea = workspace.get_work_area_for_monitor(monitor.index);
const innerArea = {
x: workArea.x + this._outerGapHorizontal,
y: workArea.y + this._outerGapVertical,
width: workArea.width - 2 * this._outerGapHorizontal,
height: workArea.height - 2 * this._outerGapVertical,
};
windowsToTile.forEach((win) => {
if (win.get_maximized()) win.unmaximize(Meta.MaximizeFlags.BOTH);
});
if (windowsToTile.length === 1) {
windowsToTile[0].move_resize_frame(
true,
innerArea.x,
innerArea.y,
innerArea.width,
innerArea.height
);
return;
}
const gap = Math.floor(this._innerGap / 2);
const masterWidth = Math.floor(innerArea.width / 2) - gap;
const master = windowsToTile[0];
master.move_resize_frame(
true,
innerArea.x,
innerArea.y,
masterWidth,
innerArea.height
);
const stackArea = {
x: innerArea.x + masterWidth + this._innerGap,
y: innerArea.y,
width: innerArea.width - masterWidth - this._innerGap,
height: innerArea.height,
};
this._splitLayout(windowsToTile.slice(1), stackArea);
}
}
// ── EXTENSIONWRAPPER ──────────────────────────
let tiler;
function enable() {
tiler = new Tiler(Me);
tiler.enable();
}
function disable() {
if (tiler) {
tiler.disable();
tiler = null;
}
}
+11 -9
View File
@@ -1,16 +1,17 @@
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// SimpleTiling  MODERN (GNOME Shell 40 - 44) // // SimpleTiling  INTERIM (GNOME Shell 41 - 44) //
// © 2025domoel  MIT // // © 2025domoel  MIT //
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// ── GLOBAL IMPORTS ──────────────────────────────────────── // ── GLOBAL IMPORTS ────────────────────────────────────────
import { Extension } from "resource:///org/gnome/shell/extensions/js/extensions/extension.js"; import Meta from 'gi://Meta';
import * as Main from "resource:///org/gnome/shell/ui/main.js"; import Shell from 'gi://Shell';
import Meta from "gi://Meta"; import Gio from 'gi://Gio';
import Shell from "gi://Shell"; import GLib from 'gi://GLib';
import Gio from "gi://Gio"; import Clutter from 'gi://Clutter';
import GLib from "gi://GLib"; import { Extension } from 'resource:///org/gnome/shell/extensions/js/extensions/extension.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
// ── CONST ──────────────────────────────────────────── // ── CONST ────────────────────────────────────────────
const WM_SCHEMA = 'org.gnome.desktop.wm.keybindings'; const WM_SCHEMA = 'org.gnome.desktop.wm.keybindings';
@@ -100,16 +101,17 @@ class InteractionHandler {
} }
_bind(key, handler) { _bind(key, handler) {
global.display.add_keybinding( Main.wm.addKeybinding(
key, key,
this._settings, this._settings,
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.ActionMode.NORMAL,
(..._args) => handler(this) (..._args) => handler(this)
); );
} }
_bindAllShortcuts() { for (const [k,h] of Object.entries(KEYBINDINGS)) this._bind(k, h); } _bindAllShortcuts() { for (const [k,h] of Object.entries(KEYBINDINGS)) this._bind(k, h); }
_unbindAllShortcuts(){ for (const k in KEYBINDINGS) global.display.remove_keybinding(k); } _unbindAllShortcuts(){ for (const k in KEYBINDINGS) Main.wm.removeKeybinding(k); }
_onSettingsChanged() { _onSettingsChanged() {
this._unbindAllShortcuts(); this._unbindAllShortcuts();
+13
View File
@@ -0,0 +1,13 @@
{
"uuid": "__UUID__",
"name": "Simple Tiling",
"description": "A Simple Tiling Extension for Gnome Shell.",
"version": __VERSION__,
"shell-version": [
"40"
],
"settings-schema": "org.gnome.shell.extensions.simple-tiling.domoel",
"preferences_ui": "prefs.js",
"url": "https://github.com/Domoel/Simple-Tiling",
"gettext-domain": "__UUID__"
}
-1
View File
@@ -4,7 +4,6 @@
"description": "A Simple Tiling Extension for Gnome Shell.", "description": "A Simple Tiling Extension for Gnome Shell.",
"version": __VERSION__, "version": __VERSION__,
"shell-version": [ "shell-version": [
"40",
"41", "41",
"42", "42",
"43", "43",
+2 -1
View File
@@ -7,7 +7,8 @@
"45", "45",
"46", "46",
"47", "47",
"48" "48",
"49"
], ],
"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",
+35 -7
View File
@@ -1,17 +1,18 @@
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// SimpleTiling  MODERN (GNOME Shell 45+) // // SimpleTiling  MODERN (GNOME Shell 45+) //
// © 2025domoel  MIT // // © 2025domoel  MIT //
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// ── GLOBAL IMPORTS ──────────────────────────────────────── // ── GLOBAL IMPORTS ────────────────────────────────────────
import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import Meta from 'gi://Meta'; import Meta from 'gi://Meta';
import Shell from 'gi://Shell'; import Shell from 'gi://Shell';
import Gio from 'gi://Gio'; import Gio from 'gi://Gio';
import GLib from 'gi://GLib'; import GLib from 'gi://GLib';
import Clutter from 'gi://Clutter'; import Clutter from 'gi://Clutter';
import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as Config from 'resource:///org/gnome/shell/misc/config.js';
// ── CONST ──────────────────────────────────────────── // ── CONST ────────────────────────────────────────────
const WM_SCHEMA = 'org.gnome.desktop.wm.keybindings'; const WM_SCHEMA = 'org.gnome.desktop.wm.keybindings';
@@ -31,6 +32,17 @@ const KEYBINDINGS = {
'focus-down': (self) => self._focusInDirection('down'), 'focus-down': (self) => self._focusInDirection('down'),
}; };
// ── VERSION CHECK ────────────────────────────────────────────
let shellVersion;
if (Shell.get_session) {
shellVersion = Shell.get_session().get_shell_version();
} else if (Config.PACKAGE_VERSION) {
shellVersion = Config.PACKAGE_VERSION;
} else {
shellVersion = global.shell_version;
}
const SHELL_MAJOR = parseInt(shellVersion.split('.')[0]);
// ── HELPERFUNCTION ──────────────────────────────────────── // ── HELPERFUNCTION ────────────────────────────────────────
function getPointerXY() { function getPointerXY() {
if (global.get_pointer) { if (global.get_pointer) {
@@ -101,16 +113,17 @@ class InteractionHandler {
} }
_bind(key, handler) { _bind(key, handler) {
global.display.add_keybinding( Main.wm.addKeybinding(
key, key,
this._settings, this._settings,
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.ActionMode.NORMAL,
(..._args) => handler(this) (..._args) => handler(this)
); );
} }
_bindAllShortcuts() { for (const [k,h] of Object.entries(KEYBINDINGS)) this._bind(k, h); } _bindAllShortcuts() { for (const [k,h] of Object.entries(KEYBINDINGS)) this._bind(k, h); }
_unbindAllShortcuts(){ for (const k in KEYBINDINGS) global.display.remove_keybinding(k); } _unbindAllShortcuts(){ for (const k in KEYBINDINGS) Main.wm.removeKeybinding(k); }
_onSettingsChanged() { _onSettingsChanged() {
this._unbindAllShortcuts(); this._unbindAllShortcuts();
@@ -347,8 +360,15 @@ class Tiler {
if (index > -1) this._centerTimeoutIds.splice(index, 1); if (index > -1) this._centerTimeoutIds.splice(index, 1);
if (!win || !win.get_display()) return GLib.SOURCE_REMOVE; if (!win || !win.get_display()) return GLib.SOURCE_REMOVE;
if (win.get_maximized()) if (SHELL_MAJOR < 49) {
if (win.get_maximized()) {
win.unmaximize(Meta.MaximizeFlags.BOTH); win.unmaximize(Meta.MaximizeFlags.BOTH);
}
} else {
if (win.is_maximized()) {
win.unmaximize();
}
}
const monitorIndex = win.get_monitor(); const monitorIndex = win.get_monitor();
const workspace = this._workspaceManager.get_active_workspace(); const workspace = this._workspaceManager.get_active_workspace();
@@ -558,7 +578,15 @@ class Tiler {
height: workArea.height - 2 * this._outerGapVertical, height: workArea.height - 2 * this._outerGapVertical,
}; };
windowsToTile.forEach((win) => { windowsToTile.forEach((win) => {
if (win.get_maximized()) win.unmaximize(Meta.MaximizeFlags.BOTH); if (SHELL_MAJOR < 49) {
if (win.get_maximized()) {
win.unmaximize(Meta.MaximizeFlags.BOTH);
}
} else {
if (win.is_maximized()) {
win.unmaximize();
}
}
}); });
if (windowsToTile.length === 1) { if (windowsToTile.length === 1) {
windowsToTile[0].move_resize_frame( windowsToTile[0].move_resize_frame(
+91
View File
@@ -0,0 +1,91 @@
//////////////////////////////////////////////////////////////////
// Simple-Tiling ENTERPRISE MENU (GNOME Shell 40 non-ESM) //
// © 2025 domoel MIT //
//////////////////////////////////////////////////////////////////
'use strict';
// ── GLOBAL IMPORTS ────────────────────────────────────────
const { Adw, Gio, Gtk, GLib } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const _ = ExtensionUtils.gettext;
function init() {
}
function buildPrefsWidget() {
const settings = ExtensionUtils.getSettings();
const page = new Adw.PreferencesPage();
// ── WINDOW GAPS ────────────────────────────────────────────
const groupGaps = new Adw.PreferencesGroup({ title: 'Window Gaps' });
page.add(groupGaps);
const rowInnerGap = new Adw.SpinRow({
title: 'Inner Gap',
subtitle: 'The gap between windows in pixels.',
adjustment: new Gtk.Adjustment({ lower: 0, upper: 100, step_increment: 1 }),
});
groupGaps.add(rowInnerGap);
settings.bind('inner-gap', rowInnerGap, 'value', Gio.SettingsBindFlags.DEFAULT);
const rowOuterH = new Adw.SpinRow({
title: 'Outer Gap (horizontal)',
subtitle: 'Left / right screen edges (pixels)',
adjustment: new Gtk.Adjustment({ lower: 0, upper: 100, step_increment: 1 }),
});
groupGaps.add(rowOuterH);
settings.bind('outer-gap-horizontal', rowOuterH, 'value', Gio.SettingsBindFlags.DEFAULT);
const rowOuterV = new Adw.SpinRow({
title: 'Outer Gap (vertical)',
subtitle: 'Top / bottom screen edges (pixels)',
adjustment: new Gtk.Adjustment({ lower: 0, upper: 100, step_increment: 1 }),
});
groupGaps.add(rowOuterV);
settings.bind('outer-gap-vertical', rowOuterV, 'value', Gio.SettingsBindFlags.DEFAULT);
// ── WINDOW BEHAVIOR ────────────────────────────────────────────
const groupBehavior = new Adw.PreferencesGroup({ title: 'Window Behavior' });
page.add(groupBehavior);
const rowNewWindow = new Adw.ComboRow({
title: 'Open new windows as',
subtitle: 'Whether a new window starts as Master or Stack',
model: new Gtk.StringList({
strings: ['Stack Window (Default)', 'Master Window'],
}),
});
groupBehavior.add(rowNewWindow);
const currentBehavior = settings.get_string('new-window-behavior');
rowNewWindow.selected = currentBehavior === 'master' ? 1 : 0;
rowNewWindow.connect('notify::selected', () => {
const newVal = rowNewWindow.selected === 1 ? 'master' : 'stack';
settings.set_string('new-window-behavior', newVal);
});
// ── KEYBINDINGS ────────────────────────────────────────────
const groupKeys = new Adw.PreferencesGroup({ title: 'Keybindings' });
page.add(groupKeys);
const rowKeys = new Adw.ActionRow({
title: 'Configure Shortcuts',
subtitle: 'Adjust all shortcuts in GNOME Keyboard settings.',
});
groupKeys.add(rowKeys);
const btnOpenKeyboard = new Gtk.Button({ label: 'Open Keyboard Settings' });
btnOpenKeyboard.connect('clicked', () => {
const appInfo = Gio.AppInfo.create_from_commandline(
'gnome-control-center keyboard', null, Gio.AppInfoCreateFlags.NONE
);
appInfo.launch([], null);
});
rowKeys.add_suffix(btnOpenKeyboard);
rowKeys.set_activatable_widget(btnOpenKeyboard);
return page;
}
+3 -2
View File
@@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// Simple-Tiling MODERN MENU (GNOME Shell 40-44) // // Simple-Tiling MODERN MENU (GNOME Shell 41-44) //
// © 2025 domoel MIT // // © 2025 domoel MIT //
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@@ -9,7 +9,8 @@ import Adw from 'gi://Adw';
import Gio from 'gi://Gio'; import Gio from 'gi://Gio';
import Gtk from 'gi://Gtk'; import Gtk from 'gi://Gtk';
import GLib from 'gi://GLib'; import GLib from 'gi://GLib';
import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/shell/extensions/js/extensions/prefs.js'; import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
export default class SimpleTilingPrefs extends ExtensionPreferences { export default class SimpleTilingPrefs extends ExtensionPreferences {
fillPreferencesWindow(window) { fillPreferencesWindow(window) {
+1 -1
View File
@@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// SimpleTiling  LEGACY MENU (GNOME Shell 3.38  44) // // SimpleTiling  LEGACY MENU (GNOME Shell 3.38) //
// © 2025domoel  MIT // // © 2025domoel  MIT //
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
+1 -1
View File
@@ -8,7 +8,7 @@ import Adw from 'gi://Adw';
import Gio from 'gi://Gio'; import Gio from 'gi://Gio';
import Gtk from 'gi://Gtk'; import Gtk from 'gi://Gtk';
import GLib from 'gi://GLib'; import GLib from 'gi://GLib';
import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/shell/extensions/prefs.js'; import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
export default class SimpleTilingPrefs extends ExtensionPreferences { export default class SimpleTilingPrefs extends ExtensionPreferences {
fillPreferencesWindow(window) { fillPreferencesWindow(window) {