Hook up axis events.
[profile/ivi/weston.git] / src / compositor-wayland.c
index 48ccd0e..0f4d4ad 100644 (file)
@@ -59,6 +59,12 @@ struct wayland_compositor {
                uint32_t event_mask;
        } parent;
 
+       struct {
+               int32_t top, bottom, left, right;
+               GLuint texture;
+               int32_t width, height;
+       } border;
+
        struct wl_list input_list;
 };
 
@@ -80,6 +86,158 @@ struct wayland_input {
        struct wl_list link;
 };
 
+
+static int
+texture_border(struct wayland_output *output)
+{
+       struct wayland_compositor *c =
+               (struct wayland_compositor *) output->base.compositor;
+       GLfloat *d;
+       unsigned int *p;
+       int i, j, k, n;
+       GLfloat x[4], y[4], u[4], v[4];
+
+       x[0] = -c->border.left;
+       x[1] = 0;
+       x[2] = output->base.current->width;
+       x[3] = output->base.current->width + c->border.right;
+
+       y[0] = -c->border.top;
+       y[1] = 0;
+       y[2] = output->base.current->height;
+       y[3] = output->base.current->height + c->border.bottom;
+
+       u[0] = 0.0;
+       u[1] = (GLfloat) c->border.left / c->border.width;
+       u[2] = (GLfloat) (c->border.width - c->border.right) / c->border.width;
+       u[3] = 1.0;
+
+       v[0] = 0.0;
+       v[1] = (GLfloat) c->border.top / c->border.height;
+       v[2] = (GLfloat) (c->border.height - c->border.bottom) / c->border.height;
+       v[3] = 1.0;
+
+       n = 8;
+       d = wl_array_add(&c->base.vertices, n * 16 * sizeof *d);
+       p = wl_array_add(&c->base.indices, n * 6 * sizeof *p);
+
+       k = 0;
+       for (i = 0; i < 3; i++)
+               for (j = 0; j < 3; j++) {
+
+                       if (i == 1 && j == 1)
+                               continue;
+
+                       d[ 0] = x[i];
+                       d[ 1] = y[j];
+                       d[ 2] = u[i];
+                       d[ 3] = v[j];
+
+                       d[ 4] = x[i];
+                       d[ 5] = y[j + 1];
+                       d[ 6] = u[i];
+                       d[ 7] = v[j + 1];
+
+                       d[ 8] = x[i + 1];
+                       d[ 9] = y[j];
+                       d[10] = u[i + 1];
+                       d[11] = v[j];
+
+                       d[12] = x[i + 1];
+                       d[13] = y[j + 1];
+                       d[14] = u[i + 1];
+                       d[15] = v[j + 1];
+
+                       p[0] = k + 0;
+                       p[1] = k + 1;
+                       p[2] = k + 2;
+                       p[3] = k + 2;
+                       p[4] = k + 1;
+                       p[5] = k + 3;
+
+                       d += 16;
+                       p += 6;
+                       k += 4;
+               }
+
+       return k / 4;
+}
+
+static void
+draw_border(struct wayland_output *output)
+{
+       struct wayland_compositor *c =
+               (struct wayland_compositor *) output->base.compositor;
+       struct weston_shader *shader = &c->base.texture_shader;
+       GLfloat *v;
+       int n;
+
+       glDisable(GL_BLEND);
+       glUseProgram(shader->program);
+       c->base.current_shader = shader;
+
+       glUniformMatrix4fv(shader->proj_uniform,
+                          1, GL_FALSE, output->base.matrix.d);
+
+       glUniform1i(shader->tex_uniform, 0);
+       glUniform1f(shader->alpha_uniform, 1);
+       glUniform1f(shader->texwidth_uniform, 1);
+
+       n = texture_border(output);
+
+       glBindTexture(GL_TEXTURE_2D, c->border.texture);
+
+       v = c->base.vertices.data;
+       glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
+       glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
+       glEnableVertexAttribArray(0);
+       glEnableVertexAttribArray(1);
+
+       glDrawElements(GL_TRIANGLES, n * 6,
+                      GL_UNSIGNED_INT, c->base.indices.data);
+
+       glDisableVertexAttribArray(1);
+       glDisableVertexAttribArray(0);
+
+       c->base.vertices.size = 0;
+       c->base.indices.size = 0;
+}
+
+static void
+create_border(struct wayland_compositor *c)
+{
+       pixman_image_t *image;
+
+       image = load_image(DATADIR "/weston/border.png");
+       if (!image) {
+               fprintf(stderr, "could'nt load border image\n");
+               return;
+       }
+
+       c->border.width = pixman_image_get_width(image);
+       c->border.height = pixman_image_get_height(image);
+
+       glGenTextures(1, &c->border.texture);
+       glBindTexture(GL_TEXTURE_2D, c->border.texture);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
+                    c->border.width,
+                    c->border.height,
+                    0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
+                    pixman_image_get_data(image));
+
+       c->border.top = 25;
+       c->border.bottom = 50;
+       c->border.left = 25;
+       c->border.right = 25;
+
+       pixman_image_unref(image);
+}
+
 static int
 wayland_input_create(struct wayland_compositor *c)
 {
@@ -108,8 +266,7 @@ wayland_compositor_init_egl(struct wayland_compositor *c)
                EGL_RED_SIZE, 1,
                EGL_GREEN_SIZE, 1,
                EGL_BLUE_SIZE, 1,
-               EGL_ALPHA_SIZE, 0,
-               EGL_DEPTH_SIZE, 1,
+               EGL_ALPHA_SIZE, 1,
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                EGL_NONE
        };
@@ -162,10 +319,11 @@ wayland_compositor_init_egl(struct wayland_compositor *c)
 }
 
 static void
-frame_done(void *data, struct wl_callback *wl_callback, uint32_t time)
+frame_done(void *data, struct wl_callback *callback, uint32_t time)
 {
        struct weston_output *output = data;
 
+       wl_callback_destroy(callback);
        weston_output_finish_frame(output, time);
 }
 
@@ -174,7 +332,8 @@ static const struct wl_callback_listener frame_listener = {
 };
 
 static void
-wayland_output_repaint(struct weston_output *output_base)
+wayland_output_repaint(struct weston_output *output_base,
+                      pixman_region32_t *damage)
 {
        struct wayland_output *output = (struct wayland_output *) output_base;
        struct wayland_compositor *compositor =
@@ -189,7 +348,9 @@ wayland_output_repaint(struct weston_output *output_base)
        }
 
        wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
-               weston_surface_draw(surface, &output->base);
+               weston_surface_draw(surface, &output->base, damage);
+
+       draw_border(output);
 
        eglSwapBuffers(compositor->base.display, output->egl_surface);
        callback = wl_surface_frame(output->parent.surface);
@@ -198,20 +359,6 @@ wayland_output_repaint(struct weston_output *output_base)
        return;
 }
 
-static int
-wayland_output_prepare_scanout_surface(struct weston_output *output_base,
-                                      struct weston_surface *es)
-{
-       return -1;
-}
-
-static int
-wayland_output_set_cursor(struct weston_output *output_base,
-                         struct weston_input_device *input)
-{
-       return -1;
-}
-
 static void
 wayland_output_destroy(struct weston_output *output_base)
 {
@@ -248,12 +395,21 @@ wayland_compositor_create_output(struct wayland_compositor *c,
        weston_output_init(&output->base, &c->base, 0, 0, width, height,
                         WL_OUTPUT_FLIPPED);
 
+       output->base.border.top = c->border.top;
+       output->base.border.bottom = c->border.bottom;
+       output->base.border.left = c->border.left;
+       output->base.border.right = c->border.right;
+
+       weston_output_move(&output->base, 0, 0);
+
        output->parent.surface =
                wl_compositor_create_surface(c->parent.compositor);
        wl_surface_set_user_data(output->parent.surface, output);
 
        output->parent.egl_window =
-               wl_egl_window_create(output->parent.surface, width, height);
+               wl_egl_window_create(output->parent.surface,
+                                    width + c->border.left + c->border.right,
+                                    height + c->border.top + c->border.bottom);
        if (!output->parent.egl_window) {
                fprintf(stderr, "failure to create wl_egl_window\n");
                goto cleanup_output;
@@ -280,13 +436,11 @@ wayland_compositor_create_output(struct wayland_compositor *c,
        /* FIXME: add shell_surface listener for resizing */
        wl_shell_surface_set_toplevel(output->parent.shell_surface);
 
-       glClearColor(0, 0, 0, 0.5);
-
        output->base.repaint = wayland_output_repaint;
-       output->base.prepare_scanout_surface =
-               wayland_output_prepare_scanout_surface;
-       output->base.set_hardware_cursor = wayland_output_set_cursor;
        output->base.destroy = wayland_output_destroy;
+       output->base.assign_planes = NULL;
+       output->base.set_backlight = NULL;
+       output->base.set_dpms = NULL;
 
        wl_list_insert(c->base.output_list.prev, &output->base.link);
 
@@ -345,13 +499,13 @@ static const struct wl_output_listener output_listener = {
 /* parent input interface */
 static void
 input_handle_motion(void *data, struct wl_input_device *input_device,
-                    uint32_t time,
-                    int32_t x, int32_t y, int32_t sx, int32_t sy)
+                   uint32_t time, int32_t sx, int32_t sy)
 {
        struct wayland_input *input = data;
        struct wayland_compositor *c = input->compositor;
 
-       notify_motion(c->base.input_device, time, sx, sy);
+       notify_motion(c->base.input_device, time,
+                     sx - c->border.left, sy - c->border.top);
 }
 
 static void
@@ -366,6 +520,16 @@ input_handle_button(void *data,
 }
 
 static void
+input_handle_axis(void *data, struct wl_input_device *input_device,
+                       uint32_t time, uint32_t axis, int32_t value)
+{
+       struct wayland_input *input = data;
+       struct wayland_compositor *c = input->compositor;
+
+       notify_axis(c->base.input_device, time, axis, value);
+}
+
+static void
 input_handle_key(void *data, struct wl_input_device *input_device,
                  uint32_t time, uint32_t key, uint32_t state)
 {
@@ -376,50 +540,68 @@ input_handle_key(void *data, struct wl_input_device *input_device,
 }
 
 static void
-input_handle_pointer_focus(void *data,
-                           struct wl_input_device *input_device,
-                           uint32_t time, struct wl_surface *surface,
-                           int32_t x, int32_t y, int32_t sx, int32_t sy)
+input_handle_pointer_enter(void *data,
+                          struct wl_input_device *input_device,
+                          uint32_t time, struct wl_surface *surface,
+                          int32_t sx, int32_t sy)
 {
        struct wayland_input *input = data;
        struct wayland_output *output;
        struct wayland_compositor *c = input->compositor;
 
-       if (surface) {
-               output = wl_surface_get_user_data(surface);
-               notify_pointer_focus(c->base.input_device,
-                                    time, &output->base, sx, sy);
-       } else {
-               notify_pointer_focus(c->base.input_device, time, NULL, 0, 0);
-       }
+       output = wl_surface_get_user_data(surface);
+       notify_pointer_focus(c->base.input_device,
+                            time, &output->base, sx, sy);
+       wl_input_device_attach(input->input_device, time, NULL, 0, 0);
 }
 
 static void
-input_handle_keyboard_focus(void *data,
-                            struct wl_input_device *input_device,
-                            uint32_t time,
-                            struct wl_surface *surface,
-                            struct wl_array *keys)
+input_handle_pointer_leave(void *data,
+                          struct wl_input_device *input_device,
+                          uint32_t time, struct wl_surface *surface)
+{
+       struct wayland_input *input = data;
+       struct wayland_compositor *c = input->compositor;
+
+       notify_pointer_focus(c->base.input_device, time, NULL, 0, 0);
+}
+
+static void
+input_handle_keyboard_enter(void *data,
+                           struct wl_input_device *input_device,
+                           uint32_t time,
+                           struct wl_surface *surface,
+                           struct wl_array *keys)
 {
        struct wayland_input *input = data;
        struct wayland_compositor *c = input->compositor;
        struct wayland_output *output;
 
-       if (surface) {
-               output = wl_surface_get_user_data(surface);
-               notify_keyboard_focus(c->base.input_device,
-                                     time, &output->base, keys);
-       } else {
-               notify_keyboard_focus(c->base.input_device, time, NULL, NULL);
-       }
+       output = wl_surface_get_user_data(surface);
+       notify_keyboard_focus(c->base.input_device, time, &output->base, keys);
+}
+
+static void
+input_handle_keyboard_leave(void *data,
+                           struct wl_input_device *input_device,
+                           uint32_t time,
+                           struct wl_surface *surface)
+{
+       struct wayland_input *input = data;
+       struct wayland_compositor *c = input->compositor;
+
+       notify_keyboard_focus(c->base.input_device, time, NULL, NULL);
 }
 
 static const struct wl_input_device_listener input_device_listener = {
        input_handle_motion,
        input_handle_button,
+       input_handle_axis,
        input_handle_key,
-       input_handle_pointer_focus,
-       input_handle_keyboard_focus,
+       input_handle_pointer_enter,
+       input_handle_pointer_leave,
+       input_handle_keyboard_enter,
+       input_handle_keyboard_leave,
 };
 
 static void
@@ -498,7 +680,8 @@ wayland_destroy(struct weston_compositor *ec)
 }
 
 static struct weston_compositor *
-wayland_compositor_create(struct wl_display *display, int width, int height)
+wayland_compositor_create(struct wl_display *display,
+                         int width, int height, const char *display_name)
 {
        struct wayland_compositor *c;
        struct wl_event_loop *loop;
@@ -510,7 +693,7 @@ wayland_compositor_create(struct wl_display *display, int width, int height)
 
        memset(c, 0, sizeof *c);
 
-       c->parent.display = wl_display_connect(NULL);
+       c->parent.display = wl_display_connect(display_name);
 
        if (c->parent.display == NULL) {
                fprintf(stderr, "failed to create display: %m\n");
@@ -533,6 +716,7 @@ wayland_compositor_create(struct wl_display *display, int width, int height)
        if (weston_compositor_init(&c->base, display) < 0)
                return NULL;
 
+       create_border(c);
        if (wayland_compositor_create_output(c, width, height) < 0)
                return NULL;
 
@@ -551,28 +735,20 @@ wayland_compositor_create(struct wl_display *display, int width, int height)
        return &c->base;
 }
 
-struct weston_compositor *
-backend_init(struct wl_display *display, char *options);
-
 WL_EXPORT struct weston_compositor *
-backend_init(struct wl_display *display, char *options)
+backend_init(struct wl_display *display, int argc, char *argv[])
 {
-       int width = 1024, height = 640, i;
-       char *p, *value;
-
-       static char * const tokens[] = { "width", "height", NULL };
-       
-       p = options;
-       while (i = getsubopt(&p, tokens, &value), i != -1) {
-               switch (i) {
-               case 0:
-                       width = strtol(value, NULL, 0);
-                       break;
-               case 1:
-                       height = strtol(value, NULL, 0);
-                       break;
-               }
-       }
+       int width = 1024, height = 640;
+       char *display_name = NULL;
+
+       const struct weston_option wayland_options[] = {
+               { WESTON_OPTION_INTEGER, "width", 0, &width },
+               { WESTON_OPTION_INTEGER, "height", 0, &height },
+               { WESTON_OPTION_STRING, "display", 0, &display_name },
+       };
+
+       parse_options(wayland_options,
+                     ARRAY_LENGTH(wayland_options), argc, argv);
 
-       return wayland_compositor_create(display, width, height);
+       return wayland_compositor_create(display, width, height, display_name);
 }