aboutsummaryrefslogtreecommitdiff
path: root/swaylock
diff options
context:
space:
mode:
Diffstat (limited to 'swaylock')
-rw-r--r--swaylock/main.c56
-rw-r--r--swaylock/password.c102
-rw-r--r--swaylock/render.c4
3 files changed, 105 insertions, 57 deletions
diff --git a/swaylock/main.c b/swaylock/main.c
index f89f2849..591df7b4 100644
--- a/swaylock/main.c
+++ b/swaylock/main.c
@@ -131,14 +131,58 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
.closed = layer_surface_closed,
};
-static void handle_wl_output_geometry(void *data, struct wl_output *output, int32_t x,
- int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel,
- const char *make, const char *model, int32_t transform) {
+static const struct wl_callback_listener surface_frame_listener;
+
+static void surface_frame_handle_done(void *data, struct wl_callback *callback,
+ uint32_t time) {
+ struct swaylock_surface *surface = data;
+
+ wl_callback_destroy(callback);
+ surface->frame_pending = false;
+
+ if (surface->dirty) {
+ // Schedule a frame in case the surface is damaged again
+ struct wl_callback *callback = wl_surface_frame(surface->surface);
+ wl_callback_add_listener(callback, &surface_frame_listener, surface);
+ surface->frame_pending = true;
+
+ render_frame(surface);
+ surface->dirty = false;
+ }
+}
+
+static const struct wl_callback_listener surface_frame_listener = {
+ .done = surface_frame_handle_done,
+};
+
+void damage_surface(struct swaylock_surface *surface) {
+ surface->dirty = true;
+ if (surface->frame_pending) {
+ return;
+ }
+
+ struct wl_callback *callback = wl_surface_frame(surface->surface);
+ wl_callback_add_listener(callback, &surface_frame_listener, surface);
+ surface->frame_pending = true;
+ wl_surface_commit(surface->surface);
+}
+
+void damage_state(struct swaylock_state *state) {
+ struct swaylock_surface *surface;
+ wl_list_for_each(surface, &state->surfaces, link) {
+ damage_surface(surface);
+ }
+}
+
+static void handle_wl_output_geometry(void *data, struct wl_output *output,
+ int32_t x, int32_t y, int32_t width_mm, int32_t height_mm,
+ int32_t subpixel, const char *make, const char *model,
+ int32_t transform) {
// Who cares
}
-static void handle_wl_output_mode(void *data, struct wl_output *output, uint32_t flags,
- int32_t width, int32_t height, int32_t refresh) {
+static void handle_wl_output_mode(void *data, struct wl_output *output,
+ uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
// Who cares
}
@@ -151,7 +195,7 @@ static void handle_wl_output_scale(void *data, struct wl_output *output,
struct swaylock_surface *surface = data;
surface->scale = factor;
if (surface->state->run_display) {
- render_frames(surface->state);
+ damage_surface(surface);
}
}
diff --git a/swaylock/password.c b/swaylock/password.c
index 1ad5cd81..6d493309 100644
--- a/swaylock/password.c
+++ b/swaylock/password.c
@@ -93,58 +93,58 @@ static void append_ch(struct swaylock_password *pw, uint32_t codepoint) {
void swaylock_handle_key(struct swaylock_state *state,
xkb_keysym_t keysym, uint32_t codepoint) {
switch (keysym) {
- case XKB_KEY_KP_Enter: /* fallthrough */
- case XKB_KEY_Return:
- state->auth_state = AUTH_STATE_VALIDATING;
- render_frames(state);
- wl_display_roundtrip(state->display);
- if (attempt_password(&state->password)) {
- state->run_display = false;
- break;
- }
- state->auth_state = AUTH_STATE_INVALID;
- render_frames(state);
+ case XKB_KEY_KP_Enter: /* fallthrough */
+ case XKB_KEY_Return:
+ state->auth_state = AUTH_STATE_VALIDATING;
+ damage_state(state);
+ wl_display_roundtrip(state->display);
+ if (attempt_password(&state->password)) {
+ state->run_display = false;
break;
- case XKB_KEY_Delete:
- case XKB_KEY_BackSpace:
- if (backspace(&state->password)) {
- state->auth_state = AUTH_STATE_BACKSPACE;
- } 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_INVALID;
+ damage_state(state);
+ break;
+ case XKB_KEY_Delete:
+ case XKB_KEY_BackSpace:
+ if (backspace(&state->password)) {
+ state->auth_state = AUTH_STATE_BACKSPACE;
+ } else {
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) {
- append_ch(&state->password, codepoint);
- state->auth_state = AUTH_STATE_INPUT;
- render_frames(state);
- }
- break;
+ }
+ damage_state(state);
+ break;
+ case XKB_KEY_Escape:
+ clear_password_buffer(&state->password);
+ state->auth_state = AUTH_STATE_CLEAR;
+ damage_state(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;
+ damage_state(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;
+ damage_state(state);
+ break;
+ default:
+ if (codepoint) {
+ append_ch(&state->password, codepoint);
+ state->auth_state = AUTH_STATE_INPUT;
+ damage_state(state);
+ }
+ break;
}
}
diff --git a/swaylock/render.c b/swaylock/render.c
index 05236dea..2032ddcf 100644
--- a/swaylock/render.c
+++ b/swaylock/render.c
@@ -23,6 +23,10 @@ void render_frame(struct swaylock_surface *surface) {
surface->current_buffer = get_next_buffer(state->shm,
surface->buffers, buffer_width, buffer_height);
+ if (surface->current_buffer == NULL) {
+ return;
+ }
+
cairo_t *cairo = surface->current_buffer->cairo;
cairo_identity_matrix(cairo);