diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2019-01-10 22:04:42 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2019-01-10 22:04:42 +1000 |
commit | ed5aafd90bd850ad27dcb36ac4438ed926480394 (patch) | |
tree | 46d0b5fe8488e5d9415cbc9a732e86c1e7100ffe /sway/input/seatop_resize_floating.c | |
parent | Merge pull request #3341 from RedSoxFan/mouse-bindings-improved (diff) | |
download | sway-ed5aafd90bd850ad27dcb36ac4438ed926480394.tar.gz sway-ed5aafd90bd850ad27dcb36ac4438ed926480394.tar.zst sway-ed5aafd90bd850ad27dcb36ac4438ed926480394.zip |
Refactor seat operations to use an interface
This splits each seat operation (drag/move tiling/floating etc) into a
separate file and introduces a struct sway_seatop_impl to abstract the
operation.
The move_tiling_threshold operation has been merged into move_tiling.
The main logic for each operation is untouched aside from variable
renames.
The following previously-static functions have been made public:
* node_at_coords
* container_raise_floating
* render_rect
* premultiply_alpha
* scale_box
Diffstat (limited to 'sway/input/seatop_resize_floating.c')
-rw-r--r-- | sway/input/seatop_resize_floating.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c new file mode 100644 index 00000000..12851b40 --- /dev/null +++ b/sway/input/seatop_resize_floating.c | |||
@@ -0,0 +1,199 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <limits.h> | ||
3 | #include <wlr/types/wlr_cursor.h> | ||
4 | #include <wlr/types/wlr_xcursor_manager.h> | ||
5 | #include "sway/input/cursor.h" | ||
6 | #include "sway/input/seat.h" | ||
7 | #include "sway/tree/arrange.h" | ||
8 | #include "sway/tree/view.h" | ||
9 | #include "sway/tree/workspace.h" | ||
10 | |||
11 | struct seatop_resize_floating_event { | ||
12 | struct sway_container *con; | ||
13 | enum wlr_edges edge; | ||
14 | bool preserve_ratio; | ||
15 | double ref_lx, ref_ly; // cursor's x/y at start of op | ||
16 | double ref_width, ref_height; // container's size at start of op | ||
17 | double ref_con_lx, ref_con_ly; // container's x/y at start of op | ||
18 | }; | ||
19 | |||
20 | static void calculate_floating_constraints(struct sway_container *con, | ||
21 | int *min_width, int *max_width, int *min_height, int *max_height) { | ||
22 | if (config->floating_minimum_width == -1) { // no minimum | ||
23 | *min_width = 0; | ||
24 | } else if (config->floating_minimum_width == 0) { // automatic | ||
25 | *min_width = 75; | ||
26 | } else { | ||
27 | *min_width = config->floating_minimum_width; | ||
28 | } | ||
29 | |||
30 | if (config->floating_minimum_height == -1) { // no minimum | ||
31 | *min_height = 0; | ||
32 | } else if (config->floating_minimum_height == 0) { // automatic | ||
33 | *min_height = 50; | ||
34 | } else { | ||
35 | *min_height = config->floating_minimum_height; | ||
36 | } | ||
37 | |||
38 | if (config->floating_maximum_width == -1) { // no maximum | ||
39 | *max_width = INT_MAX; | ||
40 | } else if (config->floating_maximum_width == 0) { // automatic | ||
41 | *max_width = con->workspace->width; | ||
42 | } else { | ||
43 | *max_width = config->floating_maximum_width; | ||
44 | } | ||
45 | |||
46 | if (config->floating_maximum_height == -1) { // no maximum | ||
47 | *max_height = INT_MAX; | ||
48 | } else if (config->floating_maximum_height == 0) { // automatic | ||
49 | *max_height = con->workspace->height; | ||
50 | } else { | ||
51 | *max_height = config->floating_maximum_height; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static void handle_motion(struct sway_seat *seat, uint32_t time_msec) { | ||
56 | struct seatop_resize_floating_event *e = seat->seatop_data; | ||
57 | struct sway_container *con = e->con; | ||
58 | enum wlr_edges edge = e->edge; | ||
59 | struct sway_cursor *cursor = seat->cursor; | ||
60 | |||
61 | // The amount the mouse has moved since the start of the resize operation | ||
62 | // Positive is down/right | ||
63 | double mouse_move_x = cursor->cursor->x - e->ref_lx; | ||
64 | double mouse_move_y = cursor->cursor->y - e->ref_ly; | ||
65 | |||
66 | if (edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM) { | ||
67 | mouse_move_x = 0; | ||
68 | } | ||
69 | if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) { | ||
70 | mouse_move_y = 0; | ||
71 | } | ||
72 | |||
73 | double grow_width = edge & WLR_EDGE_LEFT ? -mouse_move_x : mouse_move_x; | ||
74 | double grow_height = edge & WLR_EDGE_TOP ? -mouse_move_y : mouse_move_y; | ||
75 | |||
76 | if (e->preserve_ratio) { | ||
77 | double x_multiplier = grow_width / e->ref_width; | ||
78 | double y_multiplier = grow_height / e->ref_height; | ||
79 | double max_multiplier = fmax(x_multiplier, y_multiplier); | ||
80 | grow_width = e->ref_width * max_multiplier; | ||
81 | grow_height = e->ref_height * max_multiplier; | ||
82 | } | ||
83 | |||
84 | // Determine new width/height, and accommodate for floating min/max values | ||
85 | double width = e->ref_width + grow_width; | ||
86 | double height = e->ref_height + grow_height; | ||
87 | int min_width, max_width, min_height, max_height; | ||
88 | calculate_floating_constraints(con, &min_width, &max_width, | ||
89 | &min_height, &max_height); | ||
90 | width = fmax(min_width, fmin(width, max_width)); | ||
91 | height = fmax(min_height, fmin(height, max_height)); | ||
92 | |||
93 | // Apply the view's min/max size | ||
94 | if (con->view) { | ||
95 | double view_min_width, view_max_width, view_min_height, view_max_height; | ||
96 | view_get_constraints(con->view, &view_min_width, &view_max_width, | ||
97 | &view_min_height, &view_max_height); | ||
98 | width = fmax(view_min_width, fmin(width, view_max_width)); | ||
99 | height = fmax(view_min_height, fmin(height, view_max_height)); | ||
100 | } | ||
101 | |||
102 | // Recalculate these, in case we hit a min/max limit | ||
103 | grow_width = width - e->ref_width; | ||
104 | grow_height = height - e->ref_height; | ||
105 | |||
106 | // Determine grow x/y values - these are relative to the container's x/y at | ||
107 | // the start of the resize operation. | ||
108 | double grow_x = 0, grow_y = 0; | ||
109 | if (edge & WLR_EDGE_LEFT) { | ||
110 | grow_x = -grow_width; | ||
111 | } else if (edge & WLR_EDGE_RIGHT) { | ||
112 | grow_x = 0; | ||
113 | } else { | ||
114 | grow_x = -grow_width / 2; | ||
115 | } | ||
116 | if (edge & WLR_EDGE_TOP) { | ||
117 | grow_y = -grow_height; | ||
118 | } else if (edge & WLR_EDGE_BOTTOM) { | ||
119 | grow_y = 0; | ||
120 | } else { | ||
121 | grow_y = -grow_height / 2; | ||
122 | } | ||
123 | |||
124 | // Determine the amounts we need to bump everything relative to the current | ||
125 | // size. | ||
126 | int relative_grow_width = width - con->width; | ||
127 | int relative_grow_height = height - con->height; | ||
128 | int relative_grow_x = (e->ref_con_lx + grow_x) - con->x; | ||
129 | int relative_grow_y = (e->ref_con_ly + grow_y) - con->y; | ||
130 | |||
131 | // Actually resize stuff | ||
132 | con->x += relative_grow_x; | ||
133 | con->y += relative_grow_y; | ||
134 | con->width += relative_grow_width; | ||
135 | con->height += relative_grow_height; | ||
136 | |||
137 | con->content_x += relative_grow_x; | ||
138 | con->content_y += relative_grow_y; | ||
139 | con->content_width += relative_grow_width; | ||
140 | con->content_height += relative_grow_height; | ||
141 | |||
142 | arrange_container(con); | ||
143 | } | ||
144 | |||
145 | static void handle_finish(struct sway_seat *seat) { | ||
146 | cursor_set_image(seat->cursor, "left_ptr", NULL); | ||
147 | } | ||
148 | |||
149 | static void handle_abort(struct sway_seat *seat) { | ||
150 | cursor_set_image(seat->cursor, "left_ptr", NULL); | ||
151 | } | ||
152 | |||
153 | static void handle_unref(struct sway_seat *seat, struct sway_container *con) { | ||
154 | struct seatop_resize_floating_event *e = seat->seatop_data; | ||
155 | if (e->con == con) { | ||
156 | seatop_abort(seat); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | static const struct sway_seatop_impl seatop_impl = { | ||
161 | .motion = handle_motion, | ||
162 | .finish = handle_finish, | ||
163 | .abort = handle_abort, | ||
164 | .unref = handle_unref, | ||
165 | }; | ||
166 | |||
167 | void seatop_begin_resize_floating(struct sway_seat *seat, | ||
168 | struct sway_container *con, uint32_t button, enum wlr_edges edge) { | ||
169 | seatop_abort(seat); | ||
170 | |||
171 | struct seatop_resize_floating_event *e = | ||
172 | calloc(1, sizeof(struct seatop_resize_floating_event)); | ||
173 | if (!e) { | ||
174 | return; | ||
175 | } | ||
176 | e->con = con; | ||
177 | |||
178 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); | ||
179 | e->preserve_ratio = keyboard && | ||
180 | (wlr_keyboard_get_modifiers(keyboard) & WLR_MODIFIER_SHIFT); | ||
181 | |||
182 | e->edge = edge == WLR_EDGE_NONE ? WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT : edge; | ||
183 | e->ref_lx = seat->cursor->cursor->x; | ||
184 | e->ref_ly = seat->cursor->cursor->y; | ||
185 | e->ref_con_lx = con->x; | ||
186 | e->ref_con_ly = con->y; | ||
187 | e->ref_width = con->width; | ||
188 | e->ref_height = con->height; | ||
189 | |||
190 | seat->seatop_impl = &seatop_impl; | ||
191 | seat->seatop_data = e; | ||
192 | seat->seatop_button = button; | ||
193 | |||
194 | container_raise_floating(con); | ||
195 | |||
196 | const char *image = edge == WLR_EDGE_NONE ? | ||
197 | "se-resize" : wlr_xcursor_get_resize_name(edge); | ||
198 | cursor_set_image(seat->cursor, image, NULL); | ||
199 | } | ||