From 18a8befacd074fc35e5c5f64013765871f64979b Mon Sep 17 00:00:00 2001 From: Louis Pearson Date: Wed, 7 Feb 2024 01:47:13 -0700 Subject: [PATCH] feat: get touch working --- src/core.zig | 39 +++++++ src/main.zig | 322 ++++++++++++++++++++------------------------------- 2 files changed, 165 insertions(+), 196 deletions(-) diff --git a/src/core.zig b/src/core.zig index 2b36b9d..297ee14 100644 --- a/src/core.zig +++ b/src/core.zig @@ -349,3 +349,42 @@ pub const Keyboard = struct { 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, + }, + }; +}; diff --git a/src/main.zig b/src/main.zig index 9ef8760..e0fa65c 100644 --- a/src/main.zig +++ b/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; if (seat_capabilties) |caps| { - if (caps.pointer) { - wl_pointer_id_opt = id_pool.create(); - std.debug.print("wl pointer id: {}\n", .{wl_pointer_id_opt.?}); + if (caps.touch) { + wl_touch_id_opt = id_pool.create(); + std.debug.print("wl touch id: {}\n", .{wl_touch_id_opt.?}); try conn.send( wayland.core.Seat.Request, wl_seat_id, - .{ .get_pointer = .{ - .new_id = wl_pointer_id_opt.?, + .{ .get_touch = .{ + .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; // 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]) }; - const xkb_ctx = xkbcommon.Context.new(.no_flags) orelse return error.XKBInit; - defer xkb_ctx.unref(); - var xkb_keymap_opt: ?*xkbcommon.Keymap = null; - defer if (xkb_keymap_opt) |xkb_keymap| { - 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 scrollpos: [2]i32 = .{ 10, 10 }; + var touchstart: ?[2]i32 = null; var running = true; while (running) { @@ -336,10 +314,8 @@ pub fn main() !void { // put some interesting colors into the new_framebuffer renderGradient(new_framebuffer, window_size); - const text = try piece_table.writeAllAlloc(); - defer gpa.free(text); // 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( wayland.core.ShmPool.Request, @@ -409,9 +385,81 @@ pub fn main() !void { ); }, } - } else if (header.object_id == wl_pointer_id) { - const event = try wayland.deserialize(wayland.core.Pointer.Event, header, body); - std.debug.print("<- wl_pointer@{}\n", .{event}); + } else if (header.object_id == wl_touch_id) { + const event = try wayland.deserialize(wayland.core.Touch.Event, header, body); + std.debug.print("<- wl_touch@{}\n", .{event}); + event: { + switch (event) { + .down => |down| { + if (down.id != 0) break :event; + touchstart = .{ @intCast(down.x), @intCast(down.y) }; + }, + .motion => |motion| { + if (motion.id != 0) break :event; + if (touchstart) |start| { + scrollpos[0] = motion.x - start[0]; + scrollpos[1] = motion.y - start[1]; + } + }, + .up => |up| { + if (up.id != 0) break :event; + touchstart = null; + }, + .frame => { + const new_buffer_id = id_pool.create(); + const new_framebuffer = try pool_alloc.alloc(Pixel, window_size[0] * window_size[1]); + try framebuffers.put(new_buffer_id, new_framebuffer); + + // put some interesting colors into the new_framebuffer + renderGradient(new_framebuffer, window_size); + + // blit some characters + renderText(new_framebuffer, window_size, .{ @intCast(@divTrunc(scrollpos[0], 100)), @intCast(@divTrunc(scrollpos[1], 100)) }, "Hello, World!"); + + try conn.send( + wayland.core.ShmPool.Request, + wl_shm_pool_id, + .{ .create_buffer = .{ + .new_id = new_buffer_id, + .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( + wayland.core.Surface.Request, + surface_id, + .{ .attach = .{ + .buffer = new_buffer_id, + .x = 0, + .y = 0, + } }, + ); + + try conn.send( + wayland.core.Surface.Request, + surface_id, + .{ .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, + ); + }, + else => {}, + } + } } else if (header.object_id == wl_keyboard_id) { const event = try wayland.deserialize(wayland.core.Keyboard.Event, header, body); switch (event) { @@ -431,181 +479,63 @@ pub fn main() !void { 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| { - if (xkb_state_opt) |xkb_state| { - _ = xkb_state.updateMask( - mods.mods_depressed, - mods.mods_latched, - mods.mods_locked, - 0, - 0, - 0, - ); - } + std.debug.print("mod event: {}\n", .{mods}); }, .key => |key| { - if (xkb_state_opt) |xkb_state| { - const keycode: xkbcommon.Keycode = key.key + 8; - 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)]}); + std.debug.print("key event: {}\n", .{key}); + const new_buffer_id, const new_framebuffer = try getFramebuffer(&framebuffers, &id_pool, pool_alloc, window_size); - 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 => { - piece_table.delete(cursor_pos, 1) catch |e| switch (e) { - error.OutOfBounds => {}, - else => return e, - }; - }, - 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; - }, - } + // put some interesting colors into the new_framebuffer + renderGradient(new_framebuffer, window_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 - renderGradient(new_framebuffer, window_size); - - const text = try piece_table.writeAllAlloc(); - defer gpa.free(text); - // blit some characters - renderText(new_framebuffer, window_size, .{ 10, 10 }, text); - - try conn.send( - wayland.core.ShmPool.Request, - wl_shm_pool_id, - .{ .create_buffer = .{ - .new_id = new_buffer_id, - .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( - wayland.core.Surface.Request, - surface_id, - .{ .attach = .{ - .buffer = new_buffer_id, - .x = 0, - .y = 0, - } }, - ); - - try conn.send( - wayland.core.Surface.Request, - surface_id, - .{ .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, - ); - } - } - }, - else => { - std.debug.print("<- wl_keyboard@{}\n", .{event}); - }, - } - } else if (header.object_id == zwp_text_input_v3_id) { - const event = try wayland.deserialize(wayland.zwp.TextInputV3.Event, header, body); - std.debug.print("<- zwp_text_input_v3@{} event {}\n", .{ zwp_text_input_v3_id, event }); - switch (event) { - .enter => |e| { - _ = e; - - // if (e.surface == surface_id) { - try conn.send( - wayland.zwp.TextInputV3.Request, - zwp_text_input_v3_id, - .enable, - ); + // blit some characters + renderText(new_framebuffer, window_size, .{ 10, 10 }, "Hello, World!"); try conn.send( - wayland.zwp.TextInputV3.Request, - zwp_text_input_v3_id, - .{ .set_content_type = .{ - .hint = .multiline, - .purpose = .normal, + wayland.core.ShmPool.Request, + wl_shm_pool_id, + .{ .create_buffer = .{ + .new_id = new_buffer_id, + .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( - wayland.zwp.TextInputV3.Request, - zwp_text_input_v3_id, - .commit, + wayland.core.Surface.Request, + surface_id, + .{ .attach = .{ + .buffer = new_buffer_id, + .x = 0, + .y = 0, + } }, ); - // } - }, - .leave => |e| { - _ = e; - // if (e.surface == surface_id) { try conn.send( - wayland.zwp.TextInputV3.Request, - zwp_text_input_v3_id, - .disable, + wayland.core.Surface.Request, + surface_id, + .{ .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 => {}, - .commit_string => |commit| { - 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 => { + std.debug.print("<- wl_keyboard@{}\n", .{event}); }, } } 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 { - const top, const left = pos; + const left, const top = pos; const bot = @min(top + 8, fb_size[1]); const right = @min(left + textWidth(str) * 8, fb_size[0]);