2zw
Owner: IIIlllIIIllI URL: git@git.0x00nyx.xyz:seb/2zw.git
src/draw.zig
// MIT License
// Copyright (c) 2025 Sebastian <sebastian.michalk@pm.me>
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
const std = @import("std");
const C = @import("c.zig");
pub const Drw = struct {
alloc: std.mem.Allocator,
dpy: *C.Display,
scr: c_int,
vis: *C.Visual,
cmap: C.Colormap,
gc: C.GC,
font: *C.XftFont,
ascent: c_int,
descent: c_int,
lh: c_int,
pub fn init(
alloc: std.mem.Allocator,
dpy: *C.Display,
scr: c_int,
font_name: [*:0]const u8,
) !Drw {
const font = loadfont(dpy, scr, font_name) orelse
return error.FontUnavailable;
const root = C.RootWindow(dpy, scr);
const gc_opt = C.XCreateGC(dpy, root, 0, null);
if (gc_opt == null) {
C.XftFontClose(dpy, font);
return error.CreateGcFailed;
}
const gc = gc_opt.?;
const vis = C.XDefaultVisual(dpy, scr);
const cmap = C.XDefaultColormap(dpy, scr);
return Drw{
.alloc = alloc,
.dpy = dpy,
.scr = scr,
.vis = vis,
.cmap = cmap,
.gc = gc,
.font = font,
.ascent = font.*.ascent,
.descent = font.*.descent,
.lh = font.*.ascent + font.*.descent,
};
}
fn loadfont(
dpy: *C.Display,
scr: c_int,
preferred: [*:0]const u8,
) ?*C.XftFont {
const candidates = [_][*:0]const u8{
preferred,
"monospace:size=10",
"fixed",
};
for (candidates) |name| {
if (name[0] == 0) continue;
const font_ptr = C.XftFontOpenName(dpy, scr, name);
if (font_ptr != null) {
if (name != preferred) {
std.log.warn("bar font fallback to {s}", .{name});
}
return font_ptr;
}
}
return null;
}
pub fn deinit(self: *Drw) void {
C.XftFontClose(self.dpy, self.font);
_ = C.XFreeGC(self.dpy, self.gc);
}
pub fn alloccol(self: *Drw, rgb: u32) !C.ulong {
var color: C.XColor = undefined;
color.pixel = 0;
color.red = @intCast(((rgb >> 16) & 0xff) * 257);
color.green = @intCast(((rgb >> 8) & 0xff) * 257);
color.blue = @intCast((rgb & 0xff) * 257);
color.flags = @intCast(C.DoRed | C.DoGreen | C.DoBlue);
color.pad = 0;
if (C.XAllocColor(self.dpy, self.cmap, &color) == 0) {
return error.ColorAllocationFailed;
}
return color.pixel;
}
pub fn allocxftcol(self: *Drw, rgb: u32) !C.XftColor {
const r: u16 = @intCast(((rgb >> 16) & 0xff) * 257);
const g: u16 = @intCast(((rgb >> 8) & 0xff) * 257);
const b: u16 = @intCast((rgb & 0xff) * 257);
var xft_color: C.XftColor = undefined;
var render_color: C.XRenderColor = undefined;
render_color.red = r;
render_color.green = g;
render_color.blue = b;
render_color.alpha = 0xffff;
if (C.XftColorAllocValue(
self.dpy,
self.vis,
self.cmap,
&render_color,
&xft_color,
) == 0) {
return error.ColorAllocationFailed;
}
return xft_color;
}
pub fn rect(
self: *Drw,
draw: C.Drawable,
col: C.ulong,
x: c_int,
y: c_int,
w: c_uint,
h: c_uint,
) void {
_ = C.XSetForeground(self.dpy, self.gc, col);
_ = C.XFillRectangle(self.dpy, draw, self.gc, x, y, w, h);
}
pub fn text(
self: *Drw,
_: C.Drawable,
xft: *C.XftDraw,
col: *C.XftColor,
x: c_int,
y: c_int,
txt: []const u8,
) void {
if (txt.len == 0) return;
C.XftDrawStringUtf8(
xft,
col,
self.font,
x,
y,
@ptrCast(txt.ptr),
@intCast(txt.len),
);
}
pub fn textw(self: *Drw, txt: []const u8) c_int {
if (txt.len == 0) return 0;
var extents: C.XGlyphInfo = undefined;
C.XftTextExtentsUtf8(
self.dpy,
self.font,
@ptrCast(txt.ptr),
@intCast(txt.len),
&extents,
);
return @intCast(extents.xOff);
}
};