Implement the rest of river_layer_shell_v1
I still needed to call setDefault, as well as handle the .focus_* events from the river_layer_shell_seat_v1. I also fixed a memory leak where the output wasn't destroying its river_layer_shell_output_v1.
This commit is contained in:
parent
5c427234d7
commit
1cfafc4fb3
2 changed files with 75 additions and 32 deletions
|
|
@ -118,10 +118,10 @@ pub fn destroy(output: *Output) void {
|
||||||
window.link.remove();
|
window.link.remove();
|
||||||
window.destroy();
|
window.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
output.tag_layout_overrides.deinit(utils.gpa);
|
output.tag_layout_overrides.deinit(utils.gpa);
|
||||||
output.deinitWallpaperLayerSurface();
|
output.deinitWallpaperLayerSurface();
|
||||||
output.river_output_v1.destroy();
|
output.river_output_v1.destroy();
|
||||||
|
output.river_layer_shell_output_v1.destroy();
|
||||||
utils.gpa.destroy(output);
|
utils.gpa.destroy(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
105
src/Seat.zig
105
src/Seat.zig
|
|
@ -7,9 +7,11 @@ const Seat = @This();
|
||||||
context: *Context,
|
context: *Context,
|
||||||
|
|
||||||
river_seat_v1: *river.SeatV1,
|
river_seat_v1: *river.SeatV1,
|
||||||
|
river_layer_shell_seat_v1: *river.LayerShellSeatV1,
|
||||||
|
|
||||||
focused_window: ?*Window,
|
focused_window: ?*Window,
|
||||||
focused_output: ?*Output,
|
focused_output: ?*Output,
|
||||||
|
layer_focus: LayerFocus = .focus_none,
|
||||||
|
|
||||||
pointer_op: PointerOp = .none,
|
pointer_op: PointerOp = .none,
|
||||||
|
|
||||||
|
|
@ -22,9 +24,14 @@ link: wl.list.Link,
|
||||||
move_pointer_binding: ?*river.PointerBindingV1 = null,
|
move_pointer_binding: ?*river.PointerBindingV1 = null,
|
||||||
resize_pointer_binding: ?*river.PointerBindingV1 = null,
|
resize_pointer_binding: ?*river.PointerBindingV1 = null,
|
||||||
|
|
||||||
|
// We just steal the Event's tag type to use as our enum. If another event is added
|
||||||
|
// that's *not* for focus, we'll have to create our own enum and just keep it in sync.
|
||||||
|
pub const LayerFocus = @typeInfo(river.LayerShellSeatV1.Event).@"union".tag_type.?;
|
||||||
|
|
||||||
pub const PendingManage = struct {
|
pub const PendingManage = struct {
|
||||||
window: ?PendingWindow = null,
|
window: ?PendingWindow = null,
|
||||||
output: ?PendingOutput = null,
|
output: ?PendingOutput = null,
|
||||||
|
layer_focus: ?LayerFocus = null,
|
||||||
should_warp_pointer: bool = false,
|
should_warp_pointer: bool = false,
|
||||||
|
|
||||||
op_delta: ?struct { dx: i32, dy: i32 } = null,
|
op_delta: ?struct { dx: i32, dy: i32 } = null,
|
||||||
|
|
@ -63,12 +70,14 @@ pub fn create(context: *Context, river_seat_v1: *river.SeatV1) !*Seat {
|
||||||
seat.* = .{
|
seat.* = .{
|
||||||
.context = context,
|
.context = context,
|
||||||
.river_seat_v1 = river_seat_v1,
|
.river_seat_v1 = river_seat_v1,
|
||||||
|
.river_layer_shell_seat_v1 = try context.river_layer_shell_v1.getSeat(river_seat_v1),
|
||||||
.focused_window = null,
|
.focused_window = null,
|
||||||
.focused_output = null,
|
.focused_output = null,
|
||||||
.link = undefined, // Handled by the wl.list
|
.link = undefined, // Handled by the wl.list
|
||||||
};
|
};
|
||||||
|
|
||||||
seat.river_seat_v1.setListener(*Seat, seatListener, seat);
|
seat.river_seat_v1.setListener(*Seat, seatListener, seat);
|
||||||
|
seat.river_layer_shell_seat_v1.setListener(*Seat, riverLayerShellSeatListener, seat);
|
||||||
|
|
||||||
return seat;
|
return seat;
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +86,7 @@ pub fn destroy(seat: *Seat) void {
|
||||||
if (seat.move_pointer_binding) |binding| binding.destroy();
|
if (seat.move_pointer_binding) |binding| binding.destroy();
|
||||||
if (seat.resize_pointer_binding) |binding| binding.destroy();
|
if (seat.resize_pointer_binding) |binding| binding.destroy();
|
||||||
seat.river_seat_v1.destroy();
|
seat.river_seat_v1.destroy();
|
||||||
|
seat.river_layer_shell_seat_v1.destroy();
|
||||||
utils.gpa.destroy(seat);
|
utils.gpa.destroy(seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,6 +113,11 @@ fn seatListener(river_seat_v1: *river.SeatV1, event: river.SeatV1.Event, seat: *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn riverLayerShellSeatListener(river_layer_shell_seat_v1: *river.LayerShellSeatV1, event: river.LayerShellSeatV1.Event, seat: *Seat) void {
|
||||||
|
assert(seat.river_layer_shell_seat_v1 == river_layer_shell_seat_v1);
|
||||||
|
seat.pending_manage.layer_focus = std.meta.activeTag(event);
|
||||||
|
}
|
||||||
|
|
||||||
// river_window_v1 needs to be optional because ev.window is optional
|
// river_window_v1 needs to be optional because ev.window is optional
|
||||||
fn setWindowFocus(seat: *Seat, river_window_v1: ?*river.WindowV1) void {
|
fn setWindowFocus(seat: *Seat, river_window_v1: ?*river.WindowV1) void {
|
||||||
const wv1 = river_window_v1 orelse return;
|
const wv1 = river_window_v1 orelse return;
|
||||||
|
|
@ -116,33 +131,37 @@ fn setWindowFocus(seat: *Seat, river_window_v1: ?*river.WindowV1) void {
|
||||||
pub fn manage(seat: *Seat) void {
|
pub fn manage(seat: *Seat) void {
|
||||||
defer seat.pending_manage = .{};
|
defer seat.pending_manage = .{};
|
||||||
|
|
||||||
if (seat.pending_manage.window) |pending_window| {
|
// Focus events are ignored by the compositor when a layer shell has exclusive focus.
|
||||||
switch (pending_window) {
|
if (seat.layer_focus != .focus_exclusive) {
|
||||||
.window => |window| {
|
if (seat.pending_manage.window) |pending_window| {
|
||||||
if (seat.focused_window) |focused| {
|
switch (pending_window) {
|
||||||
// Tell the previously focused Window that it's no longer focused
|
.window => |window| {
|
||||||
if (focused != window) {
|
if (seat.focused_window) |focused| {
|
||||||
|
// Tell the previously focused Window that it's no longer focused
|
||||||
|
if (focused != window) {
|
||||||
|
focused.pending_render.focused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seat.focused_window = window;
|
||||||
|
seat.river_seat_v1.focusWindow(window.river_window_v1);
|
||||||
|
window.pending_render.focused = true;
|
||||||
|
},
|
||||||
|
.clear_focus => {
|
||||||
|
if (seat.focused_window) |focused| {
|
||||||
|
// Tell the previously focused Window that it's no longer focused
|
||||||
focused.pending_render.focused = false;
|
focused.pending_render.focused = false;
|
||||||
}
|
}
|
||||||
}
|
seat.focused_window = null;
|
||||||
seat.focused_window = window;
|
seat.river_seat_v1.clearFocus();
|
||||||
seat.river_seat_v1.focusWindow(window.river_window_v1);
|
},
|
||||||
window.pending_render.focused = true;
|
}
|
||||||
},
|
|
||||||
.clear_focus => {
|
|
||||||
if (seat.focused_window) |focused| {
|
|
||||||
// Tell the previously focused Window that it's no longer focused
|
|
||||||
focused.pending_render.focused = false;
|
|
||||||
}
|
|
||||||
seat.focused_window = null;
|
|
||||||
seat.river_seat_v1.clearFocus();
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (seat.pending_manage.output) |pending_output| {
|
if (seat.pending_manage.output) |pending_output| {
|
||||||
switch (pending_output) {
|
switch (pending_output) {
|
||||||
.output => |output| {
|
.output => |output| {
|
||||||
seat.focused_output = output;
|
seat.focused_output = output;
|
||||||
|
output.river_layer_shell_output_v1.setDefault();
|
||||||
},
|
},
|
||||||
.clear_focus => {
|
.clear_focus => {
|
||||||
seat.focused_output = null;
|
seat.focused_output = null;
|
||||||
|
|
@ -150,18 +169,42 @@ pub fn manage(seat: *Seat) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seat.pending_manage.should_warp_pointer) blk: {
|
// Handle layer focus changes after window focus so focused_window is up to date.
|
||||||
if (seat.context.config.pointer_warp_on_focus_change) {
|
// This overrides whatever pending_render.focused the window focus block just set.
|
||||||
const window = seat.focused_window orelse {
|
if (seat.pending_manage.layer_focus) |layer_focus| {
|
||||||
log.warn("Trying to warp-on-focus-change without a focused window.", .{});
|
seat.layer_focus = layer_focus;
|
||||||
break :blk;
|
switch (layer_focus) {
|
||||||
};
|
.focus_exclusive,
|
||||||
// Warp pointer to center of focused window;
|
.focus_non_exclusive,
|
||||||
// because the x and y coords are set during render, we need to check if
|
=> {
|
||||||
// there are new coordinates in window.pending_render.
|
if (seat.focused_window) |focused_window| {
|
||||||
const pointer_x: i32 = (window.pending_render.x orelse window.x) + @divFloor(window.width, 2);
|
focused_window.pending_render.focused = false;
|
||||||
const pointer_y: i32 = (window.pending_render.y orelse window.y) + @divFloor(window.height, 2);
|
}
|
||||||
seat.river_seat_v1.pointerWarp(pointer_x, pointer_y);
|
},
|
||||||
|
.focus_none => {
|
||||||
|
if (seat.focused_window) |focused_window| {
|
||||||
|
seat.river_seat_v1.focusWindow(focused_window.river_window_v1);
|
||||||
|
focused_window.pending_render.focused = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus doesn't change during .focus_exclusive, so pointer shouldn't get warped, either
|
||||||
|
if (seat.layer_focus != .focus_exclusive) {
|
||||||
|
if (seat.pending_manage.should_warp_pointer) blk: {
|
||||||
|
if (seat.context.config.pointer_warp_on_focus_change) {
|
||||||
|
const window = seat.focused_window orelse {
|
||||||
|
log.warn("Trying to warp-on-focus-change without a focused window.", .{});
|
||||||
|
break :blk;
|
||||||
|
};
|
||||||
|
// Warp pointer to center of focused window;
|
||||||
|
// because the x and y coords are set during render, we need to check if
|
||||||
|
// there are new coordinates in window.pending_render.
|
||||||
|
const pointer_x: i32 = (window.pending_render.x orelse window.x) + @divFloor(window.width, 2);
|
||||||
|
const pointer_y: i32 = (window.pending_render.y orelse window.y) + @divFloor(window.height, 2);
|
||||||
|
seat.river_seat_v1.pointerWarp(pointer_x, pointer_y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue