|
|
|
@ -32,14 +32,22 @@ |
|
|
|
|
#include <wayland-client.h> |
|
|
|
|
#include "screenshooter-client-protocol.h" |
|
|
|
|
|
|
|
|
|
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) |
|
|
|
|
|
|
|
|
|
/* The screenshooter is a good example of a custom object exposed by
|
|
|
|
|
* the compositor and serves as a test bed for implementing client |
|
|
|
|
* side marshalling outside libwayland.so */ |
|
|
|
|
|
|
|
|
|
static struct wl_output *output; |
|
|
|
|
static struct wl_shm *shm; |
|
|
|
|
static struct screenshooter *screenshooter; |
|
|
|
|
static int output_width, output_height; |
|
|
|
|
static struct wl_list output_list; |
|
|
|
|
|
|
|
|
|
struct screenshooter_output { |
|
|
|
|
struct wl_output *output; |
|
|
|
|
struct wl_buffer *buffer; |
|
|
|
|
int width, height, offset_x, offset_y; |
|
|
|
|
struct wl_list link; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
display_handle_geometry(void *data, |
|
|
|
@ -52,6 +60,14 @@ display_handle_geometry(void *data, |
|
|
|
|
const char *make, |
|
|
|
|
const char *model) |
|
|
|
|
{ |
|
|
|
|
struct screenshooter_output *output; |
|
|
|
|
|
|
|
|
|
output = wl_output_get_user_data(wl_output); |
|
|
|
|
|
|
|
|
|
if (wl_output == output->output) { |
|
|
|
|
output->offset_x = x; |
|
|
|
|
output->offset_y = y; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
@ -62,8 +78,15 @@ display_handle_mode(void *data, |
|
|
|
|
int height, |
|
|
|
|
int refresh) |
|
|
|
|
{ |
|
|
|
|
output_width = width; |
|
|
|
|
output_height = height; |
|
|
|
|
struct screenshooter_output *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 const struct wl_output_listener output_listener = { |
|
|
|
@ -75,9 +98,13 @@ static void |
|
|
|
|
handle_global(struct wl_display *display, uint32_t id, |
|
|
|
|
const char *interface, uint32_t version, void *data) |
|
|
|
|
{ |
|
|
|
|
static struct screenshooter_output *output; |
|
|
|
|
|
|
|
|
|
if (strcmp(interface, "wl_output") == 0) { |
|
|
|
|
output = wl_display_bind(display, id, &wl_output_interface); |
|
|
|
|
wl_output_add_listener(output, &output_listener, NULL); |
|
|
|
|
output = malloc(sizeof *output); |
|
|
|
|
output->output = wl_display_bind(display, id, &wl_output_interface); |
|
|
|
|
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_display_bind(display, id, &wl_shm_interface); |
|
|
|
|
} else if (strcmp(interface, "screenshooter") == 0) { |
|
|
|
@ -144,6 +171,8 @@ int main(int argc, char *argv[]) |
|
|
|
|
struct wl_display *display; |
|
|
|
|
struct wl_buffer *buffer; |
|
|
|
|
void *data = NULL; |
|
|
|
|
struct screenshooter_output *output, *next; |
|
|
|
|
int ss_area_width = 0, ss_area_height = 0, num_outputs = 0; |
|
|
|
|
|
|
|
|
|
display = wl_display_connect(NULL); |
|
|
|
|
if (display == NULL) { |
|
|
|
@ -151,6 +180,7 @@ int main(int argc, char *argv[]) |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
wl_list_init(&output_list); |
|
|
|
|
wl_display_add_global_listener(display, handle_global, &screenshooter); |
|
|
|
|
wl_display_iterate(display, WL_DISPLAY_READABLE); |
|
|
|
|
wl_display_roundtrip(display); |
|
|
|
@ -159,11 +189,32 @@ int main(int argc, char *argv[]) |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buffer = create_shm_buffer(output_width, output_height, &data); |
|
|
|
|
screenshooter_shoot(screenshooter, output, buffer); |
|
|
|
|
wl_list_for_each(output, &output_list, link) { |
|
|
|
|
|
|
|
|
|
if (!num_outputs) { |
|
|
|
|
ss_area_width = output->width + output->offset_x; |
|
|
|
|
ss_area_height = output->height + output->offset_y; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
ss_area_width = MAX(ss_area_width, output->offset_x + output->width); |
|
|
|
|
ss_area_height = MAX(ss_area_height, output->offset_y + output->height); |
|
|
|
|
} |
|
|
|
|
num_outputs++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buffer = create_shm_buffer(ss_area_width, ss_area_height, &data); |
|
|
|
|
|
|
|
|
|
wl_list_for_each(output, &output_list, link) { |
|
|
|
|
screenshooter_shoot(screenshooter, output->output, buffer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
wl_display_roundtrip(display); |
|
|
|
|
|
|
|
|
|
write_png(output_width, output_height, data); |
|
|
|
|
write_png(ss_area_width, ss_area_height, data); |
|
|
|
|
|
|
|
|
|
wl_list_for_each_safe(output, next, &output_list, link) { |
|
|
|
|
free(output); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|