blob: b51d3877b0d83a23e7422c0603c5aef2b9e1460a [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>
Kristian Høgsberg5503bf82008-11-06 10:38:17 -050010#include <dlfcn.h>
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040011#include <ffi.h>
Kristian Høgsberg680f1c72008-10-08 12:48:46 -040012
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040013#include "wayland.h"
Kristian Høgsberg680f1c72008-10-08 12:48:46 -040014#include "connection.h"
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040015
Kristian Høgsberg94a2e862008-10-11 21:37:55 -040016#define container_of(ptr, type, member) ({ \
17 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
18 (type *)( (char *)__mptr - offsetof(type,member) );})
19
20
Kristian Høgsbergf9212892008-10-11 18:40:23 -040021struct wl_list {
22 struct wl_list *prev;
23 struct wl_list *next;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040024};
25
Kristian Høgsbergf9212892008-10-11 18:40:23 -040026void wl_list_init(struct wl_list *list)
27{
28 list->prev = list;
29 list->next = list;
30}
31
32void
33wl_list_insert(struct wl_list *list, struct wl_list *elm)
34{
35 elm->prev = list;
36 elm->next = list->next;
37 list->next = elm;
38 elm->next->prev = elm;
39}
40
41void
42wl_list_remove(struct wl_list *elm)
43{
44 elm->prev->next = elm->next;
45 elm->next->prev = elm->prev;
46}
47
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040048struct wl_client {
Kristian Høgsberg680f1c72008-10-08 12:48:46 -040049 struct wl_connection *connection;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040050 struct wl_event_source *source;
51 struct wl_display *display;
Kristian Høgsberg94a2e862008-10-11 21:37:55 -040052 struct wl_list object_list;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050053 struct wl_list link;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040054};
55
56struct wl_display {
57 struct wl_object base;
58 struct wl_event_loop *loop;
59 struct wl_hash objects;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040060
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050061 struct wl_object *pointer;
62
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040063 struct wl_compositor *compositor;
64 struct wl_compositor_interface *compositor_interface;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040065
66 struct wl_list surface_list;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050067 struct wl_list client_list;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040068 uint32_t client_id_range;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050069
70 int32_t pointer_x;
71 int32_t pointer_y;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040072};
73
74struct wl_surface {
75 struct wl_object base;
76
77 /* provided by client */
78 int width, height;
79 int buffer;
80 int stride;
81
Kristian Høgsberg05eff512008-10-07 10:10:36 -040082 struct wl_map map;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040083 struct wl_list link;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040084
85 /* how to convert buffer contents to pixels in screen format;
86 * yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */
87
88 /* how to transform/render rectangular contents to polygons. */
Kristian Høgsberg05eff512008-10-07 10:10:36 -040089
90 void *compositor_data;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040091};
92
Kristian Høgsberg94a2e862008-10-11 21:37:55 -040093struct wl_object_ref {
94 struct wl_object *object;
95 struct wl_list link;
96};
Kristian Høgsberg05eff512008-10-07 10:10:36 -040097
98static void
99wl_surface_destroy(struct wl_client *client,
100 struct wl_surface *surface)
101{
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500102 const struct wl_compositor_interface *interface;
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400103
104 interface = client->display->compositor->interface;
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400105 interface->notify_surface_destroy(client->display->compositor,
106 surface);
107 wl_list_remove(&surface->link);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400108}
109
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400110static void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400111wl_surface_attach(struct wl_client *client,
112 struct wl_surface *surface, uint32_t name,
113 uint32_t width, uint32_t height, uint32_t stride)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400114{
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500115 const struct wl_compositor_interface *interface;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400116
117 interface = client->display->compositor->interface;
118 interface->notify_surface_attach(client->display->compositor,
119 surface, name, width, height, stride);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400120}
121
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400122static const struct wl_argument attach_arguments[] = {
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400123 { WL_ARGUMENT_UINT32 },
124 { WL_ARGUMENT_UINT32 },
125 { WL_ARGUMENT_UINT32 },
126 { WL_ARGUMENT_UINT32 },
127};
128
129void
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400130wl_surface_map(struct wl_client *client, struct wl_surface *surface,
131 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400132{
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500133 const struct wl_compositor_interface *interface;
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400134
135 /* FIXME: This needs to take a tri-mesh argument... - count
136 * and a list of tris. 0 tris means unmap. */
137
138 surface->map.x = x;
139 surface->map.y = y;
140 surface->map.width = width;
141 surface->map.height = height;
142
143 interface = client->display->compositor->interface;
144 interface->notify_surface_map(client->display->compositor,
145 surface, &surface->map);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400146}
147
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400148static const struct wl_argument map_arguments[] = {
149 { WL_ARGUMENT_UINT32 },
150 { WL_ARGUMENT_UINT32 },
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400151 { WL_ARGUMENT_UINT32 },
152 { WL_ARGUMENT_UINT32 },
153};
154
155static const struct wl_method surface_methods[] = {
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400156 { "destroy", wl_surface_destroy,
157 0, NULL },
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400158 { "attach", wl_surface_attach,
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400159 ARRAY_LENGTH(attach_arguments), attach_arguments },
160 { "map", wl_surface_map,
161 ARRAY_LENGTH(map_arguments), map_arguments }
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400162};
163
164static const struct wl_interface surface_interface = {
165 "surface", 1,
166 ARRAY_LENGTH(surface_methods),
167 surface_methods,
168};
169
170struct wl_surface *
171wl_surface_create(struct wl_display *display, uint32_t id)
172{
173 struct wl_surface *surface;
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500174 const struct wl_compositor_interface *interface;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400175
176 surface = malloc(sizeof *surface);
177 if (surface == NULL)
178 return NULL;
179
180 surface->base.id = id;
181 surface->base.interface = &surface_interface;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400182
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400183 wl_list_insert(display->surface_list.prev, &surface->link);
184
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400185 interface = display->compositor->interface;
186 interface->notify_surface_create(display->compositor, surface);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400187
188 return surface;
189}
190
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400191void
192wl_surface_set_data(struct wl_surface *surface, void *data)
193{
194 surface->compositor_data = data;
195}
196
197void *
198wl_surface_get_data(struct wl_surface *surface)
199{
200 return surface->compositor_data;
201}
202
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400203void
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400204wl_client_destroy(struct wl_client *client);
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400205
206static void
207wl_client_demarshal(struct wl_client *client, struct wl_object *target,
208 const struct wl_method *method, size_t size)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400209{
210 ffi_type *types[10];
211 ffi_cif cif;
212 uint32_t *p, result;
213 int i;
214 union {
215 uint32_t uint32;
216 const char *string;
217 void *object;
218 uint32_t new_id;
219 } values[10];
220 void *args[10];
221 struct wl_object *object;
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400222 uint32_t data[64];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400223
224 if (method->argument_count > ARRAY_LENGTH(types)) {
225 printf("too many args (%d)\n", method->argument_count);
226 return;
227 }
228
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400229 if (sizeof data < size) {
230 printf("request too big, should malloc tmp buffer here\n");
231 return;
232 }
233
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400234 types[0] = &ffi_type_pointer;
235 values[0].object = client;
236 args[0] = &values[0];
237
238 types[1] = &ffi_type_pointer;
239 values[1].object = target;
240 args[1] = &values[1];
241
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400242 wl_connection_copy(client->connection, data, size);
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400243 p = &data[2];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400244 for (i = 0; i < method->argument_count; i++) {
245 switch (method->arguments[i].type) {
246 case WL_ARGUMENT_UINT32:
247 types[i + 2] = &ffi_type_uint32;
248 values[i + 2].uint32 = *p;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400249 p++;
250 break;
251 case WL_ARGUMENT_STRING:
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400252 types[i + 2] = &ffi_type_pointer;
253 /* FIXME */
254 values[i + 2].uint32 = *p++;
255 break;
256 case WL_ARGUMENT_OBJECT:
257 types[i + 2] = &ffi_type_pointer;
258 object = wl_hash_lookup(&client->display->objects, *p);
259 if (object == NULL)
260 printf("unknown object (%d)\n", *p);
261 if (object->interface != method->arguments[i].data)
262 printf("wrong object type\n");
263 values[i + 2].object = object;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400264 p++;
265 break;
266 case WL_ARGUMENT_NEW_ID:
267 types[i + 2] = &ffi_type_uint32;
268 values[i + 2].new_id = *p;
269 object = wl_hash_lookup(&client->display->objects, *p);
270 if (object != NULL)
271 printf("object already exists (%d)\n", *p);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400272 p++;
273 break;
274 default:
275 printf("unknown type\n");
276 break;
277 }
278 args[i + 2] = &values[i + 2];
279 }
280
281 ffi_prep_cif(&cif, FFI_DEFAULT_ABI, method->argument_count + 2,
282 &ffi_type_uint32, types);
283 ffi_call(&cif, FFI_FN(method->func), &result, args);
284}
285
286static void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400287wl_client_event(struct wl_client *client, struct wl_object *object, uint32_t event)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400288{
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400289 uint32_t p[2];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400290
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400291 p[0] = object->id;
292 p[1] = event | (8 << 16);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400293 wl_connection_write(client->connection, p, sizeof p);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400294}
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400295
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400296#define WL_DISPLAY_INVALID_OBJECT 0
297#define WL_DISPLAY_INVALID_METHOD 1
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400298#define WL_DISPLAY_NO_MEMORY 2
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400299
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400300static void
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400301wl_client_connection_data(int fd, uint32_t mask, void *data)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400302{
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400303 struct wl_client *client = data;
304 struct wl_connection *connection = client->connection;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400305 const struct wl_method *method;
306 struct wl_object *object;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400307 uint32_t p[2], opcode, size;
308 uint32_t cmask = 0;
309 int len;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400310
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400311 if (mask & WL_EVENT_READABLE)
312 cmask |= WL_CONNECTION_READABLE;
313 if (mask & WL_EVENT_WRITEABLE)
314 cmask |= WL_CONNECTION_WRITABLE;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400315
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400316 len = wl_connection_data(connection, cmask);
317 if (len < 0) {
318 wl_client_destroy(client);
319 return;
320 }
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400321
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400322 while (len > sizeof p) {
323 wl_connection_copy(connection, p, sizeof p);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400324 opcode = p[1] & 0xffff;
325 size = p[1] >> 16;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400326 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400327 break;
328
329 object = wl_hash_lookup(&client->display->objects,
330 p[0]);
331 if (object == NULL) {
332 wl_client_event(client, &client->display->base,
333 WL_DISPLAY_INVALID_OBJECT);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400334 wl_connection_consume(connection, size);
335 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400336 continue;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400337 }
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400338
339 if (opcode >= object->interface->method_count) {
340 wl_client_event(client, &client->display->base,
341 WL_DISPLAY_INVALID_METHOD);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400342 wl_connection_consume(connection, size);
343 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400344 continue;
345 }
346
347 method = &object->interface->methods[opcode];
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400348 wl_client_demarshal(client, object, method, size);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400349 wl_connection_consume(connection, size);
350 len -= size;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400351 }
352}
353
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400354static int
355wl_client_connection_update(struct wl_connection *connection,
356 uint32_t mask, void *data)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400357{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400358 struct wl_client *client = data;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400359 uint32_t emask = 0;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400360
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400361 if (mask & WL_CONNECTION_READABLE)
362 emask |= WL_EVENT_READABLE;
363 if (mask & WL_CONNECTION_WRITABLE)
364 emask |= WL_EVENT_WRITEABLE;
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400365
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400366 return wl_event_loop_update_source(client->display->loop,
367 client->source, mask);
368}
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400369
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400370static void
371advertise_object(struct wl_client *client, struct wl_object *object)
372{
373 const struct wl_interface *interface;
374 static const char pad[4];
375 uint32_t length, p[2];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400376
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400377 interface = object->interface;
378 length = strlen(interface->name);
379 p[0] = object->id;
380 p[1] = length;
381 wl_connection_write(client->connection, p, sizeof p);
382 wl_connection_write(client->connection, interface->name, length);
383 wl_connection_write(client->connection, pad, -length & 3);
384}
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400385
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400386struct wl_client *
387wl_client_create(struct wl_display *display, int fd)
388{
389 struct wl_client *client;
390
391 client = malloc(sizeof *client);
392 if (client == NULL)
393 return NULL;
394
395 memset(client, 0, sizeof *client);
396 client->display = display;
397 client->source = wl_event_loop_add_fd(display->loop, fd,
398 WL_EVENT_READABLE,
399 wl_client_connection_data, client);
400 client->connection = wl_connection_create(fd,
401 wl_client_connection_update,
402 client);
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400403 wl_list_init(&client->object_list);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400404
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400405 wl_connection_write(client->connection,
406 &display->client_id_range,
407 sizeof display->client_id_range);
408 display->client_id_range += 256;
409
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400410 advertise_object(client, &display->base);
411
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500412 wl_list_insert(display->client_list.prev, &client->link);
413
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400414 return client;
415}
416
417void
418wl_client_destroy(struct wl_client *client)
419{
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400420 struct wl_object_ref *ref;
421
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400422 printf("disconnect from client %p\n", client);
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400423
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500424 wl_list_remove(&client->link);
425
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400426 while (client->object_list.next != &client->object_list) {
427 ref = container_of(client->object_list.next,
428 struct wl_object_ref, link);
429 wl_list_remove(&ref->link);
430 wl_surface_destroy(client, (struct wl_surface *) ref->object);
431 free(ref);
432 }
433
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400434 wl_event_loop_remove_source(client->display->loop, client->source);
435 wl_connection_destroy(client->connection);
436 free(client);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400437}
438
439static int
440wl_display_create_surface(struct wl_client *client,
441 struct wl_display *display, uint32_t id)
442{
443 struct wl_surface *surface;
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400444 struct wl_object_ref *ref;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400445
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400446 surface = wl_surface_create(display, id);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400447
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400448 ref = malloc(sizeof *ref);
449 if (ref == NULL) {
450 wl_client_event(client, &display->base,
451 WL_DISPLAY_NO_MEMORY);
452 return -1;
453 }
454
455 ref->object = &surface->base;
456 wl_hash_insert(&display->objects, &surface->base);
457 wl_list_insert(client->object_list.prev, &ref->link);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400458
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400459 return 0;
460}
461
462static const struct wl_argument create_surface_arguments[] = {
463 { WL_ARGUMENT_NEW_ID }
464};
465
466static const struct wl_method display_methods[] = {
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400467 { "create_surface", wl_display_create_surface,
468 ARRAY_LENGTH(create_surface_arguments), create_surface_arguments },
469};
470
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400471static const struct wl_event display_events[] = {
472 { "invalid_object" },
473 { "invalid_method" },
474};
475
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400476static const struct wl_interface display_interface = {
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400477 "display", 1,
478 ARRAY_LENGTH(display_methods), display_methods,
479 ARRAY_LENGTH(display_events), display_events,
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400480};
481
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500482static const char input_device_file[] =
483 "/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-mouse";
484
485static void
486wl_display_create_input_devices(struct wl_display *display)
487{
Kristian Høgsberg33a52bd2008-11-03 15:31:30 -0500488 const char *path;
489
490 path = getenv("WAYLAND_POINTER");
491 if (path == NULL)
492 path = input_device_file;
493
494 display->pointer = wl_input_device_create(display, path, 1);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500495
496 if (display->pointer != NULL)
497 wl_hash_insert(&display->objects, display->pointer);
498
499 display->pointer_x = 100;
500 display->pointer_y = 100;
501}
502
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400503struct wl_display *
504wl_display_create(void)
505{
506 struct wl_display *display;
507
508 display = malloc(sizeof *display);
509 if (display == NULL)
510 return NULL;
511
512 display->loop = wl_event_loop_create();
513 if (display->loop == NULL) {
514 free(display);
515 return NULL;
516 }
517
518 display->base.id = 0;
519 display->base.interface = &display_interface;
520 wl_hash_insert(&display->objects, &display->base);
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400521 wl_list_init(&display->surface_list);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500522 wl_list_init(&display->client_list);
523
524 wl_display_create_input_devices(display);
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400525
526 display->client_id_range = 256; /* Gah, arbitrary... */
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400527
528 return display;
529}
530
531void
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500532wl_display_send_event(struct wl_display *display, uint32_t *data, size_t size)
533{
534 struct wl_client *client;
535
536 client = container_of(display->client_list.next,
537 struct wl_client, link);
538 while (&client->link != &display->client_list) {
539 wl_connection_write(client->connection, data, size);
540
541 client = container_of(client->link.next,
542 struct wl_client, link);
543 }
544}
545
546#define WL_POINTER_MOTION 0
547#define WL_POINTER_BUTTON 1
548
549void
550wl_display_post_relative_event(struct wl_display *display,
551 struct wl_object *source, int dx, int dy)
552{
553 uint32_t p[4];
554
555 display->pointer_x += dx;
556 display->pointer_y += dy;
557
558 p[0] = source->id;
559 p[1] = (sizeof p << 16) | WL_POINTER_MOTION;
560 p[2] = display->pointer_x;
561 p[3] = display->pointer_y;
562
563 wl_display_send_event(display, p, sizeof p);
564}
565
566void
567wl_display_post_absolute_event(struct wl_display *display,
568 struct wl_object *source, int x, int y)
569{
570 uint32_t p[4];
571
572 display->pointer_x = x;
573 display->pointer_y = y;
574
575 p[0] = source->id;
576 p[1] = (sizeof p << 16) | WL_POINTER_MOTION;
577 p[2] = display->pointer_x;
578 p[3] = display->pointer_y;
579
580 wl_display_send_event(display, p, sizeof p);
581}
582
583void
584wl_display_post_button_event(struct wl_display *display,
585 struct wl_object *source, int button, int state)
586{
587 uint32_t p[4];
588
589 p[0] = source->id;
590 p[1] = (sizeof p << 16) | WL_POINTER_BUTTON;
591 p[2] = button;
592 p[3] = state;
593
594 wl_display_send_event(display, p, sizeof p);
595}
596
597void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400598wl_display_set_compositor(struct wl_display *display,
599 struct wl_compositor *compositor)
600{
601 display->compositor = compositor;
602}
603
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -0400604struct wl_event_loop *
605wl_display_get_event_loop(struct wl_display *display)
606{
607 return display->loop;
608}
609
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400610void
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400611wl_display_run(struct wl_display *display)
612{
613 while (1)
614 wl_event_loop_wait(display->loop);
615}
616
617/* The plan here is to generate a random anonymous socket name and
618 * advertise that through a service on the session dbus.
619 */
620static const char socket_name[] = "\0wayland";
621
622static void
623socket_data(int fd, uint32_t mask, void *data)
624{
625 struct wl_display *display = data;
626 struct sockaddr_un name;
627 socklen_t length;
628 int client_fd;
629
630 length = sizeof name;
631 client_fd = accept (fd, (struct sockaddr *) &name, &length);
632 if (client_fd < 0)
633 fprintf(stderr, "failed to accept\n");
634
635 wl_client_create(display, client_fd);
636}
637
638int
639wl_display_add_socket(struct wl_display *display)
640{
641 struct sockaddr_un name;
642 int sock;
643 socklen_t size;
644
645 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
646 if (sock < 0)
647 return -1;
648
649 name.sun_family = AF_LOCAL;
650 memcpy(name.sun_path, socket_name, sizeof socket_name);
651
652 size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
653 if (bind(sock, (struct sockaddr *) &name, size) < 0)
654 return -1;
655
656 if (listen(sock, 1) < 0)
657 return -1;
658
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400659 wl_event_loop_add_fd(display->loop, sock,
660 WL_EVENT_READABLE,
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400661 socket_data, display);
662
663 return 0;
664}
665
666
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400667struct wl_surface_iterator {
668 struct wl_list *head;
669 struct wl_surface *surface;
670 uint32_t mask;
671};
672
673struct wl_surface_iterator *
674wl_surface_iterator_create(struct wl_display *display, uint32_t mask)
675{
676 struct wl_surface_iterator *iterator;
677
678 iterator = malloc(sizeof *iterator);
679 if (iterator == NULL)
680 return NULL;
681
682 iterator->head = &display->surface_list;
683 iterator->surface = container_of(display->surface_list.next,
684 struct wl_surface, link);
685 iterator->mask = mask;
686
687 return iterator;
688}
689
690int
691wl_surface_iterator_next(struct wl_surface_iterator *iterator,
692 struct wl_surface **surface)
693{
694 if (&iterator->surface->link == iterator->head)
695 return 0;
696
697 *surface = iterator->surface;
698 iterator->surface = container_of(iterator->surface->link.next,
699 struct wl_surface, link);
700
701 return 1;
702}
703
704void
705wl_surface_iterator_destroy(struct wl_surface_iterator *iterator)
706{
707 free(iterator);
708}
709
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500710static int
711load_compositor(struct wl_display *display, const char *path)
712{
713 struct wl_compositor *(*create)(struct wl_display *display);
714 struct wl_compositor *compositor;
715 void *p;
716
717 p = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
718 if (p == NULL) {
719 fprintf(stderr, "failed to open compositor %s: %s\n",
720 path, dlerror());
721 return -1;
722 }
723
724 create = dlsym(p, "wl_compositor_create");
725 if (create == NULL) {
726 fprintf(stderr, "failed to look up compositor constructor\n");
727 return -1;
728 }
729
730 compositor = create(display);
731 if (compositor == NULL) {
732 fprintf(stderr, "couldn't create compositor\n");
733 return -1;
734 }
735
736 wl_display_set_compositor(display, compositor);
737
738 return 0;
739}
740
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400741int main(int argc, char *argv[])
742{
743 struct wl_display *display;
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500744 const char *compositor = "egl-compositor.so";
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400745
746 display = wl_display_create();
747
748 if (wl_display_add_socket(display)) {
749 fprintf(stderr, "failed to add socket: %m\n");
750 exit(EXIT_FAILURE);
751 }
752
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500753 if (argc == 2)
754 compositor = argv[1];
755 load_compositor(display, compositor);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400756
757 wl_display_run(display);
758
759 return 0;
760}