swaywm/sway

bindsym for a single keypress

Closed this issue · 1 comments

Hi,

It would be nice to be able to bindsym to a single keypress (like the way windows/kde uses to open it's launcher), instead of having to do this with a script.

I do this:

  • bind a no-op keycode for Super press/release
  • listen for the press-nop with a script
  • make sure no other keybind is pressed until the release-nop is triggered
  • add a 1 second timeout (for the case I simply forget my binds)

My current code, in case anyone is interested (it's rust):

use swayipc::{Connection, Fallible, EventType::Binding, Event};
use std::time::SystemTime;

fn main() -> Fallible<()> {
    let sway = Connection::new()?;
    let mut sway2 = Connection::new()?;

    let mut args = std::env::args();
   	let key: String = args.nth(1).unwrap();
    let mut exec: String = args.next().unwrap();
    for arg in args {
    	exec.push(' ');
    	exec.push_str(&arg)
    }
    let mut listen = false;
    let mut now = SystemTime::now();
        
    for event in sway.subscribe(vec![Binding])? {
    	if let Ok(Event::Binding(event)) = event {
    		if event.binding.command == format!("nop {}down", &key) {
    			listen = true;
    			now = SystemTime::now();
    		} else if event.binding.command == format!("nop {}up", &key) && listen && now.elapsed().unwrap().as_secs() < 1 {
				sway2.run_command(format!("exec {}", &exec))?;
       		} else {
    			listen = false;
    		}
    	}
    }
    Ok(())
}

I got the solution from the hyprland wiki:

# Start wofi opens wofi on first press, closes it on second
bindr=SUPER, SUPER_L, exec, pkill wofi || wofi

and this works on sway too, as it is masked when a keybind is pressed before.

bindsym --no-repeat --release Super_L exec sirula

I will add this into the sway wiki