removed all windows decorations properly, added window closing and compositor exiting as well as view focusing

This commit is contained in:
Harrison DiAmbrosio 2025-10-25 18:50:06 -04:00
parent f636efdfe9
commit 976900ffa6
11 changed files with 289 additions and 117 deletions

View file

@ -81,5 +81,5 @@ pub fn build(b: *std.Build) void {
const run_cmd = b.addRunArtifact(mez); const run_cmd = b.addRunArtifact(mez);
run_step.dependOn(&run_cmd.step); run_step.dependOn(&run_cmd.step);
run_cmd.step.dependOn(b.getInstallStep()); run_cmd.step.dependOn(b.getInstallStep());
run_cmd.addArg("weston-terminal"); run_cmd.addArg("alacritty");
} }

View file

@ -19,15 +19,19 @@ mez.input.add_keymap("alt", "a", {
mez.input.add_keymap("alt", "Return", { mez.input.add_keymap("alt", "Return", {
press = function() press = function()
print("spawning foot")
mez.api.spawn("foot") mez.api.spawn("foot")
end,
})
mez.input.add_keymap("alt", "c", {
press = function ()
mez.api.close()
end end
}) })
mez.api.add_keymap("alt", "p", { mez.input.add_keymap("alt", "q", {
press = function () press = function ()
print("spawning foot") mez.api.exit();
mez.api.spawn("wmenu-run")
end end
}) })

View file

@ -30,7 +30,6 @@ hold_end: wl.Listener(*wlr.Pointer.event.HoldEnd) = .init(handleHoldEnd),
mode: enum { passthrough, move, resize } = .passthrough, mode: enum { passthrough, move, resize } = .passthrough,
// Drag information // Drag information
selected_view: ?*View = null,
drag_start_x: c_int = 0, drag_start_x: c_int = 0,
drag_start_y: c_int = 0, drag_start_y: c_int = 0,
drag_view_offset_x: c_int = 0, drag_view_offset_x: c_int = 0,
@ -74,6 +73,8 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
switch (self.mode) { switch (self.mode) {
.passthrough => { .passthrough => {
if (server.root.viewAt(self.wlr_cursor.x, self.wlr_cursor.y)) |res| { if (server.root.viewAt(self.wlr_cursor.x, self.wlr_cursor.y)) |res| {
server.seat.focusView(res.view);
server.seat.wlr_seat.pointerNotifyEnter(res.surface, res.sx, res.sy); server.seat.wlr_seat.pointerNotifyEnter(res.surface, res.sx, res.sy);
server.seat.wlr_seat.pointerNotifyMotion(time_msec, res.sx, res.sy); server.seat.wlr_seat.pointerNotifyMotion(time_msec, res.sx, res.sy);
} else { } else {
@ -82,23 +83,25 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
} }
}, },
.move => { .move => {
const view = self.selected_view.?; const focused_view = server.seat.focused_view;
if(focused_view) |view| {
view.scene_tree.node.setPosition( view.scene_tree.node.setPosition(
std.math.clamp(@as(c_int, @intFromFloat(self.wlr_cursor.x)) - self.drag_view_offset_x, 0, std.math.maxInt(u32)), std.math.clamp(@as(c_int, @intFromFloat(self.wlr_cursor.x)) - self.drag_view_offset_x, 0, std.math.maxInt(u32)),
std.math.clamp(@as(c_int, @intFromFloat(self.wlr_cursor.y)) - self.drag_view_offset_y, 0, std.math.maxInt(u32)) std.math.clamp(@as(c_int, @intFromFloat(self.wlr_cursor.y)) - self.drag_view_offset_y, 0, std.math.maxInt(u32))
); );
}
}, },
.resize => { .resize => {
// Fix this resize // Fix this resize
const view = self.selected_view.?; const focused_view = server.seat.focused_view;
if(focused_view) |view| {
_ = view.xdg_toplevel.setSize( _ = view.xdg_toplevel.setSize(
@intCast(@as(c_int, @intFromFloat(self.wlr_cursor.x)) - view.scene_tree.node.x), @intCast(@as(c_int, @intFromFloat(self.wlr_cursor.x)) - view.scene_tree.node.x),
@intCast(@as(c_int, @intFromFloat(self.wlr_cursor.y)) - view.scene_tree.node.y) @intCast(@as(c_int, @intFromFloat(self.wlr_cursor.y)) - view.scene_tree.node.y)
); );
}
}, },
} }
} }
@ -128,33 +131,30 @@ fn handleButton(
_ = server.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state); _ = server.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
const view_at_result = server.root.viewAt(cursor.wlr_cursor.x, cursor.wlr_cursor.y); if (server.seat.focused_view) |view| {
if (view_at_result) |res| { server.seat.focusView(view);
server.root.focusView(res.view); server.root.focusView(view);
} }
std.log.debug("Button pressed {}", .{event.button});
switch (event.state) { switch (event.state) {
.pressed => { .pressed => {
if(server.keyboard.wlr_keyboard.getModifiers().alt) { if(server.keyboard.wlr_keyboard.getModifiers().alt) {
// Can be BTN_RIGHT, BTN_LEFT, or BTN_MIDDLE // Can be BTN_RIGHT, BTN_LEFT, or BTN_MIDDLE
if(view_at_result) |res| { if(server.seat.focused_view) |view| {
// Keep track of where the drag started // Keep track of where the drag started
cursor.selected_view = res.view;
cursor.drag_start_x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)); cursor.drag_start_x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x));
cursor.drag_start_y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y)); cursor.drag_start_y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y));
cursor.drag_view_offset_x = cursor.drag_start_x - res.view.scene_tree.node.x; cursor.drag_view_offset_x = cursor.drag_start_x - view.scene_tree.node.x;
cursor.drag_view_offset_y = cursor.drag_start_y - res.view.scene_tree.node.y; cursor.drag_view_offset_y = cursor.drag_start_y - view.scene_tree.node.y;
cursor.drag_view_width = res.view.xdg_surface.geometry.width; cursor.drag_view_width = view.xdg_toplevel.base.geometry.width;
cursor.drag_view_height = res.view.xdg_surface.geometry.height; cursor.drag_view_height = view.xdg_toplevel.base.geometry.height;
// Maybe comptime this for later reference // Maybe comptime this for later reference
if(event.button == c.libevdev_event_code_from_name(c.EV_KEY, "BTN_LEFT")) { if(event.button == c.libevdev_event_code_from_name(c.EV_KEY, "BTN_LEFT")) {
cursor.mode = .move; cursor.mode = .move;
} else if(event.button == c.libevdev_event_code_from_name(c.EV_KEY, "BTN_RIGHT")) { } else if(event.button == c.libevdev_event_code_from_name(c.EV_KEY, "BTN_RIGHT")) {
cursor.mode = .resize; cursor.mode = .resize;
_ = res.view.xdg_toplevel.setResizing(true); _ = view.xdg_toplevel.setResizing(true);
} }
} }
} }
@ -162,10 +162,9 @@ fn handleButton(
.released => { .released => {
cursor.mode = .passthrough; cursor.mode = .passthrough;
if(cursor.selected_view) |view| { if(server.seat.focused_view) |view| {
_ = view.xdg_toplevel.setResizing(false); _ = view.xdg_toplevel.setResizing(false);
} }
cursor.selected_view = null;
}, },
else => { else => {
std.log.err("Invalid/Unimplemented pointer button event type", .{}); std.log.err("Invalid/Unimplemented pointer button event type", .{});

View file

@ -21,10 +21,8 @@ options: struct {
}, },
pub fn callback(self: *const Keymap, release: bool) void { pub fn callback(self: *const Keymap, release: bool) void {
var lua_ref_idx = self.lua_press_ref_idx; const lua_ref_idx = if(release) self.lua_release_ref_idx else self.lua_press_ref_idx;
if (release) {
lua_ref_idx = self.lua_release_ref_idx;
}
const t = Lua.state.rawGetIndex(zlua.registry_index, lua_ref_idx); const t = Lua.state.rawGetIndex(zlua.registry_index, lua_ref_idx);
if (t != zlua.LuaType.function) { if (t != zlua.LuaType.function) {
std.log.err("Failed to call keybind, it doesn't have a callback.", .{}); std.log.err("Failed to call keybind, it doesn't have a callback.", .{});

View file

@ -4,6 +4,7 @@ const zlua = @import("zlua");
const gpa = std.heap.c_allocator; const gpa = std.heap.c_allocator;
const env_map = &@import("../main.zig").env_map; const env_map = &@import("../main.zig").env_map;
const server = &@import("../main.zig").server;
pub fn spawn(L: *zlua.Lua) i32 { pub fn spawn(L: *zlua.Lua) i32 {
const nargs: i32 = L.getTop(); const nargs: i32 = L.getTop();
@ -28,3 +29,31 @@ pub fn spawn(L: *zlua.Lua) i32 {
return 0; return 0;
} }
pub fn close(L: *zlua.Lua) i32 {
const nargs: i32 = L.getTop();
if (nargs != 0) {
L.raiseErrorStr("Expected no arguments", .{});
return 0;
}
if(server.seat.focused_view) |view| {
view.xdg_toplevel.sendClose();
}
return 0;
}
pub fn exit(L: *zlua.Lua) i32 {
const nargs: i32 = L.getTop();
if (nargs != 0) {
L.raiseErrorStr("Expected no arguments", .{});
return 0;
}
server.deinit();
return 0;
}

View file

@ -10,6 +10,8 @@ const posix = std.posix;
const gpa = std.heap.c_allocator; const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server; const server = &@import("main.zig").server;
focused: bool,
wlr_output: *wlr.Output, wlr_output: *wlr.Output,
scene_output: *wlr.SceneOutput, scene_output: *wlr.SceneOutput,
@ -24,6 +26,7 @@ pub fn create(wlr_output: *wlr.Output) *Output {
const output = try gpa.create(Output); const output = try gpa.create(Output);
output.* = .{ output.* = .{
.focused = false,
.wlr_output = wlr_output, .wlr_output = wlr_output,
.scene_output = try server.root.scene.createSceneOutput(wlr_output) .scene_output = try server.root.scene.createSceneOutput(wlr_output)
}; };

View file

@ -17,10 +17,8 @@ scene: *wlr.Scene,
scene_output_layout: *wlr.SceneOutputLayout, scene_output_layout: *wlr.SceneOutputLayout,
output_layout: *wlr.OutputLayout, output_layout: *wlr.OutputLayout,
focused_output: ?*Output,
views: std.ArrayList(*View) = undefined, views: std.HashMap(u64, *View, std.hash_map.AutoContext(u64), 80),
workspaces: std.ArrayList(*wlr.SceneTree) = undefined,
pub fn init(self: *Root) void { pub fn init(self: *Root) void {
std.log.info("Creating root of mezzaluna\n", .{}); std.log.info("Creating root of mezzaluna\n", .{});
@ -36,28 +34,21 @@ pub fn init(self: *Root) void {
self.* = .{ self.* = .{
.scene = scene, .scene = scene,
.output_layout = output_layout, .output_layout = output_layout,
.focused_output = null,
.xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server), .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server),
.scene_output_layout = try scene.attachOutputLayout(output_layout), .scene_output_layout = try scene.attachOutputLayout(output_layout),
.views = .init(gpa)
}; };
self.views = try std.ArrayList(*View).initCapacity(gpa, 10); // Should consider number better, prolly won't matter that much though
// Even though I would never use a changing amount of workspaces, opens more extensibility
self.workspaces = try std.ArrayList(*wlr.SceneTree).initCapacity(gpa, 10); // TODO: change to a configured number of workspaces
// TODO: Make configurable
for(0..9) |_| {
try self.workspaces.append(gpa, try self.scene.tree.createSceneTree());
}
} }
pub fn deinit(self: *Root) void { pub fn deinit(self: *Root) void {
for(self.views.items) |view| { var views_it = self.views.iterator();
view.deinit(); while(views_it.next()) |entry| {
entry.value_ptr.*.deinit();
} }
self.views.deinit(gpa);
self.workspaces.deinit(gpa); self.views.deinit();
self.output_layout.destroy(); self.output_layout.destroy();
self.scene.tree.node.destroy(); self.scene.tree.node.destroy();
@ -66,7 +57,7 @@ pub fn deinit(self: *Root) void {
pub fn addOutput(self: *Root, new_output: *Output) void { pub fn addOutput(self: *Root, new_output: *Output) void {
errdefer Utils.oomPanic(); errdefer Utils.oomPanic();
_ = try self.output_layout.addAuto(new_output.wlr_output); _ = try self.output_layout.addAuto(new_output.wlr_output);
self.focused_output = new_output; server.seat.focusOutput(new_output);
} }
const ViewAtResult = struct { const ViewAtResult = struct {

View file

@ -5,10 +5,14 @@ const wlr = @import("wlroots");
const wl = @import("wayland").server.wl; const wl = @import("wayland").server.wl;
const Utils = @import("utils.zig"); const Utils = @import("utils.zig");
const View = @import("view.zig");
const Output = @import("output.zig");
const server = &@import("main.zig").server; const server = &@import("main.zig").server;
wlr_seat: *wlr.Seat, wlr_seat: *wlr.Seat,
focused_view: ?*View,
focused_output: ?*Output,
request_set_cursor: wl.Listener(*wlr.Seat.event.RequestSetCursor) = .init(handleRequestSetCursor), request_set_cursor: wl.Listener(*wlr.Seat.event.RequestSetCursor) = .init(handleRequestSetCursor),
request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) = .init(handleRequestSetSelection), request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) = .init(handleRequestSetSelection),
@ -20,6 +24,8 @@ pub fn init(self: *Seat) void {
self.* = .{ self.* = .{
.wlr_seat = try wlr.Seat.create(server.wl_server, "default"), .wlr_seat = try wlr.Seat.create(server.wl_server, "default"),
.focused_view = null,
.focused_output = null,
}; };
self.wlr_seat.events.request_set_cursor.add(&self.request_set_cursor); self.wlr_seat.events.request_set_cursor.add(&self.request_set_cursor);
@ -33,6 +39,23 @@ pub fn deinit(self: *Seat) void {
self.wlr_seat.destroy(); self.wlr_seat.destroy();
} }
pub fn focusOutput(self: *Seat, output: *Output) void {
if(self.focused_output) |prev_output| {
prev_output.focused = false;
}
self.focused_output = output;
}
// TODO: Should focusing a view, automaticall focus the output containing it
pub fn focusView(self: *Seat, view: *View) void {
if(self.focused_view) |prev_view| {
prev_view.setFocus(false);
}
self.focused_view = view;
}
fn handleRequestSetCursor( fn handleRequestSetCursor(
_: *wl.Listener(*wlr.Seat.event.RequestSetCursor), _: *wl.Listener(*wlr.Seat.event.RequestSetCursor),
event: *wlr.Seat.event.RequestSetCursor, event: *wlr.Seat.event.RequestSetCursor,

View file

@ -116,15 +116,15 @@ pub fn init(self: *Server) void {
self.xdg_shell.events.new_popup.add(&self.new_xdg_popup); self.xdg_shell.events.new_popup.add(&self.new_xdg_popup);
// XdgDecorationManagerV1 events // XdgDecorationManagerV1 events
// self.xdg_toplevel_decoration_manager.events.new_toplevel_decoration.add(&self.new_toplevel_decoration); self.xdg_toplevel_decoration_manager.events.new_toplevel_decoration.add(&self.new_xdg_toplevel_decoration);
} }
pub fn deinit(self: *Server) void { pub fn deinit(self: *Server) noreturn {
self.new_input.link.remove(); self.new_input.link.remove();
self.new_output.link.remove(); self.new_output.link.remove();
self.new_xdg_toplevel.link.remove(); self.new_xdg_toplevel.link.remove();
self.new_xdg_popup.link.remove(); self.new_xdg_popup.link.remove();
self.new_xdg_toplevel.link.remove(); self.new_xdg_toplevel_decoration.link.remove();
self.seat.deinit(); self.seat.deinit();
self.root.deinit(); self.root.deinit();
@ -134,6 +134,9 @@ pub fn deinit(self: *Server) void {
self.wl_server.destroyClients(); self.wl_server.destroyClients();
self.wl_server.destroy(); self.wl_server.destroy();
std.log.debug("Exiting mez succesfully", .{});
std.process.exit(0);
} }
// --------- Backend event handlers --------- // --------- Backend event handlers ---------
@ -185,20 +188,23 @@ fn handleNewXdgToplevel(
_: *wl.Listener(*wlr.XdgToplevel), _: *wl.Listener(*wlr.XdgToplevel),
xdg_toplevel: *wlr.XdgToplevel xdg_toplevel: *wlr.XdgToplevel
) void { ) void {
std.log.debug("Request for new toplevel", .{});
_ = View.initFromTopLevel(xdg_toplevel); _ = View.initFromTopLevel(xdg_toplevel);
} }
fn handleNewXdgToplevelDecoration(
_: *wl.Listener(*wlr.XdgToplevelDecorationV1),
decoration: *wlr.XdgToplevelDecorationV1
) void {
std.log.debug("Request for decorations", .{});
if(server.root.views.get(@intFromPtr(decoration.toplevel))) |view| {
view.xdg_toplevel_decoration = decoration;
}
}
fn handleNewXdgPopup( fn handleNewXdgPopup(
_: *wl.Listener(*wlr.XdgPopup), _: *wl.Listener(*wlr.XdgPopup),
_: *wlr.XdgPopup _: *wlr.XdgPopup
) void { ) void {
std.log.err("Unimplemented handle new xdg popup", .{}); std.log.err("Unimplemented handle new xdg popup", .{});
} }
fn handleNewXdgToplevelDecoration(
_: *wl.Listener(*wlr.XdgToplevelDecorationV1),
decoration: *wlr.XdgToplevelDecorationV1
) void {
// TODO: Configured with lua perhaps
decoration.current.mode = .server_side;
}

32
src/tag.zig Normal file
View file

@ -0,0 +1,32 @@
const Tag = @This();
const std = @import("std");
const wl = @import("wayland").server.wl;
const wlr = @import("wlroots");
const Output = @import("output.zig");
const View = @import("view.zig");
const Utils = @import("utils.zig");
const server = @import("main.zig").server;
const gpa = std.heap.c_allocator;
output: *Output,
scene_tree: *wlr.SceneTree,
views: std.ArrayList(*View),
pub fn init(output: *Output) Tag {
errdefer Utils.oomPanic();
return .{
.output = output,
.scene_tree = try server.root.scene.tree.createSceneTree(),
.views = .initCapacity(gpa, 2), // Probably shouldn't be a magic number
};
}
pub fn deinit(self: *Tag) void {
for(self.views.items) |view| {
view
}
}

View file

@ -9,25 +9,40 @@ const Utils = @import("utils.zig");
const gpa = std.heap.c_allocator; const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server; const server = &@import("main.zig").server;
link: wl.list.Link = undefined, mapped: bool,
geometry: *wlr.Box = undefined, focused: bool,
id: u64,
// workspace: Workspace,
xdg_toplevel: *wlr.XdgToplevel, xdg_toplevel: *wlr.XdgToplevel,
xdg_surface: *wlr.XdgSurface, xdg_toplevel_decoration: ?*wlr.XdgToplevelDecorationV1,
scene_tree: *wlr.SceneTree, scene_tree: *wlr.SceneTree,
// Surface Listeners // Surface Listeners
map: wl.Listener(void) = .init(handleMap), map: wl.Listener(void) = .init(handleMap),
unmap: wl.Listener(void) = .init(handleUnmap), unmap: wl.Listener(void) = .init(handleUnmap),
commit: wl.Listener(*wlr.Surface) = .init(handleCommit), commit: wl.Listener(*wlr.Surface) = .init(handleCommit),
new_popup: wl.Listener(*wlr.XdgPopup) = .init(handleNewPopup),
ack_configure: wl.Listener(*wlr.XdgSurface.Configure) = .init(handleAckConfigure),
// XdgTopLevel Listeners // XdgTopLevel Listeners
destroy: wl.Listener(void) = .init(handleDestroy), destroy: wl.Listener(void) = .init(handleDestroy),
request_resize: wl.Listener(*wlr.XdgToplevel.event.Resize) = .init(handleRequestResize), request_resize: wl.Listener(*wlr.XdgToplevel.event.Resize) = .init(handleRequestResize),
request_move: wl.Listener(*wlr.XdgToplevel.event.Move) = .init(handleRequestMove), request_move: wl.Listener(*wlr.XdgToplevel.event.Move) = .init(handleRequestMove),
request_fullscreen: wl.Listener(void) = .init(handleRequestFullscreen),
// Not yet silly // Do we need to add these
// new_popup: wl.Listener(*wlr.XdgPopup) = wl.Listener(*wlr.XdgPopup).init(handleNewPopup), // request_show_window_menu: wl.Listener(comptime T: type) = .init(handleRequestShowWindowMenu),
// request_minimize: wl.Listener(comptime T: type) = .init(handleRequestMinimize),
// request_maximize: wl.Listener(comptime T: type) = .init(handleRequestMaximize),
set_app_id: wl.Listener(void) = .init(handleSetAppId),
set_title: wl.Listener(void) = .init(handleSetTitle),
// Do we need to add this
// set_parent: wl.Listener(void) = .init(handleSetParent),
pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) *View { pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) *View {
errdefer Utils.oomPanic(); errdefer Utils.oomPanic();
@ -37,40 +52,30 @@ pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) *View {
self.* = .{ self.* = .{
.xdg_toplevel = xdg_toplevel, .xdg_toplevel = xdg_toplevel,
.xdg_surface = xdg_toplevel.base, .focused = false,
.geometry = &xdg_toplevel.base.geometry,
.scene_tree = undefined, .scene_tree = undefined,
.xdg_toplevel_decoration = null,
.mapped = false,
.id = @intFromPtr(xdg_toplevel),
}; };
self.xdg_toplevel.base.surface.events.unmap.add(&self.unmap);
// Add new Toplevel to focused output instead of some random shit // Add new Toplevel to focused output instead of some random shit
// This is where we find out where to tile the widow, but not NOW // This is where we find out where to tile the widow, but not NOW
// We need lua for that // We need lua for that
self.scene_tree = try server.root.workspaces.items[0].createSceneXdgSurface(xdg_toplevel.base); // self.scene_tree = try server.root.workspaces.items[0].createSceneXdgSurface(xdg_toplevel.base);
self.scene_tree = try server.root.scene.tree.createSceneXdgSurface(xdg_toplevel.base);
self.scene_tree.node.data = self; self.scene_tree.node.data = self;
self.xdg_surface.data = self.scene_tree; self.xdg_toplevel.base.data = self.scene_tree;
// Attach listeners
self.xdg_surface.surface.events.map.add(&self.map);
self.xdg_surface.surface.events.unmap.add(&self.unmap);
self.xdg_surface.surface.events.commit.add(&self.commit);
self.xdg_toplevel.events.destroy.add(&self.destroy); self.xdg_toplevel.events.destroy.add(&self.destroy);
self.xdg_toplevel.events.request_move.add(&self.request_move); self.xdg_toplevel.base.surface.events.map.add(&self.map);
self.xdg_toplevel.events.request_resize.add(&self.request_resize); self.xdg_toplevel.base.surface.events.commit.add(&self.commit);
self.xdg_toplevel.base.events.new_popup.add(&self.new_popup);
// xdg_toplevel.events.request_fullscreen.add(&self.request_fullscreen); try server.root.views.put(self.id, self);
// xdg_toplevel.events.request_minimize.add(&self.request_minimize);
// xdg_toplevel.events.request_maxminize.add(&self.request_maximize);
// xdg_toplevel.events.set_title.add(&self.set_title);
// xdg_toplevel.events.set_app_id.add(&self.set_app_id);
// xdg_toplevel.events.set_parent.add(&self.set_parent);
// xdg_toplevel.events.request_show_window_menu.add(&self.request_show_window_menu);
try server.root.views.append(gpa, self);
return self; return self;
} }
@ -85,10 +90,22 @@ pub fn deinit(self: *View) void {
self.request_resize.link.remove(); self.request_resize.link.remove();
} }
// Handle borders to appropriate colros make necessary notifications
pub fn setFocus(self: *View, focus: bool) void {
self.focused = focus;
}
// --------- XdgTopLevel event handlers --------- // --------- XdgTopLevel event handlers ---------
fn handleMap(listener: *wl.Listener(void)) void { fn handleMap(listener: *wl.Listener(void)) void {
const view: *View = @fieldParentPtr("map", listener); const view: *View = @fieldParentPtr("map", listener);
std.log.info("View mapped {s}", .{view.xdg_toplevel.title orelse "(unnamed)"}); std.log.debug("Mapping view '{s}'", .{view.xdg_toplevel.title orelse "(unnamed)"});
view.xdg_toplevel.events.request_fullscreen.add(&view.request_fullscreen);
view.xdg_toplevel.events.request_move.add(&view.request_move);
view.xdg_toplevel.events.request_resize.add(&view.request_resize);
view.xdg_toplevel.events.set_app_id.add(&view.set_app_id);
view.xdg_toplevel.events.set_title.add(&view.set_title);
// view.xdg_toplevel.events.set_parent.add(&view.set_parent);
const xdg_surface = view.xdg_toplevel.base; const xdg_surface = view.xdg_toplevel.base;
server.seat.wlr_seat.keyboardNotifyEnter( server.seat.wlr_seat.keyboardNotifyEnter(
@ -96,29 +113,49 @@ fn handleMap(listener: *wl.Listener(void)) void {
server.keyboard.wlr_keyboard.keycodes[0..server.keyboard.wlr_keyboard.num_keycodes], server.keyboard.wlr_keyboard.keycodes[0..server.keyboard.wlr_keyboard.num_keycodes],
&server.keyboard.wlr_keyboard.modifiers &server.keyboard.wlr_keyboard.modifiers
); );
if(view.xdg_toplevel_decoration) |decoration| {
_ = decoration.setMode(wlr.XdgToplevelDecorationV1.Mode.server_side);
}
// Here is where we should tile and set size
view.mapped = true;
} }
fn handleUnmap(listener: *wl.Listener(void)) void { fn handleUnmap(listener: *wl.Listener(void)) void {
_ = listener; const view: *View = @fieldParentPtr("unmap", listener);
std.log.err("Unimplemented view handle unamp", .{}); std.log.debug("Unmapping view '{s}'", .{view.xdg_toplevel.title orelse "(unnamed)"});
view.request_fullscreen.link.remove();
view.request_move.link.remove();
view.request_resize.link.remove();
view.set_title.link.remove();
view.set_app_id.link.remove();
// Why does this crash mez???
// view.ack_configure.link.remove();
view.mapped = false;
} }
fn handleDestroy(listener: *wl.Listener(void)) void { fn handleDestroy(listener: *wl.Listener(void)) void {
const view: *View = @fieldParentPtr("destroy", listener); const view: *View = @fieldParentPtr("destroy", listener);
std.log.debug("Destroying view {s}", .{view.xdg_toplevel.title orelse "(unnamed)"});
// Remove decorations
view.map.link.remove(); view.map.link.remove();
view.unmap.link.remove(); view.unmap.link.remove();
view.commit.link.remove(); view.commit.link.remove();
view.destroy.link.remove(); view.destroy.link.remove();
view.new_popup.link.remove();
// Remove this view from the list of views view.xdg_toplevel.base.surface.data = null;
// for(server.root.all_views.items, 0..) |v, i| {
// if(v == view) { view.scene_tree.node.destroy();
// _ = server.root.all_views.orderedRemove(i); // Destroy popups
// break;
// } _ = server.root.views.remove(view.id);
// }
gpa.destroy(view); gpa.destroy(view);
} }
@ -132,6 +169,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
} }
} }
// --------- XdgToplevel Event Handlers ---------
fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), popup: *wlr.XdgPopup) void { fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), popup: *wlr.XdgPopup) void {
_ = listener; _ = listener;
_ = popup; _ = popup;
@ -144,7 +182,7 @@ fn handleRequestMove(
) void { ) void {
// const view: *View = @fieldParentPtr("request_move", listener); // const view: *View = @fieldParentPtr("request_move", listener);
std.log.err("The clients should not be request moves", .{}); std.log.debug("The clients should not be request moves", .{});
// server.cursor.moveView(view); // server.cursor.moveView(view);
// server.cursor.grabbed_view = view; // server.cursor.grabbed_view = view;
@ -159,7 +197,7 @@ fn handleRequestResize(
) void { ) void {
// const view: *View = @fieldParentPtr("request_resize", listener); // const view: *View = @fieldParentPtr("request_resize", listener);
std.log.err("The clients should not be request moves", .{}); std.log.debug("The clients should not be request moves", .{});
// server.cursor.grabbed_view = view; // server.cursor.grabbed_view = view;
// server.cursor.mode = .resize; // server.cursor.mode = .resize;
@ -176,3 +214,52 @@ fn handleRequestResize(
// server.cursor.grab_box.x += view.geometry.x; // server.cursor.grab_box.x += view.geometry.x;
// server.cursor.grab_box.y += view.geometry.y; // server.cursor.grab_box.y += view.geometry.y;
} }
fn handleAckConfigure(
listener: *wl.Listener(*wlr.XdgSurface.Configure),
_: *wlr.XdgSurface.Configure,
) void {
const view: *View = @fieldParentPtr("ack_configure", listener);
_ = view;
std.log.err("Unimplemented act configure", .{});
}
fn handleRequestFullscreen(
listener: *wl.Listener(void)
) void {
const view: *View = @fieldParentPtr("request_fullscreen", listener);
_ = view;
std.log.err("Unimplemented request fullscreen", .{});
}
fn handleRequestMinimize(
listener: *wl.Listener(void)
) void {
const view: *View = @fieldParentPtr("request_fullscreen", listener);
_ = view;
std.log.err("Unimplemented request minimize", .{});
}
fn handleRequestMaximize(
listener: *wl.Listener(void)
) void {
const view: *View = @fieldParentPtr("request_fullscreen", listener);
_ = view;
std.log.err("Unimplemented request maximize", .{});
}
fn handleSetAppId(
listener: *wl.Listener(void)
) void {
const view: *View = @fieldParentPtr("set_app_id", listener);
_ = view;
std.log.err("Unimplemented request maximize", .{});
}
fn handleSetTitle(
listener: *wl.Listener(void)
) void {
const view: *View = @fieldParentPtr("set_title", listener);
_ = view;
std.log.err("Unimplemented set title", .{});
}