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.