Allow floating views to appear at the mouse
This commit is contained in:
		@ -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.
 | 
				
			||||||
 | 
				
			|||||||
@ -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) = .{},
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
				
			||||||
 | 
				
			|||||||
@ -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 => {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user