diff options
author | Aylur <[email protected]> | 2024-09-01 14:17:36 +0200 |
---|---|---|
committer | Aylur <[email protected]> | 2024-09-01 14:17:36 +0200 |
commit | 3e3f045d650a839d21f7b649da7aa5c19bd2e38b (patch) | |
tree | 9a974eb0d38932d474940288c662bd1f01ea3088 /lib/hyprland | |
parent | 408faee16911ccfaa3e7dad69f9938fd4a696704 (diff) |
monorepo structuring
Diffstat (limited to 'lib/hyprland')
-rw-r--r-- | lib/hyprland/cli.vala | 42 | ||||
-rw-r--r-- | lib/hyprland/client.vala | 75 | ||||
-rw-r--r-- | lib/hyprland/config.vala.in | 6 | ||||
-rw-r--r-- | lib/hyprland/hyprland.vala | 451 | ||||
-rw-r--r-- | lib/hyprland/meson.build | 99 | ||||
-rw-r--r-- | lib/hyprland/meson_options.txt | 11 | ||||
-rw-r--r-- | lib/hyprland/monitor.vala | 71 | ||||
-rw-r--r-- | lib/hyprland/structs.vala | 42 | ||||
-rw-r--r-- | lib/hyprland/version | 1 | ||||
-rw-r--r-- | lib/hyprland/workspace.vala | 57 |
10 files changed, 855 insertions, 0 deletions
diff --git a/lib/hyprland/cli.vala b/lib/hyprland/cli.vala new file mode 100644 index 0000000..a68d63b --- /dev/null +++ b/lib/hyprland/cli.vala @@ -0,0 +1,42 @@ +static bool help; +static bool version; + +const OptionEntry[] options = { + { "version", 'v', OptionFlags.NONE, OptionArg.NONE, ref version, null, null }, + { "help", 'h', OptionFlags.NONE, OptionArg.NONE, ref help, null, null }, + { null }, +}; + +int main(string[] argv) { + try { + var opts = new OptionContext(); + opts.add_main_entries(options, null); + opts.set_help_enabled(false); + opts.set_ignore_unknown_options(false); + opts.parse(ref argv); + } catch (OptionError err) { + printerr (err.message); + return 1; + } + + if (help) { + print("Usage:\n"); + print(" %s [flags]\n\n", argv[0]); + print("Flags:\n"); + print(" -h, --help Print this help and exit\n"); + print(" -v, --version Print version number and exit\n"); + return 0; + } + + if (version) { + print(AstalHyprland.VERSION); + return 0; + } + + AstalHyprland.Hyprland.get_default().event.connect((event, args) => { + print("{ event: \"%s\", payload: \"%s\" }\n", event, args); + }); + + new MainLoop(null, false).run(); + return 0; +} diff --git a/lib/hyprland/client.vala b/lib/hyprland/client.vala new file mode 100644 index 0000000..6456667 --- /dev/null +++ b/lib/hyprland/client.vala @@ -0,0 +1,75 @@ +namespace AstalHyprland { +public class Client : Object { + public signal void removed (); + public signal void moved_to (Workspace workspace); + + public string address { get; private set; } + public bool mapped { get; private set; } + public bool hidden { get; private set; } + public int x { get; private set; } + public int y { get; private set; } + public int width { get; private set; } + public int height { get; private set; } + public Workspace workspace { get; private set; } + public bool floating { get; private set; } + public Monitor monitor { get; private set; } + public string class { get; private set; } + public string title { get; private set; } + public string initial_class { get; private set; } + public string initial_title { get; private set; } + public uint pid { get; private set; } + public bool xwayland { get; private set; } + public bool pinned { get; private set; } + public bool fullscreen { get; private set; } + public int fullscreen_mode { get; private set; } + public bool fake_fullscreen { get; private set; } + // TODO: public Group[] grouped { get; private set; } + // TODO: public Tag[] tags { get; private set; } + public string swallowing { get; private set; } + public int focus_history_id { get; private set; } + + internal void sync(Json.Object obj) { + var hyprland = Hyprland.get_default(); + + address = obj.get_string_member("address").replace("0x", ""); + mapped = obj.get_boolean_member("mapped"); + hidden = obj.get_boolean_member("hidden"); + floating = obj.get_boolean_member("floating"); + class = obj.get_string_member("class"); + title = obj.get_string_member("title"); + initial_title = obj.get_string_member("initialTitle"); + initial_class = obj.get_string_member("initialClass"); + pid = (uint)obj.get_int_member("pid"); + xwayland = obj.get_boolean_member("xwayland"); + pinned = obj.get_boolean_member("pinned"); + fullscreen = obj.get_boolean_member("fullscreen"); + fullscreen_mode = (int)obj.get_int_member("fullscreenMode"); // is this used? + fake_fullscreen = obj.get_boolean_member("fakeFullscreen"); + swallowing = obj.get_string_member("swallowing"); + focus_history_id = (int)obj.get_int_member("focusHistoryID"); + x = (int)obj.get_array_member("at").get_int_element(0); + y = (int)obj.get_array_member("at").get_int_element(1); + width = (int)obj.get_array_member("size").get_int_element(0); + height = (int)obj.get_array_member("size").get_int_element(1); + + workspace = hyprland.get_workspace((int)obj.get_object_member("workspace").get_int_member("id")); + monitor = hyprland.get_monitor((int)obj.get_int_member("monitor")); + } + + public void kill() { + Hyprland.get_default().dispatch("closewindow", "address:" + "0x" + address); + } + + public void focus() { + Hyprland.get_default().dispatch("focuswindow", "address:" + "0x" + address); + } + + public void move_to(Workspace ws) { + Hyprland.get_default().dispatch("movetoworkspacesilent", ws.id.to_string() + ",address:" + "0x" + address); + } + + public void toggle_floating() { + Hyprland.get_default().dispatch("togglefloating", "address:" + "0x" + address); + } +} +} diff --git a/lib/hyprland/config.vala.in b/lib/hyprland/config.vala.in new file mode 100644 index 0000000..65993b2 --- /dev/null +++ b/lib/hyprland/config.vala.in @@ -0,0 +1,6 @@ +namespace AstalHyprland { + public const int MAJOR_VERSION = @MAJOR_VERSION@; + public const int MINOR_VERSION = @MINOR_VERSION@; + public const int MICRO_VERSION = @MICRO_VERSION@; + public const string VERSION = "@VERSION@"; +} diff --git a/lib/hyprland/hyprland.vala b/lib/hyprland/hyprland.vala new file mode 100644 index 0000000..5359d2e --- /dev/null +++ b/lib/hyprland/hyprland.vala @@ -0,0 +1,451 @@ +namespace AstalHyprland { +public Hyprland get_default() { + return Hyprland.get_default(); +} + +public class Hyprland : Object { + private static string HIS = GLib.Environment.get_variable("HYPRLAND_INSTANCE_SIGNATURE"); + private static string RUN_DIR = GLib.Environment.get_user_runtime_dir(); + + private static Hyprland _instance; + public static Hyprland? get_default() { + if (_instance != null) + return _instance; + + var HIS = GLib.Environment.get_variable("HYPRLAND_INSTANCE_SIGNATURE"); + if (HIS == null) { + critical("Hyprland is not running"); + return null; + } + + var h = new Hyprland(); + _instance = h; + + h.socket2 = h.connection("socket2"); + h.watch_socket(new DataInputStream(h.socket2.input_stream)); + try { + h.init(); + } catch (Error err) { + critical("could not initialize: %s", err.message); + return null; + } + + return _instance; + } + + // monitors, workspaces, clients + private HashTable<int, Monitor> _monitors = + new HashTable<int, Monitor>((i) => i, (a, b) => a == b); + + private HashTable<int, Workspace> _workspaces = + new HashTable<int, Workspace>((i) => i, (a, b) => a == b); + + private HashTable<string, Client> _clients = + new HashTable<string, Client>(str_hash, str_equal); + + public List<weak Monitor> monitors { owned get { return _monitors.get_values(); } } + public List<weak Workspace> workspaces { owned get { return _workspaces.get_values(); } } + public List<weak Client> clients { owned get { return _clients.get_values(); } } + + public Monitor get_monitor(int id) { return _monitors.get(id); } + public Workspace get_workspace(int id) { return _workspaces.get(id); } + public Client? get_client(string address) { + if (address == "" || address == null) + return null; + + if (address.substring(0, 2) == "0x") + return _clients.get(address.substring(2, -1)); + + return _clients.get(address); + } + + public Monitor? get_monitor_by_name(string name) { + foreach (var mon in monitors) { + if (mon.name == name) + return mon; + } + return null; + } + + public Workspace? get_workspace_by_name(string name) { + foreach (var ws in workspaces) { + if (ws.name == name) + return ws; + } + return null; + } + + public Workspace focused_workspace { get; private set; } + public Monitor focused_monitor { get; private set; } + public Client focused_client { get; private set; } + + // other props + public List<Bind> binds { + owned get { + var list = new List<Bind>(); + try { + var arr = Json.from_string(message("j/binds")).get_array(); + foreach (var b in arr.get_elements()) + list.append(new Bind.from_json(b.get_object())); + } catch (Error err) { + critical(err.message); + } + return list; + } + } + + public Position cursor_position { + owned get { + return new Position.cursorpos(message("cursorpos")); + } + } + + // signals + public signal void event (string event, string args); + + // TODO: nag vaxry for fullscreenv2 + // public signal void fullscreen (bool fullscreen); + public signal void minimize (Client client, bool minimize); + public signal void floating (Client client, bool floating); + public signal void urgent (Client client); + public signal void client_moved (Client client, Workspace ws); + + public signal void submap (string name); + public signal void keyboard_layout (string keyboard, string layout); + public signal void config_reloaded (); + + // state + public signal void client_added (Client client); + public signal void client_removed (string address); + public signal void workspace_added (Workspace workspace); + public signal void workspace_removed (int id); + public signal void monitor_added (Monitor monitor); + public signal void monitor_removed (int id); + + private SocketConnection socket2; + + private SocketConnection? connection(string socket) { + var path = RUN_DIR + "/hypr/" + HIS + "/." + socket + ".sock"; + try { + return new SocketClient().connect(new UnixSocketAddress(path), null); + } catch (Error err) { + critical(err.message); + return null; + } + } + + private void watch_socket(DataInputStream stream) { + stream.read_line_async.begin(Priority.DEFAULT, null, (_, res) => { + try { + var line = stream.read_line_async.end(res); + handle_event.begin(line, (_, res) => { + try { + handle_event.end(res); + } catch (Error err) { + critical(err.message); + } + }); + watch_socket(stream); + } catch (Error err) { + critical(err.message); + } + }); + } + + private void write_socket( + string message, + out SocketConnection conn, + out DataInputStream stream + ) throws Error { + conn = connection("socket"); + conn.output_stream.write(message.data, null); + stream = new DataInputStream(conn.input_stream); + } + + public string message(string message) { + SocketConnection conn; + DataInputStream stream; + try { + write_socket(message, out conn, out stream); + return stream.read_upto("\x04", -1, null, null); + } catch (Error err) { + critical(err.message); + } finally { + try { + if (conn != null) + conn.close(null); + } catch (Error err) { + critical(err.message); + } + } + return ""; + } + + public async string message_async(string message) { + SocketConnection conn; + DataInputStream stream; + try { + write_socket(message, out conn, out stream); + return yield stream.read_upto_async("\x04", -1, Priority.DEFAULT, null, null); + } catch (Error err) { + critical(err.message); + } finally { + try { + conn.close(null); + } catch (Error err) { + critical(err.message); + } + } + return ""; + } + + public void dispatch(string dispatcher, string args) { + var msg = "dispatch " + dispatcher + " " + args; + message_async.begin(msg, (_, res) => { + var err = message_async.end(res); + if (err != "ok") + critical("dispatch error: %s", err); + }); + } + + public void move_cursor(int x, int y) { + dispatch("movecursor", x.to_string() + " " + y.to_string()); + + } + + // TODO: nag vaxry to make socket events and hyprctl more consistent + private void init() throws Error { + var mons = Json.from_string(message("j/monitors")).get_array(); + var wrkspcs = Json.from_string(message("j/workspaces")).get_array(); + var clnts = Json.from_string(message("j/clients")).get_array(); + + // create + foreach (var mon in mons.get_elements()) { + var id = (int)mon.get_object().get_member("id").get_int(); + var m = new Monitor(); + _monitors.insert(id, m); + + if (mon.get_object().get_member("focused").get_boolean()) + focused_monitor = m; + } + foreach (var wrkpsc in wrkspcs.get_elements()) { + var id = (int)wrkpsc.get_object().get_member("id").get_int(); + _workspaces.set(id, new Workspace()); + } + foreach (var clnt in clnts.get_elements()) { + var addr = clnt.get_object().get_member("address").get_string(); + _clients.set(addr.replace("0x", ""), new Client()); + } + + // init + foreach (var c in clnts.get_elements()) { + var addr = c.get_object().get_member("address").get_string(); + get_client(addr).sync(c.get_object()); + } + foreach (var ws in wrkspcs.get_elements()) { + var id = (int)ws.get_object().get_member("id").get_int(); + get_workspace(id).sync(ws.get_object()); + } + foreach (var mon in mons.get_elements()) { + var id = (int)mon.get_object().get_member("id").get_int(); + get_monitor(id).sync(mon.get_object()); + } + + // focused + focused_workspace = get_workspace((int)Json.from_string(message("j/activeworkspace")) + .get_object().get_member("id").get_int()); + + focused_client = get_client(Json.from_string(message("j/activewindow")) + .get_object().get_member("address").get_string()); + } + + ~Hyprland() { + if (socket2 != null) { + try { + socket2.close(null); + } catch (Error err) { + critical(err.message); + } + } + } + + public async void sync_monitors() throws Error { + var str = yield message_async("j/monitors"); + var arr = Json.from_string(str).get_array(); + foreach (var obj in arr.get_elements()) { + var id = (int)obj.get_object().get_int_member("id"); + var m = get_monitor(id); + if (m != null) + m.sync(obj.get_object()); + } + } + + public async void sync_workspaces() throws Error { + var str = yield message_async("j/workspaces"); + var arr = Json.from_string(str).get_array(); + foreach (var obj in arr.get_elements()) { + var id = (int)obj.get_object().get_int_member("id"); + var ws = get_workspace(id); + if (ws != null) + ws.sync(obj.get_object()); + + } + } + + public async void sync_clients() throws Error { + var str = yield message_async("j/clients"); + var arr = Json.from_string(str).get_array(); + foreach (var obj in arr.get_elements()) { + var addr = obj.get_object().get_string_member("address"); + var c = get_client(addr); + if (c != null) + c.sync(obj.get_object()); + } + } + + private async void handle_event(string line) throws Error { + var args = line.split(">>"); + + switch (args[0]) { + case "workspacev2": + focused_workspace = get_workspace(int.parse(args[1])); + break; + + case "focusedmon": + var argv = args[1].split(",", 2); + focused_monitor = get_monitor_by_name(argv[0]); + focused_workspace = get_workspace_by_name(argv[1]); + break; + + case "activewindowv2": + focused_client = get_client(args[1]); + break; + + // TODO: nag vaxry for fullscreenv2 that passes address + case "fullscreen": + yield sync_clients(); + break; + + case "monitorremoved": + var id = get_monitor_by_name(args[1]).id; + _monitors.get(id).removed(); + _monitors.remove(id); + monitor_removed(id); + notify_property("monitors"); + break; + + case "monitoraddedv2": + var id = int.parse(args[1].split(",", 2)[0]); + var mon = new Monitor(); + _monitors.insert(id, mon); + yield sync_monitors(); + monitor_added(mon); + notify_property("monitors"); + break; + + case "createworkspacev2": + var id = int.parse(args[1].split(",", 2)[0]); + var ws = new Workspace(); + _workspaces.insert(id, ws); + yield sync_workspaces(); + workspace_added(ws); + notify_property("workspaces"); + break; + + case "destroyworkspacev2": + var id = int.parse(args[1].split(",", 2)[0]); + _workspaces.get(id).removed(); + _workspaces.remove(id); + workspace_removed(id); + notify_property("workspaces"); + break; + + case "moveworkspacev2": + yield sync_workspaces(); + yield sync_monitors(); + break; + + case "renameworkspace": + yield sync_workspaces(); + break; + + case "activespecial": + yield sync_monitors(); + yield sync_workspaces(); + break; + + case "activelayout": + var argv = args[1].split(","); + keyboard_layout(argv[0], argv[1]); + break; + + case "openwindow": + var addr = args[1].split(",")[0]; + var client = new Client(); + _clients.insert(addr, client); + yield sync_clients(); + yield sync_workspaces(); + client_added(client); + notify_property("clients"); + break; + + case "closewindow": + _clients.get(args[1]).removed(); + _clients.remove(args[1]); + client_removed(args[1]); + yield sync_workspaces(); + notify_property("clients"); + break; + + case "movewindowv2": + yield sync_clients(); + yield sync_workspaces(); + var argv = args[1].split(","); + client_moved(get_client(argv[0]), get_workspace(int.parse(argv[1]))); + get_client(argv[0]).moved_to(get_workspace(int.parse(argv[1]))); + break; + + case "submap": + submap(args[1]); + break; + + case "changefloatingmode": + var argv = args[1].split(","); + yield sync_clients(); + floating(get_client(argv[0]), argv[1] == "0"); + break; + + case "urgent": + urgent(get_client(args[1])); + break; + + case "minimize": + var argv = args[1].split(","); + yield sync_clients(); + minimize(get_client(argv[0]), argv[1] == "0"); + break; + + case "windowtitle": + yield sync_clients(); + break; + + // TODO: + case "togglegroup": + case "moveintogroup": + case "moveoutofgroup": + case "ignoregrouplock": + case "lockgroups": + break; + + case "configreloaded": + config_reloaded(); + break; + + default: + break; + } + + event(args[0], args[1]); + } +} +} diff --git a/lib/hyprland/meson.build b/lib/hyprland/meson.build new file mode 100644 index 0000000..7112ee1 --- /dev/null +++ b/lib/hyprland/meson.build @@ -0,0 +1,99 @@ +project( + 'astal-hyprland', + 'vala', + 'c', + version: run_command('cat', join_paths(meson.project_source_root(), 'version')).stdout().strip(), + meson_version: '>= 0.62.0', + default_options: [ + 'warning_level=2', + 'werror=false', + 'c_std=gnu11', + ], +) + +assert( + get_option('lib') or get_option('cli'), + 'Either lib or cli option must be set to true.', +) + +version_split = meson.project_version().split('.') +api_version = version_split[0] + '.' + version_split[1] +gir = 'AstalHyprland-' + api_version + '.gir' +typelib = 'AstalHyprland-' + api_version + '.typelib' + +config = configure_file( + input: 'config.vala.in', + output: 'config.vala', + configuration: { + 'VERSION': meson.project_version(), + 'MAJOR_VERSION': version_split[0], + 'MINOR_VERSION': version_split[1], + 'MICRO_VERSION': version_split[2], + }, +) + +deps = [ + dependency('glib-2.0'), + dependency('gobject-2.0'), + dependency('gio-2.0'), + dependency('gio-unix-2.0'), + dependency('json-glib-1.0'), +] + +sources = [ + config, + 'client.vala', + 'cli.vala', + 'hyprland.vala', + 'monitor.vala', + 'structs.vala', + 'workspace.vala', +] + +if get_option('lib') + lib = library( + meson.project_name(), + sources, + dependencies: deps, + vala_header: meson.project_name() + '.h', + vala_vapi: meson.project_name() + '-' + api_version + '.vapi', + vala_gir: gir, + version: meson.project_version(), + install: true, + install_dir: [true, true, true, true], + ) + + import('pkgconfig').generate( + lib, + name: meson.project_name(), + filebase: meson.project_name() + '-' + api_version, + version: meson.project_version(), + subdirs: meson.project_name(), + requires: deps, + install_dir: get_option('libdir') / 'pkgconfig', + ) + + custom_target( + typelib, + command: [ + find_program('g-ir-compiler'), + '--output', '@OUTPUT@', + '--shared-library', get_option('prefix') / get_option('libdir') / '@PLAINNAME@', + meson.current_build_dir() / gir, + ], + input: lib, + output: typelib, + depends: lib, + install: true, + install_dir: get_option('libdir') / 'girepository-1.0', + ) +endif + +if get_option('cli') + executable( + meson.project_name(), + ['cli.vala', sources], + dependencies: deps, + install: true, + ) +endif diff --git a/lib/hyprland/meson_options.txt b/lib/hyprland/meson_options.txt new file mode 100644 index 0000000..f110242 --- /dev/null +++ b/lib/hyprland/meson_options.txt @@ -0,0 +1,11 @@ +option( + 'lib', + type: 'boolean', + value: true, +) + +option( + 'cli', + type: 'boolean', + value: true, +) diff --git a/lib/hyprland/monitor.vala b/lib/hyprland/monitor.vala new file mode 100644 index 0000000..d7b8028 --- /dev/null +++ b/lib/hyprland/monitor.vala @@ -0,0 +1,71 @@ +namespace AstalHyprland { +public class Monitor : Object { + public signal void removed (); + + public int id { get; private set; } + public string name { get; private set; } + public string description { get; private set; } + public string make { get; private set; } + public string model { get; private set; } + public string serial { get; private set; } + public int width { get; private set; } + public int height { get; private set; } + public double refresh_rate { get; private set; } + public int x { get; private set; } + public int y { get; private set; } + public Workspace active_workspace { get; private set; } + public Workspace special_workspace { get; private set; } + public int reserved_top { get; private set; } + public int reserved_bottom { get; private set; } + public int reserved_left { get; private set; } + public int reserved_right { get; private set; } + public double scale { get; private set; } + public bool focused { get; private set; } + public bool dpms_status { get; private set; } + public bool vrr { get; private set; } + public bool actively_tearing { get; private set; } + public bool disabled { get; private set; } + public string current_format { get; private set; } + public Array<string> available_modes { get; private set; } + + internal void sync(Json.Object obj) { + var hyprland = Hyprland.get_default(); + + id = (int)obj.get_int_member("id"); + name = obj.get_string_member("name"); + description = obj.get_string_member("description"); + make = obj.get_string_member("make"); + model = obj.get_string_member("model"); + serial = obj.get_string_member("serial"); + width = (int)obj.get_int_member("width"); + height = (int)obj.get_int_member("height"); + refresh_rate = obj.get_double_member("refreshRate"); + x = (int)obj.get_int_member("x"); + y = (int)obj.get_int_member("y"); + scale = obj.get_double_member("scale"); + focused = obj.get_boolean_member("focused"); + dpms_status = obj.get_boolean_member("dpmsStatus"); + vrr = obj.get_boolean_member("vrr"); + actively_tearing = obj.get_boolean_member("activelyTearing"); + disabled = obj.get_boolean_member("disabled"); + current_format = obj.get_string_member("currentFormat"); + + var r = obj.get_array_member("reserved"); + reserved_top = (int)r.get_int_element(0); + reserved_bottom = (int)r.get_int_element(1); + reserved_left = (int)r.get_int_element(2); + reserved_right = (int)r.get_int_element(3); + + var modes = new Array<string>(); + foreach (var mode in obj.get_array_member("availableModes").get_elements()) + modes.append_val(mode.get_string()); + + active_workspace = hyprland.get_workspace((int)obj.get_object_member("activeWorkspace").get_int_member("id")); + special_workspace = hyprland.get_workspace((int)obj.get_object_member("specialWorkspace").get_int_member("id")); + } + + public void focus() { + Hyprland.get_default().dispatch("focusmonitor", id.to_string()); + } +} +} diff --git a/lib/hyprland/structs.vala b/lib/hyprland/structs.vala new file mode 100644 index 0000000..25f70c3 --- /dev/null +++ b/lib/hyprland/structs.vala @@ -0,0 +1,42 @@ +namespace AstalHyprland { +public class Bind : Object { + public bool locked { get; construct set; } + public bool mouse { get; construct set; } + public bool release { get; construct set; } + public bool repeat { get; construct set; } + public bool non_consuming { get; construct set; } + public int64 modmask { get; construct set; } + public string submap { get; construct set; } + public string key { get; construct set; } + public int64 keycode { get; construct set; } + public bool catch_all { get; construct set; } + public string dispatcher { get; construct set; } + public string arg { get; construct set; } + + internal Bind.from_json(Json.Object obj) { + locked = obj.get_boolean_member("locked"); + mouse = obj.get_boolean_member("mouse"); + release = obj.get_boolean_member("release"); + repeat = obj.get_boolean_member("repeat"); + non_consuming = obj.get_boolean_member("non_consuming"); + modmask = obj.get_int_member("modmask"); + submap = obj.get_string_member("submap"); + key = obj.get_string_member("key"); + keycode = obj.get_int_member("keycode"); + catch_all = obj.get_boolean_member("catch_all"); + dispatcher = obj.get_string_member("dispatcher"); + arg = obj.get_string_member("arg"); + } +} + +public class Position : Object { + public int x { get; construct set; } + public int y { get; construct set; } + + internal Position.cursorpos(string pos) { + var xy = pos.split(","); + x = int.parse(xy[0].strip()); + y = int.parse(xy[1].strip()); + } +} +} diff --git a/lib/hyprland/version b/lib/hyprland/version new file mode 100644 index 0000000..6e8bf73 --- /dev/null +++ b/lib/hyprland/version @@ -0,0 +1 @@ +0.1.0 diff --git a/lib/hyprland/workspace.vala b/lib/hyprland/workspace.vala new file mode 100644 index 0000000..075f86f --- /dev/null +++ b/lib/hyprland/workspace.vala @@ -0,0 +1,57 @@ +namespace AstalHyprland { +public class Workspace : Object { + public signal void removed (); + + public List<weak Client> _clients = new List<weak Client>(); + + public int id { get; private set; } + public string name { get; private set; } + public Monitor monitor { get; private set; } + public List<weak Client> clients { owned get { return _clients.copy(); } } + public bool has_fullscreen { get; private set; } + public Client last_client { get; private set; } + + public Workspace.dummy(int id, Monitor? monitor) { + this.id = id; + this.name = id.to_string(); + this.monitor = monitor; + } + + internal List<weak Client> filter_clients() { + var hyprland = Hyprland.get_default(); + var list = new List<weak Client>(); + foreach (var client in hyprland.clients) { + if (client.workspace == this) { + list.append(client); + } + } + + return list; + } + + internal void sync(Json.Object obj) { + var hyprland = Hyprland.get_default(); + + id = (int)obj.get_int_member("id"); + name = obj.get_string_member("name"); + has_fullscreen = obj.get_boolean_member("hasfullscreen"); + + monitor = hyprland.get_monitor((int)obj.get_int_member("monitorID")); + last_client = hyprland.get_client(obj.get_string_member("lastwindow")); + + var list = filter_clients(); + if (_clients.length() != list.length()) { + _clients = list.copy(); + notify_property("clients"); + } + } + + public void focus() { + Hyprland.get_default().dispatch("workspace", id.to_string()); + } + + public void move_to(Monitor m) { + Hyprland.get_default().dispatch("moveworkspacetomonitor", id.to_string() + " " + m.id.to_string()); + } +} +} |