diff options
-rw-r--r-- | completions/bash/swaymsg | 4 | ||||
-rw-r--r-- | completions/zsh/_swaymsg | 3 | ||||
-rw-r--r-- | include/ipc.h | 5 | ||||
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | include/sway/input/seat.h | 2 | ||||
-rw-r--r-- | include/sway/ipc-server.h | 2 | ||||
-rw-r--r-- | include/sway/tree/view.h | 2 | ||||
-rw-r--r-- | sway/commands/bind.c | 52 | ||||
-rw-r--r-- | sway/commands/mark.c | 2 | ||||
-rw-r--r-- | sway/commands/move.c | 4 | ||||
-rw-r--r-- | sway/commands/reload.c | 29 | ||||
-rw-r--r-- | sway/input/cursor.c | 6 | ||||
-rw-r--r-- | sway/input/seat.c | 12 | ||||
-rw-r--r-- | sway/ipc-json.c | 9 | ||||
-rw-r--r-- | sway/ipc-server.c | 136 | ||||
-rw-r--r-- | sway/main.c | 1 | ||||
-rw-r--r-- | sway/tree/container.c | 14 | ||||
-rw-r--r-- | sway/tree/layout.c | 14 | ||||
-rw-r--r-- | sway/tree/output.c | 2 | ||||
-rw-r--r-- | sway/tree/view.c | 15 | ||||
-rw-r--r-- | swaymsg/main.c | 8 | ||||
-rw-r--r-- | swaymsg/swaymsg.1.scd | 3 |
22 files changed, 289 insertions, 38 deletions
diff --git a/completions/bash/swaymsg b/completions/bash/swaymsg index 8ec90b6f..20092bdc 100644 --- a/completions/bash/swaymsg +++ b/completions/bash/swaymsg | |||
@@ -14,7 +14,9 @@ _swaymsg() | |||
14 | 'get_marks' | 14 | 'get_marks' |
15 | 'get_bar_config' | 15 | 'get_bar_config' |
16 | 'get_version' | 16 | 'get_version' |
17 | 'get_clipboard' | 17 | 'get_binding_modes' |
18 | 'get_config' | ||
19 | 'send_tick' | ||
18 | ) | 20 | ) |
19 | 21 | ||
20 | short=( | 22 | short=( |
diff --git a/completions/zsh/_swaymsg b/completions/zsh/_swaymsg index 2e39deb6..a7a1c8e0 100644 --- a/completions/zsh/_swaymsg +++ b/completions/zsh/_swaymsg | |||
@@ -22,6 +22,9 @@ types=( | |||
22 | 'get_marks' | 22 | 'get_marks' |
23 | 'get_bar_config' | 23 | 'get_bar_config' |
24 | 'get_version' | 24 | 'get_version' |
25 | 'get_binding_modes' | ||
26 | 'get_config' | ||
27 | 'send_tick' | ||
25 | ) | 28 | ) |
26 | 29 | ||
27 | _arguments -s \ | 30 | _arguments -s \ |
diff --git a/include/ipc.h b/include/ipc.h index 0010718b..a3f60e19 100644 --- a/include/ipc.h +++ b/include/ipc.h | |||
@@ -15,6 +15,7 @@ enum ipc_command_type { | |||
15 | IPC_GET_VERSION = 7, | 15 | IPC_GET_VERSION = 7, |
16 | IPC_GET_BINDING_MODES = 8, | 16 | IPC_GET_BINDING_MODES = 8, |
17 | IPC_GET_CONFIG = 9, | 17 | IPC_GET_CONFIG = 9, |
18 | IPC_SEND_TICK = 10, | ||
18 | 19 | ||
19 | // sway-specific command types | 20 | // sway-specific command types |
20 | IPC_GET_INPUTS = 100, | 21 | IPC_GET_INPUTS = 100, |
@@ -27,8 +28,8 @@ enum ipc_command_type { | |||
27 | IPC_EVENT_WINDOW = ((1<<31) | 3), | 28 | IPC_EVENT_WINDOW = ((1<<31) | 3), |
28 | IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4), | 29 | IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4), |
29 | IPC_EVENT_BINDING = ((1<<31) | 5), | 30 | IPC_EVENT_BINDING = ((1<<31) | 5), |
30 | IPC_EVENT_MODIFIER = ((1<<31) | 6), | 31 | IPC_EVENT_SHUTDOWN = ((1<<31) | 6), |
31 | IPC_EVENT_INPUT = ((1<<31) | 7), | 32 | IPC_EVENT_TICK = ((1<<31) | 7), |
32 | }; | 33 | }; |
33 | 34 | ||
34 | #endif | 35 | #endif |
diff --git a/include/sway/config.h b/include/sway/config.h index 0f74b439..909b6827 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -488,8 +488,6 @@ int sway_binding_cmp_keys(const void *a, const void *b); | |||
488 | 488 | ||
489 | void free_sway_binding(struct sway_binding *sb); | 489 | void free_sway_binding(struct sway_binding *sb); |
490 | 490 | ||
491 | struct sway_binding *sway_binding_dup(struct sway_binding *sb); | ||
492 | |||
493 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding); | 491 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding); |
494 | 492 | ||
495 | void load_swaybars(); | 493 | void load_swaybars(); |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 07febe2c..92387601 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -99,7 +99,7 @@ void seat_configure_xcursor(struct sway_seat *seat); | |||
99 | void seat_set_focus(struct sway_seat *seat, struct sway_container *container); | 99 | void seat_set_focus(struct sway_seat *seat, struct sway_container *container); |
100 | 100 | ||
101 | void seat_set_focus_warp(struct sway_seat *seat, | 101 | void seat_set_focus_warp(struct sway_seat *seat, |
102 | struct sway_container *container, bool warp); | 102 | struct sway_container *container, bool warp, bool notify); |
103 | 103 | ||
104 | void seat_set_focus_surface(struct sway_seat *seat, | 104 | void seat_set_focus_surface(struct sway_seat *seat, |
105 | struct wlr_surface *surface, bool unfocus); | 105 | struct wlr_surface *surface, bool unfocus); |
diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h index 6469f097..4b6d0e25 100644 --- a/include/sway/ipc-server.h +++ b/include/sway/ipc-server.h | |||
@@ -16,5 +16,7 @@ void ipc_event_workspace(struct sway_container *old, | |||
16 | void ipc_event_window(struct sway_container *window, const char *change); | 16 | void ipc_event_window(struct sway_container *window, const char *change); |
17 | void ipc_event_barconfig_update(struct bar_config *bar); | 17 | void ipc_event_barconfig_update(struct bar_config *bar); |
18 | void ipc_event_mode(const char *mode, bool pango); | 18 | void ipc_event_mode(const char *mode, bool pango); |
19 | void ipc_event_shutdown(const char *reason); | ||
20 | void ipc_event_binding(struct sway_binding *binding); | ||
19 | 21 | ||
20 | #endif | 22 | #endif |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0152ed55..800df073 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -311,6 +311,8 @@ void view_clear_marks(struct sway_view *view); | |||
311 | 311 | ||
312 | bool view_has_mark(struct sway_view *view, char *mark); | 312 | bool view_has_mark(struct sway_view *view, char *mark); |
313 | 313 | ||
314 | void view_add_mark(struct sway_view *view, char *mark); | ||
315 | |||
314 | void view_update_marks_textures(struct sway_view *view); | 316 | void view_update_marks_textures(struct sway_view *view); |
315 | 317 | ||
316 | /** | 318 | /** |
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 133fd089..8270b958 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
1 | #ifdef __linux__ | 2 | #ifdef __linux__ |
2 | #include <linux/input-event-codes.h> | 3 | #include <linux/input-event-codes.h> |
3 | #elif __FreeBSD__ | 4 | #elif __FreeBSD__ |
@@ -5,9 +6,11 @@ | |||
5 | #endif | 6 | #endif |
6 | #include <xkbcommon/xkbcommon.h> | 7 | #include <xkbcommon/xkbcommon.h> |
7 | #include <xkbcommon/xkbcommon-names.h> | 8 | #include <xkbcommon/xkbcommon-names.h> |
9 | #include <string.h> | ||
8 | #include <strings.h> | 10 | #include <strings.h> |
9 | #include "sway/commands.h" | 11 | #include "sway/commands.h" |
10 | #include "sway/config.h" | 12 | #include "sway/config.h" |
13 | #include "sway/ipc-server.h" | ||
11 | #include "list.h" | 14 | #include "list.h" |
12 | #include "log.h" | 15 | #include "log.h" |
13 | #include "stringop.h" | 16 | #include "stringop.h" |
@@ -27,6 +30,33 @@ void free_sway_binding(struct sway_binding *binding) { | |||
27 | free(binding); | 30 | free(binding); |
28 | } | 31 | } |
29 | 32 | ||
33 | static struct sway_binding *sway_binding_dup(struct sway_binding *sb) { | ||
34 | struct sway_binding *new_sb = calloc(1, sizeof(struct sway_binding)); | ||
35 | if (!new_sb) { | ||
36 | return NULL; | ||
37 | } | ||
38 | |||
39 | new_sb->type = sb->type; | ||
40 | new_sb->order = sb->order; | ||
41 | new_sb->flags = sb->flags; | ||
42 | new_sb->modifiers = sb->modifiers; | ||
43 | new_sb->command = strdup(sb->command); | ||
44 | |||
45 | new_sb->keys = create_list(); | ||
46 | int i; | ||
47 | for (i = 0; i < sb->keys->length; ++i) { | ||
48 | xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); | ||
49 | if (!key) { | ||
50 | free_sway_binding(new_sb); | ||
51 | return NULL; | ||
52 | } | ||
53 | *key = *(xkb_keysym_t *)sb->keys->items[i]; | ||
54 | list_add(new_sb->keys, key); | ||
55 | } | ||
56 | |||
57 | return new_sb; | ||
58 | } | ||
59 | |||
30 | /** | 60 | /** |
31 | * Returns true if the bindings have the same key and modifier combinations. | 61 | * Returns true if the bindings have the same key and modifier combinations. |
32 | * Note that keyboard layout is not considered, so the bindings might actually | 62 | * Note that keyboard layout is not considered, so the bindings might actually |
@@ -275,11 +305,31 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { | |||
275 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) { | 305 | void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) { |
276 | wlr_log(WLR_DEBUG, "running command for binding: %s", | 306 | wlr_log(WLR_DEBUG, "running command for binding: %s", |
277 | binding->command); | 307 | binding->command); |
308 | |||
309 | struct sway_binding *binding_copy = binding; | ||
310 | bool reload = false; | ||
311 | // if this is a reload command we need to make a duplicate of the | ||
312 | // binding since it will be gone after the reload has completed. | ||
313 | if (strcasecmp(binding->command, "reload") == 0) { | ||
314 | reload = true; | ||
315 | binding_copy = sway_binding_dup(binding); | ||
316 | if (!binding_copy) { | ||
317 | wlr_log(WLR_ERROR, "Failed to duplicate binding during reload"); | ||
318 | return; | ||
319 | } | ||
320 | } | ||
321 | |||
278 | config->handler_context.seat = seat; | 322 | config->handler_context.seat = seat; |
279 | struct cmd_results *results = execute_command(binding->command, NULL); | 323 | struct cmd_results *results = execute_command(binding->command, NULL); |
280 | if (results->status != CMD_SUCCESS) { | 324 | if (results->status == CMD_SUCCESS) { |
325 | ipc_event_binding(binding_copy); | ||
326 | } else { | ||
281 | wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", | 327 | wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", |
282 | binding->command, results->error); | 328 | binding->command, results->error); |
283 | } | 329 | } |
330 | |||
331 | if (reload) { // free the binding if we made a copy | ||
332 | free_sway_binding(binding_copy); | ||
333 | } | ||
284 | free_cmd_results(results); | 334 | free_cmd_results(results); |
285 | } | 335 | } |
diff --git a/sway/commands/mark.c b/sway/commands/mark.c index 5a897e69..9ea8c301 100644 --- a/sway/commands/mark.c +++ b/sway/commands/mark.c | |||
@@ -58,7 +58,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) { | |||
58 | view_find_and_unmark(mark); | 58 | view_find_and_unmark(mark); |
59 | 59 | ||
60 | if (!toggle || !had_mark) { | 60 | if (!toggle || !had_mark) { |
61 | list_add(view->marks, strdup(mark)); | 61 | view_add_mark(view, mark); |
62 | } | 62 | } |
63 | 63 | ||
64 | free(mark); | 64 | free(mark); |
diff --git a/sway/commands/move.c b/sway/commands/move.c index 1aae3838..46ebcd83 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -98,7 +98,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
98 | container_move_to(current, destination); | 98 | container_move_to(current, destination); |
99 | struct sway_container *focus = seat_get_focus_inactive( | 99 | struct sway_container *focus = seat_get_focus_inactive( |
100 | config->handler_context.seat, old_parent); | 100 | config->handler_context.seat, old_parent); |
101 | seat_set_focus(config->handler_context.seat, focus); | 101 | seat_set_focus_warp(config->handler_context.seat, focus, true, false); |
102 | container_reap_empty(old_parent); | 102 | container_reap_empty(old_parent); |
103 | container_reap_empty(destination->parent); | 103 | container_reap_empty(destination->parent); |
104 | 104 | ||
@@ -135,7 +135,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
135 | struct sway_container *old_parent = current->parent; | 135 | struct sway_container *old_parent = current->parent; |
136 | struct sway_container *old_ws = container_parent(current, C_WORKSPACE); | 136 | struct sway_container *old_ws = container_parent(current, C_WORKSPACE); |
137 | container_move_to(current, focus); | 137 | container_move_to(current, focus); |
138 | seat_set_focus(config->handler_context.seat, old_parent); | 138 | seat_set_focus_warp(config->handler_context.seat, old_parent, true, false); |
139 | container_reap_empty(old_parent); | 139 | container_reap_empty(old_parent); |
140 | container_reap_empty(focus->parent); | 140 | container_reap_empty(focus->parent); |
141 | 141 | ||
diff --git a/sway/commands/reload.c b/sway/commands/reload.c index cea6a94b..5c1b19b4 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c | |||
@@ -1,17 +1,46 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <string.h> | ||
1 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
2 | #include "sway/config.h" | 4 | #include "sway/config.h" |
5 | #include "sway/ipc-server.h" | ||
3 | #include "sway/tree/arrange.h" | 6 | #include "sway/tree/arrange.h" |
7 | #include "list.h" | ||
4 | 8 | ||
5 | struct cmd_results *cmd_reload(int argc, char **argv) { | 9 | struct cmd_results *cmd_reload(int argc, char **argv) { |
6 | struct cmd_results *error = NULL; | 10 | struct cmd_results *error = NULL; |
7 | if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { | 11 | if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { |
8 | return error; | 12 | return error; |
9 | } | 13 | } |
14 | |||
15 | // store bar ids to check against new bars for barconfig_update events | ||
16 | list_t *bar_ids = create_list(); | ||
17 | for (int i = 0; i < config->bars->length; ++i) { | ||
18 | struct bar_config *bar = config->bars->items[i]; | ||
19 | list_add(bar_ids, strdup(bar->id)); | ||
20 | } | ||
21 | |||
10 | if (!load_main_config(config->current_config_path, true)) { | 22 | if (!load_main_config(config->current_config_path, true)) { |
11 | return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); | 23 | return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); |
12 | } | 24 | } |
25 | ipc_event_workspace(NULL, NULL, "reload"); | ||
13 | 26 | ||
14 | load_swaybars(); | 27 | load_swaybars(); |
28 | |||
29 | for (int i = 0; i < config->bars->length; ++i) { | ||
30 | struct bar_config *bar = config->bars->items[i]; | ||
31 | for (int j = 0; j < bar_ids->length; ++j) { | ||
32 | if (strcmp(bar->id, bar_ids->items[j]) == 0) { | ||
33 | ipc_event_barconfig_update(bar); | ||
34 | break; | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | |||
39 | for (int i = 0; i < bar_ids->length; ++i) { | ||
40 | free(bar_ids->items[i]); | ||
41 | } | ||
42 | list_free(bar_ids); | ||
43 | |||
15 | arrange_windows(&root_container); | 44 | arrange_windows(&root_container); |
16 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 45 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
17 | } | 46 | } |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 96ac7b33..d6fdc1da 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -349,7 +349,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
349 | output = container_parent(c, C_OUTPUT); | 349 | output = container_parent(c, C_OUTPUT); |
350 | } | 350 | } |
351 | if (output != focus) { | 351 | if (output != focus) { |
352 | seat_set_focus_warp(seat, c, false); | 352 | seat_set_focus_warp(seat, c, false, true); |
353 | } | 353 | } |
354 | } else if (c->type == C_VIEW) { | 354 | } else if (c->type == C_VIEW) { |
355 | // Focus c if the following are true: | 355 | // Focus c if the following are true: |
@@ -359,13 +359,13 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
359 | if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && | 359 | if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && |
360 | c != prev_c && | 360 | c != prev_c && |
361 | view_is_visible(c->sway_view)) { | 361 | view_is_visible(c->sway_view)) { |
362 | seat_set_focus_warp(seat, c, false); | 362 | seat_set_focus_warp(seat, c, false, true); |
363 | } else { | 363 | } else { |
364 | struct sway_container *next_focus = | 364 | struct sway_container *next_focus = |
365 | seat_get_focus_inactive(seat, &root_container); | 365 | seat_get_focus_inactive(seat, &root_container); |
366 | if (next_focus && next_focus->type == C_VIEW && | 366 | if (next_focus && next_focus->type == C_VIEW && |
367 | view_is_visible(next_focus->sway_view)) { | 367 | view_is_visible(next_focus->sway_view)) { |
368 | seat_set_focus_warp(seat, next_focus, false); | 368 | seat_set_focus_warp(seat, next_focus, false, true); |
369 | } | 369 | } |
370 | } | 370 | } |
371 | } | 371 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index a4a449e4..fe3cbc53 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -617,7 +617,7 @@ static int handle_urgent_timeout(void *data) { | |||
617 | } | 617 | } |
618 | 618 | ||
619 | void seat_set_focus_warp(struct sway_seat *seat, | 619 | void seat_set_focus_warp(struct sway_seat *seat, |
620 | struct sway_container *container, bool warp) { | 620 | struct sway_container *container, bool warp, bool notify) { |
621 | if (seat->focused_layer) { | 621 | if (seat->focused_layer) { |
622 | return; | 622 | return; |
623 | } | 623 | } |
@@ -739,7 +739,9 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
739 | 739 | ||
740 | if (last_focus) { | 740 | if (last_focus) { |
741 | if (last_workspace) { | 741 | if (last_workspace) { |
742 | ipc_event_workspace(last_workspace, container, "focus"); | 742 | if (notify && last_workspace != new_workspace) { |
743 | ipc_event_workspace(last_workspace, new_workspace, "focus"); | ||
744 | } | ||
743 | if (!workspace_is_visible(last_workspace) | 745 | if (!workspace_is_visible(last_workspace) |
744 | && workspace_is_empty(last_workspace)) { | 746 | && workspace_is_empty(last_workspace)) { |
745 | if (last_workspace == last_focus) { | 747 | if (last_workspace == last_focus) { |
@@ -766,6 +768,10 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
766 | } | 768 | } |
767 | } | 769 | } |
768 | 770 | ||
771 | if (container->type == C_VIEW) { | ||
772 | ipc_event_window(container, "focus"); | ||
773 | } | ||
774 | |||
769 | seat->has_focus = (container != NULL); | 775 | seat->has_focus = (container != NULL); |
770 | 776 | ||
771 | update_debug_tree(); | 777 | update_debug_tree(); |
@@ -773,7 +779,7 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
773 | 779 | ||
774 | void seat_set_focus(struct sway_seat *seat, | 780 | void seat_set_focus(struct sway_seat *seat, |
775 | struct sway_container *container) { | 781 | struct sway_container *container) { |
776 | seat_set_focus_warp(seat, container, true); | 782 | seat_set_focus_warp(seat, container, true, true); |
777 | } | 783 | } |
778 | 784 | ||
779 | void seat_set_focus_surface(struct sway_seat *seat, | 785 | void seat_set_focus_surface(struct sway_seat *seat, |
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index c49ea47e..4c2bcc98 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -201,6 +201,15 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
201 | bool urgent = c->type == C_VIEW ? | 201 | bool urgent = c->type == C_VIEW ? |
202 | view_is_urgent(c->sway_view) : container_has_urgent_child(c); | 202 | view_is_urgent(c->sway_view) : container_has_urgent_child(c); |
203 | json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); | 203 | json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); |
204 | |||
205 | if (c->type == C_VIEW) { | ||
206 | json_object *marks = json_object_new_array(); | ||
207 | list_t *view_marks = c->sway_view->marks; | ||
208 | for (int i = 0; i < view_marks->length; ++i) { | ||
209 | json_object_array_add(marks, json_object_new_string(view_marks->items[i])); | ||
210 | } | ||
211 | json_object_object_add(object, "marks", marks); | ||
212 | } | ||
204 | } | 213 | } |
205 | 214 | ||
206 | static void focus_inactive_children_iterator(struct sway_container *c, void *data) { | 215 | static void focus_inactive_children_iterator(struct sway_container *c, void *data) { |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index be703915..7d2d8969 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -3,12 +3,18 @@ | |||
3 | // Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0) | 3 | // Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0) |
4 | #define _XOPEN_SOURCE 700 | 4 | #define _XOPEN_SOURCE 700 |
5 | #endif | 5 | #endif |
6 | #ifdef __linux__ | ||
7 | #include <linux/input-event-codes.h> | ||
8 | #elif __FreeBSD__ | ||
9 | #include <dev/evdev/input-event-codes.h> | ||
10 | #endif | ||
6 | #include <assert.h> | 11 | #include <assert.h> |
7 | #include <errno.h> | 12 | #include <errno.h> |
8 | #include <fcntl.h> | 13 | #include <fcntl.h> |
9 | #include <json-c/json.h> | 14 | #include <json-c/json.h> |
10 | #include <stdbool.h> | 15 | #include <stdbool.h> |
11 | #include <stdint.h> | 16 | #include <stdint.h> |
17 | #include <stdio.h> | ||
12 | #include <stdlib.h> | 18 | #include <stdlib.h> |
13 | #include <string.h> | 19 | #include <string.h> |
14 | #include <sys/socket.h> | 20 | #include <sys/socket.h> |
@@ -28,6 +34,7 @@ | |||
28 | #include "sway/tree/view.h" | 34 | #include "sway/tree/view.h" |
29 | #include "list.h" | 35 | #include "list.h" |
30 | #include "log.h" | 36 | #include "log.h" |
37 | #include "util.h" | ||
31 | 38 | ||
32 | static int ipc_socket = -1; | 39 | static int ipc_socket = -1; |
33 | static struct wl_event_source *ipc_event_source = NULL; | 40 | static struct wl_event_source *ipc_event_source = NULL; |
@@ -291,13 +298,11 @@ void ipc_event_workspace(struct sway_container *old, | |||
291 | wlr_log(WLR_DEBUG, "Sending workspace::%s event", change); | 298 | wlr_log(WLR_DEBUG, "Sending workspace::%s event", change); |
292 | json_object *obj = json_object_new_object(); | 299 | json_object *obj = json_object_new_object(); |
293 | json_object_object_add(obj, "change", json_object_new_string(change)); | 300 | json_object_object_add(obj, "change", json_object_new_string(change)); |
294 | if (strcmp("focus", change) == 0) { | 301 | if (old) { |
295 | if (old) { | 302 | json_object_object_add(obj, "old", |
296 | json_object_object_add(obj, "old", | 303 | ipc_json_describe_container_recursive(old)); |
297 | ipc_json_describe_container_recursive(old)); | 304 | } else { |
298 | } else { | 305 | json_object_object_add(obj, "old", NULL); |
299 | json_object_object_add(obj, "old", NULL); | ||
300 | } | ||
301 | } | 306 | } |
302 | 307 | ||
303 | if (new) { | 308 | if (new) { |
@@ -353,6 +358,104 @@ void ipc_event_mode(const char *mode, bool pango) { | |||
353 | json_object_put(obj); | 358 | json_object_put(obj); |
354 | } | 359 | } |
355 | 360 | ||
361 | void ipc_event_shutdown(const char *reason) { | ||
362 | if (!ipc_has_event_listeners(IPC_EVENT_SHUTDOWN)) { | ||
363 | return; | ||
364 | } | ||
365 | wlr_log(WLR_DEBUG, "Sending shutdown::%s event", reason); | ||
366 | |||
367 | json_object *json = json_object_new_object(); | ||
368 | json_object_object_add(json, "change", json_object_new_string(reason)); | ||
369 | |||
370 | const char *json_string = json_object_to_json_string(json); | ||
371 | ipc_send_event(json_string, IPC_EVENT_SHUTDOWN); | ||
372 | json_object_put(json); | ||
373 | } | ||
374 | |||
375 | void ipc_event_binding(struct sway_binding *binding) { | ||
376 | if (!ipc_has_event_listeners(IPC_EVENT_BINDING)) { | ||
377 | return; | ||
378 | } | ||
379 | wlr_log(WLR_DEBUG, "Sending binding event"); | ||
380 | |||
381 | json_object *json_binding = json_object_new_object(); | ||
382 | json_object_object_add(json_binding, "command", json_object_new_string(binding->command)); | ||
383 | |||
384 | const char *names[10]; | ||
385 | int len = get_modifier_names(names, binding->modifiers); | ||
386 | json_object *modifiers = json_object_new_array(); | ||
387 | for (int i = 0; i < len; ++i) { | ||
388 | json_object_array_add(modifiers, json_object_new_string(names[i])); | ||
389 | } | ||
390 | json_object_object_add(json_binding, "event_state_mask", modifiers); | ||
391 | |||
392 | json_object *input_codes = json_object_new_array(); | ||
393 | int input_code = 0; | ||
394 | json_object *symbols = json_object_new_array(); | ||
395 | json_object *symbol = NULL; | ||
396 | |||
397 | if (binding->type == BINDING_KEYCODE) { // bindcode: populate input_codes | ||
398 | uint32_t keycode; | ||
399 | for (int i = 0; i < binding->keys->length; ++i) { | ||
400 | keycode = *(uint32_t *)binding->keys->items[i]; | ||
401 | json_object_array_add(input_codes, json_object_new_int(keycode)); | ||
402 | if (i == 0) { | ||
403 | input_code = keycode; | ||
404 | } | ||
405 | } | ||
406 | } else { // bindsym/mouse: populate symbols | ||
407 | uint32_t keysym; | ||
408 | char buffer[64]; | ||
409 | for (int i = 0; i < binding->keys->length; ++i) { | ||
410 | keysym = *(uint32_t *)binding->keys->items[i]; | ||
411 | if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) { | ||
412 | snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1); | ||
413 | } else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) { | ||
414 | continue; | ||
415 | } | ||
416 | |||
417 | json_object *str = json_object_new_string(buffer); | ||
418 | if (i == 0) { | ||
419 | // str is owned by both symbol and symbols. Make sure | ||
420 | // to bump the ref count. | ||
421 | json_object_array_add(symbols, json_object_get(str)); | ||
422 | symbol = str; | ||
423 | } else { | ||
424 | json_object_array_add(symbols, str); | ||
425 | } | ||
426 | } | ||
427 | } | ||
428 | |||
429 | json_object_object_add(json_binding, "input_codes", input_codes); | ||
430 | json_object_object_add(json_binding, "input_code", json_object_new_int(input_code)); | ||
431 | json_object_object_add(json_binding, "symbols", symbols); | ||
432 | json_object_object_add(json_binding, "symbol", symbol); | ||
433 | json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ? | ||
434 | json_object_new_string("mouse") : json_object_new_string("keyboard")); | ||
435 | |||
436 | json_object *json = json_object_new_object(); | ||
437 | json_object_object_add(json, "change", json_object_new_string("run")); | ||
438 | json_object_object_add(json, "binding", json_binding); | ||
439 | const char *json_string = json_object_to_json_string(json); | ||
440 | ipc_send_event(json_string, IPC_EVENT_BINDING); | ||
441 | json_object_put(json); | ||
442 | } | ||
443 | |||
444 | static void ipc_event_tick(const char *payload) { | ||
445 | if (!ipc_has_event_listeners(IPC_EVENT_TICK)) { | ||
446 | return; | ||
447 | } | ||
448 | wlr_log(WLR_DEBUG, "Sending tick event"); | ||
449 | |||
450 | json_object *json = json_object_new_object(); | ||
451 | json_object_object_add(json, "first", json_object_new_boolean(false)); | ||
452 | json_object_object_add(json, "payload", json_object_new_string(payload)); | ||
453 | |||
454 | const char *json_string = json_object_to_json_string(json); | ||
455 | ipc_send_event(json_string, IPC_EVENT_TICK); | ||
456 | json_object_put(json); | ||
457 | } | ||
458 | |||
356 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | 459 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { |
357 | struct ipc_client *client = data; | 460 | struct ipc_client *client = data; |
358 | 461 | ||
@@ -494,6 +597,13 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
494 | goto exit_cleanup; | 597 | goto exit_cleanup; |
495 | } | 598 | } |
496 | 599 | ||
600 | case IPC_SEND_TICK: | ||
601 | { | ||
602 | ipc_event_tick(buf); | ||
603 | ipc_send_reply(client, "{\"success\": true}", 17); | ||
604 | goto exit_cleanup; | ||
605 | } | ||
606 | |||
497 | case IPC_GET_OUTPUTS: | 607 | case IPC_GET_OUTPUTS: |
498 | { | 608 | { |
499 | json_object *outputs = json_object_new_array(); | 609 | json_object *outputs = json_object_new_array(); |
@@ -540,6 +650,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
540 | goto exit_cleanup; | 650 | goto exit_cleanup; |
541 | } | 651 | } |
542 | 652 | ||
653 | bool is_tick = false; | ||
543 | // parse requested event types | 654 | // parse requested event types |
544 | for (size_t i = 0; i < json_object_array_length(request); i++) { | 655 | for (size_t i = 0; i < json_object_array_length(request); i++) { |
545 | const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); | 656 | const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); |
@@ -549,12 +660,15 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
549 | client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); | 660 | client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); |
550 | } else if (strcmp(event_type, "mode") == 0) { | 661 | } else if (strcmp(event_type, "mode") == 0) { |
551 | client->subscribed_events |= event_mask(IPC_EVENT_MODE); | 662 | client->subscribed_events |= event_mask(IPC_EVENT_MODE); |
663 | } else if (strcmp(event_type, "shutdown") == 0) { | ||
664 | client->subscribed_events |= event_mask(IPC_EVENT_SHUTDOWN); | ||
552 | } else if (strcmp(event_type, "window") == 0) { | 665 | } else if (strcmp(event_type, "window") == 0) { |
553 | client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); | 666 | client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); |
554 | } else if (strcmp(event_type, "modifier") == 0) { | ||
555 | client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER); | ||
556 | } else if (strcmp(event_type, "binding") == 0) { | 667 | } else if (strcmp(event_type, "binding") == 0) { |
557 | client->subscribed_events |= event_mask(IPC_EVENT_BINDING); | 668 | client->subscribed_events |= event_mask(IPC_EVENT_BINDING); |
669 | } else if (strcmp(event_type, "tick") == 0) { | ||
670 | client->subscribed_events |= event_mask(IPC_EVENT_TICK); | ||
671 | is_tick = true; | ||
558 | } else { | 672 | } else { |
559 | client_valid = | 673 | client_valid = |
560 | ipc_send_reply(client, "{\"success\": false}", 18); | 674 | ipc_send_reply(client, "{\"success\": false}", 18); |
@@ -566,6 +680,10 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
566 | 680 | ||
567 | json_object_put(request); | 681 | json_object_put(request); |
568 | client_valid = ipc_send_reply(client, "{\"success\": true}", 17); | 682 | client_valid = ipc_send_reply(client, "{\"success\": true}", 17); |
683 | if (is_tick) { | ||
684 | client->current_command = IPC_EVENT_TICK; | ||
685 | ipc_send_reply(client, "{\"first\": true, \"payload\": \"\"}", 30); | ||
686 | } | ||
569 | goto exit_cleanup; | 687 | goto exit_cleanup; |
570 | } | 688 | } |
571 | 689 | ||
diff --git a/sway/main.c b/sway/main.c index a20f1dac..477ffa5a 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -36,6 +36,7 @@ struct sway_server server; | |||
36 | void sway_terminate(int exit_code) { | 36 | void sway_terminate(int exit_code) { |
37 | terminate_request = true; | 37 | terminate_request = true; |
38 | exit_value = exit_code; | 38 | exit_value = exit_code; |
39 | ipc_event_shutdown("exit"); | ||
39 | wl_display_terminate(server.wl_display); | 40 | wl_display_terminate(server.wl_display); |
40 | } | 41 | } |
41 | 42 | ||
diff --git a/sway/tree/container.c b/sway/tree/container.c index 4e85021d..b6ff4d30 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -62,8 +62,10 @@ void container_create_notify(struct sway_container *container) { | |||
62 | // TODO send ipc event type based on the container type | 62 | // TODO send ipc event type based on the container type |
63 | wl_signal_emit(&root_container.sway_root->events.new_container, container); | 63 | wl_signal_emit(&root_container.sway_root->events.new_container, container); |
64 | 64 | ||
65 | if (container->type == C_VIEW || container->type == C_CONTAINER) { | 65 | if (container->type == C_VIEW) { |
66 | ipc_event_window(container, "new"); | 66 | ipc_event_window(container, "new"); |
67 | } else if (container->type == C_WORKSPACE) { | ||
68 | ipc_event_workspace(NULL, container, "init"); | ||
67 | } | 69 | } |
68 | } | 70 | } |
69 | 71 | ||
@@ -281,7 +283,7 @@ static struct sway_container *container_output_destroy( | |||
281 | container_remove_child(workspace); | 283 | container_remove_child(workspace); |
282 | if (!workspace_is_empty(workspace)) { | 284 | if (!workspace_is_empty(workspace)) { |
283 | container_add_child(new_output, workspace); | 285 | container_add_child(new_output, workspace); |
284 | ipc_event_workspace(workspace, NULL, "move"); | 286 | ipc_event_workspace(NULL, workspace, "move"); |
285 | } else { | 287 | } else { |
286 | container_destroy(workspace); | 288 | container_destroy(workspace); |
287 | } | 289 | } |
@@ -319,7 +321,13 @@ static struct sway_container *container_destroy_noreaping( | |||
319 | } | 321 | } |
320 | 322 | ||
321 | wl_signal_emit(&con->events.destroy, con); | 323 | wl_signal_emit(&con->events.destroy, con); |
322 | ipc_event_window(con, "close"); | 324 | |
325 | // emit IPC event | ||
326 | if (con->type == C_VIEW) { | ||
327 | ipc_event_window(con, "close"); | ||
328 | } else if (con->type == C_WORKSPACE) { | ||
329 | ipc_event_workspace(NULL, con, "empty"); | ||
330 | } | ||
323 | 331 | ||
324 | // The below functions move their children to somewhere else. | 332 | // The below functions move their children to somewhere else. |
325 | if (con->type == C_OUTPUT) { | 333 | if (con->type == C_OUTPUT) { |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a0764a54..1f82e534 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -217,7 +217,9 @@ void container_move_to(struct sway_container *container, | |||
217 | container_sort_workspaces(new_parent); | 217 | container_sort_workspaces(new_parent); |
218 | seat_set_focus(seat, new_parent); | 218 | seat_set_focus(seat, new_parent); |
219 | workspace_output_raise_priority(container, old_parent, new_parent); | 219 | workspace_output_raise_priority(container, old_parent, new_parent); |
220 | ipc_event_workspace(container, NULL, "move"); | 220 | ipc_event_workspace(NULL, container, "move"); |
221 | } else if (container->type == C_VIEW) { | ||
222 | ipc_event_window(container, "move"); | ||
221 | } | 223 | } |
222 | container_notify_subtree_changed(old_parent); | 224 | container_notify_subtree_changed(old_parent); |
223 | container_notify_subtree_changed(new_parent); | 225 | container_notify_subtree_changed(new_parent); |
@@ -578,6 +580,10 @@ void container_move(struct sway_container *container, | |||
578 | container_notify_subtree_changed(old_parent); | 580 | container_notify_subtree_changed(old_parent); |
579 | container_notify_subtree_changed(container->parent); | 581 | container_notify_subtree_changed(container->parent); |
580 | 582 | ||
583 | if (container->type == C_VIEW) { | ||
584 | ipc_event_window(container, "move"); | ||
585 | } | ||
586 | |||
581 | if (old_parent) { | 587 | if (old_parent) { |
582 | seat_set_focus(config->handler_context.seat, old_parent); | 588 | seat_set_focus(config->handler_context.seat, old_parent); |
583 | seat_set_focus(config->handler_context.seat, container); | 589 | seat_set_focus(config->handler_context.seat, container); |
@@ -592,7 +598,7 @@ void container_move(struct sway_container *container, | |||
592 | next_ws = container_parent(next_ws, C_WORKSPACE); | 598 | next_ws = container_parent(next_ws, C_WORKSPACE); |
593 | } | 599 | } |
594 | if (last_ws && next_ws && last_ws != next_ws) { | 600 | if (last_ws && next_ws && last_ws != next_ws) { |
595 | ipc_event_workspace(last_ws, container, "focus"); | 601 | ipc_event_workspace(last_ws, next_ws, "focus"); |
596 | workspace_detect_urgent(last_ws); | 602 | workspace_detect_urgent(last_ws); |
597 | workspace_detect_urgent(next_ws); | 603 | workspace_detect_urgent(next_ws); |
598 | } | 604 | } |
@@ -995,13 +1001,13 @@ static void swap_focus(struct sway_container *con1, | |||
995 | if (focus == con1 && (con2->parent->layout == L_TABBED | 1001 | if (focus == con1 && (con2->parent->layout == L_TABBED |
996 | || con2->parent->layout == L_STACKED)) { | 1002 | || con2->parent->layout == L_STACKED)) { |
997 | if (workspace_is_visible(ws2)) { | 1003 | if (workspace_is_visible(ws2)) { |
998 | seat_set_focus_warp(seat, con2, false); | 1004 | seat_set_focus_warp(seat, con2, false, true); |
999 | } | 1005 | } |
1000 | seat_set_focus(seat, ws1 != ws2 ? con2 : con1); | 1006 | seat_set_focus(seat, ws1 != ws2 ? con2 : con1); |
1001 | } else if (focus == con2 && (con1->parent->layout == L_TABBED | 1007 | } else if (focus == con2 && (con1->parent->layout == L_TABBED |
1002 | || con1->parent->layout == L_STACKED)) { | 1008 | || con1->parent->layout == L_STACKED)) { |
1003 | if (workspace_is_visible(ws1)) { | 1009 | if (workspace_is_visible(ws1)) { |
1004 | seat_set_focus_warp(seat, con1, false); | 1010 | seat_set_focus_warp(seat, con1, false, true); |
1005 | } | 1011 | } |
1006 | seat_set_focus(seat, ws1 != ws2 ? con1 : con2); | 1012 | seat_set_focus(seat, ws1 != ws2 ? con1 : con2); |
1007 | } else if (ws1 != ws2) { | 1013 | } else if (ws1 != ws2) { |
diff --git a/sway/tree/output.c b/sway/tree/output.c index da535c18..31e3bf9b 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -22,7 +22,7 @@ static void restore_workspaces(struct sway_container *output) { | |||
22 | if (highest == output) { | 22 | if (highest == output) { |
23 | container_remove_child(ws); | 23 | container_remove_child(ws); |
24 | container_add_child(output, ws); | 24 | container_add_child(output, ws); |
25 | ipc_event_workspace(ws, NULL, "move"); | 25 | ipc_event_workspace(NULL, ws, "move"); |
26 | j--; | 26 | j--; |
27 | } | 27 | } |
28 | } | 28 | } |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f54cc11..48b39e80 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -864,6 +864,8 @@ void view_update_title(struct sway_view *view, bool force) { | |||
864 | 864 | ||
865 | // Update title after the global font height is updated | 865 | // Update title after the global font height is updated |
866 | container_update_title_textures(view->swayc); | 866 | container_update_title_textures(view->swayc); |
867 | |||
868 | ipc_event_window(view->swayc, "title"); | ||
867 | } | 869 | } |
868 | 870 | ||
869 | static bool find_by_mark_iterator(struct sway_container *con, | 871 | static bool find_by_mark_iterator(struct sway_container *con, |
@@ -886,6 +888,7 @@ bool view_find_and_unmark(char *mark) { | |||
886 | free(view_mark); | 888 | free(view_mark); |
887 | list_del(view->marks, i); | 889 | list_del(view->marks, i); |
888 | view_update_marks_textures(view); | 890 | view_update_marks_textures(view); |
891 | ipc_event_window(container, "mark"); | ||
889 | return true; | 892 | return true; |
890 | } | 893 | } |
891 | } | 894 | } |
@@ -893,11 +896,10 @@ bool view_find_and_unmark(char *mark) { | |||
893 | } | 896 | } |
894 | 897 | ||
895 | void view_clear_marks(struct sway_view *view) { | 898 | void view_clear_marks(struct sway_view *view) { |
896 | for (int i = 0; i < view->marks->length; ++i) { | 899 | while (view->marks->length) { |
897 | free(view->marks->items[i]); | 900 | list_del(view->marks, 0); |
901 | ipc_event_window(view->swayc, "mark"); | ||
898 | } | 902 | } |
899 | list_free(view->marks); | ||
900 | view->marks = create_list(); | ||
901 | } | 903 | } |
902 | 904 | ||
903 | bool view_has_mark(struct sway_view *view, char *mark) { | 905 | bool view_has_mark(struct sway_view *view, char *mark) { |
@@ -910,6 +912,11 @@ bool view_has_mark(struct sway_view *view, char *mark) { | |||
910 | return false; | 912 | return false; |
911 | } | 913 | } |
912 | 914 | ||
915 | void view_add_mark(struct sway_view *view, char *mark) { | ||
916 | list_add(view->marks, strdup(mark)); | ||
917 | ipc_event_window(view->swayc, "mark"); | ||
918 | } | ||
919 | |||
913 | static void update_marks_texture(struct sway_view *view, | 920 | static void update_marks_texture(struct sway_view *view, |
914 | struct wlr_texture **texture, struct border_colors *class) { | 921 | struct wlr_texture **texture, struct border_colors *class) { |
915 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 922 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
diff --git a/swaymsg/main.c b/swaymsg/main.c index c4141ca5..3767daf3 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c | |||
@@ -250,12 +250,16 @@ static void pretty_print(int type, json_object *resp) { | |||
250 | if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && | 250 | if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && |
251 | type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && | 251 | type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && |
252 | type != IPC_GET_VERSION && type != IPC_GET_SEATS && | 252 | type != IPC_GET_VERSION && type != IPC_GET_SEATS && |
253 | type != IPC_GET_CONFIG) { | 253 | type != IPC_GET_CONFIG && type != IPC_SEND_TICK) { |
254 | printf("%s\n", json_object_to_json_string_ext(resp, | 254 | printf("%s\n", json_object_to_json_string_ext(resp, |
255 | JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); | 255 | JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); |
256 | return; | 256 | return; |
257 | } | 257 | } |
258 | 258 | ||
259 | if (type == IPC_SEND_TICK) { | ||
260 | return; | ||
261 | } | ||
262 | |||
259 | if (type == IPC_GET_VERSION) { | 263 | if (type == IPC_GET_VERSION) { |
260 | pretty_print_version(resp); | 264 | pretty_print_version(resp); |
261 | return; | 265 | return; |
@@ -384,6 +388,8 @@ int main(int argc, char **argv) { | |||
384 | type = IPC_GET_BINDING_MODES; | 388 | type = IPC_GET_BINDING_MODES; |
385 | } else if (strcasecmp(cmdtype, "get_config") == 0) { | 389 | } else if (strcasecmp(cmdtype, "get_config") == 0) { |
386 | type = IPC_GET_CONFIG; | 390 | type = IPC_GET_CONFIG; |
391 | } else if (strcasecmp(cmdtype, "send_tick") == 0) { | ||
392 | type = IPC_SEND_TICK; | ||
387 | } else { | 393 | } else { |
388 | sway_abort("Unknown message type %s", cmdtype); | 394 | sway_abort("Unknown message type %s", cmdtype); |
389 | } | 395 | } |
diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index a6e279da..8cf1b222 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd | |||
@@ -64,3 +64,6 @@ _swaymsg_ [options...] [message] | |||
64 | 64 | ||
65 | *get\_config* | 65 | *get\_config* |
66 | Gets a JSON-encoded copy of the current configuration. | 66 | Gets a JSON-encoded copy of the current configuration. |
67 | |||
68 | *send\_tick* | ||
69 | Sends a tick event to all subscribed clients. | ||