aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Letan <lthms@soap.coffee>2022-08-27 16:35:15 +0200
committerThomas Letan <lthms@soap.coffee>2022-08-27 16:35:15 +0200
commitd1d43098a9121c315d9a602eb148f5f5668b1c5c (patch)
tree12889e017aa408a96436008f783bb4df3f5551ce
parentRename 'Spatial_sway_ipc' into 'Spatial_ipc' (diff)
Add a command to fetch the list of windows in the current workspace
-rw-r--r--bin/spatial/state.ml18
-rw-r--r--bin/spatialmsg/main.ml26
-rw-r--r--lib/spatial_ipc/dune2
-rw-r--r--lib/spatial_ipc/spatial_ipc.ml38
-rw-r--r--lib/spatial_ipc/spatial_ipc.mli8
5 files changed, 84 insertions, 8 deletions
diff --git a/bin/spatial/state.ml b/bin/spatial/state.ml
index f592b5b..8b67191 100644
--- a/bin/spatial/state.ml
+++ b/bin/spatial/state.ml
@@ -183,7 +183,23 @@ let client_command_handle :
true,
None )
in
- (Some res, ())
+ (Some res, { success = true })
+ | Get_windows -> (
+ let ribbon =
+ Workspaces_registry.find state.current_workspace state.workspaces
+ in
+ ( None,
+ match ribbon.visible with
+ | Some (f, l) ->
+ {
+ focus = Some f;
+ windows =
+ List.map
+ (fun id ->
+ (Windows_registry.find id state.windows).app_id)
+ (l @ ribbon.hidden);
+ }
+ | None -> { focus = None; windows = [] } ))
: _ * a)
let pp fmt state =
diff --git a/bin/spatialmsg/main.ml b/bin/spatialmsg/main.ml
index e5357d6..3c3062a 100644
--- a/bin/spatialmsg/main.ml
+++ b/bin/spatialmsg/main.ml
@@ -1,5 +1,27 @@
open Spatial_ipc
let () =
- let cmd = Sys.argv.(1) |> command_of_string_exn in
- Lwt_main.run (send_command (Run_command cmd))
+ Clap.description "A client to communicate with a Spatial instance.";
+
+ let ty = Clap.default_string ~short:'t' ~last:true "run_command" in
+
+ match ty with
+ | "run_command" ->
+ let cmd = Clap.mandatory_string ~placeholder:"CMD" () in
+ Clap.close ();
+
+ let cmd = command_of_string_exn cmd in
+ let { success } = Lwt_main.run (send_command (Run_command cmd)) in
+ if not success then exit 1
+ | "get_windows" ->
+ Clap.close ();
+
+ let reply = Lwt_main.run (send_command Get_windows) in
+ List.iteri
+ (fun idx name ->
+ Format.printf "- %s%s%s\n"
+ (if reply.focus = Some idx then "*" else "")
+ name
+ (if reply.focus = Some idx then "*" else ""))
+ reply.windows
+ | _ -> exit 2
diff --git a/lib/spatial_ipc/dune b/lib/spatial_ipc/dune
index fd055c2..f44e3d3 100644
--- a/lib/spatial_ipc/dune
+++ b/lib/spatial_ipc/dune
@@ -1,4 +1,4 @@
(library
(name spatial_ipc)
(public_name spatial-sway.ipc)
- (libraries mltp-ipc))
+ (libraries mltp-ipc data-encoding))
diff --git a/lib/spatial_ipc/spatial_ipc.ml b/lib/spatial_ipc/spatial_ipc.ml
index 66444c9..3c471ba 100644
--- a/lib/spatial_ipc/spatial_ipc.ml
+++ b/lib/spatial_ipc/spatial_ipc.ml
@@ -65,14 +65,44 @@ let command_to_string = function
| Maximize switch -> Format.sprintf "maximize %s" (switch_to_string switch)
| Split op -> Format.sprintf "split %s" (operation_to_string op)
-type 'a t = Run_command : command -> unit t
+type run_command_reply = { success : bool }
+
+let run_command_reply_encoding =
+ let open Data_encoding in
+ conv
+ (fun { success } -> success)
+ (fun success -> { success })
+ (obj1 (req "success" bool))
+
+type get_windows_reply = { focus : int option; windows : string list }
+
+let get_windows_reply_encoding : get_windows_reply Data_encoding.t =
+ let open Data_encoding in
+ conv
+ (fun { focus; windows } -> (focus, windows))
+ (fun (focus, windows) -> { focus; windows })
+ (obj2 (opt "focus" int31) (req "windows" @@ list string))
+
+type 'a t =
+ | Run_command : command -> run_command_reply t
+ | Get_windows : get_windows_reply t
+
+let reply_encoding : type a. a t -> a Data_encoding.t = function
+ | Run_command _ -> run_command_reply_encoding
+ | Get_windows -> get_windows_reply_encoding
let reply_to_string : type a. a t -> a -> string =
- fun cmd reply -> match (cmd, reply) with Run_command _, () -> ""
+ fun cmd reply ->
+ Data_encoding.Json.(to_string (construct (reply_encoding cmd) reply))
let reply_of_string : type a. a t -> string -> a option =
fun cmd reply ->
- match (cmd, reply) with Run_command _, "" -> Some () | _, _ -> None
+ let open Data_encoding.Json in
+ try
+ match from_string reply with
+ | Ok json -> Some (destruct (reply_encoding cmd) json)
+ | _ -> None
+ with _ -> None
let reply_of_string_exn cmd reply =
match reply_of_string cmd reply with
@@ -81,12 +111,14 @@ let reply_of_string_exn cmd reply =
let to_raw_message : type a. a t -> Raw_message.t = function
| Run_command cmd -> (0l, command_to_string cmd)
+ | Get_windows -> (1l, "")
type packed = Packed : 'a t -> packed
let of_raw_message (op, payload) =
match op with
| 0l -> (fun x -> Packed (Run_command x)) <$> command_of_string payload
+ | 1l -> Some (Packed Get_windows)
| _ -> None
exception Spatial_ipc_error of Socket.error
diff --git a/lib/spatial_ipc/spatial_ipc.mli b/lib/spatial_ipc/spatial_ipc.mli
index a99592f..c60d5e8 100644
--- a/lib/spatial_ipc/spatial_ipc.mli
+++ b/lib/spatial_ipc/spatial_ipc.mli
@@ -19,7 +19,13 @@ val command_of_string : string -> command option
val command_of_string_exn : string -> command
(** @raise [Invalid_argument] *)
-type 'a t = Run_command : command -> unit t
+type run_command_reply = { success : bool }
+type get_windows_reply = { focus : int option; windows : string list }
+
+type 'a t =
+ | Run_command : command -> run_command_reply t
+ | Get_windows : get_windows_reply t
+
type socket
val connect : unit -> socket Lwt.t