From 1ba884d7b852edf5823db633dc27a3c61ce7125f Mon Sep 17 00:00:00 2001 From: Louis Pearson Date: Sat, 17 Feb 2024 16:29:09 -0700 Subject: [PATCH] feat: make text follow touch/pointer --- src/core.zig | 10 +++++ src/main.zig | 117 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 99 insertions(+), 28 deletions(-) diff --git a/src/core.zig b/src/core.zig index 17ffd7d..22d48b9 100644 --- a/src/core.zig +++ b/src/core.zig @@ -309,6 +309,16 @@ pub const Surface = struct { ); } + pub fn frame(surface: Surface, callback: u32) !void { + try surface.conn.send( + Request, + surface.id, + .{ .frame = .{ + .callback = callback, + } }, + ); + } + pub fn commit(surface: Surface) !void { try surface.conn.send( Request, diff --git a/src/main.zig b/src/main.zig index aeb6baf..2e0290b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -114,16 +114,19 @@ pub fn main() !void { } } - std.debug.assert(app.state == .run); - const pool = &app.state.run.pool; - const width = app.state.run.width; - const height = app.state.run.height; + { + std.debug.assert(app.state == .run); + const pool = &app.state.run.pool; + const width = app.state.run.width; + const height = app.state.run.height; - // render - const canvas = try pool.getFramebuffer(.{ width, height }); - canvas.renderGradient(); - try canvas.attach(surface); - try app.callbacks.put(canvas.buffer.id, bufferHandler); + // render + const canvas = try pool.getFramebuffer(.{ width, height }); + canvas.renderGradient(); + try canvas.attach(surface); + try app.callbacks.put(canvas.buffer.id, bufferHandler); + } + try app.queue_redraw(); while (app.state != .close) { const header, const body = try conn.recv(); @@ -152,6 +155,7 @@ const App = struct { callbacks: std.AutoHashMap(u32, Callback), freetype_lib: freetype.Library, font_face: freetype.Face, + rerender: ?u32 = null, display: wayland.core.Display, shm: wayland.core.Shm, @@ -180,6 +184,14 @@ const App = struct { x: f32, y: f32, }, + point: ?struct { + x: f32 = 0, + y: f32 = 0, + } = null, + page_offset: struct { + x: f32, + y: f32, + }, }, close, }, @@ -195,6 +207,15 @@ const App = struct { app.callbacks.deinit(); } + fn queue_redraw(app: *App) !void { + if (app.rerender) |_| return; + const id = app.conn.id_pool.create(); + app.rerender = id; + try app.surface.frame(id); + try app.callbacks.put(id, onFrame); + try app.surface.commit(); + } + fn close(app: *App) void { std.debug.assert(app.state == .run); app.state.run.pool.deinit(); @@ -216,6 +237,7 @@ const App = struct { .pool = try Pool.init(app.ally, app.shm), .keyboard = init.keyboard.?, .mouse = .{ .x = 0, .y = 0 }, + .page_offset = .{ .x = 0, .y = 0 }, } }; try app.callbacks.put(app.state.run.keyboard.id, keyboardHandler); @@ -499,8 +521,7 @@ const Canvas = struct { var x: i32 = @intCast(pos[0]); var y: i32 = @intCast(pos[1]); while (unicode_iter.nextCodepoint()) |codepoint| { - const glyph_index = face.getCharIndex(codepoint) orelse continue; - try face.loadGlyph(glyph_index, .{ .render = true }); + try face.loadChar(codepoint, .{ .render = true }); const glyph = face.glyph(); const bitmap = glyph.bitmap(); canvas.blitFreetypeBitmap(bitmap, .{ @intCast(x + glyph.bitmapLeft()), @intCast(y - glyph.bitmapTop()) }, color); @@ -547,26 +568,32 @@ fn surfaceDesktopHandler(app: *App, header: wayland.Header, body: []const u32) ! switch (event) { .configure => |conf| { try app.xdg_surface.ack_configure(conf.serial); - - std.debug.assert(app.state == .run); - const pool = &app.state.run.pool; - const width = app.state.run.width; - const height = app.state.run.height; - - // render - const canvas = try pool.getFramebuffer(.{ width, height }); - canvas.renderGradient(); - try canvas.print(app.font_face, "Hello, World!", .{ 10, 60 }, Color.White); - try canvas.attach(app.surface); - try app.callbacks.put(canvas.buffer.id, bufferHandler); }, } } fn touchHandler(app: *App, header: wayland.Header, body: []const u32) !void { const event = try wayland.deserialize(wayland.core.Touch.Event, header, body); - _ = app; switch (event) { + .frame => {}, + .down => |touch| { + if (touch.id == 0) { + app.state.run.page_offset.x = @floatFromInt(touch.x >> 8); + app.state.run.page_offset.y = @floatFromInt(touch.y >> 8); + } else { + std.log.info("Non-zero touch id: {}", .{touch}); + } + try app.queue_redraw(); + }, + .motion => |touch| { + if (touch.id == 0) { + app.state.run.page_offset.x = @floatFromInt(touch.x >> 8); + app.state.run.page_offset.y = @floatFromInt(touch.y >> 8); + } else { + std.log.info("Non-zero touch id: {}", .{touch}); + } + try app.queue_redraw(); + }, else => { std.log.info("touch event: {}", .{event}); }, @@ -577,13 +604,15 @@ fn pointerHandler(app: *App, header: wayland.Header, body: []const u32) !void { const event = try wayland.deserialize(wayland.core.Pointer.Event, header, body); switch (event) { .enter => |enter| { - app.state.run.mouse.x = @floatFromInt(enter.surface_x); - app.state.run.mouse.y = @floatFromInt(enter.surface_y); + app.state.run.page_offset.x = @floatFromInt(enter.surface_x >> 8); + app.state.run.page_offset.y = @floatFromInt(enter.surface_y >> 8); + try app.queue_redraw(); }, .leave => |_| {}, .motion => |motion| { - app.state.run.mouse.x = @floatFromInt(motion.surface_x); - app.state.run.mouse.y = @floatFromInt(motion.surface_y); + app.state.run.page_offset.x = @floatFromInt(motion.surface_x >> 8); + app.state.run.page_offset.y = @floatFromInt(motion.surface_y >> 8); + try app.queue_redraw(); }, else => { std.log.info("pointer event: {}", .{event}); @@ -623,3 +652,35 @@ fn bufferHandler(app: *App, header: wayland.Header, body: []const u32) !void { const pool = &app.state.run.pool; try pool.freeFramebuffer(header.object_id); } + +fn onFrame(app: *App, header: wayland.Header, body: []const u32) !void { + _, _ = .{ header, body }; + app.rerender = null; + + std.debug.assert(app.state == .run); + const pool = &app.state.run.pool; + const width = app.state.run.width; + const height = app.state.run.height; + + // render + const canvas = try pool.getFramebuffer(.{ width, height }); + canvas.renderGradient(); + var offsetx: u32 = if (app.state.run.page_offset.x >= 0) @intFromFloat(app.state.run.page_offset.x) else 0; + var offsety: u32 = if (app.state.run.page_offset.y >= 0) @intFromFloat(app.state.run.page_offset.y) else 0; + if (app.state.run.point) |point| { + offsetx -|= @intFromFloat(point.x); + offsety -|= @intFromFloat(point.y); + } + std.log.info("Calculated page offset: {}, {}", .{ offsetx, offsety }); + try canvas.print( + app.font_face, + "Hello, World!", + .{ + offsetx + 10, + offsety + 60, + }, + Color.White, + ); + try canvas.attach(app.surface); + try app.callbacks.put(canvas.buffer.id, bufferHandler); +}