session-lock: use the scene graph
This commit is contained in:
parent
683ed0f04e
commit
b38676f078
@ -368,7 +368,7 @@ fn updateKeyboardFocus(self: Self, result: Root.AtResult) void {
|
|||||||
self.seat.setFocusRaw(.{ .lock_surface = lock_surface });
|
self.seat.setFocusRaw(.{ .lock_surface = lock_surface });
|
||||||
},
|
},
|
||||||
.xwayland_override_redirect => |override_redirect| {
|
.xwayland_override_redirect => |override_redirect| {
|
||||||
assert(server.lock_manager.state == .unlocked);
|
assert(server.lock_manager.state != .locked);
|
||||||
override_redirect.focusIfDesired();
|
override_redirect.focusIfDesired();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -857,7 +857,7 @@ fn shouldPassthrough(self: Self) bool {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
.resize, .move => {
|
.resize, .move => {
|
||||||
assert(server.lock_manager.state == .unlocked);
|
assert(server.lock_manager.state != .locked);
|
||||||
const target = if (self.mode == .resize) self.mode.resize.view else self.mode.move.view;
|
const target = if (self.mode == .resize) self.mode.resize.view else self.mode.move.view;
|
||||||
// The target view is no longer visible, is part of the layout, or is fullscreen.
|
// The target view is no longer visible, is part of the layout, or is fullscreen.
|
||||||
return target.current.tags & target.output.current.tags == 0 or
|
return target.current.tags & target.output.current.tags == 0 or
|
||||||
@ -872,8 +872,12 @@ fn passthrough(self: *Self, time: u32) void {
|
|||||||
assert(self.mode == .passthrough);
|
assert(self.mode == .passthrough);
|
||||||
|
|
||||||
if (server.root.at(self.wlr_cursor.x, self.wlr_cursor.y)) |result| {
|
if (server.root.at(self.wlr_cursor.x, self.wlr_cursor.y)) |result| {
|
||||||
// TODO audit session lock assertions after wlr_scene upgrade
|
if (result.node == .lock_surface) {
|
||||||
assert((result.node == .lock_surface) == (server.lock_manager.state != .unlocked));
|
assert(server.lock_manager.state != .unlocked);
|
||||||
|
} else {
|
||||||
|
assert(server.lock_manager.state != .locked);
|
||||||
|
}
|
||||||
|
|
||||||
if (result.surface) |surface| {
|
if (result.surface) |surface| {
|
||||||
self.seat.wlr_seat.pointerNotifyEnter(surface, result.sx, result.sy);
|
self.seat.wlr_seat.pointerNotifyEnter(surface, result.sx, result.sy);
|
||||||
self.seat.wlr_seat.pointerNotifyMotion(time, result.sx, result.sy);
|
self.seat.wlr_seat.pointerNotifyMotion(time, result.sx, result.sy);
|
||||||
|
@ -130,6 +130,24 @@ fn handleLockSurfacesTimeout(manager: *LockManager) c_int {
|
|||||||
assert(manager.state == .waiting_for_lock_surfaces);
|
assert(manager.state == .waiting_for_lock_surfaces);
|
||||||
manager.state = .waiting_for_blank;
|
manager.state = .waiting_for_blank;
|
||||||
|
|
||||||
|
{
|
||||||
|
var it = server.root.outputs.first;
|
||||||
|
while (it) |node| : (it = node.next) {
|
||||||
|
const output = &node.data;
|
||||||
|
|
||||||
|
switch (output.lock_render_state) {
|
||||||
|
.unlocked, .pending_lock_surface => {},
|
||||||
|
.pending_blank, .blanked, .lock_surface => {
|
||||||
|
assert(!output.normal_content.node.enabled);
|
||||||
|
assert(output.locked_content.node.enabled);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
output.normal_content.node.setEnabled(false);
|
||||||
|
output.locked_content.node.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This call is necessary in the case that all outputs in the layout are disabled.
|
// This call is necessary in the case that all outputs in the layout are disabled.
|
||||||
manager.maybeLock();
|
manager.maybeLock();
|
||||||
|
|
||||||
@ -187,6 +205,19 @@ fn handleUnlock(listener: *wl.Listener(void)) void {
|
|||||||
|
|
||||||
log.info("session unlocked", .{});
|
log.info("session unlocked", .{});
|
||||||
|
|
||||||
|
{
|
||||||
|
var it = server.root.outputs.first;
|
||||||
|
while (it) |node| : (it = node.next) {
|
||||||
|
const output = &node.data;
|
||||||
|
|
||||||
|
assert(!output.normal_content.node.enabled);
|
||||||
|
output.normal_content.node.setEnabled(true);
|
||||||
|
|
||||||
|
assert(output.locked_content.node.enabled);
|
||||||
|
output.locked_content.node.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var it = server.input_manager.seats.first;
|
var it = server.input_manager.seats.first;
|
||||||
while (it) |node| : (it = node.next) {
|
while (it) |node| : (it = node.next) {
|
||||||
@ -230,5 +261,7 @@ fn handleSurface(
|
|||||||
assert(manager.state != .unlocked);
|
assert(manager.state != .unlocked);
|
||||||
assert(manager.lock != null);
|
assert(manager.lock != null);
|
||||||
|
|
||||||
LockSurface.create(wlr_lock_surface, manager.lock.?);
|
LockSurface.create(wlr_lock_surface, manager.lock.?) catch {
|
||||||
|
wlr_lock_surface.resource.postNoMemory();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
const LockSurface = @This();
|
const LockSurface = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const wlr = @import("wlroots");
|
const wlr = @import("wlroots");
|
||||||
const wl = @import("wayland").server.wl;
|
const wl = @import("wayland").server.wl;
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ const util = @import("util.zig");
|
|||||||
|
|
||||||
const Output = @import("Output.zig");
|
const Output = @import("Output.zig");
|
||||||
const Seat = @import("Seat.zig");
|
const Seat = @import("Seat.zig");
|
||||||
|
const SceneNodeData = @import("SceneNodeData.zig");
|
||||||
|
|
||||||
wlr_lock_surface: *wlr.SessionLockSurfaceV1,
|
wlr_lock_surface: *wlr.SessionLockSurfaceV1,
|
||||||
lock: *wlr.SessionLockV1,
|
lock: *wlr.SessionLockV1,
|
||||||
@ -33,11 +35,8 @@ output_mode: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleOutp
|
|||||||
map: wl.Listener(void) = wl.Listener(void).init(handleMap),
|
map: wl.Listener(void) = wl.Listener(void).init(handleMap),
|
||||||
surface_destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
|
surface_destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
|
||||||
|
|
||||||
pub fn create(wlr_lock_surface: *wlr.SessionLockSurfaceV1, lock: *wlr.SessionLockV1) void {
|
pub fn create(wlr_lock_surface: *wlr.SessionLockSurfaceV1, lock: *wlr.SessionLockV1) error{OutOfMemory}!void {
|
||||||
const lock_surface = util.gpa.create(LockSurface) catch {
|
const lock_surface = try util.gpa.create(LockSurface);
|
||||||
wlr_lock_surface.resource.getClient().postNoMemory();
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
lock_surface.* = .{
|
lock_surface.* = .{
|
||||||
.wlr_lock_surface = wlr_lock_surface,
|
.wlr_lock_surface = wlr_lock_surface,
|
||||||
@ -45,6 +44,10 @@ pub fn create(wlr_lock_surface: *wlr.SessionLockSurfaceV1, lock: *wlr.SessionLoc
|
|||||||
};
|
};
|
||||||
wlr_lock_surface.data = @ptrToInt(lock_surface);
|
wlr_lock_surface.data = @ptrToInt(lock_surface);
|
||||||
|
|
||||||
|
const output = lock_surface.getOutput();
|
||||||
|
const tree = try output.locked_content.createSceneSubsurfaceTree(wlr_lock_surface.surface);
|
||||||
|
try SceneNodeData.attach(&tree.node, .{ .lock_surface = lock_surface });
|
||||||
|
|
||||||
wlr_lock_surface.output.events.mode.add(&lock_surface.output_mode);
|
wlr_lock_surface.output.events.mode.add(&lock_surface.output_mode);
|
||||||
wlr_lock_surface.events.map.add(&lock_surface.map);
|
wlr_lock_surface.events.map.add(&lock_surface.map);
|
||||||
wlr_lock_surface.events.destroy.add(&lock_surface.surface_destroy);
|
wlr_lock_surface.events.destroy.add(&lock_surface.surface_destroy);
|
||||||
@ -53,8 +56,6 @@ pub fn create(wlr_lock_surface: *wlr.SessionLockSurfaceV1, lock: *wlr.SessionLoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(lock_surface: *LockSurface) void {
|
pub fn destroy(lock_surface: *LockSurface) void {
|
||||||
lock_surface.output().lock_surface = null;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var surface_it = lock_surface.lock.surfaces.iterator(.forward);
|
var surface_it = lock_surface.lock.surfaces.iterator(.forward);
|
||||||
const new_focus: Seat.FocusTarget = while (surface_it.next()) |surface| {
|
const new_focus: Seat.FocusTarget = while (surface_it.next()) |surface| {
|
||||||
@ -79,7 +80,7 @@ pub fn destroy(lock_surface: *LockSurface) void {
|
|||||||
util.gpa.destroy(lock_surface);
|
util.gpa.destroy(lock_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output(lock_surface: *LockSurface) *Output {
|
fn getOutput(lock_surface: *LockSurface) *Output {
|
||||||
return @intToPtr(*Output, lock_surface.wlr_lock_surface.output.data);
|
return @intToPtr(*Output, lock_surface.wlr_lock_surface.output.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,14 +89,19 @@ fn handleOutputMode(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
|
|||||||
|
|
||||||
var output_width: i32 = undefined;
|
var output_width: i32 = undefined;
|
||||||
var output_height: i32 = undefined;
|
var output_height: i32 = undefined;
|
||||||
lock_surface.output().wlr_output.effectiveResolution(&output_width, &output_height);
|
lock_surface.getOutput().wlr_output.effectiveResolution(&output_width, &output_height);
|
||||||
_ = lock_surface.wlr_lock_surface.configure(@intCast(u32, output_width), @intCast(u32, output_height));
|
_ = lock_surface.wlr_lock_surface.configure(@intCast(u32, output_width), @intCast(u32, output_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleMap(listener: *wl.Listener(void)) void {
|
fn handleMap(listener: *wl.Listener(void)) void {
|
||||||
const lock_surface = @fieldParentPtr(LockSurface, "map", listener);
|
const lock_surface = @fieldParentPtr(LockSurface, "map", listener);
|
||||||
|
|
||||||
lock_surface.output().lock_surface = lock_surface;
|
const output = lock_surface.getOutput();
|
||||||
|
assert(output.normal_content.node.enabled);
|
||||||
|
output.normal_content.node.setEnabled(false);
|
||||||
|
|
||||||
|
assert(!output.locked_content.node.enabled);
|
||||||
|
output.locked_content.node.setEnabled(true);
|
||||||
|
|
||||||
{
|
{
|
||||||
var it = server.input_manager.seats.first;
|
var it = server.input_manager.seats.first;
|
||||||
|
@ -67,11 +67,12 @@ usable_box: wlr.Box,
|
|||||||
/// Scene node representing the entire output.
|
/// Scene node representing the entire output.
|
||||||
/// Position must be updated when the output is moved in the layout.
|
/// Position must be updated when the output is moved in the layout.
|
||||||
tree: *wlr.SceneTree,
|
tree: *wlr.SceneTree,
|
||||||
|
normal_content: *wlr.SceneTree,
|
||||||
|
locked_content: *wlr.SceneTree,
|
||||||
|
|
||||||
/// The top of the stack is the "most important" view.
|
/// The top of the stack is the "most important" view.
|
||||||
views: ViewStack(View) = .{},
|
views: ViewStack(View) = .{},
|
||||||
|
|
||||||
lock_surface: ?*LockSurface = null,
|
|
||||||
/// Tracks the currently presented frame on the output as it pertains to ext-session-lock.
|
/// Tracks the currently presented frame on the output as it pertains to ext-session-lock.
|
||||||
/// The output is initially considered blanked:
|
/// The output is initially considered blanked:
|
||||||
/// If using the DRM backend it will be blanked with the initial modeset.
|
/// If using the DRM backend it will be blanked with the initial modeset.
|
||||||
@ -121,18 +122,17 @@ mode: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleMode),
|
|||||||
frame: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleFrame),
|
frame: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleFrame),
|
||||||
present: wl.Listener(*wlr.Output.event.Present) = wl.Listener(*wlr.Output.event.Present).init(handlePresent),
|
present: wl.Listener(*wlr.Output.event.Present) = wl.Listener(*wlr.Output.event.Present).init(handlePresent),
|
||||||
|
|
||||||
pub fn init(self: *Self, wlr_output: *wlr.Output) !void {
|
pub fn create(wlr_output: *wlr.Output) !void {
|
||||||
if (!wlr_output.initRender(server.allocator, server.renderer)) return;
|
const node = try util.gpa.create(std.TailQueue(Self).Node);
|
||||||
|
errdefer util.gpa.destroy(node);
|
||||||
|
const self = &node.data;
|
||||||
|
|
||||||
|
if (!wlr_output.initRender(server.allocator, server.renderer)) return error.InitRenderFailed;
|
||||||
|
|
||||||
// Some backends don't have modes. DRM+KMS does, and we need to set a mode
|
|
||||||
// before we can use the output. The mode is a tuple of (width, height,
|
|
||||||
// refresh rate), and each monitor supports only a specific set of modes. We
|
|
||||||
// just pick the monitor's preferred mode, a more sophisticated compositor
|
|
||||||
// would let the user configure it.
|
|
||||||
if (wlr_output.preferredMode()) |preferred_mode| {
|
if (wlr_output.preferredMode()) |preferred_mode| {
|
||||||
wlr_output.setMode(preferred_mode);
|
wlr_output.setMode(preferred_mode);
|
||||||
wlr_output.enable(true);
|
wlr_output.enable(true);
|
||||||
wlr_output.commit() catch |err| {
|
wlr_output.commit() catch {
|
||||||
var it = wlr_output.modes.iterator(.forward);
|
var it = wlr_output.modes.iterator(.forward);
|
||||||
while (it.next()) |mode| {
|
while (it.next()) |mode| {
|
||||||
if (mode == preferred_mode) continue;
|
if (mode == preferred_mode) continue;
|
||||||
@ -140,15 +140,18 @@ pub fn init(self: *Self, wlr_output: *wlr.Output) !void {
|
|||||||
wlr_output.commit() catch continue;
|
wlr_output.commit() catch continue;
|
||||||
// This mode works, use it
|
// This mode works, use it
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
// If no mode works, then we will just leave the output disabled.
|
||||||
|
// Perhaps the user will want to set a custom mode using wlr-output-management.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tree = try server.root.scene.tree.createSceneTree();
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.wlr_output = wlr_output,
|
.wlr_output = wlr_output,
|
||||||
.tree = try server.root.scene.tree.createSceneTree(),
|
.tree = tree,
|
||||||
|
.normal_content = try tree.createSceneTree(),
|
||||||
|
.locked_content = try tree.createSceneTree(),
|
||||||
.usable_box = undefined,
|
.usable_box = undefined,
|
||||||
};
|
};
|
||||||
wlr_output.data = @ptrToInt(self);
|
wlr_output.data = @ptrToInt(self);
|
||||||
@ -162,8 +165,8 @@ pub fn init(self: *Self, wlr_output: *wlr.Output) !void {
|
|||||||
// Ensure that a cursor image at the output's scale factor is loaded
|
// Ensure that a cursor image at the output's scale factor is loaded
|
||||||
// for each seat.
|
// for each seat.
|
||||||
var it = server.input_manager.seats.first;
|
var it = server.input_manager.seats.first;
|
||||||
while (it) |node| : (it = node.next) {
|
while (it) |seat_node| : (it = seat_node.next) {
|
||||||
const seat = &node.data;
|
const seat = &seat_node.data;
|
||||||
seat.cursor.xcursor_manager.load(wlr_output.scale) catch
|
seat.cursor.xcursor_manager.load(wlr_output.scale) catch
|
||||||
std.log.scoped(.cursor).err("failed to load xcursor theme at scale {}", .{wlr_output.scale});
|
std.log.scoped(.cursor).err("failed to load xcursor theme at scale {}", .{wlr_output.scale});
|
||||||
}
|
}
|
||||||
@ -177,6 +180,12 @@ pub fn init(self: *Self, wlr_output: *wlr.Output) !void {
|
|||||||
self.wlr_output.effectiveResolution(&self.usable_box.width, &self.usable_box.height);
|
self.wlr_output.effectiveResolution(&self.usable_box.width, &self.usable_box.height);
|
||||||
|
|
||||||
self.setTitle();
|
self.setTitle();
|
||||||
|
|
||||||
|
const ptr_node = try util.gpa.create(std.TailQueue(*Self).Node);
|
||||||
|
ptr_node.data = &node.data;
|
||||||
|
server.root.all_outputs.append(ptr_node);
|
||||||
|
|
||||||
|
handleEnable(&self.enable, self.wlr_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getLayer(self: *Self, layer: zwlr.LayerShellV1.Layer) *std.TailQueue(LayerSurface) {
|
pub fn getLayer(self: *Self, layer: zwlr.LayerShellV1.Layer) *std.TailQueue(LayerSurface) {
|
||||||
@ -477,8 +486,6 @@ fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.lock_surface) |surface| surface.destroy();
|
|
||||||
|
|
||||||
// Remove all listeners
|
// Remove all listeners
|
||||||
self.destroy.link.remove();
|
self.destroy.link.remove();
|
||||||
self.enable.link.remove();
|
self.enable.link.remove();
|
||||||
@ -503,11 +510,19 @@ fn handleEnable(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) vo
|
|||||||
// already been added.
|
// already been added.
|
||||||
if (wlr_output.enabled) server.root.addOutput(self);
|
if (wlr_output.enabled) server.root.addOutput(self);
|
||||||
|
|
||||||
|
// We can't assert the current state of normal_content/locked_content
|
||||||
|
// here as this output may be newly created.
|
||||||
if (wlr_output.enabled) {
|
if (wlr_output.enabled) {
|
||||||
switch (server.lock_manager.state) {
|
switch (server.lock_manager.state) {
|
||||||
.unlocked => self.lock_render_state = .unlocked,
|
.unlocked => {
|
||||||
|
self.lock_render_state = .unlocked;
|
||||||
|
self.normal_content.node.setEnabled(true);
|
||||||
|
self.locked_content.node.setEnabled(false);
|
||||||
|
},
|
||||||
.waiting_for_lock_surfaces, .waiting_for_blank, .locked => {
|
.waiting_for_lock_surfaces, .waiting_for_blank, .locked => {
|
||||||
assert(self.lock_render_state == .blanked);
|
assert(self.lock_render_state == .blanked);
|
||||||
|
self.normal_content.node.setEnabled(false);
|
||||||
|
self.locked_content.node.setEnabled(true);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -103,6 +103,8 @@ pub fn init(self: *Self) !void {
|
|||||||
.noop_output = .{
|
.noop_output = .{
|
||||||
.wlr_output = noop_wlr_output,
|
.wlr_output = noop_wlr_output,
|
||||||
.tree = try scene.tree.createSceneTree(),
|
.tree = try scene.tree.createSceneTree(),
|
||||||
|
.normal_content = try scene.tree.createSceneTree(),
|
||||||
|
.locked_content = try scene.tree.createSceneTree(),
|
||||||
.usable_box = .{ .x = 0, .y = 0, .width = 0, .height = 0 },
|
.usable_box = .{ .x = 0, .y = 0, .width = 0, .height = 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -153,14 +155,15 @@ pub fn at(self: Self, lx: f64, ly: f64) ?AtResult {
|
|||||||
var it: ?*wlr.SceneNode = node_at;
|
var it: ?*wlr.SceneNode = node_at;
|
||||||
while (it) |node| : (it = node.parent) {
|
while (it) |node| : (it = node.parent) {
|
||||||
if (@intToPtr(?*SceneNodeData, node.data)) |scene_node_data| {
|
if (@intToPtr(?*SceneNodeData, node.data)) |scene_node_data| {
|
||||||
switch (scene_node_data.data) {
|
return .{
|
||||||
.view => |view| return .{
|
.surface = surface,
|
||||||
.surface = surface,
|
.sx = sx,
|
||||||
.sx = sx,
|
.sy = sy,
|
||||||
.sy = sy,
|
.node = switch (scene_node_data.data) {
|
||||||
.node = .{ .view = view },
|
.view => |view| .{ .view = view },
|
||||||
|
.lock_surface => |lock_surface| .{ .lock_surface = lock_surface },
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,28 +171,18 @@ pub fn at(self: Self, lx: f64, ly: f64) ?AtResult {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleNewOutput(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
|
fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
|
||||||
const self = @fieldParentPtr(Self, "new_output", listener);
|
const log = std.log.scoped(.output_manager);
|
||||||
std.log.scoped(.output_manager).debug("new output {s}", .{wlr_output.name});
|
|
||||||
|
|
||||||
const node = util.gpa.create(std.TailQueue(Output).Node) catch {
|
log.debug("new output {s}", .{wlr_output.name});
|
||||||
wlr_output.destroy();
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
node.data.init(wlr_output) catch {
|
|
||||||
wlr_output.destroy();
|
|
||||||
util.gpa.destroy(node);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
const ptr_node = util.gpa.create(std.TailQueue(*Output).Node) catch {
|
|
||||||
wlr_output.destroy();
|
|
||||||
util.gpa.destroy(node);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
ptr_node.data = &node.data;
|
|
||||||
|
|
||||||
self.all_outputs.append(ptr_node);
|
Output.create(wlr_output) catch |err| {
|
||||||
self.addOutput(&node.data);
|
switch (err) {
|
||||||
|
error.OutOfMemory => log.err("out of memory", .{}),
|
||||||
|
error.InitRenderFailed => log.err("failed to initialize renderer for output {s}", .{wlr_output.name}),
|
||||||
|
}
|
||||||
|
wlr_output.destroy();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the output from self.outputs and evacuate views if it is a member of
|
/// Remove the output from self.outputs and evacuate views if it is a member of
|
||||||
|
@ -22,10 +22,12 @@ const wl = @import("wayland").server.wl;
|
|||||||
|
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
|
|
||||||
|
const LockSurface = @import("LockSurface.zig");
|
||||||
const View = @import("View.zig");
|
const View = @import("View.zig");
|
||||||
|
|
||||||
const Data = union(enum) {
|
const Data = union(enum) {
|
||||||
view: *View,
|
view: *View,
|
||||||
|
lock_surface: *LockSurface,
|
||||||
};
|
};
|
||||||
|
|
||||||
node: *wlr.SceneNode,
|
node: *wlr.SceneNode,
|
||||||
|
@ -241,14 +241,14 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
|||||||
// Set the new focus
|
// Set the new focus
|
||||||
switch (new_focus) {
|
switch (new_focus) {
|
||||||
.view => |target_view| {
|
.view => |target_view| {
|
||||||
assert(server.lock_manager.state == .unlocked);
|
assert(server.lock_manager.state != .locked);
|
||||||
assert(self.focused_output == target_view.output);
|
assert(self.focused_output == target_view.output);
|
||||||
if (target_view.pending.focus == 0) target_view.setActivated(true);
|
if (target_view.pending.focus == 0) target_view.setActivated(true);
|
||||||
target_view.pending.focus += 1;
|
target_view.pending.focus += 1;
|
||||||
target_view.pending.urgent = false;
|
target_view.pending.urgent = false;
|
||||||
},
|
},
|
||||||
.layer => |target_layer| {
|
.layer => |target_layer| {
|
||||||
assert(server.lock_manager.state == .unlocked);
|
assert(server.lock_manager.state != .locked);
|
||||||
assert(self.focused_output == target_layer.output);
|
assert(self.focused_output == target_layer.output);
|
||||||
},
|
},
|
||||||
.lock_surface => assert(server.lock_manager.state != .unlocked),
|
.lock_surface => assert(server.lock_manager.state != .unlocked),
|
||||||
|
@ -63,7 +63,7 @@ pub fn create(output: *Output, xdg_toplevel: *wlr.XdgToplevel) error{OutOfMemory
|
|||||||
errdefer util.gpa.destroy(node);
|
errdefer util.gpa.destroy(node);
|
||||||
const view = &node.view;
|
const view = &node.view;
|
||||||
|
|
||||||
const tree = try output.tree.createSceneXdgSurface(xdg_toplevel.base);
|
const tree = try output.normal_content.createSceneXdgSurface(xdg_toplevel.base);
|
||||||
errdefer tree.node.destroy();
|
errdefer tree.node.destroy();
|
||||||
|
|
||||||
try view.init(output, tree, .{ .xdg_toplevel = .{
|
try view.init(output, tree, .{ .xdg_toplevel = .{
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const os = std.os;
|
const os = std.os;
|
||||||
|
|
||||||
const server = &@import("main.zig").server;
|
const server = &@import("main.zig").server;
|
||||||
@ -25,7 +26,26 @@ const log = std.log.scoped(.render);
|
|||||||
|
|
||||||
pub fn renderOutput(output: *Output) void {
|
pub fn renderOutput(output: *Output) void {
|
||||||
const scene_output = server.root.scene.getSceneOutput(output.wlr_output).?;
|
const scene_output = server.root.scene.getSceneOutput(output.wlr_output).?;
|
||||||
if (!scene_output.commit()) {
|
|
||||||
|
if (scene_output.commit()) {
|
||||||
|
if (server.lock_manager.state == .locked or
|
||||||
|
(server.lock_manager.state == .waiting_for_lock_surfaces and output.locked_content.node.enabled) or
|
||||||
|
server.lock_manager.state == .waiting_for_blank)
|
||||||
|
{
|
||||||
|
assert(!output.normal_content.node.enabled);
|
||||||
|
assert(output.locked_content.node.enabled);
|
||||||
|
|
||||||
|
switch (server.lock_manager.state) {
|
||||||
|
.unlocked => unreachable,
|
||||||
|
.locked => switch (output.lock_render_state) {
|
||||||
|
.unlocked, .pending_blank, .pending_lock_surface => unreachable,
|
||||||
|
.blanked, .lock_surface => {},
|
||||||
|
},
|
||||||
|
.waiting_for_blank => output.lock_render_state = .pending_blank,
|
||||||
|
.waiting_for_lock_surfaces => output.lock_render_state = .pending_lock_surface,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
log.err("output commit failed for {s}", .{output.wlr_output.name});
|
log.err("output commit failed for {s}", .{output.wlr_output.name});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user