aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/seat.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2019-01-10 22:04:42 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2019-01-10 22:04:42 +1000
commited5aafd90bd850ad27dcb36ac4438ed926480394 (patch)
tree46d0b5fe8488e5d9415cbc9a732e86c1e7100ffe /sway/input/seat.c
parentMerge pull request #3341 from RedSoxFan/mouse-bindings-improved (diff)
downloadsway-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/seat.c')
-rw-r--r--sway/input/seat.c236
1 files changed, 42 insertions, 194 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c
index a8df5b99..7bd889d7 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -308,7 +308,7 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) {
308 wl_list_insert(&root->drag_icons, &icon->link); 308 wl_list_insert(&root->drag_icons, &icon->link);
309 309
310 drag_icon_update_position(icon); 310 drag_icon_update_position(icon);
311 seat_end_mouse_operation(seat); 311 seatop_abort(seat);
312} 312}
313 313
314static void collect_focus_iter(struct sway_node *node, void *data) { 314static void collect_focus_iter(struct sway_node *node, void *data) {
@@ -625,18 +625,6 @@ static int handle_urgent_timeout(void *data) {
625 return 0; 625 return 0;
626} 626}
627 627
628static void container_raise_floating(struct sway_container *con) {
629 // Bring container to front by putting it at the end of the floating list.
630 struct sway_container *floater = con;
631 while (floater->parent) {
632 floater = floater->parent;
633 }
634 if (container_is_floating(floater)) {
635 list_move_to_end(floater->workspace->floating, floater);
636 node_set_dirty(&floater->workspace->node);
637 }
638}
639
640static void set_workspace(struct sway_seat *seat, 628static void set_workspace(struct sway_seat *seat,
641 struct sway_workspace *new_ws) { 629 struct sway_workspace *new_ws) {
642 if (seat->workspace == new_ws) { 630 if (seat->workspace == new_ws) {
@@ -1025,187 +1013,6 @@ struct seat_config *seat_get_config_by_name(const char *name) {
1025 return NULL; 1013 return NULL;
1026} 1014}
1027 1015
1028void seat_begin_down(struct sway_seat *seat, struct sway_container *con,
1029 uint32_t button, double sx, double sy) {
1030 seat->operation = OP_DOWN;
1031 seat->op_container = con;
1032 seat->op_button = button;
1033 seat->op_ref_lx = seat->cursor->cursor->x;
1034 seat->op_ref_ly = seat->cursor->cursor->y;
1035 seat->op_ref_con_lx = sx;
1036 seat->op_ref_con_ly = sy;
1037 seat->op_moved = false;
1038
1039 container_raise_floating(con);
1040}
1041
1042void seat_begin_move_floating(struct sway_seat *seat,
1043 struct sway_container *con, uint32_t button) {
1044 if (!seat->cursor) {
1045 wlr_log(WLR_DEBUG, "Ignoring move request due to no cursor device");
1046 return;
1047 }
1048 seat->operation = OP_MOVE_FLOATING;
1049 seat->op_container = con;
1050 seat->op_button = button;
1051
1052 container_raise_floating(con);
1053
1054 cursor_set_image(seat->cursor, "grab", NULL);
1055}
1056
1057void seat_begin_move_tiling_threshold(struct sway_seat *seat,
1058 struct sway_container *con, uint32_t button) {
1059 seat->operation = OP_MOVE_TILING_THRESHOLD;
1060 seat->op_container = con;
1061 seat->op_button = button;
1062 seat->op_target_node = NULL;
1063 seat->op_target_edge = 0;
1064 seat->op_ref_lx = seat->cursor->cursor->x;
1065 seat->op_ref_ly = seat->cursor->cursor->y;
1066}
1067
1068void seat_begin_move_tiling(struct sway_seat *seat,
1069 struct sway_container *con, uint32_t button) {
1070 seat->operation = OP_MOVE_TILING;
1071 seat->op_container = con;
1072 seat->op_button = button;
1073 seat->op_target_node = NULL;
1074 seat->op_target_edge = 0;
1075 cursor_set_image(seat->cursor, "grab", NULL);
1076}
1077
1078void seat_begin_resize_floating(struct sway_seat *seat,
1079 struct sway_container *con, uint32_t button, enum wlr_edges edge) {
1080 if (!seat->cursor) {
1081 wlr_log(WLR_DEBUG, "Ignoring resize request due to no cursor device");
1082 return;
1083 }
1084 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
1085 seat->operation = OP_RESIZE_FLOATING;
1086 seat->op_container = con;
1087 seat->op_resize_preserve_ratio = keyboard &&
1088 (wlr_keyboard_get_modifiers(keyboard) & WLR_MODIFIER_SHIFT);
1089 seat->op_resize_edge = edge == WLR_EDGE_NONE ?
1090 WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT : edge;
1091 seat->op_button = button;
1092 seat->op_ref_lx = seat->cursor->cursor->x;
1093 seat->op_ref_ly = seat->cursor->cursor->y;
1094 seat->op_ref_con_lx = con->x;
1095 seat->op_ref_con_ly = con->y;
1096 seat->op_ref_width = con->width;
1097 seat->op_ref_height = con->height;
1098
1099 container_raise_floating(con);
1100
1101 const char *image = edge == WLR_EDGE_NONE ?
1102 "se-resize" : wlr_xcursor_get_resize_name(edge);
1103 cursor_set_image(seat->cursor, image, NULL);
1104}
1105
1106void seat_begin_resize_tiling(struct sway_seat *seat,
1107 struct sway_container *con, uint32_t button, enum wlr_edges edge) {
1108 seat->operation = OP_RESIZE_TILING;
1109 seat->op_container = con;
1110 seat->op_resize_edge = edge;
1111 seat->op_button = button;
1112 seat->op_ref_lx = seat->cursor->cursor->x;
1113 seat->op_ref_ly = seat->cursor->cursor->y;
1114 seat->op_ref_con_lx = con->x;
1115 seat->op_ref_con_ly = con->y;
1116 seat->op_ref_width = con->width;
1117 seat->op_ref_height = con->height;
1118}
1119
1120static bool is_parallel(enum sway_container_layout layout,
1121 enum wlr_edges edge) {
1122 bool layout_is_horiz = layout == L_HORIZ || layout == L_TABBED;
1123 bool edge_is_horiz = edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT;
1124 return layout_is_horiz == edge_is_horiz;
1125}
1126
1127static void seat_end_move_tiling(struct sway_seat *seat) {
1128 struct sway_container *con = seat->op_container;
1129 struct sway_container *old_parent = con->parent;
1130 struct sway_workspace *old_ws = con->workspace;
1131 struct sway_node *target_node = seat->op_target_node;
1132 struct sway_workspace *new_ws = target_node->type == N_WORKSPACE ?
1133 target_node->sway_workspace : target_node->sway_container->workspace;
1134 enum wlr_edges edge = seat->op_target_edge;
1135 int after = edge != WLR_EDGE_TOP && edge != WLR_EDGE_LEFT;
1136
1137 container_detach(con);
1138
1139 // Moving container into empty workspace
1140 if (target_node->type == N_WORKSPACE && edge == WLR_EDGE_NONE) {
1141 workspace_add_tiling(new_ws, con);
1142 } else if (target_node->type == N_CONTAINER) {
1143 // Moving container before/after another
1144 struct sway_container *target = target_node->sway_container;
1145 enum sway_container_layout layout = container_parent_layout(target);
1146 if (edge && !is_parallel(layout, edge)) {
1147 enum sway_container_layout new_layout = edge == WLR_EDGE_TOP ||
1148 edge == WLR_EDGE_BOTTOM ? L_VERT : L_HORIZ;
1149 container_split(target, new_layout);
1150 }
1151 container_add_sibling(target, con, after);
1152 } else {
1153 // Target is a workspace which requires splitting
1154 enum sway_container_layout new_layout = edge == WLR_EDGE_TOP ||
1155 edge == WLR_EDGE_BOTTOM ? L_VERT : L_HORIZ;
1156 workspace_split(new_ws, new_layout);
1157 workspace_insert_tiling(new_ws, con, after);
1158 }
1159
1160 if (old_parent) {
1161 container_reap_empty(old_parent);
1162 }
1163
1164 // This is a bit dirty, but we'll set the dimensions to that of a sibling.
1165 // I don't think there's any other way to make it consistent without
1166 // changing how we auto-size containers.
1167 list_t *siblings = container_get_siblings(con);
1168 if (siblings->length > 1) {
1169 int index = list_find(siblings, con);
1170 struct sway_container *sibling = index == 0 ?
1171 siblings->items[1] : siblings->items[index - 1];
1172 con->width = sibling->width;
1173 con->height = sibling->height;
1174 }
1175
1176 arrange_workspace(old_ws);
1177 if (new_ws != old_ws) {
1178 arrange_workspace(new_ws);
1179 }
1180}
1181
1182void seat_end_mouse_operation(struct sway_seat *seat) {
1183 enum sway_seat_operation operation = seat->operation;
1184 if (seat->operation == OP_MOVE_FLOATING) {
1185 // We "move" the container to its own location so it discovers its
1186 // output again.
1187 struct sway_container *con = seat->op_container;
1188 container_floating_move_to(con, con->x, con->y);
1189 } else if (seat->operation == OP_MOVE_TILING && seat->op_target_node) {
1190 seat_end_move_tiling(seat);
1191 }
1192 seat->operation = OP_NONE;
1193 seat->op_container = NULL;
1194 if (operation == OP_DOWN) {
1195 // Set the cursor's previous coords to the x/y at the start of the
1196 // operation, so the container change will be detected if using
1197 // focus_follows_mouse and the cursor moved off the original container
1198 // during the operation.
1199 seat->cursor->previous.x = seat->op_ref_lx;
1200 seat->cursor->previous.y = seat->op_ref_ly;
1201 if (seat->op_moved) {
1202 cursor_send_pointer_motion(seat->cursor, 0);
1203 }
1204 } else {
1205 cursor_set_image(seat->cursor, "left_ptr", NULL);
1206 }
1207}
1208
1209void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, 1016void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec,
1210 uint32_t button, enum wlr_button_state state) { 1017 uint32_t button, enum wlr_button_state state) {
1211 seat->last_button = button; 1018 seat->last_button = button;
@@ -1238,3 +1045,44 @@ void seat_consider_warp_to_focus(struct sway_seat *seat) {
1238 wl_event_source_timer_update(seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); 1045 wl_event_source_timer_update(seat->cursor->hide_source, cursor_get_timeout(seat->cursor));
1239 } 1046 }
1240} 1047}
1048
1049bool seat_doing_seatop(struct sway_seat *seat) {
1050 return seat->seatop_impl != NULL;
1051}
1052
1053void seatop_unref(struct sway_seat *seat, struct sway_container *con) {
1054 if (seat->seatop_impl && seat->seatop_impl->unref) {
1055 seat->seatop_impl->unref(seat, con);
1056 }
1057}
1058
1059void seatop_motion(struct sway_seat *seat, uint32_t time_msec) {
1060 if (seat->seatop_impl && seat->seatop_impl->motion) {
1061 seat->seatop_impl->motion(seat, time_msec);
1062 }
1063}
1064
1065void seatop_finish(struct sway_seat *seat) {
1066 if (seat->seatop_impl && seat->seatop_impl->finish) {
1067 seat->seatop_impl->finish(seat);
1068 }
1069 free(seat->seatop_data);
1070 seat->seatop_data = NULL;
1071 seat->seatop_impl = NULL;
1072}
1073
1074void seatop_abort(struct sway_seat *seat) {
1075 if (seat->seatop_impl && seat->seatop_impl->abort) {
1076 seat->seatop_impl->abort(seat);
1077 }
1078 free(seat->seatop_data);
1079 seat->seatop_data = NULL;
1080 seat->seatop_impl = NULL;
1081}
1082
1083void seatop_render(struct sway_seat *seat, struct sway_output *output,
1084 pixman_region32_t *damage) {
1085 if (seat->seatop_impl && seat->seatop_impl->render) {
1086 seat->seatop_impl->render(seat, output, damage);
1087 }
1088}