diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 0037190b..af478f33 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -79,4 +79,6 @@ void bar_setup(struct swaybar *bar, void bar_run(struct swaybar *bar); void bar_teardown(struct swaybar *bar); +void free_workspaces(struct wl_list *list); + #endif diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 7f321df8..6739c28a 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -29,7 +29,7 @@ struct swaybar_config { bool binding_mode_indicator; bool wrap_scroll; bool workspace_buttons; - struct wl_list outputs; + struct wl_list outputs; // config_output::link bool all_outputs; int height; diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 3538f49c..bf12a842 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -73,5 +73,6 @@ void status_line_free(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); +void i3bar_block_free(struct i3bar_block *block); #endif diff --git a/include/swaylock/seat.h b/include/swaylock/seat.h index 44bc37d5..180ea7a0 100644 --- a/include/swaylock/seat.h +++ b/include/swaylock/seat.h @@ -27,6 +27,7 @@ enum mask { struct swaylock_xkb { uint32_t modifiers; + bool caps_lock; struct xkb_state *state; struct xkb_context *context; struct xkb_keymap *keymap; diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index ed9fea19..07b908d7 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -11,7 +11,9 @@ enum auth_state { AUTH_STATE_IDLE, + AUTH_STATE_CLEAR, AUTH_STATE_INPUT, + AUTH_STATE_INPUT_NOP, AUTH_STATE_BACKSPACE, AUTH_STATE_VALIDATING, AUTH_STATE_INVALID, diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index cad9156d..63d9c66e 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -266,10 +266,13 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface_configure_event *ev = data; struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - // TODO: floating windows are allowed to move around like this, but make - // sure tiling windows always stay in place. - wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, - ev->width, ev->height); + if (!xsurface->mapped) { + wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, + ev->width, ev->height); + return; + } + // TODO: Let floating views do whatever + configure(view, view->swayc->x, view->swayc->y, view->width, view->height); } static void handle_request_fullscreen(struct wl_listener *listener, void *data) { diff --git a/sway/input/seat.c b/sway/input/seat.c index d1fc62c4..e88bcfd1 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -476,10 +476,11 @@ void seat_set_focus_warp(struct sway_seat *seat, // find new output's old workspace, which might have to be removed if empty struct sway_container *new_output_last_ws = NULL; if (last_output && new_output && last_output != new_output) { - new_output_last_ws = seat_get_focus_by_type(seat, new_output, C_WORKSPACE); + new_output_last_ws = + seat_get_focus_by_type(seat, new_output, C_WORKSPACE); } - if (container) { + if (container && container->parent) { struct sway_seat_container *seat_con = seat_container_from_container(seat, container); if (seat_con == NULL) { @@ -488,8 +489,7 @@ void seat_set_focus_warp(struct sway_seat *seat, // put all the anscestors of this container on top of the focus stack struct sway_seat_container *parent = - seat_container_from_container(seat, - seat_con->container->parent); + seat_container_from_container(seat, container->parent); while (parent) { wl_list_remove(&parent->link); wl_list_insert(&seat->focus_stack, &parent->link); @@ -516,24 +516,24 @@ void seat_set_focus_warp(struct sway_seat *seat, // clean up unfocused empty workspace on new output if (new_output_last_ws) { if (!workspace_is_visible(new_output_last_ws) - && new_output_last_ws->children->length == 0) { + && new_output_last_ws->children->length == 0) { + if (last_workspace == new_output_last_ws) { + last_focus = NULL; + last_workspace = NULL; + } container_destroy(new_output_last_ws); } } if (last_focus) { - struct sway_container *last_ws = last_focus; - if (last_ws && last_ws->type != C_WORKSPACE) { - last_ws = container_parent(last_ws, C_WORKSPACE); - } - if (last_ws) { - ipc_event_workspace(last_ws, container, "focus"); - if (!workspace_is_visible(last_ws) - && last_ws->children->length == 0) { - if (last_ws == last_focus) { + if (last_workspace) { + ipc_event_workspace(last_workspace, container, "focus"); + if (!workspace_is_visible(last_workspace) + && last_workspace->children->length == 0) { + if (last_workspace == last_focus) { last_focus = NULL; } - container_destroy(last_ws); + container_destroy(last_workspace); } } diff --git a/swaybar/bar.c b/swaybar/bar.c index d407db4f..5b8028e5 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -25,7 +25,6 @@ #include "ipc-client.h" #include "list.h" #include "log.h" -#include "pango.h" #include "pool-buffer.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -34,6 +33,15 @@ static void bar_init(struct swaybar *bar) { wl_list_init(&bar->outputs); } +void free_workspaces(struct wl_list *list) { + struct swaybar_workspace *ws, *tmp; + wl_list_for_each_safe(ws, tmp, list, link) { + wl_list_remove(&ws->link); + free(ws->name); + free(ws); + } +} + static void swaybar_output_free(struct swaybar_output *output) { if (!output) { return; @@ -44,12 +52,7 @@ static void swaybar_output_free(struct swaybar_output *output) { wl_output_destroy(output->output); destroy_buffer(&output->buffers[0]); destroy_buffer(&output->buffers[1]); - struct swaybar_workspace *ws, *ws_tmp; - wl_list_for_each_safe(ws, ws_tmp, &output->workspaces, link) { - wl_list_remove(&ws->link); - free(ws->name); - free(ws); - } + free_workspaces(&output->workspaces); struct swaybar_hotspot *hotspot, *hotspot_tmp; wl_list_for_each_safe(hotspot, hotspot_tmp, &output->hotspots, link) { if (hotspot->destroy) { @@ -162,9 +165,11 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, return; } + // last doesn't actually need initialization, + // but gcc (7.3.1) is too dumb to figure it out struct swaybar_workspace *first = NULL; struct swaybar_workspace *active = NULL; - struct swaybar_workspace *last; + struct swaybar_workspace *last = NULL; struct swaybar_workspace *iter; wl_list_for_each(iter, &output->workspaces, link) { @@ -466,9 +471,7 @@ void bar_run(struct swaybar *bar) { static void free_outputs(struct wl_list *list) { struct swaybar_output *output, *tmp; wl_list_for_each_safe(output, tmp, list, link) { - wl_list_remove(&output->link); - free(output->name); - free(output); + swaybar_output_free(output); } } diff --git a/swaybar/config.c b/swaybar/config.c index 9169ad27..db7b0db6 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -74,5 +74,11 @@ void free_config(struct swaybar_config *config) { free(config->font); free(config->mode); free(config->sep_symbol); + struct config_output *coutput, *tmp; + wl_list_for_each_safe(coutput, tmp, &config->outputs, link) { + wl_list_remove(&coutput->link); + free(coutput->name); + free(coutput); + } free(config); } diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index dced13d2..141612a6 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -7,7 +7,7 @@ #include "swaybar/config.h" #include "swaybar/status_line.h" -static void i3bar_block_free(struct i3bar_block *block) { +void i3bar_block_free(struct i3bar_block *block) { if (!block) { return; } @@ -18,6 +18,7 @@ static void i3bar_block_free(struct i3bar_block *block) { free(block->name); free(block->instance); free(block->color); + free(block); } static bool i3bar_parse_json(struct status_line *status, const char *text) { diff --git a/swaybar/ipc.c b/swaybar/ipc.c index ed5d9a31..959fa095 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -216,15 +216,6 @@ static void ipc_parse_config( json_object_put(bar_config); } -static void free_workspaces(struct wl_list *list) { - struct swaybar_workspace *ws, *tmp; - wl_list_for_each_safe(ws, tmp, list, link) { - wl_list_remove(&ws->link); - free(ws->name); - free(ws); - } -} - void ipc_get_workspaces(struct swaybar *bar) { bar->focused_output = NULL; struct swaybar_output *output; @@ -290,8 +281,8 @@ static void ipc_get_outputs(struct swaybar *bar) { continue; } if (bar->config->all_outputs) { - struct config_output *coutput = calloc( - 1, sizeof(struct config_output)); + struct config_output *coutput = + calloc(1, sizeof(struct config_output)); coutput->name = strdup(name); coutput->index = i; wl_list_insert(&bar->config->outputs, &coutput->link); diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 8d781ca3..e0e7414a 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 199309L +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -126,5 +126,17 @@ void status_line_free(struct status_line *status) { close(status->read_fd); close(status->write_fd); kill(status->pid, SIGTERM); + switch (status->protocol) { + case PROTOCOL_I3BAR:; + struct i3bar_block *block, *tmp; + wl_list_for_each_safe(block, tmp, &status->blocks, link) { + i3bar_block_free(block); + } + free(status->i3bar_state.buffer); + break; + default: + free(status->text_state.buffer); + break; + } free(status); } diff --git a/swaylock/password.c b/swaylock/password.c index c8df3de8..1ad5cd81 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -105,11 +105,39 @@ void swaylock_handle_key(struct swaylock_state *state, state->auth_state = AUTH_STATE_INVALID; render_frames(state); break; + case XKB_KEY_Delete: case XKB_KEY_BackSpace: if (backspace(&state->password)) { state->auth_state = AUTH_STATE_BACKSPACE; - render_frames(state); + } else { + state->auth_state = AUTH_STATE_CLEAR; } + render_frames(state); + break; + case XKB_KEY_Escape: + clear_password_buffer(&state->password); + state->auth_state = AUTH_STATE_CLEAR; + render_frames(state); + break; + case XKB_KEY_Caps_Lock: + /* The state is getting active after this + * so we need to manually toggle it */ + state->xkb.caps_lock = !state->xkb.caps_lock; + state->auth_state = AUTH_STATE_INPUT_NOP; + render_frames(state); + break; + case XKB_KEY_Shift_L: + case XKB_KEY_Shift_R: + case XKB_KEY_Control_L: + case XKB_KEY_Control_R: + case XKB_KEY_Meta_L: + case XKB_KEY_Meta_R: + case XKB_KEY_Alt_L: + case XKB_KEY_Alt_R: + case XKB_KEY_Super_L: + case XKB_KEY_Super_R: + state->auth_state = AUTH_STATE_INPUT_NOP; + render_frames(state); break; default: if (codepoint) { diff --git a/swaylock/render.c b/swaylock/render.c index cd387be5..7d9d25a5 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -43,6 +43,7 @@ void render_frame(struct swaylock_surface *surface) { cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, 0, 2 * M_PI); switch (state->auth_state) { case AUTH_STATE_INPUT: + case AUTH_STATE_INPUT_NOP: case AUTH_STATE_BACKSPACE: { cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); cairo_fill_preserve(cairo); @@ -61,6 +62,12 @@ void render_frame(struct swaylock_surface *surface) { cairo_set_source_rgb(cairo, 125.0 / 255, 51.0 / 255, 0); cairo_stroke(cairo); } break; + case AUTH_STATE_CLEAR: { + cairo_set_source_rgba(cairo, 229.0/255, 164.0/255, 69.0/255, 0.75); + cairo_fill_preserve(cairo); + cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255); + cairo_stroke(cairo); + } break; default: break; } @@ -77,6 +84,15 @@ void render_frame(struct swaylock_surface *surface) { case AUTH_STATE_INVALID: text = "wrong"; break; + case AUTH_STATE_CLEAR: + text = "cleared"; + break; + case AUTH_STATE_INPUT: + case AUTH_STATE_INPUT_NOP: + if (state->xkb.caps_lock) { + text = "Caps Lock"; + cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255); + } default: break; } diff --git a/swaylock/seat.c b/swaylock/seat.c index 21db7c4f..a81899a6 100644 --- a/swaylock/seat.c +++ b/swaylock/seat.c @@ -88,6 +88,7 @@ static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, xkb_mod_mask_t mask = xkb_state_serialize_mods(state->xkb.state, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); state->xkb.modifiers = 0; + state->xkb.caps_lock = xkb_state_mod_name_is_active(state->xkb.state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED); for (uint32_t i = 0; i < MASK_LAST; ++i) { if (mask & state->xkb.masks[i]) { state->xkb.modifiers |= XKB_MODS[i];