aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "log.h"
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
const char *text, int32_t scale, bool markup) {
@@ -13,7 +14,13 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
PangoAttrList *attrs;
if (markup) {
char *buf;
- pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL);
+ GError *error = NULL;
+ if (!sway_assert(pango_parse_markup(
+ text, -1, 0, &attrs, &buf, NULL, &error),
+ "pango_parse_markup '%s' -> error %s", text,
+ error ? error->message : NULL)) {
+ return NULL;
+ }
pango_layout_set_markup(layout, buf, -1);
free(buf);
} 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);
void config_clear_handler_context(struct sway_config *config);
void free_sway_variable(struct sway_variable *var);
+
/**
* Does variable replacement for a string based on the config's currently loaded variables.
*/
@@ -385,44 +386,68 @@ char *do_var_replacement(char *str);
struct cmd_results *check_security_config();
int input_identifier_cmp(const void *item, const void *data);
+
struct input_config *new_input_config(const char* identifier);
+
void merge_input_config(struct input_config *dst, struct input_config *src);
+
struct input_config *copy_input_config(struct input_config *ic);
+
void free_input_config(struct input_config *ic);
+
void apply_input_config(struct input_config *input);
int seat_name_cmp(const void *item, const void *data);
+
struct seat_config *new_seat_config(const char* name);
+
void merge_seat_config(struct seat_config *dst, struct seat_config *src);
+
struct seat_config *copy_seat_config(struct seat_config *seat);
+
void free_seat_config(struct seat_config *ic);
+
struct seat_attachment_config *seat_attachment_config_new();
+
struct seat_attachment_config *seat_config_get_attachment(
struct seat_config *seat_config, char *identifier);
+
void apply_seat_config(struct seat_config *seat);
int output_name_cmp(const void *item, const void *data);
+
void output_get_identifier(char *identifier, size_t len,
struct sway_output *output);
+
struct output_config *new_output_config(const char *name);
+
void merge_output_config(struct output_config *dst, struct output_config *src);
+
void apply_output_config(struct output_config *oc,
struct sway_container *output);
+
void free_output_config(struct output_config *oc);
int workspace_output_cmp_workspace(const void *a, const void *b);
int sway_binding_cmp(const void *a, const void *b);
+
int sway_binding_cmp_qsort(const void *a, const void *b);
+
int sway_binding_cmp_keys(const void *a, const void *b);
+
void free_sway_binding(struct sway_binding *sb);
+
struct sway_binding *sway_binding_dup(struct sway_binding *sb);
-/* Bar stuff */
void load_swaybars();
+
void invoke_swaybar(struct bar_config *bar);
+
void terminate_swaybg(pid_t pid);
+
struct bar_config *default_bar_config(void);
+
void free_bar_config(struct bar_config *bar);
/* 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;
struct sway_input_device {
char *identifier;
struct wlr_input_device *wlr_device;
- struct input_config *config;
struct wl_list link;
struct wl_listener device_destroy;
};
@@ -27,30 +26,34 @@ struct sway_input_manager {
struct wl_listener new_input;
};
-struct sway_input_manager *sway_input_manager_create(
- struct sway_server *server);
+struct sway_input_manager *input_manager_create(struct sway_server *server);
-bool sway_input_manager_has_focus(struct sway_input_manager *input,
+bool input_manager_has_focus(struct sway_input_manager *input,
struct sway_container *container);
-void sway_input_manager_set_focus(struct sway_input_manager *input,
+void input_manager_set_focus(struct sway_input_manager *input,
struct sway_container *container);
-void sway_input_manager_configure_xcursor(struct sway_input_manager *input);
+void input_manager_configure_xcursor(struct sway_input_manager *input);
-void sway_input_manager_apply_input_config(struct sway_input_manager *input,
+void input_manager_apply_input_config(struct sway_input_manager *input,
struct input_config *input_config);
-void sway_input_manager_apply_seat_config(struct sway_input_manager *input,
+void input_manager_apply_seat_config(struct sway_input_manager *input,
struct seat_config *seat_config);
-struct sway_seat *sway_input_manager_get_default_seat(
+struct sway_seat *input_manager_get_default_seat(
struct sway_input_manager *input);
struct sway_seat *input_manager_get_seat(struct sway_input_manager *input,
const char *seat_name);
-/** Gets the last seat the user interacted with */
+/**
+ * Gets the last seat the user interacted with
+ */
struct sway_seat *input_manager_current_seat(struct sway_input_manager *input);
+struct input_config *input_device_get_config(struct sway_input_device *device);
+
+
#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 {
struct sway_seat *sway_seat;
struct sway_input_device *input_device;
struct sway_keyboard *keyboard;
- struct seat_attachment_config *attachment_config;
struct wl_list link; // sway_seat::devices
};
@@ -23,7 +22,6 @@ struct sway_seat_container {
struct sway_seat {
struct wlr_seat *wlr_seat;
- struct seat_config *config;
struct sway_cursor *cursor;
struct sway_input_manager *input;
@@ -38,28 +36,28 @@ struct sway_seat {
struct wl_list link; // input_manager::seats
};
-struct sway_seat *sway_seat_create(struct sway_input_manager *input,
+struct sway_seat *seat_create(struct sway_input_manager *input,
const char *seat_name);
-void sway_seat_destroy(struct sway_seat *seat);
+void seat_destroy(struct sway_seat *seat);
-void sway_seat_add_device(struct sway_seat *seat,
+void seat_add_device(struct sway_seat *seat,
struct sway_input_device *device);
-void sway_seat_configure_device(struct sway_seat *seat,
+void seat_configure_device(struct sway_seat *seat,
struct sway_input_device *device);
-void sway_seat_remove_device(struct sway_seat *seat,
+void seat_remove_device(struct sway_seat *seat,
struct sway_input_device *device);
-void sway_seat_configure_xcursor(struct sway_seat *seat);
+void seat_configure_xcursor(struct sway_seat *seat);
-void sway_seat_set_focus(struct sway_seat *seat, struct sway_container *container);
+void seat_set_focus(struct sway_seat *seat, struct sway_container *container);
-void sway_seat_set_focus_warp(struct sway_seat *seat,
+void seat_set_focus_warp(struct sway_seat *seat,
struct sway_container *container, bool warp);
-struct sway_container *sway_seat_get_focus(struct sway_seat *seat);
+struct sway_container *seat_get_focus(struct sway_seat *seat);
/**
* 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);
* is destroyed, or focus moves to a container with children and we need to
* descend into the next leaf in focus order.
*/
-struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat,
+struct sway_container *seat_get_focus_inactive(struct sway_seat *seat,
struct sway_container *container);
-struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat,
+struct sway_container *seat_get_focus_by_type(struct sway_seat *seat,
struct sway_container *container, enum sway_container_type type);
-void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config);
+void seat_apply_config(struct sway_seat *seat, struct seat_config *seat_config);
+
+struct seat_config *seat_get_config(struct sway_seat *seat);
#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 @@
#include "swaybar/bar.h"
void ipc_initialize(struct swaybar *bar, const char *bar_id);
-bool handle_ipc_event(struct swaybar *bar);
+bool handle_ipc_readable(struct swaybar *bar);
void ipc_get_workspaces(struct swaybar *bar);
void ipc_send_workspace_command(struct swaybar *bar, const char *ws);
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 @@
enum status_protocol {
PROTOCOL_UNDEF,
+ PROTOCOL_ERROR,
PROTOCOL_TEXT,
PROTOCOL_I3BAR,
};
+struct text_protocol_state {
+ char *buffer;
+ size_t buffer_size;
+};
+
+enum json_node_type {
+ JSON_NODE_UNKNOWN,
+ JSON_NODE_ARRAY,
+ JSON_NODE_STRING,
+};
+
+struct i3bar_protocol_state {
+ bool click_events;
+ char *buffer;
+ size_t buffer_size;
+ size_t buffer_index;
+ const char *current_node;
+ bool escape;
+ size_t depth;
+ enum json_node_type nodes[16];
+};
+
+struct i3bar_block {
+ struct wl_list link;
+ char *full_text, *short_text, *align;
+ bool urgent;
+ uint32_t *color;
+ int min_width;
+ char *name, *instance;
+ bool separator;
+ int separator_block_width;
+ bool markup;
+ // Airblader features
+ uint32_t background;
+ uint32_t border;
+ int border_top;
+ int border_bottom;
+ int border_left;
+ int border_right;
+};
+
struct status_line {
pid_t pid;
int read_fd, write_fd;
@@ -18,13 +60,18 @@ struct status_line {
enum status_protocol protocol;
const char *text;
+ struct wl_list blocks; // i3bar_block::link
- char *buffer;
- size_t buffer_size;
+ struct text_protocol_state text_state;
+ struct i3bar_protocol_state i3bar_state;
};
struct status_line *status_line_init(char *cmd);
+void status_error(struct status_line *status, const char *text);
+bool status_handle_readable(struct status_line *status);
void status_line_free(struct status_line *status);
-bool handle_status_readable(struct status_line *status);
+bool i3bar_handle_readable(struct status_line *status);
+void i3bar_block_send_click(struct status_line *status,
+ struct i3bar_block *block, int x, int y, uint32_t button);
#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) {
list_add(config->input_configs, input);
}
- sway_input_manager_apply_input_config(input_manager, input);
+ input_manager_apply_input_config(input_manager, input);
}
-void apply_seat_config(struct seat_config *seat) {
+void apply_seat_config(struct seat_config *seat_config) {
int i;
- i = list_seq_find(config->seat_configs, seat_name_cmp, seat->name);
+ i = list_seq_find(config->seat_configs, seat_name_cmp, seat_config->name);
if (i >= 0) {
// merge existing config
struct seat_config *sc = config->seat_configs->items[i];
- merge_seat_config(sc, seat);
- free_seat_config(seat);
- seat = sc;
+ merge_seat_config(sc, seat_config);
+ free_seat_config(seat_config);
+ seat_config = sc;
} else {
- list_add(config->seat_configs, seat);
+ list_add(config->seat_configs, seat_config);
}
- sway_input_manager_apply_seat_config(input_manager, seat);
+ input_manager_apply_seat_config(input_manager, seat_config);
}
/* Keep alphabetized */
@@ -267,7 +267,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
if (seat == NULL) {
// passing a NULL seat means we just pick the default seat
- seat = sway_input_manager_get_default_seat(input_manager);
+ seat = input_manager_get_default_seat(input_manager);
if (!sway_assert(seat, "could not find a seat to run the command on")) {
return NULL;
}
@@ -345,7 +345,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
// without criteria, the command acts upon the focused
// container
config->handler_context.current_container =
- sway_seat_get_focus_inactive(seat, &root_container);
+ seat_get_focus_inactive(seat, &root_container);
if (!sway_assert(config->handler_context.current_container,
"could not get focus-inactive for root container")) {
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) {
}
if (argc == 0) {
- sway_seat_set_focus(seat, con);
+ seat_set_focus(seat, con);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
@@ -50,7 +50,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
struct sway_container *next_focus = container_get_in_direction(
con, seat, direction);
if (next_focus) {
- sway_seat_set_focus(seat, next_focus);
+ seat_set_focus(seat, next_focus);
}
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,
}
free(ws_name);
struct sway_container *old_parent = current->parent;
- struct sway_container *focus = sway_seat_get_focus_inactive(
+ struct sway_container *focus = seat_get_focus_inactive(
config->handler_context.seat, ws);
container_move_to(current, focus);
- sway_seat_set_focus(config->handler_context.seat, old_parent);
+ seat_set_focus(config->handler_context.seat, old_parent);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
} else if (strcasecmp(argv[1], "to") == 0
&& strcasecmp(argv[2], "output") == 0) {
@@ -100,7 +100,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
return cmd_results_new(CMD_FAILURE, "move workspace",
"Can't find output with name/direction '%s'", argv[3]);
}
- struct sway_container *focus = sway_seat_get_focus_inactive(
+ struct sway_container *focus = seat_get_focus_inactive(
config->handler_context.seat, destination);
if (!focus) {
// We've never been to this output before
@@ -108,7 +108,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
}
struct sway_container *old_parent = current->parent;
container_move_to(current, focus);
- sway_seat_set_focus(config->handler_context.seat, old_parent);
+ seat_set_focus(config->handler_context.seat, old_parent);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
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) {
free_seat_config(config->handler_context.seat_config);
config->handler_context.seat_config = new_seat_config(argv[0]);
if (!config->handler_context.seat_config) {
- return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config");
+ return cmd_results_new(CMD_FAILURE, NULL,
+ "Couldn't allocate config");
}
wlr_log(L_DEBUG, "entering seat block: %s", argv[0]);
return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL);
@@ -28,7 +29,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) {
if (!has_context) {
config->handler_context.seat_config = new_seat_config(argv[0]);
if (!config->handler_context.seat_config) {
- return cmd_results_new(CMD_FAILURE, NULL, "Couldn't allocate config");
+ return cmd_results_new(CMD_FAILURE, NULL,
+ "Couldn't allocate config");
}
}
@@ -41,7 +43,10 @@ struct cmd_results *cmd_seat(int argc, char **argv) {
} else if (strcasecmp("fallback", argv[1]) == 0) {
res = seat_cmd_fallback(argc_new, argv_new);
} else {
- res = cmd_results_new(CMD_INVALID, "seat <name>", "Unknown command %s", argv[1]);
+ res =
+ cmd_results_new(CMD_INVALID,
+ "seat <name>", "Unknown command %s",
+ argv[1]);
}
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) {
}
workspace_switch(ws);
current_container =
- sway_seat_get_focus(config->handler_context.seat);
+ seat_get_focus(config->handler_context.seat);
struct sway_container *new_output = container_parent(current_container, C_OUTPUT);
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,
seat_name_cmp, seat_config->name) < 0) {
seat = input_manager_get_seat(input_manager,
seat_config->name);
- sway_seat_destroy(seat);
+ seat_destroy(seat);
}
}
}
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,
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus =
- sway_seat_get_focus_inactive(seat, output->swayc);
+ seat_get_focus_inactive(seat, output->swayc);
if (!focus) {
// We've never been to this output before
focus = output->swayc->children->items[0];
@@ -373,7 +373,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
wl_list_init(&output->layers[i]);
}
- sway_input_manager_configure_xcursor(input_manager);
+ input_manager_configure_xcursor(input_manager);
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
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) {
wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy);
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container);
+ struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
struct sway_container *cont = container_view_create(focus, sway_view);
sway_view->swayc = cont;
arrange_windows(cont->parent, -1, -1);
- sway_input_manager_set_focus(input_manager, cont);
+ input_manager_set_focus(input_manager, cont);
}
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) {
container_view_destroy(view->swayc);
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = sway_seat_get_focus_inactive(seat, &root_container);
+ struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
struct sway_container *cont = container_view_create(focus, view);
view->swayc = cont;
arrange_windows(cont->parent, -1, -1);
- sway_input_manager_set_focus(input_manager, cont);
+ input_manager_set_focus(input_manager, cont);
view_damage_whole(sway_surface->view);
}
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) {
wlr_xwayland_surface_set_maximized(xsurface, true);
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = sway_seat_get_focus_inactive(seat,
+ struct sway_container *focus = seat_get_focus_inactive(seat,
&root_container);
struct sway_container *cont = container_view_create(focus, view);
view->swayc = cont;
arrange_windows(cont->parent, -1, -1);
- sway_input_manager_set_focus(input_manager, cont);
+ input_manager_set_focus(input_manager, cont);
}
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,
// find the focused workspace on the output for this seat
struct sway_container *ws =
- sway_seat_get_focus_inactive(cursor->seat, output->swayc);
+ seat_get_focus_inactive(cursor->seat, output->swayc);
if (ws && ws->type != C_WORKSPACE) {
ws = container_parent(ws, C_WORKSPACE);
}
@@ -129,7 +129,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
double sx, sy;
struct sway_container *c = container_at_cursor(cursor, &surface, &sx, &sy);
if (c && config->focus_follows_mouse) {
- sway_seat_set_focus_warp(cursor->seat, c, false);
+ seat_set_focus_warp(cursor->seat, c, false);
}
// reset cursor if switching between clients
@@ -191,15 +191,15 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
if (new_ws && new_ws->type != C_WORKSPACE) {
new_ws = container_parent(new_ws, C_WORKSPACE);
}
- struct sway_container *old_ws = sway_seat_get_focus(cursor->seat);
+ struct sway_container *old_ws = seat_get_focus(cursor->seat);
if (old_ws && old_ws->type != C_WORKSPACE) {
old_ws = container_parent(old_ws, C_WORKSPACE);
}
if (new_ws != old_ws) {
- sway_seat_set_focus(cursor->seat, cont);
+ seat_set_focus(cursor->seat, cont);
}
} else {
- sway_seat_set_focus(cursor->seat, cont);
+ seat_set_focus(cursor->seat, cont);
}
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;
struct sway_seat *input_manager_current_seat(struct sway_input_manager *input) {
struct sway_seat *seat = config->handler_context.seat;
if (!seat) {
- seat = sway_input_manager_get_default_seat(input_manager);
+ seat = input_manager_get_default_seat(input_manager);
}
return seat;
}
@@ -40,7 +40,7 @@ struct sway_seat *input_manager_get_seat(
}
}
- return sway_seat_create(input, seat_name);
+ return seat_create(input, seat_name);
}
static char *get_device_identifier(struct wlr_input_device *device) {
@@ -83,7 +83,8 @@ static struct sway_input_device *input_sway_device_from_wlr(
static bool input_has_seat_configuration(struct sway_input_manager *input) {
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input->seats, link) {
- if (seat->config) {
+ struct seat_config *seat_config = seat_get_config(seat);
+ if (seat_config) {
return true;
}
}
@@ -91,9 +92,10 @@ static bool input_has_seat_configuration(struct sway_input_manager *input) {
return false;
}
-static void sway_input_manager_libinput_config_pointer(struct sway_input_device *input_device) {
+static void input_manager_libinput_config_pointer(
+ struct sway_input_device *input_device) {
struct wlr_input_device *wlr_device = input_device->wlr_device;
- struct input_config *ic = input_device->config;
+ struct input_config *ic = input_device_get_config(input_device);
struct libinput_device *libinput_device;
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
}
libinput_device = wlr_libinput_get_device_handle(wlr_device);
- wlr_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier);
+ wlr_log(L_DEBUG, "input_manager_libinput_config_pointer(%s)",
+ ic->identifier);
if (ic->accel_profile != INT_MIN) {
wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)",
ic->identifier, ic->accel_profile);
- libinput_device_config_accel_set_profile(libinput_device, ic->accel_profile);
+ libinput_device_config_accel_set_profile(libinput_device,
+ ic->accel_profile);
}
if (ic->click_method != INT_MIN) {
wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)",
ic->identifier, ic->click_method);
- libinput_device_config_click_set_method(libinput_device, ic->click_method);
+ libinput_device_config_click_set_method(libinput_device,
+ ic->click_method);
}
if (ic->drag_lock != INT_MIN) {
- wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)",
+ wlr_log(L_DEBUG,
+ "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)",
ic->identifier, ic->click_method);
- libinput_device_config_tap_set_drag_lock_enabled(libinput_device, ic->drag_lock);
+ libinput_device_config_tap_set_drag_lock_enabled(libinput_device,
+ ic->drag_lock);
}
if (ic->dwt != INT_MIN) {
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
libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt);
}
if (ic->left_handed != INT_MIN) {
- wlr_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)",
+ wlr_log(L_DEBUG,
+ "libinput_config_pointer(%s) left_handed_set_enabled(%d)",
ic->identifier, ic->left_handed);
- libinput_device_config_left_handed_set(libinput_device, ic->left_handed);
+ libinput_device_config_left_handed_set(libinput_device,
+ ic->left_handed);
}
if (ic->middle_emulation != INT_MIN) {
- wlr_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)",
+ wlr_log(L_DEBUG,
+ "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)",
ic->identifier, ic->middle_emulation);
- libinput_device_config_middle_emulation_set_enabled(libinput_device, ic->middle_emulation);
+ libinput_device_config_middle_emulation_set_enabled(libinput_device,
+ ic->middle_emulation);
}
if (ic->natural_scroll != INT_MIN) {
- wlr_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)",
+ wlr_log(L_DEBUG,
+ "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)",
ic->identifier, ic->natural_scroll);
- libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, ic->natural_scroll);
+ libinput_device_config_scroll_set_natural_scroll_enabled(
+ libinput_device, ic->natural_scroll);
}
if (ic->pointer_accel != FLT_MIN) {
wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)",
ic->identifier, ic->pointer_accel);
- libinput_device_config_accel_set_speed(libinput_device, ic->pointer_accel);
+ libinput_device_config_accel_set_speed(libinput_device,
+ ic->pointer_accel);
}
if (ic->scroll_method != INT_MIN) {
wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)",
ic->identifier, ic->scroll_method);
- libinput_device_config_scroll_set_method(libinput_device, ic->scroll_method);
+ libinput_device_config_scroll_set_method(libinput_device,
+ ic->scroll_method);
}
if (ic->send_events != INT_MIN) {
wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)",
ic->identifier, ic->send_events);
- libinput_device_config_send_events_set_mode(libinput_device, ic->send_events);
+ libinput_device_config_send_events_set_mode(libinput_device,
+ ic->send_events);
}
if (ic->tap != INT_MIN) {
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) {
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input_manager->seats, link) {
- sway_seat_remove_device(seat, input_device);
+ seat_remove_device(seat, input_device);
}
wl_list_remove(&input_device->link);
wl_list_remove(&input_device->device_destroy.link);
- free_input_config(input_device->config);
free(input_device->identifier);
free(input_device);
}
@@ -203,44 +218,36 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
wlr_log(L_DEBUG, "adding device: '%s'",
input_device->identifier);
- // find config
- for (int i = 0; i < config->input_configs->length; ++i) {
- struct input_config *input_config = config->input_configs->items[i];
- if (strcmp(input_config->identifier, input_device->identifier) == 0) {
- free_input_config(input_device->config);
- input_device->config = copy_input_config(input_config);
- break;
- }
- }
-
if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) {
- sway_input_manager_libinput_config_pointer(input_device);
+ input_manager_libinput_config_pointer(input_device);
}
struct sway_seat *seat = NULL;
if (!input_has_seat_configuration(input)) {
wlr_log(L_DEBUG, "no seat configuration, using default seat");
seat = input_manager_get_seat(input, default_seat);
- sway_seat_add_device(seat, input_device);
+ seat_add_device(seat, input_device);
return;
}
bool added = false;
wl_list_for_each(seat, &input->seats, link) {
- bool has_attachment = seat->config &&
- (seat_config_get_attachment(seat->config, input_device->identifier) ||
- seat_config_get_attachment(seat->config, "*"));
+ struct seat_config *seat_config = seat_get_config(seat);
+ bool has_attachment = seat_config &&
+ (seat_config_get_attachment(seat_config, input_device->identifier) ||
+ seat_config_get_attachment(seat_config, "*"));
if (has_attachment) {
- sway_seat_add_device(seat, input_device);
+ seat_add_device(seat, input_device);
added = true;
}
}
if (!added) {
wl_list_for_each(seat, &input->seats, link) {
- if (seat->config && seat->config->fallback == 1) {
- sway_seat_add_device(seat, input_device);
+ struct seat_config *seat_config = seat_get_config(seat);
+ if (seat_config && seat_config->fallback == 1) {
+ seat_add_device(seat, input_device);
added = true;
}
}
@@ -256,7 +263,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
input_device->device_destroy.notify = handle_device_destroy;
}
-struct sway_input_manager *sway_input_manager_create(
+struct sway_input_manager *input_manager_create(
struct sway_server *server) {
struct sway_input_manager *input =
calloc(1, sizeof(struct sway_input_manager));
@@ -277,11 +284,11 @@ struct sway_input_manager *sway_input_manager_create(
return input;
}
-bool sway_input_manager_has_focus(struct sway_input_manager *input,
+bool input_manager_has_focus(struct sway_input_manager *input,
struct sway_container *container) {
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input->seats, link) {
- if (sway_seat_get_focus(seat) == container) {
+ if (seat_get_focus(seat) == container) {
return true;
}
}
@@ -289,35 +296,32 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input,
return false;
}
-void sway_input_manager_set_focus(struct sway_input_manager *input,
+void input_manager_set_focus(struct sway_input_manager *input,
struct sway_container *container) {
struct sway_seat *seat ;
wl_list_for_each(seat, &input->seats, link) {
- sway_seat_set_focus(seat, container);
+ seat_set_focus(seat, container);
}
}
-void sway_input_manager_apply_input_config(struct sway_input_manager *input,
+void input_manager_apply_input_config(struct sway_input_manager *input,
struct input_config *input_config) {
struct sway_input_device *input_device = NULL;
wl_list_for_each(input_device, &input->devices, link) {
if (strcmp(input_device->identifier, input_config->identifier) == 0) {
- free_input_config(input_device->config);
- input_device->config = copy_input_config(input_config);
-
if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) {
- sway_input_manager_libinput_config_pointer(input_device);
+ input_manager_libinput_config_pointer(input_device);
}
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input->seats, link) {
- sway_seat_configure_device(seat, input_device);
+ seat_configure_device(seat, input_device);
}
}
}
}
-void sway_input_manager_apply_seat_config(struct sway_input_manager *input,
+void input_manager_apply_seat_config(struct sway_input_manager *input,
struct seat_config *seat_config) {
wlr_log(L_DEBUG, "applying new seat config for seat %s",
seat_config->name);
@@ -326,7 +330,7 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input,
return;
}
- sway_seat_set_config(seat, seat_config);
+ seat_apply_config(seat, seat_config);
// for every device, try to add it to a seat and if no seat has it
// attached, add it to the fallback seats.
@@ -335,11 +339,12 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input,
list_t *seat_list = create_list();
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input->seats, link) {
- if (!seat->config) {
+ struct seat_config *seat_config = seat_get_config(seat);
+ if (!seat_config) {
continue;
}
- if (seat_config_get_attachment(seat->config, "*") ||
- seat_config_get_attachment(seat->config,
+ if (seat_config_get_attachment(seat_config, "*") ||
+ seat_config_get_attachment(seat_config,
input_device->identifier)) {
list_add(seat_list, seat);
}
@@ -355,17 +360,18 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input,
}
}
if (attached) {
- sway_seat_add_device(seat, input_device);
+ seat_add_device(seat, input_device);
} else {
- sway_seat_remove_device(seat, input_device);
+ seat_remove_device(seat, input_device);
}
}
} else {
wl_list_for_each(seat, &input->seats, link) {
- if (seat->config && seat->config->fallback == 1) {
- sway_seat_add_device(seat, input_device);
+ struct seat_config *seat_config = seat_get_config(seat);
+ if (seat_config && seat_config->fallback == 1) {
+ seat_add_device(seat, input_device);
} else {
- sway_seat_remove_device(seat, input_device);
+ seat_remove_device(seat, input_device);
}
}
}
@@ -373,14 +379,14 @@ void sway_input_manager_apply_seat_config(struct sway_input_manager *input,
}
}
-void sway_input_manager_configure_xcursor(struct sway_input_manager *input) {
+void input_manager_configure_xcursor(struct sway_input_manager *input) {
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input->seats, link) {
- sway_seat_configure_xcursor(seat);
+ seat_configure_xcursor(seat);
}
}
-struct sway_seat *sway_input_manager_get_default_seat(
+struct sway_seat *input_manager_get_default_seat(
struct sway_input_manager *input) {
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input->seats, link) {
@@ -390,3 +396,15 @@ struct sway_seat *sway_input_manager_get_default_seat(
}
return seat;
}
+
+struct input_config *input_device_get_config(struct sway_input_device *device) {
+ struct input_config *input_config = NULL;
+ for (int i = 0; i < config->input_configs->length; ++i) {
+ input_config = config->input_configs->items[i];
+ if (strcmp(input_config->identifier, device->identifier) == 0) {
+ return input_config;
+ }
+ }
+
+ return NULL;
+}
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) {
struct xkb_rule_names rules;
memset(&rules, 0, sizeof(rules));
struct input_config *input_config =
- keyboard->seat_device->input_device->config;
+ input_device_get_config(keyboard->seat_device->input_device);
struct wlr_input_device *wlr_device =
keyboard->seat_device->input_device->wlr_device;
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) {
free(seat_device);
}
-void sway_seat_destroy(struct sway_seat *seat) {
- // TODO destroy seat containers
+void seat_destroy(struct sway_seat *seat) {
struct sway_seat_device *seat_device, *next;
wl_list_for_each_safe(seat_device, next, &seat->devices, link) {
seat_device_destroy(seat_device);
@@ -90,7 +89,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
struct sway_seat *seat = seat_con->seat;
struct sway_container *con = seat_con->container;
struct sway_container *parent = con->parent;
- struct sway_container *focus = sway_seat_get_focus(seat);
+ struct sway_container *focus = seat_get_focus(seat);
bool set_focus =
focus != NULL &&
@@ -102,7 +101,7 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
if (set_focus) {
struct sway_container *next_focus = NULL;
while (next_focus == NULL) {
- next_focus = sway_seat_get_focus_by_type(seat, parent, C_VIEW);
+ next_focus = seat_get_focus_by_type(seat, parent, C_VIEW);
if (next_focus == NULL && parent->type == C_WORKSPACE) {
next_focus = parent;
@@ -114,10 +113,10 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
// the structure change might have caused it to move up to the top of
// the focus stack without sending focus notifications to the view
- if (sway_seat_get_focus(seat) == next_focus) {
+ if (seat_get_focus(seat) == next_focus) {
seat_send_focus(seat, next_focus);
} else {
- sway_seat_set_focus(seat, next_focus);
+ seat_set_focus(seat, next_focus);
}
}
}
@@ -171,7 +170,7 @@ static void collect_focus_iter(struct sway_container *con, void *data) {
wl_list_insert(&seat->focus_stack, &seat_con->link);
}
-struct sway_seat *sway_seat_create(struct sway_input_manager *input,
+struct sway_seat *seat_create(struct sway_input_manager *input,
const char *seat_name) {
struct sway_seat *seat = calloc(1, sizeof(struct sway_seat));
if (!seat) {
@@ -194,7 +193,8 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input,
// init the focus stack
wl_list_init(&seat->focus_stack);
- container_for_each_descendant_dfs(&root_container, collect_focus_iter, seat);
+ container_for_each_descendant_dfs(&root_container,
+ collect_focus_iter, seat);
wl_signal_add(&root_container.sway_root->events.new_container,
&seat->new_container);
@@ -208,7 +208,7 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input,
WL_SEAT_CAPABILITY_POINTER |
WL_SEAT_CAPABILITY_TOUCH);
- sway_seat_configure_xcursor(seat);
+ seat_configure_xcursor(seat);
wl_list_insert(&input->seats, &seat->link);
@@ -226,11 +226,12 @@ static void seat_configure_keyboard(struct sway_seat *seat,
if (!seat_device->keyboard) {
sway_keyboard_create(seat, seat_device);
}
- struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard;
+ struct wlr_keyboard *wlr_keyboard =
+ seat_device->input_device->wlr_device->keyboard;
sway_keyboard_configure(seat_device->keyboard);
wlr_seat_set_keyboard(seat->wlr_seat,
seat_device->input_device->wlr_device);
- struct sway_container *focus = sway_seat_get_focus(seat);
+ struct sway_container *focus = seat_get_focus(seat);
if (focus && focus->type == C_VIEW) {
// force notify reenter to pick up the new configuration
wlr_seat_keyboard_clear_focus(seat->wlr_seat);
@@ -240,7 +241,7 @@ static void seat_configure_keyboard(struct sway_seat *seat,
}
}
-static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat,
+static struct sway_seat_device *seat_get_device(struct sway_seat *seat,
struct sway_input_device *input_device) {
struct sway_seat_device *seat_device = NULL;
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,
return NULL;
}
-void sway_seat_configure_device(struct sway_seat *seat,
+void seat_configure_device(struct sway_seat *seat,
struct sway_input_device *input_device) {
struct sway_seat_device *seat_device =
- sway_seat_get_device(seat, input_device);
+ seat_get_device(seat, input_device);
if (!seat_device) {
return;
}
- if (seat->config) {
- seat_device->attachment_config =
- seat_config_get_attachment(seat->config, input_device->identifier);
- }
-
switch (input_device->wlr_device->type) {
case WLR_INPUT_DEVICE_POINTER:
seat_configure_pointer(seat, seat_device);
@@ -280,10 +276,10 @@ void sway_seat_configure_device(struct sway_seat *seat,
}
}
-void sway_seat_add_device(struct sway_seat *seat,
+void seat_add_device(struct sway_seat *seat,
struct sway_input_device *input_device) {
- if (sway_seat_get_device(seat, input_device)) {
- sway_seat_configure_device(seat, input_device);
+ if (seat_get_device(seat, input_device)) {
+ seat_configure_device(seat, input_device);
return;
}
@@ -301,13 +297,13 @@ void sway_seat_add_device(struct sway_seat *seat,
seat_device->input_device = input_device;
wl_list_insert(&seat->devices, &seat_device->link);
- sway_seat_configure_device(seat, input_device);
+ seat_configure_device(seat, input_device);
}
-void sway_seat_remove_device(struct sway_seat *seat,
+void seat_remove_device(struct sway_seat *seat,
struct sway_input_device *input_device) {
struct sway_seat_device *seat_device =
- sway_seat_get_device(seat, input_device);
+ seat_get_device(seat, input_device);
if (!seat_device) {
return;
@@ -319,7 +315,7 @@ void sway_seat_remove_device(struct sway_seat *seat,
seat_device_destroy(seat_device);
}
-void sway_seat_configure_xcursor(struct sway_seat *seat) {
+void seat_configure_xcursor(struct sway_seat *seat) {
// TODO configure theme and size
const char *cursor_theme = NULL;
@@ -334,7 +330,8 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) {
}
for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output_container = root_container.children->items[i];
+ struct sway_container *output_container =
+ root_container.children->items[i];
struct wlr_output *output =
output_container->sway_output->wlr_output;
bool result =
@@ -353,9 +350,9 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) {
seat->cursor->cursor->y);
}
-void sway_seat_set_focus_warp(struct sway_seat *seat,
+void seat_set_focus_warp(struct sway_seat *seat,
struct sway_container *container, bool warp) {
- struct sway_container *last_focus = sway_seat_get_focus(seat);
+ struct sway_container *last_focus = seat_get_focus(seat);
if (container && last_focus == container) {
return;
@@ -409,7 +406,7 @@ void sway_seat_set_focus_warp(struct sway_seat *seat,
}
if (last_focus && last_focus->type == C_VIEW &&
- !sway_input_manager_has_focus(seat->input, last_focus)) {
+ !input_manager_has_focus(seat->input, last_focus)) {
struct sway_view *view = last_focus->sway_view;
view_set_activated(view, false);
}
@@ -417,24 +414,24 @@ void sway_seat_set_focus_warp(struct sway_seat *seat,
seat->has_focus = (container != NULL);
}
-void sway_seat_set_focus(struct sway_seat *seat,
+void seat_set_focus(struct sway_seat *seat,
struct sway_container *container) {
- sway_seat_set_focus_warp(seat, container, true);
+ seat_set_focus_warp(seat, container, true);
}
-struct sway_container *sway_seat_get_focus_inactive(struct sway_seat *seat,
+struct sway_container *seat_get_focus_inactive(struct sway_seat *seat,
struct sway_container *container) {
- return sway_seat_get_focus_by_type(seat, container, C_TYPES);
+ return seat_get_focus_by_type(seat, container, C_TYPES);
}
struct sway_container *sway_seat_get_focus(struct sway_seat *seat) {
if (!seat->has_focus) {
return NULL;
}
- return sway_seat_get_focus_inactive(seat, &root_container);
+ return seat_get_focus_inactive(seat, &root_container);
}
-struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat,
+struct sway_container *seat_get_focus_by_type(struct sway_seat *seat,
struct sway_container *container, enum sway_container_type type) {
struct sway_seat_container *current = NULL;
struct sway_container *parent = NULL;
@@ -458,25 +455,34 @@ struct sway_container *sway_seat_get_focus_by_type(struct sway_seat *seat,
return NULL;
}
-void sway_seat_set_config(struct sway_seat *seat,
- struct seat_config *seat_config) {
- // clear configs
- free_seat_config(seat->config);
- seat->config = NULL;
+struct sway_container *seat_get_focus(struct sway_seat *seat) {
+ if (!seat->has_focus) {
+ return NULL;
+ }
+ return seat_get_focus_inactive(seat, &root_container);
+}
+void seat_apply_config(struct sway_seat *seat,
+ struct seat_config *seat_config) {
struct sway_seat_device *seat_device = NULL;
- wl_list_for_each(seat_device, &seat->devices, link) {
- seat_device->attachment_config = NULL;
- }
if (!seat_config) {
return;
}
- // add configs
- seat->config = copy_seat_config(seat_config);
-
wl_list_for_each(seat_device, &seat->devices, link) {
- sway_seat_configure_device(seat, seat_device->input_device);
+ seat_configure_device(seat, seat_device->input_device);
+ }
+}
+
+struct seat_config *seat_get_config(struct sway_seat *seat) {
+ struct seat_config *seat_config = NULL;
+ for (int i = 0; i < config->seat_configs->length; ++i ) {
+ seat_config = config->seat_configs->items[i];
+ if (strcmp(seat->wlr_seat->name, seat_config->name) == 0) {
+ return seat_config;
+ }
}
+
+ return NULL;
}
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
json_object_new_string(
ipc_json_get_output_transform(wlr_output->transform)));
- struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager);
+ struct sway_seat *seat = input_manager_get_default_seat(input_manager);
const char *ws = NULL;
if (seat) {
struct sway_container *focus =
- sway_seat_get_focus_inactive(seat, container);
+ seat_get_focus_inactive(seat, container);
if (focus && focus->type != C_WORKSPACE) {
focus = container_parent(focus, C_WORKSPACE);
}
@@ -139,8 +139,8 @@ json_object *ipc_json_describe_container(struct sway_container *c) {
return NULL;
}
- struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager);
- bool focused = sway_seat_get_focus(seat) == c;
+ struct sway_seat *seat = input_manager_get_default_seat(input_manager);
+ bool focused = seat_get_focus(seat) == c;
json_object *object = json_object_new_object();
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,
// override the default focused indicator because
// it's set differently for the get_workspaces reply
struct sway_seat *seat =
- sway_input_manager_get_default_seat(input_manager);
- struct sway_container *focused_ws = sway_seat_get_focus(seat);
+ input_manager_get_default_seat(input_manager);
+ struct sway_container *focused_ws = seat_get_focus(seat);
if (focused_ws != NULL && focused_ws->type != C_WORKSPACE) {
focused_ws = container_parent(focused_ws, C_WORKSPACE);
}
@@ -399,7 +399,7 @@ static void ipc_get_workspaces_callback(struct sway_container *workspace,
json_object_new_boolean(focused));
json_object_array_add((json_object *)data, workspace_json);
- focused_ws = sway_seat_get_focus_inactive(seat, workspace->parent);
+ focused_ws = seat_get_focus_inactive(seat, workspace->parent);
if (focused_ws->type != C_WORKSPACE) {
focused_ws = container_parent(focused_ws, C_WORKSPACE);
}
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) {
return false;
}
- input_manager = sway_input_manager_create(server);
+ input_manager = input_manager_create(server);
return true;
}
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) {
// container_remove_child, which removes child from this container
while (cont->children != NULL && cont->children->length != 0) {
struct sway_container *child = cont->children->items[0];
+ container_remove_child(child);
container_destroy(child);
- list_del(cont->children, 0);
}
}
if (cont->marks) {
@@ -172,7 +172,7 @@ struct sway_container *container_output_create(
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input_manager->seats, link) {
if (!seat->has_focus) {
- sway_seat_set_focus(seat, ws);
+ seat_set_focus(seat, ws);
}
}
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,
}
wl_signal_emit(&container->events.reparent, old_parent);
if (container->type == C_WORKSPACE) {
- struct sway_seat *seat = sway_input_manager_get_default_seat(
+ struct sway_seat *seat = input_manager_get_default_seat(
input_manager);
if (old_parent->children->length == 0) {
char *ws_name = workspace_next_name(old_parent->name);
struct sway_container *ws =
container_workspace_create(old_parent, ws_name);
free(ws_name);
- sway_seat_set_focus(seat, ws);
+ seat_set_focus(seat, ws);
}
container_sort_workspaces(new_parent);
- sway_seat_set_focus(seat, new_parent);
+ seat_set_focus(seat, new_parent);
}
if (old_parent) {
arrange_windows(old_parent, -1, -1);
@@ -275,8 +275,8 @@ void arrange_windows(struct sway_container *container,
struct wlr_box *area = &output->sway_output->usable_area;
wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
area->width, area->height, area->x, area->y);
- container->width = area->width;
- container->height = area->height;
+ container->width = width = area->width;
+ container->height = height = area->height;
container->x = x = area->x;
container->y = y = area->y;
wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
@@ -441,7 +441,7 @@ static struct sway_container *get_swayc_in_output_direction(
return NULL;
}
- struct sway_container *ws = sway_seat_get_focus_inactive(seat, output);
+ struct sway_container *ws = seat_get_focus_inactive(seat, output);
if (ws->type != C_WORKSPACE) {
ws = container_parent(ws, C_WORKSPACE);
}
@@ -462,7 +462,7 @@ static struct sway_container *get_swayc_in_output_direction(
case MOVE_UP:
case MOVE_DOWN: {
struct sway_container *focused =
- sway_seat_get_focus_inactive(seat, ws);
+ seat_get_focus_inactive(seat, ws);
if (focused && focused->parent) {
struct sway_container *parent = focused->parent;
if (parent->layout == L_VERT) {
@@ -546,7 +546,7 @@ struct sway_container *container_get_in_direction(
struct sway_container *container, struct sway_seat *seat,
enum movement_direction dir) {
if (dir == MOVE_CHILD) {
- return sway_seat_get_focus_inactive(seat, container);
+ return seat_get_focus_inactive(seat, container);
}
struct sway_container *parent = container->parent;
@@ -605,7 +605,7 @@ struct sway_container *container_get_in_direction(
}
if (next->children && next->children->length) {
// TODO consider floating children as well
- return sway_seat_get_focus_by_type(seat, next, C_VIEW);
+ return seat_get_focus_by_type(seat, next, C_VIEW);
} else {
return next;
}
@@ -635,7 +635,7 @@ struct sway_container *container_get_in_direction(
wrap_candidate = parent->children->items[0];
}
if (config->force_focus_wrapping) {
- return sway_seat_get_focus_by_type(seat,
+ return seat_get_focus_by_type(seat,
wrap_candidate, C_VIEW);
}
}
@@ -643,7 +643,7 @@ struct sway_container *container_get_in_direction(
wlr_log(L_DEBUG,
"cont %d-%p dir %i sibling %d: %p", idx,
container, dir, desired, parent->children->items[desired]);
- return sway_seat_get_focus_by_type(seat,
+ return seat_get_focus_by_type(seat,
parent->children->items[desired], C_VIEW);
}
}
@@ -702,9 +702,9 @@ struct sway_container *container_split(struct sway_container *child,
cont->y = child->y;
if (child->type == C_WORKSPACE) {
- struct sway_seat *seat = sway_input_manager_get_default_seat(input_manager);
+ struct sway_seat *seat = input_manager_get_default_seat(input_manager);
struct sway_container *workspace = child;
- bool set_focus = (sway_seat_get_focus(seat) == workspace);
+ bool set_focus = (seat_get_focus(seat) == workspace);
while (workspace->children->length) {
struct sway_container *ws_child = workspace->children->items[0];
@@ -716,7 +716,7 @@ struct sway_container *container_split(struct sway_container *child,
container_set_layout(workspace, layout);
if (set_focus) {
- sway_seat_set_focus(seat, cont);
+ seat_set_focus(seat, cont);
}
} else {
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) {
struct sway_container *workspace_by_name(const char *name) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *current_workspace = NULL, *current_output = NULL;
- struct sway_container *focus = sway_seat_get_focus(seat);
+ struct sway_container *focus = seat_get_focus(seat);
if (focus) {
current_workspace = container_parent(focus, C_WORKSPACE);
current_output = container_parent(focus, C_OUTPUT);
@@ -200,7 +200,7 @@ struct sway_container *workspace_create(const char *name) {
// Otherwise create a new one
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus =
- sway_seat_get_focus_inactive(seat, &root_container);
+ seat_get_focus_inactive(seat, &root_container);
parent = focus;
parent = container_parent(parent, C_OUTPUT);
struct sway_container *new_ws = container_workspace_create(parent, name);
@@ -260,7 +260,7 @@ struct sway_container *workspace_output_prev_next_impl(
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = sway_seat_get_focus_inactive(seat, output);
+ struct sway_container *focus = seat_get_focus_inactive(seat, output);
struct sway_container *workspace = (focus->type == C_WORKSPACE ?
focus :
container_parent(focus, C_WORKSPACE));
@@ -345,7 +345,7 @@ bool workspace_switch(struct sway_container *workspace) {
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus =
- sway_seat_get_focus_inactive(seat, &root_container);
+ seat_get_focus_inactive(seat, &root_container);
if (!seat || !focus) {
return false;
}
@@ -376,11 +376,11 @@ bool workspace_switch(struct sway_container *workspace) {
wlr_log(L_DEBUG, "Switching to workspace %p:%s",
workspace, workspace->name);
- struct sway_container *next = sway_seat_get_focus_inactive(seat, workspace);
+ struct sway_container *next = seat_get_focus_inactive(seat, workspace);
if (next == NULL) {
next = workspace;
}
- sway_seat_set_focus(seat, next);
+ seat_set_focus(seat, next);
struct sway_container *output = container_parent(workspace, C_OUTPUT);
arrange_windows(output, -1, -1);
return true;
@@ -389,7 +389,7 @@ bool workspace_switch(struct sway_container *workspace) {
bool workspace_is_visible(struct sway_container *ws) {
struct sway_container *output = container_parent(ws, C_OUTPUT);
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = sway_seat_get_focus_inactive(seat, output);
+ struct sway_container *focus = seat_get_focus_inactive(seat, output);
if (focus->type != C_WORKSPACE) {
focus = container_parent(focus, C_WORKSPACE);
}
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) {
static void ipc_in(int fd, short mask, void *_bar) {
struct swaybar *bar = (struct swaybar *)_bar;
- if (handle_ipc_event(bar)) {
+ if (handle_ipc_readable(bar)) {
render_all_frames(bar);
}
}
static void status_in(int fd, short mask, void *_bar) {
struct swaybar *bar = (struct swaybar *)_bar;
- if (handle_status_readable(bar->status)) {
+ if (status_handle_readable(bar->status)) {
render_all_frames(bar);
}
}
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 @@
+#define _POSIX_C_SOURCE 200809L
+#include <json-c/json.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wlr/util/log.h>
+#include "swaybar/config.h"
+#include "swaybar/status_line.h"
+
+static void i3bar_block_free(struct i3bar_block *block) {
+ if (!block) {
+ return;
+ }
+ wl_list_remove(&block->link);
+ free(block->full_text);
+ free(block->short_text);
+ free(block->align);
+ free(block->name);
+ free(block->instance);
+ free(block->color);
+}
+
+static bool i3bar_parse_json(struct status_line *status, const char *text) {
+ struct i3bar_block *block, *tmp;
+ wl_list_for_each_safe(block, tmp, &status->blocks, link) {
+ i3bar_block_free(block);
+ }
+ json_object *results = json_tokener_parse(text);
+ if (!results) {
+ status_error(status, "[failed to parse i3bar json]");
+ return false;
+ }
+ wlr_log(L_DEBUG, "Got i3bar json: '%s'", text);
+ for (size_t i = 0; i < json_object_array_length(results); ++i) {
+ json_object *full_text, *short_text, *color, *min_width, *align, *urgent;
+ json_object *name, *instance, *separator, *separator_block_width;
+ json_object *background, *border, *border_top, *border_bottom;
+ json_object *border_left, *border_right, *markup;
+ json_object *json = json_object_array_get_idx(results, i);
+ if (!json) {
+ continue;
+ }
+ json_object_object_get_ex(json, "full_text", &full_text);
+ json_object_object_get_ex(json, "short_text", &short_text);
+ json_object_object_get_ex(json, "color", &color);
+ json_object_object_get_ex(json, "min_width", &min_width);
+ json_object_object_get_ex(json, "align", &align);
+ json_object_object_get_ex(json, "urgent", &urgent);
+ json_object_object_get_ex(json, "name", &name);
+ json_object_object_get_ex(json, "instance", &instance);
+ json_object_object_get_ex(json, "markup", &markup);
+ json_object_object_get_ex(json, "separator", &separator);
+ json_object_object_get_ex(json, "separator_block_width", &separator_block_width);
+ json_object_object_get_ex(json, "background", &background);
+ json_object_object_get_ex(json, "border", &border);
+ json_object_object_get_ex(json, "border_top", &border_top);
+ json_object_object_get_ex(json, "border_bottom", &border_bottom);
+ json_object_object_get_ex(json, "border_left", &border_left);
+ json_object_object_get_ex(json, "border_right", &border_right);
+
+ struct i3bar_block *block = calloc(1, sizeof(struct i3bar_block));
+ block->full_text = full_text ?
+ strdup(json_object_get_string(full_text)) : NULL;
+ block->short_text = short_text ?
+ strdup(json_object_get_string(short_text)) : NULL;
+ if (color) {
+ block->color = malloc(sizeof(uint32_t));
+ *block->color = parse_color(json_object_get_string(color));
+ }
+ if (min_width) {
+ json_type type = json_object_get_type(min_width);
+ if (type == json_type_int) {
+ block->min_width = json_object_get_int(min_width);
+ } else if (type == json_type_string) {
+ /* the width will be calculated when rendering */
+ block->min_width = 0;
+ }
+ }
+ block->align = strdup(align ? json_object_get_string(align) : "left");
+ block->urgent = urgent ? json_object_get_int(urgent) : false;
+ block->name = name ? strdup(json_object_get_string(name)) : NULL;
+ block->instance = instance ?
+ strdup(json_object_get_string(instance)) : NULL;
+ if (markup) {
+ block->markup = false;
+ const char *markup_str = json_object_get_string(markup);
+ if (strcmp(markup_str, "pango") == 0) {
+ block->markup = true;
+ }
+ }
+ block->separator = separator ? json_object_get_int(separator) : true;
+ block->separator_block_width = separator_block_width ?
+ json_object_get_int(separator_block_width) : 9;
+ // Airblader features
+ block->background = background ?
+ parse_color(json_object_get_string(background)) : 0;
+ block->border = border ?
+ parse_color(json_object_get_string(border)) : 0;
+ block->border_top = border_top ? json_object_get_int(border_top) : 1;
+ block->border_bottom = border_bottom ?
+ json_object_get_int(border_bottom) : 1;
+ block->border_left = border_left ? json_object_get_int(border_left) : 1;
+ block->border_right = border_right ?
+ json_object_get_int(border_right) : 1;
+ wl_list_insert(&status->blocks, &block->link);
+ }
+ return true;
+}
+
+bool i3bar_handle_readable(struct status_line *status) {
+ struct i3bar_protocol_state *state = &status->i3bar_state;
+
+ char *cur = &state->buffer[state->buffer_index];
+ ssize_t n = read(status->read_fd, cur,
+ state->buffer_size - state->buffer_index);
+ if (n == 0) {
+ return 0;
+ }
+
+ if (n == (ssize_t)(state->buffer_size - state->buffer_index)) {
+ state->buffer_size = state->buffer_size * 2;
+ char *new_buffer = realloc(state->buffer, state->buffer_size);
+ if (!new_buffer) {
+ free(state->buffer);
+ status_error(status, "[failed to allocate buffer]");
+ return -1;
+ }
+ state->buffer = new_buffer;
+ }
+
+ bool redraw = false;
+ while (*cur) {
+ if (state->nodes[state->depth] == JSON_NODE_STRING) {
+ if (!state->escape && *cur == '"') {
+ --state->depth;
+ }
+ state->escape = !state->escape && *cur == '\\';
+ } else {
+ switch (*cur) {
+ case '[':
+ ++state->depth;
+ if (state->depth >
+ sizeof(state->nodes) / sizeof(state->nodes[0])) {
+ status_error(status, "[i3bar json too deep]");
+ return false;
+ }
+ state->nodes[state->depth] = JSON_NODE_ARRAY;
+ if (state->depth == 1) {
+ state->current_node = cur;
+ }
+ break;
+ case ']':
+ if (state->nodes[state->depth] != JSON_NODE_ARRAY) {
+ status_error(status, "[failed to parse i3bar json]");
+ return false;
+ }
+ --state->depth;
+ if (state->depth == 0) {
+ // cur[1] is valid since cur[0] != '\0'
+ char p = cur[1];
+ cur[1] = '\0';
+ redraw = i3bar_parse_json(
+ status, state->current_node) || redraw;
+ cur[1] = p;
+ memmove(state->buffer, cur,
+ state->buffer_size - (cur - state->buffer));
+ cur = state->buffer;
+ state->current_node = cur + 1;
+ }
+ break;
+ case '"':
+ ++state->depth;
+ if (state->depth >
+ sizeof(state->nodes) / sizeof(state->nodes[0])) {
+ status_error(status, "[i3bar json too deep]");
+ return false;
+ }
+ state->nodes[state->depth] = JSON_NODE_STRING;
+ break;
+ }
+ }
+ ++cur;
+ }
+ state->buffer_index = cur - state->buffer;
+ return redraw;
+}
+
+void i3bar_block_send_click(struct status_line *status,
+ struct i3bar_block *block, int x, int y, uint32_t button) {
+ wlr_log(L_DEBUG, "block %s clicked", block->name ? block->name : "(nil)");
+ if (!block->name || !status->i3bar_state.click_events) {
+ return;
+ }
+
+ struct json_object *event_json = json_object_new_object();
+ json_object_object_add(event_json, "name",
+ json_object_new_string(block->name));
+ if (block->instance) {
+ json_object_object_add(event_json, "instance",
+ json_object_new_string(block->instance));
+ }
+
+ json_object_object_add(event_json, "button", json_object_new_int(button));
+ json_object_object_add(event_json, "x", json_object_new_int(x));
+ json_object_object_add(event_json, "y", json_object_new_int(y));
+ dprintf(status->write_fd, "%s\n", json_object_to_json_string(event_json));
+ json_object_put(event_json);
+}
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) {
IPC_SUBSCRIBE, subscribe, &len));
}
-bool handle_ipc_event(struct swaybar *bar) {
+bool handle_ipc_readable(struct swaybar *bar) {
struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd);
if (!resp) {
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(
'bar.c',
'config.c',
'event_loop.c',
+ 'i3bar.c',
'ipc.c',
'main.c',
'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;
static const double ws_vertical_padding = 1.5;
static const double border_width = 1;
+static uint32_t render_status_line_error(cairo_t *cairo,
+ struct swaybar_config *config, const char *error,
+ double *x, uint32_t width, uint32_t height) {
+ if (!error) {
+ return 0;
+ }
+ cairo_set_source_u32(cairo, 0xFF0000FF);
+ static const int margin = 3;
+ int text_width, text_height;
+ get_text_size(cairo, config->font,
+ &text_width, &text_height, 1, false, "%s", error);
+ uint32_t ideal_height = text_height + ws_vertical_padding * 2;
+ if (height < ideal_height) {
+ return ideal_height;
+ }
+ *x -= text_width + margin;
+ double text_y = height / 2.0 - text_height / 2.0;
+ cairo_move_to(cairo, *x, (int)floor(text_y));
+ pango_printf(cairo, config->font, 1, false, "%s", error);
+ *x -= margin;
+ return ideal_height;
+}
+
static uint32_t render_status_line_text(cairo_t *cairo,
- struct swaybar_config *config, struct status_line *status,
- bool focused, uint32_t width, uint32_t height) {
- if (!status->text) {
+ struct swaybar_config *config, const char *text,
+ bool focused, double *x, uint32_t width, uint32_t height) {
+ if (!text) {
return 0;
}
cairo_set_source_u32(cairo, focused ?
@@ -29,38 +52,211 @@ static uint32_t render_status_line_text(cairo_t *cairo,
static const int margin = 3;
int text_width, text_height;
get_text_size(cairo, config->font, &text_width, &text_height,
- 1, config->pango_markup, "%s", status->text);
+ 1, config->pango_markup, "%s", text);
uint32_t ideal_height = text_height + ws_vertical_padding * 2;
if (height < ideal_height) {
return ideal_height;
}
+ *x -= text_width + margin;
double text_y = height / 2.0 - text_height / 2.0;
- cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y));
- pango_printf(cairo, config->font, 1, config->pango_markup,
- "%s", status->text);
+ cairo_move_to(cairo, *x, (int)floor(text_y));
+ pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text);
+ *x -= margin;
+ return ideal_height;
+}
+
+static void render_sharp_line(cairo_t *cairo, uint32_t color,
+ double x, double y, double width, double height) {
+ cairo_set_source_u32(cairo, color);
+ if (width > 1 && height > 1) {
+ cairo_rectangle(cairo, x, y, width, height);
+ cairo_fill(cairo);
+ } else {
+ if (width == 1) {
+ x += 0.5;
+ height += y;
+ width = x;
+ }
+ if (height == 1) {
+ y += 0.5;
+ width += x;
+ height = y;
+ }
+ cairo_move_to(cairo, x, y);
+ cairo_set_line_width(cairo, 1.0);
+ cairo_line_to(cairo, width, height);
+ cairo_stroke(cairo);
+ }
+}
+
+static void block_hotspot_callback(struct swaybar_output *output,
+ int x, int y, uint32_t button, void *data) {
+ struct i3bar_block *block = data;
+ struct status_line *status = output->bar->status;
+ i3bar_block_send_click(status, block, x, y, button);
+}
+
+static uint32_t render_status_block(cairo_t *cairo,
+ struct swaybar_config *config, struct swaybar_output *output,
+ struct i3bar_block *block, double *x,
+ uint32_t height, bool focused, bool edge) {
+ static const int margin = 3;
+ if (!block->full_text || !*block->full_text) {
+ return 0;
+ }
+
+ int text_width, text_height;
+ get_text_size(cairo, config->font, &text_width, &text_height,
+ 1, block->markup, "%s", block->full_text);
+ int width = text_width;
+ if (width < block->min_width) {
+ width = block->min_width;
+ }
+ double block_width = width;
+ uint32_t ideal_height = text_height + ws_vertical_padding * 2;
+ if (height < ideal_height) {
+ return ideal_height;
+ }
+
+ *x -= width;
+ if (block->border && block->border_left > 0) {
+ *x -= (block->border_left + margin);
+ block_width += block->border_left + margin;
+ }
+ if (block->border && block->border_right > 0) {
+ *x -= (block->border_right + margin);
+ block_width += block->border_right + margin;
+ }
+
+ int sep_width;
+ if (!edge) {
+ if (config->sep_symbol) {
+ int _height;
+ get_text_size(cairo, config->font, &sep_width, &_height,
+ 1, false, "%s", config->sep_symbol);
+ uint32_t _ideal_height = _height + ws_vertical_padding * 2;
+ if (height < _ideal_height) {
+ return _height;
+ }
+ if (sep_width > block->separator_block_width) {
+ block->separator_block_width = sep_width + margin * 2;
+ }
+ }
+ *x -= block->separator_block_width;
+ } else {
+ *x -= margin;
+ }
+
+ struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
+ hotspot->x = *x;
+ hotspot->y = 0;
+ hotspot->width = width;
+ hotspot->height = height;
+ hotspot->callback = block_hotspot_callback;
+ hotspot->destroy = NULL;
+ hotspot->data = block;
+ wl_list_insert(&output->hotspots, &hotspot->link);
+
+ double pos = *x;
+ if (block->background) {
+ cairo_set_source_u32(cairo, block->background);
+ cairo_rectangle(cairo, pos - 0.5, 1, block_width, height);
+ cairo_fill(cairo);
+ }
+
+ if (block->border && block->border_top > 0) {
+ render_sharp_line(cairo, block->border,
+ pos - 0.5, 1, block_width, block->border_top);
+ }
+ if (block->border && block->border_bottom > 0) {
+ render_sharp_line(cairo, block->border,
+ pos - 0.5, height - 1 - block->border_bottom,
+ block_width, block->border_bottom);
+ }
+ if (block->border != 0 && block->border_left > 0) {
+ render_sharp_line(cairo, block->border,
+ pos - 0.5, 1, block->border_left, height);
+ pos += block->border_left + margin;
+ }
+
+ double offset = 0;
+ if (strncmp(block->align, "left", 5) == 0) {
+ offset = pos;
+ } else if (strncmp(block->align, "right", 5) == 0) {
+ offset = pos + width - text_width;
+ } else if (strncmp(block->align, "center", 6) == 0) {
+ offset = pos + (width - text_width) / 2;
+ }
+ cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0);
+ uint32_t color = block->color ? *block->color : config->colors.statusline;
+ cairo_set_source_u32(cairo, color);
+ pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text);
+ pos += width;
+
+ if (block->border && block->border_right > 0) {
+ pos += margin;
+ render_sharp_line(cairo, block->border,
+ pos - 0.5, 1, block->border_right, height);
+ pos += block->border_right;
+ }
+
+ if (!edge && block->separator) {
+ if (focused) {
+ cairo_set_source_u32(cairo, config->colors.focused_separator);
+ } else {
+ cairo_set_source_u32(cairo, config->colors.separator);
+ }
+ if (config->sep_symbol) {
+ offset = pos + (block->separator_block_width - sep_width) / 2;
+ cairo_move_to(cairo, offset, margin);
+ pango_printf(cairo, config->font, 1, false,
+ "%s", config->sep_symbol);
+ } else {
+ cairo_set_line_width(cairo, 1);
+ cairo_move_to(cairo,
+ pos + block->separator_block_width / 2, margin);
+ cairo_line_to(cairo,
+ pos + block->separator_block_width / 2, height - margin);
+ cairo_stroke(cairo);
+ }
+ }
return ideal_height;
}
static uint32_t render_status_line_i3bar(cairo_t *cairo,
- struct swaybar_config *config, struct status_line *status,
- bool focused, uint32_t width, uint32_t height) {
- // TODO
- return 0;
+ struct swaybar_config *config, struct swaybar_output *output,
+ struct status_line *status, bool focused,
+ double *x, uint32_t width, uint32_t height) {
+ uint32_t max_height = 0;
+ bool edge = true;
+ struct i3bar_block *block;
+ wl_list_for_each(block, &status->blocks, link) {
+ uint32_t h = render_status_block(cairo, config, output,
+ block, x, height, focused, edge);
+ max_height = h > max_height ? h : max_height;
+ edge = false;
+ }
+ return max_height;
}
static uint32_t render_status_line(cairo_t *cairo,
- struct swaybar_config *config, struct status_line *status,
- bool focused, uint32_t width, uint32_t height) {
+ struct swaybar_config *config, struct swaybar_output *output,
+ struct status_line *status, bool focused,
+ double *x, uint32_t width, uint32_t height) {
switch (status->protocol) {
+ case PROTOCOL_ERROR:
+ return render_status_line_error(cairo,
+ config, status->text, x, width, height);
case PROTOCOL_TEXT:
return render_status_line_text(cairo,
- config, status, focused, width, height);
+ config, status->text, focused, x, width, height);
case PROTOCOL_I3BAR:
- return render_status_line_i3bar(cairo,
- config, status, focused, width, height);
- default:
+ return render_status_line_i3bar(cairo, config, output, status,
+ focused, x, width, height);
+ case PROTOCOL_UNDEF:
return 0;
}
+ return 0;
}
static uint32_t render_binding_mode_indicator(cairo_t *cairo,
@@ -166,8 +362,8 @@ static uint32_t render_workspace_button(cairo_t *cairo,
struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
hotspot->x = *x;
hotspot->y = 0;
- hotspot->height = height;
hotspot->width = width;
+ hotspot->height = height;
hotspot->callback = workspace_hotspot_callback;
hotspot->destroy = free;
hotspot->data = strdup(name);
@@ -180,6 +376,7 @@ static uint32_t render_workspace_button(cairo_t *cairo,
static uint32_t render_to_cairo(cairo_t *cairo,
struct swaybar *bar, struct swaybar_output *output) {
struct swaybar_config *config = bar->config;
+ wlr_log(L_DEBUG, "output %p", output);
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
if (output->focused) {
@@ -211,9 +408,10 @@ static uint32_t render_to_cairo(cairo_t *cairo,
cairo, config, config->mode, x, output->height);
max_height = h > max_height ? h : max_height;
}
+ x = output->width;
if (bar->status) {
- uint32_t h = render_status_line(cairo, config, bar->status,
- output->focused, output->width, output->height);
+ uint32_t h = render_status_line(cairo, config, output, bar->status,
+ output->focused, &x, output->width, output->height);
max_height = h > max_height ? h : max_height;
}
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 @@
#define _POSIX_C_SOURCE
#include <fcntl.h>
+#include <json-c/json.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -9,35 +10,79 @@
#include "swaybar/status_line.h"
#include "readline.h"
-bool handle_status_readable(struct status_line *status) {
- char *line = read_line_buffer(status->read,
- status->buffer, status->buffer_size);
+void status_error(struct status_line *status, const char *text) {
+ close(status->read_fd);
+ close(status->write_fd);
+ status->protocol = PROTOCOL_ERROR;
+ status->text = text;
+}
+
+bool status_handle_readable(struct status_line *status) {
+ char *line;
switch (status->protocol) {
+ case PROTOCOL_ERROR:
+ return false;
case PROTOCOL_I3BAR:
- // TODO
+ if (i3bar_handle_readable(status) > 0) {
+ return true;
+ }
break;
case PROTOCOL_TEXT:
- status->text = line;
+ line = read_line_buffer(status->read,
+ status->text_state.buffer, status->text_state.buffer_size);
+ if (!line) {
+ status_error(status, "[error reading from status command]");
+ } else {
+ status->text = line;
+ }
return true;
case PROTOCOL_UNDEF:
+ line = read_line_buffer(status->read,
+ status->text_state.buffer, status->text_state.buffer_size);
if (!line) {
+ status_error(status, "[error reading from status command]");
return false;
}
if (line[0] == '{') {
- // TODO: JSON
+ json_object *proto = json_tokener_parse(line);
+ if (proto) {
+ json_object *version;
+ if (json_object_object_get_ex(proto, "version", &version)
+ && json_object_get_int(version) == 1) {
+ wlr_log(L_DEBUG, "Switched to i3bar protocol.");
+ status->protocol = PROTOCOL_I3BAR;
+ }
+ json_object *click_events;
+ if (json_object_object_get_ex(
+ proto, "click_events", &click_events)
+ && json_object_get_boolean(click_events)) {
+ wlr_log(L_DEBUG, "Enabled click events.");
+ status->i3bar_state.click_events = true;
+ const char *events_array = "[\n";
+ write(status->write_fd, events_array, strlen(events_array));
+ }
+ json_object_put(proto);
+ }
+
+ status->protocol = PROTOCOL_I3BAR;
+ free(status->text_state.buffer);
+ wl_list_init(&status->blocks);
+ status->i3bar_state.buffer_size = 4096;
+ status->i3bar_state.buffer =
+ malloc(status->i3bar_state.buffer_size);
} else {
- status->text = line;
status->protocol = PROTOCOL_TEXT;
+ status->text = line;
}
- return false;
+ return true;
}
return false;
}
struct status_line *status_line_init(char *cmd) {
struct status_line *status = calloc(1, sizeof(struct status_line));
- status->buffer_size = 4096;
- status->buffer = malloc(status->buffer_size);
+ status->text_state.buffer_size = 8192;
+ status->text_state.buffer = malloc(status->text_state.buffer_size);
int pipe_read_fd[2];
int pipe_write_fd[2];