Commit 82cb2aeb0424e7f6928c47a466c36d447b860d99

Authored by 신재종
1 parent 89fd7edb83
Exists in master

rename main source code

Showing 3 changed files with 1062 additions and 1062 deletions   Show diff stats
@@ -60,7 +60,7 @@ LDFLAGS+=`pkg-config --libs libjpeg` @@ -60,7 +60,7 @@ LDFLAGS+=`pkg-config --libs libjpeg`
60 60
61 all: 61 all:
62 $(GCC) $(CFLAGS) --sysroot $(SDKTARGETSYSROOT) $(LDFLAGS) $(INC) -o weston-vncserver \ 62 $(GCC) $(CFLAGS) --sysroot $(SDKTARGETSYSROOT) $(LDFLAGS) $(INC) -o weston-vncserver \
63 - screenshot.c \ 63 + vncserver.c \
64 protocol/pointer-constraints-unstable-v1-protocol.c \ 64 protocol/pointer-constraints-unstable-v1-protocol.c \
65 protocol/relative-pointer-unstable-v1-protocol.c \ 65 protocol/relative-pointer-unstable-v1-protocol.c \
66 protocol/text-cursor-position-protocol.c \ 66 protocol/text-cursor-position-protocol.c \
screenshot.c
@@ -1,1061 +0,0 @@ @@ -1,1061 +0,0 @@
1 -/*  
2 - * Copyright © 2008 Kristian Høgsberg  
3 - *  
4 - * Permission is hereby granted, free of charge, to any person obtaining a  
5 - * copy of this software and associated documentation files (the "Software"),  
6 - * to deal in the Software without restriction, including without limitation  
7 - * the rights to use, copy, modify, merge, publish, distribute, sublicense,  
8 - * and/or sell copies of the Software, and to permit persons to whom the  
9 - * Software is furnished to do so, subject to the following conditions:  
10 - *  
11 - * The above copyright notice and this permission notice (including the next  
12 - * paragraph) shall be included in all copies or substantial portions of the  
13 - * Software.  
14 - *  
15 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
16 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
17 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL  
18 - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
19 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
20 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  
21 - * DEALINGS IN THE SOFTWARE.  
22 - */  
23 -  
24 -#include "config.h"  
25 -  
26 -#include <stdint.h>  
27 -#include <errno.h>  
28 -#include <stdlib.h>  
29 -#include <stdio.h>  
30 -#include <stdbool.h>  
31 -#include <string.h>  
32 -#include <fcntl.h>  
33 -#include <libgen.h>  
34 -#include <unistd.h>  
35 -#include <limits.h>  
36 -#include <sys/epoll.h>  
37 -#include <sys/param.h>  
38 -#include <sys/mman.h>  
39 -#include <math.h>  
40 -#include <time.h>  
41 -#include <cairo.h>  
42 -#include <signal.h>  
43 -#include <assert.h>  
44 -#include <errno.h>  
45 -#include <linux/input.h>  
46 -#include <pixman.h>  
47 -  
48 -#include <wayland-client.h>  
49 -#include "weston-screenshooter-client-protocol.h"  
50 -#include "shared/os-compatibility.h"  
51 -#include "shared/xalloc.h"  
52 -#include "shared/file-util.h"  
53 -#include "shared/cairo-util.h"  
54 -#include "shared/helpers.h"  
55 -#include "window.h"  
56 -  
57 -/* The screenshooter is a good example of a custom object exposed by  
58 - * the compositor and serves as a test bed for implementing client  
59 - * side marshalling outside libwayland.so */  
60 -  
61 -int isloop = 1;  
62 -struct image *pimage;  
63 -  
64 -struct screenshooter_output  
65 -{  
66 - struct wl_output *output;  
67 - struct wl_buffer *buffer;  
68 - int width, height, offset_x, offset_y;  
69 - void *data;  
70 - struct wl_list link;  
71 -};  
72 -  
73 -struct buffer_size  
74 -{  
75 - int width, height;  
76 -  
77 - int min_x, min_y;  
78 - int max_x, max_y;  
79 -};  
80 -  
81 -struct screenshooter_data  
82 -{  
83 - struct wl_shm *shm;  
84 - struct wl_list output_list;  
85 -  
86 - struct weston_screenshooter *screenshooter;  
87 - int buffer_copy_done;  
88 -};  
89 -  
90 -struct image  
91 -{  
92 - struct window *window;  
93 - struct widget *widget;  
94 - struct display *display;  
95 - char *filename;  
96 - cairo_surface_t *image;  
97 - int fullscreen;  
98 - int *image_counter;  
99 - int32_t width, height;  
100 -  
101 - struct  
102 - {  
103 - double x;  
104 - double y;  
105 - } pointer;  
106 - bool button_pressed;  
107 -  
108 - bool initialized;  
109 - cairo_matrix_t matrix;  
110 -};  
111 -  
112 -struct display  
113 -{  
114 - struct wl_display *display;  
115 - struct wl_registry *registry;  
116 - struct wl_compositor *compositor;  
117 - struct wl_subcompositor *subcompositor;  
118 - struct wl_shm *shm;  
119 - struct wl_data_device_manager *data_device_manager;  
120 - struct text_cursor_position *text_cursor_position;  
121 - struct xdg_wm_base *xdg_shell;  
122 - struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;  
123 - struct zwp_pointer_constraints_v1 *pointer_constraints;  
124 - EGLDisplay dpy;  
125 - EGLConfig argb_config;  
126 - EGLContext argb_ctx;  
127 - cairo_device_t *argb_device;  
128 - uint32_t serial;  
129 -  
130 - int display_fd;  
131 - uint32_t display_fd_events;  
132 - struct task display_task;  
133 -  
134 - int epoll_fd;  
135 - struct wl_list deferred_list;  
136 -  
137 - int running;  
138 -  
139 - struct wl_list global_list;  
140 - struct wl_list window_list;  
141 - struct wl_list input_list;  
142 - struct wl_list output_list;  
143 -  
144 - struct theme *theme;  
145 -  
146 - struct wl_cursor_theme *cursor_theme;  
147 - struct wl_cursor **cursors;  
148 -  
149 - display_output_handler_t output_configure_handler;  
150 - display_global_handler_t global_handler;  
151 - display_global_handler_t global_handler_remove;  
152 -  
153 - void *user_data;  
154 -  
155 - struct xkb_context *xkb_context;  
156 -  
157 - /* A hack to get text extents for tooltips */  
158 - cairo_surface_t *dummy_surface;  
159 - void *dummy_surface_data;  
160 -  
161 - int data_device_manager_version;  
162 - struct wp_viewporter *viewporter;  
163 -};  
164 -  
165 -static void handler_sigint(int sig)  
166 -{  
167 - isloop = 0;  
168 -}  
169 -  
170 -static void  
171 -display_handle_geometry(void *data,  
172 - struct wl_output *wl_output,  
173 - int x,  
174 - int y,  
175 - int physical_width,  
176 - int physical_height,  
177 - int subpixel,  
178 - const char *make,  
179 - const char *model,  
180 - int transform)  
181 -{  
182 - struct screenshooter_output *output;  
183 -  
184 - output = wl_output_get_user_data(wl_output);  
185 -  
186 - if (wl_output == output->output)  
187 - {  
188 - output->offset_x = x;  
189 - output->offset_y = y;  
190 - }  
191 -}  
192 -  
193 -static void  
194 -display_handle_mode(void *data,  
195 - struct wl_output *wl_output,  
196 - uint32_t flags,  
197 - int width,  
198 - int height,  
199 - int refresh)  
200 -{  
201 - struct screenshooter_output *output;  
202 -  
203 - output = wl_output_get_user_data(wl_output);  
204 -  
205 - if ((wl_output == output->output) && (flags & WL_OUTPUT_MODE_CURRENT))  
206 - {  
207 - output->width = width;  
208 - output->height = height;  
209 - }  
210 -}  
211 -  
212 -static const struct wl_output_listener output_listener = {  
213 - display_handle_geometry,  
214 - display_handle_mode  
215 -};  
216 -  
217 -static void  
218 -screenshot_done(void *data, struct weston_screenshooter *screenshooter)  
219 -{  
220 - struct screenshooter_data *sh_data = data;  
221 - sh_data->buffer_copy_done = 1;  
222 -}  
223 -  
224 -static const struct weston_screenshooter_listener screenshooter_listener = {  
225 - screenshot_done  
226 -};  
227 -  
228 -static void  
229 -handle_global(void *data, struct wl_registry *registry,  
230 - uint32_t name, const char *interface, uint32_t version)  
231 -{  
232 - static struct screenshooter_output *output;  
233 - struct screenshooter_data *sh_data = data;  
234 -  
235 - if (strcmp(interface, "wl_output") == 0)  
236 - {  
237 - output = xmalloc(sizeof *output);  
238 - output->output = wl_registry_bind(registry, name,  
239 - &wl_output_interface, 1);  
240 - wl_list_insert(&sh_data->output_list, &output->link);  
241 - wl_output_add_listener(output->output, &output_listener, output);  
242 - }  
243 - else if (strcmp(interface, "wl_shm") == 0)  
244 - {  
245 - sh_data->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);  
246 - }  
247 - else if (strcmp(interface, "weston_screenshooter") == 0)  
248 - {  
249 - sh_data->screenshooter = wl_registry_bind(registry, name,  
250 - &weston_screenshooter_interface,  
251 - 1);  
252 - }  
253 -}  
254 -  
255 -static void  
256 -handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)  
257 -{  
258 - /* XXX: unimplemented */  
259 -}  
260 -  
261 -static const struct wl_registry_listener registry_listener = {  
262 - handle_global,  
263 - handle_global_remove  
264 -};  
265 -  
266 -static struct wl_buffer *  
267 -screenshot_create_shm_buffer(int width, int height, void **data_out,  
268 - struct wl_shm *shm)  
269 -{  
270 - struct wl_shm_pool *pool;  
271 - struct wl_buffer *buffer;  
272 - int fd, size, stride;  
273 - void *data;  
274 -  
275 - stride = width * 4;  
276 - size = stride * height;  
277 -  
278 - // printf("screenshot_create_shm_buffer width[%d] height[%d] stride[%d] size[%d]\n",width,height,stride,size);  
279 - fd = os_create_anonymous_file(size);  
280 - if (fd < 0)  
281 - {  
282 - fprintf(stderr, "creating a buffer file for %d B failed: %s\n",  
283 - size, strerror(errno));  
284 - return NULL;  
285 - }  
286 -  
287 - data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
288 - if (data == MAP_FAILED)  
289 - {  
290 - fprintf(stderr, "mmap failed: %s\n", strerror(errno));  
291 - close(fd);  
292 - return NULL;  
293 - }  
294 -  
295 - pool = wl_shm_create_pool(shm, fd, size);  
296 - close(fd);  
297 - buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride,  
298 - WL_SHM_FORMAT_XRGB8888);  
299 - wl_shm_pool_destroy(pool);  
300 -  
301 - *data_out = data;  
302 -  
303 - return buffer;  
304 -}  
305 -  
306 -  
307 -static double  
308 -get_scale(struct image *image)  
309 -{  
310 - assert(image->matrix.xy == 0.0 &&  
311 - image->matrix.yx == 0.0 &&  
312 - image->matrix.xx == image->matrix.yy);  
313 - return image->matrix.xx;  
314 -}  
315 -  
316 -static void  
317 -clamp_view(struct image *image)  
318 -{  
319 - struct rectangle allocation;  
320 - double scale = get_scale(image);  
321 - double sw, sh;  
322 - // printf("clamp scale[%f]\n",scale);  
323 - // printf("clamp image->width[%d] height[%d]\n",image->width,image->height);  
324 -  
325 - sw = image->width * scale;  
326 - sh = image->height * scale;  
327 - widget_get_allocation(image->widget, &allocation);  
328 -  
329 - // printf("clamp sw[%f] sh[%f]\n",sw,sh);  
330 - // printf("clamp allocation.width[%d] height[%d]\n"),allocation.width,allocation.height;  
331 -  
332 - if (sw < allocation.width)  
333 - {  
334 - image->matrix.x0 =  
335 - (allocation.width - image->width * scale) / 2;  
336 - }  
337 - else  
338 - {  
339 - if (image->matrix.x0 > 0.0)  
340 - {  
341 - image->matrix.x0 = 0.0;  
342 - }  
343 - if (sw + image->matrix.x0 < allocation.width)  
344 - {  
345 - image->matrix.x0 = allocation.width - sw;  
346 - }  
347 - }  
348 -  
349 - if (sh < allocation.height)  
350 - {  
351 - image->matrix.y0 =  
352 - (allocation.height - image->height * scale) / 2;  
353 - }  
354 - else  
355 - {  
356 - if (image->matrix.y0 > 0.0)  
357 - {  
358 - image->matrix.y0 = 0.0;  
359 - }  
360 - if (sh + image->matrix.y0 < allocation.height)  
361 - {  
362 - image->matrix.y0 = allocation.height - sh;  
363 - }  
364 - }  
365 -  
366 - // 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);  
367 - // printf("x0[%f] y0[%f]\n",image->matrix.x0, image->matrix.y0);  
368 -}  
369 -  
370 -static void  
371 -redraw_handler(struct widget *widget, void *data)  
372 -{  
373 - struct image *image = data;  
374 - struct rectangle allocation;  
375 - cairo_t *cr;  
376 - cairo_surface_t *surface;  
377 - double width, height, doc_aspect, window_aspect, scale;  
378 - cairo_matrix_t matrix;  
379 - cairo_matrix_t translate;  
380 -  
381 - surface = window_get_surface(image->window);  
382 - cr = cairo_create(surface);  
383 - widget_get_allocation(image->widget, &allocation);  
384 - // printf("allocation x[%d] y[%d] width[%d] height[%d]\n", allocation.x, allocation.y, allocation.width,allocation.height);  
385 -  
386 - cairo_rectangle(cr, allocation.x, allocation.y,  
387 - allocation.width, allocation.height);  
388 - cairo_clip(cr);  
389 - cairo_push_group(cr);  
390 - cairo_translate(cr, allocation.x, allocation.y);  
391 -  
392 - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);  
393 - // cairo_set_source_rgba(cr, 1, 0, 1, 0.5); // magenta transparency 50%  
394 - cairo_set_source_rgba(cr, 0, 0, 0, 0);  
395 - cairo_paint(cr);  
396 -  
397 - if (!image->initialized)  
398 - {  
399 - image->initialized = true;  
400 - width = cairo_image_surface_get_width(image->image);  
401 - height = cairo_image_surface_get_height(image->image);  
402 -  
403 - doc_aspect = width / height;  
404 - window_aspect = (double) allocation.width / allocation.height;  
405 - if (doc_aspect < window_aspect)  
406 - {  
407 - scale = allocation.height / height;  
408 - }  
409 - else  
410 - {  
411 - scale = allocation.width / width;  
412 - }  
413 -  
414 - // printf("doc_aspect[%f]\n",doc_aspect);  
415 - // printf("window_aspect[%f]\n",window_aspect);  
416 - // printf("scale[%f]\n",scale);  
417 -  
418 - image->width = width;  
419 - image->height = height;  
420 - cairo_matrix_init_scale(&image->matrix, scale, scale);  
421 -  
422 - clamp_view(image);  
423 - }  
424 -  
425 - matrix = image->matrix;  
426 - cairo_matrix_init_translate(&translate, allocation.x, allocation.y);  
427 - // 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);  
428 - cairo_matrix_multiply(&matrix, &matrix, &translate);  
429 - // 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);  
430 - cairo_set_matrix(cr, &matrix);  
431 -  
432 - cairo_set_source_surface(cr, image->image, 0, 0);  
433 - cairo_set_operator(cr, CAIRO_OPERATOR_OVER);  
434 - cairo_paint(cr);  
435 -  
436 - cairo_pop_group_to_source(cr);  
437 - cairo_paint(cr);  
438 - cairo_destroy(cr);  
439 -  
440 - cairo_surface_destroy(surface);  
441 -}  
442 -  
443 -static void  
444 -resize_handler(struct widget *widget,  
445 - int32_t width, int32_t height, void *data)  
446 -{  
447 - struct image *image = data;  
448 -  
449 - clamp_view(image);  
450 -}  
451 -  
452 -static void  
453 -keyboard_focus_handler(struct window *window,  
454 - struct input *device, void *data)  
455 -{  
456 - struct image *image = data;  
457 -  
458 - window_schedule_redraw(image->window);  
459 -}  
460 -  
461 -static int  
462 -enter_handler(struct widget *widget,  
463 - struct input *input,  
464 - float x, float y, void *data)  
465 -{  
466 - struct image *image = data;  
467 - struct rectangle allocation;  
468 -  
469 - widget_get_allocation(image->widget, &allocation);  
470 - x -= allocation.x;  
471 - y -= allocation.y;  
472 -  
473 - image->pointer.x = x;  
474 - image->pointer.y = y;  
475 -  
476 - return 1;  
477 -}  
478 -  
479 -static void  
480 -move_viewport(struct image *image, double dx, double dy)  
481 -{  
482 - double scale = get_scale(image);  
483 -  
484 - if (!image->initialized)  
485 - {  
486 - return;  
487 - }  
488 -  
489 - cairo_matrix_translate(&image->matrix, -dx/scale, -dy/scale);  
490 - clamp_view(image);  
491 -  
492 - window_schedule_redraw(image->window);  
493 -}  
494 -  
495 -static int  
496 -motion_handler(struct widget *widget,  
497 - struct input *input, uint32_t time,  
498 - float x, float y, void *data)  
499 -{  
500 - struct image *image = data;  
501 - struct rectangle allocation;  
502 -  
503 - widget_get_allocation(image->widget, &allocation);  
504 - x -= allocation.x;  
505 - y -= allocation.y;  
506 -  
507 - if (image->button_pressed)  
508 - {  
509 - move_viewport(image, image->pointer.x - x,  
510 - image->pointer.y - y);  
511 - }  
512 -  
513 - image->pointer.x = x;  
514 - image->pointer.y = y;  
515 -  
516 - return image->button_pressed ? CURSOR_DRAGGING : CURSOR_LEFT_PTR;  
517 -}  
518 -  
519 -static void  
520 -button_handler(struct widget *widget,  
521 - struct input *input, uint32_t time,  
522 - uint32_t button,  
523 - enum wl_pointer_button_state state,  
524 - void *data)  
525 -{  
526 - struct image *image = data;  
527 -  
528 - if (button == BTN_LEFT)  
529 - {  
530 - image->button_pressed =  
531 - state == WL_POINTER_BUTTON_STATE_PRESSED;  
532 -  
533 - if (state == WL_POINTER_BUTTON_STATE_PRESSED)  
534 - {  
535 - input_set_pointer_image(input, CURSOR_DRAGGING);  
536 - }  
537 - else  
538 - {  
539 - input_set_pointer_image(input, CURSOR_LEFT_PTR);  
540 - }  
541 - }  
542 -}  
543 -  
544 -static void  
545 -zoom(struct image *image, double scale)  
546 -{  
547 - double x = image->pointer.x;  
548 - double y = image->pointer.y;  
549 - cairo_matrix_t scale_matrix;  
550 -  
551 - if (!image->initialized)  
552 - {  
553 - return;  
554 - }  
555 -  
556 - if ((get_scale(image) * scale > 20.0) ||  
557 - (get_scale(image) * scale < 0.02))  
558 - {  
559 - return;  
560 - }  
561 -  
562 - cairo_matrix_init_identity(&scale_matrix);  
563 - cairo_matrix_translate(&scale_matrix, x, y);  
564 - cairo_matrix_scale(&scale_matrix, scale, scale);  
565 - cairo_matrix_translate(&scale_matrix, -x, -y);  
566 -  
567 - cairo_matrix_multiply(&image->matrix, &image->matrix, &scale_matrix);  
568 - clamp_view(image);  
569 -}  
570 -  
571 -static void  
572 -key_handler(struct window *window, struct input *input, uint32_t time,  
573 - uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,  
574 - void *data)  
575 -{  
576 - struct image *image = data;  
577 - int transform;  
578 -  
579 - if (state == WL_KEYBOARD_KEY_STATE_RELEASED)  
580 - {  
581 - return;  
582 - }  
583 -  
584 - // printf("XKB_KEY_f[%x] XKB_KEY_t[%x]\n",XKB_KEY_f,XKB_KEY_t);  
585 - // printf("sym[%x]\n",sym);  
586 -  
587 - switch (sym)  
588 - {  
589 -/*  
590 - case XKB_KEY_minus:  
591 - zoom(image, 0.8);  
592 - window_schedule_redraw(image->window);  
593 - break;  
594 - case XKB_KEY_equal:  
595 - case XKB_KEY_plus:  
596 - zoom(image, 1.2);  
597 - window_schedule_redraw(image->window);  
598 - break;  
599 -  
600 - case XKB_KEY_1:  
601 - image->matrix.xx = 1.0;  
602 - image->matrix.xy = 0.0;  
603 - image->matrix.yx = 0.0;  
604 - image->matrix.yy = 1.0;  
605 - clamp_view(image);  
606 - window_schedule_redraw(image->window);  
607 - break;  
608 -  
609 - case XKB_KEY_2:  
610 - image->matrix.xx = 0.5;  
611 - image->matrix.xy = 0.0;  
612 - image->matrix.yx = 0.0;  
613 - image->matrix.yy = 0.5;  
614 - clamp_view(image);  
615 - window_schedule_redraw(image->window);  
616 - break;  
617 - */  
618 - case XKB_KEY_f:  
619 - image->fullscreen ^= 1;  
620 - printf("image->fullscreen[%d]\n",image->fullscreen);  
621 -  
622 - window_set_fullscreen(image->window, image->fullscreen);  
623 - clamp_view(image);  
624 - window_schedule_redraw(image->window);  
625 - break;  
626 -  
627 -/*  
628 - case XKB_KEY_t:  
629 - transform = window_get_buffer_transform (image->window);  
630 - printf("transform[%d]\n",transform);  
631 - transform = (transform + 1) % 8;  
632 - window_set_buffer_transform(image->window, transform);  
633 - window_schedule_redraw(image->window);  
634 - break;  
635 - */  
636 - case XKB_KEY_q:  
637 - exit(0);  
638 - break;  
639 - }  
640 -}  
641 -  
642 -static void  
643 -axis_handler(struct widget *widget, struct input *input, uint32_t time,  
644 - uint32_t axis, wl_fixed_t value, void *data)  
645 -{  
646 - struct image *image = data;  
647 -  
648 - if ((axis == WL_POINTER_AXIS_VERTICAL_SCROLL) &&  
649 - (input_get_modifiers(input) == MOD_CONTROL_MASK))  
650 - {  
651 - /* set zoom level to 2% per 10 axis units */  
652 - zoom(image, (1.0 - wl_fixed_to_double(value) / 500.0));  
653 -  
654 - window_schedule_redraw(image->window);  
655 - }  
656 - else if (input_get_modifiers(input) == 0)  
657 - {  
658 - if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)  
659 - {  
660 - move_viewport(image, 0, wl_fixed_to_double(value));  
661 - }  
662 - else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)  
663 - {  
664 - move_viewport(image, wl_fixed_to_double(value), 0);  
665 - }  
666 - }  
667 -}  
668 -  
669 -static void  
670 -fullscreen_handler(struct window *window, void *data)  
671 -{  
672 - struct image *image = data;  
673 -  
674 - // image->fullscreen ^= 1;  
675 - window_set_fullscreen(window, image->fullscreen);  
676 -}  
677 -  
678 -int is_pass_close_handler = 0;  
679 -static void  
680 -close_handler(void *data)  
681 -{  
682 - struct image *image = data;  
683 -  
684 - *image->image_counter -= 1;  
685 -  
686 - if (*image->image_counter == 0)  
687 - {  
688 - display_exit(image->display);  
689 - }  
690 -  
691 - widget_destroy(image->widget);  
692 - window_destroy(image->window);  
693 -  
694 - free(image);  
695 -  
696 - is_pass_close_handler = 1;  
697 -}  
698 -  
699 -static char *  
700 -get_screenshot(const struct buffer_size *buff_size,  
701 - struct wl_list *output_list)  
702 -{  
703 - int output_stride, buffer_stride, i;  
704 - cairo_surface_t *surface;  
705 - char *data, *d, *s;  
706 - struct screenshooter_output *output, *next;  
707 - FILE *fp;  
708 - char filepath[PATH_MAX];  
709 -  
710 - buffer_stride = buff_size->width * 4;  
711 -  
712 - // printf("buffer_stride[%d] * buff_size->height[%d] = %d\n",buffer_stride, buff_size->height, buffer_stride * buff_size->height);  
713 - data = xmalloc(1024 * 4 * 768);  
714 - if (!data)  
715 - {  
716 - return;  
717 - }  
718 -  
719 - wl_list_for_each_safe(output, next, output_list, link)  
720 - {  
721 - if (output->offset_x == 0)  
722 - {  
723 - output_stride = 4;  
724 - d = data + 1024 * 4 * 767 + 1023 * 4;  
725 - s = output->data;  
726 -  
727 - for (i = 0; i < 1024*768; i++)  
728 - {  
729 - memcpy(d, s, output_stride);  
730 - d -= output_stride;  
731 - s += output_stride;  
732 - }  
733 -  
734 - wl_buffer_destroy(output->buffer);  
735 - int ret = munmap(output->data, 1024*4*768);  
736 - // printf("munmap error[%d]\n",ret);  
737 - // printf("%s\n",strerror(errno));  
738 - // free(output->buffer);  
739 - }  
740 -  
741 - wl_registry_destroy(output->output);  
742 - free(output);  
743 - }  
744 -  
745 - // fp = file_create_dated("/tmp", "raw-",  
746 - // ".png", filepath, sizeof(filepath));  
747 - // if (fp) {  
748 - // fwrite(data, 1, 1024 * 4 * 768, fp);  
749 - // fclose (fp);  
750 - // }  
751 -  
752 - return data;  
753 -}  
754 -  
755 -static struct image *  
756 -image_create(struct display *display, const char *filename,  
757 - int *image_counter, char *cap_img)  
758 -{  
759 - struct image *image;  
760 - char *b, *copy, title[512];  
761 -  
762 - image = zalloc(sizeof *image);  
763 - if (image == NULL)  
764 - {  
765 - return image;  
766 - }  
767 -  
768 - sprintf(title,"weston_clone_app");  
769 - image->filename = strdup(title);  
770 -  
771 - image->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32, 1024, 768, 1024*4);  
772 - double width = cairo_image_surface_get_width(image->image);  
773 - double height = cairo_image_surface_get_height(image->image);  
774 - printf("1 width[%f] height[%f]\n",width,height);  
775 -  
776 - if (!image->image)  
777 - {  
778 - free(image->filename);  
779 - free(image);  
780 -  
781 - printf("image->image failed\n");  
782 - return NULL;  
783 - }  
784 -  
785 - image->window = window_create(display);  
786 - image->widget = window_frame_create(image->window, image);  
787 - window_set_title(image->window, title);  
788 - image->display = display;  
789 - image->image_counter = image_counter;  
790 - *image_counter += 1;  
791 - image->initialized = false;  
792 -  
793 - window_set_user_data(image->window, image);  
794 - widget_set_redraw_handler(image->widget, redraw_handler);  
795 - // widget_set_resize_handler(image->widget, resize_handler);  
796 - // window_set_keyboard_focus_handler(image->window, keyboard_focus_handler);  
797 - // window_set_fullscreen_handler(image->window, fullscreen_handler);  
798 - window_set_close_handler(image->window, close_handler);  
799 -  
800 - // widget_set_enter_handler(image->widget, enter_handler);  
801 - // widget_set_motion_handler(image->widget, motion_handler);  
802 - // widget_set_button_handler(image->widget, button_handler);  
803 - // widget_set_axis_handler(image->widget, axis_handler);  
804 - window_set_key_handler(image->window, key_handler);  
805 - widget_schedule_resize(image->widget, 600, 400);  
806 -  
807 - return image;  
808 -}  
809 -  
810 -static void display_run_nonloop(struct display *display)  
811 -{  
812 - struct task *task;  
813 - struct epoll_event ep[16];  
814 - int i, count, ret;  
815 - int idx = 0;  
816 -  
817 - display->running = 1;  
818 - // while (1)  
819 - {  
820 - while (!wl_list_empty(&display->deferred_list))  
821 - {  
822 - task = container_of(display->deferred_list.prev,  
823 - struct task, link);  
824 - wl_list_remove(&task->link);  
825 - task->run(task, 0);  
826 - }  
827 -  
828 - wl_display_dispatch_pending(display->display);  
829 -  
830 - ret = wl_display_flush(display->display);  
831 - if ((ret < 0) && (errno == EAGAIN))  
832 - {  
833 - ep[0].events =  
834 - EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP;  
835 - ep[0].data.ptr = &display->display_task;  
836 -  
837 - epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD,  
838 - display->display_fd, &ep[0]);  
839 - }  
840 - else if (ret < 0)  
841 - {  
842 - // break;  
843 - return;  
844 - }  
845 -  
846 - count = epoll_wait(display->epoll_fd,  
847 - ep, ARRAY_LENGTH(ep), -1);  
848 - for (i = 0; i < count; i++)  
849 - {  
850 - task = ep[i].data.ptr;  
851 - task->run(task, ep[i].events);  
852 - }  
853 - }  
854 -}  
855 -  
856 -static int  
857 -screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list)  
858 -{  
859 - struct screenshooter_output *output;  
860 - buff_size->min_x = buff_size->min_y = INT_MAX;  
861 - buff_size->max_x = buff_size->max_y = INT_MIN;  
862 - int position = 0;  
863 -  
864 - wl_list_for_each_reverse(output, output_list, link)  
865 - {  
866 - output->offset_x = position;  
867 - position += output->width;  
868 - }  
869 -  
870 - wl_list_for_each(output, output_list, link)  
871 - {  
872 - buff_size->min_x = MIN(buff_size->min_x, output->offset_x);  
873 - buff_size->min_y = MIN(buff_size->min_y, output->offset_y);  
874 - buff_size->max_x =  
875 - MAX(buff_size->max_x, output->offset_x + output->width);  
876 - buff_size->max_y =  
877 - MAX(buff_size->max_y, output->offset_y + output->height);  
878 - }  
879 -  
880 - if ((buff_size->max_x <= buff_size->min_x) ||  
881 - (buff_size->max_y <= buff_size->min_y))  
882 - {  
883 - return -1;  
884 - }  
885 -  
886 - buff_size->width = buff_size->max_x - buff_size->min_x;  
887 - buff_size->height = buff_size->max_y - buff_size->min_y;  
888 -  
889 - return 0;  
890 -}  
891 -  
892 -char *get_weston_screen_image()  
893 -{  
894 - struct wl_display *display_cap; // screenshooter variable  
895 - struct wl_registry *registry;  
896 - struct screenshooter_output *output;  
897 - struct buffer_size buff_size = {};  
898 - struct screenshooter_data sh_data = {};  
899 - char *cap_img = NULL;  
900 -  
901 - // start of screenshoot  
902 - display_cap = wl_display_connect(NULL);  
903 - if (display_cap == NULL)  
904 - {  
905 - fprintf(stderr, "failed to create display: %s\n",  
906 - strerror(errno));  
907 - return -1;  
908 - }  
909 -  
910 - wl_list_init(&sh_data.output_list);  
911 - registry = wl_display_get_registry(display_cap);  
912 - wl_registry_add_listener(registry, &registry_listener, &sh_data);  
913 - wl_display_dispatch(display_cap);  
914 - // printf("0.1 sh_data.shm[%p]\n",sh_data.shm);  
915 - wl_display_roundtrip(display_cap);  
916 - if (sh_data.screenshooter == NULL)  
917 - {  
918 - fprintf(stderr, "display doesn't support screenshooter\n");  
919 - return -1;  
920 - }  
921 - weston_screenshooter_add_listener(sh_data.screenshooter,  
922 - &screenshooter_listener,  
923 - &sh_data);  
924 - if (screenshot_set_buffer_size(&buff_size, &sh_data.output_list))  
925 - {  
926 - printf("screenshot_set_buffer_size fail\n");  
927 - // continue;  
928 - return -1;  
929 - }  
930 -  
931 - int idx = 0;  
932 - wl_list_for_each(output, &sh_data.output_list, link)  
933 - {  
934 - if ((output->offset_x == 0) &&  
935 - ((output->width == 1024) && (output->height == 768)))  
936 - {  
937 - // printf("output->offset_x[%d]\n",output->offset_x);  
938 - output->buffer =  
939 - screenshot_create_shm_buffer(output->width,  
940 - output->height,  
941 - &output->data,  
942 - sh_data.shm);  
943 - if (output->buffer == NULL)  
944 - {  
945 - continue;  
946 - }  
947 -  
948 - weston_screenshooter_shoot(sh_data.screenshooter,  
949 - output->output,  
950 - output->buffer);  
951 -  
952 - sh_data.buffer_copy_done = 0;  
953 - wl_display_roundtrip(display_cap);  
954 - usleep(35000);  
955 -  
956 - while (!sh_data.buffer_copy_done)  
957 - {  
958 - wl_display_roundtrip(display_cap);  
959 - usleep(1000);  
960 - }  
961 - }  
962 - }  
963 - // end of screenshoot  
964 -  
965 - if (buff_size.height == 768)  
966 - {  
967 - cap_img = get_screenshot(&buff_size, &sh_data.output_list);  
968 - }  
969 - else  
970 - {  
971 - struct screenshooter_output *output, *next;  
972 - wl_list_for_each_safe(output, next, &sh_data.output_list, link)  
973 - {  
974 - int ret = munmap(output->data, 1024*4*768);  
975 - // printf("munmap error[%d]\n",ret);  
976 - // printf("%s\n",strerror(errno));  
977 -  
978 - wl_registry_destroy(output->output);  
979 - wl_list_remove(&output->link);  
980 - wl_buffer_destroy(output->buffer);  
981 - // free(output->buffer);  
982 - free(output);  
983 - }  
984 - }  
985 -  
986 - wl_registry_destroy(sh_data.shm);  
987 - wl_registry_destroy(sh_data.screenshooter);  
988 -  
989 - wl_registry_destroy(registry);  
990 - wl_display_disconnect(display_cap);  
991 -  
992 - return cap_img;  
993 -}  
994 -  
995 -int main(int argc, char *argv[])  
996 -{  
997 - struct display *d; // image.c variable  
998 - int i;  
999 - int image_counter = 0;  
1000 - char *cap_img = NULL;  
1001 - struct timespec start_time, end_time;  
1002 -  
1003 - d = display_create(&argc, argv);  
1004 - cap_img = get_weston_screen_image();  
1005 - pimage = image_create(d, argv[i], &image_counter,cap_img);  
1006 -  
1007 - // full screen with 1x zoom scale  
1008 - window_set_fullscreen(pimage->window, pimage->fullscreen = 1);  
1009 - pimage->matrix.xx = 1.0;  
1010 - pimage->matrix.xy = 0.0;  
1011 - pimage->matrix.yx = 0.0;  
1012 - pimage->matrix.yy = 1.0;  
1013 - clamp_view(pimage);  
1014 - window_schedule_redraw(pimage->window);  
1015 - display_run_nonloop(d);  
1016 -  
1017 - struct sigaction sigint;  
1018 - sigint.sa_handler = handler_sigint;  
1019 - sigemptyset(&sigint.sa_mask);  
1020 - sigint.sa_flags = SA_RESETHAND;  
1021 - sigaction(SIGINT, &sigint, NULL);  
1022 -  
1023 - clock_gettime(CLOCK_MONOTONIC, &end_time);  
1024 - memcpy(&start_time, &end_time, sizeof(struct timespec));  
1025 -  
1026 - int loop = 0;  
1027 - long long usec;  
1028 - while (isloop)  
1029 - {  
1030 - // ui loop  
1031 - display_run_nonloop(d); // 20 msec  
1032 -  
1033 - // reload image  
1034 - free(cap_img);  
1035 - cap_img = get_weston_screen_image(); // 80 msec  
1036 - cairo_surface_destroy(pimage->image); // 70 usec  
1037 - pimage->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32,1024, 768, 1024*4);  
1038 -  
1039 - // ui redraw request  
1040 - window_schedule_redraw(pimage->window);  
1041 -  
1042 - // fps calc.  
1043 - clock_gettime(CLOCK_MONOTONIC, &end_time);  
1044 - usec = (end_time.tv_sec - start_time.tv_sec) * 1000000 + (end_time.tv_nsec - start_time.tv_nsec) / 1000;  
1045 - // printf("%d : %lld usec / %lld fps\n", loop++, usec, 1000000UL / usec);  
1046 - memcpy(&start_time, &end_time, sizeof(struct timespec));  
1047 - }  
1048 -  
1049 - free(cap_img);  
1050 - if (!is_pass_close_handler)  
1051 - {  
1052 - widget_destroy(pimage->widget);  
1053 - window_destroy(pimage->window);  
1054 - }  
1055 - cairo_surface_destroy(pimage->image);  
1056 - free(pimage);  
1057 -  
1058 - display_destroy(d);  
1059 -  
1060 - return 0;  
1061 -}  
@@ -0,0 +1,1061 @@ @@ -0,0 +1,1061 @@
  1 +/*
  2 + * Copyright © 2008 Kristian Høgsberg
  3 + *
  4 + * Permission is hereby granted, free of charge, to any person obtaining a
  5 + * copy of this software and associated documentation files (the "Software"),
  6 + * to deal in the Software without restriction, including without limitation
  7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 + * and/or sell copies of the Software, and to permit persons to whom the
  9 + * Software is furnished to do so, subject to the following conditions:
  10 + *
  11 + * The above copyright notice and this permission notice (including the next
  12 + * paragraph) shall be included in all copies or substantial portions of the
  13 + * Software.
  14 + *
  15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21 + * DEALINGS IN THE SOFTWARE.
  22 + */
  23 +
  24 +#include "config.h"
  25 +
  26 +#include <stdint.h>
  27 +#include <errno.h>
  28 +#include <stdlib.h>
  29 +#include <stdio.h>
  30 +#include <stdbool.h>
  31 +#include <string.h>
  32 +#include <fcntl.h>
  33 +#include <libgen.h>
  34 +#include <unistd.h>
  35 +#include <limits.h>
  36 +#include <sys/epoll.h>
  37 +#include <sys/param.h>
  38 +#include <sys/mman.h>
  39 +#include <math.h>
  40 +#include <time.h>
  41 +#include <cairo.h>
  42 +#include <signal.h>
  43 +#include <assert.h>
  44 +#include <errno.h>
  45 +#include <linux/input.h>
  46 +#include <pixman.h>
  47 +
  48 +#include <wayland-client.h>
  49 +#include "weston-screenshooter-client-protocol.h"
  50 +#include "shared/os-compatibility.h"
  51 +#include "shared/xalloc.h"
  52 +#include "shared/file-util.h"
  53 +#include "shared/cairo-util.h"
  54 +#include "shared/helpers.h"
  55 +#include "window.h"
  56 +
  57 +/* The screenshooter is a good example of a custom object exposed by
  58 + * the compositor and serves as a test bed for implementing client
  59 + * side marshalling outside libwayland.so */
  60 +
  61 +int isloop = 1;
  62 +struct image *pimage;
  63 +
  64 +struct screenshooter_output
  65 +{
  66 + struct wl_output *output;
  67 + struct wl_buffer *buffer;
  68 + int width, height, offset_x, offset_y;
  69 + void *data;
  70 + struct wl_list link;
  71 +};
  72 +
  73 +struct buffer_size
  74 +{
  75 + int width, height;
  76 +
  77 + int min_x, min_y;
  78 + int max_x, max_y;
  79 +};
  80 +
  81 +struct screenshooter_data
  82 +{
  83 + struct wl_shm *shm;
  84 + struct wl_list output_list;
  85 +
  86 + struct weston_screenshooter *screenshooter;
  87 + int buffer_copy_done;
  88 +};
  89 +
  90 +struct image
  91 +{
  92 + struct window *window;
  93 + struct widget *widget;
  94 + struct display *display;
  95 + char *filename;
  96 + cairo_surface_t *image;
  97 + int fullscreen;
  98 + int *image_counter;
  99 + int32_t width, height;
  100 +
  101 + struct
  102 + {
  103 + double x;
  104 + double y;
  105 + } pointer;
  106 + bool button_pressed;
  107 +
  108 + bool initialized;
  109 + cairo_matrix_t matrix;
  110 +};
  111 +
  112 +struct display
  113 +{
  114 + struct wl_display *display;
  115 + struct wl_registry *registry;
  116 + struct wl_compositor *compositor;
  117 + struct wl_subcompositor *subcompositor;
  118 + struct wl_shm *shm;
  119 + struct wl_data_device_manager *data_device_manager;
  120 + struct text_cursor_position *text_cursor_position;
  121 + struct xdg_wm_base *xdg_shell;
  122 + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
  123 + struct zwp_pointer_constraints_v1 *pointer_constraints;
  124 + EGLDisplay dpy;
  125 + EGLConfig argb_config;
  126 + EGLContext argb_ctx;
  127 + cairo_device_t *argb_device;
  128 + uint32_t serial;
  129 +
  130 + int display_fd;
  131 + uint32_t display_fd_events;
  132 + struct task display_task;
  133 +
  134 + int epoll_fd;
  135 + struct wl_list deferred_list;
  136 +
  137 + int running;
  138 +
  139 + struct wl_list global_list;
  140 + struct wl_list window_list;
  141 + struct wl_list input_list;
  142 + struct wl_list output_list;
  143 +
  144 + struct theme *theme;
  145 +
  146 + struct wl_cursor_theme *cursor_theme;
  147 + struct wl_cursor **cursors;
  148 +
  149 + display_output_handler_t output_configure_handler;
  150 + display_global_handler_t global_handler;
  151 + display_global_handler_t global_handler_remove;
  152 +
  153 + void *user_data;
  154 +
  155 + struct xkb_context *xkb_context;
  156 +
  157 + /* A hack to get text extents for tooltips */
  158 + cairo_surface_t *dummy_surface;
  159 + void *dummy_surface_data;
  160 +
  161 + int data_device_manager_version;
  162 + struct wp_viewporter *viewporter;
  163 +};
  164 +
  165 +static void handler_sigint(int sig)
  166 +{
  167 + isloop = 0;
  168 +}
  169 +
  170 +static void
  171 +display_handle_geometry(void *data,
  172 + struct wl_output *wl_output,
  173 + int x,
  174 + int y,
  175 + int physical_width,
  176 + int physical_height,
  177 + int subpixel,
  178 + const char *make,
  179 + const char *model,
  180 + int transform)
  181 +{
  182 + struct screenshooter_output *output;
  183 +
  184 + output = wl_output_get_user_data(wl_output);
  185 +
  186 + if (wl_output == output->output)
  187 + {
  188 + output->offset_x = x;
  189 + output->offset_y = y;
  190 + }
  191 +}
  192 +
  193 +static void
  194 +display_handle_mode(void *data,
  195 + struct wl_output *wl_output,
  196 + uint32_t flags,
  197 + int width,
  198 + int height,
  199 + int refresh)
  200 +{
  201 + struct screenshooter_output *output;
  202 +
  203 + output = wl_output_get_user_data(wl_output);
  204 +
  205 + if ((wl_output == output->output) && (flags & WL_OUTPUT_MODE_CURRENT))
  206 + {
  207 + output->width = width;
  208 + output->height = height;
  209 + }
  210 +}
  211 +
  212 +static const struct wl_output_listener output_listener = {
  213 + display_handle_geometry,
  214 + display_handle_mode
  215 +};
  216 +
  217 +static void
  218 +screenshot_done(void *data, struct weston_screenshooter *screenshooter)
  219 +{
  220 + struct screenshooter_data *sh_data = data;
  221 + sh_data->buffer_copy_done = 1;
  222 +}
  223 +
  224 +static const struct weston_screenshooter_listener screenshooter_listener = {
  225 + screenshot_done
  226 +};
  227 +
  228 +static void
  229 +handle_global(void *data, struct wl_registry *registry,
  230 + uint32_t name, const char *interface, uint32_t version)
  231 +{
  232 + static struct screenshooter_output *output;
  233 + struct screenshooter_data *sh_data = data;
  234 +
  235 + if (strcmp(interface, "wl_output") == 0)
  236 + {
  237 + output = xmalloc(sizeof *output);
  238 + output->output = wl_registry_bind(registry, name,
  239 + &wl_output_interface, 1);
  240 + wl_list_insert(&sh_data->output_list, &output->link);
  241 + wl_output_add_listener(output->output, &output_listener, output);
  242 + }
  243 + else if (strcmp(interface, "wl_shm") == 0)
  244 + {
  245 + sh_data->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
  246 + }
  247 + else if (strcmp(interface, "weston_screenshooter") == 0)
  248 + {
  249 + sh_data->screenshooter = wl_registry_bind(registry, name,
  250 + &weston_screenshooter_interface,
  251 + 1);
  252 + }
  253 +}
  254 +
  255 +static void
  256 +handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
  257 +{
  258 + /* XXX: unimplemented */
  259 +}
  260 +
  261 +static const struct wl_registry_listener registry_listener = {
  262 + handle_global,
  263 + handle_global_remove
  264 +};
  265 +
  266 +static struct wl_buffer *
  267 +screenshot_create_shm_buffer(int width, int height, void **data_out,
  268 + struct wl_shm *shm)
  269 +{
  270 + struct wl_shm_pool *pool;
  271 + struct wl_buffer *buffer;
  272 + int fd, size, stride;
  273 + void *data;
  274 +
  275 + stride = width * 4;
  276 + size = stride * height;
  277 +
  278 + // printf("screenshot_create_shm_buffer width[%d] height[%d] stride[%d] size[%d]\n",width,height,stride,size);
  279 + fd = os_create_anonymous_file(size);
  280 + if (fd < 0)
  281 + {
  282 + fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
  283 + size, strerror(errno));
  284 + return NULL;
  285 + }
  286 +
  287 + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  288 + if (data == MAP_FAILED)
  289 + {
  290 + fprintf(stderr, "mmap failed: %s\n", strerror(errno));
  291 + close(fd);
  292 + return NULL;
  293 + }
  294 +
  295 + pool = wl_shm_create_pool(shm, fd, size);
  296 + close(fd);
  297 + buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride,
  298 + WL_SHM_FORMAT_XRGB8888);
  299 + wl_shm_pool_destroy(pool);
  300 +
  301 + *data_out = data;
  302 +
  303 + return buffer;
  304 +}
  305 +
  306 +
  307 +static double
  308 +get_scale(struct image *image)
  309 +{
  310 + assert(image->matrix.xy == 0.0 &&
  311 + image->matrix.yx == 0.0 &&
  312 + image->matrix.xx == image->matrix.yy);
  313 + return image->matrix.xx;
  314 +}
  315 +
  316 +static void
  317 +clamp_view(struct image *image)
  318 +{
  319 + struct rectangle allocation;
  320 + double scale = get_scale(image);
  321 + double sw, sh;
  322 + // printf("clamp scale[%f]\n",scale);
  323 + // printf("clamp image->width[%d] height[%d]\n",image->width,image->height);
  324 +
  325 + sw = image->width * scale;
  326 + sh = image->height * scale;
  327 + widget_get_allocation(image->widget, &allocation);
  328 +
  329 + // printf("clamp sw[%f] sh[%f]\n",sw,sh);
  330 + // printf("clamp allocation.width[%d] height[%d]\n"),allocation.width,allocation.height;
  331 +
  332 + if (sw < allocation.width)
  333 + {
  334 + image->matrix.x0 =
  335 + (allocation.width - image->width * scale) / 2;
  336 + }
  337 + else
  338 + {
  339 + if (image->matrix.x0 > 0.0)
  340 + {
  341 + image->matrix.x0 = 0.0;
  342 + }
  343 + if (sw + image->matrix.x0 < allocation.width)
  344 + {
  345 + image->matrix.x0 = allocation.width - sw;
  346 + }
  347 + }
  348 +
  349 + if (sh < allocation.height)
  350 + {
  351 + image->matrix.y0 =
  352 + (allocation.height - image->height * scale) / 2;
  353 + }
  354 + else
  355 + {
  356 + if (image->matrix.y0 > 0.0)
  357 + {
  358 + image->matrix.y0 = 0.0;
  359 + }
  360 + if (sh + image->matrix.y0 < allocation.height)
  361 + {
  362 + image->matrix.y0 = allocation.height - sh;
  363 + }
  364 + }
  365 +
  366 + // 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);
  367 + // printf("x0[%f] y0[%f]\n",image->matrix.x0, image->matrix.y0);
  368 +}
  369 +
  370 +static void
  371 +redraw_handler(struct widget *widget, void *data)
  372 +{
  373 + struct image *image = data;
  374 + struct rectangle allocation;
  375 + cairo_t *cr;
  376 + cairo_surface_t *surface;
  377 + double width, height, doc_aspect, window_aspect, scale;
  378 + cairo_matrix_t matrix;
  379 + cairo_matrix_t translate;
  380 +
  381 + surface = window_get_surface(image->window);
  382 + cr = cairo_create(surface);
  383 + widget_get_allocation(image->widget, &allocation);
  384 + // printf("allocation x[%d] y[%d] width[%d] height[%d]\n", allocation.x, allocation.y, allocation.width,allocation.height);
  385 +
  386 + cairo_rectangle(cr, allocation.x, allocation.y,
  387 + allocation.width, allocation.height);
  388 + cairo_clip(cr);
  389 + cairo_push_group(cr);
  390 + cairo_translate(cr, allocation.x, allocation.y);
  391 +
  392 + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
  393 + // cairo_set_source_rgba(cr, 1, 0, 1, 0.5); // magenta transparency 50%
  394 + cairo_set_source_rgba(cr, 0, 0, 0, 0);
  395 + cairo_paint(cr);
  396 +
  397 + if (!image->initialized)
  398 + {
  399 + image->initialized = true;
  400 + width = cairo_image_surface_get_width(image->image);
  401 + height = cairo_image_surface_get_height(image->image);
  402 +
  403 + doc_aspect = width / height;
  404 + window_aspect = (double) allocation.width / allocation.height;
  405 + if (doc_aspect < window_aspect)
  406 + {
  407 + scale = allocation.height / height;
  408 + }
  409 + else
  410 + {
  411 + scale = allocation.width / width;
  412 + }
  413 +
  414 + // printf("doc_aspect[%f]\n",doc_aspect);
  415 + // printf("window_aspect[%f]\n",window_aspect);
  416 + // printf("scale[%f]\n",scale);
  417 +
  418 + image->width = width;
  419 + image->height = height;
  420 + cairo_matrix_init_scale(&image->matrix, scale, scale);
  421 +
  422 + clamp_view(image);
  423 + }
  424 +
  425 + matrix = image->matrix;
  426 + cairo_matrix_init_translate(&translate, allocation.x, allocation.y);
  427 + // 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);
  428 + cairo_matrix_multiply(&matrix, &matrix, &translate);
  429 + // 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);
  430 + cairo_set_matrix(cr, &matrix);
  431 +
  432 + cairo_set_source_surface(cr, image->image, 0, 0);
  433 + cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
  434 + cairo_paint(cr);
  435 +
  436 + cairo_pop_group_to_source(cr);
  437 + cairo_paint(cr);
  438 + cairo_destroy(cr);
  439 +
  440 + cairo_surface_destroy(surface);
  441 +}
  442 +
  443 +static void
  444 +resize_handler(struct widget *widget,
  445 + int32_t width, int32_t height, void *data)
  446 +{
  447 + struct image *image = data;
  448 +
  449 + clamp_view(image);
  450 +}
  451 +
  452 +static void
  453 +keyboard_focus_handler(struct window *window,
  454 + struct input *device, void *data)
  455 +{
  456 + struct image *image = data;
  457 +
  458 + window_schedule_redraw(image->window);
  459 +}
  460 +
  461 +static int
  462 +enter_handler(struct widget *widget,
  463 + struct input *input,
  464 + float x, float y, void *data)
  465 +{
  466 + struct image *image = data;
  467 + struct rectangle allocation;
  468 +
  469 + widget_get_allocation(image->widget, &allocation);
  470 + x -= allocation.x;
  471 + y -= allocation.y;
  472 +
  473 + image->pointer.x = x;
  474 + image->pointer.y = y;
  475 +
  476 + return 1;
  477 +}
  478 +
  479 +static void
  480 +move_viewport(struct image *image, double dx, double dy)
  481 +{
  482 + double scale = get_scale(image);
  483 +
  484 + if (!image->initialized)
  485 + {
  486 + return;
  487 + }
  488 +
  489 + cairo_matrix_translate(&image->matrix, -dx/scale, -dy/scale);
  490 + clamp_view(image);
  491 +
  492 + window_schedule_redraw(image->window);
  493 +}
  494 +
  495 +static int
  496 +motion_handler(struct widget *widget,
  497 + struct input *input, uint32_t time,
  498 + float x, float y, void *data)
  499 +{
  500 + struct image *image = data;
  501 + struct rectangle allocation;
  502 +
  503 + widget_get_allocation(image->widget, &allocation);
  504 + x -= allocation.x;
  505 + y -= allocation.y;
  506 +
  507 + if (image->button_pressed)
  508 + {
  509 + move_viewport(image, image->pointer.x - x,
  510 + image->pointer.y - y);
  511 + }
  512 +
  513 + image->pointer.x = x;
  514 + image->pointer.y = y;
  515 +
  516 + return image->button_pressed ? CURSOR_DRAGGING : CURSOR_LEFT_PTR;
  517 +}
  518 +
  519 +static void
  520 +button_handler(struct widget *widget,
  521 + struct input *input, uint32_t time,
  522 + uint32_t button,
  523 + enum wl_pointer_button_state state,
  524 + void *data)
  525 +{
  526 + struct image *image = data;
  527 +
  528 + if (button == BTN_LEFT)
  529 + {
  530 + image->button_pressed =
  531 + state == WL_POINTER_BUTTON_STATE_PRESSED;
  532 +
  533 + if (state == WL_POINTER_BUTTON_STATE_PRESSED)
  534 + {
  535 + input_set_pointer_image(input, CURSOR_DRAGGING);
  536 + }
  537 + else
  538 + {
  539 + input_set_pointer_image(input, CURSOR_LEFT_PTR);
  540 + }
  541 + }
  542 +}
  543 +
  544 +static void
  545 +zoom(struct image *image, double scale)
  546 +{
  547 + double x = image->pointer.x;
  548 + double y = image->pointer.y;
  549 + cairo_matrix_t scale_matrix;
  550 +
  551 + if (!image->initialized)
  552 + {
  553 + return;
  554 + }
  555 +
  556 + if ((get_scale(image) * scale > 20.0) ||
  557 + (get_scale(image) * scale < 0.02))
  558 + {
  559 + return;
  560 + }
  561 +
  562 + cairo_matrix_init_identity(&scale_matrix);
  563 + cairo_matrix_translate(&scale_matrix, x, y);
  564 + cairo_matrix_scale(&scale_matrix, scale, scale);
  565 + cairo_matrix_translate(&scale_matrix, -x, -y);
  566 +
  567 + cairo_matrix_multiply(&image->matrix, &image->matrix, &scale_matrix);
  568 + clamp_view(image);
  569 +}
  570 +
  571 +static void
  572 +key_handler(struct window *window, struct input *input, uint32_t time,
  573 + uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
  574 + void *data)
  575 +{
  576 + struct image *image = data;
  577 + int transform;
  578 +
  579 + if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
  580 + {
  581 + return;
  582 + }
  583 +
  584 + // printf("XKB_KEY_f[%x] XKB_KEY_t[%x]\n",XKB_KEY_f,XKB_KEY_t);
  585 + // printf("sym[%x]\n",sym);
  586 +
  587 + switch (sym)
  588 + {
  589 +/*
  590 + case XKB_KEY_minus:
  591 + zoom(image, 0.8);
  592 + window_schedule_redraw(image->window);
  593 + break;
  594 + case XKB_KEY_equal:
  595 + case XKB_KEY_plus:
  596 + zoom(image, 1.2);
  597 + window_schedule_redraw(image->window);
  598 + break;
  599 +
  600 + case XKB_KEY_1:
  601 + image->matrix.xx = 1.0;
  602 + image->matrix.xy = 0.0;
  603 + image->matrix.yx = 0.0;
  604 + image->matrix.yy = 1.0;
  605 + clamp_view(image);
  606 + window_schedule_redraw(image->window);
  607 + break;
  608 +
  609 + case XKB_KEY_2:
  610 + image->matrix.xx = 0.5;
  611 + image->matrix.xy = 0.0;
  612 + image->matrix.yx = 0.0;
  613 + image->matrix.yy = 0.5;
  614 + clamp_view(image);
  615 + window_schedule_redraw(image->window);
  616 + break;
  617 + */
  618 + case XKB_KEY_f:
  619 + image->fullscreen ^= 1;
  620 + printf("image->fullscreen[%d]\n",image->fullscreen);
  621 +
  622 + window_set_fullscreen(image->window, image->fullscreen);
  623 + clamp_view(image);
  624 + window_schedule_redraw(image->window);
  625 + break;
  626 +
  627 +/*
  628 + case XKB_KEY_t:
  629 + transform = window_get_buffer_transform (image->window);
  630 + printf("transform[%d]\n",transform);
  631 + transform = (transform + 1) % 8;
  632 + window_set_buffer_transform(image->window, transform);
  633 + window_schedule_redraw(image->window);
  634 + break;
  635 + */
  636 + case XKB_KEY_q:
  637 + exit(0);
  638 + break;
  639 + }
  640 +}
  641 +
  642 +static void
  643 +axis_handler(struct widget *widget, struct input *input, uint32_t time,
  644 + uint32_t axis, wl_fixed_t value, void *data)
  645 +{
  646 + struct image *image = data;
  647 +
  648 + if ((axis == WL_POINTER_AXIS_VERTICAL_SCROLL) &&
  649 + (input_get_modifiers(input) == MOD_CONTROL_MASK))
  650 + {
  651 + /* set zoom level to 2% per 10 axis units */
  652 + zoom(image, (1.0 - wl_fixed_to_double(value) / 500.0));
  653 +
  654 + window_schedule_redraw(image->window);
  655 + }
  656 + else if (input_get_modifiers(input) == 0)
  657 + {
  658 + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
  659 + {
  660 + move_viewport(image, 0, wl_fixed_to_double(value));
  661 + }
  662 + else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
  663 + {
  664 + move_viewport(image, wl_fixed_to_double(value), 0);
  665 + }
  666 + }
  667 +}
  668 +
  669 +static void
  670 +fullscreen_handler(struct window *window, void *data)
  671 +{
  672 + struct image *image = data;
  673 +
  674 + // image->fullscreen ^= 1;
  675 + window_set_fullscreen(window, image->fullscreen);
  676 +}
  677 +
  678 +int is_pass_close_handler = 0;
  679 +static void
  680 +close_handler(void *data)
  681 +{
  682 + struct image *image = data;
  683 +
  684 + *image->image_counter -= 1;
  685 +
  686 + if (*image->image_counter == 0)
  687 + {
  688 + display_exit(image->display);
  689 + }
  690 +
  691 + widget_destroy(image->widget);
  692 + window_destroy(image->window);
  693 +
  694 + free(image);
  695 +
  696 + is_pass_close_handler = 1;
  697 +}
  698 +
  699 +static char *
  700 +get_screenshot(const struct buffer_size *buff_size,
  701 + struct wl_list *output_list)
  702 +{
  703 + int output_stride, buffer_stride, i;
  704 + cairo_surface_t *surface;
  705 + char *data, *d, *s;
  706 + struct screenshooter_output *output, *next;
  707 + FILE *fp;
  708 + char filepath[PATH_MAX];
  709 +
  710 + buffer_stride = buff_size->width * 4;
  711 +
  712 + // printf("buffer_stride[%d] * buff_size->height[%d] = %d\n",buffer_stride, buff_size->height, buffer_stride * buff_size->height);
  713 + data = xmalloc(1024 * 4 * 768);
  714 + if (!data)
  715 + {
  716 + return;
  717 + }
  718 +
  719 + wl_list_for_each_safe(output, next, output_list, link)
  720 + {
  721 + if (output->offset_x == 0)
  722 + {
  723 + output_stride = 4;
  724 + d = data + 1024 * 4 * 767 + 1023 * 4;
  725 + s = output->data;
  726 +
  727 + for (i = 0; i < 1024*768; i++)
  728 + {
  729 + memcpy(d, s, output_stride);
  730 + d -= output_stride;
  731 + s += output_stride;
  732 + }
  733 +
  734 + wl_buffer_destroy(output->buffer);
  735 + int ret = munmap(output->data, 1024*4*768);
  736 + // printf("munmap error[%d]\n",ret);
  737 + // printf("%s\n",strerror(errno));
  738 + // free(output->buffer);
  739 + }
  740 +
  741 + wl_registry_destroy(output->output);
  742 + free(output);
  743 + }
  744 +
  745 + // fp = file_create_dated("/tmp", "raw-",
  746 + // ".png", filepath, sizeof(filepath));
  747 + // if (fp) {
  748 + // fwrite(data, 1, 1024 * 4 * 768, fp);
  749 + // fclose (fp);
  750 + // }
  751 +
  752 + return data;
  753 +}
  754 +
  755 +static struct image *
  756 +image_create(struct display *display, const char *filename,
  757 + int *image_counter, char *cap_img)
  758 +{
  759 + struct image *image;
  760 + char *b, *copy, title[512];
  761 +
  762 + image = zalloc(sizeof *image);
  763 + if (image == NULL)
  764 + {
  765 + return image;
  766 + }
  767 +
  768 + sprintf(title,"weston_clone_app");
  769 + image->filename = strdup(title);
  770 +
  771 + image->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32, 1024, 768, 1024*4);
  772 + double width = cairo_image_surface_get_width(image->image);
  773 + double height = cairo_image_surface_get_height(image->image);
  774 + printf("1 width[%f] height[%f]\n",width,height);
  775 +
  776 + if (!image->image)
  777 + {
  778 + free(image->filename);
  779 + free(image);
  780 +
  781 + printf("image->image failed\n");
  782 + return NULL;
  783 + }
  784 +
  785 + image->window = window_create(display);
  786 + image->widget = window_frame_create(image->window, image);
  787 + window_set_title(image->window, title);
  788 + image->display = display;
  789 + image->image_counter = image_counter;
  790 + *image_counter += 1;
  791 + image->initialized = false;
  792 +
  793 + window_set_user_data(image->window, image);
  794 + widget_set_redraw_handler(image->widget, redraw_handler);
  795 + // widget_set_resize_handler(image->widget, resize_handler);
  796 + // window_set_keyboard_focus_handler(image->window, keyboard_focus_handler);
  797 + // window_set_fullscreen_handler(image->window, fullscreen_handler);
  798 + window_set_close_handler(image->window, close_handler);
  799 +
  800 + // widget_set_enter_handler(image->widget, enter_handler);
  801 + // widget_set_motion_handler(image->widget, motion_handler);
  802 + // widget_set_button_handler(image->widget, button_handler);
  803 + // widget_set_axis_handler(image->widget, axis_handler);
  804 + window_set_key_handler(image->window, key_handler);
  805 + widget_schedule_resize(image->widget, 600, 400);
  806 +
  807 + return image;
  808 +}
  809 +
  810 +static void display_run_nonloop(struct display *display)
  811 +{
  812 + struct task *task;
  813 + struct epoll_event ep[16];
  814 + int i, count, ret;
  815 + int idx = 0;
  816 +
  817 + display->running = 1;
  818 + // while (1)
  819 + {
  820 + while (!wl_list_empty(&display->deferred_list))
  821 + {
  822 + task = container_of(display->deferred_list.prev,
  823 + struct task, link);
  824 + wl_list_remove(&task->link);
  825 + task->run(task, 0);
  826 + }
  827 +
  828 + wl_display_dispatch_pending(display->display);
  829 +
  830 + ret = wl_display_flush(display->display);
  831 + if ((ret < 0) && (errno == EAGAIN))
  832 + {
  833 + ep[0].events =
  834 + EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP;
  835 + ep[0].data.ptr = &display->display_task;
  836 +
  837 + epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD,
  838 + display->display_fd, &ep[0]);
  839 + }
  840 + else if (ret < 0)
  841 + {
  842 + // break;
  843 + return;
  844 + }
  845 +
  846 + count = epoll_wait(display->epoll_fd,
  847 + ep, ARRAY_LENGTH(ep), -1);
  848 + for (i = 0; i < count; i++)
  849 + {
  850 + task = ep[i].data.ptr;
  851 + task->run(task, ep[i].events);
  852 + }
  853 + }
  854 +}
  855 +
  856 +static int
  857 +screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list)
  858 +{
  859 + struct screenshooter_output *output;
  860 + buff_size->min_x = buff_size->min_y = INT_MAX;
  861 + buff_size->max_x = buff_size->max_y = INT_MIN;
  862 + int position = 0;
  863 +
  864 + wl_list_for_each_reverse(output, output_list, link)
  865 + {
  866 + output->offset_x = position;
  867 + position += output->width;
  868 + }
  869 +
  870 + wl_list_for_each(output, output_list, link)
  871 + {
  872 + buff_size->min_x = MIN(buff_size->min_x, output->offset_x);
  873 + buff_size->min_y = MIN(buff_size->min_y, output->offset_y);
  874 + buff_size->max_x =
  875 + MAX(buff_size->max_x, output->offset_x + output->width);
  876 + buff_size->max_y =
  877 + MAX(buff_size->max_y, output->offset_y + output->height);
  878 + }
  879 +
  880 + if ((buff_size->max_x <= buff_size->min_x) ||
  881 + (buff_size->max_y <= buff_size->min_y))
  882 + {
  883 + return -1;
  884 + }
  885 +
  886 + buff_size->width = buff_size->max_x - buff_size->min_x;
  887 + buff_size->height = buff_size->max_y - buff_size->min_y;
  888 +
  889 + return 0;
  890 +}
  891 +
  892 +char *get_weston_screen_image()
  893 +{
  894 + struct wl_display *display_cap; // screenshooter variable
  895 + struct wl_registry *registry;
  896 + struct screenshooter_output *output;
  897 + struct buffer_size buff_size = {};
  898 + struct screenshooter_data sh_data = {};
  899 + char *cap_img = NULL;
  900 +
  901 + // start of screenshoot
  902 + display_cap = wl_display_connect(NULL);
  903 + if (display_cap == NULL)
  904 + {
  905 + fprintf(stderr, "failed to create display: %s\n",
  906 + strerror(errno));
  907 + return -1;
  908 + }
  909 +
  910 + wl_list_init(&sh_data.output_list);
  911 + registry = wl_display_get_registry(display_cap);
  912 + wl_registry_add_listener(registry, &registry_listener, &sh_data);
  913 + wl_display_dispatch(display_cap);
  914 + // printf("0.1 sh_data.shm[%p]\n",sh_data.shm);
  915 + wl_display_roundtrip(display_cap);
  916 + if (sh_data.screenshooter == NULL)
  917 + {
  918 + fprintf(stderr, "display doesn't support screenshooter\n");
  919 + return -1;
  920 + }
  921 + weston_screenshooter_add_listener(sh_data.screenshooter,
  922 + &screenshooter_listener,
  923 + &sh_data);
  924 + if (screenshot_set_buffer_size(&buff_size, &sh_data.output_list))
  925 + {
  926 + printf("screenshot_set_buffer_size fail\n");
  927 + // continue;
  928 + return -1;
  929 + }
  930 +
  931 + int idx = 0;
  932 + wl_list_for_each(output, &sh_data.output_list, link)
  933 + {
  934 + if ((output->offset_x == 0) &&
  935 + ((output->width == 1024) && (output->height == 768)))
  936 + {
  937 + // printf("output->offset_x[%d]\n",output->offset_x);
  938 + output->buffer =
  939 + screenshot_create_shm_buffer(output->width,
  940 + output->height,
  941 + &output->data,
  942 + sh_data.shm);
  943 + if (output->buffer == NULL)
  944 + {
  945 + continue;
  946 + }
  947 +
  948 + weston_screenshooter_shoot(sh_data.screenshooter,
  949 + output->output,
  950 + output->buffer);
  951 +
  952 + sh_data.buffer_copy_done = 0;
  953 + wl_display_roundtrip(display_cap);
  954 + usleep(35000);
  955 +
  956 + while (!sh_data.buffer_copy_done)
  957 + {
  958 + wl_display_roundtrip(display_cap);
  959 + usleep(1000);
  960 + }
  961 + }
  962 + }
  963 + // end of screenshoot
  964 +
  965 + if (buff_size.height == 768)
  966 + {
  967 + cap_img = get_screenshot(&buff_size, &sh_data.output_list);
  968 + }
  969 + else
  970 + {
  971 + struct screenshooter_output *output, *next;
  972 + wl_list_for_each_safe(output, next, &sh_data.output_list, link)
  973 + {
  974 + int ret = munmap(output->data, 1024*4*768);
  975 + // printf("munmap error[%d]\n",ret);
  976 + // printf("%s\n",strerror(errno));
  977 +
  978 + wl_registry_destroy(output->output);
  979 + wl_list_remove(&output->link);
  980 + wl_buffer_destroy(output->buffer);
  981 + // free(output->buffer);
  982 + free(output);
  983 + }
  984 + }
  985 +
  986 + wl_registry_destroy(sh_data.shm);
  987 + wl_registry_destroy(sh_data.screenshooter);
  988 +
  989 + wl_registry_destroy(registry);
  990 + wl_display_disconnect(display_cap);
  991 +
  992 + return cap_img;
  993 +}
  994 +
  995 +int main(int argc, char *argv[])
  996 +{
  997 + struct display *d; // image.c variable
  998 + int i;
  999 + int image_counter = 0;
  1000 + char *cap_img = NULL;
  1001 + struct timespec start_time, end_time;
  1002 +
  1003 + d = display_create(&argc, argv);
  1004 + cap_img = get_weston_screen_image();
  1005 + pimage = image_create(d, argv[i], &image_counter,cap_img);
  1006 +
  1007 + // full screen with 1x zoom scale
  1008 + window_set_fullscreen(pimage->window, pimage->fullscreen = 1);
  1009 + pimage->matrix.xx = 1.0;
  1010 + pimage->matrix.xy = 0.0;
  1011 + pimage->matrix.yx = 0.0;
  1012 + pimage->matrix.yy = 1.0;
  1013 + clamp_view(pimage);
  1014 + window_schedule_redraw(pimage->window);
  1015 + display_run_nonloop(d);
  1016 +
  1017 + struct sigaction sigint;
  1018 + sigint.sa_handler = handler_sigint;
  1019 + sigemptyset(&sigint.sa_mask);
  1020 + sigint.sa_flags = SA_RESETHAND;
  1021 + sigaction(SIGINT, &sigint, NULL);
  1022 +
  1023 + clock_gettime(CLOCK_MONOTONIC, &end_time);
  1024 + memcpy(&start_time, &end_time, sizeof(struct timespec));
  1025 +
  1026 + int loop = 0;
  1027 + long long usec;
  1028 + while (isloop)
  1029 + {
  1030 + // ui loop
  1031 + display_run_nonloop(d); // 20 msec
  1032 +
  1033 + // reload image
  1034 + free(cap_img);
  1035 + cap_img = get_weston_screen_image(); // 80 msec
  1036 + cairo_surface_destroy(pimage->image); // 70 usec
  1037 + pimage->image = cairo_image_surface_create_for_data(cap_img, CAIRO_FORMAT_ARGB32,1024, 768, 1024*4);
  1038 +
  1039 + // ui redraw request
  1040 + window_schedule_redraw(pimage->window);
  1041 +
  1042 + // fps calc.
  1043 + clock_gettime(CLOCK_MONOTONIC, &end_time);
  1044 + usec = (end_time.tv_sec - start_time.tv_sec) * 1000000 + (end_time.tv_nsec - start_time.tv_nsec) / 1000;
  1045 + // printf("%d : %lld usec / %lld fps\n", loop++, usec, 1000000UL / usec);
  1046 + memcpy(&start_time, &end_time, sizeof(struct timespec));
  1047 + }
  1048 +
  1049 + free(cap_img);
  1050 + if (!is_pass_close_handler)
  1051 + {
  1052 + widget_destroy(pimage->widget);
  1053 + window_destroy(pimage->window);
  1054 + }
  1055 + cairo_surface_destroy(pimage->image);
  1056 + free(pimage);
  1057 +
  1058 + display_destroy(d);
  1059 +
  1060 + return 0;
  1061 +}