1 #include "tinyds-tdm.h"
5 struct tinyds_server *server;
6 struct ds_output *ds_output;
7 struct ds_allocator *allocator;
8 #ifdef USE_TDM_BUFFER_QUEUE
9 struct tinyds_renderer renderer;
10 struct ds_tdm_buffer_queue *buffer_queue;
11 struct wl_listener buffer_queue_acquirable;
13 struct ds_swapchain *swapchain;
15 struct ds_buffer *front_buffer;
17 struct wl_listener output_destroy;
18 struct wl_listener output_frame;
22 struct wl_event_source *idle_commit;
27 struct ds_tdm_output_hwc *hwc;
28 struct ds_tdm_output_hwc_window *bg_hwc_window;
32 struct ds_tdm_output_hwc_window *cursor_hwc_window;
38 struct tinyds_server *server;
40 struct tinyds_texture *texture;
41 struct ds_xdg_surface *xdg_surface;
43 struct wl_listener xdg_surface_map;
44 struct wl_listener xdg_surface_unmap;
45 struct wl_listener xdg_surface_destroy;
46 struct wl_listener surface_commit;
47 struct wl_list link; // tinyds_server::views
49 struct ds_tdm_output_hwc_window *hwc_window;
60 struct ds_input_device *dev;
61 struct tinyds_server *server;
63 struct tinyds_view *focused_view;
65 struct wl_listener destroy;
66 struct wl_listener motion; //relative
67 struct wl_listener button;
68 struct wl_listener frame;
69 struct wl_list link; //tinyds_server::pointers
72 struct tinyds_keyboard
74 struct ds_input_device *dev;
75 struct tinyds_server *server;
77 struct wl_listener destroy;
78 struct wl_listener key;
79 struct wl_list link; //tinyds_server::keyboards
84 struct ds_input_device *dev;
85 struct tinyds_server *server;
87 struct wl_listener destroy;
88 struct wl_listener down;
89 struct wl_listener up;
90 struct wl_listener motion;
93 struct tinyds_text_input {
94 struct ds_tizen_text_input *input;
95 struct ds_tizen_text_input_manager *text_input_mgr;
97 struct tinyds_server *server;
98 struct ds_surface *surface;
100 struct wl_list input_methods;
102 struct wl_listener mgr_destroy;
103 struct wl_listener new_text_input;
105 struct wl_listener destroy;
106 struct wl_listener text_input_activate;
107 struct wl_listener text_input_deactivate;
108 struct wl_listener text_input_reset;
109 struct wl_listener text_input_set_content_type;
110 struct wl_listener text_input_invoke_action;
111 struct wl_listener text_input_commit_state;
112 struct wl_listener text_input_set_preferred_language;
115 struct tinyds_input_method {
116 struct ds_tizen_input_method *input_method;
117 struct ds_tizen_input_method_manager *input_method_mgr;
119 struct tinyds_server *server;
120 struct tinyds_text_input *input;
121 struct tinyds_input_method_context *context;
125 struct wl_listener destroy;
126 struct wl_listener mgr_destroy;
129 struct tinyds_input_method_context {
130 struct ds_tizen_input_method_context *context;
132 struct tinyds_server *server;
133 struct tinyds_text_input *input;
134 struct tinyds_input_method *input_method;
136 struct wl_listener destroy;
138 struct wl_listener im_context_commit_string;
139 struct wl_listener im_context_preedit_string;
140 struct wl_listener im_context_preedit_styling;
141 struct wl_listener im_context_preedit_cursor;
142 struct wl_listener im_context_delete_surrounding_text;
143 struct wl_listener im_context_cursor_position;
144 struct wl_listener im_context_modifiers_map;
145 struct wl_listener im_context_keysym;
146 struct wl_listener im_context_grab_keyboard;
147 struct wl_listener im_context_key;
148 struct wl_listener im_context_modifiers;
149 struct wl_listener im_context_language;
150 struct wl_listener im_context_text_direction;
153 struct tinyds_server tinyds;
155 static bool init_server(struct tinyds_server *server, struct wl_display *display);
156 static int server_dispatch_stdin(int fd, uint32_t mask, void *data);
157 static void output_handle_destroy(struct wl_listener *listener, void *data);
158 static void output_handle_frame(struct wl_listener *listener, void *data);
159 static void draw_server_with_damage(struct tinyds_server *server);
160 static void draw_output(struct tinyds_output *output);
161 static void output_swap_buffer(struct tinyds_output *output,
162 struct ds_buffer *buffer);
163 static void view_send_frame_done(struct tinyds_view *view);
164 static void output_hwc_init(struct tinyds_output *output);
165 static void output_schedule_commit(struct tinyds_output *output);
166 static void output_commit(struct tinyds_output *output);
167 #ifdef USE_TDM_BUFFER_QUEUE
168 static void output_buffer_queue_init(struct tinyds_output *output);
169 static void output_renderer_init(struct tinyds_output *output);
170 static void output_draw_with_renderer(struct tinyds_output *output);
172 static void output_swapchain_init(struct tinyds_output *output,
173 int width, int height, uint32_t format);
174 static void output_draw_with_swapchain(struct tinyds_output *output);
175 static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image);
177 static void server_add_keyboard(struct tinyds_server *server,
178 struct ds_input_device *dev);
179 static void server_add_pointer(struct tinyds_server *server,
180 struct ds_input_device *dev);
181 static void server_add_touch(struct tinyds_server *server,
182 struct ds_input_device *dev);
183 static struct tinyds_view *
184 server_view_at(struct tinyds_server *server, double lx, double ly,
185 double *sx, double *sy);
187 static bool add_new_text_input(struct tinyds_server *server);
188 static bool add_new_input_method(struct tinyds_server *server);
189 static bool add_new_input_method_context(
190 struct tinyds_input_method *input_method,
191 struct tinyds_text_input *text_input);
193 static void text_input_mgr_handle_destroy(struct wl_listener *listener,
194 void *data TINYDS_UNUSED);
195 static void text_input_mgr_handle_new_text_input(struct wl_listener *listener,
196 void *data TINYDS_UNUSED);
198 static void input_method_mgr_handle_destroy(struct wl_listener *listener,
199 void *data TINYDS_UNUSED);
201 static void input_method_handle_destroy(struct wl_listener *listener,
202 void *data TINYDS_UNUSED);
207 struct tinyds_server *server = &tinyds;
208 struct wl_display *display;
209 struct wl_event_loop *loop;
213 ds_log_init(DS_INF, NULL);
215 display = wl_display_create();
218 res = init_server(server, display);
221 socket = wl_display_add_socket_auto(display);
224 ds_backend_start(server->backend);
225 ds_backend_start(server->input_backend);
227 setenv("WAYLAND_DISPLAY", socket, true);
229 ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
231 loop = wl_display_get_event_loop(display);
232 server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
233 WL_EVENT_READABLE, server_dispatch_stdin, server);
235 wl_display_run(display);
237 protocol_trace_enable(false);
238 protocol_trace_fini();
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;
253 surface = ds_xdg_surface_get_surface(view->xdg_surface);
257 client = wl_resource_get_client(ds_surface_get_wl_resource(surface));
261 wl_client_get_credentials(client, &pid, NULL, NULL);
263 ds_inf("view pid(%u)", pid);
266 view->effect_type = ds_tizen_launch_effect_get_effect_type(view->server->effect, pid);
267 ds_tizen_launch_effect_unset_effect_type(view->server->effect, pid);
268 ds_inf("view effect_type(%d)", view->effect_type);
272 view_handle_xdg_surface_map(struct wl_listener *listener,
273 void *data TINYDS_UNUSED)
275 struct tinyds_view *view;
276 struct ds_keyboard *keyboard;
277 struct tinyds_keyboard *kbd;
279 view = wl_container_of(listener, view, xdg_surface_map);
282 view_populate_pid(view);
284 wl_list_for_each(kbd, &view->server->keyboards, link) {
285 keyboard = ds_input_device_get_keyboard(kbd->dev);
286 if (keyboard != NULL) {
287 ds_seat_keyboard_notify_enter(view->server->seat,
288 ds_xdg_surface_get_surface(view->xdg_surface),
289 keyboard->keycodes, keyboard->num_keycodes,
290 &keyboard->modifiers);
297 view_handle_xdg_surface_unmap(struct wl_listener *listener,
298 void *data TINYDS_UNUSED)
300 struct tinyds_view *view;
302 view = wl_container_of(listener, view, xdg_surface_unmap);
303 view->mapped = false;
307 view_handle_xdg_surface_destroy(struct wl_listener *listener,
308 void *data TINYDS_UNUSED)
310 struct tinyds_view *view;
312 view = wl_container_of(listener, view, xdg_surface_destroy);
314 draw_server_with_damage(view->server);
316 ds_tdm_output_hwc_window_destroy(view->hwc_window);
318 wl_list_remove(&view->xdg_surface_destroy.link);
319 wl_list_remove(&view->xdg_surface_map.link);
320 wl_list_remove(&view->xdg_surface_unmap.link);
321 wl_list_remove(&view->surface_commit.link);
322 wl_list_remove(&view->link);
327 view_handle_surface_commit(struct wl_listener *listener,
328 void *data TINYDS_UNUSED)
330 struct tinyds_view *view;
332 view = wl_container_of(listener, view, surface_commit);
333 draw_server_with_damage(view->server);
337 server_new_xdg_surface(struct wl_listener *listener, void *data)
339 static unsigned int seedx = 1;
340 static unsigned int seedy = 43210;
341 struct tinyds_server *server;
342 struct tinyds_view *view;
343 struct ds_xdg_surface *xdg_surface;
345 server = wl_container_of(listener, server, new_xdg_surface);
348 ds_inf("New xdg_surface(%p)", (void *)xdg_surface);
350 view = calloc(1, sizeof *view);
353 view->server = server;
354 view->xdg_surface = xdg_surface;
356 view->xdg_surface_map.notify = view_handle_xdg_surface_map;
357 ds_xdg_surface_add_map_listener(xdg_surface,
358 &view->xdg_surface_map);
360 view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap;
361 ds_xdg_surface_add_unmap_listener(xdg_surface,
362 &view->xdg_surface_unmap);
364 view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy;
365 ds_xdg_surface_add_destroy_listener(xdg_surface,
366 &view->xdg_surface_destroy);
368 view->surface_commit.notify = view_handle_surface_commit;
369 ds_surface_add_commit_listener(
370 ds_xdg_surface_get_surface(xdg_surface),
371 &view->surface_commit);
373 view->x = rand_r(&seedx) % 1000;
374 view->y = rand_r(&seedy) % 500;
376 view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc);
377 assert(view->hwc_window);
379 wl_list_insert(server->views.prev, &view->link);
382 view->effect_type = -1;
384 ds_inf("view at (%d, %d)", view->x, view->y);
388 backend_handle_new_output(struct wl_listener *listener, void *data)
390 struct tinyds_server *server;
391 struct tinyds_output *output;
392 struct ds_output *ds_output;
393 const struct ds_output_mode *mode;
394 struct ds_tdm_box src_box;
396 server = wl_container_of(listener, server, new_output);
399 ds_inf("New output(%p)", ds_output);
404 mode = ds_output_get_preferred_mode(ds_output);
405 ds_output_set_mode(ds_output, mode);
407 output = calloc(1, sizeof *output);
411 output->server = server;
412 output->ds_output = ds_output;
413 output->width = mode->width;
414 output->height = mode->height;
415 output->damaged = true;
416 output->committable = true;
418 output_hwc_init(output);
420 #ifdef USE_TDM_BUFFER_QUEUE
421 output_buffer_queue_init(output);
422 output_renderer_init(output);
424 output_swapchain_init(output, mode->width, mode->height,
425 DRM_FORMAT_XRGB8888);
428 output->bg_hwc_window = ds_tdm_output_hwc_window_create(output->hwc);
429 assert(output->bg_hwc_window);
433 src_box.width = output->width;
434 src_box.height = output->height;
436 ds_tdm_output_hwc_window_set_src_box(output->bg_hwc_window, &src_box);
437 ds_tdm_output_hwc_window_set_position(output->bg_hwc_window, 0, 0);
438 ds_tdm_output_hwc_window_set_dest_size(output->bg_hwc_window, output->width, output->height);
439 ds_tdm_output_hwc_window_set_transform(output->bg_hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
442 output->cursor_enabled = false;
445 output->output_destroy.notify = output_handle_destroy;
446 ds_output_add_destroy_listener(ds_output, &output->output_destroy);
448 output->output_frame.notify = output_handle_frame;
449 ds_output_add_frame_listener(ds_output, &output->output_frame);
451 ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height);
453 server->output = output;
454 server->output_x = (double)(output->width) / 2;
455 server->output_y = (double)(output->height) / 2;
457 output_schedule_commit(output);
461 backend_handle_new_input(struct wl_listener *listener, void *data)
463 struct tinyds_server *server;
464 struct ds_input_device *dev = data;
465 enum ds_input_device_type dev_type;
467 server = wl_container_of(listener, server, new_input);
469 dev_type = ds_input_device_get_type(dev);
472 case DS_INPUT_DEVICE_KEYBOARD:
473 server_add_keyboard(server, dev);
474 server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD;
476 case DS_INPUT_DEVICE_TOUCH:
477 server_add_touch(server, dev);
478 server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH;
480 case DS_INPUT_DEVICE_POINTER:
481 server_add_pointer(server, dev);
482 server->seat_caps |= WL_SEAT_CAPABILITY_POINTER;
485 ds_err("Unknown type(%d) of ds_input_device", dev_type);
489 ds_seat_set_capabilities(server->seat, server->seat_caps);
493 devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode)
495 struct ds_tizen_input_devicemgr_keymap_data *data;
497 data = calloc(1, sizeof *data);
499 ds_err("Failed to alloc memory");
503 data->name = strdup(name);
504 data->keycode = keycode;
506 wl_list_insert(list, &data->link);
510 devicemgr_cleanup_keymap_list(struct wl_list *list)
512 struct ds_tizen_input_devicemgr_keymap_data *data, *tmp;
514 wl_list_for_each_safe(data, tmp, list, link) {
515 wl_list_remove(&data->link);
522 devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr)
524 struct wl_list keymap_list;
527 wl_list_init(&keymap_list);
529 devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455);
530 devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456);
531 devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457);
532 devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458);
534 res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list);
536 ds_inf("Failed to set keymap");
538 devicemgr_cleanup_keymap_list(&keymap_list);
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_launch_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_launch_effect_unset_effect_type(server->effect, event->pid);
626 ds_tizen_launch_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_launch_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_launch_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_launch_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_launch_splash_get_pid(server->splash))
666 ds_tizen_launch_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_launch_splash *splash = data;
677 struct tinyds_view *view = NULL;
679 server = wl_container_of(listener, server, new_splash);
681 ds_inf("Launch new splash. splash(%p)", splash);
684 server->splash = 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_launch_splash_get_pid(splash);
692 server->splash_owner.notify = launch_splash_handle_owner;
693 ds_tizen_launch_splash_add_owner_listener(server->splash,
694 &server->splash_owner);
698 dpms_free_func(void *data)
700 struct tinyds_server *server = (struct tinyds_server *)data;
706 policy_free_func(void *data)
708 struct tinyds_server *server = (struct tinyds_server *)data;
710 server->policy = NULL;
714 init_server(struct tinyds_server *server, struct wl_display *display)
716 server->display = display;
718 wl_list_init(&server->views);
720 if (wl_display_init_shm(display) != 0)
723 server->backend = ds_tdm_backend_create(display);
724 if (!server->backend)
727 server->input_backend = ds_libinput_backend_create(display);
728 if (!server->input_backend) {
729 ds_backend_destroy(server->backend);
733 server->new_output.notify = backend_handle_new_output;
734 ds_backend_add_new_output_listener(server->backend,
735 &server->new_output);
737 wl_list_init(&server->keyboards);
738 wl_list_init(&server->pointers);
739 server->new_input.notify = backend_handle_new_input;
740 ds_backend_add_new_input_listener(server->input_backend, &server->new_input);
742 server->compositor = ds_compositor_create(display);
743 if (!server->compositor)
746 server->tbm_server = ds_tbm_server_create(display);
747 if (!server->tbm_server)
750 server->xdg_shell = ds_xdg_shell_create(display);
751 if (!server->xdg_shell)
754 server->new_xdg_surface.notify = server_new_xdg_surface;
755 ds_xdg_shell_add_new_surface_listener(server->xdg_shell,
756 &server->new_xdg_surface);
758 server->dpms = tinyds_dpms_init(server->display, dpms_free_func, (void *)server);
762 server->policy = tinyds_policy_init(server->display, policy_free_func, (void *)server);
766 server->seat = ds_seat_create(display, "seat0" /* arbitrary name */);
769 server->seat_caps = 0;
771 server->devicemgr = ds_tizen_input_devicemgr_create(
772 server->input_backend, server->seat);
773 if (!server->devicemgr) {
774 ds_err("Could not create ds_tizen_input_devicemgr");
778 devicemgr_set_keymap(server->devicemgr);
780 server->devicemgr_destroy.notify = devicemgr_handle_destroy;
781 ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr,
782 &server->devicemgr_destroy);
784 server->pointer_warp.notify = devicemgr_handle_pointer_warp;
785 ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr,
786 &server->pointer_warp);
788 server->effect = ds_tizen_launch_effect_create(display);
789 if (!server->effect) {
793 server->effect_destroy.notify = launch_effect_handle_destroy;
794 ds_tizen_launch_effect_add_destroy_listener(server->effect,
795 &server->effect_destroy);
797 server->effect_type_set.notify = launch_effect_handle_type_set;
798 ds_tizen_launch_effect_add_type_set_listener(server->effect,
799 &server->effect_type_set);
801 server->effect_type_unset.notify = launch_effect_handle_type_unset;
802 ds_tizen_launch_effect_add_type_unset_listener(server->effect,
803 &server->effect_type_unset);
805 server->new_splash.notify = launch_effect_handle_new_splash;
806 ds_tizen_launch_effect_add_new_splash_listener(server->effect,
807 &server->new_splash);
809 if (!add_new_text_input(server))
812 if (!add_new_input_method(server))
815 if (protocol_trace_init(display))
816 protocol_trace_enable(true);
821 ds_backend_destroy(server->backend);
822 ds_backend_destroy(server->input_backend);
828 output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
830 struct tinyds_output *output =
831 wl_container_of(listener, output, output_destroy);
833 if (output->bg_hwc_window)
834 ds_tdm_output_hwc_window_destroy(output->bg_hwc_window);
836 wl_list_remove(&output->output_destroy.link);
837 wl_list_remove(&output->output_frame.link);
839 if (output->front_buffer)
840 ds_buffer_unlock(output->front_buffer);
842 #ifdef USE_TDM_BUFFER_QUEUE
843 fini_renderer(&output->renderer);
845 if (output->swapchain)
846 ds_swapchain_destroy(output->swapchain);
848 if (output->allocator)
849 ds_allocator_destroy(output->allocator);
852 wl_display_terminate(output->server->display);
854 output->server->output = NULL;
860 output_commit(struct tinyds_output *output)
862 uint32_t num_changed = 0;
863 uint32_t num_windows = 0, current_num_windows = 0;
864 struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL;
865 struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL;
866 enum ds_tdm_output_hwc_window_composition composition;
867 struct tinyds_view *view;
869 bool need_target = false;
870 bool fully_obscured = false;
871 struct ds_buffer *ds_buffer;
872 struct ds_tdm_box src_box;
875 if (!output->committable)
878 if (!output->damaged && !output->target_updated)
881 wl_list_for_each_reverse(view, &output->server->views, link) {
882 if (!view->hwc_window)
885 ds_buffer = ds_surface_get_buffer(
886 ds_xdg_surface_get_surface(view->xdg_surface));
895 ds_buffer_get_size(ds_buffer, &w, &h);
897 if ((output->width <= w) && (output->height <= h))
898 fully_obscured = true;
901 if (fully_obscured) {
902 ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
903 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
905 ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
906 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
912 if (output->cursor_hwc_window) {
915 src_box.width = CURSOR_W;
916 src_box.height = CURSOR_H;
918 ds_tdm_output_hwc_window_set_src_box(output->cursor_hwc_window, &src_box);
919 ds_tdm_output_hwc_window_set_position(output->cursor_hwc_window, output->server->output_x, output->server->output_y);
920 ds_tdm_output_hwc_window_set_dest_size(output->cursor_hwc_window, CURSOR_W, CURSOR_H);
921 ds_tdm_output_hwc_window_set_transform(output->cursor_hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
923 ds_tdm_output_hwc_window_set_composition(output->cursor_hwc_window,
924 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
931 composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows);
932 if (!composited_hwc_windows)
935 wl_list_for_each_reverse(view, &output->server->views, link) {
936 if (!view->hwc_window)
939 ds_buffer = ds_surface_get_buffer(
940 ds_xdg_surface_get_surface(view->xdg_surface));
944 ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer);
946 ds_buffer_get_size(ds_buffer, &w, &h);
953 ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box);
954 ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y);
955 ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h);
956 ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
960 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
961 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
963 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
964 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE);
966 composited_hwc_windows[current_num_windows] = view->hwc_window;
967 current_num_windows++;
969 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
970 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
974 if (!fully_obscured) {
975 composited_hwc_windows[current_num_windows] = output->bg_hwc_window;
976 current_num_windows++;
980 if (output->cursor_hwc_window) {
981 composited_hwc_windows[current_num_windows] = output->cursor_hwc_window;
982 current_num_windows++;
987 if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows,
988 num_windows, &num_changed)) {
989 free(composited_hwc_windows);
990 ds_err("Could not hwc validate");
994 if (composited_hwc_windows)
995 free(composited_hwc_windows);
997 if (num_changed > 0) {
998 changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows);
999 if (!changed_hwc_windows)
1002 if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed,
1003 changed_hwc_windows)) {
1004 free(changed_hwc_windows);
1005 ds_err("Could not get chaged composition");
1009 for (i = 0; i < num_changed; i++) {
1010 composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]);
1011 if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) {
1018 if (changed_hwc_windows)
1019 free(changed_hwc_windows);
1021 if (need_target && output->damaged)
1022 draw_output(output);
1024 #ifdef USE_TDM_BUFFER_QUEUE
1025 struct ds_buffer *buffer;
1027 buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
1029 if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, buffer)) {
1030 ds_err("Could not set hwc client target buffer");
1034 output_swap_buffer(output, buffer);
1038 if (!ds_tdm_output_hwc_accept_validation(output->hwc)) {
1039 ds_err("Could not hwc accept validateion");
1043 ds_output_commit(output->ds_output);
1045 output->committable = false;
1046 output->damaged = false;
1047 output->target_updated = false;
1049 wl_list_for_each(view, &output->server->views, link) {
1050 enum ds_tdm_output_hwc_window_composition composition;
1055 composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1056 if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1057 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1058 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1059 view_send_frame_done(view);
1062 ds_dbg("output:%p commit", output);
1066 output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
1068 struct tinyds_output *output =
1069 wl_container_of(listener, output, output_frame);
1071 ds_dbg("output:%p handle frame", output);
1073 output->committable = true;
1075 output_commit(output);
1079 draw_server_with_damage(struct tinyds_server *server)
1081 server->output->damaged = true;
1082 output_schedule_commit(server->output);
1086 output_hwc_init(struct tinyds_output *output)
1088 struct ds_tdm_output *tdm_output;
1090 tdm_output = ds_tdm_output_from_output(output->ds_output);
1093 output->hwc = ds_tdm_output_get_hwc(tdm_output);
1094 assert(output->hwc);
1096 ds_tdm_output_hwc_set_enabled(output->hwc, true);
1099 #ifdef USE_TDM_BUFFER_QUEUE
1101 output_handle_buffer_queue_acquirable(struct wl_listener *listener,
1102 void *data TINYDS_UNUSED)
1104 struct tinyds_output *output;
1106 output = wl_container_of(listener, output, buffer_queue_acquirable);
1108 output->target_updated = true;
1109 output_schedule_commit(output);
1113 output_buffer_queue_init(struct tinyds_output *output)
1115 struct ds_tdm_output *tdm_output;
1117 tdm_output = ds_tdm_output_from_output(output->ds_output);
1120 output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output);
1121 assert(output->buffer_queue);
1123 output->buffer_queue_acquirable.notify =
1124 output_handle_buffer_queue_acquirable;
1125 ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue,
1126 &output->buffer_queue_acquirable);
1130 output_renderer_init(struct tinyds_output *output)
1132 init_renderer(&output->renderer);
1134 renderer_set_surface_queue(&output->renderer,
1135 ds_tdm_buffer_queue_get_native_queue(output->buffer_queue));
1137 renderer_set_bg_color(&output->renderer, 80, 80, 80);
1141 output_draw_with_renderer(struct tinyds_output *output)
1143 struct tinyds_view *view;
1145 ds_dbg(">> BEGIN UPDATE TEXTURES");
1147 wl_list_for_each(view, &output->server->views, link) {
1148 struct ds_buffer *ds_buffer;
1149 struct ds_tbm_client_buffer *tbm_buffer;
1150 tbm_surface_h surface;
1151 enum ds_tdm_output_hwc_window_composition composition;
1156 composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1157 if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1158 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1159 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1162 ds_buffer = ds_surface_get_buffer(
1163 ds_xdg_surface_get_surface(view->xdg_surface));
1167 tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
1171 surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
1175 renderer_add_texture(&output->renderer, surface, view->x, view->y);
1177 view_send_frame_done(view);
1180 ds_dbg("<< END UPDATE TEXTURES");
1182 renderer_draw(&output->renderer);
1186 output_swapchain_init(struct tinyds_output *output,
1187 int width, int height, uint32_t format)
1190 output->allocator = ds_tbm_allocator_create();
1191 assert(output->allocator);
1193 output->swapchain = ds_swapchain_create(output->allocator,
1194 width, height, format);
1195 assert(output->swapchain);
1199 output_draw_with_swapchain(struct tinyds_output *output)
1201 struct tinyds_view *view;
1202 struct ds_buffer *output_buffer;
1203 pixman_image_t *output_image;
1204 enum ds_tdm_output_hwc_window_composition composition;
1206 output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
1210 output_image = pixman_image_from_buffer(output_buffer,
1211 DS_BUFFER_DATA_PTR_ACCESS_WRITE);
1212 if (!output_image) {
1213 ds_buffer_unlock(output_buffer);
1217 pixman_image_fill_color(output_image, 80, 80, 80);
1219 wl_list_for_each(view, &output->server->views, link) {
1223 composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1224 if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1225 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1226 (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1229 draw_view(view, output_image);
1231 pixman_image_unref(output_image);
1233 if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, output_buffer)) {
1234 ds_err("Could not set hwc client target buffer");
1235 ds_buffer_unlock(output_buffer);
1239 output_swap_buffer(output, output_buffer);
1243 draw_view(struct tinyds_view *view, pixman_image_t *dst_image)
1245 struct ds_buffer *buffer;
1246 pixman_image_t *src_image;
1248 buffer = ds_surface_get_buffer(
1249 ds_xdg_surface_get_surface(view->xdg_surface));
1253 src_image = pixman_image_from_buffer(buffer,
1254 DS_BUFFER_DATA_PTR_ACCESS_READ);
1255 pixman_image_composite32(PIXMAN_OP_OVER,
1261 pixman_image_get_width(src_image),
1262 pixman_image_get_height(src_image));
1263 pixman_image_unref(src_image);
1265 view_send_frame_done(view);
1270 draw_output(struct tinyds_output *output)
1272 #ifdef USE_TDM_BUFFER_QUEUE
1273 output_draw_with_renderer(output);
1275 output_draw_with_swapchain(output);
1278 ds_dbg("output:%p draw", output);
1282 output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
1284 ds_output_attach_buffer(output->ds_output, buffer);
1286 if (output->front_buffer)
1287 ds_buffer_unlock(output->front_buffer);
1288 output->front_buffer = buffer;
1292 view_send_frame_done(struct tinyds_view *view)
1294 struct timespec now;
1295 clock_gettime(CLOCK_MONOTONIC, &now);
1296 ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
1301 server_dispatch_stdin(int fd, uint32_t mask, void *data)
1303 struct tinyds_server *server = data;
1305 wl_display_terminate(server->display);
1311 keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
1313 struct tinyds_keyboard *kbd;
1315 kbd = wl_container_of(listener, kbd, destroy);
1317 ds_inf("Keyboard(%p) destroyed", kbd);
1319 wl_list_remove(&kbd->destroy.link);
1320 wl_list_remove(&kbd->key.link);
1321 wl_list_remove(&kbd->link);
1327 server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym)
1330 case XKB_KEY_BackSpace:
1331 wl_display_terminate(server->display);
1341 keyboard_handle_key(struct wl_listener *listener, void *data)
1343 struct tinyds_keyboard *kbd;
1344 struct ds_event_keyboard_key *event = data;
1345 struct ds_keyboard *ds_keyboard;
1346 struct xkb_state *xkb_state;
1347 const xkb_keysym_t *syms;
1349 bool handled = false;
1351 kbd = wl_container_of(listener, kbd, key);
1353 ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), "
1354 "update_state(%d)", kbd->dev,
1355 event->keycode, event->state, event->time_msec,
1356 event->update_state);
1358 ds_keyboard = ds_input_device_get_keyboard(kbd->dev);
1360 if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1361 xkb_state = ds_keyboard_get_xkb_state(ds_keyboard);
1363 nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8,
1365 for (int i = 0; i < nsyms; i++) {
1366 handled = server_handle_keybinding(kbd->server, syms[i]);
1372 ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec,
1373 event->keycode, event->state);
1378 server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev)
1380 struct tinyds_keyboard *kbd;
1381 struct xkb_context *context;
1382 struct xkb_keymap *keymap;
1384 kbd = calloc(1, sizeof *kbd);
1388 kbd->server = server;
1390 context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
1394 keymap = xkb_keymap_new_from_names(context, NULL,
1395 XKB_KEYMAP_COMPILE_NO_FLAGS);
1398 ds_err("Failed to compile keymap");
1399 xkb_context_unref(context);
1403 ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap);
1405 xkb_keymap_unref(keymap);
1406 xkb_context_unref(context);
1408 kbd->destroy.notify = keyboard_handle_device_destroy;
1409 ds_input_device_add_destroy_listener(dev, &kbd->destroy);
1411 kbd->key.notify = keyboard_handle_key;
1412 ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key);
1414 wl_list_insert(&server->keyboards, &kbd->link);
1416 ds_inf("Keyboard(%p) added", kbd);
1424 static struct tinyds_view *
1425 server_view_at(struct tinyds_server *server, double lx, double ly,
1426 double *sx, double *sy)
1428 struct tinyds_view *view;
1429 struct ds_surface *surface;
1430 struct ds_buffer *buffer;
1431 int x, y, w = 0, h = 0;
1433 wl_list_for_each(view, &server->views, link) {
1434 surface = ds_xdg_surface_get_surface(view->xdg_surface);
1435 buffer = ds_surface_get_buffer(surface);
1436 ds_buffer_get_size(buffer, &w, &h);
1441 if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) {
1453 touch_handle_device_destroy(struct wl_listener *listener, void *data)
1455 struct tinyds_touch *touch;
1457 touch = wl_container_of(listener, touch, destroy);
1459 ds_inf("Touch(%p) destroyed", touch);
1461 wl_list_remove(&touch->destroy.link);
1462 wl_list_remove(&touch->down.link);
1463 wl_list_remove(&touch->up.link);
1464 wl_list_remove(&touch->motion.link);
1470 touch_handle_down(struct wl_listener *listener, void *data)
1472 struct ds_event_touch_down *event = data;
1473 struct tinyds_touch *touch;
1474 struct tinyds_view *view;
1475 struct tinyds_server *server;
1476 double sx = 0.f, sy = 0.f;
1478 touch = wl_container_of(listener, touch, down);
1480 server = touch->server;
1481 server->output_x = event->x * server->output->width;
1482 server->output_y = event->y * server->output->height;
1484 ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1485 touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1487 view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1490 ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface),
1491 event->time_msec, event->id, sx, sy);
1495 if (server->output && server->output->cursor_enabled) {
1496 renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1497 draw_server_with_damage(server);
1503 touch_handle_up(struct wl_listener *listener, void *data)
1505 struct ds_event_touch_up *event = data;
1506 struct tinyds_touch *touch;
1508 touch = wl_container_of(listener, touch, up);
1510 ds_inf("Touch(%p) event up: id(%d) time_msec(%d)",
1511 touch->dev, event->id, event->time_msec);
1513 ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id);
1517 touch_handle_motion(struct wl_listener *listener, void *data)
1519 struct ds_event_touch_motion *event = data;
1520 struct tinyds_touch *touch;
1521 struct tinyds_view *view;
1522 struct tinyds_server *server;
1523 double sx = 0.f, sy = 0.f;
1525 touch = wl_container_of(listener, touch, motion);
1527 server = touch->server;
1528 server->output_x = event->x * server->output->width;
1529 server->output_y = event->y * server->output->height;
1531 ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1532 touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1534 view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1537 ds_seat_touch_notify_motion(server->seat, event->time_msec,
1542 if (server->output && server->output->cursor_enabled) {
1543 renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1544 draw_server_with_damage(server);
1550 server_add_touch(struct tinyds_server *server, struct ds_input_device *dev)
1552 struct tinyds_touch *touch;
1554 touch = calloc(1, sizeof *touch);
1558 touch->server = server;
1560 touch->destroy.notify = touch_handle_device_destroy;
1561 ds_input_device_add_destroy_listener(dev, &touch->destroy);
1563 touch->down.notify = touch_handle_down;
1564 ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down);
1566 touch->up.notify = touch_handle_up;
1567 ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up);
1569 touch->motion.notify = touch_handle_motion;
1570 ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion);
1572 ds_inf("Touch(%p) added", touch);
1576 pointer_handle_device_destroy(struct wl_listener *listener, void *data)
1578 struct tinyds_pointer *pointer;
1579 struct tinyds_server *server;
1581 pointer = wl_container_of(listener, pointer, destroy);
1583 ds_inf("Pointer(%p) destroyed", pointer);
1585 wl_list_remove(&pointer->destroy.link);
1586 wl_list_remove(&pointer->motion.link);
1587 wl_list_remove(&pointer->button.link);
1588 wl_list_remove(&pointer->frame.link);
1589 wl_list_remove(&pointer->link);
1592 server = pointer->server;
1593 if (server->output && wl_list_empty(&server->pointers))
1595 server->output->cursor_enabled = false;
1596 renderer_cursor_destroy(&server->output->renderer);
1598 if (server->output->cursor_hwc_window)
1600 ds_tdm_output_hwc_window_destroy(server->output->cursor_hwc_window);
1601 server->output->cursor_hwc_window = NULL;
1603 draw_server_with_damage(server);
1611 pointer_handle_motion(struct wl_listener *listener, void *data)
1613 struct tinyds_pointer *pointer;
1614 struct ds_event_pointer_motion *event = data;
1615 struct tinyds_view *view;
1616 struct tinyds_server *server;
1620 pointer = wl_container_of(listener, pointer, motion);
1622 server = pointer->server;
1623 if (server->output) {
1624 ow = server->output->width;
1625 oh = server->output->height;
1628 if (server->output_x + event->delta_x >= ow)
1629 server->output_x = ow;
1630 else if(server->output_x + event->delta_x <= 0.f)
1631 server->output_x = 0.f;
1633 server->output_x = server->output_x + event->delta_x ;
1634 if (server->output_y + event->delta_y >= oh)
1635 server->output_y = oh;
1636 else if(server->output_y + event->delta_y <= 0.f)
1637 server->output_y = 0.f;
1639 server->output_y = server->output_y + event->delta_y ;
1641 ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f",
1642 pointer, event->delta_x, event->delta_y, server->output_x, server->output_y);
1644 view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy);
1646 if (pointer->focused_view != view) {
1647 if (pointer->focused_view) {
1648 ds_inf("Clear pointer focus from view(%p)", pointer->focused_view);
1649 ds_seat_pointer_notify_clear_focus(pointer->server->seat);
1650 pointer->focused_view = NULL;
1654 ds_inf("Set pointer focus to view(%p)", view);
1655 ds_seat_pointer_notify_enter(pointer->server->seat,
1656 ds_xdg_surface_get_surface(view->xdg_surface), sx, sy);
1657 pointer->focused_view = view;
1662 ds_seat_pointer_notify_motion(pointer->server->seat,
1663 event->time_msec, sx, sy);
1667 if (server->output && server->output->cursor_enabled) {
1668 renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1669 draw_server_with_damage(server);
1675 pointer_handle_button(struct wl_listener *listener, void *data)
1677 struct tinyds_pointer *pointer;
1678 struct ds_event_pointer_button *event = data;
1680 pointer = wl_container_of(listener, pointer, button);
1682 ds_inf("Pointer(%p) button(%d): state(%s) time(%d)",
1683 pointer, event->button,
1684 (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released",
1687 ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state);
1691 pointer_handle_frame(struct wl_listener *listener, void *data)
1693 struct tinyds_pointer *pointer;
1695 pointer = wl_container_of(listener, pointer, frame);
1697 ds_inf("Pointer(%p) frame", pointer);
1698 ds_seat_pointer_notify_frame(pointer->server->seat);
1702 server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev)
1704 struct tinyds_pointer *pointer;
1706 pointer = calloc(1, sizeof *pointer);
1710 pointer->server = server;
1712 pointer->destroy.notify = pointer_handle_device_destroy;
1713 ds_input_device_add_destroy_listener(dev, &pointer->destroy);
1715 pointer->motion.notify = pointer_handle_motion;
1716 ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev),
1719 pointer->button.notify = pointer_handle_button;
1720 ds_pointer_add_button_listener(ds_input_device_get_pointer(dev),
1723 pointer->frame.notify = pointer_handle_frame;
1724 ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev),
1727 pointer->focused_view = NULL;
1730 if (server->output && wl_list_empty(&server->pointers)) {
1731 server->output_x = (double)(server->output->width) / 2;
1732 server->output_y = (double)(server->output->height) / 2;
1734 server->output->cursor_enabled = true;
1735 renderer_cursor_create(&server->output->renderer, 255, 0, 0, CURSOR_W, CURSOR_H);
1736 renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1738 server->output->cursor_hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc);
1739 assert(server->output->cursor_hwc_window);
1740 draw_server_with_damage(server);
1744 wl_list_insert(&server->pointers, &pointer->link);
1746 ds_inf("Pointer(%p) added", pointer);
1750 output_schedule_commit_handle_idle_timer(void *data)
1752 struct tinyds_output *output = data;
1753 output->idle_commit = NULL;
1755 output_commit(output);
1759 output_schedule_commit(struct tinyds_output *output)
1761 if (output->idle_commit)
1764 struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display);
1765 output->idle_commit =
1766 wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output);
1770 text_input_mgr_handle_destroy(struct wl_listener *listener, void *data)
1772 struct tinyds_text_input *text_input;
1773 struct tinyds_server *server;
1775 ds_inf("text_input_mgr_handle_destroy");
1776 text_input = wl_container_of(listener, text_input, mgr_destroy);
1778 wl_list_remove(&text_input->mgr_destroy.link);
1779 wl_list_remove(&text_input->new_text_input.link);
1781 server = text_input->server;
1782 server->text_input = NULL;
1786 text_input_handle_destroy(struct wl_listener *listener, void *data)
1788 struct tinyds_text_input *text_input;
1790 ds_inf("text_input_handle_destroy");
1792 text_input = wl_container_of(listener, text_input, destroy);
1794 wl_list_remove(&text_input->destroy.link);
1795 wl_list_remove(&text_input->text_input_activate.link);
1796 wl_list_remove(&text_input->text_input_deactivate.link);
1797 wl_list_remove(&text_input->text_input_reset.link);
1798 wl_list_remove(&text_input->text_input_set_content_type.link);
1799 wl_list_remove(&text_input->text_input_invoke_action.link);
1800 wl_list_remove(&text_input->text_input_commit_state.link);
1801 wl_list_remove(&text_input->text_input_set_preferred_language.link);
1807 text_input_handle_activate(struct wl_listener *listener, void *data)
1809 struct tinyds_text_input *text_input;
1810 struct tinyds_input_method *input_method;
1811 struct ds_tizen_text_input_event_activate *event = data;
1813 text_input = wl_container_of(listener, text_input, text_input_activate);
1815 input_method = text_input->server->input_method;
1817 ds_inf("text_input_handle_activate. text_input(%p) seat(%p) surface(%p) text_input(%p)",
1818 text_input, event->seat, event->surface, event->text_input);
1820 if (input_method->input == text_input)
1822 if (input_method->input)
1823 ;//deactivate_input_method(server->input_method);
1824 input_method->input = text_input;
1825 wl_list_insert(&text_input->input_methods, &input_method->link);
1827 text_input->surface = event->surface;
1829 if (!add_new_input_method_context(input_method, text_input))
1832 // ds_tizen_input_method_send_set_text_input_id();
1836 text_input_handle_deactivate(struct wl_listener *listener, void *data)
1838 struct tinyds_text_input *text_input;
1839 struct tinyds_input_method *input_method, *tmp;
1840 struct ds_tizen_text_input_event_deactivate *event = data;
1842 text_input = wl_container_of(listener, text_input, text_input_deactivate);
1843 ds_inf("text_input_handle_deactivate. text_input(%p) seat(%p) text_input(%p)",
1844 text_input, event->seat, event->text_input);
1846 wl_list_for_each_safe(input_method, tmp, &text_input->input_methods, link) {
1847 if (!input_method->input_method || !input_method->context->context) continue;
1848 ds_tizen_input_method_send_deactivate(input_method->input_method, input_method->context->context);
1849 input_method->input = NULL;
1850 input_method->context = NULL;
1851 wl_list_remove(&input_method->link);
1854 text_input->surface = NULL;
1855 // ds_tizen_input_method_send_close_connection();
1859 text_input_handle_reset(struct wl_listener *listener, void *data)
1861 struct tinyds_text_input *text_input;
1862 struct tinyds_input_method *input_method;
1864 text_input = wl_container_of(listener, text_input, text_input_reset);
1866 ds_inf("text_input_handle_reset. text_input(%p)", text_input);
1868 wl_list_for_each(input_method, &text_input->input_methods, link) {
1869 if (!input_method->context || !input_method->context->context) continue;
1870 ds_tizen_input_method_context_send_reset(input_method->context->context);
1875 text_input_handle_set_content_type(struct wl_listener *listener, void *data)
1877 struct tinyds_text_input *text_input;
1878 struct ds_tizen_text_input_event_set_content_type *event = data;
1879 struct tinyds_input_method *input_method;
1881 text_input = wl_container_of(listener, text_input, text_input_set_content_type);
1883 ds_inf("text_input_handle_content_type. text_input(%p) hint(%u) purpose(%u)",
1884 text_input, event->hint, event->purpose);
1886 wl_list_for_each(input_method, &text_input->input_methods, link) {
1887 if (!input_method->context || !input_method->context->context) continue;
1888 ds_tizen_input_method_context_send_content_type(input_method->context->context,
1889 event->hint, event->purpose);
1894 text_input_handle_invoke_action(struct wl_listener *listener, void *data)
1896 struct tinyds_text_input *text_input;
1897 struct ds_tizen_text_input_event_invoke_action *event = data;
1898 struct tinyds_input_method *input_method;
1900 text_input = wl_container_of(listener, text_input, text_input_invoke_action);
1902 ds_inf("text_input_handle_invoke_action. text_input(%p) button(%u) index(%u)",
1903 text_input, event->button, event->index);
1905 wl_list_for_each(input_method, &text_input->input_methods, link) {
1906 if (!input_method->context || !input_method->context->context) continue;
1907 ds_tizen_input_method_context_send_invoke_action(input_method->context->context,
1908 event->button, event->index);
1913 text_input_handle_commit_state(struct wl_listener *listener, void *data)
1915 struct tinyds_text_input *text_input;
1916 struct ds_tizen_text_input_event_commit_state *event = data;
1917 struct tinyds_input_method *input_method;
1919 text_input = wl_container_of(listener, text_input, text_input_commit_state);
1921 ds_inf("text_input_handle_commit_state. text_input(%p) serial(%u)",
1922 text_input, event->serial);
1924 wl_list_for_each(input_method, &text_input->input_methods, link) {
1925 if (!input_method->context || !input_method->context->context) continue;
1926 ds_tizen_input_method_context_send_commit_state(input_method->context->context,
1932 text_input_handle_set_preferred_language(struct wl_listener *listener, void *data)
1934 struct tinyds_text_input *text_input;
1935 struct ds_tizen_text_input_event_set_preferred_language *event = data;
1936 struct tinyds_input_method *input_method;
1938 text_input = wl_container_of(listener, text_input, text_input_set_preferred_language);
1940 ds_inf("text_input_handle_set_preferred_language. text_input(%p) language(%s)",
1941 text_input, event->language);
1943 wl_list_for_each(input_method, &text_input->input_methods, link) {
1944 if (!input_method->context || !input_method->context->context) continue;
1945 ds_tizen_input_method_context_send_preferred_language(input_method->context->context,
1951 text_input_mgr_handle_new_text_input(struct wl_listener *listener, void *data)
1953 struct tinyds_text_input *text_input;
1954 struct ds_tizen_text_input *input = data;
1956 text_input = wl_container_of(listener, text_input, new_text_input);
1958 ds_inf("text_input_mgr_handle_new_text_input");
1960 text_input->input = input;
1962 text_input->destroy.notify = text_input_handle_destroy;
1963 ds_tizen_text_input_add_destroy_listener(text_input->input,
1964 &text_input->destroy);
1966 text_input->text_input_activate.notify = text_input_handle_activate;
1967 ds_tizen_text_input_add_activate_listener(text_input->input,
1968 &text_input->text_input_activate);
1970 text_input->text_input_deactivate.notify = text_input_handle_deactivate;
1971 ds_tizen_text_input_add_deactivate_listener(text_input->input,
1972 &text_input->text_input_deactivate);
1974 text_input->text_input_reset.notify = text_input_handle_reset;
1975 ds_tizen_text_input_add_reset_listener(text_input->input,
1976 &text_input->text_input_reset);
1978 text_input->text_input_set_content_type.notify = text_input_handle_set_content_type;
1979 ds_tizen_text_input_add_set_content_type_listener(text_input->input,
1980 &text_input->text_input_set_content_type);
1982 text_input->text_input_invoke_action.notify = text_input_handle_invoke_action;
1983 ds_tizen_text_input_add_invoke_action_listener(text_input->input,
1984 &text_input->text_input_invoke_action);
1986 text_input->text_input_commit_state.notify = text_input_handle_commit_state;
1987 ds_tizen_text_input_add_commit_state_listener(text_input->input,
1988 &text_input->text_input_commit_state);
1990 text_input->text_input_set_preferred_language.notify = text_input_handle_set_preferred_language;
1991 ds_tizen_text_input_add_set_preferred_language_listener(text_input->input,
1992 &text_input->text_input_set_preferred_language);
1996 input_method_mgr_handle_destroy(struct wl_listener *listener, void *data)
1998 struct tinyds_input_method *input_method;
2000 ds_inf("input_method_mgr_handle_destroy");
2002 input_method = wl_container_of(listener, input_method, mgr_destroy);
2004 wl_list_remove(&input_method->mgr_destroy.link);
2008 input_method_handle_destroy(struct wl_listener *listener, void *data)
2010 struct tinyds_input_method *input_method;
2011 struct tinyds_server *server;
2013 ds_inf("input_method_handle_destroy");
2015 input_method = wl_container_of(listener, input_method, destroy);
2017 wl_list_remove(&input_method->destroy.link);
2019 server = input_method->server;
2020 server->input_method = NULL;
2026 context_handle_destroy(struct wl_listener *listener, void *data)
2028 struct tinyds_input_method_context *context;
2029 struct tinyds_server *server;
2031 ds_inf("context_handle_destroy");
2033 context = wl_container_of(listener, context, destroy);
2035 wl_list_remove(&context->destroy.link);
2037 wl_list_remove(&context->im_context_commit_string.link);
2038 wl_list_remove(&context->im_context_preedit_string.link);
2039 wl_list_remove(&context->im_context_preedit_styling.link);
2040 wl_list_remove(&context->im_context_preedit_cursor.link);
2041 wl_list_remove(&context->im_context_delete_surrounding_text.link);
2042 wl_list_remove(&context->im_context_cursor_position.link);
2043 wl_list_remove(&context->im_context_modifiers_map.link);
2044 wl_list_remove(&context->im_context_keysym.link);
2045 wl_list_remove(&context->im_context_grab_keyboard.link);
2046 wl_list_remove(&context->im_context_key.link);
2047 wl_list_remove(&context->im_context_modifiers.link);
2048 wl_list_remove(&context->im_context_language.link);
2049 wl_list_remove(&context->im_context_text_direction.link);
2051 server = context->server;
2052 server->input_method->context = NULL;
2058 context_handle_commit_string(struct wl_listener *listener, void *data)
2060 struct tinyds_text_input *text_input;
2061 struct tinyds_input_method_context *context;
2062 struct ds_tizen_input_method_context_event_commit_string *event = data;
2064 context = wl_container_of(listener, context, im_context_commit_string);
2065 text_input = context->server->text_input;
2067 ds_inf("context_handle_commit_string. text_input(%p) serial(%u) text(%s)",
2068 text_input, event->serial, event->text);
2070 ds_tizen_text_input_send_commit_string(text_input->input, event->serial, event->text);
2074 context_handle_preedit_string(struct wl_listener *listener, void *data)
2076 struct tinyds_input_method_context *context;
2077 struct tinyds_text_input *text_input;
2078 struct ds_tizen_input_method_context_event_preedit_string *event = data;
2080 context = wl_container_of(listener, context, im_context_preedit_string);
2081 text_input = context->server->text_input;
2083 ds_inf("context_handle_preedit_string. text_input(%p) serial(%u) text(%s) commit(%s)",
2084 text_input, event->serial, event->text, event->commit);
2086 ds_tizen_text_input_send_preedit_string(text_input->input, event->serial, event->text, event->commit);
2090 context_handle_preedit_styling(struct wl_listener *listener, void *data)
2092 struct tinyds_input_method_context *context;
2093 struct tinyds_text_input *text_input;
2094 struct ds_tizen_input_method_context_event_preedit_styling *event = data;
2096 context = wl_container_of(listener, context, im_context_preedit_styling);
2097 text_input = context->server->text_input;
2099 ds_inf("context_handle_preedit_styling. text_input(%p) index(%u) length(%u) style(%u)",
2100 text_input, event->index, event->length, event->style);
2102 ds_tizen_text_input_send_preedit_styling(text_input->input, event->index, event->length, event->style);
2106 context_handle_preedit_cursor(struct wl_listener *listener, void *data)
2108 struct tinyds_input_method_context *context;
2109 struct tinyds_text_input *text_input;
2110 struct ds_tizen_input_method_context_event_preedit_cursor *event = data;
2112 context = wl_container_of(listener, context, im_context_preedit_cursor);
2113 text_input = context->server->text_input;
2115 ds_inf("context_handle_preedit_cursor. text_input(%p) index(%u)",
2116 text_input, event->index);
2118 ds_tizen_text_input_send_preedit_cursor(text_input->input, event->index);
2122 context_handle_delete_surrounding_text(struct wl_listener *listener, void *data)
2124 struct tinyds_input_method_context *context;
2125 struct tinyds_text_input *text_input;
2126 struct ds_tizen_input_method_context_event_delete_surrounding_text *event = data;
2128 context = wl_container_of(listener, context, im_context_delete_surrounding_text);
2129 text_input = context->server->text_input;
2131 ds_inf("context_handle_delete_surrounding_text. text_input(%p) index(%d) length(%u)",
2132 text_input, event->index, event->length);
2134 ds_tizen_text_input_send_delete_surrounding_text(text_input->input, event->index, event->length);
2138 context_handle_cursor_position(struct wl_listener *listener, void *data)
2140 struct tinyds_input_method_context *context;
2141 struct tinyds_text_input *text_input;
2142 struct ds_tizen_input_method_context_event_cursor_position *event = data;
2144 context = wl_container_of(listener, context, im_context_cursor_position);
2145 text_input = context->server->text_input;
2147 ds_inf("context_handle_cursor_position. text_input(%p) index(%d) length(%d)",
2148 text_input, event->index, event->anchor);
2150 ds_tizen_text_input_send_cursor_position(text_input->input, event->index, event->anchor);
2154 context_handle_modifiers_map(struct wl_listener *listener, void *data)
2156 struct tinyds_input_method_context *context;
2157 struct tinyds_text_input *text_input;
2158 struct ds_tizen_input_method_context_event_modifiers_map *event = data;
2160 context = wl_container_of(listener, context, im_context_modifiers_map);
2161 text_input = context->server->text_input;
2163 ds_inf("context_handle_modifiers_map. text_input(%p) map(%p)",
2164 text_input, event->map);
2166 ds_tizen_text_input_send_modifiers_map(text_input->input, event->map);
2170 context_handle_keysym(struct wl_listener *listener, void *data)
2172 struct tinyds_input_method_context *context;
2173 struct tinyds_text_input *text_input;
2174 struct ds_tizen_input_method_context_event_keysym *event = data;
2176 context = wl_container_of(listener, context, im_context_keysym);
2177 text_input = context->server->text_input;
2179 ds_inf("context_handle_keysym. text_input(%p) serial(%u) time(%u) sysm(%u) state(%u) modifiers(%u)",
2180 text_input, event->serial, event->time, event->sym, event->state, event->modifiers);
2182 ds_tizen_text_input_send_keysym(text_input->input, event->serial, event->time, event->sym, event->state, event->modifiers);
2186 context_handle_grab_keyboard(struct wl_listener *listener, void *data)
2188 struct tinyds_input_method_context *context;
2189 struct tinyds_text_input *text_input;
2191 context = wl_container_of(listener, context, im_context_grab_keyboard);
2192 text_input = context->server->text_input;
2194 ds_inf("context_handle_grab_keyboard. text_input(%p)",
2201 context_handle_key(struct wl_listener *listener, void *data)
2203 struct tinyds_input_method_context *context;
2204 struct tinyds_text_input *text_input;
2206 context = wl_container_of(listener, context, im_context_key);
2207 text_input = context->server->text_input;
2209 ds_inf("context_handle_key. text_input(%p)",
2216 context_handle_modifiers(struct wl_listener *listener, void *data)
2218 struct tinyds_input_method_context *context;
2219 struct tinyds_text_input *text_input;
2221 context = wl_container_of(listener, context, im_context_modifiers);
2222 text_input = context->server->text_input;
2224 ds_inf("context_handle_modifiers. text_input(%p)",
2231 context_handle_language(struct wl_listener *listener, void *data)
2233 struct tinyds_input_method_context *context;
2234 struct tinyds_text_input *text_input;
2235 struct ds_tizen_input_method_context_event_language *event = data;
2237 context = wl_container_of(listener, context, im_context_language);
2238 text_input = context->server->text_input;
2240 ds_inf("context_handle_language. text_input(%p) serial(%u), language(%s)",
2241 text_input, event->serial, event->language);
2243 ds_tizen_text_input_send_language(text_input->input, event->serial, event->language);
2247 context_handle_text_direction(struct wl_listener *listener, void *data)
2249 struct tinyds_input_method_context *context;
2250 struct tinyds_text_input *text_input;
2251 struct ds_tizen_input_method_context_event_text_direction *event = data;
2253 context = wl_container_of(listener, context, im_context_text_direction);
2254 text_input = context->server->text_input;
2256 ds_inf("context_handle_text_direction. text_input(%p) serial(%u), direction(%u)",
2257 text_input, event->serial, event->direction);
2259 ds_tizen_text_input_send_text_direction(text_input->input, event->serial, event->direction);
2263 add_new_text_input(struct tinyds_server *server)
2265 struct tinyds_text_input *text_input;
2267 text_input = calloc(1, sizeof *text_input);
2271 text_input->text_input_mgr = ds_tizen_text_input_manager_create(server->display);
2272 if (!text_input->text_input_mgr) {
2274 ds_err("Could not create ds_tizen_text_input_manager");
2278 wl_list_init(&text_input->input_methods);
2280 text_input->mgr_destroy.notify = text_input_mgr_handle_destroy;
2281 ds_tizen_text_input_manager_add_destroy_listener(text_input->text_input_mgr,
2282 &text_input->mgr_destroy);
2284 text_input->new_text_input.notify = text_input_mgr_handle_new_text_input;
2285 ds_tizen_text_input_manager_add_new_text_input_listener(text_input->text_input_mgr,
2286 &text_input->new_text_input);
2288 text_input->server = server;
2289 server->text_input = text_input;
2291 ds_inf("Text_Input (%p) added", text_input);
2297 add_new_input_method(struct tinyds_server *server)
2299 struct tinyds_input_method *input_method;
2301 input_method = calloc(1, sizeof *input_method);
2305 input_method->input_method = ds_tizen_input_method_create(server->display);
2306 if (!input_method->input_method) {
2308 ds_err("Could not create ds_tizen_input_method");
2311 input_method->destroy.notify = input_method_handle_destroy;
2312 ds_tizen_input_method_add_destroy_listener(input_method->input_method,
2313 &input_method->destroy);
2315 input_method->input_method_mgr = ds_tizen_input_method_manager_create(server->display);
2316 if (!input_method->input_method_mgr) {
2318 ds_err("Could not create ds_tizen_input_method_manager");
2322 input_method->mgr_destroy.notify = input_method_mgr_handle_destroy;
2323 ds_tizen_input_method_manager_add_destroy_listener(input_method->input_method_mgr,
2324 &input_method->mgr_destroy);
2326 input_method->server = server;
2327 server->input_method = input_method;
2329 ds_inf("Input_Method (%p) added", input_method);
2335 add_new_input_method_context(struct tinyds_input_method *input_method,
2336 struct tinyds_text_input *text_input)
2338 struct tinyds_input_method_context *context;
2340 context = calloc(1, sizeof *context);
2341 if (context == NULL)
2343 ds_err("calloc is failed. tinyds_input_method_context");
2346 input_method->context = context;
2347 context->input_method = input_method;
2348 context->server = input_method->server;
2349 context->input = text_input;
2351 context->context = ds_tizen_input_method_create_context(input_method->input_method);
2352 if (context->context == NULL) {
2353 ds_err("ds_tizen_input_method_create_context() failed.");
2357 context->destroy.notify = context_handle_destroy;
2358 ds_tizen_input_method_context_add_destroy_listener(context->context,
2361 context->im_context_commit_string.notify = context_handle_commit_string;
2362 ds_tizen_input_method_context_add_commit_string_listener(context->context,
2363 &context->im_context_commit_string);
2365 context->im_context_preedit_string.notify = context_handle_preedit_string;
2366 ds_tizen_input_method_context_add_preedit_string_listener(context->context,
2367 &context->im_context_preedit_string);
2369 context->im_context_preedit_styling.notify = context_handle_preedit_styling;
2370 ds_tizen_input_method_context_add_preedit_styling_listener(context->context,
2371 &context->im_context_preedit_styling);
2373 context->im_context_preedit_cursor.notify = context_handle_preedit_cursor;
2374 ds_tizen_input_method_context_add_preedit_cursor_listener(context->context,
2375 &context->im_context_preedit_cursor);
2377 context->im_context_delete_surrounding_text.notify = context_handle_delete_surrounding_text;
2378 ds_tizen_input_method_context_add_delete_surrounding_text_listener(context->context,
2379 &context->im_context_delete_surrounding_text);
2381 context->im_context_cursor_position.notify = context_handle_cursor_position;
2382 ds_tizen_input_method_context_add_cursor_position_listener(context->context,
2383 &context->im_context_cursor_position);
2385 context->im_context_modifiers_map.notify = context_handle_modifiers_map;
2386 ds_tizen_input_method_context_add_modifiers_map_listener(context->context,
2387 &context->im_context_modifiers_map);
2389 context->im_context_keysym.notify = context_handle_keysym;
2390 ds_tizen_input_method_context_add_keysym_listener(context->context,
2391 &context->im_context_keysym);
2393 context->im_context_grab_keyboard.notify = context_handle_grab_keyboard;
2394 ds_tizen_input_method_context_add_grab_keyboard_listener(context->context,
2395 &context->im_context_grab_keyboard);
2397 context->im_context_key.notify = context_handle_key;
2398 ds_tizen_input_method_context_add_key_listener(context->context,
2399 &context->im_context_key);
2401 context->im_context_modifiers.notify = context_handle_modifiers;
2402 ds_tizen_input_method_context_add_modifiers_listener(context->context,
2403 &context->im_context_modifiers);
2405 context->im_context_language.notify = context_handle_language;
2406 ds_tizen_input_method_context_add_language_listener(context->context,
2407 &context->im_context_language);
2409 context->im_context_text_direction.notify = context_handle_text_direction;
2410 ds_tizen_input_method_context_add_text_direction_listener(context->context,
2411 &context->im_context_text_direction);