Skip to content

Commit

Permalink
chore: Remove useless comments that serve no purpose
Browse files Browse the repository at this point in the history
* The code should mostly explain itself. When you're having to write
  down your intent you loose the point of having the code be "readable".

Signed-off-by: Shinyzenith <[email protected]>
  • Loading branch information
Shinyzenith committed Oct 29, 2023
1 parent c81dc40 commit d475aee
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 65 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ The entire project is licensed as BSD-2 "Simplified" unless stated otherwise in

## Aim

I want to learn how to write wlroots compositors with this project and keep everything commented to a great extent for others to learn from.
The wlroots ecosystem is hard to initially get into as per my experience and I want to change that via NextWM.
I want to learn how to write wlroots compositors with this project.

## Why multiple implementations of Nextctl?

Expand Down
48 changes: 0 additions & 48 deletions next/Server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -94,79 +94,57 @@ request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate),
pub fn init(self: *Self) !void {
logInfo();

// Creating the server itself.
self.wl_server = try wl.Server.create();
errdefer self.wl_server.destroy();

// Incorporate signal handling into the wayland event loop.
self.wl_event_loop = self.wl_server.getEventLoop();
self.sigabrt_cb = try self.wl_event_loop.addSignal(*wl.Server, std.os.SIG.ABRT, terminateCb, self.wl_server);
self.sigint_cb = try self.wl_event_loop.addSignal(*wl.Server, std.os.SIG.INT, terminateCb, self.wl_server);
self.sigquit_cb = try self.wl_event_loop.addSignal(*wl.Server, std.os.SIG.QUIT, terminateCb, self.wl_server);
self.sigterm_cb = try self.wl_event_loop.addSignal(*wl.Server, std.os.SIG.TERM, terminateCb, self.wl_server);

// Determine the backend based on the current environment to render with such as opening an X11 window if an X11 server is running.
// NOTE: This frees itself when the server is destroyed.
self.wlr_backend = try wlr.Backend.autocreate(self.wl_server);

// Created when no ouputs are available.
// NOTE: This frees itself when server is destroyed.
self.wlr_headless_backend = try wlr.Backend.createHeadless(self.wl_server);

// Creating the renderer.
self.wlr_renderer = try wlr.Renderer.autocreate(self.wlr_backend);
errdefer self.wlr_renderer.destroy();

// Autocreate an allocator. An allocator acts as a bridge between the renderer and the backend allowing us to render to the screen by handling buffer creation.
self.wlr_allocator = try wlr.Allocator.autocreate(self.wlr_backend, self.wlr_renderer);
errdefer self.wlr_allocator.destroy();

// Create the compositor from the server and renderer.
self.wlr_compositor = try wlr.Compositor.create(self.wl_server, self.wlr_renderer);
_ = try wlr.Subcompositor.create(self.wl_server);

//NOTE: This has to be initialized as one of the first wayland globals inorder to not crash on middle-button paste in gtk3...ugh.
_ = try wlr.PrimarySelectionDeviceManagerV1.create(self.wl_server);

// Create foreign toplevel manager
self.wlr_foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(self.wl_server);

// Creating a scene graph. This handles the servers rendering and damage tracking.
self.wlr_scene = try wlr.Scene.create();

// Create an output layout to work with the physical arrangement of screens.
try self.output_layout.init();

self.wlr_output_manager = try wlr.OutputManagerV1.create(self.wl_server);
_ = try wlr.XdgOutputManagerV1.create(self.wl_server, self.output_layout.wlr_output_layout);

// Create a wlr cursor object which is a wlroots utility to track the cursor on the screen.
self.wlr_cursor = try wlr.Cursor.create();
errdefer self.wlr_cursor.destroy();

// Create xdg_activation_v1
self.wlr_xdg_activation_v1 = try wlr.XdgActivationV1.create(self.wl_server);

// Create a Xcursor manager which loads up xcursor themes on all scale factors. We pass null for theme name and 24 for the cursor size.
self.wlr_xcursor_manager = try wlr.XcursorManager.create(null, default_cursor_size);
errdefer self.wlr_xcursor_manager.destroy();

// Load cursors at scale factor 1.
try self.wlr_xcursor_manager.load(1);

// Creating a xdg_shell which is a wayland protocol for application windows.
self.wlr_xdg_shell = try wlr.XdgShell.create(self.wl_server, 5);

// Creating a layer shell which is a wlroots protocol for layered textres
// such as wallpapers and bars which are drawn *over* other windows.
self.wlr_layer_shell = try wlr.LayerShellV1.create(self.wl_server);

// Creating the OutputPowerV1 protocol manager. This protocol is used by
// tools such as wayout (https://github.com/waycrate/wayout) which manage output states
// (on / off).
self.wlr_power_manager = try wlr.OutputPowerManagerV1.create(self.wl_server);

// Creating the seat.
try self.seat.init();

// Creating toplevel layers:
Expand All @@ -179,23 +157,16 @@ pub fn init(self: *Self) !void {
self.layer_tile = try self.wlr_scene.tree.createSceneTree();
self.layer_top = try self.wlr_scene.tree.createSceneTree();

// Initializing Xwayland.
if (build_options.xwayland) {
self.wlr_xwayland = try wlr.Xwayland.create(self.wl_server, self.wlr_compositor, build_options.xwayland_lazy);
self.wlr_xwayland.setSeat(self.seat.wlr_seat);
}

// Initialize wl_shm, linux-dmabuf and other buffer factory protocols.
try self.wlr_renderer.initServer(self.wl_server);

// Attach the output layout to the scene graph so we get automatic damage tracking.
try self.wlr_scene.attachOutputLayout(self.output_layout.wlr_output_layout);

// Attach the cursor to the output layout.
self.wlr_cursor.attachOutputLayout(self.output_layout.wlr_output_layout);

// NOTE: These all free themselves when wlr_server is destroy.
// Create the data device manager from the server, this generally handles the input events such as keyboard, mouse, touch etc.
_ = try wlr.DataControlManagerV1.create(self.wl_server);
_ = try wlr.DataDeviceManager.create(self.wl_server);
_ = try wlr.ExportDmabufManagerV1.create(self.wl_server);
Expand All @@ -209,42 +180,31 @@ pub fn init(self: *Self) !void {
try self.input_manager.init();
self.config = Config.init();

// Assign the new output callback to said event.
//
// zig only intializes structs with default value when using .{} notation. Since were not using that, we call `.setNotify`. In other instances
// we use `.init` on the listener declaration directly.
self.new_output.setNotify(newOutput);
self.wlr_backend.events.new_output.add(&self.new_output);

// Add a callback for when new surfaces are created.
self.new_xdg_surface.setNotify(newXdgSurface);
self.wlr_xdg_shell.events.new_surface.add(&self.new_xdg_surface);

// Add a callback for when clients want to set output power mode.
self.set_mode.setNotify(setMode);
self.wlr_power_manager.events.set_mode.add(&self.set_mode);

// Add a callback for when a new layer surface is created.
self.new_layer_surface.setNotify(newLayerSurface);
self.wlr_layer_shell.events.new_surface.add(&self.new_layer_surface);

self.request_activate.setNotify(requestActivate);
self.wlr_xdg_activation_v1.events.request_activate.add(&self.request_activate);

// Add a callback when a xwayland surface is created.
if (build_options.xwayland) {
self.new_xwayland_surface.setNotify(newXwaylandSurface);
self.wlr_xwayland.events.new_surface.add(&self.new_xwayland_surface);
}
}

// Create the socket, start the backend, and setup the environment
pub fn start(self: *Self) !void {
// We create a slice of 11 u8's ( practically a string buffer ) in which we store the socket value to be pushed later onto the env_map.
var buf: [11]u8 = undefined;
const socket = try self.wl_server.addSocketAuto(&buf);

// Set the wayland_display environment variable.
if (c.setenv("WAYLAND_DISPLAY", socket.ptr, 1) < 0) return error.SetenvError;
if (build_options.xwayland) if (c.setenv("DISPLAY", self.wlr_xwayland.display_name, 1) < 0) return error.SetenvError;

Expand Down Expand Up @@ -341,7 +301,6 @@ fn requestActivate(

// Callback that gets triggered on existence of a new output.
fn newOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
// Allocate memory to a new instance of output struct.
log.debug("Signal: wlr_backend_new_output", .{});
const output = allocator.create(Output) catch {
std.log.err("Failed to allocate new output", .{});
Expand All @@ -359,14 +318,7 @@ fn newOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
};
}

// This callback is called when a new xdg toplevel is created ( xdg toplevels are basically application windows. )
fn newXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurface) void {
// The role of the surface can be of 2 types:
// - xdg_toplevel
// - xdg_popup
//
// Popups include context menus and other floating windows that are in respect to any particular toplevel.
// We only want to manage toplevel here, popups will be managed separately.
const self = @fieldParentPtr(Self, "new_xdg_surface", listener);
log.debug("Signal: wlr_xdg_shell_new_surface", .{});
if (xdg_surface.role == .toplevel) {
Expand Down
18 changes: 3 additions & 15 deletions next/next.zig
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,11 @@ pub fn main() anyerror!void {
var args = res.args;
defer res.deinit();

// Print help message if requested.
if (args.help != 0) {
try stderr.writeAll("Usage: next [options]\n");
return clap.help(stderr, clap.Help, &params, .{});
}

// Print version information if requested.
if (args.version != 0) {
try stdout.print("Next version: {s}\n", .{build_options.version});
return;
Expand All @@ -60,7 +58,6 @@ pub fn main() anyerror!void {
runtime_log_level = .debug;
}

//Fetch the log level specified or fallback to info.
if (args.level) |level| {
if (mem.eql(u8, level, std.log.Level.err.asText())) {
runtime_log_level = .err;
Expand All @@ -76,13 +73,10 @@ pub fn main() anyerror!void {
}
}

// Fetching the startup command.
const startup_command = blk: {
// If command flag is mentioned, use it.
if (args.command) |command| {
break :blk try allocator.dupeZ(u8, command);
} else {
// Try to resolve xdg_config_home or home respectively and use their path's if possible.
if (os.getenv("XDG_CONFIG_HOME")) |xdg_config_home| {
break :blk try fs.path.joinZ(allocator, &.{ xdg_config_home, "next/nextrc" });
} else if (os.getenv("HOME")) |home| {
Expand All @@ -94,11 +88,10 @@ pub fn main() anyerror!void {
};
defer allocator.free(startup_command);

// accessZ takes a null terminated strings and checks against the mentioned bit.
// X_OK is the executable bit.
// X_OK -> executable bit.
os.accessZ(startup_command, os.X_OK) catch |err| {
if (err == error.PermissionDenied) {
// R_OK stands for the readable bit
// R_OK -> readable bit
if (os.accessZ(startup_command, os.R_OK)) {
// If the file is readable but cannot be executed then it must not have the execution bit set.
std.log.err("Failed to run nextrc file: {s}\nPlease mark the file executable with the following command:\n chmod +x {s}", .{ startup_command, startup_command });
Expand All @@ -115,7 +108,6 @@ pub fn main() anyerror!void {
return;
}

// Initializing wlroots log utility with debug level.
// TODO: Remove this entirely when zig gets good var-arg support.
wlr_fmt_log(switch (runtime_log_level) {
.debug => .debug,
Expand All @@ -132,13 +124,12 @@ pub fn main() anyerror!void {
};
try os.sigaction(os.SIG.PIPE, &sig_ign, null);

// Attempt to initialize the server, deinitialize it once the block ends.
std.log.scoped(.Next).info("Initializing server", .{});
try server.init();
defer server.deinit();

try server.start();

// Fork into a child process.
const pid = try os.fork();
if (pid == 0) {
var errno = os.errno(c.setsid());
Expand Down Expand Up @@ -194,17 +185,14 @@ pub fn log(
comptime format: []const u8,
args: anytype,
) void {
// If level of the message is higher than the message level specified then don't log it.
if (@intFromEnum(level) > @intFromEnum(runtime_log_level)) return;

// Performing some string formatting and then printing it.
const level_txt = comptime toUpper(level.asText());
const scope_txt = "[" ++ @tagName(scope) ++ "] ";

stderr.print(scope_txt ++ "(" ++ level_txt ++ ") " ++ format ++ "\n", args) catch {};
}

// Takes a string, uppercases it and returns a sentinel terminated string.
fn toUpper(comptime string: []const u8) *const [string.len:0]u8 {
comptime {
var tmp: [string.len:0]u8 = undefined;
Expand Down

0 comments on commit d475aee

Please sign in to comment.