feat: make text follow touch/pointer
parent
c3d240358a
commit
1ba884d7b8
10
src/core.zig
10
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,
|
||||
|
|
99
src/main.zig
99
src/main.zig
|
@ -114,6 +114,7 @@ pub fn main() !void {
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
std.debug.assert(app.state == .run);
|
||||
const pool = &app.state.run.pool;
|
||||
const width = app.state.run.width;
|
||||
|
@ -124,6 +125,8 @@ pub fn main() !void {
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue