feat: make text follow touch/pointer

dev
Louis Pearson 2024-02-17 16:29:09 -07:00
parent c3d240358a
commit 1ba884d7b8
2 changed files with 99 additions and 28 deletions

View File

@ -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 { pub fn commit(surface: Surface) !void {
try surface.conn.send( try surface.conn.send(
Request, Request,

View File

@ -114,16 +114,19 @@ pub fn main() !void {
} }
} }
std.debug.assert(app.state == .run); {
const pool = &app.state.run.pool; std.debug.assert(app.state == .run);
const width = app.state.run.width; const pool = &app.state.run.pool;
const height = app.state.run.height; const width = app.state.run.width;
const height = app.state.run.height;
// render // render
const canvas = try pool.getFramebuffer(.{ width, height }); const canvas = try pool.getFramebuffer(.{ width, height });
canvas.renderGradient(); canvas.renderGradient();
try canvas.attach(surface); try canvas.attach(surface);
try app.callbacks.put(canvas.buffer.id, bufferHandler); try app.callbacks.put(canvas.buffer.id, bufferHandler);
}
try app.queue_redraw();
while (app.state != .close) { while (app.state != .close) {
const header, const body = try conn.recv(); const header, const body = try conn.recv();
@ -152,6 +155,7 @@ const App = struct {
callbacks: std.AutoHashMap(u32, Callback), callbacks: std.AutoHashMap(u32, Callback),
freetype_lib: freetype.Library, freetype_lib: freetype.Library,
font_face: freetype.Face, font_face: freetype.Face,
rerender: ?u32 = null,
display: wayland.core.Display, display: wayland.core.Display,
shm: wayland.core.Shm, shm: wayland.core.Shm,
@ -180,6 +184,14 @@ const App = struct {
x: f32, x: f32,
y: f32, y: f32,
}, },
point: ?struct {
x: f32 = 0,
y: f32 = 0,
} = null,
page_offset: struct {
x: f32,
y: f32,
},
}, },
close, close,
}, },
@ -195,6 +207,15 @@ const App = struct {
app.callbacks.deinit(); 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 { fn close(app: *App) void {
std.debug.assert(app.state == .run); std.debug.assert(app.state == .run);
app.state.run.pool.deinit(); app.state.run.pool.deinit();
@ -216,6 +237,7 @@ const App = struct {
.pool = try Pool.init(app.ally, app.shm), .pool = try Pool.init(app.ally, app.shm),
.keyboard = init.keyboard.?, .keyboard = init.keyboard.?,
.mouse = .{ .x = 0, .y = 0 }, .mouse = .{ .x = 0, .y = 0 },
.page_offset = .{ .x = 0, .y = 0 },
} }; } };
try app.callbacks.put(app.state.run.keyboard.id, keyboardHandler); try app.callbacks.put(app.state.run.keyboard.id, keyboardHandler);
@ -499,8 +521,7 @@ const Canvas = struct {
var x: i32 = @intCast(pos[0]); var x: i32 = @intCast(pos[0]);
var y: i32 = @intCast(pos[1]); var y: i32 = @intCast(pos[1]);
while (unicode_iter.nextCodepoint()) |codepoint| { while (unicode_iter.nextCodepoint()) |codepoint| {
const glyph_index = face.getCharIndex(codepoint) orelse continue; try face.loadChar(codepoint, .{ .render = true });
try face.loadGlyph(glyph_index, .{ .render = true });
const glyph = face.glyph(); const glyph = face.glyph();
const bitmap = glyph.bitmap(); const bitmap = glyph.bitmap();
canvas.blitFreetypeBitmap(bitmap, .{ @intCast(x + glyph.bitmapLeft()), @intCast(y - glyph.bitmapTop()) }, color); 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) { switch (event) {
.configure => |conf| { .configure => |conf| {
try app.xdg_surface.ack_configure(conf.serial); 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 { fn touchHandler(app: *App, header: wayland.Header, body: []const u32) !void {
const event = try wayland.deserialize(wayland.core.Touch.Event, header, body); const event = try wayland.deserialize(wayland.core.Touch.Event, header, body);
_ = app;
switch (event) { 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 => { else => {
std.log.info("touch event: {}", .{event}); 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); const event = try wayland.deserialize(wayland.core.Pointer.Event, header, body);
switch (event) { switch (event) {
.enter => |enter| { .enter => |enter| {
app.state.run.mouse.x = @floatFromInt(enter.surface_x); app.state.run.page_offset.x = @floatFromInt(enter.surface_x >> 8);
app.state.run.mouse.y = @floatFromInt(enter.surface_y); app.state.run.page_offset.y = @floatFromInt(enter.surface_y >> 8);
try app.queue_redraw();
}, },
.leave => |_| {}, .leave => |_| {},
.motion => |motion| { .motion => |motion| {
app.state.run.mouse.x = @floatFromInt(motion.surface_x); app.state.run.page_offset.x = @floatFromInt(motion.surface_x >> 8);
app.state.run.mouse.y = @floatFromInt(motion.surface_y); app.state.run.page_offset.y = @floatFromInt(motion.surface_y >> 8);
try app.queue_redraw();
}, },
else => { else => {
std.log.info("pointer event: {}", .{event}); 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; const pool = &app.state.run.pool;
try pool.freeFramebuffer(header.object_id); 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);
}