diff options
author | Drew DeVault <sir@cmpwn.com> | 2015-08-17 11:37:19 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2015-08-17 11:37:19 -0400 |
commit | b48e8d1b178f2c713579dc532ff4be6edfccc5bc (patch) | |
tree | f9da3981625cd2235961f8efee7c4f3a94649241 | |
parent | Fix format warnings (diff) | |
parent | Style and other minor fixes (diff) | |
download | sway-b48e8d1b178f2c713579dc532ff4be6edfccc5bc.tar.gz sway-b48e8d1b178f2c713579dc532ff4be6edfccc5bc.tar.zst sway-b48e8d1b178f2c713579dc532ff4be6edfccc5bc.zip |
Merge pull request #54 from Luminarys/master
Added in basic floating support
-rw-r--r-- | include/container.h | 10 | ||||
-rw-r--r-- | sway/commands.c | 73 | ||||
-rw-r--r-- | sway/container.c | 56 | ||||
-rw-r--r-- | sway/handlers.c | 49 | ||||
-rw-r--r-- | sway/layout.c | 56 | ||||
-rw-r--r-- | sway/workspace.c | 13 |
6 files changed, 245 insertions, 12 deletions
diff --git a/include/container.h b/include/container.h index dd934be6..e395a55b 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -36,16 +36,24 @@ struct sway_container { | |||
36 | // Not including borders or margins | 36 | // Not including borders or margins |
37 | int width, height; | 37 | int width, height; |
38 | 38 | ||
39 | // Used for setting floating geometry | ||
40 | int desired_width, desired_height; | ||
41 | |||
39 | int x, y; | 42 | int x, y; |
40 | 43 | ||
41 | bool visible; | 44 | bool visible; |
42 | 45 | ||
46 | bool is_floating; | ||
47 | |||
43 | int weight; | 48 | int weight; |
44 | 49 | ||
45 | char *name; | 50 | char *name; |
46 | 51 | ||
47 | list_t *children; | 52 | list_t *children; |
48 | 53 | ||
54 | // Special list for floating windows in workspaces | ||
55 | list_t *floating; | ||
56 | |||
49 | struct sway_container *parent; | 57 | struct sway_container *parent; |
50 | struct sway_container *focused; | 58 | struct sway_container *focused; |
51 | }; | 59 | }; |
@@ -57,6 +65,8 @@ swayc_t *new_workspace(swayc_t * output, const char *name); | |||
57 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); | 65 | swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); |
58 | //Creates view as a sibling of current focused container, or as child of a workspace | 66 | //Creates view as a sibling of current focused container, or as child of a workspace |
59 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle); | 67 | swayc_t *new_view(swayc_t *sibling, wlc_handle handle); |
68 | //Creates view as a new floating view which is in the active workspace | ||
69 | swayc_t *new_floating_view(wlc_handle handle); | ||
60 | 70 | ||
61 | 71 | ||
62 | swayc_t *destroy_output(swayc_t *output); | 72 | swayc_t *destroy_output(swayc_t *output); |
diff --git a/sway/commands.c b/sway/commands.c index f0db4ed2..5035316e 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "workspace.h" | 13 | #include "workspace.h" |
14 | #include "commands.h" | 14 | #include "commands.h" |
15 | #include "container.h" | 15 | #include "container.h" |
16 | #include "handlers.h" | ||
16 | 17 | ||
17 | struct modifier_key { | 18 | struct modifier_key { |
18 | char *name; | 19 | char *name; |
@@ -169,6 +170,77 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) { | |||
169 | return true; | 170 | return true; |
170 | } | 171 | } |
171 | 172 | ||
173 | static bool cmd_floating(struct sway_config *config, int argc, char **argv) { | ||
174 | if (strcasecmp(argv[0], "toggle") == 0) { | ||
175 | swayc_t *view = get_focused_container(&root_container); | ||
176 | // Prevent running floating commands on things like workspaces | ||
177 | if (view->type != C_VIEW) { | ||
178 | return true; | ||
179 | } | ||
180 | int i; | ||
181 | // Change from nonfloating to floating | ||
182 | if (!view->is_floating) { | ||
183 | view->is_floating = true; | ||
184 | for (i = 0; i < view->parent->children->length; i++) { | ||
185 | if (view->parent->children->items[i] == view) { | ||
186 | // Try to use desired geometry to set w/h | ||
187 | if (view->desired_width != -1) { | ||
188 | view->width = view->desired_width; | ||
189 | } | ||
190 | if (view->desired_height != -1) { | ||
191 | view->height = view->desired_height; | ||
192 | } | ||
193 | |||
194 | // Swap from the list of whatever container the view was in | ||
195 | // to the workspace->floating list | ||
196 | list_del(view->parent->children, i); | ||
197 | list_add(active_workspace->floating, view); | ||
198 | destroy_container(view->parent); | ||
199 | |||
200 | // Set the new position of the container and arrange windows | ||
201 | view->x = (active_workspace->width - view->width)/2; | ||
202 | view->y = (active_workspace->height - view->height)/2; | ||
203 | sway_log(L_INFO, "Setting container %p to floating at coordinates X:%d Y:%d, W:%d, H:%d", view, view->x, view->y, view->width, view->height); | ||
204 | // Change parent to active_workspace | ||
205 | view->parent = active_workspace; | ||
206 | arrange_windows(active_workspace, -1, -1); | ||
207 | return true; | ||
208 | } | ||
209 | } | ||
210 | } else { | ||
211 | // Delete the view from the floating list and unset its is_floating flag | ||
212 | // Using length-1 as the index is safe because the view must be the currently | ||
213 | // focused floating output | ||
214 | list_del(active_workspace->floating, active_workspace->floating->length - 1); | ||
215 | view->is_floating = false; | ||
216 | active_workspace->focused = NULL; | ||
217 | // Get the properly focused container, and add in the view there | ||
218 | swayc_t *focused = focus_pointer(); | ||
219 | // If focused is null, it's because the currently focused container is a workspace | ||
220 | if (focused == NULL) { | ||
221 | focused = active_workspace; | ||
222 | } | ||
223 | |||
224 | sway_log(L_DEBUG, "Non-floating focused container is %p", focused); | ||
225 | |||
226 | //Case of focused workspace, just create as child of it | ||
227 | if (focused->type == C_WORKSPACE) { | ||
228 | add_child(focused, view); | ||
229 | } | ||
230 | //Regular case, create as sibling of current container | ||
231 | else { | ||
232 | add_sibling(focused, view); | ||
233 | } | ||
234 | // Refocus on the view once its been put back into the layout | ||
235 | focus_view(view); | ||
236 | arrange_windows(active_workspace, -1, -1); | ||
237 | return true; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return true; | ||
242 | } | ||
243 | |||
172 | static bool cmd_focus(struct sway_config *config, int argc, char **argv) { | 244 | static bool cmd_focus(struct sway_config *config, int argc, char **argv) { |
173 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { | 245 | if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) { |
174 | return false; | 246 | return false; |
@@ -378,6 +450,7 @@ static struct cmd_handler handlers[] = { | |||
378 | { "exec", cmd_exec }, | 450 | { "exec", cmd_exec }, |
379 | { "exec_always", cmd_exec_always }, | 451 | { "exec_always", cmd_exec_always }, |
380 | { "exit", cmd_exit }, | 452 | { "exit", cmd_exit }, |
453 | { "floating", cmd_floating }, | ||
381 | { "focus", cmd_focus }, | 454 | { "focus", cmd_focus }, |
382 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 455 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
383 | { "fullscreen", cmd_fullscreen }, | 456 | { "fullscreen", cmd_fullscreen }, |
diff --git a/sway/container.c b/sway/container.c index 4321b6ce..231876c5 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -81,6 +81,7 @@ swayc_t *new_workspace(swayc_t * output, const char *name) { | |||
81 | workspace->height = output->height; | 81 | workspace->height = output->height; |
82 | workspace->name = strdup(name); | 82 | workspace->name = strdup(name); |
83 | workspace->visible = true; | 83 | workspace->visible = true; |
84 | workspace->floating = create_list(); | ||
84 | 85 | ||
85 | add_child(output, workspace); | 86 | add_child(output, workspace); |
86 | return workspace; | 87 | return workspace; |
@@ -134,6 +135,12 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | |||
134 | view->name = strdup(title); | 135 | view->name = strdup(title); |
135 | view->visible = true; | 136 | view->visible = true; |
136 | 137 | ||
138 | view->desired_width = -1; | ||
139 | view->desired_height = -1; | ||
140 | |||
141 | // TODO: properly set this | ||
142 | view->is_floating = false; | ||
143 | |||
137 | //Case of focused workspace, just create as child of it | 144 | //Case of focused workspace, just create as child of it |
138 | if (sibling->type == C_WORKSPACE) { | 145 | if (sibling->type == C_WORKSPACE) { |
139 | add_child(sibling, view); | 146 | add_child(sibling, view); |
@@ -145,6 +152,38 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | |||
145 | return view; | 152 | return view; |
146 | } | 153 | } |
147 | 154 | ||
155 | swayc_t *new_floating_view(wlc_handle handle) { | ||
156 | const char *title = wlc_view_get_title(handle); | ||
157 | swayc_t *view = new_swayc(C_VIEW); | ||
158 | sway_log(L_DEBUG, "Adding new view %u:%s as a floating view", | ||
159 | (unsigned int)handle, title); | ||
160 | //Setup values | ||
161 | view->handle = handle; | ||
162 | view->name = strdup(title); | ||
163 | view->visible = true; | ||
164 | |||
165 | // Set the geometry of the floating view | ||
166 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); | ||
167 | |||
168 | view->x = geometry->origin.x; | ||
169 | view->y = geometry->origin.y; | ||
170 | view->width = geometry->size.w; | ||
171 | view->height = geometry->size.h; | ||
172 | |||
173 | view->desired_width = view->width; | ||
174 | view->desired_height = view->height; | ||
175 | |||
176 | view->is_floating = true; | ||
177 | |||
178 | //Case of focused workspace, just create as child of it | ||
179 | list_add(active_workspace->floating, view); | ||
180 | view->parent = active_workspace; | ||
181 | if (active_workspace->focused == NULL) { | ||
182 | active_workspace->focused = view; | ||
183 | } | ||
184 | return view; | ||
185 | } | ||
186 | |||
148 | 187 | ||
149 | swayc_t *destroy_output(swayc_t *output) { | 188 | swayc_t *destroy_output(swayc_t *output) { |
150 | if (output->children->length == 0) { | 189 | if (output->children->length == 0) { |
@@ -192,23 +231,32 @@ swayc_t *destroy_view(swayc_t *view) { | |||
192 | if (parent->type == C_CONTAINER) { | 231 | if (parent->type == C_CONTAINER) { |
193 | return destroy_container(parent); | 232 | return destroy_container(parent); |
194 | } | 233 | } |
234 | |||
195 | return parent; | 235 | return parent; |
196 | } | 236 | } |
197 | 237 | ||
198 | |||
199 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { | 238 | swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { |
200 | if (!container->children) { | 239 | if (!container->children) { |
201 | return NULL; | 240 | return NULL; |
202 | } | 241 | } |
242 | // Special case for checking floating stuff | ||
203 | int i; | 243 | int i; |
244 | if (container->type == C_WORKSPACE) { | ||
245 | for (i = 0; i < container->floating->length; ++i) { | ||
246 | swayc_t *child = container->floating->items[i]; | ||
247 | if (test(child, data)) { | ||
248 | return child; | ||
249 | } | ||
250 | } | ||
251 | } | ||
204 | for (i = 0; i < container->children->length; ++i) { | 252 | for (i = 0; i < container->children->length; ++i) { |
205 | swayc_t *child = container->children->items[i]; | 253 | swayc_t *child = container->children->items[i]; |
206 | if (test(child, data)) { | 254 | if (test(child, data)) { |
207 | return child; | 255 | return child; |
208 | } else { | 256 | } else { |
209 | swayc_t *_ = find_container(child, test, data); | 257 | swayc_t *res = find_container(child, test, data); |
210 | if (_) { | 258 | if (res) { |
211 | return _; | 259 | return res; |
212 | } | 260 | } |
213 | } | 261 | } |
214 | } | 262 | } |
diff --git a/sway/handlers.c b/sway/handlers.c index 3e83b850..77e8f237 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "handlers.h" | 10 | #include "handlers.h" |
11 | #include "stringop.h" | 11 | #include "stringop.h" |
12 | #include "workspace.h" | 12 | #include "workspace.h" |
13 | #include "container.h" | ||
13 | 14 | ||
14 | static struct wlc_origin mouse_origin; | 15 | static struct wlc_origin mouse_origin; |
15 | 16 | ||
@@ -88,17 +89,24 @@ static void handle_output_focused(wlc_handle output, bool focus) { | |||
88 | static bool handle_view_created(wlc_handle handle) { | 89 | static bool handle_view_created(wlc_handle handle) { |
89 | swayc_t *focused = get_focused_container(&root_container); | 90 | swayc_t *focused = get_focused_container(&root_container); |
90 | uint32_t type = wlc_view_get_type(handle); | 91 | uint32_t type = wlc_view_get_type(handle); |
91 | //If override_redirect/unmanaged/popup/modal/splach | 92 | // If override_redirect/unmanaged/popup/modal/splach |
92 | if (type) { | 93 | if (type) { |
93 | sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type); | 94 | sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type); |
94 | wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); | 95 | wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); |
95 | if (type & WLC_BIT_UNMANAGED) { | 96 | if (type & WLC_BIT_UNMANAGED) { |
96 | return true; | 97 | return true; |
97 | } | 98 | } |
98 | //for things like Dmenu | 99 | // For things like Dmenu |
99 | if (type & WLC_BIT_OVERRIDE_REDIRECT) { | 100 | if (type & WLC_BIT_OVERRIDE_REDIRECT) { |
100 | wlc_view_focus(handle); | 101 | wlc_view_focus(handle); |
101 | } | 102 | } |
103 | |||
104 | // Float popups | ||
105 | if (type & WLC_BIT_POPUP) { | ||
106 | swayc_t *view = new_floating_view(handle); | ||
107 | focus_view(view); | ||
108 | arrange_windows(active_workspace, -1, -1); | ||
109 | } | ||
102 | } else { | 110 | } else { |
103 | swayc_t *view = new_view(focused, handle); | 111 | swayc_t *view = new_view(focused, handle); |
104 | //Set maximize flag for windows. | 112 | //Set maximize flag for windows. |
@@ -118,6 +126,24 @@ static bool handle_view_created(wlc_handle handle) { | |||
118 | 126 | ||
119 | static void handle_view_destroyed(wlc_handle handle) { | 127 | static void handle_view_destroyed(wlc_handle handle) { |
120 | sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle); | 128 | sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle); |
129 | |||
130 | // Properly handle unmanaged views | ||
131 | uint32_t type = wlc_view_get_type(handle); | ||
132 | if (type) { | ||
133 | wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); | ||
134 | sway_log(L_DEBUG,"Unmanaged window of type %x was destroyed", type); | ||
135 | if (type & WLC_BIT_UNMANAGED) { | ||
136 | focus_view(focus_pointer()); | ||
137 | arrange_windows(active_workspace, -1, -1); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | if (type & WLC_BIT_OVERRIDE_REDIRECT) { | ||
142 | focus_view(focus_pointer()); | ||
143 | arrange_windows(active_workspace, -1, -1); | ||
144 | return; | ||
145 | } | ||
146 | } | ||
121 | swayc_t *view = get_swayc_for_handle(handle, &root_container); | 147 | swayc_t *view = get_swayc_for_handle(handle, &root_container); |
122 | swayc_t *parent; | 148 | swayc_t *parent; |
123 | swayc_t *focused = get_focused_container(&root_container); | 149 | swayc_t *focused = get_focused_container(&root_container); |
@@ -135,8 +161,23 @@ static void handle_view_focus(wlc_handle view, bool focus) { | |||
135 | return; | 161 | return; |
136 | } | 162 | } |
137 | 163 | ||
138 | static void handle_view_geometry_request(wlc_handle view, const struct wlc_geometry* geometry) { | 164 | static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) { |
139 | // deny that shit | 165 | // If the view is floating, then apply the geometry. |
166 | // Otherwise save the desired width/height for the view. | ||
167 | // This will not do anything for the time being as WLC improperly sends geometry requests | ||
168 | swayc_t *view = get_swayc_for_handle(handle, &root_container); | ||
169 | if (view) { | ||
170 | view->desired_width = geometry->size.w; | ||
171 | view->desired_height = geometry->size.h; | ||
172 | |||
173 | if (view->is_floating) { | ||
174 | view->width = view->desired_width; | ||
175 | view->height = view->desired_height; | ||
176 | view->x = geometry->origin.x; | ||
177 | view->y = geometry->origin.y; | ||
178 | arrange_windows(view->parent, -1, -1); | ||
179 | } | ||
180 | } | ||
140 | } | 181 | } |
141 | 182 | ||
142 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { | 183 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { |
diff --git a/sway/layout.c b/sway/layout.c index 4407742a..1bc65050 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -65,10 +65,20 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { | |||
65 | 65 | ||
66 | swayc_t *remove_child(swayc_t *parent, swayc_t *child) { | 66 | swayc_t *remove_child(swayc_t *parent, swayc_t *child) { |
67 | int i; | 67 | int i; |
68 | for (i = 0; i < parent->children->length; ++i) { | 68 | // Special case for floating views |
69 | if (parent->children->items[i] == child) { | 69 | if (child->is_floating) { |
70 | list_del(parent->children, i); | 70 | for (i = 0; i < parent->floating->length; ++i) { |
71 | break; | 71 | if (parent->floating->items[i] == child) { |
72 | list_del(parent->floating, i); | ||
73 | break; | ||
74 | } | ||
75 | } | ||
76 | } else { | ||
77 | for (i = 0; i < parent->children->length; ++i) { | ||
78 | if (parent->children->items[i] == child) { | ||
79 | list_del(parent->children, i); | ||
80 | break; | ||
81 | } | ||
72 | } | 82 | } |
73 | } | 83 | } |
74 | if (parent->focused == child) { | 84 | if (parent->focused == child) { |
@@ -192,6 +202,33 @@ void arrange_windows(swayc_t *container, int width, int height) { | |||
192 | } | 202 | } |
193 | break; | 203 | break; |
194 | } | 204 | } |
205 | |||
206 | // Arrage floating layouts for workspaces last | ||
207 | if (container->type == C_WORKSPACE) { | ||
208 | for (i = 0; i < container->floating->length; ++i) { | ||
209 | swayc_t *view = ((swayc_t *)container->floating->items[i]); | ||
210 | // Set the geometry | ||
211 | struct wlc_geometry geometry = { | ||
212 | .origin = { | ||
213 | .x = view->x, | ||
214 | .y = view->y | ||
215 | }, | ||
216 | .size = { | ||
217 | .w = view->width, | ||
218 | .h = view->height | ||
219 | } | ||
220 | }; | ||
221 | wlc_view_set_geometry(view->handle, &geometry); | ||
222 | |||
223 | // Bring the views to the front in order of the list, the list | ||
224 | // will be kept up to date so that more recently focused views | ||
225 | // have higher indexes | ||
226 | // This is conditional on there not being a fullscreen view in the workspace | ||
227 | if (!(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) { | ||
228 | wlc_view_bring_to_front(view->handle); | ||
229 | } | ||
230 | } | ||
231 | } | ||
195 | layout_log(&root_container, 0); | 232 | layout_log(&root_container, 0); |
196 | } | 233 | } |
197 | 234 | ||
@@ -199,7 +236,18 @@ swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { | |||
199 | if (parent->children == NULL) { | 236 | if (parent->children == NULL) { |
200 | return NULL; | 237 | return NULL; |
201 | } | 238 | } |
239 | |||
240 | // Search for floating workspaces | ||
202 | int i; | 241 | int i; |
242 | if (parent->type == C_WORKSPACE) { | ||
243 | for (i = 0; i < parent->floating->length; ++i) { | ||
244 | swayc_t *child = parent->floating->items[i]; | ||
245 | if (child->handle == handle) { | ||
246 | return child; | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
203 | for (i = 0; i < parent->children->length; ++i) { | 251 | for (i = 0; i < parent->children->length; ++i) { |
204 | swayc_t *child = parent->children->items[i]; | 252 | swayc_t *child = parent->children->items[i]; |
205 | if (child->handle == handle) { | 253 | if (child->handle == handle) { |
diff --git a/sway/workspace.c b/sway/workspace.c index 4db75f48..df646445 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -255,5 +255,18 @@ void layout_log(const swayc_t *c, int depth) { | |||
255 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | 255 | for (i = 0; i < depth; ++i) fputc(' ', stderr); |
256 | fprintf(stderr,")\n"); | 256 | fprintf(stderr,")\n"); |
257 | } | 257 | } |
258 | if (c->type == C_WORKSPACE) { | ||
259 | e = c->floating?c->floating->length:0; | ||
260 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
261 | if (e) { | ||
262 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
263 | fprintf(stderr,"(\n"); | ||
264 | for (i = 0; i < e; ++i) { | ||
265 | layout_log(c->floating->items[i], depth + 1); | ||
266 | } | ||
267 | for (i = 0; i < depth; ++i) fputc(' ', stderr); | ||
268 | fprintf(stderr,")\n"); | ||
269 | } | ||
270 | } | ||
258 | } | 271 | } |
259 | /* XXX:DEBUG:XXX */ | 272 | /* XXX:DEBUG:XXX */ |