blob: 16e97641e549caa8513f1ac7b19358b13a31810e [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øgsberg5a27f3e2008-11-02 10:55:25 -0500168handle_event(struct wl_display *display, uint32_t opcode, uint32_t size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400169{
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500170 uint32_t p[4];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400171
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500172 wl_connection_copy(display->connection, p, size);
173 if (display->event_handler != NULL)
174 display->event_handler(display, opcode, p[2], p[3],
175 display->event_handler_data);
176 wl_connection_consume(display->connection, size);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400177}
178
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500179WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400180wl_display_iterate(struct wl_display *display, uint32_t mask)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400181{
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400182 uint32_t p[2], opcode, size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400183 int len;
184
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400185 len = wl_connection_data(display->connection, mask);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400186 while (len > 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400187 if (len < sizeof p)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400188 break;
189
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400190 wl_connection_copy(display->connection, p, sizeof p);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400191 opcode = p[1] & 0xffff;
192 size = p[1] >> 16;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400193 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400194 break;
195
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500196 handle_event(display, opcode, size);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500197 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400198 }
199
200 if (len < 0) {
201 fprintf(stderr, "read error: %m\n");
202 exit(EXIT_FAILURE);
203 }
204}
205
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500206WL_EXPORT void
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500207wl_display_set_event_handler(struct wl_display *display,
208 wl_display_event_func_t handler,
209 void *data)
210{
211 /* FIXME: This needs something more generic... */
212 display->event_handler = handler;
213 display->event_handler_data = data;
214}
215
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500216WL_EXPORT uint32_t
217wl_display_allocate_id(struct wl_display *display)
218{
219 return display->id++;
220}
221
222WL_EXPORT void
223wl_display_write(struct wl_display *display, const void *data, size_t count)
224{
225 wl_connection_write(display->connection, data, count);
226}
227
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400228#define WL_DISPLAY_CREATE_SURFACE 0
229
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500230WL_EXPORT struct wl_surface *
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400231wl_display_create_surface(struct wl_display *display)
232{
233 struct wl_surface *surface;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400234 uint32_t request[3];
235
236 surface = malloc(sizeof *surface);
237 if (surface == NULL)
238 return NULL;
239
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500240 surface->proxy.id = wl_display_allocate_id(display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400241 surface->proxy.display = display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400242
243 request[0] = display->proxy.id;
244 request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16);
245 request[2] = surface->proxy.id;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400246 wl_connection_write(display->connection, request, sizeof request);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400247
248 return surface;
249}
250
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400251#define WL_SURFACE_DESTROY 0
252#define WL_SURFACE_ATTACH 1
253#define WL_SURFACE_MAP 2
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500254#define WL_SURFACE_COPY 3
255#define WL_SURFACE_DAMAGE 4
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400256
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500257WL_EXPORT void
258wl_surface_destroy(struct wl_surface *surface)
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400259{
260 uint32_t request[2];
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400261
262 request[0] = surface->proxy.id;
263 request[1] = WL_SURFACE_DESTROY | ((sizeof request) << 16);
264
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400265 wl_connection_write(surface->proxy.display->connection,
266 request, sizeof request);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400267}
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400268
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500269WL_EXPORT void
270wl_surface_attach(struct wl_surface *surface, uint32_t name,
271 int32_t width, int32_t height, uint32_t stride)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400272{
273 uint32_t request[6];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400274
275 request[0] = surface->proxy.id;
276 request[1] = WL_SURFACE_ATTACH | ((sizeof request) << 16);
277 request[2] = name;
278 request[3] = width;
279 request[4] = height;
280 request[5] = stride;
281
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400282 wl_connection_write(surface->proxy.display->connection,
283 request, sizeof request);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400284}
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400285
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500286WL_EXPORT void
287wl_surface_map(struct wl_surface *surface,
288 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400289{
290 uint32_t request[6];
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400291
292 request[0] = surface->proxy.id;
293 request[1] = WL_SURFACE_MAP | ((sizeof request) << 16);
294 request[2] = x;
295 request[3] = y;
296 request[4] = width;
297 request[5] = height;
298
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400299 wl_connection_write(surface->proxy.display->connection,
300 request, sizeof request);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400301}
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500302
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500303WL_EXPORT void
304wl_surface_copy(struct wl_surface *surface, int32_t dst_x, int32_t dst_y,
305 uint32_t name, uint32_t stride,
306 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500307{
308 uint32_t request[10];
309
310 request[0] = surface->proxy.id;
311 request[1] = WL_SURFACE_COPY | ((sizeof request) << 16);
312 request[2] = dst_x;
313 request[3] = dst_y;
314 request[4] = name;
315 request[5] = stride;
316 request[6] = x;
317 request[7] = y;
318 request[8] = width;
319 request[9] = height;
320
321 wl_connection_write(surface->proxy.display->connection,
322 request, sizeof request);
323}
324
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500325WL_EXPORT void
326wl_surface_damage(struct wl_surface *surface,
327 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500328{
329 uint32_t request[6];
330
331 request[0] = surface->proxy.id;
332 request[1] = WL_SURFACE_DAMAGE | ((sizeof request) << 16);
333 request[2] = x;
334 request[3] = y;
335 request[4] = width;
336 request[5] = height;
337
338 wl_connection_write(surface->proxy.display->connection,
339 request, sizeof request);
340}