cursor: add option to warp on output change

On output change, if the cursor is not already on the newly focused
output, it will now be warped to its center. The check is necessary,
since focusing outputs with the pointer will be implemented in
the future.
This commit is contained in:
Leon Henrik Plickat
2021-05-07 03:46:26 +02:00
committed by Isaac Freund
parent 505639432e
commit 085cca0d5e
5 changed files with 48 additions and 2 deletions

View File

@ -33,6 +33,11 @@ pub const FocusFollowsCursorMode = enum {
strict,
};
pub const WarpCursorMode = enum {
disabled,
@"on-output-change",
};
/// Color of background in RGBA (alpha should only affect nested sessions)
background_color: [4]f32 = [_]f32{ 0.0, 0.16862745, 0.21176471, 1.0 }, // Solarized base03
@ -60,6 +65,9 @@ csd_filter: std.ArrayList([]const u8),
/// The selected focus_follows_cursor mode
focus_follows_cursor: FocusFollowsCursorMode = .disabled,
/// If true, the cursor warps to the center of the focused output
warp_cursor: WarpCursorMode = .disabled,
/// The default layout namespace for outputs which have never had a per-output
/// value set. Call Output.handleLayoutNamespaceChange() on setting this if
/// Output.layout_namespace is null.

View File

@ -266,6 +266,23 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
pub fn focusOutput(self: *Self, output: *Output) void {
if (self.focused_output == 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" => {
const layout_box = server.root.output_layout.getBox(output.wlr_output).?;
if (!layout_box.containsPoint(self.cursor.wlr_cursor.x, self.cursor.wlr_cursor.y)) {
const eff_res = output.getEffectiveResolution();
const lx = @intToFloat(f32, layout_box.x + @intCast(i32, eff_res.width / 2));
const ly = @intToFloat(f32, layout_box.y + @intCast(i32, eff_res.height / 2));
if (!self.cursor.wlr_cursor.warp(null, lx, ly)) {
log.err("failed to warp cursor on output change", .{});
}
}
},
}
var it = self.status_trackers.first;
while (it) |node| : (it = node.next) node.data.sendOutput(.unfocused);

View File

@ -58,8 +58,8 @@ const str_to_impl_fn = [_]struct {
.{ .name = "focus-output", .impl = @import("command/output.zig").focusOutput },
.{ .name = "focus-view", .impl = @import("command/focus_view.zig").focusView },
.{ .name = "input", .impl = @import("command/input.zig").input },
.{ .name = "list-inputs", .impl = @import("command/input.zig").listInputs },
.{ .name = "list-input-configs", .impl = @import("command/input.zig").listInputConfigs},
.{ .name = "list-inputs", .impl = @import("command/input.zig").listInputs },
.{ .name = "map", .impl = @import("command/map.zig").map },
.{ .name = "map-pointer", .impl = @import("command/map.zig").mapPointer },
.{ .name = "mod-layout-value", .impl = @import("command/layout.zig").modLayoutValue },
@ -68,6 +68,7 @@ const str_to_impl_fn = [_]struct {
.{ .name = "output-layout", .impl = @import("command/layout.zig").outputLayout },
.{ .name = "resize", .impl = @import("command/move.zig").resize },
.{ .name = "send-to-output", .impl = @import("command/output.zig").sendToOutput },
.{ .name = "set-cursor-warp", .impl = @import("command/config.zig").setCursorWarp },
.{ .name = "set-focused-tags", .impl = @import("command/tags.zig").setFocusedTags },
.{ .name = "set-layout-value", .impl = @import("command/layout.zig").setLayoutValue },
.{ .name = "set-repeat", .impl = @import("command/set_repeat.zig").setRepeat },

View File

@ -21,6 +21,7 @@ const server = &@import("../main.zig").server;
const Error = @import("../command.zig").Error;
const Seat = @import("../Seat.zig");
const Config = @import("../Config.zig");
pub fn borderWidth(
allocator: *std.mem.Allocator,
@ -81,6 +82,18 @@ pub fn borderColorUnfocused(
while (it) |node| : (it = node.next) node.data.damage.addWhole();
}
pub fn setCursorWarp(
allocator: *std.mem.Allocator,
seat: *Seat,
args: []const []const u8,
out: *?[]const u8,
) Error!void {
if (args.len < 2) return Error.NotEnoughArguments;
if (args.len > 2) return Error.TooManyArguments;
server.config.warp_cursor = std.meta.stringToEnum(Config.WarpCursorMode, args[1]) orelse
return Error.UnknownOption;
}
/// Parse a color in the format #RRGGBB or #RRGGBBAA
fn parseRgba(string: []const u8) ![4]f32 {
if (string[0] != '#' or (string.len != 7 and string.len != 9)) return error.InvalidRgba;