14 #include "wayland-client.h"
16 static const char gem_device[] = "/dev/dri/card0";
17 static const char socket_name[] = "\0wayland";
19 static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
21 struct drm_i915_gem_create create;
22 struct drm_gem_flink flink;
23 struct drm_i915_gem_pwrite pwrite;
24 int32_t width, height, stride;
27 width = cairo_image_surface_get_width(surface);
28 height = cairo_image_surface_get_height(surface);
29 stride = cairo_image_surface_get_stride(surface);
30 data = cairo_image_surface_get_data(surface);
32 memset(&create, 0, sizeof(create));
33 create.size = height * stride;
35 if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
36 fprintf(stderr, "gem create failed: %m\n");
40 pwrite.handle = create.handle;
42 pwrite.size = height * stride;
43 pwrite.data_ptr = (uint64_t) (uintptr_t) data;
44 if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
45 fprintf(stderr, "gem pwrite failed: %m\n");
49 flink.handle = create.handle;
50 if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
51 fprintf(stderr, "gem flink failed: %m\n");
56 /* We need to hold on to the handle until the server has received
57 * the attach request... we probably need a confirmation event.
58 * I guess the breadcrumb idea will suffice. */
59 struct drm_gem_close close;
60 close.handle = create.handle;
61 if (ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) {
62 fprintf(stderr, "gem close failed: %m\n");
71 struct wl_surface *surface;
72 int x, y, width, height, stride;
73 int drag_x, drag_y, last_x, last_y;
81 draw_window(struct window *window)
83 cairo_surface_t *surface;
85 int border = 2, radius = 5;
86 int margin = (border + 1) / 2;
87 cairo_text_extents_t extents;
88 const static char title[] = "Wayland First Post";
90 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
94 cr = cairo_create(surface);
95 cairo_set_line_width (cr, border);
96 cairo_move_to(cr, margin, margin + radius);
97 cairo_arc(cr, margin + radius, margin + radius, radius,
99 cairo_line_to(cr, window->width - radius - margin, margin);
100 cairo_arc(cr, window->width - margin - radius, margin + radius, radius,
101 3 * M_PI / 2, 2 * M_PI);
102 cairo_line_to(cr, window->width - margin,
103 window->height - margin);
104 cairo_line_to(cr, margin, window->height - margin);
105 cairo_close_path(cr);
106 cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 0.9);
107 cairo_fill_preserve(cr);
108 cairo_set_source_rgba(cr, 0, 0, 0, 1);
109 cairo_set_font_size(cr, 14);
110 cairo_text_extents(cr, title, &extents);
111 cairo_move_to(cr, margin, margin + radius + extents.height + 10);
112 cairo_line_to(cr, margin + window->width, margin + radius + extents.height + 10);
115 cairo_move_to(cr, (window->width - extents.width) / 2, 10 - extents.y_bearing);
116 cairo_show_text(cr, title);
120 window->stride = cairo_image_surface_get_stride(surface);
122 window->name = name_cairo_surface(window->fd, surface);
123 cairo_surface_destroy(surface);
125 wl_surface_attach(window->surface, window->name,
126 window->width, window->height, window->stride);
128 wl_surface_map(window->surface,
129 window->x, window->y,
130 window->width, window->height);
136 connection_update(struct wl_connection *connection,
137 uint32_t mask, void *data)
139 struct pollfd *p = data;
142 if (mask & WL_CONNECTION_READABLE)
144 if (mask & WL_CONNECTION_WRITABLE)
145 p->events |= POLLOUT;
153 WINDOW_RESIZING_UPPER_LEFT,
154 WINDOW_RESIZING_UPPER_RIGHT,
155 WINDOW_RESIZING_LOWER_LEFT,
156 WINDOW_RESIZING_LOWER_RIGHT
162 LOCATION_UPPER_RIGHT,
164 LOCATION_LOWER_RIGHT,
168 void event_handler(struct wl_display *display,
170 uint32_t arg1, uint32_t arg2, void *data)
172 struct window *window = data;
173 int location, border = 4;
177 window->last_x = arg1;
178 window->last_y = arg2;
179 switch (window->state) {
181 window->x = window->drag_x + arg1;
182 window->y = window->drag_y + arg2;
183 wl_surface_map(window->surface, window->x, window->y,
184 window->width, window->height);
186 case WINDOW_RESIZING_LOWER_RIGHT:
187 window->width = window->drag_x + arg1;
188 window->height = window->drag_y + arg2;
189 window->need_redraw = 1;
194 if (window->x + border <= window->last_x &&
195 window->last_x < window->x + window->width - border &&
196 window->y + border <= window->last_y &&
197 window->last_y < window->y + window->height - border) {
198 location = LOCATION_INTERIOR;
199 } else if (window->x + window->width - grip_size <= window->last_x &&
200 window->last_x < window->x + window->width &&
201 window->y + window->height - grip_size <= window->last_y &&
202 window->last_y < window->y + window->height) {
203 location = LOCATION_LOWER_RIGHT;
205 location = LOCATION_OUTSIDE;
208 if (opcode == 1 && arg1 == 0 && arg2 == 1) {
210 case LOCATION_INTERIOR:
211 window->drag_x = window->x - window->last_x;
212 window->drag_y = window->y - window->last_y;
213 window->state = WINDOW_MOVING;
215 case LOCATION_LOWER_RIGHT:
216 window->drag_x = window->width - window->last_x;
217 window->drag_y = window->height - window->last_y;
218 window->state = WINDOW_RESIZING_LOWER_RIGHT;
221 window->state = WINDOW_STABLE;
224 } else if (opcode == 1 && arg1 == 0 && arg2 == 0) {
225 window->state = WINDOW_STABLE;
229 int main(int argc, char *argv[])
231 struct wl_display *display;
236 struct window window;
238 fd = open(gem_device, O_RDWR);
240 fprintf(stderr, "drm open failed: %m\n");
244 display = wl_display_create(socket_name,
245 connection_update, &p[0]);
246 if (display == NULL) {
247 fprintf(stderr, "failed to create display: %m\n");
250 p[0].fd = wl_display_get_fd(display);
252 window.surface = wl_display_create_surface(display);
257 window.state = WINDOW_STABLE;
260 s = draw_window(&window);
262 wl_display_set_event_handler(display, event_handler, &window);
264 while (ret = poll(p, 1, -1), ret >= 0) {
266 if (p[0].revents & POLLIN)
267 mask |= WL_CONNECTION_READABLE;
268 if (p[0].revents & POLLOUT)
269 mask |= WL_CONNECTION_WRITABLE;
271 wl_display_iterate(display, mask);
272 if (window.need_redraw) {
273 draw_window(&window);
274 window.need_redraw = 0;