From 78955de9598ed578edf533f00fc0b2e107961644 Mon Sep 17 00:00:00 2001 From: Janis Date: Wed, 21 Dec 2022 16:27:17 +0100 Subject: [PATCH] proper output of selected rect --- main.zig | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 159 insertions(+), 14 deletions(-) diff --git a/main.zig b/main.zig index cea64a1..b98223f 100644 --- a/main.zig +++ b/main.zig @@ -274,7 +274,6 @@ const Output = struct { self.output.destroy(); } - fn setSourceU32(c: *Cairo.cairo_t, color: u32) void { Cairo.cairo_set_source_rgba( c, @@ -299,7 +298,7 @@ const Output = struct { fn drawDimensions(self: *Self, c: *Cairo.cairo_t, color: u32, box: *const Box) void { const opts = self.state.getOptions(); - const font_family = if (opts.@"font-family") |ff| ff.ptr else null; + const font_family = opts.@"font-family".ptr; Cairo.cairo_select_font_face(c, font_family, Cairo.CAIRO_FONT_SLANT_NORMAL, @@ -528,7 +527,7 @@ const Seat = struct { pointer: ?struct { pointer: *wl.Pointer, - current_surface_offset: ?Point = null, + current_surface_geom: ?Box = null, stage: SelectionStage = .Edit, selection: SelectionState = SelectionState.None(), } = null, @@ -614,21 +613,21 @@ const Seat = struct { switch (event) { .enter => |enter| { if (self.state.getOutputForSurface(enter.surface.?)) |output| { - self.pointer.?.current_surface_offset = output.logical_geometry.position; + self.pointer.?.current_surface_geom = output.logical_geometry; } - std.debug.print("surface offset: {?}\n", .{self.pointer.?.current_surface_offset}); + std.debug.print("surface geom: {?}\n", .{self.pointer.?.current_surface_geom}); }, .leave => { - self.pointer.?.current_surface_offset = null; + self.pointer.?.current_surface_geom = null; }, .motion => |motion| { const x = motion.surface_x.toInt(); const y = motion.surface_y.toInt(); const xy = Point{.x = x, .y = y,}; - if (self.pointer.?.current_surface_offset) |offset| { - const point = xy.added(offset); + if (self.pointer.?.current_surface_geom) |geom| { + const point = xy.added(geom.position); switch (self.pointer.?.stage) { .Edit => { @@ -676,7 +675,7 @@ const Seat = struct { .updating => |selection| { const box = selection.asBox(); self.pointer.?.selection = .{.post = box}; - return self.calculateRedraws(); + return self.state.finish(box, self.pointer.?.current_surface_geom.?); }, else => {}, } @@ -1116,9 +1115,44 @@ const State = struct { } } - fn finish(self: *Self, box: Box) void { - _ = self; - _ = box; + fn finish(self: *Self, box: Box, surface_geom: Box) void { + self.running = false; + + const format = OutputFormat.fromFormatStr(self.ally, self.getOptions().format) catch return; + var iter = format.iter(); + + const stdout = std.io.getStdOut().writer(); + while (iter.next()) |entry| { + if (entry.piece) |piece| { + _ = stdout.write(piece) catch return; + } + if (entry.arg) |arg| { + switch (arg) { + .X => {stdout.print("{}", .{box.getX(i32)}) catch return;}, + .Y => {stdout.print("{}", .{box.getY(i32)}) catch return;}, + .Width => {stdout.print("{}", .{box.getWidth(u32)}) catch return;}, + .Height => {stdout.print("{}", .{box.getHeight(u32)}) catch return;}, + .XRel => {stdout.print("{}", .{box.getX(i32) - surface_geom.getX(i32)}) catch return;}, + .YRel => {stdout.print("{}", .{box.getY(i32) - surface_geom.getY(i32)}) catch return;}, + .WidthClamped => { + stdout.print( + "{}", + .{@min(box.getWidth(i32), + surface_geom.getRightMost(i32) - box.getX(i32))}, + ) catch return; + }, + .HeightClamped=> { + stdout.print( + "{}", + .{@min(box.getHeight(i32), + surface_geom.getBottomMost(i32) - box.getY(i32))}, + ) catch return; + }, + // TODO: implement label and outputname + } + } + } + _ = stdout.write("\n") catch null; } fn removeOutput(self: *Self, output: *Output) void { @@ -1184,8 +1218,8 @@ const Args = struct { border: u32 = 0x000000FF, selection: u32 = 0x00000000, choice: u32 = 0xFFFFFF40, - format: ?[]const u8 = "%x,%y %wx%h\n", - @"font-family": ?[]const u8 = "sans-serif", + format: []const u8 = "%x,%y %wx%h\n", + @"font-family": [:0]const u8 = "sans-serif", @"border-weight": u32 = 2, @"single-point": bool = false, @"output-boxes": bool = false, @@ -1280,3 +1314,114 @@ pub fn run(ally: std.mem.Allocator) !void { pub fn main() !void { try run(std.heap.c_allocator); } + +const OutputFormat = struct { + const Self = @This(); + + const Arg = enum { + X, + Y, + Width, + Height, + XRel, + YRel, + WidthClamped, + HeightClamped, + // TODO: + // OutputName, + // SelectionName, + + fn fromChar(c: u8) ?Arg { + switch (c) { + 'x' => {return .X;}, + 'y' => {return .Y;}, + 'X' => {return .XRel;}, + 'Y' => {return .YRel;}, + 'w' => {return .Width;}, + 'h' => {return .Height;}, + 'W' => {return .WidthClamped;}, + 'H' => {return .HeightClamped;}, + else => {return null;}, + } + } + }; + + const Entry = struct {piece: ?[]const u8, arg: Arg}; + + list: std.ArrayList(Entry), + last_piece: ?[]const u8, + + const Iterator = struct { + format: Self, + i: usize = 0, + + pub fn next(self: *@This()) ?struct {piece: ?[]const u8, arg: ?Arg} { + const items = self.format.list.items; + if (self.i < items.len) { + const item = &items[self.i]; + self.i += 1; + + return .{.piece = item.piece, .arg = item.arg}; + } else if (self.i == items.len and self.format.last_piece != null) { + self.i += 1; + return .{.piece = self.format.last_piece, .arg = null}; + } else { + return null; + } + } + }; + + fn iter(self: Self) Iterator { + return .{ + .format = self, + }; + } + + fn deinit(self: Self) void { + self.list.deinit(); + } + + /// this does not copy! returned object is only valid as long as 'str' is valid. + fn fromFormatStr(ally: std.mem.Allocator, str: []const u8) !Self { + var window: struct {start: usize, end: usize} = .{.start = 0, .end = 0}; + var pieces = std.ArrayList(Entry).init(ally); + + var i: usize = 0; + while (i < str.len) { + defer i += 1; + const c = str[i]; + + window.end = i; + + if (c == '%') { + if (str.len > i) { + i += 1; + if (Arg.fromChar(str[i])) |arg| { + const piece = if (window.start != window.end) str[window.start..window.end] else null; + window.start = i + 1; + window.end = i + 1; + + std.debug.print("piece: '{?s}', arg: {?}\n", .{piece, arg}); + try pieces.append(.{.piece = piece, .arg = arg}); + } + } + } + } + + const last_piece = if (window.start != window.end) str[window.start..window.end] else null; + std.debug.print("piece: '{?s}'\n", .{last_piece}); + + return Self{ + .list = pieces, + .last_piece = last_piece, + }; + } +}; + +test "format parsing" { + const ally = std.testing.allocator; + const a = try OutputFormat.fromFormatStr(ally, "%x,%y blob %wx%h"); + defer a.deinit(); + const b = try OutputFormat.fromFormatStr(ally, "%t,%y blob %wx%h"); + defer b.deinit(); +}