This commit is contained in:
2023-05-15 00:23:01 +09:00
parent f2e2952d1d
commit c8b260fac9
4 changed files with 147 additions and 57 deletions

View File

@@ -11,7 +11,8 @@ const Indicator = Me.imports.sources.indicator;
class Extension {
constructor() {
this._state = new State.StateManager();
this._renderer = new Renderer.Renderer(this._state);
this._settings = ExtensionUtils.getSettings("org.gnome.shell.extensions.fairy");
this._renderer = new Renderer.Renderer(this._state, this._settings);
this._keybinds = new Keybinds.KeyboardManager(this._state, this._renderer);
this._indicator = new Indicator.Indicator(this._state, this._renderer);
}

View File

@@ -5,7 +5,7 @@ const { Adw, Gio, Gtk } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
function init() { }
function init() {}
function _createKeybind(settings, keybind) {
// TODO: Set the title to the gsettings's title.
@@ -16,7 +16,39 @@ function _createKeybind(settings, keybind) {
// settings.bind(keybind, listener, );
row.add_suffix(listener);
row.activable_widget = listener;
return row
return row;
}
function _createBool(settings, { title, key }) {
const row = new Adw.ActionRow({ title: title });
const toggle = new Gtk.Switch({
active: settings.get_boolean(key),
valign: Gtk.Align.CENTER,
});
settings.bind(key, toggle, "active", Gio.SettingsBindFlags.DEFAULT);
row.add_suffix(toggle);
row.activatable_widget = toggle;
return row;
}
function _createUint(settings, { title, key }) {
const row = new Adw.ActionRow({ title: title });
const input = new Gtk.SpinButton({
adjustment: new Gtk.Adjustment({
lower: 0,
upper: 100,
step_increment: 1,
value: settings.get_uint(key),
}),
});
settings.bind(key, input, "value", Gio.SettingsBindFlags.DEFAULT);
row.add_suffix(input);
row.activatable_widget = input;
return row;
}
function fillPreferencesWindow(window) {
@@ -26,25 +58,36 @@ function fillPreferencesWindow(window) {
const page = new Adw.PreferencesPage();
page.set_title("General");
const group = new Adw.PreferencesGroup();
page.add(group);
const row = new Adw.ActionRow({ title: "Show Layout Indicator" });
group.add(row);
const toggle = new Gtk.Switch({
active: settings.get_boolean("show-layout"),
valign: Gtk.Align.CENTER,
});
settings.bind(
"show-layout",
toggle,
"active",
Gio.SettingsBindFlags.DEFAULT
const general = new Adw.PreferencesGroup();
page.add(general);
general.add(
_createBool(settings, {
title: "Show Layout Indicator",
key: "show-layout",
})
);
row.add_suffix(toggle);
row.activatable_widget = toggle;
const gaps = new Adw.PreferencesGroup();
page.add(gaps);
gaps.add(
_createUint(settings, {
title: "Gap size",
key: "gap-size",
})
);
gaps.add(
_createUint(settings, {
title: "Outer gap size",
key: "outer-gap-size",
})
);
gaps.add(
_createBool(settings, {
title: "Smart gaps",
key: "smart-gaps",
})
);
const keybinds = new Adw.PreferencesPage();
keybinds.set_title("Keybinds");

View File

@@ -1,12 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema id="org.gnome.shell.extensions.fairy" path="/org/gnome/shell/extensions/fairy/">
<!-- Behavior things -->
<key type="s" name="default-layout">
<default>'tiling'</default>
<summary>Available: floating, tiling, monocle</summary>
</key>
<!-- Visual things -->
<key type="b" name="show-layout">
<default>true</default>
@@ -24,10 +18,15 @@
</key>
<key type="u" name="gap-size">
<default>4</default>
<default>10</default>
<summary> The size of the gap between windows in the workarea</summary>
</key>
<key type="u" name="outer-gap-size">
<default>20</default>
<summary> The size of the gap between windows and the edge of the monitor</summary>
</key>
<key type="b" name="smart-gaps">
<default>true</default>
<summary>True to hide gaps when there is a single window</summary>

View File

@@ -10,9 +10,15 @@ const Me = ExtensionUtils.getCurrentExtension();
var Renderer = GObject.registerClass(
class Renderer extends GObject.Object {
_init(state) {
_init(state, settings) {
super._init();
this._state = state;
this._settings = settings;
this.gaps = {
smart: true,
size: 10,
outerGaps: 20,
};
log("fairy init!");
}
@@ -23,6 +29,12 @@ var Renderer = GObject.registerClass(
enable() {
this._bindSignals();
this.gaps = {
smart: this._settings.get_boolean("smart-gaps"),
size: this._settings.get_uint("gap-size"),
outerGaps: this._settings.get_uint("outer-gap-size"),
};
for (const window of global.display.list_all_windows())
this.trackWindow(window);
@@ -69,8 +81,7 @@ var Renderer = GObject.registerClass(
// Wait until window actor is available
let waitForWindowId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
// Stop if the window doesn't exist anymore or the parent is gone
if (!window.get_workspace())
return GLib.SOURCE_REMOVE;
if (!window.get_workspace()) return GLib.SOURCE_REMOVE;
// Continue if there's no actor available yet
if (!windowActor) {
@@ -116,6 +127,8 @@ var Renderer = GObject.registerClass(
}
}
this._state.windows = [];
this._settings.disconnect("changed");
}
_bindSignals() {
@@ -123,7 +136,11 @@ var Renderer = GObject.registerClass(
global.display.connect("window-created", (_display, window) =>
this._waitForWindow(window, () => {
this.trackWindow(window);
this._state.focus(window);
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this._state.focus(window);
// Do not retrigger this idle.
return false;
});
this.renderForWindow(window);
})
),
@@ -135,8 +152,8 @@ var Renderer = GObject.registerClass(
global.workspace_manager.connect("active-workspace-changed", () => {
// Convert gnome workspaces to fairy's tags
const workspace = global.display
.get_workspace_manager()
.get_active_workspace_index();
.get_workspace_manager()
.get_active_workspace_index();
const tags = 0b1 << workspace;
log("Switch to tags", tags);
if (Meta.prefs_get_workspaces_only_on_primary()) {
@@ -150,6 +167,24 @@ var Renderer = GObject.registerClass(
}
}),
];
this._settings.connect("changed", (_, key) => {
log("Proprety changed", key);
switch (key) {
case "gap-size":
this.gaps.size = this._settings.get_uint(key);
this.renderAll();
break;
case "outer-gap-size":
this.gaps.outerGaps = this._settings.get_uint(key);
this.renderAll();
break;
case "smart-gaps":
this.gaps.smart = this._settings.get_boolean(key);
this.renderAll();
break;
}
});
}
/**
@@ -215,11 +250,11 @@ var Renderer = GObject.registerClass(
const tags = this._state.monitors[mon].tags;
// This retrieve the lower tag present in the tags set.
const tag = (tags & ~(tags - 1));
const tag = tags & ~(tags - 1);
if (tags !== tag) return;
// Retrieve the gnome workspace for the tag (inverse of 0b1 << tag)
const workspace = Math.log2(tag);
console.log("Switching to", tags, tag, workspace)
console.log("Switching to", tags, tag, workspace);
global.display
.get_workspace_manager()
@@ -255,10 +290,10 @@ var Renderer = GObject.registerClass(
.get_workspace_manager()
.get_active_workspace_index();
for (const window of this._state.render(mon, tags)) {
const windows = this._state.render(mon, tags);
for (const window of windows) {
if (window.handle.get_monitor() !== mon)
window.handle.move_to_monitor(mon);
// if (!(window.tags & 0b1 << workIdx) || window.currentWorkspace !== workIdx) {
if (window.handle.get_workspace().index() !== workIdx) {
// The window is visible because another tag as been bringed
// so we need to ask gnome to move windows (temporarly to the current workspace)
@@ -282,35 +317,47 @@ var Renderer = GObject.registerClass(
window.handle.maximize(Meta.MaximizeFlags.BOTH);
// Do not resize if maximizing to keep the overview tiled.
continue;
}
else window.handle.unmaximize(Meta.MaximizeFlags.BOTH);
} else window.handle.unmaximize(Meta.MaximizeFlags.BOTH);
}
// TODO: Add gaps
log(
"Rezing percent: ",
window.x,
window.y,
window.width,
window.height,
"Real values",
monGeo.x + (window.x * monGeo.width) / 100,
monGeo.y + (window.y * monGeo.height) / 100,
(window.width * monGeo.width) / 100,
(window.height * monGeo.height) / 100
);
let size = {
x: (window.x * monGeo.width) / 100,
y: (window.y * monGeo.height) / 100,
width: (window.width * monGeo.width) / 100,
height: (window.height * monGeo.height) / 100,
};
// let cmpWindow = window.handle.get_compositor_private();
// cmpWindow.remove_all_transitions();
if (this._state.monitors[mon].layout !== "monocle" && (windows.length > 1 || !this.gaps.smart))
size = this.addGaps(size, monGeo);
window.handle.move_resize_frame(
true,
monGeo.x + (window.x * monGeo.width) / 100,
monGeo.y + (window.y * monGeo.height) / 100,
(window.width * monGeo.width) / 100,
(window.height * monGeo.height) / 100
monGeo.x + size.x,
monGeo.y + size.y,
size.width,
size.height
);
}
}
addGaps(window, monGeo) {
const gapSize = this.gaps.size;
// Inner gaps are applied two times so to make outers the same visual size we 2x
const outerGaps = this.gaps.outerGaps * 2;
return {
...window,
x: window.x === 0 ? outerGaps : window.x + gapSize,
y: window.y === 0 ? outerGaps : window.y + gapSize,
width:
window.width -
(window.x === 0 ? outerGaps : gapSize) -
(window.x + window.width === monGeo.width ? outerGaps : gapSize),
height:
window.height -
(window.y === 0 ? outerGaps : gapSize) -
(window.y + window.height === monGeo.height ? outerGaps : gapSize),
};
}
}
);