Refactor keybindings to be runtime defined.
This commit is contained in:
parent
15f97314a9
commit
fa65333789
8 changed files with 116 additions and 68 deletions
|
@ -4,23 +4,33 @@ const c = @import("c.zig");
|
|||
const Server = @import("server.zig").Server;
|
||||
const ViewStack = @import("view_stack.zig").ViewStack;
|
||||
|
||||
pub const Arg = union {
|
||||
int: i32,
|
||||
uint: u32,
|
||||
float: f64,
|
||||
none: void,
|
||||
};
|
||||
|
||||
pub const Command = fn (server: *Server, arg: Arg) void;
|
||||
|
||||
/// Exit the compositor, terminating the wayland session.
|
||||
pub fn exitCompositor(server: *Server) void {
|
||||
pub fn exitCompositor(server: *Server, arg: Arg) void {
|
||||
c.wl_display_terminate(server.wl_display);
|
||||
}
|
||||
|
||||
/// Shift focus to the next visible view, wrapping if needed.
|
||||
pub fn focusNextView(server: *Server) void {
|
||||
pub fn focusNextView(server: *Server, arg: Arg) void {
|
||||
server.root.focusNextView();
|
||||
}
|
||||
|
||||
/// Shift focus to the previous visible view, wrapping if needed.
|
||||
pub fn focusPrevView(server: *Server) void {
|
||||
pub fn focusPrevView(server: *Server, arg: Arg) void {
|
||||
server.root.focusPrevView();
|
||||
}
|
||||
|
||||
/// Modify the number of master views
|
||||
pub fn modifyMasterCount(server: *Server, delta: i32) void {
|
||||
pub fn modifyMasterCount(server: *Server, arg: Arg) void {
|
||||
const delta = arg.int;
|
||||
server.root.master_count = @intCast(u32, std.math.max(
|
||||
0,
|
||||
@intCast(i32, server.root.master_count) + delta,
|
||||
|
@ -29,7 +39,8 @@ pub fn modifyMasterCount(server: *Server, delta: i32) void {
|
|||
}
|
||||
|
||||
/// Modify the percent of the width of the screen that the master views occupy.
|
||||
pub fn modifyMasterFactor(server: *Server, delta: f64) void {
|
||||
pub fn modifyMasterFactor(server: *Server, arg: Arg) void {
|
||||
const delta = arg.float;
|
||||
const new_master_factor = std.math.min(
|
||||
std.math.max(server.root.master_factor + delta, 0.05),
|
||||
0.95,
|
||||
|
@ -42,7 +53,7 @@ pub fn modifyMasterFactor(server: *Server, delta: f64) void {
|
|||
|
||||
/// Bump the focused view to the top of the stack.
|
||||
/// TODO: if the top of the stack is focused, bump the next visible view.
|
||||
pub fn zoom(server: *Server) void {
|
||||
pub fn zoom(server: *Server, arg: Arg) void {
|
||||
if (server.root.focused_view) |current_focus| {
|
||||
const node = @fieldParentPtr(ViewStack.Node, "view", current_focus);
|
||||
if (node != server.root.views.first) {
|
||||
|
@ -54,13 +65,15 @@ pub fn zoom(server: *Server) void {
|
|||
}
|
||||
|
||||
/// Switch focus to the passed tags.
|
||||
pub fn focusTags(server: *Server, tags: u32) void {
|
||||
pub fn focusTags(server: *Server, arg: Arg) void {
|
||||
const tags = arg.uint;
|
||||
server.root.pending_focused_tags = tags;
|
||||
server.root.arrange();
|
||||
}
|
||||
|
||||
/// Set the tags of the focused view.
|
||||
pub fn setFocusedViewTags(server: *Server, tags: u32) void {
|
||||
pub fn setFocusedViewTags(server: *Server, arg: Arg) void {
|
||||
const tags = arg.uint;
|
||||
if (server.root.focused_view) |view| {
|
||||
if (view.current_tags != tags) {
|
||||
view.pending_tags = tags;
|
||||
|
@ -71,7 +84,7 @@ pub fn setFocusedViewTags(server: *Server, tags: u32) void {
|
|||
|
||||
/// Spawn a program.
|
||||
/// TODO: make this take a program as a paramter and spawn that
|
||||
pub fn spawn(server: *Server) void {
|
||||
pub fn spawn(server: *Server, arg: Arg) void {
|
||||
const argv = [_][]const u8{ "/bin/sh", "-c", "alacritty" };
|
||||
const child = std.ChildProcess.init(&argv, std.heap.c_allocator) catch unreachable;
|
||||
std.ChildProcess.spawn(child) catch unreachable;
|
||||
|
|
62
src/config.zig
Normal file
62
src/config.zig
Normal file
|
@ -0,0 +1,62 @@
|
|||
const std = @import("std");
|
||||
const c = @import("c.zig");
|
||||
const command = @import("command.zig");
|
||||
|
||||
const Server = @import("server.zig");
|
||||
|
||||
pub const Config = struct {
|
||||
const Self = @This();
|
||||
|
||||
/// Width of borders in pixels
|
||||
border_width: u32 = 2,
|
||||
|
||||
/// Amount of view padding in pixels
|
||||
view_padding: u32 = 10,
|
||||
|
||||
const Keybind = struct {
|
||||
keysym: c.xkb_keysym_t,
|
||||
modifiers: u32,
|
||||
command: command.Command,
|
||||
arg: command.Arg,
|
||||
};
|
||||
|
||||
/// All user-defined keybindings
|
||||
keybinds: std.ArrayList(Keybind),
|
||||
|
||||
pub fn init(self: *Self, allocator: *std.mem.Allocator) !void {
|
||||
self.border_width = 2;
|
||||
self.view_padding = 10;
|
||||
|
||||
self.keybinds = std.ArrayList(Keybind).init(allocator);
|
||||
|
||||
const mod = c.WLR_MODIFIER_LOGO;
|
||||
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_j, .modifiers = mod, .command = command.focusNextView, .arg = .{ .none = {} } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_k, .modifiers = mod, .command = command.focusPrevView, .arg = .{ .none = {} } });
|
||||
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_h, .modifiers = mod, .command = command.modifyMasterFactor, .arg = .{ .float = 0.05 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_l, .modifiers = mod, .command = command.modifyMasterFactor, .arg = .{ .float = -0.05 } });
|
||||
|
||||
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_1, .modifiers = mod, .command = command.focusTags, .arg = .{ .uint = 1 << 0 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_2, .modifiers = mod, .command = command.focusTags, .arg = .{ .uint = 1 << 1 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_3, .modifiers = mod, .command = command.focusTags, .arg = .{ .uint = 1 << 2 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_4, .modifiers = mod, .command = command.focusTags, .arg = .{ .uint = 1 << 3 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_5, .modifiers = mod, .command = command.focusTags, .arg = .{ .uint = 1 << 4 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_6, .modifiers = mod, .command = command.focusTags, .arg = .{ .uint = 1 << 5 } });
|
||||
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_h, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.modifyMasterCount, .arg = .{ .int = 1 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_l, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.modifyMasterCount, .arg = .{ .int = -1 } });
|
||||
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_Return, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.spawn, .arg = .{ .none = {} } });
|
||||
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_1, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 1 << 0 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_2, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 1 << 1 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_3, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 1 << 2 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_4, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 1 << 3 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_5, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 1 << 4 } });
|
||||
try self.keybinds.append(Keybind{ .keysym = c.XKB_KEY_6, .modifiers = mod | c.WLR_MODIFIER_SHIFT, .command = command.setFocusedViewTags, .arg = .{ .uint = 1 << 5 } });
|
||||
}
|
||||
};
|
|
@ -112,7 +112,7 @@ pub const Keyboard = struct {
|
|||
if (keyboard.handleBuiltinKeybind(translated_keysyms.?[i])) {
|
||||
handled = true;
|
||||
break;
|
||||
} else if (keyboard.seat.server.handleKeybinding(translated_keysyms.?[i], modifiers)) {
|
||||
} else if (keyboard.seat.handleKeybinding(translated_keysyms.?[i], modifiers)) {
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ pub const Keyboard = struct {
|
|||
if (keyboard.handleBuiltinKeybind(raw_keysyms.?[i])) {
|
||||
handled = true;
|
||||
break;
|
||||
} else if (keyboard.seat.server.handleKeybinding(raw_keysyms.?[i], modifiers)) {
|
||||
} else if (keyboard.seat.handleKeybinding(raw_keysyms.?[i], modifiers)) {
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -129,8 +129,8 @@ pub const Output = struct {
|
|||
// If we have a stashed buffer, we are in the middle of a transaction
|
||||
// and need to render that buffer until the transaction is complete.
|
||||
if (view.stashed_buffer) |buffer| {
|
||||
const border_width = view.root.border_width;
|
||||
const view_padding = view.root.view_padding;
|
||||
const border_width = view.root.server.config.border_width;
|
||||
const view_padding = view.root.server.config.view_padding;
|
||||
var box = c.wlr_box{
|
||||
.x = view.current_box.x + @intCast(i32, border_width + view_padding),
|
||||
.y = view.current_box.y + @intCast(i32, border_width + view_padding),
|
||||
|
@ -194,11 +194,13 @@ pub const Output = struct {
|
|||
return;
|
||||
}
|
||||
|
||||
const border_width = view.root.server.config.border_width;
|
||||
const view_padding = view.root.server.config.view_padding;
|
||||
var box = c.wlr_box{
|
||||
.x = @floatToInt(c_int, rdata.ox) + view.current_box.x + sx +
|
||||
@intCast(c_int, view.root.border_width + view.root.view_padding),
|
||||
@intCast(c_int, border_width + view_padding),
|
||||
.y = @floatToInt(c_int, rdata.oy) + view.current_box.y + sy +
|
||||
@intCast(c_int, view.root.border_width + view.root.view_padding),
|
||||
@intCast(c_int, border_width + view_padding),
|
||||
.width = surface.current.width,
|
||||
.height = surface.current.height,
|
||||
};
|
||||
|
@ -229,8 +231,8 @@ pub const Output = struct {
|
|||
[_]f32{ 0.57647059, 0.63137255, 0.63137255, 1.0 } // Solarized base1
|
||||
else
|
||||
[_]f32{ 0.34509804, 0.43137255, 0.45882353, 1.0 }; // Solarized base01
|
||||
const border_width = self.root.border_width;
|
||||
const view_padding = self.root.view_padding;
|
||||
const border_width = self.root.server.config.border_width;
|
||||
const view_padding = self.root.server.config.view_padding;
|
||||
|
||||
// left border
|
||||
border.x = @floatToInt(c_int, ox) + view.current_box.x + @intCast(c_int, view_padding);
|
||||
|
|
10
src/root.zig
10
src/root.zig
|
@ -34,12 +34,6 @@ pub const Root = struct {
|
|||
/// Percentage of the total screen that the master section takes up.
|
||||
master_factor: f64,
|
||||
|
||||
/// Width of borders in pixels
|
||||
border_width: u32,
|
||||
|
||||
/// Amount of view padding in pixels
|
||||
view_padding: u32,
|
||||
|
||||
/// Number of pending configures sent in the current transaction.
|
||||
/// A value of 0 means there is no current transaction.
|
||||
pending_configures: u32,
|
||||
|
@ -69,10 +63,6 @@ pub const Root = struct {
|
|||
|
||||
self.master_factor = 0.6;
|
||||
|
||||
self.border_width = 4;
|
||||
|
||||
self.view_padding = 10;
|
||||
|
||||
self.pending_configures = 0;
|
||||
|
||||
self.transaction_timer = null;
|
||||
|
|
13
src/seat.zig
13
src/seat.zig
|
@ -41,6 +41,19 @@ pub const Seat = struct {
|
|||
self.cursor.destroy();
|
||||
}
|
||||
|
||||
/// Handle any user-defined keybinding for the passed keysym and modifiers
|
||||
/// Returns true if the key was handled
|
||||
pub fn handleKeybinding(self: Self, keysym: c.xkb_keysym_t, modifiers: u32) bool {
|
||||
for (self.server.config.keybinds.items) |keybind| {
|
||||
if (modifiers == keybind.modifiers and keysym == keybind.keysym) {
|
||||
// Execute the bound command
|
||||
keybind.command(self.server, keybind.arg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn addKeyboard(self: *Self, device: *c.wlr_input_device) !void {
|
||||
c.wlr_seat_set_keyboard(self.wlr_seat, device);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
|||
const c = @import("c.zig");
|
||||
const command = @import("command.zig");
|
||||
|
||||
const Config = @import("config.zig").Config;
|
||||
const DecorationManager = @import("decoration_manager.zig").DecorationManager;
|
||||
const Output = @import("output.zig").Output;
|
||||
const Root = @import("root.zig").Root;
|
||||
|
@ -25,6 +26,8 @@ pub const Server = struct {
|
|||
root: Root,
|
||||
seat: Seat,
|
||||
|
||||
config: Config,
|
||||
|
||||
listen_new_output: c.wl_listener,
|
||||
listen_new_xdg_surface: c.wl_listener,
|
||||
|
||||
|
@ -73,6 +76,8 @@ pub const Server = struct {
|
|||
|
||||
try self.seat.init(self);
|
||||
|
||||
try self.config.init(self.allocator);
|
||||
|
||||
// Register our listeners for new outputs and xdg_surfaces.
|
||||
self.listen_new_output.notify = handleNewOutput;
|
||||
c.wl_signal_add(&self.wlr_backend.events.new_output, &self.listen_new_output);
|
||||
|
@ -112,45 +117,6 @@ pub const Server = struct {
|
|||
c.wl_display_run(self.wl_display);
|
||||
}
|
||||
|
||||
/// Handle all compositor keybindings
|
||||
/// Note: this is a hacky initial implementation for testing and will be rewritten eventually
|
||||
pub fn handleKeybinding(self: *Self, sym: c.xkb_keysym_t, modifiers: u32) bool {
|
||||
if (modifiers & @intCast(u32, c.WLR_MODIFIER_LOGO) == 0) {
|
||||
return false;
|
||||
}
|
||||
if (modifiers & @intCast(u32, c.WLR_MODIFIER_SHIFT) != 0) {
|
||||
switch (sym) {
|
||||
c.XKB_KEY_H => command.modifyMasterCount(self, 1),
|
||||
c.XKB_KEY_L => command.modifyMasterCount(self, -1),
|
||||
c.XKB_KEY_Return => command.spawn(self),
|
||||
c.XKB_KEY_1 => command.setFocusedViewTags(self, 1 << 0),
|
||||
c.XKB_KEY_2 => command.setFocusedViewTags(self, 1 << 1),
|
||||
c.XKB_KEY_3 => command.setFocusedViewTags(self, 1 << 2),
|
||||
c.XKB_KEY_4 => command.setFocusedViewTags(self, 1 << 3),
|
||||
c.XKB_KEY_5 => command.setFocusedViewTags(self, 1 << 4),
|
||||
c.XKB_KEY_6 => command.setFocusedViewTags(self, 1 << 5),
|
||||
else => return false,
|
||||
}
|
||||
} else {
|
||||
switch (sym) {
|
||||
c.XKB_KEY_e => command.exitCompositor(self),
|
||||
c.XKB_KEY_j => command.focusNextView(self),
|
||||
c.XKB_KEY_k => command.focusPrevView(self),
|
||||
c.XKB_KEY_h => command.modifyMasterFactor(self, 0.05),
|
||||
c.XKB_KEY_l => command.modifyMasterFactor(self, -0.05),
|
||||
c.XKB_KEY_Return => command.zoom(self),
|
||||
c.XKB_KEY_1 => command.focusTags(self, 1 << 0),
|
||||
c.XKB_KEY_2 => command.focusTags(self, 1 << 1),
|
||||
c.XKB_KEY_3 => command.focusTags(self, 1 << 2),
|
||||
c.XKB_KEY_4 => command.focusTags(self, 1 << 3),
|
||||
c.XKB_KEY_5 => command.focusTags(self, 1 << 4),
|
||||
c.XKB_KEY_6 => command.focusTags(self, 1 << 5),
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn handleNewOutput(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
const server = @fieldParentPtr(Server, "listen_new_output", listener.?);
|
||||
const wlr_output = @ptrCast(*c.wlr_output, @alignCast(@alignOf(*c.wlr_output), data));
|
||||
|
|
|
@ -91,10 +91,12 @@ pub const View = struct {
|
|||
|
||||
pub fn configurePending(self: *Self) void {
|
||||
if (self.pending_box) |pending_box| {
|
||||
const border_width = self.root.server.config.border_width;
|
||||
const view_padding = self.root.server.config.view_padding;
|
||||
self.pending_serial = c.wlr_xdg_toplevel_set_size(
|
||||
self.wlr_xdg_surface,
|
||||
pending_box.width - self.root.border_width * 2 - self.root.view_padding * 2,
|
||||
pending_box.height - self.root.border_width * 2 - self.root.view_padding * 2,
|
||||
pending_box.width - border_width * 2 - view_padding * 2,
|
||||
pending_box.height - border_width * 2 - view_padding * 2,
|
||||
);
|
||||
} else {
|
||||
// TODO: log warning
|
||||
|
|
Loading…
Reference in a new issue