core: wayland: implement keyboard input & window resizing (#1293)
This commit is contained in:
parent
51e6899505
commit
06f61044fb
3 changed files with 69 additions and 50 deletions
|
|
@ -49,7 +49,7 @@ backend: Backend,
|
||||||
// these arrays are used as info messages to the user that some features are missing
|
// these arrays are used as info messages to the user that some features are missing
|
||||||
// please keep these up to date until we can remove them
|
// please keep these up to date until we can remove them
|
||||||
const MISSING_FEATURES_X11 = [_][]const u8{ "Resizing window", "Changing display mode", "VSync", "Setting window border/title/cursor" };
|
const MISSING_FEATURES_X11 = [_][]const u8{ "Resizing window", "Changing display mode", "VSync", "Setting window border/title/cursor" };
|
||||||
const MISSING_FEATURES_WAYLAND = [_][]const u8{ "Resizing window", "Keyboard input", "Changing display mode", "VSync", "Setting window border/title/cursor" };
|
const MISSING_FEATURES_WAYLAND = [_][]const u8{ "Changing display mode", "VSync", "Setting window border/title/cursor" };
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
linux: *Linux,
|
linux: *Linux,
|
||||||
|
|
@ -87,21 +87,19 @@ pub fn init(
|
||||||
|
|
||||||
// Try to initialize the desired backend, falling back to the other if that one is not supported
|
// Try to initialize the desired backend, falling back to the other if that one is not supported
|
||||||
switch (desired_backend) {
|
switch (desired_backend) {
|
||||||
.x11 => blk: {
|
.x11 => {
|
||||||
const x11 = X11.init(linux, core, options) catch |err| {
|
X11.init(linux, core, options) catch |err| {
|
||||||
const err_msg = switch (err) {
|
const err_msg = switch (err) {
|
||||||
error.LibraryNotFound => "Missing X11 library",
|
error.LibraryNotFound => "Missing X11 library",
|
||||||
error.FailedToConnectToDisplay => "Failed to connect to X11 display",
|
error.FailedToConnectToDisplay => "Failed to connect to X11 display",
|
||||||
else => "An unknown error occured while trying to connect to X11",
|
else => "An unknown error occured while trying to connect to X11",
|
||||||
};
|
};
|
||||||
log.err("{s}\n\nFalling back to Wayland\n", .{err_msg});
|
log.err("{s}\n\nFalling back to Wayland\n", .{err_msg});
|
||||||
linux.backend = .{ .wayland = try Wayland.init(linux, core, options) };
|
try Wayland.init(linux, core, options);
|
||||||
break :blk;
|
|
||||||
};
|
};
|
||||||
linux.backend = .{ .x11 = x11 };
|
|
||||||
},
|
},
|
||||||
.wayland => blk: {
|
.wayland => {
|
||||||
const wayland = Wayland.init(linux, core, options) catch |err| {
|
Wayland.init(linux, core, options) catch |err| {
|
||||||
const err_msg = switch (err) {
|
const err_msg = switch (err) {
|
||||||
error.NoServerSideDecorationSupport => "Server Side Decorations aren't supported",
|
error.NoServerSideDecorationSupport => "Server Side Decorations aren't supported",
|
||||||
error.LibraryNotFound => "Missing Wayland library",
|
error.LibraryNotFound => "Missing Wayland library",
|
||||||
|
|
@ -109,10 +107,8 @@ pub fn init(
|
||||||
else => "An unknown error occured while trying to connect to Wayland",
|
else => "An unknown error occured while trying to connect to Wayland",
|
||||||
};
|
};
|
||||||
log.err("{s}\n\nFalling back to X11\n", .{err_msg});
|
log.err("{s}\n\nFalling back to X11\n", .{err_msg});
|
||||||
linux.backend = .{ .x11 = try X11.init(linux, core, options) };
|
try X11.init(linux, core, options);
|
||||||
break :blk;
|
|
||||||
};
|
};
|
||||||
linux.backend = .{ .wayland = wayland };
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +140,7 @@ pub fn deinit(linux: *Linux) void {
|
||||||
|
|
||||||
pub fn update(linux: *Linux) !void {
|
pub fn update(linux: *Linux) !void {
|
||||||
switch (linux.backend) {
|
switch (linux.backend) {
|
||||||
.wayland => {},
|
.wayland => try linux.backend.wayland.update(),
|
||||||
.x11 => try linux.backend.x11.update(),
|
.x11 => try linux.backend.x11.update(),
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -75,42 +75,45 @@ pub fn init(
|
||||||
linux: *Linux,
|
linux: *Linux,
|
||||||
core: *Core.Mod,
|
core: *Core.Mod,
|
||||||
options: InitOptions,
|
options: InitOptions,
|
||||||
) !Wayland {
|
) !void {
|
||||||
libwaylandclient_global = try LibWaylandClient.load();
|
libwaylandclient_global = try LibWaylandClient.load();
|
||||||
var wl = Wayland{
|
linux.backend = .{
|
||||||
.core = @fieldParentPtr("platform", linux),
|
.wayland = Wayland{
|
||||||
.state = core.state(),
|
.core = @fieldParentPtr("platform", linux),
|
||||||
.libxkbcommon = try LibXkbCommon.load(),
|
.state = core.state(),
|
||||||
.libwaylandclient = libwaylandclient_global,
|
.libxkbcommon = try LibXkbCommon.load(),
|
||||||
.interfaces = Interfaces{},
|
.libwaylandclient = libwaylandclient_global,
|
||||||
.display = libwaylandclient_global.wl_display_connect(null) orelse return error.FailedToConnectToDisplay,
|
.interfaces = Interfaces{},
|
||||||
.title = try options.allocator.dupeZ(u8, options.title),
|
.display = libwaylandclient_global.wl_display_connect(null) orelse return error.FailedToConnectToDisplay,
|
||||||
.size = &linux.size,
|
.title = try options.allocator.dupeZ(u8, options.title),
|
||||||
.modifiers = .{
|
.size = &linux.size,
|
||||||
.alt = false,
|
.modifiers = .{
|
||||||
.caps_lock = false,
|
.alt = false,
|
||||||
.control = false,
|
.caps_lock = false,
|
||||||
.num_lock = false,
|
.control = false,
|
||||||
.shift = false,
|
.num_lock = false,
|
||||||
.super = false,
|
.shift = false,
|
||||||
|
.super = false,
|
||||||
|
},
|
||||||
|
.input_state = .{},
|
||||||
|
.modifier_indices = .{ // TODO: make sure these are always getting initialized, we don't want undefined behavior
|
||||||
|
.control_index = undefined,
|
||||||
|
.alt_index = undefined,
|
||||||
|
.shift_index = undefined,
|
||||||
|
.super_index = undefined,
|
||||||
|
.caps_lock_index = undefined,
|
||||||
|
.num_lock_index = undefined,
|
||||||
|
},
|
||||||
|
.surface_descriptor = undefined,
|
||||||
|
.surface = undefined,
|
||||||
},
|
},
|
||||||
.input_state = .{},
|
|
||||||
.modifier_indices = .{ // TODO: make sure these are always getting initialized, we don't want undefined behavior
|
|
||||||
.control_index = undefined,
|
|
||||||
.alt_index = undefined,
|
|
||||||
.shift_index = undefined,
|
|
||||||
.super_index = undefined,
|
|
||||||
.caps_lock_index = undefined,
|
|
||||||
.num_lock_index = undefined,
|
|
||||||
},
|
|
||||||
.surface_descriptor = undefined,
|
|
||||||
.surface = undefined,
|
|
||||||
};
|
};
|
||||||
|
var wl = &linux.backend.wayland;
|
||||||
wl.xkb_context = wl.libxkbcommon.xkb_context_new(0) orelse return error.FailedToGetXkbContext;
|
wl.xkb_context = wl.libxkbcommon.xkb_context_new(0) orelse return error.FailedToGetXkbContext;
|
||||||
const registry = c.wl_display_get_registry(wl.display) orelse return error.FailedToGetDisplayRegistry;
|
const registry = c.wl_display_get_registry(wl.display) orelse return error.FailedToGetDisplayRegistry;
|
||||||
|
|
||||||
// TODO: handle error return value here
|
// TODO: handle error return value here
|
||||||
_ = c.wl_registry_add_listener(registry, ®istry_listener.listener, &wl);
|
_ = c.wl_registry_add_listener(registry, ®istry_listener.listener, wl);
|
||||||
|
|
||||||
//Round trip to get all the registry objects
|
//Round trip to get all the registry objects
|
||||||
_ = wl.libwaylandclient.wl_display_roundtrip(wl.display);
|
_ = wl.libwaylandclient.wl_display_roundtrip(wl.display);
|
||||||
|
|
@ -145,10 +148,10 @@ pub fn init(
|
||||||
const toplevel = c.xdg_surface_get_toplevel(xdg_surface) orelse return error.UnableToGetXdgTopLevel;
|
const toplevel = c.xdg_surface_get_toplevel(xdg_surface) orelse return error.UnableToGetXdgTopLevel;
|
||||||
|
|
||||||
// TODO: handle this return value
|
// TODO: handle this return value
|
||||||
_ = c.xdg_surface_add_listener(xdg_surface, &xdg_surface_listener.listener, &wl);
|
_ = c.xdg_surface_add_listener(xdg_surface, &xdg_surface_listener.listener, wl);
|
||||||
|
|
||||||
// TODO: handle this return value
|
// TODO: handle this return value
|
||||||
_ = c.xdg_toplevel_add_listener(toplevel, &xdg_toplevel_listener.listener, &wl);
|
_ = c.xdg_toplevel_add_listener(toplevel, &xdg_toplevel_listener.listener, wl);
|
||||||
|
|
||||||
// Commit changes to surface
|
// Commit changes to surface
|
||||||
c.wl_surface_commit(wl.surface);
|
c.wl_surface_commit(wl.surface);
|
||||||
|
|
@ -170,8 +173,6 @@ pub fn init(
|
||||||
c.wl_surface_commit(wl.surface);
|
c.wl_surface_commit(wl.surface);
|
||||||
// TODO: handle return value
|
// TODO: handle return value
|
||||||
_ = wl.libwaylandclient.wl_display_roundtrip(wl.display);
|
_ = wl.libwaylandclient.wl_display_roundtrip(wl.display);
|
||||||
|
|
||||||
return wl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(
|
pub fn deinit(
|
||||||
|
|
@ -182,6 +183,27 @@ pub fn deinit(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(wl: *Wayland) !void {
|
pub fn update(wl: *Wayland) !void {
|
||||||
|
while (wl.libwaylandclient.wl_display_flush(wl.display) == -1) {
|
||||||
|
if (std.posix.errno(-1) == std.posix.E.AGAIN) {
|
||||||
|
log.err("flush error", .{});
|
||||||
|
return error.FlushError;
|
||||||
|
}
|
||||||
|
var pollfd = [_]std.posix.pollfd{
|
||||||
|
std.posix.pollfd{
|
||||||
|
.fd = wl.libwaylandclient.wl_display_get_fd(wl.display),
|
||||||
|
.events = std.posix.POLL.OUT,
|
||||||
|
.revents = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
while (try std.posix.poll(&pollfd, 1) == -1) {
|
||||||
|
const errno = std.posix.errno(-1);
|
||||||
|
if (errno == std.posix.E.INTR or errno == std.posix.E.AGAIN) {
|
||||||
|
log.err("poll error", .{});
|
||||||
|
return error.PollError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ = wl.libwaylandclient.wl_display_roundtrip(wl.display);
|
_ = wl.libwaylandclient.wl_display_roundtrip(wl.display);
|
||||||
|
|
||||||
wl.core.input.tick();
|
wl.core.input.tick();
|
||||||
|
|
@ -399,8 +421,9 @@ const keyboard_listener = struct {
|
||||||
//Close the fd
|
//Close the fd
|
||||||
std.posix.close(fd);
|
std.posix.close(fd);
|
||||||
|
|
||||||
|
//Release reference to old state and create new state
|
||||||
|
wl.libxkbcommon.xkb_state_unref(wl.xkb_state);
|
||||||
const state = wl.libxkbcommon.xkb_state_new(keymap).?;
|
const state = wl.libxkbcommon.xkb_state_new(keymap).?;
|
||||||
defer wl.libxkbcommon.xkb_state_unref(state);
|
|
||||||
|
|
||||||
//this chain hurts me. why must C be this way.
|
//this chain hurts me. why must C be this way.
|
||||||
const locale = std.posix.getenv("LC_ALL") orelse std.posix.getenv("LC_CTYPE") orelse std.posix.getenv("LANG") orelse "C";
|
const locale = std.posix.getenv("LC_ALL") orelse std.posix.getenv("LC_CTYPE") orelse std.posix.getenv("LANG") orelse "C";
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ pub fn init(
|
||||||
linux: *Linux,
|
linux: *Linux,
|
||||||
core: *Core.Mod,
|
core: *Core.Mod,
|
||||||
options: InitOptions,
|
options: InitOptions,
|
||||||
) !X11 {
|
) !void {
|
||||||
// TODO(core): return errors.NotSupported if not supported
|
// TODO(core): return errors.NotSupported if not supported
|
||||||
const libx11 = try LibX11.load();
|
const libx11 = try LibX11.load();
|
||||||
|
|
||||||
|
|
@ -152,7 +152,7 @@ pub fn init(
|
||||||
.display = display,
|
.display = display,
|
||||||
.window = @intCast(window),
|
.window = @intCast(window),
|
||||||
};
|
};
|
||||||
var x11 = X11{
|
linux.backend = .{ .x11 = X11{
|
||||||
.core = @fieldParentPtr("platform", linux),
|
.core = @fieldParentPtr("platform", linux),
|
||||||
.state = core.state(),
|
.state = core.state(),
|
||||||
.allocator = options.allocator,
|
.allocator = options.allocator,
|
||||||
|
|
@ -188,7 +188,8 @@ pub fn init(
|
||||||
.cursors = std.mem.zeroes([@typeInfo(CursorShape).@"enum".fields.len]?c.Cursor),
|
.cursors = std.mem.zeroes([@typeInfo(CursorShape).@"enum".fields.len]?c.Cursor),
|
||||||
.surface_descriptor = surface_descriptor,
|
.surface_descriptor = surface_descriptor,
|
||||||
.libxkbcommon = try LibXkbCommon.load(),
|
.libxkbcommon = try LibXkbCommon.load(),
|
||||||
};
|
} };
|
||||||
|
var x11 = &linux.backend.x11;
|
||||||
_ = libx11.XrmInitialize();
|
_ = libx11.XrmInitialize();
|
||||||
defer _ = libx11.XFreeColormap(display, colormap);
|
defer _ = libx11.XFreeColormap(display, colormap);
|
||||||
for (0..2) |i| {
|
for (0..2) |i| {
|
||||||
|
|
@ -239,7 +240,6 @@ pub fn init(
|
||||||
}
|
}
|
||||||
// TODO: remove allocation
|
// TODO: remove allocation
|
||||||
x11.cursors[@intFromEnum(CursorShape.arrow)] = try x11.createStandardCursor(.arrow);
|
x11.cursors[@intFromEnum(CursorShape.arrow)] = try x11.createStandardCursor(.arrow);
|
||||||
return x11;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(
|
pub fn deinit(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue