diff --git a/include/sway/extensions.h b/include/sway/extensions.h index f6b0c00e..e1fbbb9f 100644 --- a/include/sway/extensions.h +++ b/include/sway/extensions.h @@ -27,6 +27,9 @@ struct panel_config { struct wl_client *client; // wlc handle for this panel's surface, not set until panel is created wlc_handle handle; + + enum desktop_shell_hide_modes hide_mode; + enum desktop_shell_hide_state hide; }; struct desktop_shell_state { diff --git a/protocols/desktop-shell.xml b/protocols/desktop-shell.xml index 581f0c5d..1b2f8b30 100644 --- a/protocols/desktop-shell.xml +++ b/protocols/desktop-shell.xml @@ -116,6 +116,32 @@ + + + + + + + + + + + + + + Tell the shell whether or not panel is in hide mode + i.e. whether to allocate a fixed amount of space + for the panel (hide mode false) or not (hide mode true) + + + + + + + Tell the shell whether or not panel is currently hidden + + + diff --git a/sway/extensions.c b/sway/extensions.c index 96957dbf..89afb848 100644 --- a/sway/extensions.c +++ b/sway/extensions.c @@ -133,6 +133,34 @@ static void set_panel(struct wl_client *client, struct wl_resource *resource, wlc_output_schedule_render(config->output); } +static void set_panel_hide_mode(struct wl_client *client, struct wl_resource *resource, + uint32_t mode) { + struct panel_config *config = find_or_create_panel_config(resource); + config->hide_mode = mode; + if (mode == 0) { + wlc_view_set_mask(wlc_handle_from_wl_surface_resource(config->wl_surface_res), false); + } else { + wlc_view_set_mask(wlc_handle_from_wl_surface_resource(config->wl_surface_res), true); + } + arrange_windows(&root_container, -1, -1); + wlc_output_schedule_render(config->output); +} + +static void set_panel_hide(struct wl_client *client, struct wl_resource *resource, + uint32_t hide) { + sway_log(L_ERROR, "Attempting to find panel %p", resource); + struct panel_config *config = find_or_create_panel_config(resource); + config->hide = hide; + if (hide == 0) { + sway_log(L_ERROR, "Hiding panel %p", resource); + wlc_view_set_mask(wlc_handle_from_wl_surface_resource(config->wl_surface_res), false); + } else if (hide == 1) { + sway_log(L_ERROR, "Showing panel %p", resource); + wlc_view_set_mask(wlc_handle_from_wl_surface_resource(config->wl_surface_res), true); + } + wlc_output_schedule_render(config->output); +} + static void desktop_set_lock_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface) { sway_log(L_ERROR, "desktop_set_lock_surface is not currently supported"); } @@ -169,7 +197,9 @@ static struct desktop_shell_interface desktop_shell_implementation = { .unlock = desktop_unlock, .set_grab_surface = set_grab_surface, .desktop_ready = desktop_ready, - .set_panel_position = set_panel_position + .set_panel_position = set_panel_position, + .set_panel_hide_mode = set_panel_hide_mode, + .set_panel_hide = set_panel_hide }; static void desktop_shell_bind(struct wl_client *client, void *data, diff --git a/sway/layout.c b/sway/layout.c index 69291daf..f61402af 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -1006,19 +1006,21 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { if (config->output == output->handle) { struct wlc_size size = *wlc_surface_get_size(config->surface); sway_log(L_DEBUG, "-> Found panel for this workspace: %ux%u, position: %u", size.w, size.h, config->panel_position); - switch (config->panel_position) { - case DESKTOP_SHELL_PANEL_POSITION_TOP: - y += size.h; height -= size.h; - break; - case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: - height -= size.h; - break; - case DESKTOP_SHELL_PANEL_POSITION_LEFT: - x += size.w; width -= size.w; - break; - case DESKTOP_SHELL_PANEL_POSITION_RIGHT: - width -= size.w; - break; + if (config->hide_mode == DESKTOP_SHELL_HIDE_MODES_SHOW) { + switch (config->panel_position) { + case DESKTOP_SHELL_PANEL_POSITION_TOP: + y += size.h; height -= size.h; + break; + case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: + height -= size.h; + break; + case DESKTOP_SHELL_PANEL_POSITION_LEFT: + x += size.w; width -= size.w; + break; + case DESKTOP_SHELL_PANEL_POSITION_RIGHT: + width -= size.w; + break; + } } } } diff --git a/swaybar/bar.c b/swaybar/bar.c index abde1cc9..98572ffa 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -163,6 +163,15 @@ void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { output->output, bar_output->window->surface); desktop_shell_set_panel_position(bar_output->registry->desktop_shell, bar->config->position); + switch (bar->config->display_mode) { + case MODE_HIDE: + case MODE_INVISIBLE: + desktop_shell_set_panel_hide_mode(bar_output->registry->desktop_shell, DESKTOP_SHELL_HIDE_MODES_HIDE); + break; + case MODE_DOCK: + desktop_shell_set_panel_hide_mode(bar_output->registry->desktop_shell, DESKTOP_SHELL_HIDE_MODES_SHOW); + break; + } window_make_shell(bar_output->window); diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 2a1fe219..34a9abe9 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -383,27 +383,42 @@ bool handle_ipc_event(struct bar *bar) { break; } case IPC_EVENT_MODIFIER: { - json_object *result = json_tokener_parse(resp->payload); - if (!result) { - free_ipc_response(resp); - sway_log(L_ERROR, "failed to parse payload as json"); - return false; - } - json_object *json_change; - if (json_object_object_get_ex(result, "change", &json_change)) { - const char *change = json_object_get_string(json_change); - if (strcmp(change, "pressed") == 0) { - bar->config->hidden_state = BAR_SHOW; - } else { //must be "released" - bar->config->hidden_state = BAR_HIDDEN; + if (bar->config->display_mode == MODE_HIDE) { + json_object *result = json_tokener_parse(resp->payload); + if (!result) { + free_ipc_response(resp); + sway_log(L_ERROR, "failed to parse payload as json"); + return false; } - - } else { - sway_log(L_ERROR, "failed to parse response"); + json_object *json_change; + if (json_object_object_get_ex(result, "change", &json_change)) { + const char *change = json_object_get_string(json_change); + if (strcmp(change, "pressed") == 0) { + bar->config->hidden_state = BAR_SHOW; + sway_log(L_ERROR, "Showing bar on %d outputs", bar->outputs->length); + int i; + for (i = 0; i < bar->outputs->length; ++i) { + struct output *bar_output = bar->outputs->items[i]; + sway_log(L_ERROR, "showing bar on input %d, with registry %p", i, bar_output->registry); + desktop_shell_set_panel_hide(bar_output->registry->desktop_shell, DESKTOP_SHELL_HIDE_STATE_SHOW); + } + } else { //must be "released" + bar->config->hidden_state = BAR_HIDDEN; + sway_log(L_ERROR, "Hiding bar"); + int i; + for (i = 0; i < bar->outputs->length; ++i) { + struct output *bar_output = bar->outputs->items[i]; + desktop_shell_set_panel_hide(bar_output->registry->desktop_shell, DESKTOP_SHELL_HIDE_STATE_HIDE); + } + } + + } else { + sway_log(L_ERROR, "failed to parse response"); + } + + json_object_put(result); + break; } - - json_object_put(result); - break; } default: free_ipc_response(resp); diff --git a/swaybar/render.c b/swaybar/render.c index a46826b2..2b53aa45 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -286,67 +286,58 @@ void render(struct output *output, struct config *config, struct status_line *li cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); cairo_restore(cairo); - // Could also be done by always rendering then conditionally clearing and drawing alpha - // That may be preferable down the line - if (!(config->display_mode == MODE_HIDE) || config->hidden_state == BAR_SHOW) { + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - - // Background - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_background); - } else { - cairo_set_source_u32(cairo, config->colors.background); - } - cairo_paint(cairo); - - // Command output - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_statusline); - } else { - cairo_set_source_u32(cairo, config->colors.statusline); - } - - int width, height; - - if (line->protocol == TEXT) { - get_text_size(window->cairo, window->font, &width, &height, - window->scale, config->pango_markup, "%s", line->text_line); - cairo_move_to(cairo, (window->width * window->scale) - - margin - width, margin); - pango_printf(window->cairo, window->font, window->scale, - config->pango_markup, "%s", line->text_line); - } else if (line->protocol == I3BAR && line->block_line) { - double pos = (window->width * window->scale) - 0.5; - bool edge = true; - for (i = line->block_line->length - 1; i >= 0; --i) { - struct status_block *block = line->block_line->items[i]; - if (block->full_text && block->full_text[0]) { - render_block(window, config, block, &pos, edge, is_focused); - edge = false; - } - } - } - - cairo_set_line_width(cairo, 1.0); - double x = 0.5; - - // Workspaces - if (config->workspace_buttons) { - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - render_workspace_button(window, config, ws, &x); - } - } - - // binding mode indicator - if (config->mode && config->binding_mode_indicator) { - render_binding_mode_indicator(window, config, x); - } + // Background + if (is_focused) { + cairo_set_source_u32(cairo, config->colors.focused_background); } else { - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - cairo_set_source_u32(cairo, 0x00000000); - cairo_paint(cairo); + cairo_set_source_u32(cairo, config->colors.background); + } + cairo_paint(cairo); + + // Command output + if (is_focused) { + cairo_set_source_u32(cairo, config->colors.focused_statusline); + } else { + cairo_set_source_u32(cairo, config->colors.statusline); + } + + int width, height; + + if (line->protocol == TEXT) { + get_text_size(window->cairo, window->font, &width, &height, + window->scale, config->pango_markup, "%s", line->text_line); + cairo_move_to(cairo, (window->width * window->scale) + - margin - width, margin); + pango_printf(window->cairo, window->font, window->scale, + config->pango_markup, "%s", line->text_line); + } else if (line->protocol == I3BAR && line->block_line) { + double pos = (window->width * window->scale) - 0.5; + bool edge = true; + for (i = line->block_line->length - 1; i >= 0; --i) { + struct status_block *block = line->block_line->items[i]; + if (block->full_text && block->full_text[0]) { + render_block(window, config, block, &pos, edge, is_focused); + edge = false; + } + } + } + + cairo_set_line_width(cairo, 1.0); + double x = 0.5; + + // Workspaces + if (config->workspace_buttons) { + for (i = 0; i < output->workspaces->length; ++i) { + struct workspace *ws = output->workspaces->items[i]; + render_workspace_button(window, config, ws, &x); + } + } + + // binding mode indicator + if (config->mode && config->binding_mode_indicator) { + render_binding_mode_indicator(window, config, x); } }