Split the geometry information from weston_surface out into weston_view
authorJason Ekstrand <jason@jlekstrand.net>
Sun, 13 Oct 2013 03:38:11 +0000 (22:38 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 22 Oct 2013 20:34:11 +0000 (13:34 -0700)
The weston_surface structure is split into two structures:

 * The weston_surface structure storres everything required for a
   client-side or server-side surface.  This includes buffers; callbacks;
   backend private data; input, damage, and opaque regions; and a few other
   bookkeeping bits.

 * The weston_view structure represents an entity in the scenegraph and
   storres all of the geometry information.  This includes clip region,
   alpha, position, and the transformation list as well as all of the
   temporary information derived from the geometry state.  Because a view,
   and not a surface, is a scenegraph element, the view is what is placed
   in layers and planes.

There are a few things worth noting about the surface/view split:

 1. This is *not* a modification to the protocol.  It is, instead, a
    modification to Weston's internal scenegraph to allow a single surface
    to exist in multiple places at a time.  Clients are completely unaware
    of how many views to a particular surface exist.

 2. A view is considered a direct child of a surface and is destroyed when
    the surface is destroyed.  Because of this, the view.surface pointer is
    always valid and non-null.

 3. The compositor's surface_list is replaced with a view_list.  Due to
    subsurfaces, building the view list is a little more complicated than
    it used to be and involves building a tree of views on the fly whenever
    subsurfaces are used.  However, this means that backends can remain
    completely subsurface-agnostic.

 4. Surfaces and views both keep track of which outputs they are on.

 5. The weston_surface structure now has width and height fields.  These
    are populated when a new buffer is attached before surface.configure
    is called.  This is because there are many surface-based operations
    that really require the width and height and digging through the views
    didn't work well.

Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
17 files changed:
src/animation.c
src/compositor-drm.c
src/compositor.c
src/compositor.h
src/data-device.c
src/gl-renderer.c
src/input.c
src/pixman-renderer.c
src/rpi-renderer.c
src/shell.c
src/spring-tool.c
src/tablet-shell.c
src/xwayland/window-manager.c
src/zoom.c
tests/surface-global-test.c
tests/surface-test.c
tests/weston-test.c

index 909e243..5eacb7b 100644 (file)
@@ -34,7 +34,7 @@
 
 WL_EXPORT void
 weston_spring_init(struct weston_spring *spring,
-                double k, double current, double target)
+                  double k, double current, double target)
 {
        spring->k = k;
        spring->friction = 400.0;
@@ -114,52 +114,52 @@ weston_spring_done(struct weston_spring *spring)
                fabs(spring->current - spring->target) < 0.002;
 }
 
-typedef        void (*weston_surface_animation_frame_func_t)(struct weston_surface_animation *animation);
+typedef        void (*weston_view_animation_frame_func_t)(struct weston_view_animation *animation);
 
-struct weston_surface_animation {
-       struct weston_surface *surface;
+struct weston_view_animation {
+       struct weston_view *view;
        struct weston_animation animation;
        struct weston_spring spring;
        struct weston_transform transform;
        struct wl_listener listener;
        float start, stop;
-       weston_surface_animation_frame_func_t frame;
-       weston_surface_animation_frame_func_t reset;
-       weston_surface_animation_done_func_t done;
+       weston_view_animation_frame_func_t frame;
+       weston_view_animation_frame_func_t reset;
+       weston_view_animation_done_func_t done;
        void *data;
 };
 
 static void
-weston_surface_animation_destroy(struct weston_surface_animation *animation)
+weston_view_animation_destroy(struct weston_view_animation *animation)
 {
        wl_list_remove(&animation->animation.link);
        wl_list_remove(&animation->listener.link);
        wl_list_remove(&animation->transform.link);
        if (animation->reset)
                animation->reset(animation);
-       weston_surface_geometry_dirty(animation->surface);
+       weston_view_geometry_dirty(animation->view);
        if (animation->done)
                animation->done(animation, animation->data);
        free(animation);
 }
 
 static void
-handle_animation_surface_destroy(struct wl_listener *listener, void *data)
+handle_animation_view_destroy(struct wl_listener *listener, void *data)
 {
-       struct weston_surface_animation *animation =
+       struct weston_view_animation *animation =
                container_of(listener,
-                            struct weston_surface_animation, listener);
+                            struct weston_view_animation, listener);
 
-       weston_surface_animation_destroy(animation);
+       weston_view_animation_destroy(animation);
 }
 
 static void
-weston_surface_animation_frame(struct weston_animation *base,
-                              struct weston_output *output, uint32_t msecs)
+weston_view_animation_frame(struct weston_animation *base,
+                           struct weston_output *output, uint32_t msecs)
 {
-       struct weston_surface_animation *animation =
+       struct weston_view_animation *animation =
                container_of(base,
-                            struct weston_surface_animation, animation);
+                            struct weston_view_animation, animation);
 
        if (base->frame_counter <= 1)
                animation->spring.timestamp = msecs;
@@ -167,32 +167,32 @@ weston_surface_animation_frame(struct weston_animation *base,
        weston_spring_update(&animation->spring, msecs);
 
        if (weston_spring_done(&animation->spring)) {
-               weston_surface_animation_destroy(animation);
+               weston_view_animation_destroy(animation);
                return;
        }
 
        if (animation->frame)
                animation->frame(animation);
 
-       weston_surface_geometry_dirty(animation->surface);
-       weston_compositor_schedule_repaint(animation->surface->compositor);
+       weston_view_geometry_dirty(animation->view);
+       weston_view_schedule_repaint(animation->view);
 }
 
