rivertile: create default layout generator
This commit is contained in:
		@ -68,6 +68,13 @@ pub fn build(b: *std.build.Builder) !void {
 | 
				
			|||||||
        riverctl.install();
 | 
					        riverctl.install();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const rivertile = b.addExecutable("rivertile", "rivertile/main.zig");
 | 
				
			||||||
 | 
					        rivertile.setTarget(target);
 | 
				
			||||||
 | 
					        rivertile.setBuildMode(mode);
 | 
				
			||||||
 | 
					        rivertile.install();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (man_pages) {
 | 
					    if (man_pages) {
 | 
				
			||||||
        const scdoc_step = ScdocStep.create(b);
 | 
					        const scdoc_step = ScdocStep.create(b);
 | 
				
			||||||
        try scdoc_step.install();
 | 
					        try scdoc_step.install();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										128
									
								
								rivertile/main.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								rivertile/main.zig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					// This file is part of river, a dynamic tiling wayland compositor.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright 2020 Isaac Freund
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std = @import("std");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Orientation = enum {
 | 
				
			||||||
 | 
					    left,
 | 
				
			||||||
 | 
					    right,
 | 
				
			||||||
 | 
					    top,
 | 
				
			||||||
 | 
					    bottom,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// This is an implementation of the  default "tiled" layout of dwm and the
 | 
				
			||||||
 | 
					/// 3 other orientations thereof. This code is written with the left
 | 
				
			||||||
 | 
					/// orientation in mind and then the input/output values are adjusted to apply
 | 
				
			||||||
 | 
					/// the necessary transformations to derive the other 3.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// With 4 views and one master, the left layout looks something like this:
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// +-----------------------+------------+
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       +------------+
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       +------------+
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// |                       |            |
 | 
				
			||||||
 | 
					/// +-----------------------+------------+
 | 
				
			||||||
 | 
					pub fn main() !void {
 | 
				
			||||||
 | 
					    // first arg must be left, right, top, or bottom
 | 
				
			||||||
 | 
					    const master_location = std.meta.stringToEnum(Orientation, std.mem.spanZ(std.os.argv[1])).?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // the other 5 are passed by river and described in river-layouts(7)
 | 
				
			||||||
 | 
					    const num_views = try std.fmt.parseInt(u32, std.mem.spanZ(std.os.argv[2]), 10);
 | 
				
			||||||
 | 
					    const master_count = try std.fmt.parseInt(u32, std.mem.spanZ(std.os.argv[3]), 10);
 | 
				
			||||||
 | 
					    const master_factor = try std.fmt.parseFloat(f64, std.mem.spanZ(std.os.argv[4]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const width_arg: u32 = switch (master_location) {
 | 
				
			||||||
 | 
					        .left, .right => 5,
 | 
				
			||||||
 | 
					        .top, .bottom => 6,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    const height_arg: u32 = if (width_arg == 5) 6 else 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const output_width = try std.fmt.parseInt(u32, std.mem.spanZ(std.os.argv[width_arg]), 10);
 | 
				
			||||||
 | 
					    const output_height = try std.fmt.parseInt(u32, std.mem.spanZ(std.os.argv[height_arg]), 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const secondary_count = num_views - master_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // to make things pixel-perfect, we make the first master and first secondary
 | 
				
			||||||
 | 
					    // view slightly larger if the height is not evenly divisible
 | 
				
			||||||
 | 
					    var master_width: u32 = undefined;
 | 
				
			||||||
 | 
					    var master_height: u32 = undefined;
 | 
				
			||||||
 | 
					    var master_height_rem: u32 = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var secondary_width: u32 = undefined;
 | 
				
			||||||
 | 
					    var secondary_height: u32 = undefined;
 | 
				
			||||||
 | 
					    var secondary_height_rem: u32 = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (master_count > 0 and secondary_count > 0) {
 | 
				
			||||||
 | 
					        master_width = @floatToInt(u32, master_factor * @intToFloat(f64, output_width));
 | 
				
			||||||
 | 
					        master_height = output_height / master_count;
 | 
				
			||||||
 | 
					        master_height_rem = output_height % master_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        secondary_width = output_width - master_width;
 | 
				
			||||||
 | 
					        secondary_height = output_height / secondary_count;
 | 
				
			||||||
 | 
					        secondary_height_rem = output_height % secondary_count;
 | 
				
			||||||
 | 
					    } else if (master_count > 0) {
 | 
				
			||||||
 | 
					        master_width = output_width;
 | 
				
			||||||
 | 
					        master_height = output_height / master_count;
 | 
				
			||||||
 | 
					        master_height_rem = output_height % master_count;
 | 
				
			||||||
 | 
					    } else if (secondary_width > 0) {
 | 
				
			||||||
 | 
					        master_width = 0;
 | 
				
			||||||
 | 
					        secondary_width = output_width;
 | 
				
			||||||
 | 
					        secondary_height = output_height / secondary_count;
 | 
				
			||||||
 | 
					        secondary_height_rem = output_height % secondary_count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Buffering the output makes things faster
 | 
				
			||||||
 | 
					    var stdout_buf = std.io.bufferedOutStream(std.io.getStdOut().outStream());
 | 
				
			||||||
 | 
					    const stdout = stdout_buf.outStream();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var i: u32 = 0;
 | 
				
			||||||
 | 
					    while (i < num_views) : (i += 1) {
 | 
				
			||||||
 | 
					        var x: u32 = undefined;
 | 
				
			||||||
 | 
					        var y: u32 = undefined;
 | 
				
			||||||
 | 
					        var width: u32 = undefined;
 | 
				
			||||||
 | 
					        var height: u32 = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (i < master_count) {
 | 
				
			||||||
 | 
					            x = 0;
 | 
				
			||||||
 | 
					            y = i * master_height + if (i > 0) master_height_rem else 0;
 | 
				
			||||||
 | 
					            width = master_width;
 | 
				
			||||||
 | 
					            height = master_height + if (i == 0) master_height_rem else 0;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            x = master_width;
 | 
				
			||||||
 | 
					            y = (i - master_count) * secondary_height + if (i > master_count) secondary_height_rem else 0;
 | 
				
			||||||
 | 
					            width = secondary_width;
 | 
				
			||||||
 | 
					            height = secondary_height + if (i == master_count) secondary_height_rem else 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (master_location) {
 | 
				
			||||||
 | 
					            .left => try stdout.print("{} {} {} {}\n", .{ x, y, width, height }),
 | 
				
			||||||
 | 
					            .right => try stdout.print("{} {} {} {}\n", .{ output_width - x - width, y, width, height }),
 | 
				
			||||||
 | 
					            .top => try stdout.print("{} {} {} {}\n", .{ y, x, height, width }),
 | 
				
			||||||
 | 
					            .bottom => try stdout.print("{} {} {} {}\n", .{ y, output_width - x - width, height, width }),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try stdout_buf.flush();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user