From 82cb2aeb0424e7f6928c47a466c36d447b860d99 Mon Sep 17 00:00:00 2001 From: shin jaejong Date: Wed, 21 Sep 2022 11:28:28 +0900 Subject: [PATCH] rename main source code --- Makefile | 2 +- screenshot.c | 1061 ---------------------------------------------------------- vncserver.c | 1061 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1062 insertions(+), 1062 deletions(-) delete mode 100644 screenshot.c create mode 100644 vncserver.c diff --git a/Makefile b/Makefile index a21b465..c31130a 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ LDFLAGS+=`pkg-config --libs libjpeg` all: $(GCC) $(CFLAGS) --sysroot $(SDKTARGETSYSROOT) $(LDFLAGS) $(INC) -o weston-vncserver \ - screenshot.c \ + vncserver.c \ protocol/pointer-constraints-unstable-v1-protocol.c \ protocol/relative-pointer-unstable-v1-protocol.c \ protocol/text-cursor-position-protocol.c \ diff --git a/screenshot.c b/screenshot.c deleted file mode 100644 index d586310..0000000 --- a/screenshot.c +++ /dev/null @@ -1,1061 +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. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "weston-screenshooter-client-protocol.h" -#include "shared/os-compatibility.h" -#include "shared/xalloc.h" -#include "shared/file-util.h" -#include "shared/cairo-util.h" -#include "shared/helpers.h" -#include "window.h" - -/* 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 */ - -int isloop = 1; -struct image *pimage; - -struct screenshooter_output -{ - struct wl_output *output; - struct wl_buffer *buffer; - int width, height, offset_x, offset_y; - void *data; - struct wl_list link; -}; - -struct buffer_size -{ - int width, height; - - int min_x, min_y; - int max_x, max_y; -}; - -struct screenshooter_data -{ - struct wl_shm *shm; - struct wl_list output_list; - - struct weston_screenshooter *screenshooter; - int buffer_copy_done; -}; - -struct image -{ - struct window *window; - struct widget *widget; - struct display *display; - char *filename; - cairo_surface_t *image; - int fullscreen; - int *image_counter; - int32_t width, height; - - struct - { - double x; - double y; - } pointer; - bool button_pressed; - - bool initialized; - cairo_matrix_t matrix; -}; - -struct display -{ - struct wl_display *display; - struct wl_registry *registry; - struct wl_compositor *compositor; - struct wl_subcompositor *subcompositor; - struct wl_shm *shm; - struct wl_data_device_manager *data_device_manager; - struct text_cursor_position *text_cursor_position; - struct xdg_wm_base *xdg_shell; - struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; - struct zwp_pointer_constraints_v1 *pointer_constraints; - EGLDisplay dpy; - EGLConfig argb_config; - EGLContext argb_ctx; - cairo_device_t *argb_device; - uint32_t serial; - - int display_fd; - uint32_t display_fd_events; - struct task display_task; - - int epoll_fd; - struct wl_list deferred_list; - - int running; - - struct wl_list global_list; - struct wl_list window_list; - struct wl_list input_list; - struct wl_list output_list; - - struct theme *theme; - - struct wl_cursor_theme *cursor_theme; - struct wl_cursor **cursors; - - display_output_handler_t output_configure_handler; - display_global_handler_t global_handler; - display_global_handler_t global_handler_remove; - - void *user_data; - - struct xkb_context *xkb_context; - - /* A hack to get text extents for tooltips */ - cairo_surface_t *dummy_surface; - void *dummy_surface_data; - - int data_device_manager_version; - struct wp_viewporter *viewporter; -}; - -static void handler_sigint(int sig) -{ - isloop = 0; -} - -static void -display_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) -{ - 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 -display_handle_mode(void *data, - struct wl_output *wl_output, - uint32_t flags, - int width, - int height, - int refresh) -{ - 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 = { - display_handle_geometry, - display_handle_mode -}; - -static void -screenshot_done(void *data, struct weston_screenshooter *screenshooter) -{ - struct screenshooter_data *sh_data = data; - sh_data->buffer_copy_done = 1; -} - -static const struct weston_screenshooter_listener screenshooter_listener = { - 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; - struct screenshooter_data *sh_data = data; - - if (strcmp(interface, "wl_output") == 0) - { - output = xmalloc(sizeof *output); - output->output = wl_registry_bind(registry, name, - &wl_output_interface, 1); - wl_list_insert(&sh_data->output_list, &output->link); - wl_output_add_listener(output->output, &output_listener, output); - } - else if (strcmp(interface, "wl_shm") == 0) - { - sh_data->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); - } - else if (strcmp(interface, "weston_screenshooter") == 0) - { - sh_data->screenshooter = wl_registry_bind(registry, name, - &weston_screenshooter_interface, - 1); - } -} - -static void -handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) -{ - /* XXX: unimplemented */ -} - -static const struct wl_registry_listener registry_listener = { - handle_global, - handle_global_remove -}; - -static struct wl_buffer * -screenshot_create_shm_buffer(int width, int height, void **data_out, - struct wl_shm *shm) -{ - struct wl_shm_pool *pool; - struct wl_buffer *buffer; - int fd, size, stride; - void *data; - - stride = width * 4; - size = stride * height; - - // printf("screenshot_create_shm_buffer width[%d] height[%d] stride[%d] size[%d]\n",width,height,stride,size); - fd = os_create_anonymous_file(size); - if (fd < 0) - { - fprintf(stderr, "creating a buffer file for %d B failed: %s\n", - size, strerror(errno)); - return NULL; - } - - data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) - { - fprintf(stderr, "mmap failed: %s\n", strerror(errno)); - close(fd); - return NULL; - } - - pool = wl_shm_create_pool(shm, fd, size); - close(fd); - 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 double -get_scale(struct image *image) -{ - assert(image->matrix.xy == 0.0 && - image->matrix.yx == 0.0 && - image->matrix.xx == image->matrix.yy); - return image->matrix.xx; -} - -static void -clamp_view(struct image *image) -{ - struct rectangle allocation; - double scale = get_scale(image); - double sw, sh; - // printf("clamp scale[%f]\n",scale); - // printf("clamp image->width[%d] height[%d]\n",image->width,image->height); - - sw = image->width * scale; - sh = image->height * scale; - widget_get_allocation(image->widget, &allocation); - - // printf("clamp sw[%f] sh[%f]\n",sw,sh); - // printf("clamp allocation.width[%d] height[%d]\n"),allocation.width,allocation.height; - - if (sw < allocation.width) - { - image->matrix.x0 = - (allocation.width - image->width * scale) / 2; - } - else - { - if (image->matrix.x0 > 0.0) - { - image->matrix.x0 = 0.0; - } - if (sw + image->matrix.x0 < allocation.width) - { - image->matrix.x0 = allocation.width - sw; - } - } - - if (sh < allocation.height) - { - image->matrix.y0 = - (allocation.height - image->height * scale) / 2; - } - else - { - if (image->matrix.y0 > 0.0) - { - image->matrix.y0 = 0.0; - } - if (sh + image->matrix.y0 < allocation.height) - { - image->matrix.y0 = allocation.height - sh; - } - } - - // printf("clamp matrix x0:%f y0:%fxx:%f xy:%f yx:%f yy:%f\n",image->matrix.x0,image->matrix.y0, image->matrix.xx,image->matrix.xy,image->matrix.yx,image->matrix.yy); - // printf("x0[%f] y0[%f]\n",image->matrix.x0, image->matrix.y0); -} - -static void -redraw_handler(struct widget *widget, void *data) -{ - struct image *image = data; - struct rectangle allocation; - cairo_t *cr; - cairo_surface_t *surface; - double width, height, doc_aspect, window_aspect, scale; - cairo_matrix_t matrix; - cairo_matrix_t translate; - - surface = window_get_surface(image->window); - cr = cairo_create(surface); - widget_get_allocation(image->widget, &allocation); - // printf("allocation x[%d] y[%d] width[%d] height[%d]\n", allocation.x, allocation.y, allocation.width,allocation.height); - - cairo_rectangle(cr, allocation.x, allocation.y, - allocation.width, allocation.height); - cairo_clip(cr); - cairo_push_group(cr); - cairo_translate(cr, allocation.x, allocation.y); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - // cairo_set_source_rgba(cr, 1, 0, 1, 0.5); // magenta transparency 50% - cairo_set_source_rgba(cr, 0, 0, 0, 0); - cairo_paint(cr); - - if (!image->initialized) - { - image->initialized = true; - width = cairo_image_surface_get_width(image->image); - height = cairo_image_surface_get_height(image->image); - - doc_aspect = width / height; - window_aspect = (double) allocation.width / allocation.height; - if (doc_aspect < window_aspect) - { - scale = allocation.height / height; - } - else - { - scale = allocation.width / width; - } - - // printf("doc_aspect[%f]\n",doc_aspect); - // printf("window_aspect[%f]\n",window_aspect); - // printf("scale[%f]\n",scale); - - image->width = width; - image->height = height; - cairo_matrix_init_scale(&image->matrix, scale, scale); - - clamp_view(image); - } - - matrix = image->matrix; - cairo_matrix_init_translate(&translate, allocation.x, allocation.y); - // printf("init matrix x0:%f y0:%f xx:%f xy:%f yx:%f yy:%f\n",matrix.x0,matrix.y0,matrix.xx,matrix.xy,matrix.yx,matrix.yy); - cairo_matrix_multiply(&matrix, &matrix, &translate); - // printf("mult matrix x0:%f y0:%f xx:%f xy:%f yx:%f yy:%f\n",matrix.x0,matrix.y0,matrix.xx,matrix.xy,matrix.yx,matrix.yy); - cairo_set_matrix(cr, &matrix); - - cairo_set_source_surface(cr, image->image, 0, 0); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_paint(cr); - - cairo_pop_group_to_source(cr); - cairo_paint(cr); - cairo_destroy(cr); - - cairo_surface_destroy(surface); -} - -static void -resize_handler(struct widget *widget, - int32_t width, int32_t height, void *data) -{ - struct image *image = data; - - clamp_view(image); -} - -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - struct image *image = data; - - window_schedule_redraw(image->window); -} - -static int -enter_handler(struct widget *widget, - struct input *input, - float x, float y, void *data) -{ - struct image *image = data; - struct rectangle allocation; - - widget_get_allocation(image->widget, &allocation); - x -= allocation.x; - y -= allocation.y; - - image->pointer.x = x; - image->pointer.y = y; - - return 1; -} - -static void -move_viewport(struct image *image, double dx, double dy) -{ - double scale = get_scale(image); - - if (!image->initialized) - { - return; - } - - cairo_matrix_translate(&image->matrix, -dx/scale, -dy/scale); - clamp_view(image); - - window_schedule_redraw(image->window); -} - -static int -motion_handler(struct widget *widget, - struct input *input, uint32_t time, - float x, float y, void *data) -{ - struct image *image = data; - struct rectangle allocation; - - widget_get_allocation(image->widget, &allocation); - x -= allocation.x; - y -= allocation.y; - - if (image->button_pressed) - { - move_viewport(image, image->pointer.x - x, - image->pointer.y - y); - } - - image->pointer.x = x; - image->pointer.y = y; - - return image->button_pressed ? CURSOR_DRAGGING : CURSOR_LEFT_PTR; -} - -static void -button_handler(struct widget *widget, - struct input *input, uint32_t time, - uint32_t button, - enum wl_pointer_button_state state, - void *data) -{ - struct image *image = data; - - if (button == BTN_LEFT) - { - image->button_pressed = - state == WL_POINTER_BUTTON_STATE_PRESSED; - - if (state == WL_POINTER_BUTTON_STATE_PRESSED) - { - input_set_pointer_image(input, CURSOR_DRAGGING); - } - else - { - input_set_pointer_image(input, CURSOR_LEFT_PTR); - } - } -} - -static void -zoom(struct image *image, double scale) -{ - double x = image->pointer.x; - double y = image->pointer.y; - cairo_matrix_t scale_matrix; - - if (!image->initialized) - { - return; - } - - if ((get_scale(image) * scale > 20.0) || - (get_scale(image) * scale < 0.02)) - { - return; - } - - cairo_matrix_init_identity(&scale_matrix); - cairo_matrix_translate(&scale_matrix, x, y); - cairo_matrix_scale(&scale_matrix, scale, scale); - cairo_matrix_translate(&scale_matrix, -x, -y); - - cairo_matrix_multiply(&image->matrix, &image->matrix, &scale_matrix); - clamp_view(image); -} - -static void -key_handler(struct window *window, struct input *input, uint32_t time, - uint32_t key, uint32_t sym, enum wl_keyboard_key_state state, - void *data) -{ - struct image *image = data; - int transform; - - if (state == WL_KEYBOARD_KEY_STATE_RELEASED) - { - return; - } - - // printf("XKB_KEY_f[%x] XKB_KEY_t[%x]\n",XKB_KEY_f,XKB_KEY_t); - // printf("sym[%x]\n",sym); - - switch (sym) - { -/* - case XKB_KEY_minus: - zoom(image, 0.8); - window_schedule_redraw(image->window); - break; - case XKB_KEY_equal: - case XKB_KEY_plus: - zoom(image, 1.2); - window_schedule_redraw(image->window); - break; - - case XKB_KEY_1: - image->matrix.xx = 1.0; - image->matrix.xy = 0.0; - image->matrix.yx = 0.0; - image->matrix.yy = 1.0; - clamp_view(image); - window_schedule_redraw(image->window); - break; - - case XKB_KEY_2: - image->matrix.xx = 0.5; - image->matrix.xy = 0.0; - image->matrix.yx = 0.0; - image->matrix.yy = 0.5; - clamp_view(image); - window_schedule_redraw(image->window); - break; - */ - case XKB_KEY_f: - image->fullscreen ^= 1; - printf("image->fullscreen[%d]\n",image->fullscreen); - - window_set_fullscreen(image->window, image->fullscreen); - clamp_view(image); - window_schedule_redraw(image->window); - break; - -/* - case XKB_KEY_t: - transform = window_get_buffer_transform (image->window); - printf("transform[%d]\n",transform); - transform = (transform + 1) % 8; - window_set_buffer_transform(image->window, transform); - window_schedule_redraw(image->window); - break; - */ - case XKB_KEY_q: - exit(0); - break; - } -} - -static void -axis_handler(struct widget *widget, struct input *input, uint32_t time, - uint32_t axis, wl_fixed_t value, void *data) -{ - struct image *image = data; - - if ((axis == WL_POINTER_AXIS_VERTICAL_SCROLL) && - (input_get_modifiers(input) == MOD_CONTROL_MASK)) - { - /* set zoom level to 2% per 10 axis units */ - zoom(image, (1.0 - wl_fixed_to_double(value) / 500.0)); - - window_schedule_redraw(image->window); - } - else if (input_get_modifiers(input) == 0) - { - if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) - { - move_viewport(image, 0, wl_fixed_to_double(value)); - } - else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) - { - move_viewport(image, wl_fixed_to_double(value), 0); - } - } -} - -static void -fullscreen_handler(struct window *window, void *data) -{ - struct image *image = data; - - // image->fullscreen ^= 1; - window_set_fullscreen(window, image->fullscreen); -} - -int is_pass_close_handler = 0; -static void -close_handler(void *data) -{ - struct image *image = data; - - *image->image_counter -= 1; - - if (*image->image_counter == 0) - { - display_exit(image->display); - } - - widget_destroy(image->widget); - window_destroy(image->window); - - free(image); - - is_pass_close_handler = 1; -} - -static char * -get_screenshot(const struct buffer_size *buff_size, - struct wl_list *output_list) -{ - int output_stride, buffer_stride, i; - cairo_surface_t *surface; - char *data, *d, *s; - struct screenshooter_output *output, *next; - FILE *fp; - char filepath[PATH_MAX]; - - buffer_stride = buff_size->width * 4; - - // printf("buffer_stride[%d] * buff_size->height[%d] = %d\n",buffer_stride, buff_size->height, buffer_stride * buff_size->height); - data = xmalloc(1024 * 4 * 768); - if (!data) - { - return; - } - - wl_list_for_each_safe(output, next, output_list, link) - { - if (output->offset_x == 0) - { - output_stride = 4; - d = data + 1024 * 4 * 767 + 1023 * 4; - s = output->data; - - for (i = 0; i < 1024*768; i++) - { - memcpy(d, s, output_stride); - d -= output_stride; - s += output_stride; - } - - wl_buffer_destroy(output->buffer); - int ret = munmap(output->data, 1024*4*768); - // printf("munmap error[%d]\n",ret); - // printf("%s\n",strerror(errno)); - // free(output->buffer); - } - - wl_registry_destroy(output->output); - free(output); - } - - // fp = file_create_dated("/tmp", "raw-", - // ".png", filepath, sizeof(filepath)); - // if (fp) { - // fwrite(data, 1, 1024 * 4 * 768, fp); - // fclose (fp); - // } - - return data; -} - -static struct image * -image_create(struct display *display, const char *filename, - int *image_counter, char *cap_img) -{ - struct image *image; - char *b, *copy, title[512]; - - image = zalloc(sizeof *image); - if (image == NULL) - { - return image; - } - - sprintf(title,"weston_clone_app"); - image->filename = strdup(title); - - image->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32, 1024, 768, 1024*4); - double width = cairo_image_surface_get_width(image->image); - double height = cairo_image_surface_get_height(image->image); - printf("1 width[%f] height[%f]\n",width,height); - - if (!image->image) - { - free(image->filename); - free(image); - - printf("image->image failed\n"); - return NULL; - } - - image->window = window_create(display); - image->widget = window_frame_create(image->window, image); - window_set_title(image->window, title); - image->display = display; - image->image_counter = image_counter; - *image_counter += 1; - image->initialized = false; - - window_set_user_data(image->window, image); - widget_set_redraw_handler(image->widget, redraw_handler); - // widget_set_resize_handler(image->widget, resize_handler); - // window_set_keyboard_focus_handler(image->window, keyboard_focus_handler); - // window_set_fullscreen_handler(image->window, fullscreen_handler); - window_set_close_handler(image->window, close_handler); - - // widget_set_enter_handler(image->widget, enter_handler); - // widget_set_motion_handler(image->widget, motion_handler); - // widget_set_button_handler(image->widget, button_handler); - // widget_set_axis_handler(image->widget, axis_handler); - window_set_key_handler(image->window, key_handler); - widget_schedule_resize(image->widget, 600, 400); - - return image; -} - -static void display_run_nonloop(struct display *display) -{ - struct task *task; - struct epoll_event ep[16]; - int i, count, ret; - int idx = 0; - - display->running = 1; - // while (1) - { - while (!wl_list_empty(&display->deferred_list)) - { - task = container_of(display->deferred_list.prev, - struct task, link); - wl_list_remove(&task->link); - task->run(task, 0); - } - - wl_display_dispatch_pending(display->display); - - ret = wl_display_flush(display->display); - if ((ret < 0) && (errno == EAGAIN)) - { - ep[0].events = - EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP; - ep[0].data.ptr = &display->display_task; - - epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, - display->display_fd, &ep[0]); - } - else if (ret < 0) - { - // break; - return; - } - - count = epoll_wait(display->epoll_fd, - ep, ARRAY_LENGTH(ep), -1); - for (i = 0; i < count; i++) - { - task = ep[i].data.ptr; - task->run(task, ep[i].events); - } - } -} - -static int -screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list) -{ - struct screenshooter_output *output; - buff_size->min_x = buff_size->min_y = INT_MAX; - buff_size->max_x = buff_size->max_y = INT_MIN; - int position = 0; - - wl_list_for_each_reverse(output, output_list, link) - { - output->offset_x = position; - position += output->width; - } - - wl_list_for_each(output, output_list, link) - { - buff_size->min_x = MIN(buff_size->min_x, output->offset_x); - buff_size->min_y = MIN(buff_size->min_y, output->offset_y); - buff_size->max_x = - MAX(buff_size->max_x, output->offset_x + output->width); - buff_size->max_y = - MAX(buff_size->max_y, output->offset_y + output->height); - } - - if ((buff_size->max_x <= buff_size->min_x) || - (buff_size->max_y <= buff_size->min_y)) - { - return -1; - } - - buff_size->width = buff_size->max_x - buff_size->min_x; - buff_size->height = buff_size->max_y - buff_size->min_y; - - return 0; -} - -char *get_weston_screen_image() -{ - struct wl_display *display_cap; // screenshooter variable - struct wl_registry *registry; - struct screenshooter_output *output; - struct buffer_size buff_size = {}; - struct screenshooter_data sh_data = {}; - char *cap_img = NULL; - - // start of screenshoot - display_cap = wl_display_connect(NULL); - if (display_cap == NULL) - { - fprintf(stderr, "failed to create display: %s\n", - strerror(errno)); - return -1; - } - - wl_list_init(&sh_data.output_list); - registry = wl_display_get_registry(display_cap); - wl_registry_add_listener(registry, ®istry_listener, &sh_data); - wl_display_dispatch(display_cap); - // printf("0.1 sh_data.shm[%p]\n",sh_data.shm); - wl_display_roundtrip(display_cap); - if (sh_data.screenshooter == NULL) - { - fprintf(stderr, "display doesn't support screenshooter\n"); - return -1; - } - weston_screenshooter_add_listener(sh_data.screenshooter, - &screenshooter_listener, - &sh_data); - if (screenshot_set_buffer_size(&buff_size, &sh_data.output_list)) - { - printf("screenshot_set_buffer_size fail\n"); - // continue; - return -1; - } - - int idx = 0; - wl_list_for_each(output, &sh_data.output_list, link) - { - if ((output->offset_x == 0) && - ((output->width == 1024) && (output->height == 768))) - { - // printf("output->offset_x[%d]\n",output->offset_x); - output->buffer = - screenshot_create_shm_buffer(output->width, - output->height, - &output->data, - sh_data.shm); - if (output->buffer == NULL) - { - continue; - } - - weston_screenshooter_shoot(sh_data.screenshooter, - output->output, - output->buffer); - - sh_data.buffer_copy_done = 0; - wl_display_roundtrip(display_cap); - usleep(35000); - - while (!sh_data.buffer_copy_done) - { - wl_display_roundtrip(display_cap); - usleep(1000); - } - } - } - // end of screenshoot - - if (buff_size.height == 768) - { - cap_img = get_screenshot(&buff_size, &sh_data.output_list); - } - else - { - struct screenshooter_output *output, *next; - wl_list_for_each_safe(output, next, &sh_data.output_list, link) - { - int ret = munmap(output->data, 1024*4*768); - // printf("munmap error[%d]\n",ret); - // printf("%s\n",strerror(errno)); - - wl_registry_destroy(output->output); - wl_list_remove(&output->link); - wl_buffer_destroy(output->buffer); - // free(output->buffer); - free(output); - } - } - - wl_registry_destroy(sh_data.shm); - wl_registry_destroy(sh_data.screenshooter); - - wl_registry_destroy(registry); - wl_display_disconnect(display_cap); - - return cap_img; -} - -int main(int argc, char *argv[]) -{ - struct display *d; // image.c variable - int i; - int image_counter = 0; - char *cap_img = NULL; - struct timespec start_time, end_time; - - d = display_create(&argc, argv); - cap_img = get_weston_screen_image(); - pimage = image_create(d, argv[i], &image_counter,cap_img); - - // full screen with 1x zoom scale - window_set_fullscreen(pimage->window, pimage->fullscreen = 1); - pimage->matrix.xx = 1.0; - pimage->matrix.xy = 0.0; - pimage->matrix.yx = 0.0; - pimage->matrix.yy = 1.0; - clamp_view(pimage); - window_schedule_redraw(pimage->window); - display_run_nonloop(d); - - struct sigaction sigint; - sigint.sa_handler = handler_sigint; - sigemptyset(&sigint.sa_mask); - sigint.sa_flags = SA_RESETHAND; - sigaction(SIGINT, &sigint, NULL); - - clock_gettime(CLOCK_MONOTONIC, &end_time); - memcpy(&start_time, &end_time, sizeof(struct timespec)); - - int loop = 0; - long long usec; - while (isloop) - { - // ui loop - display_run_nonloop(d); // 20 msec - - // reload image - free(cap_img); - cap_img = get_weston_screen_image(); // 80 msec - cairo_surface_destroy(pimage->image); // 70 usec - pimage->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32,1024, 768, 1024*4); - - // ui redraw request - window_schedule_redraw(pimage->window); - - // fps calc. - clock_gettime(CLOCK_MONOTONIC, &end_time); - usec = (end_time.tv_sec - start_time.tv_sec) * 1000000 + (end_time.tv_nsec - start_time.tv_nsec) / 1000; - // printf("%d : %lld usec / %lld fps\n", loop++, usec, 1000000UL / usec); - memcpy(&start_time, &end_time, sizeof(struct timespec)); - } - - free(cap_img); - if (!is_pass_close_handler) - { - widget_destroy(pimage->widget); - window_destroy(pimage->window); - } - cairo_surface_destroy(pimage->image); - free(pimage); - - display_destroy(d); - - return 0; -} diff --git a/vncserver.c b/vncserver.c new file mode 100644 index 0000000..d586310 --- /dev/null +++ b/vncserver.c @@ -0,0 +1,1061 @@ +/* + * 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. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "weston-screenshooter-client-protocol.h" +#include "shared/os-compatibility.h" +#include "shared/xalloc.h" +#include "shared/file-util.h" +#include "shared/cairo-util.h" +#include "shared/helpers.h" +#include "window.h" + +/* 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 */ + +int isloop = 1; +struct image *pimage; + +struct screenshooter_output +{ + struct wl_output *output; + struct wl_buffer *buffer; + int width, height, offset_x, offset_y; + void *data; + struct wl_list link; +}; + +struct buffer_size +{ + int width, height; + + int min_x, min_y; + int max_x, max_y; +}; + +struct screenshooter_data +{ + struct wl_shm *shm; + struct wl_list output_list; + + struct weston_screenshooter *screenshooter; + int buffer_copy_done; +}; + +struct image +{ + struct window *window; + struct widget *widget; + struct display *display; + char *filename; + cairo_surface_t *image; + int fullscreen; + int *image_counter; + int32_t width, height; + + struct + { + double x; + double y; + } pointer; + bool button_pressed; + + bool initialized; + cairo_matrix_t matrix; +}; + +struct display +{ + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; + struct wl_shm *shm; + struct wl_data_device_manager *data_device_manager; + struct text_cursor_position *text_cursor_position; + struct xdg_wm_base *xdg_shell; + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; + struct zwp_pointer_constraints_v1 *pointer_constraints; + EGLDisplay dpy; + EGLConfig argb_config; + EGLContext argb_ctx; + cairo_device_t *argb_device; + uint32_t serial; + + int display_fd; + uint32_t display_fd_events; + struct task display_task; + + int epoll_fd; + struct wl_list deferred_list; + + int running; + + struct wl_list global_list; + struct wl_list window_list; + struct wl_list input_list; + struct wl_list output_list; + + struct theme *theme; + + struct wl_cursor_theme *cursor_theme; + struct wl_cursor **cursors; + + display_output_handler_t output_configure_handler; + display_global_handler_t global_handler; + display_global_handler_t global_handler_remove; + + void *user_data; + + struct xkb_context *xkb_context; + + /* A hack to get text extents for tooltips */ + cairo_surface_t *dummy_surface; + void *dummy_surface_data; + + int data_device_manager_version; + struct wp_viewporter *viewporter; +}; + +static void handler_sigint(int sig) +{ + isloop = 0; +} + +static void +display_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) +{ + 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 +display_handle_mode(void *data, + struct wl_output *wl_output, + uint32_t flags, + int width, + int height, + int refresh) +{ + 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 = { + display_handle_geometry, + display_handle_mode +}; + +static void +screenshot_done(void *data, struct weston_screenshooter *screenshooter) +{ + struct screenshooter_data *sh_data = data; + sh_data->buffer_copy_done = 1; +} + +static const struct weston_screenshooter_listener screenshooter_listener = { + 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; + struct screenshooter_data *sh_data = data; + + if (strcmp(interface, "wl_output") == 0) + { + output = xmalloc(sizeof *output); + output->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + wl_list_insert(&sh_data->output_list, &output->link); + wl_output_add_listener(output->output, &output_listener, output); + } + else if (strcmp(interface, "wl_shm") == 0) + { + sh_data->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); + } + else if (strcmp(interface, "weston_screenshooter") == 0) + { + sh_data->screenshooter = wl_registry_bind(registry, name, + &weston_screenshooter_interface, + 1); + } +} + +static void +handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + /* XXX: unimplemented */ +} + +static const struct wl_registry_listener registry_listener = { + handle_global, + handle_global_remove +}; + +static struct wl_buffer * +screenshot_create_shm_buffer(int width, int height, void **data_out, + struct wl_shm *shm) +{ + struct wl_shm_pool *pool; + struct wl_buffer *buffer; + int fd, size, stride; + void *data; + + stride = width * 4; + size = stride * height; + + // printf("screenshot_create_shm_buffer width[%d] height[%d] stride[%d] size[%d]\n",width,height,stride,size); + fd = os_create_anonymous_file(size); + if (fd < 0) + { + fprintf(stderr, "creating a buffer file for %d B failed: %s\n", + size, strerror(errno)); + return NULL; + } + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) + { + fprintf(stderr, "mmap failed: %s\n", strerror(errno)); + close(fd); + return NULL; + } + + pool = wl_shm_create_pool(shm, fd, size); + close(fd); + 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 double +get_scale(struct image *image) +{ + assert(image->matrix.xy == 0.0 && + image->matrix.yx == 0.0 && + image->matrix.xx == image->matrix.yy); + return image->matrix.xx; +} + +static void +clamp_view(struct image *image) +{ + struct rectangle allocation; + double scale = get_scale(image); + double sw, sh; + // printf("clamp scale[%f]\n",scale); + // printf("clamp image->width[%d] height[%d]\n",image->width,image->height); + + sw = image->width * scale; + sh = image->height * scale; + widget_get_allocation(image->widget, &allocation); + + // printf("clamp sw[%f] sh[%f]\n",sw,sh); + // printf("clamp allocation.width[%d] height[%d]\n"),allocation.width,allocation.height; + + if (sw < allocation.width) + { + image->matrix.x0 = + (allocation.width - image->width * scale) / 2; + } + else + { + if (image->matrix.x0 > 0.0) + { + image->matrix.x0 = 0.0; + } + if (sw + image->matrix.x0 < allocation.width) + { + image->matrix.x0 = allocation.width - sw; + } + } + + if (sh < allocation.height) + { + image->matrix.y0 = + (allocation.height - image->height * scale) / 2; + } + else + { + if (image->matrix.y0 > 0.0) + { + image->matrix.y0 = 0.0; + } + if (sh + image->matrix.y0 < allocation.height) + { + image->matrix.y0 = allocation.height - sh; + } + } + + // printf("clamp matrix x0:%f y0:%fxx:%f xy:%f yx:%f yy:%f\n",image->matrix.x0,image->matrix.y0, image->matrix.xx,image->matrix.xy,image->matrix.yx,image->matrix.yy); + // printf("x0[%f] y0[%f]\n",image->matrix.x0, image->matrix.y0); +} + +static void +redraw_handler(struct widget *widget, void *data) +{ + struct image *image = data; + struct rectangle allocation; + cairo_t *cr; + cairo_surface_t *surface; + double width, height, doc_aspect, window_aspect, scale; + cairo_matrix_t matrix; + cairo_matrix_t translate; + + surface = window_get_surface(image->window); + cr = cairo_create(surface); + widget_get_allocation(image->widget, &allocation); + // printf("allocation x[%d] y[%d] width[%d] height[%d]\n", allocation.x, allocation.y, allocation.width,allocation.height); + + cairo_rectangle(cr, allocation.x, allocation.y, + allocation.width, allocation.height); + cairo_clip(cr); + cairo_push_group(cr); + cairo_translate(cr, allocation.x, allocation.y); + + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + // cairo_set_source_rgba(cr, 1, 0, 1, 0.5); // magenta transparency 50% + cairo_set_source_rgba(cr, 0, 0, 0, 0); + cairo_paint(cr); + + if (!image->initialized) + { + image->initialized = true; + width = cairo_image_surface_get_width(image->image); + height = cairo_image_surface_get_height(image->image); + + doc_aspect = width / height; + window_aspect = (double) allocation.width / allocation.height; + if (doc_aspect < window_aspect) + { + scale = allocation.height / height; + } + else + { + scale = allocation.width / width; + } + + // printf("doc_aspect[%f]\n",doc_aspect); + // printf("window_aspect[%f]\n",window_aspect); + // printf("scale[%f]\n",scale); + + image->width = width; + image->height = height; + cairo_matrix_init_scale(&image->matrix, scale, scale); + + clamp_view(image); + } + + matrix = image->matrix; + cairo_matrix_init_translate(&translate, allocation.x, allocation.y); + // printf("init matrix x0:%f y0:%f xx:%f xy:%f yx:%f yy:%f\n",matrix.x0,matrix.y0,matrix.xx,matrix.xy,matrix.yx,matrix.yy); + cairo_matrix_multiply(&matrix, &matrix, &translate); + // printf("mult matrix x0:%f y0:%f xx:%f xy:%f yx:%f yy:%f\n",matrix.x0,matrix.y0,matrix.xx,matrix.xy,matrix.yx,matrix.yy); + cairo_set_matrix(cr, &matrix); + + cairo_set_source_surface(cr, image->image, 0, 0); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_paint(cr); + + cairo_pop_group_to_source(cr); + cairo_paint(cr); + cairo_destroy(cr); + + cairo_surface_destroy(surface); +} + +static void +resize_handler(struct widget *widget, + int32_t width, int32_t height, void *data) +{ + struct image *image = data; + + clamp_view(image); +} + +static void +keyboard_focus_handler(struct window *window, + struct input *device, void *data) +{ + struct image *image = data; + + window_schedule_redraw(image->window); +} + +static int +enter_handler(struct widget *widget, + struct input *input, + float x, float y, void *data) +{ + struct image *image = data; + struct rectangle allocation; + + widget_get_allocation(image->widget, &allocation); + x -= allocation.x; + y -= allocation.y; + + image->pointer.x = x; + image->pointer.y = y; + + return 1; +} + +static void +move_viewport(struct image *image, double dx, double dy) +{ + double scale = get_scale(image); + + if (!image->initialized) + { + return; + } + + cairo_matrix_translate(&image->matrix, -dx/scale, -dy/scale); + clamp_view(image); + + window_schedule_redraw(image->window); +} + +static int +motion_handler(struct widget *widget, + struct input *input, uint32_t time, + float x, float y, void *data) +{ + struct image *image = data; + struct rectangle allocation; + + widget_get_allocation(image->widget, &allocation); + x -= allocation.x; + y -= allocation.y; + + if (image->button_pressed) + { + move_viewport(image, image->pointer.x - x, + image->pointer.y - y); + } + + image->pointer.x = x; + image->pointer.y = y; + + return image->button_pressed ? CURSOR_DRAGGING : CURSOR_LEFT_PTR; +} + +static void +button_handler(struct widget *widget, + struct input *input, uint32_t time, + uint32_t button, + enum wl_pointer_button_state state, + void *data) +{ + struct image *image = data; + + if (button == BTN_LEFT) + { + image->button_pressed = + state == WL_POINTER_BUTTON_STATE_PRESSED; + + if (state == WL_POINTER_BUTTON_STATE_PRESSED) + { + input_set_pointer_image(input, CURSOR_DRAGGING); + } + else + { + input_set_pointer_image(input, CURSOR_LEFT_PTR); + } + } +} + +static void +zoom(struct image *image, double scale) +{ + double x = image->pointer.x; + double y = image->pointer.y; + cairo_matrix_t scale_matrix; + + if (!image->initialized) + { + return; + } + + if ((get_scale(image) * scale > 20.0) || + (get_scale(image) * scale < 0.02)) + { + return; + } + + cairo_matrix_init_identity(&scale_matrix); + cairo_matrix_translate(&scale_matrix, x, y); + cairo_matrix_scale(&scale_matrix, scale, scale); + cairo_matrix_translate(&scale_matrix, -x, -y); + + cairo_matrix_multiply(&image->matrix, &image->matrix, &scale_matrix); + clamp_view(image); +} + +static void +key_handler(struct window *window, struct input *input, uint32_t time, + uint32_t key, uint32_t sym, enum wl_keyboard_key_state state, + void *data) +{ + struct image *image = data; + int transform; + + if (state == WL_KEYBOARD_KEY_STATE_RELEASED) + { + return; + } + + // printf("XKB_KEY_f[%x] XKB_KEY_t[%x]\n",XKB_KEY_f,XKB_KEY_t); + // printf("sym[%x]\n",sym); + + switch (sym) + { +/* + case XKB_KEY_minus: + zoom(image, 0.8); + window_schedule_redraw(image->window); + break; + case XKB_KEY_equal: + case XKB_KEY_plus: + zoom(image, 1.2); + window_schedule_redraw(image->window); + break; + + case XKB_KEY_1: + image->matrix.xx = 1.0; + image->matrix.xy = 0.0; + image->matrix.yx = 0.0; + image->matrix.yy = 1.0; + clamp_view(image); + window_schedule_redraw(image->window); + break; + + case XKB_KEY_2: + image->matrix.xx = 0.5; + image->matrix.xy = 0.0; + image->matrix.yx = 0.0; + image->matrix.yy = 0.5; + clamp_view(image); + window_schedule_redraw(image->window); + break; + */ + case XKB_KEY_f: + image->fullscreen ^= 1; + printf("image->fullscreen[%d]\n",image->fullscreen); + + window_set_fullscreen(image->window, image->fullscreen); + clamp_view(image); + window_schedule_redraw(image->window); + break; + +/* + case XKB_KEY_t: + transform = window_get_buffer_transform (image->window); + printf("transform[%d]\n",transform); + transform = (transform + 1) % 8; + window_set_buffer_transform(image->window, transform); + window_schedule_redraw(image->window); + break; + */ + case XKB_KEY_q: + exit(0); + break; + } +} + +static void +axis_handler(struct widget *widget, struct input *input, uint32_t time, + uint32_t axis, wl_fixed_t value, void *data) +{ + struct image *image = data; + + if ((axis == WL_POINTER_AXIS_VERTICAL_SCROLL) && + (input_get_modifiers(input) == MOD_CONTROL_MASK)) + { + /* set zoom level to 2% per 10 axis units */ + zoom(image, (1.0 - wl_fixed_to_double(value) / 500.0)); + + window_schedule_redraw(image->window); + } + else if (input_get_modifiers(input) == 0) + { + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) + { + move_viewport(image, 0, wl_fixed_to_double(value)); + } + else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) + { + move_viewport(image, wl_fixed_to_double(value), 0); + } + } +} + +static void +fullscreen_handler(struct window *window, void *data) +{ + struct image *image = data; + + // image->fullscreen ^= 1; + window_set_fullscreen(window, image->fullscreen); +} + +int is_pass_close_handler = 0; +static void +close_handler(void *data) +{ + struct image *image = data; + + *image->image_counter -= 1; + + if (*image->image_counter == 0) + { + display_exit(image->display); + } + + widget_destroy(image->widget); + window_destroy(image->window); + + free(image); + + is_pass_close_handler = 1; +} + +static char * +get_screenshot(const struct buffer_size *buff_size, + struct wl_list *output_list) +{ + int output_stride, buffer_stride, i; + cairo_surface_t *surface; + char *data, *d, *s; + struct screenshooter_output *output, *next; + FILE *fp; + char filepath[PATH_MAX]; + + buffer_stride = buff_size->width * 4; + + // printf("buffer_stride[%d] * buff_size->height[%d] = %d\n",buffer_stride, buff_size->height, buffer_stride * buff_size->height); + data = xmalloc(1024 * 4 * 768); + if (!data) + { + return; + } + + wl_list_for_each_safe(output, next, output_list, link) + { + if (output->offset_x == 0) + { + output_stride = 4; + d = data + 1024 * 4 * 767 + 1023 * 4; + s = output->data; + + for (i = 0; i < 1024*768; i++) + { + memcpy(d, s, output_stride); + d -= output_stride; + s += output_stride; + } + + wl_buffer_destroy(output->buffer); + int ret = munmap(output->data, 1024*4*768); + // printf("munmap error[%d]\n",ret); + // printf("%s\n",strerror(errno)); + // free(output->buffer); + } + + wl_registry_destroy(output->output); + free(output); + } + + // fp = file_create_dated("/tmp", "raw-", + // ".png", filepath, sizeof(filepath)); + // if (fp) { + // fwrite(data, 1, 1024 * 4 * 768, fp); + // fclose (fp); + // } + + return data; +} + +static struct image * +image_create(struct display *display, const char *filename, + int *image_counter, char *cap_img) +{ + struct image *image; + char *b, *copy, title[512]; + + image = zalloc(sizeof *image); + if (image == NULL) + { + return image; + } + + sprintf(title,"weston_clone_app"); + image->filename = strdup(title); + + image->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32, 1024, 768, 1024*4); + double width = cairo_image_surface_get_width(image->image); + double height = cairo_image_surface_get_height(image->image); + printf("1 width[%f] height[%f]\n",width,height); + + if (!image->image) + { + free(image->filename); + free(image); + + printf("image->image failed\n"); + return NULL; + } + + image->window = window_create(display); + image->widget = window_frame_create(image->window, image); + window_set_title(image->window, title); + image->display = display; + image->image_counter = image_counter; + *image_counter += 1; + image->initialized = false; + + window_set_user_data(image->window, image); + widget_set_redraw_handler(image->widget, redraw_handler); + // widget_set_resize_handler(image->widget, resize_handler); + // window_set_keyboard_focus_handler(image->window, keyboard_focus_handler); + // window_set_fullscreen_handler(image->window, fullscreen_handler); + window_set_close_handler(image->window, close_handler); + + // widget_set_enter_handler(image->widget, enter_handler); + // widget_set_motion_handler(image->widget, motion_handler); + // widget_set_button_handler(image->widget, button_handler); + // widget_set_axis_handler(image->widget, axis_handler); + window_set_key_handler(image->window, key_handler); + widget_schedule_resize(image->widget, 600, 400); + + return image; +} + +static void display_run_nonloop(struct display *display) +{ + struct task *task; + struct epoll_event ep[16]; + int i, count, ret; + int idx = 0; + + display->running = 1; + // while (1) + { + while (!wl_list_empty(&display->deferred_list)) + { + task = container_of(display->deferred_list.prev, + struct task, link); + wl_list_remove(&task->link); + task->run(task, 0); + } + + wl_display_dispatch_pending(display->display); + + ret = wl_display_flush(display->display); + if ((ret < 0) && (errno == EAGAIN)) + { + ep[0].events = + EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP; + ep[0].data.ptr = &display->display_task; + + epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, + display->display_fd, &ep[0]); + } + else if (ret < 0) + { + // break; + return; + } + + count = epoll_wait(display->epoll_fd, + ep, ARRAY_LENGTH(ep), -1); + for (i = 0; i < count; i++) + { + task = ep[i].data.ptr; + task->run(task, ep[i].events); + } + } +} + +static int +screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list) +{ + struct screenshooter_output *output; + buff_size->min_x = buff_size->min_y = INT_MAX; + buff_size->max_x = buff_size->max_y = INT_MIN; + int position = 0; + + wl_list_for_each_reverse(output, output_list, link) + { + output->offset_x = position; + position += output->width; + } + + wl_list_for_each(output, output_list, link) + { + buff_size->min_x = MIN(buff_size->min_x, output->offset_x); + buff_size->min_y = MIN(buff_size->min_y, output->offset_y); + buff_size->max_x = + MAX(buff_size->max_x, output->offset_x + output->width); + buff_size->max_y = + MAX(buff_size->max_y, output->offset_y + output->height); + } + + if ((buff_size->max_x <= buff_size->min_x) || + (buff_size->max_y <= buff_size->min_y)) + { + return -1; + } + + buff_size->width = buff_size->max_x - buff_size->min_x; + buff_size->height = buff_size->max_y - buff_size->min_y; + + return 0; +} + +char *get_weston_screen_image() +{ + struct wl_display *display_cap; // screenshooter variable + struct wl_registry *registry; + struct screenshooter_output *output; + struct buffer_size buff_size = {}; + struct screenshooter_data sh_data = {}; + char *cap_img = NULL; + + // start of screenshoot + display_cap = wl_display_connect(NULL); + if (display_cap == NULL) + { + fprintf(stderr, "failed to create display: %s\n", + strerror(errno)); + return -1; + } + + wl_list_init(&sh_data.output_list); + registry = wl_display_get_registry(display_cap); + wl_registry_add_listener(registry, ®istry_listener, &sh_data); + wl_display_dispatch(display_cap); + // printf("0.1 sh_data.shm[%p]\n",sh_data.shm); + wl_display_roundtrip(display_cap); + if (sh_data.screenshooter == NULL) + { + fprintf(stderr, "display doesn't support screenshooter\n"); + return -1; + } + weston_screenshooter_add_listener(sh_data.screenshooter, + &screenshooter_listener, + &sh_data); + if (screenshot_set_buffer_size(&buff_size, &sh_data.output_list)) + { + printf("screenshot_set_buffer_size fail\n"); + // continue; + return -1; + } + + int idx = 0; + wl_list_for_each(output, &sh_data.output_list, link) + { + if ((output->offset_x == 0) && + ((output->width == 1024) && (output->height == 768))) + { + // printf("output->offset_x[%d]\n",output->offset_x); + output->buffer = + screenshot_create_shm_buffer(output->width, + output->height, + &output->data, + sh_data.shm); + if (output->buffer == NULL) + { + continue; + } + + weston_screenshooter_shoot(sh_data.screenshooter, + output->output, + output->buffer); + + sh_data.buffer_copy_done = 0; + wl_display_roundtrip(display_cap); + usleep(35000); + + while (!sh_data.buffer_copy_done) + { + wl_display_roundtrip(display_cap); + usleep(1000); + } + } + } + // end of screenshoot + + if (buff_size.height == 768) + { + cap_img = get_screenshot(&buff_size, &sh_data.output_list); + } + else + { + struct screenshooter_output *output, *next; + wl_list_for_each_safe(output, next, &sh_data.output_list, link) + { + int ret = munmap(output->data, 1024*4*768); + // printf("munmap error[%d]\n",ret); + // printf("%s\n",strerror(errno)); + + wl_registry_destroy(output->output); + wl_list_remove(&output->link); + wl_buffer_destroy(output->buffer); + // free(output->buffer); + free(output); + } + } + + wl_registry_destroy(sh_data.shm); + wl_registry_destroy(sh_data.screenshooter); + + wl_registry_destroy(registry); + wl_display_disconnect(display_cap); + + return cap_img; +} + +int main(int argc, char *argv[]) +{ + struct display *d; // image.c variable + int i; + int image_counter = 0; + char *cap_img = NULL; + struct timespec start_time, end_time; + + d = display_create(&argc, argv); + cap_img = get_weston_screen_image(); + pimage = image_create(d, argv[i], &image_counter,cap_img); + + // full screen with 1x zoom scale + window_set_fullscreen(pimage->window, pimage->fullscreen = 1); + pimage->matrix.xx = 1.0; + pimage->matrix.xy = 0.0; + pimage->matrix.yx = 0.0; + pimage->matrix.yy = 1.0; + clamp_view(pimage); + window_schedule_redraw(pimage->window); + display_run_nonloop(d); + + struct sigaction sigint; + sigint.sa_handler = handler_sigint; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + clock_gettime(CLOCK_MONOTONIC, &end_time); + memcpy(&start_time, &end_time, sizeof(struct timespec)); + + int loop = 0; + long long usec; + while (isloop) + { + // ui loop + display_run_nonloop(d); // 20 msec + + // reload image + free(cap_img); + cap_img = get_weston_screen_image(); // 80 msec + cairo_surface_destroy(pimage->image); // 70 usec + pimage->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32,1024, 768, 1024*4); + + // ui redraw request + window_schedule_redraw(pimage->window); + + // fps calc. + clock_gettime(CLOCK_MONOTONIC, &end_time); + usec = (end_time.tv_sec - start_time.tv_sec) * 1000000 + (end_time.tv_nsec - start_time.tv_nsec) / 1000; + // printf("%d : %lld usec / %lld fps\n", loop++, usec, 1000000UL / usec); + memcpy(&start_time, &end_time, sizeof(struct timespec)); + } + + free(cap_img); + if (!is_pass_close_handler) + { + widget_destroy(pimage->widget); + window_destroy(pimage->window); + } + cairo_surface_destroy(pimage->image); + free(pimage); + + display_destroy(d); + + return 0; +} -- 2.1.4