code: Add Root.removeOutput
This commit is contained in:
parent
fc549d6249
commit
10373da634
@ -72,6 +72,10 @@ attach_mode: AttachMode = .top,
|
|||||||
/// List of status tracking objects relaying changes to this output to clients.
|
/// List of status tracking objects relaying changes to this output to clients.
|
||||||
status_trackers: std.SinglyLinkedList(OutputStatus) = .{},
|
status_trackers: std.SinglyLinkedList(OutputStatus) = .{},
|
||||||
|
|
||||||
|
/// Whether or not the output is active
|
||||||
|
/// An active output can have focus (e.g. an output turned off by dpms is active)
|
||||||
|
active: bool = false,
|
||||||
|
|
||||||
// All listeners for this output, in alphabetical order
|
// All listeners for this output, in alphabetical order
|
||||||
listen_destroy: c.wl_listener = undefined,
|
listen_destroy: c.wl_listener = undefined,
|
||||||
listen_frame: c.wl_listener = undefined,
|
listen_frame: c.wl_listener = undefined,
|
||||||
@ -503,45 +507,10 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
|||||||
const root = self.root;
|
const root = self.root;
|
||||||
|
|
||||||
log.debug(.server, "output '{}' destroyed", .{self.wlr_output.name});
|
log.debug(.server, "output '{}' destroyed", .{self.wlr_output.name});
|
||||||
|
// Remove the destroyed output from root if it wasn't already removed
|
||||||
// Use the first output in the list that is not the one being destroyed.
|
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
||||||
// If there is no other real output, use the noop output.
|
if (self.active) {
|
||||||
var output_it = root.outputs.first;
|
root.removeOutput(node);
|
||||||
const fallback_output = while (output_it) |output_node| : (output_it = output_node.next) {
|
|
||||||
if (&output_node.data != self) {
|
|
||||||
break &output_node.data;
|
|
||||||
}
|
|
||||||
} else &root.noop_output;
|
|
||||||
|
|
||||||
// Move all views from the destroyed output to the fallback one
|
|
||||||
while (self.views.last) |node| {
|
|
||||||
const view = &node.view;
|
|
||||||
view.sendToOutput(fallback_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close all layer surfaces on the destroyed output
|
|
||||||
for (self.layers) |*layer, layer_idx| {
|
|
||||||
while (layer.pop()) |node| {
|
|
||||||
const layer_surface = &node.data;
|
|
||||||
// We need to move the closing layer surface to the noop output
|
|
||||||
// since it may not be immediately destoryed. This just a request
|
|
||||||
// to close which will trigger unmap and destroy events in
|
|
||||||
// response, and the LayerSurface needs a valid output to
|
|
||||||
// handle them.
|
|
||||||
root.noop_output.layers[layer_idx].prepend(node);
|
|
||||||
layer_surface.output = &root.noop_output;
|
|
||||||
c.wlr_layer_surface_v1_close(layer_surface.wlr_layer_surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any seat has the destroyed output focused, focus the fallback one
|
|
||||||
var seat_it = root.server.input_manager.seats.first;
|
|
||||||
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
|
|
||||||
const seat = &seat_node.data;
|
|
||||||
if (seat.focused_output == self) {
|
|
||||||
seat.focusOutput(fallback_output);
|
|
||||||
seat.focus(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all listeners
|
// Remove all listeners
|
||||||
@ -549,20 +518,12 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
|||||||
c.wl_list_remove(&self.listen_frame.link);
|
c.wl_list_remove(&self.listen_frame.link);
|
||||||
c.wl_list_remove(&self.listen_mode.link);
|
c.wl_list_remove(&self.listen_mode.link);
|
||||||
|
|
||||||
// Clean up the wlr_output
|
|
||||||
self.wlr_output.data = null;
|
|
||||||
|
|
||||||
// Free the layout command
|
// Free the layout command
|
||||||
util.gpa.free(self.layout);
|
util.gpa.free(self.layout);
|
||||||
|
|
||||||
// Remove the destroyed output from the list
|
// Clean up the wlr_output
|
||||||
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
self.wlr_output.data = null;
|
||||||
root.outputs.remove(node);
|
|
||||||
util.gpa.destroy(node);
|
util.gpa.destroy(node);
|
||||||
|
|
||||||
// Arrange the root in case evacuated views affect the layout
|
|
||||||
fallback_output.arrangeViews();
|
|
||||||
root.startTransaction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleFrame(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handleFrame(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
|
@ -35,6 +35,11 @@ const DragIcon = @import("DragIcon.zig");
|
|||||||
server: *Server,
|
server: *Server,
|
||||||
|
|
||||||
wlr_output_layout: *c.wlr_output_layout,
|
wlr_output_layout: *c.wlr_output_layout,
|
||||||
|
|
||||||
|
/// A list of all outputs
|
||||||
|
all_outputs: std.TailQueue(*Output) = .{},
|
||||||
|
|
||||||
|
/// A list of all active outputs. See Output.active
|
||||||
outputs: std.TailQueue(Output) = .{},
|
outputs: std.TailQueue(Output) = .{},
|
||||||
|
|
||||||
/// This output is used internally when no real outputs are available.
|
/// This output is used internally when no real outputs are available.
|
||||||
@ -91,10 +96,58 @@ pub fn deinit(self: *Self) void {
|
|||||||
if (c.wl_event_source_remove(self.transaction_timer) < 0) unreachable;
|
if (c.wl_event_source_remove(self.transaction_timer) < 0) unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes the output in node.data from self.outputs
|
||||||
|
/// The node is not freed
|
||||||
|
pub fn removeOutput(self: *Self, node: *std.TailQueue(Output).Node) void {
|
||||||
|
const output = &node.data;
|
||||||
|
self.outputs.remove(node);
|
||||||
|
output.active = false;
|
||||||
|
|
||||||
|
// Use the first output in the list as fallback.
|
||||||
|
// If there is no other real output, use the noop output.
|
||||||
|
const fallback_output = if (self.outputs.first) |output_node| &output_node.data else &self.noop_output;
|
||||||
|
|
||||||
|
// Move all views from the destroyed output to the fallback one
|
||||||
|
while (output.views.last) |view_node| {
|
||||||
|
const view = &view_node.view;
|
||||||
|
view.sendToOutput(fallback_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close all layer surfaces on the removed output
|
||||||
|
for (output.layers) |*layer, layer_idx| {
|
||||||
|
while (layer.pop()) |layer_node| {
|
||||||
|
const layer_surface = &layer_node.data;
|
||||||
|
// We need to move the closing layer surface to the noop output
|
||||||
|
// since it may not be immediately destoryed. This just a request
|
||||||
|
// to close which will trigger unmap and destroy events in
|
||||||
|
// response, and the LayerSurface needs a valid output to
|
||||||
|
// handle them.
|
||||||
|
self.noop_output.layers[layer_idx].prepend(layer_node);
|
||||||
|
layer_surface.output = &self.noop_output;
|
||||||
|
c.wlr_layer_surface_v1_close(layer_surface.wlr_layer_surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any seat has the removed output focused, focus the fallback one
|
||||||
|
var seat_it = self.server.input_manager.seats.first;
|
||||||
|
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
|
||||||
|
const seat = &seat_node.data;
|
||||||
|
if (seat.focused_output == output) {
|
||||||
|
seat.focusOutput(fallback_output);
|
||||||
|
seat.focus(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrange the root in case evacuated views affect the layout
|
||||||
|
fallback_output.arrangeViews();
|
||||||
|
self.startTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds the output in node.data to self.outputs
|
/// Adds the output in node.data to self.outputs
|
||||||
/// The Output in node.data must be initalized
|
/// The Output in node.data must be initalized
|
||||||
pub fn addOutput(self: *Self, node: *std.TailQueue(Output).Node) void {
|
pub fn addOutput(self: *Self, node: *std.TailQueue(Output).Node) void {
|
||||||
self.outputs.append(node);
|
self.outputs.append(node);
|
||||||
|
node.data.active = true;
|
||||||
|
|
||||||
// Add the new output to the layout. The add_auto function arranges outputs
|
// Add the new output to the layout. The add_auto function arranges outputs
|
||||||
// from left-to-right in the order they appear. A more sophisticated
|
// from left-to-right in the order they appear. A more sophisticated
|
||||||
|
Loading…
Reference in New Issue
Block a user