Add move/add tags for windows

This commit is contained in:
2023-05-14 17:20:35 +09:00
parent 6382a5a7c3
commit f2e2952d1d
4 changed files with 161 additions and 42 deletions

View File

@@ -164,6 +164,81 @@
<default><![CDATA[['<Super><Ctrl>9']]]></default>
<summary>add the current's monitor tag to 9</summary>
</key>
<!-- TODO: Add fullscreen, monitors and tags key -->
<key type="as" name="moveto-tag-1">
<default><![CDATA[['<Super><Shift>1']]]></default>
<summary>Move the selected window to the tag 1</summary>
</key>
<key type="as" name="moveto-tag-2">
<default><![CDATA[['<Super><Shift>2']]]></default>
<summary>Move the selected window to the tag 2</summary>
</key>
<key type="as" name="moveto-tag-3">
<default><![CDATA[['<Super><Shift>3']]]></default>
<summary>Move the selected window to the tag 3</summary>
</key>
<key type="as" name="moveto-tag-4">
<default><![CDATA[['<Super><Shift>4']]]></default>
<summary>Move the selected window to the tag 4</summary>
</key>
<key type="as" name="moveto-tag-5">
<default><![CDATA[['<Super><Shift>5']]]></default>
<summary>Move the selected window to the tag 5</summary>
</key>
<key type="as" name="moveto-tag-6">
<default><![CDATA[['<Super><Shift>6']]]></default>
<summary>Move the selected window to the tag 6</summary>
</key>
<key type="as" name="moveto-tag-7">
<default><![CDATA[['<Super><Shift>7']]]></default>
<summary>Move the selected window to the tag 7</summary>
</key>
<key type="as" name="moveto-tag-8">
<default><![CDATA[['<Super><Shift>8']]]></default>
<summary>Move the selected window to the tag 8</summary>
</key>
<key type="as" name="moveto-tag-9">
<default><![CDATA[['<Super><Shift>9']]]></default>
<summary>Move the selected window to the tag 9</summary>
</key>
<key type="as" name="addto-tag-1">
<default><![CDATA[['<Super><Ctrl><Shift>1']]]></default>
<summary>Add the selected window to the tag 1</summary>
</key>
<key type="as" name="addto-tag-2">
<default><![CDATA[['<Super><Ctrl><Shift>2']]]></default>
<summary>Add the selected window to the tag 2</summary>
</key>
<key type="as" name="addto-tag-3">
<default><![CDATA[['<Super><Ctrl><Shift>3']]]></default>
<summary>Add the selected window to the tag 3</summary>
</key>
<key type="as" name="addto-tag-4">
<default><![CDATA[['<Super><Ctrl><Shift>4']]]></default>
<summary>Add the selected window to the tag 4</summary>
</key>
<key type="as" name="addto-tag-5">
<default><![CDATA[['<Super><Ctrl><Shift>5']]]></default>
<summary>Add the selected window to the tag 5</summary>
</key>
<key type="as" name="addto-tag-6">
<default><![CDATA[['<Super><Ctrl><Shift>6']]]></default>
<summary>Add the selected window to the tag 6</summary>
</key>
<key type="as" name="addto-tag-7">
<default><![CDATA[['<Super><Ctrl><Shift>7']]]></default>
<summary>Add the selected window to the tag 7</summary>
</key>
<key type="as" name="addto-tag-8">
<default><![CDATA[['<Super><Ctrl><Shift>8']]]></default>
<summary>Add the selected window to the tag 8</summary>
</key>
<key type="as" name="addto-tag-9">
<default><![CDATA[['<Super><Ctrl><Shift>9']]]></default>
<summary>Add the selected window to the tag 9</summary>
</key>
<!-- TODO: Add fullscreen, monitors -->
</schema>
</schemalist>

View File

