aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rw-r--r--backend/libinput/events.c5
-rw-r--r--backend/session/session.c2
-rw-r--r--backend/wayland/backend.c14
-rw-r--r--backend/x11/backend.c10
-rw-r--r--include/rootston/keyboard.h3
-rw-r--r--rootston/config.c2
-rw-r--r--rootston/cursor.c2
-rw-r--r--rootston/keyboard.c207
-rw-r--r--rootston/rootston.ini.example2
-rw-r--r--rootston/seat.c1
-rw-r--r--types/wlr_data_device.c5
-rw-r--r--types/wlr_keyboard.c5
-rw-r--r--types/wlr_output.c12
-rw-r--r--types/wlr_screenshooter.c3
-rw-r--r--types/wlr_wl_shell.c2
16 files changed, 196 insertions, 93 deletions
diff --git a/README.md b/README.md
index 0f221e3c..06ef8dcb 100644
--- a/README.md
+++ b/README.md
@@ -33,3 +33,17 @@ Run these commands:
ninja -C build
(On FreeBSD, you need to pass an extra flag to prevent a linking error: `meson build -D b_lundef=false`)
+
+## Running the Reference Compositor
+
+wlroots comes with a reference compositor called rootston that demonstrates the
+features of the library.
+
+After building, run rootston from a terminal or VT with:
+
+ ./build/rootston/rootston
+
+Now you can run windows in the compositor from the command line or by
+configuring bindings in your
+[`rootston.ini`](https://github.com/swaywm/wlroots/blob/master/rootston/rootston.ini.example)
+file.
diff --git a/backend/libinput/events.c b/backend/libinput/events.c
index 5da45c67..3ca41124 100644
--- a/backend/libinput/events.c
+++ b/backend/libinput/events.c
@@ -66,10 +66,11 @@ static void handle_device_added(struct wlr_libinput_backend *backend,
int product = libinput_device_get_id_product(libinput_dev);
const char *name = libinput_device_get_name(libinput_dev);
struct wl_list *wlr_devices = calloc(1, sizeof(struct wl_list));
- wl_list_init(wlr_devices);
if (!wlr_devices) {
- goto fail;
+ wlr_log(L_ERROR, "Allocation failed");
+ return;
}
+ wl_list_init(wlr_devices);
wlr_log(L_DEBUG, "Added %s [%d:%d]", name, vendor, product);
if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) {
diff --git a/backend/session/session.c b/backend/session/session.c
index 760830c3..657558fd 100644
--- a/backend/session/session.c
+++ b/backend/session/session.c
@@ -249,7 +249,7 @@ static size_t explicit_find_gpus(struct wlr_session *session,
}
} while ((ptr = strtok_r(NULL, ":", &save)));
- free(ptr);
+ free(gpus);
return i;
}
diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c
index 532935b8..1801f3e0 100644
--- a/backend/wayland/backend.c
+++ b/backend/wayland/backend.c
@@ -12,10 +12,15 @@
#include "backend/wayland.h"
#include "xdg-shell-unstable-v6-client-protocol.h"
-
static int dispatch_events(int fd, uint32_t mask, void *data) {
struct wlr_wl_backend *backend = data;
int count = 0;
+
+ if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
+ wl_display_terminate(backend->local_display);
+ return 0;
+ }
+
if (mask & WL_EVENT_READABLE) {
count = wl_display_dispatch(backend->remote_display);
}
@@ -36,7 +41,7 @@ static bool wlr_wl_backend_start(struct wlr_backend *_backend) {
wlr_log(L_INFO, "Initializating wayland backend");
wlr_wl_registry_poll(backend);
- if (!(backend->compositor) || (!(backend->shell))) {
+ if (!backend->compositor || !backend->shell) {
wlr_log_errno(L_ERROR, "Could not obtain retrieve required globals");
return false;
}
@@ -49,10 +54,9 @@ static bool wlr_wl_backend_start(struct wlr_backend *_backend) {
struct wl_event_loop *loop = wl_display_get_event_loop(backend->local_display);
int fd = wl_display_get_fd(backend->remote_display);
- int events = WL_EVENT_READABLE | WL_EVENT_ERROR |
- WL_EVENT_HANGUP;
+ int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
backend->remote_display_src = wl_event_loop_add_fd(loop, fd, events,
- dispatch_events, backend);
+ dispatch_events, backend);
wl_event_source_check(backend->remote_display_src);
return true;
diff --git a/backend/x11/backend.c b/backend/x11/backend.c
index 97b0dd8c..b798daf6 100644
--- a/backend/x11/backend.c
+++ b/backend/x11/backend.c
@@ -155,9 +155,14 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e
static int x11_event(int fd, uint32_t mask, void *data) {
struct wlr_x11_backend *x11 = data;
+
+ if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
+ wl_display_terminate(x11->wl_display);
+ return 0;
+ }
+
xcb_generic_event_t *e;
bool quit = false;
-
while (!quit && (e = xcb_poll_for_event(x11->xcb_conn))) {
quit = handle_x11_event(x11, e);
free(e);
@@ -205,7 +210,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
int fd = xcb_get_file_descriptor(x11->xcb_conn);
struct wl_event_loop *ev = wl_display_get_event_loop(display);
- x11->event_source = wl_event_loop_add_fd(ev, fd, WL_EVENT_READABLE, x11_event, x11);
+ int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
+ x11->event_source = wl_event_loop_add_fd(ev, fd, events, x11_event, x11);
if (!x11->event_source) {
wlr_log(L_ERROR, "Could not create event source");
goto error_x11;
diff --git a/include/rootston/keyboard.h b/include/rootston/keyboard.h
index 15e7c9c4..39650d7c 100644
--- a/include/rootston/keyboard.h
+++ b/include/rootston/keyboard.h
@@ -16,7 +16,8 @@ struct roots_keyboard {
struct wl_listener keyboard_key;
struct wl_listener keyboard_modifiers;
- xkb_keysym_t pressed_keysyms[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
+ xkb_keysym_t pressed_keysyms_translated[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
+ xkb_keysym_t pressed_keysyms_raw[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
};
struct roots_keyboard *roots_keyboard_create(struct wlr_input_device *device,
diff --git a/rootston/config.c b/rootston/config.c
index 7ffbb786..727b52d0 100644
--- a/rootston/config.c
+++ b/rootston/config.c
@@ -405,7 +405,7 @@ void roots_config_destroy(struct roots_config *config) {
}
struct roots_keyboard_config *kc, *ktmp = NULL;
- wl_list_for_each_safe(kc, ktmp, &config->bindings, link) {
+ wl_list_for_each_safe(kc, ktmp, &config->keyboards, link) {
free(kc->name);
free(kc->rules);
free(kc->model);
diff --git a/rootston/cursor.c b/rootston/cursor.c
index b6325fdc..35fe9c25 100644
--- a/rootston/cursor.c
+++ b/rootston/cursor.c
@@ -18,9 +18,9 @@ struct roots_cursor *roots_cursor_create(struct roots_seat *seat) {
}
cursor->cursor = wlr_cursor_create();
if (!cursor->cursor) {
+ free(cursor);
return NULL;
}
-
return cursor;
}
diff --git a/rootston/keyboard.c b/rootston/keyboard.c
index c118e55c..39f46a32 100644
--- a/rootston/keyboard.c
+++ b/rootston/keyboard.c
@@ -13,16 +13,76 @@
#include "rootston/seat.h"
#include "rootston/keyboard.h"
-static ssize_t keyboard_pressed_keysym_index(struct roots_keyboard *keyboard,
+static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms,
xkb_keysym_t keysym) {
- for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; i++) {
- if (keyboard->pressed_keysyms[i] == keysym) {
+ for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) {
+ if (pressed_keysyms[i] == keysym) {
return i;
}
}
return -1;
}
+static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) {
+ size_t n = 0;
+ for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) {
+ if (pressed_keysyms[i] != XKB_KEY_NoSymbol) {
+ ++n;
+ }
+ }
+ return n;
+}
+
+static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms,
+ xkb_keysym_t keysym) {
+ ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym);
+ if (i < 0) {
+ i = pressed_keysyms_index(pressed_keysyms, XKB_KEY_NoSymbol);
+ if (i >= 0) {
+ pressed_keysyms[i] = keysym;
+ }
+ }
+}
+
+static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms,
+ xkb_keysym_t keysym) {
+ ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym);
+ if (i >= 0) {
+ pressed_keysyms[i] = XKB_KEY_NoSymbol;
+ }
+}
+
+static bool keysym_is_modifier(xkb_keysym_t keysym) {
+ switch (keysym) {
+ case XKB_KEY_Shift_L: case XKB_KEY_Shift_R:
+ case XKB_KEY_Control_L: case XKB_KEY_Control_R:
+ case XKB_KEY_Caps_Lock:
+ case XKB_KEY_Shift_Lock:
+ 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:
+ case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms,
+ const xkb_keysym_t *keysyms, size_t keysyms_len,
+ enum wlr_key_state state) {
+ for (size_t i = 0; i < keysyms_len; ++i) {
+ if (keysym_is_modifier(keysyms[i])) {
+ continue;
+ }
+ if (state == WLR_KEY_PRESSED) {
+ pressed_keysyms_add(pressed_keysyms, keysyms[i]);
+ } else { // WLR_KEY_RELEASED
+ pressed_keysyms_remove(pressed_keysyms, keysyms[i]);
+ }
+ }
+}
+
static const char *exec_prefix = "exec ";
static void keyboard_binding_execute(struct roots_keyboard *keyboard,
@@ -56,21 +116,14 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,
}
/**
- * Process a keypress from the keyboard.
+ * Execute a built-in, hardcoded compositor binding. These are triggered from a
+ * single keysym.
*
* Returns true if the keysym was handled by a binding and false if the event
* should be propagated to clients.
*/
-static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
+static bool keyboard_execute_compositor_binding(struct roots_keyboard *keyboard,
xkb_keysym_t keysym) {
- ssize_t i = keyboard_pressed_keysym_index(keyboard, keysym);
- if (i < 0) {
- i = keyboard_pressed_keysym_index(keyboard, XKB_KEY_NoSymbol);
- if (i >= 0) {
- keyboard->pressed_keysyms[i] = keysym;
- }
- }
-
if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
keysym <= XKB_KEY_XF86Switch_VT_12) {
struct roots_server *server = keyboard->input->server;
@@ -90,17 +143,37 @@ static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
wlr_seat_keyboard_end_grab(keyboard->seat->seat);
}
- uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
+ return false;
+}
+
+/**
+ * Execute keyboard bindings. These include compositor bindings and user-defined
+ * bindings.
+ *
+ * Returns true if the keysym was handled by a binding and false if the event
+ * should be propagated to clients.
+ */
+static bool keyboard_execute_binding(struct roots_keyboard *keyboard,
+ xkb_keysym_t *pressed_keysyms, uint32_t modifiers,
+ const xkb_keysym_t *keysyms, size_t keysyms_len) {
+ for (size_t i = 0; i < keysyms_len; ++i) {
+ if (keyboard_execute_compositor_binding(keyboard, keysyms[i])) {
+ return true;
+ }
+ }
+
+ // User-defined bindings
+ size_t n = pressed_keysyms_length(pressed_keysyms);
struct wl_list *bindings = &keyboard->input->server->config->bindings;
struct roots_binding_config *bc;
wl_list_for_each(bc, bindings, link) {
- if (modifiers ^ bc->modifiers) {
+ if (modifiers ^ bc->modifiers || n != bc->keysyms_len) {
continue;
}
bool ok = true;
for (size_t i = 0; i < bc->keysyms_len; i++) {
- ssize_t j = keyboard_pressed_keysym_index(keyboard, bc->keysyms[i]);
+ ssize_t j = pressed_keysyms_index(pressed_keysyms, bc->keysyms[i]);
if (j < 0) {
ok = false;
break;
@@ -116,85 +189,75 @@ static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
return false;
}
-static void keyboard_keysym_release(struct roots_keyboard *keyboard,
- xkb_keysym_t keysym) {
- ssize_t i = keyboard_pressed_keysym_index(keyboard, keysym);
- if (i >= 0) {
- keyboard->pressed_keysyms[i] = XKB_KEY_NoSymbol;
- }
-}
/*
- * Process keypresses from the keyboard as xkb sees them.
+ * Get keysyms and modifiers from the keyboard as xkb sees them.
*
* This uses the xkb keysyms translation based on pressed modifiers and clears
* the consumed modifiers from the list of modifiers passed to keybind
* detection.
*
- * (On US layout) this will trigger: [Alt]+[at]
+ * On US layout, pressing Alt+Shift+2 will trigger Alt+@.
*/
-static bool keyboard_keysyms_xkb(struct roots_keyboard *keyboard,
- uint32_t keycode, enum wlr_key_state state) {
- uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
- const xkb_keysym_t *syms;
- int syms_len = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
- keycode, &syms);
- uint32_t consumed = xkb_state_key_get_consumed_mods2(
+static size_t keyboard_keysyms_translated(struct roots_keyboard *keyboard,
+ xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
+ uint32_t *modifiers) {
+ *modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
+ xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2(
keyboard->device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB);
+ *modifiers = *modifiers & ~consumed;
- modifiers = modifiers & ~consumed;
-
- bool handled = false;
- for (int i = 0; i < syms_len; i++) {
- if (state) {
- bool keysym_handled =
- keyboard_keysym_press(keyboard, syms[i]);
- handled = handled || keysym_handled;
- } else { // WLR_KEY_RELEASED
- keyboard_keysym_release(keyboard, syms[i]);
- }
- }
-
- return handled;
+ return xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
+ keycode, keysyms);
}
+
/*
- * Process keypresses from the keyboard as if modifiers didn't change keysyms.
+ * Get keysyms and modifiers from the keyboard as if modifiers didn't change
+ * keysyms.
*
* This avoids the xkb keysym translation based on modifiers considered pressed
- * in the state and uses the list of modifiers saved on the rootston side.
+ * in the state.
*
- * This will trigger the keybind: [Alt]+[Shift]+2
+ * This will trigger keybinds such as Alt+Shift+2.
*/
-static bool keyboard_keysyms_simple(struct roots_keyboard *keyboard,
- uint32_t keycode, enum wlr_key_state state) {
- const xkb_keysym_t *syms;
+static size_t keyboard_keysyms_raw(struct roots_keyboard *keyboard,
+ xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
+ uint32_t *modifiers) {
+ *modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
+
xkb_layout_index_t layout_index = xkb_state_key_get_layout(
keyboard->device->keyboard->xkb_state, keycode);
- int syms_len = xkb_keymap_key_get_syms_by_level(
- keyboard->device->keyboard->keymap, keycode, layout_index, 0, &syms);
-
- bool handled = false;
- for (int i = 0; i < syms_len; i++) {
- if (state) {
- bool keysym_handled = keyboard_keysym_press(keyboard, syms[i]);
- handled = handled || keysym_handled;
- } else { // WLR_KEY_RELEASED
- keyboard_keysym_release(keyboard, syms[i]);
- }
- }
-
- return handled;
+ return xkb_keymap_key_get_syms_by_level(keyboard->device->keyboard->keymap,
+ keycode, layout_index, 0, keysyms);
}
void roots_keyboard_handle_key(struct roots_keyboard *keyboard,
struct wlr_event_keyboard_key *event) {
- uint32_t keycode = event->keycode + 8;
+ xkb_keycode_t keycode = event->keycode + 8;
+
+ bool handled = false;
+ uint32_t modifiers;
+ const xkb_keysym_t *keysyms;
+ size_t keysyms_len;
- bool handled = keyboard_keysyms_xkb(keyboard, keycode, event->state);
+ // Handle translated keysyms
- if (!handled) {
- bool key_handled = keyboard_keysyms_simple(keyboard, keycode,
- event->state);
- handled = handled || key_handled;
+ keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &keysyms,
+ &modifiers);
+ pressed_keysyms_update(keyboard->pressed_keysyms_translated, keysyms,
+ keysyms_len, event->state);
+ if (event->state == WLR_KEY_PRESSED) {
+ handled = keyboard_execute_binding(keyboard,
+ keyboard->pressed_keysyms_translated, modifiers, keysyms,
+ keysyms_len);
+ }
+
+ // Handle raw keysyms
+ keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &keysyms, &modifiers);
+ pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, keysyms_len,
+ event->state);
+ if (event->state == WLR_KEY_PRESSED && !handled) {
+ handled = keyboard_execute_binding(keyboard,
+ keyboard->pressed_keysyms_raw, modifiers, keysyms, keysyms_len);
}
if (!handled) {
diff --git a/rootston/rootston.ini.example b/rootston/rootston.ini.example
index 433dc78f..c33b0f04 100644
--- a/rootston/rootston.ini.example
+++ b/rootston/rootston.ini.example
@@ -40,6 +40,6 @@ meta-key = Logo
# - "close" to close the current view
# - "next_window" to cycle through windows
[bindings]
-Logo+Shift+E = exit
+Logo+Shift+e = exit
Logo+q = close
Alt+Tab = next_window
diff --git a/rootston/seat.c b/rootston/seat.c
index 38dfc49d..b92643ad 100644
--- a/rootston/seat.c
+++ b/rootston/seat.c
@@ -274,7 +274,6 @@ struct roots_seat *roots_seat_create(struct roots_input *input, char *name) {
seat->seat = wlr_seat_create(input->server->wl_display, name);
if (!seat->seat) {
free(seat);
- roots_cursor_destroy(seat->cursor);
return NULL;
}
diff --git a/types/wlr_data_device.c b/types/wlr_data_device.c
index 57122818..999faa22 100644
--- a/types/wlr_data_device.c
+++ b/types/wlr_data_device.c
@@ -713,7 +713,10 @@ static void data_device_start_drag(struct wl_client *client,
if (!seat_client_start_drag(seat_client, source, icon, origin, serial)) {
wl_resource_post_no_memory(device_resource);
- } else {
+ return;
+ }
+
+ if (source) {
source->seat_client = seat_client;
}
}
diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c
index 98ebeed5..c4f2ed52 100644
--- a/types/wlr_keyboard.c
+++ b/types/wlr_keyboard.c
@@ -105,7 +105,10 @@ void wlr_keyboard_init(struct wlr_keyboard *kb,
}
void wlr_keyboard_destroy(struct wlr_keyboard *kb) {
- if (kb && kb->impl && kb->impl->destroy) {
+ if (kb == NULL) {
+ return;
+ }
+ if (kb->impl && kb->impl->destroy) {
kb->impl->destroy(kb);
} else {
wl_list_remove(&kb->events.key.listener_list);
diff --git a/types/wlr_output.c b/types/wlr_output.c
index df02afec..411dd404 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -29,8 +29,7 @@ static void wl_output_send_to_resource(struct wl_resource *resource) {
if (version >= WL_OUTPUT_MODE_SINCE_VERSION) {
struct wlr_output_mode *mode;
wl_list_for_each(mode, &output->modes, link) {
- // TODO: mode->flags should just be preferred
- uint32_t flags = mode->flags;
+ uint32_t flags = mode->flags & WL_OUTPUT_MODE_PREFERRED;
if (output->current_mode == mode) {
flags |= WL_OUTPUT_MODE_CURRENT;
}
@@ -62,13 +61,17 @@ static void wlr_output_send_current_mode_to_resource(
}
if (output->current_mode != NULL) {
struct wlr_output_mode *mode = output->current_mode;
- wl_output_send_mode(resource, mode->flags | WL_OUTPUT_MODE_CURRENT,
+ uint32_t flags = mode->flags & WL_OUTPUT_MODE_PREFERRED;
+ wl_output_send_mode(resource, flags | WL_OUTPUT_MODE_CURRENT,
mode->width, mode->height, mode->refresh);
} else {
// Output has no mode, send the current width/height
wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT, output->width,
output->height, 0);
}
+ if (version >= WL_OUTPUT_DONE_SINCE_VERSION) {
+ wl_output_send_done(resource);
+ }
}
static void wl_output_destroy(struct wl_resource *resource) {
@@ -163,6 +166,9 @@ bool wlr_output_set_mode(struct wlr_output *output,
void wlr_output_update_size(struct wlr_output *output, int32_t width,
int32_t height) {
+ if (output->width == width && output->height == height) {
+ return;
+ }
output->width = width;
output->height = height;
wlr_output_update_matrix(output);
diff --git a/types/wlr_screenshooter.c b/types/wlr_screenshooter.c
index a78c7ad7..94b45384 100644
--- a/types/wlr_screenshooter.c
+++ b/types/wlr_screenshooter.c
@@ -85,6 +85,7 @@ static void screenshooter_shoot(struct wl_client *client,
struct wlr_screenshot *screenshot =
calloc(1, sizeof(struct wlr_screenshot));
if (!screenshot) {
+ free(pixels);
wl_resource_post_no_memory(screenshooter_resource);
return;
}
@@ -96,6 +97,7 @@ static void screenshooter_shoot(struct wl_client *client,
wl_resource_get_version(screenshooter_resource), id);
if (screenshot->resource == NULL) {
free(screenshot);
+ free(pixels);
wl_resource_post_no_memory(screenshooter_resource);
return;
}
@@ -109,6 +111,7 @@ static void screenshooter_shoot(struct wl_client *client,
if (!state) {
wl_resource_destroy(screenshot->resource);
free(screenshot);
+ free(pixels);
wl_resource_post_no_memory(screenshooter_resource);
return;
}
diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c
index 31032fef..abe967d7 100644
--- a/types/wlr_wl_shell.c
+++ b/types/wlr_wl_shell.c
@@ -347,7 +347,7 @@ static void shell_surface_protocol_set_popup(struct wl_client *client,
transient_state->flags = flags;
struct wlr_wl_shell_surface_popup_state *popup_state =
- calloc(1, sizeof(struct wlr_wl_shell_surface_transient_state));
+ calloc(1, sizeof(struct wlr_wl_shell_surface_popup_state));
if (popup_state == NULL) {
free(transient_state);
wl_client_post_no_memory(client);