cursor: implement implicit grabs
When a button is held down and the cursor leaves a surface, events now continue to be sent to the client. This allows e.g. dragging a scroll bar from outside the surface.
This commit is contained in:
parent
91052f7477
commit
0c4e3295b1
@ -42,18 +42,21 @@ const ResizeData = struct {
|
||||
|
||||
const Mode = union(enum) {
|
||||
passthrough: void,
|
||||
down: *View,
|
||||
move: *View,
|
||||
resize: ResizeData,
|
||||
|
||||
/// Enter move or resize mode
|
||||
fn enter(self: *Self, mode: @TagType(Mode), event: *c.wlr_event_pointer_button, view: *View) void {
|
||||
std.debug.assert(self.mode == .passthrough);
|
||||
|
||||
log.debug(.cursor, "enter {} mode", .{@tagName(mode)});
|
||||
|
||||
switch (mode) {
|
||||
.passthrough => unreachable,
|
||||
.down => self.mode = .{ .down = view },
|
||||
.move, .resize => {
|
||||
const cur_box = &view.current.box;
|
||||
self.mode = switch (mode) {
|
||||
.passthrough => unreachable,
|
||||
.passthrough, .down => unreachable,
|
||||
.move => .{ .move = view },
|
||||
.resize => .{
|
||||
.resize = .{
|
||||
@ -80,14 +83,25 @@ const Mode = union(enum) {
|
||||
if (mode == .move) "move" else "se-resize",
|
||||
self.wlr_cursor,
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Return from move/resize to passthrough
|
||||
/// Return from down/move/resize to passthrough
|
||||
fn leave(self: *Self, event: *c.wlr_event_pointer_button) void {
|
||||
std.debug.assert(self.mode != .passthrough);
|
||||
|
||||
log.debug(.cursor, "leave {} mode", .{@tagName(self.mode)});
|
||||
|
||||
// If we were in down mode, we need pass along the release event
|
||||
if (self.mode == .down)
|
||||
_ = c.wlr_seat_pointer_notify_button(
|
||||
self.seat.wlr_seat,
|
||||
event.time_msec,
|
||||
event.button,
|
||||
event.state,
|
||||
);
|
||||
|
||||
self.mode = .passthrough;
|
||||
passthrough(self, event.time_msec);
|
||||
}
|
||||
@ -100,6 +114,15 @@ const Mode = union(enum) {
|
||||
c.wlr_cursor_move(self.wlr_cursor, device, delta_x, delta_y);
|
||||
passthrough(self, time);
|
||||
},
|
||||
.down => |view| {
|
||||
c.wlr_cursor_move(self.wlr_cursor, device, delta_x, delta_y);
|
||||
c.wlr_seat_pointer_notify_motion(
|
||||
self.seat.wlr_seat,
|
||||
time,
|
||||
self.wlr_cursor.x - @intToFloat(f64, view.current.box.x),
|
||||
self.wlr_cursor.y - @intToFloat(f64, view.current.box.y),
|
||||
);
|
||||
},
|
||||
.move => |view| {
|
||||
var output_width: c_int = undefined;
|
||||
var output_height: c_int = undefined;
|
||||
@ -364,6 +387,8 @@ fn handleButton(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
else => {},
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
Mode.enter(self, .down, event, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,7 @@ pub fn isCursorActionTarget(self: Self, view: *View) bool {
|
||||
const seat = &node.data;
|
||||
switch (seat.cursor.mode) {
|
||||
.passthrough => {},
|
||||
.down => |target_view| if (target_view == view) break true,
|
||||
.move => |target_view| if (target_view == view) break true,
|
||||
.resize => |data| if (data.view == view) break true,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user