diff options
-rw-r--r-- | sway/tree/workspace.c | 159 |
1 files changed, 83 insertions, 76 deletions
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 622f01ec..e450b87f 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -107,96 +107,103 @@ static bool workspace_valid_on_output(const char *output_name, | |||
107 | return true; | 107 | return true; |
108 | } | 108 | } |
109 | 109 | ||
110 | char *workspace_next_name(const char *output_name) { | 110 | static void workspace_name_from_binding(const struct sway_binding * binding, |
111 | wlr_log(WLR_DEBUG, "Workspace: Generating new workspace name for output %s", | 111 | const char* output_name, int *min_order, char **earliest_name) { |
112 | output_name); | 112 | char *cmdlist = strdup(binding->command); |
113 | // Scan all workspace bindings to find the next available workspace name, | 113 | char *dup = cmdlist; |
114 | // if none are found/available then default to a number | 114 | char *name = NULL; |
115 | struct sway_mode *mode = config->current_mode; | 115 | |
116 | 116 | // workspace n | |
117 | // TODO: iterate over keycode bindings too | 117 | char *cmd = argsep(&cmdlist, " "); |
118 | int order = INT_MAX; | 118 | if (cmdlist) { |
119 | char *target = NULL; | 119 | name = argsep(&cmdlist, ",;"); |
120 | for (int i = 0; i < mode->keysym_bindings->length; ++i) { | 120 | } |
121 | struct sway_binding *binding = mode->keysym_bindings->items[i]; | 121 | |
122 | char *cmdlist = strdup(binding->command); | 122 | if (strcmp("workspace", cmd) == 0 && name) { |
123 | char *dup = cmdlist; | 123 | char *_target = strdup(name); |
124 | char *name = NULL; | 124 | _target = do_var_replacement(_target); |
125 | 125 | strip_quotes(_target); | |
126 | // workspace n | 126 | while (isspace(*_target)) { |
127 | char *cmd = argsep(&cmdlist, " "); | 127 | memmove(_target, _target+1, strlen(_target+1)); |
128 | if (cmdlist) { | ||
129 | name = argsep(&cmdlist, ",;"); | ||
130 | } | 128 | } |
129 | wlr_log(WLR_DEBUG, "Got valid workspace command for target: '%s'", | ||
130 | _target); | ||
131 | 131 | ||
132 | if (strcmp("workspace", cmd) == 0 && name) { | 132 | // Make sure that the command references an actual workspace |
133 | char *_target = strdup(name); | 133 | // not a command about workspaces |
134 | _target = do_var_replacement(_target); | 134 | if (strcmp(_target, "next") == 0 || |
135 | strip_quotes(_target); | ||
136 | while (isspace(*_target)) { | ||
137 | memmove(_target, _target+1, strlen(_target+1)); | ||
138 | } | ||
139 | wlr_log(WLR_DEBUG, "Got valid workspace command for target: '%s'", | ||
140 | _target); | ||
141 | |||
142 | // Make sure that the command references an actual workspace | ||
143 | // not a command about workspaces | ||
144 | if (strcmp(_target, "next") == 0 || | ||
145 | strcmp(_target, "prev") == 0 || | 135 | strcmp(_target, "prev") == 0 || |
146 | strcmp(_target, "next_on_output") == 0 || | 136 | strcmp(_target, "next_on_output") == 0 || |
147 | strcmp(_target, "prev_on_output") == 0 || | 137 | strcmp(_target, "prev_on_output") == 0 || |
148 | strcmp(_target, "number") == 0 || | 138 | strcmp(_target, "number") == 0 || |
149 | strcmp(_target, "back_and_forth") == 0 || | 139 | strcmp(_target, "back_and_forth") == 0 || |
150 | strcmp(_target, "current") == 0) | 140 | strcmp(_target, "current") == 0) { |
151 | { | 141 | free(_target); |
152 | free(_target); | 142 | free(dup); |
153 | free(dup); | 143 | return; |
154 | continue; | 144 | } |
155 | } | ||
156 | |||
157 | // If the command is workspace number <name>, isolate the name | ||
158 | if (strncmp(_target, "number ", strlen("number ")) == 0) { | ||
159 | size_t length = strlen(_target) - strlen("number ") + 1; | ||
160 | char *temp = malloc(length); | ||
161 | strncpy(temp, _target + strlen("number "), length - 1); | ||
162 | temp[length - 1] = '\0'; | ||
163 | free(_target); | ||
164 | _target = temp; | ||
165 | wlr_log(WLR_DEBUG, "Isolated name from workspace number: '%s'", _target); | ||
166 | |||
167 | // Make sure the workspace number doesn't already exist | ||
168 | if (workspace_by_number(_target)) { | ||
169 | free(_target); | ||
170 | free(dup); | ||
171 | continue; | ||
172 | } | ||
173 | } | ||
174 | 145 | ||
175 | // Make sure that the workspace doesn't already exist | 146 | // If the command is workspace number <name>, isolate the name |
176 | if (workspace_by_name(_target)) { | 147 | if (strncmp(_target, "number ", strlen("number ")) == 0) { |
148 | size_t length = strlen(_target) - strlen("number ") + 1; | ||
149 | char *temp = malloc(length); | ||
150 | strncpy(temp, _target + strlen("number "), length - 1); | ||
151 | temp[length - 1] = '\0'; | ||
152 | free(_target); | ||
153 | _target = temp; | ||
154 | wlr_log(WLR_DEBUG, "Isolated name from workspace number: '%s'", _target); | ||
155 | |||
156 | // Make sure the workspace number doesn't already exist | ||
157 | if (workspace_by_number(_target)) { | ||
177 | free(_target); | 158 | free(_target); |
178 | free(dup); | 159 | free(dup); |
179 | continue; | 160 | return; |
180 | } | 161 | } |
162 | } | ||
181 | 163 | ||
182 | // make sure that the workspace can appear on the given | 164 | // Make sure that the workspace doesn't already exist |
183 | // output | 165 | if (workspace_by_name(_target)) { |
184 | if (!workspace_valid_on_output(output_name, _target)) { | 166 | free(_target); |
185 | free(_target); | 167 | free(dup); |
186 | free(dup); | 168 | return; |
187 | continue; | 169 | } |
188 | } | ||
189 | 170 | ||
190 | if (binding->order < order) { | 171 | // make sure that the workspace can appear on the given |
191 | order = binding->order; | 172 | // output |
192 | free(target); | 173 | if (!workspace_valid_on_output(output_name, _target)) { |
193 | target = _target; | 174 | free(_target); |
194 | wlr_log(WLR_DEBUG, "Workspace: Found free name %s", _target); | 175 | free(dup); |
195 | } else { | 176 | return; |
196 | free(_target); | ||
197 | } | ||
198 | } | 177 | } |
199 | free(dup); | 178 | |
179 | if (binding->order < *min_order) { | ||
180 | *min_order = binding->order; | ||
181 | free(*earliest_name); | ||
182 | *earliest_name = _target; | ||
183 | wlr_log(WLR_DEBUG, "Workspace: Found free name %s", _target); | ||
184 | } else { | ||
185 | free(_target); | ||
186 | } | ||
187 | } | ||
188 | free(dup); | ||
189 | } | ||
190 | |||
191 | char *workspace_next_name(const char *output_name) { | ||
192 | wlr_log(WLR_DEBUG, "Workspace: Generating new workspace name for output %s", | ||
193 | output_name); | ||
194 | // Scan all workspace bindings to find the next available workspace name, | ||
195 | // if none are found/available then default to a number | ||
196 | struct sway_mode *mode = config->current_mode; | ||
197 | |||
198 | int order = INT_MAX; | ||
199 | char *target = NULL; | ||
200 | for (int i = 0; i < mode->keysym_bindings->length; ++i) { | ||
201 | workspace_name_from_binding(mode->keysym_bindings->items[i], | ||
202 | output_name, &order, &target); | ||
203 | } | ||
204 | for (int i = 0; i < mode->keycode_bindings->length; ++i) { | ||
205 | workspace_name_from_binding(mode->keycode_bindings->items[i], | ||
206 | output_name, &order, &target); | ||
200 | } | 207 | } |
201 | if (target != NULL) { | 208 | if (target != NULL) { |
202 | return target; | 209 | return target; |