commit d95b817

Michael Forney  ·  2014-02-08 07:28:55 +0000 UTC
parent 3333dfd
view: Make view implementations explicitly change view state

This way, the framebuffer plane can keep a constant size (even if an
oversized buffer is attached). Additionally this enables some tricks for
ensuring smooth move+resize (common operation for tiling window
managers).
8 files changed,  +117, -114
+29, -21
  1@@ -68,6 +68,9 @@ struct view
  2     struct swc_surface * surface;
  3     struct wld_buffer * buffer;
  4 
  5+    /* Whether or not the view is visible (mapped). */
  6+    bool visible;
  7+
  8     /* The box that the surface covers (including it's border). */
  9     pixman_box32_t extents;
 10 
 11@@ -426,12 +429,14 @@ static void schedule_updates(uint32_t screens)
 12     compositor.scheduled_updates |= screens;
 13 }
 14 
 15-static bool update(struct swc_view * view)
 16+static bool update(struct swc_view * base)
 17 {
 18+    struct view * view = (void *) base;
 19+
 20     if (!compositor.active || !view->visible)
 21         return false;
 22 
 23-    schedule_updates(view->screens);
 24+    schedule_updates(view->base.screens);
 25 
 26     return true;
 27 }
 28@@ -443,38 +448,36 @@ static bool attach(struct swc_view * base, struct wld_buffer * buffer)
 29     if (!renderer_attach(view, buffer))
 30         return false;
 31 
 32-    return true;
 33-}
 34-
 35-static bool move(struct swc_view * base, int32_t x, int32_t y)
 36-{
 37-    struct view * view = (void *) base;
 38-
 39-    if (view->base.visible)
 40+    if (view->visible && view->base.buffer)
 41     {
 42         damage_below_view(view);
 43         update(&view->base);
 44     }
 45 
 46+    swc_view_set_size_from_buffer(&view->base, buffer);
 47+
 48     return true;
 49 }
 50 
 51-static void resize(struct swc_view * base)
 52+static bool move(struct swc_view * base, int32_t x, int32_t y)
 53 {
 54     struct view * view = (void *) base;
 55 
 56-    if (view->base.visible)
 57+    if (view->visible)
 58     {
 59         damage_below_view(view);
 60         update(&view->base);
 61     }
 62+
 63+    swc_view_set_position(&view->base, x, y);
 64+
 65+    return true;
 66 }
 67 
 68 const static struct swc_view_impl view_impl = {
 69     .update = &update,
 70     .attach = &attach,
 71-    .move = &move,
 72-    .resize = &resize,
 73+    .move = &move
 74 };
 75 
 76 static void handle_view_event(struct wl_listener * listener, void * data)
 77@@ -487,22 +490,24 @@ static void handle_view_event(struct wl_listener * listener, void * data)
 78         case SWC_VIEW_EVENT_MOVED:
 79             update_extents(view);
 80 
 81-            if (view->base.visible)
 82+            if (view->visible)
 83             {
 84                 /* Assume worst-case no clipping until we draw the next frame (in case
 85                  * the surface gets moved again before that). */
 86                 pixman_region32_init(&view->clip);
 87 
 88                 damage_below_view(view);
 89+                swc_view_update_screens(&view->base);
 90                 update(&view->base);
 91             }
 92             break;
 93         case SWC_VIEW_EVENT_RESIZED:
 94             update_extents(view);
 95 
 96-            if (view->base.visible)
 97+            if (view->visible)
 98             {
 99                 damage_below_view(view);
100+                swc_view_update_screens(&view->base);
101                 update(&view->base);
102             }
103             break;
104@@ -519,11 +524,11 @@ bool swc_compositor_add_surface(struct swc_surface * surface)
105         return false;
106 
107     swc_view_initialize(&view->base, &view_impl);
108-    view->base.visible = false;
109     view->event_listener.notify = &handle_view_event;
110     wl_signal_add(&view->base.event_signal, &view->event_listener);
111     view->surface = surface;
112     view->buffer = NULL;
113+    view->visible = false;
114     view->extents.x1 = 0;
115     view->extents.y1 = 0;
116     view->extents.x2 = 0;
117@@ -560,7 +565,7 @@ void swc_compositor_surface_show(struct swc_surface * surface)
118     if (view->base.impl != &view_impl)
119         return;
120 
121-    if (view->base.visible)
122+    if (view->visible)
123         return;
124 
125     printf("showing surface %u\n", wl_resource_get_id(surface->resource));
126@@ -569,8 +574,10 @@ void swc_compositor_surface_show(struct swc_surface * surface)
127      * surface gets moved before that. */
128     pixman_region32_clear(&view->clip);
129 
130+    view->visible = true;
131+    swc_view_update_screens(&view->base);
132+
133     damage_view(view);
134-    swc_view_set_visibility(&view->base, true);
135     update(&view->base);
136     wl_list_insert(&compositor.views, &view->link);
137 }
138@@ -582,15 +589,16 @@ void swc_compositor_surface_hide(struct swc_surface * surface)
139     if (view->base.impl != &view_impl)
140         return;
141 
142-    if (!view->base.visible)
143+    if (!view->visible)
144         return;
145 
146     /* Update all the outputs the surface was on. */
147     update(&view->base);
148 
149     damage_below_view(view);
150-    swc_view_set_visibility(&view->base, false);
151     wl_list_remove(&view->link);
152+    swc_view_set_screens(&view->base, 0);
153+    view->visible = false;
154 }
155 
156 void swc_compositor_surface_set_border_width(struct swc_surface * surface,
+8, -3
 1@@ -68,6 +68,8 @@ static bool attach(struct swc_view * view, struct wld_buffer * buffer)
 2         }
 3     }
 4 
 5+    swc_view_set_size_from_buffer(view, buffer);
 6+
 7     return true;
 8 }
 9 
