diff --git a/examples/meson.build b/examples/meson.build index 8d38b888..8a60e1ed 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -53,10 +53,6 @@ examples = { 'src': ['output-layout.c', 'cat.c'], 'dep': [wlroots], }, - 'screenshot': { - 'src': 'screenshot.c', - 'dep': [wayland_client, wlr_protos, rt], - }, 'idle': { 'src': 'idle.c', 'dep': [wayland_client, wlr_protos, threads], diff --git a/examples/screenshot.c b/examples/screenshot.c deleted file mode 100644 index 914f3994..00000000 --- a/examples/screenshot.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#define _POSIX_C_SOURCE 200112L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "screenshooter-client-protocol.h" - -static struct wl_shm *shm = NULL; -static struct orbital_screenshooter *screenshooter = NULL; -static struct wl_list output_list; -static bool buffer_copy_done; - -struct screenshooter_output { - struct wl_output *output; - int width, height; - struct wl_list link; -}; - -static void output_handle_geometry(void *data, struct wl_output *wl_output, - int x, int y, int physical_width, int physical_height, int subpixel, - const char *make, const char *model, int transform) { - // No-op -} - -static void output_handle_mode(void *data, struct wl_output *wl_output, - uint32_t flags, int width, int height, int refresh) { - struct screenshooter_output *output = wl_output_get_user_data(wl_output); - - if (wl_output == output->output && (flags & WL_OUTPUT_MODE_CURRENT)) { - output->width = width; - output->height = height; - } -} - -static void output_handle_done(void *data, struct wl_output *wl_output) { - // No-op -} - -static const struct wl_output_listener output_listener = { - .geometry = output_handle_geometry, - .mode = output_handle_mode, - .done = output_handle_done, -}; - -static void screenshot_done(void *data, struct orbital_screenshot *screenshot) { - buffer_copy_done = true; -} - -static const struct orbital_screenshot_listener screenshot_listener = { - .done = screenshot_done, -}; - -static void handle_global(void *data, struct wl_registry *registry, - uint32_t name, const char *interface, uint32_t version) { - static struct screenshooter_output *output; - - if (strcmp(interface, "wl_output") == 0) { - output = calloc(1, sizeof(*output)); - output->output = wl_registry_bind(registry, name, &wl_output_interface, - 1); - wl_list_insert(&output_list, &output->link); - wl_output_add_listener(output->output, &output_listener, output); - } else if (strcmp(interface, "wl_shm") == 0) { - shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); - } else if (strcmp(interface, "orbital_screenshooter") == 0) { - screenshooter = wl_registry_bind(registry, name, - &orbital_screenshooter_interface, 1); - } -} - -static void handle_global_remove(void *data, struct wl_registry *registry, - uint32_t name) { - // Who cares? -} - -static const struct wl_registry_listener registry_listener = { - .global = handle_global, - .global_remove = handle_global_remove, -}; - -static struct wl_buffer *create_shm_buffer(int width, int height, - void **data_out) { - int stride = width * 4; - int size = stride * height; - - const char shm_name[] = "/wlroots-screenshot"; - int fd = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, 0); - if (fd < 0) { - fprintf(stderr, "shm_open failed\n"); - return NULL; - } - shm_unlink(shm_name); - - int ret; - while ((ret = ftruncate(fd, size)) == EINTR) { - // No-op - } - if (ret < 0) { - close(fd); - fprintf(stderr, "ftruncate failed\n"); - return NULL; - } - - void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) { - fprintf(stderr, "mmap failed: %m\n"); - close(fd); - return NULL; - } - - struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); - close(fd); - struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, width, height, - stride, WL_SHM_FORMAT_XRGB8888); - wl_shm_pool_destroy(pool); - - *data_out = data; - - return buffer; -} - -static void write_image(const char *filename, int width, int height, - void *data) { - char size[10 + 1 + 10 + 2 + 1]; // int32_t are max 10 digits - sprintf(size, "%dx%d+0", width, height); - - int fd[2]; - if (pipe(fd) != 0) { - fprintf(stderr, "cannot create pipe: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - - pid_t child = fork(); - if (child < 0) { - fprintf(stderr, "fork() failed\n"); - exit(EXIT_FAILURE); - } else if (child != 0) { - close(fd[0]); - if (write(fd[1], data, 4 * width * height) < 0) { - fprintf(stderr, "write() failed: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - close(fd[1]); - waitpid(child, NULL, 0); - } else { - close(fd[1]); - if (dup2(fd[0], 0) != 0) { - fprintf(stderr, "cannot dup the pipe\n"); - exit(EXIT_FAILURE); - } - close(fd[0]); - // We requested WL_SHM_FORMAT_XRGB8888 in little endian, so that's BGRA - // in big endian. - execlp("convert", "convert", "-depth", "8", "-size", size, "bgra:-", - "-alpha", "opaque", filename, NULL); - fprintf(stderr, "cannot execute convert\n"); - exit(EXIT_FAILURE); - } -} - -int main(int argc, char *argv[]) { - struct wl_display * display = wl_display_connect(NULL); - if (display == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - wl_list_init(&output_list); - struct wl_registry *registry = wl_display_get_registry(display); - wl_registry_add_listener(registry, ®istry_listener, NULL); - wl_display_dispatch(display); - wl_display_roundtrip(display); - - if (screenshooter == NULL) { - fprintf(stderr, "display doesn't support screenshooter\n"); - return -1; - } - - int i = 0; - struct screenshooter_output *output; - wl_list_for_each(output, &output_list, link) { - void *data = NULL; - struct wl_buffer *buffer = - create_shm_buffer(output->width, output->height, &data); - if (buffer == NULL) { - return -1; - } - struct orbital_screenshot *screenshot = orbital_screenshooter_shoot( - screenshooter, output->output, buffer); - orbital_screenshot_add_listener(screenshot, &screenshot_listener, - screenshot); - buffer_copy_done = false; - while (!buffer_copy_done) { - wl_display_roundtrip(display); - } - - char filename[24 + 10]; // int32_t are max 10 digits - snprintf(filename, sizeof(filename), "wayland-screenshot-%d.png", i); - - write_image(filename, output->width, output->height, data); - wl_buffer_destroy(buffer); - ++i; - } - - return EXIT_SUCCESS; -} diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index bc582334..791f5a8b 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -47,9 +45,7 @@ struct roots_desktop { struct wlr_compositor *compositor; struct wlr_xdg_shell_v6 *xdg_shell_v6; struct wlr_xdg_shell *xdg_shell; - struct wlr_gamma_control_manager *gamma_control_manager; struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1; - struct wlr_screenshooter *screenshooter; struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1; struct wlr_server_decoration_manager *server_decoration_manager; struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager; diff --git a/include/wlr/types/meson.build b/include/wlr/types/meson.build index c7e7bdbf..288fd1c5 100644 --- a/include/wlr/types/meson.build +++ b/include/wlr/types/meson.build @@ -9,7 +9,6 @@ install_headers( 'wlr_foreign_toplevel_management_v1.h', 'wlr_fullscreen_shell_v1.h', 'wlr_gamma_control_v1.h', - 'wlr_gamma_control.h', 'wlr_gtk_primary_selection.h', 'wlr_idle_inhibit_v1.h', 'wlr_idle.h', @@ -34,7 +33,6 @@ install_headers( 'wlr_region.h', 'wlr_relative_pointer_v1.h', 'wlr_screencopy_v1.h', - 'wlr_screenshooter.h', 'wlr_seat.h', 'wlr_server_decoration.h', 'wlr_surface.h', diff --git a/include/wlr/types/wlr_gamma_control.h b/include/wlr/types/wlr_gamma_control.h deleted file mode 100644 index 912a413c..00000000 --- a/include/wlr/types/wlr_gamma_control.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This an unstable interface of wlroots. No guarantees are made regarding the - * future consistency of this API. - */ -#ifndef WLR_USE_UNSTABLE -#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" -#endif - -#ifndef WLR_TYPES_WLR_GAMMA_CONTROL_H -#define WLR_TYPES_WLR_GAMMA_CONTROL_H - -#include - -struct wlr_gamma_control_manager { - struct wl_global *global; - struct wl_list controls; // wlr_gamma_control::link - - struct wl_listener display_destroy; - - struct { - struct wl_signal destroy; - } events; - - void *data; -}; - -struct wlr_gamma_control { - struct wl_resource *resource; - struct wlr_output *output; - struct wl_list link; - - struct wl_listener output_destroy_listener; - - struct { - struct wl_signal destroy; - } events; - - void* data; -}; - -struct wlr_gamma_control_manager *wlr_gamma_control_manager_create( - struct wl_display *display); -void wlr_gamma_control_manager_destroy( - struct wlr_gamma_control_manager *gamma_control_manager); - -#endif diff --git a/include/wlr/types/wlr_screenshooter.h b/include/wlr/types/wlr_screenshooter.h deleted file mode 100644 index d90ed5e1..00000000 --- a/include/wlr/types/wlr_screenshooter.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This protocol is obsolete and will be removed in a future version. The - * recommended replacement is wlr-screencopy. - */ - -/* - * This an unstable interface of wlroots. No guarantees are made regarding the - * future consistency of this API. - */ -#ifndef WLR_USE_UNSTABLE -#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" -#endif - -#ifndef WLR_TYPES_WLR_SCREENSHOOTER_H -#define WLR_TYPES_WLR_SCREENSHOOTER_H - -#include - -/** - * A very basic screenshooter interrface which implements the Orbital protocol. - */ -struct wlr_screenshooter { - struct wl_global *global; - struct wl_list screenshots; // wlr_screenshot::link - - struct wl_listener display_destroy; - - struct { - struct wl_signal destroy; - } events; - - void *data; -}; - -struct wlr_screenshot { - struct wl_resource *resource; - struct wl_resource *output_resource; - struct wl_list link; - - struct wlr_output *output; - struct wlr_screenshooter *screenshooter; - - void* data; -}; - -struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display); -void wlr_screenshooter_destroy(struct wlr_screenshooter *screenshooter); - -#endif diff --git a/protocol/gamma-control.xml b/protocol/gamma-control.xml deleted file mode 100644 index e6e33265..00000000 --- a/protocol/gamma-control.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - Copyright © 2015 Giulio camuffo - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/protocol/meson.build b/protocol/meson.build index 7cc10320..7e4c5606 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -25,11 +25,9 @@ protocols = [ [wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], - 'gamma-control.xml', 'gtk-primary-selection.xml', 'idle.xml', 'input-method-unstable-v2.xml', - 'screenshooter.xml', 'server-decoration.xml', 'virtual-keyboard-unstable-v1.xml', 'wlr-data-control-unstable-v1.xml', @@ -52,7 +50,6 @@ client_protocols = [ [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'], 'idle.xml', 'input-method-unstable-v2.xml', - 'screenshooter.xml', 'wlr-export-dmabuf-unstable-v1.xml', 'wlr-foreign-toplevel-management-unstable-v1.xml', 'wlr-gamma-control-unstable-v1.xml', diff --git a/protocol/screenshooter.xml b/protocol/screenshooter.xml deleted file mode 100644 index fc48eac9..00000000 --- a/protocol/screenshooter.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/rootston/desktop.c b/rootston/desktop.c index 96063995..3d9888e3 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -379,11 +378,8 @@ struct roots_desktop *desktop_create(struct roots_server *server, } #endif - desktop->gamma_control_manager = wlr_gamma_control_manager_create( - server->wl_display); desktop->gamma_control_manager_v1 = wlr_gamma_control_manager_v1_create( server->wl_display); - desktop->screenshooter = wlr_screenshooter_create(server->wl_display); desktop->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display); desktop->server_decoration_manager = diff --git a/types/meson.build b/types/meson.build index 72d3f84a..94d37873 100644 --- a/types/meson.build +++ b/types/meson.build @@ -32,7 +32,6 @@ lib_wlr_types = static_library( 'wlr_foreign_toplevel_management_v1.c', 'wlr_fullscreen_shell_v1.c', 'wlr_gamma_control_v1.c', - 'wlr_gamma_control.c', 'wlr_gtk_primary_selection.c', 'wlr_idle_inhibit_v1.c', 'wlr_idle.c', @@ -57,7 +56,6 @@ lib_wlr_types = static_library( 'wlr_region.c', 'wlr_relative_pointer_v1.c', 'wlr_screencopy_v1.c', - 'wlr_screenshooter.c', 'wlr_server_decoration.c', 'wlr_surface.c', 'wlr_switch.c', diff --git a/types/wlr_gamma_control.c b/types/wlr_gamma_control.c deleted file mode 100644 index 40ca2aca..00000000 --- a/types/wlr_gamma_control.c +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "gamma-control-protocol.h" -#include "util/signal.h" - -static void resource_destroy(struct wl_client *client, - struct wl_resource *resource) { - wl_resource_destroy(resource); -} - -static void gamma_control_destroy(struct wlr_gamma_control *gamma_control) { - if (gamma_control == NULL) { - return; - } - wlr_signal_emit_safe(&gamma_control->events.destroy, gamma_control); - wl_list_remove(&gamma_control->output_destroy_listener.link); - wl_resource_set_user_data(gamma_control->resource, NULL); - wl_list_remove(&gamma_control->link); - free(gamma_control); -} - -static const struct gamma_control_interface gamma_control_impl; - -static struct wlr_gamma_control *gamma_control_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, &gamma_control_interface, - &gamma_control_impl)); - return wl_resource_get_user_data(resource); -} - -static void gamma_control_destroy_resource(struct wl_resource *resource) { - struct wlr_gamma_control *gamma_control = - gamma_control_from_resource(resource); - gamma_control_destroy(gamma_control); -} - -static void gamma_control_handle_output_destroy(struct wl_listener *listener, - void *data) { - struct wlr_gamma_control *gamma_control = - wl_container_of(listener, gamma_control, output_destroy_listener); - gamma_control_destroy(gamma_control); -} - -static void gamma_control_set_gamma(struct wl_client *client, - struct wl_resource *gamma_control_resource, struct wl_array *red, - struct wl_array *green, struct wl_array *blue) { - struct wlr_gamma_control *gamma_control = - gamma_control_from_resource(gamma_control_resource); - - if (gamma_control == NULL) { - return; - } - - if (red->size != green->size || red->size != blue->size) { - wl_resource_post_error(gamma_control_resource, - GAMMA_CONTROL_ERROR_INVALID_GAMMA, - "The gamma ramps don't have the same size"); - return; - } - - uint32_t size = red->size / sizeof(uint16_t); - uint16_t *r = (uint16_t *)red->data; - uint16_t *g = (uint16_t *)green->data; - uint16_t *b = (uint16_t *)blue->data; - - wlr_output_set_gamma(gamma_control->output, size, r, g, b); -} - -static void gamma_control_reset_gamma(struct wl_client *client, - struct wl_resource *gamma_control_resource) { - // TODO -} - -static const struct gamma_control_interface gamma_control_impl = { - .destroy = resource_destroy, - .set_gamma = gamma_control_set_gamma, - .reset_gamma = gamma_control_reset_gamma, -}; - -static const struct gamma_control_manager_interface gamma_control_manager_impl; - -static struct wlr_gamma_control_manager *gamma_control_manager_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, &gamma_control_manager_interface, - &gamma_control_manager_impl)); - return wl_resource_get_user_data(resource); -} - -static void gamma_control_manager_get_gamma_control(struct wl_client *client, - struct wl_resource *gamma_control_manager_resource, uint32_t id, - struct wl_resource *output_resource) { - struct wlr_gamma_control_manager *manager = - gamma_control_manager_from_resource(gamma_control_manager_resource); - struct wlr_output *output = wlr_output_from_resource(output_resource); - - struct wlr_gamma_control *gamma_control = - calloc(1, sizeof(struct wlr_gamma_control)); - if (gamma_control == NULL) { - wl_client_post_no_memory(client); - return; - } - gamma_control->output = output; - - int version = wl_resource_get_version(gamma_control_manager_resource); - gamma_control->resource = wl_resource_create(client, - &gamma_control_interface, version, id); - if (gamma_control->resource == NULL) { - free(gamma_control); - wl_client_post_no_memory(client); - return; - } - wlr_log(WLR_DEBUG, "new gamma_control %p (res %p)", gamma_control, - gamma_control->resource); - wl_resource_set_implementation(gamma_control->resource, - &gamma_control_impl, gamma_control, gamma_control_destroy_resource); - - wl_signal_init(&gamma_control->events.destroy); - - wl_signal_add(&output->events.destroy, - &gamma_control->output_destroy_listener); - gamma_control->output_destroy_listener.notify = - gamma_control_handle_output_destroy; - - wl_list_insert(&manager->controls, &gamma_control->link); - - gamma_control_send_gamma_size(gamma_control->resource, - wlr_output_get_gamma_size(output)); -} - -static const struct gamma_control_manager_interface gamma_control_manager_impl = { - .get_gamma_control = gamma_control_manager_get_gamma_control, -}; - -static void gamma_control_manager_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - struct wlr_gamma_control_manager *manager = data; - assert(client && manager); - - struct wl_resource *resource = wl_resource_create(client, - &gamma_control_manager_interface, version, id); - if (resource == NULL) { - wl_client_post_no_memory(client); - return; - } - wl_resource_set_implementation(resource, &gamma_control_manager_impl, - manager, NULL); -} - -void wlr_gamma_control_manager_destroy( - struct wlr_gamma_control_manager *manager) { - if (!manager) { - return; - } - struct wlr_gamma_control *gamma_control, *tmp; - wl_list_for_each_safe(gamma_control, tmp, &manager->controls, link) { - gamma_control_destroy(gamma_control); - } - wlr_signal_emit_safe(&manager->events.destroy, manager); - wl_list_remove(&manager->display_destroy.link); - wl_global_destroy(manager->global); - free(manager); -} - -static void handle_display_destroy(struct wl_listener *listener, void *data) { - struct wlr_gamma_control_manager *manager = - wl_container_of(listener, manager, display_destroy); - wlr_gamma_control_manager_destroy(manager); -} - -struct wlr_gamma_control_manager *wlr_gamma_control_manager_create( - struct wl_display *display) { - struct wlr_gamma_control_manager *manager = - calloc(1, sizeof(struct wlr_gamma_control_manager)); - if (!manager) { - return NULL; - } - struct wl_global *global = wl_global_create(display, - &gamma_control_manager_interface, 1, manager, - gamma_control_manager_bind); - if (!global) { - free(manager); - return NULL; - } - manager->global = global; - - wl_signal_init(&manager->events.destroy); - wl_list_init(&manager->controls); - - manager->display_destroy.notify = handle_display_destroy; - wl_display_add_destroy_listener(display, &manager->display_destroy); - - return manager; -} diff --git a/types/wlr_screenshooter.c b/types/wlr_screenshooter.c deleted file mode 100644 index 63309050..00000000 --- a/types/wlr_screenshooter.c +++ /dev/null @@ -1,217 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "screenshooter-protocol.h" -#include "util/signal.h" - -static struct wlr_screenshot *screenshot_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, &orbital_screenshot_interface, - NULL)); - return wl_resource_get_user_data(resource); -} - -struct screenshot_state { - struct wl_shm_buffer *shm_buffer; - struct wlr_screenshot *screenshot; - struct wl_listener frame_listener; -}; - -static void screenshot_destroy(struct wlr_screenshot *screenshot) { - wl_list_remove(&screenshot->link); - wl_resource_set_user_data(screenshot->resource, NULL); - free(screenshot); -} - -static void handle_screenshot_resource_destroy( - struct wl_resource *screenshot_resource) { - struct wlr_screenshot *screenshot = - screenshot_from_resource(screenshot_resource); - if (screenshot != NULL) { - screenshot_destroy(screenshot); - } -} - -static void output_handle_frame(struct wl_listener *listener, void *_data) { - struct screenshot_state *state = wl_container_of(listener, state, - frame_listener); - struct wlr_output *output = state->screenshot->output; - struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); - struct wl_shm_buffer *shm_buffer = state->shm_buffer; - - if (!(output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) { - return; - } - - enum wl_shm_format format = wl_shm_buffer_get_format(shm_buffer); - int32_t width = wl_shm_buffer_get_width(shm_buffer); - int32_t height = wl_shm_buffer_get_height(shm_buffer); - int32_t stride = wl_shm_buffer_get_stride(shm_buffer); - wl_shm_buffer_begin_access(shm_buffer); - void *data = wl_shm_buffer_get_data(shm_buffer); - bool ok = wlr_renderer_read_pixels(renderer, format, NULL, stride, - width, height, 0, 0, 0, 0, data); - wl_shm_buffer_end_access(shm_buffer); - - if (!ok) { - wlr_log(WLR_ERROR, "Cannot read pixels"); - goto cleanup; - } - - orbital_screenshot_send_done(state->screenshot->resource); - -cleanup: - wl_list_remove(&listener->link); - free(state); -} - -static const struct orbital_screenshooter_interface screenshooter_impl; - -static struct wlr_screenshooter *screenshooter_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, &orbital_screenshooter_interface, - &screenshooter_impl)); - return wl_resource_get_user_data(resource); -} - -static void screenshooter_shoot(struct wl_client *client, - struct wl_resource *screenshooter_resource, uint32_t id, - struct wl_resource *output_resource, - struct wl_resource *buffer_resource) { - struct wlr_screenshooter *screenshooter = - screenshooter_from_resource(screenshooter_resource); - struct wlr_output *output = wlr_output_from_resource(output_resource); - - struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); - if (renderer == NULL) { - wlr_log(WLR_ERROR, "Backend doesn't have a renderer"); - return; - } - - struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get(buffer_resource); - if (shm_buffer == NULL) { - wlr_log(WLR_ERROR, "Invalid buffer: not a shared memory buffer"); - return; - } - - int32_t width = wl_shm_buffer_get_width(shm_buffer); - int32_t height = wl_shm_buffer_get_height(shm_buffer); - if (width < output->width || height < output->height) { - wlr_log(WLR_ERROR, "Invalid buffer: too small"); - return; - } - - uint32_t format = wl_shm_buffer_get_format(shm_buffer); - if (!wlr_renderer_format_supported(renderer, format)) { - wlr_log(WLR_ERROR, "Invalid buffer: unsupported format"); - return; - } - - struct wlr_screenshot *screenshot = - calloc(1, sizeof(struct wlr_screenshot)); - if (!screenshot) { - wl_resource_post_no_memory(screenshooter_resource); - return; - } - screenshot->output_resource = output_resource; - screenshot->output = output; - screenshot->screenshooter = screenshooter; - screenshot->resource = wl_resource_create(client, - &orbital_screenshot_interface, - wl_resource_get_version(screenshooter_resource), id); - if (screenshot->resource == NULL) { - free(screenshot); - wl_resource_post_no_memory(screenshooter_resource); - return; - } - wl_resource_set_implementation(screenshot->resource, NULL, screenshot, - handle_screenshot_resource_destroy); - wl_list_insert(&screenshooter->screenshots, &screenshot->link); - - wlr_log(WLR_DEBUG, "new screenshot %p (res %p)", screenshot, - screenshot->resource); - - struct screenshot_state *state = calloc(1, sizeof(struct screenshot_state)); - if (!state) { - wl_resource_destroy(screenshot->resource); - free(screenshot); - wl_resource_post_no_memory(screenshooter_resource); - return; - } - state->shm_buffer = shm_buffer; - state->screenshot = screenshot; - state->frame_listener.notify = output_handle_frame; - wl_signal_add(&output->events.precommit, &state->frame_listener); - - // Schedule a buffer commit - output->needs_frame = true; - wlr_output_schedule_frame(output); -} - -static const struct orbital_screenshooter_interface screenshooter_impl = { - .shoot = screenshooter_shoot, -}; - -static void screenshooter_bind(struct wl_client *wl_client, void *data, - uint32_t version, uint32_t id) { - struct wlr_screenshooter *screenshooter = data; - assert(wl_client && screenshooter); - - struct wl_resource *wl_resource = wl_resource_create(wl_client, - &orbital_screenshooter_interface, version, id); - if (wl_resource == NULL) { - wl_client_post_no_memory(wl_client); - return; - } - wl_resource_set_implementation(wl_resource, &screenshooter_impl, - screenshooter, NULL); -} - -void wlr_screenshooter_destroy(struct wlr_screenshooter *screenshooter) { - if (!screenshooter) { - return; - } - wl_list_remove(&screenshooter->display_destroy.link); - struct wlr_screenshot *screenshot, *tmp; - wl_list_for_each_safe(screenshot, tmp, &screenshooter->screenshots, link) { - screenshot_destroy(screenshot); - } - wlr_signal_emit_safe(&screenshooter->events.destroy, screenshooter); - wl_global_destroy(screenshooter->global); - free(screenshooter); -} - -static void handle_display_destroy(struct wl_listener *listener, void *data) { - struct wlr_screenshooter *screenshooter = - wl_container_of(listener, screenshooter, display_destroy); - wlr_screenshooter_destroy(screenshooter); -} - -struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display) { - struct wlr_screenshooter *screenshooter = - calloc(1, sizeof(struct wlr_screenshooter)); - if (!screenshooter) { - return NULL; - } - - wl_list_init(&screenshooter->screenshots); - wl_signal_init(&screenshooter->events.destroy); - - screenshooter->display_destroy.notify = handle_display_destroy; - wl_display_add_destroy_listener(display, &screenshooter->display_destroy); - - screenshooter->global = wl_global_create(display, - &orbital_screenshooter_interface, 1, screenshooter, screenshooter_bind); - if (screenshooter->global == NULL) { - free(screenshooter); - return NULL; - } - - return screenshooter; -}