Fix next/prev-window commands

The prev-window commands never worked.  They only switched between the last two
recently used windows ignoring all others.
timeout_old
Tassilo Horn 3 years ago
parent 637cbff935
commit d83acacea0
  1. 51
      src/cmds.rs
  2. 7
      src/con.rs
  3. 1
      src/demon.rs

@ -26,6 +26,7 @@ use rand;
use rand::prelude::SliceRandom;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::atomic;
use std::sync::Arc;
use std::sync::RwLock;
use swayipc as s;
@ -140,6 +141,24 @@ pub enum SwayrCommand {
ExecuteSwayrCommand,
}
impl SwayrCommand {
fn is_prev_next_window_variant(&self) -> bool {
matches!(
self,
SwayrCommand::NextWindow { .. }
| SwayrCommand::PrevWindow { .. }
| SwayrCommand::NextTiledWindow { .. }
| SwayrCommand::PrevTiledWindow { .. }
| SwayrCommand::NextTabbedOrStackedWindow { .. }
| SwayrCommand::PrevTabbedOrStackedWindow { .. }
| SwayrCommand::NextFloatingWindow { .. }
| SwayrCommand::PrevFloatingWindow { .. }
| SwayrCommand::NextSimilarWindow { .. }
| SwayrCommand::PrevSimilarWindow { .. }
)
}
}
pub struct ExecSwayrCmdArgs<'a> {
pub cmd: &'a SwayrCommand,
pub extra_props: Arc<RwLock<HashMap<i64, con::ExtraProps>>>,
@ -156,8 +175,25 @@ fn always_true(_x: &con::Window) -> bool {
true
}
static IN_NEXT_PREV_WINDOW_SEQ: atomic::AtomicBool =
atomic::AtomicBool::new(false);
pub fn exec_swayr_cmd(args: ExecSwayrCmdArgs) {
let props = args.extra_props;
if args.cmd.is_prev_next_window_variant() {
let before =
IN_NEXT_PREV_WINDOW_SEQ.swap(true, atomic::Ordering::SeqCst);
if !before {
let mut map = props.write().unwrap();
for val in map.values_mut() {
val.last_focus_time_for_next_prev_seq = val.last_focus_time;
}
}
} else {
IN_NEXT_PREV_WINDOW_SEQ.store(false, atomic::Ordering::SeqCst);
}
match args.cmd {
SwayrCommand::SwitchToUrgentOrLRUWindow => {
switch_to_urgent_or_lru_window(Some(&*props.read().unwrap()))
@ -393,15 +429,22 @@ pub fn focus_window_in_direction(
}
};
let windows: Vec<con::Window> = con::get_windows(root, false, extra_props)
.into_iter()
.filter(|w| pred(w))
.collect();
let mut windows: Vec<con::Window> =
con::get_windows(root, false, extra_props)
.into_iter()
.filter(|w| pred(w))
.collect();
if windows.len() < 2 {
return;
}
windows.sort_by(|a, b| {
let lru_a = a.last_focus_time_for_next_prev_seq();
let lru_b = b.last_focus_time_for_next_prev_seq();
lru_a.cmp(&lru_b).reverse()
});
let is_focused_window: Box<dyn Fn(&con::Window) -> bool> =
if !windows.iter().any(|w| w.is_focused()) {
let last_focused_win_id = windows.get(0).unwrap().get_id();

@ -113,6 +113,7 @@ impl NodeMethods for s::Node {
pub struct ExtraProps {
/// Milliseconds since UNIX epoch.
pub last_focus_time: u128,
pub last_focus_time_for_next_prev_seq: u128,
}
#[derive(Debug)]
@ -176,6 +177,12 @@ impl Window<'_> {
let layout = &self.get_parent().layout;
layout == &s::NodeLayout::Tabbed || layout == &s::NodeLayout::Stacked
}
pub fn last_focus_time_for_next_prev_seq(&self) -> u128 {
self.extra_props
.as_ref()
.map_or(0, |wp| wp.last_focus_time_for_next_prev_seq)
}
}
impl PartialEq for Window<'_> {

@ -186,6 +186,7 @@ fn update_last_focus_time(
id,
con::ExtraProps {
last_focus_time: get_epoch_time_as_millis(),
last_focus_time_for_next_prev_seq: 0,
},
);
}

Loading…
Cancel
Save