10@@ -76,13 +78,14 @@ static bool move(struct swc_view * view, int32_t x, int32_t y)
11     struct swc_cursor_plane * plane = CONTAINER_OF(view, typeof(*plane), view);
12 
13     if (drmModeMoveCursor(swc.drm->fd, plane->crtc,
14-                          x - view->screen->base.geometry.x,
15-                          y - view->screen->base.geometry.y) != 0)
16+                          x - plane->origin->x, y - plane->origin->y) != 0)
17     {
18         ERROR("Could not move cursor: %s\n", strerror(errno));
19         return false;
20     }
21 
22+    swc_view_set_position(view, x, y);
23+
24     return true;
25 }
26 
27@@ -107,11 +110,13 @@ static void handle_launch_event(struct wl_listener * listener, void * data)
28     }
29 }
30 
31-bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, uint32_t crtc)
32+bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, uint32_t crtc,
33+                                 const struct swc_rectangle * origin)
34 {
35     if (drmModeSetCursor(swc.drm->fd, crtc, 0, 0, 0) != 0)
36         return false;
37 
38+    plane->origin = origin;
39     plane->crtc = crtc;
40     plane->launch_listener.notify = &handle_launch_event;
41     wl_signal_add(&swc.launch->event_signal, &plane->launch_listener);
+3, -2
 1@@ -29,12 +29,13 @@
 2 struct swc_cursor_plane
 3 {
 4     struct swc_view view;
 5+    const struct swc_rectangle * origin;
 6     uint32_t crtc;
 7     struct wl_listener launch_listener;
 8 };
 9 
10-bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane,
11-                                 uint32_t crtc);
12+bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, uint32_t crtc,
13+                                 const struct swc_rectangle * origin);
14 
15 void swc_cursor_plane_finalize(struct swc_cursor_plane * plane);
16 
+2, -0
1@@ -148,6 +148,8 @@ static bool attach(struct swc_view * view, struct wld_buffer * buffer)
2 
3 static bool move(struct swc_view * view, int32_t x, int32_t y)
4 {
5+    swc_view_set_position(view, x, y);
6+
7     return true;
8 }
9 
+9, -0
 1@@ -104,11 +104,15 @@ static bool attach(struct swc_view * view, struct wld_buffer * buffer)
 2 
 3     /* TODO: Send an early release to the buffer */
 4 
 5+    swc_view_set_size_from_buffer(view, buffer);
 6+
 7     return true;
 8 }
 9 
