stevee

My wayland statusbar
git clone git://gtms.dev/stevee
Log | Files | Refs | Submodules | README | LICENSE

commit 4934bf6a9050f492e5ae8133eb0efb160e55835d
parent 27e73da715bc9ace58bef0d1082cc364a8a35064
Author: Andrea Feletto <andrea@andreafeletto.com>
Date:   Mon, 11 Apr 2022 16:11:04 +0200

shrink subsurface buffers

Diffstat:
Asrc/Bar.zig | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Config.zig | 34++++++++++++++++++++++++++++++++++
Msrc/Loop.zig | 5-----
Dsrc/Surface.zig | 146-------------------------------------------------------------------------------
Msrc/Tags.zig | 14+++++++-------
Dsrc/config.zig | 34----------------------------------
Msrc/main.zig | 2+-
Msrc/modules.zig | 1-
Msrc/modules/Alsa.zig | 14+++++++-------
Msrc/modules/Backlight.zig | 10+++++-----
Msrc/modules/Battery.zig | 14+++++++-------
Msrc/render.zig | 214++++++++++++++++++++++++++++++++++---------------------------------------------
Msrc/utils.zig | 16++++++++++++++++
Msrc/wayland.zig | 50++++++++++++++++++++++++++------------------------
14 files changed, 331 insertions(+), 358 deletions(-)

