Allow floating views to appear at the mouse

This commit is contained in:
Alexander Rosenberg 2024-11-01 15:43:17 -07:00
parent 2061ae2c4c
commit dbe2cb72f8
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
4 changed files with 57 additions and 18 deletions

View File

@ -298,9 +298,11 @@ matches everything while _\*\*_ and the empty string are invalid.
with make: _HP Inc._, model: _HP 22w_, and serial: _CNC93720WF_, the with make: _HP Inc._, model: _HP 22w_, and serial: _CNC93720WF_, the
identifier would be: _HP Inc. HP 22w CNC93720WF_. If the make, model, or identifier would be: _HP Inc. HP 22w CNC93720WF_. If the make, model, or
serial is unknown, the word "Unknown" is used instead. serial is unknown, the word "Unknown" is used instead.
- *position*: Set the initial position of the view, clamping to the - *position*: Set the initial position of the view, clamping to the bounds
bounds of the output. Requires x and y coordinates of the view as of the output. Requires x and y coordinates of the view as arguments, both
arguments, both of which must be non-negative. Applies only to new views. of which must be non-negative. Optionally, the string "mouse" can appear
as the only argument. In this case, the view will appear at the mouse's
position. Applies only to new views.
- *dimensions*: Set the initial dimensions of the view, clamping to the - *dimensions*: Set the initial dimensions of the view, clamping to the
constraints of the view. Requires width and height of the view as constraints of the view. Requires width and height of the view as
arguments, both of which must be non-negative. Applies only to new views. arguments, both of which must be non-negative. Applies only to new views.

View File

@ -58,11 +58,21 @@ pub const HideCursorWhenTypingMode = enum {
enabled, enabled,
}; };
pub const PositionType = enum {
absolute,
at_mouse,
};
pub const Position = struct { pub const Position = struct {
x: u31, x: u31,
y: u31, y: u31,
}; };
pub const FloatPosition = union(PositionType) {
absolute: Position,
at_mouse,
};
pub const Dimensions = struct { pub const Dimensions = struct {
width: u31, width: u31,
height: u31, height: u31,
@ -98,7 +108,7 @@ rules: struct {
ssd: RuleList(bool) = .{}, ssd: RuleList(bool) = .{},
tags: RuleList(u32) = .{}, tags: RuleList(u32) = .{},
output: RuleList([]const u8) = .{}, output: RuleList([]const u8) = .{},
position: RuleList(Position) = .{}, position: RuleList(FloatPosition) = .{},
dimensions: RuleList(Dimensions) = .{}, dimensions: RuleList(Dimensions) = .{},
fullscreen: RuleList(bool) = .{}, fullscreen: RuleList(bool) = .{},
tearing: RuleList(bool) = .{}, tearing: RuleList(bool) = .{},

View File

@ -678,8 +678,17 @@ pub fn map(view: *View) !void {
server.input_manager.defaultSeat().focused_output; server.input_manager.defaultSeat().focused_output;
if (server.config.rules.position.match(view)) |position| { if (server.config.rules.position.match(view)) |position| {
view.pending.box.x = position.x; switch (position) {
view.pending.box.y = position.y; .absolute => |pos| {
view.pending.box.x = pos.x;
view.pending.box.y = pos.y;
},
.at_mouse => {
const cursor = server.input_manager.defaultSeat().cursor.wlr_cursor;
view.pending.box.x = @as(c_int, @intFromFloat(cursor.x));
view.pending.box.y = @as(c_int, @intFromFloat(cursor.y));
},
}
} else if (output) |o| { } else if (output) |o| {
// Center the initial pending box on the output // Center the initial pending box on the output
view.pending.box.x = @divTrunc(@max(0, o.usable_box.width - view.pending.box.width), 2); view.pending.box.x = @divTrunc(@max(0, o.usable_box.width - view.pending.box.width), 2);

View File

@ -54,10 +54,17 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
const action = std.meta.stringToEnum(Action, result.args[0]) orelse return Error.UnknownOption; const action = std.meta.stringToEnum(Action, result.args[0]) orelse return Error.UnknownOption;
var pos_is_mouse = false;
const positional_arguments_count: u8 = switch (action) { const positional_arguments_count: u8 = switch (action) {
.float, .@"no-float", .ssd, .csd, .fullscreen, .@"no-fullscreen", .tearing, .@"no-tearing" => 1, .float, .@"no-float", .ssd, .csd, .fullscreen, .@"no-fullscreen", .tearing, .@"no-tearing" => 1,
.tags, .output => 2, .tags, .output => 2,
.position, .dimensions => 3, .dimensions => 3,
.position => blk: {
if (result.args.len >= 2 and std.mem.eql(u8, result.args[1], "mouse")) {
pos_is_mouse = true;
break :blk 2;
} else break :blk 3;
},
}; };
if (result.args.len > positional_arguments_count) return Error.TooManyArguments; if (result.args.len > positional_arguments_count) return Error.TooManyArguments;
if (result.args.len < positional_arguments_count) return Error.NotEnoughArguments; if (result.args.len < positional_arguments_count) return Error.NotEnoughArguments;
@ -111,16 +118,24 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
}); });
}, },
.position => { .position => {
const x = try fmt.parseInt(u31, result.args[1], 10); if (pos_is_mouse) {
const y = try fmt.parseInt(u31, result.args[2], 10); try server.config.rules.position.add(.{
try server.config.rules.position.add(.{ .app_id_glob = app_id_glob,
.app_id_glob = app_id_glob, .title_glob = title_glob,
.title_glob = title_glob, .value = .at_mouse,
.value = .{ });
.x = x, } else {
.y = y, const x = try fmt.parseInt(u31, result.args[1], 10);
}, const y = try fmt.parseInt(u31, result.args[2], 10);
}); try server.config.rules.position.add(.{
.app_id_glob = app_id_glob,
.title_glob = title_glob,
.value = .{ .absolute = .{
.x = x,
.y = y,
} },
});
}
}, },
.dimensions => { .dimensions => {
const width = try fmt.parseInt(u31, result.args[1], 10); const width = try fmt.parseInt(u31, result.args[1], 10);
@ -277,7 +292,10 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!
for (server.config.rules.position.rules.items) |rule| { for (server.config.rules.position.rules.items) |rule| {
try fmt.formatBuf(rule.title_glob, .{ .width = title_column_max, .alignment = .left }, writer); try fmt.formatBuf(rule.title_glob, .{ .width = title_column_max, .alignment = .left }, writer);
try fmt.formatBuf(rule.app_id_glob, .{ .width = app_id_column_max, .alignment = .left }, writer); try fmt.formatBuf(rule.app_id_glob, .{ .width = app_id_column_max, .alignment = .left }, writer);
try writer.print("{d},{d}\n", .{ rule.value.x, rule.value.y }); switch (rule.value) {
.absolute => |pos| try writer.print("{d},{d}\n", .{ pos.x, pos.y }),
.at_mouse => try writer.print("mouse\n", .{}),
}
} }
}, },
.dimensions => { .dimensions => {