diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 221 |
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) { | |||
1159 | int container_sibling_index(const struct sway_container *child) { | 1158 | int 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 | |||
1162 | void 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 | |||
1205 | void 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 | |||
1217 | struct 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 | |||
1233 | void 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 | |||
1248 | struct 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 | |||
1270 | enum 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 | |||
1293 | struct 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 | |||
1324 | struct 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 | } | ||