Skip to content

Commit

Permalink
X11 keyboard suport
Browse files Browse the repository at this point in the history
  • Loading branch information
malcolmstill committed Mar 4, 2024
1 parent 2ff60b2 commit d7ffc23
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
with:
version: master
- run: sudo apt-get update
- run: sudo apt-get install libx11-dev libxcb1-dev libx11-xcb-dev libegl-dev libgles-dev libsystemd-dev libudev-dev libinput-dev libdrm-dev libgbm-dev libxkbcommon-dev
- run: sudo apt-get install libx11-dev libxcb1-dev libx11-xcb-dev libegl-dev libgles-dev libsystemd-dev libudev-dev libinput-dev libdrm-dev libgbm-dev libxkbcommon-dev libxkbcommon-x11-dev
- run: zig build
# - run: zig build -fstage1 (stage 1 doesn't support packed struct(u32))
lint:
Expand Down
1 change: 1 addition & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub fn build(b: *std.Build) void {
exe.linkSystemLibrary("c");
exe.linkSystemLibrary("gl");
exe.linkSystemLibrary("xkbcommon");
exe.linkSystemLibrary("xkbcommon-x11");
exe.linkSystemLibrary("libsystemd");
exe.linkSystemLibrary("libudev");
exe.linkSystemLibrary("libinput");
Expand Down
8 changes: 8 additions & 0 deletions src/backend/backend.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,26 @@ pub const Backend = union(BackendType) {

pub const BackendEventType = enum {
sync,
key_press,
button_press,
mouse_move,
resize,
};

pub const BackendEvent = union(BackendEventType) {
sync: u32,
key_press: KeyPress,
button_press: ButtonPress,
mouse_move: MouseMove,
resize: Resize,
};

pub const KeyPress = struct {
time: u32,
button: u32,
state: u32,
};

pub const ButtonPress = struct {
x: i16,
y: i16,
Expand Down
72 changes: 70 additions & 2 deletions src/backend/x11.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ const c = @cImport({
@cInclude("EGL/egl.h");
@cInclude("GLES3/gl3.h");
@cInclude("X11/Xlib-xcb.h");
@cInclude("xkbcommon/xkbcommon.h");
@cInclude("xkbcommon/xkbcommon-x11.h");
});

const Event = @import("../subsystem.zig").Event;
const Backend = @import("backend.zig").Backend;

Expand All @@ -29,16 +32,33 @@ pub const X11 = struct {
fd: i32,
display: *c.Display,
outputs: std.ArrayList(X11Output),
xkb_context: *c.xkb_context,
device_id: i32,
keymap: *c.xkb_keymap,
state: *c.xkb_state,
min_keycode: u8,

pub fn init(allocator: mem.Allocator) !X11 {
const display: *c.Display = c.XOpenDisplay(null) orelse return error.FailedToOpenDisplay;
const conn = c.XGetXCBConnection(display) orelse return error.FailedToGetXcbConnection;

return X11{
const xkb_context = c.xkb_context_new(c.XKB_CONTEXT_NO_FLAGS) orelse return error.X11XkbContextFailed;
const device_id = c.xkb_x11_get_core_keyboard_device_id(conn);
const keymap = c.xkb_x11_keymap_new_from_device(xkb_context, conn, device_id, c.XKB_KEYMAP_COMPILE_NO_FLAGS) orelse return error.X11XkbKeymapFailed;
const state = c.xkb_x11_state_new_from_device(keymap, conn, device_id) orelse return error.X11XkbStateFailed;

const setup = c.xcb_get_setup(conn);

return .{
.conn = conn,
.fd = c.xcb_get_file_descriptor(conn),
.display = display,
.outputs = std.ArrayList(X11Output).init(allocator),
.xkb_context = xkb_context,
.device_id = device_id,
.keymap = keymap,
.state = state,
.min_keycode = setup.*.min_keycode,
};
}

Expand All @@ -65,6 +85,49 @@ pub const X11 = struct {
// std.log.info("event response type = {}", .{ev.*.response_type});

switch (ev.*.response_type & ~mask) {
c.XCB_KEY_PRESS => {
const press: *c.xcb_key_press_event_t = @ptrCast(ev);

_ = c.xkb_state_update_key(it.x11.state, press.detail, c.XKB_KEY_DOWN);
const keysym = c.xkb_state_key_get_one_sym(it.x11.state, press.detail);

std.log.info("key press = {} keysym = {}", .{ press.detail, keysym });

return .{
.backend = .{
.backend = it.backend,
.output = press.event,
.event = .{
.key_press = .{
.time = press.time,
.button = keysym - 8,
.state = 1,
},
},
},
};
},
c.XCB_KEY_RELEASE => {
const press: *c.xcb_key_release_event_t = @ptrCast(ev);
// std.log.info("button press = {}x{} 0x{x}", .{ press.event_x, press.event_y, press.state });

_ = c.xkb_state_update_key(it.x11.state, press.detail, c.XKB_KEY_UP);
const keysym = c.xkb_state_key_get_one_sym(it.x11.state, press.detail);

return .{
.backend = .{
.backend = it.backend,
.output = press.event,
.event = .{
.key_press = .{
.time = press.time,
.button = keysym - 8,
.state = 0,
},
},
},
};
},
c.XCB_BUTTON_PRESS => {
const press: *c.xcb_button_press_event_t = @ptrCast(ev);
// std.log.info("button press = {}x{} 0x{x}", .{ press.event_x, press.event_y, press.state });
Expand Down Expand Up @@ -187,7 +250,12 @@ pub const X11 = struct {
const screen = iter.data;

const mask = c.XCB_CW_EVENT_MASK;
var valwin = [1]u32{c.XCB_EVENT_MASK_BUTTON_PRESS | c.XCB_EVENT_MASK_BUTTON_RELEASE | c.XCB_EVENT_MASK_POINTER_MOTION | c.XCB_EVENT_MASK_EXPOSURE};
var valwin = [1]u32{c.XCB_EVENT_MASK_BUTTON_PRESS |
c.XCB_EVENT_MASK_BUTTON_RELEASE |
c.XCB_EVENT_MASK_POINTER_MOTION |
c.XCB_EVENT_MASK_EXPOSURE |
c.XCB_EVENT_MASK_KEY_PRESS |
c.XCB_EVENT_MASK_KEY_RELEASE};

const window = c.xcb_generate_id(backend.conn);
_ = c.xcb_create_window(
Expand Down
8 changes: 3 additions & 5 deletions src/client.zig
Original file line number Diff line number Diff line change
Expand Up @@ -660,13 +660,11 @@ pub const Client = struct {

if (client.wl_seat != null) client.wl_keyboard = wl_keyboard;

if (client.server.xkb) |*xkb| {
const fd_size = try xkb.getKeymap();
const fd_size = try client.server.xkb.getKeymap();

try wl_keyboard.sendKeymap(.xkb_v1, fd_size.fd, @intCast(fd_size.size));
try wl_keyboard.sendKeymap(.xkb_v1, fd_size.fd, @intCast(fd_size.size));

if (msg.wl_seat.version >= 4) try wl_keyboard.sendRepeatInfo(1, 2000);
}
if (msg.wl_seat.version >= 4) try wl_keyboard.sendRepeatInfo(1, 2000);
},
.get_touch => |_| return error.NotImplement,
.release => |_| return error.NotImplement,
Expand Down
7 changes: 6 additions & 1 deletion src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub fn main() !void {

var counter = FrameCounter.init();

while (true) {
while (server.running) {
var it = epoll.wait(-1);

while (try it.next()) |s| switch (s) {
Expand All @@ -73,6 +73,11 @@ pub fn main() !void {
.err => std.debug.print("got err\n", .{}),
},
.backend => |ev| switch (ev.event) {
.key_press => |kp| {
// log.info("button press = {} {} (0x{x})", .{ bp.button, bp.state, ev.output });

try server.keyboard(kp.time, kp.button, kp.state);
},
.button_press => |bp| {
// log.info("button press = {} {} (0x{x})", .{ bp.button, bp.state, ev.output });

Expand Down
23 changes: 9 additions & 14 deletions src/resource/window.zig
Original file line number Diff line number Diff line change
Expand Up @@ -616,22 +616,17 @@ pub const Window = struct {
const client = window.client;
const wl_keyboard = client.wl_keyboard orelse return;

try wl_keyboard.sendKey(
const state = if (action == 0) wl.WlKeyboard.KeyState.released else wl.WlKeyboard.KeyState.pressed;

try wl_keyboard.sendKey(client.nextSerial(), time, button, state);

try wl_keyboard.sendModifiers(
client.nextSerial(),
time,
button,
action,
window.client.server.mods_depressed,
window.client.server.mods_latched,
window.client.server.mods_locked,
window.client.server.mods_group,
);

// TODO: reinstate
// try prot.wl_keyboard_send_modifiers(
// wl_keyboard,
// client.nextSerial(),
// compositor.COMPOSITOR.mods_depressed,
// compositor.COMPOSITOR.mods_latched,
// compositor.COMPOSITOR.mods_locked,
// compositor.COMPOSITOR.mods_group,
// );
}

/// Deinitialise window.
Expand Down
24 changes: 22 additions & 2 deletions src/server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,21 @@ pub const Server = struct {
move: ?Move = null,
resize: ?Resize = null,

mods_depressed: u32 = 0,
mods_latched: u32 = 0,
mods_locked: u32 = 0,
mods_group: u32 = 0,

current_view: ?*View = null,

pointer_x: f64 = 0.0,
pointer_y: f64 = 0.0,

output_base: u32 = 1000,

xkb: ?Xkb = null,
xkb: Xkb,

running: bool = true,

const ClientNode = std.TailQueue(Client).Node;
const Self = @This();
Expand All @@ -92,7 +99,7 @@ pub const Server = struct {
};

pub fn init(alloc: mem.Allocator) !Server {
return Server{
return .{
.alloc = alloc,
.server = try socket(),
.clients = try IterablePool(Client, u8).init(alloc, 255),
Expand Down Expand Up @@ -225,6 +232,19 @@ pub const Server = struct {
try view.updatePointer(server.pointer_x, server.pointer_y);
}

pub fn keyboard(server: *Self, time: u32, button: u32, action: u32) !void {
if (button == 224 or button == 25) server.running = false;

server.xkb.updateKey(button, action);
server.mods_depressed = server.xkb.serializeDepressed();
server.mods_latched = server.xkb.serializeLatched();
server.mods_locked = server.xkb.serializeLocked();
server.mods_group = server.xkb.serializeGroup();

const view = server.current_view orelse return;
try view.keyboard(time, button, action);
}

pub fn iterator(server: *Server) SubsystemIterator {
return SubsystemIterator{ .server = Iterator.init(server) };
}
Expand Down

0 comments on commit d7ffc23

Please sign in to comment.