clients: Replace transformed with a toytoolkit implementation
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Fri, 30 Nov 2012 15:34:26 +0000 (17:34 +0200)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 30 Nov 2012 19:24:18 +0000 (14:24 -0500)
clients/Makefile.am
clients/transformed.c

index 5eae23a..5034aa6 100644 (file)
@@ -42,16 +42,11 @@ endif
 
 if BUILD_SIMPLE_EGL_CLIENTS
 simple_egl_clients_programs =                  \
-       simple-egl                              \
-       transformed
+       simple-egl
 
 simple_egl_SOURCES = simple-egl.c
 simple_egl_CPPFLAGS = $(SIMPLE_EGL_CLIENT_CFLAGS)
 simple_egl_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
-
-transformed_SOURCES = transformed.c
-transformed_CPPFLAGS = $(SIMPLE_EGL_CLIENT_CFLAGS)
-transformed_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
 endif
 
 if BUILD_CLIENTS
@@ -67,6 +62,7 @@ clients_programs =                            \
        eventdemo                               \
        clickdot                                \
        editor                                  \
+       transformed                             \
        $(full_gl_client_programs)
 
 desktop_shell = weston-desktop-shell
@@ -123,6 +119,9 @@ eventdemo_LDADD = $(toolkit_libs)
 clickdot_SOURCES = clickdot.c
 clickdot_LDADD = $(toolkit_libs)
 
+transformed_SOURCES = transformed.c
+transformed_LDADD = $(toolkit_libs)
+
 editor_SOURCES =                               \
        editor.c                                \
        text-protocol.c                         \
index 9c019fb..be840d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2011 Benjamin Franzke
+ * Copyright © 2008 Kristian Høgsberg
  * Copyright © 2012 Intel Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * OF THIS SOFTWARE.
  */
 
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdbool.h>
 #include <math.h>
-#include <assert.h>
-#include <signal.h>
+#include <cairo.h>
 
 #include <linux/input.h>
-
 #include <wayland-client.h>
-#include <wayland-egl.h>
-
-#include <GLES2/gl2.h>
-#include <EGL/egl.h>
-
-struct window;
-struct seat;
-
-struct display {
-       struct wl_display *display;
-       struct wl_registry *registry;
-       struct wl_compositor *compositor;
-       struct wl_shell *shell;
-       struct wl_seat *seat;
-       struct wl_pointer *pointer;
-       struct wl_keyboard *keyboard;
-       struct wl_shm *shm;
-       struct wl_list output_list;
-       struct {
-               EGLDisplay dpy;
-               EGLContext ctx;
-               EGLConfig conf;
-       } egl;
-       struct window *window;
-};
-
-struct output {
-       struct wl_output *output;
-       int transform;
-       struct wl_list link;
-};
+#include "window.h"
 
-struct geometry {
-       int width, height;
-};
-
-struct window {
+struct transformed {
        struct display *display;
-       struct geometry geometry, window_size;
-       struct {
-               GLuint fbo;
-               GLuint color_rbo;
-
-               GLuint transform_uniform;
-
-               GLuint pos;
-               GLuint col;
-       } gl;
-
-       struct output *output;
-       struct wl_egl_window *native;
-       struct wl_surface *surface;
-       struct wl_shell_surface *shell_surface;
-       EGLSurface egl_surface;
-       struct wl_callback *callback;
-       int fullscreen, configured;
-};
-
-static const char *vert_shader_text =
-       "uniform mat4 transform;\n"
-       "attribute vec4 pos;\n"
-       "attribute vec4 color;\n"
-       "varying vec4 v_color;\n"
-       "void main() {\n"
-       "  gl_Position = transform * pos;\n"
-       "  v_color = color;\n"
-       "}\n";
-
-static const char *frag_shader_text =
-       "precision mediump float;\n"
-       "varying vec4 v_color;\n"
-       "void main() {\n"
-       "  gl_FragColor = v_color;\n"
-       "}\n";
-
-static int running = 1;
-
-static void
-init_egl(struct display *display)
-{
-       static const EGLint context_attribs[] = {
-               EGL_CONTEXT_CLIENT_VERSION, 2,
-               EGL_NONE
-       };
-
-       EGLint config_attribs[] = {
-               EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-               EGL_RED_SIZE, 1,
-               EGL_GREEN_SIZE, 1,
-               EGL_BLUE_SIZE, 1,
-               EGL_ALPHA_SIZE, 0,
-               EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-               EGL_NONE
-       };
-
-       EGLint major, minor, n;
-       EGLBoolean ret;
-
-       display->egl.dpy = eglGetDisplay(display->display);
-       assert(display->egl.dpy);
-
-       ret = eglInitialize(display->egl.dpy, &major, &minor);
-       assert(ret == EGL_TRUE);
-       ret = eglBindAPI(EGL_OPENGL_ES_API);
-       assert(ret == EGL_TRUE);
-
-       ret = eglChooseConfig(display->egl.dpy, config_attribs,
-                             &display->egl.conf, 1, &n);
-       assert(ret && n == 1);
-
-       display->egl.ctx = eglCreateContext(display->egl.dpy,
-                                           display->egl.conf,
-                                           EGL_NO_CONTEXT, context_attribs);
-       assert(display->egl.ctx);
-
-}
-
-static void
-fini_egl(struct display *display)
-{
-       /* Required, otherwise segfault in egl_dri2.c: dri2_make_current()
-        * on eglReleaseThread(). */
-       eglMakeCurrent(display->egl.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
-                      EGL_NO_CONTEXT);
-
-       eglTerminate(display->egl.dpy);
-       eglReleaseThread();
-}
-
-static GLuint
-create_shader(struct window *window, const char *source, GLenum shader_type)
-{
-       GLuint shader;
-       GLint status;
-
-       shader = glCreateShader(shader_type);
-       assert(shader != 0);
-
-       glShaderSource(shader, 1, (const char **) &source, NULL);
-       glCompileShader(shader);
-
-       glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
-       if (!status) {
-               char log[1000];
-               GLsizei len;
-               glGetShaderInfoLog(shader, 1000, &len, log);
-               fprintf(stderr, "Error: compiling %s: %*s\n",
-                       shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
-                       len, log);
-               exit(1);
-       }
-
-       return shader;
-}
-
-static void
-init_gl(struct window *window)
-{
-       GLuint frag, vert;
-       GLuint program;
-       GLint status;
-
-       frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER);
-       vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER);
-
-       program = glCreateProgram();
-       glAttachShader(program, frag);
-       glAttachShader(program, vert);
-       glLinkProgram(program);
-
-       glGetProgramiv(program, GL_LINK_STATUS, &status);
-       if (!status) {
-               char log[1000];
-               GLsizei len;
-               glGetProgramInfoLog(program, 1000, &len, log);
-               fprintf(stderr, "Error: linking:\n%*s\n", len, log);
-               exit(1);
-       }
-
-       glUseProgram(program);
-
-       window->gl.pos = 0;
-       window->gl.col = 1;
-
-       glBindAttribLocation(program, window->gl.pos, "pos");
-       glBindAttribLocation(program, window->gl.col, "color");
-       glLinkProgram(program);
-
-       window->gl.transform_uniform =
-               glGetUniformLocation(program, "transform");
-}
-
-static void
-handle_ping(void *data, struct wl_shell_surface *shell_surface,
-           uint32_t serial)
-{
-       wl_shell_surface_pong(shell_surface, serial);
-}
-
-static void
-handle_configure(void *data, struct wl_shell_surface *shell_surface,
-                uint32_t edges, int32_t width, int32_t height)
-{
-       struct window *window = data;
-       int transform = WL_OUTPUT_TRANSFORM_NORMAL;
-       int32_t tmp;
-
-       window->geometry.width = width;
-       window->geometry.height = height;
-
-       if (!window->fullscreen)
-               window->window_size = window->geometry;
-
-       if (window->output)
-               transform = window->output->transform;
-
-       switch (transform) {
-       case WL_OUTPUT_TRANSFORM_90:
-       case WL_OUTPUT_TRANSFORM_270:
-       case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-       case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-               tmp = width;
-               width = height;
-               height = tmp;
-               break;
-       default:
-               break;
-       }
-
-       if (window->native)
-               wl_egl_window_resize(window->native, width, height, 0, 0);
-}
-
-static void
-handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
-{
-}
-
-static const struct wl_shell_surface_listener shell_surface_listener = {
-       handle_ping,
-       handle_configure,
-       handle_popup_done
-};
-
-static void
-toggle_fullscreen(struct window *window, int fullscreen);
-
-static void
-surface_enter(void *data, struct wl_surface *wl_surface,
-             struct wl_output *wl_output)
-{
-       struct window *window = data;
-       struct output *output = NULL;
-
-       wl_list_for_each(output, &window->display->output_list, link) {
-               if (output->output == wl_output)
-                       break;
-       }
-
-       if (output && output->output == wl_output) {
-               /* We use the output information only for rendering according
-                * to the output transform. Since we can't "please" two
-                * different outputs if they have a different transform, just
-                * do it according to the last output the surface entered. */
-               window->output = output;
-
-               /* Force a redraw with the new transform */
-               toggle_fullscreen(window, window->fullscreen);
-       }
-}
-
-static void
-surface_leave(void *data, struct wl_surface *wl_surface,
-             struct wl_output *wl_output)
-{
-       struct window *window = data;
-       struct output *output = NULL;
-
-       wl_list_for_each(output, &window->display->output_list, link) {
-               if (output->output == wl_output)
-                       break;
-       }
-
-       if (output && output->output == wl_output && output == window->output)
-               window->output = NULL;
-}
-
-static const struct wl_surface_listener surface_listener = {
-       surface_enter,
-       surface_leave
-};
-
-static void
-redraw(struct window *window);
-
-static void
-configure_callback(void *data, struct wl_callback *callback, uint32_t  time)
-{
-       struct window *window = data;
-
-       wl_callback_destroy(callback);
-
-       redraw(window);
-}
-
-static struct wl_callback_listener configure_callback_listener = {
-       configure_callback,
+       struct window *window;
+       struct widget *widget;
+       int width, height;
+       int fullscreen;
 };
 
 static void
