8 #include <drm_fourcc.h>
10 #include <wayland-server.h>
11 #include <libds/log.h>
12 #include <libds/backend.h>
13 #include <libds/output.h>
14 #include <libds/compositor.h>
15 #include <libds/xdg_shell.h>
16 #include <libds-tizen/allocator/tbm.h>
17 #include <libds-tizen/backend/tdm.h>
18 #include <libds/backend/libinput.h>
19 #include <libds-tizen/tbm_server.h>
20 #include <libds-tizen/dpms.h>
21 #include <libds/input_device.h>
22 #include <libds/keyboard.h>
23 #include <libds/touch.h>
24 #include <libds/pointer.h>
25 #include <libds/seat.h>
26 #include <libds-tizen/input_devicemgr.h>
27 #include <xkbcommon/xkbcommon.h>
28 #include <libds/interfaces/keyboard.h>
29 #include <libds-tizen/launch.h>
30 #include <libds-tizen/backend/tdm_output_hwc.h>
32 #define USE_TDM_BUFFER_QUEUE
34 #ifdef USE_TDM_BUFFER_QUEUE
35 #include "pixman-tbm-helper.h"
36 #include "tinyds-tdm-renderer.h"
38 #include <libds/swapchain.h>
41 #include "pixman-helper.h"
43 #define TINYDS_UNUSED __attribute__((unused))
44 struct tinyds_keyboard;
45 struct tinyds_pointer;
49 struct tinyds_server *server;
50 struct ds_output *ds_output;
51 struct ds_allocator *allocator;
52 #ifdef USE_TDM_BUFFER_QUEUE
53 struct tinyds_renderer renderer;
54 struct ds_tdm_buffer_queue *buffer_queue;
55 struct wl_listener buffer_queue_acquirable;
57 struct ds_swapchain *swapchain;
59 struct ds_buffer *front_buffer;
61 struct wl_listener output_destroy;
62 struct wl_listener output_frame;
66 struct wl_event_source *idle_commit;
71 struct ds_tdm_output_hwc *hwc;
72 struct ds_tdm_output_hwc_window *bg_hwc_window;
77 struct ds_tizen_dpms *ds_dpms;
78 struct tinyds_server *server;
80 struct wl_listener destroy;
81 struct wl_listener set_dpms;
82 struct wl_listener get_dpms;
87 struct ds_tbm_server *tbm_server;
89 struct wl_display *display;
91 struct ds_backend *backend;
92 struct ds_backend *input_backend;
93 struct ds_compositor *compositor;
94 struct ds_xdg_shell *xdg_shell;
97 double output_x, output_y;
98 struct ds_tizen_input_devicemgr *devicemgr;
99 struct ds_tizen_launch_effect *effect;
100 struct ds_tizen_launch_splash *splash;
102 struct tinyds_output *output;
103 struct tinyds_dpms *dpms;
104 struct wl_event_source *stdin_source;
106 struct wl_list views;
108 struct wl_listener new_output;
109 struct wl_listener new_input;
110 struct wl_listener new_xdg_surface;
111 struct wl_listener devicemgr_destroy;
112 struct wl_listener pointer_warp;
113 struct wl_listener effect_destroy;
114 struct wl_listener effect_type_set;
115 struct wl_listener effect_type_unset;
116 struct wl_listener new_splash;
117 struct wl_listener splash_owner;
119 struct wl_list keyboards;
120 struct wl_list pointers;
125 struct tinyds_server *server;
127 struct tinyds_texture *texture;
128 struct ds_xdg_surface *xdg_surface;
130 struct wl_listener xdg_surface_map;
131 struct wl_listener xdg_surface_unmap;
132 struct wl_listener xdg_surface_destroy;
133 struct wl_listener surface_commit;
134 struct wl_list link; // tinyds_server::views
136 struct ds_tdm_output_hwc_window *hwc_window;
145 struct tinyds_pointer
147 struct ds_input_device *dev;
148 struct tinyds_server *server;
150 struct tinyds_view *focused_view;
152 struct wl_listener destroy;
153 struct wl_listener motion; //relative
154 struct wl_listener button;
155 struct wl_listener frame;
156 struct wl_list link; //tinyds_server::pointers
159 struct tinyds_keyboard
161 struct ds_input_device *dev;
162 struct tinyds_server *server;
164 struct wl_listener destroy;
165 struct wl_listener key;
166 struct wl_list link; //tinyds_server::keyboards
171 struct ds_input_device *dev;
172 struct tinyds_server *server;
174 struct wl_listener destroy;
175 struct wl_listener down;
176 struct wl_listener up;
177 struct wl_listener motion;
180 struct tinyds_server tinyds;
182 static bool init_server(struct tinyds_server *server, struct wl_display *display);
183 static int server_dispatch_stdin(int fd, uint32_t mask, void *data);
184 static void output_handle_destroy(struct wl_listener *listener, void *data);
185 static void output_handle_frame(struct wl_listener *listener, void *data);
186 static void draw_server_with_damage(struct tinyds_server *server);
187 static void draw_output(struct tinyds_output *output);
188 static void output_swap_buffer(struct tinyds_output *output,
189 struct ds_buffer *buffer);
190 static void view_send_frame_done(struct tinyds_view *view);
191 static void output_hwc_init(struct tinyds_output *output);
192 static void output_schedule_commit(struct tinyds_output *output);
193 static void output_commit(struct tinyds_output *output);
194 #ifdef USE_TDM_BUFFER_QUEUE
195 static void output_buffer_queue_init(struct tinyds_output *output);
196 static void output_renderer_init(struct tinyds_output *output);
197 static void output_draw_with_renderer(struct tinyds_output *output);
199 static void output_swapchain_init(struct tinyds_output *output,
200 int width, int height, uint32_t format);
201 static void output_draw_with_swapchain(struct tinyds_output *output);
202 static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image);
204 static void dpms_handle_destroy(struct wl_listener *listener, void *data);
205 static void dpms_handle_set_dpms(struct wl_listener *listener, void *data);
206 static void dpms_handle_get_dpms(struct wl_listener *listener, void *data);
207 static void server_add_keyboard(struct tinyds_server *server,
208 struct ds_input_device *dev);
209 static void server_add_pointer(struct tinyds_server *server,
210 struct ds_input_device *dev);
211 static void server_add_touch(struct tinyds_server *server,
212 struct ds_input_device *dev);
214 static struct tinyds_view *
215 server_view_at(struct tinyds_server *server, double lx, double ly,
216 double *sx, double *sy);
221 struct tinyds_server *server = &tinyds;
222 struct wl_display *display;
223 struct wl_event_loop *loop;
227 ds_log_init(DS_INF, NULL);
229 display = wl_display_create();
232 res = init_server(server, display);
235 socket = wl_display_add_socket_auto(display);
238 ds_backend_start(server->backend);
239 ds_backend_start(server->input_backend);
241 setenv("WAYLAND_DISPLAY", socket, true);
243 ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
245 loop = wl_display_get_event_loop(display);
246 server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
247 WL_EVENT_READABLE, server_dispatch_stdin, server);
249 wl_display_run(display);
251 wl_display_destroy_clients(display);
252 wl_display_destroy(display);
258 view_populate_pid(struct tinyds_view *view)
261 struct wl_client *client = NULL;
262 struct ds_surface *surface = ds_xdg_surface_get_surface(view->xdg_surface);
265 client = wl_resource_get_client(ds_surface_get_wl_resource(surface));
266 wl_client_get_credentials(client, &pid, NULL, NULL);
268 ds_inf("view pid(%u)", pid);
271 view->effect_type = ds_tizen_launch_effect_get_effect_type(view->server->effect, pid);
272 ds_tizen_launch_effect_unset_effect_type(view->server->effect, pid);
273 ds_inf("view effect_type(%d)", view->effect_type);
277 view_handle_xdg_surface_map(struct wl_listener *listener,
278 void *data TINYDS_UNUSED)
280 struct tinyds_view *view;
281 struct ds_keyboard *keyboard;
282 struct tinyds_keyboard *kbd;
284 view = wl_container_of(listener, view, xdg_surface_map);
287 view_populate_pid(view);
289 wl_list_for_each(kbd, &view->server->keyboards, link) {
290 keyboard = ds_input_device_get_keyboard(kbd->dev);
291 if (keyboard != NULL) {
292 ds_seat_keyboard_notify_enter(view->server->seat,
293 ds_xdg_surface_get_surface(view->xdg_surface),
294 keyboard->keycodes, keyboard->num_keycodes,
295 &keyboard->modifiers);
302 view_handle_xdg_surface_unmap(struct wl_listener *listener,
303 void *data TINYDS_UNUSED)
305 struct tinyds_view *view;
307 view = wl_container_of(listener, view, xdg_surface_unmap);
308 view->mapped = false;
312 view_handle_xdg_surface_destroy(struct wl_listener *listener,
313 void *data TINYDS_UNUSED)
315 struct tinyds_view *view;
317 view = wl_container_of(listener, view, xdg_surface_destroy);
319 draw_server_with_damage(view->server);
321 ds_tdm_output_hwc_window_destroy(view->hwc_window);
323 wl_list_remove(&view->xdg_surface_destroy.link);
324 wl_list_remove(&view->xdg_surface_map.link);
325 wl_list_remove(&view->xdg_surface_unmap.link);
326 wl_list_remove(&view->surface_commit.link);
327 wl_list_remove(&view->link);
332 view_handle_surface_commit(struct wl_listener *listener,
333 void *data TINYDS_UNUSED)
335 struct tinyds_view *view;
337 view = wl_container_of(listener, view, surface_commit);
338 draw_server_with_damage(view->server);
342 server_new_xdg_surface(struct wl_listener *listener, void *data)
344 struct tinyds_server *server;
345 struct tinyds_view *view;
346 struct ds_xdg_surface *xdg_surface;
348 server = wl_container_of(listener, server, new_xdg_surface);
351 ds_inf("New xdg_surface(%p)", (void *)xdg_surface);
353 view = calloc(1, sizeof *view);
356 view->server = server;
357 view->xdg_surface = xdg_surface;
359 view->xdg_surface_map.notify = view_handle_xdg_surface_map;
360 ds_xdg_surface_add_map_listener(xdg_surface,
361 &view->xdg_surface_map);
363 view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap;
364 ds_xdg_surface_add_unmap_listener(xdg_surface,
365 &view->xdg_surface_unmap);
367 view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy;
368 ds_xdg_surface_add_destroy_listener(xdg_surface,
369 &view->xdg_surface_destroy);
371 view->surface_commit.notify = view_handle_surface_commit;
372 ds_surface_add_commit_listener(
373 ds_xdg_surface_get_surface(xdg_surface),
374 &view->surface_commit);
376 view->x = rand() % 1000;
377 view->y = rand() % 500;
379 view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc);
380 assert(view->hwc_window);
382 wl_list_insert(server->views.prev, &view->link);
385 view->effect_type = -1;
387 ds_inf("view at (%d, %d)", view->x, view->y);
391 backend_handle_new_output(struct wl_listener *listener, void *data)
393 struct tinyds_server *server;
394 struct tinyds_output *output;
395 struct ds_output *ds_output;
396 const struct ds_output_mode *mode;
397 struct ds_tdm_box src_box;
399 server = wl_container_of(listener, server, new_output);
402 ds_inf("New output(%p)", ds_output);
407 mode = ds_output_get_preferred_mode(ds_output);
408 ds_output_set_mode(ds_output, mode);
410 output = calloc(1, sizeof *output);
414 output->server = server;
415 output->ds_output = ds_output;
416 output->width = mode->width;
417 output->height = mode->height;
418 output->damaged = true;
419 output->committable = true;
421 output_hwc_init(output);
423 #ifdef USE_TDM_BUFFER_QUEUE
424 output_buffer_queue_init(output);
425 output_renderer_init(output);
427 output_swapchain_init(output, mode->width, mode->height,
428 DRM_FORMAT_XRGB8888);
431 output->bg_hwc_window = ds_tdm_output_hwc_window_create(output->hwc);
432 assert(output->bg_hwc_window);
436 src_box.width = output->width;
437 src_box.height = output->height;
439 ds_tdm_output_hwc_window_set_src_box(output->bg_hwc_window, &src_box);
440 ds_tdm_output_hwc_window_set_position(output->bg_hwc_window, 0, 0);
441 ds_tdm_output_hwc_window_set_dest_size(output->bg_hwc_window, output->width, output->height);
442 ds_tdm_output_hwc_window_set_transform(output->bg_hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
444 output->output_destroy.notify = output_handle_destroy;
445 ds_output_add_destroy_listener(ds_output, &output->output_destroy);
447 output->output_frame.notify = output_handle_frame;
448 ds_output_add_frame_listener(ds_output, &output->output_frame);
450 ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height);
452 server->output = output;
454 output_schedule_commit(output);
458 add_new_dpms(struct tinyds_server *server)
460 struct tinyds_dpms *dpms;
462 dpms = calloc(1, sizeof *dpms);
466 dpms->ds_dpms = ds_tizen_dpms_create(server->display);
467 if (!dpms->ds_dpms) {
469 ds_err("Could not create ds_tizen_dpms");
473 dpms->destroy.notify = dpms_handle_destroy;
474 ds_tizen_dpms_add_destroy_listener(dpms->ds_dpms, &dpms->destroy);
476 dpms->set_dpms.notify = dpms_handle_set_dpms;
477 ds_tizen_dpms_add_set_dpms_listener(dpms->ds_dpms, &dpms->set_dpms);
479 dpms->get_dpms.notify = dpms_handle_get_dpms;
480 ds_tizen_dpms_add_get_dpms_listener(dpms->ds_dpms, &dpms->get_dpms);
484 ds_inf("Dpms (%p) added", dpms);
490 backend_handle_new_input(struct wl_listener *listener, void *data)
492 struct tinyds_server *server;
493 struct ds_input_device *dev = data;
494 enum ds_input_device_type dev_type;
496 server = wl_container_of(listener, server, new_input);
498 dev_type = ds_input_device_get_type(dev);
501 case DS_INPUT_DEVICE_KEYBOARD:
502 server_add_keyboard(server, dev);
503 server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD;
505 case DS_INPUT_DEVICE_TOUCH:
506 server_add_touch(server, dev);
507 server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH;
509 case DS_INPUT_DEVICE_POINTER:
510 server_add_pointer(server, dev);
511 server->seat_caps |= WL_SEAT_CAPABILITY_POINTER;
514 ds_err("Unknown type(%d) of ds_input_device", dev_type);
518 ds_seat_set_capabilities(server->seat, server->seat_caps);
522 devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode)
524 struct ds_tizen_input_devicemgr_keymap_data *data;
526 data = calloc(1, sizeof *data);
528 ds_err("Failed to alloc memory\n");
532 data->name = strdup(name);
533 data->keycode = keycode;
535 wl_list_insert(list, &data->link);
539 devicemgr_remove_keymap_data(struct wl_list *list, int keycode)
541 struct ds_tizen_input_devicemgr_keymap_data *data, *tmp;
543 wl_list_for_each_safe(data, tmp, list, link) {
544 if (data->keycode == keycode) {
545 wl_list_remove(&data->link);
552 devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr)
554 struct wl_list keymap_list;
557 wl_list_init(&keymap_list);
559 devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455);
560 devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456);
561 devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457);
562 devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458);
564 res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list);
566 ds_inf("Failed to set keymap");
568 devicemgr_remove_keymap_data(&keymap_list, 455);
569 devicemgr_remove_keymap_data(&keymap_list, 456);
570 devicemgr_remove_keymap_data(&keymap_list, 457);
571 devicemgr_remove_keymap_data(&keymap_list, 458);
575 devicemgr_handle_pointer_warp(struct wl_listener *listener, void *data)
577 struct tinyds_server *server;
578 struct tinyds_pointer *pointer;
579 struct ds_tizen_input_devicemgr_event_pointer_warp *event = data;
580 double sx = 0.f, sy = 0.f;
581 struct tinyds_view *view = NULL;
583 server = wl_container_of(listener, server, pointer_warp);
585 ds_inf("Pointer warp: surface(%p) x(%.2f) y(%.2f)", event->surface,
588 wl_list_for_each(pointer, &server->pointers, link){
589 if (!pointer->focused_view) continue;
590 view = pointer->focused_view;
594 if (event->surface != ds_xdg_surface_get_surface(view->xdg_surface)) {
595 ds_inf("Pointer is not on the requested surface");
599 server->output_x = view->x + (event->x * server->output->width);
600 server->output_y = view->y + (event->y * server->output->height);
602 server_view_at(server, server->output_x, server->output_y, &sx, &sy);
604 ds_inf("notify motion: sx:%.2f sy:%.2f, output_x:%.1f, output_y:%.1f",
605 sx, sy, server->output_x, server->output_y);
607 ds_seat_pointer_notify_motion(server->seat,
608 event->time_msec, sx, sy);
612 devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
614 struct tinyds_server *server =
615 wl_container_of(listener, server, devicemgr_destroy);
617 wl_list_remove(&server->devicemgr_destroy.link);
618 wl_list_remove(&server->pointer_warp.link);
620 server->devicemgr = NULL;
624 launch_effect_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
626 struct tinyds_server *server =
627 wl_container_of(listener, server, effect_destroy);
629 wl_list_remove(&server->effect_destroy.link);
630 wl_list_remove(&server->effect_type_set.link);
631 wl_list_remove(&server->effect_type_unset.link);
632 wl_list_remove(&server->new_splash.link);
634 server->effect = NULL;
638 launch_effect_handle_type_set(struct wl_listener *listener, void *data)
640 struct tinyds_server *server;
641 struct ds_tizen_launch_effect_event_type_set *event = data;
642 struct tinyds_view *view = NULL;
643 bool existing = false;
645 server = wl_container_of(listener, server, effect_type_set);
647 ds_inf("Launch effect. type_set: pid(%u) type:%s", event->pid, (event->effect_type == 1) ? "depth-in" : "launch");
649 wl_list_for_each(view, &server->views, link) {
650 if (view->pid == event->pid) {
651 view->effect_type = event->effect_type;
652 ds_inf("Launch effect. existing pid");
657 ds_tizen_launch_effect_unset_effect_type(server->effect, event->pid);
659 ds_tizen_launch_effect_set_effect_type(server->effect, event->pid, event->effect_type);
664 launch_effect_handle_type_unset(struct wl_listener *listener, void *data)
666 struct tinyds_server *server;
667 struct ds_tizen_launch_effect_event_type_unset *event = data;
668 struct tinyds_view *view = NULL;
670 server = wl_container_of(listener, server, effect_type_unset);
672 ds_inf("Launch effect. type_unset: pid(%u)", event->pid);
674 wl_list_for_each(view, &server->views, link) {
675 if (view->pid == event->pid) {
676 view->effect_type = -1;
677 ds_inf("Launch effect. pid found");
680 ds_tizen_launch_effect_unset_effect_type(server->effect, event->pid);
684 launch_splash_handle_owner(struct wl_listener *listener, void *data)
686 struct tinyds_server *server;
687 struct ds_tizen_launch_splash_event_owner *event = data;
688 struct tinyds_view *view = NULL;
690 server = wl_container_of(listener, server, splash_owner);
692 ds_inf("Splash owner. pid(%u)", event->pid);
694 wl_list_for_each(view, &server->views, link) {
695 if (view->pid == event->pid) {
696 if (event->pid == ds_tizen_launch_splash_get_pid(server->splash))
699 ds_tizen_launch_splash_set_pid(server->splash, event->pid);
706 launch_effect_handle_new_splash(struct wl_listener *listener, void *data)
708 struct tinyds_server *server;
709 struct ds_tizen_launch_splash *splash = data;
710 struct tinyds_view *view = NULL;
712 server = wl_container_of(listener, server, new_splash);
714 ds_inf("Launch new splash. splash(%p)", splash);
717 server->splash = splash;
719 // new view for "Launchscreen"
720 view = calloc(1, sizeof *view);
722 wl_list_insert(server->views.prev, &view->link);
723 view->pid = ds_tizen_launch_splash_get_pid(splash);
725 server->splash_owner.notify = launch_splash_handle_owner;
726 ds_tizen_launch_splash_add_owner_listener(server->splash,
727 &server->splash_owner);
731 init_server(struct tinyds_server *server, struct wl_display *display)
733 server->display = display;
735 wl_list_init(&server->views);
737 if (wl_display_init_shm(display) != 0)
740 server->backend = ds_tdm_backend_create(display);
741 if (!server->backend)
744 server->input_backend = ds_libinput_backend_create(display);
745 if (!server->input_backend) {
746 ds_backend_destroy(server->backend);
750 server->new_output.notify = backend_handle_new_output;
751 ds_backend_add_new_output_listener(server->backend,
752 &server->new_output);
754 wl_list_init(&server->keyboards);
755 wl_list_init(&server->pointers);
756 server->new_input.notify = backend_handle_new_input;
757 ds_backend_add_new_input_listener(server->input_backend, &server->new_input);
759 server->compositor = ds_compositor_create(display);
760 if (!server->compositor)
763 server->tbm_server = ds_tbm_server_create(display);
764 if (!server->tbm_server)
767 server->xdg_shell = ds_xdg_shell_create(display);
768 if (!server->xdg_shell)
771 server->new_xdg_surface.notify = server_new_xdg_surface;
772 ds_xdg_shell_add_new_surface_listener(server->xdg_shell,
773 &server->new_xdg_surface);
775 if (!add_new_dpms(server))
778 server->seat = ds_seat_create(display, "seat0" /* arbitrary name */);
781 server->seat_caps = 0;
783 server->devicemgr = ds_tizen_input_devicemgr_create(
784 server->input_backend, server->seat);
785 if (!server->devicemgr) {
789 devicemgr_set_keymap(server->devicemgr);
791 server->devicemgr_destroy.notify = devicemgr_handle_destroy;
792 ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr,
793 &server->devicemgr_destroy);
795 server->pointer_warp.notify = devicemgr_handle_pointer_warp;
796 ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr,
797 &server->pointer_warp);
799 server->effect = ds_tizen_launch_effect_create(display);
800 if (!server->effect) {
804 server->effect_destroy.notify = launch_effect_handle_destroy;
805 ds_tizen_launch_effect_add_destroy_listener(server->effect,
806 &server->effect_destroy);
808 server->effect_type_set.notify = launch_effect_handle_type_set;
809 ds_tizen_launch_effect_add_type_set_listener(server->effect,
810 &server->effect_type_set);
812 server->effect_type_unset.notify = launch_effect_handle_type_unset;
813 ds_tizen_launch_effect_add_type_unset_listener(server->effect,
814 &server->effect_type_unset);
816 server->new_splash.notify = launch_effect_handle_new_splash;
817 ds_tizen_launch_effect_add_new_splash_listener(server->effect,
818 &server->new_splash);
823 ds_backend_destroy(server->backend);
824 ds_backend_destroy(server->input_backend);
830 output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
832 struct tinyds_output *output =
833 wl_container_of(listener, output, output_destroy);
835 if (output->bg_hwc_window)
836 ds_tdm_output_hwc_window_destroy(output->bg_hwc_window);
838 wl_list_remove(&output->output_destroy.link);
839 wl_list_remove(&output->output_frame.link);
841 if (output->front_buffer)
842 ds_buffer_unlock(output->front_buffer);
844 #ifdef USE_TDM_BUFFER_QUEUE
845 fini_renderer(&output->renderer);
847 if (output->swapchain)
848 ds_swapchain_destroy(output->swapchain);
850 if (output->allocator)
851 ds_allocator_destroy(output->allocator);
854 wl_display_terminate(output->server->display);
856 output->server->output = NULL;
862 output_commit(struct tinyds_output *output)
864 uint32_t num_changed = 0;
865 uint32_t num_windows = 0, current_num_windows = 0;
866 struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL;
867 struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL;
868 enum ds_tdm_output_hwc_window_composition composition;
869 struct tinyds_view *view;
871 bool need_target = false;
872 bool fully_obscured = false;
873 struct ds_buffer *ds_buffer;
874 struct ds_tdm_box src_box;
877 if (!output->committable)
880 if (!output->damaged && !output->target_updated)
883 wl_list_for_each_reverse(view, &output->server->views, link) {
884 if (!view->hwc_window)
887 ds_buffer = ds_surface_get_buffer(
888 ds_xdg_surface_get_surface(view->xdg_surface));
897 ds_buffer_get_size(ds_buffer, &w, &h);
899 if ((output->width <= w) && (output->height <= h))
900 fully_obscured = true;
903 if (fully_obscured) {
904 ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
905 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
907 ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
908 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
914 composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows);
915 if (!composited_hwc_windows)
918 wl_list_for_each_reverse(view, &output->server->views, link) {
919 if (!view->hwc_window)
922 ds_buffer = ds_surface_get_buffer(
923 ds_xdg_surface_get_surface(view->xdg_surface));
927 ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer);
929 ds_buffer_get_size(ds_buffer, &w, &h);
936 ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box);
937 ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y);
938 ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h);
939 ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
942 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
943 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE);
945 composited_hwc_windows[current_num_windows] = view->hwc_window;
946 current_num_windows++;
948 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
949 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
953 if (!fully_obscured) {
954 composited_hwc_windows[current_num_windows] = output->bg_hwc_window;
955 current_num_windows++;
959 if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows,
960 num_windows, &num_changed)) {
961 free(composited_hwc_windows);
962 ds_err("Could not hwc validate");
966 if (composited_hwc_windows)
967 free(composited_hwc_windows);
969 if (num_changed > 0) {
970 changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows);
971 if (!changed_hwc_windows)
974 if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed,
975 changed_hwc_windows)) {
976 free(changed_hwc_windows);
977 ds_err("Could not get chaged composition");
981 for (i = 0; i < num_changed; i++) {
982 composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]);
983 if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) {
990 if (changed_hwc_windows)
991 free(changed_hwc_windows);
993 if (need_target && output->damaged)
996 #ifdef USE_TDM_BUFFER_QUEUE
997 struct ds_buffer *buffer;
999 buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
1001 if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, buffer)) {
1002 ds_err("Could not set hwc client target buffer");
1006 output_swap_buffer(output, buffer);
1010 if (!ds_tdm_output_hwc_accept_validation(output->hwc)) {
1011 ds_err("Could not hwc accept validateion");
1015 ds_output_commit(output->ds_output);
1017 output->committable = false;
1018 output->damaged = false;
1019 output->target_updated = false;
1021 wl_list_for_each(view, &output->server->views, link) {
1022 enum ds_tdm_output_hwc_window_composition composition;
1027 composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1028 if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1029 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1030 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1031 view_send_frame_done(view);
1034 ds_dbg("output:%p commit", output);
1038 output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
1040 struct tinyds_output *output =
1041 wl_container_of(listener, output, output_frame);
1043 ds_dbg("output:%p handle frame", output);
1045 output->committable = true;
1047 output_commit(output);
1051 draw_server_with_damage(struct tinyds_server *server)
1053 server->output->damaged = true;
1054 output_schedule_commit(server->output);
1058 output_hwc_init(struct tinyds_output *output)
1060 struct ds_tdm_output *tdm_output;
1062 tdm_output = ds_tdm_output_from_output(output->ds_output);
1065 output->hwc = ds_tdm_output_get_hwc(tdm_output);
1066 assert(output->hwc);
1068 ds_tdm_output_hwc_set_enabled(output->hwc, true);
1071 #ifdef USE_TDM_BUFFER_QUEUE
1073 output_handle_buffer_queue_acquirable(struct wl_listener *listener,
1074 void *data TINYDS_UNUSED)
1076 struct tinyds_output *output;
1078 output = wl_container_of(listener, output, buffer_queue_acquirable);
1080 output->target_updated = true;
1081 output_schedule_commit(output);
1085 output_buffer_queue_init(struct tinyds_output *output)
1087 struct ds_tdm_output *tdm_output;
1089 tdm_output = ds_tdm_output_from_output(output->ds_output);
1092 output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output);
1093 assert(output->buffer_queue);
1095 output->buffer_queue_acquirable.notify =
1096 output_handle_buffer_queue_acquirable;
1097 ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue,
1098 &output->buffer_queue_acquirable);
1102 output_renderer_init(struct tinyds_output *output)
1104 init_renderer(&output->renderer);
1106 renderer_set_surface_queue(&output->renderer,
1107 ds_tdm_buffer_queue_get_native_queue(output->buffer_queue));
1109 renderer_set_bg_color(&output->renderer, 80, 80, 80);
1113 output_draw_with_renderer(struct tinyds_output *output)
1115 struct tinyds_view *view;
1117 ds_dbg(">> BEGIN UPDATE TEXTURES");
1119 wl_list_for_each(view, &output->server->views, link) {
1120 struct ds_buffer *ds_buffer;
1121 struct ds_tbm_client_buffer *tbm_buffer;
1122 tbm_surface_h surface;
1123 enum ds_tdm_output_hwc_window_composition composition;
1128 composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1129 if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1130 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1131 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1134 ds_buffer = ds_surface_get_buffer(
1135 ds_xdg_surface_get_surface(view->xdg_surface));
1139 tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
1143 surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
1147 renderer_add_texture(&output->renderer, surface, view->x, view->y);
1149 view_send_frame_done(view);
1152 ds_dbg("<< END UPDATE TEXTURES");
1154 renderer_draw(&output->renderer);
1158 output_swapchain_init(struct tinyds_output *output,
1159 int width, int height, uint32_t format)
1162 output->allocator = ds_tbm_allocator_create();
1163 assert(output->allocator);
1165 output->swapchain = ds_swapchain_create(output->allocator,
1166 width, height, format);
1167 assert(output->swapchain);
1171 output_draw_with_swapchain(struct tinyds_output *output)
1173 struct tinyds_view *view;
1174 struct ds_buffer *output_buffer;
1175 pixman_image_t *output_image;
1176 enum ds_tdm_output_hwc_window_composition composition;
1178 output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
1182 output_image = pixman_image_from_buffer(output_buffer,
1183 DS_BUFFER_DATA_PTR_ACCESS_WRITE);
1184 if (!output_image) {
1185 ds_buffer_unlock(output_buffer);
1189 pixman_image_fill_color(output_image, 80, 80, 80);
1191 wl_list_for_each(view, &output->server->views, link) {
1195 composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1196 if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1197 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1198 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1201 draw_view(view, output_image);
1203 pixman_image_unref(output_image);
1205 if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, output_buffer)) {
1206 ds_err("Could not set hwc client target buffer");
1207 ds_buffer_unlock(output_buffer);
1211 output_swap_buffer(output, output_buffer);
1215 draw_view(struct tinyds_view *view, pixman_image_t *dst_image)
1217 struct ds_buffer *buffer;
1218 pixman_image_t *src_image;
1220 buffer = ds_surface_get_buffer(
1221 ds_xdg_surface_get_surface(view->xdg_surface));
1225 src_image = pixman_image_from_buffer(buffer,
1226 DS_BUFFER_DATA_PTR_ACCESS_READ);
1227 pixman_image_composite32(PIXMAN_OP_OVER,
1233 pixman_image_get_width(src_image),
1234 pixman_image_get_height(src_image));
1235 pixman_image_unref(src_image);
1237 view_send_frame_done(view);
1242 draw_output(struct tinyds_output *output)
1244 #ifdef USE_TDM_BUFFER_QUEUE
1245 output_draw_with_renderer(output);
1247 output_draw_with_swapchain(output);
1250 ds_dbg("output:%p draw", output);
1254 output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
1256 ds_output_attach_buffer(output->ds_output, buffer);
1258 if (output->front_buffer)
1259 ds_buffer_unlock(output->front_buffer);
1260 output->front_buffer = buffer;
1264 view_send_frame_done(struct tinyds_view *view)
1266 struct timespec now;
1267 clock_gettime(CLOCK_MONOTONIC, &now);
1268 ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
1273 server_dispatch_stdin(int fd, uint32_t mask, void *data)
1275 struct tinyds_server *server = data;
1277 wl_display_terminate(server->display);
1283 dpms_handle_destroy(struct wl_listener *listener, void *data)
1285 struct tinyds_dpms *dpms;
1287 dpms = wl_container_of(listener, dpms, destroy);
1289 ds_inf("Dpms(%p) destroyed", dpms);
1291 wl_list_remove(&dpms->destroy.link);
1292 wl_list_remove(&dpms->set_dpms.link);
1293 wl_list_remove(&dpms->get_dpms.link);
1299 dpms_handle_set_dpms(struct wl_listener *listener, void *data)
1301 struct tinyds_dpms *dpms;
1302 struct ds_tizen_dpms_event *event = data;
1304 dpms = wl_container_of(listener, dpms, set_dpms);
1306 ds_inf("Dpms(%p) set dpms : %d", dpms, event->mode);
1309 //set dpms mode to output
1310 ds_tizen_dpms_send_set_result(dpms->ds_dpms, event->mode,
1311 DS_TIZEN_DPMS_ERROR_NONE);
1315 dpms_handle_get_dpms(struct wl_listener *listener, void *data)
1317 struct tinyds_dpms *dpms;
1319 dpms = wl_container_of(listener, dpms, get_dpms);
1321 ds_inf("Dpms(%p) get dpms", dpms);
1324 //get dpms mode from output
1325 ds_tizen_dpms_send_get_result(dpms->ds_dpms, DS_TIZEN_DPMS_MODE_ON,
1326 DS_TIZEN_DPMS_ERROR_NONE);
1330 keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
1332 struct tinyds_keyboard *kbd;
1334 kbd = wl_container_of(listener, kbd, destroy);
1336 ds_inf("Keyboard(%p) destroyed", kbd);
1338 wl_list_remove(&kbd->destroy.link);
1339 wl_list_remove(&kbd->key.link);
1340 wl_list_remove(&kbd->link);
1346 server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym)
1349 case XKB_KEY_BackSpace:
1350 wl_display_terminate(server->display);
1360 keyboard_handle_key(struct wl_listener *listener, void *data)
1362 struct tinyds_keyboard *kbd;
1363 struct ds_event_keyboard_key *event = data;
1364 struct ds_keyboard *ds_keyboard;
1365 struct xkb_state *xkb_state;
1366 const xkb_keysym_t *syms;
1368 bool handled = false;
1370 kbd = wl_container_of(listener, kbd, key);
1372 ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), "
1373 "update_state(%d)", kbd->dev,
1374 event->keycode, event->state, event->time_msec,
1375 event->update_state);
1377 ds_keyboard = ds_input_device_get_keyboard(kbd->dev);
1379 if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1380 xkb_state = ds_keyboard_get_xkb_state(ds_keyboard);
1382 nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8,
1384 for (int i = 0; i < nsyms; i++) {
1385 handled = server_handle_keybinding(kbd->server, syms[i]);
1391 ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec,
1392 event->keycode, event->state);
1397 server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev)
1399 struct tinyds_keyboard *kbd;
1400 struct xkb_context *context;
1401 struct xkb_keymap *keymap;
1403 kbd = calloc(1, sizeof *kbd);
1407 kbd->server = server;
1409 context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
1410 keymap = xkb_keymap_new_from_names(context, NULL,
1411 XKB_KEYMAP_COMPILE_NO_FLAGS);
1414 ds_err("Failed to compile keymap");
1415 xkb_context_unref(context);
1418 ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap);
1420 xkb_keymap_unref(keymap);
1421 xkb_context_unref(context);
1423 kbd->destroy.notify = keyboard_handle_device_destroy;
1424 ds_input_device_add_destroy_listener(dev, &kbd->destroy);
1426 kbd->key.notify = keyboard_handle_key;
1427 ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key);
1429 wl_list_insert(&server->keyboards, &kbd->link);
1431 ds_inf("Keyboard(%p) added", kbd);
1434 static struct tinyds_view *
1435 server_view_at(struct tinyds_server *server, double lx, double ly,
1436 double *sx, double *sy)
1438 struct tinyds_view *view;
1439 struct ds_surface *surface;
1440 struct ds_buffer *buffer;
1441 int x, y, w = 0, h = 0;
1443 wl_list_for_each(view, &server->views, link) {
1444 surface = ds_xdg_surface_get_surface(view->xdg_surface);
1445 buffer = ds_surface_get_buffer(surface);
1446 ds_buffer_get_size(buffer, &w, &h);
1451 if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) {
1463 touch_handle_device_destroy(struct wl_listener *listener, void *data)
1465 struct tinyds_touch *touch;
1467 touch = wl_container_of(listener, touch, destroy);
1469 ds_inf("Touch(%p) destroyed", touch);
1471 wl_list_remove(&touch->destroy.link);
1472 wl_list_remove(&touch->down.link);
1473 wl_list_remove(&touch->up.link);
1474 wl_list_remove(&touch->motion.link);
1480 touch_handle_down(struct wl_listener *listener, void *data)
1482 struct ds_event_touch_down *event = data;
1483 struct tinyds_touch *touch;
1484 struct tinyds_view *view;
1485 struct tinyds_server *server;
1486 double sx = 0.f, sy = 0.f;
1488 touch = wl_container_of(listener, touch, down);
1490 server = touch->server;
1491 server->output_x = event->x * server->output->width;
1492 server->output_y = event->y * server->output->height;
1494 ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1495 touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1497 view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1500 ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface),
1501 event->time_msec, event->id, sx, sy);
1506 touch_handle_up(struct wl_listener *listener, void *data)
1508 struct ds_event_touch_up *event = data;
1509 struct tinyds_touch *touch;
1511 touch = wl_container_of(listener, touch, up);
1513 ds_inf("Touch(%p) event up: id(%d) time_msec(%d)",
1514 touch->dev, event->id, event->time_msec);
1516 ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id);
1520 touch_handle_motion(struct wl_listener *listener, void *data)
1522 struct ds_event_touch_motion *event = data;
1523 struct tinyds_touch *touch;
1524 struct tinyds_view *view;
1525 struct tinyds_server *server;
1526 double sx = 0.f, sy = 0.f;
1528 touch = wl_container_of(listener, touch, motion);
1530 server = touch->server;
1531 server->output_x = event->x * server->output->width;
1532 server->output_y = event->y * server->output->height;
1534 ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1535 touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1537 view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1540 ds_seat_touch_notify_motion(server->seat, event->time_msec,
1546 server_add_touch(struct tinyds_server *server, struct ds_input_device *dev)
1548 struct tinyds_touch *touch;
1550 touch = calloc(1, sizeof *touch);
1554 touch->server = server;
1556 touch->destroy.notify = touch_handle_device_destroy;
1557 ds_input_device_add_destroy_listener(dev, &touch->destroy);
1559 touch->down.notify = touch_handle_down;
1560 ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down);
1562 touch->up.notify = touch_handle_up;
1563 ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up);
1565 touch->motion.notify = touch_handle_motion;
1566 ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion);
1568 ds_inf("Touch(%p) added", touch);
1572 pointer_handle_device_destroy(struct wl_listener *listener, void *data)
1574 struct tinyds_pointer *pointer;
1576 pointer = wl_container_of(listener, pointer, destroy);
1578 ds_inf("Pointer(%p) destroyed", pointer);
1580 wl_list_remove(&pointer->destroy.link);
1581 wl_list_remove(&pointer->motion.link);
1582 wl_list_remove(&pointer->button.link);
1583 wl_list_remove(&pointer->frame.link);
1584 wl_list_remove(&pointer->link);
1590 pointer_handle_motion(struct wl_listener *listener, void *data)
1592 struct tinyds_pointer *pointer;
1593 struct ds_event_pointer_motion *event = data;
1594 struct tinyds_view *view;
1595 struct tinyds_server *server;
1599 pointer = wl_container_of(listener, pointer, motion);
1601 server = pointer->server;
1602 if (server->output) {
1603 ow = server->output->width;
1604 oh = server->output->height;
1607 if (server->output_x + event->delta_x >= ow)
1608 server->output_x = ow;
1609 else if(server->output_x + event->delta_x <= 0.f)
1610 server->output_x = 0.f;
1612 server->output_x = server->output_x + event->delta_x ;
1613 if (server->output_y + event->delta_y >= oh)
1614 server->output_y = oh;
1615 else if(server->output_y + event->delta_y <= 0.f)
1616 server->output_y = 0.f;
1618 server->output_y = server->output_y + event->delta_y ;
1620 ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f",
1621 pointer, event->delta_x, event->delta_y, server->output_x, server->output_y);
1623 view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy);
1625 if (pointer->focused_view != view) {
1626 if (pointer->focused_view) {
1627 ds_inf("Clear pointer focus from view(%p)", pointer->focused_view);
1628 ds_seat_pointer_notify_clear_focus(pointer->server->seat);
1629 pointer->focused_view = NULL;
1633 ds_inf("Set pointer focus to view(%p)", view);
1634 ds_seat_pointer_notify_enter(pointer->server->seat,
1635 ds_xdg_surface_get_surface(view->xdg_surface), sx, sy);
1636 pointer->focused_view = view;
1641 ds_seat_pointer_notify_motion(pointer->server->seat,
1642 event->time_msec, sx, sy);
1647 pointer_handle_button(struct wl_listener *listener, void *data)
1649 struct tinyds_pointer *pointer;
1650 struct ds_event_pointer_button *event = data;
1652 pointer = wl_container_of(listener, pointer, button);
1654 ds_inf("Pointer(%p) button(%d): state(%s) time(%d)",
1655 pointer, event->button,
1656 (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released",
1659 ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state);
1663 pointer_handle_frame(struct wl_listener *listener, void *data)
1665 struct tinyds_pointer *pointer;
1667 pointer = wl_container_of(listener, pointer, frame);
1669 ds_inf("Pointer(%p) frame", pointer);
1670 ds_seat_pointer_notify_frame(pointer->server->seat);
1674 server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev)
1676 struct tinyds_pointer *pointer;
1678 pointer = calloc(1, sizeof *pointer);
1682 pointer->server = server;
1683 server->output_x = 200;
1684 server->output_y = 200;
1686 pointer->destroy.notify = pointer_handle_device_destroy;
1687 ds_input_device_add_destroy_listener(dev, &pointer->destroy);
1689 pointer->motion.notify = pointer_handle_motion;
1690 ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev),
1693 pointer->button.notify = pointer_handle_button;
1694 ds_pointer_add_button_listener(ds_input_device_get_pointer(dev),
1697 pointer->frame.notify = pointer_handle_frame;
1698 ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev),
1701 pointer->focused_view = NULL;
1703 wl_list_insert(&server->pointers, &pointer->link);
1705 ds_inf("Pointer(%p) added", pointer);
1710 output_schedule_commit_handle_idle_timer(void *data)
1712 struct tinyds_output *output = data;
1713 output->idle_commit = NULL;
1715 output_commit(output);
1719 output_schedule_commit(struct tinyds_output *output)
1721 if (output->idle_commit)
1724 struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display);
1725 output->idle_commit =
1726 wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output);