diff options
author | emersion <contact@emersion.fr> | 2018-04-02 15:30:58 -0400 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-04-02 15:30:58 -0400 |
commit | a4a241697ae591289d7c14eff972e1ef787216e2 (patch) | |
tree | d82d3c3eba2946670aa634a62d03feb7102f0bf8 | |
parent | Xwayland unmanaged views aren't views anymore (diff) | |
parent | Merge pull request #1699 from acrisci/seat-fixes (diff) | |
download | sway-a4a241697ae591289d7c14eff972e1ef787216e2.tar.gz sway-a4a241697ae591289d7c14eff972e1ef787216e2.tar.zst sway-a4a241697ae591289d7c14eff972e1ef787216e2.zip |
Merge branch 'wlroots' into view-redesign
35 files changed, 1055 insertions, 265 deletions
diff --git a/common/pango.c b/common/pango.c index 2ae7883c..658d2876 100644 --- a/common/pango.c +++ b/common/pango.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include "log.h" | ||
9 | 10 | ||
10 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | 11 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, |
11 | const char *text, int32_t scale, bool markup) { | 12 | const char *text, int32_t scale, bool markup) { |
@@ -13,7 +14,13 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | |||
13 | PangoAttrList *attrs; | 14 | PangoAttrList *attrs; |
14 | if (markup) { | 15 | if (markup) { |
15 | char *buf; | 16 | char *buf; |
16 | pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL); | 17 | GError *error = NULL; |
18 | if (!sway_assert(pango_parse_markup( | ||
19 | text, -1, 0, &attrs, &buf, NULL, &error), | ||
20 | "pango_parse_markup '%s' -> error %s", text, | ||
21 | error ? error->message : NULL)) { | ||
22 | return NULL; | ||
23 | } | ||
17 | pango_layout_set_markup(layout, buf, -1); | 24 | pango_layout_set_markup(layout, buf, -1); |
18 | free(buf); | 25 | free(buf); |
19 | } else { | 26 | } else { |
diff --git a/include/sway/config.h b/include/sway/config.h index 03b51948..91f772b5 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -377,6 +377,7 @@ void free_config(struct sway_config *config); | |||
377 | void config_clear_handler_context(struct sway_config *config); | 377 | void config_clear_handler_context(struct sway_config *config); |
378 | 378 | ||
379 | void free_sway_variable(struct sway_variable *var); | 379 | void free_sway_variable(struct sway_variable *var); |
380 | |||
380 | /** | 381 | /** |
381 | * Does variable replacement for a string based on the config's currently loaded variables. | 382 | * Does variable replacement for a string based on the config's currently loaded variables. |
382 | */ | 383 | */ |
@@ -385,44 +386,68 @@ char *do_var_replacement(char *str); | |||
385 | struct cmd_results *check_security_config(); | 386 | struct cmd_results *check_security_config(); |
386 | 387 | ||
387 | int input_identifier_cmp(const void *item, const void *data); | 388 | int input_identifier_cmp(const void *item, const void *data); |
389 | |||
388 | struct input_config *new_input_config(const char* identifier); | 390 | struct input_config *new_input_config(const char* identifier); |
391 | |||
389 | void merge_input_config(struct input_config *dst, struct input_config *src); | 392 | void merge_input_config(struct input_config *dst, struct input_config *src); |
393 | |||
390 | struct input_config *copy_input_config(struct input_config *ic); | 394 | struct input_config *copy_input_config(struct input_config *ic); |
395 | |||
391 | void free_input_config(struct input_config *ic); | 396 | void free_input_config(struct input_config *ic); |
397 | |||
392 | void apply_input_config(struct input_config *input); | 398 | void apply_input_config(struct input_config *input); |
393 | 399 | ||
394 | int seat_name_cmp(const void *item, const void *data); | 400 | int seat_name_cmp(const void *item, const void *data); |
401 | |||
395 | struct seat_config *new_seat_config(const char* name); | 402 | struct seat_config *new_seat_config(const char* name); |
403 | |||
396 | void merge_seat_config(struct seat_config *dst, struct seat_config *src); | 404 | void merge_seat_config(struct seat_config *dst, struct seat_config *src); |
405 | |||
397 | struct seat_config *copy_seat_config(struct seat_config *seat); | 406 | struct seat_config *copy_seat_config(struct seat_config *seat); |
407 | |||
398 | void free_seat_config(struct seat_config *ic); | 408 | void free_seat_config(struct seat_config *ic); |
409 | |||
399 | struct seat_attachment_config *seat_attachment_config_new(); | 410 | struct seat_attachment_config *seat_attachment_config_new(); |
411 | |||
400 | struct seat_attachment_config *seat_config_get_attachment( | 412 | struct seat_attachment_config *seat_config_get_attachment( |
401 | struct seat_config *seat_config, char *identifier); | 413 | struct seat_config *seat_config, char *identifier); |
414 | |||
402 | void apply_seat_config(struct seat_config *seat); | 415 | void apply_seat_config(struct seat_config *seat); |
403 | 416 | ||
404 | int output_name_cmp(const void *item, const void *data); | 417 | int output_name_cmp(const void *item, const void *data); |
418 | |||
405 | void output_get_identifier(char *identifier, size_t len, | 419 | void output_get_identifier(char *identifier, size_t len, |
406 | struct sway_output *output); | 420 | struct sway_output *output); |
421 | |||
407 | struct output_config *new_output_config(const char *name); | 422 | struct output_config *new_output_config(const char *name); |
423 | |||
408 | void merge_output_config(struct output_config *dst, struct output_config *src); | 424 | void merge_output_config(struct output_config *dst, struct output_config *src); |
425 | |||
409 | void apply_output_config(struct output_config *oc, | 426 | void apply_output_config(struct output_config *oc, |
410 | struct sway_container *output); | 427 | struct sway_container *output); |
428 | |||
411 | void free_output_config(struct output_config *oc); | 429 | void free_output_config(struct output_config *oc); |
412 | 430 | ||
413 | int workspace_output_cmp_workspace(const void *a, const void *b); | 431 | int workspace_output_cmp_workspace(const void *a, const void *b); |
414 | 432 | ||
415 | int sway_binding_cmp(const void *a, const void *b); | 433 | int sway_binding_cmp(const void *a, const void *b); |
434 | |||
416 | int sway_binding_cmp_qsort(const void *a, const void *b); | 435 | int sway_binding_cmp_qsort(const void *a, const void *b); |
436 | |||
417 | int sway_binding_cmp_keys(const void *a, const void *b); | 437 | int sway_binding_cmp_keys(const void *a, const void *b); |
438 | |||
418 | void free_sway_binding(struct sway_binding *sb); | 439 | void free_sway_binding(struct sway_binding *sb); |
440 | |||
419 | struct sway_binding *sway_binding_dup(struct sway_binding *sb); | 441 | struct sway_binding *sway_binding_dup(struct sway_binding *sb); |
420 | 442 | ||
421 | /* Bar stuff */ | ||
422 | void load_swaybars(); | 443 | void load_swaybars(); |
444 | |||
423 | void invoke_swaybar(struct bar_config *bar); | 445 | void invoke_swaybar(struct bar_config *bar); |
446 | |||
424 | void terminate_swaybg(pid_t pid); | 447 | void terminate_swaybg(pid_t pid); |
448 | |||
425 | struct bar_config *default_bar_config(void); | 449 | struct bar_config *default_bar_config(void); |
450 | |||
426 | void free_bar_config(struct bar_config *bar); | 451 | void free_bar_config(struct bar_config *bar); |
427 | 452 | ||
428 | /* Global config singleton. */ | 453 | /* Global config singleton. */ |
diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index c6c73dba..8e39a4a7 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h | |||
@@ -14,7 +14,6 @@ extern struct sway_input_manager *input_manager; | |||
14 | struct sway_input_device { | 14 | struct sway_input_device { |
15 | char *identifier; | 15 | char *identifier; |
16 | struct wlr_input_device *wlr_device; | 16 | struct wlr_input_device *wlr_device; |
17 | struct input_config *config; | ||
18 | struct wl_list link; | 17 | struct wl_list link; |
19 | struct wl_listener device_destroy; | 18 | struct wl_listener device_destroy; |
20 | }; | 19 | }; |
@@ -27,30 +26,34 @@ struct sway_input_manager { | |||
27 | struct wl_listener new_input; | 26 | struct wl_listener new_input; |
28 | }; | 27 | }; |
29 | 28 | ||
30 | struct sway_input_manager *sway_input_manager_create( | 29 | struct sway_input_manager *input_manager_create(struct sway_server *server); |
31 | struct sway_server *server); | ||
32 | 30 | ||
33 | bool sway_input_manager_has_focus(struct sway_input_manager *input, | 31 | bool input_manager_has_focus(struct sway_input_manager *input, |
34 | struct sway_container *container); | 32 | struct sway_container *container); |
35 | 33 | ||
36 | void sway_input_manager_set_focus(struct sway_input_manager *input, | 34 | void input_manager_set_focus(struct sway_input_manager *input, |
37 | struct sway_container *container); | 35 | struct sway_container *container); |
38 | 36 | ||
39 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input); | 37 | void input_manager_configure_xcursor(struct sway_input_manager *input); |
40 | 38 | ||
41 | void sway_input_manager_apply_input_config(struct sway_input_manager *input, | 39 | void input_manager_apply_input_config(struct sway_input_manager *input, |
42 | struct input_config *input_config); | 40 | struct input_config *input_config); |
43 | 41 | ||
44 | void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | 42 | void input_manager_apply_seat_config(struct sway_input_manager *input, |
45 | struct seat_config *seat_config); | 43 | struct seat_config *seat_config); |
46 | 44 | ||
47 | struct sway_seat *sway_input_manager_get_default_seat( | 45 | struct sway_seat *input_manager_get_default_seat( |
48 | struct sway_input_manager *input); | 46 | struct sway_input_manager *input); |
49 | 47 | ||
50 | struct sway_seat *input_manager_get_seat(struct sway_input_manager *input, | 48 | struct sway_seat *input_manager_get_seat(struct sway_input_manager *input, |
51 | const char *seat_name); | 49 | const char *seat_name); |
52 | 50 | ||
53 | /** Gets the last seat the user interacted with */ | 51 | /** |
52 | * Gets the last seat the user interacted with | ||
53 | */ | ||
54 | struct sway_seat *input_manager_current_seat(struct sway_input_manager *input); | 54 | struct sway_seat *input_manager_current_seat(struct sway_input_manager *input); |
55 | 55 | ||
56 | struct input_config *input_device_get_config(struct sway_input_device *device); | ||
57 | |||
58 | |||
56 | #endif | 59 | #endif |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 31210a5a..5c3c2c4f 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -8,7 +8,6 @@ struct sway_seat_device { | |||
8 | struct sway_seat *sway_seat; | 8 | struct sway_seat *sway_seat; |
9 | struct sway_input_device *input_device; | 9 | struct sway_input_device *input_device; |
10 | struct sway_keyboard *keyboard; | 10 | struct sway_keyboard *keyboard; |
11 | struct seat_attachment_config *attachment_config; | ||
12 | struct wl_list link; // sway_seat::devices | 11 | struct wl_list link; // sway_seat::devices |
13 | }; | 12 | }; |
14 | 13 | ||
@@ -23,7 +22,6 @@ struct sway_seat_container { | |||
23 | 22 | ||
24 | struct sway_seat { | 23 | struct sway_seat { |
25 | struct wlr_seat *wlr_seat; | 24 | struct wlr_seat *wlr_seat; |
26 | struct seat_config *config; | ||
27 | struct sway_cursor *cursor; | 25 | struct sway_cursor *cursor; |
28 | struct sway_input_manager *input; | 26 | struct sway_input_manager *input; |
29 | 27 | ||
@@ -38,28 +36,28 @@ struct sway_seat { | |||
38 | struct wl_list link; // input_manager::seats | 36 | struct wl_list link; // input_manager::seats |
39 | }; | 37 | }; |
40 | 38 | ||
41 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | 39 | struct sway_seat *seat_create(struct sway_input_manager *input, |
42 | const char *seat_name); | 40 | const char *seat_name); |
43 | 41 | ||
44 | void sway_seat_destroy(struct sway_seat *seat); | 42 | void seat_destroy(struct sway_seat *seat); |
45 | 43 | ||
46 | void sway_seat_add_device(struct sway_seat *seat, | 44 | void seat_add_device(struct sway_seat *seat, |
47 | struct sway_input_device *device); | 45 | struct sway_input_device *device); |
48 | 46 | ||
49 | void sway_seat_configure_device(struct sway_seat *seat, | 47 | void seat_configure_device(struct sway_seat *seat, |
50 | struct sway_input_device *device); | 48 | struct sway_input_device *device); |
51 | 49 | ||
52 | void sway_seat_remove_device(struct sway_seat *seat, | 50 | void seat_remove_device(struct sway_seat *seat, |
53 | struct sway_input_device *device); | 51 | struct sway_input_device *device); |
54 | 52 | ||
55 | void sway_seat_configure_xcursor(struct sway_seat *seat); | 53 | void seat_configure_xcursor(struct sway_seat *seat); |
56 | 54 | ||
57 | void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); | 55 | void seat_set_focus(struct sway_seat *seat, struct sway_container *container); |
58 | 56 | ||
59 | void sway_seat_set_focus_warp(struct sway_seat *seat, | 57 | void seat_set_focus_warp(struct sway_seat *seat, |
60 | struct sway_container *container, bool warp); | 58 | struct sway_container *container, bool warp); |
61 | 59 | ||
62 | struct sway_container *sway_seat_get_focus(struct sway_seat *seat); | 60 | struct sway_container *seat_get_focus(struct sway_seat *seat); |
63 | 61 | ||
64 | /** | 62 | /** |
65 | * Return the last container to be focused for the seat (or the most recently | 63 | * Return the last container to be focused for the seat (or the most recently |
@@ -70,12 +68,14 @@ struct sway_container *sway_seat_get_focus(struct sway_seat *seat); | |||
70 | * is destroyed, or focus moves to a container with children and we need to | 68 | * is destroyed, or focus moves to a container with children and we need to |
71 | * descend into the next leaf in focus order. | 69 | * descend into the next leaf in focus order. |
72 | */ | 70 | */ |
73 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, | 71 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, |
74 | struct sway_container *container); | 72 | struct sway_container *container); |
75 | 73 | ||
76 | struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, | 74 | struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, |
77 | enum sway_container_type type); | 75 | enum sway_container_type type); |
78 | 76 | ||
79 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); | 77 | void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config); |
78 | |||
79 | struct seat_config *seat_get_config(struct sway_seat *seat); | ||
80 | 80 | ||
81 | #endif | 81 | #endif |
diff --git a/include/sway/output.h b/include/sway/output.h index cfe7502b..98d0f83f 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -37,4 +37,6 @@ void output_damage_whole(struct sway_output *output); | |||
37 | void output_damage_whole_view(struct sway_output *output, | 37 | void output_damage_whole_view(struct sway_output *output, |
38 | struct sway_view *view); | 38 | struct sway_view *view); |
39 | 39 | ||
40 | struct sway_container *output_by_name(const char *name); | ||
41 | |||
40 | #endif | 42 | #endif |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 423c0a22..bd02197c 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -85,9 +85,14 @@ struct sway_container { | |||
85 | 85 | ||
86 | struct { | 86 | struct { |
87 | struct wl_signal destroy; | 87 | struct wl_signal destroy; |
88 | // Raised after the tree updates, but before arrange_windows | ||
89 | // Passed the previous parent | ||
90 | struct wl_signal reparent; | ||
88 | } events; | 91 | } events; |
89 | }; | 92 | }; |
90 | 93 | ||
94 | const char *container_type_to_str(enum sway_container_type type); | ||
95 | |||
91 | // TODO only one container create function and pass the type? | 96 | // TODO only one container create function and pass the type? |
92 | struct sway_container *container_output_create( | 97 | struct sway_container *container_output_create( |
93 | struct sway_output *sway_output); | 98 | struct sway_output *sway_output); |
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index fecf1582..a14152e8 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -11,9 +11,6 @@ enum movement_direction { | |||
11 | MOVE_DOWN, | 11 | MOVE_DOWN, |
12 | MOVE_PARENT, | 12 | MOVE_PARENT, |
13 | MOVE_CHILD, | 13 | MOVE_CHILD, |
14 | MOVE_NEXT, | ||
15 | MOVE_PREV, | ||
16 | MOVE_FIRST | ||
17 | }; | 14 | }; |
18 | 15 | ||
19 | struct sway_container; | 16 | struct sway_container; |
@@ -32,7 +29,8 @@ struct sway_root { | |||
32 | 29 | ||
33 | void layout_init(void); | 30 | void layout_init(void); |
34 | 31 | ||
35 | void container_add_child(struct sway_container *parent, struct sway_container *child); | 32 | void container_add_child(struct sway_container *parent, |
33 | struct sway_container *child); | ||
36 | 34 | ||
37 | struct sway_container *container_add_sibling(struct sway_container *parent, | 35 | struct sway_container *container_add_sibling(struct sway_container *parent, |
38 | struct sway_container *child); | 36 | struct sway_container *child); |
@@ -44,7 +42,11 @@ struct sway_container *container_reap_empty(struct sway_container *container); | |||
44 | void container_move_to(struct sway_container* container, | 42 | void container_move_to(struct sway_container* container, |
45 | struct sway_container* destination); | 43 | struct sway_container* destination); |
46 | 44 | ||
47 | enum sway_container_layout container_get_default_layout(struct sway_container *output); | 45 | void container_move(struct sway_container *container, |
46 | enum movement_direction dir, int move_amt); | ||
47 | |||
48 | enum sway_container_layout container_get_default_layout( | ||
49 | struct sway_container *output); | ||
48 | 50 | ||
49 | void container_sort_workspaces(struct sway_container *output); | 51 | void container_sort_workspaces(struct sway_container *output); |
50 | 52 | ||
diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index 6ea7c4d6..a1696bcf 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include "swaybar/bar.h" | 4 | #include "swaybar/bar.h" |
5 | 5 | ||
6 | void ipc_initialize(struct swaybar *bar, const char *bar_id); | 6 | void ipc_initialize(struct swaybar *bar, const char *bar_id); |
7 | bool handle_ipc_event(struct swaybar *bar); | 7 | bool handle_ipc_readable(struct swaybar *bar); |
8 | void ipc_get_workspaces(struct swaybar *bar); | 8 | void ipc_get_workspaces(struct swaybar *bar); |
9 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws); | 9 | void ipc_send_workspace_command(struct swaybar *bar, const char *ws); |
10 | 10 | ||
diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 6c595df0..3538f49c 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h | |||
@@ -7,10 +7,52 @@ | |||
7 | 7 | ||
8 | enum status_protocol { | 8 | enum status_protocol { |
9 | PROTOCOL_UNDEF, | 9 | PROTOCOL_UNDEF, |
10 | PROTOCOL_ERROR, | ||
10 | PROTOCOL_TEXT, | 11 | PROTOCOL_TEXT, |
11 | PROTOCOL_I3BAR, | 12 | PROTOCOL_I3BAR, |
12 | }; | 13 | }; |
13 | 14 | ||
15 | struct text_protocol_state { | ||
16 | char *buffer; | ||
17 | size_t buffer_size; | ||
18 | }; | ||
19 | |||
20 | enum json_node_type { | ||
21 | JSON_NODE_UNKNOWN, | ||
22 | JSON_NODE_ARRAY, | ||
23 | JSON_NODE_STRING, | ||
24 | }; | ||
25 | |||
26 | struct i3bar_protocol_state { | ||
27 | bool click_events; | ||
28 | char *buffer; | ||
29 | size_t buffer_size; | ||
30 | size_t buffer_index; | ||
31 | const char *current_node; | ||
32 | bool escape; | ||
33 | size_t depth; | ||
34 | enum json_node_type nodes[16]; | ||
35 | }; | ||
36 | |||
37 | struct i3bar_block { | ||
38 | struct wl_list link; | ||
39 | char *full_text, *short_text, *align; | ||
40 | bool urgent; | ||
41 | uint32_t *color; | ||
42 | int min_width; | ||
43 | char *name, *instance; | ||
44 | bool separator; | ||
45 | int separator_block_width; | ||
46 | bool markup; | ||
47 | // Airblader features | ||
48 | uint32_t background; | ||
49 | uint32_t border; | ||
50 | int border_top; | ||
51 | int border_bottom; | ||
52 | int border_left; | ||
53 | int border_right; | ||
54 | }; | ||
55 | |||
14 | struct status_line { | 56 | struct status_line { |
15 | pid_t pid; | 57 | pid_t pid; |
16 | int read_fd, write_fd; | 58 | int read_fd, write_fd; |
@@ -18,13 +60,18 @@ struct status_line { | |||
18 | 60 | ||
19 | enum status_protocol protocol; | 61 | enum status_protocol protocol; |
20 | const char *text; | 62 | const char *text; |
63 | struct wl_list blocks; // i3bar_block::link | ||
21 | 64 | ||
22 | char *buffer; | 65 | struct text_protocol_state text_state; |
23 | size_t buffer_size; | 66 | struct i3bar_protocol_state i3bar_state; |
24 | }; | 67 | }; |
25 | 68 | ||
26 | struct status_line *status_line_init(char *cmd); | 69 | struct status_line *status_line_init(char *cmd); |
70 | void status_error(struct status_line *status, const char *text); | ||
71 | bool status_handle_readable(struct status_line *status); | ||
27 | void status_line_free(struct status_line *status); | 72 | void status_line_free(struct status_line *status); |
28 | bool handle_status_readable(struct status_line *status); | 73 | bool i3bar_handle_readable(struct status_line *status); |
74 | void i3bar_block_send_click(struct status_line *status, | ||
75 | struct i3bar_block *block, int x, int y, uint32_t button); | ||
29 | 76 | ||
30 | #endif | 77 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index 90544220..9ba252b0 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -72,23 +72,23 @@ void apply_input_config(struct input_config *input) { | |||
72 | list_add(config->input_configs, input); | 72 | list_add(config->input_configs, input); |
73 | } | 73 | } |
74 | 74 | ||
75 | sway_input_manager_apply_input_config(input_manager, input); | 75 | input_manager_apply_input_config(input_manager, input); |
76 | } | 76 | } |
77 | 77 | ||
78 | void apply_seat_config(struct seat_config *seat) { | 78 | void apply_seat_config(struct seat_config *seat_config) { |
79 | int i; | 79 | int i; |
80 | i = list_seq_find(config->seat_configs, seat_name_cmp, seat->name); | 80 | i = list_seq_find(config->seat_configs, seat_name_cmp, seat_config->name); |
81 | if (i >= 0) { | 81 | if (i >= 0) { |
82 | // merge existing config | 82 | // merge existing config |
83 | struct seat_config *sc = config->seat_configs->items[i]; | 83 | struct seat_config *sc = config->seat_configs->items[i]; |
84 | merge_seat_config(sc, seat); | 84 | merge_seat_config(sc, seat_config); |
85 | free_seat_config(seat); | 85 | free_seat_config(seat_config); |
86 | seat = sc; | 86 | seat_config = sc; |
87 | } else { | 87 | } else { |
88 | list_add(config->seat_configs, seat); | 88 | list_add(config->seat_configs, seat_config); |
89 | } | 89 | } |
90 | 90 | ||
91 | sway_input_manager_apply_seat_config(input_manager, seat); | 91 | input_manager_apply_seat_config(input_manager, seat_config); |
92 | } | 92 | } |
93 | 93 | ||
94 | /* Keep alphabetized */ | 94 | /* Keep alphabetized */ |
@@ -162,6 +162,7 @@ static struct cmd_handler command_handlers[] = { | |||
162 | { "focus", cmd_focus }, | 162 | { "focus", cmd_focus }, |
163 | { "kill", cmd_kill }, | 163 | { "kill", cmd_kill }, |
164 | { "layout", cmd_layout }, | 164 | { "layout", cmd_layout }, |
165 | { "move", cmd_move }, | ||
165 | { "reload", cmd_reload }, | 166 | { "reload", cmd_reload }, |
166 | }; | 167 | }; |
167 | 168 | ||
@@ -262,7 +263,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { | |||
262 | 263 | ||
263 | if (seat == NULL) { | 264 | if (seat == NULL) { |
264 | // passing a NULL seat means we just pick the default seat | 265 | // passing a NULL seat means we just pick the default seat |
265 | seat = sway_input_manager_get_default_seat(input_manager); | 266 | seat = input_manager_get_default_seat(input_manager); |
266 | if (!sway_assert(seat, "could not find a seat to run the command on")) { | 267 | if (!sway_assert(seat, "could not find a seat to run the command on")) { |
267 | return NULL; | 268 | return NULL; |
268 | } | 269 | } |
@@ -340,7 +341,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { | |||
340 | // without criteria, the command acts upon the focused | 341 | // without criteria, the command acts upon the focused |
341 | // container | 342 | // container |
342 | config->handler_context.current_container = | 343 | config->handler_context.current_container = |
343 | sway_seat_get_focus_inactive(seat, &root_container); | 344 | seat_get_focus_inactive(seat, &root_container); |
344 | if (!sway_assert(config->handler_context.current_container, | 345 | if (!sway_assert(config->handler_context.current_container, |
345 | "could not get focus-inactive for root container")) { | 346 | "could not get focus-inactive for root container")) { |
346 | return NULL; | 347 | return NULL; |
diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 64f079f4..74d9d535 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c | |||
@@ -20,10 +20,6 @@ static bool parse_movement_direction(const char *name, | |||
20 | *out = MOVE_PARENT; | 20 | *out = MOVE_PARENT; |
21 | } else if (strcasecmp(name, "child") == 0) { | 21 | } else if (strcasecmp(name, "child") == 0) { |
22 | *out = MOVE_CHILD; | 22 | *out = MOVE_CHILD; |
23 | } else if (strcasecmp(name, "next") == 0) { | ||
24 | *out = MOVE_NEXT; | ||
25 | } else if (strcasecmp(name, "prev") == 0) { | ||
26 | *out = MOVE_PREV; | ||
27 | } else { | 23 | } else { |
28 | return false; | 24 | return false; |
29 | } | 25 | } |
@@ -40,7 +36,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { | |||
40 | } | 36 | } |
41 | 37 | ||
42 | if (argc == 0) { | 38 | if (argc == 0) { |
43 | sway_seat_set_focus(seat, con); | 39 | seat_set_focus(seat, con); |
44 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 40 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
45 | } | 41 | } |
46 | 42 | ||
@@ -51,9 +47,10 @@ struct cmd_results *cmd_focus(int argc, char **argv) { | |||
51 | "Expected 'focus <direction|parent|child|mode_toggle>' or 'focus output <direction|name>'"); | 47 | "Expected 'focus <direction|parent|child|mode_toggle>' or 'focus output <direction|name>'"); |
52 | } | 48 | } |
53 | 49 | ||
54 | struct sway_container *next_focus = container_get_in_direction(con, seat, direction); | 50 | struct sway_container *next_focus = container_get_in_direction( |
51 | con, seat, direction); | ||
55 | if (next_focus) { | 52 | if (next_focus) { |
56 | sway_seat_set_focus(seat, next_focus); | 53 | seat_set_focus(seat, next_focus); |
57 | } | 54 | } |
58 | 55 | ||
59 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 56 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/move.c b/sway/commands/move.c new file mode 100644 index 00000000..644c622b --- /dev/null +++ b/sway/commands/move.c | |||
@@ -0,0 +1,184 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include <wlr/types/wlr_output.h> | ||
4 | #include <wlr/types/wlr_output_layout.h> | ||
5 | #include <wlr/util/log.h> | ||
6 | #include "sway/commands.h" | ||
7 | #include "sway/input/seat.h" | ||
8 | #include "sway/output.h" | ||
9 | #include "sway/tree/container.h" | ||
10 | #include "sway/tree/layout.h" | ||
11 | #include "sway/tree/workspace.h" | ||
12 | #include "stringop.h" | ||
13 | #include "list.h" | ||
14 | |||
15 | static const char* expected_syntax = | ||
16 | "Expected 'move <left|right|up|down> <[px] px>' or " | ||
17 | "'move <container|window> to workspace <name>' or " | ||
18 | "'move <container|window|workspace> to output <name|direction>' or " | ||
19 | "'move position mouse'"; | ||
20 | |||
21 | static struct sway_container *output_in_direction(const char *direction, | ||
22 | struct wlr_output *reference, int ref_ox, int ref_oy) { | ||
23 | int ref_lx = ref_ox + reference->lx, | ||
24 | ref_ly = ref_oy + reference->ly; | ||
25 | struct { | ||
26 | char *name; | ||
27 | enum wlr_direction direction; | ||
28 | } names[] = { | ||
29 | { "up", WLR_DIRECTION_UP }, | ||
30 | { "down", WLR_DIRECTION_DOWN }, | ||
31 | { "left", WLR_DIRECTION_LEFT }, | ||
32 | { "right", WLR_DIRECTION_RIGHT }, | ||
33 | }; | ||
34 | for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i) { | ||
35 | if (strcasecmp(names[i].name, direction) == 0) { | ||
36 | struct wlr_output *adjacent = wlr_output_layout_adjacent_output( | ||
37 | root_container.sway_root->output_layout, | ||
38 | names[i].direction, reference, ref_lx, ref_ly); | ||
39 | if (adjacent) { | ||
40 | struct sway_output *sway_output = adjacent->data; | ||
41 | return sway_output->swayc; | ||
42 | } | ||
43 | break; | ||
44 | } | ||
45 | } | ||
46 | return output_by_name(direction); | ||
47 | } | ||
48 | |||
49 | static struct cmd_results *cmd_move_container(struct sway_container *current, | ||
50 | int argc, char **argv) { | ||
51 | struct cmd_results *error = NULL; | ||
52 | if ((error = checkarg(argc, "move container/window", | ||
53 | EXPECTED_AT_LEAST, 4))) { | ||
54 | return error; | ||
55 | } else if (strcasecmp(argv[1], "to") == 0 | ||
56 | && strcasecmp(argv[2], "workspace") == 0) { | ||
57 | // move container to workspace x | ||
58 | if (current->type == C_WORKSPACE) { | ||
59 | // TODO: Wrap children in a container and move that | ||
60 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
61 | } else if (current->type != C_CONTAINER && current->type != C_VIEW) { | ||
62 | return cmd_results_new(CMD_FAILURE, "move", | ||
63 | "Can only move containers and views."); | ||
64 | } | ||
65 | struct sway_container *ws; | ||
66 | const char *num_name = NULL; | ||
67 | char *ws_name = NULL; | ||
68 | if (argc == 5 && strcasecmp(argv[3], "number") == 0) { | ||
69 | // move "container to workspace number x" | ||
70 | num_name = argv[4]; | ||
71 | ws = workspace_by_number(num_name); | ||
72 | } else { | ||
73 | ws_name = join_args(argv + 3, argc - 3); | ||
74 | ws = workspace_by_name(ws_name); | ||
75 | } | ||
76 | if (!ws) { | ||
77 | ws = workspace_create(ws_name ? ws_name : num_name); | ||
78 | } | ||
79 | free(ws_name); | ||
80 | struct sway_container *old_parent = current->parent; | ||
81 | struct sway_container *focus = seat_get_focus_inactive( | ||
82 | config->handler_context.seat, ws); | ||
83 | container_move_to(current, focus); | ||
84 | seat_set_focus(config->handler_context.seat, old_parent); | ||
85 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
86 | } else if (strcasecmp(argv[1], "to") == 0 | ||
87 | && strcasecmp(argv[2], "output") == 0) { | ||
88 | if (current->type == C_WORKSPACE) { | ||
89 | // TODO: Wrap children in a container and move that | ||
90 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
91 | } else if (current->type != C_CONTAINER | ||
92 | && current->type != C_VIEW) { | ||
93 | return cmd_results_new(CMD_FAILURE, "move", | ||
94 | "Can only move containers and views."); | ||
95 | } | ||
96 | struct sway_container *source = container_parent(current, C_OUTPUT); | ||
97 | struct sway_container *destination = output_in_direction(argv[3], | ||
98 | source->sway_output->wlr_output, current->x, current->y); | ||
99 | if (!destination) { | ||
100 | return cmd_results_new(CMD_FAILURE, "move workspace", | ||
101 | "Can't find output with name/direction '%s'", argv[3]); | ||
102 | } | ||
103 | struct sway_container *focus = seat_get_focus_inactive( | ||
104 | config->handler_context.seat, destination); | ||
105 | if (!focus) { | ||
106 | // We've never been to this output before | ||
107 | focus = destination->children->items[0]; | ||
108 | } | ||
109 | struct sway_container *old_parent = current->parent; | ||
110 | container_move_to(current, focus); | ||
111 | seat_set_focus(config->handler_context.seat, old_parent); | ||
112 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
113 | } | ||
114 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | ||
115 | } | ||
116 | |||
117 | static struct cmd_results *cmd_move_workspace(struct sway_container *current, | ||
118 | int argc, char **argv) { | ||
119 | struct cmd_results *error = NULL; | ||
120 | if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) { | ||
121 | return error; | ||
122 | } else if (strcasecmp(argv[1], "to") != 0 | ||
123 | || strcasecmp(argv[2], "output") != 0) { | ||
124 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | ||
125 | } | ||
126 | struct sway_container *source = container_parent(current, C_OUTPUT); | ||
127 | int center_x = current->width / 2 + current->x, | ||
128 | center_y = current->height / 2 + current->y; | ||
129 | struct sway_container *destination = output_in_direction(argv[3], | ||
130 | source->sway_output->wlr_output, center_x, center_y); | ||
131 | if (!destination) { | ||
132 | return cmd_results_new(CMD_FAILURE, "move workspace", | ||
133 | "Can't find output with name/direction '%s'", argv[3]); | ||
134 | } | ||
135 | if (current->type != C_WORKSPACE) { | ||
136 | current = container_parent(current, C_WORKSPACE); | ||
137 | } | ||
138 | container_move_to(current, destination); | ||
139 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
140 | } | ||
141 | |||
142 | struct cmd_results *cmd_move(int argc, char **argv) { | ||
143 | struct cmd_results *error = NULL; | ||
144 | int move_amt = 10; | ||
145 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { | ||
146 | return error; | ||
147 | } | ||
148 | struct sway_container *current = config->handler_context.current_container; | ||
149 | |||
150 | if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0)) { | ||
151 | char *inv; | ||
152 | move_amt = (int)strtol(argv[1], &inv, 10); | ||
153 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
154 | return cmd_results_new(CMD_FAILURE, "move", | ||
155 | "Invalid distance specified"); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | if (strcasecmp(argv[0], "left") == 0) { | ||
160 | container_move(current, MOVE_LEFT, move_amt); | ||
161 | } else if (strcasecmp(argv[0], "right") == 0) { | ||
162 | container_move(current, MOVE_RIGHT, move_amt); | ||
163 | } else if (strcasecmp(argv[0], "up") == 0) { | ||
164 | container_move(current, MOVE_UP, move_amt); | ||
165 | } else if (strcasecmp(argv[0], "down") == 0) { | ||
166 | container_move(current, MOVE_DOWN, move_amt); | ||
167 | } else if (strcasecmp(argv[0], "container") == 0 | ||
168 | || strcasecmp(argv[0], "window") == 0) { | ||
169 | return cmd_move_container(current, argc, argv); | ||
170 | } else if (strcasecmp(argv[0], "workspace") == 0) { | ||
171 | return cmd_move_workspace(current, argc, argv); | ||
172 | } else if (strcasecmp(argv[0], "scratchpad") == 0 | ||
173 | || (strcasecmp(argv[0], "to") == 0 | ||
174 | && strcasecmp(argv[1], "scratchpad") == 0)) { | ||
175 | // TODO: scratchpad | ||
176 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
177 | } else if (strcasecmp(argv[0], "position") == 0) { | ||
178 | // TODO: floating | ||
179 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | ||
180 | } else { | ||
181 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | ||
182 | } | ||
183 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
184 | } | ||
diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 45079616..819b769c 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c | |||
@@ -14,7 +14,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) { | |||
14 | free_seat_config(config->handler_context.seat_config); | 14 | free_seat_config(config->handler_context.seat_config); |
15 | config->handler_context.seat_config = new_seat_config(argv[0]); | 15 | config->handler_context.seat_config = new_seat_config(argv[0]); |
16 | if (!config->handler_context.seat_config) { | 16 | if (!config->handler_context.seat_config) { |
17 | return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); | 17 | return cmd_results_new(CMD_FAILURE, NULL, |
18 | "Couldn't allocate config"); | ||
18 | } | 19 | } |
19 | wlr_log(L_DEBUG, "entering seat block: %s", argv[0]); | 20 | wlr_log(L_DEBUG, "entering seat block: %s", argv[0]); |
20 | return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); | 21 | return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); |
@@ -28,7 +29,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) { | |||
28 | if (!has_context) { | 29 | if (!has_context) { |
29 | config->handler_context.seat_config = new_seat_config(argv[0]); | 30 | config->handler_context.seat_config = new_seat_config(argv[0]); |
30 | if (!config->handler_context.seat_config) { | 31 | if (!config->handler_context.seat_config) { |
31 | return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config"); | 32 | return cmd_results_new(CMD_FAILURE, NULL, |
33 | "Couldn't allocate config"); | ||
32 | } | 34 | } |
33 | } | 35 | } |
34 | 36 | ||
@@ -41,7 +43,10 @@ struct cmd_results *cmd_seat(int argc, char **argv) { | |||
41 | } else if (strcasecmp("fallback", argv[1]) == 0) { | 43 | } else if (strcasecmp("fallback", argv[1]) == 0) { |
42 | res = seat_cmd_fallback(argc_new, argv_new); | 44 | res = seat_cmd_fallback(argc_new, argv_new); |
43 | } else { | 45 | } else { |
44 | res = cmd_results_new(CMD_INVALID, "seat <name>", "Unknown command %s", argv[1]); | 46 | res = |
47 | cmd_results_new(CMD_INVALID, | ||
48 | "seat <name>", "Unknown command %s", | ||
49 | argv[1]); | ||
45 | } | 50 | } |
46 | 51 | ||
47 | if (!has_context) { | 52 | if (!has_context) { |
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 8f39e5fc..aa4096f7 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c | |||
@@ -91,7 +91,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | |||
91 | } | 91 | } |
92 | workspace_switch(ws); | 92 | workspace_switch(ws); |
93 | current_container = | 93 | current_container = |
94 | sway_seat_get_focus(config->handler_context.seat); | 94 | seat_get_focus(config->handler_context.seat); |
95 | struct sway_container *new_output = container_parent(current_container, C_OUTPUT); | 95 | struct sway_container *new_output = container_parent(current_container, C_OUTPUT); |
96 | 96 | ||
97 | if (config->mouse_warping && old_output != new_output) { | 97 | if (config->mouse_warping && old_output != new_output) { |
diff --git a/sway/config.c b/sway/config.c index 0eecf7f6..90b833ab 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -125,7 +125,7 @@ static void destroy_removed_seats(struct sway_config *old_config, | |||
125 | seat_name_cmp, seat_config->name) < 0) { | 125 | seat_name_cmp, seat_config->name) < 0) { |
126 | seat = input_manager_get_seat(input_manager, | 126 | seat = input_manager_get_seat(input_manager, |
127 | seat_config->name); | 127 | seat_config->name); |
128 | sway_seat_destroy(seat); | 128 | seat_destroy(seat); |
129 | } | 129 | } |
130 | } | 130 | } |
131 | } | 131 | } |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 352f4af3..10ed1f6d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -245,10 +245,13 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
245 | 245 | ||
246 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 246 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
247 | struct sway_container *focus = | 247 | struct sway_container *focus = |
248 | sway_seat_get_focus_inactive(seat, output->swayc); | 248 | seat_get_focus_inactive(seat, output->swayc); |
249 | struct sway_container *workspace = (focus->type == C_WORKSPACE ? | 249 | if (!focus) { |
250 | focus : | 250 | // We've never been to this output before |
251 | container_parent(focus, C_WORKSPACE)); | 251 | focus = output->swayc->children->items[0]; |
252 | } | ||
253 | struct sway_container *workspace = focus->type == C_WORKSPACE ? | ||
254 | focus : container_parent(focus, C_WORKSPACE); | ||
252 | 255 | ||
253 | struct render_data rdata = { | 256 | struct render_data rdata = { |
254 | .output = output, | 257 | .output = output, |
@@ -393,7 +396,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
393 | wl_list_init(&output->layers[i]); | 396 | wl_list_init(&output->layers[i]); |
394 | } | 397 | } |
395 | 398 | ||
396 | sway_input_manager_configure_xcursor(input_manager); | 399 | input_manager_configure_xcursor(input_manager); |
397 | 400 | ||
398 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | 401 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); |
399 | output->destroy.notify = handle_destroy; | 402 | output->destroy.notify = handle_destroy; |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 77ab9e31..97b4473c 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -85,7 +85,7 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, | |||
85 | 85 | ||
86 | // find the focused workspace on the output for this seat | 86 | // find the focused workspace on the output for this seat |
87 | struct sway_container *ws = | 87 | struct sway_container *ws = |
88 | sway_seat_get_focus_inactive(cursor->seat, output->swayc); | 88 | seat_get_focus_inactive(cursor->seat, output->swayc); |
89 | if (ws && ws->type != C_WORKSPACE) { | 89 | if (ws && ws->type != C_WORKSPACE) { |
90 | ws = container_parent(ws, C_WORKSPACE); | 90 | ws = container_parent(ws, C_WORKSPACE); |
91 | } | 91 | } |
@@ -130,7 +130,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
130 | double sx, sy; | 130 | double sx, sy; |
131 | struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); | 131 | struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); |
132 | if (c && config->focus_follows_mouse) { | 132 | if (c && config->focus_follows_mouse) { |
133 | sway_seat_set_focus_warp(cursor->seat, c, false); | 133 | seat_set_focus_warp(cursor->seat, c, false); |
134 | } | 134 | } |
135 | 135 | ||
136 | // reset cursor if switching between clients | 136 | // reset cursor if switching between clients |
@@ -192,15 +192,15 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
192 | if (new_ws && new_ws->type != C_WORKSPACE) { | 192 | if (new_ws && new_ws->type != C_WORKSPACE) { |
193 | new_ws = container_parent(new_ws, C_WORKSPACE); | 193 | new_ws = container_parent(new_ws, C_WORKSPACE); |
194 | } | 194 | } |
195 | struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); | 195 | struct sway_container *old_ws = seat_get_focus(cursor->seat); |
196 | if (old_ws && old_ws->type != C_WORKSPACE) { | 196 | if (old_ws && old_ws->type != C_WORKSPACE) { |
197 | old_ws = container_parent(old_ws, C_WORKSPACE); | 197 | old_ws = container_parent(old_ws, C_WORKSPACE); |
198 | } | 198 | } |
199 | if (new_ws != old_ws) { | 199 | if (new_ws != old_ws) { |
200 | sway_seat_set_focus(cursor->seat, cont); | 200 | seat_set_focus(cursor->seat, cont); |
201 | } | 201 | } |
202 | } else { | 202 | } else { |
203 | sway_seat_set_focus(cursor->seat, cont); | 203 | seat_set_focus(cursor->seat, cont); |
204 | } | 204 | } |
205 | 205 | ||
206 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, | 206 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, |
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index d421a03f..c3507f65 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -26,7 +26,7 @@ struct seat_config *current_seat_config = NULL; | |||
26 | struct sway_seat *input_manager_current_seat(struct sway_input_manager *input) { | 26 | struct sway_seat *input_manager_current_seat(struct sway_input_manager *input) { |
27 | struct sway_seat *seat = config->handler_context.seat; | 27 | struct sway_seat *seat = config->handler_context.seat; |
28 | if (!seat) { | 28 | if (!seat) { |
29 | seat = sway_input_manager_get_default_seat(input_manager); | 29 | seat = input_manager_get_default_seat(input_manager); |
30 | } | 30 | } |
31 | return seat; | 31 | return seat; |
32 | } | 32 | } |
@@ -40,7 +40,7 @@ struct sway_seat *input_manager_get_seat( | |||
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
43 | return sway_seat_create(input, seat_name); | 43 | return seat_create(input, seat_name); |
44 | } | 44 | } |
45 | 45 | ||
46 | static char *get_device_identifier(struct wlr_input_device *device) { | 46 | static char *get_device_identifier(struct wlr_input_device *device) { |
@@ -83,7 +83,8 @@ static struct sway_input_device *input_sway_device_from_wlr( | |||
83 | static bool input_has_seat_configuration(struct sway_input_manager *input) { | 83 | static bool input_has_seat_configuration(struct sway_input_manager *input) { |
84 | struct sway_seat *seat = NULL; | 84 | struct sway_seat *seat = NULL; |
85 | wl_list_for_each(seat, &input->seats, link) { | 85 | wl_list_for_each(seat, &input->seats, link) { |
86 | if (seat->config) { | 86 | struct seat_config *seat_config = seat_get_config(seat); |
87 | if (seat_config) { | ||
87 | return true; | 88 | return true; |
88 | } | 89 | } |
89 | } | 90 | } |
@@ -91,9 +92,10 @@ static bool input_has_seat_configuration(struct sway_input_manager *input) { | |||
91 | return false; | 92 | return false; |
92 | } | 93 | } |
93 | 94 | ||
94 | static void sway_input_manager_libinput_config_pointer(struct sway_input_device *input_device) { | 95 | static void input_manager_libinput_config_pointer( |
96 | struct sway_input_device *input_device) { | ||
95 | struct wlr_input_device *wlr_device = input_device->wlr_device; | 97 | struct wlr_input_device *wlr_device = input_device->wlr_device; |
96 | struct input_config *ic = input_device->config; | 98 | struct input_config *ic = input_device_get_config(input_device); |
97 | struct libinput_device *libinput_device; | 99 | struct libinput_device *libinput_device; |
98 | 100 | ||
99 | if (!ic || !wlr_input_device_is_libinput(wlr_device)) { | 101 | if (!ic || !wlr_input_device_is_libinput(wlr_device)) { |
@@ -101,22 +103,27 @@ static void sway_input_manager_libinput_config_pointer(struct sway_input_device | |||
101 | } | 103 | } |
102 | 104 | ||
103 | libinput_device = wlr_libinput_get_device_handle(wlr_device); | 105 | libinput_device = wlr_libinput_get_device_handle(wlr_device); |
104 | wlr_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier); | 106 | wlr_log(L_DEBUG, "input_manager_libinput_config_pointer(%s)", |
107 | ic->identifier); | ||
105 | 108 | ||
106 | if (ic->accel_profile != INT_MIN) { | 109 | if (ic->accel_profile != INT_MIN) { |
107 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", | 110 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", |
108 | ic->identifier, ic->accel_profile); | 111 | ic->identifier, ic->accel_profile); |
109 | libinput_device_config_accel_set_profile(libinput_device, ic->accel_profile); | 112 | libinput_device_config_accel_set_profile(libinput_device, |
113 | ic->accel_profile); | ||
110 | } | 114 | } |
111 | if (ic->click_method != INT_MIN) { | 115 | if (ic->click_method != INT_MIN) { |
112 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", | 116 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", |
113 | ic->identifier, ic->click_method); | 117 | ic->identifier, ic->click_method); |
114 | libinput_device_config_click_set_method(libinput_device, ic->click_method); | 118 | libinput_device_config_click_set_method(libinput_device, |
119 | ic->click_method); | ||
115 | } | 120 | } |
116 | if (ic->drag_lock != INT_MIN) { | 121 | if (ic->drag_lock != INT_MIN) { |
117 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", | 122 | wlr_log(L_DEBUG, |
123 | "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", | ||
118 | ic->identifier, ic->click_method); | 124 | ic->identifier, ic->click_method); |
119 | libinput_device_config_tap_set_drag_lock_enabled(libinput_device, ic->drag_lock); | 125 | libinput_device_config_tap_set_drag_lock_enabled(libinput_device, |
126 | ic->drag_lock); | ||
120 | } | 127 | } |
121 | if (ic->dwt != INT_MIN) { | 128 | if (ic->dwt != INT_MIN) { |
122 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", | 129 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", |
@@ -124,34 +131,43 @@ static void sway_input_manager_libinput_config_pointer(struct sway_input_device | |||
124 | libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); | 131 | libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); |
125 | } | 132 | } |
126 | if (ic->left_handed != INT_MIN) { | 133 | if (ic->left_handed != INT_MIN) { |
127 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", | 134 | wlr_log(L_DEBUG, |
135 | "libinput_config_pointer(%s) left_handed_set_enabled(%d)", | ||
128 | ic->identifier, ic->left_handed); | 136 | ic->identifier, ic->left_handed); |
129 | libinput_device_config_left_handed_set(libinput_device, ic->left_handed); | 137 | libinput_device_config_left_handed_set(libinput_device, |
138 | ic->left_handed); | ||
130 | } | 139 | } |
131 | if (ic->middle_emulation != INT_MIN) { | 140 | if (ic->middle_emulation != INT_MIN) { |
132 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", | 141 | wlr_log(L_DEBUG, |
142 | "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", | ||
133 | ic->identifier, ic->middle_emulation); | 143 | ic->identifier, ic->middle_emulation); |
134 | libinput_device_config_middle_emulation_set_enabled(libinput_device, ic->middle_emulation); | 144 | libinput_device_config_middle_emulation_set_enabled(libinput_device, |
145 | ic->middle_emulation); | ||
135 | } | 146 | } |
136 | if (ic->natural_scroll != INT_MIN) { | 147 | if (ic->natural_scroll != INT_MIN) { |
137 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", | 148 | wlr_log(L_DEBUG, |
149 | "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", | ||
138 | ic->identifier, ic->natural_scroll); | 150 | ic->identifier, ic->natural_scroll); |
139 | libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, ic->natural_scroll); | 151 | libinput_device_config_scroll_set_natural_scroll_enabled( |
152 | libinput_device, ic->natural_scroll); | ||
140 | } | 153 | } |
141 | if (ic->pointer_accel != FLT_MIN) { | 154 | if (ic->pointer_accel != FLT_MIN) { |
142 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", | 155 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", |
143 | ic->identifier, ic->pointer_accel); | 156 | ic->identifier, ic->pointer_accel); |
144 | libinput_device_config_accel_set_speed(libinput_device, ic->pointer_accel); | 157 | libinput_device_config_accel_set_speed(libinput_device, |
158 | ic->pointer_accel); | ||
145 | } | 159 | } |
146 | if (ic->scroll_method != INT_MIN) { | 160 | if (ic->scroll_method != INT_MIN) { |
147 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", | 161 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", |
148 | ic->identifier, ic->scroll_method); | 162 | ic->identifier, ic->scroll_method); |
149 | libinput_device_config_scroll_set_method(libinput_device, ic->scroll_method); | 163 | libinput_device_config_scroll_set_method(libinput_device, |
164 | ic->scroll_method); | ||
150 | } | 165 | } |
151 | if (ic->send_events != INT_MIN) { | 166 | if (ic->send_events != INT_MIN) { |
152 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", | 167 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", |
153 | ic->identifier, ic->send_events); | 168 | ic->identifier, ic->send_events); |
154 | libinput_device_config_send_events_set_mode(libinput_device, ic->send_events); | 169 | libinput_device_config_send_events_set_mode(libinput_device, |
170 | ic->send_events); | ||
155 | } | 171 | } |
156 | if (ic->tap != INT_MIN) { | 172 | if (ic->tap != INT_MIN) { |
157 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", | 173 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", |
@@ -175,12 +191,11 @@ static void handle_device_destroy(struct wl_listener *listener, void *data) { | |||
175 | 191 | ||
176 | struct sway_seat *seat = NULL; | 192 | struct sway_seat *seat = NULL; |
177 | wl_list_for_each(seat, &input_manager->seats, link) { | 193 | wl_list_for_each(seat, &input_manager->seats, link) { |
178 | sway_seat_remove_device(seat, input_device); | 194 | seat_remove_device(seat, input_device); |
179 | } | 195 | } |
180 | 196 | ||
181 | wl_list_remove(&input_device->link); | 197 | wl_list_remove(&input_device->link); |
182 | wl_list_remove(&input_device->device_destroy.link); | 198 | wl_list_remove(&input_device->device_destroy.link); |
183 | free_input_config(input_device->config); | ||
184 | free(input_device->identifier); | 199 | free(input_device->identifier); |
185 | free(input_device); | 200 | free(input_device); |
186 | } | 201 | } |
@@ -203,44 +218,36 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
203 | wlr_log(L_DEBUG, "adding device: '%s'", | 218 | wlr_log(L_DEBUG, "adding device: '%s'", |
204 | input_device->identifier); | 219 | input_device->identifier); |
205 | 220 | ||
206 | // find config | ||
207 | for (int i = 0; i < config->input_configs->length; ++i) { | ||
208 | struct input_config *input_config = config->input_configs->items[i]; | ||
209 | if (strcmp(input_config->identifier, input_device->identifier) == 0) { | ||
210 | free_input_config(input_device->config); | ||
211 | input_device->config = copy_input_config(input_config); | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { | 221 | if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { |
217 | sway_input_manager_libinput_config_pointer(input_device); | 222 | input_manager_libinput_config_pointer(input_device); |
218 | } | 223 | } |
219 | 224 | ||
220 | struct sway_seat *seat = NULL; | 225 | struct sway_seat *seat = NULL; |
221 | if (!input_has_seat_configuration(input)) { | 226 | if (!input_has_seat_configuration(input)) { |
222 | wlr_log(L_DEBUG, "no seat configuration, using default seat"); | 227 | wlr_log(L_DEBUG, "no seat configuration, using default seat"); |
223 | seat = input_manager_get_seat(input, default_seat); | 228 | seat = input_manager_get_seat(input, default_seat); |
224 | sway_seat_add_device(seat, input_device); | 229 | seat_add_device(seat, input_device); |
225 | return; | 230 | return; |
226 | } | 231 | } |
227 | 232 | ||
228 | bool added = false; | 233 | bool added = false; |
229 | wl_list_for_each(seat, &input->seats, link) { | 234 | wl_list_for_each(seat, &input->seats, link) { |
230 | bool has_attachment = seat->config && | 235 | struct seat_config *seat_config = seat_get_config(seat); |
231 | (seat_config_get_attachment(seat->config, input_device->identifier) || | 236 | bool has_attachment = seat_config && |
232 | seat_config_get_attachment(seat->config, "*")); | 237 | (seat_config_get_attachment(seat_config, input_device->identifier) || |
238 | seat_config_get_attachment(seat_config, "*")); | ||
233 | 239 | ||
234 | if (has_attachment) { | 240 | if (has_attachment) { |
235 | sway_seat_add_device(seat, input_device); | 241 | seat_add_device(seat, input_device); |
236 | added = true; | 242 | added = true; |
237 | } | 243 | } |
238 | } | 244 | } |
239 | 245 | ||
240 | if (!added) { | 246 | if (!added) { |
241 | wl_list_for_each(seat, &input->seats, link) { | 247 | wl_list_for_each(seat, &input->seats, link) { |
242 | if (seat->config && seat->config->fallback == 1) { | 248 | struct seat_config *seat_config = seat_get_config(seat); |
243 | sway_seat_add_device(seat, input_device); | 249 | if (seat_config && seat_config->fallback == 1) { |
250 | seat_add_device(seat, input_device); | ||
244 | added = true; | 251 | added = true; |
245 | } | 252 | } |
246 | } | 253 | } |
@@ -256,7 +263,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
256 | input_device->device_destroy.notify = handle_device_destroy; | 263 | input_device->device_destroy.notify = handle_device_destroy; |
257 | } | 264 | } |
258 | 265 | ||
259 | struct sway_input_manager *sway_input_manager_create( | 266 | struct sway_input_manager *input_manager_create( |
260 | struct sway_server *server) { | 267 | struct sway_server *server) { |
261 | struct sway_input_manager *input = | 268 | struct sway_input_manager *input = |
262 | calloc(1, sizeof(struct sway_input_manager)); | 269 | calloc(1, sizeof(struct sway_input_manager)); |
@@ -277,11 +284,11 @@ struct sway_input_manager *sway_input_manager_create( | |||
277 | return input; | 284 | return input; |
278 | } | 285 | } |
279 | 286 | ||
280 | bool sway_input_manager_has_focus(struct sway_input_manager *input, | 287 | bool input_manager_has_focus(struct sway_input_manager *input, |
281 | struct sway_container *container) { | 288 | struct sway_container *container) { |
282 | struct sway_seat *seat = NULL; | 289 | struct sway_seat *seat = NULL; |
283 | wl_list_for_each(seat, &input->seats, link) { | 290 | wl_list_for_each(seat, &input->seats, link) { |
284 | if (sway_seat_get_focus(seat) == container) { | 291 | if (seat_get_focus(seat) == container) { |
285 | return true; | 292 | return true; |
286 | } | 293 | } |
287 | } | 294 | } |
@@ -289,35 +296,32 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, | |||
289 | return false; | 296 | return false; |
290 | } | 297 | } |
291 | 298 | ||
292 | void sway_input_manager_set_focus(struct sway_input_manager *input, | 299 | void input_manager_set_focus(struct sway_input_manager *input, |
293 | struct sway_container *container) { | 300 | struct sway_container *container) { |
294 | struct sway_seat *seat ; | 301 | struct sway_seat *seat ; |
295 | wl_list_for_each(seat, &input->seats, link) { | 302 | wl_list_for_each(seat, &input->seats, link) { |
296 | sway_seat_set_focus(seat, container); | 303 | seat_set_focus(seat, container); |
297 | } | 304 | } |
298 | } | 305 | } |
299 | 306 | ||
300 | void sway_input_manager_apply_input_config(struct sway_input_manager *input, | 307 | void input_manager_apply_input_config(struct sway_input_manager *input, |
301 | struct input_config *input_config) { | 308 | struct input_config *input_config) { |
302 | struct sway_input_device *input_device = NULL; | 309 | struct sway_input_device *input_device = NULL; |
303 | wl_list_for_each(input_device, &input->devices, link) { | 310 | wl_list_for_each(input_device, &input->devices, link) { |
304 | if (strcmp(input_device->identifier, input_config->identifier) == 0) { | 311 | if (strcmp(input_device->identifier, input_config->identifier) == 0) { |
305 | free_input_config(input_device->config); | ||
306 | input_device->config = copy_input_config(input_config); | ||
307 | |||
308 | if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { | 312 | if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { |
309 | sway_input_manager_libinput_config_pointer(input_device); | 313 | input_manager_libinput_config_pointer(input_device); |
310 | } | 314 | } |
311 | 315 | ||
312 | struct sway_seat *seat = NULL; | 316 | struct sway_seat *seat = NULL; |
313 | wl_list_for_each(seat, &input->seats, link) { | 317 | wl_list_for_each(seat, &input->seats, link) { |
314 | sway_seat_configure_device(seat, input_device); | 318 | seat_configure_device(seat, input_device); |
315 | } | 319 | } |
316 | } | 320 | } |
317 | } | 321 | } |
318 | } | 322 | } |
319 | 323 | ||
320 | void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | 324 | void input_manager_apply_seat_config(struct sway_input_manager *input, |
321 | struct seat_config *seat_config) { | 325 | struct seat_config *seat_config) { |
322 | wlr_log(L_DEBUG, "applying new seat config for seat %s", | 326 | wlr_log(L_DEBUG, "applying new seat config for seat %s", |
323 | seat_config->name); | 327 | seat_config->name); |
@@ -326,7 +330,7 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | |||
326 | return; | 330 | return; |
327 | } | 331 | } |
328 | 332 | ||
329 | sway_seat_set_config(seat, seat_config); | 333 | seat_apply_config(seat, seat_config); |
330 | 334 | ||
331 | // for every device, try to add it to a seat and if no seat has it | 335 | // for every device, try to add it to a seat and if no seat has it |
332 | // attached, add it to the fallback seats. | 336 | // attached, add it to the fallback seats. |
@@ -335,11 +339,12 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | |||
335 | list_t *seat_list = create_list(); | 339 | list_t *seat_list = create_list(); |
336 | struct sway_seat *seat = NULL; | 340 | struct sway_seat *seat = NULL; |
337 | wl_list_for_each(seat, &input->seats, link) { | 341 | wl_list_for_each(seat, &input->seats, link) { |
338 | if (!seat->config) { | 342 | struct seat_config *seat_config = seat_get_config(seat); |
343 | if (!seat_config) { | ||
339 | continue; | 344 | continue; |
340 | } | 345 | } |
341 | if (seat_config_get_attachment(seat->config, "*") || | 346 | if (seat_config_get_attachment(seat_config, "*") || |
342 | seat_config_get_attachment(seat->config, | 347 | seat_config_get_attachment(seat_config, |
343 | input_device->identifier)) { | 348 | input_device->identifier)) { |
344 | list_add(seat_list, seat); | 349 | list_add(seat_list, seat); |
345 | } | 350 | } |
@@ -355,17 +360,18 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | |||
355 | } | 360 | } |
356 | } | 361 | } |
357 | if (attached) { | 362 | if (attached) { |
358 | sway_seat_add_device(seat, input_device); | 363 | seat_add_device(seat, input_device); |
359 | } else { | 364 | } else { |
360 | sway_seat_remove_device(seat, input_device); | 365 | seat_remove_device(seat, input_device); |
361 | } | 366 | } |
362 | } | 367 | } |
363 | } else { | 368 | } else { |
364 | wl_list_for_each(seat, &input->seats, link) { | 369 | wl_list_for_each(seat, &input->seats, link) { |
365 | if (seat->config && seat->config->fallback == 1) { | 370 | struct seat_config *seat_config = seat_get_config(seat); |
366 | sway_seat_add_device(seat, input_device); | 371 | if (seat_config && seat_config->fallback == 1) { |
372 | seat_add_device(seat, input_device); | ||
367 | } else { | 373 | } else { |
368 | sway_seat_remove_device(seat, input_device); | 374 | seat_remove_device(seat, input_device); |
369 | } | 375 | } |
370 | } | 376 | } |
371 | } | 377 | } |
@@ -373,14 +379,14 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | |||
373 | } | 379 | } |
374 | } | 380 | } |
375 | 381 | ||
376 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { | 382 | void input_manager_configure_xcursor(struct sway_input_manager *input) { |
377 | struct sway_seat *seat = NULL; | 383 | struct sway_seat *seat = NULL; |
378 | wl_list_for_each(seat, &input->seats, link) { | 384 | wl_list_for_each(seat, &input->seats, link) { |
379 | sway_seat_configure_xcursor(seat); | 385 | seat_configure_xcursor(seat); |
380 | } | 386 | } |
381 | } | 387 | } |
382 | 388 | ||
383 | struct sway_seat *sway_input_manager_get_default_seat( | 389 | struct sway_seat *input_manager_get_default_seat( |
384 | struct sway_input_manager *input) { | 390 | struct sway_input_manager *input) { |
385 | struct sway_seat *seat = NULL; | 391 | struct sway_seat *seat = NULL; |
386 | wl_list_for_each(seat, &input->seats, link) { | 392 | wl_list_for_each(seat, &input->seats, link) { |
@@ -390,3 +396,15 @@ struct sway_seat *sway_input_manager_get_default_seat( | |||
390 | } | 396 | } |
391 | return seat; | 397 | return seat; |
392 | } | 398 | } |
399 | |||
400 | struct input_config *input_device_get_config(struct sway_input_device *device) { | ||
401 | struct input_config *input_config = NULL; | ||
402 | for (int i = 0; i < config->input_configs->length; ++i) { | ||
403 | input_config = config->input_configs->items[i]; | ||
404 | if (strcmp(input_config->identifier, device->identifier) == 0) { | ||
405 | return input_config; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | return NULL; | ||
410 | } | ||
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 99685052..dbb0c359 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -97,8 +97,8 @@ static void keyboard_execute_command(struct sway_keyboard *keyboard, | |||
97 | config->handler_context.seat = keyboard->seat_device->sway_seat; | 97 | config->handler_context.seat = keyboard->seat_device->sway_seat; |
98 | struct cmd_results *results = execute_command(binding->command, NULL); | 98 | struct cmd_results *results = execute_command(binding->command, NULL); |
99 | if (results->status != CMD_SUCCESS) { | 99 | if (results->status != CMD_SUCCESS) { |
100 | wlr_log(L_DEBUG, "could not run command for binding: %s", | 100 | wlr_log(L_DEBUG, "could not run command for binding: %s (%s)", |
101 | binding->command); | 101 | binding->command, results->error); |
102 | } | 102 | } |
103 | free_cmd_results(results); | 103 | free_cmd_results(results); |
104 | } | 104 | } |
@@ -428,7 +428,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
428 | struct xkb_rule_names rules; | 428 | struct xkb_rule_names rules; |
429 | memset(&rules, 0, sizeof(rules)); | 429 | memset(&rules, 0, sizeof(rules)); |
430 | struct input_config *input_config = | 430 | struct input_config *input_config = |
431 | keyboard->seat_device->input_device->config; | 431 | input_device_get_config(keyboard->seat_device->input_device); |
432 | struct wlr_input_device *wlr_device = | 432 | struct wlr_input_device *wlr_device = |
433 | keyboard->seat_device->input_device->wlr_device; | 433 | keyboard->seat_device->input_device->wlr_device; |
434 | 434 | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index 9aa34aca..27636c1e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -25,7 +25,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { | |||
25 | free(seat_device); | 25 | free(seat_device); |
26 | } | 26 | } |
27 | 27 | ||
28 | void sway_seat_destroy(struct sway_seat *seat) { | 28 | void seat_destroy(struct sway_seat *seat) { |
29 | struct sway_seat_device *seat_device, *next; | 29 | struct sway_seat_device *seat_device, *next; |
30 | wl_list_for_each_safe(seat_device, next, &seat->devices, link) { | 30 | wl_list_for_each_safe(seat_device, next, &seat->devices, link) { |
31 | seat_device_destroy(seat_device); | 31 | seat_device_destroy(seat_device); |
@@ -42,18 +42,19 @@ static void handle_seat_container_destroy(struct wl_listener *listener, | |||
42 | struct sway_seat *seat = seat_con->seat; | 42 | struct sway_seat *seat = seat_con->seat; |
43 | struct sway_container *con = seat_con->container; | 43 | struct sway_container *con = seat_con->container; |
44 | 44 | ||
45 | bool is_focus = (sway_seat_get_focus(seat) == con); | 45 | bool is_focus = (seat_get_focus(seat) == con); |
46 | 46 | ||
47 | wl_list_remove(&seat_con->link); | 47 | wl_list_remove(&seat_con->link); |
48 | 48 | ||
49 | if (is_focus) { | 49 | if (is_focus) { |
50 | // pick next focus | 50 | // pick next focus |
51 | sway_seat_set_focus(seat, NULL); | 51 | seat_set_focus(seat, NULL); |
52 | struct sway_container *next = sway_seat_get_focus_inactive(seat, con->parent); | 52 | struct sway_container *next = |
53 | seat_get_focus_inactive(seat, con->parent); | ||
53 | if (next == NULL) { | 54 | if (next == NULL) { |
54 | next = con->parent; | 55 | next = con->parent; |
55 | } | 56 | } |
56 | sway_seat_set_focus(seat, next); | 57 | seat_set_focus(seat, next); |
57 | } | 58 | } |
58 | 59 | ||
59 | wl_list_remove(&seat_con->destroy.link); | 60 | wl_list_remove(&seat_con->destroy.link); |
@@ -110,7 +111,7 @@ static void collect_focus_iter(struct sway_container *con, void *data) { | |||
110 | wl_list_insert(&seat->focus_stack, &seat_con->link); | 111 | wl_list_insert(&seat->focus_stack, &seat_con->link); |
111 | } | 112 | } |
112 | 113 | ||
113 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | 114 | struct sway_seat *seat_create(struct sway_input_manager *input, |
114 | const char *seat_name) { | 115 | const char *seat_name) { |
115 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); | 116 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); |
116 | if (!seat) { | 117 | if (!seat) { |
@@ -133,7 +134,8 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, | |||
133 | // init the focus stack | 134 | // init the focus stack |
134 | wl_list_init(&seat->focus_stack); | 135 | wl_list_init(&seat->focus_stack); |
135 | 136 | ||
136 | container_for_each_descendant_dfs(&root_container, collect_focus_iter, seat); | 137 | container_for_each_descendant_dfs(&root_container, |
138 | collect_focus_iter, seat); | ||
137 | 139 | ||
138 | wl_signal_add(&root_container.sway_root->events.new_container, | 140 | wl_signal_add(&root_container.sway_root->events.new_container, |
139 | &seat->new_container); | 141 | &seat->new_container); |
@@ -147,7 +149,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, | |||
147 | WL_SEAT_CAPABILITY_POINTER | | 149 | WL_SEAT_CAPABILITY_POINTER | |
148 | WL_SEAT_CAPABILITY_TOUCH); | 150 | WL_SEAT_CAPABILITY_TOUCH); |
149 | 151 | ||
150 | sway_seat_configure_xcursor(seat); | 152 | seat_configure_xcursor(seat); |
151 | 153 | ||
152 | wl_list_insert(&input->seats, &seat->link); | 154 | wl_list_insert(&input->seats, &seat->link); |
153 | 155 | ||
@@ -165,11 +167,12 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
165 | if (!seat_device->keyboard) { | 167 | if (!seat_device->keyboard) { |
166 | sway_keyboard_create(seat, seat_device); | 168 | sway_keyboard_create(seat, seat_device); |
167 | } | 169 | } |
168 | struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; | 170 | struct wlr_keyboard *wlr_keyboard = |
171 | seat_device->input_device->wlr_device->keyboard; | ||
169 | sway_keyboard_configure(seat_device->keyboard); | 172 | sway_keyboard_configure(seat_device->keyboard); |
170 | wlr_seat_set_keyboard(seat->wlr_seat, | 173 | wlr_seat_set_keyboard(seat->wlr_seat, |
171 | seat_device->input_device->wlr_device); | 174 | seat_device->input_device->wlr_device); |
172 | struct sway_container *focus = sway_seat_get_focus(seat); | 175 | struct sway_container *focus = seat_get_focus(seat); |
173 | if (focus && focus->type == C_VIEW) { | 176 | if (focus && focus->type == C_VIEW) { |
174 | // force notify reenter to pick up the new configuration | 177 | // force notify reenter to pick up the new configuration |
175 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); | 178 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); |
@@ -179,7 +182,7 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
179 | } | 182 | } |
180 | } | 183 | } |
181 | 184 | ||
182 | static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, | 185 | static struct sway_seat_device *seat_get_device(struct sway_seat *seat, |
183 | struct sway_input_device *input_device) { | 186 | struct sway_input_device *input_device) { |
184 | struct sway_seat_device *seat_device = NULL; | 187 | struct sway_seat_device *seat_device = NULL; |
185 | wl_list_for_each(seat_device, &seat->devices, link) { | 188 | wl_list_for_each(seat_device, &seat->devices, link) { |
@@ -191,19 +194,14 @@ static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, | |||
191 | return NULL; | 194 | return NULL; |
192 | } | 195 | } |
193 | 196 | ||
194 | void sway_seat_configure_device(struct sway_seat *seat, | 197 | void seat_configure_device(struct sway_seat *seat, |
195 | struct sway_input_device *input_device) { | 198 | struct sway_input_device *input_device) { |
196 | struct sway_seat_device *seat_device = | 199 | struct sway_seat_device *seat_device = |
197 | sway_seat_get_device(seat, input_device); | 200 | seat_get_device(seat, input_device); |
198 | if (!seat_device) { | 201 | if (!seat_device) { |
199 | return; | 202 | return; |
200 | } | 203 | } |
201 | 204 | ||
202 | if (seat->config) { | ||
203 | seat_device->attachment_config = | ||
204 | seat_config_get_attachment(seat->config, input_device->identifier); | ||
205 | } | ||
206 | |||
207 | switch (input_device->wlr_device->type) { | 205 | switch (input_device->wlr_device->type) { |
208 | case WLR_INPUT_DEVICE_POINTER: | 206 | case WLR_INPUT_DEVICE_POINTER: |
209 | seat_configure_pointer(seat, seat_device); | 207 | seat_configure_pointer(seat, seat_device); |
@@ -219,10 +217,10 @@ void sway_seat_configure_device(struct sway_seat *seat, | |||
219 | } | 217 | } |
220 | } | 218 | } |
221 | 219 | ||
222 | void sway_seat_add_device(struct sway_seat *seat, | 220 | void seat_add_device(struct sway_seat *seat, |
223 | struct sway_input_device *input_device) { | 221 | struct sway_input_device *input_device) { |
224 | if (sway_seat_get_device(seat, input_device)) { | 222 | if (seat_get_device(seat, input_device)) { |
225 | sway_seat_configure_device(seat, input_device); | 223 | seat_configure_device(seat, input_device); |
226 | return; | 224 | return; |
227 | } | 225 | } |
228 | 226 | ||
@@ -240,13 +238,13 @@ void sway_seat_add_device(struct sway_seat *seat, | |||
240 | seat_device->input_device = input_device; | 238 | seat_device->input_device = input_device; |
241 | wl_list_insert(&seat->devices, &seat_device->link); | 239 | wl_list_insert(&seat->devices, &seat_device->link); |
242 | 240 | ||
243 | sway_seat_configure_device(seat, input_device); | 241 | seat_configure_device(seat, input_device); |
244 | } | 242 | } |
245 | 243 | ||
246 | void sway_seat_remove_device(struct sway_seat *seat, | 244 | void seat_remove_device(struct sway_seat *seat, |
247 | struct sway_input_device *input_device) { | 245 | struct sway_input_device *input_device) { |
248 | struct sway_seat_device *seat_device = | 246 | struct sway_seat_device *seat_device = |
249 | sway_seat_get_device(seat, input_device); | 247 | seat_get_device(seat, input_device); |
250 | 248 | ||
251 | if (!seat_device) { | 249 | if (!seat_device) { |
252 | return; | 250 | return; |
@@ -258,7 +256,7 @@ void sway_seat_remove_device(struct sway_seat *seat, | |||
258 | seat_device_destroy(seat_device); | 256 | seat_device_destroy(seat_device); |
259 | } | 257 | } |
260 | 258 | ||
261 | void sway_seat_configure_xcursor(struct sway_seat *seat) { | 259 | void seat_configure_xcursor(struct sway_seat *seat) { |
262 | // TODO configure theme and size | 260 | // TODO configure theme and size |
263 | const char *cursor_theme = NULL; | 261 | const char *cursor_theme = NULL; |
264 | 262 | ||
@@ -273,7 +271,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { | |||
273 | } | 271 | } |
274 | 272 | ||
275 | for (int i = 0; i < root_container.children->length; ++i) { | 273 | for (int i = 0; i < root_container.children->length; ++i) { |
276 | struct sway_container *output_container = root_container.children->items[i]; | 274 | struct sway_container *output_container = |
275 | root_container.children->items[i]; | ||
277 | struct wlr_output *output = | 276 | struct wlr_output *output = |
278 | output_container->sway_output->wlr_output; | 277 | output_container->sway_output->wlr_output; |
279 | bool result = | 278 | bool result = |
@@ -292,9 +291,9 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { | |||
292 | seat->cursor->cursor->y); | 291 | seat->cursor->cursor->y); |
293 | } | 292 | } |
294 | 293 | ||
295 | void sway_seat_set_focus_warp(struct sway_seat *seat, | 294 | void seat_set_focus_warp(struct sway_seat *seat, |
296 | struct sway_container *container, bool warp) { | 295 | struct sway_container *container, bool warp) { |
297 | struct sway_container *last_focus = sway_seat_get_focus(seat); | 296 | struct sway_container *last_focus = seat_get_focus(seat); |
298 | 297 | ||
299 | if (container && last_focus == container) { | 298 | if (container && last_focus == container) { |
300 | return; | 299 | return; |
@@ -364,7 +363,7 @@ void sway_seat_set_focus_warp(struct sway_seat *seat, | |||
364 | } | 363 | } |
365 | 364 | ||
366 | if (last_focus && last_focus->type == C_VIEW && | 365 | if (last_focus && last_focus->type == C_VIEW && |
367 | !sway_input_manager_has_focus(seat->input, last_focus)) { | 366 | !input_manager_has_focus(seat->input, last_focus)) { |
368 | struct sway_view *view = last_focus->sway_view; | 367 | struct sway_view *view = last_focus->sway_view; |
369 | view_set_activated(view, false); | 368 | view_set_activated(view, false); |
370 | } | 369 | } |
@@ -372,12 +371,13 @@ void sway_seat_set_focus_warp(struct sway_seat *seat, | |||
372 | seat->has_focus = (container != NULL); | 371 | seat->has_focus = (container != NULL); |
373 | } | 372 | } |
374 | 373 | ||
375 | void sway_seat_set_focus(struct sway_seat *seat, | 374 | void seat_set_focus(struct sway_seat *seat, |
376 | struct sway_container *container) { | 375 | struct sway_container *container) { |
377 | sway_seat_set_focus_warp(seat, container, true); | 376 | seat_set_focus_warp(seat, container, true); |
378 | } | 377 | } |
379 | 378 | ||
380 | struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, struct sway_container *container) { | 379 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, |
380 | struct sway_container *container) { | ||
381 | struct sway_seat_container *current = NULL; | 381 | struct sway_seat_container *current = NULL; |
382 | struct sway_container *parent = NULL; | 382 | struct sway_container *parent = NULL; |
383 | wl_list_for_each(current, &seat->focus_stack, link) { | 383 | wl_list_for_each(current, &seat->focus_stack, link) { |
@@ -398,16 +398,17 @@ struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, stru | |||
398 | return NULL; | 398 | return NULL; |
399 | } | 399 | } |
400 | 400 | ||
401 | struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { | 401 | struct sway_container *seat_get_focus(struct sway_seat *seat) { |
402 | if (!seat->has_focus) { | 402 | if (!seat->has_focus) { |
403 | return NULL; | 403 | return NULL; |
404 | } | 404 | } |
405 | return sway_seat_get_focus_inactive(seat, &root_container); | 405 | return seat_get_focus_inactive(seat, &root_container); |
406 | } | 406 | } |
407 | 407 | ||
408 | struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, | 408 | struct sway_container *seat_get_focus_by_type(struct sway_seat *seat, |
409 | enum sway_container_type type) { | 409 | enum sway_container_type type) { |
410 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); | 410 | struct sway_container *focus = |
411 | seat_get_focus_inactive(seat, &root_container); | ||
411 | if (focus->type == type) { | 412 | if (focus->type == type) { |
412 | return focus; | 413 | return focus; |
413 | } | 414 | } |
@@ -415,25 +416,27 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, | |||
415 | return container_parent(focus, type); | 416 | return container_parent(focus, type); |
416 | } | 417 | } |
417 | 418 | ||
418 | void sway_seat_set_config(struct sway_seat *seat, | 419 | void seat_apply_config(struct sway_seat *seat, |
419 | struct seat_config *seat_config) { | 420 | struct seat_config *seat_config) { |
420 | // clear configs | ||
421 | free_seat_config(seat->config); | ||
422 | seat->config = NULL; | ||
423 | |||
424 | struct sway_seat_device *seat_device = NULL; | 421 | struct sway_seat_device *seat_device = NULL; |
425 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
426 | seat_device->attachment_config = NULL; | ||
427 | } | ||
428 | 422 | ||
429 | if (!seat_config) { | 423 | if (!seat_config) { |
430 | return; | 424 | return; |
431 | } | 425 | } |
432 | 426 | ||
433 | // add configs | ||
434 | seat->config = copy_seat_config(seat_config); | ||
435 | |||
436 | wl_list_for_each(seat_device, &seat->devices, link) { | 427 | wl_list_for_each(seat_device, &seat->devices, link) { |
437 | sway_seat_configure_device(seat, seat_device->input_device); | 428 | seat_configure_device(seat, seat_device->input_device); |
438 | } | 429 | } |
439 | } | 430 | } |
431 | |||
432 | struct seat_config *seat_get_config(struct sway_seat *seat) { | ||
433 | struct seat_config *seat_config = NULL; | ||
434 | for (int i = 0; i < config->seat_configs->length; ++i ) { | ||
435 | seat_config = config->seat_configs->items[i]; | ||
436 | if (strcmp(seat->wlr_seat->name, seat_config->name) == 0) { | ||
437 | return seat_config; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | return NULL; | ||
442 | } | ||
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 7c5f7304..3427c8ec 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -88,11 +88,11 @@ static void ipc_json_describe_output(struct sway_container *container, json_obje | |||
88 | json_object_new_string( | 88 | json_object_new_string( |
89 | ipc_json_get_output_transform(wlr_output->transform))); | 89 | ipc_json_get_output_transform(wlr_output->transform))); |
90 | 90 | ||
91 | struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); | 91 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); |
92 | const char *ws = NULL; | 92 | const char *ws = NULL; |
93 | if (seat) { | 93 | if (seat) { |
94 | struct sway_container *focus = | 94 | struct sway_container *focus = |
95 | sway_seat_get_focus_inactive(seat, container); | 95 | seat_get_focus_inactive(seat, container); |
96 | if (focus && focus->type != C_WORKSPACE) { | 96 | if (focus && focus->type != C_WORKSPACE) { |
97 | focus = container_parent(focus, C_WORKSPACE); | 97 | focus = container_parent(focus, C_WORKSPACE); |
98 | } | 98 | } |
@@ -139,8 +139,8 @@ json_object *ipc_json_describe_container(struct sway_container *c) { | |||
139 | return NULL; | 139 | return NULL; |
140 | } | 140 | } |
141 | 141 | ||
142 | struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); | 142 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); |
143 | bool focused = sway_seat_get_focus(seat) == c; | 143 | bool focused = seat_get_focus(seat) == c; |
144 | 144 | ||
145 | json_object *object = json_object_new_object(); | 145 | json_object *object = json_object_new_object(); |
146 | 146 | ||
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 869f1ed0..df5fb699 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -388,8 +388,8 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, | |||
388 | // override the default focused indicator because | 388 | // override the default focused indicator because |
389 | // it's set differently for the get_workspaces reply | 389 | // it's set differently for the get_workspaces reply |
390 | struct sway_seat *seat = | 390 | struct sway_seat *seat = |
391 | sway_input_manager_get_default_seat(input_manager); | 391 | input_manager_get_default_seat(input_manager); |
392 | struct sway_container *focused_ws = sway_seat_get_focus(seat); | 392 | struct sway_container *focused_ws = seat_get_focus(seat); |
393 | if (focused_ws != NULL && focused_ws->type != C_WORKSPACE) { | 393 | if (focused_ws != NULL && focused_ws->type != C_WORKSPACE) { |
394 | focused_ws = container_parent(focused_ws, C_WORKSPACE); | 394 | focused_ws = container_parent(focused_ws, C_WORKSPACE); |
395 | } | 395 | } |
@@ -399,7 +399,7 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace, | |||
399 | json_object_new_boolean(focused)); | 399 | json_object_new_boolean(focused)); |
400 | json_object_array_add((json_object *)data, workspace_json); | 400 | json_object_array_add((json_object *)data, workspace_json); |
401 | 401 | ||
402 | focused_ws = sway_seat_get_focus_inactive(seat, workspace->parent); | 402 | focused_ws = seat_get_focus_inactive(seat, workspace->parent); |
403 | if (focused_ws->type != C_WORKSPACE) { | 403 | if (focused_ws->type != C_WORKSPACE) { |
404 | focused_ws = container_parent(focused_ws, C_WORKSPACE); | 404 | focused_ws = container_parent(focused_ws, C_WORKSPACE); |
405 | } | 405 | } |
diff --git a/sway/meson.build b/sway/meson.build index 0cc620ea..38945b4c 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -19,6 +19,7 @@ sway_sources = files( | |||
19 | 'commands/input.c', | 19 | 'commands/input.c', |
20 | 'commands/layout.c', | 20 | 'commands/layout.c', |
21 | 'commands/mode.c', | 21 | 'commands/mode.c', |
22 | 'commands/move.c', | ||
22 | 'commands/seat.c', | 23 | 'commands/seat.c', |
23 | 'commands/seat/attach.c', | 24 | 'commands/seat/attach.c', |
24 | 'commands/seat/fallback.c', | 25 | 'commands/seat/fallback.c', |
diff --git a/sway/server.c b/sway/server.c index f5cc199c..54945312 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -109,7 +109,7 @@ bool server_init(struct sway_server *server) { | |||
109 | return false; | 109 | return false; |
110 | } | 110 | } |
111 | 111 | ||
112 | input_manager = sway_input_manager_create(server); | 112 | input_manager = input_manager_create(server); |
113 | return true; | 113 | return true; |
114 | } | 114 | } |
115 | 115 | ||
diff --git a/sway/tree/container.c b/sway/tree/container.c index 746dbf1f..ea0b7d5c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -33,6 +33,23 @@ static list_t *get_bfs_queue() { | |||
33 | return bfs_queue; | 33 | return bfs_queue; |
34 | } | 34 | } |
35 | 35 | ||
36 | const char *container_type_to_str(enum sway_container_type type) { | ||
37 | switch (type) { | ||
38 | case C_ROOT: | ||
39 | return "C_ROOT"; | ||
40 | case C_OUTPUT: | ||
41 | return "C_OUTPUT"; | ||
42 | case C_WORKSPACE: | ||
43 | return "C_WORKSPACE"; | ||
44 | case C_CONTAINER: | ||
45 | return "C_CONTAINER"; | ||
46 | case C_VIEW: | ||
47 | return "C_VIEW"; | ||
48 | default: | ||
49 | return "C_UNKNOWN"; | ||
50 | } | ||
51 | } | ||
52 | |||
36 | static void notify_new_container(struct sway_container *container) { | 53 | static void notify_new_container(struct sway_container *container) { |
37 | wl_signal_emit(&root_container.sway_root->events.new_container, container); | 54 | wl_signal_emit(&root_container.sway_root->events.new_container, container); |
38 | ipc_event_window(container, "new"); | 55 | ipc_event_window(container, "new"); |
@@ -54,6 +71,7 @@ static struct sway_container *container_create(enum sway_container_type type) { | |||
54 | } | 71 | } |
55 | 72 | ||
56 | wl_signal_init(&c->events.destroy); | 73 | wl_signal_init(&c->events.destroy); |
74 | wl_signal_init(&c->events.reparent); | ||
57 | 75 | ||
58 | return c; | 76 | return c; |
59 | } | 77 | } |
@@ -144,7 +162,7 @@ struct sway_container *container_output_create( | |||
144 | struct sway_seat *seat = NULL; | 162 | struct sway_seat *seat = NULL; |
145 | wl_list_for_each(seat, &input_manager->seats, link) { | 163 | wl_list_for_each(seat, &input_manager->seats, link) { |
146 | if (!seat->has_focus) { | 164 | if (!seat->has_focus) { |
147 | sway_seat_set_focus(seat, ws); | 165 | seat_set_focus(seat, ws); |
148 | } | 166 | } |
149 | } | 167 | } |
150 | 168 | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 122ea494..3333f9f1 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -106,8 +106,10 @@ struct sway_container *container_reap_empty(struct sway_container *container) { | |||
106 | if (!sway_assert(container, "reaping null container")) { | 106 | if (!sway_assert(container, "reaping null container")) { |
107 | return NULL; | 107 | return NULL; |
108 | } | 108 | } |
109 | wlr_log(L_DEBUG, "reaping %p %s", container, container->name); | 109 | wlr_log(L_DEBUG, "Reaping %p %s '%s'", container, |
110 | while (container != &root_container && container->children->length == 0) { | 110 | container_type_to_str(container->type), container->name); |
111 | while (container->type != C_ROOT && container->type != C_OUTPUT | ||
112 | && container->children->length == 0) { | ||
111 | if (container->type == C_WORKSPACE) { | 113 | if (container->type == C_WORKSPACE) { |
112 | if (!workspace_is_visible(container)) { | 114 | if (!workspace_is_visible(container)) { |
113 | struct sway_container *parent = container->parent; | 115 | struct sway_container *parent = container->parent; |
@@ -138,22 +140,46 @@ struct sway_container *container_remove_child(struct sway_container *child) { | |||
138 | return container_reap_empty(parent); | 140 | return container_reap_empty(parent); |
139 | } | 141 | } |
140 | 142 | ||
141 | void container_move_to(struct sway_container* container, | 143 | void container_move_to(struct sway_container *container, |
142 | struct sway_container* destination) { | 144 | struct sway_container *destination) { |
143 | if (container == destination | 145 | if (container == destination |
144 | || container_has_anscestor(container, destination)) { | 146 | || container_has_anscestor(container, destination)) { |
145 | return; | 147 | return; |
146 | } | 148 | } |
147 | struct sway_container *old_parent = container_remove_child(container); | 149 | struct sway_container *old_parent = container_remove_child(container); |
148 | container->width = container->height = 0; | 150 | container->width = container->height = 0; |
149 | struct sway_container *new_parent = | 151 | struct sway_container *new_parent; |
150 | container_add_sibling(destination, container); | 152 | if (destination->type == C_VIEW) { |
153 | new_parent = container_add_sibling(destination, container); | ||
154 | } else { | ||
155 | new_parent = destination; | ||
156 | container_add_child(destination, container); | ||
157 | } | ||
158 | wl_signal_emit(&container->events.reparent, old_parent); | ||
159 | if (container->type == C_WORKSPACE) { | ||
160 | struct sway_seat *seat = input_manager_get_default_seat( | ||
161 | input_manager); | ||
162 | if (old_parent->children->length == 0) { | ||
163 | char *ws_name = workspace_next_name(old_parent->name); | ||
164 | struct sway_container *ws = | ||
165 | container_workspace_create(old_parent, ws_name); | ||
166 | free(ws_name); | ||
167 | seat_set_focus(seat, ws); | ||
168 | } | ||
169 | container_sort_workspaces(new_parent); | ||
170 | seat_set_focus(seat, new_parent); | ||
171 | } | ||
151 | if (old_parent) { | 172 | if (old_parent) { |
152 | arrange_windows(old_parent, -1, -1); | 173 | arrange_windows(old_parent, -1, -1); |
153 | } | 174 | } |
154 | arrange_windows(new_parent, -1, -1); | 175 | arrange_windows(new_parent, -1, -1); |
155 | } | 176 | } |
156 | 177 | ||
178 | void container_move(struct sway_container *container, | ||
179 | enum movement_direction dir, int move_amt) { | ||
180 | // TODO | ||
181 | } | ||
182 | |||
157 | enum sway_container_layout container_get_default_layout( | 183 | enum sway_container_layout container_get_default_layout( |
158 | struct sway_container *output) { | 184 | struct sway_container *output) { |
159 | if (config->default_layout != L_NONE) { | 185 | if (config->default_layout != L_NONE) { |
@@ -248,8 +274,8 @@ void arrange_windows(struct sway_container *container, | |||
248 | struct wlr_box *area = &output->sway_output->usable_area; | 274 | struct wlr_box *area = &output->sway_output->usable_area; |
249 | wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", | 275 | wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", |
250 | area->width, area->height, area->x, area->y); | 276 | area->width, area->height, area->x, area->y); |
251 | container->width = area->width; | 277 | container->width = width = area->width; |
252 | container->height = area->height; | 278 | container->height = height = area->height; |
253 | container->x = x = area->x; | 279 | container->x = x = area->x; |
254 | container->y = y = area->y; | 280 | container->y = y = area->y; |
255 | wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", | 281 | wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", |
@@ -406,7 +432,7 @@ static struct sway_container *get_swayc_in_output_direction( | |||
406 | return NULL; | 432 | return NULL; |
407 | } | 433 | } |
408 | 434 | ||
409 | struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); | 435 | struct sway_container *ws = seat_get_focus_inactive(seat, output); |
410 | if (ws->type != C_WORKSPACE) { | 436 | if (ws->type != C_WORKSPACE) { |
411 | ws = container_parent(ws, C_WORKSPACE); | 437 | ws = container_parent(ws, C_WORKSPACE); |
412 | } | 438 | } |
@@ -427,7 +453,7 @@ static struct sway_container *get_swayc_in_output_direction( | |||
427 | case MOVE_UP: | 453 | case MOVE_UP: |
428 | case MOVE_DOWN: { | 454 | case MOVE_DOWN: { |
429 | struct sway_container *focused = | 455 | struct sway_container *focused = |
430 | sway_seat_get_focus_inactive(seat, ws); | 456 | seat_get_focus_inactive(seat, ws); |
431 | if (focused && focused->parent) { | 457 | if (focused && focused->parent) { |
432 | struct sway_container *parent = focused->parent; | 458 | struct sway_container *parent = focused->parent; |
433 | if (parent->layout == L_VERT) { | 459 | if (parent->layout == L_VERT) { |
@@ -511,7 +537,7 @@ static struct sway_container *get_swayc_in_direction_under( | |||
511 | struct sway_container *container, enum movement_direction dir, | 537 | struct sway_container *container, enum movement_direction dir, |
512 | struct sway_seat *seat, struct sway_container *limit) { | 538 | struct sway_seat *seat, struct sway_container *limit) { |
513 | if (dir == MOVE_CHILD) { | 539 | if (dir == MOVE_CHILD) { |
514 | return sway_seat_get_focus_inactive(seat, container); | 540 | return seat_get_focus_inactive(seat, container); |
515 | } | 541 | } |
516 | 542 | ||
517 | struct sway_container *parent = container->parent; | 543 | struct sway_container *parent = container->parent; |
@@ -523,26 +549,6 @@ static struct sway_container *get_swayc_in_direction_under( | |||
523 | } | 549 | } |
524 | } | 550 | } |
525 | 551 | ||
526 | if (dir == MOVE_PREV || dir == MOVE_NEXT) { | ||
527 | int focused_idx = index_child(container); | ||
528 | if (focused_idx == -1) { | ||
529 | return NULL; | ||
530 | } else { | ||
531 | int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) % | ||
532 | parent->children->length; | ||
533 | if (desired < 0) { | ||
534 | desired += parent->children->length; | ||
535 | } | ||
536 | return parent->children->items[desired]; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | // If moving to an adjacent output we need a starting position (since this | ||
541 | // output might border to multiple outputs). | ||
542 | //struct wlc_point abs_pos; | ||
543 | //get_layout_center_position(container, &abs_pos); | ||
544 | |||
545 | |||
546 | // TODO WLR fullscreen | 552 | // TODO WLR fullscreen |
547 | /* | 553 | /* |
548 | if (container->type == C_VIEW && swayc_is_fullscreen(container)) { | 554 | if (container->type == C_VIEW && swayc_is_fullscreen(container)) { |
@@ -591,7 +597,7 @@ static struct sway_container *get_swayc_in_direction_under( | |||
591 | } | 597 | } |
592 | if (next->children && next->children->length) { | 598 | if (next->children && next->children->length) { |
593 | // TODO consider floating children as well | 599 | // TODO consider floating children as well |
594 | return sway_seat_get_focus_inactive(seat, next); | 600 | return seat_get_focus_inactive(seat, next); |
595 | } else { | 601 | } else { |
596 | return next; | 602 | return next; |
597 | } | 603 | } |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 80a36ac7..0509db23 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <strings.h> | ||
1 | #include "sway/tree/container.h" | 2 | #include "sway/tree/container.h" |
2 | #include "sway/tree/layout.h" | 3 | #include "sway/tree/layout.h" |
3 | #include "sway/output.h" | 4 | #include "sway/output.h" |
@@ -38,3 +39,13 @@ struct sway_container *container_output_destroy(struct sway_container *output) { | |||
38 | container_destroy(output); | 39 | container_destroy(output); |
39 | return &root_container; | 40 | return &root_container; |
40 | } | 41 | } |
42 | |||
43 | struct sway_container *output_by_name(const char *name) { | ||
44 | for (int i = 0; i < root_container.children->length; ++i) { | ||
45 | struct sway_container *output = root_container.children->items[i]; | ||
46 | if (strcasecmp(output->name, name) == 0){ | ||
47 | return output; | ||
48 | } | ||
49 | } | ||
50 | return NULL; | ||
51 | } | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index 8f044621..09c804e4 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -139,7 +139,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
139 | } | 139 | } |
140 | 140 | ||
141 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 141 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
142 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, | 142 | struct sway_container *focus = seat_get_focus_inactive(seat, |
143 | &root_container); | 143 | &root_container); |
144 | struct sway_container *cont = container_view_create(focus, view); | 144 | struct sway_container *cont = container_view_create(focus, view); |
145 | 145 | ||
@@ -147,7 +147,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
147 | view->swayc = cont; | 147 | view->swayc = cont; |
148 | 148 | ||
149 | arrange_windows(cont->parent, -1, -1); | 149 | arrange_windows(cont->parent, -1, -1); |
150 | sway_input_manager_set_focus(input_manager, cont); | 150 | input_manager_set_focus(input_manager, cont); |
151 | 151 | ||
152 | view_damage_whole(view); | 152 | view_damage_whole(view); |
153 | view_update_outputs(view, NULL); | 153 | view_update_outputs(view, NULL); |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c629f1f1..74330884 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -158,7 +158,7 @@ static bool _workspace_by_name(struct sway_container *view, void *data) { | |||
158 | struct sway_container *workspace_by_name(const char *name) { | 158 | struct sway_container *workspace_by_name(const char *name) { |
159 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 159 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
160 | struct sway_container *current_workspace = NULL, *current_output = NULL; | 160 | struct sway_container *current_workspace = NULL, *current_output = NULL; |
161 | struct sway_container *focus = sway_seat_get_focus(seat); | 161 | struct sway_container *focus = seat_get_focus(seat); |
162 | if (focus) { | 162 | if (focus) { |
163 | current_workspace = container_parent(focus, C_WORKSPACE); | 163 | current_workspace = container_parent(focus, C_WORKSPACE); |
164 | current_output = container_parent(focus, C_OUTPUT); | 164 | current_output = container_parent(focus, C_OUTPUT); |
@@ -200,7 +200,7 @@ struct sway_container *workspace_create(const char *name) { | |||
200 | // Otherwise create a new one | 200 | // Otherwise create a new one |
201 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 201 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
202 | struct sway_container *focus = | 202 | struct sway_container *focus = |
203 | sway_seat_get_focus_inactive(seat, &root_container); | 203 | seat_get_focus_inactive(seat, &root_container); |
204 | parent = focus; | 204 | parent = focus; |
205 | parent = container_parent(parent, C_OUTPUT); | 205 | parent = container_parent(parent, C_OUTPUT); |
206 | struct sway_container *new_ws = container_workspace_create(parent, name); | 206 | struct sway_container *new_ws = container_workspace_create(parent, name); |
@@ -260,7 +260,7 @@ struct sway_container *workspace_output_prev_next_impl( | |||
260 | } | 260 | } |
261 | 261 | ||
262 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 262 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
263 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); | 263 | struct sway_container *focus = seat_get_focus_inactive(seat, output); |
264 | struct sway_container *workspace = (focus->type == C_WORKSPACE ? | 264 | struct sway_container *workspace = (focus->type == C_WORKSPACE ? |
265 | focus : | 265 | focus : |
266 | container_parent(focus, C_WORKSPACE)); | 266 | container_parent(focus, C_WORKSPACE)); |
@@ -345,13 +345,13 @@ bool workspace_switch(struct sway_container *workspace) { | |||
345 | } | 345 | } |
346 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 346 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
347 | struct sway_container *focus = | 347 | struct sway_container *focus = |
348 | sway_seat_get_focus_inactive(seat, &root_container); | 348 | seat_get_focus_inactive(seat, &root_container); |
349 | if (!seat || !focus) { | 349 | if (!seat || !focus) { |
350 | return false; | 350 | return false; |
351 | } | 351 | } |
352 | struct sway_container *active_ws = focus; | 352 | struct sway_container *active_ws = focus; |
353 | if (active_ws->type != C_WORKSPACE) { | 353 | if (active_ws->type != C_WORKSPACE) { |
354 | container_parent(focus, C_WORKSPACE); | 354 | active_ws = container_parent(focus, C_WORKSPACE); |
355 | } | 355 | } |
356 | 356 | ||
357 | if (config->auto_back_and_forth | 357 | if (config->auto_back_and_forth |
@@ -376,11 +376,11 @@ bool workspace_switch(struct sway_container *workspace) { | |||
376 | 376 | ||
377 | wlr_log(L_DEBUG, "Switching to workspace %p:%s", | 377 | wlr_log(L_DEBUG, "Switching to workspace %p:%s", |
378 | workspace, workspace->name); | 378 | workspace, workspace->name); |
379 | struct sway_container *next = sway_seat_get_focus_inactive(seat, workspace); | 379 | struct sway_container *next = seat_get_focus_inactive(seat, workspace); |
380 | if (next == NULL) { | 380 | if (next == NULL) { |
381 | next = workspace; | 381 | next = workspace; |
382 | } | 382 | } |
383 | sway_seat_set_focus(seat, next); | 383 | seat_set_focus(seat, next); |
384 | struct sway_container *output = container_parent(workspace, C_OUTPUT); | 384 | struct sway_container *output = container_parent(workspace, C_OUTPUT); |
385 | arrange_windows(output, -1, -1); | 385 | arrange_windows(output, -1, -1); |
386 | return true; | 386 | return true; |
@@ -389,7 +389,7 @@ bool workspace_switch(struct sway_container *workspace) { | |||
389 | bool workspace_is_visible(struct sway_container *ws) { | 389 | bool workspace_is_visible(struct sway_container *ws) { |
390 | struct sway_container *output = container_parent(ws, C_OUTPUT); | 390 | struct sway_container *output = container_parent(ws, C_OUTPUT); |
391 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 391 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
392 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); | 392 | struct sway_container *focus = seat_get_focus_inactive(seat, output); |
393 | if (focus->type != C_WORKSPACE) { | 393 | if (focus->type != C_WORKSPACE) { |
394 | focus = container_parent(focus, C_WORKSPACE); | 394 | focus = container_parent(focus, C_WORKSPACE); |
395 | } | 395 | } |
diff --git a/swaybar/bar.c b/swaybar/bar.c index f743236c..fb417095 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -308,14 +308,14 @@ static void display_in(int fd, short mask, void *_bar) { | |||
308 | 308 | ||
309 | static void ipc_in(int fd, short mask, void *_bar) { | 309 | static void ipc_in(int fd, short mask, void *_bar) { |
310 | struct swaybar *bar = (struct swaybar *)_bar; | 310 | struct swaybar *bar = (struct swaybar *)_bar; |
311 | if (handle_ipc_event(bar)) { | 311 | if (handle_ipc_readable(bar)) { |
312 | render_all_frames(bar); | 312 | render_all_frames(bar); |
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
316 | static void status_in(int fd, short mask, void *_bar) { | 316 | static void status_in(int fd, short mask, void *_bar) { |
317 | struct swaybar *bar = (struct swaybar *)_bar; | 317 | struct swaybar *bar = (struct swaybar *)_bar; |
318 | if (handle_status_readable(bar->status)) { | 318 | if (status_handle_readable(bar->status)) { |
319 | render_all_frames(bar); | 319 | render_all_frames(bar); |
320 | } | 320 | } |
321 | } | 321 | } |
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c new file mode 100644 index 00000000..46459e24 --- /dev/null +++ b/swaybar/i3bar.c | |||
@@ -0,0 +1,208 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <json-c/json.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include <unistd.h> | ||
6 | #include <wlr/util/log.h> | ||
7 | #include "swaybar/config.h" | ||
8 | #include "swaybar/status_line.h" | ||
9 | |||
10 | static void i3bar_block_free(struct i3bar_block *block) { | ||
11 | if (!block) { | ||
12 | return; | ||
13 | } | ||
14 | wl_list_remove(&block->link); | ||
15 | free(block->full_text); | ||
16 | free(block->short_text); | ||
17 | free(block->align); | ||
18 | free(block->name); | ||
19 | free(block->instance); | ||
20 | free(block->color); | ||
21 | } | ||
22 | |||
23 | static bool i3bar_parse_json(struct status_line *status, const char *text) { | ||
24 | struct i3bar_block *block, *tmp; | ||
25 | wl_list_for_each_safe(block, tmp, &status->blocks, link) { | ||
26 | i3bar_block_free(block); | ||
27 | } | ||
28 | json_object *results = json_tokener_parse(text); | ||
29 | if (!results) { | ||
30 | status_error(status, "[failed to parse i3bar json]"); | ||
31 | return false; | ||
32 | } | ||
33 | wlr_log(L_DEBUG, "Got i3bar json: '%s'", text); | ||
34 | for (size_t i = 0; i < json_object_array_length(results); ++i) { | ||
35 | json_object *full_text, *short_text, *color, *min_width, *align, *urgent; | ||
36 | json_object *name, *instance, *separator, *separator_block_width; | ||
37 | json_object *background, *border, *border_top, *border_bottom; | ||
38 | json_object *border_left, *border_right, *markup; | ||
39 | json_object *json = json_object_array_get_idx(results, i); | ||
40 | if (!json) { | ||
41 | continue; | ||
42 | } | ||
43 | json_object_object_get_ex(json, "full_text", &full_text); | ||
44 | json_object_object_get_ex(json, "short_text", &short_text); | ||
45 | json_object_object_get_ex(json, "color", &color); | ||
46 | json_object_object_get_ex(json, "min_width", &min_width); | ||
47 | json_object_object_get_ex(json, "align", &align); | ||
48 | json_object_object_get_ex(json, "urgent", &urgent); | ||
49 | json_object_object_get_ex(json, "name", &name); | ||
50 | json_object_object_get_ex(json, "instance", &instance); | ||
51 | json_object_object_get_ex(json, "markup", &markup); | ||
52 | json_object_object_get_ex(json, "separator", &separator); | ||
53 | json_object_object_get_ex(json, "separator_block_width", &separator_block_width); | ||
54 | json_object_object_get_ex(json, "background", &background); | ||
55 | json_object_object_get_ex(json, "border", &border); | ||
56 | json_object_object_get_ex(json, "border_top", &border_top); | ||
57 | json_object_object_get_ex(json, "border_bottom", &border_bottom); | ||
58 | json_object_object_get_ex(json, "border_left", &border_left); | ||
59 | json_object_object_get_ex(json, "border_right", &border_right); | ||
60 | |||
61 | struct i3bar_block *block = calloc(1, sizeof(struct i3bar_block)); | ||
62 | block->full_text = full_text ? | ||
63 | strdup(json_object_get_string(full_text)) : NULL; | ||
64 | block->short_text = short_text ? | ||
65 | strdup(json_object_get_string(short_text)) : NULL; | ||
66 | if (color) { | ||
67 | block->color = malloc(sizeof(uint32_t)); | ||
68 | *block->color = parse_color(json_object_get_string(color)); | ||
69 | } | ||
70 | if (min_width) { | ||
71 | json_type type = json_object_get_type(min_width); | ||
72 | if (type == json_type_int) { | ||
73 | block->min_width = json_object_get_int(min_width); | ||
74 | } else if (type == json_type_string) { | ||
75 | /* the width will be calculated when rendering */ | ||
76 | block->min_width = 0; | ||
77 | } | ||
78 | } | ||
79 | block->align = strdup(align ? json_object_get_string(align) : "left"); | ||
80 | block->urgent = urgent ? json_object_get_int(urgent) : false; | ||
81 | block->name = name ? strdup(json_object_get_string(name)) : NULL; | ||
82 | block->instance = instance ? | ||
83 | strdup(json_object_get_string(instance)) : NULL; | ||
84 | if (markup) { | ||
85 | block->markup = false; | ||
86 | const char *markup_str = json_object_get_string(markup); | ||
87 | if (strcmp(markup_str, "pango") == 0) { | ||
88 | block->markup = true; | ||
89 | } | ||
90 | } | ||
91 | block->separator = separator ? json_object_get_int(separator) : true; | ||
92 | block->separator_block_width = separator_block_width ? | ||
93 | json_object_get_int(separator_block_width) : 9; | ||
94 | // Airblader features | ||
95 | block->background = background ? | ||
96 | parse_color(json_object_get_string(background)) : 0; | ||
97 | block->border = border ? | ||
98 | parse_color(json_object_get_string(border)) : 0; | ||
99 | block->border_top = border_top ? json_object_get_int(border_top) : 1; | ||
100 | block->border_bottom = border_bottom ? | ||
101 | json_object_get_int(border_bottom) : 1; | ||
102 | block->border_left = border_left ? json_object_get_int(border_left) : 1; | ||
103 | block->border_right = border_right ? | ||
104 | json_object_get_int(border_right) : 1; | ||
105 | wl_list_insert(&status->blocks, &block->link); | ||
106 | } | ||
107 | return true; | ||
108 | } | ||
109 | |||
110 | bool i3bar_handle_readable(struct status_line *status) { | ||
111 | struct i3bar_protocol_state *state = &status->i3bar_state; | ||
112 | |||
113 | char *cur = &state->buffer[state->buffer_index]; | ||
114 | ssize_t n = read(status->read_fd, cur, | ||
115 | state->buffer_size - state->buffer_index); | ||
116 | if (n == 0) { | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | if (n == (ssize_t)(state->buffer_size - state->buffer_index)) { | ||
121 | state->buffer_size = state->buffer_size * 2; | ||
122 | char *new_buffer = realloc(state->buffer, state->buffer_size); | ||
123 | if (!new_buffer) { | ||
124 | free(state->buffer); | ||
125 | status_error(status, "[failed to allocate buffer]"); | ||
126 | return -1; | ||
127 | } | ||
128 | state->buffer = new_buffer; | ||
129 | } | ||
130 | |||
131 | bool redraw = false; | ||
132 | while (*cur) { | ||
133 | if (state->nodes[state->depth] == JSON_NODE_STRING) { | ||
134 | if (!state->escape && *cur == '"') { | ||
135 | --state->depth; | ||
136 | } | ||
137 | state->escape = !state->escape && *cur == '\\'; | ||
138 | } else { | ||
139 | switch (*cur) { | ||
140 | case '[': | ||
141 | ++state->depth; | ||
142 | if (state->depth > | ||
143 | sizeof(state->nodes) / sizeof(state->nodes[0])) { | ||
144 | status_error(status, "[i3bar json too deep]"); | ||
145 | return false; | ||
146 | } | ||
147 | state->nodes[state->depth] = JSON_NODE_ARRAY; | ||
148 | if (state->depth == 1) { | ||
149 | state->current_node = cur; | ||
150 | } | ||
151 | break; | ||
152 | case ']': | ||
153 | if (state->nodes[state->depth] != JSON_NODE_ARRAY) { | ||
154 | status_error(status, "[failed to parse i3bar json]"); | ||
155 | return false; | ||
156 | } | ||
157 | --state->depth; | ||
158 | if (state->depth == 0) { | ||
159 | // cur[1] is valid since cur[0] != '\0' | ||
160 | char p = cur[1]; | ||
161 | cur[1] = '\0'; | ||
162 | redraw = i3bar_parse_json( | ||
163 | status, state->current_node) || redraw; | ||
164 | cur[1] = p; | ||
165 | memmove(state->buffer, cur, | ||
166 | state->buffer_size - (cur - state->buffer)); | ||
167 | cur = state->buffer; | ||
168 | state->current_node = cur + 1; | ||
169 | } | ||
170 | break; | ||
171 | case '"': | ||
172 | ++state->depth; | ||
173 | if (state->depth > | ||
174 | sizeof(state->nodes) / sizeof(state->nodes[0])) { | ||
175 | status_error(status, "[i3bar json too deep]"); | ||
176 | return false; | ||
177 | } | ||
178 | state->nodes[state->depth] = JSON_NODE_STRING; | ||
179 | break; | ||
180 | } | ||
181 | } | ||
182 | ++cur; | ||
183 | } | ||
184 | state->buffer_index = cur - state->buffer; | ||
185 | return redraw; | ||
186 | } | ||
187 | |||
188 | void i3bar_block_send_click(struct status_line *status, | ||
189 | struct i3bar_block *block, int x, int y, uint32_t button) { | ||
190 | wlr_log(L_DEBUG, "block %s clicked", block->name ? block->name : "(nil)"); | ||
191 | if (!block->name || !status->i3bar_state.click_events) { | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | struct json_object *event_json = json_object_new_object(); | ||
196 | json_object_object_add(event_json, "name", | ||
197 | json_object_new_string(block->name)); | ||
198 | if (block->instance) { | ||
199 | json_object_object_add(event_json, "instance", | ||
200 | json_object_new_string(block->instance)); | ||
201 | } | ||
202 | |||
203 | json_object_object_add(event_json, "button", json_object_new_int(button)); | ||
204 | json_object_object_add(event_json, "x", json_object_new_int(x)); | ||
205 | json_object_object_add(event_json, "y", json_object_new_int(y)); | ||
206 | dprintf(status->write_fd, "%s\n", json_object_to_json_string(event_json)); | ||
207 | json_object_put(event_json); | ||
208 | } | ||
diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 64583df0..ed5d9a31 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c | |||
@@ -323,7 +323,7 @@ void ipc_initialize(struct swaybar *bar, const char *bar_id) { | |||
323 | IPC_SUBSCRIBE, subscribe, &len)); | 323 | IPC_SUBSCRIBE, subscribe, &len)); |
324 | } | 324 | } |
325 | 325 | ||
326 | bool handle_ipc_event(struct swaybar *bar) { | 326 | bool handle_ipc_readable(struct swaybar *bar) { |
327 | struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); | 327 | struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); |
328 | if (!resp) { | 328 | if (!resp) { |
329 | return false; | 329 | return false; |
diff --git a/swaybar/meson.build b/swaybar/meson.build index bf6f6d7a..d65edb11 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build | |||
@@ -3,6 +3,7 @@ executable( | |||
3 | 'bar.c', | 3 | 'bar.c', |
4 | 'config.c', | 4 | 'config.c', |
5 | 'event_loop.c', | 5 | 'event_loop.c', |
6 | 'i3bar.c', | ||
6 | 'ipc.c', | 7 | 'ipc.c', |
7 | 'main.c', | 8 | 'main.c', |
8 | 'render.c', | 9 | 'render.c', |
diff --git a/swaybar/render.c b/swaybar/render.c index c2358724..6f3b0788 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -18,10 +18,33 @@ static const int ws_horizontal_padding = 5; | |||
18 | static const double ws_vertical_padding = 1.5; | 18 | static const double ws_vertical_padding = 1.5; |
19 | static const double border_width = 1; | 19 | static const double border_width = 1; |
20 | 20 | ||
21 | static uint32_t render_status_line_error(cairo_t *cairo, | ||
22 | struct swaybar_config *config, const char *error, | ||
23 | double *x, uint32_t width, uint32_t height) { | ||
24 | if (!error) { | ||
25 | return 0; | ||
26 | } | ||
27 | cairo_set_source_u32(cairo, 0xFF0000FF); | ||
28 | static const int margin = 3; | ||
29 | int text_width, text_height; | ||
30 | get_text_size(cairo, config->font, | ||
31 | &text_width, &text_height, 1, false, "%s", error); | ||
32 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | ||
33 | if (height < ideal_height) { | ||
34 | return ideal_height; | ||
35 | } | ||
36 | *x -= text_width + margin; | ||
37 | double text_y = height / 2.0 - text_height / 2.0; | ||
38 | cairo_move_to(cairo, *x, (int)floor(text_y)); | ||
39 | pango_printf(cairo, config->font, 1, false, "%s", error); | ||
40 | *x -= margin; | ||
41 | return ideal_height; | ||
42 | } | ||
43 | |||
21 | static uint32_t render_status_line_text(cairo_t *cairo, | 44 | static uint32_t render_status_line_text(cairo_t *cairo, |
22 | struct swaybar_config *config, struct status_line *status, | 45 | struct swaybar_config *config, const char *text, |
23 | bool focused, uint32_t width, uint32_t height) { | 46 | bool focused, double *x, uint32_t width, uint32_t height) { |
24 | if (!status->text) { | 47 | if (!text) { |
25 | return 0; | 48 | return 0; |
26 | } | 49 | } |
27 | cairo_set_source_u32(cairo, focused ? | 50 | cairo_set_source_u32(cairo, focused ? |
@@ -29,38 +52,211 @@ static uint32_t render_status_line_text(cairo_t *cairo, | |||
29 | static const int margin = 3; | 52 | static const int margin = 3; |
30 | int text_width, text_height; | 53 | int text_width, text_height; |
31 | get_text_size(cairo, config->font, &text_width, &text_height, | 54 | get_text_size(cairo, config->font, &text_width, &text_height, |
32 | 1, config->pango_markup, "%s", status->text); | 55 | 1, config->pango_markup, "%s", text); |
33 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 56 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; |
34 | if (height < ideal_height) { | 57 | if (height < ideal_height) { |
35 | return ideal_height; | 58 | return ideal_height; |
36 | } | 59 | } |
60 | *x -= text_width + margin; | ||
37 | double text_y = height / 2.0 - text_height / 2.0; | 61 | double text_y = height / 2.0 - text_height / 2.0; |
38 | cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); | 62 | cairo_move_to(cairo, *x, (int)floor(text_y)); |
39 | pango_printf(cairo, config->font, 1, config->pango_markup, | 63 | pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); |
40 | "%s", status->text); | 64 | *x -= margin; |
65 | return ideal_height; | ||
66 | } | ||
67 | |||
68 | static void render_sharp_line(cairo_t *cairo, uint32_t color, | ||
69 | double x, double y, double width, double height) { | ||
70 | cairo_set_source_u32(cairo, color); | ||
71 | if (width > 1 && height > 1) { | ||
72 | cairo_rectangle(cairo, x, y, width, height); | ||
73 | cairo_fill(cairo); | ||
74 | } else { | ||
75 | if (width == 1) { | ||
76 | x += 0.5; | ||
77 | height += y; | ||
78 | width = x; | ||
79 | } | ||
80 | if (height == 1) { | ||
81 | y += 0.5; | ||
82 | width += x; | ||
83 | height = y; | ||
84 | } | ||
85 | cairo_move_to(cairo, x, y); | ||
86 | cairo_set_line_width(cairo, 1.0); | ||
87 | cairo_line_to(cairo, width, height); | ||
88 | cairo_stroke(cairo); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static void block_hotspot_callback(struct swaybar_output *output, | ||
93 | int x, int y, uint32_t button, void *data) { | ||
94 | struct i3bar_block *block = data; | ||
95 | struct status_line *status = output->bar->status; | ||
96 | i3bar_block_send_click(status, block, x, y, button); | ||
97 | } | ||
98 | |||
99 | static uint32_t render_status_block(cairo_t *cairo, | ||
100 | struct swaybar_config *config, struct swaybar_output *output, | ||
101 | struct i3bar_block *block, double *x, | ||
102 | uint32_t height, bool focused, bool edge) { | ||
103 | static const int margin = 3; | ||
104 | if (!block->full_text || !*block->full_text) { | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | int text_width, text_height; | ||
109 | get_text_size(cairo, config->font, &text_width, &text_height, | ||
110 | 1, block->markup, "%s", block->full_text); | ||
111 | int width = text_width; | ||
112 | if (width < block->min_width) { | ||
113 | width = block->min_width; | ||
114 | } | ||
115 | double block_width = width; | ||
116 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | ||
117 | if (height < ideal_height) { | ||
118 | return ideal_height; | ||
119 | } | ||
120 | |||
121 | *x -= width; | ||
122 | if (block->border && block->border_left > 0) { | ||
123 | *x -= (block->border_left + margin); | ||
124 | block_width += block->border_left + margin; | ||
125 | } | ||
126 | if (block->border && block->border_right > 0) { | ||
127 | *x -= (block->border_right + margin); | ||
128 | block_width += block->border_right + margin; | ||
129 | } | ||
130 | |||
131 | int sep_width; | ||
132 | if (!edge) { | ||
133 | if (config->sep_symbol) { | ||
134 | int _height; | ||
135 | get_text_size(cairo, config->font, &sep_width, &_height, | ||
136 | 1, false, "%s", config->sep_symbol); | ||
137 | uint32_t _ideal_height = _height + ws_vertical_padding * 2; | ||
138 | if (height < _ideal_height) { | ||
139 | return _height; | ||
140 | } | ||
141 | if (sep_width > block->separator_block_width) { | ||
142 | block->separator_block_width = sep_width + margin * 2; | ||
143 | } | ||
144 | } | ||
145 | *x -= block->separator_block_width; | ||
146 | } else { | ||
147 | *x -= margin; | ||
148 | } | ||
149 | |||
150 | struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); | ||
151 | hotspot->x = *x; | ||
152 | hotspot->y = 0; | ||
153 | hotspot->width = width; | ||
154 | hotspot->height = height; | ||
155 | hotspot->callback = block_hotspot_callback; | ||
156 | hotspot->destroy = NULL; | ||
157 | hotspot->data = block; | ||
158 | wl_list_insert(&output->hotspots, &hotspot->link); | ||
159 | |||
160 | double pos = *x; | ||
161 | if (block->background) { | ||
162 | cairo_set_source_u32(cairo, block->background); | ||
163 | cairo_rectangle(cairo, pos - 0.5, 1, block_width, height); | ||
164 | cairo_fill(cairo); | ||
165 | } | ||
166 | |||
167 | if (block->border && block->border_top > 0) { | ||
168 | render_sharp_line(cairo, block->border, | ||
169 | pos - 0.5, 1, block_width, block->border_top); | ||
170 | } | ||
171 | if (block->border && block->border_bottom > 0) { | ||
172 | render_sharp_line(cairo, block->border, | ||
173 | pos - 0.5, height - 1 - block->border_bottom, | ||
174 | block_width, block->border_bottom); | ||
175 | } | ||
176 | if (block->border != 0 && block->border_left > 0) { | ||
177 | render_sharp_line(cairo, block->border, | ||
178 | pos - 0.5, 1, block->border_left, height); | ||
179 | pos += block->border_left + margin; | ||
180 | } | ||
181 | |||
182 | double offset = 0; | ||
183 | if (strncmp(block->align, "left", 5) == 0) { | ||
184 | offset = pos; | ||
185 | } else if (strncmp(block->align, "right", 5) == 0) { | ||
186 | offset = pos + width - text_width; | ||
187 | } else if (strncmp(block->align, "center", 6) == 0) { | ||
188 | offset = pos + (width - text_width) / 2; | ||
189 | } | ||
190 | cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); | ||
191 | uint32_t color = block->color ? *block->color : config->colors.statusline; | ||
192 | cairo_set_source_u32(cairo, color); | ||
193 | pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text); | ||
194 | pos += width; | ||
195 | |||
196 | if (block->border && block->border_right > 0) { | ||
197 | pos += margin; | ||
198 | render_sharp_line(cairo, block->border, | ||
199 | pos - 0.5, 1, block->border_right, height); | ||
200 | pos += block->border_right; | ||
201 | } | ||
202 | |||
203 | if (!edge && block->separator) { | ||
204 | if (focused) { | ||
205 | cairo_set_source_u32(cairo, config->colors.focused_separator); | ||
206 | } else { | ||
207 | cairo_set_source_u32(cairo, config->colors.separator); | ||
208 | } | ||
209 | if (config->sep_symbol) { | ||
210 | offset = pos + (block->separator_block_width - sep_width) / 2; | ||
211 | cairo_move_to(cairo, offset, margin); | ||
212 | pango_printf(cairo, config->font, 1, false, | ||
213 | "%s", config->sep_symbol); | ||
214 | } else { | ||
215 | cairo_set_line_width(cairo, 1); | ||
216 | cairo_move_to(cairo, | ||
217 | pos + block->separator_block_width / 2, margin); | ||
218 | cairo_line_to(cairo, | ||
219 | pos + block->separator_block_width / 2, height - margin); | ||
220 | cairo_stroke(cairo); | ||
221 | } | ||
222 | } | ||
41 | return ideal_height; | 223 | return ideal_height; |
42 | } | 224 | } |
43 | 225 | ||
44 | static uint32_t render_status_line_i3bar(cairo_t *cairo, | 226 | static uint32_t render_status_line_i3bar(cairo_t *cairo, |
45 | struct swaybar_config *config, struct status_line *status, | 227 | struct swaybar_config *config, struct swaybar_output *output, |
46 | bool focused, uint32_t width, uint32_t height) { | 228 | struct status_line *status, bool focused, |
47 | // TODO | 229 | double *x, uint32_t width, uint32_t height) { |
48 | return 0; | 230 | uint32_t max_height = 0; |
231 | bool edge = true; | ||
232 | struct i3bar_block *block; | ||
233 | wl_list_for_each(block, &status->blocks, link) { | ||
234 | uint32_t h = render_status_block(cairo, config, output, | ||
235 | block, x, height, focused, edge); | ||
236 | max_height = h > max_height ? h : max_height; | ||
237 | edge = false; | ||
238 | } | ||
239 | return max_height; | ||
49 | } | 240 | } |
50 | 241 | ||
51 | static uint32_t render_status_line(cairo_t *cairo, | 242 | static uint32_t render_status_line(cairo_t *cairo, |
52 | struct swaybar_config *config, struct status_line *status, | 243 | struct swaybar_config *config, struct swaybar_output *output, |
53 | bool focused, uint32_t width, uint32_t height) { | 244 | struct status_line *status, bool focused, |
245 | double *x, uint32_t width, uint32_t height) { | ||
54 | switch (status->protocol) { | 246 | switch (status->protocol) { |
247 | case PROTOCOL_ERROR: | ||
248 | return render_status_line_error(cairo, | ||
249 | config, status->text, x, width, height); | ||
55 | case PROTOCOL_TEXT: | 250 | case PROTOCOL_TEXT: |
56 | return render_status_line_text(cairo, | 251 | return render_status_line_text(cairo, |
57 | config, status, focused, width, height); | 252 | config, status->text, focused, x, width, height); |
58 | case PROTOCOL_I3BAR: | 253 | case PROTOCOL_I3BAR: |
59 | return render_status_line_i3bar(cairo, | 254 | return render_status_line_i3bar(cairo, config, output, status, |
60 | config, status, focused, width, height); | 255 | focused, x, width, height); |
61 | default: | 256 | case PROTOCOL_UNDEF: |
62 | return 0; | 257 | return 0; |
63 | } | 258 | } |
259 | return 0; | ||
64 | } | 260 | } |
65 | 261 | ||
66 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, | 262 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, |
@@ -166,8 +362,8 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
166 | struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); | 362 | struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); |
167 | hotspot->x = *x; | 363 | hotspot->x = *x; |
168 | hotspot->y = 0; | 364 | hotspot->y = 0; |
169 | hotspot->height = height; | ||
170 | hotspot->width = width; | 365 | hotspot->width = width; |
366 | hotspot->height = height; | ||
171 | hotspot->callback = workspace_hotspot_callback; | 367 | hotspot->callback = workspace_hotspot_callback; |
172 | hotspot->destroy = free; | 368 | hotspot->destroy = free; |
173 | hotspot->data = strdup(name); | 369 | hotspot->data = strdup(name); |
@@ -180,6 +376,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
180 | static uint32_t render_to_cairo(cairo_t *cairo, | 376 | static uint32_t render_to_cairo(cairo_t *cairo, |
181 | struct swaybar *bar, struct swaybar_output *output) { | 377 | struct swaybar *bar, struct swaybar_output *output) { |
182 | struct swaybar_config *config = bar->config; | 378 | struct swaybar_config *config = bar->config; |
379 | wlr_log(L_DEBUG, "output %p", output); | ||
183 | 380 | ||
184 | cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); | 381 | cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); |
185 | if (output->focused) { | 382 | if (output->focused) { |
@@ -211,9 +408,10 @@ static uint32_t render_to_cairo(cairo_t *cairo, | |||
211 | cairo, config, config->mode, x, output->height); | 408 | cairo, config, config->mode, x, output->height); |
212 | max_height = h > max_height ? h : max_height; | 409 | max_height = h > max_height ? h : max_height; |
213 | } | 410 | } |
411 | x = output->width; | ||
214 | if (bar->status) { | 412 | if (bar->status) { |
215 | uint32_t h = render_status_line(cairo, config, bar->status, | 413 | uint32_t h = render_status_line(cairo, config, output, bar->status, |
216 | output->focused, output->width, output->height); | 414 | output->focused, &x, output->width, output->height); |
217 | max_height = h > max_height ? h : max_height; | 415 | max_height = h > max_height ? h : max_height; |
218 | } | 416 | } |
219 | 417 | ||
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 3454f207..cc7e217f 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #define _POSIX_C_SOURCE | 1 | #define _POSIX_C_SOURCE |
2 | #include <fcntl.h> | 2 | #include <fcntl.h> |
3 | #include <json-c/json.h> | ||
3 | #include <stdlib.h> | 4 | #include <stdlib.h> |
4 | #include <string.h> | 5 | #include <string.h> |
5 | #include <stdio.h> | 6 | #include <stdio.h> |
@@ -9,35 +10,79 @@ | |||
9 | #include "swaybar/status_line.h" | 10 | #include "swaybar/status_line.h" |
10 | #include "readline.h" | 11 | #include "readline.h" |
11 | 12 | ||
12 | bool handle_status_readable(struct status_line *status) { | 13 | void status_error(struct status_line *status, const char *text) { |
13 | char *line = read_line_buffer(status->read, | 14 | close(status->read_fd); |
14 | status->buffer, status->buffer_size); | 15 | close(status->write_fd); |
16 | status->protocol = PROTOCOL_ERROR; | ||
17 | status->text = text; | ||
18 | } | ||
19 | |||
20 | bool status_handle_readable(struct status_line *status) { | ||
21 | char *line; | ||
15 | switch (status->protocol) { | 22 | switch (status->protocol) { |
23 | case PROTOCOL_ERROR: | ||
24 | return false; | ||
16 | case PROTOCOL_I3BAR: | 25 | case PROTOCOL_I3BAR: |
17 | // TODO | 26 | if (i3bar_handle_readable(status) > 0) { |
27 | return true; | ||
28 | } | ||
18 | break; | 29 | break; |
19 | case PROTOCOL_TEXT: | 30 | case PROTOCOL_TEXT: |
20 | status->text = line; | 31 | line = read_line_buffer(status->read, |
32 | status->text_state.buffer, status->text_state.buffer_size); | ||
33 | if (!line) { | ||
34 | status_error(status, "[error reading from status command]"); | ||
35 | } else { | ||
36 | status->text = line; | ||
37 | } | ||
21 | return true; | 38 | return true; |
22 | case PROTOCOL_UNDEF: | 39 | case PROTOCOL_UNDEF: |
40 | line = read_line_buffer(status->read, | ||
41 | status->text_state.buffer, status->text_state.buffer_size); | ||
23 | if (!line) { | 42 | if (!line) { |
43 | status_error(status, "[error reading from status command]"); | ||
24 | return false; | 44 | return false; |
25 | } | 45 | } |
26 | if (line[0] == '{') { | 46 | if (line[0] == '{') { |
27 | // TODO: JSON | 47 | json_object *proto = json_tokener_parse(line); |
48 | if (proto) { | ||
49 | json_object *version; | ||
50 | if (json_object_object_get_ex(proto, "version", &version) | ||
51 | && json_object_get_int(version) == 1) { | ||
52 | wlr_log(L_DEBUG, "Switched to i3bar protocol."); | ||
53 | status->protocol = PROTOCOL_I3BAR; | ||
54 | } | ||
55 | json_object *click_events; | ||
56 | if (json_object_object_get_ex( | ||
57 | proto, "click_events", &click_events) | ||
58 | && json_object_get_boolean(click_events)) { | ||
59 | wlr_log(L_DEBUG, "Enabled click events."); | ||
60 | status->i3bar_state.click_events = true; | ||
61 | const char *events_array = "[\n"; | ||
62 | write(status->write_fd, events_array, strlen(events_array)); | ||
63 | } | ||
64 | json_object_put(proto); | ||
65 | } | ||
66 | |||
67 | status->protocol = PROTOCOL_I3BAR; | ||
68 | free(status->text_state.buffer); | ||
69 | wl_list_init(&status->blocks); | ||
70 | status->i3bar_state.buffer_size = 4096; | ||
71 | status->i3bar_state.buffer = | ||
72 | malloc(status->i3bar_state.buffer_size); | ||
28 | } else { | 73 | } else { |
29 | status->text = line; | ||
30 | status->protocol = PROTOCOL_TEXT; | 74 | status->protocol = PROTOCOL_TEXT; |
75 | status->text = line; | ||
31 | } | 76 | } |
32 | return false; | 77 | return true; |
33 | } | 78 | } |
34 | return false; | 79 | return false; |
35 | } | 80 | } |
36 | 81 | ||
37 | struct status_line *status_line_init(char *cmd) { | 82 | struct status_line *status_line_init(char *cmd) { |
38 | struct status_line *status = calloc(1, sizeof(struct status_line)); | 83 | struct status_line *status = calloc(1, sizeof(struct status_line)); |
39 | status->buffer_size = 4096; | 84 | status->text_state.buffer_size = 8192; |
40 | status->buffer = malloc(status->buffer_size); | 85 | status->text_state.buffer = malloc(status->text_state.buffer_size); |
41 | 86 | ||
42 | int pipe_read_fd[2]; | 87 | int pipe_read_fd[2]; |
43 | int pipe_write_fd[2]; | 88 | int pipe_write_fd[2]; |