-toggle_fullscreen(struct window *window, int fullscreen)
-{
-       struct wl_callback *callback;
-
-       window->fullscreen = fullscreen;
-
-       if (fullscreen) {
-               wl_shell_surface_set_fullscreen(window->shell_surface,
-                                               WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
-                                               0, NULL);
-       } else {
-               wl_shell_surface_set_toplevel(window->shell_surface);
-               handle_configure(window, window->shell_surface, 0,
-                                window->window_size.width,
-                                window->window_size.height);
-       }
-
-       callback = wl_display_sync(window->display->display);
-       wl_callback_add_listener(callback, &configure_callback_listener,
-                                window);
-}
-
-static void
-create_surface(struct window *window)
-{
-       struct display *display = window->display;
-       EGLBoolean ret;
-       
-       window->surface = wl_compositor_create_surface(display->compositor);
-       window->shell_surface = wl_shell_get_shell_surface(display->shell,
-                                                          window->surface);
-
-       wl_surface_add_listener(window->surface, &surface_listener, window);
-       wl_shell_surface_add_listener(window->shell_surface,
-                                     &shell_surface_listener, window);
-
-       window->native =
-               wl_egl_window_create(window->surface,
-                                    window->window_size.width,
-                                    window->window_size.height);
-       window->egl_surface =
-               eglCreateWindowSurface(display->egl.dpy,
-                                      display->egl.conf,
-                                      window->native, NULL);
-
-       wl_shell_surface_set_title(window->shell_surface, "simple-egl");
-
-       ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
-                            window->egl_surface, window->display->egl.ctx);
-       assert(ret == EGL_TRUE);
-
-       toggle_fullscreen(window, window->fullscreen);
-}
-
-static void
-destroy_surface(struct window *window)
-{
-       wl_egl_window_destroy(window->native);
-
-       wl_shell_surface_destroy(window->shell_surface);
-       wl_surface_destroy(window->surface);
-
-       if (window->callback)
-               wl_callback_destroy(window->callback);
-}
-
-static void
-update_transform(struct window *window)
+update_transform(cairo_t *cr, enum wl_output_transform transform)
 {
-       int transform = WL_OUTPUT_TRANSFORM_NORMAL;
-       int swap_w_h = 0;
-       int flip;
+       double angle;
 
-       GLfloat mat[4][4] = {
-               { 1, 0, 0, 0 },
-               { 0, 1, 0, 0 },
-               { 0, 0, 1, 0 },
-               { 0, 0, 0, 1 }
-       };
-
-
-       if (window->output)
-               transform = window->output->transform;
+       cairo_matrix_t m;
 
        switch(transform) {
        case WL_OUTPUT_TRANSFORM_FLIPPED:
        case WL_OUTPUT_TRANSFORM_FLIPPED_90:
        case WL_OUTPUT_TRANSFORM_FLIPPED_180:
        case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-               flip = -1;
+               cairo_matrix_init(&m, -1, 0, 0, 1, 0, 0);
                break;
        default:
-               flip = 1;
+               cairo_matrix_init_identity(&m);
                break;
        }
-
        switch (transform) {
        case WL_OUTPUT_TRANSFORM_NORMAL:
        case WL_OUTPUT_TRANSFORM_FLIPPED:
-               mat[0][0] = flip;
-               mat[0][1] = 0;
-               mat[1][0] = 0;
-               mat[1][1] = 1;
+       default:
+               angle = 0;
                break;
        case WL_OUTPUT_TRANSFORM_90:
        case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-               mat[0][0] = 0;
-               mat[0][1] = -flip;
-               mat[1][0] = 1;
-               mat[1][1] = 0;
-               swap_w_h = 1;
+               angle = M_PI_2;
                break;
        case WL_OUTPUT_TRANSFORM_180:
        case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-               mat[0][0] = -flip;
-               mat[0][1] = 0;
-               mat[1][0] = 0;
-               mat[1][1] = -1;
+               angle = M_PI;
                break;
        case WL_OUTPUT_TRANSFORM_270:
        case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-               mat[0][0] = 0;
-               mat[0][1] = flip;
-               mat[1][0] = -1;
-               mat[1][1] = 0;
-               swap_w_h = 1;
-               break;
-       default:
+               angle = M_PI + M_PI_2;
                break;
        }
 
-       if (swap_w_h)
-               glViewport(0, 0, window->geometry.height,
-                          window->geometry.width);
-       else
-               glViewport(0, 0, window->geometry.width,
-                          window->geometry.height);
-
-       glUniformMatrix4fv(window->gl.transform_uniform, 1, GL_FALSE,
-                          (GLfloat *) mat);
-       wl_surface_set_buffer_transform(window->surface, transform);
-       printf("Rendering buffer with transform == %d\n", transform);
+       cairo_rotate(cr, angle);
+       cairo_transform(cr, &m);
 }
 
 static void
