Skip to content

Instantly share code, notes, and snippets.

@atareao
Created December 8, 2023 07:26
Show Gist options
  • Save atareao/032be4a4920e281e35dca561bedee05e to your computer and use it in GitHub Desktop.
Save atareao/032be4a4920e281e35dca561bedee05e to your computer and use it in GitHub Desktop.
#!/usr/bin/gjs --include-path=.
'use strict';
imports.searchPath.unshift('.');
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const struct = imports.utils.struct;
const concatArrayBuffers = imports.utils.concatArrayBuffers;
const SWAYSOCK = GLib.getenv('SWAYSOCK');
const MAGIC = "i3-ipc";
const STRUCT_HEADER = "<6sII";
const STRUCT_HEADER_LENGTH = 14;
const socket_address = new Gio.UnixSocketAddress({path: SWAYSOCK});
console.log(socket_address);
class Sway{
#SWAYSOCK = GLib.getenv('SWAYSOCK');
#MAGIC = "i3-ipc";
#STRUCT_HEADER = "<6sII";
#STRUCT_HEADER_LENGTH = 14;
#MsgType = {
RUN_COMMAND: 0,
GET_WORKSPACES: 1,
SUBSCRIBE: 2,
GET_OUTPUTS: 3,
GET_TREE: 4,
GET_MARKS: 5,
GET_BAR_CONFG: 6,
GET_VERSION: 7,
GET_BINDING_MODES: 8,
GET_CONFIG: 9,
SEND_TICK: 10,
SYNC: 11,
GET_BINDING_STATE: 12
}
constructor(){
}
#pack(msg_type, payload){
console.log(`pack: ${msg_type} - ${payload}`);
const m = (new TextEncoder()).encode(this.#MAGIC);
const pb = (new TextEncoder()).encode(payload);
const s = new Uint8Array(struct("<II").pack(pb.length, msg_type));
return concatArrayBuffers(m, s, pb);
}
#unpack_header(data){
console.log("unpack_header");
const slice = data.slice(0, this.#STRUCT_HEADER_LENGTH);
return struct(this.#STRUCT_HEADER).unpack(slice.buffer);
}
#unpack(data){
console.log("unpack");
const [msg_magic, msg_length, msg_type] = this.#unpack_header(data)
const msg_size = this.#STRUCT_HEADER_LENGTH + msg_length;
const payload = data.slice(this.#STRUCT_HEADER_LENGTH, msg_size);
return (new TextDecoder()).decode(payload);
}
#recv(connection){
console.log(`recv: ${connection}`);
const input = connection.get_input_stream();
let data = input.read_bytes(this.#STRUCT_HEADER_LENGTH, null).get_data();
const [msg_magic, msg_length, msg_type] = this.#unpack_header(data);
const msg_size = this.#STRUCT_HEADER_LENGTH + msg_length;
console.log(data.length);
while(data.length < msg_size){
const new_input = input.read_bytes(msg_length, null).get_data();
const new_data = new Uint8Array(data.length + new_input.length)
new_data.set(data, 0);
new_data.set(new_input, data.length);
data = new_data;
}
const response = this.#unpack(data);
return JSON.parse(response);
}
#send(msg_type, payload=''){
let connection = null;
try {
let client = new Gio.SocketClient();
connection = client.connect(socket_address, null);
if (!connection) {
throw "Connection failed"
}
let output = connection.get_output_stream();
output.write_bytes(this.#pack(msg_type, payload), null);
const response = this.#recv(connection);
console.log(`Message type: ${msg_type}. Payload: ${payload}. Response: ${response}`);
return response
} catch (err) {
console.error(err);
return false;
}finally{
if (connection != null){
connection.close(null);
}
}
}
runCommand(command){
console.log("runCommand")
return this.#send(this.#MsgType.RUN_COMMAND, command);
}
getWorkspaces(){
console.log("getWorkspaces")
return this.#send(this.#MsgType.GET_WORKSPACES);
}
getOutputs(){
console.log("getOutputs")
return this.#send(this.#MsgType.GET_OUTPUTS);
}
}
const sway = new Sway();
console.log(sway.getWorkspaces());
console.log(sway.getOutputs());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment