diff --git a/include/config.h b/include/config.h index d591daf2a..35797ac28 100644 --- a/include/config.h +++ b/include/config.h @@ -92,6 +92,13 @@ struct workspace_output { char *workspace; }; +struct pid_workspace { + pid_t *pid; + char *workspace; +}; + +void free_pid_workspace(struct pid_workspace *pw); + struct bar_config { /** * One of "dock", "hide", "invisible" @@ -175,6 +182,7 @@ struct sway_config { list_t *bars; list_t *cmd_queue; list_t *workspace_outputs; + list_t *pid_workspaces; list_t *output_configs; list_t *input_configs; list_t *criteria; diff --git a/sway/commands.c b/sway/commands.c index 83a9e7e97..08920c1c5 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -549,12 +549,19 @@ static struct cmd_results *cmd_exec_always(int argc, char **argv) { close(fd[0]); // cleanup child process wait(0); - if (*child > 0) { - sway_log(L_DEBUG, "Child process created with pid %d", *child); + swayc_t *ws = swayc_active_workspace(); + if (*child > 0 && ws) { + sway_log(L_DEBUG, "Child process created with pid %d for workspace %s", *child, ws->name); + struct pid_workspace *pw = malloc(sizeof(struct pid_workspace)); + pw->pid = child; + pw->workspace = strdup(ws->name); + list_add(config->pid_workspaces, pw); // TODO: keep track of this pid and open the corresponding view on the current workspace // blocked pending feature in wlc + } else { + free(child); } - free(child); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config.c b/sway/config.c index 151081235..321534edf 100644 --- a/sway/config.c +++ b/sway/config.c @@ -89,6 +89,15 @@ static void free_workspace_output(struct workspace_output *wo) { free(wo); } +void free_pid_workspace(struct pid_workspace *pw) { + if (!pw) { + return; + } + free(pw->pid); + free(pw->workspace); + free(pw); +} + void free_config(struct sway_config *config) { int i; for (i = 0; i < config->symbols->length; ++i) { @@ -113,6 +122,11 @@ void free_config(struct sway_config *config) { } list_free(config->workspace_outputs); + for (i = 0; i < config->pid_workspaces->length; ++i) { + free_pid_workspace(config->pid_workspaces->items[i]); + } + list_free(config->pid_workspaces); + for (i = 0; i < config->criteria->length; ++i) { free_criteria(config->criteria->items[i]); } @@ -148,6 +162,7 @@ static void config_defaults(struct sway_config *config) { config->modes = create_list(); config->bars = create_list(); config->workspace_outputs = create_list(); + config->pid_workspaces = create_list(); config->criteria = create_list(); config->input_configs = create_list(); config->output_configs = create_list(); diff --git a/sway/handlers.c b/sway/handlers.c index f8dd9f4d2..317b03a86 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -185,6 +185,63 @@ static bool handle_view_created(wlc_handle handle) { if (parent) { focused = swayc_by_handle(parent); } + + // TODO: test with wayland apps (gnome terminal or corebird) + + // try to match this up to a pid_workspace + struct wl_client *client = wlc_view_get_wl_client(handle); + pid_t pid; + struct pid_workspace *pw = NULL; + + sway_log(L_DEBUG, "checking pid workspaces, handle is %lu", handle); + + if (client) { + sway_log(L_DEBUG, "found client"); + wl_client_get_credentials(client, &pid, NULL, NULL); + } + + sway_log(L_DEBUG, "all pid_workspaces"); + for (int k = 0; k < config->pid_workspaces->length; k++) { + pw = config->pid_workspaces->items[k]; + sway_log(L_DEBUG, "pid %d workspace %s", *pw->pid, pw->workspace); + } + + if (pid) { + sway_log(L_DEBUG, "found pid %d for client", pid); + int i; + for (i = 0; i < config->pid_workspaces->length; i++) { + pw = config->pid_workspaces->items[i]; + pid_t *pw_pid = pw->pid; + sway_log(L_DEBUG, "checking pid %d against pid %d, i is %d", pid, *pw_pid, i); + if (pid == *pw_pid) { + sway_log(L_DEBUG, "found pid_workspace for pid, %d %s", pid, pw->workspace); + break; + } + pw = NULL; + } + + swayc_t *ws = NULL; + + if (pw) { + ws = workspace_by_name(pw->workspace); + + if (!ws) { + sway_log(L_DEBUG, "creating workspace %s because it disappeared", pw->workspace); + ws = workspace_create(pw->workspace); + } + + if (ws) { + sway_log(L_DEBUG, "workspace exists, name is %s", ws->name); + focused = ws; + } + + list_del(config->pid_workspaces, i); + } + } + + free_pid_workspace(pw); + // free(&pid); + if (!focused || focused->type == C_OUTPUT) { focused = get_focused_container(&root_container); // Move focus from floating view @@ -220,7 +277,7 @@ static bool handle_view_created(wlc_handle handle) { // Dmenu keeps viewfocus, but others with this flag don't, for now simulate // dmenu case WLC_BIT_OVERRIDE_REDIRECT: -// locked_view_focus = true; + // locked_view_focus = true; wlc_view_focus(handle); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); wlc_view_bring_to_front(handle);