These are undocumented, outdated protocols that have a better wlr-protocols equivalent.master
parent
abddd7b4db
commit
3dec88e455
@ -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 <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -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 <wayland-server.h>
|
|
||||||
|
|
||||||
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
|
|
@ -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 <wayland-server.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
@ -1,57 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<protocol name="gamma_control">
|
|
||||||
|
|
||||||
<copyright>
|
|
||||||
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.
|
|
||||||
</copyright>
|
|
||||||
|
|
||||||
<interface name="gamma_control_manager" version="1">
|
|
||||||
<request name="destroy" type="destructor"/>
|
|
||||||
|
|
||||||
<request name="get_gamma_control">
|
|
||||||
<arg name="id" type="new_id" interface="gamma_control"/>
|
|
||||||
<arg name="output" type="object" interface="wl_output"/>
|
|
||||||
</request>
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
<interface name="gamma_control" version="1">
|
|
||||||
<enum name="error">
|
|
||||||
<entry name="invalid_gamma" value="0"/>
|
|
||||||
</enum>
|
|
||||||
|
|
||||||
<request name="destroy" type="destructor"/>
|
|
||||||
|
|
||||||
<request name="set_gamma">
|
|
||||||
<arg name="red" type="array"/>
|
|
||||||
<arg name="green" type="array"/>
|
|
||||||
<arg name="blue" type="array"/>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="reset_gamma"/>
|
|
||||||
|
|
||||||
<event name="gamma_size">
|
|
||||||
<arg name="size" type="uint"/>
|
|
||||||
</event>
|
|
||||||
</interface>
|
|
||||||
</protocol>
|
|
@ -1,16 +0,0 @@
|
|||||||
<protocol name="orbital_screenshooter">
|
|
||||||
|
|
||||||
<interface name="orbital_screenshooter" version="1">
|
|
||||||
<request name="shoot">
|
|
||||||
<arg name="id" type="new_id" interface="orbital_screenshot"/>
|
|
||||||
<arg name="output" type="object" interface="wl_output"/>
|
|
||||||
<arg name="buffer" type="object" interface="wl_buffer"/>
|
|
||||||
</request>
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
<interface name="orbital_screenshot" version="1">
|
|
||||||
<event name="done">
|
|
||||||
</event>
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
</protocol>
|
|
@ -1,197 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <wayland-server.h>
|
|
||||||
#include <wlr/types/wlr_gamma_control.h>
|
|
||||||
#include <wlr/types/wlr_output.h>
|
|
||||||
#include <wlr/util/log.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -1,217 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <wayland-server.h>
|
|
||||||
#include <wlr/backend.h>
|
|
||||||
#include <wlr/render/wlr_renderer.h>
|
|
||||||
#include <wlr/types/wlr_output.h>
|
|
||||||
#include <wlr/types/wlr_screenshooter.h>
|
|
||||||
#include <wlr/util/log.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
Loading…
Reference in new issue