mirror of
https://github.com/zoriya/fairy.git
synced 2025-12-06 05:36:09 +00:00
Add keybinds and monitor staet
This commit is contained in:
15
extension.js
15
extension.js
@@ -6,16 +6,22 @@ const Me = ExtensionUtils.getCurrentExtension();
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
|
||||
const Windows = Me.imports.sources.windows;
|
||||
const State = Me.imports.sources.state;
|
||||
const Renderer = Me.imports.sources.renderer;
|
||||
const Keybinds = Me.imports.sources.keybinds;
|
||||
|
||||
class Extension {
|
||||
constructor() {
|
||||
this._state = new State.StateManager();
|
||||
this._renderer = new Renderer.Renderer(this._state);
|
||||
this._keybinds = new Keybinds.KeyboardManager(this._state, this._renderer);
|
||||
|
||||
this._layoutIndicator = null;
|
||||
this._windows = new Windows.WindowManager();
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._windows.enable();
|
||||
this._renderer.enable();
|
||||
this._keybinds.enable();
|
||||
|
||||
this.settings = ExtensionUtils.getSettings(
|
||||
"org.gnome.shell.extensions.fairy"
|
||||
@@ -43,7 +49,8 @@ class Extension {
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._windows.disable();
|
||||
this._renderer.disable();
|
||||
this._keybinds.disable();
|
||||
this._layoutIndicator.destroy();
|
||||
this._layoutIndicator = null;
|
||||
|
||||
|
||||
78
sources/keybinds.js
Normal file
78
sources/keybinds.js
Normal file
@@ -0,0 +1,78 @@
|
||||
"use strict";
|
||||
|
||||
const GObject = imports.gi.GObject;
|
||||
const Main = imports.ui.main;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
var KeyboardManager = GObject.registerClass(
|
||||
class KeyboardManager extends GObject.Object {
|
||||
_init(state, renderer) {
|
||||
super._init();
|
||||
this._state = state;
|
||||
this._renderer = renderer;
|
||||
// TODO: Handle rerender from here.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {() => void} action
|
||||
*/
|
||||
_addBinding(key, action) {
|
||||
const settings = ExtensionUtils.getSettings(
|
||||
"org.gnome.shell.extensions.fairy.keybinds"
|
||||
);
|
||||
|
||||
Main.wm.addKeybinding(
|
||||
key,
|
||||
settings,
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
*/
|
||||
_removeBinding(key) {
|
||||
Main.wm.removeKeybinding(key);
|
||||
}
|
||||
|
||||
enable() {
|
||||
this._addBinding("incrmfact", () => {
|
||||
const mon = global.display.get_current_monitor();
|
||||
const state = this._state.monitors[mon];
|
||||
state.mfact = Math.min(95, state.mfact + 5);
|
||||
this._renderer.render(mon);
|
||||
});
|
||||
this._addBinding("decmfact", () => {
|
||||
const mon = global.display.get_current_monitor();
|
||||
const state = this._state.monitors[mon];
|
||||
state.mfact = Math.max(5, state.mfact - 5);
|
||||
this._renderer.render(mon);
|
||||
});
|
||||
|
||||
this._addBinding("incrnmaster", () => {
|
||||
const mon = global.display.get_current_monitor();
|
||||
this._state.monitors[mon].mfact += 1;
|
||||
this._renderer.render(mon);
|
||||
});
|
||||
this._addBinding("decnmaster", () => {
|
||||
const mon = global.display.get_current_monitor();
|
||||
if (this._state.monitors[mon].nmaster > 0)
|
||||
this._state.monitors[mon].nmaster -= 1;
|
||||
this._renderer.render(mon);
|
||||
});
|
||||
}
|
||||
|
||||
disable() {
|
||||
this._removeBinding("incrmfact");
|
||||
this._removeBinding("decrmfact");
|
||||
|
||||
this._removeBinding("incrnmaster");
|
||||
this._removeBinding("decrnmaster");
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -8,13 +8,11 @@ const Mainloop = imports.mainloop;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
|
||||
const Layout = Me.imports.sources.layout;
|
||||
|
||||
var WindowManager = GObject.registerClass(
|
||||
class WindowManager extends GObject.Object {
|
||||
_init() {
|
||||
var Renderer = GObject.registerClass(
|
||||
class Renderer extends GObject.Object {
|
||||
_init(state) {
|
||||
super._init();
|
||||
this._layout = new Layout.Layout();
|
||||
this._state = state
|
||||
log("fairy init");
|
||||
}
|
||||
|
||||
@@ -84,12 +82,17 @@ var WindowManager = GObject.registerClass(
|
||||
}
|
||||
|
||||
_removeSignals() {
|
||||
for (const signal of this._signals) {
|
||||
for (const signal of this._displaySignals) {
|
||||
global.display.disconnect(signal);
|
||||
}
|
||||
this._signals = undefined;
|
||||
this._displaySignals = undefined;
|
||||
|
||||
for (const window of this._layout.windows) {
|
||||
for (const signal of this._wmSignals) {
|
||||
global.window_manager.disconnect(signal);
|
||||
}
|
||||
this._wmSignals = undefined;
|
||||
|
||||
for (const window of this._state.windows) {
|
||||
if (window._signals) {
|
||||
for (const signal of window._signals) window.disconnect(signal);
|
||||
}
|
||||
@@ -99,11 +102,11 @@ var WindowManager = GObject.registerClass(
|
||||
actor._signals = [];
|
||||
}
|
||||
}
|
||||
this._layout.windows = [];
|
||||
this._state.windows = [];
|
||||
}
|
||||
|
||||
_bindSignals() {
|
||||
this._signals = [
|
||||
this._displaySignals = [
|
||||
global.display.connect("window-created", (_display, window) =>
|
||||
this._waitForWindow(window, () => {
|
||||
this.trackWindow(window);
|
||||
@@ -114,6 +117,18 @@ var WindowManager = GObject.registerClass(
|
||||
//
|
||||
// }),
|
||||
];
|
||||
this._wmSignals = [
|
||||
global.window_manager.connect("switch-workspace", (_wm, _from, to, _direction) => {
|
||||
// Convert gnome workspaces to fairy's tags
|
||||
to = 0b1 << to;
|
||||
if (Meta.prefs_get_workspaces_only_on_primary()) {
|
||||
this._state.monitors[global.display.get_primary_monitor()].tags = to;
|
||||
} else {
|
||||
for (let i = 0; i < this._state.monitors.length; i++)
|
||||
this._state.monitors[i].tags = to;
|
||||
}
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +142,7 @@ var WindowManager = GObject.registerClass(
|
||||
}),
|
||||
window.connect("workspace-changed", (window) => {
|
||||
if (!this._isValidWindow(window)) return;
|
||||
const [oldW, newW] = this._layout.updateByHandle(window);
|
||||
const [oldW, newW] = this._state.updateByHandle(window);
|
||||
if (oldW) this.render(oldW.monitor, oldW.tags);
|
||||
if (newW) this.render(newW.monitor, newW.tags);
|
||||
}),
|
||||
@@ -135,12 +150,12 @@ var WindowManager = GObject.registerClass(
|
||||
const actor = window.get_compositor_private();
|
||||
actor._signals = [
|
||||
actor.connect("destroy", (actor) => {
|
||||
const faWindow = this._layout.popByActor(actor);
|
||||
const faWindow = this._state.popByActor(actor);
|
||||
if (faWindow) this.render(faWindow.monitor, faWindow.tags);
|
||||
}),
|
||||
];
|
||||
|
||||
this._layout.newWindow(window);
|
||||
this._state.newWindow(window);
|
||||
}
|
||||
|
||||
renderAll() {
|
||||
@@ -155,18 +170,17 @@ var WindowManager = GObject.registerClass(
|
||||
|
||||
renderForWindow(window) {
|
||||
const mon = window.get_monitor();
|
||||
// TODO: The on_all_workspaces handling is faulty.
|
||||
const workspace = window.on_all_workspaces
|
||||
? ~0
|
||||
: window.get_workspace().index() + 1;
|
||||
this.render(mon, workspace);
|
||||
this.render(mon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} mon
|
||||
* @param {number} tags
|
||||
* @param {number?} tags
|
||||
*/
|
||||
render(mon, tags) {
|
||||
console.log("monitors", this._state.monitors)
|
||||
if (!tags) 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.
|
||||
const monGeo = global.display
|
||||
@@ -174,7 +188,7 @@ var WindowManager = GObject.registerClass(
|
||||
.get_active_workspace()
|
||||
.get_work_area_for_monitor(mon);
|
||||
|
||||
for (const window of this._layout.render(mon, tags)) {
|
||||
for (const window of this._state.render(mon, tags)) {
|
||||
if (window.handle.get_monitor() !== mon)
|
||||
window.handle.move_to_monitor(mon);
|
||||
if (window.handle.minimized !== window.minimized) {
|
||||
@@ -2,19 +2,20 @@
|
||||
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
var Layout = GObject.registerClass(
|
||||
class Layout extends GObject.Object {
|
||||
var StateManager = GObject.registerClass(
|
||||
class StateManager extends GObject.Object {
|
||||
_init() {
|
||||
super._init();
|
||||
// Simpler to set 30 monitors than track creation/supression of monitors.
|
||||
this._monitors = new Array(30).map(() => ({
|
||||
this.monitors = [...new Array(30)].map(() => ({
|
||||
/**
|
||||
* @type {Meta.Window} focused window's handle
|
||||
*/
|
||||
focused: null,
|
||||
tags: 1,
|
||||
layout: "tiled",
|
||||
nmaster: 1,
|
||||
nfact: 60,
|
||||
mfact: 55,
|
||||
}));
|
||||
|
||||
/**
|
||||
@@ -80,7 +81,7 @@ var Layout = GObject.registerClass(
|
||||
* @returns WindowGeometry[]
|
||||
*/
|
||||
render(mon, tags) {
|
||||
const { layout, nmaster, nfact } = this._monitors[mon];
|
||||
const { layout, nmaster, mfact } = this.monitors[mon];
|
||||
const windows = this.windows.filter(
|
||||
(x) => x.monitor === mon && x.tags & tags
|
||||
);
|
||||
@@ -91,7 +92,7 @@ var Layout = GObject.registerClass(
|
||||
case "monocle":
|
||||
return [
|
||||
{
|
||||
handle: this._monitors[mon].focused,
|
||||
handle: this.monitors[mon].focused,
|
||||
maximized: true,
|
||||
minimized: false,
|
||||
x: 0,
|
||||
@@ -111,17 +112,19 @@ var Layout = GObject.registerClass(
|
||||
handle: x.handle,
|
||||
maximized: false,
|
||||
minimized: false,
|
||||
x: i < nmaster ? 0 : nfact,
|
||||
x: i < nmaster ? 0 : mfact,
|
||||
y: stackIndex * (100 / stackLength),
|
||||
width:
|
||||
windows.length <= nmaster
|
||||
? 100
|
||||
: i < nmaster
|
||||
? nfact
|
||||
: 100 - nfact,
|
||||
? mfact
|
||||
: 100 - mfact,
|
||||
height: 100 / stackLength,
|
||||
};
|
||||
});
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user