aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/transaction.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-06-03 16:35:06 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-06-09 10:08:43 +1000
commit59c94887018bdfa578c4371c4275061ca6e71b3e (patch)
tree62bdaa6ac4777d1fcb292013bddd2043dad7765a /sway/desktop/transaction.c
parentMerge pull request #2115 from RedSoxFan/restore-workspaces (diff)
downloadsway-59c94887018bdfa578c4371c4275061ca6e71b3e.tar.gz
sway-59c94887018bdfa578c4371c4275061ca6e71b3e.tar.zst
sway-59c94887018bdfa578c4371c4275061ca6e71b3e.zip
WIP: Atomic layout updates ground work
Diffstat (limited to 'sway/desktop/transaction.c')
-rw-r--r--sway/desktop/transaction.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
new file mode 100644
index 00000000..69f97e3d
--- /dev/null
+++ b/sway/desktop/transaction.c
@@ -0,0 +1,214 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h>
3#include <stdlib.h>
4#include <string.h>
5#include <wlr/types/wlr_linux_dmabuf.h>
6#include "sway/debug.h"
7#include "sway/desktop/transaction.h"
8#include "sway/output.h"
9#include "sway/tree/container.h"
10#include "sway/tree/view.h"
11#include "list.h"
12#include "log.h"
13
14/**
15 * How long we should wait for views to respond to the configure before giving
16 * up and applying the transaction anyway.
17 */
18#define TIMEOUT_MS 200
19
20struct sway_transaction_instruction {
21 struct sway_transaction *transaction;
22 struct sway_container *container;
23 struct sway_container_state state;
24 uint32_t serial;
25};
26
27struct sway_transaction *transaction_create() {
28 struct sway_transaction *transaction =
29 calloc(1, sizeof(struct sway_transaction));
30 transaction->instructions = create_list();
31 transaction->damage = create_list();
32 return transaction;
33}
34
35static void transaction_destroy(struct sway_transaction *transaction) {
36 int i;
37 // Free instructions
38 for (i = 0; i < transaction->instructions->length; ++i) {
39 struct sway_transaction_instruction *instruction =
40 transaction->instructions->items[i];
41 if (instruction->container->type == C_VIEW) {
42 struct sway_view *view = instruction->container->sway_view;
43 for (int j = 0; j < view->instructions->length; ++j) {
44 if (view->instructions->items[j] == instruction) {
45 list_del(view->instructions, j);
46 break;
47 }
48 }
49 }
50 free(instruction);
51 }
52 list_free(transaction->instructions);
53
54 // Free damage
55 for (i = 0; i < transaction->damage->length; ++i) {
56 struct wlr_box *box = transaction->damage->items[i];
57 free(box);
58 }
59 list_free(transaction->damage);
60
61 free(transaction);
62}
63
64void transaction_add_container(struct sway_transaction *transaction,
65 struct sway_container *container) {
66 struct sway_transaction_instruction *instruction =
67 calloc(1, sizeof(struct sway_transaction_instruction));
68 instruction->transaction = transaction;
69 instruction->container = container;
70 memcpy(&instruction->state, &container->pending,
71 sizeof(struct sway_container_state));
72 list_add(transaction->instructions, instruction);
73}
74
75void transaction_add_damage(struct sway_transaction *transaction,
76 struct wlr_box *_box) {
77 struct wlr_box *box = calloc(1, sizeof(struct wlr_box));
78 memcpy(box, _box, sizeof(struct wlr_box));
79 list_add(transaction->damage, box);
80}
81
82static void save_view_texture(struct sway_view *view) {
83 wlr_texture_destroy(view->saved_texture);
84 view->saved_texture = NULL;
85
86 // TODO: Copy the texture and store it in view->saved_texture.
87}
88
89static void remove_saved_view_texture(struct sway_view *view) {
90 wlr_texture_destroy(view->saved_texture);
91 view->saved_texture = NULL;
92}
93
94/**
95 * Apply a transaction to the "current" state of the tree.
96 *
97 * This is mostly copying stuff from the pending state into the main swayc
98 * properties, but also includes reparenting and deleting containers.
99 */
100static void transaction_apply(struct sway_transaction *transaction) {
101 int i;
102 for (i = 0; i < transaction->instructions->length; ++i) {
103 struct sway_transaction_instruction *instruction =
104 transaction->instructions->items[i];
105 struct sway_container_state *state = &instruction->state;
106 struct sway_container *container = instruction->container;
107
108 container->layout = state->layout;
109 container->x = state->swayc_x;
110 container->y = state->swayc_y;
111 container->width = state->swayc_width;
112 container->height = state->swayc_height;
113
114 if (container->type == C_VIEW) {
115 struct sway_view *view = container->sway_view;
116 view->x = state->view_x;
117 view->y = state->view_y;
118 view->width = state->view_width;
119 view->height = state->view_height;
120 view->is_fullscreen = state->is_fullscreen;
121 view->border = state->border;
122 view->border_thickness = state->border_thickness;
123 view->border_top = state->border_top;
124 view->border_left = state->border_left;
125 view->border_right = state->border_right;
126 view->border_bottom = state->border_bottom;
127
128 remove_saved_view_texture(view);
129 }
130 }
131
132 // Damage
133 for (i = 0; i < transaction->damage->length; ++i) {
134 struct wlr_box *box = transaction->damage->items[i];
135 for (int j = 0; j < root_container.children->length; ++j) {
136 struct sway_container *output = root_container.children->items[j];
137 output_damage_box(output->sway_output, box);
138 }
139 }
140
141 update_debug_tree();
142}
143
144static int handle_timeout(void *data) {
145 struct sway_transaction *transaction = data;
146 wlr_log(L_DEBUG, "Transaction %p timed out (%li waiting), applying anyway",
147 transaction, transaction->num_waiting);
148 transaction_apply(transaction);
149 transaction_destroy(transaction);
150 return 0;
151}
152
153void transaction_commit(struct sway_transaction *transaction) {
154 wlr_log(L_DEBUG, "Transaction %p committing with %i instructions",
155 transaction, transaction->instructions->length);
156 transaction->num_waiting = 0;
157 for (int i = 0; i < transaction->instructions->length; ++i) {
158 struct sway_transaction_instruction *instruction =
159 transaction->instructions->items[i];
160 if (instruction->container->type == C_VIEW) {
161 struct sway_view *view = instruction->container->sway_view;
162 instruction->serial = view_configure(view,
163 instruction->state.view_x,
164 instruction->state.view_y,
165 instruction->state.view_width,
166 instruction->state.view_height);
167 if (instruction->serial) {
168 save_view_texture(view);
169 list_add(view->instructions, instruction);
170 ++transaction->num_waiting;
171 }
172 }
173 }
174 if (!transaction->num_waiting) {
175 // This can happen if the transaction only contains xwayland views
176 wlr_log(L_DEBUG, "Transaction %p has nothing to wait for, applying",
177 transaction);
178 transaction_apply(transaction);
179 transaction_destroy(transaction);
180 return;
181 }
182
183 // Set up a timer which the views must respond within
184 transaction->timer = wl_event_loop_add_timer(server.wl_event_loop,
185 handle_timeout, transaction);
186 wl_event_source_timer_update(transaction->timer, TIMEOUT_MS);
187}
188
189void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) {
190 // Find the instruction
191 struct sway_transaction_instruction *instruction = NULL;
192 for (int i = 0; i < view->instructions->length; ++i) {
193 struct sway_transaction_instruction *tmp_instruction =
194 view->instructions->items[i];
195 if (tmp_instruction->serial == serial) {
196 instruction = tmp_instruction;
197 list_del(view->instructions, i);
198 break;
199 }
200 }
201 if (!instruction) {
202 // This can happen if the view acknowledges the configure after the
203 // transaction has timed out and applied.
204 return;
205 }
206 // If all views are ready, apply the transaction
207 struct sway_transaction *transaction = instruction->transaction;
208 if (--transaction->num_waiting == 0) {
209 wlr_log(L_DEBUG, "Transaction %p is ready, applying", transaction);
210 wl_event_source_timer_update(transaction->timer, 0);
211 transaction_apply(transaction);
212 transaction_destroy(transaction);
213 }
214}