-static struct weston_surface_animation *
-weston_surface_animation_run(struct weston_surface *surface,
-                            float start, float stop,
-                            weston_surface_animation_frame_func_t frame,
-                            weston_surface_animation_frame_func_t reset,
-                            weston_surface_animation_done_func_t done,
-                            void *data)
+static struct weston_view_animation *
+weston_view_animation_run(struct weston_view *view,
+                         float start, float stop,
+                         weston_view_animation_frame_func_t frame,
+                         weston_view_animation_frame_func_t reset,
+                         weston_view_animation_done_func_t done,
+                         void *data)
 {
-       struct weston_surface_animation *animation;
+       struct weston_view_animation *animation;
 
        animation = malloc(sizeof *animation);
        if (!animation)
                return NULL;
 
-       animation->surface = surface;
+       animation->view = view;
        animation->frame = frame;
        animation->reset = reset;
        animation->done = done;
@@ -200,35 +200,35 @@ weston_surface_animation_run(struct weston_surface *surface,
        animation->start = start;
        animation->stop = stop;
        weston_matrix_init(&animation->transform.matrix);
-       wl_list_insert(&surface->geometry.transformation_list,
+       wl_list_insert(&view->geometry.transformation_list,
                       &animation->transform.link);
        weston_spring_init(&animation->spring, 200.0, 0.0, 1.0);
        animation->spring.friction = 700;
        animation->animation.frame_counter = 0;
-       animation->animation.frame = weston_surface_animation_frame;
-       weston_surface_animation_frame(&animation->animation, NULL, 0);
+       animation->animation.frame = weston_view_animation_frame;
+       weston_view_animation_frame(&animation->animation, NULL, 0);
 
-       animation->listener.notify = handle_animation_surface_destroy;
-       wl_signal_add(&surface->destroy_signal, &animation->listener);
+       animation->listener.notify = handle_animation_view_destroy;
+       wl_signal_add(&view->destroy_signal, &animation->listener);
 
-       wl_list_insert(&surface->output->animation_list,
+       wl_list_insert(&view->output->animation_list,
                       &animation->animation.link);
 
        return animation;
 }
 
 static void
-reset_alpha(struct weston_surface_animation *animation)
+reset_alpha(struct weston_view_animation *animation)
 {
-       struct weston_surface *surface = animation->surface;
+       struct weston_view *view = animation->view;
 
-       surface->alpha = animation->stop;
+       view->alpha = animation->stop;
 }
 
 static void
-zoom_frame(struct weston_surface_animation *animation)
+zoom_frame(struct weston_view_animation *animation)
 {
-       struct weston_surface *es = animation->surface;
+       struct weston_view *es = animation->view;
        float scale;
 
        scale = animation->start +
@@ -248,15 +248,15 @@ zoom_frame(struct weston_surface_animation *animation)
                es->alpha = 1.0;
 }
 
-WL_EXPORT struct weston_surface_animation *
-weston_zoom_run(struct weston_surface *surface, float start, float stop,
-               weston_surface_animation_done_func_t done, void *data)
+WL_EXPORT struct weston_view_animation *
+weston_zoom_run(struct weston_view *view, float start, float stop,
+               weston_view_animation_done_func_t done, void *data)
 {
-       struct weston_surface_animation *zoom;
+       struct weston_view_animation *zoom;
 
-       zoom = weston_surface_animation_run(surface, start, stop,
-                                           zoom_frame, reset_alpha,
-                                           done, data);
+       zoom = weston_view_animation_run(view, start, stop,
+                                        zoom_frame, reset_alpha,
+                                        done, data);
 
        weston_spring_init(&zoom->spring, 300.0, start, stop);
        zoom->spring.friction = 1400;
@@ -266,45 +266,45 @@ weston_zoom_run(struct weston_surface *surface, float start, float stop,
 }
 
 static void
-fade_frame(struct weston_surface_animation *animation)
+fade_frame(struct weston_view_animation *animation)
 {
        if (animation->spring.current > 0.999)
-               animation->surface->alpha = 1;
+               animation->view->alpha = 1;
        else if (animation->spring.current < 0.001 )
-               animation->surface->alpha = 0;
+               animation->view->alpha = 0;
        else
-               animation->surface->alpha = animation->spring.current;
+               animation->view->alpha = animation->spring.current;
 }
 
-WL_EXPORT struct weston_surface_animation *
-weston_fade_run(struct weston_surface *surface,
+WL_EXPORT struct weston_view_animation *
+weston_fade_run(struct weston_view *view,
                float start, float end, float k,
-               weston_surface_animation_done_func_t done, void *data)
+               weston_view_animation_done_func_t done, void *data)
 {
-       struct weston_surface_animation *fade;
+       struct weston_view_animation *fade;
 
-       fade = weston_surface_animation_run(surface, 0, end,
-                                           fade_frame, reset_alpha,
-                                           done, data);
+       fade = weston_view_animation_run(view, 0, end,
+                                        fade_frame, reset_alpha,
+                                        done, data);
 
        weston_spring_init(&fade->spring, k, start, end);
 
        fade->spring.friction = 1400;
        fade->spring.previous = -(end - start) * 0.03;
 
-       surface->alpha = start;
+       view->alpha = start;
 
        return fade;
 }
 
 WL_EXPORT void
-weston_fade_update(struct weston_surface_animation *fade, float target)
+weston_fade_update(struct weston_view_animation *fade, float target)
 {
        fade->spring.target = target;
 }
 
 static void
-slide_frame(struct weston_surface_animation *animation)
+slide_frame(struct weston_view_animation *animation)
 {
        float scale;
 
@@ -315,15 +315,15 @@ slide_frame(struct weston_surface_animation *animation)
        weston_matrix_translate(&animation->transform.matrix, 0, scale, 0);
 }
 
-WL_EXPORT struct weston_surface_animation *
-weston_slide_run(struct weston_surface *surface, float start, float stop,
-               weston_surface_animation_done_func_t done, void *data)
+WL_EXPORT struct weston_view_animation *
+weston_slide_run(struct weston_view *view, float start, float stop,
+                weston_view_animation_done_func_t done, void *data)
 {
-       struct weston_surface_animation *animation;
+       struct weston_view_animation *animation;
 
-       animation = weston_surface_animation_run(surface, start, stop,
-                                                slide_frame, NULL, done,
-                                                data);
+       animation = weston_view_animation_run(view, start, stop,
+                                             slide_frame, NULL, done,
+                                             data);
        if (!animation)
                return NULL;
 
index 60b4cba..e32e4a8 100644 (file)
@@ -156,7 +156,7 @@ struct drm_output {
        struct gbm_bo *cursor_bo[2];
        struct weston_plane cursor_plane;
        struct weston_plane fb_plane;
-       struct weston_surface *cursor_surface;
+       struct weston_view *cursor_view;
        int current_cursor;
        struct drm_fb *current, *next;
        struct backlight *backlight;
@@ -448,23 +448,23 @@ drm_output_check_scanout_format(struct drm_output *output,
 }
 
 static struct weston_plane *
-drm_output_prepare_scanout_surface(struct weston_output *_output,
-                                  struct weston_surface *es)
+drm_output_prepare_scanout_view(struct weston_output *_output,
+                               struct weston_view *ev)
 {
        struct drm_output *output = (struct drm_output *) _output;
        struct drm_compositor *c =
                (struct drm_compositor *) output->base.compositor;
-       struct weston_buffer *buffer = es->buffer_ref.buffer;
+       struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
        struct gbm_bo *bo;
        uint32_t format;
 
-       if (es->geometry.x != output->base.x ||
-           es->geometry.y != output->base.y ||
+       if (ev->geometry.x != output->base.x ||
+           ev->geometry.y != output->base.y ||
            buffer == NULL || c->gbm == NULL ||
            buffer->width != output->base.current_mode->width ||
            buffer->height != output->base.current_mode->height ||
-           output->base.transform != es->buffer_transform ||
-           es->transform.enabled)
+           output->base.transform != ev->surface->buffer_transform ||
+           ev->transform.enabled)
                return NULL;
 
        bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
@@ -474,7 +474,7 @@ drm_output_prepare_scanout_surface(struct weston_output *_output,
        if (!bo)
                return NULL;
 
-       format = drm_output_check_scanout_format(output, es, bo);
+       format = drm_output_check_scanout_format(output, ev->surface, bo);
        if (format == 0) {
                gbm_bo_destroy(bo);
                return NULL;
@@ -766,7 +766,7 @@ page_flip_handler(int fd, unsigned int frame,
 
 static uint32_t
 drm_output_check_sprite_format(struct drm_sprite *s,
-                              struct weston_surface *es, struct gbm_bo *bo)
+                              struct weston_view *ev, struct gbm_bo *bo)
 {
        uint32_t i, format;
 
@@ -776,9 +776,9 @@ drm_output_check_sprite_format(struct drm_sprite *s,
                pixman_region32_t r;
 
                pixman_region32_init_rect(&r, 0, 0,
-                                         es->geometry.width,
-                                         es->geometry.height);
-               pixman_region32_subtract(&r, &r, &es->opaque);
+                                         ev->geometry.width,
+                                         ev->geometry.height);
+               pixman_region32_subtract(&r, &r, &ev->surface->opaque);
 
                if (!pixman_region32_not_empty(&r))
                        format = GBM_FORMAT_XRGB8888;
@@ -794,15 +794,15 @@ drm_output_check_sprite_format(struct drm_sprite *s,
 }
 
 static int
-drm_surface_transform_supported(struct weston_surface *es)
+drm_view_transform_supported(struct weston_view *ev)
 {
-       return !es->transform.enabled ||
-               (es->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
+       return !ev->transform.enabled ||
+               (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
 }
 
 static struct weston_plane *
-drm_output_prepare_overlay_surface(struct weston_output *output_base,
-                                  struct weston_surface *es)
+drm_output_prepare_overlay_view(struct weston_output *output_base,
+                               struct weston_view *ev)
 {
        struct weston_compositor *ec = output_base->compositor;
        struct drm_compositor *c =(struct drm_compositor *) ec;
@@ -817,28 +817,28 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
        if (c->gbm == NULL)
                return NULL;
 
-       if (es->buffer_transform != output_base->transform)
+       if (ev->surface->buffer_transform != output_base->transform)
                return NULL;
 
-       if (es->buffer_scale != output_base->current_scale)
+       if (ev->surface->buffer_scale != output_base->current_scale)
                return NULL;
 
        if (c->sprites_are_broken)
                return NULL;
 
-       if (es->output_mask != (1u << output_base->id))
+       if (ev->output_mask != (1u << output_base->id))
                return NULL;
 
-       if (es->buffer_ref.buffer == NULL)
+       if (ev->surface->buffer_ref.buffer == NULL)
                return NULL;
 
-       if (es->alpha != 1.0f)
+       if (ev->alpha != 1.0f)
                return NULL;
 
-       if (wl_shm_buffer_get(es->buffer_ref.buffer->resource))
+       if (wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource))
                return NULL;
 
-       if (!drm_surface_transform_supported(es))
+       if (!drm_view_transform_supported(ev))
                return NULL;
 
        wl_list_for_each(s, &c->sprite_list, link) {
@@ -856,12 +856,12 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
                return NULL;
 
        bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
-                          es->buffer_ref.buffer->resource,
+                          ev->surface->buffer_ref.buffer->resource,
                           GBM_BO_USE_SCANOUT);
        if (!bo)
                return NULL;
 
-       format = drm_output_check_sprite_format(s, es, bo);
+       format = drm_output_check_sprite_format(s, ev, bo);
        if (format == 0) {
                gbm_bo_destroy(bo);
                return NULL;
@@ -873,9 +873,9 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
                return NULL;
        }
 
-       drm_fb_set_buffer(s->next, es->buffer_ref.buffer);
+       drm_fb_set_buffer(s->next, ev->surface->buffer_ref.buffer);
 
-       box = pixman_region32_extents(&es->transform.boundingbox);
+       box = pixman_region32_extents(&ev->transform.boundingbox);
        s->plane.x = box->x1;
        s->plane.y = box->y1;
 
@@ -885,7 +885,7 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
         * for us already).
         */
        pixman_region32_init(&dest_rect);
-       pixman_region32_intersect(&dest_rect, &es->transform.boundingbox,
+       pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox,
                                  &output_base->region);
        pixman_region32_translate(&dest_rect, -output_base->x, -output_base->y);
        box = pixman_region32_extents(&dest_rect);
@@ -901,36 +901,37 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
        pixman_region32_fini(&dest_rect);
 
        pixman_region32_init(&src_rect);
-       pixman_region32_intersect(&src_rect, &es->transform.boundingbox,
+       pixman_region32_intersect(&src_rect, &ev->transform.boundingbox,
                                  &output_base->region);
        box = pixman_region32_extents(&src_rect);
 
-       weston_surface_from_global_fixed(es,
-                                        wl_fixed_from_int(box->x1),
-                                        wl_fixed_from_int(box->y1),
-                                        &sx1, &sy1);
-       weston_surface_from_global_fixed(es,
-                                        wl_fixed_from_int(box->x2),
-                                        wl_fixed_from_int(box->y2),
-                                        &sx2, &sy2);
+       weston_view_from_global_fixed(ev,
+                                     wl_fixed_from_int(box->x1),
+                                     wl_fixed_from_int(box->y1),
+                                     &sx1, &sy1);
+       weston_view_from_global_fixed(ev,
+                                     wl_fixed_from_int(box->x2),
+                                     wl_fixed_from_int(box->y2),
+                                     &sx2, &sy2);
 
        if (sx1 < 0)
                sx1 = 0;
        if (sy1 < 0)
                sy1 = 0;
-       if (sx2 > wl_fixed_from_int(es->geometry.width))
-               sx2 = wl_fixed_from_int(es->geometry.width);
-       if (sy2 > wl_fixed_from_int(es->geometry.height))
-               sy2 = wl_fixed_from_int(es->geometry.height);
+       if (sx2 > wl_fixed_from_int(ev->geometry.width))
+               sx2 = wl_fixed_from_int(ev->geometry.width);
+       if (sy2 > wl_fixed_from_int(ev->geometry.height))
+               sy2 = wl_fixed_from_int(ev->geometry.height);
 
        tbox.x1 = sx1;
        tbox.y1 = sy1;
        tbox.x2 = sx2;
        tbox.y2 = sy2;
 
-       tbox = weston_transformed_rect(wl_fixed_from_int(es->geometry.width),
-                                      wl_fixed_from_int(es->geometry.height),
-                                      es->buffer_transform, es->buffer_scale, tbox);
+       tbox = weston_transformed_rect(wl_fixed_from_int(ev->geometry.width),
+                                      wl_fixed_from_int(ev->geometry.height),
+                                      ev->surface->buffer_transform,
+                                      ev->surface->buffer_scale, tbox);
 
        s->src_x = tbox.x1 << 8;
        s->src_y = tbox.y1 << 8;
@@ -942,8 +943,8 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
 }
 
 static struct weston_plane *
-drm_output_prepare_cursor_surface(struct weston_output *output_base,
-                                 struct weston_surface *es)
+drm_output_prepare_cursor_view(struct weston_output *output_base,
+                              struct weston_view *ev)
 {
        struct drm_compositor *c =
                (struct drm_compositor *) output_base->compositor;
@@ -953,18 +954,18 @@ drm_output_prepare_cursor_surface(struct weston_output *output_base,
                return NULL;
        if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
                return NULL;
-       if (output->cursor_surface)
+       if (output->cursor_view)
                return NULL;
-       if (es->output_mask != (1u << output_base->id))
+       if (ev->output_mask != (1u << output_base->id))
                return NULL;
        if (c->cursors_are_broken)
                return NULL;
-       if (es->buffer_ref.buffer == NULL ||
-           !wl_shm_buffer_get(es->buffer_ref.buffer->resource) ||
-           es->geometry.width > 64 || es->geometry.height > 64)
+       if (ev->surface->buffer_ref.buffer == NULL ||
+           !wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource) ||
+           ev->geometry.width > 64 || ev->geometry.height > 64)
                return NULL;
 
-       output->cursor_surface = es;
+       output->cursor_view = ev;
 
        return &output->cursor_plane;
 }
@@ -972,7 +973,7 @@ drm_output_prepare_cursor_surface(struct weston_output *output_base,
 static void
 drm_output_set_cursor(struct drm_output *output)
 {
-       struct weston_surface *es = output->cursor_surface;
+       struct weston_view *ev = output->cursor_view;
        struct drm_compositor *c =
                (struct drm_compositor *) output->base.compositor;
        EGLint handle, stride;
@@ -981,24 +982,24 @@ drm_output_set_cursor(struct drm_output *output)
        unsigned char *s;
        int i, x, y;
 
-       output->cursor_surface = NULL;
-       if (es == NULL) {
+       output->cursor_view = NULL;
+       if (ev == NULL) {
                drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
                return;
        }
 
-       if (es->buffer_ref.buffer &&
+       if (ev->surface->buffer_ref.buffer &&
            pixman_region32_not_empty(&output->cursor_plane.damage)) {
                pixman_region32_fini(&output->cursor_plane.damage);
                pixman_region32_init(&output->cursor_plane.damage);
                output->current_cursor ^= 1;
                bo = output->cursor_bo[output->current_cursor];
                memset(buf, 0, sizeof buf);
-               stride = wl_shm_buffer_get_stride(es->buffer_ref.buffer->shm_buffer);
-               s = wl_shm_buffer_get_data(es->buffer_ref.buffer->shm_buffer);
-               for (i = 0; i < es->geometry.height; i++)
+               stride = wl_shm_buffer_get_stride(ev->surface->buffer_ref.buffer->shm_buffer);
+               s = wl_shm_buffer_get_data(ev->surface->buffer_ref.buffer->shm_buffer);
+               for (i = 0; i < ev->geometry.height; i++)
                        memcpy(buf + i * 64, s + i * stride,
-                              es->geometry.width * 4);
+                              ev->geometry.width * 4);
 
                if (gbm_bo_write(bo, buf, sizeof buf) < 0)
                        weston_log("failed update cursor: %m\n");
@@ -1011,8 +1012,8 @@ drm_output_set_cursor(struct drm_output *output)
                }
        }
 
-       x = (es->geometry.x - output->base.x) * output->base.current_scale;
-       y = (es->geometry.y - output->base.y) * output->base.current_scale;
+       x = (ev->geometry.x - output->base.x) * output->base.current_scale;
+       y = (ev->geometry.y - output->base.y) * output->base.current_scale;
        if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
                if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y)) {
                        weston_log("failed to move cursor: %m\n");
@@ -1029,7 +1030,7 @@ drm_assign_planes(struct weston_output *output)
 {
        struct drm_compositor *c =
                (struct drm_compositor *) output->compositor;
-       struct weston_surface *es, *next;
+       struct weston_view *ev, *next;
        pixman_region32_t overlap, surface_overlap;
        struct weston_plane *primary, *next_plane;
 
@@ -1048,36 +1049,39 @@ drm_assign_planes(struct weston_output *output)
         */
        pixman_region32_init(&overlap);
        primary = &c->base.primary_plane;
-       wl_list_for_each_safe(es, next, &c->base.surface_list, link) {
+
+       /* Flag all visible surfaces as keep_buffer = 1 */
+       wl_list_for_each(ev, &c->base.view_list, link)
+               ev->surface->keep_buffer = 1;
+
+       wl_list_for_each_safe(ev, next, &c->base.view_list, link) {
                /* test whether this buffer can ever go into a plane:
                 * non-shm, or small enough to be a cursor
                 */
-               if ((es->buffer_ref.buffer &&
-                    !wl_shm_buffer_get(es->buffer_ref.buffer->resource)) ||
-                   (es->geometry.width <= 64 && es->geometry.height <= 64))
-                       es->keep_buffer = 1;
-               else
-                       es->keep_buffer = 0;
+               if (!ev->surface->buffer_ref.buffer ||
+                   (wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource) &&
+                   (ev->geometry.width > 64 || ev->geometry.height > 64)))
+                       ev->surface->keep_buffer = 0;
 
                pixman_region32_init(&surface_overlap);
                pixman_region32_intersect(&surface_overlap, &overlap,
-                                         &es->transform.boundingbox);
+                                         &ev->transform.boundingbox);
 
                next_plane = NULL;
                if (pixman_region32_not_empty(&surface_overlap))
                        next_plane = primary;
                if (next_plane == NULL)
-                       next_plane = drm_output_prepare_cursor_surface(output, es);
+                       next_plane = drm_output_prepare_cursor_view(output, ev);
                if (next_plane == NULL)
-                       next_plane = drm_output_prepare_scanout_surface(output, es);
+                       next_plane = drm_output_prepare_scanout_view(output, ev);
                if (next_plane == NULL)
-                       next_plane = drm_output_prepare_overlay_surface(output, es);
+                       next_plane = drm_output_prepare_overlay_view(output, ev);
                if (next_plane == NULL)
                        next_plane = primary;
-               weston_surface_move_to_plane(es, next_plane);
+               weston_view_move_to_plane(ev, next_plane);
                if (next_plane == primary)
                        pixman_region32_union(&overlap, &overlap,
-                                             &es->transform.boundingbox);
+                                             &ev->transform.boundingbox);
 
                pixman_region32_fini(&surface_overlap);
        }
index 3a028bc..11f582e 100644 (file)
@@ -93,7 +93,7 @@ weston_output_transform_scale_init(struct weston_output *output,
                                   uint32_t transform, uint32_t scale);
 
 static void
-weston_compositor_build_surface_list(struct weston_compositor *compositor);
+weston_compositor_build_view_list(struct weston_compositor *compositor);
 
 WL_EXPORT int
 weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode,
@@ -347,6 +347,50 @@ region_init_infinite(pixman_region32_t *region)
 static struct weston_subsurface *
 weston_surface_to_subsurface(struct weston_surface *surface);
 
+WL_EXPORT struct weston_view *
+weston_view_create(struct weston_surface *surface)
+{
+       struct weston_view *view;
+
+       view = calloc(1, sizeof *view);
+       if (view == NULL)
+               return NULL;
+
+       view->surface = surface;
+
+       if (surface->compositor->renderer->create_view &&
+           surface->compositor->renderer->create_view(view) < 0) {
+               free(view);
+               return NULL;
+       }
+
+       /* Assign to surface */
+       wl_list_insert(&surface->views, &view->surface_link);
+
+       wl_signal_init(&view->destroy_signal);
+       wl_list_init(&view->link);
+       wl_list_init(&view->layer_link);
+
+       view->plane = &surface->compositor->primary_plane;
+
+       pixman_region32_init(&view->clip);
+
+       view->alpha = 1.0;
+       pixman_region32_init(&view->transform.opaque);
+
+       wl_list_init(&view->geometry.transformation_list);
+       wl_list_insert(&view->geometry.transformation_list,
+                      &view->transform.position.link);
+       weston_matrix_init(&view->transform.position.matrix);
+       wl_list_init(&view->geometry.child_list);
+       pixman_region32_init(&view->transform.boundingbox);
+       view->transform.dirty = 1;
+
+       view->output = NULL;
+
+       return view;
+}
+
 WL_EXPORT struct weston_surface *
 weston_surface_create(struct weston_compositor *compositor)
 {
@@ -360,11 +404,7 @@ weston_surface_create(struct weston_compositor *compositor)
 
        surface->resource = NULL;
 
-       wl_list_init(&surface->link);
-       wl_list_init(&surface->layer_link);
-
        surface->compositor = compositor;
-       surface->alpha = 1.0;
        surface->ref_count = 1;
 
        if (compositor->renderer->create_surface(surface) < 0) {
@@ -377,23 +417,15 @@ weston_surface_create(struct weston_compositor *compositor)
        surface->pending.buffer_transform = surface->buffer_transform;
        surface->pending.buffer_scale = surface->buffer_scale;
        surface->output = NULL;
-       surface->plane = &compositor->primary_plane;
        surface->pending.newly_attached = 0;
 
        pixman_region32_init(&surface->damage);
        pixman_region32_init(&surface->opaque);
-       pixman_region32_init(&surface->clip);
        region_init_infinite(&surface->input);
-       pixman_region32_init(&surface->transform.opaque);
-       wl_list_init(&surface->frame_callback_list);
 
-       wl_list_init(&surface->geometry.transformation_list);
-       wl_list_insert(&surface->geometry.transformation_list,
-                      &surface->transform.position.link);
-       weston_matrix_init(&surface->transform.position.matrix);
-       wl_list_init(&surface->geometry.child_list);
-       pixman_region32_init(&surface->transform.boundingbox);
-       surface->transform.dirty = 1;
+       wl_list_init(&surface->views);
+
+       wl_list_init(&surface->frame_callback_list);
 
        surface->pending.buffer_destroy_listener.notify =
                surface_handle_pending_buffer_destroy;
@@ -416,13 +448,13 @@ weston_surface_set_color(struct weston_surface *surface,
 }
 
 WL_EXPORT void
-weston_surface_to_global_float(struct weston_surface *surface,
-                              float sx, float sy, float *x, float *y)
+weston_view_to_global_float(struct weston_view *view,
+                           float sx, float sy, float *x, float *y)
 {
-       if (surface->transform.enabled) {
+       if (view->transform.enabled) {
                struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
 
-               weston_matrix_transform(&surface->transform.matrix, &v);
+               weston_matrix_transform(&view->transform.matrix, &v);
 
                if (fabsf(v.f[3]) < 1e-6) {
                        weston_log("warning: numerical instability in "
@@ -436,8 +468,8 @@ weston_surface_to_global_float(struct weston_surface *surface,
                *x = v.f[0] / v.f[3];
                *y = v.f[1] / v.f[3];
        } else {
-               *x = sx + surface->geometry.x;
-               *y = sy + surface->geometry.y;
+               *x = sx + view->geometry.x;
+               *y = sy + view->geometry.y;
        }
 }
 
@@ -525,8 +557,8 @@ WL_EXPORT void
 weston_surface_to_buffer_float(struct weston_surface *surface,
                               float sx, float sy, float *bx, float *by)
 {
-       weston_transformed_coord(surface->geometry.width,
-                                surface->geometry.height,
+       weston_transformed_coord(surface->width,
+                                surface->height,
                                 surface->buffer_transform,
                                 surface->buffer_scale,
                                 sx, sy, bx, by);
@@ -538,8 +570,8 @@ weston_surface_to_buffer(struct weston_surface *surface,
 {
        float bxf, byf;
 
-       weston_transformed_coord(surface->geometry.width,
-                                surface->geometry.height,
+       weston_transformed_coord(surface->width,
+                                surface->height,
                                 surface->buffer_transform,
                                 surface->buffer_scale,
                                 sx, sy, &bxf, &byf);
@@ -551,35 +583,35 @@ WL_EXPORT pixman_box32_t
 weston_surface_to_buffer_rect(struct weston_surface *surface,
                              pixman_box32_t rect)
 {
-       return weston_transformed_rect(surface->geometry.width,
-                                      surface->geometry.height,
+       return weston_transformed_rect(surface->width,
+                                      surface->height,
                                       surface->buffer_transform,
                                       surface->buffer_scale,
                                       rect);
 }
 
 WL_EXPORT void
-weston_surface_move_to_plane(struct weston_surface *surface,
+weston_view_move_to_plane(struct weston_view *view,
                             struct weston_plane *plane)
 {
-       if (surface->plane == plane)
+       if (view->plane == plane)
                return;
 
-       weston_surface_damage_below(surface);
-       surface->plane = plane;
-       weston_surface_damage(surface);
+       weston_view_damage_below(view);
+       view->plane = plane;
+       weston_surface_damage(view->surface);
 }
 
 WL_EXPORT void
-weston_surface_damage_below(struct weston_surface *surface)
+weston_view_damage_below(struct weston_view *view)
 {
        pixman_region32_t damage;
 
        pixman_region32_init(&damage);
-       pixman_region32_subtract(&damage, &surface->transform.boundingbox,
-                                &surface->clip);
-       pixman_region32_union(&surface->plane->damage,
-                             &surface->plane->damage, &damage);
+       pixman_region32_subtract(&damage, &view->transform.boundingbox,
+                                &view->clip);
+       pixman_region32_union(&view->plane->damage,
+                             &view->plane->damage, &damage);
        pixman_region32_fini(&damage);
 }
 
@@ -618,7 +650,43 @@ weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
 static void
 weston_surface_assign_output(struct weston_surface *es)
 {
-       struct weston_compositor *ec = es->compositor;
+       struct weston_output *new_output;
+       struct weston_view *view;
+       pixman_region32_t region;
+       uint32_t max, area, mask;
+       pixman_box32_t *e;
+
+       new_output = NULL;
+       max = 0;
+       mask = 0;
+       pixman_region32_init(&region);
+       wl_list_for_each(view, &es->views, surface_link) {
+               if (!view->output)
+                       continue;
+
+               pixman_region32_intersect(&region, &view->transform.boundingbox,
+                                         &view->output->region);
+
+               e = pixman_region32_extents(&region);
+               area = (e->x2 - e->x1) * (e->y2 - e->y1);
+
+               mask |= view->output_mask;
+
+               if (area >= max) {
+                       new_output = view->output;
+                       max = area;
+               }
+       }
+       pixman_region32_fini(&region);
+
+       es->output = new_output;
+       weston_surface_update_output_mask(es, mask);
+}
+
+static void
+weston_view_assign_output(struct weston_view *ev)
+{
+       struct weston_compositor *ec = ev->surface->compositor;
        struct weston_output *output, *new_output;
        pixman_region32_t region;
        uint32_t max, area, mask;
@@ -629,7 +697,7 @@ weston_surface_assign_output(struct weston_surface *es)
        mask = 0;
        pixman_region32_init(&region);
        wl_list_for_each(output, &ec->output_list, link) {
-               pixman_region32_intersect(&region, &es->transform.boundingbox,
+               pixman_region32_intersect(&region, &ev->transform.boundingbox,
                                          &output->region);
 
                e = pixman_region32_extents(&region);
@@ -645,14 +713,16 @@ weston_surface_assign_output(struct weston_surface *es)
        }
        pixman_region32_fini(&region);
 
-       es->output = new_output;
-       weston_surface_update_output_mask(es, mask);
+       ev->output = new_output;
+       ev->output_mask = mask;
+
+       weston_surface_assign_output(ev->surface);
 }
 
 static void
-surface_compute_bbox(struct weston_surface *surface, int32_t sx, int32_t sy,
-                    int32_t width, int32_t height,
-                    pixman_region32_t *bbox)
+view_compute_bbox(struct weston_view *view, int32_t sx, int32_t sy,
+                 int32_t width, int32_t height,
+                 pixman_region32_t *bbox)
 {
        float min_x = HUGE_VALF,  min_y = HUGE_VALF;
        float max_x = -HUGE_VALF, max_y = -HUGE_VALF;
@@ -673,8 +743,7 @@ surface_compute_bbox(struct weston_surface *surface, int32_t sx, int32_t sy,
 
        for (i = 0; i < 4; ++i) {
                float x, y;
-               weston_surface_to_global_float(surface,
-                                              s[i][0], s[i][1], &x, &y);
+               weston_view_to_global_float(view, s[i][0], s[i][1], &x, &y);
                if (x < min_x)
                        min_x = x;
                if (x > max_x)
@@ -692,57 +761,57 @@ surface_compute_bbox(struct weston_surface *surface, int32_t sx, int32_t sy,
 }
 
 static void
-weston_surface_update_transform_disable(struct weston_surface *surface)
+weston_view_update_transform_disable(struct weston_view *view)
 {
-       surface->transform.enabled = 0;
+       view->transform.enabled = 0;
 
        /* round off fractions when not transformed */
-       surface->geometry.x = roundf(surface->geometry.x);
-       surface->geometry.y = roundf(surface->geometry.y);
+       view->geometry.x = roundf(view->geometry.x);
+       view->geometry.y = roundf(view->geometry.y);
 
        /* Otherwise identity matrix, but with x and y translation. */
-       surface->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
-       surface->transform.position.matrix.d[12] = surface->geometry.x;
-       surface->transform.position.matrix.d[13] = surface->geometry.y;
+       view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
+       view->transform.position.matrix.d[12] = view->geometry.x;
+       view->transform.position.matrix.d[13] = view->geometry.y;
 
-       surface->transform.matrix = surface->transform.position.matrix;
+       view->transform.matrix = view->transform.position.matrix;
 
-       surface->transform.inverse = surface->transform.position.matrix;
-       surface->transform.inverse.d[12] = -surface->geometry.x;
-       surface->transform.inverse.d[13] = -surface->geometry.y;
+       view->transform.inverse = view->transform.position.matrix;
+       view->transform.inverse.d[12] = -view->geometry.x;
+       view->transform.inverse.d[13] = -view->geometry.y;
 
-       pixman_region32_init_rect(&surface->transform.boundingbox,
-                                 surface->geometry.x,
-                                 surface->geometry.y,
-                                 surface->geometry.width,
-                                 surface->geometry.height);
+       pixman_region32_init_rect(&view->transform.boundingbox,
+                                 view->geometry.x,
+                                 view->geometry.y,
+                                 view->geometry.width,
+                                 view->geometry.height);
 
-       if (surface->alpha == 1.0) {
-               pixman_region32_copy(&surface->transform.opaque,
-                                    &surface->opaque);
-               pixman_region32_translate(&surface->transform.opaque,
-                                         surface->geometry.x,
-                                         surface->geometry.y);
+       if (view->alpha == 1.0) {
+               pixman_region32_copy(&view->transform.opaque,
+                                    &view->surface->opaque);
+               pixman_region32_translate(&view->transform.opaque,
+                                         view->geometry.x,
+                                         view->geometry.y);
        }
 }
 
 static int
-weston_surface_update_transform_enable(struct weston_surface *surface)
+weston_view_update_transform_enable(struct weston_view *view)
 {
-       struct weston_surface *parent = surface->geometry.parent;
-       struct weston_matrix *matrix = &surface->transform.matrix;
-       struct weston_matrix *inverse = &surface->transform.inverse;
+       struct weston_view *parent = view->geometry.parent;
+       struct weston_matrix *matrix = &view->transform.matrix;
+       struct weston_matrix *inverse = &view->transform.inverse;
        struct weston_transform *tform;
 
-       surface->transform.enabled = 1;
+       view->transform.enabled = 1;
 
        /* Otherwise identity matrix, but with x and y translation. */
-       surface->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
-       surface->transform.position.matrix.d[12] = surface->geometry.x;
-       surface->transform.position.matrix.d[13] = surface->geometry.y;
+       view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
+       view->transform.position.matrix.d[12] = view->geometry.x;
+       view->transform.position.matrix.d[13] = view->geometry.y;
 
        weston_matrix_init(matrix);
-       wl_list_for_each(tform, &surface->geometry.transformation_list, link)
+       wl_list_for_each(tform, &view->geometry.transformation_list, link)
                weston_matrix_multiply(matrix, &tform->matrix);
 
        if (parent)
@@ -750,143 +819,144 @@ weston_surface_update_transform_enable(struct weston_surface *surface)
 
        if (weston_matrix_invert(inverse, matrix) < 0) {
                /* Oops, bad total transformation, not invertible */
-               weston_log("error: weston_surface %p"
-                       " transformation not invertible.\n", surface);
+               weston_log("error: weston_view %p"
+                       " transformation not invertible.\n", view);
                return -1;
        }
 
-       surface_compute_bbox(surface, 0, 0, surface->geometry.width,
-                            surface->geometry.height,
-                            &surface->transform.boundingbox);
+       view_compute_bbox(view, 0, 0, view->geometry.width,
+                         view->geometry.height,
+                         &view->transform.boundingbox);
 
        return 0;
 }
 
 WL_EXPORT void
-weston_surface_update_transform(struct weston_surface *surface)
+weston_view_update_transform(struct weston_view *view)
 {
-       struct weston_surface *parent = surface->geometry.parent;
+       struct weston_view *parent = view->geometry.parent;
 
-       if (!surface->transform.dirty)
+       if (!view->transform.dirty)
                return;
 
        if (parent)
-               weston_surface_update_transform(parent);
+               weston_view_update_transform(parent);
 
-       surface->transform.dirty = 0;
+       view->transform.dirty = 0;
 
-       weston_surface_damage_below(surface);
+       weston_view_damage_below(view);
 
-       pixman_region32_fini(&surface->transform.boundingbox);
-       pixman_region32_fini(&surface->transform.opaque);
-       pixman_region32_init(&surface->transform.opaque);
+       pixman_region32_fini(&view->transform.boundingbox);
+       pixman_region32_fini(&view->transform.opaque);
+       pixman_region32_init(&view->transform.opaque);
 
        /* transform.position is always in transformation_list */
-       if (surface->geometry.transformation_list.next ==
-           &surface->transform.position.link &&
-           surface->geometry.transformation_list.prev ==
-           &surface->transform.position.link &&
+       if (view->geometry.transformation_list.next ==
+           &view->transform.position.link &&
+           view->geometry.transformation_list.prev ==
+           &view->transform.position.link &&
            !parent) {
-               weston_surface_update_transform_disable(surface);
+               weston_view_update_transform_disable(view);
        } else {
-               if (weston_surface_update_transform_enable(surface) < 0)
-                       weston_surface_update_transform_disable(surface);
+               if (weston_view_update_transform_enable(view) < 0)
+                       weston_view_update_transform_disable(view);
        }
 
-       weston_surface_damage_below(surface);
+       weston_view_damage_below(view);
 
-       weston_surface_assign_output(surface);
+       weston_view_assign_output(view);
 
-       wl_signal_emit(&surface->compositor->transform_signal, surface);
+       wl_signal_emit(&view->surface->compositor->transform_signal,
+                      view->surface);
 }
 
 WL_EXPORT void
-weston_surface_geometry_dirty(struct weston_surface *surface)
+weston_view_geometry_dirty(struct weston_view *view)
 {
-       struct weston_surface *child;
+       struct weston_view *child;
 
        /*
-        * The invariant: if surface->geometry.dirty, then all surfaces
-        * in surface->geometry.child_list have geometry.dirty too.
+        * The invariant: if view->geometry.dirty, then all views
+        * in view->geometry.child_list have geometry.dirty too.
         * Corollary: if not parent->geometry.dirty, then all ancestors
         * are not dirty.
         */
 
-       if (surface->transform.dirty)
+       if (view->transform.dirty)
                return;
 
-       surface->transform.dirty = 1;
+       view->transform.dirty = 1;
 
-       wl_list_for_each(child, &surface->geometry.child_list,
+       wl_list_for_each(child, &view->geometry.child_list,
                         geometry.parent_link)
-               weston_surface_geometry_dirty(child);
+               weston_view_geometry_dirty(child);
 }
 
 WL_EXPORT void
-weston_surface_to_global_fixed(struct weston_surface *surface,
-                              wl_fixed_t sx, wl_fixed_t sy,
-                              wl_fixed_t *x, wl_fixed_t *y)
+weston_view_to_global_fixed(struct weston_view *view,
+                           wl_fixed_t vx, wl_fixed_t vy,
+                           wl_fixed_t *x, wl_fixed_t *y)
 {
        float xf, yf;
 
-       weston_surface_to_global_float(surface,
-                                      wl_fixed_to_double(sx),
-                                      wl_fixed_to_double(sy),
-                                      &xf, &yf);
+       weston_view_to_global_float(view,
+                                   wl_fixed_to_double(vx),
+                                   wl_fixed_to_double(vy),
+                                   &xf, &yf);
        *x = wl_fixed_from_double(xf);
        *y = wl_fixed_from_double(yf);
 }
 
 WL_EXPORT void
-weston_surface_from_global_float(struct weston_surface *surface,
-                                float x, float y, float *sx, float *sy)
+weston_view_from_global_float(struct weston_view *view,
+                             float x, float y, float *vx, float *vy)
 {
-       if (surface->transform.enabled) {
+       if (view->transform.enabled) {
                struct weston_vector v = { { x, y, 0.0f, 1.0f } };
 
-               weston_matrix_transform(&surface->transform.inverse, &v);
+               weston_matrix_transform(&view->transform.inverse, &v);
 
                if (fabsf(v.f[3]) < 1e-6) {
                        weston_log("warning: numerical instability in "
-                               "weston_surface_from_global(), divisor = %g\n",
+                               "weston_view_from_global(), divisor = %g\n",
                                v.f[3]);
-                       *sx = 0;
-                       *sy = 0;
+                       *vx = 0;
+                       *vy = 0;
                        return;
                }
 
-               *sx = v.f[0] / v.f[3];
-               *sy = v.f[1] / v.f[3];
+               *vx = v.f[0] / v.f[3];
+               *vy = v.f[1] / v.f[3];
        } else {
-               *sx = x - surface->geometry.x;
-               *sy = y - surface->geometry.y;
+               *vx = x - view->geometry.x;
+               *vy = y - view->geometry.y;
        }
 }
 
 WL_EXPORT void
-weston_surface_from_global_fixed(struct weston_surface *surface,
-                                wl_fixed_t x, wl_fixed_t y,
-                                wl_fixed_t *sx, wl_fixed_t *sy)
+weston_view_from_global_fixed(struct weston_view *view,
+                             wl_fixed_t x, wl_fixed_t y,
+                             wl_fixed_t *vx, wl_fixed_t *vy)
 {
-       float sxf, syf;
+       float vxf, vyf;
 
-       weston_surface_from_global_float(surface,
-                                        wl_fixed_to_double(x),
-                                        wl_fixed_to_double(y),
-                                        &sxf, &syf);
-       *sx = wl_fixed_from_double(sxf);
-       *sy = wl_fixed_from_double(syf);
+       weston_view_from_global_float(view,
+                                     wl_fixed_to_double(x),
+                                     wl_fixed_to_double(y),
+                                     &vxf, &vyf);
+       *vx = wl_fixed_from_double(vxf);
+       *vy = wl_fixed_from_double(vyf);
 }
 
 WL_EXPORT void
-weston_surface_from_global(struct weston_surface *surface,
-                          int32_t x, int32_t y, int32_t *sx, int32_t *sy)
+weston_view_from_global(struct weston_view *view,
+                       int32_t x, int32_t y, int32_t *vx, int32_t *vy)
 {
-       float sxf, syf;
+       float vxf, vyf;
 
-       weston_surface_from_global_float(surface, x, y, &sxf, &syf);
-       *sx = floorf(sxf);
-       *sy = floorf(syf);
+       weston_view_from_global_float(view, x, y, &vxf, &vyf);
+       *vx = floorf(vxf);
+       *vy = floorf(vyf);
 }
 
 WL_EXPORT void
@@ -900,67 +970,85 @@ weston_surface_schedule_repaint(struct weston_surface *surface)
 }
 
 WL_EXPORT void
+weston_view_schedule_repaint(struct weston_view *view)
+{
+       struct weston_output *output;
+
+       wl_list_for_each(output, &view->surface->compositor->output_list, link)
+               if (view->output_mask & (1 << output->id))
+                       weston_output_schedule_repaint(output);
+}
+
+WL_EXPORT void
 weston_surface_damage(struct weston_surface *surface)
 {
        pixman_region32_union_rect(&surface->damage, &surface->damage,
-                                  0, 0, surface->geometry.width,
-                                  surface->geometry.height);
+                                  0, 0, surface->width,
+                                  surface->height);
 
        weston_surface_schedule_repaint(surface);
 }
 
 WL_EXPORT void
-weston_surface_configure(struct weston_surface *surface,
-                        float x, float y, int width, int height)
+weston_view_configure(struct weston_view *view,
+                     float x, float y, int width, int height)
 {
-       surface->geometry.x = x;
-       surface->geometry.y = y;
-       surface->geometry.width = width;
-       surface->geometry.height = height;
-       weston_surface_geometry_dirty(surface);
+       view->geometry.x = x;
+       view->geometry.y = y;
+       view->geometry.width = width;
+       view->geometry.height = height;
+       weston_view_geometry_dirty(view);
 }
 
 WL_EXPORT void
-weston_surface_set_position(struct weston_surface *surface,
-                           float x, float y)
+weston_view_set_position(struct weston_view *view, float x, float y)
 {
-       surface->geometry.x = x;
-       surface->geometry.y = y;
-       weston_surface_geometry_dirty(surface);
+       view->geometry.x = x;
+       view->geometry.y = y;
+       weston_view_geometry_dirty(view);
 }
 
 static void
 transform_parent_handle_parent_destroy(struct wl_listener *listener,
                                       void *data)
 {
-       struct weston_surface *surface =
-               container_of(listener, struct weston_surface,
+       struct weston_view *view =
+               container_of(listener, struct weston_view,
                             geometry.parent_destroy_listener);
 
-       weston_surface_set_transform_parent(surface, NULL);
+       weston_view_set_transform_parent(view, NULL);
 }
 
 WL_EXPORT void
-weston_surface_set_transform_parent(struct weston_surface *surface,
-                                   struct weston_surface *parent)
+weston_view_set_transform_parent(struct weston_view *view,
+                                   struct weston_view *parent)
 {
-       if (surface->geometry.parent) {
-               wl_list_remove(&surface->geometry.parent_destroy_listener.link);
-               wl_list_remove(&surface->geometry.parent_link);
+       if (view->geometry.parent) {
+               wl_list_remove(&view->geometry.parent_destroy_listener.link);
+               wl_list_remove(&view->geometry.parent_link);
        }
 
-       surface->geometry.parent = parent;
+       view->geometry.parent = parent;
 
-       surface->geometry.parent_destroy_listener.notify =
+       view->geometry.parent_destroy_listener.notify =
                transform_parent_handle_parent_destroy;
        if (parent) {
                wl_signal_add(&parent->destroy_signal,
-                             &surface->geometry.parent_destroy_listener);
+                             &view->geometry.parent_destroy_listener);
                wl_list_insert(&parent->geometry.child_list,
-                              &surface->geometry.parent_link);
+                              &view->geometry.parent_link);
        }
 
-       weston_surface_geometry_dirty(surface);
+       weston_view_geometry_dirty(view);
+}
+
+WL_EXPORT int
+weston_view_is_mapped(struct weston_view *view)
+{
+       if (view->output)
+               return 1;
+       else
+               return 0;
 }
 
 WL_EXPORT int
@@ -1018,20 +1106,20 @@ weston_compositor_get_time(void)
        return tv.tv_sec * 1000 + tv.tv_usec / 1000;
 }
 
-WL_EXPORT struct weston_surface *
-weston_compositor_pick_surface(struct weston_compositor *compositor,
-                              wl_fixed_t x, wl_fixed_t y,
-                              wl_fixed_t *sx, wl_fixed_t *sy)
+WL_EXPORT struct weston_view *
+weston_compositor_pick_view(struct weston_compositor *compositor,
+                           wl_fixed_t x, wl_fixed_t y,
+                           wl_fixed_t *vx, wl_fixed_t *vy)
 {
-       struct weston_surface *surface;
+       struct weston_view *view;
 
-       wl_list_for_each(surface, &compositor->surface_list, link) {
-               weston_surface_from_global_fixed(surface, x, y, sx, sy);
-               if (pixman_region32_contains_point(&surface->input,
-                                                  wl_fixed_to_int(*sx),
-                                                  wl_fixed_to_int(*sy),
+       wl_list_for_each(view, &compositor->view_list, link) {
+               weston_view_from_global_fixed(view, x, y, vx, vy);
+               if (pixman_region32_contains_point(&view->surface->input,
+                                                  wl_fixed_to_int(*vx),
+                                                  wl_fixed_to_int(*vy),
                                                   NULL))
-                       return surface;
+                       return view;
        }
 
        return NULL;
@@ -1050,29 +1138,48 @@ weston_compositor_repick(struct weston_compositor *compositor)
 }
 
 WL_EXPORT void
-weston_surface_unmap(struct weston_surface *surface)
+weston_view_unmap(struct weston_view *view)
 {
        struct weston_seat *seat;
 
-       weston_surface_damage_below(surface);
-       surface->output = NULL;
-       wl_list_remove(&surface->layer_link);
-       wl_list_remove(&surface->link);
-       wl_list_init(&surface->link);
+       if (!weston_view_is_mapped(view))
+               return;
+
+       weston_view_damage_below(view);
+       view->output = NULL;
+       wl_list_remove(&view->layer_link);
+       wl_list_init(&view->layer_link);
+       wl_list_remove(&view->link);
+       wl_list_init(&view->link);
+       /* We need to do this before torching the output mask */
+       weston_view_schedule_repaint(view);
+       view->output_mask = 0;
+       weston_surface_assign_output(view->surface);
+
+       if (weston_surface_is_mapped(view->surface))
+               return;
 
-       wl_list_for_each(seat, &surface->compositor->seat_list, link) {
-               if (seat->keyboard && seat->keyboard->focus == surface)
+       wl_list_for_each(seat, &view->surface->compositor->seat_list, link) {
+               if (seat->keyboard && seat->keyboard->focus == view->surface)
                        weston_keyboard_set_focus(seat->keyboard, NULL);
-               if (seat->pointer && seat->pointer->focus == surface)
+               if (seat->pointer && seat->pointer->focus == view)
                        weston_pointer_set_focus(seat->pointer,
                                                 NULL,
                                                 wl_fixed_from_int(0),
                                                 wl_fixed_from_int(0));
-               if (seat->touch && seat->touch->focus == surface)
+               if (seat->touch && seat->touch->focus == view)
                        weston_touch_set_focus(seat, NULL);
        }
+}
 
-       weston_surface_schedule_repaint(surface);
+WL_EXPORT void
+weston_surface_unmap(struct weston_surface *surface)
+{
+       struct weston_view *view;
+
+       wl_list_for_each(view, &surface->views, surface_link)
+               weston_view_unmap(view);
+       surface->output = NULL;
 }
 
 struct weston_frame_callback {
@@ -1080,24 +1187,51 @@ struct weston_frame_callback {
        struct wl_list link;
 };
 
+WL_EXPORT void
+weston_view_destroy(struct weston_view *view)
+{
+       wl_signal_emit(&view->destroy_signal, view);
+
+       assert(wl_list_empty(&view->geometry.child_list));
+
+       if (weston_view_is_mapped(view)) {
+               weston_view_unmap(view);
+               weston_compositor_build_view_list(view->surface->compositor);
+       }
+
+       wl_list_remove(&view->link);
+       wl_list_remove(&view->layer_link);
+
+       pixman_region32_fini(&view->clip);
+       pixman_region32_fini(&view->transform.boundingbox);
+
+       weston_view_set_transform_parent(view, NULL);
+
+       if (view->surface->compositor->renderer->destroy_view)
+               view->surface->compositor->renderer->destroy_view(view);
+
+       wl_list_remove(&view->surface_link);
+
+       free(view);
+}
 
 WL_EXPORT void
 weston_surface_destroy(struct weston_surface *surface)
 {
        struct weston_compositor *compositor = surface->compositor;
        struct weston_frame_callback *cb, *next;
+       struct weston_view *ev, *nv;
 
        if (--surface->ref_count > 0)
                return;
 
        wl_signal_emit(&surface->destroy_signal, &surface->resource);
 
-       assert(wl_list_empty(&surface->geometry.child_list));
        assert(wl_list_empty(&surface->subsurface_list_pending));
        assert(wl_list_empty(&surface->subsurface_list));
 
-       if (weston_surface_is_mapped(surface))
-               weston_surface_unmap(surface);
+       wl_list_for_each_safe(ev, nv, &surface->views, surface_link)
+               weston_view_destroy(ev);
 
        wl_list_for_each_safe(cb, next,
                              &surface->pending.frame_callback_list, link)
@@ -1114,17 +1248,13 @@ weston_surface_destroy(struct weston_surface *surface)
 
        compositor->renderer->destroy_surface(surface);
 
-       pixman_region32_fini(&surface->transform.boundingbox);
        pixman_region32_fini(&surface->damage);
        pixman_region32_fini(&surface->opaque);
-       pixman_region32_fini(&surface->clip);
        pixman_region32_fini(&surface->input);
 
        wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link)
                wl_resource_destroy(cb->resource);
 
-       weston_surface_set_transform_parent(surface, NULL);
-
        free(surface);
 }
 
@@ -1223,12 +1353,12 @@ weston_surface_attach(struct weston_surface *surface,
 }
 
 WL_EXPORT void
-weston_surface_restack(struct weston_surface *surface, struct wl_list *below)
+weston_view_restack(struct weston_view *view, struct wl_list *below)
 {
-       wl_list_remove(&surface->layer_link);
-       wl_list_insert(below, &surface->layer_link);
-       weston_surface_damage_below(surface);
-       weston_surface_damage(surface);
+       wl_list_remove(&view->layer_link);
+       wl_list_insert(below, &view->layer_link);
+       weston_view_damage_below(view);
+       weston_surface_damage(view->surface);
 }
 
 WL_EXPORT void
@@ -1252,43 +1382,53 @@ weston_output_damage(struct weston_output *output)
 }
 
 static void
-surface_accumulate_damage(struct weston_surface *surface,
-                         pixman_region32_t *opaque)
+surface_flush_damage(struct weston_surface *surface)
 {
        if (surface->buffer_ref.buffer &&
            wl_shm_buffer_get(surface->buffer_ref.buffer->resource))
                surface->compositor->renderer->flush_damage(surface);
 
-       if (surface->transform.enabled) {
+       empty_region(&surface->damage);
+}
+
+static void
+view_accumulate_damage(struct weston_view *view,
+                      pixman_region32_t *opaque)
+{
+       pixman_region32_t damage;
+
+       pixman_region32_init(&damage);
+       if (view->transform.enabled) {
                pixman_box32_t *extents;
 
-               extents = pixman_region32_extents(&surface->damage);
-               surface_compute_bbox(surface, extents->x1, extents->y1,
-                                    extents->x2 - extents->x1,
-                                    extents->y2 - extents->y1,
-                                    &surface->damage);
-               pixman_region32_translate(&surface->damage,
-                                         -surface->plane->x,
-                                         -surface->plane->y);
+               extents = pixman_region32_extents(&view->surface->damage);
+               view_compute_bbox(view, extents->x1, extents->y1,
+                                 extents->x2 - extents->x1,
+                                 extents->y2 - extents->y1,
+                                 &damage);
+               pixman_region32_translate(&damage,
+                                         -view->plane->x,
+                                         -view->plane->y);
        } else {
-               pixman_region32_translate(&surface->damage,
-                                         surface->geometry.x - surface->plane->x,
-                                         surface->geometry.y - surface->plane->y);
+               pixman_region32_copy(&damage, &view->surface->damage);
+               pixman_region32_translate(&damage,
+                                         view->geometry.x - view->plane->x,
+                                         view->geometry.y - view->plane->y);
        }
 
-       pixman_region32_subtract(&surface->damage, &surface->damage, opaque);
-       pixman_region32_union(&surface->plane->damage,
-                             &surface->plane->damage, &surface->damage);
-       empty_region(&surface->damage);
-       pixman_region32_copy(&surface->clip, opaque);
-       pixman_region32_union(opaque, opaque, &surface->transform.opaque);
+       pixman_region32_subtract(&damage, &damage, opaque);
+       pixman_region32_union(&view->plane->damage,
+                             &view->plane->damage, &damage);
+       pixman_region32_fini(&damage);
+       pixman_region32_copy(&view->clip, opaque);
+       pixman_region32_union(opaque, opaque, &view->transform.opaque);
 }
 
 static void
 compositor_accumulate_damage(struct weston_compositor *ec)
 {
        struct weston_plane *plane;
-       struct weston_surface *es;
+       struct weston_view *ev;
        pixman_region32_t opaque, clip;
 
        pixman_region32_init(&clip);
@@ -1298,11 +1438,11 @@ compositor_accumulate_damage(struct weston_compositor *ec)
 
                pixman_region32_init(&opaque);
 
-               wl_list_for_each(es, &ec->surface_list, link) {
-                       if (es->plane != plane)
+               wl_list_for_each(ev, &ec->view_list, link) {
+                       if (ev->plane != plane)
                                continue;
 
-                       surface_accumulate_damage(es, &opaque);
+                       view_accumulate_damage(ev, &opaque);
                }
 
                pixman_region32_union(&clip, &clip, &opaque);
@@ -1311,7 +1451,16 @@ compositor_accumulate_damage(struct weston_compositor *ec)
 
        pixman_region32_fini(&clip);
 
-       wl_list_for_each(es, &ec->surface_list, link) {
+       wl_list_for_each(ev, &ec->view_list, link)
+               ev->surface->touched = 0;
+
+       wl_list_for_each(ev, &ec->view_list, link) {
+               if (ev->surface->touched)
+                       continue;
+               ev->surface->touched = 1;
+
+               surface_flush_damage(ev->surface);
+
                /* Both the renderer and the backend have seen the buffer
                 * by now. If renderer needs the buffer, it has its own
                 * reference set. If the backend wants to keep the buffer
@@ -1320,56 +1469,122 @@ compositor_accumulate_damage(struct weston_compositor *ec)
                 * reference now, and allow early buffer release. This enables
                 * clients to use single-buffering.
                 */
-               if (!es->keep_buffer)
-                       weston_buffer_reference(&es->buffer_ref, NULL);
+               if (!ev->surface->keep_buffer)
+                       weston_buffer_reference(&ev->surface->buffer_ref, NULL);
        }
 }
 
 static void
-surface_list_add(struct weston_compositor *compositor,
-                struct weston_surface *surface)
+surface_stash_subsurface_views(struct weston_surface *surface)
 {
        struct weston_subsurface *sub;
 
-       if (wl_list_empty(&surface->subsurface_list)) {
-               weston_surface_update_transform(surface);
-               wl_list_insert(compositor->surface_list.prev, &surface->link);
-               return;
+       wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
+               if (sub->surface == surface)
+                       continue;
+
+               wl_list_insert_list(&sub->unused_views, &sub->surface->views);
+               wl_list_init(&sub->surface->views);
+
+               surface_stash_subsurface_views(sub->surface);
        }
+}
+
+static void
+surface_free_unused_subsurface_views(struct weston_surface *surface)
+{
+       struct weston_subsurface *sub;
+       struct weston_view *view, *nv;
 
        wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
-               if (!weston_surface_is_mapped(sub->surface))
+               if (sub->surface == surface)
                        continue;
 
-               if (sub->surface == surface) {
-                       weston_surface_update_transform(sub->surface);
-                       wl_list_insert(compositor->surface_list.prev,
-                                      &sub->surface->link);
-               } else {
-                       surface_list_add(compositor, sub->surface);
+               wl_list_for_each_safe(view, nv, &sub->unused_views, surface_link)
+                       weston_view_destroy(view);
+
+               surface_free_unused_subsurface_views(sub->surface);
+       }
+}
+
+static void
+view_list_add_subsurface_view(struct weston_compositor *compositor,
+                             struct weston_subsurface *sub,
+                             struct weston_view *parent)
+{
+       struct weston_subsurface *child;
+       struct weston_view *view = NULL, *iv;
+
+       wl_list_for_each(iv, &sub->unused_views, surface_link) {
+               if (iv->geometry.parent == parent) {
+                       view = iv;
+                       break;
                }
        }
+
+       if (view) {
+               /* Put it back in the surface's list of views */
+               wl_list_remove(&view->surface_link);
+               wl_list_insert(&sub->surface->views, &view->surface_link);
+       } else {
+               view = weston_view_create(sub->surface);
+               weston_view_configure(view,
+                                     sub->position.x,
+                                     sub->position.y,
+                                     sub->surface->width,
+                                     sub->surface->height);
+               weston_view_set_transform_parent(view, parent);
+       }
+
+       weston_view_update_transform(view);
+       wl_list_insert(compositor->view_list.next, &view->link);
+
+       wl_list_for_each(child, &sub->surface->subsurface_list, parent_link)
+               if (child->surface != sub->surface)
+                       view_list_add_subsurface_view(compositor, child, view);
 }
 
 static void
-weston_compositor_build_surface_list(struct weston_compositor *compositor)
+view_list_add(struct weston_compositor *compositor,
+             struct weston_view *view)
 {
-       struct weston_surface *surface;
+       struct weston_subsurface *sub;
+
+       weston_view_update_transform(view);
+       wl_list_insert(compositor->view_list.prev, &view->link);
+
+       wl_list_for_each(sub, &view->surface->subsurface_list, parent_link)
+               if (sub->surface != view->surface)
+                       view_list_add_subsurface_view(compositor, sub, view);
+}
+
+static void
+weston_compositor_build_view_list(struct weston_compositor *compositor)
+{
+       struct weston_view *view;
        struct weston_layer *layer;
 
-       wl_list_init(&compositor->surface_list);
+       wl_list_for_each(layer, &compositor->layer_list, link)
+               wl_list_for_each(view, &layer->view_list, layer_link)
+                       surface_stash_subsurface_views(view->surface);
+
+       wl_list_init(&compositor->view_list);
        wl_list_for_each(layer, &compositor->layer_list, link) {
-               wl_list_for_each(surface, &layer->surface_list, layer_link) {
-                       surface_list_add(compositor, surface);
+               wl_list_for_each(view, &layer->view_list, layer_link) {
+                       view_list_add(compositor, view);
                }
        }
+
+       wl_list_for_each(layer, &compositor->layer_list, link)
+               wl_list_for_each(view, &layer->view_list, layer_link)
+                       surface_free_unused_subsurface_views(view->surface);
 }
 
 static int
 weston_output_repaint(struct weston_output *output, uint32_t msecs)
 {
        struct weston_compositor *ec = output->compositor;
-       struct weston_surface *es;
+       struct weston_view *ev;
        struct weston_animation *animation, *next;
        struct weston_frame_callback *cb, *cnext;
        struct wl_list frame_callback_list;
@@ -1377,20 +1592,23 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs)
        int r;
 
        /* Rebuild the surface list and update surface transforms up front. */
-       weston_compositor_build_surface_list(ec);
+       weston_compositor_build_view_list(ec);
 
        if (output->assign_planes && !output->disable_planes)
                output->assign_planes(output);
        else
-               wl_list_for_each(es, &ec->surface_list, link)
-                       weston_surface_move_to_plane(es, &ec->primary_plane);
+               wl_list_for_each(ev, &ec->view_list, link)
+                       weston_view_move_to_plane(ev, &ec->primary_plane);
 
        wl_list_init(&frame_callback_list);
-       wl_list_for_each(es, &ec->surface_list, link) {
-               if (es->output == output) {
+       wl_list_for_each(ev, &ec->view_list, link) {
+               /* Note: This operation is safe to do multiple times on the
+                * same surface.
+                */
+               if (ev->surface->output == output) {
                        wl_list_insert_list(&frame_callback_list,
-                                           &es->frame_callback_list);
-                       wl_list_init(&es->frame_callback_list);
+                                           &ev->surface->frame_callback_list);
+                       wl_list_init(&ev->surface->frame_callback_list);
                }
        }
 
@@ -1476,7 +1694,7 @@ idle_repaint(void *data)
 WL_EXPORT void
 weston_layer_init(struct weston_layer *layer, struct wl_list *below)
 {
-       wl_list_init(&layer->surface_list);
+       wl_list_init(&layer->view_list);
        if (below != NULL)
                wl_list_insert(below, &layer->link);
 }
@@ -1649,9 +1867,8 @@ weston_surface_commit_subsurface_order(struct weston_surface *surface)
 static void
 weston_surface_commit(struct weston_surface *surface)
 {
+       struct weston_view *view;
        pixman_region32_t opaque;
-       int surface_width = 0;
-       int surface_height = 0;
 
        /* wl_surface.set_buffer_transform */
        surface->buffer_transform = surface->pending.buffer_transform;
@@ -1663,15 +1880,18 @@ weston_surface_commit(struct weston_surface *surface)
        if (surface->pending.buffer || surface->pending.newly_attached)
                weston_surface_attach(surface, surface->pending.buffer);
 
+       surface->width = 0;
+       surface->height = 0;
        if (surface->buffer_ref.buffer) {
-               surface_width = weston_surface_buffer_width(surface);
-               surface_height = weston_surface_buffer_height(surface);
+               /* This already includes the buffer scale */
+               surface->width = weston_surface_buffer_width(surface);
+               surface->height = weston_surface_buffer_height(surface);
        }
 
        if (surface->configure && surface->pending.newly_attached)
                surface->configure(surface,
                                   surface->pending.sx, surface->pending.sy,
-                                  surface_width, surface_height);
+                                  surface->width, surface->height);
 
        if (surface->pending.buffer)
                wl_list_remove(&surface->pending.buffer_destroy_listener.link);
@@ -1685,20 +1905,21 @@ weston_surface_commit(struct weston_surface *surface)
                              &surface->pending.damage);
        pixman_region32_intersect_rect(&surface->damage, &surface->damage,
                                       0, 0,
-                                      surface->geometry.width,
-                                      surface->geometry.height);
+                                      surface->width,
+                                      surface->height);
        empty_region(&surface->pending.damage);
 
        /* wl_surface.set_opaque_region */
        pixman_region32_init_rect(&opaque, 0, 0,
-                                 surface->geometry.width,
-                                 surface->geometry.height);
+                                 surface->width,
+                                 surface->height);
        pixman_region32_intersect(&opaque,
                                  &opaque, &surface->pending.opaque);
 
        if (!pixman_region32_equal(&opaque, &surface->opaque)) {
                pixman_region32_copy(&surface->opaque, &opaque);
-               weston_surface_geometry_dirty(surface);
+               wl_list_for_each(view, &surface->views, surface_link)
+                       weston_view_geometry_dirty(view);
        }
 
        pixman_region32_fini(&opaque);
@@ -1706,8 +1927,8 @@ weston_surface_commit(struct weston_surface *surface)
        /* wl_surface.set_input_region */
        pixman_region32_fini(&surface->input);
        pixman_region32_init_rect(&surface->input, 0, 0,
-                                 surface->geometry.width,
-                                 surface->geometry.height);
+                                 surface->width,
+                                 surface->height);
        pixman_region32_intersect(&surface->input,
                                  &surface->input, &surface->pending.input);
 
@@ -1880,9 +2101,8 @@ static void
 weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
 {
        struct weston_surface *surface = sub->surface;
+       struct weston_view *view;
        pixman_region32_t opaque;
-       int surface_width = 0;
-       int surface_height = 0;
 
        /* wl_surface.set_buffer_transform */
        surface->buffer_transform = sub->cached.buffer_transform;
@@ -1895,14 +2115,16 @@ weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
                weston_surface_attach(surface, sub->cached.buffer_ref.buffer);
        weston_buffer_reference(&sub->cached.buffer_ref, NULL);
 
+       surface->width = 0;
+       surface->height = 0;
        if (surface->buffer_ref.buffer) {
-               surface_width = weston_surface_buffer_width(surface);
-               surface_height = weston_surface_buffer_height(surface);
+               surface->width = weston_surface_buffer_width(surface);
+               surface->height = weston_surface_buffer_height(surface);
        }
 
        if (surface->configure && sub->cached.newly_attached)
                surface->configure(surface, sub->cached.sx, sub->cached.sy,
-                                  surface_width, surface_height);
+                                  surface->width, surface->height);
        sub->cached.sx = 0;
        sub->cached.sy = 0;
        sub->cached.newly_attached = 0;
@@ -1912,20 +2134,21 @@ weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
                              &sub->cached.damage);
        pixman_region32_intersect_rect(&surface->damage, &surface->damage,
                                       0, 0,
-                                      surface->geometry.width,
-                                      surface->geometry.height);
+                                      surface->width,
+                                      surface->height);
        empty_region(&sub->cached.damage);
 
        /* wl_surface.set_opaque_region */
        pixman_region32_init_rect(&opaque, 0, 0,
-                                 surface->geometry.width,
-                                 surface->geometry.height);
+                                 surface->width,
+                                 surface->height);
        pixman_region32_intersect(&opaque,
                                  &opaque, &sub->cached.opaque);
 
        if (!pixman_region32_equal(&opaque, &surface->opaque)) {
                pixman_region32_copy(&surface->opaque, &opaque);
-               weston_surface_geometry_dirty(surface);
+               wl_list_for_each(view, &surface->views, surface_link)
+                       weston_view_geometry_dirty(view);
        }
 
        pixman_region32_fini(&opaque);
@@ -1933,8 +2156,8 @@ weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
        /* wl_surface.set_input_region */
        pixman_region32_fini(&surface->input);
        pixman_region32_init_rect(&surface->input, 0, 0,
-                                 surface->geometry.width,
-                                 surface->geometry.height);
+                                 surface->width,
+                                 surface->height);
        pixman_region32_intersect(&surface->input,
                                  &surface->input, &sub->cached.input);
 
@@ -2058,9 +2281,13 @@ static void
 weston_subsurface_parent_commit(struct weston_subsurface *sub,
                                int parent_is_synchronized)
 {
+       struct weston_view *view;
        if (sub->position.set) {
-               weston_surface_set_position(sub->surface,
-                                           sub->position.x, sub->position.y);
+               wl_list_for_each(view, &sub->surface->views, surface_link)
+                       weston_view_set_position(view,
+                                                sub->position.x,
+                                                sub->position.y);
+
                sub->position.set = 0;
        }
 
@@ -2073,19 +2300,19 @@ subsurface_configure(struct weston_surface *surface, int32_t dx, int32_t dy,
                     int32_t width, int32_t height)
 {
        struct weston_compositor *compositor = surface->compositor;
+       struct weston_view *view;
 
-       weston_surface_configure(surface,
-                                surface->geometry.x + dx,
-                                surface->geometry.y + dy,
-                                width, height);
+       wl_list_for_each(view, &surface->views, surface_link)
+               weston_view_configure(view,
+                                     view->geometry.x + dx,
+                                     view->geometry.y + dy,
+                                     width, height);
 
        /* No need to check parent mappedness, because if parent is not
         * mapped, parent is not in a visible layer, so this sub-surface
         * will not be drawn either.
         */
        if (!weston_surface_is_mapped(surface)) {
-               wl_list_init(&surface->layer_link);
-
                /* Cannot call weston_surface_update_transform(),
                 * because that would call it also for the parent surface,
                 * which might not be mapped yet. That would lead to
@@ -2357,6 +2584,8 @@ weston_subsurface_link_surface(struct weston_subsurface *sub,
 static void
 weston_subsurface_destroy(struct weston_subsurface *sub)
 {
+       struct weston_view *view, *next;
+
        assert(sub->surface);
 
        if (sub->resource) {
@@ -2364,7 +2593,9 @@ weston_subsurface_destroy(struct weston_subsurface *sub)
                assert(sub->parent_destroy_listener.notify ==
                       subsurface_handle_parent_destroy);
 
-               weston_surface_set_transform_parent(sub->surface, NULL);
+               wl_list_for_each_safe(view, next, &sub->surface->views, surface_link)
+                       weston_view_destroy(view);
+
                if (sub->parent)
                        weston_subsurface_unlink_parent(sub);
 
@@ -2403,6 +2634,8 @@ weston_subsurface_create(uint32_t id, struct weston_surface *surface,
        if (!sub)
                return NULL;
 
+       wl_list_init(&sub->unused_views);
+
        sub->resource =
                wl_resource_create(client, &wl_subsurface_interface, 1, id);
        if (!sub->resource) {
@@ -2417,7 +2650,6 @@ weston_subsurface_create(uint32_t id, struct weston_surface *surface,
        weston_subsurface_link_parent(sub, parent);
        weston_subsurface_cache_init(sub);
        sub->synchronized = 1;
-       weston_surface_set_transform_parent(surface, parent);
 
        return sub;
 }
@@ -2455,6 +2687,7 @@ subcompositor_get_subsurface(struct wl_client *client,
        struct weston_surface *parent =
                wl_resource_get_user_data(parent_resource);
        struct weston_subsurface *sub;
+       struct weston_view *view, *subview;
        static const char where[] = "get_subsurface: wl_subsurface@";
 
        if (surface == parent) {
@@ -2783,7 +3016,7 @@ weston_output_update_matrix(struct weston_output *output)
                magnification = 1 / (1 - output->zoom.spring_z.current);
                weston_matrix_init(&camera);
                weston_matrix_init(&modelview);
-               weston_output_update_zoom(output, output->zoom.type);
+               weston_output_update_zoom(output);
                weston_matrix_translate(&camera, output->zoom.trans_x,
                                        -output->zoom.trans_y, 0);
                weston_matrix_invert(&modelview, &camera);
@@ -3012,7 +3245,7 @@ weston_compositor_init(struct weston_compositor *ec,
                              ec, bind_subcompositor))
                return -1;
 
-       wl_list_init(&ec->surface_list);
+       wl_list_init(&ec->view_list);
        wl_list_init(&ec->plane_list);
        wl_list_init(&ec->layer_list);
        wl_list_init(&ec->seat_list);
@@ -3044,7 +3277,6 @@ weston_compositor_init(struct weston_compositor *ec,
        ec->ping_handler = NULL;
 
        screenshooter_create(ec);
-       text_cursor_position_notifier_create(ec);
        text_backend_init(ec);
 
        wl_data_device_manager_init(ec->wl_display);
index 5128875..8ae757b 100644 (file)
@@ -92,6 +92,8 @@ struct weston_shell_interface {
        struct shell_surface *(*create_shell_surface)(void *shell,
                                                      struct weston_surface *surface,
                                                      const struct weston_shell_client *client);
+       struct weston_view *(*get_primary_view)(void *shell,
+                                               struct shell_surface *shsurf);
 
        void (*set_toplevel)(struct shell_surface *shsurf);
 
@@ -140,18 +142,12 @@ struct weston_spring {
        uint32_t clip;
 };
 
-enum {
-       ZOOM_FOCUS_POINTER,
-       ZOOM_FOCUS_TEXT
-};
-
 struct weston_fixed_point {
        wl_fixed_t x, y;
 };
 
 struct weston_output_zoom {
        int active;
-       uint32_t type;
        float increment;
        float level;
        float max_level;
@@ -163,7 +159,6 @@ struct weston_output_zoom {
        struct weston_fixed_point from;
        struct weston_fixed_point to;
        struct weston_fixed_point current;
-       struct weston_fixed_point text_cursor;
 };
 
 /* bit compatible with drm definitions. */
@@ -311,11 +306,11 @@ struct weston_pointer {
 
        struct wl_list resource_list;
        struct wl_list focus_resource_list;
-       struct weston_surface *focus;
+       struct weston_view *focus;
        uint32_t focus_serial;
        struct wl_signal focus_signal;
 
-       struct weston_surface *sprite;
+       struct weston_view *sprite;
        struct wl_listener sprite_destroy_listener;
        int32_t hotspot_x, hotspot_y;
 
@@ -336,7 +331,7 @@ struct weston_touch {
 
        struct wl_list resource_list;
        struct wl_list focus_resource_list;
-       struct weston_surface *focus;
+       struct weston_view *focus;
        uint32_t focus_serial;
        struct wl_signal focus_signal;
 
@@ -354,7 +349,7 @@ void
 weston_pointer_destroy(struct weston_pointer *pointer);
 void
 weston_pointer_set_focus(struct weston_pointer *pointer,
-                        struct weston_surface *surface,
+                        struct weston_view *view,
                         wl_fixed_t sx, wl_fixed_t sy);
 void
 weston_pointer_start_grab(struct weston_pointer *pointer,
@@ -384,7 +379,7 @@ void
 weston_touch_destroy(struct weston_touch *touch);
 void
 weston_touch_set_focus(struct weston_seat *seat,
-                         struct weston_surface *surface);
+                      struct weston_view *view);
 void
 weston_touch_start_grab(struct weston_touch *device,
                        struct weston_touch_grab *grab);
@@ -504,7 +499,7 @@ enum {
 };
 
 struct weston_layer {
-       struct wl_list surface_list;
+       struct wl_list view_list;
        struct wl_list link;
 };
 
@@ -525,10 +520,12 @@ struct weston_renderer {
        void (*flush_damage)(struct weston_surface *surface);
        void (*attach)(struct weston_surface *es, struct weston_buffer *buffer);
        int (*create_surface)(struct weston_surface *surface);
+       int (*create_view)(struct weston_view *view);
        void (*surface_set_color)(struct weston_surface *surface,
                               float red, float green,
                               float blue, float alpha);
        void (*destroy_surface)(struct weston_surface *surface);
+       void (*destroy_view)(struct weston_view *view);
        void (*destroy)(struct weston_compositor *ec);
 };
 
@@ -574,7 +571,7 @@ struct weston_compositor {
        struct wl_list output_list;
        struct wl_list seat_list;
        struct wl_list layer_list;
-       struct wl_list surface_list;
+       struct wl_list view_list;
        struct wl_list plane_list;
        struct wl_list key_binding_list;
        struct wl_list button_binding_list;
@@ -685,51 +682,52 @@ struct weston_subsurface {
        } cached;
 
        int synchronized;
+
+       /* Used for constructing the view tree */
+       struct wl_list unused_views;
 };
 
-/* Using weston_surface transformations
+/* Using weston_view transformations
  *
- * To add a transformation to a surface, create a struct weston_transform, and
- * add it to the list surface->geometry.transformation_list. Whenever you
- * change the list, anything under surface->geometry, or anything in the
+ * To add a transformation to a view, create a struct weston_transform, and
+ * add it to the list view->geometry.transformation_list. Whenever you
+ * change the list, anything under view->geometry, or anything in the
  * weston_transforms linked into the list, you must call
- * weston_surface_geometry_dirty().
+ * weston_view_geometry_dirty().
  *
  * The order in the list defines the order of transformations. Let the list
  * contain the transformation matrices M1, ..., Mn as head to tail. The
- * transformation is applied to surface-local coordinate vector p as
+ * transformation is applied to view-local coordinate vector p as
  *    P = Mn * ... * M2 * M1 * p
  * to produce the global coordinate vector P. The total transform
  *    Mn * ... * M2 * M1
- * is cached in surface->transform.matrix, and the inverse of it in
- * surface->transform.inverse.
+ * is cached in view->transform.matrix, and the inverse of it in
+ * view->transform.inverse.
  *
- * The list always contains surface->transform.position transformation, which
- * is the translation by surface->geometry.x and y.
+ * The list always contains view->transform.position transformation, which
+ * is the translation by view->geometry.x and y.
  *
  * If you want to apply a transformation in local coordinates, add your
  * weston_transform to the head of the list. If you want to apply a
  * transformation in global coordinates, add it to the tail of the list.
  *
- * If surface->geometry.parent is set, the total transformation of this
- * surface will be the parent's total transformation and this transformation
+ * If view->geometry.parent is set, the total transformation of this
+ * view will be the parent's total transformation and this transformation
  * combined:
  *    Mparent * Mn * ... * M2 * M1
  */
 
-struct weston_surface {
-       struct wl_resource *resource;
+struct weston_view {
+       struct weston_surface *surface;
+       struct wl_list surface_link;
        struct wl_signal destroy_signal;
-       struct weston_compositor *compositor;
-       pixman_region32_t clip;
-       pixman_region32_t damage;
-       pixman_region32_t opaque;        /* part of geometry, see below */
-       pixman_region32_t input;
+
        struct wl_list link;
        struct wl_list layer_link;
-       float alpha;                     /* part of geometry, see below */
        struct weston_plane *plane;
-       int32_t ref_count;
+
+       pixman_region32_t clip;
+       float alpha;                     /* part of geometry, see below */
 
        void *renderer_state;
 
@@ -745,14 +743,14 @@ struct weston_surface {
                struct wl_list transformation_list;
 
                /* managed by weston_surface_set_transform_parent() */
-               struct weston_surface *parent;
+               struct weston_view *parent;
                struct wl_listener parent_destroy_listener;
                struct wl_list child_list; /* geometry.parent_link */
                struct wl_list parent_link;
        } geometry;
 
        /* State derived from geometry state, read-only.
-        * This is updated by weston_surface_update_transform().
+        * This is updated by weston_view_update_transform().
         */
        struct {
                int dirty;
@@ -782,6 +780,39 @@ struct weston_surface {
         * displayed on.
         */
        uint32_t output_mask;
+};
+
+struct weston_surface {
+       struct wl_resource *resource;
+       struct wl_signal destroy_signal;
+       struct weston_compositor *compositor;
+       pixman_region32_t damage;
+       pixman_region32_t opaque;        /* part of geometry, see below */
+       pixman_region32_t input;
+       int32_t width, height;
+       int32_t ref_count;
+
+       /* Not for long-term storage.  This exists for book-keeping while
+        * iterating over surfaces and views
+        */
+       int32_t touched;
+
+       void *renderer_state;
+
+       struct wl_list views;
+
+       /*
+        * Which output to vsync this surface to.
+        * Used to determine, whether to send or queue frame events.
+        * Must be NULL, if 'link' is not in weston_compositor::surface_list.
+        */
+       struct weston_output *output;
+
+       /*
+        * A more complete representation of all outputs this surface is
+        * displayed on.
+        */
+       uint32_t output_mask;
 
        struct wl_list frame_callback_list;
 
@@ -843,29 +874,29 @@ void
 weston_version(int *major, int *minor, int *micro);
 
 void
-weston_surface_update_transform(struct weston_surface *surface);
+weston_view_update_transform(struct weston_view *view);
 
 void
-weston_surface_geometry_dirty(struct weston_surface *surface);
+weston_view_geometry_dirty(struct weston_view *view);
 
 void
-weston_surface_to_global_fixed(struct weston_surface *surface,
-                              wl_fixed_t sx, wl_fixed_t sy,
-                              wl_fixed_t *x, wl_fixed_t *y);
+weston_view_to_global_fixed(struct weston_view *view,
+                           wl_fixed_t sx, wl_fixed_t sy,
+                           wl_fixed_t *x, wl_fixed_t *y);
 void
-weston_surface_to_global_float(struct weston_surface *surface,
-                              float sx, float sy, float *x, float *y);
+weston_view_to_global_float(struct weston_view *view,
+                           float sx, float sy, float *x, float *y);
 
 void
-weston_surface_from_global_float(struct weston_surface *surface,
-                                float x, float y, float *sx, float *sy);
+weston_view_from_global_float(struct weston_view *view,
+                             float x, float y, float *vx, float *vy);
 void
-weston_surface_from_global(struct weston_surface *surface,
-                          int32_t x, int32_t y, int32_t *sx, int32_t *sy);
+weston_view_from_global(struct weston_view *view,
+                       int32_t x, int32_t y, int32_t *vx, int32_t *vy);
 void
-weston_surface_from_global_fixed(struct weston_surface *surface,
-                                wl_fixed_t x, wl_fixed_t y,
-                                wl_fixed_t *sx, wl_fixed_t *sy);
+weston_view_from_global_fixed(struct weston_view *view,
+                             wl_fixed_t x, wl_fixed_t y,
+                             wl_fixed_t *vx, wl_fixed_t *vy);
 int32_t
 weston_surface_buffer_width(struct weston_surface *surface);
 int32_t
@@ -876,8 +907,7 @@ weston_surface_to_buffer_float(struct weston_surface *surface,
                               float x, float y, float *bx, float *by);
 WL_EXPORT void
 weston_surface_to_buffer(struct weston_surface *surface,
-                         int sx, int sy, int *bx, int *by);
-
+                        int sx, int sy, int *bx, int *by);
 pixman_box32_t
 weston_surface_to_buffer_rect(struct weston_surface *surface,
                              pixman_box32_t rect);
@@ -959,10 +989,10 @@ void
 weston_compositor_offscreen(struct weston_compositor *compositor);
 void
 weston_compositor_sleep(struct weston_compositor *compositor);
-struct weston_surface *
-weston_compositor_pick_surface(struct weston_compositor *compositor,
-                              wl_fixed_t x, wl_fixed_t y,
-                              wl_fixed_t *sx, wl_fixed_t *sy);
+struct weston_view *
+weston_compositor_pick_view(struct weston_compositor *compositor,
+                           wl_fixed_t x, wl_fixed_t y,
+                           wl_fixed_t *sx, wl_fixed_t *sy);
 
 
 struct weston_binding;
@@ -1048,20 +1078,32 @@ weston_compositor_top(struct weston_compositor *compositor);
 struct weston_surface *
 weston_surface_create(struct weston_compositor *compositor);
 
+struct weston_view *
+weston_view_create(struct weston_surface *surface);
+
+void
+weston_view_destroy(struct weston_view *view);
+
+void
+weston_view_configure(struct weston_view *view,
+                     float x, float y, int width, int height);
+
 void
-weston_surface_configure(struct weston_surface *surface,
-                        float x, float y, int width, int height);
+weston_view_restack(struct weston_view *surface, struct wl_list *below);
 
 void
-weston_surface_restack(struct weston_surface *surface, struct wl_list *below);
+weston_view_set_position(struct weston_view *view,
+                        float x, float y);
 
 void
-weston_surface_set_position(struct weston_surface *surface,
-                           float x, float y);
+weston_view_set_transform_parent(struct weston_view *view,
+                                struct weston_view *parent);
+
+int
+weston_view_is_mapped(struct weston_view *view);
 
 void
-weston_surface_set_transform_parent(struct weston_surface *surface,
-                                   struct weston_surface *parent);
+weston_view_schedule_repaint(struct weston_view *view);
 
 int
 weston_surface_is_mapped(struct weston_surface *surface);
@@ -1073,11 +1115,14 @@ void
 weston_surface_damage(struct weston_surface *surface);
 
 void
-weston_surface_damage_below(struct weston_surface *surface);
+weston_view_damage_below(struct weston_view *view);
 
 void
-weston_surface_move_to_plane(struct weston_surface *surface,
-                            struct weston_plane *plane);
+weston_view_move_to_plane(struct weston_view *view,
+                         struct weston_plane *plane);
+void
+weston_view_unmap(struct weston_view *view);
+
 void
 weston_surface_unmap(struct weston_surface *surface);
 
@@ -1100,12 +1145,9 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display,
 void
 weston_compositor_shutdown(struct weston_compositor *ec);
 void
-weston_text_cursor_position_notify(struct weston_surface *surface,
-                                               wl_fixed_t x, wl_fixed_t y);
-void
 weston_output_init_zoom(struct weston_output *output);
 void
-weston_output_update_zoom(struct weston_output *output, uint32_t type);
+weston_output_update_zoom(struct weston_output *output);
 void
 weston_output_update_matrix(struct weston_output *output);
 void
@@ -1187,9 +1229,6 @@ screenshooter_create(struct weston_compositor *ec);
 struct clipboard *
 clipboard_create(struct weston_seat *seat);
 
-void
-text_cursor_position_notifier_create(struct weston_compositor *ec);
-
 int
 text_backend_init(struct weston_compositor *ec);
 
@@ -1212,23 +1251,23 @@ weston_client_launch(struct weston_compositor *compositor,
 void
 weston_watch_process(struct weston_process *process);
 
-struct weston_surface_animation;
-typedef        void (*weston_surface_animation_done_func_t)(struct weston_surface_animation *animation, void *data);
+struct weston_view_animation;
+typedef        void (*weston_view_animation_done_func_t)(struct weston_view_animation *animation, void *data);
 
-struct weston_surface_animation *
-weston_zoom_run(struct weston_surface *surface, float start, float stop,
-               weston_surface_animation_done_func_t done, void *data);
+struct weston_view_animation *
+weston_zoom_run(struct weston_view *view, float start, float stop,
+               weston_view_animation_done_func_t done, void *data);
 
-struct weston_surface_animation *
-weston_fade_run(struct weston_surface *surface,
+struct weston_view_animation *
+weston_fade_run(struct weston_view *view,
                float start, float end, float k,
-               weston_surface_animation_done_func_t done, void *data);
+               weston_view_animation_done_func_t done, void *data);
 void
-weston_fade_update(struct weston_surface_animation *fade, float target);
+weston_fade_update(struct weston_view_animation *fade, float target);
 
-struct weston_surface_animation *
-weston_slide_run(struct weston_surface *surface, float start, float stop,
-                weston_surface_animation_done_func_t done, void *data);
+struct weston_view_animation *
+weston_slide_run(struct weston_view *view, float start, float stop,
+                weston_view_animation_done_func_t done, void *data);
 
 void
 weston_surface_set_color(struct weston_surface *surface,
index 858235f..3e22b51 100644 (file)
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <assert.h>
 
 #include "compositor.h"
 
@@ -33,11 +34,11 @@ struct weston_drag {
        struct wl_client *client;
        struct weston_data_source *data_source;
        struct wl_listener data_source_listener;
-       struct weston_surface *focus;
+       struct weston_view *focus;
        struct wl_resource *focus_resource;
        struct wl_listener focus_listener;
        struct weston_pointer_grab grab;
-       struct weston_surface *icon;
+       struct weston_view *icon;
        struct wl_listener icon_destroy_listener;
        int32_t dx, dy;
 };
@@ -178,14 +179,17 @@ drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_
        struct wl_list *list;
        float fx, fy;
 
+       assert(es->configure == drag_surface_configure);
+
        if (!weston_surface_is_mapped(es) && es->buffer_ref.buffer) {
-               if (pointer->sprite && weston_surface_is_mapped(pointer->sprite))
+               if (pointer->sprite && weston_view_is_mapped(pointer->sprite))
                        list = &pointer->sprite->layer_link;
                else
-                       list = &es->compositor->cursor_layer.surface_list;
+                       list = &es->compositor->cursor_layer.view_list;
 
-               wl_list_insert(list, &es->layer_link);
-               weston_surface_update_transform(es);
+               wl_list_remove(&drag->icon->layer_link);
+               wl_list_insert(list, &drag->icon->layer_link);
+               weston_view_update_transform(drag->icon);
                empty_region(&es->pending.input);
        }
 
@@ -194,7 +198,7 @@ drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_
 
        fx = wl_fixed_to_double(pointer->x) + drag->dx;
        fy = wl_fixed_to_double(pointer->y) + drag->dy;
-       weston_surface_configure(es, fx, fy, width, height);
+       weston_view_configure(drag->icon, fx, fy, width, height);
 }
 
 static void
@@ -207,7 +211,7 @@ destroy_drag_focus(struct wl_listener *listener, void *data)
 }
 
 static void
-weston_drag_set_focus(struct weston_drag *drag, struct weston_surface *surface,
+weston_drag_set_focus(struct weston_drag *drag, struct weston_view *view,
                      wl_fixed_t sx, wl_fixed_t sy)
 {
        struct weston_pointer *pointer = drag->grab.pointer;
@@ -215,6 +219,11 @@ weston_drag_set_focus(struct weston_drag *drag, struct weston_surface *surface,
        struct wl_display *display = pointer->seat->compositor->wl_display;
        uint32_t serial;
 
+       if (drag->focus && view && drag->focus->surface == view->surface) {
+               drag->focus = view;
+               return;
+       }
+
        if (drag->focus_resource) {
                wl_data_device_send_leave(drag->focus_resource);
                wl_list_remove(&drag->focus_listener.link);
@@ -222,15 +231,15 @@ weston_drag_set_focus(struct weston_drag *drag, struct weston_surface *surface,
                drag->focus = NULL;
        }
 
-       if (!surface)
+       if (!view || !view->surface->resource)
                return;
 
        if (!drag->data_source &&
-           wl_resource_get_client(surface->resource) != drag->client)
+           wl_resource_get_client(view->surface->resource) != drag->client)
                return;
 
        resource = wl_resource_find_for_client(&pointer->seat->drag_resource_list,
-                                              wl_resource_get_client(surface->resource));
+                                              wl_resource_get_client(view->surface->resource));
        if (!resource)
                return;
 
@@ -243,10 +252,10 @@ weston_drag_set_focus(struct weston_drag *drag, struct weston_surface *surface,
                        return;
        }
 
-       wl_data_device_send_enter(resource, serial, surface->resource,
+       wl_data_device_send_enter(resource, serial, view->surface->resource,
                                  sx, sy, offer);
 
-       drag->focus = surface;
+       drag->focus = view;
        drag->focus_listener.notify = destroy_drag_focus;
        wl_resource_add_destroy_listener(resource, &drag->focus_listener);
        drag->focus_resource = resource;
@@ -258,14 +267,14 @@ drag_grab_focus(struct weston_pointer_grab *grab)
        struct weston_drag *drag =
                container_of(grab, struct weston_drag, grab);
        struct weston_pointer *pointer = grab->pointer;
-       struct weston_surface *surface;
+       struct weston_view *view;
        wl_fixed_t sx, sy;
 
-       surface = weston_compositor_pick_surface(pointer->seat->compositor,
-                                                pointer->x, pointer->y,
-                                                &sx, &sy);
-       if (drag->focus != surface)
-               weston_drag_set_focus(drag, surface, sx, sy);
+       view = weston_compositor_pick_view(pointer->seat->compositor,
+                                          pointer->x, pointer->y,
+                                          &sx, &sy);
+       if (drag->focus != view)
+               weston_drag_set_focus(drag, view, sx, sy);
 }
 
 static void
@@ -280,14 +289,14 @@ drag_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
        if (drag->icon) {
                fx = wl_fixed_to_double(pointer->x) + drag->dx;
                fy = wl_fixed_to_double(pointer->y) + drag->dy;
-               weston_surface_set_position(drag->icon, fx, fy);
-               weston_surface_schedule_repaint(drag->icon);
+               weston_view_set_position(drag->icon, fx, fy);
+               weston_view_schedule_repaint(drag->icon);
        }
 
        if (drag->focus_resource) {
-               weston_surface_from_global_fixed(drag->focus,
-                                                pointer->x, pointer->y,
-                                                &sx, &sy);
+               weston_view_from_global_fixed(drag->focus,
+                                             pointer->x, pointer->y,
+                                             &sx, &sy);
 
                wl_data_device_send_motion(drag->focus_resource, time, sx, sy);
        }
@@ -297,12 +306,13 @@ static void
 data_device_end_drag_grab(struct weston_drag *drag)
 {
        if (drag->icon) {
-               if (weston_surface_is_mapped(drag->icon))
-                       weston_surface_unmap(drag->icon);
+               if (weston_view_is_mapped(drag->icon))
+                       weston_view_unmap(drag->icon);
 
-               drag->icon->configure = NULL;
-               empty_region(&drag->icon->pending.input);
+               drag->icon->surface->configure = NULL;
+               empty_region(&drag->icon->surface->pending.input);
                wl_list_remove(&drag->icon_destroy_listener.link);
+               weston_view_destroy(drag->icon);
        }
 
        weston_drag_set_focus(drag, NULL, 0, 0);
@@ -373,21 +383,28 @@ weston_seat_start_drag(struct weston_seat *seat,
        drag->grab.interface = &drag_grab_interface;
        drag->client = client;
        drag->data_source = source;
-       drag->icon = icon;
-
-       if (source) {
-               drag->data_source_listener.notify = destroy_data_device_source;
-               wl_signal_add(&source->destroy_signal,
-                             &drag->data_source_listener);
-       }
 
        if (icon) {
+               drag->icon = weston_view_create(icon);
+               if (drag->icon == NULL) {
+                       free(drag);
+                       return -1;
+               }
+
                drag->icon_destroy_listener.notify = handle_drag_icon_destroy;
                wl_signal_add(&icon->destroy_signal,
                              &drag->icon_destroy_listener);
 
                icon->configure = drag_surface_configure;
                icon->configure_private = drag;
+       } else {
+               drag->icon = NULL;
+       }
+
+       if (source) {
+               drag->data_source_listener.notify = destroy_data_device_source;
+               wl_signal_add(&source->destroy_signal,
+                             &drag->data_source_listener);
        }
 
        weston_pointer_set_focus(seat->pointer, NULL,
@@ -409,7 +426,8 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
 
        if (seat->pointer->button_count == 0 ||
            seat->pointer->grab_serial != serial ||
-           seat->pointer->focus != wl_resource_get_user_data(origin_resource))
+           !seat->pointer->focus ||
+           seat->pointer->focus->surface != wl_resource_get_user_data(origin_resource))
                return;
 
        /* FIXME: Check that the data source type array isn't empty. */
index f02445b..2cb24fa 100644 (file)
@@ -193,7 +193,7 @@ gl_renderer_print_egl_error_state(void)
  * polygon area.
  */
 static int
-calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
+calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
                pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
 {
 
@@ -213,8 +213,8 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
 
        /* transform surface to screen space: */
        for (i = 0; i < surf.n; i++)
-               weston_surface_to_global_float(es, surf.x[i], surf.y[i],
-                                              &surf.x[i], &surf.y[i]);
+               weston_view_to_global_float(ev, surf.x[i], surf.y[i],
+                                           &surf.x[i], &surf.y[i]);
 
        /* find bounding box: */
        min_x = max_x = surf.x[0];
@@ -238,9 +238,8 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
         * there will be only four edges.  We just need to clip the surface
         * vertices to the clip rect bounds:
         */
-       if (!es->transform.enabled) {
+       if (!ev->transform.enabled)
                return clip_simple(&ctx, &surf, ex, ey);
-       }
 
        /* Transformed case: use a general polygon clipping algorithm to
         * clip the surface rectangle with each side of 'rect'.
@@ -257,11 +256,11 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
 }
 
 static int
-texture_region(struct weston_surface *es, pixman_region32_t *region,
+texture_region(struct weston_view *ev, pixman_region32_t *region,
                pixman_region32_t *surf_region)
 {
-       struct gl_surface_state *gs = get_surface_state(es);
-       struct weston_compositor *ec = es->compositor;
+       struct gl_surface_state *gs = get_surface_state(ev->surface);
+       struct weston_compositor *ec = ev->surface->compositor;
        struct gl_renderer *gr = get_renderer(ec);
        GLfloat *v, inv_width, inv_height;
        unsigned int *vtxcnt, nvtx = 0;
@@ -302,18 +301,20 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
                         * form the intersection of the clip rect and the transformed
                         * surface.
                         */
-                       n = calculate_edges(es, rect, surf_rect, ex, ey);
+                       n = calculate_edges(ev, rect, surf_rect, ex, ey);
                        if (n < 3)
                                continue;
 
                        /* emit edge points: */
                        for (k = 0; k < n; k++) {
-                               weston_surface_from_global_float(es, ex[k], ey[k], &sx, &sy);
+                               weston_view_from_global_float(ev, ex[k], ey[k],
+                                                             &sx, &sy);
                                /* position: */
                                *(v++) = ex[k];
                                *(v++) = ey[k];
                                /* texcoord: */
-                               weston_surface_to_buffer_float(es, sx, sy,
+                               weston_surface_to_buffer_float(ev->surface,
+                                                              sx, sy,
                                                               &bx, &by);
                                *(v++) = bx * inv_width;
                                if (gs->y_inverted) {
@@ -331,9 +332,9 @@ texture_region(struct weston_surface *es, pixman_region32_t *region,
 }
 
 static void
-triangle_fan_debug(struct weston_surface *surface, int first, int count)
+triangle_fan_debug(struct weston_view *view, int first, int count)
 {
-       struct weston_compositor *compositor = surface->compositor;
+       struct weston_compositor *compositor = view->surface->compositor;
        struct gl_renderer *gr = get_renderer(compositor);
        int i;
        GLushort *buffer;
@@ -371,10 +372,10 @@ triangle_fan_debug(struct weston_surface *surface, int first, int count)
 }
 
 static void
-repaint_region(struct weston_surface *es, pixman_region32_t *region,
+repaint_region(struct weston_view *ev, pixman_region32_t *region,
                pixman_region32_t *surf_region)
 {
-       struct weston_compositor *ec = es->compositor;
+       struct weston_compositor *ec = ev->surface->compositor;
        struct gl_renderer *gr = get_renderer(ec);
        GLfloat *v;
        unsigned int *vtxcnt;
@@ -388,7 +389,7 @@ repaint_region(struct weston_surface *es, pixman_region32_t *region,
         * polygon for each pair, and store it as a triangle fan if
         * it has a non-zero area (at least 3 vertices1, actually).
         */
-       nfans = texture_region(es, region, surf_region);
+       nfans = texture_region(ev, region, surf_region);
 
        v = gr->vertices.data;
        vtxcnt = gr->vtxcnt.data;
@@ -404,7 +405,7 @@ repaint_region(struct weston_surface *es, pixman_region32_t *region,
        for (i = 0, first = 0; i < nfans; i++) {
                glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
                if (gr->fan_debug)
-                       triangle_fan_debug(es, first, vtxcnt[i]);
+                       triangle_fan_debug(ev, first, vtxcnt[i]);
                first += vtxcnt[i];
        }
 
@@ -464,28 +465,28 @@ use_shader(struct gl_renderer *gr, struct gl_shader *shader)
 
 static void
 shader_uniforms(struct gl_shader *shader,
-                      struct weston_surface *surface,
-                      struct weston_output *output)
+               struct weston_view *view,
+               struct weston_output *output)
 {
        int i;
-       struct gl_surface_state *gs = get_surface_state(surface);
+       struct gl_surface_state *gs = get_surface_state(view->surface);
 
        glUniformMatrix4fv(shader->proj_uniform,
                           1, GL_FALSE, output->matrix.d);
        glUniform4fv(shader->color_uniform, 1, gs->color);
-       glUniform1f(shader->alpha_uniform, surface->alpha);
+       glUniform1f(shader->alpha_uniform, view->alpha);
 
        for (i = 0; i < gs->num_textures; i++)
                glUniform1i(shader->tex_uniforms[i], i);
 }
 
 static void
-draw_surface(struct weston_surface *es, struct weston_output *output,
-            pixman_region32_t *damage) /* in global coordinates */
+draw_view(struct weston_view *ev, struct weston_output *output,
+         pixman_region32_t *damage) /* in global coordinates */
 {
-       struct weston_compositor *ec = es->compositor;
+       struct weston_compositor *ec = ev->surface->compositor;
        struct gl_renderer *gr = get_renderer(ec);
-       struct gl_surface_state *gs = get_surface_state(es);
+       struct gl_surface_state *gs = get_surface_state(ev->surface);
        /* repaint bounding region in global coordinates: */
        pixman_region32_t repaint;
        /* non-opaque region in surface coordinates: */
@@ -495,8 +496,8 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
 
        pixman_region32_init(&repaint);
        pixman_region32_intersect(&repaint,
-                                 &es->transform.boundingbox, damage);
-       pixman_region32_subtract(&repaint, &repaint, &es->clip);
+                                 &ev->transform.boundingbox, damage);
+       pixman_region32_subtract(&repaint, &repaint, &ev->clip);
 
        if (!pixman_region32_not_empty(&repaint))
                goto out;
@@ -505,13 +506,14 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
 
        if (gr->fan_debug) {
                use_shader(gr, &gr->solid_shader);
-               shader_uniforms(&gr->solid_shader, es, output);
+               shader_uniforms(&gr->solid_shader, ev, output);
        }
 
        use_shader(gr, gs->shader);
-       shader_uniforms(gs->shader, es, output);
+       shader_uniforms(gs->shader, ev, output);
 
-       if (es->transform.enabled || output->zoom.active || output->current_scale != es->buffer_scale)
+       if (ev->transform.enabled || output->zoom.active ||
+           output->current_scale != ev->surface->buffer_scale)
                filter = GL_LINEAR;
        else
                filter = GL_NEAREST;
@@ -525,10 +527,11 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
 
        /* blended region is whole surface minus opaque region: */
        pixman_region32_init_rect(&surface_blend, 0, 0,
-                                 es->geometry.width, es->geometry.height);
-       pixman_region32_subtract(&surface_blend, &surface_blend, &es->opaque);
+                                 ev->geometry.width, ev->geometry.height);
+       pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
 
-       if (pixman_region32_not_empty(&es->opaque)) {
+       /* XXX: Should we be using ev->transform.opaque here? */
+       if (pixman_region32_not_empty(&ev->surface->opaque)) {
                if (gs->shader == &gr->texture_shader_rgba) {
                        /* Special case for RGBA textures with possibly
                         * bad data in alpha channel: use the shader
@@ -536,21 +539,21 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
                         * Xwayland surfaces need this.
                         */
                        use_shader(gr, &gr->texture_shader_rgbx);
-                       shader_uniforms(&gr->texture_shader_rgbx, es, output);
+                       shader_uniforms(&gr->texture_shader_rgbx, ev, output);
                }
 
-               if (es->alpha < 1.0)
+               if (ev->alpha < 1.0)
                        glEnable(GL_BLEND);
                else
                        glDisable(GL_BLEND);
 
-               repaint_region(es, &repaint, &es->opaque);
+               repaint_region(ev, &repaint, &ev->surface->opaque);
        }
 
        if (pixman_region32_not_empty(&surface_blend)) {
                use_shader(gr, gs->shader);
                glEnable(GL_BLEND);
-               repaint_region(es, &repaint, &surface_blend);
+               repaint_region(ev, &repaint, &surface_blend);
        }
 
        pixman_region32_fini(&surface_blend);
@@ -560,14 +563,14 @@ out:
 }
 
 static void
-repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
+repaint_views(struct weston_output *output, pixman_region32_t *damage)
 {
        struct weston_compositor *compositor = output->compositor;
-       struct weston_surface *surface;
+       struct weston_view *view;
 
-       wl_list_for_each_reverse(surface, &compositor->surface_list, link)
-               if (surface->plane == &compositor->primary_plane)
-                       draw_surface(surface, output, damage);
+       wl_list_for_each_reverse(view, &compositor->view_list, link)
+               if (view->plane == &compositor->primary_plane)
+                       draw_view(view, output, damage);
 }
 
 
@@ -762,7 +765,7 @@ gl_renderer_repaint_output(struct weston_output *output,
                pixman_region32_subtract(&undamaged, &output->region,
                                         output_damage);
                gr->fan_debug = 0;
-               repaint_surfaces(output, &undamaged);
+               repaint_views(output, &undamaged);
                gr->fan_debug = 1;
                pixman_region32_fini(&undamaged);
        }
@@ -775,7 +778,7 @@ gl_renderer_repaint_output(struct weston_output *output,
 
        pixman_region32_union(&total_damage, &buffer_damage, output_damage);
 
-       repaint_surfaces(output, &total_damage);
+       repaint_views(output, &total_damage);
 
        pixman_region32_fini(&total_damage);
        pixman_region32_fini(&buffer_damage);
@@ -830,6 +833,8 @@ gl_renderer_flush_damage(struct weston_surface *surface)
        struct gl_renderer *gr = get_renderer(surface->compositor);
        struct gl_surface_state *gs = get_surface_state(surface);
        struct weston_buffer *buffer = gs->buffer_ref.buffer;
+       struct weston_view *view;
+       int texture_used;
        GLenum format;
        int pixel_type;
 
@@ -850,7 +855,14 @@ gl_renderer_flush_damage(struct weston_surface *surface)
         * hold the reference to the buffer, in case the surface
         * migrates back to the primary plane.
         */
-       if (surface->plane != &surface->compositor->primary_plane)
+       texture_used = 0;
+       wl_list_for_each(view, &surface->views, surface_link) {
+               if (view->plane == &surface->compositor->primary_plane) {
+                       texture_used = 1;
+                       break;
+               }
+       }
+       if (!texture_used)
                return;
 
        if (!pixman_region32_not_empty(&gs->texture_damage))
index 9648f62..5ad247a 100644 (file)
@@ -96,18 +96,18 @@ static void
 default_grab_focus(struct weston_pointer_grab *grab)
 {
        struct weston_pointer *pointer = grab->pointer;
-       struct weston_surface *surface;
+       struct weston_view *view;
        wl_fixed_t sx, sy;
 
        if (pointer->button_count > 0)
                return;
 
-       surface = weston_compositor_pick_surface(pointer->seat->compositor,
-                                                pointer->x, pointer->y,
-                                                &sx, &sy);
+       view = weston_compositor_pick_view(pointer->seat->compositor,
+                                          pointer->x, pointer->y,
+                                          &sx, &sy);
 
-       if (pointer->focus != surface)
-               weston_pointer_set_focus(pointer, surface, sx, sy);
+       if (pointer->focus != view)
+               weston_pointer_set_focus(pointer, view, sx, sy);
 }
 
 static void
@@ -120,9 +120,9 @@ default_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
 
        resource_list = &pointer->focus_resource_list;
        wl_resource_for_each(resource, resource_list) {
-               weston_surface_from_global_fixed(pointer->focus,
-                                                pointer->x, pointer->y,
-                                                &sx, &sy);
+               weston_view_from_global_fixed(pointer->focus,
+                                             pointer->x, pointer->y,
+                                             &sx, &sy);
                wl_pointer_send_motion(resource, time, sx, sy);
        }
 }
@@ -133,7 +133,7 @@ default_grab_button(struct weston_pointer_grab *grab,
 {
        struct weston_pointer *pointer = grab->pointer;
        struct weston_compositor *compositor = pointer->seat->compositor;
-       struct weston_surface *surface;
+       struct weston_view *view;
        struct wl_resource *resource;
        uint32_t serial;
        enum wl_pointer_button_state state = state_w;
@@ -154,12 +154,11 @@ default_grab_button(struct weston_pointer_grab *grab,
 
        if (pointer->button_count == 0 &&
            state == WL_POINTER_BUTTON_STATE_RELEASED) {
-               surface = weston_compositor_pick_surface(compositor,
-                                                        pointer->x,
-                                                        pointer->y,
-                                                        &sx, &sy);
+               view = weston_compositor_pick_view(compositor,
+                                                  pointer->x, pointer->y,
+                                                  &sx, &sy);
 
-               weston_pointer_set_focus(pointer, surface, sx, sy);
+               weston_pointer_set_focus(pointer, view, sx, sy);
        }
 }
 
@@ -186,7 +185,7 @@ default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
                serial = wl_display_next_serial(display);
                wl_resource_for_each(resource, resource_list)
                                wl_touch_send_down(resource, serial, time,
-                                                  touch->focus->resource,
+                                                  touch->focus->surface->resource,
                                                   touch_id, sx, sy);
        }
 }
@@ -295,6 +294,15 @@ find_resource_for_surface(struct wl_list *list, struct weston_surface *surface)
        return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource));
 }
 
+static struct wl_resource *
+find_resource_for_view(struct wl_list *list, struct weston_view *view)
+{
+       if (!view)
+               return NULL;
+
+       return find_resource_for_surface(list, view->surface);
+}
+
 static void
 default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
                       uint32_t mods_depressed, uint32_t mods_latched,
@@ -311,9 +319,9 @@ default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
                wl_keyboard_send_modifiers(resource, serial, mods_depressed,
                                           mods_latched, mods_locked, group);
        }
-       if (pointer && pointer->focus && pointer->focus != keyboard->focus) {
+       if (pointer && pointer->focus && pointer->focus->surface != keyboard->focus) {
                struct wl_client *pointer_client =
-                       wl_resource_get_client(pointer->focus->resource);
+                       wl_resource_get_client(pointer->focus->surface->resource);
                send_modifiers_to_client_in_list(pointer_client,
                                                 &keyboard->resource_list,
                                                 serial,
@@ -330,12 +338,13 @@ static const struct weston_keyboard_grab_interface
 static void
 pointer_unmap_sprite(struct weston_pointer *pointer)
 {
-       if (weston_surface_is_mapped(pointer->sprite))
-               weston_surface_unmap(pointer->sprite);
+       if (weston_surface_is_mapped(pointer->sprite->surface))
+               weston_surface_unmap(pointer->sprite->surface);
 
        wl_list_remove(&pointer->sprite_destroy_listener.link);
-       pointer->sprite->configure = NULL;
-       pointer->sprite->configure_private = NULL;
+       pointer->sprite->surface->configure = NULL;
+       pointer->sprite->surface->configure_private = NULL;
+       weston_view_destroy(pointer->sprite);
        pointer->sprite = NULL;
 }
 
@@ -461,7 +470,7 @@ seat_send_updated_caps(struct weston_seat *seat)
 
 WL_EXPORT void
 weston_pointer_set_focus(struct weston_pointer *pointer,
-                        struct weston_surface *surface,
+                        struct weston_view *view,
                         wl_fixed_t sx, wl_fixed_t sy)
 {
        struct weston_keyboard *kbd = pointer->seat->keyboard;
@@ -469,27 +478,33 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
        struct wl_display *display = pointer->seat->compositor->wl_display;
        uint32_t serial;
        struct wl_list *focus_resource_list;
+       int different_surface = 0;
+
+       if ((!pointer->focus && view) ||
+           (pointer->focus && !view) ||
+           (pointer->focus && pointer->focus->surface != view->surface))
+               different_surface = 1;
 
        focus_resource_list = &pointer->focus_resource_list;
 
-       if (!wl_list_empty(focus_resource_list) && pointer->focus != surface) {
+       if (!wl_list_empty(focus_resource_list) && different_surface) {
                serial = wl_display_next_serial(display);
                wl_resource_for_each(resource, focus_resource_list) {
                        wl_pointer_send_leave(resource, serial,
-                                             pointer->focus->resource);
+                                             pointer->focus->surface->resource);
                }
 
                move_resources(&pointer->resource_list, focus_resource_list);
        }
 
-       if (find_resource_for_surface(&pointer->resource_list, surface) &&
-           pointer->focus != surface) {
+       if (find_resource_for_view(&pointer->resource_list, view) &&
+           different_surface) {
                struct wl_client *surface_client =
-                       wl_resource_get_client(surface->resource);
+                       wl_resource_get_client(view->surface->resource);
 
                serial = wl_display_next_serial(display);
 
-               if (kbd && kbd->focus != pointer->focus)
+               if (kbd && kbd->focus != view->surface)
                        send_modifiers_to_client_in_list(surface_client,
                                                         &kbd->resource_list,
                                                         serial,
@@ -502,14 +517,14 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
                wl_resource_for_each(resource, focus_resource_list) {
                        wl_pointer_send_enter(resource,
                                              serial,
-                                             surface->resource,
+                                             view->surface->resource,
                                              sx, sy);
                }
 
                pointer->focus_serial = serial;
        }
 
-       pointer->focus = surface;
+       pointer->focus = view;
        wl_signal_emit(&pointer->focus_signal, pointer);
 }
 
@@ -676,13 +691,13 @@ move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
                if (output->zoom.active &&
                    pixman_region32_contains_point(&output->region,
                                                   ix, iy, NULL))
-                       weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
+                       weston_output_update_zoom(output);
 
        if (pointer->sprite) {
-               weston_surface_set_position(pointer->sprite,
-                                           ix - pointer->hotspot_x,
-                                           iy - pointer->hotspot_y);
-               weston_surface_schedule_repaint(pointer->sprite);
+               weston_view_set_position(pointer->sprite,
+                                        ix - pointer->hotspot_x,
+                                        iy - pointer->hotspot_y);
+               weston_view_schedule_repaint(pointer->sprite);
        }
 }
 
@@ -906,8 +921,7 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
 {
        struct weston_compositor *compositor = seat->compositor;
        struct weston_keyboard *keyboard = seat->keyboard;
-       struct weston_surface *focus =
-               (struct weston_surface *) keyboard->focus;
+       struct weston_surface *focus = keyboard->focus;
        struct weston_keyboard_grab *grab = keyboard->grab;
        uint32_t serial = wl_display_next_serial(compositor->wl_display);
        uint32_t *k, *end;
@@ -1045,28 +1059,30 @@ notify_keyboard_focus_out(struct weston_seat *seat)
 }
 
 WL_EXPORT void
-weston_touch_set_focus(struct weston_seat *seat, struct weston_surface *surface)
+weston_touch_set_focus(struct weston_seat *seat, struct weston_view *view)
 {
        struct wl_list *focus_resource_list;
 
        focus_resource_list = &seat->touch->focus_resource_list;
 
-       if (seat->touch->focus == surface)
+       if (seat->touch->focus->surface == view->surface) {
+               seat->touch->focus = view;
                return;
+       }
 
        if (!wl_list_empty(focus_resource_list)) {
                move_resources(&seat->touch->resource_list,
                               focus_resource_list);
        }
 
-       if (surface) {
+       if (view) {
                struct wl_client *surface_client =
-                       wl_resource_get_client(surface->resource);
+                       wl_resource_get_client(view->surface->resource);
                move_resources_for_client(focus_resource_list,
                                          &seat->touch->resource_list,
                                          surface_client);
        }
-       seat->touch->focus = surface;
+       seat->touch->focus = view;
 }
 
 /**
@@ -1084,7 +1100,7 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
        struct weston_compositor *ec = seat->compositor;
        struct weston_touch *touch = seat->touch;
        struct weston_touch_grab *grab = touch->grab;
-       struct weston_surface *es;
+       struct weston_view *ev;
        wl_fixed_t sx, sy;
 
        /* Update grab's global coordinates. */
@@ -1099,15 +1115,15 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
 
                seat->num_tp++;
 
-               /* the first finger down picks the surface, and all further go
-                * to that surface for the remainder of the touch session i.e.
+               /* the first finger down picks the view, and all further go
+                * to that view for the remainder of the touch session i.e.
                 * until all touch points are up again. */
                if (seat->num_tp == 1) {
-                       es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
-                       weston_touch_set_focus(seat, es);
+                       ev = weston_compositor_pick_view(ec, x, y, &sx, &sy);
+                       weston_touch_set_focus(seat, ev);
                } else if (touch->focus) {
-                       es = (struct weston_surface *) touch->focus;
-                       weston_surface_from_global_fixed(es, x, y, &sx, &sy);
+                       ev = touch->focus;
+                       weston_view_from_global_fixed(ev, x, y, &sx, &sy);
                } else {
                        /* Unexpected condition: We have non-initial touch but
                         * there is no focused surface.
@@ -1129,11 +1145,11 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
 
                break;
        case WL_TOUCH_MOTION:
-               es = (struct weston_surface *) touch->focus;
-               if (!es)
+               ev = touch->focus;
+               if (!ev)
                        break;
 
-               weston_surface_from_global_fixed(es, x, y, &sx, &sy);
+               weston_view_from_global_fixed(ev, x, y, &sx, &sy);
                grab->interface->motion(grab, time, touch_id, sx, sy);
                break;
        case WL_TOUCH_UP:
@@ -1159,7 +1175,7 @@ pointer_cursor_surface_configure(struct weston_surface *es,
        if (width == 0)
                return;
 
-       assert(es == pointer->sprite);
+       assert(es == pointer->sprite->surface);
 
        pointer->hotspot_x -= dx;
        pointer->hotspot_y -= dy;
@@ -1167,14 +1183,14 @@ pointer_cursor_surface_configure(struct weston_surface *es,
        x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
        y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
 
-       weston_surface_configure(pointer->sprite, x, y, width, height);
+       weston_view_configure(pointer->sprite, x, y, width, height);
 
        empty_region(&es->pending.input);
 
        if (!weston_surface_is_mapped(es)) {
-               wl_list_insert(&es->compositor->cursor_layer.surface_list,
-                              &es->layer_link);
-               weston_surface_update_transform(es);
+               wl_list_insert(&es->compositor->cursor_layer.view_list,
+                              &pointer->sprite->layer_link);
+               weston_view_update_transform(pointer->sprite);
        }
 }
 
@@ -1191,17 +1207,17 @@ pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
 
        if (pointer->focus == NULL)
                return;
-       /* pointer->focus->resource can be NULL. Surfaces like the
+       /* pointer->focus->surface->resource can be NULL. Surfaces like the
        black_surface used in shell.c for fullscreen don't have
        a resource, but can still have focus */
-       if (pointer->focus->resource == NULL)
+       if (pointer->focus->surface->resource == NULL)
                return;
-       if (wl_resource_get_client(pointer->focus->resource) != client)
+       if (wl_resource_get_client(pointer->focus->surface->resource) != client)
                return;
        if (pointer->focus_serial - serial > UINT32_MAX / 2)
                return;
 
-       if (surface && surface != pointer->sprite) {
+       if (surface && pointer->sprite && surface != pointer->sprite->surface) {
                if (surface->configure) {
                        wl_resource_post_error(surface->resource,
                                               WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -1222,7 +1238,7 @@ pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
 
        surface->configure = pointer_cursor_surface_configure;
        surface->configure_private = pointer;
-       pointer->sprite = surface;
+       pointer->sprite = weston_view_create(surface);
        pointer->hotspot_x = x;
        pointer->hotspot_y = y;
 
@@ -1266,24 +1282,21 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
        wl_resource_set_implementation(cr, &pointer_interface, seat->pointer,
                                       unbind_resource);
 
-       if (seat->pointer->focus && seat->pointer->focus->resource &&
-           wl_resource_get_client(seat->pointer->focus->resource) == client) {
-               struct weston_surface *surface;
+       if (seat->pointer->focus && seat->pointer->focus->surface->resource &&
+           wl_resource_get_client(seat->pointer->focus->surface->resource) == client) {
                wl_fixed_t sx, sy;
 
-               surface = (struct weston_surface *) seat->pointer->focus;
-               weston_surface_from_global_fixed(surface,
-                                                seat->pointer->x,
-                                                seat->pointer->y,
-                                                &sx,
-                                                &sy);
+               weston_view_from_global_fixed(seat->pointer->focus,
+                                             seat->pointer->x,
+                                             seat->pointer->y,
+                                             &sx, &sy);
 
                wl_list_remove(wl_resource_get_link(cr));
                wl_list_insert(&seat->pointer->focus_resource_list,
                               wl_resource_get_link(cr));
                wl_pointer_send_enter(cr,
                                      seat->pointer->focus_serial,
-                                     surface->resource,
+                                     seat->pointer->focus->surface->resource,
                                      sx, sy);
        }
 }
@@ -1309,7 +1322,7 @@ should_send_modifiers_to_client(struct weston_seat *seat,
 
        if (seat->pointer &&
            seat->pointer->focus &&
-           wl_resource_get_client(seat->pointer->focus->resource) == client)
+           wl_resource_get_client(seat->pointer->focus->surface->resource) == client)
                return 1;
 
        return 0;
@@ -1406,7 +1419,7 @@ seat_get_touch(struct wl_client *client, struct wl_resource *resource,
        }
 
        if (seat->touch->focus &&
-           wl_resource_get_client(seat->touch->focus->resource) == client) {
+           wl_resource_get_client(seat->touch->focus->surface->resource) == client) {
                wl_list_insert(&seat->touch->resource_list,
                               wl_resource_get_link(cr));
        } else {
index 987c539..85fcd4c 100644 (file)
@@ -223,16 +223,16 @@ region_global_to_output(struct weston_output *output, pixman_region32_t *region)
 #define D2F(v) pixman_double_to_fixed((double)v)
 
 static void
-repaint_region(struct weston_surface *es, struct weston_output *output,
+repaint_region(struct weston_view *ev, struct weston_output *output,
               pixman_region32_t *region, pixman_region32_t *surf_region,
               pixman_op_t pixman_op)
 {
        struct pixman_renderer *pr =
                (struct pixman_renderer *) output->compositor->renderer;
-       struct pixman_surface_state *ps = get_surface_state(es);
+       struct pixman_surface_state *ps = get_surface_state(ev->surface);
        struct pixman_output_state *po = get_output_state(output);
        pixman_region32_t final_region;
-       float surface_x, surface_y;
+       float view_x, view_y;
        pixman_transform_t transform;
        pixman_fixed_t fw, fh;
 
@@ -246,11 +246,11 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
                pixman_region32_copy(&final_region, surf_region);
 
                /* Convert from surface to global coordinates */
-               if (!es->transform.enabled) {
-                       pixman_region32_translate(&final_region, es->geometry.x, es->geometry.y);
+               if (!ev->transform.enabled) {
+                       pixman_region32_translate(&final_region, ev->geometry.x, ev->geometry.y);
                } else {
-                       weston_surface_to_global_float(es, 0, 0, &surface_x, &surface_y);
-                       pixman_region32_translate(&final_region, (int)surface_x, (int)surface_y);
+                       weston_view_to_global_float(ev, 0, 0, &view_x, &view_y);
+                       pixman_region32_translate(&final_region, (int)view_x, (int)view_y);
                }
 
                /* We need to paint the intersection */
@@ -314,22 +314,22 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
                                   pixman_double_to_fixed (output->x),
                                   pixman_double_to_fixed (output->y));
 
-       if (es->transform.enabled) {
+       if (ev->transform.enabled) {
                /* Pixman supports only 2D transform matrix, but Weston uses 3D,
                 * so we're omitting Z coordinate here
                 */
                pixman_transform_t surface_transform = {{
-                               { D2F(es->transform.matrix.d[0]),
-                                 D2F(es->transform.matrix.d[4]),
-                                 D2F(es->transform.matrix.d[12]),
+                               { D2F(ev->transform.matrix.d[0]),
+                                 D2F(ev->transform.matrix.d[4]),
+                                 D2F(ev->transform.matrix.d[12]),
                                },
-                               { D2F(es->transform.matrix.d[1]),
-                                 D2F(es->transform.matrix.d[5]),
-                                 D2F(es->transform.matrix.d[13]),
+                               { D2F(ev->transform.matrix.d[1]),
+                                 D2F(ev->transform.matrix.d[5]),
+                                 D2F(ev->transform.matrix.d[13]),
                                },
-                               { D2F(es->transform.matrix.d[3]),
-                                 D2F(es->transform.matrix.d[7]),
-                                 D2F(es->transform.matrix.d[15]),
+                               { D2F(ev->transform.matrix.d[3]),
+                                 D2F(ev->transform.matrix.d[7]),
+                                 D2F(ev->transform.matrix.d[15]),
                                }
                        }};
 
@@ -337,15 +337,15 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
                pixman_transform_multiply (&transform, &surface_transform, &transform);
        } else {
                pixman_transform_translate(&transform, NULL,
-                                          pixman_double_to_fixed ((double)-es->geometry.x),
-                                          pixman_double_to_fixed ((double)-es->geometry.y));
+                                          pixman_double_to_fixed ((double)-ev->geometry.x),
+                                          pixman_double_to_fixed ((double)-ev->geometry.y));
        }
 
 
-       fw = pixman_int_to_fixed(es->geometry.width);
-       fh = pixman_int_to_fixed(es->geometry.height);
+       fw = pixman_int_to_fixed(ev->geometry.width);
+       fh = pixman_int_to_fixed(ev->geometry.height);
 
-       switch (es->buffer_transform) {
+       switch (ev->surface->buffer_transform) {
        case WL_OUTPUT_TRANSFORM_FLIPPED:
        case WL_OUTPUT_TRANSFORM_FLIPPED_90:
        case WL_OUTPUT_TRANSFORM_FLIPPED_180:
@@ -357,7 +357,7 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
                break;
        }
 
-       switch (es->buffer_transform) {
+       switch (ev->surface->buffer_transform) {
        default:
        case WL_OUTPUT_TRANSFORM_NORMAL:
        case WL_OUTPUT_TRANSFORM_FLIPPED:
@@ -380,12 +380,12 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
        }
 
        pixman_transform_scale(&transform, NULL,
-                              pixman_double_to_fixed ((double)es->buffer_scale),
-                              pixman_double_to_fixed ((double)es->buffer_scale));
+                              pixman_double_to_fixed ((double)ev->surface->buffer_scale),
+                              pixman_double_to_fixed ((double)ev->surface->buffer_scale));
 
        pixman_image_set_transform(ps->image, &transform);
 
-       if (es->transform.enabled || output->current_scale != es->buffer_scale)
+       if (ev->transform.enabled || output->current_scale != ev->surface->buffer_scale)
                pixman_image_set_filter(ps->image, PIXMAN_FILTER_BILINEAR, NULL, 0);
        else
                pixman_image_set_filter(ps->image, PIXMAN_FILTER_NEAREST, NULL, 0);
@@ -417,10 +417,10 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
 }
 
 static void
-draw_surface(struct weston_surface *es, struct weston_output *output,
-            pixman_region32_t *damage) /* in global coordinates */
+draw_view(struct weston_view *ev, struct weston_output *output,
+         pixman_region32_t *damage) /* in global coordinates */
 {
-       struct pixman_surface_state *ps = get_surface_state(es);
+       struct pixman_surface_state *ps = get_surface_state(ev->surface);
        /* repaint bounding region in global coordinates: */
        pixman_region32_t repaint;
        /* non-opaque region in surface coordinates: */
@@ -432,8 +432,8 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
 
        pixman_region32_init(&repaint);
        pixman_region32_intersect(&repaint,
-                                 &es->transform.boundingbox, damage);
-       pixman_region32_subtract(&repaint, &repaint, &es->clip);
+                                 &ev->transform.boundingbox, damage);
+       pixman_region32_subtract(&repaint, &repaint, &ev->clip);
 
        if (!pixman_region32_not_empty(&repaint))
                goto out;
@@ -444,21 +444,21 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
        }
 
        /* TODO: Implement repaint_region_complex() using pixman_composite_trapezoids() */
-       if (es->transform.enabled &&
-           es->transform.matrix.type != WESTON_MATRIX_TRANSFORM_TRANSLATE) {
-               repaint_region(es, output, &repaint, NULL, PIXMAN_OP_OVER);
+       if (ev->transform.enabled &&
+           ev->transform.matrix.type != WESTON_MATRIX_TRANSFORM_TRANSLATE) {
+               repaint_region(ev, output, &repaint, NULL, PIXMAN_OP_OVER);
        } else {
                /* blended region is whole surface minus opaque region: */
                pixman_region32_init_rect(&surface_blend, 0, 0,
-                                         es->geometry.width, es->geometry.height);
-               pixman_region32_subtract(&surface_blend, &surface_blend, &es->opaque);
+                                         ev->geometry.width, ev->geometry.height);
+               pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
 
-               if (pixman_region32_not_empty(&es->opaque)) {
-                       repaint_region(es, output, &repaint, &es->opaque, PIXMAN_OP_SRC);
+               if (pixman_region32_not_empty(&ev->surface->opaque)) {
+                       repaint_region(ev, output, &repaint, &ev->surface->opaque, PIXMAN_OP_SRC);
                }
 
                if (pixman_region32_not_empty(&surface_blend)) {
-                       repaint_region(es, output, &repaint, &surface_blend, PIXMAN_OP_OVER);
+                       repaint_region(ev, output, &repaint, &surface_blend, PIXMAN_OP_OVER);
                }
                pixman_region32_fini(&surface_blend);
        }
@@ -471,11 +471,11 @@ static void
 repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
 {
        struct weston_compositor *compositor = output->compositor;
-       struct weston_surface *surface;
+       struct weston_view *view;
 
-       wl_list_for_each_reverse(surface, &compositor->surface_list, link)
-               if (surface->plane == &compositor->primary_plane)
-                       draw_surface(surface, output, damage);
+       wl_list_for_each_reverse(view, &compositor->view_list, link)
+               if (view->plane == &compositor->primary_plane)
+                       draw_view(view, output, damage);
 }
 
 static void
index a95cc60..ea48b08 100644 (file)
@@ -104,13 +104,8 @@ enum buffer_type {
 struct rpir_surface {
        struct weston_surface *surface;
 
-       /* If link is empty, the surface is guaranteed to not be on screen,
-        * i.e. updates removing Elements have completed.
-        */
-       struct wl_list link;
-
-       DISPMANX_ELEMENT_HANDLE_T handle;
-       int layer;
+       struct wl_list views;
+       int visible_views;
        int need_swap;
        int single_buffer;
 
@@ -127,6 +122,20 @@ struct rpir_surface {
        enum buffer_type buffer_type;
 };
 
+struct rpir_view {
+       struct rpir_surface *surface;
+       struct wl_list surface_link;
+       struct weston_view *view;
+
+       /* If link is empty, the view is guaranteed to not be on screen,
+        * i.e. updates removing Elements have completed.
+        */
+       struct wl_list link;
+
+       DISPMANX_ELEMENT_HANDLE_T handle;
+       int layer;
+};
+
 struct rpir_output {
        DISPMANX_DISPLAY_HANDLE_T display;
 
@@ -134,10 +143,10 @@ struct rpir_output {
        struct weston_matrix matrix;
 
        /* all Elements currently on screen */
-       struct wl_list surface_list; /* struct rpir_surface::link */
+       struct wl_list view_list; /* struct rpir_surface::link */
 
        /* Elements just removed, waiting for update completion */
-       struct wl_list surface_cleanup_list; /* struct rpir_surface::link */
+       struct wl_list view_cleanup_list; /* struct rpir_surface::link */
 
        struct rpi_resource capture_buffer;
        uint8_t *capture_data;
@@ -164,6 +173,12 @@ to_rpir_surface(struct weston_surface *surface)
        return surface->renderer_state;
 }
 
+static inline struct rpir_view *
+to_rpir_view(struct weston_view *view)
+{
+       return view->renderer_state;
+}
+
 static inline struct rpir_output *
 to_rpir_output(struct weston_output *output)
 {
@@ -356,9 +371,8 @@ rpir_surface_create(struct rpi_renderer *renderer)
        if (!surface)
                return NULL;
 
-       wl_list_init(&surface->link);
+       surface->visible_views = 0;
        surface->single_buffer = renderer->single_buffer;
-       surface->handle = DISPMANX_NO_HANDLE;
        rpi_resource_init(&surface->resources[0]);
        rpi_resource_init(&surface->resources[1]);
        surface->front = &surface->resources[0];
@@ -376,15 +390,18 @@ rpir_surface_create(struct rpi_renderer *renderer)
 static void
 rpir_surface_destroy(struct rpir_surface *surface)
 {
-       wl_list_remove(&surface->link);
-
-       if (surface->handle != DISPMANX_NO_HANDLE)
+       if (surface->visible_views)
                weston_log("ERROR rpi: destroying on-screen element\n");
 
+       assert(wl_list_empty(&surface->views));
+
+       if (surface->surface)
+               surface->surface->renderer_state = NULL;
+
        pixman_region32_fini(&surface->prev_damage);
        rpi_resource_release(&surface->resources[0]);
        rpi_resource_release(&surface->resources[1]);
-       DBG("rpir_surface %p destroyed (%u)\n", surface, surface->handle);
+       DBG("rpir_surface %p destroyed (%u)\n", surface, surface->visible_views);
 
        if (surface->egl_back != NULL) {
                weston_buffer_reference(&surface->egl_back->buffer_ref, NULL);
@@ -436,6 +453,46 @@ rpir_surface_damage(struct rpir_surface *surface, struct weston_buffer *buffer,
        return ret;
 }
 
+static struct rpir_view *
+rpir_view_create(struct rpir_surface *surface)
+{
+       struct rpir_view *view;
+
+       view = calloc(1, sizeof *view);
+       if (!view)
+               return NULL;
+
+       view->surface = surface;
+       wl_list_insert(&surface->views, &view->surface_link);
+
+       wl_list_init(&view->link);
+       view->handle = DISPMANX_NO_HANDLE;
+
+       return view;
+}
+
+static void
+rpir_view_destroy(struct rpir_view *view)
+{
+       wl_list_remove(&view->link);
+
+       if (view->handle != DISPMANX_NO_HANDLE) {
+               view->surface->visible_views--;
+               weston_log("ERROR rpi: destroying on-screen element\n");
+       }
+
+       if (view->view)
+               view->view->renderer_state = NULL;
+
+       wl_list_remove(&view->surface_link);
+       if (wl_list_empty(&view->surface->views) && view->surface->surface == NULL)
+               rpir_surface_destroy(view->surface);
+
+       DBG("rpir_view %p destroyed (%d)\n", view, view->handle);
+
+       free(view);
+}
+
 static void
 matrix_type_str(struct weston_matrix *matrix, char *buf, int len)
 {
@@ -495,13 +552,13 @@ warn_bad_matrix(struct weston_matrix *total, struct weston_matrix *output,
 /*#define SURFACE_TRANSFORM */
 
 static int
-rpir_surface_compute_rects(struct rpir_surface *surface,
-                          VC_RECT_T *src_rect, VC_RECT_T *dst_rect,
-                          VC_IMAGE_TRANSFORM_T *flipmask)
+rpir_view_compute_rects(struct rpir_view *view,
+                       VC_RECT_T *src_rect, VC_RECT_T *dst_rect,
+                       VC_IMAGE_TRANSFORM_T *flipmask)
 {
-       struct weston_output *output_base = surface->surface->output;
+       struct weston_output *output_base = view->view->surface->output;
        struct rpir_output *output = to_rpir_output(output_base);
-       struct weston_matrix matrix = surface->surface->transform.matrix;
+       struct weston_matrix matrix = view->view->transform.matrix;
        VC_IMAGE_TRANSFORM_T flipt = 0;
        int src_x, src_y;
        int dst_x, dst_y;
@@ -523,14 +580,15 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
        src_x = 0 << 16;
        src_y = 0 << 16;
 
-       if (surface->buffer_type == BUFFER_TYPE_EGL) {
-               struct weston_buffer *buffer = surface->egl_front->buffer_ref.buffer;
+       if (view->surface->buffer_type == BUFFER_TYPE_EGL) {
+               struct weston_buffer *buffer =
+                       view->surface->egl_front->buffer_ref.buffer;
 
                src_width = buffer->width << 16;
                src_height = buffer->height << 16;
        } else {
-               src_width = surface->front->width << 16;
-               src_height = surface->front->height << 16;
+               src_width = view->surface->front->width << 16;
+               src_height = view->surface->front->height << 16;
        }
 
        weston_matrix_multiply(&matrix, &output->matrix);
@@ -541,7 +599,7 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
        if (matrix.type >= WESTON_MATRIX_TRANSFORM_ROTATE) {
 #endif
                warn_bad_matrix(&matrix, &output->matrix,
-                               &surface->surface->transform.matrix);
+                               &view->view->transform.matrix);
        } else {
                if (matrix.type & WESTON_MATRIX_TRANSFORM_ROTATE) {
                        if (fabsf(matrix.d[0]) < 1e-4f &&
@@ -552,13 +610,13 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
                                /* no transpose */
                        } else {
                                warn_bad_matrix(&matrix, &output->matrix,
-                                       &surface->surface->transform.matrix);
+                                       &view->view->transform.matrix);
                        }
                }
        }
 
-       p2.f[0] = surface->surface->geometry.width;
-       p2.f[1] = surface->surface->geometry.height;
+       p2.f[0] = view->view->geometry.width;
+       p2.f[1] = view->view->geometry.height;
 
        /* transform top-left and bot-right corner into screen coordinates */
        weston_matrix_transform(&matrix, &p1);
@@ -680,9 +738,9 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
        src_width = int_max(src_width, 0);
        src_height = int_max(src_height, 0);
 
-       DBG("rpir_surface %p %dx%d: p1 %f, %f; p2 %f, %f\n", surface,
-           surface->surface->geometry.width,
-           surface->surface->geometry.height,
+       DBG("rpir_view %p %dx%d: p1 %f, %f; p2 %f, %f\n", view,
+           view->view->geometry.width,
+           view->view->geometry.height,
            p1.f[0], p1.f[1], p2.f[0], p2.f[1]);
        DBG("src rect %d;%d, %d;%d, %d;%dx%d;%d\n",
            src_x >> 16, src_x & 0xffff,
@@ -706,7 +764,7 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
        }
 
        /* EGL buffers will be upside-down related to what DispmanX expects */
-       if (surface->buffer_type == BUFFER_TYPE_EGL)
+       if (view->surface->buffer_type == BUFFER_TYPE_EGL)
                flipt ^= TRANSFORM_VFLIP;
 
        vc_dispmanx_rect_set(src_rect, src_x, src_y, src_width, src_height);
@@ -760,8 +818,8 @@ rpir_surface_get_resource(struct rpir_surface *surface)
 }
 
 static int
-rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
-                   DISPMANX_UPDATE_HANDLE_T update, int layer)
+rpir_view_dmx_add(struct rpir_view *view, struct rpir_output *output,
+                 DISPMANX_UPDATE_HANDLE_T update, int layer)
 {
        /* Do not use DISPMANX_FLAGS_ALPHA_PREMULT here.
         * If you define PREMULT and ALPHA_MIX, the hardware will not
@@ -771,7 +829,7 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
        VC_DISPMANX_ALPHA_T alphasetup = {
                DISPMANX_FLAGS_ALPHA_FROM_SOURCE |
                DISPMANX_FLAGS_ALPHA_MIX,
-               float2uint8(surface->surface->alpha), /* opacity 0-255 */
+               float2uint8(view->view->alpha), /* opacity 0-255 */
                0 /* mask resource handle */
        };
        VC_RECT_T dst_rect;
@@ -780,18 +838,17 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
        int ret;
        DISPMANX_RESOURCE_HANDLE_T resource_handle;
 
-       resource_handle = rpir_surface_get_resource(surface);
+       resource_handle = rpir_surface_get_resource(view->surface);
        if (resource_handle == DISPMANX_NO_HANDLE) {
                weston_log("%s: no buffer yet, aborting\n", __func__);
                return 0;
        }
 
-       ret = rpir_surface_compute_rects(surface, &src_rect, &dst_rect,
-                                        &flipmask);
+       ret = rpir_view_compute_rects(view, &src_rect, &dst_rect, &flipmask);
        if (ret < 0)
                return 0;
 
-       surface->handle = vc_dispmanx_element_add(
+       view->handle = vc_dispmanx_element_add(
                update,
                output->display,
                layer,
@@ -802,37 +859,42 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
                &alphasetup,
                NULL /* clamp */,
                vc_image2dispmanx_transform(flipmask));
-       DBG("rpir_surface %p add %u, alpha %f resource %d\n", surface,
-           surface->handle, surface->surface->alpha, resource_handle);
+       DBG("rpir_surface %p add %u, alpha %f resource %d\n", view,
+           view->handle, view->view->alpha, resource_handle);
+
+       if (view->handle == DISPMANX_NO_HANDLE)
+               return -1;
+
+       view->surface->visible_views++;
 
        return 1;
 }
 
 static void
-rpir_surface_dmx_swap(struct rpir_surface *surface,
-                     DISPMANX_UPDATE_HANDLE_T update)
+rpir_view_dmx_swap(struct rpir_view *view,
+                  DISPMANX_UPDATE_HANDLE_T update)
 {
        VC_RECT_T rect;
        pixman_box32_t *r;
 
        /* XXX: skip, iff resource was not reallocated, and single-buffering */
-       vc_dispmanx_element_change_source(update, surface->handle,
-                                         surface->front->handle);
+       vc_dispmanx_element_change_source(update, view->handle,
+                                         view->surface->front->handle);
 
        /* This is current damage now, after rpir_surface_damage() */
-       r = pixman_region32_extents(&surface->prev_damage);
+       r = pixman_region32_extents(&view->surface->prev_damage);
 
        vc_dispmanx_rect_set(&rect, r->x1, r->y1,
                             r->x2 - r->x1, r->y2 - r->y1);
-       vc_dispmanx_element_modified(update, surface->handle, &rect);
-       DBG("rpir_surface %p swap\n", surface);
+       vc_dispmanx_element_modified(update, view->handle, &rect);
+       DBG("rpir_view %p swap\n", view);
 }
 
 static int
-rpir_surface_dmx_move(struct rpir_surface *surface,
-                     DISPMANX_UPDATE_HANDLE_T update, int layer)
+rpir_view_dmx_move(struct rpir_view *view,
+                  DISPMANX_UPDATE_HANDLE_T update, int layer)
 {
-       uint8_t alpha = float2uint8(surface->surface->alpha);
+       uint8_t alpha = float2uint8(view->view->alpha);
        VC_RECT_T dst_rect;
        VC_RECT_T src_rect;
        VC_IMAGE_TRANSFORM_T flipmask;
@@ -840,28 +902,27 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
 
        /* XXX: return early, if all attributes stay the same */
 
-       if (surface->buffer_type == BUFFER_TYPE_EGL) {
+       if (view->surface->buffer_type == BUFFER_TYPE_EGL) {
                DISPMANX_RESOURCE_HANDLE_T resource_handle;
 
-               resource_handle = rpir_surface_get_resource(surface);
+               resource_handle = rpir_surface_get_resource(view->surface);
                if (resource_handle == DISPMANX_NO_HANDLE) {
                        weston_log("%s: no buffer yet, aborting\n", __func__);
                        return 0;
                }
 
                vc_dispmanx_element_change_source(update,
-                                                 surface->handle,
+                                                 view->handle,
                                                  resource_handle);
        }
 
-       ret = rpir_surface_compute_rects(surface, &src_rect, &dst_rect,
-                                        &flipmask);
+       ret = rpir_view_compute_rects(view, &src_rect, &dst_rect, &flipmask);
        if (ret < 0)
                return 0;
 
        ret = vc_dispmanx_element_change_attributes(
                update,
-               surface->handle,
+               view->handle,
                ELEMENT_CHANGE_LAYER |
                        ELEMENT_CHANGE_OPACITY |
                        ELEMENT_CHANGE_TRANSFORM |
@@ -875,7 +936,7 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
                /* This really is DISPMANX_TRANSFORM_T, no matter
                 * what the header says. */
                vc_image2dispmanx_transform(flipmask));
-       DBG("rpir_surface %p move\n", surface);
+       DBG("rpir_view %p move\n", view);
 
        if (ret)
                return -1;
@@ -884,15 +945,16 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
 }
 
 static void
-rpir_surface_dmx_remove(struct rpir_surface *surface,
-                       DISPMANX_UPDATE_HANDLE_T update)
+rpir_view_dmx_remove(struct rpir_view *view,
+                    DISPMANX_UPDATE_HANDLE_T update)
 {
-       if (surface->handle == DISPMANX_NO_HANDLE)
+       if (view->handle == DISPMANX_NO_HANDLE)
                return;
 
-       vc_dispmanx_element_remove(update, surface->handle);
-       DBG("rpir_surface %p remove %u\n", surface, surface->handle);
-       surface->handle = DISPMANX_NO_HANDLE;
+       vc_dispmanx_element_remove(update, view->handle);
+       DBG("rpir_view %p remove %u\n", view, view->handle);
+       view->handle = DISPMANX_NO_HANDLE;
+       view->surface->visible_views--;
 }
 
 static void
@@ -900,23 +962,31 @@ rpir_surface_swap_pointers(struct rpir_surface *surface)
 {
        struct rpi_resource *tmp;
 
-       tmp = surface->front;
-       surface->front = surface->back;
-       surface->back = tmp;
-       surface->need_swap = 0;
+       if (surface->buffer_type == BUFFER_TYPE_EGL) {
+               if (surface->egl_back != NULL) {
+                       assert(surface->egl_old_front == NULL);
+                       surface->egl_old_front = surface->egl_front;
+                       surface->egl_front = surface->egl_back;
+                       surface->egl_back = NULL;
+               }
+       } else {
+               tmp = surface->front;
+               surface->front = surface->back;
+               surface->back = tmp;
+       }
        DBG("new back %p, new front %p\n", surface->back, surface->front);
 }
 
 static int
-is_surface_not_visible(struct weston_surface *surface)
+is_view_not_visible(struct weston_view *view)
 {
        /* Return true, if surface is guaranteed to be totally obscured. */
        int ret;
        pixman_region32_t unocc;
 
        pixman_region32_init(&unocc);
-       pixman_region32_subtract(&unocc, &surface->transform.boundingbox,
-                                &surface->clip);
+       pixman_region32_subtract(&unocc, &view->transform.boundingbox,
+                                &view->clip);
        ret = !pixman_region32_not_empty(&unocc);
        pixman_region32_fini(&unocc);
 
@@ -924,81 +994,55 @@ is_surface_not_visible(struct weston_surface *surface)
 }
 
 static void
-rpir_surface_update(struct rpir_surface *surface, struct rpir_output *output,
-                   DISPMANX_UPDATE_HANDLE_T update, int layer)
+rpir_view_update(struct rpir_view *view, struct rpir_output *output,
+                DISPMANX_UPDATE_HANDLE_T update, int layer)
 {
-       int need_swap = surface->need_swap;
        int ret;
        int obscured;
 
-       if (surface->buffer_type == BUFFER_TYPE_EGL) {
-               if (surface->egl_back != NULL) {
-                       assert(surface->egl_old_front == NULL);
-                       surface->egl_old_front = surface->egl_front;
-                       surface->egl_front = surface->egl_back;
-                       surface->egl_back = NULL;
-               }
-               if (surface->egl_front->buffer_ref.buffer == NULL) {
-                       weston_log("warning: client unreffed current front buffer\n");
-
-                       wl_list_remove(&surface->link);
-                       if (surface->handle == DISPMANX_NO_HANDLE) {
-                               wl_list_init(&surface->link);
-                       } else {
-                               rpir_surface_dmx_remove(surface, update);
-                               wl_list_insert(&output->surface_cleanup_list,
-                                                  &surface->link);
-                       }
-
-                       goto out;
-               }
-       } else {
-               if (need_swap)
-                       rpir_surface_swap_pointers(surface);
-       }
 
-       obscured = is_surface_not_visible(surface->surface);
+       obscured = is_view_not_visible(view->view);
        if (obscured) {
-               DBG("rpir_surface %p totally obscured.\n", surface);
+               DBG("rpir_view %p totally obscured.\n", view);
 
-               wl_list_remove(&surface->link);
-               if (surface->handle == DISPMANX_NO_HANDLE) {
-                       wl_list_init(&surface->link);
+               wl_list_remove(&view->link);
+               if (view->handle == DISPMANX_NO_HANDLE) {
+                       wl_list_init(&view->link);
                } else {
-                       rpir_surface_dmx_remove(surface, update);
-                       wl_list_insert(&output->surface_cleanup_list,
-                                      &surface->link);
+                       rpir_view_dmx_remove(view, update);
+                       wl_list_insert(&output->view_cleanup_list,
+                                      &view->link);
                }
 
                goto out;
        }
 
-       if (surface->handle == DISPMANX_NO_HANDLE) {
-               ret = rpir_surface_dmx_add(surface, output, update, layer);
+       if (view->handle == DISPMANX_NO_HANDLE) {
+               ret = rpir_view_dmx_add(view, output, update, layer);
                if (ret == 0) {
-                       wl_list_remove(&surface->link);
-                       wl_list_init(&surface->link);
+                       wl_list_remove(&view->link);
+                       wl_list_init(&view->link);
                } else if (ret < 0) {
-                       weston_log("ERROR rpir_surface_dmx_add() failed.\n");
+                       weston_log("ERROR rpir_view_dmx_add() failed.\n");
                }
        } else {
-               if (need_swap)
-                       rpir_surface_dmx_swap(surface, update);
+               if (view->surface->need_swap)
+                       rpir_view_dmx_swap(view, update);
 
-               ret = rpir_surface_dmx_move(surface, update, layer);
+               ret = rpir_view_dmx_move(view, update, layer);
                if (ret == 0) {
-                       rpir_surface_dmx_remove(surface, update);
+                       rpir_view_dmx_remove(view, update);
 
-                       wl_list_remove(&surface->link);
-                       wl_list_insert(&output->surface_cleanup_list,
-                                      &surface->link);
+                       wl_list_remove(&view->link);
+                       wl_list_insert(&output->view_cleanup_list,
+                                      &view->link);
                } else if (ret < 0) {
-                       weston_log("ERROR rpir_surface_dmx_move() failed.\n");
+                       weston_log("ERROR rpir_view_dmx_move() failed.\n");
                }
        }
 
 out:
-       surface->layer = layer;
+       view->layer = layer;
 }
 
 static int
@@ -1105,15 +1149,15 @@ static void
 rpir_output_dmx_remove_all(struct rpir_output *output,
                           DISPMANX_UPDATE_HANDLE_T update)
 {
-       struct rpir_surface *surface;
+       struct rpir_view *view;
 
-       while (!wl_list_empty(&output->surface_list)) {
-               surface = container_of(output->surface_list.next,
-                                      struct rpir_surface, link);
-               rpir_surface_dmx_remove(surface, update);
+       while (!wl_list_empty(&output->view_list)) {
+               view = container_of(output->view_list.next,
+                                   struct rpir_view, link);
+               rpir_view_dmx_remove(view, update);
 
-               wl_list_remove(&surface->link);
-               wl_list_insert(&output->surface_cleanup_list, &surface->link);
+               wl_list_remove(&view->link);
+               wl_list_insert(&output->view_cleanup_list, &view->link);
        }
 }
 
@@ -1186,8 +1230,8 @@ rpi_renderer_repaint_output(struct weston_output *base,
 {
        struct weston_compositor *compositor = base->compositor;
        struct rpir_output *output = to_rpir_output(base);
-       struct weston_surface *ws;
-       struct rpir_surface *surface;
+       struct weston_view *wv;
+       struct rpir_view *view;
        struct wl_list done_list;
        int layer = 1;
 
@@ -1199,27 +1243,59 @@ rpi_renderer_repaint_output(struct weston_output *base,
        free(output->capture_data);
        output->capture_data = NULL;
 
+       /* Swap resources on surfaces as needed */
+       wl_list_for_each_reverse(wv, &compositor->view_list, link)
+               wv->surface->touched = 0;
+
+       wl_list_for_each_reverse(wv, &compositor->view_list, link) {
+               view = to_rpir_view(wv);
+
+               if (!wv->surface->touched) {
+                       wv->surface->touched = 1;
+
+                       if (view->surface->need_swap)
+                               rpir_surface_swap_pointers(view->surface);
+               }
+
+               if (view->surface->egl_front->buffer_ref.buffer == NULL) {
+                       weston_log("warning: client unreffed current front buffer\n");
+
+                       wl_list_remove(&view->link);
+                       if (view->handle == DISPMANX_NO_HANDLE) {
+                               wl_list_init(&view->link);
+                       } else {
+                               rpir_view_dmx_remove(view, output->update);
+                               wl_list_insert(&output->view_cleanup_list,
+                                              &view->link);
+                       }
+               }
+       }
+
        /* update all renderable surfaces */
        wl_list_init(&done_list);
-       wl_list_for_each_reverse(ws, &compositor->surface_list, link) {
-               if (ws->plane != &compositor->primary_plane)
+       wl_list_for_each_reverse(wv, &compositor->view_list, link) {
+               if (wv->plane != &compositor->primary_plane)
                        continue;
 
-               surface = to_rpir_surface(ws);
-               assert(!wl_list_empty(&surface->link) ||
-                      surface->handle == DISPMANX_NO_HANDLE);
+               view = to_rpir_view(wv);
+               assert(!wl_list_empty(&view->link) ||
+                      view->handle == DISPMANX_NO_HANDLE);
 
-               wl_list_remove(&surface->link);
-               wl_list_insert(&done_list, &surface->link);
-               rpir_surface_update(surface, output, output->update, layer++);
+               wl_list_remove(&view->link);
+               wl_list_insert(&done_list, &view->link);
+               rpir_view_update(view, output, output->update, layer++);
        }
 
+       /* Mark all surfaces as swapped */
+       wl_list_for_each_reverse(wv, &compositor->view_list, link)
+               to_rpir_surface(wv->surface)->need_swap = 0;
+
        /* Remove all surfaces that are still on screen, but were
         * not rendered this time.
         */
        rpir_output_dmx_remove_all(output, output->update);
 
-       wl_list_insert_list(&output->surface_list, &done_list);
+       wl_list_insert_list(&output->view_list, &done_list);
        output->update = DISPMANX_NO_HANDLE;
 
        /* The frame_signal is emitted in rpi_renderer_finish_frame(),
@@ -1263,7 +1339,7 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
                        /* XXX: need to check if in middle of update */
                        rpi_resource_release(surface->back);
 
-               if (surface->handle == DISPMANX_NO_HANDLE)
+               if (!surface->visible_views)
                        /* XXX: cannot do this, if middle of an update */
                        rpi_resource_release(surface->front);
 
@@ -1336,6 +1412,23 @@ rpi_renderer_create_surface(struct weston_surface *base)
        return 0;
 }
 
+static int
+rpi_renderer_create_view(struct weston_view *base)
+{
+       struct rpir_surface *surface = to_rpir_surface(base->surface);
+       struct rpir_view *view;
+
+       assert(base->renderer_state == NULL);
+
+       view = rpir_view_create(surface);
+       if (!view)
+               return -1;
+
+       view->view = base;
+       base->renderer_state = view;
+       return 0;
+}
+
 static void
 rpi_renderer_surface_set_color(struct weston_surface *base,
                               float red, float green, float blue, float alpha)
@@ -1390,13 +1483,27 @@ rpi_renderer_destroy_surface(struct weston_surface *base)
        surface->surface = NULL;
        base->renderer_state = NULL;
 
-       /* If guaranteed to not be on screen, just detroy it. */
-       if (wl_list_empty(&surface->link))
+       if (wl_list_empty(&surface->views))
                rpir_surface_destroy(surface);
+}
 
-       /* Otherwise, the surface is either on screen and needs
+static void
+rpi_renderer_destroy_view(struct weston_view *base)
+{
+       struct rpir_view *view = to_rpir_view(base);
+
+       assert(view);
+       assert(view->view == base);
+       if (!view)
+               return;
+
+       /* If guaranteed to not be on screen, just detroy it. */
+       if (wl_list_empty(&view->link))
+               rpir_view_destroy(view);
+
+       /* Otherwise, the view is either on screen and needs
         * to be removed by a repaint update, or it is in the
-        * surface_cleanup_list, and will be destroyed by
+        * view_cleanup_list, and will be destroyed by
         * rpi_renderer_finish_frame().
         */
 }
@@ -1440,8 +1547,10 @@ rpi_renderer_create(struct weston_compositor *compositor,
        renderer->base.flush_damage = rpi_renderer_flush_damage;
        renderer->base.attach = rpi_renderer_attach;
        renderer->base.create_surface = rpi_renderer_create_surface;
+       renderer->base.create_view = rpi_renderer_create_view;
        renderer->base.surface_set_color = rpi_renderer_surface_set_color;
        renderer->base.destroy_surface = rpi_renderer_destroy_surface;
+       renderer->base.destroy_view = rpi_renderer_destroy_view;
        renderer->base.destroy = rpi_renderer_destroy;
 
 #ifdef ENABLE_EGL
@@ -1504,8 +1613,8 @@ rpi_renderer_output_create(struct weston_output *base,
 
        output->display = display;
        output->update = DISPMANX_NO_HANDLE;
-       wl_list_init(&output->surface_list);
-       wl_list_init(&output->surface_cleanup_list);
+       wl_list_init(&output->view_list);
+       wl_list_init(&output->view_cleanup_list);
        rpi_resource_init(&output->capture_buffer);
        base->renderer_state = output;
 
@@ -1516,7 +1625,7 @@ WL_EXPORT void
 rpi_renderer_output_destroy(struct weston_output *base)
 {
        struct rpir_output *output = to_rpir_output(base);
-       struct rpir_surface *surface;
+       struct rpir_view *view;
        DISPMANX_UPDATE_HANDLE_T update;
 
        rpi_resource_release(&output->capture_buffer);
@@ -1527,12 +1636,10 @@ rpi_renderer_output_destroy(struct weston_output *base)
        rpir_output_dmx_remove_all(output, update);
        vc_dispmanx_update_submit_sync(update);
 
-       while (!wl_list_empty(&output->surface_cleanup_list)) {
-               surface = container_of(output->surface_cleanup_list.next,
-                                      struct rpir_surface, link);
-               if (surface->surface)
-                       surface->surface->renderer_state = NULL;
-               rpir_surface_destroy(surface);
+       while (!wl_list_empty(&output->view_cleanup_list)) {
+               view = container_of(output->view_cleanup_list.next,
+                                   struct rpir_view, link);
+               rpir_view_destroy(view);
        }
 
        free(output);
@@ -1553,41 +1660,41 @@ rpi_renderer_finish_frame(struct weston_output *base)
 {
        struct rpir_output *output = to_rpir_output(base);
        struct weston_compositor *compositor = base->compositor;
-       struct weston_surface *ws;
-       struct rpir_surface *surface;
+       struct weston_view *wv;
+       struct rpir_view *view;
 
-       while (!wl_list_empty(&output->surface_cleanup_list)) {
-               surface = container_of(output->surface_cleanup_list.next,
-                                      struct rpir_surface, link);
+       while (!wl_list_empty(&output->view_cleanup_list)) {
+               view = container_of(output->view_cleanup_list.next,
+                                   struct rpir_view, link);
 
-               if (surface->surface) {
-                       /* The weston_surface still exists, but is
+               if (view->view) {
+                       /* The weston_view still exists, but is
                         * temporarily not visible, and hence its Element
                         * was removed. The current front buffer contents
                         * must be preserved.
                         */
-                       if (!surface->single_buffer)
-                               rpi_resource_release(surface->back);
+                       if (!view->surface->visible_views)
+                               rpi_resource_release(view->surface->back);
 
-                       wl_list_remove(&surface->link);
-                       wl_list_init(&surface->link);
+                       wl_list_remove(&view->link);
+                       wl_list_init(&view->link);
                } else {
-                       rpir_surface_destroy(surface);
+                       rpir_view_destroy(view);
                }
        }
 
-       wl_list_for_each(ws, &compositor->surface_list, link) {
-               surface = to_rpir_surface(ws);
+       wl_list_for_each(wv, &compositor->view_list, link) {
+               view = to_rpir_view(wv);
 
-               if (surface->buffer_type != BUFFER_TYPE_EGL)
+               if (view->surface->buffer_type != BUFFER_TYPE_EGL)
                        continue;
 
-               if(surface->egl_old_front == NULL)
+               if (view->surface->egl_old_front == NULL)
                        continue;
 
-               weston_buffer_reference(&surface->egl_old_front->buffer_ref, NULL);
-               free(surface->egl_old_front);
-               surface->egl_old_front = NULL;
+               weston_buffer_reference(&view->surface->egl_old_front->buffer_ref, NULL);
+               free(view->surface->egl_old_front);
+               view->surface->egl_old_front = NULL;
        }
 
        wl_signal_emit(&base->frame_signal, base);
index e0c3527..9663870 100644 (file)
@@ -79,6 +79,7 @@ struct input_panel_surface {
 
        struct wl_list link;
        struct weston_surface *surface;
+       struct weston_view *view;
        struct wl_listener surface_destroy_listener;
 
        struct weston_output *output;
@@ -155,8 +156,8 @@ struct desktop_shell {
        } input_panel;
 
        struct {
-               struct weston_surface *surface;
-               struct weston_surface_animation *animation;
+               struct weston_view *view;
+               struct weston_view_animation *animation;
                enum fade_type type;
                struct wl_event_source *startup_timer;
        } fade;
@@ -186,6 +187,7 @@ struct shell_surface {
        struct wl_signal destroy_signal;
 
        struct weston_surface *surface;
+       struct weston_view *view;
        struct wl_listener surface_destroy_listener;
        struct weston_surface *parent;
        struct desktop_shell *shell;
@@ -218,7 +220,7 @@ struct shell_surface {
                enum wl_shell_surface_fullscreen_method type;
                struct weston_transform transform; /* matrix from x, y */
                uint32_t framerate;
-               struct weston_surface *black_surface;
+               struct weston_view *black_view;
        } fullscreen;
 
        struct ping_timer *ping_timer;
@@ -299,17 +301,17 @@ static bool
 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
 {
        struct desktop_shell *shell;
-       struct weston_surface *top_fs_es;
+       struct weston_view *top_fs_ev;
 
        shell = shell_surface_get_shell(shsurf);
 
-       if (wl_list_empty(&shell->fullscreen_layer.surface_list))
+       if (wl_list_empty(&shell->fullscreen_layer.view_list))
                return false;
 
-       top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
-                                struct weston_surface,
+       top_fs_ev = container_of(shell->fullscreen_layer.view_list.next,
+                                struct weston_view,
                                 layer_link);
-       return (shsurf == get_shell_surface(top_fs_es));
+       return (shsurf == get_shell_surface(top_fs_ev->surface));
 }
 
 static void
@@ -323,6 +325,26 @@ destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
        grab->shsurf = NULL;
 }
 
+static struct weston_view *
+get_default_view(struct weston_surface *surface)
+{
+       struct shell_surface *shsurf;
+       struct weston_view *view;
+
+       if (!surface || wl_list_empty(&surface->views))
+               return NULL;
+
+       shsurf = get_shell_surface(surface);
+       if (shsurf)
+               return shsurf->view;
+
+       wl_list_for_each(view, &surface->views, surface_link)
+               if (weston_view_is_mapped(view))
+                       return view;
+
+       return container_of(surface->views.next, struct weston_view, surface_link);
+}
+
 static void
 popup_grab_end(struct weston_pointer *pointer);
 
@@ -347,7 +369,8 @@ shell_grab_start(struct shell_grab *grab,
        if (shell->child.desktop_shell) {
                desktop_shell_send_grab_cursor(shell->child.desktop_shell,
                                               cursor);
-               weston_pointer_set_focus(pointer, shell->grab_surface,
+               weston_pointer_set_focus(pointer,
+                                        get_default_view(shell->grab_surface),
                                         wl_fixed_from_int(0),
                                         wl_fixed_from_int(0));
        }
@@ -380,7 +403,8 @@ shell_touch_grab_start(struct shell_touch_grab *grab,
 
        weston_touch_start_grab(touch, &grab->grab);
        if (shell->child.desktop_shell)
-               weston_touch_set_focus(touch->seat, shell->grab_surface);
+               weston_touch_set_focus(touch->seat,
+                                      get_default_view(shell->grab_surface));
 }
 
 static void
@@ -393,7 +417,7 @@ shell_touch_grab_end(struct shell_touch_grab *grab)
 }
 
 static void
-center_on_output(struct weston_surface *surface,
+center_on_output(struct weston_view *view,
                 struct weston_output *output);
 
 static enum weston_keyboard_modifier
@@ -481,17 +505,17 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data)
                                                 struct focus_state,
                                                 surface_destroy_listener);
        struct desktop_shell *shell;
-       struct weston_surface *main_surface;
-       struct weston_surface *surface, *next;
+       struct weston_surface *main_surface, *next;
+       struct weston_view *view;
 
        main_surface = weston_surface_get_main_surface(state->keyboard_focus);
 
        next = NULL;
-       wl_list_for_each(surface, &state->ws->layer.surface_list, layer_link) {
-               if (surface == main_surface)
+       wl_list_for_each(view, &state->ws->layer.view_list, layer_link) {
+               if (view->surface == main_surface)
                        continue;
 
-               next = surface;
+               next = view->surface;
                break;
        }
 
@@ -630,7 +654,7 @@ workspace_create(void)
 static int
 workspace_is_empty(struct workspace *ws)
 {
-       return wl_list_empty(&ws->layer.surface_list);
+       return wl_list_empty(&ws->layer.view_list);
 }
 
 static struct workspace *
@@ -666,53 +690,53 @@ get_output_height(struct weston_output *output)
 }
 
 static void
-surface_translate(struct weston_surface *surface, double d)
+view_translate(struct weston_view *view, double d)
 {
-       struct shell_surface *shsurf = get_shell_surface(surface);
+       struct shell_surface *shsurf = get_shell_surface(view->surface);
        struct weston_transform *transform;
 
        transform = &shsurf->workspace_transform;
        if (wl_list_empty(&transform->link))
-               wl_list_insert(surface->geometry.transformation_list.prev,
+               wl_list_insert(view->geometry.transformation_list.prev,
                               &shsurf->workspace_transform.link);
 
        weston_matrix_init(&shsurf->workspace_transform.matrix);
        weston_matrix_translate(&shsurf->workspace_transform.matrix,
                                0.0, d, 0.0);
-       weston_surface_geometry_dirty(surface);
+       weston_view_geometry_dirty(view);
 }
 
 static void
 workspace_translate_out(struct workspace *ws, double fraction)
 {
-       struct weston_surface *surface;
+       struct weston_view *view;
        unsigned int height;
        double d;
 
-       wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
-               height = get_output_height(surface->output);
+       wl_list_for_each(view, &ws->layer.view_list, layer_link) {
+               height = get_output_height(view->surface->output);
                d = height * fraction;
 
-               surface_translate(surface, d);
+               view_translate(view, d);
        }
 }
 
 static void
 workspace_translate_in(struct workspace *ws, double fraction)
 {
-       struct weston_surface *surface;
+       struct weston_view *view;
        unsigned int height;
        double d;
 
-       wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
-               height = get_output_height(surface->output);
+       wl_list_for_each(view, &ws->layer.view_list, layer_link) {
+               height = get_output_height(view->surface->output);
 
                if (fraction > 0)
                        d = -(height - height * fraction);
                else
                        d = height + height * fraction;
 
-               surface_translate(surface, d);
+               view_translate(view, d);
        }
 }
 
@@ -746,16 +770,16 @@ reverse_workspace_change_animation(struct desktop_shell *shell,
 static void
 workspace_deactivate_transforms(struct workspace *ws)
 {
-       struct weston_surface *surface;
+       struct weston_view *view;
        struct shell_surface *shsurf;
 
-       wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
-               shsurf = get_shell_surface(surface);
+       wl_list_for_each(view, &ws->layer.view_list, layer_link) {
+               shsurf = get_shell_surface(view->surface);
                if (!wl_list_empty(&shsurf->workspace_transform.link)) {
                        wl_list_remove(&shsurf->workspace_transform.link);
                        wl_list_init(&shsurf->workspace_transform.link);
                }
-               weston_surface_geometry_dirty(surface);
+               weston_view_geometry_dirty(view);
        }
 }
 
@@ -881,7 +905,7 @@ change_workspace(struct desktop_shell *shell, unsigned int index)
                return;
 
        /* Don't change workspace when there is any fullscreen surfaces. */
-       if (!wl_list_empty(&shell->fullscreen_layer.surface_list))
+       if (!wl_list_empty(&shell->fullscreen_layer.view_list))
                return;
 
        from = get_current_workspace(shell);
@@ -913,7 +937,7 @@ change_workspace(struct desktop_shell *shell, unsigned int index)
 static bool
 workspace_has_only(struct workspace *ws, struct weston_surface *surface)
 {
-       struct wl_list *list = &ws->layer.surface_list;
+       struct wl_list *list = &ws->layer.view_list;
        struct wl_list *e;
 
        if (wl_list_empty(list))
@@ -924,20 +948,20 @@ workspace_has_only(struct workspace *ws, struct weston_surface *surface)
        if (e->next != list)
                return false;
 
-       return container_of(e, struct weston_surface, layer_link) == surface;
+       return container_of(e, struct weston_view, layer_link)->surface == surface;
 }
 
 static void
-move_surface_to_workspace(struct desktop_shell *shell,
-                         struct weston_surface *surface,
-                         uint32_t workspace)
+move_view_to_workspace(struct desktop_shell *shell,
+                      struct weston_view *view,
+                      uint32_t workspace)
 {
        struct workspace *from;
        struct workspace *to;
        struct weston_seat *seat;
        struct weston_surface *focus;
 
-       assert(weston_surface_get_main_surface(surface) == surface);
+       assert(weston_surface_get_main_surface(view->surface) == view->surface);
 
        if (workspace == shell->workspaces.current)
                return;
@@ -948,20 +972,20 @@ move_surface_to_workspace(struct desktop_shell *shell,
        from = get_current_workspace(shell);
        to = get_workspace(shell, workspace);
 
-       wl_list_remove(&surface->layer_link);
-       wl_list_insert(&to->layer.surface_list, &surface->layer_link);
+       wl_list_remove(&view->layer_link);
+       wl_list_insert(&to->layer.view_list, &view->layer_link);
 
-       drop_focus_state(shell, from, surface);
+       drop_focus_state(shell, from, view->surface);
        wl_list_for_each(seat, &shell->compositor->seat_list, link) {
                if (!seat->keyboard)
                        continue;
 
                focus = weston_surface_get_main_surface(seat->keyboard->focus);
-               if (focus == surface)
+               if (focus == view->surface)
                        weston_keyboard_set_focus(seat->keyboard, NULL);
        }
 
-       weston_surface_damage_below(surface);
+       weston_view_damage_below(view);
 }
 
 static void
@@ -970,21 +994,23 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
                                  unsigned int index)
 {
        struct weston_surface *surface;
+       struct weston_view *view;
        struct shell_surface *shsurf;
        struct workspace *from;
        struct workspace *to;
        struct focus_state *state;
 
        surface = weston_surface_get_main_surface(seat->keyboard->focus);
-       if (surface == NULL ||
+       view = get_default_view(surface);
+       if (view == NULL ||
            index == shell->workspaces.current)
                return;
 
        from = get_current_workspace(shell);
        to = get_workspace(shell, index);
 
-       wl_list_remove(&surface->layer_link);
-       wl_list_insert(&to->layer.surface_list, &surface->layer_link);
+       wl_list_remove(&view->layer_link);
+       wl_list_insert(&to->layer.view_list, &view->layer_link);
 
        replace_focus_state(shell, to, seat);
        drop_focus_state(shell, from, surface);
@@ -1034,9 +1060,13 @@ workspace_manager_move_surface(struct wl_client *client,
        struct weston_surface *surface =
                wl_resource_get_user_data(surface_resource);
        struct weston_surface *main_surface;
+       struct weston_view *view;
 
        main_surface = weston_surface_get_main_surface(surface);
-       move_surface_to_workspace(shell, main_surface, workspace);
+       view = get_default_view(main_surface);
+       if (!view)
+               return;
+       move_view_to_workspace(shell, view, workspace);
 }
 
 static const struct workspace_manager_interface workspace_manager_implementation = {
@@ -1107,8 +1137,9 @@ touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
 
        es = shsurf->surface;
 
-       weston_surface_configure(es, dx, dy,
-                                es->geometry.width, es->geometry.height);
+       weston_view_configure(shsurf->view, dx, dy,
+                             shsurf->view->geometry.width,
+                             shsurf->view->geometry.height);
 
        weston_compositor_schedule_repaint(es->compositor);
 }
@@ -1134,9 +1165,9 @@ surface_touch_move(struct shell_surface *shsurf, struct weston_seat *seat)
        if (!move)
                return -1;
 
-       move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
+       move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
                        seat->touch->grab_x;
-       move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
+       move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
                        seat->touch->grab_y;
 
        shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf,
@@ -1156,19 +1187,17 @@ move_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
        struct weston_move_grab *move = (struct weston_move_grab *) grab;
        struct weston_pointer *pointer = grab->pointer;
        struct shell_surface *shsurf = move->base.shsurf;
-       struct weston_surface *es;
        int dx = wl_fixed_to_int(pointer->x + move->dx);
        int dy = wl_fixed_to_int(pointer->y + move->dy);
 
        if (!shsurf)
                return;
 
-       es = shsurf->surface;
-
-       weston_surface_configure(es, dx, dy,
-                                es->geometry.width, es->geometry.height);
+       weston_view_configure(shsurf->view, dx, dy,
+                             shsurf->view->geometry.width,
+                             shsurf->view->geometry.height);
 
-       weston_compositor_schedule_repaint(es->compositor);
+       weston_compositor_schedule_repaint(shsurf->surface->compositor);
 }
 
 static void
@@ -1208,9 +1237,9 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *seat)
        if (!move)
                return -1;
 
-       move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
+       move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
                        seat->pointer->grab_x;
-       move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
+       move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
                        seat->pointer->grab_y;
 
        shell_grab_start(&move->base, &move_grab_interface, shsurf,
@@ -1230,13 +1259,13 @@ shell_surface_move(struct wl_client *client, struct wl_resource *resource,
        if (seat->pointer &&
            seat->pointer->button_count > 0 &&
            seat->pointer->grab_serial == serial) {
-               surface = weston_surface_get_main_surface(seat->pointer->focus);
+               surface = weston_surface_get_main_surface(seat->pointer->focus->surface);
                if ((surface == shsurf->surface) && 
                    (surface_move(shsurf, seat) < 0))
                        wl_resource_post_no_memory(resource);
        } else if (seat->touch &&
                   seat->touch->grab_serial == serial) {
-               surface = weston_surface_get_main_surface(seat->touch->focus);
+               surface = weston_surface_get_main_surface(seat->touch->focus->surface);
                if ((surface == shsurf->surface) && 
                    (surface_touch_move(shsurf, seat) < 0))
                        wl_resource_post_no_memory(resource);
@@ -1262,11 +1291,11 @@ resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
        if (!shsurf)
                return;
 
-       weston_surface_from_global_fixed(shsurf->surface,
-                                        pointer->grab_x, pointer->grab_y,
-                                        &from_x, &from_y);
-       weston_surface_from_global_fixed(shsurf->surface,
-                                        pointer->x, pointer->y, &to_x, &to_y);
+       weston_view_from_global_fixed(shsurf->view,
+                                     pointer->grab_x, pointer->grab_y,
+                                     &from_x, &from_y);
+       weston_view_from_global_fixed(shsurf->view,
+                                     pointer->x, pointer->y, &to_x, &to_y);
 
        width = resize->width;
        if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
@@ -1332,15 +1361,15 @@ surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x,
        struct weston_subsurface *subsurface;
 
        pixman_region32_init_rect(&region, 0, 0,
-                                 surface->geometry.width,
-                                 surface->geometry.height);
+                                 surface->width,
+                                 surface->height);
 
        wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
                pixman_region32_union_rect(&region, &region,
                                           subsurface->position.x,
                                           subsurface->position.y,
-                                          subsurface->surface->geometry.width,
-                                          subsurface->surface->geometry.height);
+                                          subsurface->surface->width,
+                                          subsurface->surface->height);
        }
 
        box = pixman_region32_extents(&region);
@@ -1396,7 +1425,7 @@ shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
        if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
                return;
 
-       surface = weston_surface_get_main_surface(seat->pointer->focus);
+       surface = weston_surface_get_main_surface(seat->pointer->focus->surface);
        if (seat->pointer->button_count == 0 ||
            seat->pointer->grab_serial != serial ||
            surface != shsurf->surface)
@@ -1414,14 +1443,14 @@ busy_cursor_grab_focus(struct weston_pointer_grab *base)
 {
        struct shell_grab *grab = (struct shell_grab *) base;
        struct weston_pointer *pointer = base->pointer;
-       struct weston_surface *surface;
+       struct weston_view *view;
        wl_fixed_t sx, sy;
 
-       surface = weston_compositor_pick_surface(pointer->seat->compositor,
-                                                pointer->x, pointer->y,
-                                                &sx, &sy);
+       view = weston_compositor_pick_view(pointer->seat->compositor,
+                                          pointer->x, pointer->y,
+                                          &sx, &sy);
 
-       if (!grab->shsurf || grab->shsurf->surface != surface)
+       if (!grab->shsurf || grab->shsurf->surface != view->surface)
                end_busy_cursor(grab->shsurf, pointer);
 }
 
@@ -1501,7 +1530,7 @@ ping_timeout_handler(void *data)
        shsurf->unresponsive = 1;
 
        wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
-               if (seat->pointer->focus == shsurf->surface)
+               if (seat->pointer->focus->surface == shsurf->surface)
                        set_busy_cursor(shsurf, seat->pointer);
 
        return 1;
@@ -1541,22 +1570,22 @@ static void
 handle_pointer_focus(struct wl_listener *listener, void *data)
 {
        struct weston_pointer *pointer = data;
-       struct weston_surface *surface = pointer->focus;
+       struct weston_view *view = pointer->focus;
        struct weston_compositor *compositor;
        struct shell_surface *shsurf;
        uint32_t serial;
 
-       if (!surface)
+       if (!view)
                return;
 
-       compositor = surface->compositor;
-       shsurf = get_shell_surface(surface);
+       compositor = view->surface->compositor;
+       shsurf = get_shell_surface(view->surface);
 
        if (shsurf && shsurf->unresponsive) {
                set_busy_cursor(shsurf, pointer);
        } else {
                serial = wl_display_next_serial(compositor->wl_display);
-               ping_handler(surface, serial);
+               ping_handler(view->surface, serial);
        }
 }
 
@@ -1661,21 +1690,21 @@ shell_unset_fullscreen(struct shell_surface *shsurf)
        shsurf->fullscreen.framerate = 0;
        wl_list_remove(&shsurf->fullscreen.transform.link);
        wl_list_init(&shsurf->fullscreen.transform.link);
-       if (shsurf->fullscreen.black_surface)
-               weston_surface_destroy(shsurf->fullscreen.black_surface);
-       shsurf->fullscreen.black_surface = NULL;
+       if (shsurf->fullscreen.black_view)
+               weston_surface_destroy(shsurf->fullscreen.black_view->surface);
+       shsurf->fullscreen.black_view = NULL;
        shsurf->fullscreen_output = NULL;
-       weston_surface_set_position(shsurf->surface,
-                                   shsurf->saved_x, shsurf->saved_y);
+       weston_view_set_position(shsurf->view,
+                                shsurf->saved_x, shsurf->saved_y);
        if (shsurf->saved_rotation_valid) {
-               wl_list_insert(&shsurf->surface->geometry.transformation_list,
+               wl_list_insert(&shsurf->view->geometry.transformation_list,
                               &shsurf->rotation.transform.link);
                shsurf->saved_rotation_valid = false;
        }
 
        ws = get_current_workspace(shsurf->shell);
-       wl_list_remove(&shsurf->surface->layer_link);
-       wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link);
+       wl_list_remove(&shsurf->view->layer_link);
+       wl_list_insert(&ws->layer.view_list, &shsurf->view->layer_link);
 }
 
 static void
@@ -1684,19 +1713,19 @@ shell_unset_maximized(struct shell_surface *shsurf)
        struct workspace *ws;
        /* undo all maximized things here */
        shsurf->output = get_default_output(shsurf->surface->compositor);
-       weston_surface_set_position(shsurf->surface,
-                                   shsurf->saved_x,
-                                   shsurf->saved_y);
+       weston_view_set_position(shsurf->view,
+                                shsurf->saved_x,
+                                shsurf->saved_y);
 
        if (shsurf->saved_rotation_valid) {
-               wl_list_insert(&shsurf->surface->geometry.transformation_list,
-                                                  &shsurf->rotation.transform.link);
+               wl_list_insert(&shsurf->view->geometry.transformation_list,
+                              &shsurf->rotation.transform.link);
                shsurf->saved_rotation_valid = false;
        }
 
        ws = get_current_workspace(shsurf->shell);
-       wl_list_remove(&shsurf->surface->layer_link);
-       wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link);
+       wl_list_remove(&shsurf->view->layer_link);
+       wl_list_insert(&ws->layer.view_list, &shsurf->view->layer_link);
 }
 
 static int
@@ -1724,8 +1753,8 @@ reset_shell_surface_type(struct shell_surface *surface)
 static void
 set_surface_type(struct shell_surface *shsurf)
 {
-       struct weston_surface *surface = shsurf->surface;
        struct weston_surface *pes = shsurf->parent;
+       struct weston_view *pev = get_default_view(pes);
 
        reset_shell_surface_type(shsurf);
 
@@ -1736,28 +1765,29 @@ set_surface_type(struct shell_surface *shsurf)
        case SHELL_SURFACE_TOPLEVEL:
                break;
        case SHELL_SURFACE_TRANSIENT:
-               weston_surface_set_position(surface,
-                               pes->geometry.x + shsurf->transient.x,
-                               pes->geometry.y + shsurf->transient.y);
+               if (pev)
+                       weston_view_set_position(shsurf->view,
+                                                pev->geometry.x + shsurf->transient.x,
+                                                pev->geometry.y + shsurf->transient.y);
                break;
 
        case SHELL_SURFACE_MAXIMIZED:
        case SHELL_SURFACE_FULLSCREEN:
-               shsurf->saved_x = surface->geometry.x;
-               shsurf->saved_y = surface->geometry.y;
+               shsurf->saved_x = shsurf->view->geometry.x;
+               shsurf->saved_y = shsurf->view->geometry.y;
                shsurf->saved_position_valid = true;
 
                if (!wl_list_empty(&shsurf->rotation.transform.link)) {
                        wl_list_remove(&shsurf->rotation.transform.link);
                        wl_list_init(&shsurf->rotation.transform.link);
-                       weston_surface_geometry_dirty(shsurf->surface);
+                       weston_view_geometry_dirty(shsurf->view);
                        shsurf->saved_rotation_valid = true;
                }
                break;
 
        case SHELL_SURFACE_XWAYLAND:
-               weston_surface_set_position(surface, shsurf->transient.x,
-                                           shsurf->transient.y);
+               weston_view_set_position(shsurf->view, shsurf->transient.x,
+                                        shsurf->transient.y);
                break;
 
        default:
@@ -1815,15 +1845,15 @@ static int
 get_output_panel_height(struct desktop_shell *shell,
                        struct weston_output *output)
 {
-       struct weston_surface *surface;
+       struct weston_view *view;
        int panel_height = 0;
 
        if (!output)
                return 0;
 
-       wl_list_for_each(surface, &shell->panel_layer.surface_list, layer_link) {
-               if (surface->output == output) {
-                       panel_height = surface->geometry.height;
+       wl_list_for_each(view, &shell->panel_layer.view_list, layer_link) {
+               if (view->surface->output == output) {
+                       panel_height = view->geometry.height;
                        break;
                }
        }
@@ -1864,29 +1894,37 @@ shell_surface_set_maximized(struct wl_client *client,
 static void
 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height);
 
-static struct weston_surface *
+static struct weston_view *
 create_black_surface(struct weston_compositor *ec,
                     struct weston_surface *fs_surface,
                     float x, float y, int w, int h)
 {
        struct weston_surface *surface = NULL;
+       struct weston_view *view;
 
        surface = weston_surface_create(ec);
        if (surface == NULL) {
                weston_log("no memory\n");
                return NULL;
        }
+       view = weston_view_create(surface);
+       if (surface == NULL) {
+               weston_log("no memory\n");
+               weston_surface_destroy(surface);
+               return NULL;
+       }
 
        surface->configure = black_surface_configure;
        surface->configure_private = fs_surface;
-       weston_surface_configure(surface, x, y, w, h);
        weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
        pixman_region32_fini(&surface->opaque);
        pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
        pixman_region32_fini(&surface->input);
        pixman_region32_init_rect(&surface->input, 0, 0, w, h);
 
-       return surface;
+       weston_view_configure(view, x, y, w, h);
+
+       return view;
 }
 
 /* Create black surface and append it to the associated fullscreen surface.
@@ -1903,33 +1941,35 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
        if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
                restore_output_mode(output);
 
-       if (!shsurf->fullscreen.black_surface)
-               shsurf->fullscreen.black_surface =
+       if (!shsurf->fullscreen.black_view)
+               shsurf->fullscreen.black_view =
                        create_black_surface(surface->compositor,
                                             surface,
                                             output->x, output->y,
                                             output->width,
                                             output->height);
 
-       wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
-       wl_list_insert(&surface->layer_link,
-                      &shsurf->fullscreen.black_surface->layer_link);
-       shsurf->fullscreen.black_surface->output = output;
+       wl_list_remove(&shsurf->fullscreen.black_view->layer_link);
+       wl_list_insert(&shsurf->view->layer_link,
+                      &shsurf->fullscreen.black_view->layer_link);
+       shsurf->fullscreen.black_view->surface->output = output;
+       shsurf->fullscreen.black_view->output = output;
 
-       surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y,
+       surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
                                        &surf_width, &surf_height);
 
        switch (shsurf->fullscreen.type) {
        case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
                if (surface->buffer_ref.buffer)
-                       center_on_output(surface, shsurf->fullscreen_output);
+                       center_on_output(shsurf->view, shsurf->fullscreen_output);
                break;
        case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
                /* 1:1 mapping between surface and output dimensions */
                if (output->width == surf_width &&
                        output->height == surf_height) {
-                       weston_surface_set_position(surface, output->x - surf_x,
-                                                            output->y - surf_y);
+                       weston_view_set_position(shsurf->view,
+                                                output->x - surf_x,
+                                                output->y - surf_y);
                        break;
                }
 
@@ -1938,8 +1978,9 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
 
                output_aspect = (float) output->width /
                        (float) output->height;
-               surface_aspect = (float) surface->geometry.width /
-                       (float) surface->geometry.height;
+               /* XXX: Use surf_width and surf_height here? */
+               surface_aspect = (float) surface->width /
+                       (float) surface->height;
                if (output_aspect < surface_aspect)
                        scale = (float) output->width /
                                (float) surf_width;
@@ -1949,11 +1990,11 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
 
                weston_matrix_scale(matrix, scale, scale, 1);
                wl_list_remove(&shsurf->fullscreen.transform.link);
-               wl_list_insert(&surface->geometry.transformation_list,
+               wl_list_insert(&shsurf->view->geometry.transformation_list,
                               &shsurf->fullscreen.transform.link);
                x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
                y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
-               weston_surface_set_position(surface, x, y);
+               weston_view_set_position(shsurf->view, x, y);
 
                break;
        case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
@@ -1965,23 +2006,23 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
 
                        if (weston_output_switch_mode(output, &mode, surface->buffer_scale,
                                        WESTON_MODE_SWITCH_SET_TEMPORARY) == 0) {
-                               weston_surface_set_position(surface,
-                                                           output->x - surf_x,
-                                                           output->y - surf_y);
-                               weston_surface_configure(shsurf->fullscreen.black_surface,
-                                                        output->x - surf_x,
-                                                        output->y - surf_y,
-                                                        output->width,
-                                                        output->height);
+                               weston_view_set_position(shsurf->view,
+                                                        output->x - surf_x,
+                                                        output->y - surf_y);
+                               weston_view_configure(shsurf->fullscreen.black_view,
+                                                     output->x - surf_x,
+                                                     output->y - surf_y,
+                                                     output->width,
+                                                     output->height);
                                break;
                        } else {
                                restore_output_mode(output);
-                               center_on_output(surface, output);
+                               center_on_output(shsurf->view, output);
                        }
                }
                break;
        case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
-               center_on_output(surface, output);
+               center_on_output(shsurf->view, output);
                break;
        default:
                break;
@@ -1993,26 +2034,25 @@ static void
 shell_stack_fullscreen(struct shell_surface *shsurf)
 {
        struct weston_output *output = shsurf->fullscreen_output;
-       struct weston_surface *surface = shsurf->surface;
        struct desktop_shell *shell = shell_surface_get_shell(shsurf);
 
-       wl_list_remove(&surface->layer_link);
-       wl_list_insert(&shell->fullscreen_layer.surface_list,
-                      &surface->layer_link);
-       weston_surface_damage(surface);
+       wl_list_remove(&shsurf->view->layer_link);
+       wl_list_insert(&shell->fullscreen_layer.view_list,
+                      &shsurf->view->layer_link);
+       weston_surface_damage(shsurf->surface);
 
-       if (!shsurf->fullscreen.black_surface)
-               shsurf->fullscreen.black_surface =
-                       create_black_surface(surface->compositor,
-                                            surface,
+       if (!shsurf->fullscreen.black_view)
+               shsurf->fullscreen.black_view =
+                       create_black_surface(shsurf->surface->compositor,
+                                            shsurf->surface,
                                             output->x, output->y,
                                             output->width,
                                             output->height);
 
-       wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
-       wl_list_insert(&surface->layer_link,
-                      &shsurf->fullscreen.black_surface->layer_link);
-       weston_surface_damage(shsurf->fullscreen.black_surface);
+       wl_list_remove(&shsurf->fullscreen.black_view->layer_link);
+       wl_list_insert(&shsurf->view->layer_link,
+                      &shsurf->fullscreen.black_view->layer_link);
+       weston_surface_damage(shsurf->fullscreen.black_view->surface);
 }
 
 static void
@@ -2141,18 +2181,19 @@ static void
 popup_grab_focus(struct weston_pointer_grab *grab)
 {
        struct weston_pointer *pointer = grab->pointer;
-       struct weston_surface *surface;
+       struct weston_view *view;
        struct shell_seat *shseat =
            container_of(grab, struct shell_seat, popup_grab.grab);
        struct wl_client *client = shseat->popup_grab.client;
        wl_fixed_t sx, sy;
 
-       surface = weston_compositor_pick_surface(pointer->seat->compositor,
-                                                pointer->x, pointer->y,
-                                                &sx, &sy);
+       view = weston_compositor_pick_view(pointer->seat->compositor,
+                                          pointer->x, pointer->y,
+                                          &sx, &sy);
 
-       if (surface && wl_resource_get_client(surface->resource) == client) {
-               weston_pointer_set_focus(pointer, surface, sx, sy);
+       if (view && view->surface->resource &&
+           wl_resource_get_client(view->surface->resource) == client) {
+               weston_pointer_set_focus(pointer, view, sx, sy);
        } else {
                weston_pointer_set_focus(pointer, NULL,
                                         wl_fixed_from_int(0),
@@ -2168,9 +2209,9 @@ popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
        wl_fixed_t sx, sy;
 
        wl_resource_for_each(resource, &pointer->focus_resource_list) {
-               weston_surface_from_global_fixed(pointer->focus,
-                                                pointer->x, pointer->y,
-                                                &sx, &sy);
+               weston_view_from_global_fixed(pointer->focus,
+                                             pointer->x, pointer->y,
+                                             &sx, &sy);
                wl_pointer_send_motion(resource, time, sx, sy);
        }
 }
@@ -2276,14 +2317,14 @@ static void
 shell_map_popup(struct shell_surface *shsurf)
 {
        struct shell_seat *shseat = shsurf->popup.shseat;
-       struct weston_surface *es = shsurf->surface;
-       struct weston_surface *parent = shsurf->parent;
+       struct weston_view *parent_view = get_default_view(shsurf->parent);
 
-       es->output = parent->output;
+       shsurf->surface->output = parent_view->output;
+       shsurf->view->output = parent_view->output;
 
-       weston_surface_set_transform_parent(es, parent);
-       weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
-       weston_surface_update_transform(es);
+       weston_view_set_transform_parent(shsurf->view, parent_view);
+       weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y);
+       weston_view_update_transform(shsurf->view);
 
        if (shseat->seat->pointer->grab_serial == shsurf->popup.serial) {
                add_popup_grab(shsurf, shseat);
@@ -2337,8 +2378,8 @@ destroy_shell_surface(struct shell_surface *shsurf)
            shell_surface_is_top_fullscreen(shsurf))
                restore_output_mode (shsurf->fullscreen_output);
 
-       if (shsurf->fullscreen.black_surface)
-               weston_surface_destroy(shsurf->fullscreen.black_surface);
+       if (shsurf->fullscreen.black_view)
+               weston_surface_destroy(shsurf->fullscreen.black_view->surface);
 
        /* As destroy_resource() use wl_list_for_each_safe(),
         * we can always remove the listener.
@@ -2348,6 +2389,8 @@ destroy_shell_surface(struct shell_surface *shsurf)
        ping_timer_destroy(shsurf);
        free(shsurf->title);
 
+       weston_view_destroy(shsurf->view);
+
        wl_list_remove(&shsurf->link);
        free(shsurf);
 }
@@ -2402,6 +2445,13 @@ create_shell_surface(void *shell, struct weston_surface *surface,
                return NULL;
        }
 
+       shsurf->view = weston_view_create(surface);
+       if (!shsurf->view) {
+               weston_log("no memory to allocate shell surface\n");
+               free(shsurf);
+               return NULL;
+       }
+
        surface->configure = shell_surface_configure;
        surface->configure_private = shsurf;
 
@@ -2412,7 +2462,7 @@ create_shell_surface(void *shell, struct weston_surface *surface,
        shsurf->surface = surface;
        shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
        shsurf->fullscreen.framerate = 0;
-       shsurf->fullscreen.black_surface = NULL;
+       shsurf->fullscreen.black_view = NULL;
        shsurf->ping_timer = NULL;
        wl_list_init(&shsurf->fullscreen.transform.link);
 
@@ -2439,6 +2489,12 @@ create_shell_surface(void *shell, struct weston_surface *surface,
        return shsurf;
 }
 
+static struct weston_view *
+get_primary_view(void *shell, struct shell_surface *shsurf)
+{
+       return shsurf->view;
+}
+
 static void
 shell_get_shell_surface(struct wl_client *client,
                        struct wl_resource *resource,
@@ -2534,25 +2590,25 @@ terminate_screensaver(struct desktop_shell *shell)
 }
 
 static void
-configure_static_surface(struct weston_surface *es, struct weston_layer *layer, int32_t width, int32_t height)
+configure_static_view(struct weston_view *ev, struct weston_layer *layer, int32_t width, int32_t height)
 {
-       struct weston_surface *s, *next;
+       struct weston_view *v, *next;
 
        if (width == 0)
                return;
 
-       wl_list_for_each_safe(s, next, &layer->surface_list, layer_link) {
-               if (s->output == es->output && s != es) {
-                       weston_surface_unmap(s);
-                       s->configure = NULL;
+       wl_list_for_each_safe(v, next, &layer->view_list, layer_link) {
+               if (v->output == ev->output && v != ev) {
+                       weston_view_unmap(v);
+                       v->surface->configure = NULL;
                }
        }
 
-       weston_surface_configure(es, es->output->x, es->output->y, width, height);
+       weston_view_configure(ev, ev->output->x, ev->output->y, width, height);
 
-       if (wl_list_empty(&es->layer_link)) {
-               wl_list_insert(&layer->surface_list, &es->layer_link);
-               weston_compositor_schedule_repaint(es->compositor);
+       if (wl_list_empty(&ev->layer_link)) {
+               wl_list_insert(&layer->view_list, &ev->layer_link);
+               weston_compositor_schedule_repaint(ev->surface->compositor);
        }
 }
 
@@ -2560,8 +2616,11 @@ static void
 background_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
 {
        struct desktop_shell *shell = es->configure_private;
+       struct weston_view *view;
 
-       configure_static_surface(es, &shell->background_layer, width, height);
+       view = container_of(es->views.next, struct weston_view, surface_link);
+
+       configure_static_view(view, &shell->background_layer, width, height);
 }
 
 static void
@@ -2573,6 +2632,7 @@ desktop_shell_set_background(struct wl_client *client,
        struct desktop_shell *shell = wl_resource_get_user_data(resource);
        struct weston_surface *surface =
                wl_resource_get_user_data(surface_resource);
+       struct weston_view *view, *next;
 
        if (surface->configure) {
                wl_resource_post_error(surface_resource,
@@ -2581,9 +2641,14 @@ desktop_shell_set_background(struct wl_client *client,
                return;
        }
 
+       wl_list_for_each_safe(view, next, &surface->views, surface_link)
+               weston_view_destroy(view);
+       view = weston_view_create(surface);
+
        surface->configure = background_configure;
        surface->configure_private = shell;
        surface->output = wl_resource_get_user_data(output_resource);
+       view->output = surface->output;
        desktop_shell_send_configure(resource, 0,
                                     surface_resource,
                                     surface->output->width,
@@ -2594,8 +2659,11 @@ static void
 panel_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
 {
        struct desktop_shell *shell = es->configure_private;
+       struct weston_view *view;
+
+       view = container_of(es->views.next, struct weston_view, surface_link);
 
-       configure_static_surface(es, &shell->panel_layer, width, height);
+       configure_static_view(view, &shell->panel_layer, width, height);
 }
 
 static void
@@ -2607,6 +2675,7 @@ desktop_shell_set_panel(struct wl_client *client,
        struct desktop_shell *shell = wl_resource_get_user_data(resource);
        struct weston_surface *surface =
                wl_resource_get_user_data(surface_resource);
+       struct weston_view *view, *next;
 
        if (surface->configure) {
                wl_resource_post_error(surface_resource,
@@ -2615,9 +2684,14 @@ desktop_shell_set_panel(struct wl_client *client,
                return;
        }
 
+       wl_list_for_each_safe(view, next, &surface->views, surface_link)
+               weston_view_destroy(view);
+       view = weston_view_create(surface);
+
        surface->configure = panel_configure;
        surface->configure_private = shell;
        surface->output = wl_resource_get_user_data(output_resource);
+       view->output = surface->output;
        desktop_shell_send_configure(resource, 0,
                                     surface_resource,
                                     surface->output->width,
@@ -2628,18 +2702,23 @@ static void
 lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
 {
        struct desktop_shell *shell = surface->configure_private;
+       struct weston_view *view;
+
+       view = container_of(surface->views.next, struct weston_view, surface_link);
 
        if (width == 0)
                return;
 
-       surface->geometry.width = width;
-       surface->geometry.height = height;
-       center_on_output(surface, get_default_output(shell->compositor));
+       surface->width = width;
+       surface->height = height;
+       view->geometry.width = width;
+       view->geometry.height = height;
+       center_on_output(view, get_default_output(shell->compositor));
 
        if (!weston_surface_is_mapped(surface)) {
-               wl_list_insert(&shell->lock_layer.surface_list,
-                              &surface->layer_link);
-               weston_surface_update_transform(surface);
+               wl_list_insert(&shell->lock_layer.view_list,
+                              &view->layer_link);
+               weston_view_update_transform(view);
                shell_fade(shell, FADE_IN);
        }
 }
@@ -2816,21 +2895,21 @@ resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *d
            shsurf->type == SHELL_SURFACE_MAXIMIZED)
                return;
 
-       weston_surface_from_global(surface,
-                                  wl_fixed_to_int(seat->pointer->grab_x),
-                                  wl_fixed_to_int(seat->pointer->grab_y),
-                                  &x, &y);
+       weston_view_from_global(shsurf->view,
+                               wl_fixed_to_int(seat->pointer->grab_x),
+                               wl_fixed_to_int(seat->pointer->grab_y),
+                               &x, &y);
 
-       if (x < surface->geometry.width / 3)
+       if (x < shsurf->view->geometry.width / 3)
                edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
-       else if (x < 2 * surface->geometry.width / 3)
+       else if (x < 2 * shsurf->view->geometry.width / 3)
                edges |= 0;
        else
                edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
 
-       if (y < surface->geometry.height / 3)
+       if (y < shsurf->view->geometry.height / 3)
                edges |= WL_SHELL_SURFACE_RESIZE_TOP;
-       else if (y < 2 * surface->geometry.height / 3)
+       else if (y < 2 * shsurf->view->geometry.height / 3)
                edges |= 0;
        else
                edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
@@ -2857,14 +2936,14 @@ surface_opacity_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
        if (!shsurf)
                return;
 
-       surface->alpha -= wl_fixed_to_double(value) * step;
+       shsurf->view->alpha -= wl_fixed_to_double(value) * step;
 
-       if (surface->alpha > 1.0)
-               surface->alpha = 1.0;
-       if (surface->alpha < step)
-               surface->alpha = step;
+       if (shsurf->view->alpha > 1.0)
+               shsurf->view->alpha = 1.0;
+       if (shsurf->view->alpha < step)
+               shsurf->view->alpha = step;
 
-       weston_surface_geometry_dirty(surface);
+       weston_view_geometry_dirty(shsurf->view);
        weston_surface_damage(surface);
 }
 
@@ -2906,7 +2985,7 @@ do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
 
                        output->zoom.spring_z.target = output->zoom.level;
 
-                       weston_output_update_zoom(output, output->zoom.type);
+                       weston_output_update_zoom(output);
                }
        }
 }
@@ -2941,23 +3020,20 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
                container_of(grab, struct rotate_grab, base.grab);
        struct weston_pointer *pointer = grab->pointer;
        struct shell_surface *shsurf = rotate->base.shsurf;
-       struct weston_surface *surface;
        float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
 
        if (!shsurf)
                return;
 
-       surface = shsurf->surface;
-
-       cx = 0.5f * surface->geometry.width;
-       cy = 0.5f * surface->geometry.height;
+       cx = 0.5f * shsurf->view->geometry.width;
+       cy = 0.5f * shsurf->view->geometry.height;
 
        dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
        dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
        r = sqrtf(dx * dx + dy * dy);
 
        wl_list_remove(&shsurf->rotation.transform.link);
-       weston_surface_geometry_dirty(shsurf->surface);
+       weston_view_geometry_dirty(shsurf->view);
 
        if (r > 20.0f) {
                struct weston_matrix *matrix =
@@ -2973,7 +3049,7 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
                weston_matrix_translate(matrix, cx, cy, 0.0f);
 
                wl_list_insert(
-                       &shsurf->surface->geometry.transformation_list,
+                       &shsurf->view->geometry.transformation_list,
                        &shsurf->rotation.transform.link);
        } else {
                wl_list_init(&shsurf->rotation.transform.link);
@@ -2983,14 +3059,14 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
 
        /* We need to adjust the position of the surface
         * in case it was resized in a rotated state before */
-       cposx = surface->geometry.x + cx;
-       cposy = surface->geometry.y + cy;
+       cposx = shsurf->view->geometry.x + cx;
+       cposy = shsurf->view->geometry.y + cy;
        dposx = rotate->center.x - cposx;
        dposy = rotate->center.y - cposy;
        if (dposx != 0.0f || dposy != 0.0f) {
-               weston_surface_set_position(surface,
-                                           surface->geometry.x + dposx,
-                                           surface->geometry.y + dposy);
+               weston_view_set_position(shsurf->view,
+                                        shsurf->view->geometry.x + dposx,
+                                        shsurf->view->geometry.y + dposy);
        }
 
        /* Repaint implies weston_surface_update_transform(), which
@@ -3036,10 +3112,10 @@ surface_rotate(struct shell_surface *surface, struct weston_seat *seat)
        if (!rotate)
                return;
 
-       weston_surface_to_global_float(surface->surface,
-                                      surface->surface->geometry.width * 0.5f,
-                                      surface->surface->geometry.height * 0.5f,
-                                      &rotate->center.x, &rotate->center.y);
+       weston_view_to_global_float(surface->view,
+                                   surface->view->geometry.width * 0.5f,
+                                   surface->view->geometry.height * 0.5f,
+                                   &rotate->center.x, &rotate->center.y);
 
        dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
        dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
@@ -3087,13 +3163,13 @@ static void
 lower_fullscreen_layer(struct desktop_shell *shell)
 {
        struct workspace *ws;
-       struct weston_surface *surface, *prev;
+       struct weston_view *view, *prev;
 
        ws = get_current_workspace(shell);
-       wl_list_for_each_reverse_safe(surface, prev,
-                                     &shell->fullscreen_layer.surface_list,
+       wl_list_for_each_reverse_safe(view, prev,
+                                     &shell->fullscreen_layer.view_list,
                                      layer_link)
-               weston_surface_restack(surface, &ws->layer.surface_list);
+               weston_view_restack(view, &ws->layer.view_list);
 }
 
 static void
@@ -3101,6 +3177,7 @@ activate(struct desktop_shell *shell, struct weston_surface *es,
         struct weston_seat *seat)
 {
        struct weston_surface *main_surface;
+       struct weston_view *main_view;
        struct focus_state *state;
        struct workspace *ws;
 
@@ -3125,7 +3202,9 @@ activate(struct desktop_shell *shell, struct weston_surface *es,
        default:
                restore_all_output_modes(shell->compositor);
                ws = get_current_workspace(shell);
-               weston_surface_restack(main_surface, &ws->layer.surface_list);
+               main_view = get_default_view(main_surface);
+               if (main_view)
+                       weston_view_restack(main_view, &ws->layer.view_list);
                break;
        }
 }
@@ -3156,6 +3235,7 @@ activate_binding(struct weston_seat *seat,
 
        if (!focus)
                return;
+       focus = seat->pointer->focus->surface;
 
        if (is_black_surface(focus, &main_surface))
                focus = main_surface;
@@ -3241,7 +3321,7 @@ unlock(struct desktop_shell *shell)
 }
 
 static void
-shell_fade_done(struct weston_surface_animation *animation, void *data)
+shell_fade_done(struct weston_view_animation *animation, void *data)
 {
        struct desktop_shell *shell = data;
 
@@ -3249,8 +3329,8 @@ shell_fade_done(struct weston_surface_animation *animation, void *data)
 
        switch (shell->fade.type) {
        case FADE_IN:
-               weston_surface_destroy(shell->fade.surface);
-               shell->fade.surface = NULL;
+               weston_surface_destroy(shell->fade.view->surface);
+               shell->fade.view = NULL;
                break;
        case FADE_OUT:
                lock(shell);
@@ -3258,23 +3338,30 @@ shell_fade_done(struct weston_surface_animation *animation, void *data)
        }
 }
 
-static struct weston_surface *
+static struct weston_view *
 shell_fade_create_surface(struct desktop_shell *shell)
 {
        struct weston_compositor *compositor = shell->compositor;
        struct weston_surface *surface;
+       struct weston_view *view;
 
        surface = weston_surface_create(compositor);
        if (!surface)
                return NULL;
 
-       weston_surface_configure(surface, 0, 0, 8192, 8192);
+       view = weston_view_create(surface);
+       if (!view) {
+               weston_surface_destroy(surface);
+               return NULL;
+       }
+
+       weston_view_configure(view, 0, 0, 8192, 8192);
        weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
-       wl_list_insert(&compositor->fade_layer.surface_list,
-                      &surface->layer_link);
+       wl_list_insert(&compositor->fade_layer.view_list,
+                      &view->layer_link);
        pixman_region32_init(&surface->input);
 
-       return surface;
+       return view;
 }
 
 static void
@@ -3296,20 +3383,20 @@ shell_fade(struct desktop_shell *shell, enum fade_type type)
 
        shell->fade.type = type;
 
-       if (shell->fade.surface == NULL) {
-               shell->fade.surface = shell_fade_create_surface(shell);
-               if (!shell->fade.surface)
+       if (shell->fade.view == NULL) {
+               shell->fade.view = shell_fade_create_surface(shell);
+               if (!shell->fade.view)
                        return;
 
-               shell->fade.surface->alpha = 1.0 - tint;
-               weston_surface_update_transform(shell->fade.surface);
+               shell->fade.view->alpha = 1.0 - tint;
+               weston_view_update_transform(shell->fade.view);
        }
 
        if (shell->fade.animation)
                weston_fade_update(shell->fade.animation, tint);
        else
                shell->fade.animation =
-                       weston_fade_run(shell->fade.surface,
+                       weston_fade_run(shell->fade.view,
                                        1.0 - tint, tint, 300.0,
                                        shell_fade_done, shell);
 }
@@ -3322,8 +3409,8 @@ do_shell_fade_startup(void *data)
        if (shell->startup_animation_type == ANIMATION_FADE)
                shell_fade(shell, FADE_IN);
        else if (shell->startup_animation_type == ANIMATION_NONE) {
-               weston_surface_destroy(shell->fade.surface);
-               shell->fade.surface = NULL;
+               weston_surface_destroy(shell->fade.view->surface);
+               shell->fade.view = NULL;
        }
 }
 
@@ -3361,18 +3448,18 @@ shell_fade_init(struct desktop_shell *shell)
 
        struct wl_event_loop *loop;
 
-       if (shell->fade.surface != NULL) {
+       if (shell->fade.view != NULL) {
                weston_log("%s: warning: fade surface already exists\n",
                           __func__);
                return;
        }
 
-       shell->fade.surface = shell_fade_create_surface(shell);
-       if (!shell->fade.surface)
+       shell->fade.view = shell_fade_create_surface(shell);
+       if (!shell->fade.view)
                return;
 
-       weston_surface_update_transform(shell->fade.surface);
-       weston_surface_damage(shell->fade.surface);
+       weston_view_update_transform(shell->fade.view);
+       weston_surface_damage(shell->fade.view->surface);
 
        loop = wl_display_get_event_loop(shell->compositor->wl_display);
        shell->fade.startup_timer =
@@ -3405,8 +3492,7 @@ show_input_panels(struct wl_listener *listener, void *data)
        struct desktop_shell *shell =
                container_of(listener, struct desktop_shell,
                             show_input_panel_listener);
-       struct input_panel_surface *surface, *next;
-       struct weston_surface *ws;
+       struct input_panel_surface *ipsurf, *next;
 
        shell->text_input.surface = (struct weston_surface*)data;
 
@@ -3419,17 +3505,17 @@ show_input_panels(struct wl_listener *listener, void *data)
                wl_list_insert(&shell->panel_layer.link,
                               &shell->input_panel_layer.link);
 
-       wl_list_for_each_safe(surface, next,
+       wl_list_for_each_safe(ipsurf, next,
                              &shell->input_panel.surfaces, link) {
-               ws = surface->surface;
-               if (!ws->buffer_ref.buffer)
+               if (!ipsurf->surface->buffer_ref.buffer)
                        continue;
-               wl_list_insert(&shell->input_panel_layer.surface_list,
-                              &ws->layer_link);
-               weston_surface_geometry_dirty(ws);
-               weston_surface_update_transform(ws);
-               weston_surface_damage(ws);
-               weston_slide_run(ws, ws->geometry.height, 0, NULL, NULL);
+               wl_list_insert(&shell->input_panel_layer.view_list,
+                              &ipsurf->view->layer_link);
+               weston_view_geometry_dirty(ipsurf->view);
+               weston_view_update_transform(ipsurf->view);
+               weston_surface_damage(ipsurf->surface);
+               weston_slide_run(ipsurf->view, ipsurf->view->geometry.height,
+                                0, NULL, NULL);
        }
 }
 
@@ -3439,7 +3525,7 @@ hide_input_panels(struct wl_listener *listener, void *data)
        struct desktop_shell *shell =
                container_of(listener, struct desktop_shell,
                             hide_input_panel_listener);
-       struct weston_surface *surface, *next;
+       struct weston_view *view, *next;
 
        if (!shell->showing_input_panels)
                return;
@@ -3449,9 +3535,9 @@ hide_input_panels(struct wl_listener *listener, void *data)
        if (!shell->locked)
                wl_list_remove(&shell->input_panel_layer.link);
 
-       wl_list_for_each_safe(surface, next,
-                             &shell->input_panel_layer.surface_list, layer_link)
-               weston_surface_unmap(surface);
+       wl_list_for_each_safe(view, next,
+                             &shell->input_panel_layer.view_list, layer_link)
+               weston_view_unmap(view);
 }
 
 static void
@@ -3465,22 +3551,22 @@ update_input_panels(struct wl_listener *listener, void *data)
 }
 
 static void
-center_on_output(struct weston_surface *surface, struct weston_output *output)
+center_on_output(struct weston_view *view, struct weston_output *output)
 {
        int32_t surf_x, surf_y, width, height;
        float x, y;
 
-       surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y, &width, &height);
+       surface_subsurfaces_boundingbox(view->surface, &surf_x, &surf_y, &width, &height);
 
        x = output->x + (output->width - width) / 2 - surf_x / 2;
        y = output->y + (output->height - height) / 2 - surf_y / 2;
 
-       weston_surface_configure(surface, x, y, width, height);
+       weston_view_configure(view, x, y, width, height);
 }
 
 static void
-weston_surface_set_initial_position (struct weston_surface *surface,
-                                    struct desktop_shell *shell)
+weston_view_set_initial_position(struct weston_view *view,
+                                struct desktop_shell *shell)
 {
        struct weston_compositor *compositor = shell->compositor;
        int ix = 0, iy = 0;
@@ -3510,8 +3596,8 @@ weston_surface_set_initial_position (struct weston_surface *surface,
        }
 
        if (!target_output) {
-               weston_surface_set_position(surface, 10 + random() % 400,
-                                          10 + random() % 400);
+               weston_view_set_position(view, 10 + random() % 400,
+                                        10 + random() % 400);
                return;
        }
 
@@ -3520,9 +3606,9 @@ weston_surface_set_initial_position (struct weston_surface *surface,
         * output.
         */
        panel_height = get_output_panel_height(shell, target_output);
-       range_x = target_output->width - surface->geometry.width;
+       range_x = target_output->width - view->geometry.width;
        range_y = (target_output->height - panel_height) -
-                 surface->geometry.height;
+                 view->geometry.height;
 
        if (range_x > 0)
                dx = random() % range_x;
@@ -3537,61 +3623,65 @@ weston_surface_set_initial_position (struct weston_surface *surface,
        x = target_output->x + dx;
        y = target_output->y + dy;
 
-       weston_surface_set_position (surface, x, y);
+       weston_view_set_position(view, x, y);
 }
 
 static void
-map(struct desktop_shell *shell, struct weston_surface *surface,
+map(struct desktop_shell *shell, struct shell_surface *shsurf,
     int32_t width, int32_t height, int32_t sx, int32_t sy)
 {
        struct weston_compositor *compositor = shell->compositor;
-       struct shell_surface *shsurf = get_shell_surface(surface);
-       enum shell_surface_type surface_type = shsurf->type;
-       struct weston_surface *parent;
+       struct weston_view *parent;
        struct weston_seat *seat;
        struct workspace *ws;
        int panel_height = 0;
        int32_t surf_x, surf_y;
 
-       surface->geometry.width = width;
-       surface->geometry.height = height;
-       weston_surface_geometry_dirty(surface);
+       shsurf->view->geometry.width = width;
+       shsurf->view->geometry.height = height;
+       weston_view_geometry_dirty(shsurf->view);
 
        /* initial positioning, see also configure() */
-       switch (surface_type) {
+       switch (shsurf->type) {
        case SHELL_SURFACE_TOPLEVEL:
-               weston_surface_set_initial_position(surface, shell);
+               weston_view_set_initial_position(shsurf->view, shell);
                break;
        case SHELL_SURFACE_FULLSCREEN:
-               center_on_output(surface, shsurf->fullscreen_output);
+               center_on_output(shsurf->view, shsurf->fullscreen_output);
                shell_map_fullscreen(shsurf);
                break;
        case SHELL_SURFACE_MAXIMIZED:
                /* use surface configure to set the geometry */
-               panel_height = get_output_panel_height(shell,surface->output);
-               surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
-                                                                NULL, NULL);
-               weston_surface_set_position(surface, shsurf->output->x - surf_x,
-                                           shsurf->output->y + panel_height - surf_y);
+               panel_height = get_output_panel_height(shell, shsurf->output);
+               surface_subsurfaces_boundingbox(shsurf->surface,
+                                               &surf_x, &surf_y, NULL, NULL);
+               weston_view_set_position(shsurf->view,
+                                        shsurf->output->x - surf_x,
+                                        shsurf->output->y + panel_height - surf_y);
                break;
        case SHELL_SURFACE_POPUP:
                shell_map_popup(shsurf);
                break;
        case SHELL_SURFACE_NONE:
-               weston_surface_set_position(surface,
-                                           surface->geometry.x + sx,
-                                           surface->geometry.y + sy);
+               weston_view_set_position(shsurf->view,
+                                        shsurf->view->geometry.x + sx,
+                                        shsurf->view->geometry.y + sy);
                break;
        default:
                ;
        }
 
        /* surface stacking order, see also activate() */
-       switch (surface_type) {
+       switch (shsurf->type) {
        case SHELL_SURFACE_POPUP:
        case SHELL_SURFACE_TRANSIENT:
-               parent = shsurf->parent;
-               wl_list_insert(parent->layer_link.prev, &surface->layer_link);
+               /* TODO: Handle a parent with multiple views */
+               parent = get_default_view(shsurf->parent);
+               if (parent) {
+                       wl_list_remove(&shsurf->view->layer_link);
+                       wl_list_insert(parent->layer_link.prev,
+                                      &shsurf->view->layer_link);
+               }
                break;
        case SHELL_SURFACE_FULLSCREEN:
        case SHELL_SURFACE_NONE:
@@ -3599,17 +3689,20 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
        case SHELL_SURFACE_XWAYLAND:
        default:
                ws = get_current_workspace(shell);
-               wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
+               wl_list_remove(&shsurf->view->layer_link);
+               wl_list_insert(&ws->layer.view_list, &shsurf->view->layer_link);
                break;
        }
 
-       if (surface_type != SHELL_SURFACE_NONE) {
-               weston_surface_update_transform(surface);
-               if (surface_type == SHELL_SURFACE_MAXIMIZED)
-                       surface->output = shsurf->output;
+       if (shsurf->type != SHELL_SURFACE_NONE) {
+               weston_view_update_transform(shsurf->view);
+               if (shsurf->type == SHELL_SURFACE_MAXIMIZED) {
+                       shsurf->surface->output = shsurf->output;
+                       shsurf->view->output = shsurf->output;
+               }
        }
 
-       switch (surface_type) {
+       switch (shsurf->type) {
        /* XXX: xwayland's using the same fields for transient type */
        case SHELL_SURFACE_XWAYLAND:
        case SHELL_SURFACE_TRANSIENT:
@@ -3621,21 +3714,21 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
        case SHELL_SURFACE_MAXIMIZED:
                if (!shell->locked) {
                        wl_list_for_each(seat, &compositor->seat_list, link)
-                               activate(shell, surface, seat);
+                               activate(shell, shsurf->surface, seat);
                }
                break;
        default:
                break;
        }
 
-       if (surface_type == SHELL_SURFACE_TOPLEVEL)
+       if (shsurf->type == SHELL_SURFACE_TOPLEVEL)
        {
                switch (shell->win_animation_type) {
                case ANIMATION_FADE:
-                       weston_fade_run(surface, 0.0, 1.0, 300.0, NULL, NULL);
+                       weston_fade_run(shsurf->view, 0.0, 1.0, 300.0, NULL, NULL);
                        break;
                case ANIMATION_ZOOM:
-                       weston_zoom_run(surface, 0.5, 1.0, NULL, NULL);
+                       weston_zoom_run(shsurf->view, 0.5, 1.0, NULL, NULL);
                        break;
                default:
                        break;
@@ -3649,13 +3742,19 @@ configure(struct desktop_shell *shell, struct weston_surface *surface,
 {
        enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
        struct shell_surface *shsurf;
+       struct weston_view *view;
        int32_t surf_x, surf_y;
 
        shsurf = get_shell_surface(surface);
        if (shsurf)
                surface_type = shsurf->type;
 
-       weston_surface_configure(surface, x, y, width, height);
+       /* TODO:
+        * This should probably be changed to be more shell_surface
+        * dependent
+        */
+       wl_list_for_each(view, &surface->views, surface_link)
+               weston_view_configure(view, x, y, width, height);
 
        switch (surface_type) {
        case SHELL_SURFACE_FULLSCREEN:
@@ -3666,9 +3765,9 @@ configure(struct desktop_shell *shell, struct weston_surface *surface,
                /* setting x, y and using configure to change that geometry */
                surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
                                                                 NULL, NULL);
-               surface->geometry.x = surface->output->x - surf_x;
-               surface->geometry.y = surface->output->y +
-               get_output_panel_height(shell,surface->output) - surf_y;
+               shsurf->view->geometry.x = shsurf->output->x - surf_x;
+               shsurf->view->geometry.y = shsurf->output->y +
+                       get_output_panel_height(shell,shsurf->output) - surf_y;
                break;
        case SHELL_SURFACE_TOPLEVEL:
                break;
@@ -3678,7 +3777,8 @@ configure(struct desktop_shell *shell, struct weston_surface *surface,
 
        /* XXX: would a fullscreen surface need the same handling? */
        if (surface->output) {
-               weston_surface_update_transform(surface);
+               wl_list_for_each(view, &surface->views, surface_link)
+                       weston_view_update_transform(view);
 
                if (surface_type == SHELL_SURFACE_MAXIMIZED)
                        surface->output = shsurf->output;
@@ -3708,18 +3808,18 @@ shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32
        }
 
        if (!weston_surface_is_mapped(es)) {
-               map(shell, es, width, height, sx, sy);
+               map(shell, shsurf, width, height, sx, sy);
        } else if (type_changed || sx != 0 || sy != 0 ||
-                  es->geometry.width != width ||
-                  es->geometry.height != height) {
+                  shsurf->view->geometry.width != width ||
+                  shsurf->view->geometry.height != height) {
                float from_x, from_y;
                float to_x, to_y;
 
-               weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
-               weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
+               weston_view_to_global_float(shsurf->view, 0, 0, &from_x, &from_y);
+               weston_view_to_global_float(shsurf->view, sx, sy, &to_x, &to_y);
                configure(shell, es,
-                         es->geometry.x + to_x - from_x,
-                         es->geometry.y + to_y - from_y,
+                         shsurf->view->geometry.x + to_x - from_x,
+                         shsurf->view->geometry.y + to_y - from_y,
                          width, height);
        }
 }
@@ -3824,6 +3924,7 @@ static void
 screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
 {
        struct desktop_shell *shell = surface->configure_private;
+       struct weston_view *view;
 
        if (width == 0)
                return;
@@ -3832,12 +3933,13 @@ screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy, in
        if (!shell->locked)
                return;
 
-       center_on_output(surface, surface->output);
+       view = container_of(surface->views.next, struct weston_view, surface_link);
+       center_on_output(view, surface->output);
 
-       if (wl_list_empty(&surface->layer_link)) {
-               wl_list_insert(shell->lock_layer.surface_list.prev,
-                              &surface->layer_link);
-               weston_surface_update_transform(surface);
+       if (wl_list_empty(&view->layer_link)) {
+               wl_list_insert(shell->lock_layer.view_list.prev,
+                              &view->layer_link);
+               weston_view_update_transform(view);
                wl_event_source_timer_update(shell->screensaver.timer,
                                             shell->screensaver.duration);
                shell_fade(shell, FADE_IN);
@@ -3854,6 +3956,12 @@ screensaver_set_surface(struct wl_client *client,
        struct weston_surface *surface =
                wl_resource_get_user_data(surface_resource);
        struct weston_output *output = wl_resource_get_user_data(output_resource);
+       struct weston_view *view, *next;
+
+       /* Make sure we only have one view */
+       wl_list_for_each_safe(view, next, &surface->views, surface_link)
+               weston_view_destroy(view);
+       weston_view_create(surface);
 
        surface->configure = screensaver_configure;
        surface->configure_private = shell;
@@ -3915,23 +4023,21 @@ input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy, in
        fprintf(stderr, "%s panel: %d, output: %p\n", __FUNCTION__, ip_surface->panel, ip_surface->output);
 
        if (ip_surface->panel) {
-               x = shell->text_input.surface->geometry.x + shell->text_input.cursor_rectangle.x2;
-               y = shell->text_input.surface->geometry.y + shell->text_input.cursor_rectangle.y2;
+               x = get_default_view(shell->text_input.surface)->geometry.x + shell->text_input.cursor_rectangle.x2;
+               y = get_default_view(shell->text_input.surface)->geometry.y + shell->text_input.cursor_rectangle.y2;
        } else {
                x = ip_surface->output->x + (ip_surface->output->width - width) / 2;
                y = ip_surface->output->y + ip_surface->output->height - height;
        }
 
-       weston_surface_configure(surface,
-                                x, y,
-                                width, height);
+       weston_view_configure(ip_surface->view, x, y, width, height);
 
        if (show_surface) {
-               wl_list_insert(&shell->input_panel_layer.surface_list,
-                              &surface->layer_link);
-               weston_surface_update_transform(surface);
+               wl_list_insert(&shell->input_panel_layer.view_list,
+                              &ip_surface->view->layer_link);
+               weston_view_update_transform(ip_surface->view);
                weston_surface_damage(surface);
-               weston_slide_run(surface, surface->geometry.height, 0, NULL, NULL);
+               weston_slide_run(ip_surface->view, ip_surface->view->geometry.height, 0, NULL, NULL);
        }
 }
 
@@ -3944,6 +4050,7 @@ destroy_input_panel_surface(struct input_panel_surface *input_panel_surface)
        wl_list_remove(&input_panel_surface->link);
 
        input_panel_surface->surface->configure = NULL;
+       weston_view_destroy(input_panel_surface->view);
 
        free(input_panel_surface);
 }
@@ -3988,6 +4095,7 @@ create_input_panel_surface(struct desktop_shell *shell,
        input_panel_surface->shell = shell;
 
        input_panel_surface->surface = surface;
+       input_panel_surface->view = weston_view_create(surface);
 
        wl_signal_init(&input_panel_surface->destroy_signal);
        input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy;
@@ -4124,33 +4232,33 @@ struct switcher {
 static void
 switcher_next(struct switcher *switcher)
 {
-       struct weston_surface *surface;
+       struct weston_view *view;
        struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
        struct shell_surface *shsurf;
        struct workspace *ws = get_current_workspace(switcher->shell);
 
-       wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
-               switch (get_shell_surface_type(surface)) {
+       wl_list_for_each(view, &ws->layer.view_list, layer_link) {
+               switch (get_shell_surface_type(view->surface)) {
                case SHELL_SURFACE_TOPLEVEL:
                case SHELL_SURFACE_FULLSCREEN:
                case SHELL_SURFACE_MAXIMIZED:
                        if (first == NULL)
-                               first = surface;
+                               first = view->surface;
                        if (prev == switcher->current)
-                               next = surface;
-                       prev = surface;
-                       surface->alpha = 0.25;
-                       weston_surface_geometry_dirty(surface);
-                       weston_surface_damage(surface);
+                               next = view->surface;
+                       prev = view->surface;
+                       view->alpha = 0.25;
+                       weston_view_geometry_dirty(view);
+                       weston_surface_damage(view->surface);
                        break;
                default:
                        break;
                }
 
-               if (is_black_surface(surface, NULL)) {
-                       surface->alpha = 0.25;
-                       weston_surface_geometry_dirty(surface);
-                       weston_surface_damage(surface);
+               if (is_black_surface(view->surface, NULL)) {
+                       view->alpha = 0.25;
+                       weston_view_geometry_dirty(view);
+                       weston_surface_damage(view->surface);
                }
        }
 
@@ -4164,11 +4272,12 @@ switcher_next(struct switcher *switcher)
        wl_signal_add(&next->destroy_signal, &switcher->listener);
 
        switcher->current = next;
-       next->alpha = 1.0;
+       wl_list_for_each(view, &next->views, surface_link)
+               view->alpha = 1.0;
 
        shsurf = get_shell_surface(switcher->current);
        if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
-               shsurf->fullscreen.black_surface->alpha = 1.0;
+               shsurf->fullscreen.black_view->alpha = 1.0;
 }
 
 static void
@@ -4183,13 +4292,13 @@ switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
 static void
 switcher_destroy(struct switcher *switcher)
 {
-       struct weston_surface *surface;
+       struct weston_view *view;
        struct weston_keyboard *keyboard = switcher->grab.keyboard;
        struct workspace *ws = get_current_workspace(switcher->shell);
 
-       wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
-               surface->alpha = 1.0;
-               weston_surface_damage(surface);
+       wl_list_for_each(view, &ws->layer.view_list, layer_link) {
+               view->alpha = 1.0;
+               weston_surface_damage(view->surface);
        }
 
        if (switcher->current)
@@ -4638,6 +4747,7 @@ module_init(struct weston_compositor *ec,
        ec->ping_handler = ping_handler;
        ec->shell_interface.shell = shell;
        ec->shell_interface.create_shell_surface = create_shell_surface;
+       ec->shell_interface.get_primary_view = get_primary_view;
        ec->shell_interface.set_toplevel = set_toplevel;
        ec->shell_interface.set_transient = set_transient;
        ec->shell_interface.set_fullscreen = set_fullscreen;
index 935acc4..41cc52c 100644 (file)
@@ -25,7 +25,7 @@
 #include "compositor.h"
 
 WL_EXPORT void
-weston_surface_geometry_dirty(struct weston_surface *surface)
+weston_view_geometry_dirty(struct weston_view *view)
 {
 }
 
@@ -36,7 +36,7 @@ weston_log(const char *fmt, ...)
 }
 
 WL_EXPORT void
-weston_compositor_schedule_repaint(struct weston_compositor *compositor)
+weston_view_schedule_repaint(struct weston_view *view)
 {
 }
 
index b055ab2..5e92678 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <linux/input.h>
+#include <assert.h>
 
 #include "compositor.h"
 #include "tablet-shell-server-protocol.h"
@@ -124,27 +125,43 @@ tablet_shell_set_state(struct tablet_shell *shell, int state)
        shell->state = state;
 }
 
+static struct weston_view *
+get_surface_view(struct weston_surface *surface, int create)
+{
+       if (!surface)
+               return NULL;
+
+       if (wl_list_empty(&surface->views)) {
+               if (create)
+                       return weston_view_create(surface);
+               else
+                       return NULL;
+       }
+
+       return container_of(surface->views.next, struct weston_view, surface_link);
+}
+
 static void
 tablet_shell_surface_configure(struct weston_surface *surface,
                               int32_t sx, int32_t sy, int32_t width, int32_t height)
 {
        struct tablet_shell *shell = get_shell(surface->compositor);
+       struct weston_view *view = get_surface_view(surface, 0);
+       assert(view);
 
        if (weston_surface_is_mapped(surface) || width == 0)
                return;
 
-       weston_surface_configure(surface, 0, 0, width, height);
-
        if (surface == shell->lockscreen_surface) {
-                       wl_list_insert(&shell->lockscreen_layer.surface_list,
-                                       &surface->layer_link);
+               wl_list_insert(&shell->lockscreen_layer.view_list,
+                               &view->layer_link);
        } else if (surface == shell->switcher_surface) {
                /* */
        } else if (surface == shell->home_surface) {
                if (shell->state == STATE_STARTING) {
                        /* homescreen always visible, at the bottom */
-                       wl_list_insert(&shell->homescreen_layer.surface_list,
-                                       &surface->layer_link);
+                       wl_list_insert(&shell->homescreen_layer.view_list,
+                                       &view->layer_link);
 
                        tablet_shell_set_state(shell, STATE_LOCKED);
                        shell->previous_state = STATE_HOME;
@@ -155,12 +172,15 @@ tablet_shell_surface_configure(struct weston_surface *surface,
                   shell->current_client->client == wl_resource_get_client(surface->resource)) {
                tablet_shell_set_state(shell, STATE_TASK);
                shell->current_client->surface = surface;
-               weston_zoom_run(surface, 0.3, 1.0, NULL, NULL);
-               wl_list_insert(&shell->application_layer.surface_list,
-                              &surface->layer_link);
+               weston_zoom_run(view, 0.3, 1.0, NULL, NULL);
+               wl_list_insert(&shell->application_layer.view_list,
+                              &view->layer_link);
        }
 
-       weston_surface_update_transform(surface);
+       if (view) {
+               weston_view_configure(view, 0, 0, width, height);
+               weston_view_update_transform(view);
+       }
 }
 
 static void
@@ -181,10 +201,12 @@ tablet_shell_set_lockscreen(struct wl_client *client,
 {
        struct tablet_shell *shell = wl_resource_get_user_data(resource);
        struct weston_surface *es = wl_resource_get_user_data(surface_resource);
+       struct weston_view *view;
 
-       weston_surface_set_position(es, 0, 0);
+       view = weston_view_create(es);
+       weston_view_set_position(view, 0, 0);
        shell->lockscreen_surface = es;
-       shell->lockscreen_surface->configure = tablet_shell_surface_configure;
+       es->configure = tablet_shell_surface_configure;
        shell->lockscreen_listener.notify = handle_lockscreen_surface_destroy;
        wl_signal_add(&es->destroy_signal, &shell->lockscreen_listener);
 }
@@ -208,14 +230,16 @@ tablet_shell_set_switcher(struct wl_client *client,
 {
        struct tablet_shell *shell = wl_resource_get_user_data(resource);
        struct weston_surface *es = wl_resource_get_user_data(surface_resource);
+       struct weston_view *view;
 
        /* FIXME: Switcher should be centered and the compositor
         * should do the tinting of the background.  With the cache
         * layer idea, we should be able to hit the framerate on the
         * fade/zoom in. */
-       shell->switcher_surface = es;
-       weston_surface_set_position(shell->switcher_surface, 0, 0);
+       view = weston_view_create(es);
+       weston_view_set_position(view, 0, 0);
 
+       shell->switcher_surface = es;
        shell->switcher_listener.notify = handle_switcher_surface_destroy;
        wl_signal_add(&es->destroy_signal, &shell->switcher_listener);
 }
@@ -226,15 +250,18 @@ tablet_shell_set_homescreen(struct wl_client *client,
                            struct wl_resource *surface_resource)
 {
        struct tablet_shell *shell = wl_resource_get_user_data(resource);
+       struct weston_surface *es = wl_resource_get_user_data(surface_resource);
+       struct weston_view *view;
 
-       shell->home_surface = wl_resource_get_user_data(surface_resource);
-       shell->home_surface->configure = tablet_shell_surface_configure;
+       view = weston_view_create(es);
+       weston_view_set_position(view, 0, 0);
 
-       weston_surface_set_position(shell->home_surface, 0, 0);
+       shell->home_surface = es;
+       es->configure = tablet_shell_surface_configure;
 }
 
 static void
-minimize_zoom_done(struct weston_surface_animation *zoom, void *data)
+minimize_zoom_done(struct weston_view_animation *zoom, void *data)
 {
        struct tablet_shell *shell = data;
        struct weston_compositor *compositor = shell->compositor;
@@ -246,11 +273,12 @@ minimize_zoom_done(struct weston_surface_animation *zoom, void *data)
 
 static void
 tablet_shell_switch_to(struct tablet_shell *shell,
-                            struct weston_surface *surface)
+                      struct weston_surface *surface)
 {
        struct weston_compositor *compositor = shell->compositor;
        struct weston_seat *seat;
        struct weston_surface *current;
+       struct weston_view *view = get_surface_view(surface, 1);
 
        if (shell->state == STATE_SWITCHER) {
                wl_list_remove(&shell->switcher_listener.link);
@@ -262,15 +290,15 @@ tablet_shell_switch_to(struct tablet_shell *shell,
 
                if (shell->current_client && shell->current_client->surface) {
                        current = shell->current_client->surface;
-                       weston_zoom_run(current, 1.0, 0.3,
-                                     minimize_zoom_done, shell);
+                       weston_zoom_run(get_surface_view(current, 0), 1.0, 0.3,
+                                       minimize_zoom_done, shell);
                }
        } else {
-               fprintf(stderr, "switch to %p\n", surface);
+               fprintf(stderr, "switch to %p\n", view);
                wl_list_for_each(seat, &compositor->seat_list, link)
-                       weston_surface_activate(surface, seat);
+                       weston_surface_activate(view->surface, seat);
                tablet_shell_set_state(shell, STATE_TASK);
-               weston_zoom_run(surface, 0.3, 1.0, NULL, NULL);
+               weston_zoom_run(view, 0.3, 1.0, NULL, NULL);
        }
 }
 
index a889278..9c500e1 100644 (file)
@@ -124,6 +124,7 @@ struct weston_wm_window {
        cairo_surface_t *cairo_surface;
        struct weston_surface *surface;
        struct shell_surface *shsurf;
+       struct weston_view *view;
        struct wl_listener surface_destroy_listener;
        struct wl_event_source *repaint_source;
        struct wl_event_source *configure_source;
@@ -716,13 +717,13 @@ weston_wm_window_transform(struct wl_listener *listener, void *data)
        if (!window || !wm)
                return;
 
-       if (!weston_surface_is_mapped(surface))
+       if (!window->view || !weston_view_is_mapped(window->view))
                return;
 
-       if (window->x != surface->geometry.x ||
-           window->y != surface->geometry.y) {
-               values[0] = surface->geometry.x;
-               values[1] = surface->geometry.y;
+       if (window->x != window->view->geometry.x ||
+           window->y != window->view->geometry.y) {
+               values[0] = window->view->geometry.x;
+               values[1] = window->view->geometry.y;
                mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
 
                xcb_configure_window(wm->conn, window->frame_id, mask, values);
@@ -958,7 +959,8 @@ weston_wm_window_draw_decoration(void *data)
                                                  window->width + 2,
                                                  window->height + 2);
                }
-               weston_surface_geometry_dirty(window->surface);
+               if (window->view)
+                       weston_view_geometry_dirty(window->view);
        }
 
        if (window->surface && !window->fullscreen) {
@@ -986,7 +988,8 @@ weston_wm_window_schedule_repaint(struct weston_wm_window *window)
                                pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0,
                                                          width, height);
                        }
-                       weston_surface_geometry_dirty(window->surface);
+                       if (window->view)
+                               weston_view_geometry_dirty(window->view);
                }
                return;
        }
@@ -1177,8 +1180,8 @@ weston_wm_window_handle_moveresize(struct weston_wm_window *window,
        struct weston_shell_interface *shell_interface =
                &wm->server->compositor->shell_interface;
 
-       if (seat->pointer->button_count != 1 ||
-           seat->pointer->focus != window->surface)
+       if (seat->pointer->button_count != 1 || !window->view
+           || seat->pointer->focus != window->view)
                return;
 
        detail = client_message->data.data32[2];
@@ -2169,10 +2172,15 @@ xserver_map_shell_surface(struct weston_wm *wm,
        if (!shell_interface->create_shell_surface)
                return;
 
+       if (!shell_interface->get_primary_view)
+               return;
+
        window->shsurf = 
                shell_interface->create_shell_surface(shell_interface->shell,
                                                      window->surface,
                                                      &shell_client);
+       window->view = shell_interface->get_primary_view(shell_interface->shell,
+                                                        window->shsurf);
 
        if (window->name)
                shell_interface->set_title(window->shsurf, window->name);
index 220b2b6..962ed6d 100644 (file)
 #include "compositor.h"
 #include "text-cursor-position-server-protocol.h"
 
-struct text_cursor_position {
-       struct weston_compositor *ec;
-       struct wl_global *global;
-       struct wl_listener destroy_listener;
-};
-
-static void
-text_cursor_position_notify(struct wl_client *client,
-                           struct wl_resource *resource,
-                           struct wl_resource *surface_resource,
-                           wl_fixed_t x, wl_fixed_t y)
-{
-       struct weston_surface *surface =
-               wl_resource_get_user_data(surface_resource);
-
-       weston_text_cursor_position_notify(surface, x, y);
-}
-
-struct text_cursor_position_interface text_cursor_position_implementation = {
-       text_cursor_position_notify
-};
-
-static void
-bind_text_cursor_position(struct wl_client *client,
-            void *data, uint32_t version, uint32_t id)
-{
-       struct wl_resource *resource;
-
-       resource = wl_resource_create(client,
-                                     &text_cursor_position_interface, 1, id);
-       if (resource)
-               wl_resource_set_implementation(resource,
-                                              &text_cursor_position_implementation,
-                                              data, NULL);
-}
-
-static void
-text_cursor_position_notifier_destroy(struct wl_listener *listener, void *data)
-{
-       struct text_cursor_position *text_cursor_position =
-               container_of(listener, struct text_cursor_position, destroy_listener);
-
-       wl_global_destroy(text_cursor_position->global);
-       free(text_cursor_position);
-}
-
-void
-text_cursor_position_notifier_create(struct weston_compositor *ec)
-{
-       struct text_cursor_position *text_cursor_position;
-
-       text_cursor_position = malloc(sizeof *text_cursor_position);
-       if (text_cursor_position == NULL)
-               return;
-
-       text_cursor_position->ec = ec;
-
-       text_cursor_position->global =
-               wl_global_create(ec->wl_display,
-                                &text_cursor_position_interface, 1,
-                                text_cursor_position,
-                                bind_text_cursor_position);
-
-       text_cursor_position->destroy_listener.notify =
-               text_cursor_position_notifier_destroy;
-       wl_signal_add(&ec->destroy_signal, &text_cursor_position->destroy_listener);
-}
-
-WL_EXPORT void
-weston_text_cursor_position_notify(struct weston_surface *surface,
-                                               wl_fixed_t cur_pos_x,
-                                               wl_fixed_t cur_pos_y)
-{
-       struct weston_output *output;
-       wl_fixed_t global_x, global_y;
-
-       weston_surface_to_global_fixed(surface, cur_pos_x, cur_pos_y,
-                                               &global_x, &global_y);
-
-       wl_list_for_each(output, &surface->compositor->output_list, link)
-               if (output->zoom.active &&
-                   pixman_region32_contains_point(&output->region,
-                                               wl_fixed_to_int(global_x),
-                                               wl_fixed_to_int(global_y),
-                                               NULL)) {
-                       output->zoom.text_cursor.x = global_x;
-                       output->zoom.text_cursor.y = global_y;
-                       weston_output_update_zoom(output, ZOOM_FOCUS_TEXT);
-               }
-}
-
 static void
 weston_zoom_frame_z(struct weston_animation *animation,
                struct weston_output *output, uint32_t msecs)
@@ -176,12 +85,8 @@ weston_zoom_frame_xy(struct weston_animation *animation,
 
        if (weston_spring_done(&output->zoom.spring_xy)) {
                output->zoom.spring_xy.current = output->zoom.spring_xy.target;
-               output->zoom.current.x =
-                       output->zoom.type == ZOOM_FOCUS_POINTER ?
-                               seat->pointer->x : output->zoom.text_cursor.x;
-               output->zoom.current.y =
-                       output->zoom.type == ZOOM_FOCUS_POINTER ?
-                               seat->pointer->y : output->zoom.text_cursor.y;
+               output->zoom.current.x = seat->pointer->x;
+               output->zoom.current.y = seat->pointer->y;
                wl_list_remove(&animation->link);
                wl_list_init(&animation->link);
        }
@@ -251,7 +156,6 @@ weston_zoom_apply_output_transform(struct weston_output *output,
 static void
 weston_output_update_zoom_transform(struct weston_output *output)
 {
-       uint32_t type = output->zoom.type;
        float global_x, global_y;
        wl_fixed_t x = output->zoom.current.x;
        wl_fixed_t y = output->zoom.current.y;
@@ -265,8 +169,7 @@ weston_output_update_zoom_transform(struct weston_output *output)
            level == 0.0f)
                return;
 
-       if (type == ZOOM_FOCUS_POINTER &&
-                       wl_list_empty(&output->zoom.animation_xy.link))
+       if (wl_list_empty(&output->zoom.animation_xy.link))
                zoom_area_center_from_pointer(output, &x, &y);
 
        global_x = wl_fixed_to_double(x);
@@ -297,39 +200,8 @@ weston_output_update_zoom_transform(struct weston_output *output)
 }
 
 static void
-weston_zoom_transition(struct weston_output *output, uint32_t type,
-                                               wl_fixed_t x, wl_fixed_t y)
+weston_zoom_transition(struct weston_output *output, wl_fixed_t x, wl_fixed_t y)
 {
-       if (output->zoom.type != type) {
-               /* Set from/to points and start animation */
-               output->zoom.spring_xy.current = 0.0;
-               output->zoom.spring_xy.previous = 0.0;
-               output->zoom.spring_xy.target = 1.0;
-
-               if (wl_list_empty(&output->zoom.animation_xy.link)) {
-                       output->zoom.animation_xy.frame_counter = 0;
-                       wl_list_insert(output->animation_list.prev,
-                               &output->zoom.animation_xy.link);
-
-                       output->zoom.from.x = (type == ZOOM_FOCUS_TEXT) ?
-                                               x : output->zoom.text_cursor.x;
-                       output->zoom.from.y = (type == ZOOM_FOCUS_TEXT) ?
-                                               y : output->zoom.text_cursor.y;
-               } else {
-                       output->zoom.from.x = output->zoom.current.x;
-                       output->zoom.from.y = output->zoom.current.y;
-               }
-
-               output->zoom.to.x = (type == ZOOM_FOCUS_POINTER) ?
-                                               x : output->zoom.text_cursor.x;
-               output->zoom.to.y = (type == ZOOM_FOCUS_POINTER) ?
-                                               y : output->zoom.text_cursor.y;
-               output->zoom.current.x = output->zoom.from.x;
-               output->zoom.current.y = output->zoom.from.y;
-
-               output->zoom.type = type;
-       }
-
        if (output->zoom.level != output->zoom.spring_z.current) {
                output->zoom.spring_z.target = output->zoom.level;
                if (wl_list_empty(&output->zoom.animation_z.link)) {
@@ -344,7 +216,7 @@ weston_zoom_transition(struct weston_output *output, uint32_t type,
 }
 
 WL_EXPORT void
-weston_output_update_zoom(struct weston_output *output, uint32_t type)
+weston_output_update_zoom(struct weston_output *output)
 {
        struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
        wl_fixed_t x = seat->pointer->x;
@@ -352,27 +224,15 @@ weston_output_update_zoom(struct weston_output *output, uint32_t type)
 
        zoom_area_center_from_pointer(output, &x, &y);
 
-       if (type == ZOOM_FOCUS_POINTER) {
-               if (wl_list_empty(&output->zoom.animation_xy.link)) {
-                       output->zoom.current.x = seat->pointer->x;
-                       output->zoom.current.y = seat->pointer->y;
-               } else {
-                       output->zoom.to.x = x;
-                       output->zoom.to.y = y;
-               }
-       }
-
-       if (type == ZOOM_FOCUS_TEXT) {
-               if (wl_list_empty(&output->zoom.animation_xy.link)) {
-                       output->zoom.current.x = output->zoom.text_cursor.x;
-                       output->zoom.current.y = output->zoom.text_cursor.y;
-               } else {
-                       output->zoom.to.x = output->zoom.text_cursor.x;
-                       output->zoom.to.y = output->zoom.text_cursor.y;
-               }
+       if (wl_list_empty(&output->zoom.animation_xy.link)) {
+               output->zoom.current.x = seat->pointer->x;
+               output->zoom.current.y = seat->pointer->y;
+       } else {
+               output->zoom.to.x = x;
+               output->zoom.to.y = y;
        }
 
-       weston_zoom_transition(output, type, x, y);
+       weston_zoom_transition(output, x, y);
        weston_output_update_zoom_transform(output);
 }
 
@@ -385,7 +245,6 @@ weston_output_init_zoom(struct weston_output *output)
        output->zoom.level = 0.0;
        output->zoom.trans_x = 0.0;
        output->zoom.trans_y = 0.0;
-       output->zoom.type = ZOOM_FOCUS_POINTER;
        weston_spring_init(&output->zoom.spring_z, 250.0, 0.0, 0.0);
        output->zoom.spring_z.friction = 1000;
        output->zoom.animation_z.frame = weston_zoom_frame_z;
index 04b64d6..788e694 100644 (file)
@@ -29,39 +29,42 @@ surface_to_from_global(void *data)
 {
        struct weston_compositor *compositor = data;
        struct weston_surface *surface;
+       struct weston_view *view;
        float x, y;
        wl_fixed_t fx, fy;
        int32_t ix, iy;
 
        surface = weston_surface_create(compositor);
        assert(surface);
-       weston_surface_configure(surface, 5, 10, 50, 50);
-       weston_surface_update_transform(surface);
+       view = weston_view_create(surface);
+       assert(view);
+       weston_view_configure(view, 5, 10, 50, 50);
+       weston_view_update_transform(view);
 
-       weston_surface_to_global_float(surface, 33, 22, &x, &y);
+       weston_view_to_global_float(view, 33, 22, &x, &y);
        assert(x == 38 && y == 32);
 
-       weston_surface_to_global_float(surface, -8, -2, &x, &y);
+       weston_view_to_global_float(view, -8, -2, &x, &y);
        assert(x == -3 && y == 8);
 
-       weston_surface_to_global_fixed(surface, wl_fixed_from_int(12),
+       weston_view_to_global_fixed(view, wl_fixed_from_int(12),
                                       wl_fixed_from_int(5), &fx, &fy);
        assert(fx == wl_fixed_from_int(17) && fy == wl_fixed_from_int(15));
 
-       weston_surface_from_global_float(surface, 38, 32, &x, &y);
+       weston_view_from_global_float(view, 38, 32, &x, &y);
        assert(x == 33 && y == 22);
 
-       weston_surface_from_global_float(surface, 42, 5, &x, &y);
+       weston_view_from_global_float(view, 42, 5, &x, &y);
        assert(x == 37 && y == -5);
 
-       weston_surface_from_global_fixed(surface, wl_fixed_from_int(21),
+       weston_view_from_global_fixed(view, wl_fixed_from_int(21),
                                         wl_fixed_from_int(100), &fx, &fy);
        assert(fx == wl_fixed_from_int(16) && fy == wl_fixed_from_int(90));
 
-       weston_surface_from_global(surface, 0, 0, &ix, &iy);
+       weston_view_from_global(view, 0, 0, &ix, &iy);
        assert(ix == -5 && iy == -10);
 
-       weston_surface_from_global(surface, 5, 10, &ix, &iy);
+       weston_view_from_global(view, 5, 10, &ix, &iy);
        assert(ix == 0 && iy == 0);
 
        wl_display_terminate(compositor->wl_display);
index e8af2ed..4a8b2b2 100644 (file)
@@ -31,20 +31,23 @@ surface_transform(void *data)
 {
        struct weston_compositor *compositor = data;
        struct weston_surface *surface;
+       struct weston_view *view;
        float x, y;
 
        surface = weston_surface_create(compositor);
        assert(surface);
-       weston_surface_configure(surface, 100, 100, 200, 200);
-       weston_surface_update_transform(surface);
-       weston_surface_to_global_float(surface, 20, 20, &x, &y);
+       view = weston_view_create(surface);
+       assert(view);
+       weston_view_configure(view, 100, 100, 200, 200);
+       weston_view_update_transform(view);
+       weston_view_to_global_float(view, 20, 20, &x, &y);
 
        fprintf(stderr, "20,20 maps to %f, %f\n", x, y);
        assert(x == 120 && y == 120);
 
-       weston_surface_set_position(surface, 150, 300);
-       weston_surface_update_transform(surface);
-       weston_surface_to_global_float(surface, 50, 40, &x, &y);
+       weston_view_set_position(view, 150, 300);
+       weston_view_update_transform(view);
+       weston_view_to_global_float(view, 50, 40, &x, &y);
        assert(x == 200 && y == 340);
 
        wl_display_terminate(compositor->wl_display);
index a825d12..5f341d8 100644 (file)
@@ -36,6 +36,7 @@ struct weston_test {
 
 struct weston_test_surface {
        struct weston_surface *surface;
+       struct weston_view *view;
        int32_t x, y;
        struct weston_test *test;
 };
@@ -79,15 +80,16 @@ test_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy, i
        struct weston_test_surface *test_surface = surface->configure_private;
        struct weston_test *test = test_surface->test;
 
-       if (wl_list_empty(&surface->layer_link))
-               wl_list_insert(&test->layer.surface_list,
-                              &surface->layer_link);
+       if (wl_list_empty(&test_surface->view->layer_link))
+               wl_list_insert(&test->layer.view_list,
+                              &test_surface->view->layer_link);
 
-       weston_surface_configure(surface, test_surface->x, test_surface->y,
-                                width, height);
+       weston_view_configure(test_surface->view,
+                             test_surface->x, test_surface->y,
+                             width, height);
 
-       if (!weston_surface_is_mapped(surface))
-               weston_surface_update_transform(surface);
+       if (!weston_view_is_mapped(test_surface->view))
+               weston_view_update_transform(test_surface->view);
 }
 
 static void
@@ -99,13 +101,23 @@ move_surface(struct wl_client *client, struct wl_resource *resource,
                wl_resource_get_user_data(surface_resource);
        struct weston_test_surface *test_surface;
 
-       surface->configure = test_surface_configure;
-       if (surface->configure_private == NULL)
-               surface->configure_private = malloc(sizeof *test_surface);
        test_surface = surface->configure_private;
-       if (test_surface == NULL) {
-               wl_resource_post_no_memory(resource);
-               return;
+       if (!test_surface) {
+               test_surface = malloc(sizeof *test_surface);
+               if (!test_surface) {
+                       wl_resource_post_no_memory(resource);
+                       return;
+               }
+
+               test_surface->view = weston_view_create(surface);
+               if (!test_surface->view) {
+                       wl_resource_post_no_memory(resource);
+                       free(test_surface);
+                       return;
+               }
+
+               surface->configure_private = test_surface;
+               surface->configure = test_surface_configure;
        }
 
        test_surface->surface = surface;