-redraw(struct window *window)
+draw_stuff(cairo_surface_t *surface, int width, int height, int transform)
 {
-       static const GLfloat verts[8][2] = {
-               {  0.0,  0.0 },
-               {  0.0,  1.0 },
-               {  0.0,  0.0 },
-               {  1.0,  0.0 },
-               {  0.0,  0.0 },
-               { -1.0,  0.0 },
-               {  0.0,  0.0 },
-               {  0.0, -1.0 }
-       };
-       static const GLfloat colors[8][3] = {
-               { 1, 0, 0 },
-               { 1, 0, 0 },
-               { 0, 1, 0 },
-               { 0, 1, 0 },
-               { 1, 1, 1 },
-               { 1, 1, 1 },
-               { 1, 1, 1 },
-               { 1, 1, 1 }
-       };
-       struct wl_region *region;
-
-       update_transform(window);
-
-       glClearColor(0.0, 0.0, 0.0, 1.0);
-       glClear(GL_COLOR_BUFFER_BIT);
-
-       glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
-       glVertexAttribPointer(window->gl.col, 3, GL_FLOAT, GL_FALSE, 0, colors);
-       glEnableVertexAttribArray(window->gl.pos);
-       glEnableVertexAttribArray(window->gl.col);
-
-       glDrawArrays(GL_LINES, 0, 8);
-
-       glDisableVertexAttribArray(window->gl.pos);
-       glDisableVertexAttribArray(window->gl.col);
-
-       region = wl_compositor_create_region(window->display->compositor);
-       wl_region_add(region, 0, 0,
-                     window->geometry.width,
-                     window->geometry.height);
-       wl_surface_set_opaque_region(window->surface, region);
-       wl_region_destroy(region);
-
-       eglSwapBuffers(window->display->egl.dpy, window->egl_surface);
-}
+       cairo_t *cr;
+       int tmp;
 
