diff --git a/runtime/master.lua b/runtime/master.lua index 84748de..2e27f64 100644 --- a/runtime/master.lua +++ b/runtime/master.lua @@ -91,7 +91,7 @@ local default_config = { M.tile_tag = function(tag_id) local tag = M.state.tags[tag_id] - local area = mez.output.get_available_area(0) + local area = mez.output.get_state(0).available_area if tag.master == nil then return end diff --git a/src/Output.zig b/src/Output.zig index aa4902d..720e931 100644 --- a/src/Output.zig +++ b/src/Output.zig @@ -8,6 +8,7 @@ const std = @import("std"); const Utils = @import("Utils.zig"); const Server = @import("Server.zig"); +const Root = @import("Root.zig"); const View = @import("View.zig"); const LayerSurface = @import("LayerSurface.zig"); @@ -25,15 +26,12 @@ const Layers = struct { overlay: *wlr.SceneTree, }; -focused: bool, id: u64, fullscreens: std.ArrayList(*View), wlr_output: *wlr.Output, -state: wlr.Output.State, -tree: *wlr.SceneTree, -scene_node_data: SceneNodeData, scene_output: *wlr.SceneOutput, +scene_node_data: SceneNodeData, non_exclusive_area: wlr.Box, layers: Layers, @@ -46,61 +44,48 @@ destroy: wl.Listener(*wlr.Output) = .init(handleDestroy), pub fn init(wlr_output: *wlr.Output) ?*Output { errdefer Utils.oomPanic(); + if (!wlr_output.initRender(server.allocator, server.renderer)) { + std.log.err("Unable to start output {s}", .{wlr_output.name}); + return null; + } + const self = try gpa.create(Output); + errdefer self.deinit(); self.* = .{ - .focused = false, .id = @intFromPtr(wlr_output), .wlr_output = wlr_output, - .tree = try server.root.scene.tree.createSceneTree(), .fullscreens = std.ArrayList(*View).initCapacity(gpa, 8) catch Utils.oomPanic(), .non_exclusive_area = .{ .x = 0, .y = 0, .width = 0, .height = 0 }, + .scene_output = try server.root.scene.createSceneOutput(wlr_output), + .scene_node_data = SceneNodeData{ .output = self }, .layers = .{ - .background = try self.tree.createSceneTree(), - .bottom = try self.tree.createSceneTree(), - .content = try self.tree.createSceneTree(), - .top = try self.tree.createSceneTree(), - .overlay = try self.tree.createSceneTree(), + .background = try self.scene_output.scene.tree.createSceneTree(), + .bottom = try self.scene_output.scene.tree.createSceneTree(), + .content = try self.scene_output.scene.tree.createSceneTree(), + .top = try self.scene_output.scene.tree.createSceneTree(), + .overlay = try self.scene_output.scene.tree.createSceneTree(), }, - - .scene_output = try server.root.scene.createSceneOutput(wlr_output), - .scene_node_data = SceneNodeData{ .output = self }, - .state = wlr.Output.State.init() }; + self.wlr_output.data = self; + wlr_output.events.frame.add(&self.frame); - wlr_output.events.request_state.add(&self.request_state); wlr_output.events.destroy.add(&self.destroy); + wlr_output.events.request_state.add(&self.request_state); - errdefer deinit(self); + var state = wlr.Output.State.init(); + defer state.finish(); - if (!wlr_output.initRender(server.allocator, server.renderer)) { - std.log.err("Unable to start output {s}", .{wlr_output.name}); - return null; - } + if (wlr_output.preferredMode()) |mode| state.setMode(mode); - self.state.setEnabled(true); + state.setEnabled(true); - if (wlr_output.preferredMode()) |mode| { - self.state.setMode(mode); - } - - if (!wlr_output.commitState(&self.state)) { - std.log.err("Unable to commit state to output {s}", .{wlr_output.name}); - return null; + if (!wlr_output.commitState(&state)) { + std.log.err("Unable to commit state to output {s}", .{ wlr_output.name }); } - // TODO: Allow user to define output positions - const layout_output = try server.root.output_layout.addAuto(self.wlr_output); - server.root.scene_output_layout.addOutput(layout_output, self.scene_output); - self.arrangeLayers(); - - self.setFocused(); - - self.wlr_output.data = self; - self.tree.node.data = &self.scene_node_data; - server.events.exec("OutputInitPost", .{self.id}, "After a new output is initialized. You're probably looking for OutputStateChange."); return self; @@ -112,23 +97,15 @@ pub fn deinit(self: *Output) void { self.frame.link.remove(); self.request_state.link.remove(); self.destroy.link.remove(); - - self.state.finish(); - self.wlr_output.destroy(); - server.events.exec("OutputDeinitPost", .{}, "After an output is de-initialized."); - gpa.destroy(self); + + server.events.exec("OutputDeinitPost", .{}, "After an output is de-initialized."); } pub fn setFocused(self: *Output) void { - if (server.getDefaultSeat().focused_output) |prev_output| { - prev_output.focused = false; - } - server.getDefaultSeat().focused_output = self; - self.focused = true; } const SurfaceAtResult = struct { @@ -205,49 +182,36 @@ fn handleRequestState( listener: *wl.Listener(*wlr.Output.event.RequestState), event: *wlr.Output.event.RequestState, ) void { - const output: *Output = @fieldParentPtr("request_state", listener); + const self: *Output = @fieldParentPtr("request_state", listener); - if (!output.wlr_output.commitState(event.state)) { + if (!self.wlr_output.commitState(event.state)) { std.log.warn("failed to set output state {}", .{event.state}); // nothing should've changed, so we don't do anything return; } - // update the config with all monitors and send it to the output_manager - const config = wlr.OutputConfigurationV1.create() catch Utils.oomPanic(); - var iter = server.root.scene.outputs.iterator(.forward); - while (iter.next()) |out| { - _ = wlr.OutputConfigurationV1.Head.create(config, out.output) catch Utils.oomPanic(); - } - server.root.output_manager.setConfiguration(config); - - // make sure the layers are behaving - arrangeLayers(output); + Root.configureOutputs(&server.root); + self.arrangeLayers(); - server.events.exec("OutputStateChange", .{output.id}, "After an outputs state has been changed."); + server.events.exec("OutputStateChange", .{self.id}, "After an outputs state has been changed."); } -fn handleFrame(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { - const scene_output = server.root.scene.getSceneOutput(wlr_output); +fn handleFrame(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { + const self: *Output = @fieldParentPtr("frame", listener); - if (scene_output == null) { - std.log.err("Unable to get scene output to render", .{}); - return; + if (!self.scene_output.commit(null)) { + std.log.warn("setting output state failed for output: {}", .{ self.id }); } - // std.log.info("Rendering commited scene output\n", .{}); - _ = scene_output.?.commit(null); - - var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported"); - scene_output.?.sendFrameDone(&now); + var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch { + std.debug.panic("CLOCK_MONOTONIC not supported", .{}); + }; + self.scene_output.sendFrameDone(&now); } fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { - std.log.debug("Handling destroy", .{}); const output: *Output = @fieldParentPtr("destroy", listener); - std.log.debug("removing output: {s}", .{output.wlr_output.name}); - output.frame.link.remove(); output.request_state.link.remove(); output.destroy.link.remove(); @@ -269,12 +233,10 @@ pub fn arrangeLayers(self: *Output) void { inline for (@typeInfo(zwlr.LayerShellV1.Layer).@"enum".fields) |comptime_layer| { const layer: *wlr.SceneTree = @field(self.layers, comptime_layer.name); - var it = layer.children.safeIterator(.forward); + var it = layer.children.iterator(.forward); while (it.next()) |node| { if (node.data == null) continue; - - // if (@as(?*SceneNodeData, @alignCast(@ptrCast(node.data)))) |node_data| { const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(node.data.?)); const layer_surface: *LayerSurface = switch (scene_node_data.*) { @@ -282,6 +244,9 @@ pub fn arrangeLayers(self: *Output) void { else => continue, }; + // TEST: should we set the layersurface to the correct output? + if (layer_surface.output.wlr_output != self.wlr_output) continue; + if (!layer_surface.wlr_layer_surface.initialized) continue; // TEST: river seems to try and prevent clients from taking an @@ -291,13 +256,20 @@ pub fn arrangeLayers(self: *Output) void { layer_surface.scene_layer_surface.configure( &full_box, - &self.non_exclusive_area, + &self.non_exclusive_area ); - // TEST: are these calls useless? - // const x = layer_surface.scene_layer_surface.tree.node.x; - // const y = layer_surface.scene_layer_surface.tree.node.y; - // layer_surface.scene_layer_surface.tree.node.setPosition(x, y); + // set the position of the new layersurface relative to the output + // it belongs to + const x = layer_surface.output.scene_output.x; + const y = layer_surface.output.scene_output.y; + layer_surface.scene_layer_surface.tree.node.setPosition(x, y); + layer_surface.scene_layer_surface.tree.node.subsurfaceTreeSetClip(&.{ + .x = 0, + .y = 0, + .width = layer_surface.output.wlr_output.width, + .height = layer_surface.output.wlr_output.height, + }); } } } diff --git a/src/Root.zig b/src/Root.zig index d43afab..2840bc6 100644 --- a/src/Root.zig +++ b/src/Root.zig @@ -18,7 +18,6 @@ const Utils = @import("Utils.zig"); scene_node_data: SceneNode.Data, scene: *wlr.Scene, -scene_output_layout: *wlr.SceneOutputLayout, output_layout: *wlr.OutputLayout, output_manager: *wlr.OutputManagerV1, output_power_manager: *wlr.OutputPowerManagerV1, @@ -45,7 +44,6 @@ pub fn init(self: *Root) void { .output_manager = try wlr.OutputManagerV1.create(server.wl_server), .output_power_manager = try wlr.OutputPowerManagerV1.create(server.wl_server), .output_layout = output_layout, - .scene_output_layout = try scene.attachOutputLayout(output_layout), }; if (server.linux_dmabuf) |dmabuf| self.scene.setLinuxDmabufV1(dmabuf); @@ -75,6 +73,26 @@ pub fn deinit(self: *Root) void { self.scene.tree.node.destroy(); } +pub fn configureOutputs(self: *const Root) void { + // update the config with all monitors and send it to the output_manager + const config = wlr.OutputConfigurationV1.create() catch Utils.oomPanic(); + + // TODO: do we ommit disabled monitors here? + var iter = self.scene.outputs.iterator(.forward); + while (iter.next()) |scene_output| { + const config_head = wlr.OutputConfigurationV1.Head.create(config, scene_output.output) catch Utils.oomPanic(); + + if (self.output_layout.get(scene_output.output)) |_| { + _ = self.output_layout.addAuto(scene_output.output) catch Utils.oomPanic(); + } + + config_head.state.x = scene_output.x; + config_head.state.y = scene_output.y; + } + + self.output_manager.setConfiguration(config); +} + // Search output_layout's outputs, and each outputs views pub fn viewById(self: *Root, id: u64) ?*View { var output_it = self.output_layout.outputs.iterator(.forward); diff --git a/src/Seat.zig b/src/Seat.zig index 3778c7d..184971d 100644 --- a/src/Seat.zig +++ b/src/Seat.zig @@ -169,10 +169,6 @@ pub fn focusSurface(self: *Seat, to_focus: ?FocusData) void { } pub fn focusOutput(self: *Seat, output: *Output) void { - if (self.focused_output) |prev_output| { - prev_output.focused = false; - } - self.focused_output = output; } diff --git a/src/Server.zig b/src/Server.zig index 7ccb698..19988a8 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -286,8 +286,30 @@ fn handleNewInput(listener: *wl.Listener(*wlr.InputDevice), device: *wlr.InputDe }); } -fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { - _ = Output.init(wlr_output); +fn handleNewOutput(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { + const self: *Server = @fieldParentPtr("new_output", listener); + const output = Output.init(wlr_output) orelse { + std.log.err("Failed to create new output", .{}); + return; + }; + + // TODO: Allow user to define output positions + const layout_output = self.root.output_layout.addAuto(output.wlr_output) catch { + std.log.err("failed to add output to the output layout", .{}); + return; + }; + + output.scene_output.setPosition(layout_output.x, layout_output.y); + + // FIXME: without this the lua api can crash mez very easily. Thankfully we + // don't have a case for not having any output selected, but it'd still be + // better if we didn't crash. + if (self.getDefaultSeat().focused_output == null) { + self.getDefaultSeat().focusOutput(output); + } + + Root.configureOutputs(&self.root); + output.arrangeLayers(); } fn handleNewXdgToplevel(_: *wl.Listener(*wlr.XdgToplevel), xdg_toplevel: *wlr.XdgToplevel) void { diff --git a/src/View.zig b/src/View.zig index afc1f83..26a6440 100644 --- a/src/View.zig +++ b/src/View.zig @@ -275,9 +275,10 @@ fn handleUnmap(listener: *wl.Listener(void)) void { server.events.exec("ViewUnmapPre", .{view.id}, "Before the view is unmapped. This view is still currently visibile to the user."); - if (server.getDefaultSeat().focused_surface) |fs| { - if (fs == .view and fs.view == view) { - server.getDefaultSeat().focusSurface(null); + var iter = server.seats.iterator(.forward); + while (iter.next()) |seat| { + if (seat.focused_surface) |fs| { + if (fs == .view and fs.view == view) seat.focusSurface(null); } } diff --git a/src/lua/Output.zig b/src/lua/Output.zig index 69ff9bb..58c31d3 100644 --- a/src/lua/Output.zig +++ b/src/lua/Output.zig @@ -4,12 +4,22 @@ const zlua = @import("zlua"); const Output = @import("../Output.zig"); const LuaUtils = @import("LuaUtils.zig"); +const Utils = @import("../Utils.zig"); const Seat = @import("Seat.zig"); const SceneNode = @import("../SceneNode.zig"); const server = &@import("../main.zig").server; const wlr = @import("wlroots"); +const wl = @import("wayland").server.wl; const posix = std.posix; +const gpa = std.heap.c_allocator; + +const Mode = struct { + width: i32, + height: i32, + refresh: f64, + preferred: bool, +}; fn output_id_err(L: *zlua.Lua) noreturn { L.raiseErrorStr("The output id must be >= 0 and < inf", .{}); @@ -57,6 +67,26 @@ pub fn get_focused_id(L: *zlua.Lua) i32 { return 1; } +/// ---Remove focus from current output, and set to given id +/// ---@param seat_id integer Id of the seat to be focused, 0 for default seat +/// ---@param output_id integer? Id of the output to be focused +pub fn set_focused(L: *zlua.Lua) i32 { + const seat = if (!L.isNil(1)) blk: { + const seat_id = LuaUtils.coerceInteger(u32, L.checkInteger(1)) catch Seat.seat_id_err(L); + break :blk LuaUtils.seatFromId(seat_id) orelse { + L.pushNil(); + return 1; + }; + } else server.getDefaultSeat(); + const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(2)) catch output_id_err(L); + if (server.root.outputById(output_id)) |output| { + seat.focusOutput(output); + } + + L.pushNil(); + return 1; +} + /// Returns all the ids of views within an output /// ---@param output_id integer 0 maps to focused output /// ---@return integer[]? @@ -87,15 +117,65 @@ pub fn get_views(L: *zlua.Lua) i32 { return 1; } -/// ---Get refresh rate for the output +const get_output_state = struct { + refresh: f64, + scale: f32, + resolution: struct { width: c_int = 0, height: c_int = 0 }, + available_area: wlr.Box, + position: struct { x: c_int, y: c_int }, + transform: [:0]const u8, + make: ?[:0]const u8, + serial: ?[:0]const u8, + model: ?[:0]const u8, + description: ?[:0]const u8, + name: [:0]const u8, + modes: []Mode, +}; + +/// ---Get the state of an output /// ---@param output_id integer 0 maps to focused output -/// ---@return integer? -pub fn get_rate(L: *zlua.Lua) i32 { +/// ---@return get_output_state? +pub fn get_state(L: *zlua.Lua) i32 { const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); if (output) |o| { - L.pushInteger(@intCast(o.wlr_output.refresh)); + const output_layout = server.root.output_layout.get(o.wlr_output); + const modes: []Mode = gpa.alloc(Mode, o.wlr_output.modes.length()) catch Utils.oomPanic(); + defer gpa.free(modes); + var iter = o.wlr_output.modes.iterator(.forward); + + L.pushAny(get_output_state { + .scale = o.wlr_output.scale, + .resolution = .{ + .width = o.wlr_output.width, + .height = o.wlr_output.height, + }, + .position = .{ + .x = if (output_layout) |l| l.x else 0, + .y = if (output_layout) |l| l.y else 0, + }, + .refresh = @as(f64, @floatFromInt(o.wlr_output.refresh)) / 1000.0, + .available_area = o.non_exclusive_area, + .transform = @tagName(o.wlr_output.transform), + .make = if (o.wlr_output.make) |m| std.mem.span(m) else null, + .serial = if (o.wlr_output.make) |s| std.mem.span(s) else null, + .model = if (o.wlr_output.model) |m| std.mem.span(m) else null, + .description = if (o.wlr_output.description) |d| std.mem.span(d) else null, + .name = std.mem.span(o.wlr_output.name), + .modes = blk: { + var i: u32 = 0; // I wonder how many modes a display can have + while (iter.next()) |mode| : (i += 1) { + modes[i] = Mode{ + .width = mode.width, + .height = mode.height, + .refresh = @as(f64, @floatFromInt(mode.refresh)) / 1000.0, + .preferred = mode.preferred, + }; + } + break: blk modes; + }, + }) catch unreachable; return 1; } @@ -103,179 +183,53 @@ pub fn get_rate(L: *zlua.Lua) i32 { return 1; } -/// ---Set the scale for the output -/// ---@param output_id integer 0 maps to focused output -/// ---@param scale number -pub fn set_scale(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - - if (output) |o| { - var state: wlr.Output.State = .init(); - defer state.finish(); - - // We don't allow scales below 0 - const new_scale: f32 = @floatCast(L.checkNumber(2)); - state.setScale(if (new_scale <= 0) o.wlr_output.scale else new_scale); - _ = o.wlr_output.commitState(&state); - - o.arrangeLayers(); - } - - return 0; -} - -/// ---Get the scale for the output -/// ---@param output_id integer 0 maps to focused output -/// ---@return number? scale -pub fn get_scale(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - - if (output) |o| { - L.pushNumber(o.wlr_output.scale); - return 1; - } - - return 0; -} - -/// ---Get resolution in pixels of the output -/// ---@param output_id integer 0 maps to focused output -/// ---@return { width: integer, height: integer }? -pub fn get_resolution(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); - - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - if (output) |o| { - L.newTable(); - - L.pushInteger(@intCast(o.wlr_output.width)); - L.setField(-2, "width"); - - L.pushInteger(@intCast(o.wlr_output.height)); - L.setField(-2, "height"); - - return 1; - } - - L.pushNil(); - return 1; -} - -/// ---Get the serial for the output -/// ---@param output_id integer 0 maps to focused output -/// ---@return string? -pub fn get_serial(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); - - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - if (output) |o| { - if (o.wlr_output.serial == null) { - L.pushNil(); - return 1; - } - - _ = L.pushString(std.mem.span(o.wlr_output.serial.?)); - return 1; - } - - L.pushNil(); - return 1; -} +// TODO: remove the default values once we switch to a commit after 22cad3a +/// all setter data is optional +const set_output_state = struct { + position: ?struct { x: c_int = 0, y: c_int = 0 } = null, + scale: ?f32 = null, + transform: ?wl.Output.Transform = null, + mode: ?Mode = null, +}; -/// ---Get the make for the output -/// ---@param output_id integer 0 maps to focused output -/// ---@return string? -pub fn get_make(L: *zlua.Lua) i32 { +pub fn set_state(L: *zlua.Lua) i32 { const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); if (output) |o| { - if (o.wlr_output.make == null) { - L.pushNil(); - return 1; - } - - _ = L.pushString(std.mem.span(o.wlr_output.make.?)); - return 1; - } - - L.pushNil(); - return 1; -} - -/// ---Get the model for the output -/// ---@param output_id integer 0 maps to focused output -/// ---@return string? -pub fn get_model(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); + const lua_state = L.toAny(set_output_state, 2) catch |err| { + L.raiseErrorStr("Output state is not usable! `%s`", .{ @errorName(err).ptr }); + }; - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - if (output) |o| { - if (o.wlr_output.model == null) { - L.pushNil(); - return 1; + var new_state: wlr.Output.State = .init(); + defer new_state.finish(); + + if (lua_state.scale) |v| new_state.setScale(if (v <= 0) o.wlr_output.scale else v); + if (lua_state.transform) |v| new_state.setTransform(v); + if (lua_state.mode) |v| new_state.setCustomMode(v.width, v.height, @intFromFloat(v.refresh * 1000)); + if (lua_state.position) |v| { + if (server.root.output_layout.get(o.wlr_output)) |layout| { + layout.x = v.x; + layout.y = v.y; + } } - _ = L.pushString(std.mem.span(o.wlr_output.model.?)); - return 1; - } - - L.pushNil(); - return 1; -} - -/// ---Get the description for the output -/// ---@param output_id integer 0 maps to focused output -/// ---@return string? -pub fn get_description(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); - - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - if (output) |o| { - if (o.wlr_output.description == null) { - L.pushNil(); - return 1; + if (!o.wlr_output.testState(&new_state) + or !o.wlr_output.commitState(&new_state)) { + L.raiseErrorStr("Output state is not usable!", .{}); } - _ = L.pushString(std.mem.span(o.wlr_output.description.?)); - return 1; - } - - L.pushNil(); - return 1; -} - -/// ---Get the name of the output -/// ---@param output_id integer 0 maps to focused output -/// ---@return string -pub fn get_name(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); + // keep the output manager in sync with the output + server.root.configureOutputs(); - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - if (output) |o| { - _ = L.pushString(std.mem.span(o.wlr_output.name)); - return 1; + o.arrangeLayers(); + return 0; } L.pushNil(); return 1; } -/// ---Get the space not exclusively occupied -/// ---@param output_id integer 0 maps to focused output -/// ---@return Box? -pub fn get_available_area(L: *zlua.Lua) i32 { - const output_id = LuaUtils.coerceInteger(u64, L.checkInteger(1)) catch output_id_err(L); - const output: ?*Output = if (output_id == 0) server.getDefaultSeat().focused_output else server.root.outputById(output_id); - - if (output == null) return 0; - - L.pushAny(output.?.non_exclusive_area) catch unreachable; - return 1; -} - /// ---Get the id of the output's fullscreened view if it exists /// ---@param output_id integer 0 maps to focused output /// ---@return integer? diff --git a/src/lua/View.zig b/src/lua/View.zig index 3d5b9ea..0a0f624 100644 --- a/src/lua/View.zig +++ b/src/lua/View.zig @@ -32,7 +32,7 @@ pub fn get_all_ids(L: *zlua.Lua) i32 { } const output: *Output = @ptrCast(@alignCast(o.output.data.?)); - if (!output.state.enabled) continue; + if (!output.wlr_output.enabled) continue; // Only search the content and fullscreen layers for views var iter = SceneNode.iterator(@constCast(&[_]*wlr.SceneTree{