mirror of
https://github.com/danbulant/dots-hyprland
synced 2026-05-24 12:22:09 +00:00
sway workspace indicator
This commit is contained in:
parent
fb2cb6ed7e
commit
c5744aa2fe
4 changed files with 482 additions and 369 deletions
|
|
@ -64,6 +64,7 @@ export default {
|
|||
};
|
||||
|
||||
// Stuff that don't need to be toggled. And they're async so ugh...
|
||||
// Bar().catch(print);
|
||||
forMonitors(Bar);
|
||||
forMonitors(BarCornerTopleft);
|
||||
forMonitors(BarCornerTopright);
|
||||
|
|
@ -1,309 +1,303 @@
|
|||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
if (typeof b !== "function" && b !== null)
|
||||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
import GLib from 'gi://GLib';
|
||||
import Gio from 'gi://Gio';
|
||||
import Service from "resource:///com/github/Aylur/ags/service.js";
|
||||
|
||||
const SIS = GLib.getenv('SWAYSOCK');
|
||||
|
||||
export const PAYLOAD_TYPE = {
|
||||
MESSAGE_RUN_COMMAND: 0,
|
||||
MESSAGE_GET_WORKSPACES: 1,
|
||||
MESSAGE_SUBSCRIBE: 2,
|
||||
MESSAGE_GET_OUTPUTS: 3,
|
||||
MESSAGE_GET_TREE: 4,
|
||||
MESSAGE_GET_MARKS: 5,
|
||||
MESSAGE_GET_BAR_CONFIG: 6,
|
||||
MESSAGE_GET_VERSION: 7,
|
||||
MESSAGE_GET_BINDING_NODES: 8,
|
||||
MESSAGE_GET_CONFIG: 9,
|
||||
MESSAGE_SEND_TICK: 10,
|
||||
MESSAGE_SYNC: 11,
|
||||
MESSAGE_GET_BINDING_STATE: 12,
|
||||
MESSAGE_GET_INPUTS: 100,
|
||||
MESSAGE_GET_SEATS: 101,
|
||||
EVENT_WORKSPACE: 0x80000000,
|
||||
EVENT_MODE: 0x80000002,
|
||||
EVENT_WINDOW: 0x80000003,
|
||||
EVENT_BARCONFIG_UPDATE: 0x80000004,
|
||||
EVENT_BINDING: 0x80000005,
|
||||
EVENT_SHUTDOWN: 0x80000006,
|
||||
EVENT_TICK: 0x80000007,
|
||||
EVENT_BAR_STATE_UPDATE: 0x80000014,
|
||||
EVENT_INPUT: 0x80000015,
|
||||
}
|
||||
|
||||
const Client_Event = {
|
||||
change: undefined,
|
||||
container: undefined,
|
||||
}
|
||||
|
||||
const Workspace_Event = {
|
||||
change: undefined,
|
||||
current: undefined,
|
||||
old: undefined,
|
||||
}
|
||||
|
||||
const Geometry = {
|
||||
x: undefined,
|
||||
y: undefined,
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
}
|
||||
|
||||
//NOTE: not all properties are listed here
|
||||
export const Node = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
type: undefined,
|
||||
border: undefined,
|
||||
current_border_width: undefined,
|
||||
layout: undefined,
|
||||
orientation: undefined,
|
||||
percent: undefined,
|
||||
rect: undefined,
|
||||
window_rect: undefined,
|
||||
deco_rect: undefined,
|
||||
geometry: undefined,
|
||||
urgent: undefined,
|
||||
sticky: undefined,
|
||||
marks: undefined,
|
||||
focused: undefined,
|
||||
active: undefined,
|
||||
focus: undefined,
|
||||
nodes: undefined,
|
||||
floating_nodes: undefined,
|
||||
representation: undefined,
|
||||
fullscreen_mode: undefined,
|
||||
app_id: undefined,
|
||||
pid: undefined,
|
||||
visible: undefined,
|
||||
shell: undefined,
|
||||
output: undefined,
|
||||
inhibit_idle: undefined,
|
||||
idle_inhibitors: {
|
||||
application: undefined,
|
||||
user: undefined,
|
||||
},
|
||||
window: undefined,
|
||||
window_properties: {
|
||||
title: undefined,
|
||||
class: undefined,
|
||||
instance: undefined,
|
||||
window_role: undefined,
|
||||
window_type: undefined,
|
||||
transient_for: undefined,
|
||||
}
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
|
||||
export class SwayActiveClient extends Service {
|
||||
static {
|
||||
Service.register(this, {}, {
|
||||
'id': ['int'],
|
||||
'name': ['string'],
|
||||
'class': ['string'],
|
||||
});
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
var _a, _b, _c, _d;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sway = exports.Sway = exports.SwayActives = exports.SwayActiveID = exports.SwayActiveClient = void 0;
|
||||
var _1 = require("gi://GLib");
|
||||
var _2 = require("gi://Gio");
|
||||
var service_js_1 = require("../service.js");
|
||||
var SIS = _1.default.getenv('SWAYSOCK');
|
||||
var SwayActiveClient = /** @class */ (function (_super) {
|
||||
__extends(SwayActiveClient, _super);
|
||||
function SwayActiveClient() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this._id = 0;
|
||||
_this._name = '';
|
||||
_this._class = '';
|
||||
return _this;
|
||||
}
|
||||
Object.defineProperty(SwayActiveClient.prototype, "id", {
|
||||
get: function () { return this._id; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(SwayActiveClient.prototype, "name", {
|
||||
get: function () { return this._name; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(SwayActiveClient.prototype, "class", {
|
||||
get: function () { return this._class; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
SwayActiveClient.prototype.updateProperty = function (prop, value) {
|
||||
_super.prototype.updateProperty.call(this, prop, value);
|
||||
|
||||
_id = 0;
|
||||
_name = '';
|
||||
_class = '';
|
||||
|
||||
get id() { return this._id; }
|
||||
get name() { return this._name; }
|
||||
get class() { return this._class; }
|
||||
|
||||
updateProperty(prop, value) {
|
||||
if (!['id', 'name', 'class'].includes(prop)) return;
|
||||
super.updateProperty(prop, value);
|
||||
this.emit('changed');
|
||||
};
|
||||
return SwayActiveClient;
|
||||
}(service_js_1.default));
|
||||
exports.SwayActiveClient = SwayActiveClient;
|
||||
_a = SwayActiveClient;
|
||||
(function () {
|
||||
service_js_1.default.register(_a, {}, {
|
||||
'id': ['int'],
|
||||
'name': ['string'],
|
||||
'class': ['string'],
|
||||
});
|
||||
})();
|
||||
var SwayActiveID = /** @class */ (function (_super) {
|
||||
__extends(SwayActiveID, _super);
|
||||
function SwayActiveID() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this._id = 1;
|
||||
_this._name = '';
|
||||
return _this;
|
||||
}
|
||||
Object.defineProperty(SwayActiveID.prototype, "id", {
|
||||
get: function () { return this._id; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(SwayActiveID.prototype, "name", {
|
||||
get: function () { return this._name; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
SwayActiveID.prototype.update = function (id, name) {
|
||||
_super.prototype.updateProperty.call(this, 'id', id);
|
||||
_super.prototype.updateProperty.call(this, 'name', name);
|
||||
}
|
||||
|
||||
export class SwayActiveID extends Service {
|
||||
static {
|
||||
Service.register(this, {}, {
|
||||
'id': ['int'],
|
||||
'name': ['string'],
|
||||
});
|
||||
}
|
||||
|
||||
_id = 0;
|
||||
_name = '';
|
||||
|
||||
get id() { return this._id; }
|
||||
get name() { return this._name; }
|
||||
|
||||
update(id, name) {
|
||||
super.updateProperty('id', id);
|
||||
super.updateProperty('name', name);
|
||||
this.emit('changed');
|
||||
};
|
||||
return SwayActiveID;
|
||||
}(service_js_1.default));
|
||||
exports.SwayActiveID = SwayActiveID;
|
||||
_b = SwayActiveID;
|
||||
(function () {
|
||||
service_js_1.default.register(_b, {}, {
|
||||
'id': ['int'],
|
||||
'name': ['string'],
|
||||
});
|
||||
})();
|
||||
var SwayActives = /** @class */ (function (_super) {
|
||||
__extends(SwayActives, _super);
|
||||
function SwayActives() {
|
||||
var _this = _super.call(this) || this;
|
||||
_this._client = new SwayActiveClient;
|
||||
_this._monitor = new SwayActiveID;
|
||||
_this._workspace = new SwayActiveID;
|
||||
['client', 'workspace', 'monitor'].forEach(function (obj) {
|
||||
_this["_".concat(obj)].connect('changed', function () {
|
||||
_this.notify(obj);
|
||||
_this.emit('changed');
|
||||
}
|
||||
}
|
||||
|
||||
export class SwayActives extends Service {
|
||||
static {
|
||||
Service.register(this, {}, {
|
||||
'client': ['jsobject'],
|
||||
'monitor': ['jsobject'],
|
||||
'workspace': ['jsobject'],
|
||||
});
|
||||
}
|
||||
|
||||
_client = new SwayActiveClient;
|
||||
_monitor = new SwayActiveID;
|
||||
_workspace = new SwayActiveID;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
(['client', 'workspace', 'monitor']).forEach(obj => {
|
||||
this[`_${obj}`].connect('changed', () => {
|
||||
this.notify(obj);
|
||||
this.emit('changed');
|
||||
});
|
||||
});
|
||||
return _this;
|
||||
}
|
||||
Object.defineProperty(SwayActives.prototype, "client", {
|
||||
get: function () { return this._client; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(SwayActives.prototype, "monitor", {
|
||||
get: function () { return this._monitor; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(SwayActives.prototype, "workspace", {
|
||||
get: function () { return this._workspace; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
return SwayActives;
|
||||
}(service_js_1.default));
|
||||
exports.SwayActives = SwayActives;
|
||||
_c = SwayActives;
|
||||
(function () {
|
||||
service_js_1.default.register(_c, {}, {
|
||||
'client': ['jsobject'],
|
||||
'monitor': ['jsobject'],
|
||||
'workspace': ['jsobject'],
|
||||
});
|
||||
})();
|
||||
var Sway = /** @class */ (function (_super) {
|
||||
__extends(Sway, _super);
|
||||
function Sway() {
|
||||
var _this = this;
|
||||
|
||||
get client() { return this._client; }
|
||||
get monitor() { return this._monitor; }
|
||||
get workspace() { return this._workspace; }
|
||||
}
|
||||
|
||||
export class Sway extends Service {
|
||||
static {
|
||||
Service.register(this, {}, {
|
||||
'active': ['jsobject'],
|
||||
'monitors': ['jsobject'],
|
||||
'workspaces': ['jsobject'],
|
||||
'clients': ['jsobject'],
|
||||
});
|
||||
}
|
||||
|
||||
_decoder = new TextDecoder();
|
||||
_encoder = new TextEncoder();
|
||||
_socket;
|
||||
|
||||
_active;
|
||||
_monitors;
|
||||
_workspaces;
|
||||
_clients;
|
||||
|
||||
get active() { return this._active; }
|
||||
get monitors() { return Array.from(this._monitors.values()); }
|
||||
get workspaces() { return Array.from(this._workspaces.values()); }
|
||||
get clients() { return Array.from(this._clients.values()); }
|
||||
|
||||
getMonitor(id) { return this._monitors.get(id); }
|
||||
getWorkspace(name) { return this._workspaces.get(name); }
|
||||
getClient(id) { return this._clients.get(id); }
|
||||
|
||||
msg(payload) { this._send(PAYLOAD_TYPE.MESSAGE_RUN_COMMAND, payload); }
|
||||
|
||||
constructor() {
|
||||
if (!SIS)
|
||||
console.error('Sway is not running');
|
||||
_this = _super.call(this) || this;
|
||||
_this._decoder = new TextDecoder();
|
||||
_this._encoder = new TextEncoder();
|
||||
_this._active = new SwayActives();
|
||||
_this._monitors = new Map();
|
||||
_this._workspaces = new Map();
|
||||
_this._clients = new Map();
|
||||
var socket = new _2.default.SocketClient().connect(new _2.default.UnixSocketAddress({
|
||||
path: "".concat(SIS),
|
||||
super();
|
||||
|
||||
this._active = new SwayActives();
|
||||
this._monitors = new Map();
|
||||
this._workspaces = new Map();
|
||||
this._clients = new Map();
|
||||
|
||||
this._socket = new Gio.SocketClient().connect(new Gio.UnixSocketAddress({
|
||||
path: `${SIS}`,
|
||||
}), null);
|
||||
_this._watchSocket(socket.get_input_stream());
|
||||
_this._output_stream = socket.get_output_stream();
|
||||
_this.send(4 /* PAYLOAD_TYPE.MESSAGE_GET_TREE */, '');
|
||||
_this.send(2 /* PAYLOAD_TYPE.MESSAGE_SUBSCRIBE */, JSON.stringify(['window', 'workspace']));
|
||||
_this._active.connect('changed', function () { return _this.emit('changed'); });
|
||||
['monitor', 'workspace', 'client'].forEach(function (active) {
|
||||
return _this._active.connect("notify::".concat(active), function () { return _this.notify('active'); });
|
||||
});
|
||||
return _this;
|
||||
|
||||
this._watchSocket(this._socket.get_input_stream());
|
||||
this._send(PAYLOAD_TYPE.MESSAGE_GET_TREE, '');
|
||||
this._send(PAYLOAD_TYPE.MESSAGE_SUBSCRIBE, JSON.stringify(['window', 'workspace']));
|
||||
|
||||
this._active.connect('changed', () => this.emit('changed'));
|
||||
['monitor', 'workspace', 'client'].forEach(active =>
|
||||
this._active.connect(`notify::${active}`, () => this.notify('active')));
|
||||
}
|
||||
Object.defineProperty(Sway.prototype, "active", {
|
||||
get: function () { return this._active; },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Sway.prototype, "monitors", {
|
||||
get: function () { return Array.from(this._monitors.values()); },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Sway.prototype, "workspaces", {
|
||||
get: function () { return Array.from(this._workspaces.values()); },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Sway.prototype, "clients", {
|
||||
get: function () { return Array.from(this._clients.values()); },
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Sway.prototype.getMonitor = function (id) { return this._monitors.get(id); };
|
||||
Sway.prototype.getWorkspace = function (name) { return this._workspaces.get(name); };
|
||||
Sway.prototype.getClient = function (id) { return this._clients.get(id); };
|
||||
Sway.prototype.send = function (payloadType, payload) {
|
||||
var pb = this._encoder.encode(payload);
|
||||
var type = new Uint32Array([payloadType]);
|
||||
var pl = new Uint32Array([pb.length]);
|
||||
var magic_string = this._encoder.encode('i3-ipc');
|
||||
var data = new Uint8Array(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], magic_string, true), (new Uint8Array(pl.buffer)), true), (new Uint8Array(type.buffer)), true), pb, true));
|
||||
this._output_stream.write(data, null);
|
||||
};
|
||||
Sway.prototype._watchSocket = function (stream) {
|
||||
var _this = this;
|
||||
stream.read_bytes_async(14, _1.default.PRIORITY_DEFAULT, null, function (_, resultHeader) {
|
||||
var data = stream.read_bytes_finish(resultHeader).get_data();
|
||||
|
||||
_send(payloadType, payload) {
|
||||
const pb = this._encoder.encode(payload);
|
||||
const type = new Uint32Array([payloadType]);
|
||||
const pl = new Uint32Array([pb.length]);
|
||||
const magic_string = this._encoder.encode('i3-ipc');
|
||||
const data = new Uint8Array([
|
||||
...magic_string,
|
||||
...(new Uint8Array(pl.buffer)),
|
||||
...(new Uint8Array(type.buffer)),
|
||||
...pb]);
|
||||
this._socket.get_output_stream().write(data, null);
|
||||
}
|
||||
|
||||
_watchSocket(stream) {
|
||||
stream.read_bytes_async(14, GLib.PRIORITY_DEFAULT, null, (_, resultHeader) => {
|
||||
const data = stream.read_bytes_finish(resultHeader).get_data();
|
||||
if (!data)
|
||||
return;
|
||||
var payloadLength = new Uint32Array(data.slice(6, 10).buffer)[0];
|
||||
var payloadType = new Uint32Array(data.slice(10, 14).buffer)[0];
|
||||
stream.read_bytes_async(payloadLength, _1.default.PRIORITY_DEFAULT, null, function (_, resultPayload) {
|
||||
var data = stream.read_bytes_finish(resultPayload).get_data();
|
||||
if (!data)
|
||||
return;
|
||||
_this._onEvent(payloadType, JSON.parse(_this._decoder.decode(data)));
|
||||
_this._watchSocket(stream);
|
||||
});
|
||||
const payloadLength = new Uint32Array(data.slice(6, 10).buffer)[0];
|
||||
const payloadType = new Uint32Array(data.slice(10, 14).buffer)[0];
|
||||
stream.read_bytes_async(
|
||||
payloadLength,
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
null,
|
||||
(_, resultPayload) => {
|
||||
const data = stream.read_bytes_finish(resultPayload).get_data();
|
||||
if (!data)
|
||||
return;
|
||||
this._onEvent(payloadType, JSON.parse(this._decoder.decode(data)));
|
||||
this._watchSocket(stream);
|
||||
});
|
||||
});
|
||||
};
|
||||
Sway.prototype._onEvent = function (event_type, event) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_e) {
|
||||
if (!event)
|
||||
return [2 /*return*/];
|
||||
try {
|
||||
switch (event_type) {
|
||||
case 2147483648 /* PAYLOAD_TYPE.EVENT_WORKSPACE */:
|
||||
this._handleWorkspaceEvent(event);
|
||||
break;
|
||||
case 2147483651 /* PAYLOAD_TYPE.EVENT_WINDOW */:
|
||||
this._handleWindowEvent(event);
|
||||
break;
|
||||
case 4 /* PAYLOAD_TYPE.MESSAGE_GET_TREE */:
|
||||
this._handleTreeMessage(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logError(error);
|
||||
}
|
||||
this.emit('changed');
|
||||
return [2 /*return*/];
|
||||
});
|
||||
});
|
||||
};
|
||||
Sway.prototype._handleWorkspaceEvent = function (workspaceEvent) {
|
||||
var workspace = workspaceEvent.current;
|
||||
}
|
||||
|
||||
async _onEvent(event_type, event) {
|
||||
if (!event)
|
||||
return;
|
||||
try {
|
||||
switch (event_type) {
|
||||
case PAYLOAD_TYPE.EVENT_WORKSPACE:
|
||||
this._handleWorkspaceEvent(event);
|
||||
break;
|
||||
case PAYLOAD_TYPE.EVENT_WINDOW:
|
||||
this._handleWindowEvent(event);
|
||||
break;
|
||||
case PAYLOAD_TYPE.MESSAGE_GET_TREE:
|
||||
this._handleTreeMessage(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error);
|
||||
}
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_handleWorkspaceEvent(workspaceEvent) {
|
||||
const workspace = workspaceEvent.current;
|
||||
switch (workspaceEvent.change) {
|
||||
case 'init':
|
||||
this._workspaces.set(workspace.name, workspace);
|
||||
this.notify('workspaces');
|
||||
break;
|
||||
case 'empty':
|
||||
this._workspaces.delete(workspace.name);
|
||||
this.notify('workspaces');
|
||||
break;
|
||||
case 'focus':
|
||||
this._active.workspace.update(workspace.id, workspace.name);
|
||||
this._active.monitor.update(1, workspace.output);
|
||||
|
||||
this._workspaces.set(workspace.name, workspace);
|
||||
this._workspaces.set(workspaceEvent.old.name, workspaceEvent.old);
|
||||
this.notify('workspaces');
|
||||
break;
|
||||
case 'rename':
|
||||
if (this._active.workspace.id === workspace.id)
|
||||
this._active.workspace.updateProperty('name', workspace.name);
|
||||
this._workspaces.set(workspace.name, workspace);
|
||||
this.notify('workspaces');
|
||||
break;
|
||||
case 'reload':
|
||||
break;
|
||||
|
|
@ -311,34 +305,36 @@ var Sway = /** @class */ (function (_super) {
|
|||
case 'urgent':
|
||||
default:
|
||||
this._workspaces.set(workspace.name, workspace);
|
||||
this.notify('workspaces');
|
||||
}
|
||||
};
|
||||
Sway.prototype._handleWindowEvent = function (clientEvent) {
|
||||
var _e;
|
||||
var client = clientEvent.container;
|
||||
var id = client.id;
|
||||
this.notify('workspaces');
|
||||
}
|
||||
|
||||
_handleWindowEvent(clientEvent) {
|
||||
const client = clientEvent.container;
|
||||
const id = client.id;
|
||||
switch (clientEvent.change) {
|
||||
case 'new':
|
||||
this._clients.set(id, client);
|
||||
this.notify('clients');
|
||||
break;
|
||||
case 'close':
|
||||
this._clients.delete(id);
|
||||
this.notify('clients');
|
||||
case 'floating':
|
||||
case 'move':
|
||||
// Refresh tree since client events don't contain the relevant information
|
||||
// to be able to modify `workspace.nodes` or `workspace.floating_nodes`.
|
||||
// There has to be a better way than this though :/
|
||||
this._send(PAYLOAD_TYPE.MESSAGE_GET_TREE, '');
|
||||
break;
|
||||
case 'focus':
|
||||
if (this._active.client.id === id)
|
||||
return;
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
var current_active = this._clients.get(this._active.client.id);
|
||||
const current_active = this._clients.get(this._active.client.id);
|
||||
if (current_active)
|
||||
current_active.focused = false;
|
||||
this._active.client.updateProperty('id', id);
|
||||
this._active.client.updateProperty('name', client.name);
|
||||
this._active.client.updateProperty('class', client.shell === 'xwayland'
|
||||
? ((_e = client.window_properties) === null || _e === void 0 ? void 0 : _e.class) || ''
|
||||
: client.app_id);
|
||||
? client.window_properties?.class || ''
|
||||
: client.app_id,
|
||||
);
|
||||
break;
|
||||
case 'title':
|
||||
if (client.focused)
|
||||
|
|
@ -347,43 +343,39 @@ var Sway = /** @class */ (function (_super) {
|
|||
this.notify('clients');
|
||||
break;
|
||||
case 'fullscreen_mode':
|
||||
case 'move':
|
||||
case 'floating':
|
||||
case 'urgent':
|
||||
case 'mark':
|
||||
default:
|
||||
this._clients.set(id, client);
|
||||
this.notify('clients');
|
||||
}
|
||||
};
|
||||
Sway.prototype._handleTreeMessage = function (node) {
|
||||
var _this = this;
|
||||
var _e;
|
||||
}
|
||||
|
||||
_handleTreeMessage(node) {
|
||||
switch (node.type) {
|
||||
case 'root':
|
||||
this._workspaces.clear();
|
||||
this._clients.clear();
|
||||
this._monitors.clear();
|
||||
node.nodes.map(function (n) { return _this._handleTreeMessage(n); });
|
||||
['workspaces', 'clients', 'monitors'].forEach(function (t) {
|
||||
_this.notify(t);
|
||||
});
|
||||
node.nodes.map(n => this._handleTreeMessage(n));
|
||||
break;
|
||||
case 'output':
|
||||
this._monitors.set(node.id, node);
|
||||
if (node.active)
|
||||
this._active.monitor.updateProperty('name', node.name);
|
||||
node.nodes.map(function (n) { return _this._handleTreeMessage(n); });
|
||||
this._active.monitor.update(node.id, node.name);
|
||||
node.nodes.map(n => this._handleTreeMessage(n));
|
||||
this.notify('monitors');
|
||||
break;
|
||||
case 'workspace':
|
||||
this._workspaces.set(node.name, node);
|
||||
// I think I'm missing something. There has to be a better way.
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
var hasFocusedChild_1 = function (n) { return n.nodes.some(function (c) { return c.focused || hasFocusedChild_1(c); }); };
|
||||
if (hasFocusedChild_1(node))
|
||||
const hasFocusedChild =
|
||||
(n) => n.nodes.some(c => c.focused || hasFocusedChild(c));
|
||||
if (node.focused || hasFocusedChild(node))
|
||||
this._active.workspace.update(node.id, node.name);
|
||||
node.nodes.map(function (n) { return _this._handleTreeMessage(n); });
|
||||
|
||||
node.nodes.map(n => this._handleTreeMessage(n));
|
||||
this.notify('workspaces');
|
||||
break;
|
||||
case 'con':
|
||||
|
|
@ -393,25 +385,16 @@ var Sway = /** @class */ (function (_super) {
|
|||
this._active.client.updateProperty('id', node.id);
|
||||
this._active.client.updateProperty('name', node.name);
|
||||
this._active.client.updateProperty('class', node.shell === 'xwayland'
|
||||
? ((_e = node.window_properties) === null || _e === void 0 ? void 0 : _e.class) || ''
|
||||
: node.app_id);
|
||||
? node.window_properties?.class || ''
|
||||
: node.app_id,
|
||||
);
|
||||
}
|
||||
node.nodes.map(function (n) { return _this._handleTreeMessage(n); });
|
||||
node.nodes.map(n => this._handleTreeMessage(n));
|
||||
this.notify('clients');
|
||||
break;
|
||||
}
|
||||
};
|
||||
return Sway;
|
||||
}(service_js_1.default));
|
||||
exports.Sway = Sway;
|
||||
_d = Sway;
|
||||
(function () {
|
||||
service_js_1.default.register(_d, {}, {
|
||||
'active': ['jsobject'],
|
||||
'monitors': ['jsobject'],
|
||||
'workspaces': ['jsobject'],
|
||||
'clients': ['jsobject'],
|
||||
});
|
||||
})();
|
||||
exports.sway = new Sway;
|
||||
exports.default = exports.sway;
|
||||
}
|
||||
}
|
||||
|
||||
export const sway = new Sway;
|
||||
export default sway;
|
||||
|
|
@ -11,8 +11,11 @@ const OptionalWorkspaces = async () => {
|
|||
try {
|
||||
return (await import('./workspaces_hyprland.js')).default();
|
||||
} catch {
|
||||
// return (await import('./workspaces_sway.js')).default();
|
||||
return null;
|
||||
try {
|
||||
return (await import('./workspaces_sway.js')).default();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,58 +1,184 @@
|
|||
const { GLib, Gdk, Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
const Cairo = imports.cairo;
|
||||
const Pango = imports.gi.Pango;
|
||||
const PangoCairo = imports.gi.PangoCairo;
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Sway from "../../services/sway.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import options from "../../options.js";
|
||||
import { range } from "../../utils.js";
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, DrawingArea, EventBox } = Widget;
|
||||
|
||||
const NUM_OF_WORKSPACES = 10;
|
||||
const dummyWs = Box({ className: 'bar-ws' }); // Not shown. Only for getting size props
|
||||
const dummyActiveWs = Box({ className: 'bar-ws bar-ws-active' }); // Not shown. Only for getting size props
|
||||
const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not shown. Only for getting size props
|
||||
|
||||
const dispatch = (arg) => Utils.execAsync(`swaymsg workspace ${arg}`);
|
||||
const switchToWorkspace = (arg) => Utils.execAsync(`swaymsg workspace ${arg}`).catch(print);
|
||||
const switchToRelativeWorkspace = (self, num) =>
|
||||
execAsync([`${App.configDir}/scripts/sway/swayToRelativeWs.sh`, `${num}`]).catch(print);
|
||||
|
||||
const Workspaces = () => {
|
||||
const ws = options.workspaces.value || 20;
|
||||
return Widget.Box({
|
||||
children: range(ws).map((i) =>
|
||||
Widget.Button({
|
||||
setup: (btn) => (btn.id = i),
|
||||
on_clicked: () => dispatch(i),
|
||||
child: Widget.Label({
|
||||
label: `${i}`,
|
||||
class_name: "indicator",
|
||||
vpack: "center",
|
||||
}),
|
||||
setup: (self) => self.hook(Sway, (btn) => {
|
||||
btn.toggleClassName("active", Sway.active.workspace.name == i);
|
||||
btn.toggleClassName(
|
||||
"occupied",
|
||||
Sway.getWorkspace(`${i}`)?.nodes.length > 0,
|
||||
);
|
||||
}),
|
||||
const WorkspaceContents = (count = 10) => {
|
||||
return DrawingArea({
|
||||
css: `transition: 90ms cubic-bezier(0.1, 1, 0, 1);`,
|
||||
attribute: {
|
||||
initialized: false,
|
||||
workspaceMask: 0,
|
||||
updateMask: (self) => {
|
||||
if (self.attribute.initialized) return; // We only need this to run once
|
||||
const workspaces = Sway.workspaces;
|
||||
let workspaceMask = 0;
|
||||
// console.log('----------------')
|
||||
for (let i = 0; i < workspaces.length; i++) {
|
||||
const ws = workspaces[i];
|
||||
// console.log(ws.name, ',', ws.num);
|
||||
if (!Number(ws.name)) return;
|
||||
const id = Number(ws.name);
|
||||
if (id <= 0) continue; // Ignore scratchpads
|
||||
if (id > count) return; // Not rendered
|
||||
if (workspaces[i].windows > 0) {
|
||||
workspaceMask |= (1 << id);
|
||||
}
|
||||
}
|
||||
self.attribute.workspaceMask = workspaceMask;
|
||||
self.attribute.initialized = true;
|
||||
},
|
||||
toggleMask: (self, occupied, name) => {
|
||||
if (occupied) self.attribute.workspaceMask |= (1 << parseInt(name));
|
||||
else self.attribute.workspaceMask &= ~(1 << parseInt(name));
|
||||
},
|
||||
},
|
||||
setup: (area) => area
|
||||
.hook(Sway.active.workspace, (area) => {
|
||||
area.setCss(`font-size: ${Sway.active.workspace.name}px;`)
|
||||
})
|
||||
),
|
||||
setup: (self) => self.hook(Sway.active.workspace,
|
||||
(box) => box.children.map((btn) => {
|
||||
btn.visible = Sway.workspaces.some(
|
||||
(ws) => ws.name == btn.id,
|
||||
);
|
||||
})
|
||||
),
|
||||
});
|
||||
};
|
||||
.hook(Sway, (self) => self.attribute.updateMask(self), 'notify::workspaces')
|
||||
// .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, true, name), 'workspace-added')
|
||||
// .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, false, name), 'workspace-removed')
|
||||
.on('draw', Lang.bind(area, (area, cr) => {
|
||||
const allocation = area.get_allocation();
|
||||
const { width, height } = allocation;
|
||||
|
||||
export default () => Widget.EventBox({
|
||||
class_name: "workspaces panel-button",
|
||||
child: Widget.Box({
|
||||
// its nested like this to keep it consistent with other PanelButton widgets
|
||||
child: Widget.EventBox({
|
||||
on_scroll_up: () => dispatch("next"),
|
||||
on_scroll_down: () => dispatch("prev"),
|
||||
class_name: "eventbox",
|
||||
// binds: [["child", options.workspaces, "value", Workspaces]],
|
||||
setup: (self) => self
|
||||
.hook(options.workspaces, (self) => Selection.child = Workspaces(), "value")
|
||||
,
|
||||
}),
|
||||
const workspaceStyleContext = dummyWs.get_style_context();
|
||||
const workspaceDiameter = workspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const workspaceRadius = workspaceDiameter / 2;
|
||||
const workspaceFontSize = workspaceStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 4 * 3;
|
||||
const workspaceFontFamily = workspaceStyleContext.get_property('font-family', Gtk.StateFlags.NORMAL);
|
||||
const wsbg = workspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const wsfg = workspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const occupiedWorkspaceStyleContext = dummyOccupiedWs.get_style_context();
|
||||
const occupiedbg = occupiedWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const occupiedfg = occupiedWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWorkspaceStyleContext = dummyActiveWs.get_style_context();
|
||||
const activebg = activeWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const activefg = activeWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
area.set_size_request(workspaceDiameter * count, -1);
|
||||
const widgetStyleContext = area.get_style_context();
|
||||
const activeWs = widgetStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWsCenterX = -(workspaceDiameter / 2) + (workspaceDiameter * activeWs);
|
||||
const activeWsCenterY = height / 2;
|
||||
|
||||
// Font
|
||||
const layout = PangoCairo.create_layout(cr);
|
||||
const fontDesc = Pango.font_description_from_string(`${workspaceFontFamily[0]} ${workspaceFontSize}`);
|
||||
layout.set_font_description(fontDesc);
|
||||
cr.setAntialias(Cairo.Antialias.BEST);
|
||||
// Get kinda min radius for number indicators
|
||||
layout.set_text("0".repeat(count.toString().length), -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const indicatorRadius = Math.max(layoutWidth, layoutHeight) / 2 * 1.2; // a bit smaller than sqrt(2)*radius
|
||||
const indicatorGap = workspaceRadius - indicatorRadius;
|
||||
|
||||
// Draw workspace numbers
|
||||
for (let i = 1; i <= count; i++) {
|
||||
if (area.attribute.workspaceMask & (1 << i)) {
|
||||
// Draw bg highlight
|
||||
cr.setSourceRGBA(occupiedbg.red, occupiedbg.green, occupiedbg.blue, occupiedbg.alpha);
|
||||
const wsCenterX = -(workspaceRadius) + (workspaceDiameter * i);
|
||||
const wsCenterY = height / 2;
|
||||
if (!(area.attribute.workspaceMask & (1 << (i - 1)))) { // Left
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, 0.5 * Math.PI, 1.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX - workspaceRadius, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
if (!(area.attribute.workspaceMask & (1 << (i + 1)))) { // Right
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, -0.5 * Math.PI, 0.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
|
||||
// Set color for text
|
||||
cr.setSourceRGBA(occupiedfg.red, occupiedfg.green, occupiedfg.blue, occupiedfg.alpha);
|
||||
}
|
||||
else
|
||||
cr.setSourceRGBA(wsfg.red, wsfg.green, wsfg.blue, wsfg.alpha);
|
||||
layout.set_text(`${i}`, -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const x = -workspaceRadius + (workspaceDiameter * i) - (layoutWidth / 2);
|
||||
const y = (height - layoutHeight) / 2;
|
||||
cr.moveTo(x, y);
|
||||
// cr.showText(text);
|
||||
PangoCairo.show_layout(cr, layout);
|
||||
cr.stroke();
|
||||
}
|
||||
|
||||
// Draw active ws
|
||||
// base
|
||||
cr.setSourceRGBA(activebg.red, activebg.green, activebg.blue, activebg.alpha);
|
||||
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
// inner decor
|
||||
cr.setSourceRGBA(activefg.red, activefg.green, activefg.blue, activefg.alpha);
|
||||
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius * 0.2, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
}))
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
export default () => EventBox({
|
||||
onScrollUp: (self) => switchToRelativeWorkspace(self, -1),
|
||||
onScrollDown: (self) => switchToRelativeWorkspace(self, +1),
|
||||
onMiddleClickRelease: () => App.toggleWindow('overview'),
|
||||
onSecondaryClickRelease: () => App.toggleWindow('osk'),
|
||||
attribute: { clicked: false },
|
||||
child: Box({
|
||||
homogeneous: true,
|
||||
className: 'bar-group-margin',
|
||||
children: [Box({
|
||||
className: 'bar-group bar-group-standalone bar-group-pad',
|
||||
css: 'min-width: 2px;',
|
||||
children: [
|
||||
WorkspaceContents(10),
|
||||
]
|
||||
})]
|
||||
}),
|
||||
setup: (self) => {
|
||||
console.log('[LOG] Sway workspace module loaded')
|
||||
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
|
||||
self.on('motion-notify-event', (self, event) => {
|
||||
if (!self.attribute.clicked) return;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth);
|
||||
switchToWorkspace(wsId);
|
||||
})
|
||||
self.on('button-press-event', (self, event) => {
|
||||
if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here
|
||||
self.attribute.clicked = true;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth);
|
||||
switchToWorkspace(wsId);
|
||||
})
|
||||
self.on('button-release-event', (self) => self.attribute.clicked = false);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue