stevee

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

Tags.zig (2496B)


      1 const std = @import("std");
      2 
      3 const zriver = @import("wayland").client.zriver;
      4 
      5 const Monitor = @import("Monitor.zig");
      6 const render = @import("render.zig");
      7 const Input = @import("Input.zig");
      8 const Tags = @This();
      9 
     10 const state = &@import("root").state;
     11 
     12 monitor: *Monitor,
     13 output_status: *zriver.OutputStatusV1,
     14 tags: [5]Tag,
     15 
     16 pub const Tag = struct {
     17     label: u8,
     18     focused: bool = false,
     19     occupied: bool = false,
     20 };
     21 
     22 pub fn create(monitor: *Monitor) !*Tags {
     23     const self = try state.gpa.create(Tags);
     24     const manager = state.wayland.status_manager.?;
     25 
     26     self.monitor = monitor;
     27     self.output_status = try manager.getRiverOutputStatus(monitor.output);
     28     for (&self.tags, 0..) |*tag, i| {
     29         tag.label = '1' + @as(u8, @intCast(i));
     30     }
     31 
     32     self.output_status.setListener(*Tags, outputStatusListener, self);
     33     return self;
     34 }
     35 
     36 pub fn destroy(self: *Tags) void {
     37     self.output_status.destroy();
     38     state.gpa.destroy(self);
     39 }
     40 
     41 fn outputStatusListener(
     42     _: *zriver.OutputStatusV1,
     43     event: zriver.OutputStatusV1.Event,
     44     tags: *Tags,
     45 ) void {
     46     switch (event) {
     47         .focused_tags => |data| {
     48             for (&tags.tags, 0..) |*tag, i| {
     49                 const mask = @as(u32, 1) << @as(u5, @intCast(i));
     50                 tag.focused = data.tags & mask != 0;
     51             }
     52         },
     53         .view_tags => |data| {
     54             for (&tags.tags) |*tag| {
     55                 tag.occupied = false;
     56             }
     57             for (data.tags.slice(u32)) |view| {
     58                 for (&tags.tags, 0..) |*tag, i| {
     59                     const mask = @as(u32, 1) << @as(u5, @intCast(i));
     60                     if (view & mask != 0) tag.occupied = true;
     61                 }
     62             }
     63         },
     64     }
     65     if (tags.monitor.bar) |bar| {
     66         if (bar.configured) {
     67             render.renderTags(bar) catch return;
     68             bar.tags.surface.commit();
     69             bar.background.surface.commit();
     70         }
     71     }
     72 }
     73 
     74 pub fn handleClick(self: *Tags, x: u32, input: *Input) !void {
     75     const control = state.wayland.control.?;
     76 
     77     if (self.monitor.bar) |bar| {
     78         const index = x / bar.height;
     79         const payload = try std.fmt.allocPrintZ(
     80             state.gpa,
     81             "{d}",
     82             .{@as(u32, 1) << @as(u5, @intCast(index))},
     83         );
     84         defer state.gpa.free(payload);
     85 
     86         control.addArgument("set-focused-tags");
     87         control.addArgument(payload);
     88         const callback = try control.runCommand(input.seat);
     89         _ = callback;
     90     }
     91 }