blob: 20fbcb8276b8cb7afbc02082ba32df0137a1cdbf [file] [log] [blame]
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -04001#include <stdlib.h>
2#include <stdint.h>
3#include <stddef.h>
4#include <stdio.h>
5#include <errno.h>
6#include <string.h>
7#include <unistd.h>
8#include <sys/socket.h>
9#include <sys/un.h>
10#include <ffi.h>
Kristian Høgsberg680f1c72008-10-08 12:48:46 -040011
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040012#include "wayland.h"
Kristian Høgsberg680f1c72008-10-08 12:48:46 -040013#include "connection.h"
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040014
15#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
16
Kristian Høgsbergf9212892008-10-11 18:40:23 -040017struct wl_list {
18 struct wl_list *prev;
19 struct wl_list *next;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040020};
21
Kristian Høgsbergf9212892008-10-11 18:40:23 -040022void wl_list_init(struct wl_list *list)
23{
24 list->prev = list;
25 list->next = list;
26}
27
28void
29wl_list_insert(struct wl_list *list, struct wl_list *elm)
30{
31 elm->prev = list;
32 elm->next = list->next;
33 list->next = elm;
34 elm->next->prev = elm;
35}
36
37void
38wl_list_remove(struct wl_list *elm)
39{
40 elm->prev->next = elm->next;
41 elm->next->prev = elm->prev;
42}
43
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040044struct wl_client {
Kristian Høgsberg680f1c72008-10-08 12:48:46 -040045 struct wl_connection *connection;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040046 struct wl_event_source *source;
47 struct wl_display *display;
48};
49
50struct wl_display {
51 struct wl_object base;
52 struct wl_event_loop *loop;
53 struct wl_hash objects;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040054
55 struct wl_compositor *compositor;
56 struct wl_compositor_interface *compositor_interface;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040057
58 struct wl_list surface_list;
59 uint32_t client_id_range;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040060};
61
62struct wl_surface {
63 struct wl_object base;
64
65 /* provided by client */
66 int width, height;
67 int buffer;
68 int stride;
69
Kristian Høgsberg05eff512008-10-07 10:10:36 -040070 struct wl_map map;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040071 struct wl_list link;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040072
73 /* how to convert buffer contents to pixels in screen format;
74 * yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */
75
76 /* how to transform/render rectangular contents to polygons. */
Kristian Høgsberg05eff512008-10-07 10:10:36 -040077
78 void *compositor_data;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040079};
80
Kristian Høgsberg05eff512008-10-07 10:10:36 -040081
82static void
83wl_surface_destroy(struct wl_client *client,
84 struct wl_surface *surface)
85{
86 struct wl_compositor_interface *interface;
87
88 interface = client->display->compositor->interface;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040089 interface->notify_surface_destroy(client->display->compositor,
90 surface);
91 wl_list_remove(&surface->link);
Kristian Høgsberg05eff512008-10-07 10:10:36 -040092}
93
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040094static void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040095wl_surface_attach(struct wl_client *client,
96 struct wl_surface *surface, uint32_t name,
97 uint32_t width, uint32_t height, uint32_t stride)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040098{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040099 struct wl_compositor_interface *interface;
100
101 interface = client->display->compositor->interface;
102 interface->notify_surface_attach(client->display->compositor,
103 surface, name, width, height, stride);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400104}
105
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400106static const struct wl_argument attach_arguments[] = {
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400107 { WL_ARGUMENT_UINT32 },
108 { WL_ARGUMENT_UINT32 },
109 { WL_ARGUMENT_UINT32 },
110 { WL_ARGUMENT_UINT32 },
111};
112
113void
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400114wl_surface_map(struct wl_client *client, struct wl_surface *surface,
115 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400116{
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400117 struct wl_compositor_interface *interface;
118
119 /* FIXME: This needs to take a tri-mesh argument... - count
120 * and a list of tris. 0 tris means unmap. */
121
122 surface->map.x = x;
123 surface->map.y = y;
124 surface->map.width = width;
125 surface->map.height = height;
126
127 interface = client->display->compositor->interface;
128 interface->notify_surface_map(client->display->compositor,
129 surface, &surface->map);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400130}
131
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400132static const struct wl_argument map_arguments[] = {
133 { WL_ARGUMENT_UINT32 },
134 { WL_ARGUMENT_UINT32 },
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400135 { WL_ARGUMENT_UINT32 },
136 { WL_ARGUMENT_UINT32 },
137};
138
139static const struct wl_method surface_methods[] = {
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400140 { "destroy", wl_surface_destroy,
141 0, NULL },
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400142 { "attach", wl_surface_attach,
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400143 ARRAY_LENGTH(attach_arguments), attach_arguments },
144 { "map", wl_surface_map,
145 ARRAY_LENGTH(map_arguments), map_arguments }
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400146};
147
148static const struct wl_interface surface_interface = {
149 "surface", 1,
150 ARRAY_LENGTH(surface_methods),
151 surface_methods,
152};
153
154struct wl_surface *
155wl_surface_create(struct wl_display *display, uint32_t id)
156{
157 struct wl_surface *surface;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400158 struct wl_compositor_interface *interface;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400159
160 surface = malloc(sizeof *surface);
161 if (surface == NULL)
162 return NULL;
163
164 surface->base.id = id;
165 surface->base.interface = &surface_interface;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400166
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400167 wl_list_insert(display->surface_list.prev, &surface->link);
168
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400169 interface = display->compositor->interface;
170 interface->notify_surface_create(display->compositor, surface);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400171
172 return surface;
173}
174
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400175void
176wl_surface_set_data(struct wl_surface *surface, void *data)
177{
178 surface->compositor_data = data;
179}
180
181void *
182wl_surface_get_data(struct wl_surface *surface)
183{
184 return surface->compositor_data;
185}
186
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400187void
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400188wl_client_destroy(struct wl_client *client);
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400189
190static void
191wl_client_demarshal(struct wl_client *client, struct wl_object *target,
192 const struct wl_method *method, size_t size)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400193{
194 ffi_type *types[10];
195 ffi_cif cif;
196 uint32_t *p, result;
197 int i;
198 union {
199 uint32_t uint32;
200 const char *string;
201 void *object;
202 uint32_t new_id;
203 } values[10];
204 void *args[10];
205 struct wl_object *object;
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400206 uint32_t data[64];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400207
208 if (method->argument_count > ARRAY_LENGTH(types)) {
209 printf("too many args (%d)\n", method->argument_count);
210 return;
211 }
212
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400213 if (sizeof data < size) {
214 printf("request too big, should malloc tmp buffer here\n");
215 return;
216 }
217
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400218 types[0] = &ffi_type_pointer;
219 values[0].object = client;
220 args[0] = &values[0];
221
222 types[1] = &ffi_type_pointer;
223 values[1].object = target;
224 args[1] = &values[1];
225
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400226 wl_connection_copy(client->connection, data, size);
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400227 p = &data[2];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400228 for (i = 0; i < method->argument_count; i++) {
229 switch (method->arguments[i].type) {
230 case WL_ARGUMENT_UINT32:
231 types[i + 2] = &ffi_type_uint32;
232 values[i + 2].uint32 = *p;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400233 p++;
234 break;
235 case WL_ARGUMENT_STRING:
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400236 types[i + 2] = &ffi_type_pointer;
237 /* FIXME */
238 values[i + 2].uint32 = *p++;
239 break;
240 case WL_ARGUMENT_OBJECT:
241 types[i + 2] = &ffi_type_pointer;
242 object = wl_hash_lookup(&client->display->objects, *p);
243 if (object == NULL)
244 printf("unknown object (%d)\n", *p);
245 if (object->interface != method->arguments[i].data)
246 printf("wrong object type\n");
247 values[i + 2].object = object;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400248 p++;
249 break;
250 case WL_ARGUMENT_NEW_ID:
251 types[i + 2] = &ffi_type_uint32;
252 values[i + 2].new_id = *p;
253 object = wl_hash_lookup(&client->display->objects, *p);
254 if (object != NULL)
255 printf("object already exists (%d)\n", *p);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400256 p++;
257 break;
258 default:
259 printf("unknown type\n");
260 break;
261 }
262 args[i + 2] = &values[i + 2];
263 }
264
265 ffi_prep_cif(&cif, FFI_DEFAULT_ABI, method->argument_count + 2,
266 &ffi_type_uint32, types);
267 ffi_call(&cif, FFI_FN(method->func), &result, args);
268}
269
270static void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400271wl_client_event(struct wl_client *client, struct wl_object *object, uint32_t event)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400272{
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400273 uint32_t p[2];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400274
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400275 p[0] = object->id;
276 p[1] = event | (8 << 16);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400277 wl_connection_write(client->connection, p, sizeof p);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400278}
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400279
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400280#define WL_DISPLAY_INVALID_OBJECT 0
281#define WL_DISPLAY_INVALID_METHOD 1
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400282
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400283static void
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400284wl_client_connection_data(int fd, uint32_t mask, void *data)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400285{
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400286 struct wl_client *client = data;
287 struct wl_connection *connection = client->connection;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400288 const struct wl_method *method;
289 struct wl_object *object;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400290 uint32_t p[2], opcode, size;
291 uint32_t cmask = 0;
292 int len;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400293
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400294 if (mask & WL_EVENT_READABLE)
295 cmask |= WL_CONNECTION_READABLE;
296 if (mask & WL_EVENT_WRITEABLE)
297 cmask |= WL_CONNECTION_WRITABLE;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400298
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400299 len = wl_connection_data(connection, cmask);
300 if (len < 0) {
301 wl_client_destroy(client);
302 return;
303 }
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400304
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400305 while (len > sizeof p) {
306 wl_connection_copy(connection, p, sizeof p);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400307 opcode = p[1] & 0xffff;
308 size = p[1] >> 16;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400309 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400310 break;
311
312 object = wl_hash_lookup(&client->display->objects,
313 p[0]);
314 if (object == NULL) {
315 wl_client_event(client, &client->display->base,
316 WL_DISPLAY_INVALID_OBJECT);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400317 wl_connection_consume(connection, size);
318 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400319 continue;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400320 }
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400321
322 if (opcode >= object->interface->method_count) {
323 wl_client_event(client, &client->display->base,
324 WL_DISPLAY_INVALID_METHOD);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400325 wl_connection_consume(connection, size);
326 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400327 continue;
328 }
329
330 method = &object->interface->methods[opcode];
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400331 wl_client_demarshal(client, object, method, size);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400332 wl_connection_consume(connection, size);
333 len -= size;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400334 }
335}
336
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400337static int
338wl_client_connection_update(struct wl_connection *connection,
339 uint32_t mask, void *data)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400340{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400341 struct wl_client *client = data;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400342 uint32_t emask = 0;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400343
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400344 if (mask & WL_CONNECTION_READABLE)
345 emask |= WL_EVENT_READABLE;
346 if (mask & WL_CONNECTION_WRITABLE)
347 emask |= WL_EVENT_WRITEABLE;
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400348
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400349 return wl_event_loop_update_source(client->display->loop,
350 client->source, mask);
351}
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400352
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400353static void
354advertise_object(struct wl_client *client, struct wl_object *object)
355{
356 const struct wl_interface *interface;
357 static const char pad[4];
358 uint32_t length, p[2];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400359
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400360 interface = object->interface;
361 length = strlen(interface->name);
362 p[0] = object->id;
363 p[1] = length;
364 wl_connection_write(client->connection, p, sizeof p);
365 wl_connection_write(client->connection, interface->name, length);
366 wl_connection_write(client->connection, pad, -length & 3);
367}
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400368
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400369struct wl_client *
370wl_client_create(struct wl_display *display, int fd)
371{
372 struct wl_client *client;
373
374 client = malloc(sizeof *client);
375 if (client == NULL)
376 return NULL;
377
378 memset(client, 0, sizeof *client);
379 client->display = display;
380 client->source = wl_event_loop_add_fd(display->loop, fd,
381 WL_EVENT_READABLE,
382 wl_client_connection_data, client);
383 client->connection = wl_connection_create(fd,
384 wl_client_connection_update,
385 client);
386
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400387 wl_connection_write(client->connection,
388 &display->client_id_range,
389 sizeof display->client_id_range);
390 display->client_id_range += 256;
391
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400392 advertise_object(client, &display->base);
393
394 return client;
395}
396
397void
398wl_client_destroy(struct wl_client *client)
399{
400 printf("disconnect from client %p\n", client);
401 wl_event_loop_remove_source(client->display->loop, client->source);
402 wl_connection_destroy(client->connection);
403 free(client);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400404}
405
406static int
407wl_display_create_surface(struct wl_client *client,
408 struct wl_display *display, uint32_t id)
409{
410 struct wl_surface *surface;
411
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400412 surface = wl_surface_create(display, id);
413 wl_hash_insert(&display->objects, &surface->base);
414
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400415 /* FIXME: garbage collect client resources when client exits. */
416
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400417 return 0;
418}
419
420static const struct wl_argument create_surface_arguments[] = {
421 { WL_ARGUMENT_NEW_ID }
422};
423
424static const struct wl_method display_methods[] = {
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400425 { "create_surface", wl_display_create_surface,
426 ARRAY_LENGTH(create_surface_arguments), create_surface_arguments },
427};
428
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400429static const struct wl_event display_events[] = {
430 { "invalid_object" },
431 { "invalid_method" },
432};
433
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400434static const struct wl_interface display_interface = {
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400435 "display", 1,
436 ARRAY_LENGTH(display_methods), display_methods,
437 ARRAY_LENGTH(display_events), display_events,
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400438};
439
440struct wl_display *
441wl_display_create(void)
442{
443 struct wl_display *display;
444
445 display = malloc(sizeof *display);
446 if (display == NULL)
447 return NULL;
448
449 display->loop = wl_event_loop_create();
450 if (display->loop == NULL) {
451 free(display);
452 return NULL;
453 }
454
455 display->base.id = 0;
456 display->base.interface = &display_interface;
457 wl_hash_insert(&display->objects, &display->base);
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400458 wl_list_init(&display->surface_list);
459
460 display->client_id_range = 256; /* Gah, arbitrary... */
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400461
462 return display;
463}
464
465void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400466wl_display_set_compositor(struct wl_display *display,
467 struct wl_compositor *compositor)
468{
469 display->compositor = compositor;
470}
471
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -0400472struct wl_event_loop *
473wl_display_get_event_loop(struct wl_display *display)
474{
475 return display->loop;
476}
477
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400478void
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400479wl_display_run(struct wl_display *display)
480{
481 while (1)
482 wl_event_loop_wait(display->loop);
483}
484
485/* The plan here is to generate a random anonymous socket name and
486 * advertise that through a service on the session dbus.
487 */
488static const char socket_name[] = "\0wayland";
489
490static void
491socket_data(int fd, uint32_t mask, void *data)
492{
493 struct wl_display *display = data;
494 struct sockaddr_un name;
495 socklen_t length;
496 int client_fd;
497
498 length = sizeof name;
499 client_fd = accept (fd, (struct sockaddr *) &name, &length);
500 if (client_fd < 0)
501 fprintf(stderr, "failed to accept\n");
502
503 wl_client_create(display, client_fd);
504}
505
506int
507wl_display_add_socket(struct wl_display *display)
508{
509 struct sockaddr_un name;
510 int sock;
511 socklen_t size;
512
513 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
514 if (sock < 0)
515 return -1;
516
517 name.sun_family = AF_LOCAL;
518 memcpy(name.sun_path, socket_name, sizeof socket_name);
519
520 size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
521 if (bind(sock, (struct sockaddr *) &name, size) < 0)
522 return -1;
523
524 if (listen(sock, 1) < 0)
525 return -1;
526
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400527 wl_event_loop_add_fd(display->loop, sock,
528 WL_EVENT_READABLE,
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400529 socket_data, display);
530
531 return 0;
532}
533
534
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400535#define container_of(ptr, type, member) ({ \
536 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
537 (type *)( (char *)__mptr - offsetof(type,member) );})
538
539struct wl_surface_iterator {
540 struct wl_list *head;
541 struct wl_surface *surface;
542 uint32_t mask;
543};
544
545struct wl_surface_iterator *
546wl_surface_iterator_create(struct wl_display *display, uint32_t mask)
547{
548 struct wl_surface_iterator *iterator;
549
550 iterator = malloc(sizeof *iterator);
551 if (iterator == NULL)
552 return NULL;
553
554 iterator->head = &display->surface_list;
555 iterator->surface = container_of(display->surface_list.next,
556 struct wl_surface, link);
557 iterator->mask = mask;
558
559 return iterator;
560}
561
562int
563wl_surface_iterator_next(struct wl_surface_iterator *iterator,
564 struct wl_surface **surface)
565{
566 if (&iterator->surface->link == iterator->head)
567 return 0;
568
569 *surface = iterator->surface;
570 iterator->surface = container_of(iterator->surface->link.next,
571 struct wl_surface, link);
572
573 return 1;
574}
575
576void
577wl_surface_iterator_destroy(struct wl_surface_iterator *iterator)
578{
579 free(iterator);
580}
581
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400582int main(int argc, char *argv[])
583{
584 struct wl_display *display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400585 struct wl_compositor *compositor;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400586
587 display = wl_display_create();
588
589 if (wl_display_add_socket(display)) {
590 fprintf(stderr, "failed to add socket: %m\n");
591 exit(EXIT_FAILURE);
592 }
593
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400594 compositor = wl_compositor_create(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400595 wl_display_set_compositor(display, compositor);
596
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400597 printf("wayland online, display is %p\n", display);
598
599 wl_display_run(display);
600
601 return 0;
602}