screenshooter: Don't assume output offsets start at zero

dev
Scott Moreau 13 years ago committed by Kristian Høgsberg
parent 72c2372148
commit 2074f1d788
  1. 38
      clients/screenshot.c

@ -26,14 +26,14 @@
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h>
#include <sys/param.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <cairo.h> #include <cairo.h>
#include <wayland-client.h> #include <wayland-client.h>
#include "screenshooter-client-protocol.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 screenshooter is a good example of a custom object exposed by
* the compositor and serves as a test bed for implementing client * the compositor and serves as a test bed for implementing client
* side marshalling outside libwayland.so */ * side marshalling outside libwayland.so */
@ -41,6 +41,7 @@
static struct wl_shm *shm; static struct wl_shm *shm;
static struct screenshooter *screenshooter; static struct screenshooter *screenshooter;
static struct wl_list output_list; static struct wl_list output_list;
int min_x, min_y, max_x, max_y;
int buffer_copy_done; int buffer_copy_done;
struct screenshooter_output { struct screenshooter_output {
@ -182,7 +183,8 @@ write_png(int width, int height)
wl_list_for_each_safe(output, next, &output_list, link) { wl_list_for_each_safe(output, next, &output_list, link) {
output_stride = output->width * 4; output_stride = output->width * 4;
s = output->data; s = output->data;
d = data + output->offset_y * buffer_stride + output->offset_x * 4; d = data + (output->offset_y - min_y) * buffer_stride +
(output->offset_x - min_x) * 4;
for (i = 0; i < output->height; i++) { for (i = 0; i < output->height; i++) {
memcpy(d, s, output_stride); memcpy(d, s, output_stride);
@ -201,11 +203,34 @@ write_png(int width, int height)
free(data); free(data);
} }
static int
set_buffer_size(int *width, int *height)
{
struct screenshooter_output *output;
min_x = min_y = INT_MAX;
max_x = max_y = INT_MIN;
wl_list_for_each(output, &output_list, link) {
min_x = MIN(min_x, output->offset_x);
min_y = MIN(min_y, output->offset_y);
max_x = MAX(max_x, output->offset_x + output->width);
max_y = MAX(max_y, output->offset_y + output->height);
}
if (max_x <= min_x || max_y <= min_y)
return -1;
*width = max_x - min_x;
*height = max_y - min_y;
return 0;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct wl_display *display; struct wl_display *display;
struct screenshooter_output *output; struct screenshooter_output *output;
int width = 0, height = 0; int width, height;
display = wl_display_connect(NULL); display = wl_display_connect(NULL);
if (display == NULL) { if (display == NULL) {
@ -224,12 +249,13 @@ int main(int argc, char *argv[])
screenshooter_add_listener(screenshooter, &screenshooter_listener, screenshooter); screenshooter_add_listener(screenshooter, &screenshooter_listener, screenshooter);
if (set_buffer_size(&width, &height))
return -1;
wl_list_for_each(output, &output_list, link) { wl_list_for_each(output, &output_list, link) {
output->buffer = create_shm_buffer(output->width, output->height, &output->data); output->buffer = create_shm_buffer(output->width, output->height, &output->data);
screenshooter_shoot(screenshooter, output->output, output->buffer); screenshooter_shoot(screenshooter, output->output, output->buffer);
width = MAX(width, output->offset_x + output->width);
height = MAX(height, output->offset_y + output->height);
buffer_copy_done = 0; buffer_copy_done = 0;
while (!buffer_copy_done) while (!buffer_copy_done)
wl_display_roundtrip(display); wl_display_roundtrip(display);

Loading…
Cancel
Save