commit aae2679e7485e558b4271760e11f75176bb3e644
parent 4db11685b9299e8ea857c6e508d7a6d8ddd001d9
Author: Andrea Feletto <andrea@andreafeletto.com>
Date: Thu, 20 Jan 2022 12:45:31 +0100
add stdin widget with utf8 support
Diffstat:
4 files changed, 131 insertions(+), 39 deletions(-)
diff --git a/src/event.zig b/src/event.zig
@@ -10,7 +10,7 @@ const State = @import("main.zig").State;
pub const Loop = struct {
state: *State,
- fds: [2]os.pollfd,
+ fds: [3]os.pollfd,
pub fn init(state: *State) !Loop {
const tfd = os.linux.timerfd_create(
@@ -36,6 +36,11 @@ pub const Loop = struct {
.events = os.POLL.IN,
.revents = 0,
},
+ .{
+ .fd = os.linux.STDIN_FILENO,
+ .events = os.POLL.IN,
+ .revents = 0,
+ },
},
};
}
@@ -84,6 +89,23 @@ pub const Loop = struct {
}
}
}
+
+ // stdin
+ if (self.fds[2].revents & os.POLL.IN != 0) {
+ var buffer = [_]u8{0} ** 256;
+ const len = try os.read(self.fds[2].fd, &buffer);
+ if (len == 0) continue;
+
+ for (self.state.wayland.outputs.items) |output| {
+ if (output.surface) |surface| {
+ if (surface.configured) {
+ render.renderCustom(surface, buffer[0 .. len - 1]) catch continue;
+ surface.customSurface.commit();
+ surface.backgroundSurface.commit();
+ }
+ }
+ }
+ }
}
}
};
diff --git a/src/render.zig b/src/render.zig
@@ -80,15 +80,23 @@ pub fn renderClock(surface: *Surface) !void {
const str = try formatDatetime(state);
defer state.allocator.free(str);
- // convert chars to ints for fcft
- const cint = try state.allocator.alloc(c_int, str.len);
- defer state.allocator.free(cint);
- for (str) |char, i| cint[i] = char;
+ // ut8 encoding
+ const utf8 = try std.unicode.Utf8View.init(str);
+ var utf8_iter = utf8.iterator();
- const run = try fcft.TextRun.rasterize(state.config.font, cint, .default);
- defer run.destroy();
+ var runes = try state.allocator.alloc(c_int, str.len);
+ defer state.allocator.free(runes);
var i: usize = 0;
+ while (utf8_iter.nextCodepoint()) |rune| : (i += 1) {
+ runes[i] = rune;
+ }
+ runes = state.allocator.resize(runes, i).?;
+
+ const run = try fcft.TextRun.rasterize(state.config.font, runes, .default);
+ defer run.destroy();
+
+ i = 0;
var text_width: u32 = 0;
while (i < run.count) : (i += 1) {
text_width += @intCast(u32, run.glyphs[i].advance.x);
@@ -104,15 +112,69 @@ pub fn renderClock(surface: *Surface) !void {
const glyph = run.glyphs[i];
const x = x_offset + @intCast(i32, glyph.x);
const y = y_offset + state.config.font.ascent - @intCast(i32, glyph.y);
- pixman.Image.composite32(
- .over,
- color,
- glyph.pix,
- buffer.pix.?,
- 0, 0, 0, 0,
- x, y,
- glyph.width, glyph.height,
- );
+ pixman.Image.composite32(.over, color, glyph.pix, buffer.pix.?, 0, 0, 0, 0, x, y, glyph.width, glyph.height);
+ x_offset += glyph.advance.x;
+ }
+
+ wlSurface.setBufferScale(surface.output.scale);
+ wlSurface.damageBuffer(0, 0, surface.width, surface.height);
+ wlSurface.attach(buffer.buffer, 0, 0);
+}
+
+pub fn renderCustom(surface: *Surface, str: []const u8) !void {
+ const state = surface.output.state;
+ const wlSurface = surface.customSurface;
+
+ const buffer = try Buffer.nextBuffer(
+ &surface.customBuffers,
+ surface.output.state.wayland.shm,
+ surface.width,
+ surface.height,
+ );
+ buffer.busy = true;
+
+ // clear the buffer
+ const bg_area = [_]pixman.Rectangle16{
+ .{ .x = 0, .y = 0, .width = surface.width, .height = surface.height },
+ };
+ const bg_color = mem.zeroes(pixman.Color);
+ _ = pixman.Image.fillRectangles(.src, buffer.pix.?, &bg_color, 1, &bg_area);
+
+ // ut8 encoding
+ const utf8 = try std.unicode.Utf8View.init(str);
+ var utf8_iter = utf8.iterator();
+
+ var runes = try state.allocator.alloc(c_int, str.len);
+ defer state.allocator.free(runes);
+
+ var i: usize = 0;
+ while (utf8_iter.nextCodepoint()) |rune| : (i += 1) {
+ runes[i] = rune;
+ }
+ runes = state.allocator.resize(runes, i).?;
+
+ const run = try fcft.TextRun.rasterize(state.config.font, runes, .default);
+ defer run.destroy();
+
+ // compute offsets
+ i = 0;
+ var text_width: u32 = 0;
+ while (i < run.count) : (i += 1) {
+ text_width += @intCast(u32, run.glyphs[i].advance.x);
+ }
+
+ const font_height = @intCast(u32, state.config.font.height);
+ var x_offset = @intCast(i32, surface.width - text_width);
+ var y_offset = @intCast(i32, @divFloor(surface.height - font_height, 2));
+
+ // resterize
+ i = 0;
+ var color = pixman.Image.createSolidFill(&state.config.foregroundColor).?;
+ while (i < run.count) : (i += 1) {
+ const glyph = run.glyphs[i];
+ const x = x_offset + @intCast(i32, glyph.x);
+ const y = y_offset + state.config.font.ascent - @intCast(i32, glyph.y);
+ pixman.Image.composite32(.over, color, glyph.pix, buffer.pix.?, 0, 0, 0, 0, x, y, glyph.width, glyph.height);
x_offset += glyph.advance.x;
}
@@ -164,15 +226,7 @@ fn renderTag(
const glyph = try fcft.Glyph.rasterize(font, tag.label, .default);
const x = offset + @divFloor(size - glyph.width, 2);
const y = @divFloor(size - glyph.height, 2);
- pixman.Image.composite32(
- .over,
- char,
- glyph.pix,
- pix,
- 0, 0, 0, 0,
- x, y,
- glyph.width, glyph.height,
- );
+ pixman.Image.composite32(.over, char, glyph.pix, pix, 0, 0, 0, 0, x, y, glyph.width, glyph.height);
}
fn formatDatetime(state: *State) ![]const u8 {
diff --git a/src/tags.zig b/src/tags.zig
@@ -80,7 +80,7 @@ pub const Tags = struct {
const payload = try std.fmt.allocPrintZ(
state.allocator,
"{d}",
- .{ @as(u32, 1) << @intCast(u5, index) },
+ .{@as(u32, 1) << @intCast(u5, index)},
);
defer state.allocator.free(payload);
diff --git a/src/wayland.zig b/src/wayland.zig
@@ -116,11 +116,11 @@ pub const Wayland = struct {
}
for (self.outputs.items) |output| {
if (output.surface) |surface| {
- if (
- surface.backgroundSurface == wlSurface or
+ if (surface.backgroundSurface == wlSurface or
surface.tagsSurface == wlSurface or
- surface.clockSurface == wlSurface
- ) {
+ surface.clockSurface == wlSurface or
+ surface.customSurface == wlSurface)
+ {
return surface;
}
}
@@ -281,19 +281,24 @@ pub const Surface = struct {
clockSubsurface: *wl.Subsurface,
clockBuffers: [2]Buffer,
+ customSurface: *wl.Surface,
+ customSubsurface: *wl.Subsurface,
+ customBuffers: [2]Buffer,
+
configured: bool,
width: u16,
height: u16,
pub fn create(output: *Output) !*Surface {
const state = output.state;
+ const wayland = state.wayland;
const self = try state.allocator.create(Surface);
self.output = output;
self.configured = false;
- self.backgroundSurface = try state.wayland.compositor.createSurface();
- self.layerSurface = try state.wayland.layerShell.getLayerSurface(
+ self.backgroundSurface = try wayland.compositor.createSurface();
+ self.layerSurface = try wayland.layerShell.getLayerSurface(
self.backgroundSurface,
output.wlOutput,
.overlay,
@@ -301,20 +306,27 @@ pub const Surface = struct {
);
self.backgroundBuffers = mem.zeroes([2]Buffer);
- self.tagsSurface = try state.wayland.compositor.createSurface();
- self.tagsSubsurface = try state.wayland.subcompositor.getSubsurface(
+ self.tagsSurface = try wayland.compositor.createSurface();
+ self.tagsSubsurface = try wayland.subcompositor.getSubsurface(
self.tagsSurface,
self.backgroundSurface,
);
self.tagsBuffers = mem.zeroes([2]Buffer);
- self.clockSurface = try state.wayland.compositor.createSurface();
- self.clockSubsurface = try state.wayland.subcompositor.getSubsurface(
+ self.clockSurface = try wayland.compositor.createSurface();
+ self.clockSubsurface = try wayland.subcompositor.getSubsurface(
self.clockSurface,
self.backgroundSurface,
);
self.clockBuffers = mem.zeroes([2]Buffer);
+ self.customSurface = try wayland.compositor.createSurface();
+ self.customSubsurface = try wayland.subcompositor.getSubsurface(
+ self.customSurface,
+ self.backgroundSurface,
+ );
+ self.customBuffers = mem.zeroes([2]Buffer);
+
// setup layer surface
self.layerSurface.setSize(0, state.config.height);
self.layerSurface.setAnchor(
@@ -327,9 +339,7 @@ pub const Surface = struct {
// setup subsurfaces
self.tagsSubsurface.setPosition(0, 0);
self.clockSubsurface.setPosition(0, 0);
- // const region = try state.wayland.compositor.createRegion();
- // self.tagsSurface.setInputRegion(region);
- // region.destroy();
+ self.customSubsurface.setPosition(0, 0);
self.tagsSurface.commit();
self.clockSurface.commit();
@@ -356,6 +366,11 @@ pub const Surface = struct {
self.clockBuffers[0].deinit();
self.clockBuffers[1].deinit();
+ self.customSurface.destroy();
+ self.customSubsurface.destroy();
+ self.customBuffers[0].deinit();
+ self.customBuffers[1].deinit();
+
self.output.state.allocator.destroy(self);
}
@@ -378,6 +393,7 @@ pub const Surface = struct {
surface.tagsSurface.commit();
surface.clockSurface.commit();
+ surface.customSurface.commit();
surface.backgroundSurface.commit();
},
.closed => {