Cursor: add on-focus-change option
Warp the cursor to the center of the focused view if the cursor is not in the bounding box of that view already. This helps the user to keep track of their cursor when they mostly use the keyboard and the cursor becomes hidden most of the time, also helps trackpad/trackpoint users.
This commit is contained in:
parent
3141940efb
commit
8036ae2bd1
@ -64,7 +64,7 @@ function __riverctl_completion ()
|
||||
"unmap") OPTS="-release" ;;
|
||||
"attach-mode") OPTS="top bottom" ;;
|
||||
"focus-follows-cursor") OPTS="disabled normal always" ;;
|
||||
"set-cursor-warp") OPTS="disabled on-output-change" ;;
|
||||
"set-cursor-warp") OPTS="disabled on-output-change on-focus-change" ;;
|
||||
"hide-cursor") OPTS="timeout when-typing" ;;
|
||||
*) return ;;
|
||||
esac
|
||||
|
@ -79,7 +79,7 @@ complete -c riverctl -x -n '__fish_seen_subcommand_from map' -a
|
||||
complete -c riverctl -x -n '__fish_seen_subcommand_from unmap' -a '-release'
|
||||
complete -c riverctl -x -n '__fish_seen_subcommand_from attach-mode' -a 'top bottom'
|
||||
complete -c riverctl -x -n '__fish_seen_subcommand_from focus-follows-cursor' -a 'disabled normal always'
|
||||
complete -c riverctl -x -n '__fish_seen_subcommand_from set-cursor-warp' -a 'disabled on-output-change'
|
||||
complete -c riverctl -x -n '__fish_seen_subcommand_from set-cursor-warp' -a 'disabled on-output-change on-focus-change'
|
||||
|
||||
# Subcommands for 'input'
|
||||
complete -c riverctl -x -n '__fish_seen_subcommand_from input; and __fish_riverctl_complete_arg 2' -a "(__riverctl_list_input_devices)"
|
||||
|
@ -178,7 +178,7 @@ _riverctl()
|
||||
unmap) _alternative 'arguments:optional:(-release)' ;;
|
||||
attach-mode) _alternative 'arguments:args:(top bottom)' ;;
|
||||
focus-follows-cursor) _alternative 'arguments:args:(disabled normal always)' ;;
|
||||
set-cursor-warp) _alternative 'arguments:args:(disabled on-output-change)' ;;
|
||||
set-cursor-warp) _alternative 'arguments:args:(disabled on-output-change on-focus-change)' ;;
|
||||
hide-cursor) _riverctl_hide_cursor ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
|
@ -307,12 +307,14 @@ A complete list may be found in _/usr/include/linux/input-event-codes.h_
|
||||
Hide the cursor when pressing any non-modifier key. Show the cursor
|
||||
again on any movement.
|
||||
|
||||
*set-cursor-warp* *disabled*|*on-output-change*
|
||||
*set-cursor-warp* *disabled*|*on-output-change*|*on-focus-change*
|
||||
Set the cursor warp mode. There are two available modes:
|
||||
|
||||
- _disabled_: Cursor will not be warped. This is the default.
|
||||
- _on-output-change_: When a different output is focused, the cursor will be
|
||||
warped to its center.
|
||||
- _on-focus-change_: When a different view/output is focused, the cursor will be
|
||||
warped to its center.
|
||||
|
||||
*set-repeat* _rate_ _delay_
|
||||
Set the keyboard repeat rate to _rate_ key repeats per second and
|
||||
|
@ -36,6 +36,7 @@ pub const FocusFollowsCursorMode = enum {
|
||||
pub const WarpCursorMode = enum {
|
||||
disabled,
|
||||
@"on-output-change",
|
||||
@"on-focus-change",
|
||||
};
|
||||
|
||||
pub const HideCursorWhenTypingMode = enum {
|
||||
|
@ -105,6 +105,7 @@ pressed_count: u32 = 0,
|
||||
hide_cursor_timer: *wl.EventSource,
|
||||
|
||||
hidden: bool = false,
|
||||
may_need_warp: bool = false,
|
||||
|
||||
axis: wl.Listener(*wlr.Pointer.event.Axis) = wl.Listener(*wlr.Pointer.event.Axis).init(handleAxis),
|
||||
frame: wl.Listener(*wlr.Cursor) = wl.Listener(*wlr.Cursor).init(handleFrame),
|
||||
@ -1050,6 +1051,9 @@ pub fn checkFocusFollowsCursor(self: *Self) void {
|
||||
/// the target view of a cursor operation potentially being moved to a non-visible tag,
|
||||
/// becoming fullscreen, etc.
|
||||
pub fn updateState(self: *Self) void {
|
||||
if (self.may_need_warp) {
|
||||
self.warp();
|
||||
}
|
||||
if (self.shouldPassthrough()) {
|
||||
self.mode = .passthrough;
|
||||
var now: os.timespec = undefined;
|
||||
@ -1103,3 +1107,49 @@ fn passthrough(self: *Self, time: u32) void {
|
||||
self.clearFocus();
|
||||
}
|
||||
}
|
||||
|
||||
fn warp(self: *Self) void {
|
||||
self.may_need_warp = false;
|
||||
if (self.seat.focused_output == &server.root.noop_output) return;
|
||||
// Warp pointer to center of the focused view/output (In layout coordinates) if enabled.
|
||||
var output_layout_box: wlr.Box = undefined;
|
||||
server.root.output_layout.getBox(self.seat.focused_output.wlr_output, &output_layout_box);
|
||||
const target_box = switch (server.config.warp_cursor) {
|
||||
.disabled => return,
|
||||
.@"on-output-change" => output_layout_box,
|
||||
.@"on-focus-change" => switch (self.seat.focused) {
|
||||
.layer, .lock_surface, .none => output_layout_box,
|
||||
.view => |view| wlr.Box{
|
||||
.x = output_layout_box.x + view.current.box.x,
|
||||
.y = output_layout_box.y + view.current.box.y,
|
||||
.width = view.current.box.width,
|
||||
.height = view.current.box.height,
|
||||
},
|
||||
.xwayland_override_redirect => |or_window| wlr.Box{
|
||||
.x = or_window.xwayland_surface.x,
|
||||
.y = or_window.xwayland_surface.y,
|
||||
.width = or_window.xwayland_surface.width,
|
||||
.height = or_window.xwayland_surface.height,
|
||||
},
|
||||
},
|
||||
};
|
||||
// Checking against the usable box here gives much better UX when, for example,
|
||||
// a status bar allows using the pointer to change tag/view focus.
|
||||
const usable_box = self.seat.focused_output.usable_box;
|
||||
const usable_layout_box = wlr.Box{
|
||||
.x = output_layout_box.x + usable_box.x,
|
||||
.y = output_layout_box.y + usable_box.y,
|
||||
.width = usable_box.width,
|
||||
.height = usable_box.height,
|
||||
};
|
||||
if (!output_layout_box.containsPoint(self.wlr_cursor.x, self.wlr_cursor.y) or
|
||||
(usable_layout_box.containsPoint(self.wlr_cursor.x, self.wlr_cursor.y) and
|
||||
!target_box.containsPoint(self.wlr_cursor.x, self.wlr_cursor.y)))
|
||||
{
|
||||
const lx = @intToFloat(f64, target_box.x + @divTrunc(target_box.width, 2));
|
||||
const ly = @intToFloat(f64, target_box.y + @divTrunc(target_box.height, 2));
|
||||
if (!self.wlr_cursor.warp(null, lx, ly)) {
|
||||
log.err("failed to warp cursor on focus change", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,6 +265,10 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||
PointerConstraint.warpToHint(&self.cursor);
|
||||
constraint.sendDeactivated();
|
||||
self.cursor.constraint = null;
|
||||
} else {
|
||||
// Depending on configuration and cursor position, changing keyboard focus
|
||||
// may cause the cursor to be warped.
|
||||
self.cursor.may_need_warp = true;
|
||||
}
|
||||
} else {
|
||||
self.wlr_seat.keyboardClearFocus();
|
||||
@ -273,6 +277,10 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||
PointerConstraint.warpToHint(&self.cursor);
|
||||
constraint.sendDeactivated();
|
||||
self.cursor.constraint = null;
|
||||
} else {
|
||||
// Depending on configuration and cursor position, changing keyboard focus
|
||||
// may cause the cursor to be warped.
|
||||
self.cursor.may_need_warp = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,28 +321,6 @@ pub fn focusOutput(self: *Self, output: *Output) void {
|
||||
|
||||
it = self.status_trackers.first;
|
||||
while (it) |node| : (it = node.next) node.data.sendOutput(.focused);
|
||||
|
||||
if (self.focused_output == &server.root.noop_output) return;
|
||||
|
||||
// Warp pointer to center of newly focused output (In layout coordinates),
|
||||
// but only if cursor is not already on the output and this feature is enabled.
|
||||
switch (server.config.warp_cursor) {
|
||||
.disabled => {},
|
||||
.@"on-output-change" => {
|
||||
var layout_box: wlr.Box = undefined;
|
||||
server.root.output_layout.getBox(output.wlr_output, &layout_box);
|
||||
if (!layout_box.containsPoint(self.cursor.wlr_cursor.x, self.cursor.wlr_cursor.y)) {
|
||||
var output_width: i32 = undefined;
|
||||
var output_height: i32 = undefined;
|
||||
output.wlr_output.effectiveResolution(&output_width, &output_height);
|
||||
const lx = @intToFloat(f64, layout_box.x + @divTrunc(output_width, 2));
|
||||
const ly = @intToFloat(f64, layout_box.y + @divTrunc(output_height, 2));
|
||||
if (!self.cursor.wlr_cursor.warp(null, lx, ly)) {
|
||||
log.err("failed to warp cursor on output change", .{});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handleActivity(self: Self) void {
|
||||
|
Loading…
Reference in New Issue
Block a user