blob: 29c3c9861ecce94cf62cc688afa3339c04757b15 [file] [log] [blame]
Quentin Glidic248dd102016-08-12 10:41:34 +02001/*
2 * Copyright © 2016 Quentin "Sardem FF7" Glidic
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "config.h"
25
26#include <wayland-server.h>
27
28#include "compositor.h"
29#include "zalloc.h"
30
31#include "libweston-desktop.h"
32#include "internal.h"
33
34struct weston_desktop_client {
35 struct weston_desktop *desktop;
36 struct wl_client *client;
37 struct wl_resource *resource;
38 struct wl_list surface_list;
39 uint32_t ping_serial;
40 struct wl_event_source *ping_timer;
41 struct wl_signal destroy_signal;
42};
43
44void
45weston_desktop_client_add_destroy_listener(struct weston_desktop_client *client,
46 struct wl_listener *listener)
47{
48 wl_signal_add(&client->destroy_signal, listener);
49}
50
51static void
52weston_desktop_client_destroy(struct wl_resource *resource)
53{
54 struct weston_desktop_client *client =
55 wl_resource_get_user_data(resource);
56 struct wl_list *list = &client->surface_list;
57 struct wl_list *link, *tmp;
58
59 wl_signal_emit(&client->destroy_signal, client);
60
61 for (link = list->next, tmp = link->next;
62 link != list;
63 link = tmp, tmp = link->next) {
64 wl_list_remove(link);
65 wl_list_init(link);
66 }
67
68 if (client->ping_timer != NULL)
69 wl_event_source_remove(client->ping_timer);
70
71 free(client);
72}
73
74static int
75weston_desktop_client_ping_timeout(void *user_data)
76{
77 struct weston_desktop_client *client = user_data;
78
79 weston_desktop_api_ping_timeout(client->desktop, client);
80 return 1;
81}
82
83struct weston_desktop_client *
84weston_desktop_client_create(struct weston_desktop *desktop,
85 struct wl_client *wl_client,
86 wl_dispatcher_func_t dispatcher,
87 const struct wl_interface *interface,
88 const void *implementation, uint32_t version,
89 uint32_t id)
90{
91 struct weston_desktop_client *client;
92 struct wl_display *display;
93 struct wl_event_loop *loop;
94
95 client = zalloc(sizeof(struct weston_desktop_client));
96 if (client == NULL) {
97 if (wl_client != NULL)
98 wl_client_post_no_memory(wl_client);
99 return NULL;
100 }
101
102 client->desktop = desktop;
103 client->client = wl_client;
104
105 wl_list_init(&client->surface_list);
106 wl_signal_init(&client->destroy_signal);
107
108 if (wl_client == NULL)
109 return client;
110
111 client->resource = wl_resource_create(wl_client, interface, version, id);
112 if (client->resource == NULL) {
113 wl_client_post_no_memory(wl_client);
114 free(client);
115 return NULL;
116 }
117
118 if (dispatcher != NULL)
119 wl_resource_set_dispatcher(client->resource, dispatcher,
120 weston_desktop_client_destroy, client,
121 weston_desktop_client_destroy);
122 else
123 wl_resource_set_implementation(client->resource, implementation,
124 client,
125 weston_desktop_client_destroy);
126
127
128 display = wl_client_get_display(client->client);
129 loop = wl_display_get_event_loop(display);
130 client->ping_timer =
131 wl_event_loop_add_timer(loop,
132 weston_desktop_client_ping_timeout,
133 client);
134 if (client->ping_timer == NULL)
135 wl_client_post_no_memory(wl_client);
136
137 return client;
138}
139
140struct weston_desktop *
141weston_desktop_client_get_desktop(struct weston_desktop_client *client)
142{
143 return client->desktop;
144}
145
146struct wl_resource *
147weston_desktop_client_get_resource(struct weston_desktop_client *client)
148{
149 return client->resource;
150}
151
152struct wl_list *
153weston_desktop_client_get_surface_list(struct weston_desktop_client *client)
154{
155 return &client->surface_list;
156}
157
158WL_EXPORT struct wl_client *
159weston_desktop_client_get_client(struct weston_desktop_client *client)
160{
161 return client->client;
162}
163
164WL_EXPORT void
165weston_desktop_client_for_each_surface(struct weston_desktop_client *client,
166 void (*callback)(struct weston_desktop_surface *surface, void *user_data),
167 void *user_data)
168{
169 struct wl_list *list = &client->surface_list;
170 struct wl_list *link;
171
172 for (link = list->next; link != list; link = link->next)
173 callback(weston_desktop_surface_from_client_link(link),
174 user_data);
175}
176
177WL_EXPORT int
178weston_desktop_client_ping(struct weston_desktop_client *client)
179{
180 struct weston_desktop_surface *surface =
181 weston_desktop_surface_from_client_link(client->surface_list.next);
182 const struct weston_desktop_surface_implementation *implementation =
183 weston_desktop_surface_get_implementation(surface);
184 void *implementation_data =
185 weston_desktop_surface_get_implementation_data(surface);
186
187 if (implementation->ping == NULL)
188 return -1;
189
190 if (client->ping_serial != 0)
191 return 1;
192
193 client->ping_serial =
194 wl_display_next_serial(wl_client_get_display(client->client));
195 wl_event_source_timer_update(client->ping_timer, 10000);
196
197 implementation->ping(surface, client->ping_serial, implementation_data);
198
199 return 0;
200}
201
202void
203weston_desktop_client_pong(struct weston_desktop_client *client, uint32_t serial)
204{
205 if (client->ping_serial != serial)
206 return;
207
208 weston_desktop_api_pong(client->desktop, client);
209
210 wl_event_source_timer_update(client->ping_timer, 0);
211 client->ping_serial = 0;
212}