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 | 60 | |
61 | 61 | all: |
62 | 62 | $(GCC) $(CFLAGS) --sysroot $(SDKTARGETSYSROOT) $(LDFLAGS) $(INC) -o weston-vncserver \ |
63 | - screenshot.c \ | |
63 | + vncserver.c \ | |
64 | 64 | protocol/pointer-constraints-unstable-v1-protocol.c \ |
65 | 65 | protocol/relative-pointer-unstable-v1-protocol.c \ |
66 | 66 | protocol/text-cursor-position-protocol.c \ | ... | ... |
screenshot.c
... | ... | @@ -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 @@ |
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 | +} | ... | ... |