@@ -53,15 +53,10 @@ var KeyboardManager = GObject.registerClass(
const state = this._state.monitors[mon];
const idx = this._state.workIndexByHandle(state.focused);
const newW = this._state.workIndex(mon, state.tags, idx + 1);
this._state.focus(newW.handle);
});
this._addBinding("cycle-next", () => {
const mon = global.display.get_current_monitor();
const state = this._state.monitors[mon];
const idx = this._state.workIndexByHandle(state.focused);
const win = this._state.workIndex(mon, state.tags, idx - 1);
this._state.focus(win.handle);
if (newW && newW.handle !== state.focused)
this._state.focus(newW.handle);
});
this._addBinding("cycle-next", () => this._focusNext());
this._addBinding("incrmfact", () => {
const mon = global.display.get_current_monitor();
@@ -114,14 +109,14 @@ var KeyboardManager = GObject.registerClass(
this._renderer.render(mon);
});
for (const tagNbr = 1; tagNbr < 10; tagNbr++) {
for (let tagNbr = 0; tagNbr < 9; tagNbr++) {
const tag = 0b1 << tagNbr;
this._addBinding(`set-tag-${tagNbr}`, () => {
this._addBinding(`set-tag-${tagNbr + 1}`, () => {
const mon = global.display.get_current_monitor();
this._renderer.setTags(mon, tag);
});
this._addBinding(`add-tag-${tagNbr}`, () => {
this._addBinding(`add-tag-${tagNbr + 1}`, () => {
const mon = global.display.get_current_monitor();
const currTags = this._state.monitors[mon].tags;
// Add the tag to the monitor but if the tag is already present, remove it
@@ -133,12 +128,29 @@ var KeyboardManager = GObject.registerClass(
: currTags | tag
);
});
this._addBinding(`moveto-tag-${tagNbr + 1}`, () => {
const mon = global.display.get_current_monitor();
const handle = this._state.monitors[mon].focused;
const window = this._state.windows.find((x) => x.handle === handle);
this._focusNext();
window.tags = tag;
window.handle.change_workspace_by_index(tagNbr, false);
this._renderer.renderAll();
});
this._addBinding(`addto-tag-${tagNbr + 1}`, () => {
const mon = global.display.get_current_monitor();
const handle = this._state.monitors[mon].focused;
const window = this._state.windows.find((x) => x.handle === handle);
if (window.tags & tag) window.tags &= ~tag;
else window.tags |= tag;
this._renderer.renderAll();
});
}
this._addBinding("set-tag-all", () => {
const mon = global.display.get_current_monitor();
const takkenTags = 0;
for (const i = 0; i < this._state.monitors.length; i++)
for (let i = 0; i < this._state.monitors.length; i++)
takkenTags |= this._state.monitors[i];
this._state.monitors[mon].tags |= ~takkenTags;
@@ -163,11 +175,14 @@ var KeyboardManager = GObject.registerClass(
this._removeBinding("swap-prev");
this._removeBinding("zoom");
for (const i = 1; i < 10; i++) {
for (let i = 1; i < 10; i++) {
this._removeBinding(`set-tag-${i}`);
this._removeBinding(`add-tag-${i}`);
this._removeBinding(`moveto-tag-${i}`);
this._removeBinding(`addto-tag-${i}`);
}
this._removeBinding("set-tag-all");
this._removeBinding("moveto-tag-all");
}
_switchLayout(mode) {
@@ -179,5 +194,13 @@ var KeyboardManager = GObject.registerClass(
state.oldLayout = currentLayout;
this._renderer.render(mon);
}
_focusNext() {
const mon = global.display.get_current_monitor();
const state = this._state.monitors[mon];
const idx = this._state.workIndexByHandle(state.focused);
const win = this._state.workIndex(mon, state.tags, idx - 1);
if (win && win.handle !== state.focused) this._state.focus(win.handle);
}
}
);

View File

@@ -141,11 +141,11 @@ var Renderer = GObject.registerClass(
log("Switch to tags", tags);
if (Meta.prefs_get_workspaces_only_on_primary()) {
const primaryMon = global.display.get_primary_monitor();
this.setTag(primaryMon, tags);
this.setTags(primaryMon, tags);
} else {
for (let i = 0; i < this._state.monitors.length; i++) {
this._state.monitors[i].tags = tags;
this.render(i, tags);
this.render(i);
}
}
}),
@@ -153,13 +153,13 @@ var Renderer = GObject.registerClass(
}
/**
* @param {Meta.Window} window
* @param {Meta.Window} handle
*/
trackWindow(window) {
if (!this._isValidWindow(window)) return;
trackWindow(handle) {
if (!this._isValidWindow(handle)) return;
// Add window signals
window._signals = [
window.connect("unmanaging", (handle) => {
handle._signals = [
handle.connect("unmanaging", (handle) => {
handle._isInvalid = true;
const idx = this._state.workIndexByHandle(handle);
const faWindow = this._state.popByHandle(handle);
@@ -170,29 +170,34 @@ var Renderer = GObject.registerClass(
const newWindow = this._state.workIndex(faWindow.monitor, tags, idx);
if (newWindow) this._state.focus(newWindow.handle);
this.render(faWindow.monitor, tags);
this.render(faWindow.monitor);
}),
window.connect("workspace-changed", (window) => {
if (!this._isValidWindow(window)) return;
const [oldW, newW] = this._state.updateByHandle(window);
if (oldW) this.render(oldW.monitor, oldW.tags);
if (newW) this.render(newW.monitor, newW.tags);
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);
if (oldW) this.render(oldW.monitor);
if (newW) this.render(newW.monitor);
}),
window.connect("focus", (window) => {
if (!this._isValidWindow(window)) return;
this._state.monitors[window.get_monitor()].focused = window;
handle.connect("focus", (handle) => {
if (!this._isValidWindow(handle)) return;
this._state.monitors[handle.get_monitor()].focused = handle;
}),
];
this._state.newWindow(window);
this._state.newWindow(handle);
}
setTag(mon, tags) {
setTags(mon, tags) {
const currTags = this._state.monitors[mon].tags;
this._state.monitors[mon].tags = tags;
this._setGWorkspaceIfNeeded(mon);
for (const i = 0; i < this._state.monitors.length; i++) {
for (let i = 0; i < this._state.monitors.length; 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.
@@ -213,7 +218,8 @@ var Renderer = GObject.registerClass(
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) + 1;
const workspace = Math.log2(tag);
console.log("Switching to", tags, tag, workspace)
global.display
.get_workspace_manager()
@@ -224,7 +230,7 @@ var Renderer = GObject.registerClass(
renderAll() {
const monN = global.display.get_n_monitors();
for (let mon = 0; mon < monN; mon++) {
this.render(mon, this._state.monitors[mon].tags);
this.render(mon);
}
}
@@ -235,10 +241,9 @@ var Renderer = GObject.registerClass(
/**
* @param {number} mon
* @param {number?} tags
*/
render(mon, tags) {
if (!tags) tags = this._state.monitors[mon].tags;
render(mon) {
const tags = this._state.monitors[mon].tags;
// We don't care which workspace it is, we just want the geometry
// for the current monitor without the panel.
@@ -246,10 +251,21 @@ var Renderer = GObject.registerClass(
.get_workspace_manager()
.get_active_workspace()
.get_work_area_for_monitor(mon);
const workIdx = global.display
.get_workspace_manager()
.get_active_workspace_index();
for (const window of this._state.render(mon, tags)) {
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)
log("Invalid workspace", window.tags, 0b1 << workIdx);
window.handle._ignoreWorkspaceChange = true;
window.handle.change_workspace_by_index(workIdx, true);
}
if (window.floating) continue;

View File

@@ -4,7 +4,6 @@ const GObject = imports.gi.GObject;
const GLib = imports.gi.GLib;
const Mainloop = imports.mainloop;
var StateManager = GObject.registerClass(
class StateManager extends GObject.Object {
_init() {
@@ -146,8 +145,8 @@ var StateManager = GObject.registerClass(
if (newIdx < 0) newIdx = windows.length + newIdx;
newIdx %= windows.length;
const gIdx = this.windows.findIndex(x => x === windows[idx]);
const gNewIdx = this.windows.findIndex(x => x === windows[newIdx]);
const gIdx = this.windows.findIndex((x) => x === windows[idx]);
const gNewIdx = this.windows.findIndex((x) => x === windows[newIdx]);
const tmp = this.windows[gIdx];
this.windows[gIdx] = this.windows[gNewIdx];
@@ -180,9 +179,13 @@ var StateManager = GObject.registerClass(
// TODO: Implement other layouts
switch (layout) {
case "monocle":
const focused = this.windows.find(
(x) => x.handle === this.monitors[mon].focused
);
return [
{
handle: this.monitors[mon].focused,
...focused,
handle: focused.hanlde,
maximized: true,
minimized: false,
x: 0,
@@ -199,6 +202,7 @@ var StateManager = GObject.registerClass(
: windows.length - nmaster;
const stackIndex = i < nmaster ? i : i - nmaster;
return {
...x,
handle: x.handle,
maximized: false,
minimized: false,
@@ -215,6 +219,7 @@ var StateManager = GObject.registerClass(
});
case "floating":
return windows.map((x) => ({
...x,
handle: x.handle,
floating: true,
}));