10 static bool move(struct swc_view * view, int32_t x, int32_t y)
11 {
12+    swc_view_set_position(view, x, y);
13+
14     return true;
15 }
16 
17@@ -135,6 +139,11 @@ static void handle_view_event(struct wl_listener * listener, void * data)
18                 swc_view_move(&screen->planes.cursor.view,
19                               view->geometry.x, view->geometry.y);
20             }
21+
22+            swc_view_update_screens(view);
23+            break;
24+        case SWC_VIEW_EVENT_RESIZED:
25+            swc_view_update_screens(view);
26             break;
27         case SWC_VIEW_EVENT_SCREENS_CHANGED:
28             wl_list_for_each(screen, &swc.screens, link)
+2, -4
 1@@ -80,15 +80,13 @@ struct screen * screen_new(uint32_t crtc, struct swc_output * output)
 2         goto error1;
 3     }
 4 
 5-    if (!swc_cursor_plane_initialize(&screen->planes.cursor, crtc))
 6+    if (!swc_cursor_plane_initialize(&screen->planes.cursor, crtc,
 7+                                     &screen->base.geometry))
 8     {
 9         ERROR("Failed to initialize cursor plane\n");
10         goto error2;
11     }
12 
13-    screen->planes.framebuffer.view.screen = screen;
14-    screen->planes.cursor.view.screen = screen;
15-
16     swc_view_move(&screen->planes.framebuffer.view, x, 0);
17     screen->base.geometry = screen->planes.framebuffer.view.geometry;
18     screen->base.usable_geometry = screen->base.geometry;
+54, -57
  1@@ -29,53 +29,10 @@
  2 
  3 #include <wld/wld.h>
  4 
  5-static void update_screens(struct swc_view * view)
  6-{
  7-    struct swc_view_event_data data = { .view = view };
  8-    uint32_t old = view->screens, new = 0;
  9-    struct screen * screen;
 10-
 11-    if (view->visible)
 12-    {
 13-        wl_list_for_each(screen, &swc.screens, link)
 14-        {
 15-            if (swc_rectangle_overlap(&screen->base.geometry, &view->geometry))
 16-                new |= screen_mask(screen);
 17-        }
 18-    }
 19-
 20-    if (new == old)
 21-        return;
 22-
 23-    view->screens = new;
 24-
 25-    data.screens_changed.entered = new & ~old;
 26-    data.screens_changed.left = old & ~new;
 27-    swc_send_event(&view->event_signal, SWC_VIEW_EVENT_SCREENS_CHANGED, &data);
 28-}
 29-
 30-static void set_size(struct swc_view * view, uint32_t width, uint32_t height)
 31-{
 32-    if (view->geometry.width != width || view->geometry.height != height)
 33-    {
 34-        struct swc_view_event_data data = { .view = view };
 35-
 36-        if (view->impl->resize)
 37-            view->impl->resize(view);
 38-
 39-        view->geometry.width = width;
 40-        view->geometry.height = height;
 41-        update_screens(view);
 42-
 43-        swc_send_event(&view->event_signal, SWC_VIEW_EVENT_RESIZED, &data);
 44-    }
 45-}
 46-
 47 void swc_view_initialize(struct swc_view * view,
 48                          const struct swc_view_impl * impl)
 49 {
 50     view->impl = impl;
 51-    view->visible = true;
 52     view->geometry.x = 0;
 53     view->geometry.y = 0;
 54     view->geometry.width = 0;
 55@@ -99,12 +56,7 @@ bool swc_view_attach(struct swc_view * view, struct wld_buffer * buffer)
 56             wld_buffer_unreference(view->buffer);
 57 
 58         if (buffer)
 59-        {
 60             wld_buffer_reference(buffer);
 61-            set_size(view, buffer->width, buffer->height);
 62-        }
 63-        else
 64-            set_size(view, 0, 0);
 65 
 66         view->buffer = buffer;
 67         return true;
 68@@ -119,27 +71,72 @@ bool swc_view_update(struct swc_view * view)
 69 }
 70 
 71 bool swc_view_move(struct swc_view * view, int32_t x, int32_t y)
 72+{
 73+    return view->impl->move(view, x, y);
 74+}
 75+
 76+void swc_view_set_position(struct swc_view * view, int32_t x, int32_t y)
 77 {
 78     struct swc_view_event_data data = { .view = view };
 79 
 80     if (x == view->geometry.x && y == view->geometry.y)
 81-        return true;
 82-
 83-    if (!view->impl->move || !view->impl->move(view, x, y))
 84-        return false;
 85+        return;
 86 
 87     view->geometry.x = x;
 88     view->geometry.y = y;
 89-    update_screens(view);
 90     swc_send_event(&view->event_signal, SWC_VIEW_EVENT_MOVED, &data);
 91+}
 92+
 93+void swc_view_set_size(struct swc_view * view, uint32_t width, uint32_t height)
 94+{
 95+    struct swc_view_event_data data = { .view = view };
 96+
 97+    if (view->geometry.width == width && view->geometry.height == height)
 98+        return;
 99+
100+    view->geometry.width = width;
101+    view->geometry.height = height;
102+    swc_send_event(&view->event_signal, SWC_VIEW_EVENT_RESIZED, &data);
103+}
104+
105+void swc_view_set_size_from_buffer(struct swc_view * view,
106+                                   struct wld_buffer * buffer)
107+{
108+    if (buffer)
109+        swc_view_set_size(view, buffer->width, buffer->height);
110+    else
111+        swc_view_set_size(view, 0, 0);
112+}
113+
114+void swc_view_set_screens(struct swc_view * view, uint32_t screens)
115+{
116+    if (view->screens == screens)
117+        return;
118+
119+    struct swc_view_event_data data = {
120+        .view = view,
121+        .screens_changed = {
122+            .entered = screens & ~view->screens,
123+            .left = view->screens & ~screens
124+        }
125+    };
126 
127-    return true;
128+    view->screens = screens;
129+    swc_send_event(&view->event_signal, SWC_VIEW_EVENT_SCREENS_CHANGED, &data);
130 }
131 
132-void swc_view_set_visibility(struct swc_view * view, bool visible)
133+void swc_view_update_screens(struct swc_view * view)
134 {
135-    view->visible = visible;
136-    update_screens(view);
137+    uint32_t screens = 0;
138+    struct screen * screen;
139+
140+    wl_list_for_each(screen, &swc.screens, link)
141+    {
142+        if (swc_rectangle_overlap(&screen->base.geometry, &view->geometry))
143+            screens |= screen_mask(screen);
144+    }
145+
146+    swc_view_set_screens(view, screens);
147 }
148 
149 void swc_view_frame(struct swc_view * view, uint32_t time)
+10, -27
 1@@ -34,8 +34,7 @@ enum
 2     /* Sent when the origin of the view has moved. */
 3     SWC_VIEW_EVENT_MOVED,
 4 
 5-    /* Sent when the view's size changes. This occurs when a buffer of
 6-     * different dimensions is attached to the view. */
 7+    /* Sent when the view's size changes. */
 8     SWC_VIEW_EVENT_RESIZED,
 9 
10     /* Sent when the set of screens the view is visible on changes. */
11@@ -82,16 +81,8 @@ struct swc_view
12     const struct swc_view_impl * impl;
13 
14     struct wl_signal event_signal;
15-    bool visible;
16-    uint32_t screens;
17-
18     struct swc_rectangle geometry;
19-
20-    /**
21-     * The screen that the view belongs to (for example if framebuffer or
22-     * cursor plane), or NULL.
23-     */
24-    struct screen * screen;
25+    uint32_t screens;
26 
27     struct wld_buffer * buffer;
28 };
29@@ -106,14 +97,6 @@ struct swc_view_impl
30     bool (* update)(struct swc_view * view);
31     bool (* attach)(struct swc_view * view, struct wld_buffer * buffer);
32     bool (* move)(struct swc_view * view, int32_t x, int32_t y);
33-
34-    /**
35-     * This function indicates to the view that it is about to be resized.
36-     *
37-     * The view can use this function to do any necessary damage calculations
38-     * with the geometry of the view before the resize occurs.
39-     */
40-    void (* resize)(struct swc_view * view);
41 };
42 
43 /**
44@@ -150,14 +133,14 @@ bool swc_view_update(struct swc_view * view);
45  */
46 bool swc_view_move(struct swc_view * view, int32_t x, int32_t y);
47 
48-/**
49- * Set the visibility flag of the view.
50- *
51- * This retains the view's geometry, but indicates that it will not be shown
52- * when the next frame is finished. This is useful when an unmapped or
53- * minimized state is desired.
54- */
55-void swc_view_set_visibility(struct swc_view * view, bool visible);
56+/**** For internal view use only ****/
57+
58+void swc_view_set_position(struct swc_view * view, int32_t x, int32_t y);
59+void swc_view_set_size(struct swc_view * view, uint32_t width, uint32_t height);
60+void swc_view_set_size_from_buffer(struct swc_view * view,
61+                                   struct wld_buffer * bufer);
62+void swc_view_set_screens(struct swc_view * view, uint32_t screens);
63+void swc_view_update_screens(struct swc_view * view);
64 
65 /**
66  * Send a new frame event through the view's event signal.