-static void
-pointer_handle_enter(void *data, struct wl_pointer *pointer,
-                    uint32_t serial, struct wl_surface *surface,
-                    wl_fixed_t sx, wl_fixed_t sy)
-{
-       wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
-}
+       if (transform & 1) {
+               tmp = width;
+               width = height;
+               height = tmp;
+       }
 
-static void
-pointer_handle_leave(void *data, struct wl_pointer *pointer,
-                    uint32_t serial, struct wl_surface *surface)
-{
-}
+       cr = cairo_create(surface);
 
-static void
-pointer_handle_motion(void *data, struct wl_pointer *pointer,
-                     uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
-{
-}
+       cairo_identity_matrix(cr);
+       cairo_translate(cr, width / 2, height / 2);
+       cairo_scale(cr, width / 2, height / 2);
 
-static void
-pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
-                     uint32_t serial, uint32_t time, uint32_t button,
-                     uint32_t state)
-{
-}
+       update_transform(cr, transform);
 
-static void
-pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
-                   uint32_t time, uint32_t axis, wl_fixed_t value)
-{
-}
+       cairo_set_source_rgba(cr, 0, 0, 0.3, 1.0);
+       cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
+       cairo_rectangle(cr, -1, -1, 2, 2);
+       cairo_fill(cr);
 
-static const struct wl_pointer_listener pointer_listener = {
-       pointer_handle_enter,
-       pointer_handle_leave,
-       pointer_handle_motion,
-       pointer_handle_button,
-       pointer_handle_axis,
-};
+       cairo_set_source_rgb(cr, 1, 0, 0);
+       cairo_move_to(cr, 0,  0);
+       cairo_line_to(cr, 0, -1);
 
-static void
-keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
-                      uint32_t format, int fd, uint32_t size)
-{
-}
+       cairo_save(cr);
+       cairo_identity_matrix(cr);
+       cairo_set_line_width(cr, 2.0);
+       cairo_stroke(cr);
+       cairo_restore(cr);
 
-static void
-keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
-                     uint32_t serial, struct wl_surface *surface,
-                     struct wl_array *keys)
-{
-}
+       cairo_set_source_rgb(cr, 0, 1, 0);
+       cairo_move_to(cr, 0, 0);
+       cairo_line_to(cr, 1, 0);
 
-static void
-keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
-                     uint32_t serial, struct wl_surface *surface)
-{
-}
+       cairo_save(cr);
+       cairo_identity_matrix(cr);
+       cairo_set_line_width(cr, 2.0);
+       cairo_stroke(cr);
+       cairo_restore(cr);
 
-static void
-keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
-                   uint32_t serial, uint32_t time, uint32_t key,
-                   uint32_t state)
-{
-       struct display *d = data;
+       cairo_set_source_rgb(cr, 1, 1, 1);
+       cairo_move_to(cr, 0, 0);
+       cairo_line_to(cr, 0, 1);
+       cairo_move_to(cr,  0, 0);
+       cairo_line_to(cr, -1, 0);
+
+       cairo_save(cr);
+       cairo_identity_matrix(cr);
+       cairo_set_line_width(cr, 2.0);
+       cairo_stroke(cr);
+       cairo_restore(cr);
 
-       if (key == KEY_F11 && state)
-               toggle_fullscreen(d->window, d->window->fullscreen ^ 1);
-       else if (key == KEY_ESC && state)
-               running = 0;
+       cairo_destroy(cr);
 }
 
 static void
-keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
-                         uint32_t serial, uint32_t mods_depressed,
-                         uint32_t mods_latched, uint32_t mods_locked,
-                         uint32_t group)
+fullscreen_handler(struct window *window, void *data)
 {
-}
+       struct transformed *transformed = data;
 
-static const struct wl_keyboard_listener keyboard_listener = {
-       keyboard_handle_keymap,
-       keyboard_handle_enter,
-       keyboard_handle_leave,
-       keyboard_handle_key,
-       keyboard_handle_modifiers,
-};
+       transformed->fullscreen ^= 1;
+       window_set_fullscreen(window, transformed->fullscreen);
+}
 
 static void
-seat_handle_capabilities(void *data, struct wl_seat *seat,
-                        enum wl_seat_capability caps)
+redraw_handler(struct widget *widget, void *data)
 {
-       struct display *d = data;
-
-       if ((caps & WL_SEAT_CAPABILITY_POINTER) && !d->pointer) {
-               d->pointer = wl_seat_get_pointer(seat);
-               wl_pointer_add_listener(d->pointer, &pointer_listener, d);
-       } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && d->pointer) {
-               wl_pointer_destroy(d->pointer);
-               d->pointer = NULL;
-       }
+       struct transformed *transformed = data;
+       struct rectangle allocation;
+       cairo_surface_t *surface;
+       int transform;
 
-       if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
-               d->keyboard = wl_seat_get_keyboard(seat);
-               wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
-       } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
-               wl_keyboard_destroy(d->keyboard);
-               d->keyboard = NULL;
+       surface = window_get_surface(transformed->window);
+       if (surface == NULL ||
+           cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
+               fprintf(stderr, "failed to create cairo egl surface\n");
+               return;
        }
-}
 
-static const struct wl_seat_listener seat_listener = {
-       seat_handle_capabilities,
-};
+       widget_get_allocation(transformed->widget, &allocation);
+       transform = window_get_buffer_transform(transformed->window);
 
-static void
-output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
-                      int physical_width, int physical_height, int subpixel,
-                      const char *make, const char *model, int transform)
-{
-       struct output *output = data;
+       draw_stuff(surface, allocation.width, allocation.height, transform);
 
-       output->transform = transform;
+       cairo_surface_destroy(surface);
 }
 
 static void
-output_handle_mode(void *data, struct wl_output *output, uint32_t flags,
-                  int width, int height, int refresh)
+output_handler(struct window *window, struct output *output, int enter,
+              void *data)
 {
-}
-
-static const struct wl_output_listener output_listener = {
-       output_handle_geometry,
-       output_handle_mode
-};
+       if (!enter)
+               return;
 
-static void
-registry_handle_global(void *data, struct wl_registry *registry,
-                      uint32_t name, const char *interface, uint32_t version)
-{
-       struct display *d = data;
-
-       if (strcmp(interface, "wl_compositor") == 0) {
-               d->compositor =
-                       wl_registry_bind(registry, name,
-                                        &wl_compositor_interface, 1);
-       } else if (strcmp(interface, "wl_shell") == 0) {
-               d->shell = wl_registry_bind(registry, name,
-                                           &wl_shell_interface, 1);
-       } else if (strcmp(interface, "wl_seat") == 0) {
-               d->seat = wl_registry_bind(registry, name,
-                                          &wl_seat_interface, 1);
-               wl_seat_add_listener(d->seat, &seat_listener, d);
-       } else if (strcmp(interface, "wl_output") == 0) {
-               struct output *output = malloc(sizeof *output);
-
-               if (!output)
-                       return;
-
-               output->output = wl_registry_bind(registry, name,
-                                                 &wl_output_interface, 1);
-               wl_output_add_listener(output->output, &output_listener,
-                                      output);
-               wl_list_insert(&d->output_list, &output->link);
-       }
+       window_set_buffer_transform(window, output_get_transform(output));
+       window_schedule_redraw(window);
 }
 
