mirror of
https://github.com/swaywm/sway.git
synced 2025-11-06 13:29:50 -05:00
Implement pid->workspace tracking
When you spawn a process with the exec command, sway now notes the workspace you had focused and the pid of the child process, then assigns that workspace to the child when its window appears. Some of this is carried over from sway 0.15, but with some major refactoring and centralization of state.
This commit is contained in:
parent
62a7b762ac
commit
acd79e1505
10 changed files with 154 additions and 33 deletions
|
|
@ -9,6 +9,7 @@
|
|||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/ipc-server.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/container.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
|
|
@ -516,3 +517,114 @@ struct sway_container *workspace_output_get_highest_available(
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pid_workspace {
|
||||
pid_t pid;
|
||||
char *workspace;
|
||||
struct timespec time_added;
|
||||
|
||||
struct sway_container *output;
|
||||
struct wl_listener output_destroy;
|
||||
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
static struct wl_list pid_workspaces;
|
||||
|
||||
struct sway_container *workspace_for_pid(pid_t pid) {
|
||||
if (!pid_workspaces.prev && !pid_workspaces.next) {
|
||||
wl_list_init(&pid_workspaces);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sway_container *ws = NULL;
|
||||
struct pid_workspace *pw = NULL;
|
||||
|
||||
wlr_log(L_DEBUG, "Looking up workspace for pid %d", pid);
|
||||
|
||||
do {
|
||||
struct pid_workspace *_pw = NULL;
|
||||
wl_list_for_each(_pw, &pid_workspaces, link) {
|
||||
if (pid == _pw->pid) {
|
||||
pw = _pw;
|
||||
wlr_log(L_DEBUG,
|
||||
"found pid_workspace for pid %d, workspace %s",
|
||||
pid, pw->workspace);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
pid = get_parent_pid(pid);
|
||||
} while (pid > 1);
|
||||
found:
|
||||
|
||||
if (pw && pw->workspace) {
|
||||
ws = workspace_by_name(pw->workspace);
|
||||
|
||||
if (!ws) {
|
||||
wlr_log(L_DEBUG,
|
||||
"Creating workspace %s for pid %d because it disappeared",
|
||||
pw->workspace, pid);
|
||||
ws = workspace_create(pw->output, pw->workspace);
|
||||
}
|
||||
|
||||
wl_list_remove(&pw->output_destroy.link);
|
||||
wl_list_remove(&pw->link);
|
||||
free(pw->workspace);
|
||||
free(pw);
|
||||
}
|
||||
|
||||
return ws;
|
||||
}
|
||||
|
||||
static void pw_handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||
struct pid_workspace *pw = wl_container_of(listener, pw, output_destroy);
|
||||
pw->output = NULL;
|
||||
}
|
||||
|
||||
void workspace_record_pid(pid_t pid) {
|
||||
wlr_log(L_DEBUG, "Recording workspace for process %d", pid);
|
||||
if (!pid_workspaces.prev && !pid_workspaces.next) {
|
||||
wl_list_init(&pid_workspaces);
|
||||
}
|
||||
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
struct sway_container *ws =
|
||||
seat_get_focus_inactive(seat, &root_container);
|
||||
if (ws && ws->type != C_WORKSPACE) {
|
||||
ws = container_parent(ws, C_WORKSPACE);
|
||||
}
|
||||
if (!ws) {
|
||||
wlr_log(L_DEBUG, "Bailing out, no workspace");
|
||||
return;
|
||||
}
|
||||
struct sway_container *output = ws->parent;
|
||||
if (!output) {
|
||||
wlr_log(L_DEBUG, "Bailing out, no output");
|
||||
return;
|
||||
}
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
// Remove expired entries
|
||||
static const int timeout = 60;
|
||||
struct pid_workspace *old, *_old;
|
||||
wl_list_for_each_safe(old, _old, &pid_workspaces, link) {
|
||||
if (now.tv_sec - old->time_added.tv_sec >= timeout) {
|
||||
wl_list_remove(&old->output_destroy.link);
|
||||
wl_list_remove(&old->link);
|
||||
free(old->workspace);
|
||||
free(old);
|
||||
}
|
||||
}
|
||||
|
||||
struct pid_workspace *pw = calloc(1, sizeof(struct pid_workspace));
|
||||
pw->workspace = strdup(ws->name);
|
||||
pw->output = output;
|
||||
pw->pid = pid;
|
||||
memcpy(&pw->time_added, &now, sizeof(struct timespec));
|
||||
pw->output_destroy.notify = pw_handle_output_destroy;
|
||||
wl_signal_add(&output->sway_output->wlr_output->events.destroy,
|
||||
&pw->output_destroy);
|
||||
wl_list_insert(&pid_workspaces, &pw->link);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue