Merge branch 'master' into feature/wlr-seat-touch

This commit is contained in:
Tony Crisci 2017-11-16 16:19:17 -05:00
commit 584ff1df4c
16 changed files with 196 additions and 93 deletions

View File

@ -33,3 +33,17 @@ Run these commands:
ninja -C build ninja -C build
(On FreeBSD, you need to pass an extra flag to prevent a linking error: `meson build -D b_lundef=false`) (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.

View File

@ -66,10 +66,11 @@ static void handle_device_added(struct wlr_libinput_backend *backend,
int product = libinput_device_get_id_product(libinput_dev); int product = libinput_device_get_id_product(libinput_dev);
const char *name = libinput_device_get_name(libinput_dev); const char *name = libinput_device_get_name(libinput_dev);
struct wl_list *wlr_devices = calloc(1, sizeof(struct wl_list)); struct wl_list *wlr_devices = calloc(1, sizeof(struct wl_list));
wl_list_init(wlr_devices);
if (!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); wlr_log(L_DEBUG, "Added %s [%d:%d]", name, vendor, product);
if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) {

View File

@ -249,7 +249,7 @@ static size_t explicit_find_gpus(struct wlr_session *session,
} }
} while ((ptr = strtok_r(NULL, ":", &save))); } while ((ptr = strtok_r(NULL, ":", &save)));
free(ptr); free(gpus);
return i; return i;
} }

View File

@ -12,10 +12,15 @@
#include "backend/wayland.h" #include "backend/wayland.h"
#include "xdg-shell-unstable-v6-client-protocol.h" #include "xdg-shell-unstable-v6-client-protocol.h"
static int dispatch_events(int fd, uint32_t mask, void *data) { static int dispatch_events(int fd, uint32_t mask, void *data) {
struct wlr_wl_backend *backend = data; struct wlr_wl_backend *backend = data;
int count = 0; 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) { if (mask & WL_EVENT_READABLE) {
count = wl_display_dispatch(backend->remote_display); 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_log(L_INFO, "Initializating wayland backend");
wlr_wl_registry_poll(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"); wlr_log_errno(L_ERROR, "Could not obtain retrieve required globals");
return false; 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); struct wl_event_loop *loop = wl_display_get_event_loop(backend->local_display);
int fd = wl_display_get_fd(backend->remote_display); int fd = wl_display_get_fd(backend->remote_display);
int events = WL_EVENT_READABLE | WL_EVENT_ERROR | int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
WL_EVENT_HANGUP;
backend->remote_display_src = wl_event_loop_add_fd(loop, fd, events, 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); wl_event_source_check(backend->remote_display_src);
return true; return true;

View File

@ -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) { static int x11_event(int fd, uint32_t mask, void *data) {
struct wlr_x11_backend *x11 = 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; xcb_generic_event_t *e;
bool quit = false; bool quit = false;
while (!quit && (e = xcb_poll_for_event(x11->xcb_conn))) { while (!quit && (e = xcb_poll_for_event(x11->xcb_conn))) {
quit = handle_x11_event(x11, e); quit = handle_x11_event(x11, e);
free(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); int fd = xcb_get_file_descriptor(x11->xcb_conn);
struct wl_event_loop *ev = wl_display_get_event_loop(display); 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) { if (!x11->event_source) {
wlr_log(L_ERROR, "Could not create event source"); wlr_log(L_ERROR, "Could not create event source");
goto error_x11; goto error_x11;

View File

@ -16,7 +16,8 @@ struct roots_keyboard {
struct wl_listener keyboard_key; struct wl_listener keyboard_key;
struct wl_listener keyboard_modifiers; 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, struct roots_keyboard *roots_keyboard_create(struct wlr_input_device *device,

View File

@ -405,7 +405,7 @@ void roots_config_destroy(struct roots_config *config) {
} }
struct roots_keyboard_config *kc, *ktmp = NULL; 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->name);
free(kc->rules); free(kc->rules);
free(kc->model); free(kc->model);

View File

@ -18,9 +18,9 @@ struct roots_cursor *roots_cursor_create(struct roots_seat *seat) {
} }
cursor->cursor = wlr_cursor_create(); cursor->cursor = wlr_cursor_create();
if (!cursor->cursor) { if (!cursor->cursor) {
free(cursor);
return NULL; return NULL;
} }
return cursor; return cursor;
} }

View File

@ -13,16 +13,76 @@
#include "rootston/seat.h" #include "rootston/seat.h"
#include "rootston/keyboard.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) { xkb_keysym_t keysym) {
for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; i++) { for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) {
if (keyboard->pressed_keysyms[i] == keysym) { if (pressed_keysyms[i] == keysym) {
return i; return i;
} }
} }
return -1; 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 const char *exec_prefix = "exec ";
static void keyboard_binding_execute(struct roots_keyboard *keyboard, 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 * Returns true if the keysym was handled by a binding and false if the event
* should be propagated to clients. * 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) { 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 && if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
keysym <= XKB_KEY_XF86Switch_VT_12) { keysym <= XKB_KEY_XF86Switch_VT_12) {
struct roots_server *server = keyboard->input->server; 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); 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 wl_list *bindings = &keyboard->input->server->config->bindings;
struct roots_binding_config *bc; struct roots_binding_config *bc;
wl_list_for_each(bc, bindings, link) { wl_list_for_each(bc, bindings, link) {
if (modifiers ^ bc->modifiers) { if (modifiers ^ bc->modifiers || n != bc->keysyms_len) {
continue; continue;
} }
bool ok = true; bool ok = true;
for (size_t i = 0; i < bc->keysyms_len; i++) { 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) { if (j < 0) {
ok = false; ok = false;
break; break;
@ -116,85 +189,75 @@ static bool keyboard_keysym_press(struct roots_keyboard *keyboard,
return false; 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 * This uses the xkb keysyms translation based on pressed modifiers and clears
* the consumed modifiers from the list of modifiers passed to keybind * the consumed modifiers from the list of modifiers passed to keybind
* detection. * 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, static size_t keyboard_keysyms_translated(struct roots_keyboard *keyboard,
uint32_t keycode, enum wlr_key_state state) { xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); uint32_t *modifiers) {
const xkb_keysym_t *syms; *modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
int syms_len = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2(
keycode, &syms);
uint32_t consumed = xkb_state_key_get_consumed_mods2(
keyboard->device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); keyboard->device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB);
*modifiers = *modifiers & ~consumed;
modifiers = modifiers & ~consumed; return xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
keycode, keysyms);
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;
} }
/* /*
* 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 * 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, static size_t keyboard_keysyms_raw(struct roots_keyboard *keyboard,
uint32_t keycode, enum wlr_key_state state) { xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
const xkb_keysym_t *syms; uint32_t *modifiers) {
*modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
xkb_layout_index_t layout_index = xkb_state_key_get_layout( xkb_layout_index_t layout_index = xkb_state_key_get_layout(
keyboard->device->keyboard->xkb_state, keycode); keyboard->device->keyboard->xkb_state, keycode);
int syms_len = xkb_keymap_key_get_syms_by_level( return xkb_keymap_key_get_syms_by_level(keyboard->device->keyboard->keymap,
keyboard->device->keyboard->keymap, keycode, layout_index, 0, &syms); keycode, layout_index, 0, keysyms);
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;
} }
void roots_keyboard_handle_key(struct roots_keyboard *keyboard, void roots_keyboard_handle_key(struct roots_keyboard *keyboard,
struct wlr_event_keyboard_key *event) { struct wlr_event_keyboard_key *event) {
uint32_t keycode = event->keycode + 8; xkb_keycode_t keycode = event->keycode + 8;
bool handled = keyboard_keysyms_xkb(keyboard, keycode, event->state); bool handled = false;
uint32_t modifiers;
const xkb_keysym_t *keysyms;
size_t keysyms_len;
if (!handled) { // Handle translated keysyms
bool key_handled = keyboard_keysyms_simple(keyboard, keycode,
event->state); keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &keysyms,
handled = handled || key_handled; &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) { if (!handled) {

View File

@ -40,6 +40,6 @@ meta-key = Logo
# - "close" to close the current view # - "close" to close the current view
# - "next_window" to cycle through windows # - "next_window" to cycle through windows
[bindings] [bindings]
Logo+Shift+E = exit Logo+Shift+e = exit
Logo+q = close Logo+q = close
Alt+Tab = next_window Alt+Tab = next_window

View File

@ -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); seat->seat = wlr_seat_create(input->server->wl_display, name);
if (!seat->seat) { if (!seat->seat) {
free(seat); free(seat);
roots_cursor_destroy(seat->cursor);
return NULL; return NULL;
} }

View File

@ -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)) { if (!seat_client_start_drag(seat_client, source, icon, origin, serial)) {
wl_resource_post_no_memory(device_resource); wl_resource_post_no_memory(device_resource);
} else { return;
}
if (source) {
source->seat_client = seat_client; source->seat_client = seat_client;
} }
} }

View File

@ -105,7 +105,10 @@ void wlr_keyboard_init(struct wlr_keyboard *kb,
} }
void wlr_keyboard_destroy(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); kb->impl->destroy(kb);
} else { } else {
wl_list_remove(&kb->events.key.listener_list); wl_list_remove(&kb->events.key.listener_list);

View File

@ -29,8 +29,7 @@ static void wl_output_send_to_resource(struct wl_resource *resource) {
if (version >= WL_OUTPUT_MODE_SINCE_VERSION) { if (version >= WL_OUTPUT_MODE_SINCE_VERSION) {
struct wlr_output_mode *mode; struct wlr_output_mode *mode;
wl_list_for_each(mode, &output->modes, link) { wl_list_for_each(mode, &output->modes, link) {
// TODO: mode->flags should just be preferred uint32_t flags = mode->flags & WL_OUTPUT_MODE_PREFERRED;
uint32_t flags = mode->flags;
if (output->current_mode == mode) { if (output->current_mode == mode) {
flags |= WL_OUTPUT_MODE_CURRENT; flags |= WL_OUTPUT_MODE_CURRENT;
} }
@ -62,13 +61,17 @@ static void wlr_output_send_current_mode_to_resource(
} }
if (output->current_mode != NULL) { if (output->current_mode != NULL) {
struct wlr_output_mode *mode = output->current_mode; 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); mode->width, mode->height, mode->refresh);
} else { } else {
// Output has no mode, send the current width/height // Output has no mode, send the current width/height
wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT, output->width, wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT, output->width,
output->height, 0); output->height, 0);
} }
if (version >= WL_OUTPUT_DONE_SINCE_VERSION) {
wl_output_send_done(resource);
}
} }
static void wl_output_destroy(struct wl_resource *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, void wlr_output_update_size(struct wlr_output *output, int32_t width,
int32_t height) { int32_t height) {
if (output->width == width && output->height == height) {
return;
}
output->width = width; output->width = width;
output->height = height; output->height = height;
wlr_output_update_matrix(output); wlr_output_update_matrix(output);

View File

@ -85,6 +85,7 @@ static void screenshooter_shoot(struct wl_client *client,
struct wlr_screenshot *screenshot = struct wlr_screenshot *screenshot =
calloc(1, sizeof(struct wlr_screenshot)); calloc(1, sizeof(struct wlr_screenshot));
if (!screenshot) { if (!screenshot) {
free(pixels);
wl_resource_post_no_memory(screenshooter_resource); wl_resource_post_no_memory(screenshooter_resource);
return; return;
} }
@ -96,6 +97,7 @@ static void screenshooter_shoot(struct wl_client *client,
wl_resource_get_version(screenshooter_resource), id); wl_resource_get_version(screenshooter_resource), id);
if (screenshot->resource == NULL) { if (screenshot->resource == NULL) {
free(screenshot); free(screenshot);
free(pixels);
wl_resource_post_no_memory(screenshooter_resource); wl_resource_post_no_memory(screenshooter_resource);
return; return;
} }
@ -109,6 +111,7 @@ static void screenshooter_shoot(struct wl_client *client,
if (!state) { if (!state) {
wl_resource_destroy(screenshot->resource); wl_resource_destroy(screenshot->resource);
free(screenshot); free(screenshot);
free(pixels);
wl_resource_post_no_memory(screenshooter_resource); wl_resource_post_no_memory(screenshooter_resource);
return; return;
} }

View File

@ -347,7 +347,7 @@ static void shell_surface_protocol_set_popup(struct wl_client *client,
transient_state->flags = flags; transient_state->flags = flags;
struct wlr_wl_shell_surface_popup_state *popup_state = 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) { if (popup_state == NULL) {
free(transient_state); free(transient_state);
wl_client_post_no_memory(client); wl_client_post_no_memory(client);