From 6d94f77457e34fc8a295e18a27e10fb39ee3b8a0 Mon Sep 17 00:00:00 2001 From: David Eklov Date: Sun, 10 Jul 2016 09:47:35 -0500 Subject: [PATCH 1/8] Revert "swaybg: Make swaybg a shell surface" This reverts commit 99bda4afe27d9e5723ab6b0ebe5eabb0caaa8eeb. It turned out that code to handle swaybg as shell surface was broken so we don't want to make swaybg a shell surface until this has been fixed. --- swaybg/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/swaybg/main.c b/swaybg/main.c index 4e0cc4b3..fbd0d16b 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -54,7 +54,6 @@ int main(int argc, const char **argv) { sway_abort("Failed to create surfaces."); } desktop_shell_set_background(registry->desktop_shell, output->output, window->surface); - window_make_shell(window); list_add(surfaces, window); #ifdef WITH_GDK_PIXBUF From 4bb45abc46def3f05f83561745349c121e6a8a2a Mon Sep 17 00:00:00 2001 From: David Eklov Date: Sun, 10 Jul 2016 11:03:39 -0500 Subject: [PATCH 2/8] Don't treat backgrounds as shell surfaces This code had some issues. Remove it now so that we can start clean and fix it later. --- include/extensions.h | 2 -- sway/extensions.c | 1 - sway/handlers.c | 13 +------------ 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/include/extensions.h b/include/extensions.h index 7c508b5e..2e2e4b07 100644 --- a/include/extensions.h +++ b/include/extensions.h @@ -11,8 +11,6 @@ struct background_config { wlc_resource surface; // we need the wl_resource of the surface in the destructor struct wl_resource *wl_surface_res; - // used to determine if client is a background - struct wl_client *client; }; struct panel_config { diff --git a/sway/extensions.c b/sway/extensions.c index 1fe15ac5..ab425fa7 100644 --- a/sway/extensions.c +++ b/sway/extensions.c @@ -73,7 +73,6 @@ static void set_background(struct wl_client *client, struct wl_resource *resourc } sway_log(L_DEBUG, "Setting surface %p as background for output %d", surface, (int)output); struct background_config *config = malloc(sizeof(struct background_config)); - config->client = client; config->output = output; config->surface = wlc_resource_from_wl_surface_resource(surface); config->wl_surface_res = surface; diff --git a/sway/handlers.c b/sway/handlers.c index 4336b6c7..c339fa5e 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -176,17 +176,6 @@ static void handle_output_focused(wlc_handle output, bool focus) { } } -static bool client_is_background(struct wl_client *client) { - int i; - for (i = 0; i < desktop_shell.backgrounds->length; i++) { - struct background_config *config = desktop_shell.backgrounds->items[i]; - if (config->client == client) { - return true; - } - } - return false; -} - static bool client_is_panel(struct wl_client *client) { int i; for (i = 0; i < desktop_shell.panels->length; i++) { @@ -229,7 +218,7 @@ static bool handle_view_created(wlc_handle handle) { struct wl_client *client = wlc_view_get_wl_client(handle); pid_t pid; - if (client_is_background(client) || client_is_panel(client)) { + if (client_is_panel(client)) { return true; } From 5c4f52f9537ad0e8e1f251392fea986871ab73b0 Mon Sep 17 00:00:00 2001 From: David Eklov Date: Wed, 6 Jul 2016 00:28:14 -0500 Subject: [PATCH 3/8] Set panels' geometries correctly and don't render them explicitly Panels were explicitly rendered by calling wlc_surface_render in handle_output_pre_render. Calling wlc_surface_render does not set the surface's geometry (like wlc_view_set_geometry does). Sway did not call wlc_view_set_geometry for panels, so wlc defaulted their geometry to be at the origin. This is not correct for bars unless their location is top. Furthermore, for a surface to receive pointer events, its mask has to be set to visible. This causes wlc to render these surfaces, causing panels and backgrounds to be rendered twice. This commit makes panels and surfaces visible, sets the correct geometries and removes the code that explicitly rendered them. --- include/extensions.h | 2 + sway/handlers.c | 113 ++++++++++++++++++++++++++++--------------- 2 files changed, 76 insertions(+), 39 deletions(-) diff --git a/include/extensions.h b/include/extensions.h index 2e2e4b07..d26e95c1 100644 --- a/include/extensions.h +++ b/include/extensions.h @@ -23,6 +23,8 @@ struct panel_config { enum desktop_shell_panel_position panel_position; // used to determine if client is a panel struct wl_client *client; + // wlc handle for this panel's surface, not set until panel is created + wlc_handle handle; }; struct desktop_shell_state { diff --git a/sway/handlers.c b/sway/handlers.c index c339fa5e..a7a87564 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -33,6 +33,66 @@ // Event handled by sway and should not be sent to client #define EVENT_HANDLED true +static struct panel_config *if_panel_find_config(struct wl_client *client) { + int i; + for (i = 0; i < desktop_shell.panels->length; i++) { + struct panel_config *config = desktop_shell.panels->items[i]; + if (config->client == client) { + return config; + } + } + return NULL; +} + +static struct wlc_geometry compute_panel_geometry(struct panel_config *config) { + const struct wlc_size resolution = *wlc_output_get_resolution(config->output); + const struct wlc_geometry *old = wlc_view_get_geometry(config->handle); + struct wlc_geometry new; + + switch (config->panel_position) { + case DESKTOP_SHELL_PANEL_POSITION_TOP: + new.origin.x = 0; + new.origin.y = 0; + new.size.w = resolution.w; + new.size.h = old->size.h; + break; + case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: + new.origin.x = 0; + new.origin.y = resolution.h - old->size.h; + new.size.w = resolution.w; + new.size.h = old->size.h; + break; + case DESKTOP_SHELL_PANEL_POSITION_LEFT: + new.origin.x = 0; + new.origin.y = 0; + new.size.w = old->size.w; + new.size.h = resolution.h; + break; + case DESKTOP_SHELL_PANEL_POSITION_RIGHT: + new.origin.x = resolution.w - old->size.w; + new.origin.y = 0; + new.size.w = old->size.w; + new.size.h = resolution.h; + break; + } + + return new; +} + +static void update_panel_geometry(struct panel_config *config) { + struct wlc_geometry geometry = compute_panel_geometry(config); + wlc_view_set_geometry(config->handle, 0, &geometry); +} + +static void update_panel_geometries(wlc_handle output) { + for (int i = 0; i < desktop_shell.panels->length; i++) { + struct panel_config *config = desktop_shell.panels->items[i]; + if (config->output == output) { + update_panel_geometry(config); + } + } +} + /* Handles */ static bool handle_input_created(struct libinput_device *device) { @@ -119,32 +179,6 @@ static void handle_output_pre_render(wlc_handle output) { break; } } - - for (i = 0; i < desktop_shell.panels->length; ++i) { - struct panel_config *config = desktop_shell.panels->items[i]; - if (config->output == output) { - struct wlc_size size = *wlc_surface_get_size(config->surface); - struct wlc_geometry geo = { - .size = size - }; - switch (config->panel_position) { - case DESKTOP_SHELL_PANEL_POSITION_TOP: - geo.origin = (struct wlc_point){ 0, 0 }; - break; - case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: - geo.origin = (struct wlc_point){ 0, resolution.h - size.h }; - break; - case DESKTOP_SHELL_PANEL_POSITION_LEFT: - geo.origin = (struct wlc_point){ 0, 0 }; - break; - case DESKTOP_SHELL_PANEL_POSITION_RIGHT: - geo.origin = (struct wlc_point){ resolution.w - size.w, 0 }; - break; - } - wlc_surface_render(config->surface, &geo); - break; - } - } } static void handle_output_post_render(wlc_handle output) { @@ -158,10 +192,16 @@ static void handle_view_pre_render(wlc_handle view) { static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); + swayc_t *c = swayc_by_handle(output); - if (!c) return; + if (!c) { + return; + } c->width = to->w; c->height = to->h; + + update_panel_geometries(output); + arrange_windows(&root_container, -1, -1); } @@ -176,17 +216,6 @@ static void handle_output_focused(wlc_handle output, bool focus) { } } -static bool client_is_panel(struct wl_client *client) { - int i; - for (i = 0; i < desktop_shell.panels->length; i++) { - struct panel_config *config = desktop_shell.panels->items[i]; - if (config->client == client) { - return true; - } - } - return false; -} - static void ws_cleanup() { swayc_t *op, *ws; int i = 0, j; @@ -217,8 +246,14 @@ static bool handle_view_created(wlc_handle handle) { bool return_to_workspace = false; struct wl_client *client = wlc_view_get_wl_client(handle); pid_t pid; + struct panel_config *panel_config = NULL; - if (client_is_panel(client)) { + panel_config = if_panel_find_config(client); + if (panel_config) { + panel_config->handle = handle; + update_panel_geometry(panel_config); + wlc_view_set_mask(handle, VISIBLE); + wlc_view_set_output(handle, panel_config->output); return true; } From 103954dd2b7bc54140f19ceda2508f17b1cf5427 Mon Sep 17 00:00:00 2001 From: David Eklov Date: Sun, 10 Jul 2016 22:23:47 -0500 Subject: [PATCH 4/8] Setup to receive mouse click events and log them --- swaybar/bar.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/swaybar/bar.c b/swaybar/bar.c index 6d858f92..ed18b5e6 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -58,6 +58,10 @@ struct output *new_output(const char *name) { return output; } +static void mouse_button_notify(struct window *window, wl_fixed_t x, wl_fixed_t y, uint32_t button) { + sway_log(L_DEBUG, "Mouse button %d clicked at %d %d\n", button, x, y); +} + void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { /* initialize bar with default values */ bar_init(bar); @@ -92,6 +96,9 @@ void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { /* set font */ bar_output->window->font = bar->config->font; + /* set font */ + bar_output->window->pointer_input.notify = mouse_button_notify; + /* set window height */ set_window_height(bar_output->window, bar->config->height); } From c805e42635f3935ccf0ce927143433b94c78a3e7 Mon Sep 17 00:00:00 2001 From: David Eklov Date: Sun, 10 Jul 2016 22:47:10 -0500 Subject: [PATCH 5/8] Extract workspace size computation from render_workspace_button() Also remove some unnecessary strtup()s and rename a few variables and functions. --- include/bar/bar.h | 3 +++ include/bar/render.h | 5 +++++ swaybar/render.c | 34 +++++++++++++++++++--------------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/include/bar/bar.h b/include/bar/bar.h index c20efc55..a3c511d9 100644 --- a/include/bar/bar.h +++ b/include/bar/bar.h @@ -32,6 +32,9 @@ struct workspace { bool urgent; }; +/** Global bar state */ +extern struct bar swaybar; + /** * Setup bar. */ diff --git a/include/bar/render.h b/include/bar/render.h index 931a1cdd..114f43f4 100644 --- a/include/bar/render.h +++ b/include/bar/render.h @@ -14,4 +14,9 @@ void render(struct output *output, struct config *config, struct status_line *li */ void set_window_height(struct window *window, int height); +/** + * Compute the size of a workspace name + */ +void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height); + #endif /* _SWAYBAR_RENDER_H */ diff --git a/swaybar/render.c b/swaybar/render.c index 273bd4f0..cea36f52 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -172,7 +172,7 @@ static void render_block(struct window *window, struct config *config, struct st } -static char *handle_workspace_number(bool strip_num, const char *ws_name) { +static const char *strip_workspace_name(bool strip_num, const char *ws_name) { bool strip = false; int i; @@ -190,18 +190,23 @@ static char *handle_workspace_number(bool strip_num, const char *ws_name) { } if (strip) { - return strdup(ws_name + i); + return ws_name + i; } - return strdup(ws_name); + return ws_name; +} + +void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height) { + const char *stripped_name = strip_workspace_name(swaybar.config->strip_workspace_numbers, workspace_name); + + get_text_size(window->cairo, window->font, width, height, false, "%s", stripped_name); + *width += 2 * ws_horizontal_padding; + *height += 2 * ws_vertical_padding; } static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) { - // strip workspace numbers if required - char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name); + const char *stripped_name = strip_workspace_name(config->strip_workspace_numbers, ws->name); - int width, height; - get_text_size(window->cairo, window->font, &width, &height, false, "%s", name); struct box_colors box_colors; if (ws->urgent) { box_colors = config->colors.urgent_workspace; @@ -213,26 +218,25 @@ static void render_workspace_button(struct window *window, struct config *config box_colors = config->colors.inactive_workspace; } + int width, height; + workspace_button_size(window, stripped_name, &width, &height); + // background cairo_set_source_u32(window->cairo, box_colors.background); - cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); + cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); cairo_fill(window->cairo); // border cairo_set_source_u32(window->cairo, box_colors.border); - cairo_rectangle(window->cairo, *x, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); + cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); cairo_stroke(window->cairo); // text cairo_set_source_u32(window->cairo, box_colors.text); cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin); - pango_printf(window->cairo, window->font, false, "%s", name); + pango_printf(window->cairo, window->font, false, "%s", stripped_name); - *x += width + ws_horizontal_padding * 2 + ws_spacing; - - free(name); + *x += width + ws_spacing; } static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) { From 679c7b397c4e9dfdc69d6c67c523494dfe987f60 Mon Sep 17 00:00:00 2001 From: David Eklov Date: Mon, 11 Jul 2016 00:03:15 -0500 Subject: [PATCH 6/8] Use int instead of wl_fixed_t for mouse coordinates --- include/client/window.h | 6 +++--- wayland/window.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/client/window.h b/include/client/window.h index 7be4fff3..55a12225 100644 --- a/include/client/window.h +++ b/include/client/window.h @@ -28,10 +28,10 @@ struct cursor { }; struct pointer_input { - wl_fixed_t last_x; - wl_fixed_t last_y; + int last_x; + int last_y; - void (*notify)(struct window *window, wl_fixed_t x, wl_fixed_t y, uint32_t button); + void (*notify)(struct window *window, int x, int y, uint32_t button); }; struct window { diff --git a/wayland/window.c b/wayland/window.c index e055e244..9b6e5b00 100644 --- a/wayland/window.c +++ b/wayland/window.c @@ -32,8 +32,8 @@ static void pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { struct window *window = data; - window->pointer_input.last_x = sx_w; - window->pointer_input.last_y = sy_w; + window->pointer_input.last_x = wl_fixed_to_int(sx_w); + window->pointer_input.last_y = wl_fixed_to_int(sy_w); } static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, From a0c8799c8008da4eccde3ae4bd5865b5c4422058 Mon Sep 17 00:00:00 2001 From: David Eklov Date: Mon, 11 Jul 2016 00:11:38 -0500 Subject: [PATCH 7/8] Compute what workspace button is clicked This commit does not do anything with this information other than logging it. --- include/bar/ipc.h | 6 ++++++ swaybar/bar.c | 29 ++++++++++++++++++++++++++++- swaybar/ipc.c | 4 ++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/include/bar/ipc.h b/include/bar/ipc.h index 741c067b..c11931d0 100644 --- a/include/bar/ipc.h +++ b/include/bar/ipc.h @@ -13,5 +13,11 @@ void ipc_bar_init(struct bar *bar, const char *bar_id); */ bool handle_ipc_event(struct bar *bar); + +/** + * Send workspace command to sway + */ +void ipc_send_workspace_command(const char *workspace_name); + #endif /* _SWAYBAR_IPC_H */ diff --git a/swaybar/bar.c b/swaybar/bar.c index ed18b5e6..4f8063ac 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -58,8 +58,35 @@ struct output *new_output(const char *name) { return output; } -static void mouse_button_notify(struct window *window, wl_fixed_t x, wl_fixed_t y, uint32_t button) { +static void mouse_button_notify(struct window *window, int x, int y, uint32_t button) { sway_log(L_DEBUG, "Mouse button %d clicked at %d %d\n", button, x, y); + + struct output *clicked_output = NULL; + for (int i = 0; i < swaybar.outputs->length; i++) { + struct output *output = swaybar.outputs->items[i]; + if (window == output->window) { + clicked_output = output; + break; + } + } + + if (!sway_assert(clicked_output != NULL, "Got pointer event for non-existing output")) { + return; + } + + double button_x = 0.5; + for (int i = 0; i < clicked_output->workspaces->length; i++) { + struct workspace *workspace = clicked_output->workspaces->items[i]; + int button_width, button_height; + + workspace_button_size(window, workspace->name, &button_width, &button_height); + + button_x += button_width; + if (x <= button_x) { + ipc_send_workspace_command(workspace->name); + break; + } + } } void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index dacee4c2..6697742e 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -7,6 +7,10 @@ #include "bar/config.h" #include "bar/ipc.h" +void ipc_send_workspace_command(const char *workspace_name) { + sway_log(L_DEBUG, "Clicked on window %s", workspace_name); +} + static void ipc_parse_config(struct config *config, const char *payload) { json_object *bar_config = json_tokener_parse(payload); json_object *tray_output, *mode, *hidden_bar, *position, *status_command; From 8a232c8cfd60c1469ceaaa911f31a6d75e8ad851 Mon Sep 17 00:00:00 2001 From: David Eklov Date: Mon, 11 Jul 2016 00:50:23 -0500 Subject: [PATCH 8/8] Send command to sway to change workspace when workspace button is clicked --- swaybar/ipc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 6697742e..15f40508 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -8,7 +8,12 @@ #include "bar/ipc.h" void ipc_send_workspace_command(const char *workspace_name) { - sway_log(L_DEBUG, "Clicked on window %s", workspace_name); + uint32_t size = strlen("workspace ") + strlen(workspace_name) + 1; + + char command[size]; + sprintf(command, "workspace %s", workspace_name); + + ipc_single_command(swaybar.ipc_socketfd, IPC_COMMAND, command, &size); } static void ipc_parse_config(struct config *config, const char *payload) {