Commit 82cb2aeb0424e7f6928c47a466c36d447b860d99
1 parent
89fd7edb83
Exists in
master
rename main source code
Showing
3 changed files
with
1062 additions
and
1062 deletions
Show diff stats
Makefile
@@ -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, ®istry_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 | -} |
vncserver.c
@@ -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, ®istry_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 | +} |