git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit7d4a1d7c872cd4087986ce19554fd839594b52fb
parent5a94fa177b
authorIsaac Freund <[email protected]>
date2024-06-28 11:15
river: remove various config options

 river/Config.zig   |  49 ---------------
 river/Cursor.zig   | 179 ++---------------------------------------------------
 river/Keyboard.zig |  11 ----
 river/Output.zig   |   6 --
 river/Seat.zig     |   9 ---
 river/View.zig     |  64 +------------------
 6 files changed, 8 insertions(+), 310 deletions(-)

diff --git a/river/Config.zig b/river/Config.zig
index 0b54f77..66a284a 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -31,33 +31,6 @@ const Mode = @import("Mode.zig");
 const RuleList = @import("rule_list.zig").RuleList;
 const View = @import("View.zig");
 
-pub const AttachMode = union(enum) {
-    top,
-    bottom,
-    after: u32,
-    above,
-    below,
-};
-
-pub const FocusFollowsCursorMode = enum {
-    disabled,
-    /// Only change focus on entering a surface
-    normal,
-    /// Change focus on any cursor movement
-    always,
-};
-
-pub const WarpCursorMode = enum {
-    disabled,
-    @"on-output-change",
-    @"on-focus-change",
-};
-
-pub const HideCursorWhenTypingMode = enum {
-    disabled,
-    enabled,
-};
-
 pub const Position = struct {
     x: u31,
     y: u31,
@@ -100,35 +73,15 @@ rules: struct {
     fullscreen: RuleList(bool) = .{},
 } = .{},
 
-/// 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.
-default_layout_namespace: []const u8 = &[0]u8{},
-
 /// Bitmask restricting the tags of newly created views.
 spawn_tagmask: u32 = std.math.maxInt(u32),
 
-/// Determines where new views will be attached to the view stack.
-default_attach_mode: AttachMode = .top,
-
 /// Keyboard repeat rate in characters per second
 repeat_rate: u31 = 25,
 
 /// Keyboard repeat delay in milliseconds
 repeat_delay: u31 = 600,
 
-/// Cursor hide timeout in milliseconds
-cursor_hide_timeout: u31 = 0,
-
-/// Hide the cursor while typing
-cursor_hide_when_typing: HideCursorWhenTypingMode = .disabled,
-
 xkb_context: *xkb.Context,
 /// The xkb keymap used for all keyboards
 keymap: *xkb.Keymap,
@@ -183,8 +136,6 @@ pub fn deinit(config: *Config) void {
     config.rules.dimensions.deinit();
     config.rules.fullscreen.deinit();
 
-    util.gpa.free(config.default_layout_namespace);
-
     config.keymap.unref();
     config.xkb_context.unref();
 }
diff --git a/river/Cursor.zig b/river/Cursor.zig
index c873936..95b6acb 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -131,19 +131,11 @@ xcursor_name: ?[*:0]const u8 = null,
 /// Number of distinct buttons currently pressed
 pressed_count: u32 = 0,
 
-hide_cursor_timer: *wl.EventSource,
-
-hidden: bool = false,
-may_need_warp: bool = false,
-
 /// The pointer constraint for the surface that currently has keyboard focus, if any.
 /// This constraint is not necessarily active, activation only occurs once the cursor
 /// has been moved inside the constraint region.
 constraint: ?*PointerConstraint = null,
 
-/// View under the cursor, defined by view geometry rather than input region
-focus_follows_cursor_target: ?*View = null,
-
 /// Keeps track of the last known location of all touch points in layout coordinates.
 /// This information is necessary for proper touch dnd support if there are multiple touch points.
 touch_points: std.AutoHashMapUnmanaged(i32, LayoutPoint) = .{},
@@ -201,15 +193,11 @@ pub fn init(cursor: *Cursor, seat: *Seat) !void {
     const xcursor_manager = try wlr.XcursorManager.create(null, default_size);
     errdefer xcursor_manager.destroy();
 
-    const event_loop = server.wl_server.getEventLoop();
     cursor.* = .{
         .seat = seat,
         .wlr_cursor = wlr_cursor,
         .xcursor_manager = xcursor_manager,
-        .hide_cursor_timer = try event_loop.addTimer(*Cursor, handleHideCursorTimeout, cursor),
     };
-    errdefer cursor.hide_cursor_timer.remove();
-    try cursor.hide_cursor_timer.timerUpdate(server.config.cursor_hide_timeout);
     try cursor.setTheme(null, null);
 
     // wlr_cursor *only* displays an image on screen. It does not move around
@@ -243,7 +231,6 @@ pub fn init(cursor: *Cursor, seat: *Seat) !void {
 }
 
 pub fn deinit(cursor: *Cursor) void {
-    cursor.hide_cursor_timer.remove();
     cursor.xcursor_manager.destroy();
     cursor.wlr_cursor.destroy();
 }
@@ -307,7 +294,6 @@ fn handleAxis(listener: *wl.Listener(*wlr.Pointer.event.Axis), event: *wlr.Point
     const device: *InputDevice = @ptrFromInt(event.device.data);
 
     cursor.seat.handleActivity();
-    cursor.unhide();
 
     // Notify the client with pointer focus of the axis event.
     cursor.seat.wlr_seat.pointerNotifyAxis(
@@ -332,7 +318,6 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
     const cursor: *Cursor = @fieldParentPtr("button", listener);
 
     cursor.seat.handleActivity();
-    cursor.unhide();
 
     if (event.state == .released) {
         assert(cursor.pressed_count > 0);
@@ -744,40 +729,6 @@ fn handleRequestSetCursor(
     }
 }
 
-pub fn hide(cursor: *Cursor) void {
-    if (cursor.pressed_count > 0) return;
-
-    // Hiding the cursor and sending wl_pointer.leave whlie a pointer constraint
-    // is active does not make much sense. In particular, doing so seems to interact
-    // poorly with Xwayland's pointer constraints implementation.
-    if (cursor.constraint) |constraint| {
-        if (constraint.state == .active) return;
-    }
-
-    cursor.hidden = true;
-    cursor.wlr_cursor.unsetImage();
-    cursor.xcursor_name = null;
-    cursor.seat.wlr_seat.pointerNotifyClearFocus();
-    cursor.hide_cursor_timer.timerUpdate(0) catch {
-        log.err("failed to update cursor hide timeout", .{});
-    };
-}
-
-pub fn unhide(cursor: *Cursor) void {
-    cursor.hide_cursor_timer.timerUpdate(server.config.cursor_hide_timeout) catch {
-        log.err("failed to update cursor hide timeout", .{});
-    };
-    if (!cursor.hidden) return;
-    cursor.hidden = false;
-    cursor.updateState();
-}
-
-fn handleHideCursorTimeout(cursor: *Cursor) c_int {
-    log.debug("hide cursor timeout", .{});
-    cursor.hide();
-    return 0;
-}
-
 pub fn startMove(cursor: *Cursor, view: *View) void {
     // Guard against assertion in enterMode()
     if (view.current.output == null) return;
@@ -884,8 +835,6 @@ fn enterMode(cursor: *Cursor, mode: Mode, view: *View, xcursor_name: [*:0]const
 }
 
 fn processMotion(cursor: *Cursor, device: *wlr.InputDevice, time: u32, delta_x: f64, delta_y: f64, unaccel_dx: f64, unaccel_dy: f64) void {
-    cursor.unhide();
-
     server.input_manager.relative_pointer_manager.sendRelativeMotion(
         cursor.seat.wlr_seat,
         @as(u64, time) * 1000,
@@ -913,7 +862,6 @@ fn processMotion(cursor: *Cursor, device: *wlr.InputDevice, time: u32, delta_x:
 
             switch (cursor.mode) {
                 .passthrough => {
-                    cursor.checkFocusFollowsCursor();
                     cursor.passthrough(time);
                 },
                 .down => |data| {
@@ -1008,90 +956,24 @@ fn processMotion(cursor: *Cursor, device: *wlr.InputDevice, time: u32, delta_x:
     }
 }
 
-pub fn checkFocusFollowsCursor(cursor: *Cursor) void {
-    // Don't do focus-follows-cursor if a pointer drag is in progress as focus
-    // change can't occur.
-    if (cursor.seat.drag == .pointer) return;
-    if (server.config.focus_follows_cursor == .disabled) return;
-
-    const last_target = cursor.focus_follows_cursor_target;
-    cursor.updateFocusFollowsCursorTarget();
-    if (cursor.focus_follows_cursor_target) |view| {
-        // In .normal mode, only entering a view changes focus
-        if (server.config.focus_follows_cursor == .normal and
-            last_target == view) return;
-        if (cursor.seat.focused != .view or cursor.seat.focused.view != view) {
-            if (view.current.output) |output| {
-                cursor.seat.focusOutput(output);
-                cursor.seat.focus(view);
-                server.root.applyPending();
-            }
-        }
-    } else {
-        // The output doesn't contain any views, just focus the output.
-        cursor.updateOutputFocus(cursor.wlr_cursor.x, cursor.wlr_cursor.y);
-    }
-}
-
-fn updateFocusFollowsCursorTarget(cursor: *Cursor) void {
-    if (server.root.at(cursor.wlr_cursor.x, cursor.wlr_cursor.y)) |result| {
-        switch (result.data) {
-            .view => |view| {
-                // Some windows have an input region bigger than their window
-                // geometry, we only want to update this when the cursor
-                // properly enters the window (the box that we draw borders around)
-                // in order to avoid clashes with cursor warping on focus change.
-                if (view.current.output) |output| {
-                    var output_layout_box: wlr.Box = undefined;
-                    server.root.output_layout.getBox(output.wlr_output, &output_layout_box);
-
-                    const cursor_ox = cursor.wlr_cursor.x - @as(f64, @floatFromInt(output_layout_box.x));
-                    const cursor_oy = cursor.wlr_cursor.y - @as(f64, @floatFromInt(output_layout_box.y));
-                    if (view.current.box.containsPoint(cursor_ox, cursor_oy)) {
-                        cursor.focus_follows_cursor_target = view;
-                    }
-                }
-            },
-            .layer_surface, .lock_surface => {
-                cursor.focus_follows_cursor_target = null;
-            },
-            .override_redirect => {
-                assert(build_options.xwayland);
-                assert(server.xwayland != null);
-                cursor.focus_follows_cursor_target = null;
-            },
-        }
-    } else {
-        // The cursor is not above any view
-        cursor.focus_follows_cursor_target = null;
-    }
-}
-
 /// Handle potential change in location of views on the output, as well as
 /// the target view of a cursor operation potentially being moved to a non-visible tag,
 /// becoming fullscreen, etc.
 pub fn updateState(cursor: *Cursor) void {
-    if (cursor.may_need_warp) {
-        cursor.warp();
-    }
-
     if (cursor.constraint) |constraint| {
         constraint.updateState();
     }
 
     switch (cursor.mode) {
         .passthrough => {
-            cursor.updateFocusFollowsCursorTarget();
-            if (!cursor.hidden) {
-                var now: posix.timespec = undefined;
-                posix.clock_gettime(posix.CLOCK.MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported");
-                const msec: u32 = @intCast(now.tv_sec * std.time.ms_per_s +
-                    @divTrunc(now.tv_nsec, std.time.ns_per_ms));
-                cursor.passthrough(msec);
-            }
+            var now: posix.timespec = undefined;
+            posix.clock_gettime(posix.CLOCK.MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported");
+            const msec: u32 = @intCast(now.tv_sec * std.time.ms_per_s +
+                @divTrunc(now.tv_nsec, std.time.ns_per_ms));
+            cursor.passthrough(msec);
         },
         // TODO: Leave down mode if the target surface is no longer visible.
-        .down => assert(!cursor.hidden),
+        .down => {},
         .move, .resize => {
             // Moving and resizing of views is handled through the transaction system. Therefore,
             // we must inspect the inflight_mode instead if a move or a resize is in progress.
@@ -1110,7 +992,6 @@ pub fn updateState(cursor: *Cursor) void {
             switch (cursor.inflight_mode) {
                 .passthrough, .down => {},
                 inline .move, .resize => |data, mode| {
-                    assert(!cursor.hidden);
 
                     // These conditions are checked in Root.applyPending()
                     const output = data.view.current.output orelse return;
@@ -1166,54 +1047,6 @@ fn passthrough(cursor: *Cursor, time: u32) void {
     cursor.clearFocus();
 }
 
-fn warp(cursor: *Cursor) void {
-    cursor.may_need_warp = false;
-
-    const focused_output = cursor.seat.focused_output orelse 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(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 (cursor.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,
-            },
-            .override_redirect => |override_redirect| wlr.Box{
-                .x = override_redirect.xwayland_surface.x,
-                .y = override_redirect.xwayland_surface.y,
-                .width = override_redirect.xwayland_surface.width,
-                .height = override_redirect.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 = 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(cursor.wlr_cursor.x, cursor.wlr_cursor.y) or
-        (usable_layout_box.containsPoint(cursor.wlr_cursor.x, cursor.wlr_cursor.y) and
-        !target_box.containsPoint(cursor.wlr_cursor.x, cursor.wlr_cursor.y)))
-    {
-        const lx: f64 = @floatFromInt(target_box.x + @divTrunc(target_box.width, 2));
-        const ly: f64 = @floatFromInt(target_box.y + @divTrunc(target_box.height, 2));
-        if (!cursor.wlr_cursor.warp(null, lx, ly)) {
-            log.err("failed to warp cursor on focus change", .{});
-        }
-    }
-}
-
 fn updateDragIcons(cursor: *Cursor) void {
     var it = server.root.drag_icons.children.iterator(.forward);
     while (it.next()) |node| {
diff --git a/river/Keyboard.zig b/river/Keyboard.zig
index 3c659d8..b0479d3 100644
--- a/river/Keyboard.zig
+++ b/river/Keyboard.zig
@@ -168,17 +168,6 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
 
     const keysyms = xkb_state.keyGetSyms(keycode);
 
-    // Hide cursor when typing
-    for (keysyms) |sym| {
-        if (server.config.cursor_hide_when_typing == .enabled and
-            !released and
-            !isModifier(sym))
-        {
-            keyboard.device.seat.cursor.hide();
-            break;
-        }
-    }
-
     for (keysyms) |sym| {
         if (!released and handleBuiltinMapping(sym)) return;
     }
diff --git a/river/Output.zig b/river/Output.zig
index e1382ca..daaa20d 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -164,8 +164,6 @@ current: struct {
 /// Remembered version of tags (from last run)
 previous_tags: u32 = 1 << 0,
 
-attach_mode: ?Config.AttachMode = null,
-
 destroy: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleDestroy),
 request_state: wl.Listener(*wlr.Output.event.RequestState) = wl.Listener(*wlr.Output.event.RequestState).init(handleRequestState),
 frame: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleFrame),
@@ -597,7 +595,3 @@ fn setTitle(output: Output) void {
         output.wlr_output.x11SetTitle(title);
     }
 }
-
-pub fn attachMode(output: Output) Config.AttachMode {
-    return output.attach_mode orelse server.config.default_attach_mode;
-}
diff --git a/river/Seat.zig b/river/Seat.zig
index 0e5638e..b5c160f 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -284,10 +284,6 @@ pub fn setFocusRaw(seat: *Seat, new_focus: FocusTarget) void {
             }
         }
     }
-
-    // Depending on configuration and cursor position, changing keyboard focus
-    // may cause the cursor to be warped.
-    seat.cursor.may_need_warp = true;
 }
 
 /// Send keyboard enter/leave events and handle pointer constraints
@@ -325,10 +321,6 @@ pub fn focusOutput(seat: *Seat, output: ?*Output) void {
     if (seat.focused_output == output) return;
 
     seat.focused_output = output;
-
-    // Depending on configuration and cursor position, changing output focus
-    // may cause the cursor to be warped.
-    seat.cursor.may_need_warp = true;
 }
 
 pub fn handleActivity(seat: Seat) void {
@@ -563,7 +555,6 @@ fn handleDragDestroy(listener: *wl.Listener(*wlr.Drag), _: *wlr.Drag) void {
     switch (seat.drag) {
         .none => unreachable,
         .pointer => {
-            seat.cursor.checkFocusFollowsCursor();
             seat.cursor.updateState();
         },
         .touch => {},
diff --git a/river/View.zig b/river/View.zig
index e6654c2..7d10c12 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -54,11 +54,6 @@ const Impl = union(enum) {
     none,
 };
 
-const AttachRelativeMode = enum {
-    above,
-    below,
-};
-
 pub const State = struct {
     /// The output the view is currently assigned to.
     /// May be null if there are no outputs or for newly created views.
@@ -519,13 +514,7 @@ pub fn setPendingOutput(view: *View, output: *Output) void {
     view.pending_wm_stack_link.remove();
     view.pending_focus_stack_link.remove();
 
-    switch (output.attachMode()) {
-        .top => output.pending.wm_stack.prepend(view),
-        .bottom => output.pending.wm_stack.append(view),
-        .after => |n| view.attachAfter(&output.pending, n),
-        .above => view.attachRelative(&output.pending, .above),
-        .below => view.attachRelative(&output.pending, .below),
-    }
+    output.pending.wm_stack.prepend(view);
     output.pending.focus_stack.prepend(view);
 
     if (view.pending.fullscreen) {
@@ -578,49 +567,6 @@ pub fn applyConstraints(view: *View, box: *wlr.Box) void {
     box.height = math.clamp(box.height, view.constraints.min_height, view.constraints.max_height);
 }
 
-/// Attach after n visible, not-floating views in the pending wm_stack
-pub fn attachAfter(view: *View, output_pending: *Output.PendingState, n: usize) void {
-    var visible: u32 = 0;
-    var it = output_pending.wm_stack.iterator(.forward);
-
-    while (it.next()) |other| {
-        if (visible >= n) break;
-        if (!other.pending.float and other.pending.tags & output_pending.tags != 0) {
-            visible += 1;
-        }
-    }
-
-    it.current.prev.?.insert(&view.pending_wm_stack_link);
-}
-
-/// Attach above or below the currently focused view
-pub fn attachRelative(view: *View, output_pending: *Output.PendingState, mode: AttachRelativeMode) void {
-    const focus_stack_head = output_pending.focus_stack.first() orelse {
-        output_pending.wm_stack.append(view);
-        return;
-    };
-
-    // There are two cases to consider here:
-    //
-    // 1. The first view in the focus stack is visible given the currently focused tags.
-    // In this case, inserting directly before/after that view in the wm_stack is correct.
-    //
-    // 2. There are no views visible given the currently focused tags. In this case it
-    // doesn't matter where in the wm_stack the new view is inserted as it will be the only
-    // view visible.
-
-    var it = output_pending.wm_stack.iterator(.forward);
-    while (it.next()) |other| {
-        if (other == focus_stack_head) {
-            switch (mode) {
-                .above => other.pending_wm_stack_link.prev.?.insert(&view.pending_wm_stack_link),
-                .below => other.pending_wm_stack_link.insert(&view.pending_wm_stack_link),
-            }
-            return;
-        }
-    }
-}
-
 /// Called by the impl when the surface is ready to be displayed
 pub fn map(view: *View) !void {
     log.debug("view '{?s}' mapped", .{view.getTitle()});
@@ -675,13 +621,7 @@ pub fn map(view: *View) !void {
         view.pending_wm_stack_link.remove();
         view.pending_focus_stack_link.remove();
 
-        switch (server.config.default_attach_mode) {
-            .top => server.root.fallback_pending.wm_stack.prepend(view),
-            .bottom => server.root.fallback_pending.wm_stack.append(view),
-            .after => |n| view.attachAfter(&server.root.fallback_pending, n),
-            .above => view.attachRelative(&server.root.fallback_pending, .above),
-            .below => view.attachRelative(&server.root.fallback_pending, .below),
-        }
+        server.root.fallback_pending.wm_stack.prepend(view);
         server.root.fallback_pending.focus_stack.prepend(view);
 
         view.inflight_wm_stack_link.remove();