blob: 5de66f7e5d1951842ad7e2717270d6cfa18987a0 [file] [log] [blame]
Kristian Høgsberga67a71a2008-10-07 10:10:36 -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 <ctype.h>
11#include <sys/poll.h>
12
Kristian Høgsberg427524a2008-10-08 13:32:07 -040013#include "connection.h"
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050014#include "wayland-util.h"
Kristian Høgsberg427524a2008-10-08 13:32:07 -040015#include "wayland-client.h"
16
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040017static const char socket_name[] = "\0wayland";
18
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050019struct wl_global {
20 uint32_t id;
21 char *interface;
22 struct wl_list link;
23};
24
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040025struct wl_proxy {
Kristian Høgsberg427524a2008-10-08 13:32:07 -040026 struct wl_display *display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040027 uint32_t id;
28};
29
30struct wl_display {
31 struct wl_proxy proxy;
Kristian Høgsberg427524a2008-10-08 13:32:07 -040032 struct wl_connection *connection;
33 int fd;
34 uint32_t id;
Kristian Høgsbergfb590842008-11-07 14:27:23 -050035 uint32_t mask;
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050036 struct wl_list global_list;
Kristian Høgsbergfb590842008-11-07 14:27:23 -050037
38 wl_display_update_func_t update;
39 void *update_data;
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -050040
41 wl_display_event_func_t event_handler;
42 void *event_handler_data;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040043};
44
45struct wl_surface {
46 struct wl_proxy proxy;
47};
48
Kristian Høgsbergfb590842008-11-07 14:27:23 -050049static int
50connection_update(struct wl_connection *connection,
51 uint32_t mask, void *data)
52{
53 struct wl_display *display = data;
54
55 display->mask = mask;
56 if (display->update)
57 return display->update(display->mask,
58 display->update_data);
59
60 return 0;
61}
62
Kristian Høgsbergb7a01922008-11-08 15:39:41 -050063WL_EXPORT struct wl_display *
Kristian Høgsbergfb590842008-11-07 14:27:23 -050064wl_display_create(const char *address)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040065{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040066 struct wl_display *display;
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050067 struct wl_global *global;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040068 struct sockaddr_un name;
69 socklen_t size;
70 char buffer[256];
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050071 uint32_t id, length, count, i;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040072
Kristian Høgsberg427524a2008-10-08 13:32:07 -040073 display = malloc(sizeof *display);
74 if (display == NULL)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040075 return NULL;
76
Kristian Høgsberg427524a2008-10-08 13:32:07 -040077 memset(display, 0, sizeof *display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -040078 display->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
79 if (display->fd < 0) {
80 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040081 return NULL;
82 }
83
84 name.sun_family = AF_LOCAL;
85 memcpy(name.sun_path, address, strlen(address + 1) + 2);
86
87 size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
88
Kristian Høgsberg427524a2008-10-08 13:32:07 -040089 if (connect(display->fd, (struct sockaddr *) &name, size) < 0) {
90 close(display->fd);
91 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040092 return NULL;
93 }
94
Kristian Høgsbergf9212892008-10-11 18:40:23 -040095 /* FIXME: We'll need a protocol for getting a new range, I
96 * guess... */
97 read(display->fd, &display->id, sizeof display->id);
98
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050099 read(display->fd, &count, sizeof count);
100
101 wl_list_init(&display->global_list);
102 for (i = 0; i < count; i++) {
103 /* FIXME: actually discover advertised objects here. */
104 read(display->fd, &id, sizeof id);
105 read(display->fd, &length, sizeof length);
106 read(display->fd, buffer, (length + 3) & ~3);
107
108 global = malloc(sizeof *global);
109 if (global == NULL)
110 return NULL;
111
112 global->id = id;
113 global->interface = malloc(length + 1);
114 memcpy(global->interface, buffer, length);
115 global->interface[length] = '\0';
116 wl_list_insert(display->global_list.prev, &global->link);
117 }
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400118
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400119 display->proxy.display = display;
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500120 display->proxy.id = wl_display_get_object_id(display, "display");
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400121
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400122 display->connection = wl_connection_create(display->fd,
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500123 connection_update,
124 display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400125
126 return display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400127}
128
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500129WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400130wl_display_destroy(struct wl_display *display)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400131{
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400132 wl_connection_destroy(display->connection);
133 close(display->fd);
134 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400135}
136
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500137WL_EXPORT uint32_t
138wl_display_get_object_id(struct wl_display *display, const char *interface)
139{
140 struct wl_global *global;
141
142 global = container_of(display->global_list.next,
143 struct wl_global, link);
144 while (&global->link != &display->global_list) {
145 if (strcmp(global->interface, interface) == 0)
146 return global->id;
147
148 global = container_of(global->link.next,
149 struct wl_global, link);
150 }
151
152 return 0;
153}
154
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500155WL_EXPORT int
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500156wl_display_get_fd(struct wl_display *display,
157 wl_display_update_func_t update, void *data)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400158{
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500159 display->update = update;
160 display->update_data = data;
161
162 display->update(display->mask, display->update_data);
163
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400164 return display->fd;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400165}
166
167static void
Kristian Høgsberg40979232008-11-25 22:40:39 -0500168handle_event(struct wl_display *display,
169 uint32_t object, uint32_t opcode, uint32_t size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400170{
Kristian Høgsberg40979232008-11-25 22:40:39 -0500171 uint32_t p[10];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400172
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500173 wl_connection_copy(display->connection, p, size);
174 if (display->event_handler != NULL)
Kristian Høgsberg40979232008-11-25 22:40:39 -0500175 display->event_handler(display, object, opcode, size, p + 2,
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500176 display->event_handler_data);
177 wl_connection_consume(display->connection, size);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400178}
179
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500180WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400181wl_display_iterate(struct wl_display *display, uint32_t mask)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400182{
Kristian Høgsberg40979232008-11-25 22:40:39 -0500183 uint32_t p[2], object, opcode, size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400184 int len;
185
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400186 len = wl_connection_data(display->connection, mask);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400187 while (len > 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400188 if (len < sizeof p)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400189 break;
190
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400191 wl_connection_copy(display->connection, p, sizeof p);
Kristian Høgsberg40979232008-11-25 22:40:39 -0500192 object = p[0];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400193 opcode = p[1] & 0xffff;
194 size = p[1] >> 16;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400195 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400196 break;
197
Kristian Høgsberg40979232008-11-25 22:40:39 -0500198 handle_event(display, object, opcode, size);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500199 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400200 }
201
202 if (len < 0) {
203 fprintf(stderr, "read error: %m\n");
204 exit(EXIT_FAILURE);
205 }
206}
207
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500208WL_EXPORT void
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500209wl_display_set_event_handler(struct wl_display *display,
210 wl_display_event_func_t handler,
211 void *data)
212{
213 /* FIXME: This needs something more generic... */
214 display->event_handler = handler;
215 display->event_handler_data = data;
216}
217
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500218WL_EXPORT uint32_t
219wl_display_allocate_id(struct wl_display *display)
220{
221 return display->id++;
222}
223
224WL_EXPORT void
225wl_display_write(struct wl_display *display, const void *data, size_t count)
226{
227 wl_connection_write(display->connection, data, count);
228}
229
Kristian Høgsberg40979232008-11-25 22:40:39 -0500230#define WL_DISPLAY_CREATE_SURFACE 0
231#define WL_DISPLAY_COMMIT 1
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400232
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500233WL_EXPORT struct wl_surface *
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400234wl_display_create_surface(struct wl_display *display)
235{
236 struct wl_surface *surface;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400237 uint32_t request[3];
238
239 surface = malloc(sizeof *surface);
240 if (surface == NULL)
241 return NULL;
242
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500243 surface->proxy.id = wl_display_allocate_id(display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400244 surface->proxy.display = display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400245
246 request[0] = display->proxy.id;
247 request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16);
248 request[2] = surface->proxy.id;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400249 wl_connection_write(display->connection, request, sizeof request);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400250
251 return surface;
252}
253
Kristian Høgsberg40979232008-11-25 22:40:39 -0500254WL_EXPORT void
255wl_display_commit(struct wl_display *display, uint32_t key)
256{
257 uint32_t request[3];
258
259 request[0] = display->proxy.id;
260 request[1] = WL_DISPLAY_COMMIT | ((sizeof request) << 16);
261 request[2] = key;
262 wl_connection_write(display->connection, request, sizeof request);
263}
264
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400265#define WL_SURFACE_DESTROY 0
266#define WL_SURFACE_ATTACH 1
267#define WL_SURFACE_MAP 2
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500268#define WL_SURFACE_COPY 3
269#define WL_SURFACE_DAMAGE 4
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400270
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500271WL_EXPORT void
272wl_surface_destroy(struct wl_surface *surface)
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400273{
274 uint32_t request[2];
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400275
276 request[0] = surface->proxy.id;
277 request[1] = WL_SURFACE_DESTROY | ((sizeof request) << 16);
278
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400279 wl_connection_write(surface->proxy.display->connection,
280 request, sizeof request);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400281}
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400282
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500283WL_EXPORT void
284wl_surface_attach(struct wl_surface *surface, uint32_t name,
285 int32_t width, int32_t height, uint32_t stride)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400286{
287 uint32_t request[6];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400288
289 request[0] = surface->proxy.id;
290 request[1] = WL_SURFACE_ATTACH | ((sizeof request) << 16);
291 request[2] = name;
292 request[3] = width;
293 request[4] = height;
294 request[5] = stride;
295
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400296 wl_connection_write(surface->proxy.display->connection,
297 request, sizeof request);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400298}
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400299
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500300WL_EXPORT void
301wl_surface_map(struct wl_surface *surface,
302 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400303{
304 uint32_t request[6];
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400305
306 request[0] = surface->proxy.id;
307 request[1] = WL_SURFACE_MAP | ((sizeof request) << 16);
308 request[2] = x;
309 request[3] = y;
310 request[4] = width;
311 request[5] = height;
312
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400313 wl_connection_write(surface->proxy.display->connection,
314 request, sizeof request);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400315}
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500316
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500317WL_EXPORT void
318wl_surface_copy(struct wl_surface *surface, int32_t dst_x, int32_t dst_y,
319 uint32_t name, uint32_t stride,
320 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500321{
322 uint32_t request[10];
323
324 request[0] = surface->proxy.id;
325 request[1] = WL_SURFACE_COPY | ((sizeof request) << 16);
326 request[2] = dst_x;
327 request[3] = dst_y;
328 request[4] = name;
329 request[5] = stride;
330 request[6] = x;
331 request[7] = y;
332 request[8] = width;
333 request[9] = height;
334
335 wl_connection_write(surface->proxy.display->connection,
336 request, sizeof request);
337}
338
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500339WL_EXPORT void
340wl_surface_damage(struct wl_surface *surface,
341 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500342{
343 uint32_t request[6];
344
345 request[0] = surface->proxy.id;
346 request[1] = WL_SURFACE_DAMAGE | ((sizeof request) << 16);
347 request[2] = x;
348 request[3] = y;
349 request[4] = width;
350 request[5] = height;
351
352 wl_connection_write(surface->proxy.display->connection,
353 request, sizeof request);
354}