aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2016-06-11 15:02:26 -0400
committerLibravatar GitHub <noreply@github.com>2016-06-11 15:02:26 -0400
commit6388e1e288009fc12af3fe418a6faf8cfe9926f7 (patch)
treed1b4fb33848d09c71602005c57919a903ce3d72d
parentMany improvements to man pages (diff)
parentcleanup + add timeouts for pid_workspace list (diff)
downloadsway-6388e1e288009fc12af3fe418a6faf8cfe9926f7.tar.gz
sway-6388e1e288009fc12af3fe418a6faf8cfe9926f7.tar.zst
sway-6388e1e288009fc12af3fe418a6faf8cfe9926f7.zip
Merge pull request #701 from zandrmartin/assign-command
messy start of a fix for #462
-rw-r--r--common/util.c31
-rw-r--r--include/config.h13
-rw-r--r--include/util.h8
-rw-r--r--include/workspace.h2
-rw-r--r--sway/commands.c13
-rw-r--r--sway/config.c60
-rw-r--r--sway/handlers.c30
-rw-r--r--sway/workspace.c52
8 files changed, 204 insertions, 5 deletions
diff --git a/common/util.c b/common/util.c
index 13397437..12cb7470 100644
--- a/common/util.c
+++ b/common/util.c
@@ -1,6 +1,10 @@
1#include <math.h> 1#include <math.h>
2 2#include <stdio.h>
3#include <string.h>
4#include <stdlib.h>
5#include "readline.h"
3#include "util.h" 6#include "util.h"
7#include "log.h"
4 8
5int wrap(int i, int max) { 9int wrap(int i, int max) {
6 return ((i % max) + max) % max; 10 return ((i % max) + max) % max;
@@ -64,3 +68,28 @@ int get_modifier_names(const char **names, uint32_t modifier_masks) {
64 68
65 return length; 69 return length;
66} 70}
71
72pid_t get_parent_pid(pid_t child) {
73 pid_t parent;
74 char file_name[100];
75 char *buffer = NULL;
76 char *token = NULL;
77 const char *sep = " ";
78 FILE *stat = NULL;
79
80 sprintf(file_name, "/proc/%d/stat", child);
81
82 if ((stat = fopen(file_name, "r")) && (buffer = read_line(stat))) {
83 fclose(stat);
84
85 token = strtok(buffer, sep); // pid
86 token = strtok(NULL, sep); // executable name
87 token = strtok(NULL, sep); // state
88 token = strtok(NULL, sep); // parent pid
89
90 parent = strtol(token, NULL, 10);
91 return (parent == child) ? -1 : parent;
92 }
93
94 return -1;
95}
diff --git a/include/config.h b/include/config.h
index d591daf2..bf278ddb 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1,11 +1,14 @@
1#ifndef _SWAY_CONFIG_H 1#ifndef _SWAY_CONFIG_H
2#define _SWAY_CONFIG_H 2#define _SWAY_CONFIG_H
3 3
4#define PID_WORKSPACE_TIMEOUT 60
5
4#include <libinput.h> 6#include <libinput.h>
5#include <stdint.h> 7#include <stdint.h>
6#include <wlc/geometry.h> 8#include <wlc/geometry.h>
7#include <wlc/wlc.h> 9#include <wlc/wlc.h>
8#include <xkbcommon/xkbcommon.h> 10#include <xkbcommon/xkbcommon.h>
11#include <time.h>
9#include "wayland-desktop-shell-server-protocol.h" 12#include "wayland-desktop-shell-server-protocol.h"
10#include "list.h" 13#include "list.h"
11#include "layout.h" 14#include "layout.h"
@@ -92,6 +95,15 @@ struct workspace_output {
92 char *workspace; 95 char *workspace;
93}; 96};
94 97
98struct pid_workspace {
99 pid_t *pid;
100 char *workspace;
101 time_t *time_added;
102};
103
104void pid_workspace_add(struct pid_workspace *pw);
105void free_pid_workspace(struct pid_workspace *pw);
106
95struct bar_config { 107struct bar_config {
96 /** 108 /**
97 * One of "dock", "hide", "invisible" 109 * One of "dock", "hide", "invisible"
@@ -175,6 +187,7 @@ struct sway_config {
175 list_t *bars; 187 list_t *bars;
176 list_t *cmd_queue; 188 list_t *cmd_queue;
177 list_t *workspace_outputs; 189 list_t *workspace_outputs;
190 list_t *pid_workspaces;
178 list_t *output_configs; 191 list_t *output_configs;
179 list_t *input_configs; 192 list_t *input_configs;
180 list_t *criteria; 193 list_t *criteria;
diff --git a/include/util.h b/include/util.h
index dc47e343..6f21bff0 100644
--- a/include/util.h
+++ b/include/util.h
@@ -2,6 +2,7 @@
2#define _SWAY_UTIL_H 2#define _SWAY_UTIL_H
3 3
4#include <stdint.h> 4#include <stdint.h>
5#include <unistd.h>
5#include <wlc/wlc.h> 6#include <wlc/wlc.h>
6#include <xkbcommon/xkbcommon.h> 7#include <xkbcommon/xkbcommon.h>
7 8
@@ -36,4 +37,11 @@ const char *get_modifier_name_by_mask(uint32_t modifier);
36 */ 37 */
37int get_modifier_names(const char **names, uint32_t modifier_masks); 38int get_modifier_names(const char **names, uint32_t modifier_masks);
38 39
40/**
41 * Get the pid of a parent process given the pid of a child process.
42 *
43 * Returns the parent pid or NULL if the parent pid cannot be determined.
44 */
45pid_t get_parent_pid(pid_t pid);
46
39#endif 47#endif
diff --git a/include/workspace.h b/include/workspace.h
index 6911e3d4..c268fafa 100644
--- a/include/workspace.h
+++ b/include/workspace.h
@@ -2,6 +2,7 @@
2#define _SWAY_WORKSPACE_H 2#define _SWAY_WORKSPACE_H
3 3
4#include <wlc/wlc.h> 4#include <wlc/wlc.h>
5#include <unistd.h>
5#include "list.h" 6#include "list.h"
6#include "layout.h" 7#include "layout.h"
7 8
@@ -16,5 +17,6 @@ swayc_t *workspace_output_next();
16swayc_t *workspace_next(); 17swayc_t *workspace_next();
17swayc_t *workspace_output_prev(); 18swayc_t *workspace_output_prev();
18swayc_t *workspace_prev(); 19swayc_t *workspace_prev();
20swayc_t *workspace_for_pid(pid_t pid);
19 21
20#endif 22#endif
diff --git a/sway/commands.c b/sway/commands.c
index 07e7e53d..5e84ea9a 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -549,12 +549,19 @@ static struct cmd_results *cmd_exec_always(int argc, char **argv) {
549 close(fd[0]); 549 close(fd[0]);
550 // cleanup child process 550 // cleanup child process
551 wait(0); 551 wait(0);
552 if (*child > 0) { 552 swayc_t *ws = swayc_active_workspace();
553 sway_log(L_DEBUG, "Child process created with pid %d", *child); 553 if (*child > 0 && ws) {
554 sway_log(L_DEBUG, "Child process created with pid %d for workspace %s", *child, ws->name);
555 struct pid_workspace *pw = malloc(sizeof(struct pid_workspace));
556 pw->pid = child;
557 pw->workspace = strdup(ws->name);
558 pid_workspace_add(pw);
554 // TODO: keep track of this pid and open the corresponding view on the current workspace 559 // TODO: keep track of this pid and open the corresponding view on the current workspace
555 // blocked pending feature in wlc 560 // blocked pending feature in wlc
561 } else {
562 free(child);
556 } 563 }
557 free(child); 564
558 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 565 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
559} 566}
560 567
diff --git a/sway/config.c b/sway/config.c
index 7530e530..819a70ce 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -89,6 +89,60 @@ static void free_workspace_output(struct workspace_output *wo) {
89 free(wo); 89 free(wo);
90} 90}
91 91
92static void pid_workspace_cleanup() {
93 struct timespec ts;
94 struct pid_workspace *pw = NULL;
95
96 clock_gettime(CLOCK_MONOTONIC, &ts);
97
98 // work backwards through list and remove any entries
99 // older than PID_WORKSPACE_TIMEOUT
100 for (int i = config->pid_workspaces->length - 1; i > -1; i--) {
101 pw = config->pid_workspaces->items[i];
102
103 if (difftime(ts.tv_sec, *pw->time_added) >= PID_WORKSPACE_TIMEOUT) {
104 list_del(config->pid_workspaces, i);
105 }
106 }
107}
108
109// de-dupe pid_workspaces to ensure pid uniqueness
110void pid_workspace_add(struct pid_workspace *pw) {
111 struct pid_workspace *list_pw = NULL;
112 struct timespec ts;
113 time_t *now = malloc(sizeof(time_t));
114
115 pid_workspace_cleanup();
116
117 // add current time to pw
118 clock_gettime(CLOCK_MONOTONIC, &ts);
119 *now = ts.tv_sec;
120
121 pw->time_added = now;
122
123 // work backwards through list and delete any entries that
124 // have the same pid as that in our new pid_workspace
125 for (int i = config->pid_workspaces->length - 1; i > -1; i--) {
126 list_pw = config->pid_workspaces->items[i];
127
128 if (pw->pid == list_pw->pid) {
129 list_del(config->pid_workspaces, i);
130 }
131 }
132
133 list_add(config->pid_workspaces, pw);
134}
135
136void free_pid_workspace(struct pid_workspace *pw) {
137 if (!pw) {
138 return;
139 }
140 free(pw->pid);
141 free(pw->workspace);
142 free(pw->time_added);
143 free(pw);
144}
145
92void free_config(struct sway_config *config) { 146void free_config(struct sway_config *config) {
93 int i; 147 int i;
94 for (i = 0; i < config->symbols->length; ++i) { 148 for (i = 0; i < config->symbols->length; ++i) {
@@ -113,6 +167,11 @@ void free_config(struct sway_config *config) {
113 } 167 }
114 list_free(config->workspace_outputs); 168 list_free(config->workspace_outputs);
115 169
170 for (i = 0; i < config->pid_workspaces->length; ++i) {
171 free_pid_workspace(config->pid_workspaces->items[i]);
172 }
173 list_free(config->pid_workspaces);
174
116 for (i = 0; i < config->criteria->length; ++i) { 175 for (i = 0; i < config->criteria->length; ++i) {
117 free_criteria(config->criteria->items[i]); 176 free_criteria(config->criteria->items[i]);
118 } 177 }
@@ -148,6 +207,7 @@ static void config_defaults(struct sway_config *config) {
148 config->modes = create_list(); 207 config->modes = create_list();
149 config->bars = create_list(); 208 config->bars = create_list();
150 config->workspace_outputs = create_list(); 209 config->workspace_outputs = create_list();
210 config->pid_workspaces = create_list();
151 config->criteria = create_list(); 211 config->criteria = create_list();
152 config->input_configs = create_list(); 212 config->input_configs = create_list();
153 config->output_configs = create_list(); 213 config->output_configs = create_list();
diff --git a/sway/handlers.c b/sway/handlers.c
index f8dd9f4d..b38f05a6 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -180,11 +180,32 @@ static bool handle_view_created(wlc_handle handle) {
180 wlc_handle parent = wlc_view_get_parent(handle); 180 wlc_handle parent = wlc_view_get_parent(handle);
181 swayc_t *focused = NULL; 181 swayc_t *focused = NULL;
182 swayc_t *newview = NULL; 182 swayc_t *newview = NULL;
183 swayc_t *current_ws = swayc_active_workspace();
184 bool return_to_workspace = false;
185 struct wl_client *client = wlc_view_get_wl_client(handle);
186 pid_t pid;
183 187
184 // Get parent container, to add view in 188 // Get parent container, to add view in
185 if (parent) { 189 if (parent) {
186 focused = swayc_by_handle(parent); 190 focused = swayc_by_handle(parent);
187 } 191 }
192
193 if (client) {
194 // below only works on wayland windows. need a wlc
195 // api that will work for both wayland and x.
196 wl_client_get_credentials(client, &pid, NULL, NULL);
197
198 if (pid) {
199 // using newview as a temp storage location here,
200 // rather than adding yet another workspace var
201 if ((newview = workspace_for_pid(pid))) {
202 focused = newview;
203 newview = NULL;
204 return_to_workspace = true;
205 }
206 }
207 }
208
188 if (!focused || focused->type == C_OUTPUT) { 209 if (!focused || focused->type == C_OUTPUT) {
189 focused = get_focused_container(&root_container); 210 focused = get_focused_container(&root_container);
190 // Move focus from floating view 211 // Move focus from floating view
@@ -220,7 +241,7 @@ static bool handle_view_created(wlc_handle handle) {
220 // Dmenu keeps viewfocus, but others with this flag don't, for now simulate 241 // Dmenu keeps viewfocus, but others with this flag don't, for now simulate
221 // dmenu 242 // dmenu
222 case WLC_BIT_OVERRIDE_REDIRECT: 243 case WLC_BIT_OVERRIDE_REDIRECT:
223// locked_view_focus = true; 244 // locked_view_focus = true;
224 wlc_view_focus(handle); 245 wlc_view_focus(handle);
225 wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); 246 wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
226 wlc_view_bring_to_front(handle); 247 wlc_view_bring_to_front(handle);
@@ -273,6 +294,13 @@ static bool handle_view_created(wlc_handle handle) {
273 list_add(output->unmanaged, h); 294 list_add(output->unmanaged, h);
274 } 295 }
275 wlc_view_set_mask(handle, VISIBLE); 296 wlc_view_set_mask(handle, VISIBLE);
297
298 if (return_to_workspace && current_ws) {
299 // we were on one workspace, switched to another to add this view,
300 // now let's return to where we were
301 workspace_switch(current_ws);
302 set_focused_container(current_ws->focused);
303 }
276 return true; 304 return true;
277} 305}
278 306
diff --git a/sway/workspace.c b/sway/workspace.c
index 82573d2e..5319aec4 100644
--- a/sway/workspace.c
+++ b/sway/workspace.c
@@ -5,6 +5,7 @@
5#include <wlc/wlc.h> 5#include <wlc/wlc.h>
6#include <string.h> 6#include <string.h>
7#include <strings.h> 7#include <strings.h>
8#include <sys/types.h>
8#include "ipc-server.h" 9#include "ipc-server.h"
9#include "workspace.h" 10#include "workspace.h"
10#include "layout.h" 11#include "layout.h"
@@ -309,3 +310,54 @@ bool workspace_switch(swayc_t *workspace) {
309 arrange_windows(output, -1, -1); 310 arrange_windows(output, -1, -1);
310 return true; 311 return true;
311} 312}
313
314swayc_t *workspace_for_pid(pid_t pid) {
315 int i;
316 swayc_t *ws = NULL;
317 struct pid_workspace *pw = NULL;
318
319 sway_log(L_DEBUG, "looking for workspace for pid %d", pid);
320
321 // leaving this here as it's useful for debugging
322 // sway_log(L_DEBUG, "all pid_workspaces");
323 // for (int k = 0; k < config->pid_workspaces->length; k++) {
324 // pw = config->pid_workspaces->items[k];
325 // sway_log(L_DEBUG, "pid %d workspace %s time_added %li", *pw->pid, pw->workspace, *pw->time_added);
326 // }
327
328 do {
329 for (i = 0; i < config->pid_workspaces->length; i++) {
330 pw = config->pid_workspaces->items[i];
331 pid_t *pw_pid = pw->pid;
332
333 if (pid == *pw_pid) {
334 sway_log(L_DEBUG, "found pid_workspace for pid %d, workspace %s", pid, pw->workspace);
335 break; // out of for loop
336 }
337
338 pw = NULL;
339 }
340
341 if (pw) {
342 break; // out of do-while loop
343 }
344
345 pid = get_parent_pid(pid);
346 // no sense in looking for matches for pid 0.
347 // also, if pid == getpid(), that is the compositor's
348 // pid, which definitely isn't helpful
349 } while (pid > 0 && pid != getpid());
350
351 if (pw) {
352 ws = workspace_by_name(pw->workspace);
353
354 if (!ws) {
355 sway_log(L_DEBUG, "Creating workspace %s for pid %d because it disappeared", pw->workspace, pid);
356 ws = workspace_create(pw->workspace);
357 }
358
359 list_del(config->pid_workspaces, i);
360 }
361
362 return ws;
363}