6 #include "libds/xdg_shell.h"
10 #define XDG_WM_BASE_VERSION 2
11 #define XDG_SHELL_PING_TIMEOUT 10000
13 static void xdg_shell_handle_display_destroy(struct wl_listener *listener,
15 static void xdg_shell_bind(struct wl_client *wl_client, void *data,
16 uint32_t verison, uint32_t id);
18 WL_EXPORT struct ds_xdg_shell *
19 ds_xdg_shell_create(struct wl_display *display)
21 struct ds_xdg_shell *shell;
23 shell = calloc(1, sizeof *shell);
28 shell->ping_timeout = XDG_SHELL_PING_TIMEOUT;
30 wl_list_init(&shell->clients);
32 shell->global = wl_global_create(display, &xdg_wm_base_interface,
33 XDG_WM_BASE_VERSION, shell, xdg_shell_bind);
39 wl_signal_init(&shell->events.destroy);
40 wl_signal_init(&shell->events.new_surface);
42 shell->display_destroy.notify = xdg_shell_handle_display_destroy;
43 wl_display_add_destroy_listener(display, &shell->display_destroy);
45 ds_inf("Global created: xdg_wm_base shell(%p)", shell);
51 ds_xdg_shell_add_destroy_listener(struct ds_xdg_shell *shell,
52 struct wl_listener *listener)
54 wl_signal_add(&shell->events.destroy, listener);
58 ds_xdg_shell_add_new_surface_listener(struct ds_xdg_shell *shell,
59 struct wl_listener *listener)
61 wl_signal_add(&shell->events.new_surface, listener);
65 xdg_shell_handle_display_destroy(struct wl_listener *listener, void *data)
67 struct ds_xdg_shell *shell;
69 shell = wl_container_of(listener, shell, display_destroy);
71 ds_inf("Global destroy: xdg_wm_base shell(%p)", shell);
73 wl_signal_emit(&shell->events.destroy, shell);
74 wl_list_remove(&shell->display_destroy.link);
75 wl_global_destroy(shell->global);
80 xdg_shell_handle_destroy(struct wl_client *wl_client,
81 struct wl_resource *resource)
83 struct ds_xdg_client *client;
85 client = wl_resource_get_user_data(resource);
87 if (!wl_list_empty(&client->surfaces)) {
88 wl_resource_post_error(client->resource,
89 XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
90 "xdg_wm_base was destroyed before children");
94 wl_resource_destroy(resource);
98 xdg_shell_handle_create_positioner(struct wl_client *wl_client,
99 struct wl_resource *resource, uint32_t id)
105 xdg_shell_handle_get_xdg_surface(struct wl_client *wl_client,
106 struct wl_resource *resource, uint32_t id,
107 struct wl_resource *surface_resource)
109 struct ds_xdg_client *client;
110 struct ds_surface *surface;
112 client = wl_resource_get_user_data(resource);
113 surface = ds_surface_from_resource(surface_resource);
114 create_xdg_surface(client, surface, id);
118 xdg_shell_handle_pong(struct wl_client *wl_client,
119 struct wl_resource *resource, uint32_t serial)
121 struct ds_xdg_client *client;
123 client = wl_resource_get_user_data(resource);
124 if (client->ping_serial != serial)
127 wl_event_source_timer_update(client->ping_timer, 0);
128 client->ping_serial = 0;
131 static const struct xdg_wm_base_interface xdg_shell_impl =
133 .destroy = xdg_shell_handle_destroy,
134 .create_positioner = xdg_shell_handle_create_positioner,
135 .get_xdg_surface = xdg_shell_handle_get_xdg_surface,
136 .pong = xdg_shell_handle_pong,
140 xdg_client_handle_resource_destroy(struct wl_resource *resource)
142 struct ds_xdg_client *client;
143 struct ds_xdg_surface *surface, *tmp;
145 client = wl_resource_get_user_data(resource);
147 wl_list_for_each_safe(surface, tmp, &client->surfaces, link)
148 destroy_xdg_surface(surface);
150 if (client->ping_timer != NULL)
151 wl_event_source_remove(client->ping_timer);
153 wl_list_remove(&client->link);
158 xdg_client_handle_ping_timeout(void *user_data)
160 struct ds_xdg_client *client = user_data;
161 struct ds_xdg_surface *surface;
163 wl_list_for_each(surface, &client->surfaces, link)
164 wl_signal_emit(&surface->events.ping_timeout, surface);
166 client->ping_serial = 0;
172 xdg_client_init_ping_timer(struct ds_xdg_client *client)
174 struct wl_display *display;
175 struct wl_event_loop *loop;
177 display = wl_client_get_display(client->wl_client);
178 loop = wl_display_get_event_loop(display);
179 client->ping_timer = wl_event_loop_add_timer(loop,
180 xdg_client_handle_ping_timeout, client);
181 if (client->ping_timer == NULL)
182 wl_client_post_no_memory(client->wl_client);
186 xdg_shell_bind(struct wl_client *wl_client, void *data, uint32_t version,
189 struct ds_xdg_shell *shell = data;
190 struct ds_xdg_client *client;
192 client = calloc(1, sizeof *client);
193 if (client == NULL) {
194 wl_client_post_no_memory(wl_client);
198 client->wl_client = wl_client;
199 client->shell = shell;
201 wl_list_init(&client->surfaces);
204 wl_resource_create(wl_client, &xdg_wm_base_interface, version, id);
205 if (client->resource == NULL) {
207 wl_client_post_no_memory(wl_client);
211 wl_resource_set_implementation(client->resource, &xdg_shell_impl, client,
212 xdg_client_handle_resource_destroy);
214 wl_list_insert(&shell->clients, &client->link);
216 xdg_client_init_ping_timer(client);