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/effect.h>
31 #define USE_TDM_BUFFER_QUEUE
33 #ifdef USE_TDM_BUFFER_QUEUE
34 #include "pixman-tbm-helper.h"
35 #include "tinyds-tdm-renderer.h"
37 #include <libds/swapchain.h>
40 #include "pixman-helper.h"
42 #define TINYDS_UNUSED __attribute__((unused))
43 struct tinyds_keyboard;
44 struct tinyds_pointer;
48 struct tinyds_server *server;
49 struct ds_output *ds_output;
50 struct ds_allocator *allocator;
51 #ifdef USE_TDM_BUFFER_QUEUE
52 struct tinyds_renderer renderer;
53 struct ds_tdm_buffer_queue *buffer_queue;
54 struct wl_listener buffer_queue_acquirable;
56 struct ds_swapchain *swapchain;
58 struct ds_buffer *front_buffer;
60 struct wl_listener output_destroy;
61 struct wl_listener output_frame;
71 struct ds_tizen_dpms *ds_dpms;
72 struct tinyds_server *server;
74 struct wl_listener destroy;
75 struct wl_listener set_dpms;
76 struct wl_listener get_dpms;
81 struct ds_tbm_server *tbm_server;
83 struct wl_display *display;
85 struct ds_backend *backend;
86 struct ds_backend *input_backend;
87 struct ds_compositor *compositor;
88 struct ds_xdg_shell *xdg_shell;
91 double output_x, output_y;
92 struct ds_tizen_input_devicemgr *devicemgr;
93 struct ds_tizen_effect *effect;
94 struct ds_tizen_splash *splash;
96 struct tinyds_output *output;
97 struct tinyds_dpms *dpms;
98 struct wl_event_source *stdin_source;
100 struct wl_list views;
102 struct wl_listener new_output;
103 struct wl_listener new_input;
104 struct wl_listener new_xdg_surface;
105 struct wl_listener devicemgr_destroy;
106 struct wl_listener pointer_warp;
107 struct wl_listener effect_destroy;
108 struct wl_listener effect_type_set;
109 struct wl_listener effect_type_unset;
110 struct wl_listener new_splash;
111 struct wl_listener splash_owner;
113 struct wl_list keyboards;
114 struct wl_list pointers;
119 struct tinyds_server *server;
121 struct tinyds_texture *texture;
122 struct ds_xdg_surface *xdg_surface;
124 struct wl_listener xdg_surface_map;
125 struct wl_listener xdg_surface_unmap;
126 struct wl_listener xdg_surface_destroy;
127 struct wl_listener surface_commit;
128 struct wl_list link; // tinyds_server::views
137 struct tinyds_pointer
139 struct ds_input_device *dev;
140 struct tinyds_server *server;
142 struct tinyds_view *focused_view;
144 struct wl_listener destroy;
145 struct wl_listener motion; //relative
146 struct wl_listener button;
147 struct wl_listener frame;
148 struct wl_list link; //tinyds_server::pointers
151 struct tinyds_keyboard
153 struct ds_input_device *dev;
154 struct tinyds_server *server;
156 struct wl_listener destroy;
157 struct wl_listener key;
158 struct wl_list link; //tinyds_server::keyboards
163 struct ds_input_device *dev;
164 struct tinyds_server *server;
166 struct wl_listener destroy;
167 struct wl_listener down;
168 struct wl_listener up;
169 struct wl_listener motion;
172 struct tinyds_server tinyds;
174 static bool init_server(struct tinyds_server *server, struct wl_display *display);
175 static int server_dispatch_stdin(int fd, uint32_t mask, void *data);
176 static void output_handle_destroy(struct wl_listener *listener, void *data);
177 static void output_handle_frame(struct wl_listener *listener, void *data);
178 static void draw_server_with_damage(struct tinyds_server *server);
179 static void draw_output(struct tinyds_output *output);
180 static void output_swap_buffer(struct tinyds_output *output,
181 struct ds_buffer *buffer);
182 static void view_send_frame_done(struct tinyds_view *view);
183 #ifdef USE_TDM_BUFFER_QUEUE
184 static void output_buffer_queue_init(struct tinyds_output *output);
185 static void output_renderer_init(struct tinyds_output *output);
186 static void output_draw_with_renderer(struct tinyds_output *output);
188 static void output_swapchain_init(struct tinyds_output *output,
189 int width, int height, uint32_t format);
190 static void output_draw_with_swapchain(struct tinyds_output *output);
191 static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image);
193 static void dpms_handle_destroy(struct wl_listener *listener, void *data);
194 static void dpms_handle_set_dpms(struct wl_listener *listener, void *data);
195 static void dpms_handle_get_dpms(struct wl_listener *listener, void *data);
196 static void server_add_keyboard(struct tinyds_server *server,
197 struct ds_input_device *dev);
198 static void server_add_pointer(struct tinyds_server *server,
199 struct ds_input_device *dev);
200 static void server_add_touch(struct tinyds_server *server,
201 struct ds_input_device *dev);
203 static struct tinyds_view *
204 server_view_at(struct tinyds_server *server, double lx, double ly,
205 double *sx, double *sy);
210 struct tinyds_server *server = &tinyds;
211 struct wl_display *display;
212 struct wl_event_loop *loop;
216 ds_log_init(DS_INF, NULL);
218 display = wl_display_create();
221 res = init_server(server, display);
224 socket = wl_display_add_socket_auto(display);
227 ds_backend_start(server->backend);
228 ds_backend_start(server->input_backend);
230 setenv("WAYLAND_DISPLAY", socket, true);
232 ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
234 loop = wl_display_get_event_loop(display);
235 server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
236 WL_EVENT_READABLE, server_dispatch_stdin, server);
238 wl_display_run(display);
240 wl_display_destroy_clients(display);
241 wl_display_destroy(display);
247 view_populate_pid(struct tinyds_view *view)
250 struct wl_client *client = NULL;
251 struct ds_surface *surface = ds_xdg_surface_get_surface(view->xdg_surface);
254 client = wl_resource_get_client(ds_surface_get_wl_resource(surface));
255 wl_client_get_credentials(client, &pid, NULL, NULL);
257 ds_inf("view pid(%u)", pid);
260 view->effect_type = ds_tizen_effect_get_effect_type(view->server->effect, pid);
261 ds_tizen_effect_unset_effect_type(view->server->effect, pid);
262 ds_inf("view effect_type(%d)", view->effect_type);
266 view_handle_xdg_surface_map(struct wl_listener *listener,
267 void *data TINYDS_UNUSED)
269 struct tinyds_view *view;
270 struct ds_keyboard *keyboard;
271 struct tinyds_keyboard *kbd;
273 view = wl_container_of(listener, view, xdg_surface_map);
276 view_populate_pid(view);
278 wl_list_for_each(kbd, &view->server->keyboards, link) {
279 keyboard = ds_input_device_get_keyboard(kbd->dev);
280 if (keyboard != NULL) {
281 ds_seat_keyboard_notify_enter(view->server->seat,
282 ds_xdg_surface_get_surface(view->xdg_surface),
283 keyboard->keycodes, keyboard->num_keycodes,
284 &keyboard->modifiers);
291 view_handle_xdg_surface_unmap(struct wl_listener *listener,
292 void *data TINYDS_UNUSED)
294 struct tinyds_view *view;
296 view = wl_container_of(listener, view, xdg_surface_unmap);
297 view->mapped = false;
301 view_handle_xdg_surface_destroy(struct wl_listener *listener,
302 void *data TINYDS_UNUSED)
304 struct tinyds_view *view;
305 struct tinyds_server *server;
307 view = wl_container_of(listener, view, xdg_surface_destroy);
308 server = view->server;
310 wl_list_remove(&view->xdg_surface_destroy.link);
311 wl_list_remove(&view->xdg_surface_map.link);
312 wl_list_remove(&view->xdg_surface_unmap.link);
313 wl_list_remove(&view->surface_commit.link);
314 wl_list_remove(&view->link);
317 draw_server_with_damage(server);
321 view_handle_surface_commit(struct wl_listener *listener,
322 void *data TINYDS_UNUSED)
324 struct tinyds_view *view;
326 view = wl_container_of(listener, view, surface_commit);
327 draw_server_with_damage(view->server);
331 server_new_xdg_surface(struct wl_listener *listener, void *data)
333 struct tinyds_server *server;
334 struct tinyds_view *view;
335 struct ds_xdg_surface *xdg_surface;
337 server = wl_container_of(listener, server, new_xdg_surface);
340 ds_inf("New xdg_surface(%p)", (void *)xdg_surface);
342 view = calloc(1, sizeof *view);
345 view->server = server;
346 view->xdg_surface = xdg_surface;
348 view->xdg_surface_map.notify = view_handle_xdg_surface_map;
349 ds_xdg_surface_add_map_listener(xdg_surface,
350 &view->xdg_surface_map);
352 view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap;
353 ds_xdg_surface_add_unmap_listener(xdg_surface,
354 &view->xdg_surface_unmap);
356 view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy;
357 ds_xdg_surface_add_destroy_listener(xdg_surface,
358 &view->xdg_surface_destroy);
360 view->surface_commit.notify = view_handle_surface_commit;
361 ds_surface_add_commit_listener(
362 ds_xdg_surface_get_surface(xdg_surface),
363 &view->surface_commit);
365 wl_list_insert(server->views.prev, &view->link);
367 view->x = rand() % 1000;
368 view->y = rand() % 500;
371 view->effect_type = -1;
373 ds_inf("view at (%d, %d)", view->x, view->y);
377 backend_handle_new_output(struct wl_listener *listener, void *data)
379 struct tinyds_server *server;
380 struct tinyds_output *output;
381 struct ds_output *ds_output;
382 const struct ds_output_mode *mode;
384 server = wl_container_of(listener, server, new_output);
387 ds_inf("New output(%p)", ds_output);
392 mode = ds_output_get_preferred_mode(ds_output);
393 ds_output_set_mode(ds_output, mode);
395 output = calloc(1, sizeof *output);
399 output->server = server;
400 output->ds_output = ds_output;
401 output->width = mode->width;
402 output->height = mode->height;
403 output->drawable = true;
404 output->damaged = true;
406 #ifdef USE_TDM_BUFFER_QUEUE
407 output_buffer_queue_init(output);
408 output_renderer_init(output);
410 output_swapchain_init(output, mode->width, mode->height,
411 DRM_FORMAT_XRGB8888);
414 output->output_destroy.notify = output_handle_destroy;
415 ds_output_add_destroy_listener(ds_output, &output->output_destroy);
417 output->output_frame.notify = output_handle_frame;
418 ds_output_add_frame_listener(ds_output, &output->output_frame);
420 ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height);
422 server->output = output;
428 add_new_dpms(struct tinyds_server *server)
430 struct tinyds_dpms *dpms;
432 dpms = calloc(1, sizeof *dpms);
436 dpms->ds_dpms = ds_tizen_dpms_create(server->display);
440 dpms->destroy.notify = dpms_handle_destroy;
441 ds_tizen_dpms_add_destroy_listener(dpms->ds_dpms, &dpms->destroy);
443 dpms->set_dpms.notify = dpms_handle_set_dpms;
444 ds_tizen_dpms_add_set_dpms_listener(dpms->ds_dpms, &dpms->set_dpms);
446 dpms->get_dpms.notify = dpms_handle_get_dpms;
447 ds_tizen_dpms_add_get_dpms_listener(dpms->ds_dpms, &dpms->get_dpms);
451 ds_inf("Dpms (%p) added", dpms);
457 backend_handle_new_input(struct wl_listener *listener, void *data)
459 struct tinyds_server *server;
460 struct ds_input_device *dev = data;
461 enum ds_input_device_type dev_type;
463 server = wl_container_of(listener, server, new_input);
465 dev_type = ds_input_device_get_type(dev);
468 case DS_INPUT_DEVICE_KEYBOARD:
469 server_add_keyboard(server, dev);
470 server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD;
472 case DS_INPUT_DEVICE_TOUCH:
473 server_add_touch(server, dev);
474 server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH;
476 case DS_INPUT_DEVICE_POINTER:
477 server_add_pointer(server, dev);
478 server->seat_caps |= WL_SEAT_CAPABILITY_POINTER;
481 ds_err("Unknown type(%d) of ds_input_device", dev_type);
485 ds_seat_set_capabilities(server->seat, server->seat_caps);
489 devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode)
491 struct ds_tizen_input_devicemgr_keymap_data *data;
493 data = calloc(1, sizeof *data);
495 ds_err("Failed to alloc memory\n");
499 data->name = strdup(name);
500 data->keycode = keycode;
502 wl_list_insert(list, &data->link);
506 devicemgr_remove_keymap_data(struct wl_list *list, int keycode)
508 struct ds_tizen_input_devicemgr_keymap_data *data, *tmp;
510 wl_list_for_each_safe(data, tmp, list, link) {
511 if (data->keycode == keycode) {
512 wl_list_remove(&data->link);
519 devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr)
521 struct wl_list keymap_list;
524 wl_list_init(&keymap_list);
526 devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455);
527 devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456);
528 devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457);
529 devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458);
531 res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list);
533 ds_inf("Failed to set keymap");
535 devicemgr_remove_keymap_data(&keymap_list, 455);
536 devicemgr_remove_keymap_data(&keymap_list, 456);
537 devicemgr_remove_keymap_data(&keymap_list, 457);
538 devicemgr_remove_keymap_data(&keymap_list, 458);
542 devicemgr_handle_pointer_warp(struct wl_listener *listener, void *data)
544 struct tinyds_server *server;
545 struct tinyds_pointer *pointer;
546 struct ds_tizen_input_devicemgr_event_pointer_warp *event = data;
547 double sx = 0.f, sy = 0.f;
548 struct tinyds_view *view = NULL;
550 server = wl_container_of(listener, server, pointer_warp);
552 ds_inf("Pointer warp: surface(%p) x(%.2f) y(%.2f)", event->surface,
555 wl_list_for_each(pointer, &server->pointers, link){
556 if (!pointer->focused_view) continue;
557 view = pointer->focused_view;
561 if (event->surface != ds_xdg_surface_get_surface(view->xdg_surface)) {
562 ds_inf("Pointer is not on the requested surface");
566 server->output_x = view->x + (event->x * server->output->width);
567 server->output_y = view->y + (event->y * server->output->height);
569 server_view_at(server, server->output_x, server->output_y, &sx, &sy);
571 ds_inf("notify motion: sx:%.2f sy:%.2f, output_x:%.1f, output_y:%.1f",
572 sx, sy, server->output_x, server->output_y);
574 ds_seat_pointer_notify_motion(server->seat,
575 event->time_msec, sx, sy);
579 devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
581 struct tinyds_server *server =
582 wl_container_of(listener, server, devicemgr_destroy);
584 wl_list_remove(&server->devicemgr_destroy.link);
585 wl_list_remove(&server->pointer_warp.link);
587 server->devicemgr = NULL;
591 launch_effect_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
593 struct tinyds_server *server =
594 wl_container_of(listener, server, effect_destroy);
596 wl_list_remove(&server->effect_destroy.link);
597 wl_list_remove(&server->effect_type_set.link);
598 wl_list_remove(&server->effect_type_unset.link);
599 wl_list_remove(&server->new_splash.link);
601 server->effect = NULL;
605 launch_effect_handle_type_set(struct wl_listener *listener, void *data)
607 struct tinyds_server *server;
608 struct ds_tizen_effect_event_type_set *event = data;
609 struct tinyds_view *view = NULL;
610 bool existing = false;
612 server = wl_container_of(listener, server, effect_type_set);
614 ds_inf("Launch effect. type_set: pid(%u) type:%s", event->pid, (event->effect_type == 1) ? "depth-in" : "launch");
616 wl_list_for_each(view, &server->views, link) {
617 if (view->pid == event->pid) {
618 view->effect_type = event->effect_type;
619 ds_inf("Launch effect. existing pid");
624 ds_tizen_effect_unset_effect_type(server->effect, event->pid);
626 ds_tizen_effect_set_effect_type(server->effect, event->pid, event->effect_type);
631 launch_effect_handle_type_unset(struct wl_listener *listener, void *data)
633 struct tinyds_server *server;
634 struct ds_tizen_effect_event_type_unset *event = data;
635 struct tinyds_view *view = NULL;
637 server = wl_container_of(listener, server, effect_type_unset);
639 ds_inf("Launch effect. type_unset: pid(%u)", event->pid);
641 wl_list_for_each(view, &server->views, link) {
642 if (view->pid == event->pid) {
643 view->effect_type = -1;
644 ds_inf("Launch effect. pid found");
647 ds_tizen_effect_unset_effect_type(server->effect, event->pid);
651 launch_splash_handle_owner(struct wl_listener *listener, void *data)
653 struct tinyds_server *server;
654 struct ds_tizen_splash_event_owner *event = data;
655 struct tinyds_view *view = NULL;
657 server = wl_container_of(listener, server, splash_owner);
659 ds_inf("Splash owner. pid(%u)", event->pid);
661 wl_list_for_each(view, &server->views, link) {
662 if (view->pid == event->pid) {
663 if (event->pid == ds_tizen_splash_get_pid(server->splash))
666 ds_tizen_splash_set_pid(server->splash, event->pid);
673 launch_effect_handle_new_splash(struct wl_listener *listener, void *data)
675 struct tinyds_server *server;
676 struct ds_tizen_effect_event_new_splash *event = data;
677 struct tinyds_view *view = NULL;
679 server = wl_container_of(listener, server, new_splash);
681 ds_inf("Launch new splash. splash(%p)", event->splash);
682 if (!event->splash) return;
684 server->splash = event->splash;
686 // new view for "Launchscreen"
687 view = calloc(1, sizeof *view);
689 wl_list_insert(server->views.prev, &view->link);
690 view->pid = ds_tizen_splash_get_pid(event->splash);
692 server->splash_owner.notify = launch_splash_handle_owner;
693 ds_tizen_splash_add_owner_listener(server->splash,
694 &server->splash_owner);
698 init_server(struct tinyds_server *server, struct wl_display *display)
700 server->display = display;
702 wl_list_init(&server->views);
704 if (wl_display_init_shm(display) != 0)
707 server->backend = ds_tdm_backend_create(display);
708 if (!server->backend)
711 server->input_backend = ds_libinput_backend_create(display);
712 if (!server->input_backend) {
713 ds_backend_destroy(server->backend);
717 server->new_output.notify = backend_handle_new_output;
718 ds_backend_add_new_output_listener(server->backend,
719 &server->new_output);
721 wl_list_init(&server->keyboards);
722 wl_list_init(&server->pointers);
723 server->new_input.notify = backend_handle_new_input;
724 ds_backend_add_new_input_listener(server->input_backend, &server->new_input);
726 server->compositor = ds_compositor_create(display);
727 if (!server->compositor)
730 server->tbm_server = ds_tbm_server_create(display);
731 if (!server->tbm_server)
734 server->xdg_shell = ds_xdg_shell_create(display);
735 if (!server->xdg_shell)
738 server->new_xdg_surface.notify = server_new_xdg_surface;
739 ds_xdg_shell_add_new_surface_listener(server->xdg_shell,
740 &server->new_xdg_surface);
742 if (!add_new_dpms(server))
745 server->seat = ds_seat_create(display, "seat0" /* arbitrary name */);
748 server->seat_caps = 0;
750 server->devicemgr = ds_tizen_input_devicemgr_create(
751 server->input_backend, server->seat);
752 if (!server->devicemgr) {
756 devicemgr_set_keymap(server->devicemgr);
758 server->devicemgr_destroy.notify = devicemgr_handle_destroy;
759 ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr,
760 &server->devicemgr_destroy);
762 server->pointer_warp.notify = devicemgr_handle_pointer_warp;
763 ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr,
764 &server->pointer_warp);
766 server->effect = ds_tizen_effect_create(display);
767 if (!server->effect) {
771 server->effect_destroy.notify = launch_effect_handle_destroy;
772 ds_tizen_effect_add_destroy_listener(server->effect,
773 &server->effect_destroy);
775 server->effect_type_set.notify = launch_effect_handle_type_set;
776 ds_tizen_effect_add_type_set_listener(server->effect,
777 &server->effect_type_set);
779 server->effect_type_unset.notify = launch_effect_handle_type_unset;
780 ds_tizen_effect_add_type_unset_listener(server->effect,
781 &server->effect_type_unset);
783 server->new_splash.notify = launch_effect_handle_new_splash;
784 ds_tizen_effect_add_new_splash_listener(server->effect,
785 &server->new_splash);
790 ds_backend_destroy(server->backend);
791 ds_backend_destroy(server->input_backend);
797 output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
799 struct tinyds_output *output =
800 wl_container_of(listener, output, output_destroy);
802 wl_list_remove(&output->output_destroy.link);
803 wl_list_remove(&output->output_frame.link);
805 if (output->front_buffer)
806 ds_buffer_unlock(output->front_buffer);
808 #ifdef USE_TDM_BUFFER_QUEUE
809 fini_renderer(&output->renderer);
811 if (output->swapchain)
812 ds_swapchain_destroy(output->swapchain);
814 if (output->allocator)
815 ds_allocator_destroy(output->allocator);
818 wl_display_terminate(output->server->display);
820 output->server->output = NULL;
826 output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
828 struct tinyds_output *output =
829 wl_container_of(listener, output, output_frame);
831 output->drawable = true;
836 draw_server_with_damage(struct tinyds_server *server)
838 server->output->damaged = true;
839 draw_output(server->output);
842 #ifdef USE_TDM_BUFFER_QUEUE
844 output_handle_buffer_queue_acquirable(struct wl_listener *listener,
845 void *data TINYDS_UNUSED)
847 struct tinyds_output *output;
848 struct ds_buffer *buffer;
850 output = wl_container_of(listener, output, buffer_queue_acquirable);
852 buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
855 output_swap_buffer(output, buffer);
859 output_buffer_queue_init(struct tinyds_output *output)
861 struct ds_tdm_output *tdm_output;
863 tdm_output = ds_tdm_output_from_output(output->ds_output);
866 output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output);
867 assert(output->buffer_queue);
869 output->buffer_queue_acquirable.notify =
870 output_handle_buffer_queue_acquirable;
871 ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue,
872 &output->buffer_queue_acquirable);
876 output_renderer_init(struct tinyds_output *output)
878 init_renderer(&output->renderer);
880 renderer_set_surface_queue(&output->renderer,
881 ds_tdm_buffer_queue_get_native_queue(output->buffer_queue));
883 renderer_set_bg_color(&output->renderer, 80, 80, 80);
887 output_draw_with_renderer(struct tinyds_output *output)
889 struct tinyds_view *view;
891 ds_dbg(">> BEGIN UPDATE TEXTURES");
893 wl_list_for_each(view, &output->server->views, link) {
894 struct ds_buffer *ds_buffer;
895 struct ds_tbm_client_buffer *tbm_buffer;
896 tbm_surface_h surface;
901 ds_buffer = ds_surface_get_buffer(
902 ds_xdg_surface_get_surface(view->xdg_surface));
905 tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
908 surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
910 renderer_add_texture(&output->renderer, surface, view->x, view->y);
912 view_send_frame_done(view);
915 ds_dbg("<< END UPDATE TEXTURES");
917 renderer_draw(&output->renderer);
922 output_swapchain_init(struct tinyds_output *output,
923 int width, int height, uint32_t format);
926 output->allocator = ds_tbm_allocator_create();
927 assert(output->allocator);
929 output->swapchain = ds_swapchain_create(output->allocator,
930 width, height, format);
931 assert(output->swapchain);
935 output_draw_with_swapchain(struct tinyds_output *output)
937 struct tinyds_view *view;
938 struct ds_buffer *output_buffer;
939 pixman_image_t *output_image;
941 output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
945 output_image = pixman_image_from_buffer(output_buffer,
946 DS_BUFFER_DATA_PTR_ACCESS_WRITE);
948 ds_buffer_unlock(output_buffer);
952 pixman_image_fill_color(output_image, 80, 80, 80);
954 wl_list_for_each(view, &output->server->views, link) {
957 draw_view(view, output_image);
959 pixman_image_unref(output_image);
961 output_swap_buffer(output, output_buffer);
965 draw_view(struct tinyds_view *view, pixman_image_t *dst_image)
967 struct ds_buffer *buffer;
968 pixman_image_t *src_image;
970 buffer = ds_surface_get_buffer(
971 ds_xdg_surface_get_surface(view->xdg_surface));
975 src_image = pixman_image_from_buffer(buffer,
976 DS_BUFFER_DATA_PTR_ACCESS_READ);
977 pixman_image_composite32(PIXMAN_OP_OVER,
983 pixman_image_get_width(src_image),
984 pixman_image_get_height(src_image));
985 pixman_image_unref(src_image);
987 view_send_frame_done(view);
992 draw_output(struct tinyds_output *output)
995 if (!output->drawable || !output->damaged)
998 #ifdef USE_TDM_BUFFER_QUEUE
999 output_draw_with_renderer(output);
1001 output_draw_with_swapchain(output);
1004 output->drawable = false;
1005 output->damaged = false;
1009 output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
1011 ds_output_attach_buffer(output->ds_output, buffer);
1012 ds_output_commit(output->ds_output);
1014 if (output->front_buffer)
1015 ds_buffer_unlock(output->front_buffer);
1016 output->front_buffer = buffer;
1020 view_send_frame_done(struct tinyds_view *view)
1022 struct timespec now;
1023 clock_gettime(CLOCK_MONOTONIC, &now);
1024 ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
1029 server_dispatch_stdin(int fd, uint32_t mask, void *data)
1031 struct tinyds_server *server = data;
1033 wl_display_terminate(server->display);
1039 dpms_handle_destroy(struct wl_listener *listener, void *data)
1041 struct tinyds_dpms *dpms;
1043 dpms = wl_container_of(listener, dpms, destroy);
1045 ds_inf("Dpms(%p) destroyed", dpms);
1047 wl_list_remove(&dpms->destroy.link);
1048 wl_list_remove(&dpms->set_dpms.link);
1049 wl_list_remove(&dpms->get_dpms.link);
1055 dpms_handle_set_dpms(struct wl_listener *listener, void *data)
1057 struct tinyds_dpms *dpms;
1058 struct ds_tizen_dpms_event *event = data;
1060 dpms = wl_container_of(listener, dpms, set_dpms);
1062 ds_inf("Dpms(%p) set dpms : %d", dpms, event->mode);
1065 //set dpms mode to output
1066 ds_tizen_dpms_send_set_result(dpms->ds_dpms, event->mode,
1067 DS_TIZEN_DPMS_ERROR_NONE);
1071 dpms_handle_get_dpms(struct wl_listener *listener, void *data)
1073 struct tinyds_dpms *dpms;
1075 dpms = wl_container_of(listener, dpms, get_dpms);
1077 ds_inf("Dpms(%p) get dpms", dpms);
1080 //get dpms mode from output
1081 ds_tizen_dpms_send_get_result(dpms->ds_dpms, DS_TIZEN_DPMS_MODE_ON,
1082 DS_TIZEN_DPMS_ERROR_NONE);
1086 keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
1088 struct tinyds_keyboard *kbd;
1090 kbd = wl_container_of(listener, kbd, destroy);
1092 ds_inf("Keyboard(%p) destroyed", kbd);
1094 wl_list_remove(&kbd->destroy.link);
1095 wl_list_remove(&kbd->key.link);
1096 wl_list_remove(&kbd->link);
1102 server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym)
1105 case XKB_KEY_BackSpace:
1106 wl_display_terminate(server->display);
1116 keyboard_handle_key(struct wl_listener *listener, void *data)
1118 struct tinyds_keyboard *kbd;
1119 struct ds_event_keyboard_key *event = data;
1120 struct ds_keyboard *ds_keyboard;
1121 struct xkb_state *xkb_state;
1122 const xkb_keysym_t *syms;
1124 bool handled = false;
1126 kbd = wl_container_of(listener, kbd, key);
1128 ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), "
1129 "update_state(%d)", kbd->dev,
1130 event->keycode, event->state, event->time_msec,
1131 event->update_state);
1133 ds_keyboard = ds_input_device_get_keyboard(kbd->dev);
1135 if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1136 xkb_state = ds_keyboard_get_xkb_state(ds_keyboard);
1138 nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8,
1140 for (int i = 0; i < nsyms; i++) {
1141 handled = server_handle_keybinding(kbd->server, syms[i]);
1147 ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec,
1148 event->keycode, event->state);
1153 server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev)
1155 struct tinyds_keyboard *kbd;
1156 struct xkb_context *context;
1157 struct xkb_keymap *keymap;
1159 kbd = calloc(1, sizeof *kbd);
1163 kbd->server = server;
1165 context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
1166 keymap = xkb_keymap_new_from_names(context, NULL,
1167 XKB_KEYMAP_COMPILE_NO_FLAGS);
1170 ds_err("Failed to compile keymap");
1171 xkb_context_unref(context);
1174 ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap);
1176 xkb_keymap_unref(keymap);
1177 xkb_context_unref(context);
1179 kbd->destroy.notify = keyboard_handle_device_destroy;
1180 ds_input_device_add_destroy_listener(dev, &kbd->destroy);
1182 kbd->key.notify = keyboard_handle_key;
1183 ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key);
1185 wl_list_insert(&server->keyboards, &kbd->link);
1187 ds_inf("Keyboard(%p) added", kbd);
1190 static struct tinyds_view *
1191 server_view_at(struct tinyds_server *server, double lx, double ly,
1192 double *sx, double *sy)
1194 struct tinyds_view *view;
1195 struct ds_surface *surface;
1196 struct ds_buffer *buffer;
1197 int x, y, w = 0, h = 0;
1199 wl_list_for_each(view, &server->views, link) {
1200 surface = ds_xdg_surface_get_surface(view->xdg_surface);
1201 buffer = ds_surface_get_buffer(surface);
1202 ds_buffer_get_size(buffer, &w, &h);
1207 if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) {
1219 touch_handle_device_destroy(struct wl_listener *listener, void *data)
1221 struct tinyds_touch *touch;
1223 touch = wl_container_of(listener, touch, destroy);
1225 ds_inf("Touch(%p) destroyed", touch);
1227 wl_list_remove(&touch->destroy.link);
1228 wl_list_remove(&touch->down.link);
1229 wl_list_remove(&touch->up.link);
1230 wl_list_remove(&touch->motion.link);
1236 touch_handle_down(struct wl_listener *listener, void *data)
1238 struct ds_event_touch_down *event = data;
1239 struct tinyds_touch *touch;
1240 struct tinyds_view *view;
1241 struct tinyds_server *server;
1242 double sx = 0.f, sy = 0.f;
1244 touch = wl_container_of(listener, touch, down);
1246 server = touch->server;
1247 server->output_x = event->x * server->output->width;
1248 server->output_y = event->y * server->output->height;
1250 ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1251 touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1253 view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1256 ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface),
1257 event->time_msec, event->id, sx, sy);
1262 touch_handle_up(struct wl_listener *listener, void *data)
1264 struct ds_event_touch_up *event = data;
1265 struct tinyds_touch *touch;
1267 touch = wl_container_of(listener, touch, up);
1269 ds_inf("Touch(%p) event up: id(%d) time_msec(%d)",
1270 touch->dev, event->id, event->time_msec);
1272 ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id);
1276 touch_handle_motion(struct wl_listener *listener, void *data)
1278 struct ds_event_touch_motion *event = data;
1279 struct tinyds_touch *touch;
1280 struct tinyds_view *view;
1281 struct tinyds_server *server;
1282 double sx = 0.f, sy = 0.f;
1284 touch = wl_container_of(listener, touch, motion);
1286 server = touch->server;
1287 server->output_x = event->x * server->output->width;
1288 server->output_y = event->y * server->output->height;
1290 ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1291 touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1293 view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1296 ds_seat_touch_notify_motion(server->seat, event->time_msec,
1302 server_add_touch(struct tinyds_server *server, struct ds_input_device *dev)
1304 struct tinyds_touch *touch;
1306 touch = calloc(1, sizeof *touch);
1310 touch->server = server;
1312 touch->destroy.notify = touch_handle_device_destroy;
1313 ds_input_device_add_destroy_listener(dev, &touch->destroy);
1315 touch->down.notify = touch_handle_down;
1316 ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down);
1318 touch->up.notify = touch_handle_up;
1319 ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up);
1321 touch->motion.notify = touch_handle_motion;
1322 ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion);
1324 ds_inf("Touch(%p) added", touch);
1328 pointer_handle_device_destroy(struct wl_listener *listener, void *data)
1330 struct tinyds_pointer *pointer;
1332 pointer = wl_container_of(listener, pointer, destroy);
1334 ds_inf("Pointer(%p) destroyed", pointer);
1336 wl_list_remove(&pointer->destroy.link);
1337 wl_list_remove(&pointer->motion.link);
1338 wl_list_remove(&pointer->button.link);
1339 wl_list_remove(&pointer->frame.link);
1340 wl_list_remove(&pointer->link);
1346 pointer_handle_motion(struct wl_listener *listener, void *data)
1348 struct tinyds_pointer *pointer;
1349 struct ds_event_pointer_motion *event = data;
1350 struct tinyds_view *view;
1351 struct tinyds_server *server;
1355 pointer = wl_container_of(listener, pointer, motion);
1357 server = pointer->server;
1358 if (server->output) {
1359 ow = server->output->width;
1360 oh = server->output->height;
1363 if (server->output_x + event->delta_x >= ow)
1364 server->output_x = ow;
1365 else if(server->output_x + event->delta_x <= 0.f)
1366 server->output_x = 0.f;
1368 server->output_x = server->output_x + event->delta_x ;
1369 if (server->output_y + event->delta_y >= oh)
1370 server->output_y = oh;
1371 else if(server->output_y + event->delta_y <= 0.f)
1372 server->output_y = 0.f;
1374 server->output_y = server->output_y + event->delta_y ;
1376 ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f",
1377 pointer, event->delta_x, event->delta_y, server->output_x, server->output_y);
1379 view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy);
1381 if (pointer->focused_view != view) {
1382 if (pointer->focused_view) {
1383 ds_inf("Clear pointer focus from view(%p)", pointer->focused_view);
1384 ds_seat_pointer_notify_clear_focus(pointer->server->seat);
1385 pointer->focused_view = NULL;
1389 ds_inf("Set pointer focus to view(%p)", view);
1390 ds_seat_pointer_notify_enter(pointer->server->seat,
1391 ds_xdg_surface_get_surface(view->xdg_surface), sx, sy);
1392 pointer->focused_view = view;
1397 ds_seat_pointer_notify_motion(pointer->server->seat,
1398 event->time_msec, sx, sy);
1403 pointer_handle_button(struct wl_listener *listener, void *data)
1405 struct tinyds_pointer *pointer;
1406 struct ds_event_pointer_button *event = data;
1408 pointer = wl_container_of(listener, pointer, button);
1410 ds_inf("Pointer(%p) button(%d): state(%s) time(%d)",
1411 pointer, event->button,
1412 (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released",
1415 ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state);
1419 pointer_handle_frame(struct wl_listener *listener, void *data)
1421 struct tinyds_pointer *pointer;
1423 pointer = wl_container_of(listener, pointer, frame);
1425 ds_inf("Pointer(%p) frame", pointer);
1426 ds_seat_pointer_notify_frame(pointer->server->seat);
1430 server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev)
1432 struct tinyds_pointer *pointer;
1434 pointer = calloc(1, sizeof *pointer);
1438 pointer->server = server;
1439 server->output_x = 200;
1440 server->output_y = 200;
1442 pointer->destroy.notify = pointer_handle_device_destroy;
1443 ds_input_device_add_destroy_listener(dev, &pointer->destroy);
1445 pointer->motion.notify = pointer_handle_motion;
1446 ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev),
1449 pointer->button.notify = pointer_handle_button;
1450 ds_pointer_add_button_listener(ds_input_device_get_pointer(dev),
1453 pointer->frame.notify = pointer_handle_frame;
1454 ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev),
1457 pointer->focused_view = NULL;
1459 wl_list_insert(&server->pointers, &pointer->link);
1461 ds_inf("Pointer(%p) added", pointer);