diff options
-rw-r--r-- | include/sway/desktop/transaction.h | 5 | ||||
-rw-r--r-- | include/sway/tree/container.h | 7 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 99 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 5 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 5 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 2 | ||||
-rw-r--r-- | sway/tree/container.c | 6 | ||||
-rw-r--r-- | sway/tree/root.c | 2 |
8 files changed, 51 insertions, 80 deletions
diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index 56361d94..7ac924e7 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h | |||
@@ -20,6 +20,8 @@ | |||
20 | * create and commits a transaction from the dirty containers. | 20 | * create and commits a transaction from the dirty containers. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | struct sway_transaction_instruction; | ||
24 | |||
23 | /** | 25 | /** |
24 | * Find all dirty containers, create and commit a transaction containing them, | 26 | * Find all dirty containers, create and commit a transaction containing them, |
25 | * and unmark them as dirty. | 27 | * and unmark them as dirty. |
@@ -31,7 +33,8 @@ void transaction_commit_dirty(void); | |||
31 | * | 33 | * |
32 | * When all views in the transaction are ready, the layout will be applied. | 34 | * When all views in the transaction are ready, the layout will be applied. |
33 | */ | 35 | */ |
34 | void transaction_notify_view_ready(struct sway_view *view, uint32_t serial); | 36 | void transaction_notify_view_ready_by_serial(struct sway_view *view, |
37 | uint32_t serial); | ||
35 | 38 | ||
36 | /** | 39 | /** |
37 | * Notify the transaction system that a view is ready for the new layout, but | 40 | * Notify the transaction system that a view is ready for the new layout, but |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 2a22f196..b64a2e63 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -151,7 +151,12 @@ struct sway_container { | |||
151 | struct wlr_texture *title_urgent; | 151 | struct wlr_texture *title_urgent; |
152 | size_t title_height; | 152 | size_t title_height; |
153 | 153 | ||
154 | list_t *instructions; // struct sway_transaction_instruction * | 154 | // The number of transactions which reference this container. |
155 | size_t ntxnrefs; | ||
156 | |||
157 | // If this container is a view and is waiting for the client to respond to a | ||
158 | // configure then this will be populated, otherwise NULL. | ||
159 | struct sway_transaction_instruction *instruction; | ||
155 | 160 | ||
156 | bool destroying; | 161 | bool destroying; |
157 | 162 | ||
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index a449ffaa..c08730ce 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c | |||
@@ -43,12 +43,14 @@ struct sway_transaction_instruction { | |||
43 | struct sway_container *container; | 43 | struct sway_container *container; |
44 | struct sway_container_state state; | 44 | struct sway_container_state state; |
45 | uint32_t serial; | 45 | uint32_t serial; |
46 | bool ready; | ||
47 | }; | 46 | }; |
48 | 47 | ||
49 | static struct sway_transaction *transaction_create() { | 48 | static struct sway_transaction *transaction_create() { |
50 | struct sway_transaction *transaction = | 49 | struct sway_transaction *transaction = |
51 | calloc(1, sizeof(struct sway_transaction)); | 50 | calloc(1, sizeof(struct sway_transaction)); |
51 | if (!sway_assert(transaction, "Unable to allocate transaction")) { | ||
52 | return NULL; | ||
53 | } | ||
52 | transaction->instructions = create_list(); | 54 | transaction->instructions = create_list(); |
53 | if (server.debug_txn_timings) { | 55 | if (server.debug_txn_timings) { |
54 | clock_gettime(CLOCK_MONOTONIC, &transaction->create_time); | 56 | clock_gettime(CLOCK_MONOTONIC, &transaction->create_time); |
@@ -62,13 +64,11 @@ static void transaction_destroy(struct sway_transaction *transaction) { | |||
62 | struct sway_transaction_instruction *instruction = | 64 | struct sway_transaction_instruction *instruction = |
63 | transaction->instructions->items[i]; | 65 | transaction->instructions->items[i]; |
64 | struct sway_container *con = instruction->container; | 66 | struct sway_container *con = instruction->container; |
65 | for (int j = 0; j < con->instructions->length; ++j) { | 67 | con->ntxnrefs--; |
66 | if (con->instructions->items[j] == instruction) { | 68 | if (con->instruction == instruction) { |
67 | list_del(con->instructions, j); | 69 | con->instruction = NULL; |
68 | break; | ||
69 | } | ||
70 | } | 70 | } |
71 | if (con->destroying && !con->instructions->length) { | 71 | if (con->destroying && con->ntxnrefs == 0) { |
72 | container_free(con); | 72 | container_free(con); |
73 | } | 73 | } |
74 | free(instruction); | 74 | free(instruction); |
@@ -130,12 +130,16 @@ static void transaction_add_container(struct sway_transaction *transaction, | |||
130 | struct sway_container *container) { | 130 | struct sway_container *container) { |
131 | struct sway_transaction_instruction *instruction = | 131 | struct sway_transaction_instruction *instruction = |
132 | calloc(1, sizeof(struct sway_transaction_instruction)); | 132 | calloc(1, sizeof(struct sway_transaction_instruction)); |
133 | if (!sway_assert(instruction, "Unable to allocate instruction")) { | ||
134 | return; | ||
135 | } | ||
133 | instruction->transaction = transaction; | 136 | instruction->transaction = transaction; |
134 | instruction->container = container; | 137 | instruction->container = container; |
135 | 138 | ||
136 | copy_pending_state(container, &instruction->state); | 139 | copy_pending_state(container, &instruction->state); |
137 | 140 | ||
138 | list_add(transaction->instructions, instruction); | 141 | list_add(transaction->instructions, instruction); |
142 | container->ntxnrefs++; | ||
139 | } | 143 | } |
140 | 144 | ||
141 | /** | 145 | /** |
@@ -195,21 +199,11 @@ static void transaction_apply(struct sway_transaction *transaction) { | |||
195 | memcpy(&container->current, &instruction->state, | 199 | memcpy(&container->current, &instruction->state, |
196 | sizeof(struct sway_container_state)); | 200 | sizeof(struct sway_container_state)); |
197 | 201 | ||
198 | if (container->type == C_VIEW) { | 202 | if (container->type == C_VIEW && container->sway_view->saved_buffer) { |
199 | if (container->destroying) { | 203 | view_remove_saved_buffer(container->sway_view); |
200 | if (container->instructions->length == 1 && | ||
201 | container->sway_view->saved_buffer) { | ||
202 | view_remove_saved_buffer(container->sway_view); | ||
203 | } | ||
204 | } else { | ||
205 | if (container->sway_view->saved_buffer) { | ||
206 | view_remove_saved_buffer(container->sway_view); | ||
207 | } | ||
208 | if (container->instructions->length > 1) { | ||
209 | view_save_buffer(container->sway_view); | ||
210 | } | ||
211 | } | ||
212 | } | 204 | } |
205 | |||
206 | container->instruction = NULL; | ||
213 | } | 207 | } |
214 | } | 208 | } |
215 | 209 | ||
@@ -269,20 +263,8 @@ static bool should_configure(struct sway_container *con, | |||
269 | if (con->destroying) { | 263 | if (con->destroying) { |
270 | return false; | 264 | return false; |
271 | } | 265 | } |
272 | // The settled dimensions are what size the view will be once any pending | 266 | if (con->current.view_width == instruction->state.view_width && |
273 | // configures have applied (excluding the one we might be configuring now). | 267 | con->current.view_height == instruction->state.view_height) { |
274 | // If these match the dimensions that this transaction wants then we don't | ||
275 | // need to configure it. | ||
276 | int settled_width = con->current.view_width; | ||
277 | int settled_height = con->current.view_height; | ||
278 | if (con->instructions->length) { | ||
279 | struct sway_transaction_instruction *last_instruction = | ||
280 | con->instructions->items[con->instructions->length - 1]; | ||
281 | settled_width = last_instruction->state.view_width; | ||
282 | settled_height = last_instruction->state.view_height; | ||
283 | } | ||
284 | if (settled_width == instruction->state.view_width && | ||
285 | settled_height == instruction->state.view_height) { | ||
286 | return false; | 268 | return false; |
287 | } | 269 | } |
288 | return true; | 270 | return true; |
@@ -312,10 +294,10 @@ static void transaction_commit(struct sway_transaction *transaction) { | |||
312 | struct timespec when; | 294 | struct timespec when; |
313 | wlr_surface_send_frame_done(con->sway_view->surface, &when); | 295 | wlr_surface_send_frame_done(con->sway_view->surface, &when); |
314 | } | 296 | } |
315 | if (con->type == C_VIEW && !con->sway_view->saved_buffer) { | 297 | if (con->type == C_VIEW) { |
316 | view_save_buffer(con->sway_view); | 298 | view_save_buffer(con->sway_view); |
317 | } | 299 | } |
318 | list_add(con->instructions, instruction); | 300 | con->instruction = instruction; |
319 | } | 301 | } |
320 | transaction->num_configures = transaction->num_waiting; | 302 | transaction->num_configures = transaction->num_waiting; |
321 | if (server.debug_txn_timings) { | 303 | if (server.debug_txn_timings) { |
@@ -347,7 +329,6 @@ static void transaction_commit(struct sway_transaction *transaction) { | |||
347 | 329 | ||
348 | static void set_instruction_ready( | 330 | static void set_instruction_ready( |
349 | struct sway_transaction_instruction *instruction) { | 331 | struct sway_transaction_instruction *instruction) { |
350 | instruction->ready = true; | ||
351 | struct sway_transaction *transaction = instruction->transaction; | 332 | struct sway_transaction *transaction = instruction->transaction; |
352 | 333 | ||
353 | if (server.debug_txn_timings) { | 334 | if (server.debug_txn_timings) { |
@@ -371,44 +352,25 @@ static void set_instruction_ready( | |||
371 | wl_event_source_timer_update(transaction->timer, 0); | 352 | wl_event_source_timer_update(transaction->timer, 0); |
372 | } | 353 | } |
373 | } | 354 | } |
374 | } | ||
375 | 355 | ||
376 | /** | 356 | instruction->container->instruction = NULL; |
377 | * Mark all of the view's instructions as ready up to and including the | ||
378 | * instruction at the given index. This allows the view to skip a configure. | ||
379 | */ | ||
380 | static void set_instructions_ready(struct sway_view *view, int index) { | ||
381 | for (int i = 0; i <= index; ++i) { | ||
382 | struct sway_transaction_instruction *instruction = | ||
383 | view->swayc->instructions->items[i]; | ||
384 | if (!instruction->ready) { | ||
385 | set_instruction_ready(instruction); | ||
386 | } | ||
387 | } | ||
388 | transaction_progress_queue(); | 357 | transaction_progress_queue(); |
389 | } | 358 | } |
390 | 359 | ||
391 | void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) { | 360 | void transaction_notify_view_ready_by_serial(struct sway_view *view, |
392 | for (int i = 0; i < view->swayc->instructions->length; ++i) { | 361 | uint32_t serial) { |
393 | struct sway_transaction_instruction *instruction = | 362 | struct sway_transaction_instruction *instruction = view->swayc->instruction; |
394 | view->swayc->instructions->items[i]; | 363 | if (view->swayc->instruction->serial == serial) { |
395 | if (instruction->serial == serial && !instruction->ready) { | 364 | set_instruction_ready(instruction); |
396 | set_instructions_ready(view, i); | ||
397 | return; | ||
398 | } | ||
399 | } | 365 | } |
400 | } | 366 | } |
401 | 367 | ||
402 | void transaction_notify_view_ready_by_size(struct sway_view *view, | 368 | void transaction_notify_view_ready_by_size(struct sway_view *view, |
403 | int width, int height) { | 369 | int width, int height) { |
404 | for (int i = 0; i < view->swayc->instructions->length; ++i) { | 370 | struct sway_transaction_instruction *instruction = view->swayc->instruction; |
405 | struct sway_transaction_instruction *instruction = | 371 | if (instruction->state.view_width == width && |
406 | view->swayc->instructions->items[i]; | 372 | instruction->state.view_height == height) { |
407 | if (!instruction->ready && instruction->state.view_width == width && | 373 | set_instruction_ready(instruction); |
408 | instruction->state.view_height == height) { | ||
409 | set_instructions_ready(view, i); | ||
410 | return; | ||
411 | } | ||
412 | } | 374 | } |
413 | } | 375 | } |
414 | 376 | ||
@@ -417,6 +379,9 @@ void transaction_commit_dirty(void) { | |||
417 | return; | 379 | return; |
418 | } | 380 | } |
419 | struct sway_transaction *transaction = transaction_create(); | 381 | struct sway_transaction *transaction = transaction_create(); |
382 | if (!transaction) { | ||
383 | return; | ||
384 | } | ||
420 | for (int i = 0; i < server.dirty_containers->length; ++i) { | 385 | for (int i = 0; i < server.dirty_containers->length; ++i) { |
421 | struct sway_container *container = server.dirty_containers->items[i]; | 386 | struct sway_container *container = server.dirty_containers->items[i]; |
422 | transaction_add_container(transaction, container); | 387 | transaction_add_container(transaction, container); |
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index af9d49b8..6a7a3f7f 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -254,8 +254,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
254 | return; | 254 | return; |
255 | } | 255 | } |
256 | 256 | ||
257 | if (view->swayc->instructions->length) { | 257 | if (view->swayc->instruction) { |
258 | transaction_notify_view_ready(view, xdg_surface->configure_serial); | 258 | transaction_notify_view_ready_by_serial(view, |
259 | xdg_surface->configure_serial); | ||
259 | } | 260 | } |
260 | 261 | ||
261 | view_damage_from(view); | 262 | view_damage_from(view); |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index c6ac0f4e..5b3c7b2b 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -250,8 +250,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
250 | if (!view->swayc) { | 250 | if (!view->swayc) { |
251 | return; | 251 | return; |
252 | } | 252 | } |
253 | if (view->swayc->instructions->length) { | 253 | if (view->swayc->instruction) { |
254 | transaction_notify_view_ready(view, xdg_surface_v6->configure_serial); | 254 | transaction_notify_view_ready_by_serial(view, |
255 | xdg_surface_v6->configure_serial); | ||
255 | } | 256 | } |
256 | 257 | ||
257 | view_damage_from(view); | 258 | view_damage_from(view); |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 5e8afa65..14f59b9c 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -284,7 +284,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
284 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | 284 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
285 | struct wlr_surface_state *surface_state = &xsurface->surface->current; | 285 | struct wlr_surface_state *surface_state = &xsurface->surface->current; |
286 | 286 | ||
287 | if (view->swayc->instructions->length) { | 287 | if (view->swayc->instruction) { |
288 | transaction_notify_view_ready_by_size(view, | 288 | transaction_notify_view_ready_by_size(view, |
289 | surface_state->width, surface_state->height); | 289 | surface_state->width, surface_state->height); |
290 | } else if (container_is_floating(view->swayc)) { | 290 | } else if (container_is_floating(view->swayc)) { |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 45e54080..eb06edc2 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -108,7 +108,6 @@ struct sway_container *container_create(enum sway_container_type type) { | |||
108 | c->layout = L_NONE; | 108 | c->layout = L_NONE; |
109 | c->type = type; | 109 | c->type = type; |
110 | c->alpha = 1.0f; | 110 | c->alpha = 1.0f; |
111 | c->instructions = create_list(); | ||
112 | 111 | ||
113 | if (type != C_VIEW) { | 112 | if (type != C_VIEW) { |
114 | c->children = create_list(); | 113 | c->children = create_list(); |
@@ -140,8 +139,8 @@ void container_free(struct sway_container *cont) { | |||
140 | "Tried to free container which wasn't marked as destroying")) { | 139 | "Tried to free container which wasn't marked as destroying")) { |
141 | return; | 140 | return; |
142 | } | 141 | } |
143 | if (!sway_assert(cont->instructions->length == 0, | 142 | if (!sway_assert(cont->ntxnrefs == 0, "Tried to free container " |
144 | "Tried to free container with pending instructions")) { | 143 | "which is still referenced by transactions")) { |
145 | return; | 144 | return; |
146 | } | 145 | } |
147 | free(cont->name); | 146 | free(cont->name); |
@@ -150,7 +149,6 @@ void container_free(struct sway_container *cont) { | |||
150 | wlr_texture_destroy(cont->title_focused_inactive); | 149 | wlr_texture_destroy(cont->title_focused_inactive); |
151 | wlr_texture_destroy(cont->title_unfocused); | 150 | wlr_texture_destroy(cont->title_unfocused); |
152 | wlr_texture_destroy(cont->title_urgent); | 151 | wlr_texture_destroy(cont->title_urgent); |
153 | list_free(cont->instructions); | ||
154 | list_free(cont->children); | 152 | list_free(cont->children); |
155 | list_free(cont->current.children); | 153 | list_free(cont->current.children); |
156 | 154 | ||
diff --git a/sway/tree/root.c b/sway/tree/root.c index 79f2194e..068e7911 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c | |||
@@ -26,7 +26,6 @@ void root_create(void) { | |||
26 | root_container.type = C_ROOT; | 26 | root_container.type = C_ROOT; |
27 | root_container.layout = L_NONE; | 27 | root_container.layout = L_NONE; |
28 | root_container.name = strdup("root"); | 28 | root_container.name = strdup("root"); |
29 | root_container.instructions = create_list(); | ||
30 | root_container.children = create_list(); | 29 | root_container.children = create_list(); |
31 | root_container.current.children = create_list(); | 30 | root_container.current.children = create_list(); |
32 | wl_signal_init(&root_container.events.destroy); | 31 | wl_signal_init(&root_container.events.destroy); |
@@ -55,7 +54,6 @@ void root_destroy(void) { | |||
55 | free(root_container.sway_root); | 54 | free(root_container.sway_root); |
56 | 55 | ||
57 | // root_container | 56 | // root_container |
58 | list_free(root_container.instructions); | ||
59 | list_free(root_container.children); | 57 | list_free(root_container.children); |
60 | list_free(root_container.current.children); | 58 | list_free(root_container.current.children); |
61 | free(root_container.name); | 59 | free(root_container.name); |