This commit is contained in:
Tudor Brindus 2021-04-12 21:12:15 +02:00 committed by GitHub
commit ed722d14fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 48 deletions

View file

@ -22,6 +22,15 @@ struct sway_cursor {
double x, y; double x, y;
struct sway_node *node; struct sway_node *node;
} previous; } previous;
// Not to be confused with `previous` above; they store entirely unrelated
// data.
struct {
double sx, sy;
struct sway_node *node;
struct wlr_surface *surface;
} current;
struct wlr_xcursor_manager *xcursor_manager; struct wlr_xcursor_manager *xcursor_manager;
struct wl_list tablets; struct wl_list tablets;
struct wl_list tablet_pads; struct wl_list tablet_pads;
@ -79,10 +88,6 @@ struct sway_cursor {
struct sway_node; struct sway_node;
struct sway_node *node_at_coords(
struct sway_seat *seat, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy);
void sway_cursor_destroy(struct sway_cursor *cursor); void sway_cursor_destroy(struct sway_cursor *cursor);
struct sway_cursor *sway_cursor_create(struct sway_seat *seat); struct sway_cursor *sway_cursor_create(struct sway_seat *seat);

View file

@ -618,11 +618,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
struct sway_container *con = NULL; struct sway_container *con = NULL;
if (binding->type == BINDING_MOUSESYM if (binding->type == BINDING_MOUSESYM
|| binding->type == BINDING_MOUSECODE) { || binding->type == BINDING_MOUSECODE) {
struct wlr_surface *surface = NULL; struct sway_node *node = seat->cursor->current.node;
double sx, sy;
struct sway_node *node = node_at_coords(seat,
seat->cursor->cursor->x, seat->cursor->cursor->y,
&surface, &sx, &sy);
if (node && node->type == N_CONTAINER) { if (node && node->type == N_CONTAINER) {
con = node->sway_container; con = node->sway_container;
} }

View file

@ -74,7 +74,7 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
* Returns the node at the cursor's position. If there is a surface at that * Returns the node at the cursor's position. If there is a surface at that
* location, it is stored in **surface (it may not be a view). * location, it is stored in **surface (it may not be a view).
*/ */
struct sway_node *node_at_coords( static struct sway_node *node_at_coords(
struct sway_seat *seat, double lx, double ly, struct sway_seat *seat, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) { struct wlr_surface **surface, double *sx, double *sy) {
// check for unmanaged views first // check for unmanaged views first
@ -340,6 +340,50 @@ void cursor_unhide(struct sway_cursor *cursor) {
wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor));
} }
static bool cursor_motion_is_constrained(struct sway_cursor *cursor,
enum wlr_input_device_type type) {
// Only apply pointer constraints to real pointer input.
return cursor->active_constraint && type == WLR_INPUT_DEVICE_POINTER;
}
static void cursor_update_current_node(struct sway_cursor *cursor,
enum wlr_input_device_type type) {
struct sway_node *node = NULL;
struct wlr_surface *surface = NULL;
double sx = 0, sy = 0;
if (cursor_motion_is_constrained(cursor, type)) {
struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint;
struct sway_view *view = view_from_wlr_surface(constraint->surface);
if (view) {
struct sway_container *con = view->container;
sx = cursor->cursor->x - con->pending.content_x + view->geometry.x;
sy = cursor->cursor->y - con->pending.content_y + view->geometry.y;
if (pixman_region32_contains_point(&constraint->region, floor(sx),
floor(sy), NULL)) {
node = &view->container->node;
surface = constraint->surface;
}
}
}
// This is subtle: this means that if an actively constrained surface is
// partially occluded by another node (say, by a floating node), the cursor
// shall remain constrained and pass "under" the floating node. Need to
// check both `node` and `surface` since neither implies the other.
if (!node && !surface) {
node = node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y,
&surface, &sx, &sy);
}
cursor->current.sx = sx;
cursor->current.sy = sy;
cursor->current.node = node;
cursor->current.surface = surface;
}
static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
struct wlr_input_device *device, double dx, double dy, struct wlr_input_device *device, double dx, double dy,
double dx_unaccel, double dy_unaccel) { double dx_unaccel, double dy_unaccel) {
@ -348,17 +392,12 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
cursor->seat->wlr_seat, (uint64_t)time_msec * 1000, cursor->seat->wlr_seat, (uint64_t)time_msec * 1000,
dx, dy, dx_unaccel, dy_unaccel); dx, dy, dx_unaccel, dy_unaccel);
// Only apply pointer constraints to real pointer input. cursor_update_current_node(cursor, device->type);
if (cursor->active_constraint && device->type == WLR_INPUT_DEVICE_POINTER) {
struct wlr_surface *surface = NULL;
double sx, sy;
node_at_coords(cursor->seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (cursor->active_constraint->surface != surface) { if (cursor_motion_is_constrained(cursor, device->type)) {
return; assert(cursor->active_constraint->surface == cursor->current.surface);
}
double sx = cursor->current.sx, sy = cursor->current.sy;
double sx_confined, sy_confined; double sx_confined, sy_confined;
if (!wlr_region_confine(&cursor->confine, sx, sy, sx + dx, sy + dy, if (!wlr_region_confine(&cursor->confine, sx, sy, sx + dx, sy + dy,
&sx_confined, &sy_confined)) { &sx_confined, &sy_confined)) {
@ -370,6 +409,7 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
} }
wlr_cursor_move(cursor->cursor, device, dx, dy); wlr_cursor_move(cursor->cursor, device, dx, dy);
cursor_update_current_node(cursor, device->type);
seatop_pointer_motion(cursor->seat, time_msec); seatop_pointer_motion(cursor->seat, time_msec);
} }
@ -608,10 +648,8 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
break; break;
} }
double sx, sy; struct wlr_surface *surface = cursor->current.surface;
struct wlr_surface *surface = NULL;
struct sway_seat *seat = cursor->seat; struct sway_seat *seat = cursor->seat;
node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
// The logic for whether we should send a tablet event or an emulated pointer // The logic for whether we should send a tablet event or an emulated pointer
// event is tricky. It comes down to: // event is tricky. It comes down to:
@ -626,6 +664,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
if (!cursor->simulating_pointer_from_tool_tip && if (!cursor->simulating_pointer_from_tool_tip &&
((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) || ((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) ||
wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) { wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) {
cursor_update_current_node(cursor, input_device->wlr_device->type);
seatop_tablet_tool_motion(seat, tool, time_msec); seatop_tablet_tool_motion(seat, tool, time_msec);
} else { } else {
wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool);
@ -839,8 +878,11 @@ static void check_constraint_region(struct sway_cursor *cursor) {
sx + con->pending.content_x - view->geometry.x, sx + con->pending.content_x - view->geometry.x,
sy + con->pending.content_y - view->geometry.y); sy + con->pending.content_y - view->geometry.y);
cursor_update_current_node(cursor, WLR_INPUT_DEVICE_POINTER);
cursor_rebase(cursor); cursor_rebase(cursor);
} }
} else {
cursor_update_current_node(cursor, WLR_INPUT_DEVICE_POINTER);
} }
} }
@ -1279,6 +1321,7 @@ static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) {
// Warp the pointer as well, so that on the next pointer rebase we don't // Warp the pointer as well, so that on the next pointer rebase we don't
// send an unexpected synthetic motion event to clients. // send an unexpected synthetic motion event to clients.
wlr_seat_pointer_warp(constraint->seat, sx, sy); wlr_seat_pointer_warp(constraint->seat, sx, sy);
cursor_update_current_node(cursor, WLR_INPUT_DEVICE_POINTER);
} }
} }

View file

@ -213,10 +213,9 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
} }
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = cursor->current.surface;
double sx, sy; double sx = cursor->current.sx, sy = cursor->current.sy;
struct sway_node *node = node_at_coords(seat, struct sway_node *node = cursor->current.node;
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (!sway_assert(surface, if (!sway_assert(surface,
"Expected null-surface tablet input to route through pointer emulation")) { "Expected null-surface tablet input to route through pointer emulation")) {
@ -328,10 +327,9 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
// Determine what's under the cursor // Determine what's under the cursor
struct wlr_surface *surface = NULL; struct wlr_surface *surface = cursor->current.surface;
double sx, sy; double sx = cursor->current.sx, sy = cursor->current.sy;
struct sway_node *node = node_at_coords(seat, struct sway_node *node = cursor->current.node;
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
struct sway_container *cont = node && node->type == N_CONTAINER ? struct sway_container *cont = node && node->type == N_CONTAINER ?
node->sway_container : NULL; node->sway_container : NULL;
@ -574,10 +572,9 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
struct seatop_default_event *e = seat->seatop_data; struct seatop_default_event *e = seat->seatop_data;
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = cursor->current.surface;
double sx, sy; double sx = cursor->current.sx, sy = cursor->current.sy;
struct sway_node *node = node_at_coords(seat, struct sway_node *node = cursor->current.node;
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (config->focus_follows_mouse != FOLLOWS_NO) { if (config->focus_follows_mouse != FOLLOWS_NO) {
check_focus_follows_mouse(seat, e, node); check_focus_follows_mouse(seat, e, node);
@ -608,10 +605,9 @@ static void handle_tablet_tool_motion(struct sway_seat *seat,
struct seatop_default_event *e = seat->seatop_data; struct seatop_default_event *e = seat->seatop_data;
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = cursor->current.surface;
double sx, sy; double sx = cursor->current.sx, sy = cursor->current.sy;
struct sway_node *node = node_at_coords(seat, struct sway_node *node = cursor->current.node;
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (config->focus_follows_mouse != FOLLOWS_NO) { if (config->focus_follows_mouse != FOLLOWS_NO) {
check_focus_follows_mouse(seat, e, node); check_focus_follows_mouse(seat, e, node);
@ -664,10 +660,8 @@ static void handle_pointer_axis(struct sway_seat *seat,
struct seatop_default_event *e = seat->seatop_data; struct seatop_default_event *e = seat->seatop_data;
// Determine what's under the cursor // Determine what's under the cursor
struct wlr_surface *surface = NULL; struct wlr_surface *surface = cursor->current.surface;
double sx, sy; struct sway_node *node = cursor->current.node;
struct sway_node *node = node_at_coords(seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
struct sway_container *cont = node && node->type == N_CONTAINER ? struct sway_container *cont = node && node->type == N_CONTAINER ?
node->sway_container : NULL; node->sway_container : NULL;
enum wlr_edges edge = cont ? find_edge(cont, surface, cursor) : WLR_EDGE_NONE; enum wlr_edges edge = cont ? find_edge(cont, surface, cursor) : WLR_EDGE_NONE;
@ -756,8 +750,7 @@ static void handle_rebase(struct sway_seat *seat, uint32_t time_msec) {
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
double sx = 0.0, sy = 0.0; double sx = 0.0, sy = 0.0;
e->previous_node = node_at_coords(seat, e->previous_node = cursor->current.node;
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (surface) { if (surface) {
if (seat_is_input_allowed(seat, surface)) { if (seat_is_input_allowed(seat, surface)) {

View file

@ -94,11 +94,8 @@ static void resize_box(struct wlr_box *box, enum wlr_edges edge,
static void handle_motion_postthreshold(struct sway_seat *seat) { static void handle_motion_postthreshold(struct sway_seat *seat) {
struct seatop_move_tiling_event *e = seat->seatop_data; struct seatop_move_tiling_event *e = seat->seatop_data;
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
struct sway_node *node = node_at_coords(seat, struct sway_node *node = cursor->current.node;
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
// Damage the old location // Damage the old location
desktop_damage_box(&e->drop_box); desktop_damage_box(&e->drop_box);