blob: 2e5bd18becf31369f8775fe49ccdd04102563207 [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
13static const char socket_name[] = "\0wayland";
14
15struct wl_buffer {
16 char data[4096];
17 int head, tail;
18};
19
20struct wl_connection {
21 int fd;
22 struct wl_buffer in, out;
23 struct wl_display *display;
24 uint32_t id;
25};
26
27struct wl_proxy {
28 struct wl_connection *connection;
29 uint32_t id;
30};
31
32struct wl_display {
33 struct wl_proxy proxy;
34};
35
36struct wl_surface {
37 struct wl_proxy proxy;
38};
39
40struct wl_connection *
41wl_connection_create(const char *address)
42{
43 struct wl_connection *connection;
44 struct wl_display *display;
45 struct sockaddr_un name;
46 socklen_t size;
47 char buffer[256];
48 uint32_t id, length;
49
50 connection = malloc(sizeof *connection);
51 if (connection == NULL)
52 return NULL;
53
54 memset(connection, 0, sizeof *connection);
55 connection->id = 256; /* Need to get our id-range. */
56 connection->fd = socket(PF_LOCAL, SOCK_STREAM, 0);
57 if (connection->fd < 0) {
58 free(connection);
59 return NULL;
60 }
61
62 name.sun_family = AF_LOCAL;
63 memcpy(name.sun_path, address, strlen(address + 1) + 2);
64
65 size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
66
67 if (connect (connection->fd, (struct sockaddr *) &name, size) < 0) {
68 close(connection->fd);
69 free(connection);
70 return NULL;
71 }
72
73 /* FIXME: actually discover advertised objects here. */
74 read(connection->fd, &id, sizeof id);
75 read(connection->fd, &length, sizeof length);
76 read(connection->fd, buffer, (length + 3) & ~3);
77
78 display = malloc(sizeof *display);
79 display->proxy.connection = connection;
80 display->proxy.id = id;
81 connection->display = display;
82
83 return connection;
84}
85
86void
87wl_connection_destroy(struct wl_connection *connection)
88{
89 close(connection->fd);
90 free(connection->display);
91 free(connection);
92}
93
94int
95wl_connection_get_fd(struct wl_connection *connection)
96{
97 return connection->fd;
98}
99
100static void
101handle_event(struct wl_connection *connection)
102{
103 struct wl_buffer *b;
104 uint32_t *p, opcode, size;
105
106 b = &connection->in;
107 p = (uint32_t *) (b->data + b->tail);
108 opcode = p[1] & 0xffff;
109 size = p[1] >> 16;
110 printf("signal from object %d, opcode %d, size %d\n",
111 p[0], opcode, size);
112 b->tail += size;
113}
114
115void
116wl_connection_iterate(struct wl_connection *connection)
117{
118 struct wl_buffer *b;
119 uint32_t *p, opcode, size;
120 int len;
121
122 b = &connection->in;
123 len = read(connection->fd, b->data + b->head, sizeof b->data);
124 b->head += len;
125 while (len > 0) {
126
127 if (b->head - b->tail < 8)
128 break;
129
130 p = (uint32_t *) (b->data + b->tail);
131 opcode = p[1] & 0xffff;
132 size = p[1] >> 16;
133 if (b->head - b->tail < size)
134 break;
135
136 handle_event(connection);
137 }
138
139 if (len < 0) {
140 fprintf(stderr, "read error: %m\n");
141 exit(EXIT_FAILURE);
142 }
143}
144
145int
146wl_connection_flush(struct wl_connection *connection)
147{
148 struct wl_buffer *b;
149 int len;
150
151 b = &connection->out;
152 if (b->head == b->tail)
153 return 0;
154
155 len = write(connection->fd, b->data + b->tail, b->head - b->tail);
156 b->tail += len;
157
158 return len;
159};
160
161struct wl_display *
162wl_connection_get_display(struct wl_connection *connection)
163{
164 return connection->display;
165}
166
167#define WL_DISPLAY_CREATE_SURFACE 0
168
169struct wl_surface *
170wl_display_create_surface(struct wl_display *display)
171{
172 struct wl_surface *surface;
173 struct wl_connection *connection;
174 uint32_t request[3];
175
176 surface = malloc(sizeof *surface);
177 if (surface == NULL)
178 return NULL;
179
180 connection = display->proxy.connection;
181 surface->proxy.id = connection->id++;
182 surface->proxy.connection = connection;
183
184 request[0] = display->proxy.id;
185 request[1] = WL_DISPLAY_CREATE_SURFACE | ((sizeof request) << 16);
186 request[2] = surface->proxy.id;
187
188 memcpy(connection->out.data + connection->out.head,
189 request, sizeof request);
190 connection->out.head += sizeof request;
191
192 return surface;
193}
194
195#define WL_SURFACE_ATTACH 0
196
197void wl_surface_attach(struct wl_surface *surface,
198 uint32_t name, int width, int height, int stride)
199{
200 uint32_t request[6];
201 struct wl_connection *connection;
202
203 request[0] = surface->proxy.id;
204 request[1] = WL_SURFACE_ATTACH | ((sizeof request) << 16);
205 request[2] = name;
206 request[3] = width;
207 request[4] = height;
208 request[5] = stride;
209
210 connection = surface->proxy.connection;
211 memcpy(connection->out.data + connection->out.head,
212 request, sizeof request);
213 connection->out.head += sizeof request;
214}