tree: restore workspaces after monitor reconnect
This commit is contained in:
parent
eaa3b85a97
commit
7476e6f2d9
6 changed files with 80 additions and 9 deletions
|
|
@ -359,8 +359,9 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
height: 0,
|
height: 0,
|
||||||
refresh_rate_millihz: 0,
|
refresh_rate_millihz: 0,
|
||||||
},
|
},
|
||||||
"none",
|
"jay",
|
||||||
"none",
|
"dummy-output",
|
||||||
|
"0",
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
)),
|
)),
|
||||||
|
|
@ -378,6 +379,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
});
|
});
|
||||||
let dummy_workspace = Rc::new(WorkspaceNode {
|
let dummy_workspace = Rc::new(WorkspaceNode {
|
||||||
id: state.node_ids.next(),
|
id: state.node_ids.next(),
|
||||||
|
is_dummy: true,
|
||||||
output: CloneCell::new(dummy_output.clone()),
|
output: CloneCell::new(dummy_output.clone()),
|
||||||
position: Default::default(),
|
position: Default::default(),
|
||||||
container: Default::default(),
|
container: Default::default(),
|
||||||
|
|
@ -387,6 +389,8 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
output_link: Default::default(),
|
output_link: Default::default(),
|
||||||
visible: Default::default(),
|
visible: Default::default(),
|
||||||
fullscreen: Default::default(),
|
fullscreen: Default::default(),
|
||||||
|
visible_on_desired_output: Default::default(),
|
||||||
|
desired_output: CloneCell::new(dummy_output.global.output_id.clone()),
|
||||||
});
|
});
|
||||||
dummy_workspace.output_link.set(Some(
|
dummy_workspace.output_link.set(Some(
|
||||||
dummy_output.workspaces.add_last(dummy_workspace.clone()),
|
dummy_output.workspaces.add_last(dummy_workspace.clone()),
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,7 @@ pub struct WlOutputGlobal {
|
||||||
pub state: Rc<State>,
|
pub state: Rc<State>,
|
||||||
pub connector: Rc<ConnectorData>,
|
pub connector: Rc<ConnectorData>,
|
||||||
pub pos: Cell<Rect>,
|
pub pos: Cell<Rect>,
|
||||||
pub manufacturer: String,
|
pub output_id: Rc<OutputId>,
|
||||||
pub display: String,
|
|
||||||
pub mode: Cell<backend::Mode>,
|
pub mode: Cell<backend::Mode>,
|
||||||
pub node: CloneCell<Option<Rc<OutputNode>>>,
|
pub node: CloneCell<Option<Rc<OutputNode>>>,
|
||||||
pub width_mm: i32,
|
pub width_mm: i32,
|
||||||
|
|
@ -82,6 +81,13 @@ pub struct WlOutputGlobal {
|
||||||
pub destroyed: Cell<bool>,
|
pub destroyed: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
pub struct OutputId {
|
||||||
|
pub manufacturer: String,
|
||||||
|
pub model: String,
|
||||||
|
pub serial_number: String,
|
||||||
|
}
|
||||||
|
|
||||||
impl WlOutputGlobal {
|
impl WlOutputGlobal {
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
self.node.take();
|
self.node.take();
|
||||||
|
|
@ -96,6 +102,7 @@ impl WlOutputGlobal {
|
||||||
mode: &backend::Mode,
|
mode: &backend::Mode,
|
||||||
manufacturer: &str,
|
manufacturer: &str,
|
||||||
product: &str,
|
product: &str,
|
||||||
|
serial_number: &str,
|
||||||
width_mm: i32,
|
width_mm: i32,
|
||||||
height_mm: i32,
|
height_mm: i32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
@ -104,8 +111,11 @@ impl WlOutputGlobal {
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
connector: connector.clone(),
|
connector: connector.clone(),
|
||||||
pos: Cell::new(Rect::new_sized(x1, 0, mode.width, mode.height).unwrap()),
|
pos: Cell::new(Rect::new_sized(x1, 0, mode.width, mode.height).unwrap()),
|
||||||
manufacturer: manufacturer.to_string(),
|
output_id: Rc::new(OutputId {
|
||||||
display: product.to_string(),
|
manufacturer: manufacturer.to_string(),
|
||||||
|
model: product.to_string(),
|
||||||
|
serial_number: serial_number.to_string(),
|
||||||
|
}),
|
||||||
mode: Cell::new(*mode),
|
mode: Cell::new(*mode),
|
||||||
node: Default::default(),
|
node: Default::default(),
|
||||||
width_mm,
|
width_mm,
|
||||||
|
|
@ -268,8 +278,8 @@ impl WlOutput {
|
||||||
physical_width: self.global.width_mm,
|
physical_width: self.global.width_mm,
|
||||||
physical_height: self.global.height_mm,
|
physical_height: self.global.height_mm,
|
||||||
subpixel: SP_UNKNOWN,
|
subpixel: SP_UNKNOWN,
|
||||||
make: &self.global.manufacturer,
|
make: &self.global.output_id.manufacturer,
|
||||||
model: &self.global.display,
|
model: &self.global.output_id.model,
|
||||||
transform: TF_NORMAL,
|
transform: TF_NORMAL,
|
||||||
};
|
};
|
||||||
self.client.event(event);
|
self.client.event(event);
|
||||||
|
|
|
||||||
|
|
@ -395,6 +395,7 @@ impl State {
|
||||||
}
|
}
|
||||||
let workspace = Rc::new(WorkspaceNode {
|
let workspace = Rc::new(WorkspaceNode {
|
||||||
id: self.node_ids.next(),
|
id: self.node_ids.next(),
|
||||||
|
is_dummy: false,
|
||||||
output: CloneCell::new(output.clone()),
|
output: CloneCell::new(output.clone()),
|
||||||
position: Cell::new(Default::default()),
|
position: Cell::new(Default::default()),
|
||||||
container: Default::default(),
|
container: Default::default(),
|
||||||
|
|
@ -404,6 +405,8 @@ impl State {
|
||||||
output_link: Cell::new(None),
|
output_link: Cell::new(None),
|
||||||
visible: Cell::new(false),
|
visible: Cell::new(false),
|
||||||
fullscreen: Default::default(),
|
fullscreen: Default::default(),
|
||||||
|
visible_on_desired_output: Cell::new(false),
|
||||||
|
desired_output: CloneCell::new(output.global.output_id.clone()),
|
||||||
});
|
});
|
||||||
workspace
|
workspace
|
||||||
.output_link
|
.output_link
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ impl ConnectorHandler {
|
||||||
&info.initial_mode,
|
&info.initial_mode,
|
||||||
&info.manufacturer,
|
&info.manufacturer,
|
||||||
&info.product,
|
&info.product,
|
||||||
|
&info.serial_number,
|
||||||
info.width_mm,
|
info.width_mm,
|
||||||
info.height_mm,
|
info.height_mm,
|
||||||
));
|
));
|
||||||
|
|
@ -138,6 +139,46 @@ impl ConnectorHandler {
|
||||||
if let Some(config) = self.state.config.get() {
|
if let Some(config) = self.state.config.get() {
|
||||||
config.connector_connected(self.id);
|
config.connector_connected(self.id);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
for source in self.state.outputs.lock().values() {
|
||||||
|
if source.node.id == on.id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut ws_to_move = vec![];
|
||||||
|
for ws in source.node.workspaces.iter() {
|
||||||
|
if ws.is_dummy {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ws.desired_output.get() == global.output_id {
|
||||||
|
ws_to_move.push(ws.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ws in ws_to_move {
|
||||||
|
on.workspaces.add_last_existing(&ws);
|
||||||
|
if ws.visible_on_desired_output.get() && on.workspace.get().is_none() {
|
||||||
|
on.show_workspace(&ws);
|
||||||
|
} else {
|
||||||
|
ws.set_visible(false);
|
||||||
|
}
|
||||||
|
if let Some(visible) = source.node.workspace.get() {
|
||||||
|
if visible.id == ws.id {
|
||||||
|
source.node.workspace.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if source.node.workspace.get().is_none() {
|
||||||
|
if let Some(ws) = source.node.workspaces.first() {
|
||||||
|
source.node.show_workspace(&ws);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
source.node.update_render_data();
|
||||||
|
}
|
||||||
|
if on.workspace.get().is_none() {
|
||||||
|
if let Some(ws) = on.workspaces.first() {
|
||||||
|
on.show_workspace(&ws);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
on.update_render_data();
|
on.update_render_data();
|
||||||
self.state.root.outputs.set(self.id, on.clone());
|
self.state.root.outputs.set(self.id, on.clone());
|
||||||
self.state.root.update_extents();
|
self.state.root.update_extents();
|
||||||
|
|
@ -177,6 +218,7 @@ impl ConnectorHandler {
|
||||||
for ws in on.workspaces.iter() {
|
for ws in on.workspaces.iter() {
|
||||||
let is_visible =
|
let is_visible =
|
||||||
!target_is_dummy && target.workspaces.is_empty() && ws.visible.get();
|
!target_is_dummy && target.workspaces.is_empty() && ws.visible.get();
|
||||||
|
ws.visible_on_desired_output.set(ws.visible.get());
|
||||||
ws.output.set(target.clone());
|
ws.output.set(target.clone());
|
||||||
target.workspaces.add_last_existing(&ws);
|
target.workspaces.add_last_existing(&ws);
|
||||||
if is_visible {
|
if is_visible {
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ impl OutputNode {
|
||||||
};
|
};
|
||||||
let workspace = Rc::new(WorkspaceNode {
|
let workspace = Rc::new(WorkspaceNode {
|
||||||
id: self.state.node_ids.next(),
|
id: self.state.node_ids.next(),
|
||||||
|
is_dummy: false,
|
||||||
output: CloneCell::new(self.clone()),
|
output: CloneCell::new(self.clone()),
|
||||||
position: Default::default(),
|
position: Default::default(),
|
||||||
container: Default::default(),
|
container: Default::default(),
|
||||||
|
|
@ -177,6 +178,8 @@ impl OutputNode {
|
||||||
output_link: Default::default(),
|
output_link: Default::default(),
|
||||||
visible: Cell::new(true),
|
visible: Cell::new(true),
|
||||||
fullscreen: Default::default(),
|
fullscreen: Default::default(),
|
||||||
|
visible_on_desired_output: Cell::new(false),
|
||||||
|
desired_output: CloneCell::new(self.global.output_id.clone()),
|
||||||
});
|
});
|
||||||
self.state.workspaces.set(name, workspace.clone());
|
self.state.workspaces.set(name, workspace.clone());
|
||||||
workspace
|
workspace
|
||||||
|
|
@ -214,6 +217,7 @@ impl OutputNode {
|
||||||
pub fn create_workspace(self: &Rc<Self>, name: &str) -> Rc<WorkspaceNode> {
|
pub fn create_workspace(self: &Rc<Self>, name: &str) -> Rc<WorkspaceNode> {
|
||||||
let ws = Rc::new(WorkspaceNode {
|
let ws = Rc::new(WorkspaceNode {
|
||||||
id: self.state.node_ids.next(),
|
id: self.state.node_ids.next(),
|
||||||
|
is_dummy: false,
|
||||||
output: CloneCell::new(self.clone()),
|
output: CloneCell::new(self.clone()),
|
||||||
position: Cell::new(Default::default()),
|
position: Cell::new(Default::default()),
|
||||||
container: Default::default(),
|
container: Default::default(),
|
||||||
|
|
@ -223,6 +227,8 @@ impl OutputNode {
|
||||||
output_link: Cell::new(None),
|
output_link: Cell::new(None),
|
||||||
visible: Cell::new(false),
|
visible: Cell::new(false),
|
||||||
fullscreen: Default::default(),
|
fullscreen: Default::default(),
|
||||||
|
visible_on_desired_output: Cell::new(false),
|
||||||
|
desired_output: CloneCell::new(self.global.output_id.clone()),
|
||||||
});
|
});
|
||||||
ws.output_link
|
ws.output_link
|
||||||
.set(Some(self.workspaces.add_last(ws.clone())));
|
.set(Some(self.workspaces.add_last(ws.clone())));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
cursor::KnownCursor,
|
cursor::KnownCursor,
|
||||||
ifs::wl_seat::{NodeSeatState, WlSeatGlobal},
|
ifs::{
|
||||||
|
wl_output::OutputId,
|
||||||
|
wl_seat::{NodeSeatState, WlSeatGlobal},
|
||||||
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
render::Renderer,
|
render::Renderer,
|
||||||
tree::{
|
tree::{
|
||||||
|
|
@ -20,6 +23,7 @@ tree_id!(WorkspaceNodeId);
|
||||||
|
|
||||||
pub struct WorkspaceNode {
|
pub struct WorkspaceNode {
|
||||||
pub id: WorkspaceNodeId,
|
pub id: WorkspaceNodeId,
|
||||||
|
pub is_dummy: bool,
|
||||||
pub output: CloneCell<Rc<OutputNode>>,
|
pub output: CloneCell<Rc<OutputNode>>,
|
||||||
pub position: Cell<Rect>,
|
pub position: Cell<Rect>,
|
||||||
pub container: CloneCell<Option<Rc<ContainerNode>>>,
|
pub container: CloneCell<Option<Rc<ContainerNode>>>,
|
||||||
|
|
@ -29,6 +33,8 @@ pub struct WorkspaceNode {
|
||||||
pub output_link: Cell<Option<LinkedNode<Rc<WorkspaceNode>>>>,
|
pub output_link: Cell<Option<LinkedNode<Rc<WorkspaceNode>>>>,
|
||||||
pub visible: Cell<bool>,
|
pub visible: Cell<bool>,
|
||||||
pub fullscreen: CloneCell<Option<Rc<dyn ToplevelNode>>>,
|
pub fullscreen: CloneCell<Option<Rc<dyn ToplevelNode>>>,
|
||||||
|
pub visible_on_desired_output: Cell<bool>,
|
||||||
|
pub desired_output: CloneCell<Rc<OutputId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkspaceNode {
|
impl WorkspaceNode {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue