mirror of
https://github.com/NickHu/sway
synced 2024-12-27 21:58:11 +01:00
Restore workspaces to outputs based on priority
This commit is contained in:
parent
c65c84444e
commit
5c9a917df9
5 changed files with 130 additions and 17 deletions
|
@ -9,6 +9,7 @@ struct sway_workspace {
|
||||||
struct sway_container *swayc;
|
struct sway_container *swayc;
|
||||||
struct sway_view *fullscreen;
|
struct sway_view *fullscreen;
|
||||||
struct sway_container *floating;
|
struct sway_container *floating;
|
||||||
|
list_t *output_priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern char *prev_workspace_name;
|
extern char *prev_workspace_name;
|
||||||
|
@ -33,4 +34,12 @@ bool workspace_is_visible(struct sway_container *ws);
|
||||||
|
|
||||||
bool workspace_is_empty(struct sway_container *ws);
|
bool workspace_is_empty(struct sway_container *ws);
|
||||||
|
|
||||||
|
void workspace_output_raise_priority(struct sway_container *workspace,
|
||||||
|
struct sway_container *old_output, struct sway_container *new_output);
|
||||||
|
|
||||||
|
void workspace_output_add_priority(struct sway_container *workspace,
|
||||||
|
struct sway_container *output);
|
||||||
|
|
||||||
|
struct sway_container *workspace_output_get_highest_available(
|
||||||
|
struct sway_container *ws, struct sway_container *exclude);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -213,6 +213,9 @@ static struct sway_container *container_workspace_destroy(
|
||||||
sway_workspace->floating->parent = NULL;
|
sway_workspace->floating->parent = NULL;
|
||||||
_container_destroy(sway_workspace->floating);
|
_container_destroy(sway_workspace->floating);
|
||||||
|
|
||||||
|
list_foreach(sway_workspace->output_priority, free);
|
||||||
|
list_free(sway_workspace->output_priority);
|
||||||
|
|
||||||
free(sway_workspace);
|
free(sway_workspace);
|
||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
|
@ -234,24 +237,33 @@ static struct sway_container *container_output_destroy(
|
||||||
// program
|
// program
|
||||||
if (root_container.children->length > 1) {
|
if (root_container.children->length > 1) {
|
||||||
// Move workspace from this output to another output
|
// Move workspace from this output to another output
|
||||||
struct sway_container *other_output =
|
struct sway_container *fallback_output =
|
||||||
root_container.children->items[0];
|
root_container.children->items[0];
|
||||||
if (other_output == output) {
|
if (fallback_output == output) {
|
||||||
other_output = root_container.children->items[1];
|
fallback_output = root_container.children->items[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
while (output->children->length) {
|
while (output->children->length) {
|
||||||
struct sway_container *workspace = output->children->items[0];
|
struct sway_container *workspace = output->children->items[0];
|
||||||
|
|
||||||
|
struct sway_container *new_output =
|
||||||
|
workspace_output_get_highest_available(workspace, output);
|
||||||
|
if (!new_output) {
|
||||||
|
new_output = fallback_output;
|
||||||
|
workspace_output_add_priority(workspace, new_output);
|
||||||
|
}
|
||||||
|
|
||||||
container_remove_child(workspace);
|
container_remove_child(workspace);
|
||||||
if (workspace->children->length > 0) {
|
if (!workspace_is_empty(workspace)) {
|
||||||
container_add_child(other_output, workspace);
|
container_add_child(new_output, workspace);
|
||||||
ipc_event_workspace(workspace, NULL, "move");
|
ipc_event_workspace(workspace, NULL, "move");
|
||||||
} else {
|
} else {
|
||||||
container_workspace_destroy(workspace);
|
container_workspace_destroy(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container_sort_workspaces(new_output);
|
||||||
|
arrange_output(new_output);
|
||||||
}
|
}
|
||||||
container_sort_workspaces(other_output);
|
|
||||||
arrange_output(other_output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,6 +445,9 @@ void container_descendants(struct sway_container *root,
|
||||||
func(item, data);
|
func(item, data);
|
||||||
}
|
}
|
||||||
container_descendants(item, type, func, data);
|
container_descendants(item, type, func, data);
|
||||||
|
if (i < root->children->length && root->children->items[i] != item) {
|
||||||
|
--i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ void container_move_to(struct sway_container *container,
|
||||||
}
|
}
|
||||||
container_sort_workspaces(new_parent);
|
container_sort_workspaces(new_parent);
|
||||||
seat_set_focus(seat, new_parent);
|
seat_set_focus(seat, new_parent);
|
||||||
|
workspace_output_raise_priority(container, old_parent, new_parent);
|
||||||
}
|
}
|
||||||
container_notify_subtree_changed(old_parent);
|
container_notify_subtree_changed(old_parent);
|
||||||
container_notify_subtree_changed(new_parent);
|
container_notify_subtree_changed(new_parent);
|
||||||
|
|
|
@ -1,11 +1,35 @@
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include "sway/ipc-server.h"
|
||||||
#include "sway/output.h"
|
#include "sway/output.h"
|
||||||
|
#include "sway/tree/arrange.h"
|
||||||
#include "sway/tree/output.h"
|
#include "sway/tree/output.h"
|
||||||
#include "sway/tree/workspace.h"
|
#include "sway/tree/workspace.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
static void restore_workspace(struct sway_container *ws, void *output) {
|
||||||
|
if (ws->parent == output) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sway_container *highest = workspace_output_get_highest_available(
|
||||||
|
ws, NULL);
|
||||||
|
if (!highest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highest == output) {
|
||||||
|
struct sway_container *other = container_remove_child(ws);
|
||||||
|
container_add_child(output, ws);
|
||||||
|
ipc_event_workspace(ws, NULL, "move");
|
||||||
|
|
||||||
|
container_sort_workspaces(output);
|
||||||
|
arrange_output(output);
|
||||||
|
arrange_output(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct sway_container *output_create(
|
struct sway_container *output_create(
|
||||||
struct sway_output *sway_output) {
|
struct sway_output *sway_output) {
|
||||||
const char *name = sway_output->wlr_output->name;
|
const char *name = sway_output->wlr_output->name;
|
||||||
|
@ -56,19 +80,24 @@ struct sway_container *output_create(
|
||||||
output->width = size.width;
|
output->width = size.width;
|
||||||
output->height = size.height;
|
output->height = size.height;
|
||||||
|
|
||||||
// Create workspace
|
container_descendants(&root_container, C_WORKSPACE, restore_workspace,
|
||||||
char *ws_name = workspace_next_name(output->name);
|
output);
|
||||||
wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
|
|
||||||
struct sway_container *ws = workspace_create(output, ws_name);
|
if (!output->children->length) {
|
||||||
// Set each seat's focus if not already set
|
// Create workspace
|
||||||
struct sway_seat *seat = NULL;
|
char *ws_name = workspace_next_name(output->name);
|
||||||
wl_list_for_each(seat, &input_manager->seats, link) {
|
wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
|
||||||
if (!seat->has_focus) {
|
struct sway_container *ws = workspace_create(output, ws_name);
|
||||||
seat_set_focus(seat, ws);
|
// Set each seat's focus if not already set
|
||||||
|
struct sway_seat *seat = NULL;
|
||||||
|
wl_list_for_each(seat, &input_manager->seats, link) {
|
||||||
|
if (!seat->has_focus) {
|
||||||
|
seat_set_focus(seat, ws);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
free(ws_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ws_name);
|
|
||||||
container_create_notify(output);
|
container_create_notify(output);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,9 @@ struct sway_container *workspace_create(struct sway_container *output,
|
||||||
swayws->floating = container_create(C_CONTAINER);
|
swayws->floating = container_create(C_CONTAINER);
|
||||||
swayws->floating->parent = swayws->swayc;
|
swayws->floating->parent = swayws->swayc;
|
||||||
swayws->floating->layout = L_FLOATING;
|
swayws->floating->layout = L_FLOATING;
|
||||||
|
swayws->output_priority = create_list();
|
||||||
workspace->sway_workspace = swayws;
|
workspace->sway_workspace = swayws;
|
||||||
|
workspace_output_add_priority(workspace, output);
|
||||||
|
|
||||||
container_add_child(output, workspace);
|
container_add_child(output, workspace);
|
||||||
container_sort_workspaces(output);
|
container_sort_workspaces(output);
|
||||||
|
@ -454,3 +456,60 @@ bool workspace_is_empty(struct sway_container *ws) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int find_output(const void *id1, const void *id2) {
|
||||||
|
return strcmp(id1, id2) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_output_raise_priority(struct sway_container *workspace,
|
||||||
|
struct sway_container *old_output, struct sway_container *output) {
|
||||||
|
struct sway_workspace *ws = workspace->sway_workspace;
|
||||||
|
|
||||||
|
int old_index = list_seq_find(ws->output_priority, find_output,
|
||||||
|
old_output->name);
|
||||||
|
if (old_index < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_index = list_seq_find(ws->output_priority, find_output,
|
||||||
|
output->name);
|
||||||
|
if (new_index < 0) {
|
||||||
|
list_insert(ws->output_priority, old_index, strdup(output->name));
|
||||||
|
} else if (new_index > old_index) {
|
||||||
|
char *name = ws->output_priority->items[new_index];
|
||||||
|
list_del(ws->output_priority, new_index);
|
||||||
|
list_insert(ws->output_priority, old_index, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void workspace_output_add_priority(struct sway_container *workspace,
|
||||||
|
struct sway_container *output) {
|
||||||
|
int index = list_seq_find(workspace->sway_workspace->output_priority,
|
||||||
|
find_output, output->name);
|
||||||
|
if (index < 0) {
|
||||||
|
list_add(workspace->sway_workspace->output_priority,
|
||||||
|
strdup(output->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _output_by_name(struct sway_container *output, void *data) {
|
||||||
|
return output->type == C_OUTPUT && strcasecmp(output->name, data) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sway_container *workspace_output_get_highest_available(
|
||||||
|
struct sway_container *ws, struct sway_container *exclude) {
|
||||||
|
for (int i = 0; i < ws->sway_workspace->output_priority->length; i++) {
|
||||||
|
char *name = ws->sway_workspace->output_priority->items[i];
|
||||||
|
if (exclude && strcasecmp(name, exclude->name) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sway_container *output = container_find(&root_container,
|
||||||
|
_output_by_name, name);
|
||||||
|
if (output) {
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue