1*84e872a0SLloyd Pique /*
2*84e872a0SLloyd Pique * Copyright © 2008 Kristian Høgsberg
3*84e872a0SLloyd Pique *
4*84e872a0SLloyd Pique * Permission is hereby granted, free of charge, to any person obtaining
5*84e872a0SLloyd Pique * a copy of this software and associated documentation files (the
6*84e872a0SLloyd Pique * "Software"), to deal in the Software without restriction, including
7*84e872a0SLloyd Pique * without limitation the rights to use, copy, modify, merge, publish,
8*84e872a0SLloyd Pique * distribute, sublicense, and/or sell copies of the Software, and to
9*84e872a0SLloyd Pique * permit persons to whom the Software is furnished to do so, subject to
10*84e872a0SLloyd Pique * the following conditions:
11*84e872a0SLloyd Pique *
12*84e872a0SLloyd Pique * The above copyright notice and this permission notice (including the
13*84e872a0SLloyd Pique * next paragraph) shall be included in all copies or substantial
14*84e872a0SLloyd Pique * portions of the Software.
15*84e872a0SLloyd Pique *
16*84e872a0SLloyd Pique * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*84e872a0SLloyd Pique * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*84e872a0SLloyd Pique * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*84e872a0SLloyd Pique * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20*84e872a0SLloyd Pique * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21*84e872a0SLloyd Pique * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22*84e872a0SLloyd Pique * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*84e872a0SLloyd Pique * SOFTWARE.
24*84e872a0SLloyd Pique */
25*84e872a0SLloyd Pique
26*84e872a0SLloyd Pique #define _GNU_SOURCE
27*84e872a0SLloyd Pique
28*84e872a0SLloyd Pique #include <stdbool.h>
29*84e872a0SLloyd Pique #include <stdlib.h>
30*84e872a0SLloyd Pique #include <stdint.h>
31*84e872a0SLloyd Pique #include <stddef.h>
32*84e872a0SLloyd Pique #include <stdio.h>
33*84e872a0SLloyd Pique #include <stdarg.h>
34*84e872a0SLloyd Pique #include <errno.h>
35*84e872a0SLloyd Pique #include <string.h>
36*84e872a0SLloyd Pique #include <unistd.h>
37*84e872a0SLloyd Pique #include <sys/socket.h>
38*84e872a0SLloyd Pique #include <sys/un.h>
39*84e872a0SLloyd Pique #include <dlfcn.h>
40*84e872a0SLloyd Pique #include <assert.h>
41*84e872a0SLloyd Pique #include <sys/time.h>
42*84e872a0SLloyd Pique #include <fcntl.h>
43*84e872a0SLloyd Pique #include <sys/eventfd.h>
44*84e872a0SLloyd Pique #include <sys/file.h>
45*84e872a0SLloyd Pique #include <sys/stat.h>
46*84e872a0SLloyd Pique
47*84e872a0SLloyd Pique #include "wayland-util.h"
48*84e872a0SLloyd Pique #include "wayland-private.h"
49*84e872a0SLloyd Pique #include "wayland-server-private.h"
50*84e872a0SLloyd Pique #include "wayland-server.h"
51*84e872a0SLloyd Pique #include "wayland-os.h"
52*84e872a0SLloyd Pique
53*84e872a0SLloyd Pique /* This is the size of the char array in struct sock_addr_un.
54*84e872a0SLloyd Pique * No Wayland socket can be created with a path longer than this,
55*84e872a0SLloyd Pique * including the null terminator.
56*84e872a0SLloyd Pique */
57*84e872a0SLloyd Pique #ifndef UNIX_PATH_MAX
58*84e872a0SLloyd Pique #define UNIX_PATH_MAX 108
59*84e872a0SLloyd Pique #endif
60*84e872a0SLloyd Pique
61*84e872a0SLloyd Pique #define LOCK_SUFFIX ".lock"
62*84e872a0SLloyd Pique #define LOCK_SUFFIXLEN 5
63*84e872a0SLloyd Pique
64*84e872a0SLloyd Pique struct wl_socket {
65*84e872a0SLloyd Pique int fd;
66*84e872a0SLloyd Pique int fd_lock;
67*84e872a0SLloyd Pique struct sockaddr_un addr;
68*84e872a0SLloyd Pique char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
69*84e872a0SLloyd Pique struct wl_list link;
70*84e872a0SLloyd Pique struct wl_event_source *source;
71*84e872a0SLloyd Pique char *display_name;
72*84e872a0SLloyd Pique };
73*84e872a0SLloyd Pique
74*84e872a0SLloyd Pique struct wl_client {
75*84e872a0SLloyd Pique struct wl_connection *connection;
76*84e872a0SLloyd Pique struct wl_event_source *source;
77*84e872a0SLloyd Pique struct wl_display *display;
78*84e872a0SLloyd Pique struct wl_resource *display_resource;
79*84e872a0SLloyd Pique struct wl_list link;
80*84e872a0SLloyd Pique struct wl_map objects;
81*84e872a0SLloyd Pique struct wl_priv_signal destroy_signal;
82*84e872a0SLloyd Pique struct wl_priv_signal destroy_late_signal;
83*84e872a0SLloyd Pique pid_t pid;
84*84e872a0SLloyd Pique uid_t uid;
85*84e872a0SLloyd Pique gid_t gid;
86*84e872a0SLloyd Pique int error;
87*84e872a0SLloyd Pique struct wl_priv_signal resource_created_signal;
88*84e872a0SLloyd Pique };
89*84e872a0SLloyd Pique
90*84e872a0SLloyd Pique struct wl_display {
91*84e872a0SLloyd Pique struct wl_event_loop *loop;
92*84e872a0SLloyd Pique int run;
93*84e872a0SLloyd Pique
94*84e872a0SLloyd Pique uint32_t next_global_name;
95*84e872a0SLloyd Pique uint32_t serial;
96*84e872a0SLloyd Pique
97*84e872a0SLloyd Pique struct wl_list registry_resource_list;
98*84e872a0SLloyd Pique struct wl_list global_list;
99*84e872a0SLloyd Pique struct wl_list socket_list;
100*84e872a0SLloyd Pique struct wl_list client_list;
101*84e872a0SLloyd Pique struct wl_list protocol_loggers;
102*84e872a0SLloyd Pique
103*84e872a0SLloyd Pique struct wl_priv_signal destroy_signal;
104*84e872a0SLloyd Pique struct wl_priv_signal create_client_signal;
105*84e872a0SLloyd Pique
106*84e872a0SLloyd Pique struct wl_array additional_shm_formats;
107*84e872a0SLloyd Pique
108*84e872a0SLloyd Pique wl_display_global_filter_func_t global_filter;
109*84e872a0SLloyd Pique void *global_filter_data;
110*84e872a0SLloyd Pique
111*84e872a0SLloyd Pique int terminate_efd;
112*84e872a0SLloyd Pique struct wl_event_source *term_source;
113*84e872a0SLloyd Pique };
114*84e872a0SLloyd Pique
115*84e872a0SLloyd Pique struct wl_global {
116*84e872a0SLloyd Pique struct wl_display *display;
117*84e872a0SLloyd Pique const struct wl_interface *interface;
118*84e872a0SLloyd Pique uint32_t name;
119*84e872a0SLloyd Pique uint32_t version;
120*84e872a0SLloyd Pique void *data;
121*84e872a0SLloyd Pique wl_global_bind_func_t bind;
122*84e872a0SLloyd Pique struct wl_list link;
123*84e872a0SLloyd Pique bool removed;
124*84e872a0SLloyd Pique };
125*84e872a0SLloyd Pique
126*84e872a0SLloyd Pique struct wl_resource {
127*84e872a0SLloyd Pique struct wl_object object;
128*84e872a0SLloyd Pique wl_resource_destroy_func_t destroy;
129*84e872a0SLloyd Pique struct wl_list link;
130*84e872a0SLloyd Pique /* Unfortunately some users of libwayland (e.g. mesa) still use the
131*84e872a0SLloyd Pique * deprecated wl_resource struct, even if creating it with the new
132*84e872a0SLloyd Pique * wl_resource_create(). So we cannot change the layout of the struct
133*84e872a0SLloyd Pique * unless after the data field. */
134*84e872a0SLloyd Pique struct wl_signal deprecated_destroy_signal;
135*84e872a0SLloyd Pique struct wl_client *client;
136*84e872a0SLloyd Pique void *data;
137*84e872a0SLloyd Pique int version;
138*84e872a0SLloyd Pique wl_dispatcher_func_t dispatcher;
139*84e872a0SLloyd Pique struct wl_priv_signal destroy_signal;
140*84e872a0SLloyd Pique };
141*84e872a0SLloyd Pique
142*84e872a0SLloyd Pique struct wl_protocol_logger {
143*84e872a0SLloyd Pique struct wl_list link;
144*84e872a0SLloyd Pique wl_protocol_logger_func_t func;
145*84e872a0SLloyd Pique void *user_data;
146*84e872a0SLloyd Pique };
147*84e872a0SLloyd Pique
148*84e872a0SLloyd Pique static int debug_server = 0;
149*84e872a0SLloyd Pique
150*84e872a0SLloyd Pique static void
log_closure(struct wl_resource * resource,struct wl_closure * closure,int send)151*84e872a0SLloyd Pique log_closure(struct wl_resource *resource,
152*84e872a0SLloyd Pique struct wl_closure *closure, int send)
153*84e872a0SLloyd Pique {
154*84e872a0SLloyd Pique struct wl_object *object = &resource->object;
155*84e872a0SLloyd Pique struct wl_display *display = resource->client->display;
156*84e872a0SLloyd Pique struct wl_protocol_logger *protocol_logger;
157*84e872a0SLloyd Pique struct wl_protocol_logger_message message;
158*84e872a0SLloyd Pique
159*84e872a0SLloyd Pique if (debug_server)
160*84e872a0SLloyd Pique wl_closure_print(closure, object, send, NULL);
161*84e872a0SLloyd Pique
162*84e872a0SLloyd Pique if (!wl_list_empty(&display->protocol_loggers)) {
163*84e872a0SLloyd Pique message.resource = resource;
164*84e872a0SLloyd Pique message.message_opcode = closure->opcode;
165*84e872a0SLloyd Pique message.message = closure->message;
166*84e872a0SLloyd Pique message.arguments_count = closure->count;
167*84e872a0SLloyd Pique message.arguments = closure->args;
168*84e872a0SLloyd Pique wl_list_for_each(protocol_logger,
169*84e872a0SLloyd Pique &display->protocol_loggers, link) {
170*84e872a0SLloyd Pique protocol_logger->func(protocol_logger->user_data,
171*84e872a0SLloyd Pique send ? WL_PROTOCOL_LOGGER_EVENT :
172*84e872a0SLloyd Pique WL_PROTOCOL_LOGGER_REQUEST,
173*84e872a0SLloyd Pique &message);
174*84e872a0SLloyd Pique }
175*84e872a0SLloyd Pique }
176*84e872a0SLloyd Pique }
177*84e872a0SLloyd Pique
178*84e872a0SLloyd Pique static bool
verify_objects(struct wl_resource * resource,uint32_t opcode,union wl_argument * args)179*84e872a0SLloyd Pique verify_objects(struct wl_resource *resource, uint32_t opcode,
180*84e872a0SLloyd Pique union wl_argument *args)
181*84e872a0SLloyd Pique {
182*84e872a0SLloyd Pique struct wl_object *object = &resource->object;
183*84e872a0SLloyd Pique const char *signature = object->interface->events[opcode].signature;
184*84e872a0SLloyd Pique struct argument_details arg;
185*84e872a0SLloyd Pique struct wl_resource *res;
186*84e872a0SLloyd Pique int count, i;
187*84e872a0SLloyd Pique
188*84e872a0SLloyd Pique count = arg_count_for_signature(signature);
189*84e872a0SLloyd Pique for (i = 0; i < count; i++) {
190*84e872a0SLloyd Pique signature = get_next_argument(signature, &arg);
191*84e872a0SLloyd Pique switch (arg.type) {
192*84e872a0SLloyd Pique case 'n':
193*84e872a0SLloyd Pique case 'o':
194*84e872a0SLloyd Pique res = (struct wl_resource *) (args[i].o);
195*84e872a0SLloyd Pique if (res && res->client != resource->client) {
196*84e872a0SLloyd Pique wl_log("compositor bug: The compositor "
197*84e872a0SLloyd Pique "tried to use an object from one "
198*84e872a0SLloyd Pique "client in a '%s.%s' for a different "
199*84e872a0SLloyd Pique "client.\n", object->interface->name,
200*84e872a0SLloyd Pique object->interface->events[opcode].name);
201*84e872a0SLloyd Pique return false;
202*84e872a0SLloyd Pique }
203*84e872a0SLloyd Pique }
204*84e872a0SLloyd Pique }
205*84e872a0SLloyd Pique return true;
206*84e872a0SLloyd Pique }
207*84e872a0SLloyd Pique
208*84e872a0SLloyd Pique static void
handle_array(struct wl_resource * resource,uint32_t opcode,union wl_argument * args,int (* send_func)(struct wl_closure *,struct wl_connection *))209*84e872a0SLloyd Pique handle_array(struct wl_resource *resource, uint32_t opcode,
210*84e872a0SLloyd Pique union wl_argument *args,
211*84e872a0SLloyd Pique int (*send_func)(struct wl_closure *, struct wl_connection *))
212*84e872a0SLloyd Pique {
213*84e872a0SLloyd Pique struct wl_closure *closure;
214*84e872a0SLloyd Pique struct wl_object *object = &resource->object;
215*84e872a0SLloyd Pique
216*84e872a0SLloyd Pique if (resource->client->error)
217*84e872a0SLloyd Pique return;
218*84e872a0SLloyd Pique
219*84e872a0SLloyd Pique if (!verify_objects(resource, opcode, args)) {
220*84e872a0SLloyd Pique resource->client->error = 1;
221*84e872a0SLloyd Pique return;
222*84e872a0SLloyd Pique }
223*84e872a0SLloyd Pique
224*84e872a0SLloyd Pique closure = wl_closure_marshal(object, opcode, args,
225*84e872a0SLloyd Pique &object->interface->events[opcode]);
226*84e872a0SLloyd Pique
227*84e872a0SLloyd Pique if (closure == NULL) {
228*84e872a0SLloyd Pique resource->client->error = 1;
229*84e872a0SLloyd Pique return;
230*84e872a0SLloyd Pique }
231*84e872a0SLloyd Pique
232*84e872a0SLloyd Pique log_closure(resource, closure, true);
233*84e872a0SLloyd Pique
234*84e872a0SLloyd Pique if (send_func(closure, resource->client->connection))
235*84e872a0SLloyd Pique resource->client->error = 1;
236*84e872a0SLloyd Pique
237*84e872a0SLloyd Pique wl_closure_destroy(closure);
238*84e872a0SLloyd Pique }
239*84e872a0SLloyd Pique
240*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_post_event_array(struct wl_resource * resource,uint32_t opcode,union wl_argument * args)241*84e872a0SLloyd Pique wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
242*84e872a0SLloyd Pique union wl_argument *args)
243*84e872a0SLloyd Pique {
244*84e872a0SLloyd Pique handle_array(resource, opcode, args, wl_closure_send);
245*84e872a0SLloyd Pique }
246*84e872a0SLloyd Pique
247*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_post_event(struct wl_resource * resource,uint32_t opcode,...)248*84e872a0SLloyd Pique wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
249*84e872a0SLloyd Pique {
250*84e872a0SLloyd Pique union wl_argument args[WL_CLOSURE_MAX_ARGS];
251*84e872a0SLloyd Pique struct wl_object *object = &resource->object;
252*84e872a0SLloyd Pique va_list ap;
253*84e872a0SLloyd Pique
254*84e872a0SLloyd Pique va_start(ap, opcode);
255*84e872a0SLloyd Pique wl_argument_from_va_list(object->interface->events[opcode].signature,
256*84e872a0SLloyd Pique args, WL_CLOSURE_MAX_ARGS, ap);
257*84e872a0SLloyd Pique va_end(ap);
258*84e872a0SLloyd Pique
259*84e872a0SLloyd Pique wl_resource_post_event_array(resource, opcode, args);
260*84e872a0SLloyd Pique }
261*84e872a0SLloyd Pique
262*84e872a0SLloyd Pique
263*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_queue_event_array(struct wl_resource * resource,uint32_t opcode,union wl_argument * args)264*84e872a0SLloyd Pique wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode,
265*84e872a0SLloyd Pique union wl_argument *args)
266*84e872a0SLloyd Pique {
267*84e872a0SLloyd Pique handle_array(resource, opcode, args, wl_closure_queue);
268*84e872a0SLloyd Pique }
269*84e872a0SLloyd Pique
270*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_queue_event(struct wl_resource * resource,uint32_t opcode,...)271*84e872a0SLloyd Pique wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
272*84e872a0SLloyd Pique {
273*84e872a0SLloyd Pique union wl_argument args[WL_CLOSURE_MAX_ARGS];
274*84e872a0SLloyd Pique struct wl_object *object = &resource->object;
275*84e872a0SLloyd Pique va_list ap;
276*84e872a0SLloyd Pique
277*84e872a0SLloyd Pique va_start(ap, opcode);
278*84e872a0SLloyd Pique wl_argument_from_va_list(object->interface->events[opcode].signature,
279*84e872a0SLloyd Pique args, WL_CLOSURE_MAX_ARGS, ap);
280*84e872a0SLloyd Pique va_end(ap);
281*84e872a0SLloyd Pique
282*84e872a0SLloyd Pique wl_resource_queue_event_array(resource, opcode, args);
283*84e872a0SLloyd Pique }
284*84e872a0SLloyd Pique
285*84e872a0SLloyd Pique static void
wl_resource_post_error_vargs(struct wl_resource * resource,uint32_t code,const char * msg,va_list argp)286*84e872a0SLloyd Pique wl_resource_post_error_vargs(struct wl_resource *resource,
287*84e872a0SLloyd Pique uint32_t code, const char *msg, va_list argp)
288*84e872a0SLloyd Pique {
289*84e872a0SLloyd Pique struct wl_client *client = resource->client;
290*84e872a0SLloyd Pique char buffer[128];
291*84e872a0SLloyd Pique
292*84e872a0SLloyd Pique vsnprintf(buffer, sizeof buffer, msg, argp);
293*84e872a0SLloyd Pique
294*84e872a0SLloyd Pique /*
295*84e872a0SLloyd Pique * When a client aborts, its resources are destroyed in id order,
296*84e872a0SLloyd Pique * which means the display resource is destroyed first. If destruction
297*84e872a0SLloyd Pique * of any later resources results in a protocol error, we end up here
298*84e872a0SLloyd Pique * with a NULL display_resource. Do not try to send errors to an
299*84e872a0SLloyd Pique * already dead client.
300*84e872a0SLloyd Pique */
301*84e872a0SLloyd Pique if (client->error || !client->display_resource)
302*84e872a0SLloyd Pique return;
303*84e872a0SLloyd Pique
304*84e872a0SLloyd Pique wl_resource_post_event(client->display_resource,
305*84e872a0SLloyd Pique WL_DISPLAY_ERROR, resource, code, buffer);
306*84e872a0SLloyd Pique client->error = 1;
307*84e872a0SLloyd Pique
308*84e872a0SLloyd Pique }
309*84e872a0SLloyd Pique
310*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_post_error(struct wl_resource * resource,uint32_t code,const char * msg,...)311*84e872a0SLloyd Pique wl_resource_post_error(struct wl_resource *resource,
312*84e872a0SLloyd Pique uint32_t code, const char *msg, ...)
313*84e872a0SLloyd Pique {
314*84e872a0SLloyd Pique va_list ap;
315*84e872a0SLloyd Pique
316*84e872a0SLloyd Pique va_start(ap, msg);
317*84e872a0SLloyd Pique wl_resource_post_error_vargs(resource, code, msg, ap);
318*84e872a0SLloyd Pique va_end(ap);
319*84e872a0SLloyd Pique }
320*84e872a0SLloyd Pique
321*84e872a0SLloyd Pique static void
destroy_client_with_error(struct wl_client * client,const char * reason)322*84e872a0SLloyd Pique destroy_client_with_error(struct wl_client *client, const char *reason)
323*84e872a0SLloyd Pique {
324*84e872a0SLloyd Pique wl_log("%s (pid %u)\n", reason, client->pid);
325*84e872a0SLloyd Pique wl_client_destroy(client);
326*84e872a0SLloyd Pique }
327*84e872a0SLloyd Pique
328*84e872a0SLloyd Pique static int
wl_client_connection_data(int fd,uint32_t mask,void * data)329*84e872a0SLloyd Pique wl_client_connection_data(int fd, uint32_t mask, void *data)
330*84e872a0SLloyd Pique {
331*84e872a0SLloyd Pique struct wl_client *client = data;
332*84e872a0SLloyd Pique struct wl_connection *connection = client->connection;
333*84e872a0SLloyd Pique struct wl_resource *resource;
334*84e872a0SLloyd Pique struct wl_object *object;
335*84e872a0SLloyd Pique struct wl_closure *closure;
336*84e872a0SLloyd Pique const struct wl_message *message;
337*84e872a0SLloyd Pique uint32_t p[2];
338*84e872a0SLloyd Pique uint32_t resource_flags;
339*84e872a0SLloyd Pique int opcode, size, since;
340*84e872a0SLloyd Pique int len;
341*84e872a0SLloyd Pique
342*84e872a0SLloyd Pique if (mask & WL_EVENT_HANGUP) {
343*84e872a0SLloyd Pique wl_client_destroy(client);
344*84e872a0SLloyd Pique return 1;
345*84e872a0SLloyd Pique }
346*84e872a0SLloyd Pique
347*84e872a0SLloyd Pique if (mask & WL_EVENT_ERROR) {
348*84e872a0SLloyd Pique destroy_client_with_error(client, "socket error");
349*84e872a0SLloyd Pique return 1;
350*84e872a0SLloyd Pique }
351*84e872a0SLloyd Pique
352*84e872a0SLloyd Pique if (mask & WL_EVENT_WRITABLE) {
353*84e872a0SLloyd Pique len = wl_connection_flush(connection);
354*84e872a0SLloyd Pique if (len < 0 && errno != EAGAIN) {
355*84e872a0SLloyd Pique destroy_client_with_error(
356*84e872a0SLloyd Pique client, "failed to flush client connection");
357*84e872a0SLloyd Pique return 1;
358*84e872a0SLloyd Pique } else if (len >= 0) {
359*84e872a0SLloyd Pique wl_event_source_fd_update(client->source,
360*84e872a0SLloyd Pique WL_EVENT_READABLE);
361*84e872a0SLloyd Pique }
362*84e872a0SLloyd Pique }
363*84e872a0SLloyd Pique
364*84e872a0SLloyd Pique len = 0;
365*84e872a0SLloyd Pique if (mask & WL_EVENT_READABLE) {
366*84e872a0SLloyd Pique len = wl_connection_read(connection);
367*84e872a0SLloyd Pique if (len == 0 || (len < 0 && errno != EAGAIN)) {
368*84e872a0SLloyd Pique destroy_client_with_error(
369*84e872a0SLloyd Pique client, "failed to read client connection");
370*84e872a0SLloyd Pique return 1;
371*84e872a0SLloyd Pique }
372*84e872a0SLloyd Pique }
373*84e872a0SLloyd Pique
374*84e872a0SLloyd Pique while (len >= 0 && (size_t) len >= sizeof p) {
375*84e872a0SLloyd Pique wl_connection_copy(connection, p, sizeof p);
376*84e872a0SLloyd Pique opcode = p[1] & 0xffff;
377*84e872a0SLloyd Pique size = p[1] >> 16;
378*84e872a0SLloyd Pique if (len < size)
379*84e872a0SLloyd Pique break;
380*84e872a0SLloyd Pique
381*84e872a0SLloyd Pique resource = wl_map_lookup(&client->objects, p[0]);
382*84e872a0SLloyd Pique resource_flags = wl_map_lookup_flags(&client->objects, p[0]);
383*84e872a0SLloyd Pique if (resource == NULL) {
384*84e872a0SLloyd Pique wl_resource_post_error(client->display_resource,
385*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
386*84e872a0SLloyd Pique "invalid object %u", p[0]);
387*84e872a0SLloyd Pique break;
388*84e872a0SLloyd Pique }
389*84e872a0SLloyd Pique
390*84e872a0SLloyd Pique object = &resource->object;
391*84e872a0SLloyd Pique if (opcode >= object->interface->method_count) {
392*84e872a0SLloyd Pique wl_resource_post_error(client->display_resource,
393*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_METHOD,
394*84e872a0SLloyd Pique "invalid method %d, object %s@%u",
395*84e872a0SLloyd Pique opcode,
396*84e872a0SLloyd Pique object->interface->name,
397*84e872a0SLloyd Pique object->id);
398*84e872a0SLloyd Pique break;
399*84e872a0SLloyd Pique }
400*84e872a0SLloyd Pique
401*84e872a0SLloyd Pique message = &object->interface->methods[opcode];
402*84e872a0SLloyd Pique since = wl_message_get_since(message);
403*84e872a0SLloyd Pique if (!(resource_flags & WL_MAP_ENTRY_LEGACY) &&
404*84e872a0SLloyd Pique resource->version > 0 && resource->version < since) {
405*84e872a0SLloyd Pique wl_resource_post_error(client->display_resource,
406*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_METHOD,
407*84e872a0SLloyd Pique "invalid method %d (since %d < %d)"
408*84e872a0SLloyd Pique ", object %s@%u",
409*84e872a0SLloyd Pique opcode, resource->version, since,
410*84e872a0SLloyd Pique object->interface->name,
411*84e872a0SLloyd Pique object->id);
412*84e872a0SLloyd Pique break;
413*84e872a0SLloyd Pique }
414*84e872a0SLloyd Pique
415*84e872a0SLloyd Pique
416*84e872a0SLloyd Pique closure = wl_connection_demarshal(client->connection, size,
417*84e872a0SLloyd Pique &client->objects, message);
418*84e872a0SLloyd Pique
419*84e872a0SLloyd Pique if (closure == NULL && errno == ENOMEM) {
420*84e872a0SLloyd Pique wl_resource_post_no_memory(resource);
421*84e872a0SLloyd Pique break;
422*84e872a0SLloyd Pique } else if (closure == NULL ||
423*84e872a0SLloyd Pique wl_closure_lookup_objects(closure, &client->objects) < 0) {
424*84e872a0SLloyd Pique wl_resource_post_error(client->display_resource,
425*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_METHOD,
426*84e872a0SLloyd Pique "invalid arguments for %s@%u.%s",
427*84e872a0SLloyd Pique object->interface->name,
428*84e872a0SLloyd Pique object->id,
429*84e872a0SLloyd Pique message->name);
430*84e872a0SLloyd Pique wl_closure_destroy(closure);
431*84e872a0SLloyd Pique break;
432*84e872a0SLloyd Pique }
433*84e872a0SLloyd Pique
434*84e872a0SLloyd Pique log_closure(resource, closure, false);
435*84e872a0SLloyd Pique
436*84e872a0SLloyd Pique if ((resource_flags & WL_MAP_ENTRY_LEGACY) ||
437*84e872a0SLloyd Pique resource->dispatcher == NULL) {
438*84e872a0SLloyd Pique wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER,
439*84e872a0SLloyd Pique object, opcode, client);
440*84e872a0SLloyd Pique } else {
441*84e872a0SLloyd Pique wl_closure_dispatch(closure, resource->dispatcher,
442*84e872a0SLloyd Pique object, opcode);
443*84e872a0SLloyd Pique }
444*84e872a0SLloyd Pique
445*84e872a0SLloyd Pique wl_closure_destroy(closure);
446*84e872a0SLloyd Pique
447*84e872a0SLloyd Pique if (client->error)
448*84e872a0SLloyd Pique break;
449*84e872a0SLloyd Pique
450*84e872a0SLloyd Pique len = wl_connection_pending_input(connection);
451*84e872a0SLloyd Pique }
452*84e872a0SLloyd Pique
453*84e872a0SLloyd Pique if (client->error) {
454*84e872a0SLloyd Pique destroy_client_with_error(client,
455*84e872a0SLloyd Pique "error in client communication");
456*84e872a0SLloyd Pique }
457*84e872a0SLloyd Pique
458*84e872a0SLloyd Pique return 1;
459*84e872a0SLloyd Pique }
460*84e872a0SLloyd Pique
461*84e872a0SLloyd Pique /** Flush pending events to the client
462*84e872a0SLloyd Pique *
463*84e872a0SLloyd Pique * \param client The client object
464*84e872a0SLloyd Pique *
465*84e872a0SLloyd Pique * Events sent to clients are queued in a buffer and written to the
466*84e872a0SLloyd Pique * socket later - typically when the compositor has handled all
467*84e872a0SLloyd Pique * requests and goes back to block in the event loop. This function
468*84e872a0SLloyd Pique * flushes all queued up events for a client immediately.
469*84e872a0SLloyd Pique *
470*84e872a0SLloyd Pique * \memberof wl_client
471*84e872a0SLloyd Pique */
472*84e872a0SLloyd Pique WL_EXPORT void
wl_client_flush(struct wl_client * client)473*84e872a0SLloyd Pique wl_client_flush(struct wl_client *client)
474*84e872a0SLloyd Pique {
475*84e872a0SLloyd Pique wl_connection_flush(client->connection);
476*84e872a0SLloyd Pique }
477*84e872a0SLloyd Pique
478*84e872a0SLloyd Pique /** Get the display object for the given client
479*84e872a0SLloyd Pique *
480*84e872a0SLloyd Pique * \param client The client object
481*84e872a0SLloyd Pique * \return The display object the client is associated with.
482*84e872a0SLloyd Pique *
483*84e872a0SLloyd Pique * \memberof wl_client
484*84e872a0SLloyd Pique */
485*84e872a0SLloyd Pique WL_EXPORT struct wl_display *
wl_client_get_display(struct wl_client * client)486*84e872a0SLloyd Pique wl_client_get_display(struct wl_client *client)
487*84e872a0SLloyd Pique {
488*84e872a0SLloyd Pique return client->display;
489*84e872a0SLloyd Pique }
490*84e872a0SLloyd Pique
491*84e872a0SLloyd Pique static int
492*84e872a0SLloyd Pique bind_display(struct wl_client *client, struct wl_display *display);
493*84e872a0SLloyd Pique
494*84e872a0SLloyd Pique /** Create a client for the given file descriptor
495*84e872a0SLloyd Pique *
496*84e872a0SLloyd Pique * \param display The display object
497*84e872a0SLloyd Pique * \param fd The file descriptor for the socket to the client
498*84e872a0SLloyd Pique * \return The new client object or NULL on failure.
499*84e872a0SLloyd Pique *
500*84e872a0SLloyd Pique * Given a file descriptor corresponding to one end of a socket, this
501*84e872a0SLloyd Pique * function will create a wl_client struct and add the new client to
502*84e872a0SLloyd Pique * the compositors client list. At that point, the client is
503*84e872a0SLloyd Pique * initialized and ready to run, as if the client had connected to the
504*84e872a0SLloyd Pique * servers listening socket. When the client eventually sends
505*84e872a0SLloyd Pique * requests to the compositor, the wl_client argument to the request
506*84e872a0SLloyd Pique * handler will be the wl_client returned from this function.
507*84e872a0SLloyd Pique *
508*84e872a0SLloyd Pique * The other end of the socket can be passed to
509*84e872a0SLloyd Pique * wl_display_connect_to_fd() on the client side or used with the
510*84e872a0SLloyd Pique * WAYLAND_SOCKET environment variable on the client side.
511*84e872a0SLloyd Pique *
512*84e872a0SLloyd Pique * Listeners added with wl_display_add_client_created_listener() will
513*84e872a0SLloyd Pique * be notified by this function after the client is fully constructed.
514*84e872a0SLloyd Pique *
515*84e872a0SLloyd Pique * On failure this function sets errno accordingly and returns NULL.
516*84e872a0SLloyd Pique *
517*84e872a0SLloyd Pique * \memberof wl_display
518*84e872a0SLloyd Pique */
519*84e872a0SLloyd Pique WL_EXPORT struct wl_client *
wl_client_create(struct wl_display * display,int fd)520*84e872a0SLloyd Pique wl_client_create(struct wl_display *display, int fd)
521*84e872a0SLloyd Pique {
522*84e872a0SLloyd Pique struct wl_client *client;
523*84e872a0SLloyd Pique
524*84e872a0SLloyd Pique client = zalloc(sizeof *client);
525*84e872a0SLloyd Pique if (client == NULL)
526*84e872a0SLloyd Pique return NULL;
527*84e872a0SLloyd Pique
528*84e872a0SLloyd Pique wl_priv_signal_init(&client->resource_created_signal);
529*84e872a0SLloyd Pique client->display = display;
530*84e872a0SLloyd Pique client->source = wl_event_loop_add_fd(display->loop, fd,
531*84e872a0SLloyd Pique WL_EVENT_READABLE,
532*84e872a0SLloyd Pique wl_client_connection_data, client);
533*84e872a0SLloyd Pique
534*84e872a0SLloyd Pique if (!client->source)
535*84e872a0SLloyd Pique goto err_client;
536*84e872a0SLloyd Pique
537*84e872a0SLloyd Pique if (wl_os_socket_peercred(fd, &client->uid, &client->gid,
538*84e872a0SLloyd Pique &client->pid) != 0)
539*84e872a0SLloyd Pique goto err_source;
540*84e872a0SLloyd Pique
541*84e872a0SLloyd Pique client->connection = wl_connection_create(fd);
542*84e872a0SLloyd Pique if (client->connection == NULL)
543*84e872a0SLloyd Pique goto err_source;
544*84e872a0SLloyd Pique
545*84e872a0SLloyd Pique wl_map_init(&client->objects, WL_MAP_SERVER_SIDE);
546*84e872a0SLloyd Pique
547*84e872a0SLloyd Pique if (wl_map_insert_at(&client->objects, 0, 0, NULL) < 0)
548*84e872a0SLloyd Pique goto err_map;
549*84e872a0SLloyd Pique
550*84e872a0SLloyd Pique wl_priv_signal_init(&client->destroy_signal);
551*84e872a0SLloyd Pique wl_priv_signal_init(&client->destroy_late_signal);
552*84e872a0SLloyd Pique if (bind_display(client, display) < 0)
553*84e872a0SLloyd Pique goto err_map;
554*84e872a0SLloyd Pique
555*84e872a0SLloyd Pique wl_list_insert(display->client_list.prev, &client->link);
556*84e872a0SLloyd Pique
557*84e872a0SLloyd Pique wl_priv_signal_emit(&display->create_client_signal, client);
558*84e872a0SLloyd Pique
559*84e872a0SLloyd Pique return client;
560*84e872a0SLloyd Pique
561*84e872a0SLloyd Pique err_map:
562*84e872a0SLloyd Pique wl_map_release(&client->objects);
563*84e872a0SLloyd Pique wl_connection_destroy(client->connection);
564*84e872a0SLloyd Pique err_source:
565*84e872a0SLloyd Pique wl_event_source_remove(client->source);
566*84e872a0SLloyd Pique err_client:
567*84e872a0SLloyd Pique free(client);
568*84e872a0SLloyd Pique return NULL;
569*84e872a0SLloyd Pique }
570*84e872a0SLloyd Pique
571*84e872a0SLloyd Pique /** Return Unix credentials for the client
572*84e872a0SLloyd Pique *
573*84e872a0SLloyd Pique * \param client The display object
574*84e872a0SLloyd Pique * \param pid Returns the process ID
575*84e872a0SLloyd Pique * \param uid Returns the user ID
576*84e872a0SLloyd Pique * \param gid Returns the group ID
577*84e872a0SLloyd Pique *
578*84e872a0SLloyd Pique * This function returns the process ID, the user ID and the group ID
579*84e872a0SLloyd Pique * for the given client. The credentials come from getsockopt() with
580*84e872a0SLloyd Pique * SO_PEERCRED, on the client socket fd. All the pointers can be
581*84e872a0SLloyd Pique * NULL, if the caller is not interested in a particular ID.
582*84e872a0SLloyd Pique *
583*84e872a0SLloyd Pique * Note, process IDs are subject to race conditions and are not a reliable way
584*84e872a0SLloyd Pique * to identify a client.
585*84e872a0SLloyd Pique *
586*84e872a0SLloyd Pique * Be aware that for clients that a compositor forks and execs and
587*84e872a0SLloyd Pique * then connects using socketpair(), this function will return the
588*84e872a0SLloyd Pique * credentials for the compositor. The credentials for the socketpair
589*84e872a0SLloyd Pique * are set at creation time in the compositor.
590*84e872a0SLloyd Pique *
591*84e872a0SLloyd Pique * \memberof wl_client
592*84e872a0SLloyd Pique */
593*84e872a0SLloyd Pique WL_EXPORT void
wl_client_get_credentials(struct wl_client * client,pid_t * pid,uid_t * uid,gid_t * gid)594*84e872a0SLloyd Pique wl_client_get_credentials(struct wl_client *client,
595*84e872a0SLloyd Pique pid_t *pid, uid_t *uid, gid_t *gid)
596*84e872a0SLloyd Pique {
597*84e872a0SLloyd Pique if (pid)
598*84e872a0SLloyd Pique *pid = client->pid;
599*84e872a0SLloyd Pique if (uid)
600*84e872a0SLloyd Pique *uid = client->uid;
601*84e872a0SLloyd Pique if (gid)
602*84e872a0SLloyd Pique *gid = client->gid;
603*84e872a0SLloyd Pique }
604*84e872a0SLloyd Pique
605*84e872a0SLloyd Pique /** Get the file descriptor for the client
606*84e872a0SLloyd Pique *
607*84e872a0SLloyd Pique * \param client The display object
608*84e872a0SLloyd Pique * \return The file descriptor to use for the connection
609*84e872a0SLloyd Pique *
610*84e872a0SLloyd Pique * This function returns the file descriptor for the given client.
611*84e872a0SLloyd Pique *
612*84e872a0SLloyd Pique * Be sure to use the file descriptor from the client for inspection only.
613*84e872a0SLloyd Pique * If the caller does anything to the file descriptor that changes its state,
614*84e872a0SLloyd Pique * it will likely cause problems.
615*84e872a0SLloyd Pique *
616*84e872a0SLloyd Pique * See also wl_client_get_credentials().
617*84e872a0SLloyd Pique * It is recommended that you evaluate whether wl_client_get_credentials()
618*84e872a0SLloyd Pique * can be applied to your use case instead of this function.
619*84e872a0SLloyd Pique *
620*84e872a0SLloyd Pique * If you would like to distinguish just between the client and the compositor
621*84e872a0SLloyd Pique * itself from the client's request, it can be done by getting the client
622*84e872a0SLloyd Pique * credentials and by checking the PID of the client and the compositor's PID.
623*84e872a0SLloyd Pique * Regarding the case in which the socketpair() is being used, you need to be
624*84e872a0SLloyd Pique * careful. Please note the documentation for wl_client_get_credentials().
625*84e872a0SLloyd Pique *
626*84e872a0SLloyd Pique * This function can be used for a compositor to validate a request from
627*84e872a0SLloyd Pique * a client if there are additional information provided from the client's
628*84e872a0SLloyd Pique * file descriptor. For instance, suppose you can get the security contexts
629*84e872a0SLloyd Pique * from the client's file descriptor. The compositor can validate the client's
630*84e872a0SLloyd Pique * request with the contexts and make a decision whether it permits or deny it.
631*84e872a0SLloyd Pique *
632*84e872a0SLloyd Pique * \memberof wl_client
633*84e872a0SLloyd Pique */
634*84e872a0SLloyd Pique WL_EXPORT int
wl_client_get_fd(struct wl_client * client)635*84e872a0SLloyd Pique wl_client_get_fd(struct wl_client *client)
636*84e872a0SLloyd Pique {
637*84e872a0SLloyd Pique return wl_connection_get_fd(client->connection);
638*84e872a0SLloyd Pique }
639*84e872a0SLloyd Pique
640*84e872a0SLloyd Pique /** Look up an object in the client name space
641*84e872a0SLloyd Pique *
642*84e872a0SLloyd Pique * \param client The client object
643*84e872a0SLloyd Pique * \param id The object id
644*84e872a0SLloyd Pique * \return The object or NULL if there is not object for the given ID
645*84e872a0SLloyd Pique *
646*84e872a0SLloyd Pique * This looks up an object in the client object name space by its
647*84e872a0SLloyd Pique * object ID.
648*84e872a0SLloyd Pique *
649*84e872a0SLloyd Pique * \memberof wl_client
650*84e872a0SLloyd Pique */
651*84e872a0SLloyd Pique WL_EXPORT struct wl_resource *
wl_client_get_object(struct wl_client * client,uint32_t id)652*84e872a0SLloyd Pique wl_client_get_object(struct wl_client *client, uint32_t id)
653*84e872a0SLloyd Pique {
654*84e872a0SLloyd Pique return wl_map_lookup(&client->objects, id);
655*84e872a0SLloyd Pique }
656*84e872a0SLloyd Pique
657*84e872a0SLloyd Pique WL_EXPORT void
wl_client_post_no_memory(struct wl_client * client)658*84e872a0SLloyd Pique wl_client_post_no_memory(struct wl_client *client)
659*84e872a0SLloyd Pique {
660*84e872a0SLloyd Pique wl_resource_post_error(client->display_resource,
661*84e872a0SLloyd Pique WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
662*84e872a0SLloyd Pique }
663*84e872a0SLloyd Pique
664*84e872a0SLloyd Pique /** Report an internal server error
665*84e872a0SLloyd Pique *
666*84e872a0SLloyd Pique * \param client The client object
667*84e872a0SLloyd Pique * \param msg A printf-style format string
668*84e872a0SLloyd Pique * \param ... Format string arguments
669*84e872a0SLloyd Pique *
670*84e872a0SLloyd Pique * Report an unspecified internal implementation error and disconnect
671*84e872a0SLloyd Pique * the client.
672*84e872a0SLloyd Pique *
673*84e872a0SLloyd Pique * \memberof wl_client
674*84e872a0SLloyd Pique */
675*84e872a0SLloyd Pique WL_EXPORT void
wl_client_post_implementation_error(struct wl_client * client,char const * msg,...)676*84e872a0SLloyd Pique wl_client_post_implementation_error(struct wl_client *client,
677*84e872a0SLloyd Pique char const *msg, ...)
678*84e872a0SLloyd Pique {
679*84e872a0SLloyd Pique va_list ap;
680*84e872a0SLloyd Pique
681*84e872a0SLloyd Pique va_start(ap, msg);
682*84e872a0SLloyd Pique wl_resource_post_error_vargs(client->display_resource,
683*84e872a0SLloyd Pique WL_DISPLAY_ERROR_IMPLEMENTATION,
684*84e872a0SLloyd Pique msg, ap);
685*84e872a0SLloyd Pique va_end(ap);
686*84e872a0SLloyd Pique }
687*84e872a0SLloyd Pique
688*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_post_no_memory(struct wl_resource * resource)689*84e872a0SLloyd Pique wl_resource_post_no_memory(struct wl_resource *resource)
690*84e872a0SLloyd Pique {
691*84e872a0SLloyd Pique wl_resource_post_error(resource->client->display_resource,
692*84e872a0SLloyd Pique WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
693*84e872a0SLloyd Pique }
694*84e872a0SLloyd Pique
695*84e872a0SLloyd Pique /** Detect if a wl_resource uses the deprecated public definition.
696*84e872a0SLloyd Pique *
697*84e872a0SLloyd Pique * Before Wayland 1.2.0, the definition of struct wl_resource was public.
698*84e872a0SLloyd Pique * It was made opaque just before 1.2.0, and later new fields were added.
699*84e872a0SLloyd Pique * The new fields cannot be accessed if a program is using the deprecated
700*84e872a0SLloyd Pique * definition, as there would not be memory allocated for them.
701*84e872a0SLloyd Pique *
702*84e872a0SLloyd Pique * The creation pattern for the deprecated definition was wl_resource_init()
703*84e872a0SLloyd Pique * followed by wl_client_add_resource(). wl_resource_init() was an inline
704*84e872a0SLloyd Pique * function and no longer exists, but binaries might still carry it.
705*84e872a0SLloyd Pique * wl_client_add_resource() still exists for ABI compatibility.
706*84e872a0SLloyd Pique */
707*84e872a0SLloyd Pique static bool
resource_is_deprecated(struct wl_resource * resource)708*84e872a0SLloyd Pique resource_is_deprecated(struct wl_resource *resource)
709*84e872a0SLloyd Pique {
710*84e872a0SLloyd Pique struct wl_map *map = &resource->client->objects;
711*84e872a0SLloyd Pique int id = resource->object.id;
712*84e872a0SLloyd Pique
713*84e872a0SLloyd Pique /* wl_client_add_resource() marks deprecated resources with the flag. */
714*84e872a0SLloyd Pique if (wl_map_lookup_flags(map, id) & WL_MAP_ENTRY_LEGACY)
715*84e872a0SLloyd Pique return true;
716*84e872a0SLloyd Pique
717*84e872a0SLloyd Pique return false;
718*84e872a0SLloyd Pique }
719*84e872a0SLloyd Pique
720*84e872a0SLloyd Pique static enum wl_iterator_result
destroy_resource(void * element,void * data,uint32_t flags)721*84e872a0SLloyd Pique destroy_resource(void *element, void *data, uint32_t flags)
722*84e872a0SLloyd Pique {
723*84e872a0SLloyd Pique struct wl_resource *resource = element;
724*84e872a0SLloyd Pique
725*84e872a0SLloyd Pique wl_signal_emit(&resource->deprecated_destroy_signal, resource);
726*84e872a0SLloyd Pique /* Don't emit the new signal for deprecated resources, as that would
727*84e872a0SLloyd Pique * access memory outside the bounds of the deprecated struct */
728*84e872a0SLloyd Pique if (!resource_is_deprecated(resource))
729*84e872a0SLloyd Pique wl_priv_signal_final_emit(&resource->destroy_signal, resource);
730*84e872a0SLloyd Pique
731*84e872a0SLloyd Pique if (resource->destroy)
732*84e872a0SLloyd Pique resource->destroy(resource);
733*84e872a0SLloyd Pique
734*84e872a0SLloyd Pique if (!(flags & WL_MAP_ENTRY_LEGACY))
735*84e872a0SLloyd Pique free(resource);
736*84e872a0SLloyd Pique
737*84e872a0SLloyd Pique return WL_ITERATOR_CONTINUE;
738*84e872a0SLloyd Pique }
739*84e872a0SLloyd Pique
740*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_destroy(struct wl_resource * resource)741*84e872a0SLloyd Pique wl_resource_destroy(struct wl_resource *resource)
742*84e872a0SLloyd Pique {
743*84e872a0SLloyd Pique struct wl_client *client = resource->client;
744*84e872a0SLloyd Pique uint32_t id;
745*84e872a0SLloyd Pique uint32_t flags;
746*84e872a0SLloyd Pique
747*84e872a0SLloyd Pique id = resource->object.id;
748*84e872a0SLloyd Pique flags = wl_map_lookup_flags(&client->objects, id);
749*84e872a0SLloyd Pique destroy_resource(resource, NULL, flags);
750*84e872a0SLloyd Pique
751*84e872a0SLloyd Pique if (id < WL_SERVER_ID_START) {
752*84e872a0SLloyd Pique if (client->display_resource) {
753*84e872a0SLloyd Pique wl_resource_queue_event(client->display_resource,
754*84e872a0SLloyd Pique WL_DISPLAY_DELETE_ID, id);
755*84e872a0SLloyd Pique }
756*84e872a0SLloyd Pique wl_map_insert_at(&client->objects, 0, id, NULL);
757*84e872a0SLloyd Pique } else {
758*84e872a0SLloyd Pique wl_map_remove(&client->objects, id);
759*84e872a0SLloyd Pique }
760*84e872a0SLloyd Pique }
761*84e872a0SLloyd Pique
762*84e872a0SLloyd Pique WL_EXPORT uint32_t
wl_resource_get_id(struct wl_resource * resource)763*84e872a0SLloyd Pique wl_resource_get_id(struct wl_resource *resource)
764*84e872a0SLloyd Pique {
765*84e872a0SLloyd Pique return resource->object.id;
766*84e872a0SLloyd Pique }
767*84e872a0SLloyd Pique
768*84e872a0SLloyd Pique WL_EXPORT struct wl_list *
wl_resource_get_link(struct wl_resource * resource)769*84e872a0SLloyd Pique wl_resource_get_link(struct wl_resource *resource)
770*84e872a0SLloyd Pique {
771*84e872a0SLloyd Pique return &resource->link;
772*84e872a0SLloyd Pique }
773*84e872a0SLloyd Pique
774*84e872a0SLloyd Pique WL_EXPORT struct wl_resource *
wl_resource_from_link(struct wl_list * link)775*84e872a0SLloyd Pique wl_resource_from_link(struct wl_list *link)
776*84e872a0SLloyd Pique {
777*84e872a0SLloyd Pique struct wl_resource *resource;
778*84e872a0SLloyd Pique
779*84e872a0SLloyd Pique return wl_container_of(link, resource, link);
780*84e872a0SLloyd Pique }
781*84e872a0SLloyd Pique
782*84e872a0SLloyd Pique WL_EXPORT struct wl_resource *
wl_resource_find_for_client(struct wl_list * list,struct wl_client * client)783*84e872a0SLloyd Pique wl_resource_find_for_client(struct wl_list *list, struct wl_client *client)
784*84e872a0SLloyd Pique {
785*84e872a0SLloyd Pique struct wl_resource *resource;
786*84e872a0SLloyd Pique
787*84e872a0SLloyd Pique if (client == NULL)
788*84e872a0SLloyd Pique return NULL;
789*84e872a0SLloyd Pique
790*84e872a0SLloyd Pique wl_list_for_each(resource, list, link) {
791*84e872a0SLloyd Pique if (resource->client == client)
792*84e872a0SLloyd Pique return resource;
793*84e872a0SLloyd Pique }
794*84e872a0SLloyd Pique
795*84e872a0SLloyd Pique return NULL;
796*84e872a0SLloyd Pique }
797*84e872a0SLloyd Pique
798*84e872a0SLloyd Pique WL_EXPORT struct wl_client *
wl_resource_get_client(struct wl_resource * resource)799*84e872a0SLloyd Pique wl_resource_get_client(struct wl_resource *resource)
800*84e872a0SLloyd Pique {
801*84e872a0SLloyd Pique return resource->client;
802*84e872a0SLloyd Pique }
803*84e872a0SLloyd Pique
804*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_set_user_data(struct wl_resource * resource,void * data)805*84e872a0SLloyd Pique wl_resource_set_user_data(struct wl_resource *resource, void *data)
806*84e872a0SLloyd Pique {
807*84e872a0SLloyd Pique resource->data = data;
808*84e872a0SLloyd Pique }
809*84e872a0SLloyd Pique
810*84e872a0SLloyd Pique WL_EXPORT void *
wl_resource_get_user_data(struct wl_resource * resource)811*84e872a0SLloyd Pique wl_resource_get_user_data(struct wl_resource *resource)
812*84e872a0SLloyd Pique {
813*84e872a0SLloyd Pique return resource->data;
814*84e872a0SLloyd Pique }
815*84e872a0SLloyd Pique
816*84e872a0SLloyd Pique WL_EXPORT int
wl_resource_get_version(struct wl_resource * resource)817*84e872a0SLloyd Pique wl_resource_get_version(struct wl_resource *resource)
818*84e872a0SLloyd Pique {
819*84e872a0SLloyd Pique return resource->version;
820*84e872a0SLloyd Pique }
821*84e872a0SLloyd Pique
822*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_set_destructor(struct wl_resource * resource,wl_resource_destroy_func_t destroy)823*84e872a0SLloyd Pique wl_resource_set_destructor(struct wl_resource *resource,
824*84e872a0SLloyd Pique wl_resource_destroy_func_t destroy)
825*84e872a0SLloyd Pique {
826*84e872a0SLloyd Pique resource->destroy = destroy;
827*84e872a0SLloyd Pique }
828*84e872a0SLloyd Pique
829*84e872a0SLloyd Pique WL_EXPORT int
wl_resource_instance_of(struct wl_resource * resource,const struct wl_interface * interface,const void * implementation)830*84e872a0SLloyd Pique wl_resource_instance_of(struct wl_resource *resource,
831*84e872a0SLloyd Pique const struct wl_interface *interface,
832*84e872a0SLloyd Pique const void *implementation)
833*84e872a0SLloyd Pique {
834*84e872a0SLloyd Pique return wl_interface_equal(resource->object.interface, interface) &&
835*84e872a0SLloyd Pique resource->object.implementation == implementation;
836*84e872a0SLloyd Pique }
837*84e872a0SLloyd Pique
838*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_add_destroy_listener(struct wl_resource * resource,struct wl_listener * listener)839*84e872a0SLloyd Pique wl_resource_add_destroy_listener(struct wl_resource *resource,
840*84e872a0SLloyd Pique struct wl_listener * listener)
841*84e872a0SLloyd Pique {
842*84e872a0SLloyd Pique if (resource_is_deprecated(resource))
843*84e872a0SLloyd Pique wl_signal_add(&resource->deprecated_destroy_signal, listener);
844*84e872a0SLloyd Pique else
845*84e872a0SLloyd Pique wl_priv_signal_add(&resource->destroy_signal, listener);
846*84e872a0SLloyd Pique }
847*84e872a0SLloyd Pique
848*84e872a0SLloyd Pique WL_EXPORT struct wl_listener *
wl_resource_get_destroy_listener(struct wl_resource * resource,wl_notify_func_t notify)849*84e872a0SLloyd Pique wl_resource_get_destroy_listener(struct wl_resource *resource,
850*84e872a0SLloyd Pique wl_notify_func_t notify)
851*84e872a0SLloyd Pique {
852*84e872a0SLloyd Pique if (resource_is_deprecated(resource))
853*84e872a0SLloyd Pique return wl_signal_get(&resource->deprecated_destroy_signal, notify);
854*84e872a0SLloyd Pique return wl_priv_signal_get(&resource->destroy_signal, notify);
855*84e872a0SLloyd Pique }
856*84e872a0SLloyd Pique
857*84e872a0SLloyd Pique /** Retrieve the interface name (class) of a resource object.
858*84e872a0SLloyd Pique *
859*84e872a0SLloyd Pique * \param resource The resource object
860*84e872a0SLloyd Pique *
861*84e872a0SLloyd Pique * \memberof wl_resource
862*84e872a0SLloyd Pique */
863*84e872a0SLloyd Pique WL_EXPORT const char *
wl_resource_get_class(struct wl_resource * resource)864*84e872a0SLloyd Pique wl_resource_get_class(struct wl_resource *resource)
865*84e872a0SLloyd Pique {
866*84e872a0SLloyd Pique return resource->object.interface->name;
867*84e872a0SLloyd Pique }
868*84e872a0SLloyd Pique
869*84e872a0SLloyd Pique /** Safely converts an object into its corresponding resource
870*84e872a0SLloyd Pique *
871*84e872a0SLloyd Pique * \param object object to get the resource for
872*84e872a0SLloyd Pique * \return A corresponding resource, or NULL on failure
873*84e872a0SLloyd Pique *
874*84e872a0SLloyd Pique * Safely converts an object into its corresponding resource.
875*84e872a0SLloyd Pique *
876*84e872a0SLloyd Pique * This is useful for implementing functions that are given a \c wl_argument
877*84e872a0SLloyd Pique * array, and that need to do further introspection on the ".o" field, as it
878*84e872a0SLloyd Pique * is otherwise an opaque type.
879*84e872a0SLloyd Pique *
880*84e872a0SLloyd Pique * \memberof wl_resource
881*84e872a0SLloyd Pique */
882*84e872a0SLloyd Pique WL_EXPORT struct wl_resource *
wl_resource_from_object(struct wl_object * object)883*84e872a0SLloyd Pique wl_resource_from_object(struct wl_object *object)
884*84e872a0SLloyd Pique {
885*84e872a0SLloyd Pique struct wl_resource *resource;
886*84e872a0SLloyd Pique if (object == NULL)
887*84e872a0SLloyd Pique return NULL;
888*84e872a0SLloyd Pique return wl_container_of(object, resource, object);
889*84e872a0SLloyd Pique }
890*84e872a0SLloyd Pique
891*84e872a0SLloyd Pique /**
892*84e872a0SLloyd Pique * Add a listener to be called at the beginning of wl_client destruction
893*84e872a0SLloyd Pique *
894*84e872a0SLloyd Pique * The listener provided will be called when wl_client destroy has begun,
895*84e872a0SLloyd Pique * before any of that client's resources have been destroyed.
896*84e872a0SLloyd Pique *
897*84e872a0SLloyd Pique * There is no requirement to remove the link of the wl_listener when the
898*84e872a0SLloyd Pique * signal is emitted.
899*84e872a0SLloyd Pique *
900*84e872a0SLloyd Pique * \memberof wl_client
901*84e872a0SLloyd Pique */
902*84e872a0SLloyd Pique WL_EXPORT void
wl_client_add_destroy_listener(struct wl_client * client,struct wl_listener * listener)903*84e872a0SLloyd Pique wl_client_add_destroy_listener(struct wl_client *client,
904*84e872a0SLloyd Pique struct wl_listener *listener)
905*84e872a0SLloyd Pique {
906*84e872a0SLloyd Pique wl_priv_signal_add(&client->destroy_signal, listener);
907*84e872a0SLloyd Pique }
908*84e872a0SLloyd Pique
909*84e872a0SLloyd Pique WL_EXPORT struct wl_listener *
wl_client_get_destroy_listener(struct wl_client * client,wl_notify_func_t notify)910*84e872a0SLloyd Pique wl_client_get_destroy_listener(struct wl_client *client,
911*84e872a0SLloyd Pique wl_notify_func_t notify)
912*84e872a0SLloyd Pique {
913*84e872a0SLloyd Pique return wl_priv_signal_get(&client->destroy_signal, notify);
914*84e872a0SLloyd Pique }
915*84e872a0SLloyd Pique
916*84e872a0SLloyd Pique /**
917*84e872a0SLloyd Pique * Add a listener to be called at the end of wl_client destruction
918*84e872a0SLloyd Pique *
919*84e872a0SLloyd Pique * The listener provided will be called when wl_client destroy is nearly
920*84e872a0SLloyd Pique * complete, after all of that client's resources have been destroyed.
921*84e872a0SLloyd Pique *
922*84e872a0SLloyd Pique * There is no requirement to remove the link of the wl_listener when the
923*84e872a0SLloyd Pique * signal is emitted.
924*84e872a0SLloyd Pique *
925*84e872a0SLloyd Pique * \memberof wl_client
926*84e872a0SLloyd Pique * \since 1.22.0
927*84e872a0SLloyd Pique */
928*84e872a0SLloyd Pique WL_EXPORT void
wl_client_add_destroy_late_listener(struct wl_client * client,struct wl_listener * listener)929*84e872a0SLloyd Pique wl_client_add_destroy_late_listener(struct wl_client *client,
930*84e872a0SLloyd Pique struct wl_listener *listener)
931*84e872a0SLloyd Pique {
932*84e872a0SLloyd Pique wl_priv_signal_add(&client->destroy_late_signal, listener);
933*84e872a0SLloyd Pique }
934*84e872a0SLloyd Pique
935*84e872a0SLloyd Pique WL_EXPORT struct wl_listener *
wl_client_get_destroy_late_listener(struct wl_client * client,wl_notify_func_t notify)936*84e872a0SLloyd Pique wl_client_get_destroy_late_listener(struct wl_client *client,
937*84e872a0SLloyd Pique wl_notify_func_t notify)
938*84e872a0SLloyd Pique {
939*84e872a0SLloyd Pique return wl_priv_signal_get(&client->destroy_late_signal, notify);
940*84e872a0SLloyd Pique }
941*84e872a0SLloyd Pique
942*84e872a0SLloyd Pique WL_EXPORT void
wl_client_destroy(struct wl_client * client)943*84e872a0SLloyd Pique wl_client_destroy(struct wl_client *client)
944*84e872a0SLloyd Pique {
945*84e872a0SLloyd Pique uint32_t serial = 0;
946*84e872a0SLloyd Pique
947*84e872a0SLloyd Pique wl_priv_signal_final_emit(&client->destroy_signal, client);
948*84e872a0SLloyd Pique
949*84e872a0SLloyd Pique wl_client_flush(client);
950*84e872a0SLloyd Pique wl_map_for_each(&client->objects, destroy_resource, &serial);
951*84e872a0SLloyd Pique wl_map_release(&client->objects);
952*84e872a0SLloyd Pique wl_event_source_remove(client->source);
953*84e872a0SLloyd Pique close(wl_connection_destroy(client->connection));
954*84e872a0SLloyd Pique
955*84e872a0SLloyd Pique wl_priv_signal_final_emit(&client->destroy_late_signal, client);
956*84e872a0SLloyd Pique
957*84e872a0SLloyd Pique wl_list_remove(&client->link);
958*84e872a0SLloyd Pique wl_list_remove(&client->resource_created_signal.listener_list);
959*84e872a0SLloyd Pique free(client);
960*84e872a0SLloyd Pique }
961*84e872a0SLloyd Pique
962*84e872a0SLloyd Pique /* Check if a global filter is registered and use it if any.
963*84e872a0SLloyd Pique *
964*84e872a0SLloyd Pique * If no wl_global filter has been registered, this function will
965*84e872a0SLloyd Pique * return true, allowing the wl_global to be visible to the wl_client
966*84e872a0SLloyd Pique */
967*84e872a0SLloyd Pique static bool
wl_global_is_visible(const struct wl_client * client,const struct wl_global * global)968*84e872a0SLloyd Pique wl_global_is_visible(const struct wl_client *client,
969*84e872a0SLloyd Pique const struct wl_global *global)
970*84e872a0SLloyd Pique {
971*84e872a0SLloyd Pique struct wl_display *display = client->display;
972*84e872a0SLloyd Pique
973*84e872a0SLloyd Pique return (display->global_filter == NULL ||
974*84e872a0SLloyd Pique display->global_filter(client, global, display->global_filter_data));
975*84e872a0SLloyd Pique }
976*84e872a0SLloyd Pique
977*84e872a0SLloyd Pique static void
registry_bind(struct wl_client * client,struct wl_resource * resource,uint32_t name,const char * interface,uint32_t version,uint32_t id)978*84e872a0SLloyd Pique registry_bind(struct wl_client *client,
979*84e872a0SLloyd Pique struct wl_resource *resource, uint32_t name,
980*84e872a0SLloyd Pique const char *interface, uint32_t version, uint32_t id)
981*84e872a0SLloyd Pique {
982*84e872a0SLloyd Pique struct wl_global *global;
983*84e872a0SLloyd Pique struct wl_display *display = resource->data;
984*84e872a0SLloyd Pique
985*84e872a0SLloyd Pique wl_list_for_each(global, &display->global_list, link)
986*84e872a0SLloyd Pique if (global->name == name)
987*84e872a0SLloyd Pique break;
988*84e872a0SLloyd Pique
989*84e872a0SLloyd Pique if (&global->link == &display->global_list)
990*84e872a0SLloyd Pique wl_resource_post_error(resource,
991*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
992*84e872a0SLloyd Pique "invalid global %s (%d)", interface, name);
993*84e872a0SLloyd Pique else if (strcmp(global->interface->name, interface) != 0)
994*84e872a0SLloyd Pique wl_resource_post_error(resource,
995*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
996*84e872a0SLloyd Pique "invalid interface for global %u: "
997*84e872a0SLloyd Pique "have %s, wanted %s",
998*84e872a0SLloyd Pique name, interface, global->interface->name);
999*84e872a0SLloyd Pique else if (version == 0)
1000*84e872a0SLloyd Pique wl_resource_post_error(resource,
1001*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
1002*84e872a0SLloyd Pique "invalid version for global %s (%d): 0 is not a valid version",
1003*84e872a0SLloyd Pique interface, name);
1004*84e872a0SLloyd Pique else if (global->version < version)
1005*84e872a0SLloyd Pique wl_resource_post_error(resource,
1006*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
1007*84e872a0SLloyd Pique "invalid version for global %s (%d): have %d, wanted %d",
1008*84e872a0SLloyd Pique interface, name, global->version, version);
1009*84e872a0SLloyd Pique else if (!wl_global_is_visible(client, global))
1010*84e872a0SLloyd Pique wl_resource_post_error(resource,
1011*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
1012*84e872a0SLloyd Pique "invalid global %s (%d)", interface, name);
1013*84e872a0SLloyd Pique else
1014*84e872a0SLloyd Pique global->bind(client, global->data, version, id);
1015*84e872a0SLloyd Pique }
1016*84e872a0SLloyd Pique
1017*84e872a0SLloyd Pique static const struct wl_registry_interface registry_interface = {
1018*84e872a0SLloyd Pique registry_bind
1019*84e872a0SLloyd Pique };
1020*84e872a0SLloyd Pique
1021*84e872a0SLloyd Pique static void
display_sync(struct wl_client * client,struct wl_resource * resource,uint32_t id)1022*84e872a0SLloyd Pique display_sync(struct wl_client *client,
1023*84e872a0SLloyd Pique struct wl_resource *resource, uint32_t id)
1024*84e872a0SLloyd Pique {
1025*84e872a0SLloyd Pique struct wl_resource *callback;
1026*84e872a0SLloyd Pique uint32_t serial;
1027*84e872a0SLloyd Pique
1028*84e872a0SLloyd Pique callback = wl_resource_create(client, &wl_callback_interface, 1, id);
1029*84e872a0SLloyd Pique if (callback == NULL) {
1030*84e872a0SLloyd Pique wl_client_post_no_memory(client);
1031*84e872a0SLloyd Pique return;
1032*84e872a0SLloyd Pique }
1033*84e872a0SLloyd Pique
1034*84e872a0SLloyd Pique serial = wl_display_get_serial(client->display);
1035*84e872a0SLloyd Pique wl_callback_send_done(callback, serial);
1036*84e872a0SLloyd Pique wl_resource_destroy(callback);
1037*84e872a0SLloyd Pique }
1038*84e872a0SLloyd Pique
1039*84e872a0SLloyd Pique static void
unbind_resource(struct wl_resource * resource)1040*84e872a0SLloyd Pique unbind_resource(struct wl_resource *resource)
1041*84e872a0SLloyd Pique {
1042*84e872a0SLloyd Pique wl_list_remove(&resource->link);
1043*84e872a0SLloyd Pique }
1044*84e872a0SLloyd Pique
1045*84e872a0SLloyd Pique static void
display_get_registry(struct wl_client * client,struct wl_resource * resource,uint32_t id)1046*84e872a0SLloyd Pique display_get_registry(struct wl_client *client,
1047*84e872a0SLloyd Pique struct wl_resource *resource, uint32_t id)
1048*84e872a0SLloyd Pique {
1049*84e872a0SLloyd Pique struct wl_display *display = resource->data;
1050*84e872a0SLloyd Pique struct wl_resource *registry_resource;
1051*84e872a0SLloyd Pique struct wl_global *global;
1052*84e872a0SLloyd Pique
1053*84e872a0SLloyd Pique registry_resource =
1054*84e872a0SLloyd Pique wl_resource_create(client, &wl_registry_interface, 1, id);
1055*84e872a0SLloyd Pique if (registry_resource == NULL) {
1056*84e872a0SLloyd Pique wl_client_post_no_memory(client);
1057*84e872a0SLloyd Pique return;
1058*84e872a0SLloyd Pique }
1059*84e872a0SLloyd Pique
1060*84e872a0SLloyd Pique wl_resource_set_implementation(registry_resource,
1061*84e872a0SLloyd Pique ®istry_interface,
1062*84e872a0SLloyd Pique display, unbind_resource);
1063*84e872a0SLloyd Pique
1064*84e872a0SLloyd Pique wl_list_insert(&display->registry_resource_list,
1065*84e872a0SLloyd Pique ®istry_resource->link);
1066*84e872a0SLloyd Pique
1067*84e872a0SLloyd Pique wl_list_for_each(global, &display->global_list, link)
1068*84e872a0SLloyd Pique if (wl_global_is_visible(client, global) && !global->removed)
1069*84e872a0SLloyd Pique wl_resource_post_event(registry_resource,
1070*84e872a0SLloyd Pique WL_REGISTRY_GLOBAL,
1071*84e872a0SLloyd Pique global->name,
1072*84e872a0SLloyd Pique global->interface->name,
1073*84e872a0SLloyd Pique global->version);
1074*84e872a0SLloyd Pique }
1075*84e872a0SLloyd Pique
1076*84e872a0SLloyd Pique static const struct wl_display_interface display_interface = {
1077*84e872a0SLloyd Pique display_sync,
1078*84e872a0SLloyd Pique display_get_registry
1079*84e872a0SLloyd Pique };
1080*84e872a0SLloyd Pique
1081*84e872a0SLloyd Pique static void
destroy_client_display_resource(struct wl_resource * resource)1082*84e872a0SLloyd Pique destroy_client_display_resource(struct wl_resource *resource)
1083*84e872a0SLloyd Pique {
1084*84e872a0SLloyd Pique resource->client->display_resource = NULL;
1085*84e872a0SLloyd Pique }
1086*84e872a0SLloyd Pique
1087*84e872a0SLloyd Pique static int
bind_display(struct wl_client * client,struct wl_display * display)1088*84e872a0SLloyd Pique bind_display(struct wl_client *client, struct wl_display *display)
1089*84e872a0SLloyd Pique {
1090*84e872a0SLloyd Pique client->display_resource =
1091*84e872a0SLloyd Pique wl_resource_create(client, &wl_display_interface, 1, 1);
1092*84e872a0SLloyd Pique if (client->display_resource == NULL) {
1093*84e872a0SLloyd Pique /* DON'T send no-memory error to client - it has no
1094*84e872a0SLloyd Pique * resource to which it could post the event */
1095*84e872a0SLloyd Pique return -1;
1096*84e872a0SLloyd Pique }
1097*84e872a0SLloyd Pique
1098*84e872a0SLloyd Pique wl_resource_set_implementation(client->display_resource,
1099*84e872a0SLloyd Pique &display_interface, display,
1100*84e872a0SLloyd Pique destroy_client_display_resource);
1101*84e872a0SLloyd Pique return 0;
1102*84e872a0SLloyd Pique }
1103*84e872a0SLloyd Pique
1104*84e872a0SLloyd Pique static int
handle_display_terminate(int fd,uint32_t mask,void * data)1105*84e872a0SLloyd Pique handle_display_terminate(int fd, uint32_t mask, void *data) {
1106*84e872a0SLloyd Pique uint64_t term_event;
1107*84e872a0SLloyd Pique
1108*84e872a0SLloyd Pique if (read(fd, &term_event, sizeof(term_event)) < 0 && errno != EAGAIN)
1109*84e872a0SLloyd Pique return -1;
1110*84e872a0SLloyd Pique
1111*84e872a0SLloyd Pique return 0;
1112*84e872a0SLloyd Pique }
1113*84e872a0SLloyd Pique
1114*84e872a0SLloyd Pique /** Create Wayland display object.
1115*84e872a0SLloyd Pique *
1116*84e872a0SLloyd Pique * \return The Wayland display object. Null if failed to create
1117*84e872a0SLloyd Pique *
1118*84e872a0SLloyd Pique * This creates the wl_display object.
1119*84e872a0SLloyd Pique *
1120*84e872a0SLloyd Pique * \memberof wl_display
1121*84e872a0SLloyd Pique */
1122*84e872a0SLloyd Pique WL_EXPORT struct wl_display *
wl_display_create(void)1123*84e872a0SLloyd Pique wl_display_create(void)
1124*84e872a0SLloyd Pique {
1125*84e872a0SLloyd Pique struct wl_display *display;
1126*84e872a0SLloyd Pique const char *debug;
1127*84e872a0SLloyd Pique
1128*84e872a0SLloyd Pique debug = getenv("WAYLAND_DEBUG");
1129*84e872a0SLloyd Pique if (debug && (strstr(debug, "server") || strstr(debug, "1")))
1130*84e872a0SLloyd Pique debug_server = 1;
1131*84e872a0SLloyd Pique
1132*84e872a0SLloyd Pique display = zalloc(sizeof *display);
1133*84e872a0SLloyd Pique if (display == NULL)
1134*84e872a0SLloyd Pique return NULL;
1135*84e872a0SLloyd Pique
1136*84e872a0SLloyd Pique display->loop = wl_event_loop_create();
1137*84e872a0SLloyd Pique if (display->loop == NULL) {
1138*84e872a0SLloyd Pique free(display);
1139*84e872a0SLloyd Pique return NULL;
1140*84e872a0SLloyd Pique }
1141*84e872a0SLloyd Pique
1142*84e872a0SLloyd Pique display->terminate_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
1143*84e872a0SLloyd Pique if (display->terminate_efd < 0)
1144*84e872a0SLloyd Pique goto err_eventfd;
1145*84e872a0SLloyd Pique
1146*84e872a0SLloyd Pique display->term_source = wl_event_loop_add_fd(display->loop,
1147*84e872a0SLloyd Pique display->terminate_efd,
1148*84e872a0SLloyd Pique WL_EVENT_READABLE,
1149*84e872a0SLloyd Pique handle_display_terminate,
1150*84e872a0SLloyd Pique NULL);
1151*84e872a0SLloyd Pique
1152*84e872a0SLloyd Pique if (display->term_source == NULL)
1153*84e872a0SLloyd Pique goto err_term_source;
1154*84e872a0SLloyd Pique
1155*84e872a0SLloyd Pique wl_list_init(&display->global_list);
1156*84e872a0SLloyd Pique wl_list_init(&display->socket_list);
1157*84e872a0SLloyd Pique wl_list_init(&display->client_list);
1158*84e872a0SLloyd Pique wl_list_init(&display->registry_resource_list);
1159*84e872a0SLloyd Pique wl_list_init(&display->protocol_loggers);
1160*84e872a0SLloyd Pique
1161*84e872a0SLloyd Pique wl_priv_signal_init(&display->destroy_signal);
1162*84e872a0SLloyd Pique wl_priv_signal_init(&display->create_client_signal);
1163*84e872a0SLloyd Pique
1164*84e872a0SLloyd Pique display->next_global_name = 1;
1165*84e872a0SLloyd Pique display->serial = 0;
1166*84e872a0SLloyd Pique
1167*84e872a0SLloyd Pique display->global_filter = NULL;
1168*84e872a0SLloyd Pique display->global_filter_data = NULL;
1169*84e872a0SLloyd Pique
1170*84e872a0SLloyd Pique wl_array_init(&display->additional_shm_formats);
1171*84e872a0SLloyd Pique
1172*84e872a0SLloyd Pique return display;
1173*84e872a0SLloyd Pique
1174*84e872a0SLloyd Pique err_term_source:
1175*84e872a0SLloyd Pique close(display->terminate_efd);
1176*84e872a0SLloyd Pique err_eventfd:
1177*84e872a0SLloyd Pique wl_event_loop_destroy(display->loop);
1178*84e872a0SLloyd Pique free(display);
1179*84e872a0SLloyd Pique return NULL;
1180*84e872a0SLloyd Pique }
1181*84e872a0SLloyd Pique
1182*84e872a0SLloyd Pique static void
wl_socket_destroy(struct wl_socket * s)1183*84e872a0SLloyd Pique wl_socket_destroy(struct wl_socket *s)
1184*84e872a0SLloyd Pique {
1185*84e872a0SLloyd Pique if (s->source)
1186*84e872a0SLloyd Pique wl_event_source_remove(s->source);
1187*84e872a0SLloyd Pique if (s->addr.sun_path[0])
1188*84e872a0SLloyd Pique unlink(s->addr.sun_path);
1189*84e872a0SLloyd Pique if (s->fd >= 0)
1190*84e872a0SLloyd Pique close(s->fd);
1191*84e872a0SLloyd Pique if (s->lock_addr[0])
1192*84e872a0SLloyd Pique unlink(s->lock_addr);
1193*84e872a0SLloyd Pique if (s->fd_lock >= 0)
1194*84e872a0SLloyd Pique close(s->fd_lock);
1195*84e872a0SLloyd Pique
1196*84e872a0SLloyd Pique free(s);
1197*84e872a0SLloyd Pique }
1198*84e872a0SLloyd Pique
1199*84e872a0SLloyd Pique static struct wl_socket *
wl_socket_alloc(void)1200*84e872a0SLloyd Pique wl_socket_alloc(void)
1201*84e872a0SLloyd Pique {
1202*84e872a0SLloyd Pique struct wl_socket *s;
1203*84e872a0SLloyd Pique
1204*84e872a0SLloyd Pique s = zalloc(sizeof *s);
1205*84e872a0SLloyd Pique if (!s)
1206*84e872a0SLloyd Pique return NULL;
1207*84e872a0SLloyd Pique
1208*84e872a0SLloyd Pique s->fd = -1;
1209*84e872a0SLloyd Pique s->fd_lock = -1;
1210*84e872a0SLloyd Pique
1211*84e872a0SLloyd Pique return s;
1212*84e872a0SLloyd Pique }
1213*84e872a0SLloyd Pique
1214*84e872a0SLloyd Pique /** Destroy Wayland display object.
1215*84e872a0SLloyd Pique *
1216*84e872a0SLloyd Pique * \param display The Wayland display object which should be destroyed.
1217*84e872a0SLloyd Pique *
1218*84e872a0SLloyd Pique * This function emits the wl_display destroy signal, releases
1219*84e872a0SLloyd Pique * all the sockets added to this display, free's all the globals associated
1220*84e872a0SLloyd Pique * with this display, free's memory of additional shared memory formats and
1221*84e872a0SLloyd Pique * destroy the display object.
1222*84e872a0SLloyd Pique *
1223*84e872a0SLloyd Pique * \sa wl_display_add_destroy_listener
1224*84e872a0SLloyd Pique *
1225*84e872a0SLloyd Pique * \memberof wl_display
1226*84e872a0SLloyd Pique */
1227*84e872a0SLloyd Pique WL_EXPORT void
wl_display_destroy(struct wl_display * display)1228*84e872a0SLloyd Pique wl_display_destroy(struct wl_display *display)
1229*84e872a0SLloyd Pique {
1230*84e872a0SLloyd Pique struct wl_socket *s, *next;
1231*84e872a0SLloyd Pique struct wl_global *global, *gnext;
1232*84e872a0SLloyd Pique
1233*84e872a0SLloyd Pique wl_priv_signal_final_emit(&display->destroy_signal, display);
1234*84e872a0SLloyd Pique
1235*84e872a0SLloyd Pique wl_list_for_each_safe(s, next, &display->socket_list, link) {
1236*84e872a0SLloyd Pique wl_socket_destroy(s);
1237*84e872a0SLloyd Pique }
1238*84e872a0SLloyd Pique
1239*84e872a0SLloyd Pique close(display->terminate_efd);
1240*84e872a0SLloyd Pique wl_event_source_remove(display->term_source);
1241*84e872a0SLloyd Pique
1242*84e872a0SLloyd Pique wl_event_loop_destroy(display->loop);
1243*84e872a0SLloyd Pique
1244*84e872a0SLloyd Pique wl_list_for_each_safe(global, gnext, &display->global_list, link)
1245*84e872a0SLloyd Pique free(global);
1246*84e872a0SLloyd Pique
1247*84e872a0SLloyd Pique wl_array_release(&display->additional_shm_formats);
1248*84e872a0SLloyd Pique
1249*84e872a0SLloyd Pique wl_list_remove(&display->protocol_loggers);
1250*84e872a0SLloyd Pique
1251*84e872a0SLloyd Pique free(display);
1252*84e872a0SLloyd Pique }
1253*84e872a0SLloyd Pique
1254*84e872a0SLloyd Pique /** Set a filter function for global objects
1255*84e872a0SLloyd Pique *
1256*84e872a0SLloyd Pique * \param display The Wayland display object.
1257*84e872a0SLloyd Pique * \param filter The global filter function.
1258*84e872a0SLloyd Pique * \param data User data to be associated with the global filter.
1259*84e872a0SLloyd Pique *
1260*84e872a0SLloyd Pique * Set a filter for the wl_display to advertise or hide global objects
1261*84e872a0SLloyd Pique * to clients.
1262*84e872a0SLloyd Pique * The set filter will be used during wl_global advertisement to
1263*84e872a0SLloyd Pique * determine whether a global object should be advertised to a
1264*84e872a0SLloyd Pique * given client, and during wl_global binding to determine whether
1265*84e872a0SLloyd Pique * a given client should be allowed to bind to a global.
1266*84e872a0SLloyd Pique *
1267*84e872a0SLloyd Pique * Clients that try to bind to a global that was filtered out will
1268*84e872a0SLloyd Pique * have an error raised.
1269*84e872a0SLloyd Pique *
1270*84e872a0SLloyd Pique * Setting the filter NULL will result in all globals being
1271*84e872a0SLloyd Pique * advertised to all clients. The default is no filter.
1272*84e872a0SLloyd Pique *
1273*84e872a0SLloyd Pique * The filter should be installed before any client connects and should always
1274*84e872a0SLloyd Pique * take the same decision given a client and a global. Not doing so will result
1275*84e872a0SLloyd Pique * in inconsistent filtering and broken wl_registry event sequences.
1276*84e872a0SLloyd Pique *
1277*84e872a0SLloyd Pique * \memberof wl_display
1278*84e872a0SLloyd Pique */
1279*84e872a0SLloyd Pique WL_EXPORT void
wl_display_set_global_filter(struct wl_display * display,wl_display_global_filter_func_t filter,void * data)1280*84e872a0SLloyd Pique wl_display_set_global_filter(struct wl_display *display,
1281*84e872a0SLloyd Pique wl_display_global_filter_func_t filter,
1282*84e872a0SLloyd Pique void *data)
1283*84e872a0SLloyd Pique {
1284*84e872a0SLloyd Pique display->global_filter = filter;
1285*84e872a0SLloyd Pique display->global_filter_data = data;
1286*84e872a0SLloyd Pique }
1287*84e872a0SLloyd Pique
1288*84e872a0SLloyd Pique WL_EXPORT struct wl_global *
wl_global_create(struct wl_display * display,const struct wl_interface * interface,int version,void * data,wl_global_bind_func_t bind)1289*84e872a0SLloyd Pique wl_global_create(struct wl_display *display,
1290*84e872a0SLloyd Pique const struct wl_interface *interface, int version,
1291*84e872a0SLloyd Pique void *data, wl_global_bind_func_t bind)
1292*84e872a0SLloyd Pique {
1293*84e872a0SLloyd Pique struct wl_global *global;
1294*84e872a0SLloyd Pique struct wl_resource *resource;
1295*84e872a0SLloyd Pique
1296*84e872a0SLloyd Pique if (version < 1) {
1297*84e872a0SLloyd Pique wl_log("wl_global_create: failing to create interface "
1298*84e872a0SLloyd Pique "'%s' with version %d because it is less than 1\n",
1299*84e872a0SLloyd Pique interface->name, version);
1300*84e872a0SLloyd Pique return NULL;
1301*84e872a0SLloyd Pique }
1302*84e872a0SLloyd Pique
1303*84e872a0SLloyd Pique if (version > interface->version) {
1304*84e872a0SLloyd Pique wl_log("wl_global_create: implemented version for '%s' "
1305*84e872a0SLloyd Pique "higher than interface version (%d > %d)\n",
1306*84e872a0SLloyd Pique interface->name, version, interface->version);
1307*84e872a0SLloyd Pique return NULL;
1308*84e872a0SLloyd Pique }
1309*84e872a0SLloyd Pique
1310*84e872a0SLloyd Pique if (display->next_global_name >= UINT32_MAX) {
1311*84e872a0SLloyd Pique wl_log("wl_global_create: ran out of global names\n");
1312*84e872a0SLloyd Pique return NULL;
1313*84e872a0SLloyd Pique }
1314*84e872a0SLloyd Pique
1315*84e872a0SLloyd Pique global = zalloc(sizeof *global);
1316*84e872a0SLloyd Pique if (global == NULL)
1317*84e872a0SLloyd Pique return NULL;
1318*84e872a0SLloyd Pique
1319*84e872a0SLloyd Pique global->display = display;
1320*84e872a0SLloyd Pique global->name = display->next_global_name++;
1321*84e872a0SLloyd Pique global->interface = interface;
1322*84e872a0SLloyd Pique global->version = version;
1323*84e872a0SLloyd Pique global->data = data;
1324*84e872a0SLloyd Pique global->bind = bind;
1325*84e872a0SLloyd Pique global->removed = false;
1326*84e872a0SLloyd Pique wl_list_insert(display->global_list.prev, &global->link);
1327*84e872a0SLloyd Pique
1328*84e872a0SLloyd Pique wl_list_for_each(resource, &display->registry_resource_list, link)
1329*84e872a0SLloyd Pique if (wl_global_is_visible(resource->client, global))
1330*84e872a0SLloyd Pique wl_resource_post_event(resource,
1331*84e872a0SLloyd Pique WL_REGISTRY_GLOBAL,
1332*84e872a0SLloyd Pique global->name,
1333*84e872a0SLloyd Pique global->interface->name,
1334*84e872a0SLloyd Pique global->version);
1335*84e872a0SLloyd Pique
1336*84e872a0SLloyd Pique return global;
1337*84e872a0SLloyd Pique }
1338*84e872a0SLloyd Pique
1339*84e872a0SLloyd Pique /** Remove the global
1340*84e872a0SLloyd Pique *
1341*84e872a0SLloyd Pique * \param global The Wayland global.
1342*84e872a0SLloyd Pique *
1343*84e872a0SLloyd Pique * Broadcast a global remove event to all clients without destroying the
1344*84e872a0SLloyd Pique * global. This function can only be called once per global.
1345*84e872a0SLloyd Pique *
1346*84e872a0SLloyd Pique * wl_global_destroy() removes the global and immediately destroys it. On
1347*84e872a0SLloyd Pique * the other end, this function only removes the global, allowing clients
1348*84e872a0SLloyd Pique * that have not yet received the global remove event to continue to bind to
1349*84e872a0SLloyd Pique * it.
1350*84e872a0SLloyd Pique *
1351*84e872a0SLloyd Pique * This can be used by compositors to mitigate clients being disconnected
1352*84e872a0SLloyd Pique * because a global has been added and removed too quickly. Compositors can call
1353*84e872a0SLloyd Pique * wl_global_remove(), then wait an implementation-defined amount of time, then
1354*84e872a0SLloyd Pique * call wl_global_destroy(). Note that the destruction of a global is still
1355*84e872a0SLloyd Pique * racy, since clients have no way to acknowledge that they received the remove
1356*84e872a0SLloyd Pique * event.
1357*84e872a0SLloyd Pique *
1358*84e872a0SLloyd Pique * \since 1.17.90
1359*84e872a0SLloyd Pique */
1360*84e872a0SLloyd Pique WL_EXPORT void
wl_global_remove(struct wl_global * global)1361*84e872a0SLloyd Pique wl_global_remove(struct wl_global *global)
1362*84e872a0SLloyd Pique {
1363*84e872a0SLloyd Pique struct wl_display *display = global->display;
1364*84e872a0SLloyd Pique struct wl_resource *resource;
1365*84e872a0SLloyd Pique
1366*84e872a0SLloyd Pique if (global->removed)
1367*84e872a0SLloyd Pique wl_abort("wl_global_remove: called twice on the same "
1368*84e872a0SLloyd Pique "global '%s@%"PRIu32"'", global->interface->name,
1369*84e872a0SLloyd Pique global->name);
1370*84e872a0SLloyd Pique
1371*84e872a0SLloyd Pique wl_list_for_each(resource, &display->registry_resource_list, link)
1372*84e872a0SLloyd Pique if (wl_global_is_visible(resource->client, global))
1373*84e872a0SLloyd Pique wl_resource_post_event(resource, WL_REGISTRY_GLOBAL_REMOVE,
1374*84e872a0SLloyd Pique global->name);
1375*84e872a0SLloyd Pique
1376*84e872a0SLloyd Pique global->removed = true;
1377*84e872a0SLloyd Pique }
1378*84e872a0SLloyd Pique
1379*84e872a0SLloyd Pique WL_EXPORT void
wl_global_destroy(struct wl_global * global)1380*84e872a0SLloyd Pique wl_global_destroy(struct wl_global *global)
1381*84e872a0SLloyd Pique {
1382*84e872a0SLloyd Pique if (!global->removed)
1383*84e872a0SLloyd Pique wl_global_remove(global);
1384*84e872a0SLloyd Pique wl_list_remove(&global->link);
1385*84e872a0SLloyd Pique free(global);
1386*84e872a0SLloyd Pique }
1387*84e872a0SLloyd Pique
1388*84e872a0SLloyd Pique WL_EXPORT const struct wl_interface *
wl_global_get_interface(const struct wl_global * global)1389*84e872a0SLloyd Pique wl_global_get_interface(const struct wl_global *global)
1390*84e872a0SLloyd Pique {
1391*84e872a0SLloyd Pique return global->interface;
1392*84e872a0SLloyd Pique }
1393*84e872a0SLloyd Pique
1394*84e872a0SLloyd Pique /** Get the name of the global.
1395*84e872a0SLloyd Pique *
1396*84e872a0SLloyd Pique * \param global The global object.
1397*84e872a0SLloyd Pique * \param client Client for which to look up the global.
1398*84e872a0SLloyd Pique * \return The name of the global, or 0 if the global is not visible to the
1399*84e872a0SLloyd Pique * client.
1400*84e872a0SLloyd Pique *
1401*84e872a0SLloyd Pique * \memberof wl_global
1402*84e872a0SLloyd Pique * \since 1.22
1403*84e872a0SLloyd Pique */
1404*84e872a0SLloyd Pique WL_EXPORT uint32_t
wl_global_get_name(const struct wl_global * global,const struct wl_client * client)1405*84e872a0SLloyd Pique wl_global_get_name(const struct wl_global *global,
1406*84e872a0SLloyd Pique const struct wl_client *client)
1407*84e872a0SLloyd Pique {
1408*84e872a0SLloyd Pique return wl_global_is_visible(client, global) ? global->name : 0;
1409*84e872a0SLloyd Pique }
1410*84e872a0SLloyd Pique
1411*84e872a0SLloyd Pique /** Get the version of the given global.
1412*84e872a0SLloyd Pique *
1413*84e872a0SLloyd Pique * \param global The global object.
1414*84e872a0SLloyd Pique * \return The version advertised by the global.
1415*84e872a0SLloyd Pique *
1416*84e872a0SLloyd Pique * \memberof wl_global
1417*84e872a0SLloyd Pique * \since 1.21
1418*84e872a0SLloyd Pique */
1419*84e872a0SLloyd Pique WL_EXPORT uint32_t
wl_global_get_version(const struct wl_global * global)1420*84e872a0SLloyd Pique wl_global_get_version(const struct wl_global *global)
1421*84e872a0SLloyd Pique {
1422*84e872a0SLloyd Pique return global->version;
1423*84e872a0SLloyd Pique }
1424*84e872a0SLloyd Pique
1425*84e872a0SLloyd Pique /** Get the display object for the given global
1426*84e872a0SLloyd Pique *
1427*84e872a0SLloyd Pique * \param global The global object
1428*84e872a0SLloyd Pique * \return The display object the global is associated with.
1429*84e872a0SLloyd Pique *
1430*84e872a0SLloyd Pique * \memberof wl_global
1431*84e872a0SLloyd Pique * \since 1.20
1432*84e872a0SLloyd Pique */
1433*84e872a0SLloyd Pique WL_EXPORT struct wl_display *
wl_global_get_display(const struct wl_global * global)1434*84e872a0SLloyd Pique wl_global_get_display(const struct wl_global *global)
1435*84e872a0SLloyd Pique {
1436*84e872a0SLloyd Pique return global->display;
1437*84e872a0SLloyd Pique }
1438*84e872a0SLloyd Pique
1439*84e872a0SLloyd Pique WL_EXPORT void *
wl_global_get_user_data(const struct wl_global * global)1440*84e872a0SLloyd Pique wl_global_get_user_data(const struct wl_global *global)
1441*84e872a0SLloyd Pique {
1442*84e872a0SLloyd Pique return global->data;
1443*84e872a0SLloyd Pique }
1444*84e872a0SLloyd Pique
1445*84e872a0SLloyd Pique /** Set the global's user data
1446*84e872a0SLloyd Pique *
1447*84e872a0SLloyd Pique * \param global The global object
1448*84e872a0SLloyd Pique * \param data The user data pointer
1449*84e872a0SLloyd Pique *
1450*84e872a0SLloyd Pique * \since 1.17.90
1451*84e872a0SLloyd Pique */
1452*84e872a0SLloyd Pique WL_EXPORT void
wl_global_set_user_data(struct wl_global * global,void * data)1453*84e872a0SLloyd Pique wl_global_set_user_data(struct wl_global *global, void *data)
1454*84e872a0SLloyd Pique {
1455*84e872a0SLloyd Pique global->data = data;
1456*84e872a0SLloyd Pique }
1457*84e872a0SLloyd Pique
1458*84e872a0SLloyd Pique /** Get the current serial number
1459*84e872a0SLloyd Pique *
1460*84e872a0SLloyd Pique * \param display The display object
1461*84e872a0SLloyd Pique *
1462*84e872a0SLloyd Pique * This function returns the most recent serial number, but does not
1463*84e872a0SLloyd Pique * increment it.
1464*84e872a0SLloyd Pique *
1465*84e872a0SLloyd Pique * \memberof wl_display
1466*84e872a0SLloyd Pique */
1467*84e872a0SLloyd Pique WL_EXPORT uint32_t
wl_display_get_serial(struct wl_display * display)1468*84e872a0SLloyd Pique wl_display_get_serial(struct wl_display *display)
1469*84e872a0SLloyd Pique {
1470*84e872a0SLloyd Pique return display->serial;
1471*84e872a0SLloyd Pique }
1472*84e872a0SLloyd Pique
1473*84e872a0SLloyd Pique /** Get the next serial number
1474*84e872a0SLloyd Pique *
1475*84e872a0SLloyd Pique * \param display The display object
1476*84e872a0SLloyd Pique *
1477*84e872a0SLloyd Pique * This function increments the display serial number and returns the
1478*84e872a0SLloyd Pique * new value.
1479*84e872a0SLloyd Pique *
1480*84e872a0SLloyd Pique * \memberof wl_display
1481*84e872a0SLloyd Pique */
1482*84e872a0SLloyd Pique WL_EXPORT uint32_t
wl_display_next_serial(struct wl_display * display)1483*84e872a0SLloyd Pique wl_display_next_serial(struct wl_display *display)
1484*84e872a0SLloyd Pique {
1485*84e872a0SLloyd Pique display->serial++;
1486*84e872a0SLloyd Pique
1487*84e872a0SLloyd Pique return display->serial;
1488*84e872a0SLloyd Pique }
1489*84e872a0SLloyd Pique
1490*84e872a0SLloyd Pique WL_EXPORT struct wl_event_loop *
wl_display_get_event_loop(struct wl_display * display)1491*84e872a0SLloyd Pique wl_display_get_event_loop(struct wl_display *display)
1492*84e872a0SLloyd Pique {
1493*84e872a0SLloyd Pique return display->loop;
1494*84e872a0SLloyd Pique }
1495*84e872a0SLloyd Pique
1496*84e872a0SLloyd Pique WL_EXPORT void
wl_display_terminate(struct wl_display * display)1497*84e872a0SLloyd Pique wl_display_terminate(struct wl_display *display)
1498*84e872a0SLloyd Pique {
1499*84e872a0SLloyd Pique int ret;
1500*84e872a0SLloyd Pique uint64_t terminate = 1;
1501*84e872a0SLloyd Pique
1502*84e872a0SLloyd Pique display->run = 0;
1503*84e872a0SLloyd Pique
1504*84e872a0SLloyd Pique ret = write(display->terminate_efd, &terminate, sizeof(terminate));
1505*84e872a0SLloyd Pique assert (ret >= 0 || errno == EAGAIN);
1506*84e872a0SLloyd Pique }
1507*84e872a0SLloyd Pique
1508*84e872a0SLloyd Pique WL_EXPORT void
wl_display_run(struct wl_display * display)1509*84e872a0SLloyd Pique wl_display_run(struct wl_display *display)
1510*84e872a0SLloyd Pique {
1511*84e872a0SLloyd Pique display->run = 1;
1512*84e872a0SLloyd Pique
1513*84e872a0SLloyd Pique while (display->run) {
1514*84e872a0SLloyd Pique wl_display_flush_clients(display);
1515*84e872a0SLloyd Pique wl_event_loop_dispatch(display->loop, -1);
1516*84e872a0SLloyd Pique }
1517*84e872a0SLloyd Pique }
1518*84e872a0SLloyd Pique
1519*84e872a0SLloyd Pique WL_EXPORT void
wl_display_flush_clients(struct wl_display * display)1520*84e872a0SLloyd Pique wl_display_flush_clients(struct wl_display *display)
1521*84e872a0SLloyd Pique {
1522*84e872a0SLloyd Pique struct wl_client *client, *next;
1523*84e872a0SLloyd Pique int ret;
1524*84e872a0SLloyd Pique
1525*84e872a0SLloyd Pique wl_list_for_each_safe(client, next, &display->client_list, link) {
1526*84e872a0SLloyd Pique ret = wl_connection_flush(client->connection);
1527*84e872a0SLloyd Pique if (ret < 0 && errno == EAGAIN) {
1528*84e872a0SLloyd Pique wl_event_source_fd_update(client->source,
1529*84e872a0SLloyd Pique WL_EVENT_WRITABLE |
1530*84e872a0SLloyd Pique WL_EVENT_READABLE);
1531*84e872a0SLloyd Pique } else if (ret < 0) {
1532*84e872a0SLloyd Pique wl_client_destroy(client);
1533*84e872a0SLloyd Pique }
1534*84e872a0SLloyd Pique }
1535*84e872a0SLloyd Pique }
1536*84e872a0SLloyd Pique
1537*84e872a0SLloyd Pique /** Destroy all clients connected to the display
1538*84e872a0SLloyd Pique *
1539*84e872a0SLloyd Pique * \param display The display object
1540*84e872a0SLloyd Pique *
1541*84e872a0SLloyd Pique * This function should be called right before wl_display_destroy() to ensure
1542*84e872a0SLloyd Pique * all client resources are closed properly. Destroying a client from within
1543*84e872a0SLloyd Pique * wl_display_destroy_clients() is safe, but creating one will leak resources
1544*84e872a0SLloyd Pique * and raise a warning.
1545*84e872a0SLloyd Pique *
1546*84e872a0SLloyd Pique * \memberof wl_display
1547*84e872a0SLloyd Pique */
1548*84e872a0SLloyd Pique WL_EXPORT void
wl_display_destroy_clients(struct wl_display * display)1549*84e872a0SLloyd Pique wl_display_destroy_clients(struct wl_display *display)
1550*84e872a0SLloyd Pique {
1551*84e872a0SLloyd Pique struct wl_list tmp_client_list, *pos;
1552*84e872a0SLloyd Pique struct wl_client *client;
1553*84e872a0SLloyd Pique
1554*84e872a0SLloyd Pique /* Move the whole client list to a temporary head because some new clients
1555*84e872a0SLloyd Pique * might be added to the original head. */
1556*84e872a0SLloyd Pique wl_list_init(&tmp_client_list);
1557*84e872a0SLloyd Pique wl_list_insert_list(&tmp_client_list, &display->client_list);
1558*84e872a0SLloyd Pique wl_list_init(&display->client_list);
1559*84e872a0SLloyd Pique
1560*84e872a0SLloyd Pique /* wl_list_for_each_safe isn't enough here: it fails if the next client is
1561*84e872a0SLloyd Pique * destroyed by the destroy handler of the current one. */
1562*84e872a0SLloyd Pique while (!wl_list_empty(&tmp_client_list)) {
1563*84e872a0SLloyd Pique pos = tmp_client_list.next;
1564*84e872a0SLloyd Pique client = wl_container_of(pos, client, link);
1565*84e872a0SLloyd Pique
1566*84e872a0SLloyd Pique wl_client_destroy(client);
1567*84e872a0SLloyd Pique }
1568*84e872a0SLloyd Pique
1569*84e872a0SLloyd Pique if (!wl_list_empty(&display->client_list)) {
1570*84e872a0SLloyd Pique wl_log("wl_display_destroy_clients: cannot destroy all clients because "
1571*84e872a0SLloyd Pique "new ones were created by destroy callbacks\n");
1572*84e872a0SLloyd Pique }
1573*84e872a0SLloyd Pique }
1574*84e872a0SLloyd Pique
1575*84e872a0SLloyd Pique static int
socket_data(int fd,uint32_t mask,void * data)1576*84e872a0SLloyd Pique socket_data(int fd, uint32_t mask, void *data)
1577*84e872a0SLloyd Pique {
1578*84e872a0SLloyd Pique struct wl_display *display = data;
1579*84e872a0SLloyd Pique struct sockaddr_un name;
1580*84e872a0SLloyd Pique socklen_t length;
1581*84e872a0SLloyd Pique int client_fd;
1582*84e872a0SLloyd Pique
1583*84e872a0SLloyd Pique length = sizeof name;
1584*84e872a0SLloyd Pique client_fd = wl_os_accept_cloexec(fd, (struct sockaddr *) &name,
1585*84e872a0SLloyd Pique &length);
1586*84e872a0SLloyd Pique if (client_fd < 0)
1587*84e872a0SLloyd Pique wl_log("failed to accept: %s\n", strerror(errno));
1588*84e872a0SLloyd Pique else
1589*84e872a0SLloyd Pique if (!wl_client_create(display, client_fd))
1590*84e872a0SLloyd Pique close(client_fd);
1591*84e872a0SLloyd Pique
1592*84e872a0SLloyd Pique return 1;
1593*84e872a0SLloyd Pique }
1594*84e872a0SLloyd Pique
1595*84e872a0SLloyd Pique static int
wl_socket_lock(struct wl_socket * socket)1596*84e872a0SLloyd Pique wl_socket_lock(struct wl_socket *socket)
1597*84e872a0SLloyd Pique {
1598*84e872a0SLloyd Pique struct stat socket_stat;
1599*84e872a0SLloyd Pique
1600*84e872a0SLloyd Pique snprintf(socket->lock_addr, sizeof socket->lock_addr,
1601*84e872a0SLloyd Pique "%s%s", socket->addr.sun_path, LOCK_SUFFIX);
1602*84e872a0SLloyd Pique
1603*84e872a0SLloyd Pique socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC | O_RDWR,
1604*84e872a0SLloyd Pique (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
1605*84e872a0SLloyd Pique
1606*84e872a0SLloyd Pique if (socket->fd_lock < 0) {
1607*84e872a0SLloyd Pique wl_log("unable to open lockfile %s check permissions\n",
1608*84e872a0SLloyd Pique socket->lock_addr);
1609*84e872a0SLloyd Pique goto err;
1610*84e872a0SLloyd Pique }
1611*84e872a0SLloyd Pique
1612*84e872a0SLloyd Pique if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) {
1613*84e872a0SLloyd Pique wl_log("unable to lock lockfile %s, maybe another compositor is running\n",
1614*84e872a0SLloyd Pique socket->lock_addr);
1615*84e872a0SLloyd Pique goto err_fd;
1616*84e872a0SLloyd Pique }
1617*84e872a0SLloyd Pique
1618*84e872a0SLloyd Pique if (lstat(socket->addr.sun_path, &socket_stat) < 0 ) {
1619*84e872a0SLloyd Pique if (errno != ENOENT) {
1620*84e872a0SLloyd Pique wl_log("did not manage to stat file %s\n",
1621*84e872a0SLloyd Pique socket->addr.sun_path);
1622*84e872a0SLloyd Pique goto err_fd;
1623*84e872a0SLloyd Pique }
1624*84e872a0SLloyd Pique } else if (socket_stat.st_mode & S_IWUSR ||
1625*84e872a0SLloyd Pique socket_stat.st_mode & S_IWGRP) {
1626*84e872a0SLloyd Pique unlink(socket->addr.sun_path);
1627*84e872a0SLloyd Pique }
1628*84e872a0SLloyd Pique
1629*84e872a0SLloyd Pique return 0;
1630*84e872a0SLloyd Pique err_fd:
1631*84e872a0SLloyd Pique close(socket->fd_lock);
1632*84e872a0SLloyd Pique socket->fd_lock = -1;
1633*84e872a0SLloyd Pique err:
1634*84e872a0SLloyd Pique *socket->lock_addr = 0;
1635*84e872a0SLloyd Pique /* we did not set this value here, but without lock the
1636*84e872a0SLloyd Pique * socket won't be created anyway. This prevents the
1637*84e872a0SLloyd Pique * wl_socket_destroy from unlinking already existing socket
1638*84e872a0SLloyd Pique * created by other compositor */
1639*84e872a0SLloyd Pique *socket->addr.sun_path = 0;
1640*84e872a0SLloyd Pique
1641*84e872a0SLloyd Pique return -1;
1642*84e872a0SLloyd Pique }
1643*84e872a0SLloyd Pique
1644*84e872a0SLloyd Pique static int
wl_socket_init_for_display_name(struct wl_socket * s,const char * name)1645*84e872a0SLloyd Pique wl_socket_init_for_display_name(struct wl_socket *s, const char *name)
1646*84e872a0SLloyd Pique {
1647*84e872a0SLloyd Pique int name_size;
1648*84e872a0SLloyd Pique const char *runtime_dir = "";
1649*84e872a0SLloyd Pique const char *separator = "";
1650*84e872a0SLloyd Pique
1651*84e872a0SLloyd Pique if (name[0] != '/') {
1652*84e872a0SLloyd Pique runtime_dir = getenv("XDG_RUNTIME_DIR");
1653*84e872a0SLloyd Pique if (!runtime_dir || runtime_dir[0] != '/') {
1654*84e872a0SLloyd Pique wl_log("error: XDG_RUNTIME_DIR is invalid or not set in"
1655*84e872a0SLloyd Pique " the environment\n");
1656*84e872a0SLloyd Pique
1657*84e872a0SLloyd Pique /* to prevent programs reporting
1658*84e872a0SLloyd Pique * "failed to add socket: Success" */
1659*84e872a0SLloyd Pique errno = ENOENT;
1660*84e872a0SLloyd Pique return -1;
1661*84e872a0SLloyd Pique }
1662*84e872a0SLloyd Pique separator = "/";
1663*84e872a0SLloyd Pique }
1664*84e872a0SLloyd Pique
1665*84e872a0SLloyd Pique s->addr.sun_family = AF_LOCAL;
1666*84e872a0SLloyd Pique name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
1667*84e872a0SLloyd Pique "%s%s%s", runtime_dir, separator, name) + 1;
1668*84e872a0SLloyd Pique
1669*84e872a0SLloyd Pique assert(name_size > 0);
1670*84e872a0SLloyd Pique if (name_size > (int)sizeof s->addr.sun_path) {
1671*84e872a0SLloyd Pique wl_log("error: socket path \"%s%s%s\" plus null terminator"
1672*84e872a0SLloyd Pique " exceeds 108 bytes\n", runtime_dir, separator, name);
1673*84e872a0SLloyd Pique *s->addr.sun_path = 0;
1674*84e872a0SLloyd Pique /* to prevent programs reporting
1675*84e872a0SLloyd Pique * "failed to add socket: Success" */
1676*84e872a0SLloyd Pique errno = ENAMETOOLONG;
1677*84e872a0SLloyd Pique return -1;
1678*84e872a0SLloyd Pique }
1679*84e872a0SLloyd Pique
1680*84e872a0SLloyd Pique s->display_name = (s->addr.sun_path + name_size - 1) - strlen(name);
1681*84e872a0SLloyd Pique
1682*84e872a0SLloyd Pique return 0;
1683*84e872a0SLloyd Pique }
1684*84e872a0SLloyd Pique
1685*84e872a0SLloyd Pique static int
_wl_display_add_socket(struct wl_display * display,struct wl_socket * s)1686*84e872a0SLloyd Pique _wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
1687*84e872a0SLloyd Pique {
1688*84e872a0SLloyd Pique socklen_t size;
1689*84e872a0SLloyd Pique
1690*84e872a0SLloyd Pique s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
1691*84e872a0SLloyd Pique if (s->fd < 0) {
1692*84e872a0SLloyd Pique return -1;
1693*84e872a0SLloyd Pique }
1694*84e872a0SLloyd Pique
1695*84e872a0SLloyd Pique size = offsetof (struct sockaddr_un, sun_path) + strlen(s->addr.sun_path);
1696*84e872a0SLloyd Pique if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
1697*84e872a0SLloyd Pique wl_log("bind() failed with error: %s\n", strerror(errno));
1698*84e872a0SLloyd Pique return -1;
1699*84e872a0SLloyd Pique }
1700*84e872a0SLloyd Pique
1701*84e872a0SLloyd Pique if (listen(s->fd, 128) < 0) {
1702*84e872a0SLloyd Pique wl_log("listen() failed with error: %s\n", strerror(errno));
1703*84e872a0SLloyd Pique return -1;
1704*84e872a0SLloyd Pique }
1705*84e872a0SLloyd Pique
1706*84e872a0SLloyd Pique s->source = wl_event_loop_add_fd(display->loop, s->fd,
1707*84e872a0SLloyd Pique WL_EVENT_READABLE,
1708*84e872a0SLloyd Pique socket_data, display);
1709*84e872a0SLloyd Pique if (s->source == NULL) {
1710*84e872a0SLloyd Pique return -1;
1711*84e872a0SLloyd Pique }
1712*84e872a0SLloyd Pique
1713*84e872a0SLloyd Pique wl_list_insert(display->socket_list.prev, &s->link);
1714*84e872a0SLloyd Pique return 0;
1715*84e872a0SLloyd Pique }
1716*84e872a0SLloyd Pique
1717*84e872a0SLloyd Pique WL_EXPORT const char *
wl_display_add_socket_auto(struct wl_display * display)1718*84e872a0SLloyd Pique wl_display_add_socket_auto(struct wl_display *display)
1719*84e872a0SLloyd Pique {
1720*84e872a0SLloyd Pique struct wl_socket *s;
1721*84e872a0SLloyd Pique int displayno = 0;
1722*84e872a0SLloyd Pique char display_name[20] = "";
1723*84e872a0SLloyd Pique
1724*84e872a0SLloyd Pique /* A reasonable number of maximum default sockets. If
1725*84e872a0SLloyd Pique * you need more than this, use the explicit add_socket API. */
1726*84e872a0SLloyd Pique const int MAX_DISPLAYNO = 32;
1727*84e872a0SLloyd Pique
1728*84e872a0SLloyd Pique s = wl_socket_alloc();
1729*84e872a0SLloyd Pique if (s == NULL)
1730*84e872a0SLloyd Pique return NULL;
1731*84e872a0SLloyd Pique
1732*84e872a0SLloyd Pique do {
1733*84e872a0SLloyd Pique snprintf(display_name, sizeof display_name, "wayland-%d", displayno);
1734*84e872a0SLloyd Pique if (wl_socket_init_for_display_name(s, display_name) < 0) {
1735*84e872a0SLloyd Pique wl_socket_destroy(s);
1736*84e872a0SLloyd Pique return NULL;
1737*84e872a0SLloyd Pique }
1738*84e872a0SLloyd Pique
1739*84e872a0SLloyd Pique if (wl_socket_lock(s) < 0)
1740*84e872a0SLloyd Pique continue;
1741*84e872a0SLloyd Pique
1742*84e872a0SLloyd Pique if (_wl_display_add_socket(display, s) < 0) {
1743*84e872a0SLloyd Pique wl_socket_destroy(s);
1744*84e872a0SLloyd Pique return NULL;
1745*84e872a0SLloyd Pique }
1746*84e872a0SLloyd Pique
1747*84e872a0SLloyd Pique return s->display_name;
1748*84e872a0SLloyd Pique } while (displayno++ < MAX_DISPLAYNO);
1749*84e872a0SLloyd Pique
1750*84e872a0SLloyd Pique /* Ran out of display names. */
1751*84e872a0SLloyd Pique wl_socket_destroy(s);
1752*84e872a0SLloyd Pique errno = EINVAL;
1753*84e872a0SLloyd Pique return NULL;
1754*84e872a0SLloyd Pique }
1755*84e872a0SLloyd Pique
1756*84e872a0SLloyd Pique /** Add a socket with an existing fd to Wayland display for the clients to connect.
1757*84e872a0SLloyd Pique *
1758*84e872a0SLloyd Pique * \param display Wayland display to which the socket should be added.
1759*84e872a0SLloyd Pique * \param sock_fd The existing socket file descriptor to be used
1760*84e872a0SLloyd Pique * \return 0 if success. -1 if failed.
1761*84e872a0SLloyd Pique *
1762*84e872a0SLloyd Pique * The existing socket fd must already be created, opened, and locked.
1763*84e872a0SLloyd Pique * The fd must be properly set to CLOEXEC and bound to a socket file
1764*84e872a0SLloyd Pique * with both bind() and listen() already called.
1765*84e872a0SLloyd Pique *
1766*84e872a0SLloyd Pique * \memberof wl_display
1767*84e872a0SLloyd Pique */
1768*84e872a0SLloyd Pique WL_EXPORT int
wl_display_add_socket_fd(struct wl_display * display,int sock_fd)1769*84e872a0SLloyd Pique wl_display_add_socket_fd(struct wl_display *display, int sock_fd)
1770*84e872a0SLloyd Pique {
1771*84e872a0SLloyd Pique struct wl_socket *s;
1772*84e872a0SLloyd Pique struct stat buf;
1773*84e872a0SLloyd Pique
1774*84e872a0SLloyd Pique /* Require a valid fd or fail */
1775*84e872a0SLloyd Pique if (sock_fd < 0 || fstat(sock_fd, &buf) < 0 || !S_ISSOCK(buf.st_mode)) {
1776*84e872a0SLloyd Pique return -1;
1777*84e872a0SLloyd Pique }
1778*84e872a0SLloyd Pique
1779*84e872a0SLloyd Pique s = wl_socket_alloc();
1780*84e872a0SLloyd Pique if (s == NULL)
1781*84e872a0SLloyd Pique return -1;
1782*84e872a0SLloyd Pique
1783*84e872a0SLloyd Pique s->source = wl_event_loop_add_fd(display->loop, sock_fd,
1784*84e872a0SLloyd Pique WL_EVENT_READABLE,
1785*84e872a0SLloyd Pique socket_data, display);
1786*84e872a0SLloyd Pique if (s->source == NULL) {
1787*84e872a0SLloyd Pique wl_log("failed to establish event source\n");
1788*84e872a0SLloyd Pique wl_socket_destroy(s);
1789*84e872a0SLloyd Pique return -1;
1790*84e872a0SLloyd Pique }
1791*84e872a0SLloyd Pique
1792*84e872a0SLloyd Pique /* Reuse the existing fd */
1793*84e872a0SLloyd Pique s->fd = sock_fd;
1794*84e872a0SLloyd Pique
1795*84e872a0SLloyd Pique wl_list_insert(display->socket_list.prev, &s->link);
1796*84e872a0SLloyd Pique
1797*84e872a0SLloyd Pique return 0;
1798*84e872a0SLloyd Pique }
1799*84e872a0SLloyd Pique
1800*84e872a0SLloyd Pique /** Add a socket to Wayland display for the clients to connect.
1801*84e872a0SLloyd Pique *
1802*84e872a0SLloyd Pique * \param display Wayland display to which the socket should be added.
1803*84e872a0SLloyd Pique * \param name Name of the Unix socket.
1804*84e872a0SLloyd Pique * \return 0 if success. -1 if failed.
1805*84e872a0SLloyd Pique *
1806*84e872a0SLloyd Pique * This adds a Unix socket to Wayland display which can be used by clients to
1807*84e872a0SLloyd Pique * connect to Wayland display.
1808*84e872a0SLloyd Pique *
1809*84e872a0SLloyd Pique * If NULL is passed as name, then it would look for WAYLAND_DISPLAY env
1810*84e872a0SLloyd Pique * variable for the socket name. If WAYLAND_DISPLAY is not set, then default
1811*84e872a0SLloyd Pique * wayland-0 is used.
1812*84e872a0SLloyd Pique *
1813*84e872a0SLloyd Pique * If the socket name is a relative path, the Unix socket will be created in
1814*84e872a0SLloyd Pique * the directory pointed to by environment variable XDG_RUNTIME_DIR. If
1815*84e872a0SLloyd Pique * XDG_RUNTIME_DIR is invalid or not set, then this function fails and returns -1.
1816*84e872a0SLloyd Pique *
1817*84e872a0SLloyd Pique * If the socket name is an absolute path, then it is used as-is for the
1818*84e872a0SLloyd Pique * the Unix socket.
1819*84e872a0SLloyd Pique *
1820*84e872a0SLloyd Pique * The length of the computed socket path must not exceed the maximum length
1821*84e872a0SLloyd Pique * of a Unix socket path.
1822*84e872a0SLloyd Pique * The function also fails if the user does not have write permission in the
1823*84e872a0SLloyd Pique * directory or if the path is already in use.
1824*84e872a0SLloyd Pique *
1825*84e872a0SLloyd Pique * \memberof wl_display
1826*84e872a0SLloyd Pique */
1827*84e872a0SLloyd Pique WL_EXPORT int
wl_display_add_socket(struct wl_display * display,const char * name)1828*84e872a0SLloyd Pique wl_display_add_socket(struct wl_display *display, const char *name)
1829*84e872a0SLloyd Pique {
1830*84e872a0SLloyd Pique struct wl_socket *s;
1831*84e872a0SLloyd Pique
1832*84e872a0SLloyd Pique s = wl_socket_alloc();
1833*84e872a0SLloyd Pique if (s == NULL)
1834*84e872a0SLloyd Pique return -1;
1835*84e872a0SLloyd Pique
1836*84e872a0SLloyd Pique if (name == NULL)
1837*84e872a0SLloyd Pique name = getenv("WAYLAND_DISPLAY");
1838*84e872a0SLloyd Pique if (name == NULL)
1839*84e872a0SLloyd Pique name = "wayland-0";
1840*84e872a0SLloyd Pique
1841*84e872a0SLloyd Pique if (wl_socket_init_for_display_name(s, name) < 0) {
1842*84e872a0SLloyd Pique wl_socket_destroy(s);
1843*84e872a0SLloyd Pique return -1;
1844*84e872a0SLloyd Pique }
1845*84e872a0SLloyd Pique
1846*84e872a0SLloyd Pique if (wl_socket_lock(s) < 0) {
1847*84e872a0SLloyd Pique wl_socket_destroy(s);
1848*84e872a0SLloyd Pique return -1;
1849*84e872a0SLloyd Pique }
1850*84e872a0SLloyd Pique
1851*84e872a0SLloyd Pique if (_wl_display_add_socket(display, s) < 0) {
1852*84e872a0SLloyd Pique wl_socket_destroy(s);
1853*84e872a0SLloyd Pique return -1;
1854*84e872a0SLloyd Pique }
1855*84e872a0SLloyd Pique
1856*84e872a0SLloyd Pique return 0;
1857*84e872a0SLloyd Pique }
1858*84e872a0SLloyd Pique
1859*84e872a0SLloyd Pique WL_EXPORT void
wl_display_add_destroy_listener(struct wl_display * display,struct wl_listener * listener)1860*84e872a0SLloyd Pique wl_display_add_destroy_listener(struct wl_display *display,
1861*84e872a0SLloyd Pique struct wl_listener *listener)
1862*84e872a0SLloyd Pique {
1863*84e872a0SLloyd Pique wl_priv_signal_add(&display->destroy_signal, listener);
1864*84e872a0SLloyd Pique }
1865*84e872a0SLloyd Pique
1866*84e872a0SLloyd Pique /** Registers a listener for the client connection signal.
1867*84e872a0SLloyd Pique * When a new client object is created, \a listener will be notified, carrying
1868*84e872a0SLloyd Pique * a pointer to the new wl_client object.
1869*84e872a0SLloyd Pique *
1870*84e872a0SLloyd Pique * \ref wl_client_create
1871*84e872a0SLloyd Pique * \ref wl_display
1872*84e872a0SLloyd Pique * \ref wl_listener
1873*84e872a0SLloyd Pique *
1874*84e872a0SLloyd Pique * \param display The display object
1875*84e872a0SLloyd Pique * \param listener Signal handler object
1876*84e872a0SLloyd Pique */
1877*84e872a0SLloyd Pique WL_EXPORT void
wl_display_add_client_created_listener(struct wl_display * display,struct wl_listener * listener)1878*84e872a0SLloyd Pique wl_display_add_client_created_listener(struct wl_display *display,
1879*84e872a0SLloyd Pique struct wl_listener *listener)
1880*84e872a0SLloyd Pique {
1881*84e872a0SLloyd Pique wl_priv_signal_add(&display->create_client_signal, listener);
1882*84e872a0SLloyd Pique }
1883*84e872a0SLloyd Pique
1884*84e872a0SLloyd Pique WL_EXPORT struct wl_listener *
wl_display_get_destroy_listener(struct wl_display * display,wl_notify_func_t notify)1885*84e872a0SLloyd Pique wl_display_get_destroy_listener(struct wl_display *display,
1886*84e872a0SLloyd Pique wl_notify_func_t notify)
1887*84e872a0SLloyd Pique {
1888*84e872a0SLloyd Pique return wl_priv_signal_get(&display->destroy_signal, notify);
1889*84e872a0SLloyd Pique }
1890*84e872a0SLloyd Pique
1891*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_set_implementation(struct wl_resource * resource,const void * implementation,void * data,wl_resource_destroy_func_t destroy)1892*84e872a0SLloyd Pique wl_resource_set_implementation(struct wl_resource *resource,
1893*84e872a0SLloyd Pique const void *implementation,
1894*84e872a0SLloyd Pique void *data, wl_resource_destroy_func_t destroy)
1895*84e872a0SLloyd Pique {
1896*84e872a0SLloyd Pique resource->object.implementation = implementation;
1897*84e872a0SLloyd Pique resource->data = data;
1898*84e872a0SLloyd Pique resource->destroy = destroy;
1899*84e872a0SLloyd Pique resource->dispatcher = NULL;
1900*84e872a0SLloyd Pique }
1901*84e872a0SLloyd Pique
1902*84e872a0SLloyd Pique WL_EXPORT void
wl_resource_set_dispatcher(struct wl_resource * resource,wl_dispatcher_func_t dispatcher,const void * implementation,void * data,wl_resource_destroy_func_t destroy)1903*84e872a0SLloyd Pique wl_resource_set_dispatcher(struct wl_resource *resource,
1904*84e872a0SLloyd Pique wl_dispatcher_func_t dispatcher,
1905*84e872a0SLloyd Pique const void *implementation,
1906*84e872a0SLloyd Pique void *data, wl_resource_destroy_func_t destroy)
1907*84e872a0SLloyd Pique {
1908*84e872a0SLloyd Pique resource->dispatcher = dispatcher;
1909*84e872a0SLloyd Pique resource->object.implementation = implementation;
1910*84e872a0SLloyd Pique resource->data = data;
1911*84e872a0SLloyd Pique resource->destroy = destroy;
1912*84e872a0SLloyd Pique }
1913*84e872a0SLloyd Pique
1914*84e872a0SLloyd Pique /** Create a new resource object
1915*84e872a0SLloyd Pique *
1916*84e872a0SLloyd Pique * \param client The client owner of the new resource.
1917*84e872a0SLloyd Pique * \param interface The interface of the new resource.
1918*84e872a0SLloyd Pique * \param version The version of the new resource.
1919*84e872a0SLloyd Pique * \param id The id of the new resource. If 0, an available id will be used.
1920*84e872a0SLloyd Pique *
1921*84e872a0SLloyd Pique * Listeners added with \a wl_client_add_resource_created_listener will be
1922*84e872a0SLloyd Pique * notified at the end of this function.
1923*84e872a0SLloyd Pique *
1924*84e872a0SLloyd Pique * \memberof wl_resource
1925*84e872a0SLloyd Pique */
1926*84e872a0SLloyd Pique WL_EXPORT struct wl_resource *
wl_resource_create(struct wl_client * client,const struct wl_interface * interface,int version,uint32_t id)1927*84e872a0SLloyd Pique wl_resource_create(struct wl_client *client,
1928*84e872a0SLloyd Pique const struct wl_interface *interface,
1929*84e872a0SLloyd Pique int version, uint32_t id)
1930*84e872a0SLloyd Pique {
1931*84e872a0SLloyd Pique struct wl_resource *resource;
1932*84e872a0SLloyd Pique
1933*84e872a0SLloyd Pique resource = zalloc(sizeof *resource);
1934*84e872a0SLloyd Pique if (resource == NULL)
1935*84e872a0SLloyd Pique return NULL;
1936*84e872a0SLloyd Pique
1937*84e872a0SLloyd Pique if (id == 0) {
1938*84e872a0SLloyd Pique id = wl_map_insert_new(&client->objects, 0, NULL);
1939*84e872a0SLloyd Pique if (id == 0) {
1940*84e872a0SLloyd Pique free(resource);
1941*84e872a0SLloyd Pique return NULL;
1942*84e872a0SLloyd Pique }
1943*84e872a0SLloyd Pique }
1944*84e872a0SLloyd Pique
1945*84e872a0SLloyd Pique resource->object.id = id;
1946*84e872a0SLloyd Pique resource->object.interface = interface;
1947*84e872a0SLloyd Pique resource->object.implementation = NULL;
1948*84e872a0SLloyd Pique
1949*84e872a0SLloyd Pique wl_signal_init(&resource->deprecated_destroy_signal);
1950*84e872a0SLloyd Pique wl_priv_signal_init(&resource->destroy_signal);
1951*84e872a0SLloyd Pique
1952*84e872a0SLloyd Pique resource->destroy = NULL;
1953*84e872a0SLloyd Pique resource->client = client;
1954*84e872a0SLloyd Pique resource->data = NULL;
1955*84e872a0SLloyd Pique resource->version = version;
1956*84e872a0SLloyd Pique resource->dispatcher = NULL;
1957*84e872a0SLloyd Pique
1958*84e872a0SLloyd Pique if (wl_map_insert_at(&client->objects, 0, id, resource) < 0) {
1959*84e872a0SLloyd Pique if (errno == EINVAL) {
1960*84e872a0SLloyd Pique wl_resource_post_error(client->display_resource,
1961*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
1962*84e872a0SLloyd Pique "invalid new id %d", id);
1963*84e872a0SLloyd Pique }
1964*84e872a0SLloyd Pique free(resource);
1965*84e872a0SLloyd Pique return NULL;
1966*84e872a0SLloyd Pique }
1967*84e872a0SLloyd Pique
1968*84e872a0SLloyd Pique wl_priv_signal_emit(&client->resource_created_signal, resource);
1969*84e872a0SLloyd Pique return resource;
1970*84e872a0SLloyd Pique }
1971*84e872a0SLloyd Pique
1972*84e872a0SLloyd Pique WL_EXPORT void
wl_log_set_handler_server(wl_log_func_t handler)1973*84e872a0SLloyd Pique wl_log_set_handler_server(wl_log_func_t handler)
1974*84e872a0SLloyd Pique {
1975*84e872a0SLloyd Pique wl_log_handler = handler;
1976*84e872a0SLloyd Pique }
1977*84e872a0SLloyd Pique
1978*84e872a0SLloyd Pique /** Adds a new protocol logger.
1979*84e872a0SLloyd Pique *
1980*84e872a0SLloyd Pique * When a new protocol message arrives or is sent from the server
1981*84e872a0SLloyd Pique * all the protocol logger functions will be called, carrying the
1982*84e872a0SLloyd Pique * \a user_data pointer, the type of the message (request or
1983*84e872a0SLloyd Pique * event) and the actual message.
1984*84e872a0SLloyd Pique * The lifetime of the messages passed to the logger function ends
1985*84e872a0SLloyd Pique * when they return so the messages cannot be stored and accessed
1986*84e872a0SLloyd Pique * later.
1987*84e872a0SLloyd Pique *
1988*84e872a0SLloyd Pique * \a errno is set on error.
1989*84e872a0SLloyd Pique *
1990*84e872a0SLloyd Pique * \param display The display object
1991*84e872a0SLloyd Pique * \param func The function to call to log a new protocol message
1992*84e872a0SLloyd Pique * \param user_data The user data pointer to pass to \a func
1993*84e872a0SLloyd Pique *
1994*84e872a0SLloyd Pique * \return The protol logger object on success, NULL on failure.
1995*84e872a0SLloyd Pique *
1996*84e872a0SLloyd Pique * \sa wl_protocol_logger_destroy
1997*84e872a0SLloyd Pique *
1998*84e872a0SLloyd Pique * \memberof wl_display
1999*84e872a0SLloyd Pique */
2000*84e872a0SLloyd Pique WL_EXPORT struct wl_protocol_logger *
wl_display_add_protocol_logger(struct wl_display * display,wl_protocol_logger_func_t func,void * user_data)2001*84e872a0SLloyd Pique wl_display_add_protocol_logger(struct wl_display *display,
2002*84e872a0SLloyd Pique wl_protocol_logger_func_t func, void *user_data)
2003*84e872a0SLloyd Pique {
2004*84e872a0SLloyd Pique struct wl_protocol_logger *logger;
2005*84e872a0SLloyd Pique
2006*84e872a0SLloyd Pique logger = zalloc(sizeof *logger);
2007*84e872a0SLloyd Pique if (!logger)
2008*84e872a0SLloyd Pique return NULL;
2009*84e872a0SLloyd Pique
2010*84e872a0SLloyd Pique logger->func = func;
2011*84e872a0SLloyd Pique logger->user_data = user_data;
2012*84e872a0SLloyd Pique wl_list_insert(&display->protocol_loggers, &logger->link);
2013*84e872a0SLloyd Pique
2014*84e872a0SLloyd Pique return logger;
2015*84e872a0SLloyd Pique }
2016*84e872a0SLloyd Pique
2017*84e872a0SLloyd Pique /** Destroys a protocol logger.
2018*84e872a0SLloyd Pique *
2019*84e872a0SLloyd Pique * This function destroys a protocol logger and removes it from the display
2020*84e872a0SLloyd Pique * it was added to with \a wl_display_add_protocol_logger.
2021*84e872a0SLloyd Pique * The \a logger object becomes invalid after calling this function.
2022*84e872a0SLloyd Pique *
2023*84e872a0SLloyd Pique * \sa wl_display_add_protocol_logger
2024*84e872a0SLloyd Pique *
2025*84e872a0SLloyd Pique * \memberof wl_protocol_logger
2026*84e872a0SLloyd Pique */
2027*84e872a0SLloyd Pique WL_EXPORT void
wl_protocol_logger_destroy(struct wl_protocol_logger * logger)2028*84e872a0SLloyd Pique wl_protocol_logger_destroy(struct wl_protocol_logger *logger)
2029*84e872a0SLloyd Pique {
2030*84e872a0SLloyd Pique wl_list_remove(&logger->link);
2031*84e872a0SLloyd Pique free(logger);
2032*84e872a0SLloyd Pique }
2033*84e872a0SLloyd Pique
2034*84e872a0SLloyd Pique /** Add support for a wl_shm pixel format
2035*84e872a0SLloyd Pique *
2036*84e872a0SLloyd Pique * \param display The display object
2037*84e872a0SLloyd Pique * \param format The wl_shm pixel format to advertise
2038*84e872a0SLloyd Pique * \return A pointer to the wl_shm format that was added to the list
2039*84e872a0SLloyd Pique * or NULL if adding it to the list failed.
2040*84e872a0SLloyd Pique *
2041*84e872a0SLloyd Pique * Add the specified wl_shm format to the list of formats the wl_shm
2042*84e872a0SLloyd Pique * object advertises when a client binds to it. Adding a format to
2043*84e872a0SLloyd Pique * the list means that clients will know that the compositor supports
2044*84e872a0SLloyd Pique * this format and may use it for creating wl_shm buffers. The
2045*84e872a0SLloyd Pique * compositor must be able to handle the pixel format when a client
2046*84e872a0SLloyd Pique * requests it.
2047*84e872a0SLloyd Pique *
2048*84e872a0SLloyd Pique * The compositor by default supports WL_SHM_FORMAT_ARGB8888 and
2049*84e872a0SLloyd Pique * WL_SHM_FORMAT_XRGB8888.
2050*84e872a0SLloyd Pique *
2051*84e872a0SLloyd Pique * \memberof wl_display
2052*84e872a0SLloyd Pique */
2053*84e872a0SLloyd Pique WL_EXPORT uint32_t *
wl_display_add_shm_format(struct wl_display * display,uint32_t format)2054*84e872a0SLloyd Pique wl_display_add_shm_format(struct wl_display *display, uint32_t format)
2055*84e872a0SLloyd Pique {
2056*84e872a0SLloyd Pique uint32_t *p = NULL;
2057*84e872a0SLloyd Pique
2058*84e872a0SLloyd Pique p = wl_array_add(&display->additional_shm_formats, sizeof *p);
2059*84e872a0SLloyd Pique
2060*84e872a0SLloyd Pique if (p != NULL)
2061*84e872a0SLloyd Pique *p = format;
2062*84e872a0SLloyd Pique return p;
2063*84e872a0SLloyd Pique }
2064*84e872a0SLloyd Pique
2065*84e872a0SLloyd Pique /**
2066*84e872a0SLloyd Pique * Get list of additional wl_shm pixel formats
2067*84e872a0SLloyd Pique *
2068*84e872a0SLloyd Pique * \param display The display object
2069*84e872a0SLloyd Pique *
2070*84e872a0SLloyd Pique * This function returns the list of addition wl_shm pixel formats
2071*84e872a0SLloyd Pique * that the compositor supports. WL_SHM_FORMAT_ARGB8888 and
2072*84e872a0SLloyd Pique * WL_SHM_FORMAT_XRGB8888 are always supported and not included in the
2073*84e872a0SLloyd Pique * array, but all formats added through wl_display_add_shm_format()
2074*84e872a0SLloyd Pique * will be in the array.
2075*84e872a0SLloyd Pique *
2076*84e872a0SLloyd Pique * \sa wl_display_add_shm_format()
2077*84e872a0SLloyd Pique *
2078*84e872a0SLloyd Pique * \private
2079*84e872a0SLloyd Pique *
2080*84e872a0SLloyd Pique * \memberof wl_display
2081*84e872a0SLloyd Pique */
2082*84e872a0SLloyd Pique struct wl_array *
wl_display_get_additional_shm_formats(struct wl_display * display)2083*84e872a0SLloyd Pique wl_display_get_additional_shm_formats(struct wl_display *display)
2084*84e872a0SLloyd Pique {
2085*84e872a0SLloyd Pique return &display->additional_shm_formats;
2086*84e872a0SLloyd Pique }
2087*84e872a0SLloyd Pique
2088*84e872a0SLloyd Pique /** Get the list of currently connected clients
2089*84e872a0SLloyd Pique *
2090*84e872a0SLloyd Pique * \param display The display object
2091*84e872a0SLloyd Pique *
2092*84e872a0SLloyd Pique * This function returns a pointer to the list of clients currently
2093*84e872a0SLloyd Pique * connected to the display. You can iterate on the list by using
2094*84e872a0SLloyd Pique * the \a wl_client_for_each macro.
2095*84e872a0SLloyd Pique * The returned value is valid for the lifetime of the \a display.
2096*84e872a0SLloyd Pique * You must not modify the returned list, but only access it.
2097*84e872a0SLloyd Pique *
2098*84e872a0SLloyd Pique * \sa wl_client_for_each()
2099*84e872a0SLloyd Pique * \sa wl_client_get_link()
2100*84e872a0SLloyd Pique * \sa wl_client_from_link()
2101*84e872a0SLloyd Pique *
2102*84e872a0SLloyd Pique * \memberof wl_display
2103*84e872a0SLloyd Pique */
2104*84e872a0SLloyd Pique WL_EXPORT struct wl_list *
wl_display_get_client_list(struct wl_display * display)2105*84e872a0SLloyd Pique wl_display_get_client_list(struct wl_display *display)
2106*84e872a0SLloyd Pique {
2107*84e872a0SLloyd Pique return &display->client_list;
2108*84e872a0SLloyd Pique }
2109*84e872a0SLloyd Pique
2110*84e872a0SLloyd Pique /** Get the link by which a client is inserted in the client list
2111*84e872a0SLloyd Pique *
2112*84e872a0SLloyd Pique * \param client The client object
2113*84e872a0SLloyd Pique *
2114*84e872a0SLloyd Pique * \sa wl_client_for_each()
2115*84e872a0SLloyd Pique * \sa wl_display_get_client_list()
2116*84e872a0SLloyd Pique * \sa wl_client_from_link()
2117*84e872a0SLloyd Pique *
2118*84e872a0SLloyd Pique * \memberof wl_client
2119*84e872a0SLloyd Pique */
2120*84e872a0SLloyd Pique WL_EXPORT struct wl_list *
wl_client_get_link(struct wl_client * client)2121*84e872a0SLloyd Pique wl_client_get_link(struct wl_client *client)
2122*84e872a0SLloyd Pique {
2123*84e872a0SLloyd Pique return &client->link;
2124*84e872a0SLloyd Pique }
2125*84e872a0SLloyd Pique
2126*84e872a0SLloyd Pique /** Get a wl_client by its link
2127*84e872a0SLloyd Pique *
2128*84e872a0SLloyd Pique * \param link The link of a wl_client
2129*84e872a0SLloyd Pique *
2130*84e872a0SLloyd Pique * \sa wl_client_for_each()
2131*84e872a0SLloyd Pique * \sa wl_display_get_client_list()
2132*84e872a0SLloyd Pique * \sa wl_client_get_link()
2133*84e872a0SLloyd Pique *
2134*84e872a0SLloyd Pique * \memberof wl_client
2135*84e872a0SLloyd Pique */
2136*84e872a0SLloyd Pique WL_EXPORT struct wl_client *
wl_client_from_link(struct wl_list * link)2137*84e872a0SLloyd Pique wl_client_from_link(struct wl_list *link)
2138*84e872a0SLloyd Pique {
2139*84e872a0SLloyd Pique struct wl_client *client;
2140*84e872a0SLloyd Pique
2141*84e872a0SLloyd Pique return wl_container_of(link, client, link);
2142*84e872a0SLloyd Pique }
2143*84e872a0SLloyd Pique
2144*84e872a0SLloyd Pique /** Add a listener for the client's resource creation signal
2145*84e872a0SLloyd Pique *
2146*84e872a0SLloyd Pique * \param client The client object
2147*84e872a0SLloyd Pique * \param listener The listener to be added
2148*84e872a0SLloyd Pique *
2149*84e872a0SLloyd Pique * When a new resource is created for this client the listener
2150*84e872a0SLloyd Pique * will be notified, carrying the new resource as the data argument.
2151*84e872a0SLloyd Pique *
2152*84e872a0SLloyd Pique * \memberof wl_client
2153*84e872a0SLloyd Pique */
2154*84e872a0SLloyd Pique WL_EXPORT void
wl_client_add_resource_created_listener(struct wl_client * client,struct wl_listener * listener)2155*84e872a0SLloyd Pique wl_client_add_resource_created_listener(struct wl_client *client,
2156*84e872a0SLloyd Pique struct wl_listener *listener)
2157*84e872a0SLloyd Pique {
2158*84e872a0SLloyd Pique wl_priv_signal_add(&client->resource_created_signal, listener);
2159*84e872a0SLloyd Pique }
2160*84e872a0SLloyd Pique
2161*84e872a0SLloyd Pique struct wl_resource_iterator_context {
2162*84e872a0SLloyd Pique void *user_data;
2163*84e872a0SLloyd Pique wl_client_for_each_resource_iterator_func_t it;
2164*84e872a0SLloyd Pique };
2165*84e872a0SLloyd Pique
2166*84e872a0SLloyd Pique static enum wl_iterator_result
resource_iterator_helper(void * res,void * user_data,uint32_t flags)2167*84e872a0SLloyd Pique resource_iterator_helper(void *res, void *user_data, uint32_t flags)
2168*84e872a0SLloyd Pique {
2169*84e872a0SLloyd Pique struct wl_resource_iterator_context *context = user_data;
2170*84e872a0SLloyd Pique struct wl_resource *resource = res;
2171*84e872a0SLloyd Pique
2172*84e872a0SLloyd Pique return context->it(resource, context->user_data);
2173*84e872a0SLloyd Pique }
2174*84e872a0SLloyd Pique
2175*84e872a0SLloyd Pique /** Iterate over all the resources of a client
2176*84e872a0SLloyd Pique *
2177*84e872a0SLloyd Pique * \param client The client object
2178*84e872a0SLloyd Pique * \param iterator The iterator function
2179*84e872a0SLloyd Pique * \param user_data The user data pointer
2180*84e872a0SLloyd Pique *
2181*84e872a0SLloyd Pique * The function pointed by \a iterator will be called for each
2182*84e872a0SLloyd Pique * resource owned by the client. The \a user_data will be passed
2183*84e872a0SLloyd Pique * as the second argument of the iterator function.
2184*84e872a0SLloyd Pique * If the \a iterator function returns \a WL_ITERATOR_CONTINUE the iteration
2185*84e872a0SLloyd Pique * will continue, if it returns \a WL_ITERATOR_STOP it will stop.
2186*84e872a0SLloyd Pique *
2187*84e872a0SLloyd Pique * Creating and destroying resources while iterating is safe, but new
2188*84e872a0SLloyd Pique * resources may or may not be picked up by the iterator.
2189*84e872a0SLloyd Pique *
2190*84e872a0SLloyd Pique * \sa wl_iterator_result
2191*84e872a0SLloyd Pique *
2192*84e872a0SLloyd Pique * \memberof wl_client
2193*84e872a0SLloyd Pique */
2194*84e872a0SLloyd Pique WL_EXPORT void
wl_client_for_each_resource(struct wl_client * client,wl_client_for_each_resource_iterator_func_t iterator,void * user_data)2195*84e872a0SLloyd Pique wl_client_for_each_resource(struct wl_client *client,
2196*84e872a0SLloyd Pique wl_client_for_each_resource_iterator_func_t iterator,
2197*84e872a0SLloyd Pique void *user_data)
2198*84e872a0SLloyd Pique {
2199*84e872a0SLloyd Pique struct wl_resource_iterator_context context = {
2200*84e872a0SLloyd Pique .user_data = user_data,
2201*84e872a0SLloyd Pique .it = iterator,
2202*84e872a0SLloyd Pique };
2203*84e872a0SLloyd Pique
2204*84e872a0SLloyd Pique wl_map_for_each(&client->objects, resource_iterator_helper, &context);
2205*84e872a0SLloyd Pique }
2206*84e872a0SLloyd Pique
2207*84e872a0SLloyd Pique static void
handle_noop(struct wl_listener * listener,void * data)2208*84e872a0SLloyd Pique handle_noop(struct wl_listener *listener, void *data)
2209*84e872a0SLloyd Pique {
2210*84e872a0SLloyd Pique /* Do nothing */
2211*84e872a0SLloyd Pique }
2212*84e872a0SLloyd Pique
2213*84e872a0SLloyd Pique /** Emits this signal, notifying all registered listeners.
2214*84e872a0SLloyd Pique *
2215*84e872a0SLloyd Pique * A safer version of wl_signal_emit() which can gracefully handle additions
2216*84e872a0SLloyd Pique * and deletions of any signal listener from within listener notification
2217*84e872a0SLloyd Pique * callbacks.
2218*84e872a0SLloyd Pique *
2219*84e872a0SLloyd Pique * Listeners deleted during a signal emission and which have not already been
2220*84e872a0SLloyd Pique * notified at the time of deletion are not notified by that emission.
2221*84e872a0SLloyd Pique *
2222*84e872a0SLloyd Pique * Listeners added (or readded) during signal emission are ignored by that
2223*84e872a0SLloyd Pique * emission.
2224*84e872a0SLloyd Pique *
2225*84e872a0SLloyd Pique * Note that repurposing a listener without explicitly removing it and readding
2226*84e872a0SLloyd Pique * it is not supported and can lead to unexpected behavior.
2227*84e872a0SLloyd Pique *
2228*84e872a0SLloyd Pique * \param signal The signal object that will emit the signal
2229*84e872a0SLloyd Pique * \param data The data that will be emitted with the signal
2230*84e872a0SLloyd Pique *
2231*84e872a0SLloyd Pique * \memberof wl_signal
2232*84e872a0SLloyd Pique * \since 1.20.90
2233*84e872a0SLloyd Pique */
2234*84e872a0SLloyd Pique WL_EXPORT void
wl_signal_emit_mutable(struct wl_signal * signal,void * data)2235*84e872a0SLloyd Pique wl_signal_emit_mutable(struct wl_signal *signal, void *data)
2236*84e872a0SLloyd Pique {
2237*84e872a0SLloyd Pique struct wl_listener cursor;
2238*84e872a0SLloyd Pique struct wl_listener end;
2239*84e872a0SLloyd Pique
2240*84e872a0SLloyd Pique /* Add two special markers: one cursor and one end marker. This way, we
2241*84e872a0SLloyd Pique * know that we've already called listeners on the left of the cursor
2242*84e872a0SLloyd Pique * and that we don't want to call listeners on the right of the end
2243*84e872a0SLloyd Pique * marker. The 'it' function can remove any element it wants from the
2244*84e872a0SLloyd Pique * list without troubles.
2245*84e872a0SLloyd Pique *
2246*84e872a0SLloyd Pique * There was a previous attempt that used to steal the whole list of
2247*84e872a0SLloyd Pique * listeners but then that broke wl_signal_get().
2248*84e872a0SLloyd Pique *
2249*84e872a0SLloyd Pique * wl_list_for_each_safe tries to be safe but it fails: it works fine
2250*84e872a0SLloyd Pique * if the current item is removed, but not if the next one is. */
2251*84e872a0SLloyd Pique wl_list_insert(&signal->listener_list, &cursor.link);
2252*84e872a0SLloyd Pique cursor.notify = handle_noop;
2253*84e872a0SLloyd Pique wl_list_insert(signal->listener_list.prev, &end.link);
2254*84e872a0SLloyd Pique end.notify = handle_noop;
2255*84e872a0SLloyd Pique
2256*84e872a0SLloyd Pique while (cursor.link.next != &end.link) {
2257*84e872a0SLloyd Pique struct wl_list *pos = cursor.link.next;
2258*84e872a0SLloyd Pique struct wl_listener *l = wl_container_of(pos, l, link);
2259*84e872a0SLloyd Pique
2260*84e872a0SLloyd Pique wl_list_remove(&cursor.link);
2261*84e872a0SLloyd Pique wl_list_insert(pos, &cursor.link);
2262*84e872a0SLloyd Pique
2263*84e872a0SLloyd Pique l->notify(l, data);
2264*84e872a0SLloyd Pique }
2265*84e872a0SLloyd Pique
2266*84e872a0SLloyd Pique wl_list_remove(&cursor.link);
2267*84e872a0SLloyd Pique wl_list_remove(&end.link);
2268*84e872a0SLloyd Pique }
2269*84e872a0SLloyd Pique
2270*84e872a0SLloyd Pique /** \cond INTERNAL */
2271*84e872a0SLloyd Pique
2272*84e872a0SLloyd Pique /** Initialize a wl_priv_signal object
2273*84e872a0SLloyd Pique *
2274*84e872a0SLloyd Pique * wl_priv_signal is a safer implementation of a signal type, with the same API
2275*84e872a0SLloyd Pique * as wl_signal, but kept as a private utility of libwayland-server.
2276*84e872a0SLloyd Pique * It is safer because listeners can be removed from within wl_priv_signal_emit()
2277*84e872a0SLloyd Pique * without corrupting the signal's list.
2278*84e872a0SLloyd Pique *
2279*84e872a0SLloyd Pique * Before passing a wl_priv_signal object to any other function it must be
2280*84e872a0SLloyd Pique * initialized by using wl_priv_signal_init().
2281*84e872a0SLloyd Pique *
2282*84e872a0SLloyd Pique * \memberof wl_priv_signal
2283*84e872a0SLloyd Pique */
2284*84e872a0SLloyd Pique void
wl_priv_signal_init(struct wl_priv_signal * signal)2285*84e872a0SLloyd Pique wl_priv_signal_init(struct wl_priv_signal *signal)
2286*84e872a0SLloyd Pique {
2287*84e872a0SLloyd Pique wl_list_init(&signal->listener_list);
2288*84e872a0SLloyd Pique wl_list_init(&signal->emit_list);
2289*84e872a0SLloyd Pique }
2290*84e872a0SLloyd Pique
2291*84e872a0SLloyd Pique /** Add a listener to a signal
2292*84e872a0SLloyd Pique *
2293*84e872a0SLloyd Pique * The new listener will be called when calling wl_signal_emit(). If a listener is
2294*84e872a0SLloyd Pique * added to the signal while wl_signal_emit() is running it will be called from
2295*84e872a0SLloyd Pique * the next time wl_priv_signal_emit() is called.
2296*84e872a0SLloyd Pique * To remove a listener call wl_list_remove() on its link member.
2297*84e872a0SLloyd Pique *
2298*84e872a0SLloyd Pique * \memberof wl_priv_signal
2299*84e872a0SLloyd Pique */
2300*84e872a0SLloyd Pique void
wl_priv_signal_add(struct wl_priv_signal * signal,struct wl_listener * listener)2301*84e872a0SLloyd Pique wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener)
2302*84e872a0SLloyd Pique {
2303*84e872a0SLloyd Pique wl_list_insert(signal->listener_list.prev, &listener->link);
2304*84e872a0SLloyd Pique }
2305*84e872a0SLloyd Pique
2306*84e872a0SLloyd Pique /** Get a listener added to a signal
2307*84e872a0SLloyd Pique *
2308*84e872a0SLloyd Pique * Returns the listener added to the given \a signal and with the given
2309*84e872a0SLloyd Pique * \a notify function, or NULL if there isn't any.
2310*84e872a0SLloyd Pique * Calling this function from within wl_priv_signal_emit() is safe and will
2311*84e872a0SLloyd Pique * return the correct value.
2312*84e872a0SLloyd Pique *
2313*84e872a0SLloyd Pique * \memberof wl_priv_signal
2314*84e872a0SLloyd Pique */
2315*84e872a0SLloyd Pique struct wl_listener *
wl_priv_signal_get(struct wl_priv_signal * signal,wl_notify_func_t notify)2316*84e872a0SLloyd Pique wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify)
2317*84e872a0SLloyd Pique {
2318*84e872a0SLloyd Pique struct wl_listener *l;
2319*84e872a0SLloyd Pique
2320*84e872a0SLloyd Pique wl_list_for_each(l, &signal->listener_list, link)
2321*84e872a0SLloyd Pique if (l->notify == notify)
2322*84e872a0SLloyd Pique return l;
2323*84e872a0SLloyd Pique wl_list_for_each(l, &signal->emit_list, link)
2324*84e872a0SLloyd Pique if (l->notify == notify)
2325*84e872a0SLloyd Pique return l;
2326*84e872a0SLloyd Pique
2327*84e872a0SLloyd Pique return NULL;
2328*84e872a0SLloyd Pique }
2329*84e872a0SLloyd Pique
2330*84e872a0SLloyd Pique /** Emit the signal, calling all the installed listeners
2331*84e872a0SLloyd Pique *
2332*84e872a0SLloyd Pique * Iterate over all the listeners added to this \a signal and call
2333*84e872a0SLloyd Pique * their \a notify function pointer, passing on the given \a data.
2334*84e872a0SLloyd Pique * Removing or adding a listener from within wl_priv_signal_emit()
2335*84e872a0SLloyd Pique * is safe.
2336*84e872a0SLloyd Pique */
2337*84e872a0SLloyd Pique void
wl_priv_signal_emit(struct wl_priv_signal * signal,void * data)2338*84e872a0SLloyd Pique wl_priv_signal_emit(struct wl_priv_signal *signal, void *data)
2339*84e872a0SLloyd Pique {
2340*84e872a0SLloyd Pique struct wl_listener *l;
2341*84e872a0SLloyd Pique struct wl_list *pos;
2342*84e872a0SLloyd Pique
2343*84e872a0SLloyd Pique wl_list_insert_list(&signal->emit_list, &signal->listener_list);
2344*84e872a0SLloyd Pique wl_list_init(&signal->listener_list);
2345*84e872a0SLloyd Pique
2346*84e872a0SLloyd Pique /* Take every element out of the list and put them in a temporary list.
2347*84e872a0SLloyd Pique * This way, the 'it' func can remove any element it wants from the list
2348*84e872a0SLloyd Pique * without troubles, because we always get the first element, not the
2349*84e872a0SLloyd Pique * one after the current, which may be invalid.
2350*84e872a0SLloyd Pique * wl_list_for_each_safe tries to be safe but it fails: it works fine
2351*84e872a0SLloyd Pique * if the current item is removed, but not if the next one is. */
2352*84e872a0SLloyd Pique while (!wl_list_empty(&signal->emit_list)) {
2353*84e872a0SLloyd Pique pos = signal->emit_list.next;
2354*84e872a0SLloyd Pique l = wl_container_of(pos, l, link);
2355*84e872a0SLloyd Pique
2356*84e872a0SLloyd Pique wl_list_remove(pos);
2357*84e872a0SLloyd Pique wl_list_insert(&signal->listener_list, pos);
2358*84e872a0SLloyd Pique
2359*84e872a0SLloyd Pique l->notify(l, data);
2360*84e872a0SLloyd Pique }
2361*84e872a0SLloyd Pique }
2362*84e872a0SLloyd Pique
2363*84e872a0SLloyd Pique /** Emit the signal for the last time, calling all the installed listeners
2364*84e872a0SLloyd Pique *
2365*84e872a0SLloyd Pique * Iterate over all the listeners added to this \a signal and call
2366*84e872a0SLloyd Pique * their \a notify function pointer, passing on the given \a data.
2367*84e872a0SLloyd Pique * Removing or adding a listener from within wl_priv_signal_emit()
2368*84e872a0SLloyd Pique * is safe, as is freeing the structure containing the listener.
2369*84e872a0SLloyd Pique *
2370*84e872a0SLloyd Pique * A large body of external code assumes it's ok to free a destruction
2371*84e872a0SLloyd Pique * listener without removing that listener from the list. Mixing code
2372*84e872a0SLloyd Pique * that acts like this and code that doesn't will result in list
2373*84e872a0SLloyd Pique * corruption.
2374*84e872a0SLloyd Pique *
2375*84e872a0SLloyd Pique * We resolve this by removing each item from the list and isolating it
2376*84e872a0SLloyd Pique * in another list. We discard it completely after firing the notifier.
2377*84e872a0SLloyd Pique * This should allow interoperability between code that unlinks its
2378*84e872a0SLloyd Pique * destruction listeners and code that just frees structures they're in.
2379*84e872a0SLloyd Pique *
2380*84e872a0SLloyd Pique */
2381*84e872a0SLloyd Pique void
wl_priv_signal_final_emit(struct wl_priv_signal * signal,void * data)2382*84e872a0SLloyd Pique wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data)
2383*84e872a0SLloyd Pique {
2384*84e872a0SLloyd Pique struct wl_listener *l;
2385*84e872a0SLloyd Pique struct wl_list *pos;
2386*84e872a0SLloyd Pique
2387*84e872a0SLloyd Pique /* During a destructor notifier isolate every list item before
2388*84e872a0SLloyd Pique * notifying. This renders harmless the long standing misuse
2389*84e872a0SLloyd Pique * of freeing listeners without removing them, but allows
2390*84e872a0SLloyd Pique * callers that do choose to remove them to interoperate with
2391*84e872a0SLloyd Pique * ones that don't. */
2392*84e872a0SLloyd Pique while (!wl_list_empty(&signal->listener_list)) {
2393*84e872a0SLloyd Pique pos = signal->listener_list.next;
2394*84e872a0SLloyd Pique l = wl_container_of(pos, l, link);
2395*84e872a0SLloyd Pique
2396*84e872a0SLloyd Pique wl_list_remove(pos);
2397*84e872a0SLloyd Pique wl_list_init(pos);
2398*84e872a0SLloyd Pique
2399*84e872a0SLloyd Pique l->notify(l, data);
2400*84e872a0SLloyd Pique }
2401*84e872a0SLloyd Pique }
2402*84e872a0SLloyd Pique
2403*84e872a0SLloyd Pique /** \endcond INTERNAL */
2404*84e872a0SLloyd Pique
2405*84e872a0SLloyd Pique /** \cond */ /* Deprecated functions below. */
2406*84e872a0SLloyd Pique
2407*84e872a0SLloyd Pique uint32_t
2408*84e872a0SLloyd Pique wl_client_add_resource(struct wl_client *client,
2409*84e872a0SLloyd Pique struct wl_resource *resource) WL_DEPRECATED;
2410*84e872a0SLloyd Pique
2411*84e872a0SLloyd Pique WL_EXPORT uint32_t
wl_client_add_resource(struct wl_client * client,struct wl_resource * resource)2412*84e872a0SLloyd Pique wl_client_add_resource(struct wl_client *client,
2413*84e872a0SLloyd Pique struct wl_resource *resource)
2414*84e872a0SLloyd Pique {
2415*84e872a0SLloyd Pique if (resource->object.id == 0) {
2416*84e872a0SLloyd Pique resource->object.id =
2417*84e872a0SLloyd Pique wl_map_insert_new(&client->objects,
2418*84e872a0SLloyd Pique WL_MAP_ENTRY_LEGACY, resource);
2419*84e872a0SLloyd Pique if (resource->object.id == 0)
2420*84e872a0SLloyd Pique return 0;
2421*84e872a0SLloyd Pique } else if (wl_map_insert_at(&client->objects, WL_MAP_ENTRY_LEGACY,
2422*84e872a0SLloyd Pique resource->object.id, resource) < 0) {
2423*84e872a0SLloyd Pique if (errno == EINVAL) {
2424*84e872a0SLloyd Pique wl_resource_post_error(client->display_resource,
2425*84e872a0SLloyd Pique WL_DISPLAY_ERROR_INVALID_OBJECT,
2426*84e872a0SLloyd Pique "invalid new id %d",
2427*84e872a0SLloyd Pique resource->object.id);
2428*84e872a0SLloyd Pique }
2429*84e872a0SLloyd Pique return 0;
2430*84e872a0SLloyd Pique }
2431*84e872a0SLloyd Pique
2432*84e872a0SLloyd Pique resource->client = client;
2433*84e872a0SLloyd Pique wl_signal_init(&resource->deprecated_destroy_signal);
2434*84e872a0SLloyd Pique
2435*84e872a0SLloyd Pique return resource->object.id;
2436*84e872a0SLloyd Pique }
2437*84e872a0SLloyd Pique
2438*84e872a0SLloyd Pique struct wl_resource *
2439*84e872a0SLloyd Pique wl_client_add_object(struct wl_client *client,
2440*84e872a0SLloyd Pique const struct wl_interface *interface,
2441*84e872a0SLloyd Pique const void *implementation,
2442*84e872a0SLloyd Pique uint32_t id, void *data) WL_DEPRECATED;
2443*84e872a0SLloyd Pique
2444*84e872a0SLloyd Pique WL_EXPORT struct wl_resource *
wl_client_add_object(struct wl_client * client,const struct wl_interface * interface,const void * implementation,uint32_t id,void * data)2445*84e872a0SLloyd Pique wl_client_add_object(struct wl_client *client,
2446*84e872a0SLloyd Pique const struct wl_interface *interface,
2447*84e872a0SLloyd Pique const void *implementation, uint32_t id, void *data)
2448*84e872a0SLloyd Pique {
2449*84e872a0SLloyd Pique struct wl_resource *resource;
2450*84e872a0SLloyd Pique
2451*84e872a0SLloyd Pique resource = wl_resource_create(client, interface, -1, id);
2452*84e872a0SLloyd Pique if (resource == NULL)
2453*84e872a0SLloyd Pique wl_client_post_no_memory(client);
2454*84e872a0SLloyd Pique else
2455*84e872a0SLloyd Pique wl_resource_set_implementation(resource,
2456*84e872a0SLloyd Pique implementation, data, NULL);
2457*84e872a0SLloyd Pique
2458*84e872a0SLloyd Pique return resource;
2459*84e872a0SLloyd Pique }
2460*84e872a0SLloyd Pique
2461*84e872a0SLloyd Pique struct wl_resource *
2462*84e872a0SLloyd Pique wl_client_new_object(struct wl_client *client,
2463*84e872a0SLloyd Pique const struct wl_interface *interface,
2464*84e872a0SLloyd Pique const void *implementation, void *data) WL_DEPRECATED;
2465*84e872a0SLloyd Pique
2466*84e872a0SLloyd Pique WL_EXPORT struct wl_resource *
wl_client_new_object(struct wl_client * client,const struct wl_interface * interface,const void * implementation,void * data)2467*84e872a0SLloyd Pique wl_client_new_object(struct wl_client *client,
2468*84e872a0SLloyd Pique const struct wl_interface *interface,
2469*84e872a0SLloyd Pique const void *implementation, void *data)
2470*84e872a0SLloyd Pique {
2471*84e872a0SLloyd Pique struct wl_resource *resource;
2472*84e872a0SLloyd Pique
2473*84e872a0SLloyd Pique resource = wl_resource_create(client, interface, -1, 0);
2474*84e872a0SLloyd Pique if (resource == NULL)
2475*84e872a0SLloyd Pique wl_client_post_no_memory(client);
2476*84e872a0SLloyd Pique else
2477*84e872a0SLloyd Pique wl_resource_set_implementation(resource,
2478*84e872a0SLloyd Pique implementation, data, NULL);
2479*84e872a0SLloyd Pique
2480*84e872a0SLloyd Pique return resource;
2481*84e872a0SLloyd Pique }
2482*84e872a0SLloyd Pique
2483*84e872a0SLloyd Pique struct wl_global *
2484*84e872a0SLloyd Pique wl_display_add_global(struct wl_display *display,
2485*84e872a0SLloyd Pique const struct wl_interface *interface,
2486*84e872a0SLloyd Pique void *data, wl_global_bind_func_t bind) WL_DEPRECATED;
2487*84e872a0SLloyd Pique
2488*84e872a0SLloyd Pique WL_EXPORT struct wl_global *
wl_display_add_global(struct wl_display * display,const struct wl_interface * interface,void * data,wl_global_bind_func_t bind)2489*84e872a0SLloyd Pique wl_display_add_global(struct wl_display *display,
2490*84e872a0SLloyd Pique const struct wl_interface *interface,
2491*84e872a0SLloyd Pique void *data, wl_global_bind_func_t bind)
2492*84e872a0SLloyd Pique {
2493*84e872a0SLloyd Pique return wl_global_create(display, interface, interface->version, data, bind);
2494*84e872a0SLloyd Pique }
2495*84e872a0SLloyd Pique
2496*84e872a0SLloyd Pique void
2497*84e872a0SLloyd Pique wl_display_remove_global(struct wl_display *display,
2498*84e872a0SLloyd Pique struct wl_global *global) WL_DEPRECATED;
2499*84e872a0SLloyd Pique
2500*84e872a0SLloyd Pique WL_EXPORT void
wl_display_remove_global(struct wl_display * display,struct wl_global * global)2501*84e872a0SLloyd Pique wl_display_remove_global(struct wl_display *display, struct wl_global *global)
2502*84e872a0SLloyd Pique {
2503*84e872a0SLloyd Pique wl_global_destroy(global);
2504*84e872a0SLloyd Pique }
2505*84e872a0SLloyd Pique
2506*84e872a0SLloyd Pique /** \endcond */
2507*84e872a0SLloyd Pique
2508*84e872a0SLloyd Pique /* Functions at the end of this file are deprecated. Instead of adding new
2509*84e872a0SLloyd Pique * code here, add it before the comment above that states:
2510*84e872a0SLloyd Pique * Deprecated functions below.
2511*84e872a0SLloyd Pique */
2512