Refactor focus next/prev view/output commands

This commit is contained in:
Isaac Freund 2020-04-18 13:12:15 +02:00
parent 6914f32ce3
commit e0c6b5bf72
No known key found for this signature in database
GPG key ID: 86DED400DDFD7A11
2 changed files with 52 additions and 44 deletions

View file

@ -7,11 +7,17 @@ const Seat = @import("seat.zig").Seat;
const View = @import("view.zig").View; const View = @import("view.zig").View;
const ViewStack = @import("view_stack.zig").ViewStack; const ViewStack = @import("view_stack.zig").ViewStack;
pub const Direction = enum {
Next,
Prev,
};
pub const Arg = union { pub const Arg = union {
int: i32, int: i32,
uint: u32, uint: u32,
float: f64, float: f64,
str: []const u8, str: []const u8,
direction: Direction,
none: void, none: void,
}; };
@ -22,17 +28,18 @@ pub fn exitCompositor(seat: *Seat, arg: Arg) void {
c.wl_display_terminate(seat.input_manager.server.wl_display); c.wl_display_terminate(seat.input_manager.server.wl_display);
} }
/// Focus either the next or the previous visible view, depending on the bool /// Focus either the next or the previous visible view, depending on the enum
/// passed. /// passed. Does nothing if there are 1 or 0 views in the stack.
fn focusNextPrevView(seat: *Seat, next: bool) void { pub fn focusView(seat: *Seat, arg: Arg) void {
const direction = arg.direction;
const output = seat.focused_output; const output = seat.focused_output;
if (seat.focused_view) |current_focus| { if (seat.focused_view) |current_focus| {
// If there is a currently focused view, focus the next visible view in the stack. // If there is a currently focused view, focus the next visible view in the stack.
const focused_node = @fieldParentPtr(ViewStack(View).Node, "view", current_focus); const focused_node = @fieldParentPtr(ViewStack(View).Node, "view", current_focus);
var it = if (next) var it = switch (direction) {
ViewStack(View).iterator(focused_node, output.current_focused_tags) .Next => ViewStack(View).iterator(focused_node, output.current_focused_tags),
else .Prev => ViewStack(View).reverseIterator(focused_node, output.current_focused_tags),
ViewStack(View).reverseIterator(focused_node, output.current_focused_tags); };
// Skip past the focused node // Skip past the focused node
_ = it.next(); _ = it.next();
@ -45,27 +52,17 @@ fn focusNextPrevView(seat: *Seat, next: bool) void {
// There is either no currently focused view or the last visible view in the // There is either no currently focused view or the last visible view in the
// stack is focused and we need to wrap. // stack is focused and we need to wrap.
var it = if (next) var it = switch (direction) {
ViewStack(View).iterator(output.views.first, output.current_focused_tags) .Next => ViewStack(View).iterator(output.views.first, output.current_focused_tags),
else .Prev => ViewStack(View).reverseIterator(output.views.last, output.current_focused_tags),
ViewStack(View).reverseIterator(output.views.last, output.current_focused_tags); };
seat.focus(if (it.next()) |node| &node.view else null); seat.focus(if (it.next()) |node| &node.view else null);
} }
/// Focus the next visible view in the stack, wrapping if needed. Does
/// nothing if there is only one view in the stack.
pub fn focusNextView(seat: *Seat, arg: Arg) void {
focusNextPrevView(seat, true);
}
/// Focus the previous view in the stack, wrapping if needed. Does nothing
/// if there is only one view in the stack.
pub fn focusPrevView(seat: *Seat, arg: Arg) void {
focusNextPrevView(seat, false);
}
/// Focus either the next or the previous output, depending on the bool passed. /// Focus either the next or the previous output, depending on the bool passed.
fn focusNextPrevOutput(seat: *Seat, next: bool) void { /// Does nothing if there is only one output.
pub fn focusOutput(seat: *Seat, arg: Arg) void {
const direction = arg.direction;
const root = &seat.input_manager.server.root; const root = &seat.input_manager.server.root;
// If the noop output is focused, there are no other outputs to switch to // If the noop output is focused, there are no other outputs to switch to
if (seat.focused_output == &root.noop_output) { if (seat.focused_output == &root.noop_output) {
@ -73,27 +70,16 @@ fn focusNextPrevOutput(seat: *Seat, next: bool) void {
return; return;
} }
// Focus the next/prev output in the list if there is one, else wrap
const focused_node = @fieldParentPtr(std.TailQueue(Output).Node, "data", seat.focused_output); const focused_node = @fieldParentPtr(std.TailQueue(Output).Node, "data", seat.focused_output);
seat.focused_output = if (if (next) focused_node.next else focused_node.prev) |output_node| seat.focused_output = switch (direction) {
// Focus the next/prev output in the list if there is one .Next => if (focused_node.next) |node| &node.data else &root.outputs.first.?.data,
&output_node.data .Prev => if (focused_node.prev) |node| &node.data else &root.outputs.last.?.data,
else if (next) &root.outputs.first.?.data else &root.outputs.last.?.data; };
seat.focus(null); seat.focus(null);
} }
/// Focus the next output, wrapping if needed. Does nothing if there is
/// only one output.
pub fn focusNextOutput(seat: *Seat, arg: Arg) void {
focusNextPrevOutput(seat, true);
}
/// Focus the previous output, wrapping if needed. Does nothing if there is
/// only one output.
pub fn focusPrevOutput(seat: *Seat, arg: Arg) void {
focusNextPrevOutput(seat, false);
}
/// Modify the number of master views /// Modify the number of master views
pub fn modifyMasterCount(seat: *Seat, arg: Arg) void { pub fn modifyMasterCount(seat: *Seat, arg: Arg) void {
const delta = arg.int; const delta = arg.int;

View file

@ -45,8 +45,20 @@ pub const Config = struct {
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_e, .modifiers = mod, .command = command.exitCompositor, .arg = .{ .none = {} } }); try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_e, .modifiers = mod, .command = command.exitCompositor, .arg = .{ .none = {} } });
// Mod+J and Mod+K to focus the next/previous view in the layout stack // Mod+J and Mod+K to focus the next/previous view in the layout stack
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_j, .modifiers = mod, .command = command.focusNextView, .arg = .{ .none = {} } }); try self.keybinds.append(
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_k, .modifiers = mod, .command = command.focusPrevView, .arg = .{ .none = {} } }); Keybind{
.keysym = c.XKB_KEY_j,
.modifiers = mod,
.command = command.focusView,
.arg = .{ .direction = .Next },
},
);
try self.keybinds.append(Keybind{
.keysym = c.XKB_KEY_k,
.modifiers = mod,
.command = command.focusView,
.arg = .{ .direction = .Prev },
});
// Mod+Return to bump the focused view to the top of the layout stack, making it the new master // Mod+Return to bump the focused view to the top of the layout stack, making it the new master
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_Return, .modifiers = mod, .command = command.zoom, .arg = .{ .none = {} } }); try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_Return, .modifiers = mod, .command = command.zoom, .arg = .{ .none = {} } });
@ -98,7 +110,17 @@ pub const Config = struct {
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_0, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 0xFFFFFFFF } }); try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_0, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 0xFFFFFFFF } });
// Mod+Period and Mod+Comma to focus the next/previous output // Mod+Period and Mod+Comma to focus the next/previous output
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_period, .modifiers = mod, .command = command.focusNextOutput, .arg = .{ .none = {} } }); try self.keybinds.append(Keybind{
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_comma, .modifiers = mod, .command = command.focusPrevOutput, .arg = .{ .none = {} } }); .keysym = c.XKB_KEY_period,
.modifiers = mod,
.command = command.focusOutput,
.arg = .{ .direction = .Next },
});
try self.keybinds.append(Keybind{
.keysym = c.XKB_KEY_comma,
.modifiers = mod,
.command = command.focusOutput,
.arg = .{ .direction = .Prev },
});
} }
}; };