aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Letan <lthms@soap.coffee>2022-08-30 22:26:13 +0200
committerThomas Letan <lthms@soap.coffee>2022-08-30 22:26:13 +0200
commita7c9ae0b105c6b09aa22e80a0fa94662ea832dc5 (patch)
treec4e8ae209d651ce3c3ab05af1b71c93a6b24e5c6
parentAbstract polling ready file descriptors into a nice fold (diff)
Introduce a command to jump to a given window
The intended user of this command is a custom module of waybar, to allow a on-click event. We use this opportunity to prefer next/prev over left/right to use the same type for workspaces-related commands.
-rw-r--r--README.md8
-rw-r--r--bin/spatial/ribbon.ml24
-rw-r--r--bin/spatial/state.ml20
-rw-r--r--bin/spatialmsg/main.ml12
-rw-r--r--lib/spatial_ipc/spatial_ipc.ml46
-rw-r--r--lib/spatial_ipc/spatial_ipc.mli13
6 files changed, 90 insertions, 33 deletions
diff --git a/README.md b/README.md
index c9c3a00..f09c9a5 100644
--- a/README.md
+++ b/README.md
@@ -23,16 +23,16 @@ exec $spatialmsg
# focus is on the last window on the left of the visible area, windows
# will shift right to make room for the next candidate on the loop,
# and the window on the far right will disappear.
-bindsym $mod+t exec $spatialmsg "focus left"
+bindsym $mod+t exec $spatialmsg "focus prev"
# Same thing, for the right.
-bindsym $mod+n exec $spatialmsg "focus right"
+bindsym $mod+n exec $spatialmsg "focus next"
# Move the focused window on the left, shift the loop if necessary.
-bindsym $mod+Shift+t exec $spatialmsg "move left"
+bindsym $mod+Shift+t exec $spatialmsg "move prev"
# Move the focused window on the right, shift the loop if necessary.
-bindsym $mod+Shift+n exec $spatialmsg "move right"
+bindsym $mod+Shift+n exec $spatialmsg "move next"
# Toggle between a mode where only one window is visible (maximized
# mode), or a fixed numbers (split mode). spatial-sway will remember
diff --git a/bin/spatial/ribbon.ml b/bin/spatial/ribbon.ml
index 24777ac..5af50c1 100644
--- a/bin/spatial/ribbon.ml
+++ b/bin/spatial/ribbon.ml
@@ -165,13 +165,25 @@ let move_focus_right ribbon =
let x, l = pop_front_exn l in
{ ribbon with visible = Some (f, push_back x l) })
-let split_visible ribbon =
- let rec split_visible acc f = function
- | x :: rst when f = 0 -> Some (List.rev acc, x, rst)
- | x :: rst -> split_visible (x :: acc) (f - 1) rst
- | [] -> raise (Invalid_argument "Ribbon.split_visible")
+let rec focus_index ribbon index =
+ match ribbon.visible with
+ | Some (_, l) when index < List.length l ->
+ { ribbon with visible = Some (index, l) }
+ | Some (_, l) when index < List.length l + List.length ribbon.hidden ->
+ let ribbon = move_focus_right ribbon in
+ focus_index ribbon (index - 1)
+ | _ -> ribbon
+
+let split_at l i =
+ let rec split_visible acc i = function
+ | x :: rst when i = 0 -> Some (List.rev acc, x, rst)
+ | x :: rst -> split_visible (x :: acc) (i - 1) rst
+ | [] -> raise (Invalid_argument "Ribbon.split_at")
in
- match ribbon.visible with None -> None | Some (f, l) -> split_visible [] f l
+ split_visible [] i l
+
+let split_visible ribbon =
+ match ribbon.visible with None -> None | Some (f, l) -> split_at l f
let move_window_left ribbon =
match split_visible ribbon with
diff --git a/bin/spatial/state.ml b/bin/spatial/state.ml
index e978166..2b4f994 100644
--- a/bin/spatial/state.ml
+++ b/bin/spatial/state.ml
@@ -27,6 +27,16 @@ let insert_window default_full_view default_maximum_visible workspace window
Windows_registry.register window { app_id; workspace } state.windows;
}
+let focus_index workspace state index =
+ {
+ state with
+ workspaces =
+ Workspaces_registry.update workspace
+ (function
+ | Some ribbon -> Some (Ribbon.focus_index ribbon index) | None -> None)
+ state.workspaces;
+ }
+
let toggle_full_view workspace state =
{
state with
@@ -138,7 +148,7 @@ let client_command_handle :
| Run_command cmd ->
let res =
match cmd with
- | Focus Left ->
+ | Focus Prev ->
( {
state with
workspaces =
@@ -150,7 +160,7 @@ let client_command_handle :
},
true,
None )
- | Focus Right ->
+ | Focus Next ->
( {
state with
workspaces =
@@ -162,9 +172,11 @@ let client_command_handle :
},
true,
None )
- | Move Left ->
+ | Focus (Index x) ->
+ (focus_index state.current_workspace state x, true, None)
+ | Move Prev ->
(move_window_left state.current_workspace state, true, None)
- | Move Right ->
+ | Move Next ->
(move_window_right state.current_workspace state, true, None)
| Maximize Toggle ->
(toggle_full_view state.current_workspace state, true, None)
diff --git a/bin/spatialmsg/main.ml b/bin/spatialmsg/main.ml
index 9e7be1b..057b536 100644
--- a/bin/spatialmsg/main.ml
+++ b/bin/spatialmsg/main.ml
@@ -21,9 +21,17 @@ let () =
match (cmd, reply.focus) with
| Some idx, Some focus when idx < List.length reply.windows ->
- let name = List.nth reply.windows idx in
+ let tooltip = List.nth reply.windows idx in
+ let name =
+ match tooltip with
+ | "firefox" -> ""
+ | "kitty" -> ""
+ | "Slack" -> ""
+ | "emacs" -> ""
+ | _ -> " " ^ tooltip
+ in
let cls = if idx = focus then "focus" else "unfocus" in
- Format.(printf "%s\n%s\n%s" name name cls)
+ Format.(printf "%s\n%s\n%s" name tooltip cls)
| Some _, _ -> ()
| None, _ ->
List.iteri
diff --git a/lib/spatial_ipc/spatial_ipc.ml b/lib/spatial_ipc/spatial_ipc.ml
index 662582a..a574fc1 100644
--- a/lib/spatial_ipc/spatial_ipc.ml
+++ b/lib/spatial_ipc/spatial_ipc.ml
@@ -7,14 +7,30 @@ open Mltp_ipc
let socket_path = "/tmp/spatial-sway.socket"
let magic_string = "spatial-ipc"
-type direction = Left | Right
-
-let direction_of_string_opt = function
- | "left" -> Some Left
- | "right" -> Some Right
- | _ -> None
-
-let direction_to_string = function Left -> "left" | Right -> "right"
+type focus = Focus_kind
+type move = Move_kind
+
+type 'kind target =
+ | Prev : 'kind target
+ | Next : 'kind target
+ | Index : int -> focus target
+
+let restrict_move_target : 'k target -> move target option = function
+ | Index _ -> None
+ | Next -> Some Next
+ | Prev -> Some Prev
+
+let target_of_string_opt = function
+ | "prev" -> Some Prev
+ | "next" -> Some Next
+ | x ->
+ Option.bind (int_of_string_opt x) @@ fun x ->
+ if 0 <= x then Some (Index x) else None
+
+let target_to_string : type kind. kind target -> string = function
+ | Prev -> "prev"
+ | Next -> "next"
+ | Index x -> string_of_int x
type switch = On | Off | Toggle
@@ -36,8 +52,8 @@ let operation_of_string_opt = function
let operation_to_string = function Incr -> "increment" | Decr -> "decrement"
type command =
- | Focus of direction
- | Move of direction
+ | Focus of focus target
+ | Move of move target
| Maximize of switch
| Split of operation
@@ -47,8 +63,10 @@ let command_of_string str =
String.split_on_char ' ' str
|> List.filter (function "" -> false | _ -> true)
|> function
- | [ "focus"; dir ] -> (fun x -> Focus x) <$> direction_of_string_opt dir
- | [ "move"; dir ] -> (fun x -> Move x) <$> direction_of_string_opt dir
+ | [ "focus"; target ] -> (fun x -> Focus x) <$> target_of_string_opt target
+ | [ "move"; target ] ->
+ Option.bind (target_of_string_opt target) @@ fun target ->
+ (fun x -> Move x) <$> restrict_move_target target
| [ "maximize"; switch ] ->
(fun x -> Maximize x) <$> switch_of_string_opt switch
| [ "split"; op ] -> (fun x -> Split x) <$> operation_of_string_opt op
@@ -60,8 +78,8 @@ let command_of_string_exn str =
| None -> raise (Invalid_argument "Spatial_ipc.command_of_string_exn")
let command_to_string = function
- | Focus dir -> Format.sprintf "focus %s" (direction_to_string dir)
- | Move dir -> Format.sprintf "move %s" (direction_to_string dir)
+ | Focus dir -> Format.sprintf "focus %s" (target_to_string dir)
+ | Move dir -> Format.sprintf "move %s" (target_to_string dir)
| Maximize switch -> Format.sprintf "maximize %s" (switch_to_string switch)
| Split op -> Format.sprintf "split %s" (operation_to_string op)
diff --git a/lib/spatial_ipc/spatial_ipc.mli b/lib/spatial_ipc/spatial_ipc.mli
index d742867..6a00c14 100644
--- a/lib/spatial_ipc/spatial_ipc.mli
+++ b/lib/spatial_ipc/spatial_ipc.mli
@@ -4,13 +4,20 @@
val socket_path : string
-type direction = Left | Right
+type focus = Focus_kind
+type move = Move_kind
+
+type 'kind target =
+ | Prev : 'kind target
+ | Next : 'kind target
+ | Index : int -> focus target
+
type switch = On | Off | Toggle
type operation = Incr | Decr
type command =
- | Focus of direction
- | Move of direction
+ | Focus of focus target
+ | Move of move target
| Maximize of switch
| Split of operation