blob: 26eebce202c1588aed36bcdf8a3749de4902d7ce [file] [log] [blame]
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05001/*
2 * Copyright © 2008 Kristian Høgsberg
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040023#include <stdlib.h>
24#include <stdint.h>
25#include <stddef.h>
26#include <stdio.h>
27#include <errno.h>
28#include <string.h>
29#include <unistd.h>
30#include <sys/socket.h>
31#include <sys/un.h>
32#include <ctype.h>
33#include <sys/poll.h>
34
Kristian Høgsberg427524a2008-10-08 13:32:07 -040035#include "connection.h"
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050036#include "wayland-util.h"
Kristian Høgsberg427524a2008-10-08 13:32:07 -040037#include "wayland-client.h"
38
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040039static const char socket_name[] = "\0wayland";
40
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050041struct wl_global {
42 uint32_t id;
43 char *interface;
44 struct wl_list link;
45};
46
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040047struct wl_proxy {
Kristian Høgsberg427524a2008-10-08 13:32:07 -040048 struct wl_display *display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040049 uint32_t id;
50};
51
52struct wl_display {
53 struct wl_proxy proxy;
Kristian Høgsberg427524a2008-10-08 13:32:07 -040054 struct wl_connection *connection;
55 int fd;
56 uint32_t id;
Kristian Høgsbergfb590842008-11-07 14:27:23 -050057 uint32_t mask;
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050058 struct wl_list global_list;
Kristian Høgsbergfb590842008-11-07 14:27:23 -050059
60 wl_display_update_func_t update;
61 void *update_data;
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -050062
63 wl_display_event_func_t event_handler;
64 void *event_handler_data;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040065};
66
67struct wl_surface {
68 struct wl_proxy proxy;
69};
70
Kristian Høgsbergfb590842008-11-07 14:27:23 -050071static int
72connection_update(struct wl_connection *connection,
73 uint32_t mask, void *data)
74{
75 struct wl_display *display = data;
76
77 display->mask = mask;
78 if (display->update)
79 return display->update(display->mask,
80 display->update_data);
81
82 return 0;
83}
84
Kristian Høgsbergb7a01922008-11-08 15:39:41 -050085WL_EXPORT struct wl_display *
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -050086wl_display_create(const char *name, size_t name_size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040087{
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040088 struct wl_display *display;
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050089 struct wl_global *global;
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -050090 struct sockaddr_un addr;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040091 socklen_t size;
92 char buffer[256];
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -050093 uint32_t id, length, count, i;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040094
Kristian Høgsberg427524a2008-10-08 13:32:07 -040095 display = malloc(sizeof *display);
96 if (display == NULL)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -040097 return NULL;
98
Kristian Høgsberg427524a2008-10-08 13:32:07 -040099 memset(display, 0, sizeof *display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400100 display->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
101 if (display->fd < 0) {
102 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400103 return NULL;
104 }
105
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500106 addr.sun_family = AF_LOCAL;
107 memcpy(addr.sun_path, name, name_size);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400108
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500109 size = offsetof (struct sockaddr_un, sun_path) + name_size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400110
Kristian Høgsbergdc0f3552008-12-07 15:22:22 -0500111 if (connect(display->fd, (struct sockaddr *) &addr, size) < 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400112 close(display->fd);
113 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400114 return NULL;
115 }
116
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400117 /* FIXME: We'll need a protocol for getting a new range, I
118 * guess... */
119 read(display->fd, &display->id, sizeof display->id);
120
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500121 read(display->fd, &count, sizeof count);
122
123 wl_list_init(&display->global_list);
124 for (i = 0; i < count; i++) {
125 /* FIXME: actually discover advertised objects here. */
126 read(display->fd, &id, sizeof id);
127 read(display->fd, &length, sizeof length);
128 read(display->fd, buffer, (length + 3) & ~3);
129
130 global = malloc(sizeof *global);
131 if (global == NULL)
132 return NULL;
133
134 global->id = id;
135 global->interface = malloc(length + 1);
136 memcpy(global->interface, buffer, length);
137 global->interface[length] = '\0';
138 wl_list_insert(display->global_list.prev, &global->link);
139 }
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400140
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400141 display->proxy.display = display;
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500142 display->proxy.id = wl_display_get_object_id(display, "display");
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400143
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400144 display->connection = wl_connection_create(display->fd,
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500145 connection_update,
146 display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400147
148 return display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400149}
150
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500151WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400152wl_display_destroy(struct wl_display *display)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400153{
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400154 wl_connection_destroy(display->connection);
155 close(display->fd);
156 free(display);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400157}
158
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500159WL_EXPORT uint32_t
160wl_display_get_object_id(struct wl_display *display, const char *interface)
161{
162 struct wl_global *global;
163
164 global = container_of(display->global_list.next,
165 struct wl_global, link);
166 while (&global->link != &display->global_list) {
167 if (strcmp(global->interface, interface) == 0)
168 return global->id;
169
170 global = container_of(global->link.next,
171 struct wl_global, link);
172 }
173
174 return 0;
175}
176
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500177WL_EXPORT int
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500178wl_display_get_fd(struct wl_display *display,
179 wl_display_update_func_t update, void *data)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400180{
Kristian Høgsbergfb590842008-11-07 14:27:23 -0500181 display->update = update;
182 display->update_data = data;
183
184 display->update(display->mask, display->update_data);
185
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400186 return display->fd;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400187}
188
189static void
Kristian Høgsberg40979232008-11-25 22:40:39 -0500190handle_event(struct wl_display *display,
191 uint32_t object, uint32_t opcode, uint32_t size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400192{
Kristian Høgsberg40979232008-11-25 22:40:39 -0500193 uint32_t p[10];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400194
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500195 wl_connection_copy(display->connection, p, size);
196 if (display->event_handler != NULL)
Kristian Høgsberg40979232008-11-25 22:40:39 -0500197 display->event_handler(display, object, opcode, size, p + 2,
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500198 display->event_handler_data);
199 wl_connection_consume(display->connection, size);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400200}
201
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500202WL_EXPORT void
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400203wl_display_iterate(struct wl_display *display, uint32_t mask)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400204{
Kristian Høgsberg40979232008-11-25 22:40:39 -0500205 uint32_t p[2], object, opcode, size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400206 int len;
207
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400208 len = wl_connection_data(display->connection, mask);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400209 while (len > 0) {
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400210 if (len < sizeof p)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400211 break;
212
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400213 wl_connection_copy(display->connection, p, sizeof p);
Kristian Høgsberg40979232008-11-25 22:40:39 -0500214 object = p[0];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400215 opcode = p[1] & 0xffff;
216 size = p[1] >> 16;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400217 if (len < size)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400218 break;
219
Kristian Høgsberg40979232008-11-25 22:40:39 -0500220 handle_event(display, object, opcode, size);
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500221 len -= size;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400222 }
223
224 if (len < 0) {
225 fprintf(stderr, "read error: %m\n");
226 exit(EXIT_FAILURE);
227 }
228}
229
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500230WL_EXPORT void
Kristian Høgsberg5a27f3e2008-11-02 10:55:25 -0500231wl_display_set_event_handler(struct wl_display *display,
232 wl_display_event_func_t handler,
233 void *data)
234{
235 /* FIXME: This needs something more generic... */
236 display->event_handler = handler;
237 display->event_handler_data = data;
238}
239
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500240WL_EXPORT uint32_t
241wl_display_allocate_id(struct wl_display *display)
242{
243 return display->id++;
244}
245
246WL_EXPORT void
247wl_display_write(struct wl_display *display, const void *data, size_t count)
248{
249 wl_connection_write(display->connection, data, count);
250}
251
Kristian Høgsberg40979232008-11-25 22:40:39 -0500252#define WL_DISPLAY_CREATE_SURFACE 0
253#define WL_DISPLAY_COMMIT 1
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400254
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500255WL_EXPORT struct wl_surface *
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400256wl_display_create_surface(struct wl_display *display)
257{
258 struct wl_surface *surface;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400259 uint32_t request[3];
260
261 surface = malloc(sizeof *surface);
262 if (surface == NULL)
263 return NULL;
264
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500265 surface->proxy.id = wl_display_allocate_id(display);
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400266 surface->proxy.display = display;
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400267
268 request[0] = display->proxy.id;
269 request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16);
270 request[2] = surface->proxy.id;
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400271 wl_connection_write(display->connection, request, sizeof request);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400272
273 return surface;
274}
275
Kristian Høgsberg40979232008-11-25 22:40:39 -0500276WL_EXPORT void
277wl_display_commit(struct wl_display *display, uint32_t key)
278{
279 uint32_t request[3];
280
281 request[0] = display->proxy.id;
282 request[1] = WL_DISPLAY_COMMIT | ((sizeof request) << 16);
283 request[2] = key;
284 wl_connection_write(display->connection, request, sizeof request);
285}
286
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400287#define WL_SURFACE_DESTROY 0
288#define WL_SURFACE_ATTACH 1
289#define WL_SURFACE_MAP 2
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500290#define WL_SURFACE_COPY 3
291#define WL_SURFACE_DAMAGE 4
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400292
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500293WL_EXPORT void
294wl_surface_destroy(struct wl_surface *surface)
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400295{
296 uint32_t request[2];
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400297
298 request[0] = surface->proxy.id;
299 request[1] = WL_SURFACE_DESTROY | ((sizeof request) << 16);
300
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400301 wl_connection_write(surface->proxy.display->connection,
302 request, sizeof request);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400303}
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400304
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500305WL_EXPORT void
306wl_surface_attach(struct wl_surface *surface, uint32_t name,
307 int32_t width, int32_t height, uint32_t stride)
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400308{
309 uint32_t request[6];
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400310
311 request[0] = surface->proxy.id;
312 request[1] = WL_SURFACE_ATTACH | ((sizeof request) << 16);
313 request[2] = name;
314 request[3] = width;
315 request[4] = height;
316 request[5] = stride;
317
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400318 wl_connection_write(surface->proxy.display->connection,
319 request, sizeof request);
Kristian Høgsberga67a71a2008-10-07 10:10:36 -0400320}
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400321
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500322WL_EXPORT void
323wl_surface_map(struct wl_surface *surface,
324 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400325{
326 uint32_t request[6];
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400327
328 request[0] = surface->proxy.id;
329 request[1] = WL_SURFACE_MAP | ((sizeof request) << 16);
330 request[2] = x;
331 request[3] = y;
332 request[4] = width;
333 request[5] = height;
334
Kristian Høgsberg427524a2008-10-08 13:32:07 -0400335 wl_connection_write(surface->proxy.display->connection,
336 request, sizeof request);
Kristian Høgsberg05eff512008-10-07 10:10:36 -0400337}
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500338
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500339WL_EXPORT void
340wl_surface_copy(struct wl_surface *surface, int32_t dst_x, int32_t dst_y,
341 uint32_t name, uint32_t stride,
342 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500343{
344 uint32_t request[10];
345
346 request[0] = surface->proxy.id;
347 request[1] = WL_SURFACE_COPY | ((sizeof request) << 16);
348 request[2] = dst_x;
349 request[3] = dst_y;
350 request[4] = name;
351 request[5] = stride;
352 request[6] = x;
353 request[7] = y;
354 request[8] = width;
355 request[9] = height;
356
357 wl_connection_write(surface->proxy.display->connection,
358 request, sizeof request);
359}
360
Kristian Høgsbergb7a01922008-11-08 15:39:41 -0500361WL_EXPORT void
362wl_surface_damage(struct wl_surface *surface,
363 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500364{
365 uint32_t request[6];
366
367 request[0] = surface->proxy.id;
368 request[1] = WL_SURFACE_DAMAGE | ((sizeof request) << 16);
369 request[2] = x;
370 request[3] = y;
371 request[4] = width;
372 request[5] = height;
373
374 wl_connection_write(surface->proxy.display->connection,
375 request, sizeof request);
376}