Add README for the adventurous, allow evdev override from getenv().
[profile/ivi/wayland.git] / wayland-client.c
1 #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
13 #include "connection.h"
14 #include "wayland-client.h"
15
16 static const char socket_name[] = "\0wayland";
17
18 struct wl_proxy {
19         struct wl_display *display;
20         uint32_t id;
21 };
22
23 struct wl_display {
24         struct wl_proxy proxy;
25         struct wl_connection *connection;
26         int fd;
27         uint32_t id;
28
29         wl_display_event_func_t event_handler;
30         void *event_handler_data;
31 };
32
33 struct wl_surface {
34         struct wl_proxy proxy;
35 };
36
37 struct wl_display *
38 wl_display_create(const char *address,
39                   wl_connection_update_func_t update, void *data)
40 {
41         struct wl_display *display;
42         struct sockaddr_un name;
43         socklen_t size;
44         char buffer[256];
45         uint32_t id, length;
46
47         display = malloc(sizeof *display);
48         if (display == NULL)
49                 return NULL;
50
51         memset(display, 0, sizeof *display);
52         display->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
53         if (display->fd < 0) {
54                 free(display);
55                 return NULL;
56         }
57
58         name.sun_family = AF_LOCAL;
59         memcpy(name.sun_path, address, strlen(address + 1) + 2);
60
61         size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
62
63         if (connect(display->fd, (struct sockaddr *) &name, size) < 0) {
64                 close(display->fd);
65                 free(display);
66                 return NULL;
67         }
68
69         /* FIXME: We'll need a protocol for getting a new range, I
70          * guess... */
71         read(display->fd, &display->id, sizeof display->id);
72
73         /* FIXME: actually discover advertised objects here. */
74         read(display->fd, &id, sizeof id);
75         read(display->fd, &length, sizeof length);
76         read(display->fd, buffer, (length + 3) & ~3);
77
78         display->proxy.display = display;
79         display->proxy.id = id;
80
81         display->connection = wl_connection_create(display->fd,
82                                                    update, data);
83
84         return display;
85 }
86
87 void
88 wl_display_destroy(struct wl_display *display)
89 {
90         wl_connection_destroy(display->connection);
91         close(display->fd);
92         free(display);
93 }
94
95 int
96 wl_display_get_fd(struct wl_display *display)
97 {
98         return display->fd;
99 }
100
101 static void
102 handle_event(struct wl_display *display, uint32_t opcode, uint32_t size)
103 {
104         uint32_t p[4];
105
106         wl_connection_copy(display->connection, p, size);
107         if (display->event_handler != NULL)
108                 display->event_handler(display, opcode, p[2], p[3],
109                                        display->event_handler_data);
110         wl_connection_consume(display->connection, size);
111 }
112
113 void
114 wl_display_iterate(struct wl_display *display, uint32_t mask)
115 {
116         uint32_t p[2], opcode, size;
117         int len;
118
119         len = wl_connection_data(display->connection, mask);
120         while (len > 0) {
121                 if (len < sizeof p)
122                         break;
123                 
124                 wl_connection_copy(display->connection, p, sizeof p);
125                 opcode = p[1] & 0xffff;
126                 size = p[1] >> 16;
127                 if (len < size)
128                         break;
129
130                 handle_event(display, opcode, size);
131                 len -= size;
132         }
133
134         if (len < 0) {
135                 fprintf(stderr, "read error: %m\n");
136                 exit(EXIT_FAILURE);
137         }
138 }
139
140 void
141 wl_display_set_event_handler(struct wl_display *display,
142                              wl_display_event_func_t handler,
143                              void *data)
144 {
145         /* FIXME: This needs something more generic... */
146         display->event_handler = handler;
147         display->event_handler_data = data;
148 }
149
150 #define WL_DISPLAY_CREATE_SURFACE 0
151
152 struct wl_surface *
153 wl_display_create_surface(struct wl_display *display)
154 {
155         struct wl_surface *surface;
156         uint32_t request[3];
157
158         surface = malloc(sizeof *surface);
159         if (surface == NULL)
160                 return NULL;
161
162         surface->proxy.id = display->id++;
163         surface->proxy.display = display;
164
165         request[0] = display->proxy.id;
166         request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16);
167         request[2] = surface->proxy.id;
168         wl_connection_write(display->connection, request, sizeof request);
169
170         return surface;
171 }
172
173 #define WL_SURFACE_DESTROY      0
174 #define WL_SURFACE_ATTACH       1
175 #define WL_SURFACE_MAP          2
176
177 void wl_surface_destroy(struct wl_surface *surface)
178 {
179         uint32_t request[2];
180
181         request[0] = surface->proxy.id;
182         request[1] = WL_SURFACE_DESTROY | ((sizeof request) << 16);
183
184         wl_connection_write(surface->proxy.display->connection,
185                             request, sizeof request);
186 }
187
188 void wl_surface_attach(struct wl_surface *surface,
189                        uint32_t name, int width, int height, int stride)
190 {
191         uint32_t request[6];
192
193         request[0] = surface->proxy.id;
194         request[1] = WL_SURFACE_ATTACH | ((sizeof request) << 16);
195         request[2] = name;
196         request[3] = width;
197         request[4] = height;
198         request[5] = stride;
199
200         wl_connection_write(surface->proxy.display->connection,
201                             request, sizeof request);
202 }
203
204
205 void wl_surface_map(struct wl_surface *surface,
206                     int32_t x, int32_t y, int32_t width, int32_t height)
207 {
208         uint32_t request[6];
209
210         request[0] = surface->proxy.id;
211         request[1] = WL_SURFACE_MAP | ((sizeof request) << 16);
212         request[2] = x;
213         request[3] = y;
214         request[4] = width;
215         request[5] = height;
216
217         wl_connection_write(surface->proxy.display->connection,
218                             request, sizeof request);
219 }