Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7c72d06
set version to 17.3
domferr Jan 3, 2026
a285772
Update Italian translations in it.po (#466)
albanobattistella Jan 3, 2026
8f8bfc7
Updates German translation (de) (#448)
ChrisLauinger77 Jan 3, 2026
1286750
Update pl.po and tilingshell@ferrarodomenico.com.pot from source (#445)
alewicki95 Jan 3, 2026
efec8a2
po: Add Georgian translation (#457)
EkaterinePapava Jan 3, 2026
883fc91
Add files via upload (#453)
taijuin Jan 3, 2026
9156f12
add gresources support to preferences and create row for edge tiling …
domferr Jan 3, 2026
cbfb7a3
feat: add Wacom tablet support
domferr Jan 4, 2026
6769ac2
feat: reorder layouts
domferr Jan 4, 2026
882246f
feat: adds a settings panel and scheme for blacklist applications
kindingerlek Dec 18, 2025
39d5592
feat: expand settings for blacklisted apps
kindingerlek Dec 18, 2025
57f43bb
refact: rename from blacklist to custom rules
kindingerlek Dec 18, 2025
8c132b4
feat: integrate CustomRulesManager into TilingManager and extension i…
kindingerlek Dec 18, 2025
3587a34
feat: integrate CustomRulesManager into ResizingManager and TilingMan…
kindingerlek Dec 21, 2025
d8e29a0
feat: enhance CustomRulesManager with fullscreen default rule and ref…
kindingerlek Dec 23, 2025
a82c242
refact: rename CustomRulesApplicationConfig to ConfigRules and update…
kindingerlek Dec 23, 2025
5e9e20c
refact: remove broken accordion behavior implementation from TilingSh…
kindingerlek Dec 23, 2025
16f2ae5
refact: create a separated file for managing the custom application r…
kindingerlek Dec 23, 2025
5827567
refact: migrate from a collapse row to a modal, with better grouping …
kindingerlek Dec 23, 2025
f5621b6
feat: refactor custom application rules to use application IDs instea…
kindingerlek Dec 24, 2025
49ab3ba
refact: remove deadcoded
kindingerlek Jan 5, 2026
6b8acc8
feat: enhance import handling to support @ path aliases and improve e…
kindingerlek Jan 7, 2026
04cc230
feat: enhance import handling to support @ path aliases and improve r…
kindingerlek Jan 14, 2026
4d4231e
feat: update CustomRulesManager to register GObject class correctly a…
kindingerlek Jan 14, 2026
4f956c8
feat: Update Simplified Chinese Translation (#468)
lousuan Jan 17, 2026
5ab8d3e
feat: add sync layout option to snap assist (#469)
jessedhillon Jan 17, 2026
2edb7f3
Adaptive corner/edge snap (#323)
Gregorein Jan 17, 2026
745d2e2
chore: on GNOME 49+, use Meta.Monitor.get_display_name() (#470)
jessedhillon Jan 17, 2026
e7c07a2
fix: ensure the border is on top of the window
domferr Jan 17, 2026
10ad8a7
some readability improv
domferr Jan 17, 2026
2fea252
Merge branch 'v17.3' into feat/custom-rules
domferr Jan 17, 2026
036d40a
feat: raise all windows together
domferr Jan 17, 2026
6f06b2a
Merge branch 'v17.3' into feat/custom-rules
domferr Jan 17, 2026
dfcbbb7
fix: use quarters windows suggestions with default edge tiling
domferr Jan 17, 2026
aa96196
multiple refactoring for edge snapping
domferr Jan 17, 2026
64afeba
refactor: use Clutter.ModifierType as mask
domferr Jan 17, 2026
5990e44
fix: window borders scaling factor
domferr Jan 18, 2026
2d2d2c6
Merge branch 'v17.3' into feat/custom-rules
domferr Jan 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 67 additions & 7 deletions esbuild.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import types from '@babel/types';
import traverseBabel from '@babel/traverse';
import generatorBabel from '@babel/generator';
import { ESLint } from "eslint";
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const traverse = traverseBabel.default;
const generator = generatorBabel.default;
Expand Down Expand Up @@ -56,8 +60,9 @@ function init(meta) {
const prefsBanner = `// For GNOME Shell version before 45
const Me = imports.misc.extensionUtils.getCurrentExtension();
class ExtensionPreferences {
constructor(metadata) {
constructor(metadata, path) {
this.metadata = metadata;
this.path = path;
}

getSettings() {
Expand All @@ -73,7 +78,7 @@ function init() {

function fillPreferencesWindow(window) {
const metadata = imports.misc.extensionUtils.getCurrentExtension().metadata;
const prefs = new TilingShellExtensionPreferences(metadata);
const prefs = new TilingShellExtensionPreferences(metadata, Me.dir.get_path());
prefs.fillPreferencesWindow(window);
}
`;
Expand All @@ -88,11 +93,35 @@ async function preprocess(files) {
// drop lines tagged with "// @esbuild-drop-next-line"
text = text.replace(/\/\/\s*@esbuild-drop-next-line\s*\n.*?;/gs, '');

// Convert @ path aliases to relative imports
text = text.replace(
/import\s+([\s\S]*?)\s+from\s+['"]@([^'"]+)['"]/g,
(_match, imports, aliasPath) => {
// Remove .js extension if present for resolution
aliasPath = aliasPath.replace(/\.js$/, '');

// Replace dots with slashes to handle paths like @gi.prefs -> gi/prefs
aliasPath = aliasPath.replace(/\./g, '/');

// Calculate relative path from current file to src/<aliasPath>
const currentFileDir = path.dirname(filename);
const targetPath = path.resolve(__dirname, distDir, aliasPath);
let relativePath = path.relative(currentFileDir, targetPath).replace(/\\/g, '/');

// Ensure relative path starts with ./ or ../
if (!relativePath.startsWith('.')) {
relativePath = './' + relativePath;
}

return `import ${imports} from "${relativePath}.js"`;
}
);

// Ensure every import has ".js" at end end, excluding GJS imports
text = text.replace(
/import\s+([\s\S]*?)\s+from\s+['"]([^'"]+)['"]/g,
(_match, imports, importPath) => {
if (!importPath.endsWith('.js') && !importPath.startsWith('gi://')) {
if (!importPath.endsWith('.js') && !importPath.startsWith('gi://') && !importPath.startsWith('resource://')) {
importPath += '.js';
}
return `import ${imports} from "${importPath}"`;
Expand Down Expand Up @@ -198,13 +227,36 @@ function convertImports(text, currentFilePath, rootDirName) {
// replace import of Config
text = text.replaceAll('import * as Config from "resource:///org/gnome/Shell/Extensions/js/misc/config.js";', "const Config = imports.misc.config;");

// handle @ path aliases (convert to relative imports)
text = text.replace(
/import\s+(?:\{([^}]+)\}|([^\s]+))\s+from\s+"@([^"]+)";/gm,
(match, destructured, single, aliasPath) => {
// Remove .js extension if present
aliasPath = aliasPath.replace(/\.js$/, '');

// Convert @ alias to Me.imports path
const modulePath = aliasPath.replace(/\//g, '.');

if (destructured) {
return destructured
.split(',')
.map(i => i.trim())
.filter(Boolean)
.map(v => `const ${v} = Me.imports.${modulePath}.${v};`)
.join('\n');
} else {
return `const ${single} = Me.imports.${modulePath}.${single};`;
}
}
);

// handle relative imports
const relativeCurrent = currentFilePath.replace(
new RegExp(`^${rootDirName}[\\\\/]`), ''
);

text = text.replace(
/import\s+(?:\{([\s\S]+?)\}|([^\s]+))\s+from\s+"([\.]{1,2}\/[^"]+)";/gm,
/import\s+(?:\{([^}]+)\}|([^\s]+))\s+from\s+"(\.{1,2}\/[^"]+)";/gm,
(_, destructured, single, importPath) => {
const currentAbs = path.resolve(rootDirName, relativeCurrent);
const fullPath = path.resolve(path.dirname(currentAbs), importPath).replace(/\.(js|ts)$/, '');
Expand Down Expand Up @@ -278,8 +330,9 @@ function printError(text) {

async function processLegacyFiles(files) {
await Promise.all(files.map(async (filePath) => {
const jsFileContent = await fs.readFile(filePath, 'utf-8');
const convertedContent = convertImports(jsFileContent, filePath, distLegacyDir);
try {
const jsFileContent = await fs.readFile(filePath, 'utf-8');
const convertedContent = convertImports(jsFileContent, filePath, distLegacyDir);

// append banners
let finalContent;
Expand All @@ -296,13 +349,18 @@ async function processLegacyFiles(files) {
}

await fs.writeFile(filePath, finalContent, 'utf-8');
} catch (error) {
console.error(`\x1b[31mError processing file: ${filePath}\x1b[0m`);
console.error(error);
throw error;
}
}));
}

// build extension
build({
logLevel: "info",
entryPoints: ['src/**/*.ts', 'src/styles/stylesheet.scss', 'src/prefs.ts'],
entryPoints: ['src/**/*.ts', 'src/styles/stylesheet.scss', 'src/styles/prefs.scss', 'src/prefs.ts'],
outdir: distDir,
bundle: false,
treeShaking: false,
Expand All @@ -319,6 +377,8 @@ build({
// Post-build sync steps
fsSync.renameSync(path.resolve(distDir, "styles/stylesheet.css"), path.resolve(distDir, "stylesheet.css"));
fsSync.cpSync(resourcesDir, distDir, { recursive: true });
fsSync.renameSync(path.resolve(distDir, "styles/prefs.css"), path.resolve(distDir, "prefs.css"));
fsSync.cpSync(resourcesDir, distDir, { recursive: true });

// preprocess extension files in parallel
console.log(" 🛠️ ", "Preprocessing extension files...");
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
{
"name": "tilingshell",
"version": "17.2",
"version": "17.3",
"author": "Domenico Ferraro <ferraro.domenico125@gmail.com>",
"private": true,
"license": "GPL v2.0",
"scripts": {
"build": "npm run clean && node esbuild.mjs && npm run build:schema",
"build": "npm run clean && node esbuild.mjs && npm run build:schema && npm run build:resources",
"clean": "rm -rf dist; rm -rf dist_legacy",
"update-translations": "npm run create:translations && npm run merge:translations && npm run build:translations",
"build:schema": "npm run clean:schema && glib-compile-schemas ./resources/schemas --targetdir=./dist/schemas/ && cp ./dist/schemas/ ./dist_legacy/ -r",
"build:resources": "npm run clean:resources && glib-compile-resources --sourcedir=./resources --target=./dist/resources.gresource ./resources/resources.gresource.xml && cp ./dist/*.gresource ./dist_legacy/ -r",
"clean:schema": "rm -rf ./dist/schemas/*.compiled; rm -rf ./dist_legacy/schemas/*.compiled",
"clean:resources": "rm -rf ./dist/*.gresource; rm -rf ./dist_legacy/*.gresource",
"build:package": "npm run clean:package; npm run build && cd ./dist && zip -qr ../tilingshell@ferrarodomenico.com.zip * && cd ../dist_legacy && zip -qr ../GNOME.42-44.tilingshell@ferrarodomenico.com.zip *",
"clean:package": "rm -rf './dist/tilingshell@ferrarodomenico.com.zip'; rm -rf './dist_legacy/tilingshell@ferrarodomenico.com.zip'",
"install:extension": "mkdir -p ~/.local/share/gnome-shell/extensions/tilingshell@ferrarodomenico.com && cp ./dist$([ $(gnome-shell --version | grep -o -E '[0-9]+' | head -n 1) -le 44 ] && echo '_legacy')/* ~/.local/share/gnome-shell/extensions/tilingshell@ferrarodomenico.com/ -r",
Expand Down
8 changes: 8 additions & 0 deletions resources/icons/chevron-left-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions resources/icons/chevron-right-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions resources/icons/edge-adaptive-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions resources/icons/edge-default-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions resources/icons/edge-granular-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified resources/locale/cs/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/de/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/es/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/fr/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/it/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file added resources/locale/ka/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/nl/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/pl/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/pt_BR/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/ru/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/tr/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/uk/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/zh_CN/LC_MESSAGES/tilingshell.mo
Binary file not shown.
Binary file modified resources/locale/zh_TW/LC_MESSAGES/tilingshell.mo
Binary file not shown.
2 changes: 1 addition & 1 deletion resources/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"49"
],
"version": 99,
"version-name": "17.2",
"version-name": "17.3",
"url": "https://github.com/domferr/tilingshell",
"settings-schema": "org.gnome.shell.extensions.tilingshell",
"gettext-domain": "tilingshell",
Expand Down
8 changes: 8 additions & 0 deletions resources/resources.gresource.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Shell/Extensions/tilingshell">
<file preprocess="xml-stripblanks">icons/edge-adaptive-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/edge-default-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/edge-granular-symbolic.svg</file>
</gresource>
</gresources>
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
<summary>Enable snap assist</summary>
<description>Move the window on top of the screen to snap assist it.</description>
</key>
<key name="snap-assist-sync-layout" type="b">
<default>false</default>
<summary>Sync layout when tiling with Snap Assistant</summary>
<description>Change the desktop layout to match the layout used when tiling a window with Snap Assistant.</description>
</key>
<key name="show-indicator" type="b">
<default>true</default>
<summary>Shows indicator</summary>
Expand Down Expand Up @@ -102,6 +107,11 @@
<summary>Enable auto tiling</summary>
<description>Automatically tile a new window to the best tile according to the current layout.</description>
</key>
<key name="raise-together" type="b">
<default>false</default>
<summary>Raise tiled windows together</summary>
<description>When one tiled window is raised, raise all tiled windows into the foreground together.</description>
</key>
<key name="overridden-settings" type="s">
<default>'{}'</default>
<summary>Overridden settings</summary>
Expand Down Expand Up @@ -189,8 +199,17 @@
</key>
<key name="enable-screen-edges-windows-suggestions" type="b">
<default>false</default>
<summary>Enable window suggestions for screen edge snapping</summary>
<description>Suggests windows to occupy empty tiles when snapping to screen edges.</description>
<summary>Enable window suggestions for screen edge tiling</summary>
<description>Suggests windows to occupy empty tiles when tiling to screen edges.</description>
</key>
<key name="application-custom-rules" type="s">
<default>'[]'</default>
<summary>Application custom rules</summary>
<description>List of applications with custom feature settings (custom border, tiling, snap to border).</description>
<key name="edge-tiling-mode" type="s">
<default>'default'</default>
<summary>Edge tiling behavior</summary>
<description>Controls how windows snap to screen edges:\n'default' (corners snap to quarters, edges to halves),\n'adaptive' (snap to layout tiles by column),\n'granular' (snap to exact tile under cursor).</description>
</key>

<!-- keybindings -->
Expand Down
Loading