aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/desktop/transaction.h5
-rw-r--r--include/sway/tree/container.h7
-rw-r--r--sway/desktop/transaction.c99
-rw-r--r--sway/desktop/xdg_shell.c5
-rw-r--r--sway/desktop/xdg_shell_v6.c5
-rw-r--r--sway/desktop/xwayland.c2
-rw-r--r--sway/tree/container.c6
-rw-r--r--sway/tree/root.c2
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
23struct 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 */
34void transaction_notify_view_ready(struct sway_view *view, uint32_t serial); 36void 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
49static struct sway_transaction *transaction_create() { 48static 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
348static void set_instruction_ready( 330static 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 */
380static 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
391void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) { 360void 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
402void transaction_notify_view_ready_by_size(struct sway_view *view, 368void 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);