diff options
author | emersion <contact@emersion.fr> | 2018-04-05 14:46:02 -0400 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-04-05 15:20:45 -0400 |
commit | 45f93e165096ed04c4d1152523502ae5fc760632 (patch) | |
tree | f10b226c06968591887ade9a7b485707078cb8b6 | |
parent | Configure wlr_xdg_output_manager during init (diff) | |
download | sway-45f93e165096ed04c4d1152523502ae5fc760632.tar.gz sway-45f93e165096ed04c4d1152523502ae5fc760632.tar.zst sway-45f93e165096ed04c4d1152523502ae5fc760632.zip |
Accumulate damage from subsurfaces
-rw-r--r-- | include/sway/tree/view.h | 33 | ||||
-rw-r--r-- | sway/tree/view.c | 112 |
2 files changed, 145 insertions, 0 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index d4dace4a..f8e41652 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -45,6 +45,12 @@ struct sway_view { | |||
45 | struct wlr_xwayland_surface *wlr_xwayland_surface; | 45 | struct wlr_xwayland_surface *wlr_xwayland_surface; |
46 | struct wlr_wl_shell_surface *wlr_wl_shell_surface; | 46 | struct wlr_wl_shell_surface *wlr_wl_shell_surface; |
47 | }; | 47 | }; |
48 | |||
49 | struct { | ||
50 | struct wl_signal unmap; | ||
51 | } events; | ||
52 | |||
53 | struct wl_listener surface_new_subsurface; | ||
48 | }; | 54 | }; |
49 | 55 | ||
50 | struct sway_xdg_shell_v6_view { | 56 | struct sway_xdg_shell_v6_view { |
@@ -95,6 +101,27 @@ struct sway_wl_shell_view { | |||
95 | int pending_width, pending_height; | 101 | int pending_width, pending_height; |
96 | }; | 102 | }; |
97 | 103 | ||
104 | struct sway_view_child; | ||
105 | |||
106 | struct sway_view_child_impl { | ||
107 | void (*destroy)(struct sway_view_child *child); | ||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * A view child is a surface in the view tree, such as a subsurface or a popup. | ||
112 | */ | ||
113 | struct sway_view_child { | ||
114 | const struct sway_view_child_impl *impl; | ||
115 | |||
116 | struct sway_view *view; | ||
117 | struct wlr_surface *surface; | ||
118 | |||
119 | struct wl_listener surface_commit; | ||
120 | struct wl_listener surface_new_subsurface; | ||
121 | struct wl_listener surface_destroy; | ||
122 | struct wl_listener view_unmap; | ||
123 | }; | ||
124 | |||
98 | const char *view_get_title(struct sway_view *view); | 125 | const char *view_get_title(struct sway_view *view); |
99 | 126 | ||
100 | const char *view_get_app_id(struct sway_view *view); | 127 | const char *view_get_app_id(struct sway_view *view); |
@@ -129,4 +156,10 @@ void view_update_position(struct sway_view *view, double ox, double oy); | |||
129 | 156 | ||
130 | void view_update_size(struct sway_view *view, int width, int height); | 157 | void view_update_size(struct sway_view *view, int width, int height); |
131 | 158 | ||
159 | void view_child_init(struct sway_view_child *child, | ||
160 | const struct sway_view_child_impl *impl, struct sway_view *view, | ||
161 | struct wlr_surface *surface); | ||
162 | |||
163 | void view_child_destroy(struct sway_view_child *child); | ||
164 | |||
132 | #endif | 165 | #endif |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 3927c195..85fd3093 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -11,6 +11,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, | |||
11 | const struct sway_view_impl *impl) { | 11 | const struct sway_view_impl *impl) { |
12 | view->type = type; | 12 | view->type = type; |
13 | view->impl = impl; | 13 | view->impl = impl; |
14 | wl_signal_init(&view->events.unmap); | ||
14 | } | 15 | } |
15 | 16 | ||
16 | void view_destroy(struct sway_view *view) { | 17 | void view_destroy(struct sway_view *view) { |
@@ -123,6 +124,20 @@ static void view_update_outputs(struct sway_view *view, | |||
123 | } | 124 | } |
124 | } | 125 | } |
125 | 126 | ||
127 | static void view_subsurface_create(struct sway_view *view, | ||
128 | struct wlr_subsurface *subsurface); | ||
129 | |||
130 | static void view_init_subsurfaces(struct sway_view *view, | ||
131 | struct wlr_surface *surface); | ||
132 | |||
133 | static void view_handle_surface_new_subsurface(struct wl_listener *listener, | ||
134 | void *data) { | ||
135 | struct sway_view *view = | ||
136 | wl_container_of(listener, view, surface_new_subsurface); | ||
137 | struct wlr_subsurface *subsurface = data; | ||
138 | view_subsurface_create(view, subsurface); | ||
139 | } | ||
140 | |||
126 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | 141 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { |
127 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { | 142 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { |
128 | return; | 143 | return; |
@@ -136,11 +151,18 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
136 | view->surface = wlr_surface; | 151 | view->surface = wlr_surface; |
137 | view->swayc = cont; | 152 | view->swayc = cont; |
138 | 153 | ||
154 | view_init_subsurfaces(view, wlr_surface); | ||
155 | wl_signal_add(&wlr_surface->events.new_subsurface, | ||
156 | &view->surface_new_subsurface); | ||
157 | view->surface_new_subsurface.notify = view_handle_surface_new_subsurface; | ||
158 | |||
139 | arrange_windows(cont->parent, -1, -1); | 159 | arrange_windows(cont->parent, -1, -1); |
140 | input_manager_set_focus(input_manager, cont); | 160 | input_manager_set_focus(input_manager, cont); |
141 | 161 | ||
142 | view_damage_whole(view); | 162 | view_damage_whole(view); |
143 | view_update_outputs(view, NULL); | 163 | view_update_outputs(view, NULL); |
164 | |||
165 | // TODO: create view children for subsurfaces | ||
144 | } | 166 | } |
145 | 167 | ||
146 | void view_unmap(struct sway_view *view) { | 168 | void view_unmap(struct sway_view *view) { |
@@ -148,6 +170,8 @@ void view_unmap(struct sway_view *view) { | |||
148 | return; | 170 | return; |
149 | } | 171 | } |
150 | 172 | ||
173 | wl_signal_emit(&view->events.unmap, view); | ||
174 | |||
151 | view_damage_whole(view); | 175 | view_damage_whole(view); |
152 | 176 | ||
153 | struct sway_container *parent = container_destroy(view->swayc); | 177 | struct sway_container *parent = container_destroy(view->swayc); |
@@ -185,3 +209,91 @@ void view_update_size(struct sway_view *view, int width, int height) { | |||
185 | view_update_outputs(view, &box); | 209 | view_update_outputs(view, &box); |
186 | view_damage_whole(view); | 210 | view_damage_whole(view); |
187 | } | 211 | } |
212 | |||
213 | |||
214 | static void view_subsurface_create(struct sway_view *view, | ||
215 | struct wlr_subsurface *subsurface) { | ||
216 | struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); | ||
217 | if (child == NULL) { | ||
218 | wlr_log(L_ERROR, "Allocation failed"); | ||
219 | return; | ||
220 | } | ||
221 | view_child_init(child, NULL, view, subsurface->surface); | ||
222 | } | ||
223 | |||
224 | static void view_child_handle_surface_commit(struct wl_listener *listener, | ||
225 | void *data) { | ||
226 | struct sway_view_child *child = | ||
227 | wl_container_of(listener, child, surface_commit); | ||
228 | // TODO: only accumulate damage from the child | ||
229 | view_damage_from(child->view); | ||
230 | } | ||
231 | |||
232 | static void view_child_handle_surface_new_subsurface( | ||
233 | struct wl_listener *listener, void *data) { | ||
234 | struct sway_view_child *child = | ||
235 | wl_container_of(listener, child, surface_new_subsurface); | ||
236 | struct wlr_subsurface *subsurface = data; | ||
237 | view_subsurface_create(child->view, subsurface); | ||
238 | } | ||
239 | |||
240 | static void view_child_handle_surface_destroy(struct wl_listener *listener, | ||
241 | void *data) { | ||
242 | struct sway_view_child *child = | ||
243 | wl_container_of(listener, child, surface_destroy); | ||
244 | view_child_destroy(child); | ||
245 | } | ||
246 | |||
247 | static void view_child_handle_view_unmap(struct wl_listener *listener, | ||
248 | void *data) { | ||
249 | struct sway_view_child *child = | ||
250 | wl_container_of(listener, child, view_unmap); | ||
251 | view_child_destroy(child); | ||
252 | } | ||
253 | |||
254 | static void view_init_subsurfaces(struct sway_view *view, | ||
255 | struct wlr_surface *surface) { | ||
256 | struct wlr_subsurface *subsurface; | ||
257 | wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { | ||
258 | view_subsurface_create(view, subsurface); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | void view_child_init(struct sway_view_child *child, | ||
263 | const struct sway_view_child_impl *impl, struct sway_view *view, | ||
264 | struct wlr_surface *surface) { | ||
265 | child->impl = impl; | ||
266 | child->view = view; | ||
267 | child->surface = surface; | ||
268 | |||
269 | wl_signal_add(&surface->events.commit, &child->surface_commit); | ||
270 | child->surface_commit.notify = view_child_handle_surface_commit; | ||
271 | wl_signal_add(&surface->events.new_subsurface, | ||
272 | &child->surface_new_subsurface); | ||
273 | child->surface_new_subsurface.notify = | ||
274 | view_child_handle_surface_new_subsurface; | ||
275 | wl_signal_add(&surface->events.destroy, &child->surface_destroy); | ||
276 | child->surface_destroy.notify = view_child_handle_surface_destroy; | ||
277 | wl_signal_add(&view->events.unmap, &child->view_unmap); | ||
278 | child->view_unmap.notify = view_child_handle_view_unmap; | ||
279 | |||
280 | view_init_subsurfaces(child->view, surface); | ||
281 | |||
282 | // TODO: only damage the whole child | ||
283 | view_damage_whole(child->view); | ||
284 | } | ||
285 | |||
286 | void view_child_destroy(struct sway_view_child *child) { | ||
287 | // TODO: only damage the whole child | ||
288 | view_damage_whole(child->view); | ||
289 | |||
290 | wl_list_remove(&child->surface_commit.link); | ||
291 | wl_list_remove(&child->surface_destroy.link); | ||
292 | wl_list_remove(&child->view_unmap.link); | ||
293 | |||
294 | if (child->impl && child->impl->destroy) { | ||
295 | child->impl->destroy(child); | ||
296 | } else { | ||
297 | free(child); | ||
298 | } | ||
299 | } | ||