input: Rename wl_pointer to weston_pointer
[platform/upstream/weston.git] / src / compositor-wayland.c
index af493e7..d9d7530 100644 (file)
@@ -39,6 +39,7 @@
 #include "compositor.h"
 #include "gl-renderer.h"
 #include "../shared/image-loader.h"
+#include "../shared/os-compatibility.h"
 
 struct wayland_compositor {
        struct weston_compositor         base;
@@ -49,6 +50,7 @@ struct wayland_compositor {
                struct wl_compositor *compositor;
                struct wl_shell *shell;
                struct wl_output *output;
+               struct wl_shm *shm;
 
                struct {
                        int32_t x, y, width, height;
@@ -68,6 +70,7 @@ struct wayland_compositor {
 struct wayland_output {
        struct weston_output    base;
        struct {
+               int                      draw_initial_frame;
                struct wl_surface       *surface;
                struct wl_shell_surface *shell_surface;
                struct wl_egl_window    *egl_window;
@@ -127,6 +130,90 @@ static const struct wl_callback_listener frame_listener = {
 };
 
 static void
+buffer_release(void *data, struct wl_buffer *buffer)
+{
+       wl_buffer_destroy(buffer);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+       buffer_release
+};
+
+static void
+draw_initial_frame(struct wayland_output *output)
+{
+       struct wayland_compositor *c =
+               (struct wayland_compositor *) output->base.compositor;
+       struct wl_shm *shm = c->parent.shm;
+       struct wl_surface *surface = output->parent.surface;
+       struct wl_shm_pool *pool;
+       struct wl_buffer *buffer;
+
+       int width, height, stride;
+       int size;
+       int fd;
+       void *data;
+
+       width = output->mode.width + c->border.left + c->border.right;
+       height = output->mode.height + c->border.top + c->border.bottom;
+       stride = width * 4;
+       size = height * stride;
+
+       fd = os_create_anonymous_file(size);
+       if (fd < 0) {
+               perror("os_create_anonymous_file");
+               return;
+       }
+
+       data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+       if (data == MAP_FAILED) {
+               perror("mmap");
+               close(fd);
+               return;
+       }
+
+       pool = wl_shm_create_pool(shm, fd, size);
+
+       buffer = wl_shm_pool_create_buffer(pool, 0,
+                                          width, height,
+                                          stride,
+                                          WL_SHM_FORMAT_ARGB8888);
+       wl_buffer_add_listener(buffer, &buffer_listener, buffer);
+       wl_shm_pool_destroy(pool);
+       close(fd);
+
+       memset(data, 0, size);
+
+       wl_surface_attach(surface, buffer, 0, 0);
+
+       /* We only need to damage some part, as its only transparant
+        * pixels anyway. */
+       wl_surface_damage(surface, 0, 0, 1, 1);
+}
+
+static void
+wayland_output_start_repaint_loop(struct weston_output *output_base)
+{
+       struct wayland_output *output = (struct wayland_output *) output_base;
+       struct wl_callback *callback;
+
+       /* If this is the initial frame, we need to attach a buffer so that
+        * the compositor can map the surface and include it in its render
+        * loop. If the surface doesn't end up in the render loop, the frame
+        * callback won't be invoked. The buffer is transparent and of the
+        * same size as the future real output buffer. */
+       if (output->parent.draw_initial_frame) {
+               output->parent.draw_initial_frame = 0;
+
+               draw_initial_frame(output);
+       }
+
+       callback = wl_surface_frame(output->parent.surface);
+       wl_callback_add_listener(callback, &frame_listener, output);
+       wl_surface_commit(output->parent.surface);
+}
+
+static void
 wayland_output_repaint(struct weston_output *output_base,
                       pixman_region32_t *damage)
 {
@@ -204,6 +291,7 @@ wayland_compositor_create_output(struct wayland_compositor *c,
                        output->parent.egl_window) < 0)
                goto cleanup_window;
 
+       output->parent.draw_initial_frame = 1;
        output->parent.shell_surface =
                wl_shell_get_shell_surface(c->parent.shell,
                                           output->parent.surface);
@@ -212,6 +300,7 @@ wayland_compositor_create_output(struct wayland_compositor *c,
        wl_shell_surface_set_toplevel(output->parent.shell_surface);
 
        output->base.origin = output->base.current;
+       output->base.start_repaint_loop = wayland_output_start_repaint_loop;
        output->base.repaint = wayland_output_repaint;
        output->base.destroy = wayland_output_destroy;
        output->base.assign_planes = NULL;
@@ -361,8 +450,10 @@ input_handle_motion(void *data, struct wl_pointer *pointer,
        check_focus(input, x, y);
        if (input->focus)
                notify_motion(&input->base, time,
-                             x - wl_fixed_from_int(c->border.left),
-                             y - wl_fixed_from_int(c->border.top));
+                             x - wl_fixed_from_int(c->border.left) -
+                             input->base.seat.pointer->x,
+                             y - wl_fixed_from_int(c->border.top) -
+                             input->base.seat.pointer->y);
 }
 
 static void
@@ -578,6 +669,9 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
                                         &wl_shell_interface, 1);
        } else if (strcmp(interface, "wl_seat") == 0) {
                display_add_seat(c, name);
+       } else if (strcmp(interface, "wl_shm") == 0) {
+               c->parent.shm =
+                       wl_registry_bind(registry, name, &wl_shm_interface, 1);
        }
 }
 
@@ -612,17 +706,22 @@ wayland_restore(struct weston_compositor *ec)
 static void
 wayland_destroy(struct weston_compositor *ec)
 {
+       struct wayland_compositor *c = (struct wayland_compositor *) ec;
+
        ec->renderer->destroy(ec);
 
        weston_compositor_shutdown(ec);
 
+       if (c->parent.shm)
+               wl_shm_destroy(c->parent.shm);
+
        free(ec);
 }
 
 static struct weston_compositor *
 wayland_compositor_create(struct wl_display *display,
                          int width, int height, const char *display_name,
-                         int argc, char *argv[], const char *config_file)
+                         int *argc, char *argv[], const char *config_file)
 {
        struct wayland_compositor *c;
        struct wl_event_loop *loop;
@@ -697,7 +796,7 @@ err_free:
 }
 
 WL_EXPORT struct weston_compositor *
-backend_init(struct wl_display *display, int argc, char *argv[],
+backend_init(struct wl_display *display, int *argc, char *argv[],
             const char *config_file)
 {
        int width = 1024, height = 640;