summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <RyanDwyer@users.noreply.github.com>2018-05-28 00:14:22 +1000
committerLibravatar GitHub <noreply@github.com>2018-05-28 00:14:22 +1000
commit8fda41dab52656c7c4a0db9a835ae57cea994538 (patch)
tree2b0c481616cd738e0f6ca92be9594eec7707799b
parentImplement swap command (diff)
parentMerge pull request #2043 from emersion/pool-buffer-fixes (diff)
downloadsway-8fda41dab52656c7c4a0db9a835ae57cea994538.tar.gz
sway-8fda41dab52656c7c4a0db9a835ae57cea994538.tar.zst
sway-8fda41dab52656c7c4a0db9a835ae57cea994538.zip
Merge branch 'master' into cmd-swap
-rw-r--r--client/pool-buffer.c46
-rw-r--r--include/pool-buffer.h2
-rw-r--r--include/sway/criteria.h1
-rw-r--r--include/sway/tree/view.h2
-rw-r--r--include/swaylock/swaylock.h3
-rw-r--r--sway/criteria.c18
-rw-r--r--sway/desktop/xdg_shell.c12
-rw-r--r--sway/sway.5.scd5
-rw-r--r--sway/tree/view.c10
-rw-r--r--swaylock/main.c56
-rw-r--r--swaylock/password.c102
-rw-r--r--swaylock/render.c4
12 files changed, 185 insertions, 76 deletions
diff --git a/client/pool-buffer.c b/client/pool-buffer.c
index 1f54a77c..52438303 100644
--- a/client/pool-buffer.c
+++ b/client/pool-buffer.c
@@ -1,37 +1,56 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 500
2#include <assert.h> 2#include <assert.h>
3#include <cairo/cairo.h> 3#include <cairo/cairo.h>
4#include <fcntl.h>
5#include <pango/pangocairo.h>
4#include <stdio.h> 6#include <stdio.h>
5#include <stdlib.h> 7#include <stdlib.h>
6#include <string.h> 8#include <string.h>
7#include <sys/mman.h> 9#include <sys/mman.h>
8#include <pango/pangocairo.h>
9#include <unistd.h> 10#include <unistd.h>
10#include <wayland-client.h> 11#include <wayland-client.h>
11#include "config.h" 12#include "config.h"
12#include "pool-buffer.h" 13#include "pool-buffer.h"
13 14
15static bool set_cloexec(int fd) {
16 long flags = fcntl(fd, F_GETFD);
17 if (flags == -1) {
18 return false;
19 }
20
21 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
22 return false;
23 }
24
25 return true;
26}
27
14static int create_pool_file(size_t size, char **name) { 28static int create_pool_file(size_t size, char **name) {
15 static const char template[] = "sway-client-XXXXXX"; 29 static const char template[] = "sway-client-XXXXXX";
16 const char *path = getenv("XDG_RUNTIME_DIR"); 30 const char *path = getenv("XDG_RUNTIME_DIR");
17 if (!path) { 31 if (path == NULL) {
32 fprintf(stderr, "XDG_RUNTIME_DIR is not set\n");
18 return -1; 33 return -1;
19 } 34 }
20 35
21 int ts = (path[strlen(path) - 1] == '/'); 36 size_t name_size = strlen(template) + 1 + strlen(path) + 1;
22 37 *name = malloc(name_size);
23 *name = malloc( 38 if (*name == NULL) {
24 strlen(template) + 39 fprintf(stderr, "allocation failed\n");
25 strlen(path) + 40 return -1;
26 (ts ? 0 : 1) + 1); 41 }
27 sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); 42 snprintf(*name, name_size, "%s/%s", path, template);
28 43
29 int fd = mkstemp(*name); 44 int fd = mkstemp(*name);
30
31 if (fd < 0) { 45 if (fd < 0) {
32 return -1; 46 return -1;
33 } 47 }
34 48
49 if (!set_cloexec(fd)) {
50 close(fd);
51 return -1;
52 }
53
35 if (ftruncate(fd, size) < 0) { 54 if (ftruncate(fd, size) < 0) {
36 close(fd); 55 close(fd);
37 return -1; 56 return -1;
@@ -53,7 +72,7 @@ static struct pool_buffer *create_buffer(struct wl_shm *shm,
53 struct pool_buffer *buf, int32_t width, int32_t height, 72 struct pool_buffer *buf, int32_t width, int32_t height,
54 uint32_t format) { 73 uint32_t format) {
55 uint32_t stride = width * 4; 74 uint32_t stride = width * 4;
56 uint32_t size = stride * height; 75 size_t size = stride * height;
57 76
58 char *name; 77 char *name;
59 int fd = create_pool_file(size, &name); 78 int fd = create_pool_file(size, &name);
@@ -68,8 +87,10 @@ static struct pool_buffer *create_buffer(struct wl_shm *shm,
68 free(name); 87 free(name);
69 fd = -1; 88 fd = -1;
70 89
90 buf->size = size;
71 buf->width = width; 91 buf->width = width;
72 buf->height = height; 92 buf->height = height;
93 buf->data = data;
73 buf->surface = cairo_image_surface_create_for_data(data, 94 buf->surface = cairo_image_surface_create_for_data(data,
74 CAIRO_FORMAT_ARGB32, width, height, stride); 95 CAIRO_FORMAT_ARGB32, width, height, stride);
75 buf->cairo = cairo_create(buf->surface); 96 buf->cairo = cairo_create(buf->surface);
@@ -92,6 +113,9 @@ void destroy_buffer(struct pool_buffer *buffer) {
92 if (buffer->pango) { 113 if (buffer->pango) {
93 g_object_unref(buffer->pango); 114 g_object_unref(buffer->pango);
94 } 115 }
116 if (buffer->data) {
117 munmap(buffer->data, buffer->size);
118 }
95 memset(buffer, 0, sizeof(struct pool_buffer)); 119 memset(buffer, 0, sizeof(struct pool_buffer));
96} 120}
97 121
diff --git a/include/pool-buffer.h b/include/pool-buffer.h
index 856f7c8c..54f5be06 100644
--- a/include/pool-buffer.h
+++ b/include/pool-buffer.h
@@ -12,6 +12,8 @@ struct pool_buffer {
12 cairo_t *cairo; 12 cairo_t *cairo;
13 PangoContext *pango; 13 PangoContext *pango;
14 uint32_t width, height; 14 uint32_t width, height;
15 void *data;
16 size_t size;
15 bool busy; 17 bool busy;
16}; 18};
17 19
diff --git a/include/sway/criteria.h b/include/sway/criteria.h
index 74da132c..bd3ca0ac 100644
--- a/include/sway/criteria.h
+++ b/include/sway/criteria.h
@@ -18,6 +18,7 @@ struct criteria {
18 char *target; // workspace or output name for `assign` criteria 18 char *target; // workspace or output name for `assign` criteria
19 19
20 pcre *title; 20 pcre *title;
21 pcre *shell;
21 pcre *app_id; 22 pcre *app_id;
22 pcre *class; 23 pcre *class;
23 pcre *instance; 24 pcre *instance;
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 0fb8f1b3..a8bf4955 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -201,7 +201,7 @@ const char *view_get_window_role(struct sway_view *view);
201 201
202uint32_t view_get_window_type(struct sway_view *view); 202uint32_t view_get_window_type(struct sway_view *view);
203 203
204const char *view_get_type(struct sway_view *view); 204const char *view_get_shell(struct sway_view *view);
205 205
206void view_configure(struct sway_view *view, double ox, double oy, int width, 206void view_configure(struct sway_view *view, double ox, double oy, int width,
207 int height); 207 int height);
diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h
index dae823b8..2931fd61 100644
--- a/include/swaylock/swaylock.h
+++ b/include/swaylock/swaylock.h
@@ -56,6 +56,7 @@ struct swaylock_surface {
56 struct zwlr_layer_surface_v1 *layer_surface; 56 struct zwlr_layer_surface_v1 *layer_surface;
57 struct pool_buffer buffers[2]; 57 struct pool_buffer buffers[2];
58 struct pool_buffer *current_buffer; 58 struct pool_buffer *current_buffer;
59 bool frame_pending, dirty;
59 uint32_t width, height; 60 uint32_t width, height;
60 int32_t scale; 61 int32_t scale;
61 char *output_name; 62 char *output_name;
@@ -74,5 +75,7 @@ void swaylock_handle_key(struct swaylock_state *state,
74 xkb_keysym_t keysym, uint32_t codepoint); 75 xkb_keysym_t keysym, uint32_t codepoint);
75void render_frame(struct swaylock_surface *surface); 76void render_frame(struct swaylock_surface *surface);
76void render_frames(struct swaylock_state *state); 77void render_frames(struct swaylock_state *state);
78void damage_surface(struct swaylock_surface *surface);
79void damage_state(struct swaylock_state *state);
77 80
78#endif 81#endif
diff --git a/sway/criteria.c b/sway/criteria.c
index 4295cacc..dec5fed7 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -13,6 +13,7 @@
13 13
14bool criteria_is_empty(struct criteria *criteria) { 14bool criteria_is_empty(struct criteria *criteria) {
15 return !criteria->title 15 return !criteria->title
16 && !criteria->shell
16 && !criteria->app_id 17 && !criteria->app_id
17 && !criteria->class 18 && !criteria->class
18 && !criteria->instance 19 && !criteria->instance
@@ -29,6 +30,7 @@ bool criteria_is_empty(struct criteria *criteria) {
29 30
30void criteria_destroy(struct criteria *criteria) { 31void criteria_destroy(struct criteria *criteria) {
31 pcre_free(criteria->title); 32 pcre_free(criteria->title);
33 pcre_free(criteria->shell);
32 pcre_free(criteria->app_id); 34 pcre_free(criteria->app_id);
33 pcre_free(criteria->class); 35 pcre_free(criteria->class);
34 pcre_free(criteria->instance); 36 pcre_free(criteria->instance);
@@ -53,6 +55,13 @@ static bool criteria_matches_view(struct criteria *criteria,
53 } 55 }
54 } 56 }
55 57
58 if (criteria->shell) {
59 const char *shell = view_get_shell(view);
60 if (!shell || regex_cmp(shell, criteria->shell) != 0) {
61 return false;
62 }
63 }
64
56 if (criteria->app_id) { 65 if (criteria->app_id) {
57 const char *app_id = view_get_app_id(view); 66 const char *app_id = view_get_app_id(view);
58 if (!app_id || regex_cmp(app_id, criteria->app_id) != 0) { 67 if (!app_id || regex_cmp(app_id, criteria->app_id) != 0) {
@@ -206,6 +215,7 @@ enum criteria_token {
206 T_FLOATING, 215 T_FLOATING,
207 T_ID, 216 T_ID,
208 T_INSTANCE, 217 T_INSTANCE,
218 T_SHELL,
209 T_TILING, 219 T_TILING,
210 T_TITLE, 220 T_TITLE,
211 T_URGENT, 221 T_URGENT,
@@ -229,6 +239,8 @@ static enum criteria_token token_from_name(char *name) {
229 return T_ID; 239 return T_ID;
230 } else if (strcmp(name, "instance") == 0) { 240 } else if (strcmp(name, "instance") == 0) {
231 return T_INSTANCE; 241 return T_INSTANCE;
242 } else if (strcmp(name, "shell") == 0) {
243 return T_SHELL;
232 } else if (strcmp(name, "title") == 0) { 244 } else if (strcmp(name, "title") == 0) {
233 return T_TITLE; 245 return T_TITLE;
234 } else if (strcmp(name, "urgent") == 0) { 246 } else if (strcmp(name, "urgent") == 0) {
@@ -271,6 +283,9 @@ static char *get_focused_prop(enum criteria_token token) {
271 case T_INSTANCE: 283 case T_INSTANCE:
272 value = view_get_instance(view); 284 value = view_get_instance(view);
273 break; 285 break;
286 case T_SHELL:
287 value = view_get_shell(view);
288 break;
274 case T_TITLE: 289 case T_TITLE:
275 value = view_get_class(view); 290 value = view_get_class(view);
276 break; 291 break;
@@ -332,6 +347,9 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
332 case T_TITLE: 347 case T_TITLE:
333 generate_regex(&criteria->title, effective_value); 348 generate_regex(&criteria->title, effective_value);
334 break; 349 break;
350 case T_SHELL:
351 generate_regex(&criteria->shell, effective_value);
352 break;
335 case T_APP_ID: 353 case T_APP_ID:
336 generate_regex(&criteria->app_id, effective_value); 354 generate_regex(&criteria->app_id, effective_value);
337 break; 355 break;
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 9a0d282b..b2b95fa0 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -3,13 +3,14 @@
3#include <stdlib.h> 3#include <stdlib.h>
4#include <wayland-server.h> 4#include <wayland-server.h>
5#include <wlr/types/wlr_xdg_shell.h> 5#include <wlr/types/wlr_xdg_shell.h>
6#include <wlr/util/edges.h>
7#include "log.h"
8#include "sway/input/input-manager.h"
9#include "sway/input/seat.h"
10#include "sway/server.h"
6#include "sway/tree/container.h" 11#include "sway/tree/container.h"
7#include "sway/tree/layout.h" 12#include "sway/tree/layout.h"
8#include "sway/server.h"
9#include "sway/tree/view.h" 13#include "sway/tree/view.h"
10#include "sway/input/seat.h"
11#include "sway/input/input-manager.h"
12#include "log.h"
13 14
14static const struct sway_view_child_impl popup_impl; 15static const struct sway_view_child_impl popup_impl;
15 16
@@ -248,7 +249,8 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
248 wlr_log(L_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", 249 wlr_log(L_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'",
249 xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); 250 xdg_surface->toplevel->title, xdg_surface->toplevel->app_id);
250 wlr_xdg_surface_ping(xdg_surface); 251 wlr_xdg_surface_ping(xdg_surface);
251 wlr_xdg_toplevel_set_maximized(xdg_surface, true); 252 wlr_xdg_toplevel_set_tiled(xdg_surface, WLR_EDGE_LEFT | WLR_EDGE_RIGHT |
253 WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
252 254
253 struct sway_xdg_shell_view *xdg_shell_view = 255 struct sway_xdg_shell_view *xdg_shell_view =
254 calloc(1, sizeof(struct sway_xdg_shell_view)); 256 calloc(1, sizeof(struct sway_xdg_shell_view));
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 25a5eef5..e6bc5a1e 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -560,6 +560,11 @@ The following attributes may be matched with:
560 value is \_\_focused\_\_, then the window instance must be the same as that 560 value is \_\_focused\_\_, then the window instance must be the same as that
561 of the currently focused window. 561 of the currently focused window.
562 562
563*shell*
564 Compare value against the window shell, such as "xdg\_shell" or "xwayland".
565 Can be a regular expression. If value is \_\_focused\_\_, then the shell
566 must be the same as that of the currently focused window.
567
563*tiling* 568*tiling*
564 Matches tiling windows. 569 Matches tiling windows.
565 570
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 812d7740..d91182ed 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -107,7 +107,7 @@ uint32_t view_get_window_type(struct sway_view *view) {
107 return 0; 107 return 0;
108} 108}
109 109
110const char *view_get_type(struct sway_view *view) { 110const char *view_get_shell(struct sway_view *view) {
111 switch(view->type) { 111 switch(view->type) {
112 case SWAY_VIEW_XDG_SHELL_V6: 112 case SWAY_VIEW_XDG_SHELL_V6:
113 return "xdg_shell_v6"; 113 return "xdg_shell_v6";
@@ -654,10 +654,12 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) {
654 return title ? strlen(title) : 0; 654 return title ? strlen(title) : 0;
655 } 655 }
656 const char *title = view_get_title(view); 656 const char *title = view_get_title(view);
657 const char *app_id = view_get_app_id(view);
657 const char *class = view_get_class(view); 658 const char *class = view_get_class(view);
658 const char *instance = view_get_instance(view); 659 const char *instance = view_get_instance(view);
659 const char *shell = view_get_type(view); 660 const char *shell = view_get_shell(view);
660 size_t title_len = title ? strlen(title) : 0; 661 size_t title_len = title ? strlen(title) : 0;
662 size_t app_id_len = app_id ? strlen(app_id) : 0;
661 size_t class_len = class ? strlen(class) : 0; 663 size_t class_len = class ? strlen(class) : 0;
662 size_t instance_len = instance ? strlen(instance) : 0; 664 size_t instance_len = instance ? strlen(instance) : 0;
663 size_t shell_len = shell ? strlen(shell) : 0; 665 size_t shell_len = shell ? strlen(shell) : 0;
@@ -675,6 +677,10 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) {
675 lenient_strcat(buffer, title); 677 lenient_strcat(buffer, title);
676 len += title_len; 678 len += title_len;
677 format += 6; 679 format += 6;
680 } else if (strncmp(next, "%app_id", 7) == 0) {
681 lenient_strcat(buffer, app_id);
682 len += app_id_len;
683 format += 7;
678 } else if (strncmp(next, "%class", 6) == 0) { 684 } else if (strncmp(next, "%class", 6) == 0) {
679 lenient_strcat(buffer, class); 685 lenient_strcat(buffer, class);
680 len += class_len; 686 len += class_len;
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 = {
131 .closed = layer_surface_closed, 131 .closed = layer_surface_closed,
132}; 132};
133 133
134static void handle_wl_output_geometry(void *data, struct wl_output *output, int32_t x, 134static const struct wl_callback_listener surface_frame_listener;
135 int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, 135
136 const char *make, const char *model, int32_t transform) { 136static void surface_frame_handle_done(void *data, struct wl_callback *callback,
137 uint32_t time) {
138 struct swaylock_surface *surface = data;
139
140 wl_callback_destroy(callback);
141 surface->frame_pending = false;
142
143 if (surface->dirty) {
144 // Schedule a frame in case the surface is damaged again
145 struct wl_callback *callback = wl_surface_frame(surface->surface);
146 wl_callback_add_listener(callback, &surface_frame_listener, surface);
147 surface->frame_pending = true;
148
149 render_frame(surface);
150 surface->dirty = false;
151 }
152}
153
154static const struct wl_callback_listener surface_frame_listener = {
155 .done = surface_frame_handle_done,
156};
157
158void damage_surface(struct swaylock_surface *surface) {
159 surface->dirty = true;
160 if (surface->frame_pending) {
161 return;
162 }
163
164 struct wl_callback *callback = wl_surface_frame(surface->surface);
165 wl_callback_add_listener(callback, &surface_frame_listener, surface);
166 surface->frame_pending = true;
167 wl_surface_commit(surface->surface);
168}
169
170void damage_state(struct swaylock_state *state) {
171 struct swaylock_surface *surface;
172 wl_list_for_each(surface, &state->surfaces, link) {
173 damage_surface(surface);
174 }
175}
176
177static void handle_wl_output_geometry(void *data, struct wl_output *output,
178 int32_t x, int32_t y, int32_t width_mm, int32_t height_mm,
179 int32_t subpixel, const char *make, const char *model,
180 int32_t transform) {
137 // Who cares 181 // Who cares
138} 182}
139 183
140static void handle_wl_output_mode(void *data, struct wl_output *output, uint32_t flags, 184static void handle_wl_output_mode(void *data, struct wl_output *output,
141 int32_t width, int32_t height, int32_t refresh) { 185 uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
142 // Who cares 186 // Who cares
143} 187}
144 188
@@ -151,7 +195,7 @@ static void handle_wl_output_scale(void *data, struct wl_output *output,
151 struct swaylock_surface *surface = data; 195 struct swaylock_surface *surface = data;
152 surface->scale = factor; 196 surface->scale = factor;
153 if (surface->state->run_display) { 197 if (surface->state->run_display) {
154 render_frames(surface->state); 198 damage_surface(surface);
155 } 199 }
156} 200}
157 201
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) {
93void swaylock_handle_key(struct swaylock_state *state, 93void swaylock_handle_key(struct swaylock_state *state,
94 xkb_keysym_t keysym, uint32_t codepoint) { 94 xkb_keysym_t keysym, uint32_t codepoint) {
95 switch (keysym) { 95 switch (keysym) {
96 case XKB_KEY_KP_Enter: /* fallthrough */ 96 case XKB_KEY_KP_Enter: /* fallthrough */
97 case XKB_KEY_Return: 97 case XKB_KEY_Return:
98 state->auth_state = AUTH_STATE_VALIDATING; 98 state->auth_state = AUTH_STATE_VALIDATING;
99 render_frames(state); 99 damage_state(state);
100 wl_display_roundtrip(state->display); 100 wl_display_roundtrip(state->display);
101 if (attempt_password(&state->password)) { 101 if (attempt_password(&state->password)) {
102 state->run_display = false; 102 state->run_display = false;
103 break;
104 }
105 state->auth_state = AUTH_STATE_INVALID;
106 render_frames(state);
107 break; 103 break;
108 case XKB_KEY_Delete: 104 }
109 case XKB_KEY_BackSpace: 105 state->auth_state = AUTH_STATE_INVALID;
110 if (backspace(&state->password)) { 106 damage_state(state);
111 state->auth_state = AUTH_STATE_BACKSPACE; 107 break;
112 } else { 108 case XKB_KEY_Delete:
113 state->auth_state = AUTH_STATE_CLEAR; 109 case XKB_KEY_BackSpace:
114 } 110 if (backspace(&state->password)) {
115 render_frames(state); 111 state->auth_state = AUTH_STATE_BACKSPACE;
116 break; 112 } else {
117 case XKB_KEY_Escape:
118 clear_password_buffer(&state->password);
119 state->auth_state = AUTH_STATE_CLEAR; 113 state->auth_state = AUTH_STATE_CLEAR;
120 render_frames(state); 114 }
121 break; 115 damage_state(state);
122 case XKB_KEY_Caps_Lock: 116 break;
123 /* The state is getting active after this 117 case XKB_KEY_Escape:
124 * so we need to manually toggle it */ 118 clear_password_buffer(&state->password);
125 state->xkb.caps_lock = !state->xkb.caps_lock; 119 state->auth_state = AUTH_STATE_CLEAR;
126 state->auth_state = AUTH_STATE_INPUT_NOP; 120 damage_state(state);
127 render_frames(state); 121 break;
128 break; 122 case XKB_KEY_Caps_Lock:
129 case XKB_KEY_Shift_L: 123 /* The state is getting active after this
130 case XKB_KEY_Shift_R: 124 * so we need to manually toggle it */
131 case XKB_KEY_Control_L: 125 state->xkb.caps_lock = !state->xkb.caps_lock;
132 case XKB_KEY_Control_R: 126 state->auth_state = AUTH_STATE_INPUT_NOP;
133 case XKB_KEY_Meta_L: 127 damage_state(state);
134 case XKB_KEY_Meta_R: 128 break;
135 case XKB_KEY_Alt_L: 129 case XKB_KEY_Shift_L:
136 case XKB_KEY_Alt_R: 130 case XKB_KEY_Shift_R:
137 case XKB_KEY_Super_L: 131 case XKB_KEY_Control_L:
138 case XKB_KEY_Super_R: 132 case XKB_KEY_Control_R:
139 state->auth_state = AUTH_STATE_INPUT_NOP; 133 case XKB_KEY_Meta_L:
140 render_frames(state); 134 case XKB_KEY_Meta_R:
141 break; 135 case XKB_KEY_Alt_L:
142 default: 136 case XKB_KEY_Alt_R:
143 if (codepoint) { 137 case XKB_KEY_Super_L:
144 append_ch(&state->password, codepoint); 138 case XKB_KEY_Super_R:
145 state->auth_state = AUTH_STATE_INPUT; 139 state->auth_state = AUTH_STATE_INPUT_NOP;
146 render_frames(state); 140 damage_state(state);
147 } 141 break;
148 break; 142 default:
143 if (codepoint) {
144 append_ch(&state->password, codepoint);
145 state->auth_state = AUTH_STATE_INPUT;
146 damage_state(state);
147 }
148 break;
149 } 149 }
150} 150}
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) {
23 23
24 surface->current_buffer = get_next_buffer(state->shm, 24 surface->current_buffer = get_next_buffer(state->shm,
25 surface->buffers, buffer_width, buffer_height); 25 surface->buffers, buffer_width, buffer_height);
26 if (surface->current_buffer == NULL) {
27 return;
28 }
29
26 cairo_t *cairo = surface->current_buffer->cairo; 30 cairo_t *cairo = surface->current_buffer->cairo;
27 cairo_identity_matrix(cairo); 31 cairo_identity_matrix(cairo);
28 32