aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/focus.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-25 12:09:42 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-25 12:09:42 +1000
commitf4bc25bcc6c822e264938447940b7d75fa84319b (patch)
treeb04befcfad9b7c679b1dec388d168901fc5daf86 /sway/commands/focus.c
parentMerge pull request #2499 from RyanDwyer/refactor-destroy-functions (diff)
downloadsway-f4bc25bcc6c822e264938447940b7d75fa84319b.tar.gz
sway-f4bc25bcc6c822e264938447940b7d75fa84319b.tar.zst
sway-f4bc25bcc6c822e264938447940b7d75fa84319b.zip
Relocate container_move, container_move_to and container_get_in_direction
* container_move is only called from the move command * container_move_to was called from both the move command and the sticky command, but the sticky command can easily not call it * container_get_in_direction is only called from the focus command Moving these functions to their respective commands gives better separation of code and removes bloat from layout.c. These functions will need to be refactored to take advantage of type safety, so separating them will make this easier to refactor. The following static functions have also been moved: * is_parellel * invert_movement * move_offs * container_limit * workspace_rejigger * move_out_of_tabs_stacks * get_swayc_in_output_direction They were all used by the move functions, except for the last one which is used by focus. Other changes: * index_child has been renamed to container_sibling_index, moved to container.c and made public * sway_output_from_wlr has been renamed to output_from_wlr_output, moved to output.c and made public * container_handle_fullscreen_reparent has been made public * sway_dir_to_wlr has been made public No changes have been made to any of the moved functions, other than updating calls to functions that have been renamed.
Diffstat (limited to 'sway/commands/focus.c')
-rw-r--r--sway/commands/focus.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 6659a683..a9fa9a0f 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -31,6 +31,199 @@ static bool parse_movement_direction(const char *name,
31 return true; 31 return true;
32} 32}
33 33
34/**
35 * Get swayc in the direction of newly entered output.
36 */
37static struct sway_container *get_swayc_in_output_direction(
38 struct sway_container *output, enum movement_direction dir,
39 struct sway_seat *seat) {
40 if (!output) {
41 return NULL;
42 }
43
44 struct sway_container *ws = seat_get_focus_inactive(seat, output);
45 if (ws->type != C_WORKSPACE) {
46 ws = container_parent(ws, C_WORKSPACE);
47 }
48
49 if (ws == NULL) {
50 wlr_log(WLR_ERROR, "got an output without a workspace");
51 return NULL;
52 }
53
54 if (ws->children->length > 0) {
55 switch (dir) {
56 case MOVE_LEFT:
57 if (ws->layout == L_HORIZ || ws->layout == L_TABBED) {
58 // get most right child of new output
59 return ws->children->items[ws->children->length-1];
60 } else {
61 return seat_get_focus_inactive(seat, ws);
62 }
63 case MOVE_RIGHT:
64 if (ws->layout == L_HORIZ || ws->layout == L_TABBED) {
65 // get most left child of new output
66 return ws->children->items[0];
67 } else {
68 return seat_get_focus_inactive(seat, ws);
69 }
70 case MOVE_UP:
71 case MOVE_DOWN: {
72 struct sway_container *focused =
73 seat_get_focus_inactive(seat, ws);
74 if (focused && focused->parent) {
75 struct sway_container *parent = focused->parent;
76 if (parent->layout == L_VERT) {
77 if (dir == MOVE_UP) {
78 // get child furthest down on new output
79 int idx = parent->children->length - 1;
80 return parent->children->items[idx];
81 } else if (dir == MOVE_DOWN) {
82 // get child furthest up on new output
83 return parent->children->items[0];
84 }
85 }
86 return focused;
87 }
88 break;
89 }
90 default:
91 break;
92 }
93 }
94
95 return ws;
96}
97
98static struct sway_container *container_get_in_direction(
99 struct sway_container *container, struct sway_seat *seat,
100 enum movement_direction dir) {
101 struct sway_container *parent = container->parent;
102
103 if (dir == MOVE_CHILD) {
104 return seat_get_focus_inactive(seat, container);
105 }
106 if (container->is_fullscreen) {
107 if (dir == MOVE_PARENT) {
108 return NULL;
109 }
110 container = container_parent(container, C_OUTPUT);
111 parent = container->parent;
112 } else {
113 if (dir == MOVE_PARENT) {
114 if (parent->type == C_OUTPUT || container_is_floating(container)) {
115 return NULL;
116 } else {
117 return parent;
118 }
119 }
120 }
121
122 struct sway_container *wrap_candidate = NULL;
123 while (true) {
124 bool can_move = false;
125 int desired;
126 int idx = list_find(container->parent->children, container);
127 if (idx == -1) {
128 return NULL;
129 }
130 if (parent->type == C_ROOT) {
131 enum wlr_direction wlr_dir = 0;
132 if (!sway_assert(sway_dir_to_wlr(dir, &wlr_dir),
133 "got invalid direction: %d", dir)) {
134 return NULL;
135 }
136 int lx = container->x + container->width / 2;
137 int ly = container->y + container->height / 2;
138 struct wlr_output_layout *layout =
139 root_container.sway_root->output_layout;
140 struct wlr_output *wlr_adjacent =
141 wlr_output_layout_adjacent_output(layout, wlr_dir,
142 container->sway_output->wlr_output, lx, ly);
143 struct sway_container *adjacent =
144 output_from_wlr_output(wlr_adjacent);
145
146 if (!adjacent || adjacent == container) {
147 if (!wrap_candidate) {
148 return NULL;
149 }
150 return seat_get_focus_inactive_view(seat, wrap_candidate);
151 }
152 struct sway_container *next =
153 get_swayc_in_output_direction(adjacent, dir, seat);
154 if (next == NULL) {
155 return NULL;
156 }
157 struct sway_container *next_workspace = next;
158 if (next_workspace->type != C_WORKSPACE) {
159 next_workspace = container_parent(next_workspace, C_WORKSPACE);
160 }
161 sway_assert(next_workspace, "Next container has no workspace");
162 if (next_workspace->sway_workspace->fullscreen) {
163 return seat_get_focus_inactive(seat,
164 next_workspace->sway_workspace->fullscreen);
165 }
166 if (next->children && next->children->length) {
167 // TODO consider floating children as well
168 return seat_get_focus_inactive_view(seat, next);
169 } else {
170 return next;
171 }
172 } else {
173 if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
174 if (parent->layout == L_HORIZ || parent->layout == L_TABBED) {
175 can_move = true;
176 desired = idx + (dir == MOVE_LEFT ? -1 : 1);
177 }
178 } else {
179 if (parent->layout == L_VERT || parent->layout == L_STACKED) {
180 can_move = true;
181 desired = idx + (dir == MOVE_UP ? -1 : 1);
182 }
183 }
184 }
185
186 if (can_move) {
187 // TODO handle floating
188 if (desired < 0 || desired >= parent->children->length) {
189 can_move = false;
190 int len = parent->children->length;
191 if (config->focus_wrapping != WRAP_NO && !wrap_candidate
192 && len > 1) {
193 if (desired < 0) {
194 wrap_candidate = parent->children->items[len-1];
195 } else {
196 wrap_candidate = parent->children->items[0];
197 }
198 if (config->focus_wrapping == WRAP_FORCE) {
199 return seat_get_focus_inactive_view(seat,
200 wrap_candidate);
201 }
202 }
203 } else {
204 struct sway_container *desired_con =
205 parent->children->items[desired];
206 wlr_log(WLR_DEBUG,
207 "cont %d-%p dir %i sibling %d: %p", idx,
208 container, dir, desired, desired_con);
209 return seat_get_focus_inactive_view(seat, desired_con);
210 }
211 }
212
213 if (!can_move) {
214 container = parent;
215 parent = parent->parent;
216 if (!parent) {
217 // wrapping is the last chance
218 if (!wrap_candidate) {
219 return NULL;
220 }
221 return seat_get_focus_inactive_view(seat, wrap_candidate);
222 }
223 }
224 }
225}
226
34static struct cmd_results *focus_mode(struct sway_container *con, 227static struct cmd_results *focus_mode(struct sway_container *con,
35 struct sway_seat *seat, bool floating) { 228 struct sway_seat *seat, bool floating) {
36 struct sway_container *ws = con->type == C_WORKSPACE ? 229 struct sway_container *ws = con->type == C_WORKSPACE ?