aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r--sway/tree/container.c221
1 files changed, 220 insertions, 1 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index f9611342..f13e2e96 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -19,7 +19,6 @@
19#include "sway/output.h" 19#include "sway/output.h"
20#include "sway/server.h" 20#include "sway/server.h"
21#include "sway/tree/arrange.h" 21#include "sway/tree/arrange.h"
22#include "sway/tree/layout.h"
23#include "sway/tree/view.h" 22#include "sway/tree/view.h"
24#include "sway/tree/workspace.h" 23#include "sway/tree/workspace.h"
25#include "log.h" 24#include "log.h"
@@ -1159,3 +1158,223 @@ void container_add_gaps(struct sway_container *c) {
1159int container_sibling_index(const struct sway_container *child) { 1158int container_sibling_index(const struct sway_container *child) {
1160 return list_find(child->parent->children, child); 1159 return list_find(child->parent->children, child);
1161} 1160}
1161
1162void container_handle_fullscreen_reparent(struct sway_container *con,
1163 struct sway_container *old_parent) {
1164 if (!con->is_fullscreen) {
1165 return;
1166 }
1167 struct sway_container *old_workspace = old_parent;
1168 if (old_workspace && old_workspace->type != C_WORKSPACE) {
1169 old_workspace = container_parent(old_workspace, C_WORKSPACE);
1170 }
1171 struct sway_container *new_workspace = container_parent(con, C_WORKSPACE);
1172 if (old_workspace == new_workspace) {
1173 return;
1174 }
1175 // Unmark the old workspace as fullscreen
1176 if (old_workspace) {
1177 old_workspace->sway_workspace->fullscreen = NULL;
1178 }
1179
1180 // Mark the new workspace as fullscreen
1181 if (new_workspace->sway_workspace->fullscreen) {
1182 container_set_fullscreen(
1183 new_workspace->sway_workspace->fullscreen, false);
1184 }
1185 new_workspace->sway_workspace->fullscreen = con;
1186
1187 // Resize container to new output dimensions
1188 struct sway_container *output = new_workspace->parent;
1189 con->x = output->x;
1190 con->y = output->y;
1191 con->width = output->width;
1192 con->height = output->height;
1193
1194 if (con->type == C_VIEW) {
1195 struct sway_view *view = con->sway_view;
1196 view->x = output->x;
1197 view->y = output->y;
1198 view->width = output->width;
1199 view->height = output->height;
1200 } else {
1201 arrange_windows(new_workspace);
1202 }
1203}
1204
1205void container_insert_child(struct sway_container *parent,
1206 struct sway_container *child, int i) {
1207 struct sway_container *old_parent = child->parent;
1208 if (old_parent) {
1209 container_remove_child(child);
1210 }
1211 wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i);
1212 list_insert(parent->children, i, child);
1213 child->parent = parent;
1214 container_handle_fullscreen_reparent(child, old_parent);
1215}
1216
1217struct sway_container *container_add_sibling(struct sway_container *fixed,
1218 struct sway_container *active) {
1219 // TODO handle floating
1220 struct sway_container *old_parent = NULL;
1221 if (active->parent) {
1222 old_parent = active->parent;
1223 container_remove_child(active);
1224 }
1225 struct sway_container *parent = fixed->parent;
1226 int i = container_sibling_index(fixed);
1227 list_insert(parent->children, i + 1, active);
1228 active->parent = parent;
1229 container_handle_fullscreen_reparent(active, old_parent);
1230 return active->parent;
1231}
1232
1233void container_add_child(struct sway_container *parent,
1234 struct sway_container *child) {
1235 wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
1236 child, child->type, child->width, child->height,
1237 parent, parent->type, parent->width, parent->height);
1238 struct sway_container *old_parent = child->parent;
1239 list_add(parent->children, child);
1240 child->parent = parent;
1241 container_handle_fullscreen_reparent(child, old_parent);
1242 if (old_parent) {
1243 container_set_dirty(old_parent);
1244 }
1245 container_set_dirty(child);
1246}
1247
1248struct sway_container *container_remove_child(struct sway_container *child) {
1249 if (child->is_fullscreen) {
1250 struct sway_container *workspace = container_parent(child, C_WORKSPACE);
1251 workspace->sway_workspace->fullscreen = NULL;
1252 }
1253
1254 struct sway_container *parent = child->parent;
1255 list_t *list = container_is_floating(child) ?
1256 parent->sway_workspace->floating : parent->children;
1257 int index = list_find(list, child);
1258 if (index != -1) {
1259 list_del(list, index);
1260 }
1261 child->parent = NULL;
1262 container_notify_subtree_changed(parent);
1263
1264 container_set_dirty(parent);
1265 container_set_dirty(child);
1266
1267 return parent;
1268}
1269
1270enum sway_container_layout container_get_default_layout(
1271 struct sway_container *con) {
1272 if (con->type != C_OUTPUT) {
1273 con = container_parent(con, C_OUTPUT);
1274 }
1275
1276 if (!sway_assert(con != NULL,
1277 "container_get_default_layout must be called on an attached"
1278 " container below the root container")) {
1279 return 0;
1280 }
1281
1282 if (config->default_layout != L_NONE) {
1283 return config->default_layout;
1284 } else if (config->default_orientation != L_NONE) {
1285 return config->default_orientation;
1286 } else if (con->width >= con->height) {
1287 return L_HORIZ;
1288 } else {
1289 return L_VERT;
1290 }
1291}
1292
1293struct sway_container *container_replace_child(struct sway_container *child,
1294 struct sway_container *new_child) {
1295 struct sway_container *parent = child->parent;
1296 if (parent == NULL) {
1297 return NULL;
1298 }
1299
1300 list_t *list = container_is_floating(child) ?
1301 parent->sway_workspace->floating : parent->children;
1302 int i = list_find(list, child);
1303
1304 if (new_child->parent) {
1305 container_remove_child(new_child);
1306 }
1307 list->items[i] = new_child;
1308 new_child->parent = parent;
1309 child->parent = NULL;
1310
1311 // Set geometry for new child
1312 new_child->x = child->x;
1313 new_child->y = child->y;
1314 new_child->width = child->width;
1315 new_child->height = child->height;
1316
1317 // reset geometry for child
1318 child->width = 0;
1319 child->height = 0;
1320
1321 return parent;
1322}
1323
1324struct sway_container *container_split(struct sway_container *child,
1325 enum sway_container_layout layout) {
1326 // TODO floating: cannot split a floating container
1327 if (!sway_assert(child, "child cannot be null")) {
1328 return NULL;
1329 }
1330 if (child->type == C_WORKSPACE && child->children->length == 0) {
1331 // Special case: this just behaves like splitt
1332 child->prev_split_layout = child->layout;
1333 child->layout = layout;
1334 return child;
1335 }
1336
1337 struct sway_container *cont = container_create(C_CONTAINER);
1338
1339 wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child);
1340
1341 child->type == C_WORKSPACE ? workspace_remove_gaps(child)
1342 : container_remove_gaps(child);
1343
1344 cont->prev_split_layout = L_NONE;
1345 cont->width = child->width;
1346 cont->height = child->height;
1347 cont->x = child->x;
1348 cont->y = child->y;
1349
1350 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
1351 bool set_focus = (seat_get_focus(seat) == child);
1352
1353 container_add_gaps(cont);
1354
1355 if (child->type == C_WORKSPACE) {
1356 struct sway_container *workspace = child;
1357 while (workspace->children->length) {
1358 struct sway_container *ws_child = workspace->children->items[0];
1359 container_remove_child(ws_child);
1360 container_add_child(cont, ws_child);
1361 }
1362
1363 container_add_child(workspace, cont);
1364 enum sway_container_layout old_layout = workspace->layout;
1365 workspace->layout = layout;
1366 cont->layout = old_layout;
1367 } else {
1368 cont->layout = layout;
1369 container_replace_child(child, cont);
1370 container_add_child(cont, child);
1371 }
1372
1373 if (set_focus) {
1374 seat_set_focus(seat, cont);
1375 seat_set_focus(seat, child);
1376 }
1377
1378 container_notify_subtree_changed(cont);
1379 return cont;
1380}