-static const struct wl_registry_listener registry_listener = {
-       registry_handle_global
-};
-
-static void
-signal_int(int signum)
+static int
+motion_handler(struct widget *widget, struct input *input,
+              uint32_t time, float x, float y, void *data)
 {
-       running = 0;
+       return CURSOR_BLANK;
 }
 
 static void
-usage(int error_code)
+button_handler(struct widget *widget,
+              struct input *input, uint32_t time,
+              uint32_t button, enum wl_pointer_button_state state, void *data)
 {
-       fprintf(stderr, "Usage: simple-egl [OPTIONS]\n\n"
-               "  -f\tRun in fullscreen mode\n"
-               "  -h\tThis help text\n\n");
+       struct transformed *transformed = data;
 
-       exit(error_code);
+       switch (button) {
+       case BTN_LEFT:
+               if (state == WL_POINTER_BUTTON_STATE_PRESSED)
+                       window_move(transformed->window, input,
+                                   display_get_serial(transformed->display));
+               break;
+       case BTN_MIDDLE:
+               if (state == WL_POINTER_BUTTON_STATE_PRESSED)
+                       widget_schedule_redraw(widget);
+               break;
+       case BTN_RIGHT:
+               if (state == WL_POINTER_BUTTON_STATE_PRESSED)
+                       window_show_frame_menu(transformed->window, input, time);
+               break;
+       }
 }
 
-int
-main(int argc, char **argv)
+int main(int argc, char *argv[])
 {
-       struct sigaction sigint;
-       struct display display = { 0 };
-       struct window  window  = { 0 };
-       int i, ret = 0;
-
-       window.display = &display;
-       display.window = &window;
-       window.window_size.width  = 500;
-       window.window_size.height = 250;
-
-       wl_list_init(&display.output_list);
-
-       for (i = 1; i < argc; i++) {
-               if (strcmp("-f", argv[i]) == 0)
-                       window.fullscreen = 1;
-               else if (strcmp("-h", argv[i]) == 0)
-                       usage(EXIT_SUCCESS);
-               else
-                       usage(EXIT_FAILURE);
-       }
+       struct transformed transformed;
+       struct display *d;
 
-       display.display = wl_display_connect(NULL);
-       assert(display.display);
-
-       display.registry = wl_display_get_registry(display.display);
-       wl_registry_add_listener(display.registry,
-                                &registry_listener, &display);
-
-       wl_display_dispatch(display.display);
-
-       init_egl(&display);
-       create_surface(&window);
-       init_gl(&window);
-
-       sigint.sa_handler = signal_int;
-       sigemptyset(&sigint.sa_mask);
-       sigint.sa_flags = SA_RESETHAND;
-       sigaction(SIGINT, &sigint, NULL);
+       d = display_create(argc, argv);
+       if (d == NULL) {
+               fprintf(stderr, "failed to create display: %m\n");
+               return -1;
+       }
 
-       while (running && ret != -1)
-               ret = wl_display_dispatch(display.display);
+       transformed.width = 500;
+       transformed.height = 250;
+       transformed.display = d;
+       transformed.fullscreen = 0;
+       transformed.window = window_create(d);
+       transformed.widget =
+               window_add_widget(transformed.window, &transformed);
+       window_set_title(transformed.window, "Transformed");
 
-       fprintf(stderr, "simple-egl exiting\n");
+       widget_set_transparent(transformed.widget, 0);
 
-       destroy_surface(&window);
-       fini_egl(&display);
+       widget_set_redraw_handler(transformed.widget, redraw_handler);
+       widget_set_motion_handler(transformed.widget, motion_handler);
+       widget_set_button_handler(transformed.widget, button_handler);
 
-       if (display.shell)
-               wl_shell_destroy(display.shell);
+       window_set_fullscreen_handler(transformed.window, fullscreen_handler);
+       window_set_output_handler(transformed.window, output_handler);
 
-       if (display.compositor)
-               wl_compositor_destroy(display.compositor);
+       window_set_user_data(transformed.window, &transformed);
+       window_schedule_resize(transformed.window,
+                              transformed.width, transformed.height);
 
-       wl_display_flush(display.display);
-       wl_display_disconnect(display.display);
+       display_run(d);
 
        return 0;
 }