feat: get touch working
parent
76365322f2
commit
18a8befacd
39
src/core.zig
39
src/core.zig
|
@ -349,3 +349,42 @@ pub const Keyboard = struct {
|
||||||
pressed,
|
pressed,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Touch = struct {
|
||||||
|
pub const Request = union(enum) {
|
||||||
|
release: void,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Event = union(enum) {
|
||||||
|
down: struct {
|
||||||
|
serial: u32,
|
||||||
|
time: u32,
|
||||||
|
surface: u32,
|
||||||
|
id: i32,
|
||||||
|
x: u32,
|
||||||
|
y: u32,
|
||||||
|
},
|
||||||
|
up: struct {
|
||||||
|
serial: u32,
|
||||||
|
time: u32,
|
||||||
|
id: i32,
|
||||||
|
},
|
||||||
|
motion: struct {
|
||||||
|
time: u32,
|
||||||
|
id: i32,
|
||||||
|
x: i32, //i24.8
|
||||||
|
y: i32, //i24.8
|
||||||
|
},
|
||||||
|
frame: void,
|
||||||
|
cancel: void,
|
||||||
|
shape: struct {
|
||||||
|
id: i32,
|
||||||
|
major: i32, // fixed
|
||||||
|
minor: i32, // fixed
|
||||||
|
},
|
||||||
|
orientation: struct {
|
||||||
|
id: i32,
|
||||||
|
orientation: i32,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
262
src/main.zig
262
src/main.zig
|
@ -182,17 +182,17 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var wl_pointer_id_opt: ?u32 = null;
|
var wl_touch_id_opt: ?u32 = null;
|
||||||
var wl_keyboard_id_opt: ?u32 = null;
|
var wl_keyboard_id_opt: ?u32 = null;
|
||||||
if (seat_capabilties) |caps| {
|
if (seat_capabilties) |caps| {
|
||||||
if (caps.pointer) {
|
if (caps.touch) {
|
||||||
wl_pointer_id_opt = id_pool.create();
|
wl_touch_id_opt = id_pool.create();
|
||||||
std.debug.print("wl pointer id: {}\n", .{wl_pointer_id_opt.?});
|
std.debug.print("wl touch id: {}\n", .{wl_touch_id_opt.?});
|
||||||
try conn.send(
|
try conn.send(
|
||||||
wayland.core.Seat.Request,
|
wayland.core.Seat.Request,
|
||||||
wl_seat_id,
|
wl_seat_id,
|
||||||
.{ .get_pointer = .{
|
.{ .get_touch = .{
|
||||||
.new_id = wl_pointer_id_opt.?,
|
.new_id = wl_touch_id_opt.?,
|
||||||
} },
|
} },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ pub fn main() !void {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const wl_pointer_id = wl_pointer_id_opt orelse return error.MissingPointer;
|
const wl_touch_id = wl_touch_id_opt orelse return error.MissingTouch;
|
||||||
const wl_keyboard_id = wl_keyboard_id_opt orelse return error.MissingKeyboard;
|
const wl_keyboard_id = wl_keyboard_id_opt orelse return error.MissingKeyboard;
|
||||||
|
|
||||||
// allocate a shared memory file for display purposes
|
// allocate a shared memory file for display purposes
|
||||||
|
@ -287,31 +287,9 @@ pub fn main() !void {
|
||||||
);
|
);
|
||||||
|
|
||||||
var window_size: [2]u32 = [2]u32{ @intCast(framebuffer_size[0]), @intCast(framebuffer_size[1]) };
|
var window_size: [2]u32 = [2]u32{ @intCast(framebuffer_size[0]), @intCast(framebuffer_size[1]) };
|
||||||
const xkb_ctx = xkbcommon.Context.new(.no_flags) orelse return error.XKBInit;
|
|
||||||
defer xkb_ctx.unref();
|
|
||||||
|
|
||||||
var xkb_keymap_opt: ?*xkbcommon.Keymap = null;
|
var scrollpos: [2]i32 = .{ 10, 10 };
|
||||||
defer if (xkb_keymap_opt) |xkb_keymap| {
|
var touchstart: ?[2]i32 = null;
|
||||||
xkb_keymap.unref();
|
|
||||||
};
|
|
||||||
var xkb_state_opt: ?*xkbcommon.State = null;
|
|
||||||
defer if (xkb_state_opt) |xkb_state| {
|
|
||||||
xkb_state.unref();
|
|
||||||
};
|
|
||||||
|
|
||||||
var piece_table = try PieceTable.init(gpa, "Hello, World!");
|
|
||||||
defer piece_table.deinit();
|
|
||||||
|
|
||||||
var edit_buffer: [1024]u8 = [1]u8{0} ** 1024;
|
|
||||||
var edit_slice: ?[]u8 = null;
|
|
||||||
|
|
||||||
var delete_before: usize = 0;
|
|
||||||
var delete_after: usize = 0;
|
|
||||||
|
|
||||||
// var preedit_buffer: [1024]u8 = [1]u8{0} ** 1024;
|
|
||||||
// var preedit_slice: ?[]u8 = null;
|
|
||||||
|
|
||||||
var cursor_pos: usize = piece_table.getTotalSize();
|
|
||||||
|
|
||||||
var running = true;
|
var running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
|
@ -336,10 +314,8 @@ pub fn main() !void {
|
||||||
// put some interesting colors into the new_framebuffer
|
// put some interesting colors into the new_framebuffer
|
||||||
renderGradient(new_framebuffer, window_size);
|
renderGradient(new_framebuffer, window_size);
|
||||||
|
|
||||||
const text = try piece_table.writeAllAlloc();
|
|
||||||
defer gpa.free(text);
|
|
||||||
// blit some characters
|
// blit some characters
|
||||||
renderText(new_framebuffer, window_size, .{ 10, 10 }, text);
|
renderText(new_framebuffer, window_size, .{ @intCast(scrollpos[0]), @intCast(scrollpos[1]) }, "Hello, World!");
|
||||||
|
|
||||||
try conn.send(
|
try conn.send(
|
||||||
wayland.core.ShmPool.Request,
|
wayland.core.ShmPool.Request,
|
||||||
|
@ -409,87 +385,36 @@ pub fn main() !void {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (header.object_id == wl_pointer_id) {
|
} else if (header.object_id == wl_touch_id) {
|
||||||
const event = try wayland.deserialize(wayland.core.Pointer.Event, header, body);
|
const event = try wayland.deserialize(wayland.core.Touch.Event, header, body);
|
||||||
std.debug.print("<- wl_pointer@{}\n", .{event});
|
std.debug.print("<- wl_touch@{}\n", .{event});
|
||||||
} else if (header.object_id == wl_keyboard_id) {
|
event: {
|
||||||
const event = try wayland.deserialize(wayland.core.Keyboard.Event, header, body);
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.keymap => |keymap| {
|
.down => |down| {
|
||||||
const fd = conn.fd_queue.orderedRemove(0);
|
if (down.id != 0) break :event;
|
||||||
std.debug.print("keymap format={}, size={}, fd={}\n", .{
|
touchstart = .{ @intCast(down.x), @intCast(down.y) };
|
||||||
keymap.format,
|
|
||||||
keymap.size,
|
|
||||||
fd,
|
|
||||||
});
|
|
||||||
const mem = try std.os.mmap(
|
|
||||||
null,
|
|
||||||
keymap.size,
|
|
||||||
std.os.PROT.READ,
|
|
||||||
std.os.MAP.PRIVATE,
|
|
||||||
fd,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
std.debug.print("---START xkb file---\n{s}\n---END xkb file---\n", .{mem});
|
|
||||||
xkb_keymap_opt = xkbcommon.Keymap.newFromString(xkb_ctx, @ptrCast(mem), .text_v1, .no_flags) orelse return error.XKBKeymap;
|
|
||||||
xkb_state_opt = xkbcommon.State.new(xkb_keymap_opt.?) orelse return error.XKBStateInit;
|
|
||||||
},
|
},
|
||||||
.modifiers => |mods| {
|
.motion => |motion| {
|
||||||
if (xkb_state_opt) |xkb_state| {
|
if (motion.id != 0) break :event;
|
||||||
_ = xkb_state.updateMask(
|
if (touchstart) |start| {
|
||||||
mods.mods_depressed,
|
scrollpos[0] = motion.x - start[0];
|
||||||
mods.mods_latched,
|
scrollpos[1] = motion.y - start[1];
|
||||||
mods.mods_locked,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.key => |key| {
|
.up => |up| {
|
||||||
if (xkb_state_opt) |xkb_state| {
|
if (up.id != 0) break :event;
|
||||||
const keycode: xkbcommon.Keycode = key.key + 8;
|
touchstart = null;
|
||||||
const keysym: xkbcommon.Keysym = xkb_state.keyGetOneSym(keycode);
|
|
||||||
var buf: [64]u8 = undefined;
|
|
||||||
// const name_len = keysym.getName(&buf, buf.len);
|
|
||||||
// std.debug.print("{s}\n", .{buf[0..@intCast(name_len)]});
|
|
||||||
|
|
||||||
if (key.state == .pressed) {
|
|
||||||
const sym = xkbcommon.Keysym;
|
|
||||||
switch (@as(u32, @intFromEnum(keysym))) {
|
|
||||||
sym.BackSpace => {
|
|
||||||
try piece_table.delete(cursor_pos - 1, 1);
|
|
||||||
cursor_pos -= 1;
|
|
||||||
},
|
},
|
||||||
sym.Delete => {
|
.frame => {
|
||||||
piece_table.delete(cursor_pos, 1) catch |e| switch (e) {
|
const new_buffer_id = id_pool.create();
|
||||||
error.OutOfBounds => {},
|
const new_framebuffer = try pool_alloc.alloc(Pixel, window_size[0] * window_size[1]);
|
||||||
else => return e,
|
try framebuffers.put(new_buffer_id, new_framebuffer);
|
||||||
};
|
|
||||||
},
|
|
||||||
sym.Left => {
|
|
||||||
cursor_pos -|= 1;
|
|
||||||
},
|
|
||||||
sym.Right => {
|
|
||||||
cursor_pos += 1;
|
|
||||||
cursor_pos = @min(cursor_pos, piece_table.getTotalSize());
|
|
||||||
},
|
|
||||||
else => if (key.state == .pressed) {
|
|
||||||
const size = xkb_state.keyGetUtf8(keycode, &buf);
|
|
||||||
try piece_table.insert(cursor_pos, buf[0..size]);
|
|
||||||
cursor_pos += size;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const new_buffer_id, const new_framebuffer = try getFramebuffer(&framebuffers, &id_pool, pool_alloc, window_size);
|
|
||||||
|
|
||||||
// put some interesting colors into the new_framebuffer
|
// put some interesting colors into the new_framebuffer
|
||||||
renderGradient(new_framebuffer, window_size);
|
renderGradient(new_framebuffer, window_size);
|
||||||
|
|
||||||
const text = try piece_table.writeAllAlloc();
|
|
||||||
defer gpa.free(text);
|
|
||||||
// blit some characters
|
// blit some characters
|
||||||
renderText(new_framebuffer, window_size, .{ 10, 10 }, text);
|
renderText(new_framebuffer, window_size, .{ @intCast(@divTrunc(scrollpos[0], 100)), @intCast(@divTrunc(scrollpos[1], 100)) }, "Hello, World!");
|
||||||
|
|
||||||
try conn.send(
|
try conn.send(
|
||||||
wayland.core.ShmPool.Request,
|
wayland.core.ShmPool.Request,
|
||||||
|
@ -531,81 +456,86 @@ pub fn main() !void {
|
||||||
surface_id,
|
surface_id,
|
||||||
wayland.core.Surface.Request.commit,
|
wayland.core.Surface.Request.commit,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
std.debug.print("<- wl_keyboard@{}\n", .{event});
|
|
||||||
},
|
},
|
||||||
|
else => {},
|
||||||
}
|
}
|
||||||
} else if (header.object_id == zwp_text_input_v3_id) {
|
}
|
||||||
const event = try wayland.deserialize(wayland.zwp.TextInputV3.Event, header, body);
|
} else if (header.object_id == wl_keyboard_id) {
|
||||||
std.debug.print("<- zwp_text_input_v3@{} event {}\n", .{ zwp_text_input_v3_id, event });
|
const event = try wayland.deserialize(wayland.core.Keyboard.Event, header, body);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.enter => |e| {
|
.keymap => |keymap| {
|
||||||
_ = e;
|
const fd = conn.fd_queue.orderedRemove(0);
|
||||||
|
std.debug.print("keymap format={}, size={}, fd={}\n", .{
|
||||||
// if (e.surface == surface_id) {
|
keymap.format,
|
||||||
try conn.send(
|
keymap.size,
|
||||||
wayland.zwp.TextInputV3.Request,
|
fd,
|
||||||
zwp_text_input_v3_id,
|
});
|
||||||
.enable,
|
const mem = try std.os.mmap(
|
||||||
|
null,
|
||||||
|
keymap.size,
|
||||||
|
std.os.PROT.READ,
|
||||||
|
std.os.MAP.PRIVATE,
|
||||||
|
fd,
|
||||||
|
0,
|
||||||
);
|
);
|
||||||
|
std.debug.print("---START xkb file---\n{s}\n---END xkb file---\n", .{mem});
|
||||||
|
},
|
||||||
|
.modifiers => |mods| {
|
||||||
|
std.debug.print("mod event: {}\n", .{mods});
|
||||||
|
},
|
||||||
|
.key => |key| {
|
||||||
|
std.debug.print("key event: {}\n", .{key});
|
||||||
|
const new_buffer_id, const new_framebuffer = try getFramebuffer(&framebuffers, &id_pool, pool_alloc, window_size);
|
||||||
|
|
||||||
|
// put some interesting colors into the new_framebuffer
|
||||||
|
renderGradient(new_framebuffer, window_size);
|
||||||
|
|
||||||
|
// blit some characters
|
||||||
|
renderText(new_framebuffer, window_size, .{ 10, 10 }, "Hello, World!");
|
||||||
|
|
||||||
try conn.send(
|
try conn.send(
|
||||||
wayland.zwp.TextInputV3.Request,
|
wayland.core.ShmPool.Request,
|
||||||
zwp_text_input_v3_id,
|
wl_shm_pool_id,
|
||||||
.{ .set_content_type = .{
|
.{ .create_buffer = .{
|
||||||
.hint = .multiline,
|
.new_id = new_buffer_id,
|
||||||
.purpose = .normal,
|
.offset = @intCast(@intFromPtr(new_framebuffer.ptr) - @intFromPtr(pool_bytes.ptr)),
|
||||||
|
.width = @intCast(window_size[0]),
|
||||||
|
.height = @intCast(window_size[1]),
|
||||||
|
.stride = @as(i32, @intCast(window_size[0])) * @sizeOf([4]u8),
|
||||||
|
.format = .argb8888,
|
||||||
} },
|
} },
|
||||||
);
|
);
|
||||||
|
|
||||||
try conn.send(
|
try conn.send(
|
||||||
wayland.zwp.TextInputV3.Request,
|
wayland.core.Surface.Request,
|
||||||
zwp_text_input_v3_id,
|
surface_id,
|
||||||
.commit,
|
.{ .attach = .{
|
||||||
|
.buffer = new_buffer_id,
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
} },
|
||||||
);
|
);
|
||||||
// }
|
|
||||||
},
|
|
||||||
.leave => |e| {
|
|
||||||
_ = e;
|
|
||||||
|
|
||||||
// if (e.surface == surface_id) {
|
|
||||||
try conn.send(
|
try conn.send(
|
||||||
wayland.zwp.TextInputV3.Request,
|
wayland.core.Surface.Request,
|
||||||
zwp_text_input_v3_id,
|
surface_id,
|
||||||
.disable,
|
.{ .damage = .{
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = std.math.maxInt(i32),
|
||||||
|
.height = std.math.maxInt(i32),
|
||||||
|
} },
|
||||||
|
);
|
||||||
|
|
||||||
|
// commit the configuration
|
||||||
|
try conn.send(
|
||||||
|
wayland.core.Surface.Request,
|
||||||
|
surface_id,
|
||||||
|
wayland.core.Surface.Request.commit,
|
||||||
);
|
);
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
.preedit_string => {},
|
else => {
|
||||||
.commit_string => |commit| {
|
std.debug.print("<- wl_keyboard@{}\n", .{event});
|
||||||
edit_slice = edit_buffer[0..commit.text.len];
|
|
||||||
@memcpy(edit_slice.?, commit.text);
|
|
||||||
},
|
|
||||||
.delete_surrounding_text => |offset| {
|
|
||||||
delete_before = offset.before_length;
|
|
||||||
delete_after = offset.after_length;
|
|
||||||
},
|
|
||||||
.done => |_| {
|
|
||||||
// 1 replace existing pre-edit string with cursor
|
|
||||||
// 2 delete requested surrounding text
|
|
||||||
const start = cursor_pos - delete_before;
|
|
||||||
const end = cursor_pos + delete_after;
|
|
||||||
const length = end - start;
|
|
||||||
if (length != 0) {
|
|
||||||
try piece_table.delete(start, length);
|
|
||||||
}
|
|
||||||
// 3 insert commit string with cursor at its end
|
|
||||||
if (edit_slice) |slice| {
|
|
||||||
try piece_table.insert(cursor_pos, slice);
|
|
||||||
cursor_pos += slice.len;
|
|
||||||
edit_slice = null;
|
|
||||||
}
|
|
||||||
// 4 calculate surrounding text to send
|
|
||||||
// 5 insert new preedit text in cursor position
|
|
||||||
// 6 place cursor inside predit text
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (framebuffers.get(header.object_id)) |framebuffer_slice| {
|
} else if (framebuffers.get(header.object_id)) |framebuffer_slice| {
|
||||||
|
@ -665,7 +595,7 @@ fn textWidth(str: []const u8) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderText(framebuffer: []Pixel, fb_size: [2]u32, pos: [2]usize, str: []const u8) void {
|
fn renderText(framebuffer: []Pixel, fb_size: [2]u32, pos: [2]usize, str: []const u8) void {
|
||||||
const top, const left = pos;
|
const left, const top = pos;
|
||||||
const bot = @min(top + 8, fb_size[1]);
|
const bot = @min(top + 8, fb_size[1]);
|
||||||
const right = @min(left + textWidth(str) * 8, fb_size[0]);
|
const right = @min(left + textWidth(str) * 8, fb_size[0]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue