This commit is contained in:
2025-06-29 19:31:25 +09:00
68 changed files with 1298 additions and 1002 deletions

View File

@ -33,7 +33,6 @@ const InputDevice = @import("InputDevice.zig");
const InputManager = @import("InputManager.zig");
const InputRelay = @import("InputRelay.zig");
const Keyboard = @import("Keyboard.zig");
const KeyboardGroup = @import("KeyboardGroup.zig");
const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const Mapping = @import("Mapping.zig");
@ -84,7 +83,7 @@ mapping_repeat_timer: *wl.EventSource,
/// Currently repeating mapping, if any
repeating_mapping: ?*const Mapping = null,
keyboard_groups: std.TailQueue(KeyboardGroup) = .{},
keyboard_group: *wlr.KeyboardGroup,
/// Currently focused output. Null only when there are no outputs at all.
focused_output: ?*Output = null,
@ -121,12 +120,15 @@ pub fn init(seat: *Seat, name: [*:0]const u8) !void {
.cursor = undefined,
.relay = undefined,
.mapping_repeat_timer = mapping_repeat_timer,
.keyboard_group = try wlr.KeyboardGroup.create(),
};
seat.wlr_seat.data = @intFromPtr(seat);
seat.wlr_seat.data = seat;
try seat.cursor.init(seat);
seat.relay.init();
try seat.tryAddDevice(&seat.keyboard_group.keyboard.base);
seat.wlr_seat.events.request_set_selection.add(&seat.request_set_selection);
seat.wlr_seat.events.request_start_drag.add(&seat.request_start_drag);
seat.wlr_seat.events.start_drag.add(&seat.start_drag);
@ -142,9 +144,7 @@ pub fn deinit(seat: *Seat) void {
seat.cursor.deinit();
seat.mapping_repeat_timer.remove();
while (seat.keyboard_groups.first) |node| {
node.data.destroy();
}
seat.keyboard_group.destroy();
seat.request_set_selection.link.remove();
seat.request_start_drag.link.remove();
@ -165,14 +165,21 @@ pub fn focus(seat: *Seat, _target: ?*View) void {
// Views may not receive focus while locked.
if (server.lock_manager.state != .unlocked) return;
// While a layer surface is exclusively focused, views may not receive focus
// A layer surface with exclusive focus will prevent any view from gaining
// focus if it is on the top or overlay layer. Otherwise, only steal focus
// from a focused layer surface if there is an explicit target view.
if (seat.focused == .layer) {
const wlr_layer_surface = seat.focused.layer.wlr_layer_surface;
assert(wlr_layer_surface.surface.mapped);
if (wlr_layer_surface.current.keyboard_interactive == .exclusive and
(wlr_layer_surface.current.layer == .top or wlr_layer_surface.current.layer == .overlay))
{
return;
switch (wlr_layer_surface.current.keyboard_interactive) {
.none => {},
.exclusive => switch (wlr_layer_surface.current.layer) {
.top, .overlay => return,
.bottom, .background => if (target == null) return,
_ => {},
},
.on_demand => if (target == null) return,
_ => {},
}
}
@ -282,7 +289,7 @@ pub fn setFocusRaw(seat: *Seat, new_focus: FocusTarget) void {
if (seat.cursor.constraint) |constraint| {
assert(constraint.wlr_constraint == wlr_constraint);
} else {
seat.cursor.constraint = @ptrFromInt(wlr_constraint.data);
seat.cursor.constraint = @alignCast(@ptrCast(wlr_constraint.data));
assert(seat.cursor.constraint != null);
}
}
@ -309,7 +316,7 @@ pub fn keyboardEnterOrLeave(seat: *Seat, target_surface: ?*wlr.Surface) void {
fn keyboardNotifyEnter(seat: *Seat, wlr_surface: *wlr.Surface) void {
if (seat.wlr_seat.getKeyboard()) |wlr_keyboard| {
const keyboard: *Keyboard = @ptrFromInt(wlr_keyboard.data);
const keyboard: *Keyboard = @alignCast(@ptrCast(wlr_keyboard.data));
var keycodes: std.BoundedArray(u32, Keyboard.Pressed.capacity) = .{};
for (keyboard.pressed.keys.constSlice()) |item| {
@ -504,11 +511,11 @@ fn tryAddDevice(seat: *Seat, wlr_device: *wlr.InputDevice) !void {
seat.cursor.wlr_cursor.attachInputDevice(wlr_device);
},
.tablet_tool => {
.tablet => {
try Tablet.create(seat, wlr_device);
seat.cursor.wlr_cursor.attachInputDevice(wlr_device);
},
.switch_device => {
.@"switch" => {
const switch_device = try util.gpa.create(Switch);
errdefer util.gpa.destroy(switch_device);
@ -531,7 +538,7 @@ pub fn updateCapabilities(seat: *Seat) void {
switch (device.wlr_device.type) {
.keyboard => capabilities.keyboard = true,
.touch => capabilities.touch = true,
.pointer, .switch_device, .tablet_tool => {},
.pointer, .@"switch", .tablet => {},
.tablet_pad => unreachable,
}
}
@ -544,7 +551,7 @@ fn handleRequestSetSelection(
listener: *wl.Listener(*wlr.Seat.event.RequestSetSelection),
event: *wlr.Seat.event.RequestSetSelection,
) void {
const seat = @fieldParentPtr(Seat, "request_set_selection", listener);
const seat: *Seat = @fieldParentPtr("request_set_selection", listener);
seat.wlr_seat.setSelection(event.source, event.serial);
}
@ -552,7 +559,7 @@ fn handleRequestStartDrag(
listener: *wl.Listener(*wlr.Seat.event.RequestStartDrag),
event: *wlr.Seat.event.RequestStartDrag,
) void {
const seat = @fieldParentPtr(Seat, "request_start_drag", listener);
const seat: *Seat = @fieldParentPtr("request_start_drag", listener);
// The start_drag request is ignored by wlroots if a drag is currently in progress.
assert(seat.drag == .none);
@ -576,7 +583,7 @@ fn handleRequestStartDrag(
}
fn handleStartDrag(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void {
const seat = @fieldParentPtr(Seat, "start_drag", listener);
const seat: *Seat = @fieldParentPtr("start_drag", listener);
assert(seat.drag == .none);
switch (wlr_drag.grab_type) {
@ -599,7 +606,7 @@ fn handleStartDrag(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void
}
fn handleDragDestroy(listener: *wl.Listener(*wlr.Drag), _: *wlr.Drag) void {
const seat = @fieldParentPtr(Seat, "drag_destroy", listener);
const seat: *Seat = @fieldParentPtr("drag_destroy", listener);
seat.drag_destroy.link.remove();
switch (seat.drag) {
@ -617,6 +624,6 @@ fn handleRequestSetPrimarySelection(
listener: *wl.Listener(*wlr.Seat.event.RequestSetPrimarySelection),
event: *wlr.Seat.event.RequestSetPrimarySelection,
) void {
const seat = @fieldParentPtr(Seat, "request_set_primary_selection", listener);
const seat: *Seat = @fieldParentPtr("request_set_primary_selection", listener);
seat.wlr_seat.setPrimarySelection(event.source, event.serial);
}