Fix various toggle-visible issues

- Track "start" command internally as a special mode.
- Ensure that DoubleMemPool is in good state if draw bails.
- Ensure that Launcher does not terminate daemonized session.
- Ensure that size changes cause full force redraw.
This commit is contained in:
Kenny Levinsen
2019-09-17 16:32:51 +02:00
parent f2999fb53f
commit 4ca4fa307a
3 changed files with 89 additions and 46 deletions
+60 -42
View File
@@ -21,6 +21,7 @@ use crate::widget::{DrawContext, Widget};
use crate::cmd::Cmd;
use crate::doublemempool::DoubleMemPool;
#[derive(Debug)]
pub enum OutputMode {
Active,
All,
@@ -123,47 +124,49 @@ impl AppInner {
self.configured_surfaces = Arc::new(Mutex::new(0));
if self.visible {
match self.output_mode {
OutputMode::Active => {
if self.shell_surfaces.len() > 0 {
return;
}
if !self.visible {
self.surfaces = Vec::new();
self.shell_surfaces = Vec::new();
return;
}
match self.output_mode {
OutputMode::Active => {
if self.shell_surfaces.len() > 0 {
return;
}
let (surface, shell_surface) = AppInner::add_shell_surface(
&compositor,
&shell,
self.scale,
self.configured_surfaces.clone(),
self.draw_tx.clone(),
None,
);
self.surfaces = vec![surface];
self.shell_surfaces = vec![shell_surface];
}
OutputMode::All => {
let mut surfaces = Vec::new();
let mut shell_surfaces = Vec::new();
for output in self.outputs.iter() {
let (surface, shell_surface) = AppInner::add_shell_surface(
&compositor,
&shell,
self.scale,
self.configured_surfaces.clone(),
self.draw_tx.clone(),
None,
Some(&output.1),
);
self.surfaces = vec![surface];
self.shell_surfaces = vec![shell_surface];
}
OutputMode::All => {
let mut surfaces = Vec::new();
let mut shell_surfaces = Vec::new();
for output in self.outputs.iter() {
let (surface, shell_surface) = AppInner::add_shell_surface(
&compositor,
&shell,
self.scale,
self.configured_surfaces.clone(),
self.draw_tx.clone(),
Some(&output.1),
);
surfaces.push(surface);
shell_surfaces.push(shell_surface);
}
self.surfaces = surfaces;
self.shell_surfaces = shell_surfaces;
surfaces.push(surface);
shell_surfaces.push(shell_surface);
}
self.surfaces = surfaces;
self.shell_surfaces = shell_surfaces;
}
self.draw_tx.send(Cmd::ForceDraw).unwrap();
} else {
self.surfaces = Vec::new();
self.shell_surfaces = Vec::new();
}
self.draw_tx.send(Cmd::ForceDraw).unwrap();
}
fn add_output(&mut self, id: u32, output: wl_output::WlOutput) {
@@ -210,7 +213,7 @@ pub struct App {
}
impl App {
pub fn redraw(&mut self, mut force: bool) -> Result<(), ::std::io::Error> {
pub fn redraw(&mut self, force: bool) -> Result<(), ::std::io::Error> {
let widget = match self.widget {
Some(ref mut widget) => widget,
None => return Ok(()),
@@ -219,7 +222,9 @@ impl App {
let inner = self.inner.lock().unwrap();
let time = Local::now();
if inner.shell_surfaces.len() != *inner.configured_surfaces.lock().unwrap() {
if !inner.visible ||
inner.shell_surfaces.len() != *inner.configured_surfaces.lock().unwrap() ||
inner.surfaces.len() == 0 {
// Not ready yet
return Ok(());
}
@@ -231,6 +236,7 @@ impl App {
let size = widget.size();
let size_changed = self.last_dim != size;
let force = force | size_changed;
// resize the pool if relevant
pool.resize((4 * size.0 * size.1) as usize)
@@ -239,8 +245,8 @@ impl App {
let mut buf = Buffer::new(mmap, size);
// Copy old damage
if let Some(d) = &self.last_damage {
if !size_changed {
let force = match (force, &self.last_damage) {
(false, Some(d)) => {
let lastmmap = last.mmap();
let last = Buffer::new(lastmmap, size);
@@ -250,12 +256,10 @@ impl App {
for d in d {
last.copy_to(&mut buf, d.clone());
}
} else {
force = true;
false
}
} else {
force = true;
}
_ => true
};
if force {
buf.memset(&self.bg);
@@ -272,8 +276,9 @@ impl App {
mmap.flush().unwrap();
if !size_changed && !report.full_damage && report.damage.len() == 0 {
if !force && !report.full_damage && report.damage.len() == 0 {
// Nothing to do
self.pools.never_mind();
return Ok(());
}
@@ -319,6 +324,20 @@ impl App {
inner.outputs_changed();
}
pub fn hide(&mut self) {
let mut inner = self.inner.lock().unwrap();
inner.visible = false;
self.last_dim = (0, 0);
inner.outputs_changed();
}
pub fn show(&mut self) {
let mut inner = self.inner.lock().unwrap();
inner.visible = true;
self.last_dim = (0, 0);
inner.outputs_changed();
}
pub fn cmd_queue(&self) -> Arc<Mutex<VecDeque<Cmd>>> {
self.cmd_queue.clone()
}
@@ -470,7 +489,6 @@ impl App {
},
));
inner.lock().unwrap().outputs_changed();
event_queue.sync_roundtrip().unwrap();
//
+5 -1
View File
@@ -19,7 +19,7 @@ impl DoubleMemPool {
pub fn pool(&mut self) -> Option<(&mut MemPool, &mut MemPool)> {
let switch = self.switch;
self.switch = !self.switch;
let (last, cur) = if switch {
let (last, cur) = if !switch {
(&mut self.pool2, &mut self.pool1)
} else {
(&mut self.pool1, &mut self.pool2)
@@ -31,4 +31,8 @@ impl DoubleMemPool {
Some((last, cur))
}
}
pub fn never_mind(&mut self) {
self.switch = !self.switch;
}
}
+24 -3
View File
@@ -25,6 +25,7 @@ use cmd::Cmd;
enum Mode {
Start,
Daemonize,
StartOrKill,
ToggleVisible,
PrintConfig(bool),
@@ -63,7 +64,7 @@ fn main() {
let mode = match args.len() {
1 => Mode::Start,
2 => match args[1].as_str() {
"start" => Mode::Start,
"start" => Mode::Daemonize,
"start-or-kill" => Mode::StartOrKill,
"toggle-visible" => Mode::ToggleVisible,
"print-config" => Mode::PrintConfig(!is_yaml),
@@ -80,6 +81,8 @@ fn main() {
}
};
let mut daemon = false;
match mode {
Mode::ToggleVisible => {
if let Ok(mut socket) = UnixStream::connect(socket_path.clone()) {
@@ -101,6 +104,13 @@ fn main() {
std::process::exit(1);
};
}
Mode::Daemonize => {
if let Ok(_) = UnixStream::connect(socket_path.clone()) {
eprintln!("wldash is already running");
std::process::exit(1);
};
daemon = true;
}
Mode::PrintConfig(json) => {
if json {
println!("{}", serde_json::to_string_pretty(&config).unwrap());
@@ -133,6 +143,11 @@ fn main() {
});
let mut app = App::new(tx_draw, output_mode, background, scale);
if daemon {
app.hide();
} else {
app.show();
}
let widget = mod_rx.recv().unwrap();
app.set_widget(widget).unwrap();
@@ -224,10 +239,16 @@ fn main() {
}
Cmd::ToggleVisible => {
app.toggle_visible();
app.flush_display();
}
Cmd::Exit => {
let _ = std::fs::remove_file(socket_path);
return;
if daemon {
app.hide();
app.flush_display();
} else {
let _ = std::fs::remove_file(socket_path);
return;
}
}
},
None => {