summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-02 16:09:27 -0400
committerLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-02 16:09:27 -0400
commitd434da563239c43c5fe417ce83b23b417f2ab635 (patch)
treee154daaf43c42d11c5afb8b7739ae6b52dd01215
parentfix workspace splits (diff)
parentMerge pull request #1699 from acrisci/seat-fixes (diff)
downloadsway-d434da563239c43c5fe417ce83b23b417f2ab635.tar.gz
sway-d434da563239c43c5fe417ce83b23b417f2ab635.tar.zst
sway-d434da563239c43c5fe417ce83b23b417f2ab635.zip
Merge branch 'wlroots' into split-containers
-rw-r--r--common/pango.c9
-rw-r--r--include/sway/config.h27
-rw-r--r--include/sway/input/input-manager.h23
-rw-r--r--include/sway/input/seat.h28
-rw-r--r--include/swaybar/ipc.h2
-rw-r--r--include/swaybar/status_line.h53
-rw-r--r--sway/commands.c20
-rw-r--r--sway/commands/focus.c4
-rw-r--r--sway/commands/move.c8
-rw-r--r--sway/commands/seat.c11
-rw-r--r--sway/commands/workspace.c2
-rw-r--r--sway/config.c2
-rw-r--r--sway/desktop/output.c4
-rw-r--r--sway/desktop/wl_shell.c4
-rw-r--r--sway/desktop/xdg_shell_v6.c4
-rw-r--r--sway/desktop/xwayland.c4
-rw-r--r--sway/input/cursor.c10
-rw-r--r--sway/input/input-manager.c144
-rw-r--r--sway/input/keyboard.c2
-rw-r--r--sway/input/seat.c102
-rw-r--r--sway/ipc-json.c8
-rw-r--r--sway/ipc-server.c6
-rw-r--r--sway/server.c2
-rw-r--r--sway/tree/container.c4
-rw-r--r--sway/tree/layout.c28
-rw-r--r--sway/tree/workspace.c14
-rw-r--r--swaybar/bar.c4
-rw-r--r--swaybar/i3bar.c208
-rw-r--r--swaybar/ipc.c2
-rw-r--r--swaybar/meson.build1
-rw-r--r--swaybar/render.c238
-rw-r--r--swaybar/status_line.c65
32 files changed, 803 insertions, 240 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
10PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, 11PangoLayout *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);
377void config_clear_handler_context(struct sway_config *config); 377void config_clear_handler_context(struct sway_config *config);
378 378
379void free_sway_variable(struct sway_variable *var); 379void 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);
385struct cmd_results *check_security_config(); 386struct cmd_results *check_security_config();
386 387
387int input_identifier_cmp(const void *item, const void *data); 388int input_identifier_cmp(const void *item, const void *data);
389
388struct input_config *new_input_config(const char* identifier); 390struct input_config *new_input_config(const char* identifier);
391
389void merge_input_config(struct input_config *dst, struct input_config *src); 392void merge_input_config(struct input_config *dst, struct input_config *src);
393
390struct input_config *copy_input_config(struct input_config *ic); 394struct input_config *copy_input_config(struct input_config *ic);
395
391void free_input_config(struct input_config *ic); 396void free_input_config(struct input_config *ic);
397
392void apply_input_config(struct input_config *input); 398void apply_input_config(struct input_config *input);
393 399
394int seat_name_cmp(const void *item, const void *data); 400int seat_name_cmp(const void *item, const void *data);
401
395struct seat_config *new_seat_config(const char* name); 402struct seat_config *new_seat_config(const char* name);
403
396void merge_seat_config(struct seat_config *dst, struct seat_config *src); 404void merge_seat_config(struct seat_config *dst, struct seat_config *src);
405
397struct seat_config *copy_seat_config(struct seat_config *seat); 406struct seat_config *copy_seat_config(struct seat_config *seat);
407
398void free_seat_config(struct seat_config *ic); 408void free_seat_config(struct seat_config *ic);
409
399struct seat_attachment_config *seat_attachment_config_new(); 410struct seat_attachment_config *seat_attachment_config_new();
411
400struct seat_attachment_config *seat_config_get_attachment( 412struct seat_attachment_config *seat_config_get_attachment(
401 struct seat_config *seat_config, char *identifier); 413 struct seat_config *seat_config, char *identifier);
414
402void apply_seat_config(struct seat_config *seat); 415void apply_seat_config(struct seat_config *seat);
403 416
404int output_name_cmp(const void *item, const void *data); 417int output_name_cmp(const void *item, const void *data);
418
405void output_get_identifier(char *identifier, size_t len, 419void output_get_identifier(char *identifier, size_t len,
406 struct sway_output *output); 420 struct sway_output *output);
421
407struct output_config *new_output_config(const char *name); 422struct output_config *new_output_config(const char *name);
423
408void merge_output_config(struct output_config *dst, struct output_config *src); 424void merge_output_config(struct output_config *dst, struct output_config *src);
425
409void apply_output_config(struct output_config *oc, 426void apply_output_config(struct output_config *oc,
410 struct sway_container *output); 427 struct sway_container *output);
428
411void free_output_config(struct output_config *oc); 429void free_output_config(struct output_config *oc);
412 430
413int workspace_output_cmp_workspace(const void *a, const void *b); 431int workspace_output_cmp_workspace(const void *a, const void *b);
414 432
415int sway_binding_cmp(const void *a, const void *b); 433int sway_binding_cmp(const void *a, const void *b);
434
416int sway_binding_cmp_qsort(const void *a, const void *b); 435int sway_binding_cmp_qsort(const void *a, const void *b);
436
417int sway_binding_cmp_keys(const void *a, const void *b); 437int sway_binding_cmp_keys(const void *a, const void *b);
438
418void free_sway_binding(struct sway_binding *sb); 439void free_sway_binding(struct sway_binding *sb);
440
419struct sway_binding *sway_binding_dup(struct sway_binding *sb); 441struct sway_binding *sway_binding_dup(struct sway_binding *sb);
420 442
421/* Bar stuff */
422void load_swaybars(); 443void load_swaybars();
444
423void invoke_swaybar(struct bar_config *bar); 445void invoke_swaybar(struct bar_config *bar);
446
424void terminate_swaybg(pid_t pid); 447void terminate_swaybg(pid_t pid);
448
425struct bar_config *default_bar_config(void); 449struct bar_config *default_bar_config(void);
450
426void free_bar_config(struct bar_config *bar); 451void 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;
14struct sway_input_device { 14struct 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
30struct sway_input_manager *sway_input_manager_create( 29struct sway_input_manager *input_manager_create(struct sway_server *server);
31 struct sway_server *server);
32 30
33bool sway_input_manager_has_focus(struct sway_input_manager *input, 31bool input_manager_has_focus(struct sway_input_manager *input,
34 struct sway_container *container); 32 struct sway_container *container);
35 33
36void sway_input_manager_set_focus(struct sway_input_manager *input, 34void input_manager_set_focus(struct sway_input_manager *input,
37 struct sway_container *container); 35 struct sway_container *container);
38 36
39void sway_input_manager_configure_xcursor(struct sway_input_manager *input); 37void input_manager_configure_xcursor(struct sway_input_manager *input);
40 38
41void sway_input_manager_apply_input_config(struct sway_input_manager *input, 39void input_manager_apply_input_config(struct sway_input_manager *input,
42 struct input_config *input_config); 40 struct input_config *input_config);
43 41
44void sway_input_manager_apply_seat_config(struct sway_input_manager *input, 42void input_manager_apply_seat_config(struct sway_input_manager *input,
45 struct seat_config *seat_config); 43 struct seat_config *seat_config);
46 44
47struct sway_seat *sway_input_manager_get_default_seat( 45struct sway_seat *input_manager_get_default_seat(
48 struct sway_input_manager *input); 46 struct sway_input_manager *input);
49 47
50struct sway_seat *input_manager_get_seat(struct sway_input_manager *input, 48struct 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 */
54struct sway_seat *input_manager_current_seat(struct sway_input_manager *input); 54struct sway_seat *input_manager_current_seat(struct sway_input_manager *input);
55 55
56struct 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 38795e14..c780a52b 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
24struct sway_seat { 23struct 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
41struct sway_seat *sway_seat_create(struct sway_input_manager *input, 39struct sway_seat *seat_create(struct sway_input_manager *input,
42 const char *seat_name); 40 const char *seat_name);
43 41
44void sway_seat_destroy(struct sway_seat *seat); 42void seat_destroy(struct sway_seat *seat);
45 43
46void sway_seat_add_device(struct sway_seat *seat, 44void seat_add_device(struct sway_seat *seat,
47 struct sway_input_device *device); 45 struct sway_input_device *device);
48 46
49void sway_seat_configure_device(struct sway_seat *seat, 47void seat_configure_device(struct sway_seat *seat,
50 struct sway_input_device *device); 48 struct sway_input_device *device);
51 49
52void sway_seat_remove_device(struct sway_seat *seat, 50void seat_remove_device(struct sway_seat *seat,
53 struct sway_input_device *device); 51 struct sway_input_device *device);
54 52
55void sway_seat_configure_xcursor(struct sway_seat *seat); 53void seat_configure_xcursor(struct sway_seat *seat);
56 54
57void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container); 55void seat_set_focus(struct sway_seat *seat, struct sway_container *container);
58 56
59void sway_seat_set_focus_warp(struct sway_seat *seat, 57void seat_set_focus_warp(struct sway_seat *seat,
60 struct sway_container *container, bool warp); 58 struct sway_container *container, bool warp);
61 59
62struct sway_container *sway_seat_get_focus(struct sway_seat *seat); 60struct 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 */
73struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, 71struct sway_container *seat_get_focus_inactive(struct sway_seat *seat,
74 struct sway_container *container); 72 struct sway_container *container);
75 73
76struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, 74struct sway_container *seat_get_focus_by_type(struct sway_seat *seat,
77 struct sway_container *container, enum sway_container_type type); 75 struct sway_container *container, enum sway_container_type type);
78 76
79void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); 77void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config);
78
79struct seat_config *seat_get_config(struct sway_seat *seat);
80 80
81#endif 81#endif
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
6void ipc_initialize(struct swaybar *bar, const char *bar_id); 6void ipc_initialize(struct swaybar *bar, const char *bar_id);
7bool handle_ipc_event(struct swaybar *bar); 7bool handle_ipc_readable(struct swaybar *bar);
8void ipc_get_workspaces(struct swaybar *bar); 8void ipc_get_workspaces(struct swaybar *bar);
9void ipc_send_workspace_command(struct swaybar *bar, const char *ws); 9void 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
8enum status_protocol { 8enum 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
15struct text_protocol_state {
16 char *buffer;
17 size_t buffer_size;
18};
19
20enum json_node_type {
21 JSON_NODE_UNKNOWN,
22 JSON_NODE_ARRAY,
23 JSON_NODE_STRING,
24};
25
26struct 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
37struct 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
14struct status_line { 56struct 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
26struct status_line *status_line_init(char *cmd); 69struct status_line *status_line_init(char *cmd);
70void status_error(struct status_line *status, const char *text);
71bool status_handle_readable(struct status_line *status);
27void status_line_free(struct status_line *status); 72void status_line_free(struct status_line *status);
28bool handle_status_readable(struct status_line *status); 73bool i3bar_handle_readable(struct status_line *status);
74void 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 90012c6d..8156a08e 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
78void apply_seat_config(struct seat_config *seat) { 78void 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 */
@@ -267,7 +267,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
267 267
268 if (seat == NULL) { 268 if (seat == NULL) {
269 // passing a NULL seat means we just pick the default seat 269 // passing a NULL seat means we just pick the default seat
270 seat = sway_input_manager_get_default_seat(input_manager); 270 seat = input_manager_get_default_seat(input_manager);
271 if (!sway_assert(seat, "could not find a seat to run the command on")) { 271 if (!sway_assert(seat, "could not find a seat to run the command on")) {
272 return NULL; 272 return NULL;
273 } 273 }
@@ -345,7 +345,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
345 // without criteria, the command acts upon the focused 345 // without criteria, the command acts upon the focused
346 // container 346 // container
347 config->handler_context.current_container = 347 config->handler_context.current_container =
348 sway_seat_get_focus_inactive(seat, &root_container); 348 seat_get_focus_inactive(seat, &root_container);
349 if (!sway_assert(config->handler_context.current_container, 349 if (!sway_assert(config->handler_context.current_container,
350 "could not get focus-inactive for root container")) { 350 "could not get focus-inactive for root container")) {
351 return NULL; 351 return NULL;
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 0a521b9e..74d9d535 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -36,7 +36,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
36 } 36 }
37 37
38 if (argc == 0) { 38 if (argc == 0) {
39 sway_seat_set_focus(seat, con); 39 seat_set_focus(seat, con);
40 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 40 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
41 } 41 }
42 42
@@ -50,7 +50,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
50 struct sway_container *next_focus = container_get_in_direction( 50 struct sway_container *next_focus = container_get_in_direction(
51 con, seat, direction); 51 con, seat, direction);
52 if (next_focus) { 52 if (next_focus) {
53 sway_seat_set_focus(seat, next_focus); 53 seat_set_focus(seat, next_focus);
54 } 54 }
55 55
56 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
index ab959b77..644c622b 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -78,10 +78,10 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
78 } 78 }
79 free(ws_name); 79 free(ws_name);
80 struct sway_container *old_parent = current->parent; 80 struct sway_container *old_parent = current->parent;
81 struct sway_container *focus = sway_seat_get_focus_inactive( 81 struct sway_container *focus = seat_get_focus_inactive(
82 config->handler_context.seat, ws); 82 config->handler_context.seat, ws);
83 container_move_to(current, focus); 83 container_move_to(current, focus);
84 sway_seat_set_focus(config->handler_context.seat, old_parent); 84 seat_set_focus(config->handler_context.seat, old_parent);
85 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 85 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
86 } else if (strcasecmp(argv[1], "to") == 0 86 } else if (strcasecmp(argv[1], "to") == 0
87 && strcasecmp(argv[2], "output") == 0) { 87 && strcasecmp(argv[2], "output") == 0) {
@@ -100,7 +100,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
100 return cmd_results_new(CMD_FAILURE, "move workspace", 100 return cmd_results_new(CMD_FAILURE, "move workspace",
101 "Can't find output with name/direction '%s'", argv[3]); 101 "Can't find output with name/direction '%s'", argv[3]);
102 } 102 }
103 struct sway_container *focus = sway_seat_get_focus_inactive( 103 struct sway_container *focus = seat_get_focus_inactive(
104 config->handler_context.seat, destination); 104 config->handler_context.seat, destination);
105 if (!focus) { 105 if (!focus) {
106 // We've never been to this output before 106 // We've never been to this output before
@@ -108,7 +108,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
108 } 108 }
109 struct sway_container *old_parent = current->parent; 109 struct sway_container *old_parent = current->parent;
110 container_move_to(current, focus); 110 container_move_to(current, focus);
111 sway_seat_set_focus(config->handler_context.seat, old_parent); 111 seat_set_focus(config->handler_context.seat, old_parent);
112 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 112 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
113 } 113 }
114 return cmd_results_new(CMD_INVALID, "move", expected_syntax); 114 return cmd_results_new(CMD_INVALID, "move", expected_syntax);
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 c4265818..5e8a081c 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -228,7 +228,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
228 228
229 struct sway_seat *seat = input_manager_current_seat(input_manager); 229 struct sway_seat *seat = input_manager_current_seat(input_manager);
230 struct sway_container *focus = 230 struct sway_container *focus =
231 sway_seat_get_focus_inactive(seat, output->swayc); 231 seat_get_focus_inactive(seat, output->swayc);
232 if (!focus) { 232 if (!focus) {
233 // We've never been to this output before 233 // We've never been to this output before
234 focus = output->swayc->children->items[0]; 234 focus = output->swayc->children->items[0];
@@ -373,7 +373,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
373 wl_list_init(&output->layers[i]); 373 wl_list_init(&output->layers[i]);
374 } 374 }
375 375
376 sway_input_manager_configure_xcursor(input_manager); 376 input_manager_configure_xcursor(input_manager);
377 377
378 wl_signal_add(&wlr_output->events.destroy, &output->destroy); 378 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
379 output->destroy.notify = handle_destroy; 379 output->destroy.notify = handle_destroy;
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index 4fcc6317..c44fcf27 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -133,10 +133,10 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
133 wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); 133 wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy);
134 134
135 struct sway_seat *seat = input_manager_current_seat(input_manager); 135 struct sway_seat *seat = input_manager_current_seat(input_manager);
136 struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); 136 struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
137 struct sway_container *cont = container_view_create(focus, sway_view); 137 struct sway_container *cont = container_view_create(focus, sway_view);
138 sway_view->swayc = cont; 138 sway_view->swayc = cont;
139 139
140 arrange_windows(cont->parent, -1, -1); 140 arrange_windows(cont->parent, -1, -1);
141 sway_input_manager_set_focus(input_manager, cont); 141 input_manager_set_focus(input_manager, cont);
142} 142}
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 713437f2..cffe83fb 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -98,11 +98,11 @@ static void handle_map(struct wl_listener *listener, void *data) {
98 container_view_destroy(view->swayc); 98 container_view_destroy(view->swayc);
99 99
100 struct sway_seat *seat = input_manager_current_seat(input_manager); 100 struct sway_seat *seat = input_manager_current_seat(input_manager);
101 struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container); 101 struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
102 struct sway_container *cont = container_view_create(focus, view); 102 struct sway_container *cont = container_view_create(focus, view);
103 view->swayc = cont; 103 view->swayc = cont;
104 arrange_windows(cont->parent, -1, -1); 104 arrange_windows(cont->parent, -1, -1);
105 sway_input_manager_set_focus(input_manager, cont); 105 input_manager_set_focus(input_manager, cont);
106 106
107 view_damage_whole(sway_surface->view); 107 view_damage_whole(sway_surface->view);
108} 108}
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 273ca2bf..17f827d9 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -143,12 +143,12 @@ static void handle_map(struct wl_listener *listener, void *data) {
143 wlr_xwayland_surface_set_maximized(xsurface, true); 143 wlr_xwayland_surface_set_maximized(xsurface, true);
144 144
145 struct sway_seat *seat = input_manager_current_seat(input_manager); 145 struct sway_seat *seat = input_manager_current_seat(input_manager);
146 struct sway_container *focus = sway_seat_get_focus_inactive(seat, 146 struct sway_container *focus = seat_get_focus_inactive(seat,
147 &root_container); 147 &root_container);
148 struct sway_container *cont = container_view_create(focus, view); 148 struct sway_container *cont = container_view_create(focus, view);
149 view->swayc = cont; 149 view->swayc = cont;
150 arrange_windows(cont->parent, -1, -1); 150 arrange_windows(cont->parent, -1, -1);
151 sway_input_manager_set_focus(input_manager, cont); 151 input_manager_set_focus(input_manager, cont);
152 } 152 }
153 153
154 view_damage_whole(sway_surface->view); 154 view_damage_whole(sway_surface->view);
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index d608a9cf..7d05e942 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -84,7 +84,7 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
84 84
85 // find the focused workspace on the output for this seat 85 // find the focused workspace on the output for this seat
86 struct sway_container *ws = 86 struct sway_container *ws =
87 sway_seat_get_focus_inactive(cursor->seat, output->swayc); 87 seat_get_focus_inactive(cursor->seat, output->swayc);
88 if (ws && ws->type != C_WORKSPACE) { 88 if (ws && ws->type != C_WORKSPACE) {
89 ws = container_parent(ws, C_WORKSPACE); 89 ws = container_parent(ws, C_WORKSPACE);
90 } 90 }
@@ -129,7 +129,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
129 double sx, sy; 129 double sx, sy;
130 struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy); 130 struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy);
131 if (c && config->focus_follows_mouse) { 131 if (c && config->focus_follows_mouse) {
132 sway_seat_set_focus_warp(cursor->seat, c, false); 132 seat_set_focus_warp(cursor->seat, c, false);
133 } 133 }
134 134
135 // reset cursor if switching between clients 135 // reset cursor if switching between clients
@@ -191,15 +191,15 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
191 if (new_ws && new_ws->type != C_WORKSPACE) { 191 if (new_ws && new_ws->type != C_WORKSPACE) {
192 new_ws = container_parent(new_ws, C_WORKSPACE); 192 new_ws = container_parent(new_ws, C_WORKSPACE);
193 } 193 }
194 struct sway_container *old_ws = sway_seat_get_focus(cursor->seat); 194 struct sway_container *old_ws = seat_get_focus(cursor->seat);
195 if (old_ws && old_ws->type != C_WORKSPACE) { 195 if (old_ws && old_ws->type != C_WORKSPACE) {
196 old_ws = container_parent(old_ws, C_WORKSPACE); 196 old_ws = container_parent(old_ws, C_WORKSPACE);
197 } 197 }
198 if (new_ws != old_ws) { 198 if (new_ws != old_ws) {
199 sway_seat_set_focus(cursor->seat, cont); 199 seat_set_focus(cursor->seat, cont);
200 } 200 }
201 } else { 201 } else {
202 sway_seat_set_focus(cursor->seat, cont); 202 seat_set_focus(cursor->seat, cont);
203 } 203 }
204 204
205 wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, 205 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;
26struct sway_seat *input_manager_current_seat(struct sway_input_manager *input) { 26struct 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
46static char *get_device_identifier(struct wlr_input_device *device) { 46static char *get_device_identifier(struct wlr_input_device *device) {
@@ -83,7 +83,8 @@ static struct sway_input_device *input_sway_device_from_wlr(
83static bool input_has_seat_configuration(struct sway_input_manager *input) { 83static 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
94static void sway_input_manager_libinput_config_pointer(struct sway_input_device *input_device) { 95static 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
259struct sway_input_manager *sway_input_manager_create( 266struct 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
280bool sway_input_manager_has_focus(struct sway_input_manager *input, 287bool 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
292void sway_input_manager_set_focus(struct sway_input_manager *input, 299void 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
300void sway_input_manager_apply_input_config(struct sway_input_manager *input, 307void 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
320void sway_input_manager_apply_seat_config(struct sway_input_manager *input, 324void 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
376void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { 382void 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
383struct sway_seat *sway_input_manager_get_default_seat( 389struct 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
400struct 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 8d22b684..dbb0c359 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -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 1fd204d4..c41f7b2e 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -26,8 +26,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) {
26 free(seat_device); 26 free(seat_device);
27} 27}
28 28
29void sway_seat_destroy(struct sway_seat *seat) { 29void seat_destroy(struct sway_seat *seat) {
30 // TODO destroy seat containers
31 struct sway_seat_device *seat_device, *next; 30 struct sway_seat_device *seat_device, *next;
32 wl_list_for_each_safe(seat_device, next, &seat->devices, link) { 31 wl_list_for_each_safe(seat_device, next, &seat->devices, link) {
33 seat_device_destroy(seat_device); 32 seat_device_destroy(seat_device);
@@ -90,7 +89,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
90 struct sway_seat *seat = seat_con->seat; 89 struct sway_seat *seat = seat_con->seat;
91 struct sway_container *con = seat_con->container; 90 struct sway_container *con = seat_con->container;
92 struct sway_container *parent = con->parent; 91 struct sway_container *parent = con->parent;
93 struct sway_container *focus = sway_seat_get_focus(seat); 92 struct sway_container *focus = seat_get_focus(seat);
94 93
95 bool set_focus = 94 bool set_focus =
96 focus != NULL && 95 focus != NULL &&
@@ -102,7 +101,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
102 if (set_focus) { 101 if (set_focus) {
103 struct sway_container *next_focus = NULL; 102 struct sway_container *next_focus = NULL;
104 while (next_focus == NULL) { 103 while (next_focus == NULL) {
105 next_focus = sway_seat_get_focus_by_type(seat, parent, C_VIEW); 104 next_focus = seat_get_focus_by_type(seat, parent, C_VIEW);
106 105
107 if (next_focus == NULL && parent->type == C_WORKSPACE) { 106 if (next_focus == NULL && parent->type == C_WORKSPACE) {
108 next_focus = parent; 107 next_focus = parent;
@@ -114,10 +113,10 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
114 113
115 // the structure change might have caused it to move up to the top of 114 // the structure change might have caused it to move up to the top of
116 // the focus stack without sending focus notifications to the view 115 // the focus stack without sending focus notifications to the view
117 if (sway_seat_get_focus(seat) == next_focus) { 116 if (seat_get_focus(seat) == next_focus) {
118 seat_send_focus(seat, next_focus); 117 seat_send_focus(seat, next_focus);
119 } else { 118 } else {
120 sway_seat_set_focus(seat, next_focus); 119 seat_set_focus(seat, next_focus);
121 } 120 }
122 } 121 }
123} 122}
@@ -171,7 +170,7 @@ static void collect_focus_iter(struct sway_container *con, void *data) {
171 wl_list_insert(&seat->focus_stack, &seat_con->link); 170 wl_list_insert(&seat->focus_stack, &seat_con->link);
172} 171}
173 172
174struct sway_seat *sway_seat_create(struct sway_input_manager *input, 173struct sway_seat *seat_create(struct sway_input_manager *input,
175 const char *seat_name) { 174 const char *seat_name) {
176 struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); 175 struct sway_seat *seat = calloc(1, sizeof(struct sway_seat));
177 if (!seat) { 176 if (!seat) {
@@ -194,7 +193,8 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input,
194 // init the focus stack 193 // init the focus stack
195 wl_list_init(&seat->focus_stack); 194 wl_list_init(&seat->focus_stack);
196 195
197 container_for_each_descendant_dfs(&root_container, collect_focus_iter, seat); 196 container_for_each_descendant_dfs(&root_container,
197 collect_focus_iter, seat);
198 198
199 wl_signal_add(&root_container.sway_root->events.new_container, 199 wl_signal_add(&root_container.sway_root->events.new_container,
200 &seat->new_container); 200 &seat->new_container);
@@ -208,7 +208,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input,
208 WL_SEAT_CAPABILITY_POINTER | 208 WL_SEAT_CAPABILITY_POINTER |
209 WL_SEAT_CAPABILITY_TOUCH); 209 WL_SEAT_CAPABILITY_TOUCH);
210 210
211 sway_seat_configure_xcursor(seat); 211 seat_configure_xcursor(seat);
212 212
213 wl_list_insert(&input->seats, &seat->link); 213 wl_list_insert(&input->seats, &seat->link);
214 214
@@ -226,11 +226,12 @@ static void seat_configure_keyboard(struct sway_seat *seat,
226 if (!seat_device->keyboard) { 226 if (!seat_device->keyboard) {
227 sway_keyboard_create(seat, seat_device); 227 sway_keyboard_create(seat, seat_device);
228 } 228 }
229 struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; 229 struct wlr_keyboard *wlr_keyboard =
230 seat_device->input_device->wlr_device->keyboard;
230 sway_keyboard_configure(seat_device->keyboard); 231 sway_keyboard_configure(seat_device->keyboard);
231 wlr_seat_set_keyboard(seat->wlr_seat, 232 wlr_seat_set_keyboard(seat->wlr_seat,
232 seat_device->input_device->wlr_device); 233 seat_device->input_device->wlr_device);
233 struct sway_container *focus = sway_seat_get_focus(seat); 234 struct sway_container *focus = seat_get_focus(seat);
234 if (focus && focus->type == C_VIEW) { 235 if (focus && focus->type == C_VIEW) {
235 // force notify reenter to pick up the new configuration 236 // force notify reenter to pick up the new configuration
236 wlr_seat_keyboard_clear_focus(seat->wlr_seat); 237 wlr_seat_keyboard_clear_focus(seat->wlr_seat);
@@ -240,7 +241,7 @@ static void seat_configure_keyboard(struct sway_seat *seat,
240 } 241 }
241} 242}
242 243
243static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, 244static struct sway_seat_device *seat_get_device(struct sway_seat *seat,
244 struct sway_input_device *input_device) { 245 struct sway_input_device *input_device) {
245 struct sway_seat_device *seat_device = NULL; 246 struct sway_seat_device *seat_device = NULL;
246 wl_list_for_each(seat_device, &seat->devices, link) { 247 wl_list_for_each(seat_device, &seat->devices, link) {
@@ -252,19 +253,14 @@ static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat,
252 return NULL; 253 return NULL;
253} 254}
254 255
255void sway_seat_configure_device(struct sway_seat *seat, 256void seat_configure_device(struct sway_seat *seat,
256 struct sway_input_device *input_device) { 257 struct sway_input_device *input_device) {
257 struct sway_seat_device *seat_device = 258 struct sway_seat_device *seat_device =
258 sway_seat_get_device(seat, input_device); 259 seat_get_device(seat, input_device);
259 if (!seat_device) { 260 if (!seat_device) {
260 return; 261 return;
261 } 262 }
262 263
263 if (seat->config) {
264 seat_device->attachment_config =
265 seat_config_get_attachment(seat->config, input_device->identifier);
266 }
267
268 switch (input_device->wlr_device->type) { 264 switch (input_device->wlr_device->type) {
269 case WLR_INPUT_DEVICE_POINTER: 265 case WLR_INPUT_DEVICE_POINTER:
270 seat_configure_pointer(seat, seat_device); 266 seat_configure_pointer(seat, seat_device);
@@ -280,10 +276,10 @@ void sway_seat_configure_device(struct sway_seat *seat,
280 } 276 }
281} 277}
282 278
283void sway_seat_add_device(struct sway_seat *seat, 279void seat_add_device(struct sway_seat *seat,
284 struct sway_input_device *input_device) { 280 struct sway_input_device *input_device) {
285 if (sway_seat_get_device(seat, input_device)) { 281 if (seat_get_device(seat, input_device)) {
286 sway_seat_configure_device(seat, input_device); 282 seat_configure_device(seat, input_device);
287 return; 283 return;
288 } 284 }
289 285
@@ -301,13 +297,13 @@ void sway_seat_add_device(struct sway_seat *seat,
301 seat_device->input_device = input_device; 297 seat_device->input_device = input_device;
302 wl_list_insert(&seat->devices, &seat_device->link); 298 wl_list_insert(&seat->devices, &seat_device->link);
303 299
304 sway_seat_configure_device(seat, input_device); 300 seat_configure_device(seat, input_device);
305} 301}
306 302
307void sway_seat_remove_device(struct sway_seat *seat, 303void seat_remove_device(struct sway_seat *seat,
308 struct sway_input_device *input_device) { 304 struct sway_input_device *input_device) {
309 struct sway_seat_device *seat_device = 305 struct sway_seat_device *seat_device =
310 sway_seat_get_device(seat, input_device); 306 seat_get_device(seat, input_device);
311 307
312 if (!seat_device) { 308 if (!seat_device) {
313 return; 309 return;
@@ -319,7 +315,7 @@ void sway_seat_remove_device(struct sway_seat *seat,
319 seat_device_destroy(seat_device); 315 seat_device_destroy(seat_device);
320} 316}
321 317
322void sway_seat_configure_xcursor(struct sway_seat *seat) { 318void seat_configure_xcursor(struct sway_seat *seat) {
323 // TODO configure theme and size 319 // TODO configure theme and size
324 const char *cursor_theme = NULL; 320 const char *cursor_theme = NULL;
325 321
@@ -334,7 +330,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) {
334 } 330 }
335 331
336 for (int i = 0; i < root_container.children->length; ++i) { 332 for (int i = 0; i < root_container.children->length; ++i) {
337 struct sway_container *output_container = root_container.children->items[i]; 333 struct sway_container *output_container =
334 root_container.children->items[i];
338 struct wlr_output *output = 335 struct wlr_output *output =
339 output_container->sway_output->wlr_output; 336 output_container->sway_output->wlr_output;
340 bool result = 337 bool result =
@@ -353,9 +350,9 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) {
353 seat->cursor->cursor->y); 350 seat->cursor->cursor->y);
354} 351}
355 352
356void sway_seat_set_focus_warp(struct sway_seat *seat, 353void seat_set_focus_warp(struct sway_seat *seat,
357 struct sway_container *container, bool warp) { 354 struct sway_container *container, bool warp) {
358 struct sway_container *last_focus = sway_seat_get_focus(seat); 355 struct sway_container *last_focus = seat_get_focus(seat);
359 356
360 if (container && last_focus == container) { 357 if (container && last_focus == container) {
361 return; 358 return;
@@ -409,7 +406,7 @@ void sway_seat_set_focus_warp(struct sway_seat *seat,
409 } 406 }
410 407
411 if (last_focus && last_focus->type == C_VIEW && 408 if (last_focus && last_focus->type == C_VIEW &&
412 !sway_input_manager_has_focus(seat->input, last_focus)) { 409 !input_manager_has_focus(seat->input, last_focus)) {
413 struct sway_view *view = last_focus->sway_view; 410 struct sway_view *view = last_focus->sway_view;
414 view_set_activated(view, false); 411 view_set_activated(view, false);
415 } 412 }
@@ -417,24 +414,24 @@ void sway_seat_set_focus_warp(struct sway_seat *seat,
417 seat->has_focus = (container != NULL); 414 seat->has_focus = (container != NULL);
418} 415}
419 416
420void sway_seat_set_focus(struct sway_seat *seat, 417void seat_set_focus(struct sway_seat *seat,
421 struct sway_container *container) { 418 struct sway_container *container) {
422 sway_seat_set_focus_warp(seat, container, true); 419 seat_set_focus_warp(seat, container, true);
423} 420}
424 421
425struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat, 422struct sway_container *seat_get_focus_inactive(struct sway_seat *seat,
426 struct sway_container *container) { 423 struct sway_container *container) {
427 return sway_seat_get_focus_by_type(seat, container, C_TYPES); 424 return seat_get_focus_by_type(seat, container, C_TYPES);
428} 425}
429 426
430struct sway_container *sway_seat_get_focus(struct sway_seat *seat) { 427struct sway_container *sway_seat_get_focus(struct sway_seat *seat) {
431 if (!seat->has_focus) { 428 if (!seat->has_focus) {
432 return NULL; 429 return NULL;
433 } 430 }
434 return sway_seat_get_focus_inactive(seat, &root_container); 431 return seat_get_focus_inactive(seat, &root_container);
435} 432}
436 433
437struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat, 434struct sway_container *seat_get_focus_by_type(struct sway_seat *seat,
438 struct sway_container *container, enum sway_container_type type) { 435 struct sway_container *container, enum sway_container_type type) {
439 struct sway_seat_container *current = NULL; 436 struct sway_seat_container *current = NULL;
440 struct sway_container *parent = NULL; 437 struct sway_container *parent = NULL;
@@ -458,25 +455,34 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat,
458 return NULL; 455 return NULL;
459} 456}
460 457
461void sway_seat_set_config(struct sway_seat *seat, 458struct sway_container *seat_get_focus(struct sway_seat *seat) {
462 struct seat_config *seat_config) { 459 if (!seat->has_focus) {
463 // clear configs 460 return NULL;
464 free_seat_config(seat->config); 461 }
465 seat->config = NULL; 462 return seat_get_focus_inactive(seat, &root_container);
463}
466 464
465void seat_apply_config(struct sway_seat *seat,
466 struct seat_config *seat_config) {
467 struct sway_seat_device *seat_device = NULL; 467 struct sway_seat_device *seat_device = NULL;
468 wl_list_for_each(seat_device, &seat->devices, link) {
469 seat_device->attachment_config = NULL;
470 }
471 468
472 if (!seat_config) { 469 if (!seat_config) {
473 return; 470 return;
474 } 471 }
475 472
476 // add configs
477 seat->config = copy_seat_config(seat_config);
478
479 wl_list_for_each(seat_device, &seat->devices, link) { 473 wl_list_for_each(seat_device, &seat->devices, link) {
480 sway_seat_configure_device(seat, seat_device->input_device); 474 seat_configure_device(seat, seat_device->input_device);
475 }
476}
477
478struct seat_config *seat_get_config(struct sway_seat *seat) {
479 struct seat_config *seat_config = NULL;
480 for (int i = 0; i < config->seat_configs->length; ++i ) {
481 seat_config = config->seat_configs->items[i];
482 if (strcmp(seat->wlr_seat->name, seat_config->name) == 0) {
483 return seat_config;
484 }
481 } 485 }
486
487 return NULL;
482} 488}
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/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 9205d929..4db93ce8 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -89,8 +89,8 @@ static struct sway_container *_container_destroy(struct sway_container *cont) {
89 // container_remove_child, which removes child from this container 89 // container_remove_child, which removes child from this container
90 while (cont->children != NULL && cont->children->length != 0) { 90 while (cont->children != NULL && cont->children->length != 0) {
91 struct sway_container *child = cont->children->items[0]; 91 struct sway_container *child = cont->children->items[0];
92 container_remove_child(child);
92 container_destroy(child); 93 container_destroy(child);
93 list_del(cont->children, 0);
94 } 94 }
95 } 95 }
96 if (cont->marks) { 96 if (cont->marks) {
@@ -172,7 +172,7 @@ struct sway_container *container_output_create(
172 struct sway_seat *seat = NULL; 172 struct sway_seat *seat = NULL;
173 wl_list_for_each(seat, &input_manager->seats, link) { 173 wl_list_for_each(seat, &input_manager->seats, link) {
174 if (!seat->has_focus) { 174 if (!seat->has_focus) {
175 sway_seat_set_focus(seat, ws); 175 seat_set_focus(seat, ws);
176 } 176 }
177 } 177 }
178 178
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index bea15f8a..88463e3b 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -158,17 +158,17 @@ void container_move_to(struct sway_container *container,
158 } 158 }
159 wl_signal_emit(&container->events.reparent, old_parent); 159 wl_signal_emit(&container->events.reparent, old_parent);
160 if (container->type == C_WORKSPACE) { 160 if (container->type == C_WORKSPACE) {
161 struct sway_seat *seat = sway_input_manager_get_default_seat( 161 struct sway_seat *seat = input_manager_get_default_seat(
162 input_manager); 162 input_manager);
163 if (old_parent->children->length == 0) { 163 if (old_parent->children->length == 0) {
164 char *ws_name = workspace_next_name(old_parent->name); 164 char *ws_name = workspace_next_name(old_parent->name);
165 struct sway_container *ws = 165 struct sway_container *ws =
166 container_workspace_create(old_parent, ws_name); 166 container_workspace_create(old_parent, ws_name);
167 free(ws_name); 167 free(ws_name);
168 sway_seat_set_focus(seat, ws); 168 seat_set_focus(seat, ws);
169 } 169 }
170 container_sort_workspaces(new_parent); 170 container_sort_workspaces(new_parent);
171 sway_seat_set_focus(seat, new_parent); 171 seat_set_focus(seat, new_parent);
172 } 172 }
173 if (old_parent) { 173 if (old_parent) {
174 arrange_windows(old_parent, -1, -1); 174 arrange_windows(old_parent, -1, -1);
@@ -275,8 +275,8 @@ void arrange_windows(struct sway_container *container,
275 struct wlr_box *area = &output->sway_output->usable_area; 275 struct wlr_box *area = &output->sway_output->usable_area;
276 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", 276 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
277 area->width, area->height, area->x, area->y); 277 area->width, area->height, area->x, area->y);
278 container->width = area->width; 278 container->width = width = area->width;
279 container->height = area->height; 279 container->height = height = area->height;
280 container->x = x = area->x; 280 container->x = x = area->x;
281 container->y = y = area->y; 281 container->y = y = area->y;
282 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", 282 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
@@ -441,7 +441,7 @@ static struct sway_container *get_swayc_in_output_direction(
441 return NULL; 441 return NULL;
442 } 442 }
443 443
444 struct sway_container *ws = sway_seat_get_focus_inactive(seat, output); 444 struct sway_container *ws = seat_get_focus_inactive(seat, output);
445 if (ws->type != C_WORKSPACE) { 445 if (ws->type != C_WORKSPACE) {
446 ws = container_parent(ws, C_WORKSPACE); 446 ws = container_parent(ws, C_WORKSPACE);
447 } 447 }
@@ -462,7 +462,7 @@ static struct sway_container *get_swayc_in_output_direction(
462 case MOVE_UP: 462 case MOVE_UP:
463 case MOVE_DOWN: { 463 case MOVE_DOWN: {
464 struct sway_container *focused = 464 struct sway_container *focused =
465 sway_seat_get_focus_inactive(seat, ws); 465 seat_get_focus_inactive(seat, ws);
466 if (focused && focused->parent) { 466 if (focused && focused->parent) {
467 struct sway_container *parent = focused->parent; 467 struct sway_container *parent = focused->parent;
468 if (parent->layout == L_VERT) { 468 if (parent->layout == L_VERT) {
@@ -546,7 +546,7 @@ struct sway_container *container_get_in_direction(
546 struct sway_container *container, struct sway_seat *seat, 546 struct sway_container *container, struct sway_seat *seat,
547 enum movement_direction dir) { 547 enum movement_direction dir) {
548 if (dir == MOVE_CHILD) { 548 if (dir == MOVE_CHILD) {
549 return sway_seat_get_focus_inactive(seat, container); 549 return seat_get_focus_inactive(seat, container);
550 } 550 }
551 551
552 struct sway_container *parent = container->parent; 552 struct sway_container *parent = container->parent;
@@ -605,7 +605,7 @@ struct sway_container *container_get_in_direction(
605 } 605 }
606 if (next->children && next->children->length) { 606 if (next->children && next->children->length) {
607 // TODO consider floating children as well 607 // TODO consider floating children as well
608 return sway_seat_get_focus_by_type(seat, next, C_VIEW); 608 return seat_get_focus_by_type(seat, next, C_VIEW);
609 } else { 609 } else {
610 return next; 610 return next;
611 } 611 }
@@ -635,7 +635,7 @@ struct sway_container *container_get_in_direction(
635 wrap_candidate = parent->children->items[0]; 635 wrap_candidate = parent->children->items[0];
636 } 636 }
637 if (config->force_focus_wrapping) { 637 if (config->force_focus_wrapping) {
638 return sway_seat_get_focus_by_type(seat, 638 return seat_get_focus_by_type(seat,
639 wrap_candidate, C_VIEW); 639 wrap_candidate, C_VIEW);
640 } 640 }
641 } 641 }
@@ -643,7 +643,7 @@ struct sway_container *container_get_in_direction(
643 wlr_log(L_DEBUG, 643 wlr_log(L_DEBUG,
644 "cont %d-%p dir %i sibling %d: %p", idx, 644 "cont %d-%p dir %i sibling %d: %p", idx,
645 container, dir, desired, parent->children->items[desired]); 645 container, dir, desired, parent->children->items[desired]);
646 return sway_seat_get_focus_by_type(seat, 646 return seat_get_focus_by_type(seat,
647 parent->children->items[desired], C_VIEW); 647 parent->children->items[desired], C_VIEW);
648 } 648 }
649 } 649 }
@@ -702,9 +702,9 @@ struct sway_container *container_split(struct sway_container *child,
702 cont->y = child->y; 702 cont->y = child->y;
703 703
704 if (child->type == C_WORKSPACE) { 704 if (child->type == C_WORKSPACE) {
705 struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager); 705 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
706 struct sway_container *workspace = child; 706 struct sway_container *workspace = child;
707 bool set_focus = (sway_seat_get_focus(seat) == workspace); 707 bool set_focus = (seat_get_focus(seat) == workspace);
708 708
709 while (workspace->children->length) { 709 while (workspace->children->length) {
710 struct sway_container *ws_child = workspace->children->items[0]; 710 struct sway_container *ws_child = workspace->children->items[0];
@@ -716,7 +716,7 @@ struct sway_container *container_split(struct sway_container *child,
716 container_set_layout(workspace, layout); 716 container_set_layout(workspace, layout);
717 717
718 if (set_focus) { 718 if (set_focus) {
719 sway_seat_set_focus(seat, cont); 719 seat_set_focus(seat, cont);
720 } 720 }
721 } else { 721 } else {
722 cont->layout = layout; 722 cont->layout = layout;
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index de1bf159..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) {
158struct sway_container *workspace_by_name(const char *name) { 158struct 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,7 +345,7 @@ 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 }
@@ -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) {
389bool workspace_is_visible(struct sway_container *ws) { 389bool 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
309static void ipc_in(int fd, short mask, void *_bar) { 309static 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
316static void status_in(int fd, short mask, void *_bar) { 316static 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
10static 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
23static 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
110bool 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
188void 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
326bool handle_ipc_event(struct swaybar *bar) { 326bool 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;
18static const double ws_vertical_padding = 1.5; 18static const double ws_vertical_padding = 1.5;
19static const double border_width = 1; 19static const double border_width = 1;
20 20
21static 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
21static uint32_t render_status_line_text(cairo_t *cairo, 44static 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
68static 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
92static 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
99static 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
44static uint32_t render_status_line_i3bar(cairo_t *cairo, 226static 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
51static uint32_t render_status_line(cairo_t *cairo, 242static 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
66static uint32_t render_binding_mode_indicator(cairo_t *cairo, 262static 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,
180static uint32_t render_to_cairo(cairo_t *cairo, 376static 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
12bool handle_status_readable(struct status_line *status) { 13void 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
20bool 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
37struct status_line *status_line_init(char *cmd) { 82struct 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];