diff --git a/src/Bar.zig b/src/Bar.zig @@ -0,0 +1,135 @@ +const std = @import("std"); +const mem = std.mem; + +const wl = @import("wayland").client.wl; +const zwlr = @import("wayland").client.zwlr; + +const Buffer = @import("Buffer.zig"); +const Monitor = @import("wayland.zig").Monitor; +const render = @import("render.zig"); +const State = @import("main.zig").State; +const Bar = @This(); + +monitor: *Monitor, + +layerSurface: *zwlr.LayerSurfaceV1, +background: struct { + surface: *wl.Surface, + buffer: Buffer, +}, + +tags: Widget, +clock: Widget, +modules: Widget, + +configured: bool, +width: u16, +height: u16, + +pub const Widget = struct { + surface: *wl.Surface, + subsurface: *wl.Subsurface, + buffers: [2]Buffer, + + pub fn init(state: *State, background: *wl.Surface) !Widget { + const globals = &state.wayland.globals; + + const surface = try globals.compositor.createSurface(); + const subsurface = try globals.subcompositor.getSubsurface( + surface, + background, + ); + + return Widget{ + .surface = surface, + .subsurface = subsurface, + .buffers = mem.zeroes([2]Buffer), + }; + } + + pub fn deinit(self: *Widget) void { + self.surface.destroy(); + self.subsurface.destroy(); + self.buffers[0].deinit(); + self.buffers[1].deinit(); + } +}; + +pub fn create(monitor: *Monitor) !*Bar { + const state = monitor.state; + const globals = &state.wayland.globals; + + const self = try state.gpa.create(Bar); + self.monitor = monitor; + self.configured = false; + + self.background.surface = try globals.compositor.createSurface(); + self.layerSurface = try globals.layerShell.getLayerSurface( + self.background.surface, + monitor.output, + .top, + "levee", + ); + self.background.buffer = mem.zeroes(Buffer); + + self.tags = try Widget.init(state, self.background.surface); + self.clock = try Widget.init(state, self.background.surface); + self.modules = try Widget.init(state, self.background.surface); + + // setup layer surface + self.layerSurface.setSize(0, state.config.height); + self.layerSurface.setAnchor( + .{ .top = true, .left = true, .right = true, .bottom = false }, + ); + self.layerSurface.setExclusiveZone(state.config.height); + self.layerSurface.setMargin(0, 0, 0, 0); + self.layerSurface.setListener(*Bar, layerSurfaceListener, self); + + self.tags.surface.commit(); + self.clock.surface.commit(); + self.modules.surface.commit(); + self.background.surface.commit(); + + return self; +} + +pub fn destroy(self: *Bar) void { + self.monitor.bar = null; + + self.background.surface.destroy(); + self.layerSurface.destroy(); + self.background.buffer.deinit(); + + self.tags.deinit(); + self.clock.deinit(); + self.modules.deinit(); + + self.monitor.state.gpa.destroy(self); +} + +fn layerSurfaceListener( + layerSurface: *zwlr.LayerSurfaceV1, + event: zwlr.LayerSurfaceV1.Event, + bar: *Bar, +) void { + switch (event) { + .configure => |data| { + bar.configured = true; + bar.width = @intCast(u16, data.width); + bar.height = @intCast(u16, data.height); + + layerSurface.ackConfigure(data.serial); + + render.renderBackground(bar) catch return; + render.renderTags(bar) catch return; + render.renderClock(bar) catch return; + render.renderModules(bar) catch return; + + bar.tags.surface.commit(); + bar.clock.surface.commit(); + bar.modules.surface.commit(); + bar.background.surface.commit(); + }, + .closed => bar.destroy(), + } +} diff --git a/src/Config.zig b/src/Config.zig @@ -0,0 +1,34 @@ +const fcft = @import("fcft"); +const pixman = @import("pixman"); + +const Config = @This(); + +height: u16, +backgroundColor: pixman.Color, +foregroundColor: pixman.Color, +border: u15, +font: *fcft.Font, +clockFormat: [*:0]const u8, + +pub fn init() !Config { + var font_names = [_][*:0]const u8{"monospace:size=14"}; + + return Config{ + .height = 32, + .backgroundColor = .{ + .red = 0, + .green = 0, + .blue = 0, + .alpha = 0xffff, + }, + .foregroundColor = .{ + .red = 0xffff, + .green = 0xffff, + .blue = 0xffff, + .alpha = 0xffff, + }, + .border = 2, + .font = try fcft.Font.fromName(&font_names, null), + .clockFormat = "%d %b %Y - %R", + }; +} diff --git a/src/Loop.zig b/src/Loop.zig @@ -1,13 +1,8 @@ const std = @import("std"); -const fmt = std.fmt; const mem = std.mem; const os = std.os; -const wl = @import("wayland").client.wl; - -const Module = @import("modules.zig").Module; const State = @import("main.zig").State; -const utils = @import("utils.zig"); const Loop = @This(); state: *State, diff --git a/src/Surface.zig b/src/Surface.zig @@ -1,146 +0,0 @@ -const std = @import("std"); -const mem = std.mem; - -const wl = @import("wayland").client.wl; -const zwlr = @import("wayland").client.zwlr; - -const Buffer = @import("Buffer.zig"); -const Monitor = @import("wayland.zig").Monitor; -const render = @import("render.zig"); -const Surface = @This(); - -monitor: *Monitor, - -backgroundSurface: *wl.Surface, -layerSurface: *zwlr.LayerSurfaceV1, -backgroundBuffers: [2]Buffer, - -tagsSurface: *wl.Surface, -tagsSubsurface: *wl.Subsurface, -tagsBuffers: [2]Buffer, - -clockSurface: *wl.Surface, -clockSubsurface: *wl.Subsurface, -clockBuffers: [2]Buffer, - -modulesSurface: *wl.Surface, -modulesSubsurface: *wl.Subsurface, -modulesBuffers: [2]Buffer, - -configured: bool, -width: u16, -height: u16, - -pub fn create(monitor: *Monitor) !*Surface { - const state = monitor.state; - const globals = &state.wayland.globals; - - const self = try state.gpa.create(Surface); - self.monitor = monitor; - self.configured = false; - - self.backgroundSurface = try globals.compositor.createSurface(); - self.layerSurface = try globals.layerShell.getLayerSurface( - self.backgroundSurface, - monitor.output, - .top, - "levee", - ); - self.backgroundBuffers = mem.zeroes([2]Buffer); - - self.tagsSurface = try globals.compositor.createSurface(); - self.tagsSubsurface = try globals.subcompositor.getSubsurface( - self.tagsSurface, - self.backgroundSurface, - ); - self.tagsBuffers = mem.zeroes([2]Buffer); - - self.clockSurface = try globals.compositor.createSurface(); - self.clockSubsurface = try globals.subcompositor.getSubsurface( - self.clockSurface, - self.backgroundSurface, - ); - self.clockBuffers = mem.zeroes([2]Buffer); - - self.modulesSurface = try globals.compositor.createSurface(); - self.modulesSubsurface = try globals.subcompositor.getSubsurface( - self.modulesSurface, - self.backgroundSurface, - ); - self.modulesBuffers = mem.zeroes([2]Buffer); - - // setup layer surface - self.layerSurface.setSize(0, state.config.height); - self.layerSurface.setAnchor( - .{ .top = true, .left = true, .right = true, .bottom = false }, - ); - self.layerSurface.setExclusiveZone(state.config.height); - self.layerSurface.setMargin(0, 0, 0, 0); - self.layerSurface.setListener(*Surface, layerSurfaceListener, self); - - // setup subsurfaces - self.tagsSubsurface.setPosition(0, 0); - self.clockSubsurface.setPosition(0, 0); - self.modulesSubsurface.setPosition(0, 0); - - self.tagsSurface.commit(); - self.clockSurface.commit(); - self.backgroundSurface.commit(); - - return self; -} - -pub fn destroy(self: *Surface) void { - self.monitor.surface = null; - - self.backgroundSurface.destroy(); - self.layerSurface.destroy(); - self.backgroundBuffers[0].deinit(); - self.backgroundBuffers[1].deinit(); - - self.tagsSurface.destroy(); - self.tagsSubsurface.destroy(); - self.tagsBuffers[0].deinit(); - self.tagsBuffers[1].deinit(); - - self.clockSurface.destroy(); - self.clockSubsurface.destroy(); - self.clockBuffers[0].deinit(); - self.clockBuffers[1].deinit(); - - self.modulesSurface.destroy(); - self.modulesSubsurface.destroy(); - self.modulesBuffers[0].deinit(); - self.modulesBuffers[1].deinit(); - - self.monitor.state.gpa.destroy(self); -} - -fn layerSurfaceListener( - layerSurface: *zwlr.LayerSurfaceV1, - event: zwlr.LayerSurfaceV1.Event, - surface: *Surface, -) void { - switch (event) { - .configure => |data| { - surface.configured = true; - surface.width = @intCast(u16, data.width); - surface.height = @intCast(u16, data.height); - - layerSurface.ackConfigure(data.serial); - - render.renderBackground(surface) catch return; - render.renderTags(surface) catch return; - render.renderClock(surface) catch return; - render.renderModules(surface) catch return; - - surface.tagsSurface.commit(); - surface.clockSurface.commit(); - surface.modulesSurface.commit(); - surface.backgroundSurface.commit(); - }, - .closed => { - surface.destroy(); - }, - } -} diff --git a/src/Tags.zig b/src/Tags.zig @@ -63,11 +63,11 @@ fn outputStatusListener( } }, } - if (tags.monitor.surface) |surface| { - if (surface.configured) { - render.renderTags(surface) catch return; - surface.tagsSurface.commit(); - surface.backgroundSurface.commit(); + if (tags.monitor.bar) |bar| { + if (bar.configured) { + render.renderTags(bar) catch return; + bar.tags.surface.commit(); + bar.background.surface.commit(); } } } @@ -76,8 +76,8 @@ pub fn handleClick(self: *Tags, x: u32, input: *Input) !void { const state = self.monitor.state; const control = state.wayland.globals.control; - if (self.monitor.surface) |surface| { - const index = x / surface.height; + if (self.monitor.bar) |bar| { + const index = x / bar.height; const payload = try std.fmt.allocPrintZ( state.gpa, "{d}", diff --git a/src/config.zig b/src/config.zig @@ -1,34 +0,0 @@ -const fcft = @import("fcft"); -const pixman = @import("pixman"); - -pub const Config = struct { - height: u16, - backgroundColor: pixman.Color, - foregroundColor: pixman.Color, - border: u15, - font: *fcft.Font, - clockFormat: [*:0]const u8, - - pub fn init() !Config { - var font_names = [_][*:0]const u8{"monospace:size=14"}; - - return Config{ - .height = 32, - .backgroundColor = .{ - .red = 0, - .green = 0, - .blue = 0, - .alpha = 0xffff, - }, - .foregroundColor = .{ - .red = 0xffff, - .green = 0xffff, - .blue = 0xffff, - .alpha = 0xffff, - }, - .border = 2, - .font = try fcft.Font.fromName(&font_names, null), - .clockFormat = "%d %b %Y - %R", - }; - } -}; diff --git a/src/main.zig b/src/main.zig @@ -4,7 +4,7 @@ const mem = std.mem; const fcft = @import("fcft"); -const Config = @import("config.zig").Config; +const Config = @import("Config.zig"); const Loop = @import("Loop.zig"); const modules = @import("modules.zig"); const Wayland = @import("wayland.zig").Wayland; diff --git a/src/modules.zig b/src/modules.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const os = std.os; const Event = @import("Loop.zig").Event; diff --git a/src/modules/Alsa.zig b/src/modules/Alsa.zig @@ -101,13 +101,13 @@ fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void { _ = alsa.snd_ctl_read(self.context, event); for (self.state.wayland.monitors.items) |monitor| { - if (monitor.surface) |surface| { - if (surface.configured) { - render.renderClock(surface) catch continue; - render.renderModules(surface) catch continue; - surface.clockSurface.commit(); - surface.modulesSurface.commit(); - surface.backgroundSurface.commit(); + if (monitor.bar) |bar| { + if (bar.configured) { + render.renderClock(bar) catch continue; + render.renderModules(bar) catch continue; + bar.clock.surface.commit(); + bar.modules.surface.commit(); + bar.background.surface.commit(); } } } diff --git a/src/modules/Backlight.zig b/src/modules/Backlight.zig @@ -85,11 +85,11 @@ fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void { _ = self.monitor.receiveDevice() catch return; for (self.state.wayland.monitors.items) |monitor| { - if (monitor.surface) |surface| { - if (surface.configured) { - render.renderModules(surface) catch continue; - surface.modulesSurface.commit(); - surface.backgroundSurface.commit(); + if (monitor.bar) |bar| { + if (bar.configured) { + render.renderModules(bar) catch continue; + bar.modules.surface.commit(); + bar.background.surface.commit(); } } } diff --git a/src/modules/Battery.zig b/src/modules/Battery.zig @@ -93,13 +93,13 @@ fn callbackIn(self_opaque: *anyopaque) error{Terminate}!void { _ = os.read(self.timerFd, &expirations) catch return; for (self.state.wayland.monitors.items) |monitor| { - if (monitor.surface) |surface| { - if (surface.configured) { - render.renderClock(surface) catch continue; - render.renderModules(surface) catch continue; - surface.clockSurface.commit(); - surface.modulesSurface.commit(); - surface.backgroundSurface.commit(); + if (monitor.bar) |bar| { + if (bar.configured) { + render.renderClock(bar) catch continue; + render.renderModules(bar) catch continue; + bar.clock.surface.commit(); + bar.modules.surface.commit(); + bar.background.surface.commit(); } } } diff --git a/src/render.zig b/src/render.zig @@ -7,136 +7,114 @@ const time = @cImport(@cInclude("time.h")); const Buffer = @import("Buffer.zig"); const State = @import("main.zig").State; -const Surface = @import("Surface.zig"); +const Bar = @import("Bar.zig"); const Tag = @import("Tags.zig").Tag; +const utils = @import("utils.zig"); -pub const RenderFn = fn (*Surface) anyerror!void; +pub const RenderFn = fn (*Bar) anyerror!void; -pub fn renderBackground(surface: *Surface) !void { - const state = surface.monitor.state; - const wlSurface = surface.backgroundSurface; +pub fn renderBackground(bar: *Bar) !void { + const state = bar.monitor.state; + const wlSurface = bar.background.surface; - const buffer = try Buffer.nextBuffer( - &surface.backgroundBuffers, - state.wayland.globals.shm, - surface.width, - surface.height, - ); - buffer.busy = true; + const buffer = &bar.background.buffer; + if (buffer.width == bar.width and buffer.height == bar.height) return; + try buffer.init(state.wayland.globals.shm, bar.width, bar.height); const area = [_]pixman.Rectangle16{ - .{ .x = 0, .y = 0, .width = surface.width, .height = surface.height }, + .{ .x = 0, .y = 0, .width = bar.width, .height = bar.height }, }; const color = &state.config.backgroundColor; _ = pixman.Image.fillRectangles(.src, buffer.pix.?, color, 1, &area); - wlSurface.setBufferScale(surface.monitor.scale); - wlSurface.damageBuffer(0, 0, surface.width, surface.height); + wlSurface.setBufferScale(bar.monitor.scale); + wlSurface.damageBuffer(0, 0, bar.width, bar.height); wlSurface.attach(buffer.buffer, 0, 0); } -pub fn renderTags(surface: *Surface) !void { - const state = surface.monitor.state; - const wlSurface = surface.tagsSurface; - const tags = surface.monitor.tags.tags; +pub fn renderTags(bar: *Bar) !void { + const state = bar.monitor.state; + const surface = bar.tags.surface; + const tags = bar.monitor.tags.tags; + const width = bar.height * 9; const buffer = try Buffer.nextBuffer( - &surface.tagsBuffers, - surface.monitor.state.wayland.globals.shm, - surface.width, - surface.height, + &bar.tags.buffers, + bar.monitor.state.wayland.globals.shm, + width, + bar.height, ); buffer.busy = true; for (tags) |*tag, i| { - const offset = @intCast(i16, surface.height * i); - try renderTag(buffer.pix.?, tag, surface.height, offset, state); + const offset = @intCast(i16, bar.height * i); + try renderTag(buffer.pix.?, tag, bar.height, offset, state); } - wlSurface.setBufferScale(surface.monitor.scale); - wlSurface.damageBuffer(0, 0, surface.width, surface.height); - wlSurface.attach(buffer.buffer, 0, 0); + surface.setBufferScale(bar.monitor.scale); + surface.damageBuffer(0, 0, width, bar.height); + surface.attach(buffer.buffer, 0, 0); } -pub fn renderClock(surface: *Surface) !void { - const state = surface.monitor.state; - const wlSurface = surface.clockSurface; - - const buffer = try Buffer.nextBuffer( - &surface.clockBuffers, - surface.monitor.state.wayland.globals.shm, - surface.width, - surface.height, - ); - buffer.busy = true; +pub fn renderClock(bar: *Bar) !void { + const state = bar.monitor.state; + const surface = bar.clock.surface; + const shm = state.wayland.globals.shm; - // 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); - - // get formatted datetime + // utf8 datetime const str = try formatDatetime(state); defer state.gpa.free(str); - - // ut8 encoding - const utf8 = try std.unicode.Utf8View.init(str); - var utf8_iter = utf8.iterator(); - - var runes = try state.gpa.alloc(u32, str.len); + const runes = try utils.toUtf8(state.gpa, str); defer state.gpa.free(runes); - var i: usize = 0; - while (utf8_iter.nextCodepoint()) |rune| : (i += 1) { - runes[i] = rune; - } - runes = state.gpa.resize(runes, i).?; - - const run = try fcft.TextRun.rasterizeUtf32( - state.config.font, - runes, - .default, - ); + // resterize + const font = state.config.font; + const run = try fcft.TextRun.rasterizeUtf32(font, runes, .default); defer run.destroy(); - i = 0; - var text_width: u32 = 0; + // compute total width + var i: usize = 0; + var width: u16 = 0; while (i < run.count) : (i += 1) { - text_width += @intCast(u32, run.glyphs[i].advance.x); + width += @intCast(u16, run.glyphs[i].advance.x); } - const font_height = @intCast(u32, state.config.font.height); - var x_offset = @intCast(i32, @divFloor(surface.width - text_width, 2)); - var y_offset = @intCast(i32, @divFloor(surface.height - font_height, 2)); + // set subsurface offset + const font_height = @intCast(u32, font.height); + const x_offset = @intCast(i32, (bar.width - width) / 2); + const y_offset = @intCast(i32, (bar.height - font_height) / 2); + bar.clock.subsurface.setPosition(x_offset, y_offset); + const buffers = &bar.clock.buffers; + const buffer = try Buffer.nextBuffer(buffers, shm, width, bar.height); + buffer.busy = true; + + const bg_area = [_]pixman.Rectangle16{ + .{ .x = 0, .y = 0, .width = width, .height = bar.height }, + }; + const bg_color = mem.zeroes(pixman.Color); + _ = pixman.Image.fillRectangles(.src, buffer.pix.?, &bg_color, 1, &bg_area); + + var x: i32 = 0; 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); + x += @intCast(i32, glyph.x); + const y = 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; + x += glyph.advance.x - @intCast(i32, glyph.x); } - wlSurface.setBufferScale(surface.monitor.scale); - wlSurface.damageBuffer(0, 0, surface.width, surface.height); - wlSurface.attach(buffer.buffer, 0, 0); + surface.setBufferScale(bar.monitor.scale); + surface.damageBuffer(0, 0, width, bar.height); + surface.attach(buffer.buffer, 0, 0); } -pub fn renderModules(surface: *Surface) !void { - const state = surface.monitor.state; - const wlSurface = surface.modulesSurface; - - const buffer = try Buffer.nextBuffer( - &surface.modulesBuffers, - surface.monitor.state.wayland.globals.shm, - surface.width, - surface.height, - ); - buffer.busy = true; +pub fn renderModules(bar: *Bar) !void { + const state = bar.monitor.state; + const surface = bar.modules.surface; + const shm = state.wayland.globals.shm; // compose string var string = std.ArrayList(u8).init(state.gpa); @@ -149,57 +127,51 @@ pub fn renderModules(surface: *Surface) !void { } // ut8 encoding - const utf8 = try std.unicode.Utf8View.init(string.items); - var utf8_iter = utf8.iterator(); - - var runes = try state.gpa.alloc(u32, string.items.len); + const runes = try utils.toUtf8(state.gpa, string.items); defer state.gpa.free(runes); + // rasterize + const font = state.config.font; + const run = try fcft.TextRun.rasterizeUtf32(font, runes, .default); + defer run.destroy(); + + // compute total width var i: usize = 0; - while (utf8_iter.nextCodepoint()) |rune| : (i += 1) { - runes[i] = rune; + var width: u16 = 0; + while (i < run.count) : (i += 1) { + width += @intCast(u16, run.glyphs[i].advance.x); } - runes = state.gpa.resize(runes, i).?; - // clear the buffer + // set subsurface offset + const font_height = @intCast(u32, state.config.font.height); + var x_offset = @intCast(i32, bar.width - width); + var y_offset = @intCast(i32, @divFloor(bar.height - font_height, 2)); + bar.modules.subsurface.setPosition(x_offset, y_offset); + + const buffers = &bar.modules.buffers; + const buffer = try Buffer.nextBuffer(buffers, shm, width, bar.height); + buffer.busy = true; + const bg_area = [_]pixman.Rectangle16{ - .{ .x = 0, .y = 0, .width = surface.width, .height = surface.height }, + .{ .x = 0, .y = 0, .width = width, .height = bar.height }, }; const bg_color = mem.zeroes(pixman.Color); _ = pixman.Image.fillRectangles(.src, buffer.pix.?, &bg_color, 1, &bg_area); - // compute offsets - const run = try fcft.TextRun.rasterizeUtf32( - 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); - } - - 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 + var x: i32 = 0; 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); + x += @intCast(i32, glyph.x); + const y = 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; + x += glyph.advance.x - @intCast(i32, glyph.x); } - wlSurface.setBufferScale(surface.monitor.scale); - wlSurface.damageBuffer(0, 0, surface.width, surface.height); - wlSurface.attach(buffer.buffer, 0, 0); + surface.setBufferScale(bar.monitor.scale); + surface.damageBuffer(0, 0, width, bar.height); + surface.attach(buffer.buffer, 0, 0); } fn renderTag( diff --git a/src/utils.zig b/src/utils.zig @@ -1,5 +1,7 @@ const std = @import("std"); +const mem = std.mem; const meta = std.meta; +const unicode = std.unicode; pub fn cast(comptime to: type) fn (*anyopaque) *to { return (struct { @@ -13,3 +15,17 @@ pub fn Mask(comptime container: type) type { const len = meta.fields(container).len; return [len]bool; } + +pub fn toUtf8(gpa: mem.Allocator, bytes: []const u8) ![]u32 { + const utf8 = try unicode.Utf8View.init(bytes); + var iter = utf8.iterator(); + + var runes = try gpa.alloc(u32, bytes.len); + var i: usize = 0; + while (iter.nextCodepoint()) |rune| : (i += 1) { + runes[i] = rune; + } + + runes = gpa.resize(runes, i).?; + return runes; +} diff --git a/src/wayland.zig b/src/wayland.zig @@ -13,7 +13,7 @@ const Buffer = @import("Buffer.zig"); const Event = @import("Loop.zig").Event; const render = @import("render.zig"); const State = @import("main.zig").State; -const Surface = @import("Surface.zig"); +const Bar = @import("Bar.zig"); const Tags = @import("Tags.zig"); const utils = @import("utils.zig"); @@ -141,7 +141,9 @@ pub const Wayland = struct { } else if (strcmp(iface, zwlr.LayerShellV1.getInterface().name) == 0) { const global = try registry.bind(name, zwlr.LayerShellV1, 1); self.setGlobal(global); - } else if (strcmp(iface, zriver.StatusManagerV1.getInterface().name) == 0) { + } else if ( + strcmp(iface, zriver.StatusManagerV1.getInterface().name) == 0 + ) { const global = try registry.bind(name, zriver.StatusManagerV1, 1); self.setGlobal(global); } else if (strcmp(iface, zriver.ControlV1.getInterface().name) == 0) { @@ -166,18 +168,18 @@ pub const Wayland = struct { } } - pub fn findSurface(self: *Wayland, wlSurface: ?*wl.Surface) ?*Surface { + pub fn findBar(self: *Wayland, wlSurface: ?*wl.Surface) ?*Bar { if (wlSurface == null) { return null; } for (self.monitors.items) |monitor| { - if (monitor.surface) |surface| { - if (surface.backgroundSurface == wlSurface or - surface.tagsSurface == wlSurface or - surface.clockSurface == wlSurface or - surface.modulesSurface == wlSurface) + if (monitor.bar) |bar| { + if (bar.background.surface == wlSurface or + bar.tags.surface == wlSurface or + bar.clock.surface == wlSurface or + bar.modules.surface == wlSurface) { - return surface; + return bar; } } } @@ -191,7 +193,7 @@ pub const Monitor = struct { globalName: u32, scale: i32, - surface: ?*Surface, + bar: ?*Bar, tags: *Tags, pub fn create(state: *State, registry: *wl.Registry, name: u32) !*Monitor { @@ -201,7 +203,7 @@ pub const Monitor = struct { self.globalName = name; self.scale = 1; - self.surface = null; + self.bar = null; self.tags = try Tags.create(state, self); self.output.setListener(*Monitor, listener, self); @@ -209,8 +211,8 @@ pub const Monitor = struct { } pub fn destroy(self: *Monitor) void { - if (self.surface) |surface| { - surface.destroy(); + if (self.bar) |bar| { + bar.destroy(); } self.tags.destroy(); self.state.gpa.destroy(self); @@ -226,8 +228,8 @@ pub const Monitor = struct { .name => {}, .description => {}, .done => { - if (monitor.surface) |_| {} else { - monitor.surface = Surface.create(monitor) catch return; + if (monitor.bar) |_| {} else { + monitor.bar = Bar.create(monitor) catch return; } }, } @@ -243,7 +245,7 @@ pub const Input = struct { wlPointer: ?*wl.Pointer, x: i32, y: i32, - surface: ?*Surface, + bar: ?*Bar, }, pub fn create(state: *State, registry: *wl.Registry, name: u32) !*Input { @@ -253,7 +255,7 @@ pub const Input = struct { self.globalName = name; self.pointer.wlPointer = null; - self.pointer.surface = null; + self.pointer.bar = null; self.seat.setListener(*Input, listener, self); return self; @@ -296,11 +298,11 @@ pub const Input = struct { .enter => |data| { input.pointer.x = data.surface_x.toInt(); input.pointer.y = data.surface_y.toInt(); - const surface = input.state.wayland.findSurface(data.surface); - input.pointer.surface = surface; + const bar = input.state.wayland.findBar(data.surface); + input.pointer.bar = bar; }, .leave => |_| { - input.pointer.surface = null; + input.pointer.bar = null; }, .motion => |data| { input.pointer.x = data.surface_x.toInt(); @@ -308,12 +310,12 @@ pub const Input = struct { }, .button => |data| { if (data.state != .pressed) return; - if (input.pointer.surface) |surface| { - if (!surface.configured) return; + if (input.pointer.bar) |bar| { + if (!bar.configured) return; const x = @intCast(u32, input.pointer.x); - if (x < surface.height * 9) { - surface.monitor.tags.handleClick(x, input) catch return; + if (x < bar.height * 9) { + bar.monitor.tags.handleClick(x, input) catch return; } } },