Fix pointer warp for new and closed windows
This commit is contained in:
parent
bfa41f36b0
commit
c953fe3d68
4 changed files with 119 additions and 104 deletions
40
src/Seat.zig
40
src/Seat.zig
|
|
@ -10,14 +10,12 @@ seat_v1: *river.SeatV1,
|
||||||
|
|
||||||
focused: ?*Window,
|
focused: ?*Window,
|
||||||
|
|
||||||
/// Used to manage updates to various aspect of Seat's state
|
/// State consumed in manage phase, reset at end of manage().
|
||||||
/// Gets reset at the end of every Seat.manage() call.
|
pending_manage: PendingManage = .{},
|
||||||
pending_state: PendingState = .{},
|
|
||||||
|
|
||||||
link: wl.list.Link,
|
link: wl.list.Link,
|
||||||
|
|
||||||
/// Used to manage updates to various aspect of Seat's state
|
pub const PendingManage = struct {
|
||||||
pub const PendingState = struct {
|
|
||||||
pending_focus: ?PendingFocus = null,
|
pending_focus: ?PendingFocus = null,
|
||||||
should_warp_pointer: bool = false,
|
should_warp_pointer: bool = false,
|
||||||
|
|
||||||
|
|
@ -51,12 +49,12 @@ fn seatListener(river_seat_v1: *river.SeatV1, event: river.SeatV1.Event, seat: *
|
||||||
.pointer_enter => |ev| {
|
.pointer_enter => |ev| {
|
||||||
const window_v1 = ev.window orelse return;
|
const window_v1 = ev.window orelse return;
|
||||||
const window: *Window = @ptrCast(@alignCast(window_v1.getUserData()));
|
const window: *Window = @ptrCast(@alignCast(window_v1.getUserData()));
|
||||||
seat.pending_state.pending_focus = .{ .window = window };
|
seat.pending_manage.pending_focus = .{ .window = window };
|
||||||
},
|
},
|
||||||
.window_interaction => |ev| {
|
.window_interaction => |ev| {
|
||||||
const window_v1 = ev.window orelse return;
|
const window_v1 = ev.window orelse return;
|
||||||
const window: *Window = @ptrCast(@alignCast(window_v1.getUserData()));
|
const window: *Window = @ptrCast(@alignCast(window_v1.getUserData()));
|
||||||
seat.pending_state.pending_focus = .{ .window = window };
|
seat.pending_manage.pending_focus = .{ .window = window };
|
||||||
},
|
},
|
||||||
else => |ev| {
|
else => |ev| {
|
||||||
log.debug("unhandled event: {s}", .{@tagName(ev)});
|
log.debug("unhandled event: {s}", .{@tagName(ev)});
|
||||||
|
|
@ -65,32 +63,42 @@ fn seatListener(river_seat_v1: *river.SeatV1, event: river.SeatV1.Event, seat: *
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn manage(seat: *Seat) void {
|
pub fn manage(seat: *Seat) void {
|
||||||
defer seat.pending_state = .{};
|
defer seat.pending_manage = .{};
|
||||||
|
|
||||||
log.debug("Managing Seat, pending state={any}", .{seat.pending_state});
|
if (seat.pending_manage.pending_focus) |pending_focus| {
|
||||||
|
|
||||||
if (seat.pending_state.pending_focus) |pending_focus| {
|
|
||||||
switch (pending_focus) {
|
switch (pending_focus) {
|
||||||
.window => |window| {
|
.window => |window| {
|
||||||
|
if (seat.focused) |focused| {
|
||||||
|
// Tell the previously focused Window that it's no longer focused
|
||||||
|
if (focused != window) {
|
||||||
|
focused.pending_render.focused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
seat.focused = window;
|
seat.focused = window;
|
||||||
seat.seat_v1.focusWindow(window.window_v1);
|
seat.seat_v1.focusWindow(window.window_v1);
|
||||||
|
window.pending_render.focused = true;
|
||||||
},
|
},
|
||||||
.clear_focus => {
|
.clear_focus => {
|
||||||
|
if (seat.focused) |focused| {
|
||||||
|
// Tell the previously focused Window that it's no longer focused
|
||||||
|
focused.pending_render.focused = false;
|
||||||
|
}
|
||||||
seat.focused = null;
|
seat.focused = null;
|
||||||
seat.seat_v1.clearFocus();
|
seat.seat_v1.clearFocus();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seat.pending_state.should_warp_pointer) blk: {
|
if (seat.pending_manage.should_warp_pointer) {
|
||||||
const window = seat.focused orelse {
|
const window = seat.focused orelse {
|
||||||
log.err("Trying to warp pointer without focused window.", .{});
|
log.err("Trying to warp pointer without focused window.", .{});
|
||||||
break :blk;
|
return;
|
||||||
};
|
};
|
||||||
// TODO - CONFIG: Allow disabling this behaviour
|
// TODO - CONFIG: Allow disabling this behaviour
|
||||||
// Warp pointer to center of newly-focused windows
|
// Warp pointer to center of focused window;
|
||||||
const pointer_x: i32 = @divTrunc(window.x + window.width, 2);
|
// because the x and y coords are set later, we need to check them here.
|
||||||
const pointer_y: i32 = @divTrunc(window.y + window.height, 2);
|
const pointer_x: i32 = (window.pending_render.x orelse window.x) + @divTrunc(window.width, 2);
|
||||||
|
const pointer_y: i32 = (window.pending_render.y orelse window.y) + @divTrunc(window.height, 2);
|
||||||
seat.seat_v1.pointerWarp(pointer_x, pointer_y);
|
seat.seat_v1.pointerWarp(pointer_x, pointer_y);
|
||||||
log.debug("warped pointer to {}, {}", .{ pointer_x, pointer_y });
|
log.debug("warped pointer to {}, {}", .{ pointer_x, pointer_y });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,26 +19,29 @@ maximized: bool = false,
|
||||||
|
|
||||||
initialized: bool = false,
|
initialized: bool = false,
|
||||||
|
|
||||||
/// Used to manage updates to various aspect of Window's state
|
/// State consumed in manage() phase, reset at end of manage().
|
||||||
/// Gets reset at the end of every Window.manage() call.
|
pending_manage: PendingManage = .{},
|
||||||
///
|
|
||||||
/// It might be a good idea to have two separate versions of this so one
|
/// State consumed in render() phase, reset at end of render().
|
||||||
/// can be used in renders, but I think it's okay for now.
|
pending_render: PendingRender = .{},
|
||||||
pending_state: PendingState = .{},
|
|
||||||
|
|
||||||
link: wl.list.Link,
|
link: wl.list.Link,
|
||||||
|
|
||||||
/// Used to manage updates to various aspect of Window's state
|
pub const PendingManage = struct {
|
||||||
pub const PendingState = struct {
|
|
||||||
width: ?u31 = null,
|
width: ?u31 = null,
|
||||||
height: ?u31 = null,
|
height: ?u31 = null,
|
||||||
x: ?i32 = null,
|
|
||||||
y: ?i32 = null,
|
|
||||||
|
|
||||||
fullscreen: ?bool = null,
|
fullscreen: ?bool = null,
|
||||||
maximized: ?bool = null,
|
maximized: ?bool = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const PendingRender = struct {
|
||||||
|
x: ?i32 = null,
|
||||||
|
y: ?i32 = null,
|
||||||
|
|
||||||
|
focused: ?bool = null,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn init(window: *Window, context: *Context, river_window_v1: *river.WindowV1) void {
|
pub fn init(window: *Window, context: *Context, river_window_v1: *river.WindowV1) void {
|
||||||
window.* = .{
|
window.* = .{
|
||||||
.context = context,
|
.context = context,
|
||||||
|
|
@ -61,7 +64,18 @@ fn windowListener(river_window_v1: *river.WindowV1, event: river.WindowV1.Event,
|
||||||
var it = window.context.wm.seats.iterator(.forward);
|
var it = window.context.wm.seats.iterator(.forward);
|
||||||
while (it.next()) |seat| {
|
while (it.next()) |seat| {
|
||||||
if (seat.focused == window) {
|
if (seat.focused == window) {
|
||||||
seat.focused = null;
|
// Find another window to focus and warp pointer there
|
||||||
|
if (window.context.wm.getPrevWindow(window)) |next_focus| {
|
||||||
|
if (next_focus != window) {
|
||||||
|
seat.pending_manage.pending_focus = .{ .window = next_focus };
|
||||||
|
seat.pending_manage.should_warp_pointer = true;
|
||||||
|
} else {
|
||||||
|
// Only window in list - clear focus
|
||||||
|
seat.pending_manage.pending_focus = .clear_focus;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
seat.pending_manage.pending_focus = .clear_focus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,25 +111,19 @@ pub fn manage(window: *Window) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any new state since the last manage event
|
// Any new state since the last manage event
|
||||||
defer window.pending_state = .{};
|
defer window.pending_manage = .{};
|
||||||
const pending_state = window.pending_state;
|
const pending_manage = window.pending_manage;
|
||||||
// Layout (pre-computed by WindowManager.calculatePrimaryStackLayout())
|
// Layout (pre-computed by WindowManager.calculatePrimaryStackLayout())
|
||||||
if (pending_state.width) |new_width| {
|
if (pending_manage.width) |new_width| {
|
||||||
if (pending_state.height) |new_height| {
|
if (pending_manage.height) |new_height| {
|
||||||
window.width = new_width;
|
window.width = new_width;
|
||||||
window.height = new_height;
|
window.height = new_height;
|
||||||
window.window_v1.proposeDimensions(new_width, new_height);
|
window.window_v1.proposeDimensions(new_width, new_height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pending_state.x) |new_x| {
|
|
||||||
window.x = new_x;
|
|
||||||
}
|
|
||||||
if (pending_state.y) |new_y| {
|
|
||||||
window.y = new_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fullscreen and maximize operations
|
// Fullscreen and maximize operations
|
||||||
if (pending_state.fullscreen) |fullscreen| {
|
if (pending_manage.fullscreen) |fullscreen| {
|
||||||
window.fullscreen = fullscreen;
|
window.fullscreen = fullscreen;
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
const output = window.context.wm.outputs.first() orelse @panic("failed to get output");
|
const output = window.context.wm.outputs.first() orelse @panic("failed to get output");
|
||||||
|
|
@ -126,7 +134,7 @@ pub fn manage(window: *Window) void {
|
||||||
window.window_v1.informNotFullscreen();
|
window.window_v1.informNotFullscreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pending_state.maximized) |maximized| {
|
if (pending_manage.maximized) |maximized| {
|
||||||
window.maximized = maximized;
|
window.maximized = maximized;
|
||||||
if (maximized) {
|
if (maximized) {
|
||||||
window.window_v1.informMaximized();
|
window.window_v1.informMaximized();
|
||||||
|
|
@ -137,13 +145,28 @@ pub fn manage(window: *Window) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(window: *Window) void {
|
pub fn render(window: *Window) void {
|
||||||
// Set the window position using the pre-computed layout
|
defer window.pending_render = .{};
|
||||||
|
|
||||||
|
// TODO: We probably could just move these back to pending_manage and have PendingRiver.new_coords: bool
|
||||||
|
// This would also simplify the pointer warp behaviour in Seat.manage()
|
||||||
|
if (window.pending_render.x) |new_x| {
|
||||||
|
if (window.pending_render.y) |new_y| {
|
||||||
|
window.x = new_x;
|
||||||
|
window.y = new_y;
|
||||||
|
|
||||||
window.node_v1.setPosition(window.x, window.y);
|
window.node_v1.setPosition(window.x, window.y);
|
||||||
|
} else {
|
||||||
|
log.err("Window.pending_render with only x set", .{});
|
||||||
|
}
|
||||||
|
} else if (window.pending_render.y) |_| {
|
||||||
|
log.err("Window.pending_render with only y set", .{});
|
||||||
|
}
|
||||||
|
|
||||||
// Set borders
|
// Set borders
|
||||||
if (!window.fullscreen) {
|
if (!window.fullscreen) {
|
||||||
|
if (window.pending_render.focused) |focused| {
|
||||||
const border_width = window.context.config.border_width;
|
const border_width = window.context.config.border_width;
|
||||||
if (window.isFocused()) {
|
if (focused) {
|
||||||
const border_color_focused = window.context.config.border_color_focused;
|
const border_color_focused = window.context.config.border_color_focused;
|
||||||
window.window_v1.setBorders(.{ .top = true, .bottom = true, .left = true, .right = true }, border_width, border_color_focused.red, border_color_focused.green, border_color_focused.blue, border_color_focused.alpha);
|
window.window_v1.setBorders(.{ .top = true, .bottom = true, .left = true, .right = true }, border_width, border_color_focused.red, border_color_focused.green, border_color_focused.blue, border_color_focused.alpha);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -152,17 +175,6 @@ pub fn render(window: *Window) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Should probably make this better. Shouldn't be too bad since we only have one seat
|
|
||||||
// but there's no reason to do it like this
|
|
||||||
fn isFocused(window: *Window) bool {
|
|
||||||
var it = window.context.wm.seats.iterator(.forward);
|
|
||||||
while (it.next()) |seat| {
|
|
||||||
if (seat.focused == window) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
|
||||||
|
|
@ -87,11 +87,11 @@ fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
||||||
while (it.next()) |window| {
|
while (it.next()) |window| {
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
// Single window: maximize
|
// Single window: maximize
|
||||||
window.pending_state.x = output_x;
|
window.pending_render.x = output_x;
|
||||||
window.pending_state.y = output_y;
|
window.pending_render.y = output_y;
|
||||||
window.pending_state.width = output_width;
|
window.pending_manage.width = output_width;
|
||||||
window.pending_state.height = output_height;
|
window.pending_manage.height = output_height;
|
||||||
window.pending_state.maximized = true;
|
window.pending_manage.maximized = true;
|
||||||
} else {
|
} else {
|
||||||
// Multiple windows: primary/stack layout
|
// Multiple windows: primary/stack layout
|
||||||
// TODO: Support multiple windows in primary stack
|
// TODO: Support multiple windows in primary stack
|
||||||
|
|
@ -99,25 +99,25 @@ fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
||||||
const stack_width: u31 = output_width - primary_width;
|
const stack_width: u31 = output_width - primary_width;
|
||||||
const stack_count = count - 1;
|
const stack_count = count - 1;
|
||||||
const stack_height: u31 = @divFloor(output_height, stack_count);
|
const stack_height: u31 = @divFloor(output_height, stack_count);
|
||||||
window.pending_state.maximized = false;
|
window.pending_manage.maximized = false;
|
||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
// Primary window (first window) - right side
|
// Primary window (first window) - right side
|
||||||
window.pending_state.x = output_x + @as(i32, stack_width);
|
window.pending_render.x = output_x + @as(i32, stack_width);
|
||||||
window.pending_state.y = output_y;
|
window.pending_render.y = output_y;
|
||||||
window.pending_state.width = primary_width;
|
window.pending_manage.width = primary_width;
|
||||||
window.pending_state.height = output_height;
|
window.pending_manage.height = output_height;
|
||||||
} else {
|
} else {
|
||||||
// Stack window(s) - left side
|
// Stack window(s) - left side
|
||||||
const stack_index = index - 1;
|
const stack_index = index - 1;
|
||||||
window.pending_state.x = output_x;
|
window.pending_render.x = output_x;
|
||||||
window.pending_state.y = output_y + @as(i32, stack_index) * @as(i32, stack_height);
|
window.pending_render.y = output_y + @as(i32, stack_index) * @as(i32, stack_height);
|
||||||
window.pending_state.width = stack_width;
|
window.pending_manage.width = stack_width;
|
||||||
// Last stack window gets remaining height to avoid gaps from integer division
|
// Last stack window gets remaining height to avoid gaps from integer division
|
||||||
if (index == count - 1) {
|
if (index == count - 1) {
|
||||||
window.pending_state.height = output_height - stack_index * stack_height;
|
window.pending_manage.height = output_height - stack_index * stack_height;
|
||||||
} else {
|
} else {
|
||||||
window.pending_state.height = stack_height;
|
window.pending_manage.height = stack_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,10 +125,10 @@ fn calculatePrimaryStackLayout(wm: *WindowManager) void {
|
||||||
// Borders are automatically disabled when a window is fullscreened so we don't
|
// Borders are automatically disabled when a window is fullscreened so we don't
|
||||||
// have to worry about that.
|
// have to worry about that.
|
||||||
const border_width = wm.context.config.border_width;
|
const border_width = wm.context.config.border_width;
|
||||||
window.pending_state.height.? -= 2 * border_width;
|
window.pending_manage.height.? -= 2 * border_width;
|
||||||
window.pending_state.width.? -= 2 * border_width;
|
window.pending_manage.width.? -= 2 * border_width;
|
||||||
window.pending_state.x.? += border_width;
|
window.pending_render.x.? += border_width;
|
||||||
window.pending_state.y.? += border_width;
|
window.pending_render.y.? += border_width;
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -143,6 +143,7 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
|
||||||
std.posix.exit(1);
|
std.posix.exit(1);
|
||||||
},
|
},
|
||||||
.manage_start => {
|
.manage_start => {
|
||||||
|
log.debug("manage start", .{});
|
||||||
if (!context.initialized) {
|
if (!context.initialized) {
|
||||||
// This code (should) only be run once while initializing the WM, so let's
|
// This code (should) only be run once while initializing the WM, so let's
|
||||||
// mark it as cold.
|
// mark it as cold.
|
||||||
|
|
@ -159,12 +160,6 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
|
||||||
context.xkb_bindings.addBinding(river_seat_v1, xkbcommon.Keysym.e, .{ .mod4 = true, .shift = true }, .exit);
|
context.xkb_bindings.addBinding(river_seat_v1, xkbcommon.Keysym.e, .{ .mod4 = true, .shift = true }, .exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
var it = wm.seats.iterator(.forward);
|
|
||||||
while (it.next()) |seat| {
|
|
||||||
seat.manage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
var it = wm.outputs.iterator(.forward);
|
var it = wm.outputs.iterator(.forward);
|
||||||
while (it.next()) |output| {
|
while (it.next()) |output| {
|
||||||
|
|
@ -179,9 +174,17 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
|
||||||
window.manage();
|
window.manage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
var it = wm.seats.iterator(.forward);
|
||||||
|
while (it.next()) |seat| {
|
||||||
|
seat.manage();
|
||||||
|
}
|
||||||
|
}
|
||||||
window_manager_v1.manageFinish();
|
window_manager_v1.manageFinish();
|
||||||
|
log.debug("manage end===================", .{});
|
||||||
},
|
},
|
||||||
.render_start => {
|
.render_start => {
|
||||||
|
log.debug("render start", .{});
|
||||||
{
|
{
|
||||||
var it = wm.seats.iterator(.forward);
|
var it = wm.seats.iterator(.forward);
|
||||||
while (it.next()) |seat| {
|
while (it.next()) |seat| {
|
||||||
|
|
@ -201,6 +204,7 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window_manager_v1.renderFinish();
|
window_manager_v1.renderFinish();
|
||||||
|
log.debug("render end==================", .{});
|
||||||
},
|
},
|
||||||
.output => |ev| {
|
.output => |ev| {
|
||||||
// TODO: Support multi-output
|
// TODO: Support multi-output
|
||||||
|
|
@ -228,8 +232,8 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
|
||||||
// TODO - CONFIG: Allow appending window instead of prepending
|
// TODO - CONFIG: Allow appending window instead of prepending
|
||||||
wm.windows.prepend(window);
|
wm.windows.prepend(window);
|
||||||
const seat = wm.seats.first() orelse @panic("Failed to get seat");
|
const seat = wm.seats.first() orelse @panic("Failed to get seat");
|
||||||
seat.pending_state.pending_focus = .{ .window = window };
|
seat.pending_manage.pending_focus = .{ .window = window };
|
||||||
seat.pending_state.should_warp_pointer = true;
|
seat.pending_manage.should_warp_pointer = true;
|
||||||
|
|
||||||
wm.window_count += 1;
|
wm.window_count += 1;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ const XkbBinding = struct {
|
||||||
.spawn => |cmd| {
|
.spawn => |cmd| {
|
||||||
var child = std.process.Child.init(cmd, std.heap.c_allocator);
|
var child = std.process.Child.init(cmd, std.heap.c_allocator);
|
||||||
_ = child.spawn() catch |err| {
|
_ = child.spawn() catch |err| {
|
||||||
log.err("Failed to spawn \"{s}\": {}", .{ cmd, err });
|
log.err("Failed to spawn \"{s}\": {}", .{ cmd[0], err });
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.focus_next => {
|
.focus_next => {
|
||||||
|
|
@ -61,10 +61,10 @@ const XkbBinding = struct {
|
||||||
context.wm.windows.first();
|
context.wm.windows.first();
|
||||||
|
|
||||||
if (pending_focus) |window| {
|
if (pending_focus) |window| {
|
||||||
seat.pending_state.pending_focus = .{ .window = window };
|
seat.pending_manage.pending_focus = .{ .window = window };
|
||||||
seat.pending_state.should_warp_pointer = true;
|
seat.pending_manage.should_warp_pointer = true;
|
||||||
} else {
|
} else {
|
||||||
seat.pending_state.pending_focus = .clear_focus;
|
seat.pending_manage.pending_focus = .clear_focus;
|
||||||
}
|
}
|
||||||
// context.wm.window_manager_v1.manageDirty();
|
// context.wm.window_manager_v1.manageDirty();
|
||||||
},
|
},
|
||||||
|
|
@ -77,32 +77,23 @@ const XkbBinding = struct {
|
||||||
context.wm.windows.last();
|
context.wm.windows.last();
|
||||||
|
|
||||||
if (pending_focus) |window| {
|
if (pending_focus) |window| {
|
||||||
seat.pending_state.pending_focus = .{ .window = window };
|
seat.pending_manage.pending_focus = .{ .window = window };
|
||||||
seat.pending_state.should_warp_pointer = true;
|
seat.pending_manage.should_warp_pointer = true;
|
||||||
} else {
|
} else {
|
||||||
seat.pending_state.pending_focus = .clear_focus;
|
seat.pending_manage.pending_focus = .clear_focus;
|
||||||
}
|
}
|
||||||
// context.wm.window_manager_v1.manageDirty();
|
// context.wm.window_manager_v1.manageDirty();
|
||||||
},
|
},
|
||||||
.fullscreen => {
|
.fullscreen => {
|
||||||
const seat = context.wm.seats.first() orelse return;
|
const seat = context.wm.seats.first() orelse return;
|
||||||
const window = seat.focused orelse return;
|
const window = seat.focused orelse return;
|
||||||
window.pending_state.fullscreen = !window.fullscreen;
|
window.pending_manage.fullscreen = !window.fullscreen;
|
||||||
// context.wm.window_manager_v1.manageDirty();
|
// context.wm.window_manager_v1.manageDirty();
|
||||||
},
|
},
|
||||||
.close_window => {
|
.close_window => {
|
||||||
const seat = context.wm.seats.first() orelse return;
|
const seat = context.wm.seats.first() orelse return;
|
||||||
if (seat.focused) |window| {
|
if (seat.focused) |window| {
|
||||||
window.window_v1.close();
|
window.window_v1.close();
|
||||||
|
|
||||||
// Move focus to previous window in stack (if one exists)
|
|
||||||
if (context.wm.getPrevWindow(window)) |pending_focus| {
|
|
||||||
seat.pending_state.pending_focus = .{ .window = pending_focus };
|
|
||||||
seat.pending_state.should_warp_pointer = true;
|
|
||||||
} else {
|
|
||||||
seat.pending_state.pending_focus = .clear_focus;
|
|
||||||
}
|
|
||||||
// context.wm.window_manager_v1.manageDirty();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.exit => {
|
.exit => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue