-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathprefs_modern.js
More file actions
174 lines (150 loc) · 7.61 KB
/
Copy pathprefs_modern.js
File metadata and controls
174 lines (150 loc) · 7.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
///////////////////////////////////////////////////////////////
// Simple-Tiling – MODERN MENU (GNOME Shell 45+) //
// © 2025 domoel – MIT //
///////////////////////////////////////////////////////////////
// ── GLOBAL IMPORTS ────────────────────────────────────────
import Adw from 'gi://Adw';
import Gio from 'gi://Gio';
import Gtk from 'gi://Gtk';
import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
export default class SimpleTilingPrefs extends ExtensionPreferences {
fillPreferencesWindow(window) {
const settings = this.getSettings();
const page = new Adw.PreferencesPage();
window.add(page);
// ── WINDOW GAPS ────────────────────────────────────────────
const groupGaps = new Adw.PreferencesGroup({
title: 'Window Gaps',
description: 'Adjust spacing between windows and screen edges.'
});
page.add(groupGaps);
const rowInnerGap = new Adw.SpinRow({
title: 'Inner Gap',
subtitle: 'Space between tiled windows (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 rowMasterRatio = new Adw.SpinRow({
title: 'Master Window Width',
subtitle: 'Percentage of the work area (20–80 %)',
adjustment: new Gtk.Adjustment({ lower: 20, upper: 80, step_increment: 5 }),
});
groupBehavior.add(rowMasterRatio);
settings.bind('master-ratio', rowMasterRatio, 'value', Gio.SettingsBindFlags.DEFAULT);
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);
// ── EXCEPTIONS ─────────────────────────────────────────────
const groupExceptions = new Adw.PreferencesGroup({
title: 'Exceptions',
description: 'Apps excluded from tiling. To detect an app automatically: click 🔍, then click on the target window. Or type the WM_CLASS (X11) / App ID (Wayland) manually. Values are matched case-insensitively.',
});
page.add(groupExceptions);
const addRow = new Adw.EntryRow({ title: 'Add exception…' });
const detectBtn = new Gtk.Button({
icon_name: 'edit-find-symbolic',
valign: Gtk.Align.CENTER,
css_classes: ['flat', 'circular'],
tooltip_text: 'Detect last focused window',
});
addRow.add_prefix(detectBtn);
const addBtn = new Gtk.Button({
icon_name: 'list-add-symbolic',
valign: Gtk.Align.CENTER,
css_classes: ['flat', 'circular'],
});
addRow.add_suffix(addBtn);
const exceptionRows = [];
const refreshExceptions = () => {
exceptionRows.forEach(r => groupExceptions.remove(r));
exceptionRows.length = 0;
groupExceptions.remove(addRow);
for (const exc of settings.get_strv('exceptions')) {
const row = new Adw.ActionRow({ title: exc });
const btn = new Gtk.Button({
icon_name: 'list-remove-symbolic',
valign: Gtk.Align.CENTER,
css_classes: ['flat', 'circular'],
});
btn.connect('clicked', () => {
settings.set_strv('exceptions',
settings.get_strv('exceptions').filter(e => e !== exc));
});
row.add_suffix(btn);
groupExceptions.add(row);
exceptionRows.push(row);
}
groupExceptions.add(addRow);
};
refreshExceptions();
settings.connect('changed::exceptions', refreshExceptions);
detectBtn.connect('clicked', () => {
settings.set_boolean('pick-mode', true);
detectBtn.sensitive = false;
addRow.title = 'Click on a window…';
});
settings.connect('changed::pick-mode', () => {
if (!settings.get_boolean('pick-mode')) {
const appId = settings.get_string('last-focused-app-id');
const wmClass = settings.get_string('last-focused-wm-class');
addRow.text = appId || wmClass;
addRow.title = 'Add exception…';
detectBtn.sensitive = true;
}
});
addBtn.connect('clicked', () => {
const val = addRow.text.trim().toLowerCase();
if (!val) return;
const current = settings.get_strv('exceptions');
if (!current.includes(val))
settings.set_strv('exceptions', [...current, val]);
addRow.text = '';
});
}
}