blob: 0c1c75a1de0cc7aab0dc902ffb7874f66fd94847 [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
Kristian Høgsberg94a2e862008-10-11 21:37:55 -040015#define container_of(ptr, type, member) ({ \
16 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
17 (type *)( (char *)__mptr - offsetof(type,member) );})
18
19
Kristian Høgsbergf9212892008-10-11 18:40:23 -040020struct wl_list {
21 struct wl_list *prev;
22 struct wl_list *next;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040023};
24
Kristian Høgsbergf9212892008-10-11 18:40:23 -040025void wl_list_init(struct wl_list *list)
26{
27 list->prev = list;
28 list->next = list;
29}
30
31void
32wl_list_insert(struct wl_list *list, struct wl_list *elm)
33{
34 elm->prev = list;
35 elm->next = list->next;
36 list->next = elm;
37 elm->next->prev = elm;
38}
39
40void
41wl_list_remove(struct wl_list *elm)
42{
43 elm->prev->next = elm->next;
44 elm->next->prev = elm->prev;
45}
46
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040047struct wl_client {
Kristian Høgsberg680f1c72008-10-08 12:48:46 -040048 struct wl_connection *connection;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040049 struct wl_event_source *source;
50 struct wl_display *display;
Kristian Høgsberg94a2e862008-10-11 21:37:55 -040051 struct wl_list object_list;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050052 struct wl_list link;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040053};
54
55struct wl_display {
56 struct wl_object base;
57 struct wl_event_loop *loop;
58 struct wl_hash objects;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040059
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050060 struct wl_object *pointer;
61
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040062 struct wl_compositor *compositor;
63 struct wl_compositor_interface *compositor_interface;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040064
65 struct wl_list surface_list;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050066 struct wl_list client_list;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040067 uint32_t client_id_range;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050068
69 int32_t pointer_x;
70 int32_t pointer_y;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040071};
72
73struct wl_surface {
74 struct wl_object base;
75
76 /* provided by client */
77 int width, height;
78 int buffer;
79 int stride;
80
Kristian Høgsberg05eff512008-10-07 10:10:36 -040081 struct wl_map map;
Kristian Høgsbergf9212892008-10-11 18:40:23 -040082 struct wl_list link;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040083
84 /* how to convert buffer contents to pixels in screen format;
85 * yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */
86
87 /* how to transform/render rectangular contents to polygons. */
Kristian Høgsberg05eff512008-10-07 10:10:36 -040088
89 void *compositor_data;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -040090};
91
Kristian Høgsberg94a2e862008-10-11 21:37:55 -040092struct wl_object_ref {
93 struct wl_object *object;
94 struct wl_list link;
95};
Kristian Høgsberg05eff512008-10-07 10:10:36 -040096
97static void
98wl_surface_destroy(struct wl_client *client,
99 struct wl_surface *surface)
100{
101 struct wl_compositor_interface *interface;
102
103 interface = client->display->compositor->interface;
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400104 interface->notify_surface_destroy(client->display->compositor,
105 surface);
106 wl_list_remove(&surface->link);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400107}
108
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400109static void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400110wl_surface_attach(struct wl_client *client,
111 struct wl_surface *surface, uint32_t name,
112 uint32_t width, uint32_t height, uint32_t stride)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400113{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400114 struct wl_compositor_interface *interface;
115
116 interface = client->display->compositor->interface;
117 interface->notify_surface_attach(client->display->compositor,
118 surface, name, width, height, stride);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400119}
120
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400121static const struct wl_argument attach_arguments[] = {
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400122 { WL_ARGUMENT_UINT32 },
123 { WL_ARGUMENT_UINT32 },
124 { WL_ARGUMENT_UINT32 },
125 { WL_ARGUMENT_UINT32 },
126};
127
128void
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400129wl_surface_map(struct wl_client *client, struct wl_surface *surface,
130 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400131{
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400132 struct wl_compositor_interface *interface;
133
134 /* FIXME: This needs to take a tri-mesh argument... - count
135 * and a list of tris. 0 tris means unmap. */
136
137 surface->map.x = x;
138 surface->map.y = y;
139 surface->map.width = width;
140 surface->map.height = height;
141
142 interface = client->display->compositor->interface;
143 interface->notify_surface_map(client->display->compositor,
144 surface, &surface->map);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400145}
146
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400147static const struct wl_argument map_arguments[] = {
148 { WL_ARGUMENT_UINT32 },
149 { WL_ARGUMENT_UINT32 },
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400150 { WL_ARGUMENT_UINT32 },
151 { WL_ARGUMENT_UINT32 },
152};
153
154static const struct wl_method surface_methods[] = {
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400155 { "destroy", wl_surface_destroy,
156 0, NULL },
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400157 { "attach", wl_surface_attach,
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400158 ARRAY_LENGTH(attach_arguments), attach_arguments },
159 { "map", wl_surface_map,
160 ARRAY_LENGTH(map_arguments), map_arguments }
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400161};
162
163static const struct wl_interface surface_interface = {
164 "surface", 1,
165 ARRAY_LENGTH(surface_methods),
166 surface_methods,
167};
168
169struct wl_surface *
170wl_surface_create(struct wl_display *display, uint32_t id)
171{
172 struct wl_surface *surface;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400173 struct wl_compositor_interface *interface;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400174
175 surface = malloc(sizeof *surface);
176 if (surface == NULL)
177 return NULL;
178
179 surface->base.id = id;
180 surface->base.interface = &surface_interface;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400181
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400182 wl_list_insert(display->surface_list.prev, &surface->link);
183
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400184 interface = display->compositor->interface;
185 interface->notify_surface_create(display->compositor, surface);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400186
187 return surface;
188}
189
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400190void
191wl_surface_set_data(struct wl_surface *surface, void *data)
192{
193 surface->compositor_data = data;
194}
195
196void *
197wl_surface_get_data(struct wl_surface *surface)
198{
199 return surface->compositor_data;
200}
201
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400202void
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400203wl_client_destroy(struct wl_client *client);
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400204
205static void
206wl_client_demarshal(struct wl_client *client, struct wl_object *target,
207 const struct wl_method *method, size_t size)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400208{
209 ffi_type *types[10];
210 ffi_cif cif;
211 uint32_t *p, result;
212 int i;
213 union {
214 uint32_t uint32;
215 const char *string;
216 void *object;
217 uint32_t new_id;
218 } values[10];
219 void *args[10];
220 struct wl_object *object;
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400221 uint32_t data[64];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400222
223 if (method->argument_count > ARRAY_LENGTH(types)) {
224 printf("too many args (%d)\n", method->argument_count);
225 return;
226 }
227
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400228 if (sizeof data < size) {
229 printf("request too big, should malloc tmp buffer here\n");
230 return;
231 }
232
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400233 types[0] = &ffi_type_pointer;
234 values[0].object = client;
235 args[0] = &values[0];
236
237 types[1] = &ffi_type_pointer;
238 values[1].object = target;
239 args[1] = &values[1];
240
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400241 wl_connection_copy(client->connection, data, size);
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400242 p = &data[2];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400243 for (i = 0; i < method->argument_count; i++) {
244 switch (method->arguments[i].type) {
245 case WL_ARGUMENT_UINT32:
246 types[i + 2] = &ffi_type_uint32;
247 values[i + 2].uint32 = *p;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400248 p++;
249 break;
250 case WL_ARGUMENT_STRING:
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400251 types[i + 2] = &ffi_type_pointer;
252 /* FIXME */
253 values[i + 2].uint32 = *p++;
254 break;
255 case WL_ARGUMENT_OBJECT:
256 types[i + 2] = &ffi_type_pointer;
257 object = wl_hash_lookup(&client->display->objects, *p);
258 if (object == NULL)
259 printf("unknown object (%d)\n", *p);
260 if (object->interface != method->arguments[i].data)
261 printf("wrong object type\n");
262 values[i + 2].object = object;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400263 p++;
264 break;
265 case WL_ARGUMENT_NEW_ID:
266 types[i + 2] = &ffi_type_uint32;
267 values[i + 2].new_id = *p;
268 object = wl_hash_lookup(&client->display->objects, *p);
269 if (object != NULL)
270 printf("object already exists (%d)\n", *p);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400271 p++;
272 break;
273 default:
274 printf("unknown type\n");
275 break;
276 }
277 args[i + 2] = &values[i + 2];
278 }
279
280 ffi_prep_cif(&cif, FFI_DEFAULT_ABI, method->argument_count + 2,
281 &ffi_type_uint32, types);
282 ffi_call(&cif, FFI_FN(method->func), &result, args);
283}
284
285static void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400286wl_client_event(struct wl_client *client, struct wl_object *object, uint32_t event)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400287{
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400288 uint32_t p[2];
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400289
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400290 p[0] = object->id;
291 p[1] = event | (8 << 16);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400292 wl_connection_write(client->connection, p, sizeof p);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400293}
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400294
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400295#define WL_DISPLAY_INVALID_OBJECT 0
296#define WL_DISPLAY_INVALID_METHOD 1
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400297#define WL_DISPLAY_NO_MEMORY 2
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400298
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400299static void
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400300wl_client_connection_data(int fd, uint32_t mask, void *data)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400301{
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400302 struct wl_client *client = data;
303 struct wl_connection *connection = client->connection;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400304 const struct wl_method *method;
305 struct wl_object *object;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400306 uint32_t p[2], opcode, size;
307 uint32_t cmask = 0;
308 int len;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400309
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400310 if (mask & WL_EVENT_READABLE)
311 cmask |= WL_CONNECTION_READABLE;
312 if (mask & WL_EVENT_WRITEABLE)
313 cmask |= WL_CONNECTION_WRITABLE;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400314
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400315 len = wl_connection_data(connection, cmask);
316 if (len < 0) {
317 wl_client_destroy(client);
318 return;
319 }
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400320
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400321 while (len > sizeof p) {
322 wl_connection_copy(connection, p, sizeof p);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400323 opcode = p[1] & 0xffff;
324 size = p[1] >> 16;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400325 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400326 break;
327
328 object = wl_hash_lookup(&client->display->objects,
329 p[0]);
330 if (object == NULL) {
331 wl_client_event(client, &client->display->base,
332 WL_DISPLAY_INVALID_OBJECT);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400333 wl_connection_consume(connection, size);
334 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400335 continue;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400336 }
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400337
338 if (opcode >= object->interface->method_count) {
339 wl_client_event(client, &client->display->base,
340 WL_DISPLAY_INVALID_METHOD);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400341 wl_connection_consume(connection, size);
342 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400343 continue;
344 }
345
346 method = &object->interface->methods[opcode];
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400347 wl_client_demarshal(client, object, method, size);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400348 wl_connection_consume(connection, size);
349 len -= size;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400350 }
351}
352
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400353static int
354wl_client_connection_update(struct wl_connection *connection,
355 uint32_t mask, void *data)
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400356{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400357 struct wl_client *client = data;
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400358 uint32_t emask = 0;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400359
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400360 if (mask & WL_CONNECTION_READABLE)
361 emask |= WL_EVENT_READABLE;
362 if (mask & WL_CONNECTION_WRITABLE)
363 emask |= WL_EVENT_WRITEABLE;
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400364
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400365 return wl_event_loop_update_source(client->display->loop,
366 client->source, mask);
367}
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400368
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400369static void
370advertise_object(struct wl_client *client, struct wl_object *object)
371{
372 const struct wl_interface *interface;
373 static const char pad[4];
374 uint32_t length, p[2];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400375
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400376 interface = object->interface;
377 length = strlen(interface->name);
378 p[0] = object->id;
379 p[1] = length;
380 wl_connection_write(client->connection, p, sizeof p);
381 wl_connection_write(client->connection, interface->name, length);
382 wl_connection_write(client->connection, pad, -length & 3);
383}
Kristian Høgsbergc5089872008-10-08 10:47:59 -0400384
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400385struct wl_client *
386wl_client_create(struct wl_display *display, int fd)
387{
388 struct wl_client *client;
389
390 client = malloc(sizeof *client);
391 if (client == NULL)
392 return NULL;
393
394 memset(client, 0, sizeof *client);
395 client->display = display;
396 client->source = wl_event_loop_add_fd(display->loop, fd,
397 WL_EVENT_READABLE,
398 wl_client_connection_data, client);
399 client->connection = wl_connection_create(fd,
400 wl_client_connection_update,
401 client);
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400402 wl_list_init(&client->object_list);
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400403
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400404 wl_connection_write(client->connection,
405 &display->client_id_range,
406 sizeof display->client_id_range);
407 display->client_id_range += 256;
408
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400409 advertise_object(client, &display->base);
410
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500411 wl_list_insert(display->client_list.prev, &client->link);
412
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400413 return client;
414}
415
416void
417wl_client_destroy(struct wl_client *client)
418{
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400419 struct wl_object_ref *ref;
420
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400421 printf("disconnect from client %p\n", client);
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400422
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500423 wl_list_remove(&client->link);
424
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400425 while (client->object_list.next != &client->object_list) {
426 ref = container_of(client->object_list.next,
427 struct wl_object_ref, link);
428 wl_list_remove(&ref->link);
429 wl_surface_destroy(client, (struct wl_surface *) ref->object);
430 free(ref);
431 }
432
Kristian Høgsberg680f1c72008-10-08 12:48:46 -0400433 wl_event_loop_remove_source(client->display->loop, client->source);
434 wl_connection_destroy(client->connection);
435 free(client);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400436}
437
438static int
439wl_display_create_surface(struct wl_client *client,
440 struct wl_display *display, uint32_t id)
441{
442 struct wl_surface *surface;
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400443 struct wl_object_ref *ref;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400444
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400445 surface = wl_surface_create(display, id);
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400446
Kristian Høgsberg94a2e862008-10-11 21:37:55 -0400447 ref = malloc(sizeof *ref);
448 if (ref == NULL) {
449 wl_client_event(client, &display->base,
450 WL_DISPLAY_NO_MEMORY);
451 return -1;
452 }
453
454 ref->object = &surface->base;
455 wl_hash_insert(&display->objects, &surface->base);
456 wl_list_insert(client->object_list.prev, &ref->link);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400457
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400458 return 0;
459}
460
461static const struct wl_argument create_surface_arguments[] = {
462 { WL_ARGUMENT_NEW_ID }
463};
464
465static const struct wl_method display_methods[] = {
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400466 { "create_surface", wl_display_create_surface,
467 ARRAY_LENGTH(create_surface_arguments), create_surface_arguments },
468};
469
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400470static const struct wl_event display_events[] = {
471 { "invalid_object" },
472 { "invalid_method" },
473};
474
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400475static const struct wl_interface display_interface = {
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400476 "display", 1,
477 ARRAY_LENGTH(display_methods), display_methods,
478 ARRAY_LENGTH(display_events), display_events,
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400479};
480
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500481static const char input_device_file[] =
482 "/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-mouse";
483
484static void
485wl_display_create_input_devices(struct wl_display *display)
486{
487 display->pointer = wl_input_device_create(display, input_device_file, 1);
488
489 if (display->pointer != NULL)
490 wl_hash_insert(&display->objects, display->pointer);
491
492 display->pointer_x = 100;
493 display->pointer_y = 100;
494}
495
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400496struct wl_display *
497wl_display_create(void)
498{
499 struct wl_display *display;
500
501 display = malloc(sizeof *display);
502 if (display == NULL)
503 return NULL;
504
505 display->loop = wl_event_loop_create();
506 if (display->loop == NULL) {
507 free(display);
508 return NULL;
509 }
510
511 display->base.id = 0;
512 display->base.interface = &display_interface;
513 wl_hash_insert(&display->objects, &display->base);
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400514 wl_list_init(&display->surface_list);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500515 wl_list_init(&display->client_list);
516
517 wl_display_create_input_devices(display);
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400518
519 display->client_id_range = 256; /* Gah, arbitrary... */
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400520
521 return display;
522}
523
524void
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500525wl_display_send_event(struct wl_display *display, uint32_t *data, size_t size)
526{
527 struct wl_client *client;
528
529 client = container_of(display->client_list.next,
530 struct wl_client, link);
531 while (&client->link != &display->client_list) {
532 wl_connection_write(client->connection, data, size);
533
534 client = container_of(client->link.next,
535 struct wl_client, link);
536 }
537}
538
539#define WL_POINTER_MOTION 0
540#define WL_POINTER_BUTTON 1
541
542void
543wl_display_post_relative_event(struct wl_display *display,
544 struct wl_object *source, int dx, int dy)
545{
546 uint32_t p[4];
547
548 display->pointer_x += dx;
549 display->pointer_y += dy;
550
551 p[0] = source->id;
552 p[1] = (sizeof p << 16) | WL_POINTER_MOTION;
553 p[2] = display->pointer_x;
554 p[3] = display->pointer_y;
555
556 wl_display_send_event(display, p, sizeof p);
557}
558
559void
560wl_display_post_absolute_event(struct wl_display *display,
561 struct wl_object *source, int x, int y)
562{
563 uint32_t p[4];
564
565 display->pointer_x = x;
566 display->pointer_y = y;
567
568 p[0] = source->id;
569 p[1] = (sizeof p << 16) | WL_POINTER_MOTION;
570 p[2] = display->pointer_x;
571 p[3] = display->pointer_y;
572
573 wl_display_send_event(display, p, sizeof p);
574}
575
576void
577wl_display_post_button_event(struct wl_display *display,
578 struct wl_object *source, int button, int state)
579{
580 uint32_t p[4];
581
582 p[0] = source->id;
583 p[1] = (sizeof p << 16) | WL_POINTER_BUTTON;
584 p[2] = button;
585 p[3] = state;
586
587 wl_display_send_event(display, p, sizeof p);
588}
589
590void
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400591wl_display_set_compositor(struct wl_display *display,
592 struct wl_compositor *compositor)
593{
594 display->compositor = compositor;
595}
596
Kristian Høgsberg5ebb3172008-10-11 19:21:35 -0400597struct wl_event_loop *
598wl_display_get_event_loop(struct wl_display *display)
599{
600 return display->loop;
601}
602
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400603void
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400604wl_display_run(struct wl_display *display)
605{
606 while (1)
607 wl_event_loop_wait(display->loop);
608}
609
610/* The plan here is to generate a random anonymous socket name and
611 * advertise that through a service on the session dbus.
612 */
613static const char socket_name[] = "\0wayland";
614
615static void
616socket_data(int fd, uint32_t mask, void *data)
617{
618 struct wl_display *display = data;
619 struct sockaddr_un name;
620 socklen_t length;
621 int client_fd;
622
623 length = sizeof name;
624 client_fd = accept (fd, (struct sockaddr *) &name, &length);
625 if (client_fd < 0)
626 fprintf(stderr, "failed to accept\n");
627
628 wl_client_create(display, client_fd);
629}
630
631int
632wl_display_add_socket(struct wl_display *display)
633{
634 struct sockaddr_un name;
635 int sock;
636 socklen_t size;
637
638 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
639 if (sock < 0)
640 return -1;
641
642 name.sun_family = AF_LOCAL;
643 memcpy(name.sun_path, socket_name, sizeof socket_name);
644
645 size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
646 if (bind(sock, (struct sockaddr *) &name, size) < 0)
647 return -1;
648
649 if (listen(sock, 1) < 0)
650 return -1;
651
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400652 wl_event_loop_add_fd(display->loop, sock,
653 WL_EVENT_READABLE,
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400654 socket_data, display);
655
656 return 0;
657}
658
659
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400660struct wl_surface_iterator {
661 struct wl_list *head;
662 struct wl_surface *surface;
663 uint32_t mask;
664};
665
666struct wl_surface_iterator *
667wl_surface_iterator_create(struct wl_display *display, uint32_t mask)
668{
669 struct wl_surface_iterator *iterator;
670
671 iterator = malloc(sizeof *iterator);
672 if (iterator == NULL)
673 return NULL;
674
675 iterator->head = &display->surface_list;
676 iterator->surface = container_of(display->surface_list.next,
677 struct wl_surface, link);
678 iterator->mask = mask;
679
680 return iterator;
681}
682
683int
684wl_surface_iterator_next(struct wl_surface_iterator *iterator,
685 struct wl_surface **surface)
686{
687 if (&iterator->surface->link == iterator->head)
688 return 0;
689
690 *surface = iterator->surface;
691 iterator->surface = container_of(iterator->surface->link.next,
692 struct wl_surface, link);
693
694 return 1;
695}
696
697void
698wl_surface_iterator_destroy(struct wl_surface_iterator *iterator)
699{
700 free(iterator);
701}
702
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400703int main(int argc, char *argv[])
704{
705 struct wl_display *display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400706 struct wl_compositor *compositor;
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400707
708 display = wl_display_create();
709
710 if (wl_display_add_socket(display)) {
711 fprintf(stderr, "failed to add socket: %m\n");
712 exit(EXIT_FAILURE);
713 }
714
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400715 compositor = wl_compositor_create(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400716 wl_display_set_compositor(display, compositor);
717
Kristian Høgsberg97f1ebe2008-09-30 09:46:10 -0400718 printf("wayland online, display is %p\n", display);
719
720 wl_display_run(display);
721
722 return 0;
723}