fix: never evict the thumbnail being dragged
This commit is contained in:
1 parent
c660001a6e
commit
7998efd3c2
3 files changed
+36
-8
No files matched your search
+11
-8
@@ -4,7 +4,7 @@
|
|||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::io::{ErrorKind, Read, Write};
|
use std::io::{ErrorKind, Read, Write};
|
||||||
use std::os::unix::net::{UnixListener, UnixStream};
|
use std::os::unix::net::{UnixListener, UnixStream};
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@@ -103,6 +103,8 @@ pub struct Host {
|
|||||||
/// The drag-out in progress. Dropping the source cancels the drag.
|
/// The drag-out in progress. Dropping the source cancels the drag.
|
||||||
struct Drag {
|
struct Drag {
|
||||||
thumb: u64,
|
thumb: u64,
|
||||||
|
/// Kept here so the drop still delivers if the thumbnail goes away.
|
||||||
|
path: PathBuf,
|
||||||
source: DragSource,
|
source: DragSource,
|
||||||
icon: WlSurface,
|
icon: WlSurface,
|
||||||
icon_viewport: WpViewport,
|
icon_viewport: WpViewport,
|
||||||
@@ -172,7 +174,9 @@ pub fn run() -> Result<()> {
|
|||||||
.run(Duration::from_millis(500), &mut state, |state| {
|
.run(Duration::from_millis(500), &mut state, |state| {
|
||||||
let host = state.preview.as_mut().expect("host state");
|
let host = state.preview.as_mut().expect("host state");
|
||||||
host.tidy();
|
host.tidy();
|
||||||
let busy = host.thumbs.len() + host.writers.load(Ordering::SeqCst);
|
let busy = host.thumbs.len()
|
||||||
|
+ host.writers.load(Ordering::SeqCst)
|
||||||
|
+ usize::from(host.drag.is_some());
|
||||||
if host.core.should_exit(busy, Instant::now()) {
|
if host.core.should_exit(busy, Instant::now()) {
|
||||||
signal.stop();
|
signal.stop();
|
||||||
}
|
}
|
||||||
@@ -281,10 +285,7 @@ impl Host {
|
|||||||
let Some(drag) = self.drag.as_ref().filter(|d| d.source.inner() == source) else {
|
let Some(drag) = self.drag.as_ref().filter(|d| d.source.inner() == source) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(thumb) = self.thumbs.iter().find(|t| t.id == drag.thumb) else {
|
let path = drag.path.clone();
|
||||||
return;
|
|
||||||
};
|
|
||||||
let path = thumb.path.clone();
|
|
||||||
let writers = Arc::clone(&self.writers);
|
let writers = Arc::clone(&self.writers);
|
||||||
writers.fetch_add(1, Ordering::SeqCst);
|
writers.fetch_add(1, Ordering::SeqCst);
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
@@ -394,6 +395,7 @@ fn start_drag(state: &mut State, i: usize, start: DragStart, qh: &QueueHandle<St
|
|||||||
tracing::info!("drag-out started for {}", thumb.path.display());
|
tracing::info!("drag-out started for {}", thumb.path.display());
|
||||||
host.drag = Some(Drag {
|
host.drag = Some(Drag {
|
||||||
thumb: thumb.id,
|
thumb: thumb.id,
|
||||||
|
path: thumb.path.clone(),
|
||||||
source,
|
source,
|
||||||
icon,
|
icon,
|
||||||
icon_viewport,
|
icon_viewport,
|
||||||
@@ -469,8 +471,9 @@ fn add(state: &mut State, path: &Path, output_name: &str) -> Result<()> {
|
|||||||
let open: Vec<usize> = (0..host.thumbs.len())
|
let open: Vec<usize> = (0..host.thumbs.len())
|
||||||
.filter(|&i| host.thumbs[i].output == output.geom.name && !host.thumbs[i].is_closing())
|
.filter(|&i| host.thumbs[i].output == output.geom.name && !host.thumbs[i].is_closing())
|
||||||
.collect();
|
.collect();
|
||||||
for &i in open.iter().take(stack::excess(open.len())) {
|
let dragging: Vec<bool> = open.iter().map(|&i| host.thumbs[i].is_dragging()).collect();
|
||||||
host.thumbs[i].slide_out(&qh);
|
for k in stack::evictions(&dragging) {
|
||||||
|
host.thumbs[open[k]].slide_out(&qh);
|
||||||
}
|
}
|
||||||
host.restack();
|
host.restack();
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,17 @@ pub fn excess(count: usize) -> usize {
|
|||||||
count.saturating_sub(MAX)
|
count.saturating_sub(MAX)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Which thumbnails to evict, given whether each open one (oldest first) is
|
||||||
|
/// being dragged. A dragged one is skipped: evicting it would leave the drop
|
||||||
|
/// with nothing to deliver.
|
||||||
|
pub fn evictions(dragging_oldest_first: &[bool]) -> Vec<usize> {
|
||||||
|
let count = excess(dragging_oldest_first.len());
|
||||||
|
(0..dragging_oldest_first.len())
|
||||||
|
.filter(|&i| !dragging_oldest_first[i])
|
||||||
|
.take(count)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// What a pointer release on a thumbnail means.
|
/// What a pointer release on a thumbnail means.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Release {
|
pub enum Release {
|
||||||
@@ -191,6 +202,16 @@ mod tests {
|
|||||||
assert_eq!(bottom_margins(&[124, 124, 220]), vec![16, 152, 288]);
|
assert_eq!(bottom_margins(&[124, 124, 220]), vec![16, 152, 288]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eviction_skips_a_dragged_thumbnail() {
|
||||||
|
// Oldest first; `true` = being dragged.
|
||||||
|
let none = [false; 6];
|
||||||
|
assert_eq!(evictions(&none), vec![0]);
|
||||||
|
let oldest_dragged = [true, false, false, false, false, false];
|
||||||
|
assert_eq!(evictions(&oldest_dragged), vec![1]);
|
||||||
|
assert_eq!(evictions(&[false; 5]), Vec::<usize>::new());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn eviction_beyond_five() {
|
fn eviction_beyond_five() {
|
||||||
assert_eq!(excess(5), 0);
|
assert_eq!(excess(5), 0);
|
||||||
|
|||||||
@@ -240,6 +240,10 @@ impl Thumbnail {
|
|||||||
self.closing && (!self.visible() || anim_over(self.anim, Instant::now()))
|
self.closing && (!self.visible() || anim_over(self.anim, Instant::now()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_dragging(&self) -> bool {
|
||||||
|
self.dragging
|
||||||
|
}
|
||||||
|
|
||||||
fn visible(&self) -> bool {
|
fn visible(&self) -> bool {
|
||||||
!self.hidden && !self.dragging
|
!self.hidden && !self.dragging
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user