mirror of
https://github.com/zoriya/fairy.git
synced 2025-12-06 05:36:09 +00:00
wip: Add multi monitor support
This commit is contained in:
@@ -14,7 +14,7 @@ class Extension {
|
||||
this._state = new State.StateManager();
|
||||
this._settings = ExtensionUtils.getSettings("org.gnome.shell.extensions.fairy");
|
||||
|
||||
this._border = new Border.BorderManager(this._state);
|
||||
this._border = new Border.BorderManager(this._state, this._settings);
|
||||
this._indicator = new Indicator.Indicator(this._state, this._renderer, this._keybinds);
|
||||
this._renderer = new Renderer.Renderer(this._state, this._settings, this._indicator, this._border);
|
||||
this._keybinds = new Keybinds.KeyboardManager(this._state, this._renderer, this._indicator);
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<default>true</default>
|
||||
<summary>Should the cursor warp to newly focused windows</summary>
|
||||
</key>
|
||||
<key type="b" name="single-tagset">
|
||||
<default>false</default>
|
||||
<summary>Should tag be shared between monitors</summary>
|
||||
</key>
|
||||
|
||||
<!-- Visual things -->
|
||||
<key type="b" name="show-layout">
|
||||
|
||||
@@ -25,6 +25,7 @@ var Indicator = GObject.registerClass(
|
||||
floating: Gio.icon_new_for_string(`${Me.path}/icons/floating.svg`),
|
||||
deck: Gio.icon_new_for_string(`${Me.path}/icons/deck.svg`),
|
||||
};
|
||||
this._destroyed = true;
|
||||
}
|
||||
|
||||
endInit(ext) {
|
||||
@@ -34,7 +35,6 @@ var Indicator = GObject.registerClass(
|
||||
this._keybinds = ext._keybinds;
|
||||
}
|
||||
|
||||
|
||||
_createSelectableItem(title, cb) {
|
||||
const menuItem = new PopupMenu.PopupMenuItem(title, {});
|
||||
menuItem.connect("activate", cb);
|
||||
@@ -142,7 +142,8 @@ var Indicator = GObject.registerClass(
|
||||
const tag = 0b1 << tagNbr;
|
||||
const active = state.tags & tag;
|
||||
const hasWindow =
|
||||
this._state.windows.find((x) => x.tags & tag) !== undefined;
|
||||
this._state.windows.find((x) => x.monitor == mon && x.tags & tag) !==
|
||||
undefined;
|
||||
if (!active && !hasWindow) continue;
|
||||
const style = "width: 30px;";
|
||||
const tagBtn = new St.Button({
|
||||
|
||||
@@ -164,8 +164,13 @@ var KeyboardManager = GObject.registerClass(
|
||||
const mon = global.display.get_current_monitor();
|
||||
|
||||
let takkenTags = 0;
|
||||
for (let i = 0; i < this._state.monitors.length; i++)
|
||||
if (this._state.sharedTagset) {
|
||||
for (let i = 0; i < global.display.get_n_monitors(); i++)
|
||||
takkenTags |= this._state.monitors[i].tags;
|
||||
}
|
||||
else {
|
||||
takkenTags = ~0;
|
||||
}
|
||||
|
||||
this._state.monitors[mon].tags |= ~takkenTags;
|
||||
this._renderer.render(mon);
|
||||
|
||||
@@ -41,6 +41,7 @@ var Renderer = GObject.registerClass(
|
||||
outerGaps: this._settings.get_uint("outer-gap-size"),
|
||||
};
|
||||
this.warpEnabled = this._settings.get_boolean("warp-cursor");
|
||||
this._state.singleTagset = this._settings.get_boolean("single-tagset");
|
||||
|
||||
for (const window of global.display.list_all_windows())
|
||||
this.trackWindow(window);
|
||||
@@ -50,9 +51,14 @@ var Renderer = GObject.registerClass(
|
||||
.get_active_workspace_index();
|
||||
const tags = 0b1 << workspace;
|
||||
if (Meta.prefs_get_workspaces_only_on_primary()) {
|
||||
this._state.monitors[global.display.get_primary_monitor()].tags = tags;
|
||||
const primaryMon = global.display.get_primary_monitor();
|
||||
this._state.monitors[primaryMon].tags = tags;
|
||||
for (let i = 0; i < global.display.get_n_monitors(); i++) {
|
||||
if (primaryMon === i) continue;
|
||||
this._state.monitors[i].tags = 0b1 << i;
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < this._state.monitors.length; i++)
|
||||
for (let i = 0; i < global.display.get_n_monitors(); i++)
|
||||
this._state.monitors[i].tags = tags;
|
||||
}
|
||||
|
||||
@@ -148,9 +154,13 @@ var Renderer = GObject.registerClass(
|
||||
this._indicator.update();
|
||||
})
|
||||
),
|
||||
// global.display.connect("window-entered-monitor", (_display, monitor, window) => {
|
||||
//
|
||||
// }),
|
||||
global.display.connect("window-entered-monitor", (_display, _monitor, handle) => {
|
||||
const [oldW, newW] = this._state.updateByHandle(handle);
|
||||
log("Monitor changed for window", oldW.handle.get_title(), oldW.monitor, "to", newW.monitor);
|
||||
if (oldW) this.render(oldW.monitor);
|
||||
if (newW) this.render(newW.monitor);
|
||||
this._indicator.update();
|
||||
}),
|
||||
];
|
||||
this._workspaceSignals = [
|
||||
global.workspace_manager.connect("active-workspace-changed", () => {
|
||||
@@ -164,7 +174,7 @@ var Renderer = GObject.registerClass(
|
||||
const primaryMon = global.display.get_primary_monitor();
|
||||
this.setTags(primaryMon, tags);
|
||||
} else {
|
||||
for (let i = 0; i < this._state.monitors.length; i++) {
|
||||
for (let i = 0; i < global.display.get_n_monitors(); i++) {
|
||||
this._state.monitors[i].tags = tags;
|
||||
const focusedWindow = this._state.windows.find(
|
||||
(x) => x.handle === this._state.monitors[i].focused
|
||||
@@ -196,6 +206,16 @@ var Renderer = GObject.registerClass(
|
||||
case "warp-cursor":
|
||||
this.warpEnabled = this._settings.get_boolean(key);
|
||||
break;
|
||||
case "single-tagset":
|
||||
this._state.singleTagset = this._settings.get_boolean(key);
|
||||
const primaryMon = global.display.get_primary_monitor();
|
||||
for (let i = 0; i < global.display.get_n_monitors(); i++) {
|
||||
if (i === primaryMon) continue;
|
||||
this._state.monitors[i].tags = 0b1 << i;
|
||||
}
|
||||
this.renderAll();
|
||||
this._indicator.update();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -233,13 +253,13 @@ var Renderer = GObject.registerClass(
|
||||
this._indicator.update();
|
||||
}),
|
||||
handle.connect("workspace-changed", (handle) => {
|
||||
log("Workspace changed for window");
|
||||
if (handle._ignoreWorkspaceChange) {
|
||||
handle._ignoreWorkspaceChange = false;
|
||||
return;
|
||||
}
|
||||
if (!this._isValidWindow(handle)) return;
|
||||
const [oldW, newW] = this._state.updateByHandle(handle);
|
||||
log("Workspace changed for window", oldW.handle.get_title(), oldW.tags, "to", newW.tags);
|
||||
if (oldW) this.render(oldW.monitor);
|
||||
if (newW) this.render(newW.monitor);
|
||||
this._indicator.update();
|
||||
@@ -306,7 +326,8 @@ var Renderer = GObject.registerClass(
|
||||
this._state.monitors[mon].tags = tags;
|
||||
this._setGWorkspaceIfNeeded(mon);
|
||||
|
||||
for (let i = 0; i < this._state.monitors.length; i++) {
|
||||
if (this._state.singleTagset) {
|
||||
for (let i = 0; i < global.display.get_n_monitors(); i++) {
|
||||
if (this._state.monitors[i] & tags && mon !== i) {
|
||||
// Remove the selected tag from other monitors.
|
||||
// If the other monitor had only this tag, swap monitor's tags instead.
|
||||
@@ -315,6 +336,7 @@ var Renderer = GObject.registerClass(
|
||||
this.render(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.render(mon);
|
||||
this._indicator.update(mon);
|
||||
|
||||
@@ -25,6 +25,8 @@ var StateManager = GObject.registerClass(
|
||||
mfact: 55,
|
||||
}));
|
||||
|
||||
this.sharedTagset = false;
|
||||
|
||||
// The currently focused monitor.
|
||||
this.focusedMon = 0;
|
||||
|
||||
@@ -40,9 +42,8 @@ var StateManager = GObject.registerClass(
|
||||
*/
|
||||
_windowFromHandle(handle) {
|
||||
const mon = handle.get_monitor();
|
||||
const tags = handle.on_all_workspaces
|
||||
? ~0
|
||||
: 0b1 << handle.get_workspace().index();
|
||||
const tags = this.monitors[mon].tags;
|
||||
log("New window", handle.get_title(), "Monitor", mon, "tags", tags);
|
||||
return {
|
||||
handle,
|
||||
monitor: mon,
|
||||
@@ -58,13 +59,13 @@ var StateManager = GObject.registerClass(
|
||||
newWindow(handle) {
|
||||
const window = this._windowFromHandle(handle);
|
||||
this.monitors[window.monitor].beforeZoom = null;
|
||||
log("New window on tag", window.tags);
|
||||
log("New window on tag", window.tags, "monitor", window.monitor);
|
||||
this.windows.unshift(window);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Meta.Window} handle
|
||||
* @returns {[FairyWindow, FairyWindow]} [old, new]
|
||||
* @returns {[Fairyit worked, but recent update caused it to go bad, i literally updated today and it broke, now i need to see what package broke itWindow, FairyWindow]} [old, new]
|
||||
*/
|
||||
updateByHandle(handle) {
|
||||
const i = this.windows.findIndex((x) => x.handle === handle);
|
||||
@@ -89,7 +90,9 @@ var StateManager = GObject.registerClass(
|
||||
*/
|
||||
workIndex(mon, tags, idx) {
|
||||
const windows = this.windows.filter(
|
||||
(x) => x.monitor === mon && x.tags & tags
|
||||
this.singleTagset
|
||||
? (x) => x.tags & tags
|
||||
: (x) => x.monitor === mon && x.tags & tags
|
||||
);
|
||||
if (idx < 0) idx = windows.length + idx;
|
||||
return windows[idx % windows.length];
|
||||
@@ -102,7 +105,9 @@ var StateManager = GObject.registerClass(
|
||||
workIndexByHandle(handle) {
|
||||
const window = this.windows.find((x) => x.handle === handle);
|
||||
const windows = this.windows.filter(
|
||||
(x) => x.monitor === window.monitor && x.tags & window.tags
|
||||
this.singleTagset
|
||||
? (x) => x.tags & window.tags
|
||||
: (x) => x.monitor === window.monitor && x.tags & window.tags
|
||||
);
|
||||
return windows.findIndex((x) => x.handle === handle);
|
||||
}
|
||||
@@ -115,7 +120,9 @@ var StateManager = GObject.registerClass(
|
||||
*/
|
||||
swap(mon, tags, idx, newIdx) {
|
||||
const windows = this.windows.filter(
|
||||
(x) => x.monitor === mon && x.tags & tags
|
||||
this.singleTagset
|
||||
? (x) => x.tags & tags
|
||||
: (x) => x.monitor === mon && x.tags & tags
|
||||
);
|
||||
if (newIdx < 0) newIdx = windows.length + newIdx;
|
||||
newIdx %= windows.length;
|
||||
@@ -146,15 +153,16 @@ var StateManager = GObject.registerClass(
|
||||
*/
|
||||
render(mon, tags) {
|
||||
const windows = this.windows.filter(
|
||||
(x) => x.monitor === mon && x.tags & tags
|
||||
this.singleTagset
|
||||
? (x) => x.tags & tags
|
||||
: (x) => x.monitor === mon && x.tags & tags
|
||||
);
|
||||
log(`${windows.length} windows for monitor ${mon} with tags ${tags}`);
|
||||
return this._layout(this.monitors[mon], windows);
|
||||
}
|
||||
|
||||
_layout({ layout, nmaster, mfact, focused }, windows) {
|
||||
const focusedW = windows.find((x) => x.handle === focused)
|
||||
?? windows[0];
|
||||
const focusedW = windows.find((x) => x.handle === focused) ?? windows[0];
|
||||
|
||||
switch (layout) {
|
||||
case "monocle":
|
||||
|
||||
Reference in New Issue
Block a user