Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3eb7cddb6c | ||
|
|
2813ae0eff | ||
|
|
1b1ffc4435 | ||
|
|
cf9fabb052 | ||
|
|
43fe73bf09 | ||
|
|
d291e36b3f | ||
|
|
fe37c15f95 | ||
|
|
d4f62da6f5 | ||
|
|
1edefd9cad | ||
|
|
90ffa7df27 | ||
|
|
d69e941ec1 | ||
|
|
5e5e8876f6 | ||
|
|
886d595f91 | ||
|
|
e04237b928 | ||
|
|
ef84c519a2 | ||
|
|
1e647c7036 | ||
|
|
56f6b1668d |
@@ -1,4 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
liberapay: kennylevinsen
|
||||
custom: https://donate.kl.wtf/
|
||||
|
||||
Generated
+46
@@ -152,6 +152,12 @@ version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
@@ -185,6 +191,15 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.7"
|
||||
@@ -520,6 +535,15 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.123"
|
||||
@@ -663,6 +687,17 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
@@ -744,6 +779,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
@@ -762,6 +806,7 @@ dependencies = [
|
||||
"dlib",
|
||||
"fontconfig",
|
||||
"fuzzy-matcher",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"libpulse-binding",
|
||||
"memmap",
|
||||
@@ -776,6 +821,7 @@ dependencies = [
|
||||
"shlex",
|
||||
"timerfd",
|
||||
"unicode-segmentation",
|
||||
"walkdir",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
]
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wldash"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["Kenny Levinsen <kl@kl.wtf>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -37,6 +37,8 @@ rcalc_lib = "0.9"
|
||||
rust-ini = "0.14"
|
||||
shlex = "0.1"
|
||||
timerfd = "1.0.0"
|
||||
walkdir = "2.3.2"
|
||||
itertools = "0.10.3"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
|
||||
@@ -66,3 +66,7 @@ The launcher also accepts prefix operators to change its mode:
|
||||
- Configurability
|
||||
- Cleanup and reorganization
|
||||
- Proper line editor for the launcher
|
||||
|
||||
## How to discuss
|
||||
|
||||
Go to #kennylevinsen @ irc.libera.chat to discuss, or use [~kennylevinsen/public-inbox@lists.sr.ht](https://lists.sr.ht/~kennylevinsen/public-inbox).
|
||||
|
||||
+3
-3
@@ -37,8 +37,8 @@
|
||||
{"launcher": {
|
||||
"font_size": 32.0,
|
||||
"length": 1200,
|
||||
"app_opener": "swaymsg exec ",
|
||||
"term_opener": "alacritty -e ",
|
||||
"app_opener": "swaymsg exec -- ",
|
||||
"term_opener": "foot --",
|
||||
"url_opener": "xdg-open "
|
||||
}}
|
||||
]}
|
||||
@@ -52,4 +52,4 @@
|
||||
"blue": 0,
|
||||
"opacity": 0.9
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -45,6 +45,6 @@ widget:
|
||||
- launcher:
|
||||
font_size: 32.0
|
||||
length: 1200
|
||||
app_opener: "swaymsg exec "
|
||||
term_opener: "alacritty -e "
|
||||
app_opener: "swaymsg exec --"
|
||||
term_opener: "foot --"
|
||||
url_opener: "xdg-open "
|
||||
|
||||
+40
-40
@@ -5,11 +5,9 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use chrono::{Duration, Local, NaiveDateTime};
|
||||
|
||||
use crate::keyboard::{
|
||||
keysyms, map_keyboard, Event as KbEvent, KeyState, ModifiersState,
|
||||
};
|
||||
use crate::keyboard::{keysyms, map_keyboard, Event as KbEvent, KeyState, ModifiersState};
|
||||
|
||||
use wayland_client::protocol::{wl_compositor, wl_output, wl_pointer, wl_shm, wl_surface, wl_seat};
|
||||
use wayland_client::protocol::{wl_compositor, wl_output, wl_pointer, wl_seat, wl_shm, wl_surface};
|
||||
use wayland_client::{Display, EventQueue, GlobalEvent, GlobalManager, Main};
|
||||
use wayland_protocols::wlr::unstable::layer_shell::v1::client::{
|
||||
zwlr_layer_shell_v1, zwlr_layer_surface_v1,
|
||||
@@ -17,7 +15,7 @@ use wayland_protocols::wlr::unstable::layer_shell::v1::client::{
|
||||
|
||||
use crate::buffer::Buffer;
|
||||
use crate::color::Color;
|
||||
use crate::widget::{WaitContext, DrawContext, Widget};
|
||||
use crate::widget::{DrawContext, WaitContext, Widget};
|
||||
|
||||
use crate::cmd::Cmd;
|
||||
use crate::doublemempool::DoubleMemPool;
|
||||
@@ -68,28 +66,29 @@ impl AppInner {
|
||||
Main<wl_surface::WlSurface>,
|
||||
Main<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1>,
|
||||
) {
|
||||
let surface = compositor
|
||||
.create_surface();
|
||||
let surface = compositor.create_surface();
|
||||
|
||||
let this_is_stupid = AtomicBool::new(false);
|
||||
|
||||
let shell_surface = shell
|
||||
.get_layer_surface(
|
||||
&surface,
|
||||
output,
|
||||
zwlr_layer_shell_v1::Layer::Overlay,
|
||||
"".to_string());
|
||||
shell_surface.quick_assign(move |layer, event, _| match event {
|
||||
zwlr_layer_surface_v1::Event::Configure { serial, .. } => {
|
||||
if !this_is_stupid.compare_and_swap(false, true, Ordering::SeqCst) {
|
||||
*(configured_surfaces.lock().unwrap()) += 1;
|
||||
layer.ack_configure(serial);
|
||||
tx.send(Cmd::ForceDraw).unwrap();
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
let shell_surface = shell.get_layer_surface(
|
||||
&surface,
|
||||
output,
|
||||
zwlr_layer_shell_v1::Layer::Overlay,
|
||||
"".to_string(),
|
||||
);
|
||||
shell_surface.quick_assign(move |layer, event, _| match event {
|
||||
zwlr_layer_surface_v1::Event::Configure { serial, .. } => {
|
||||
if this_is_stupid
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_ok()
|
||||
{
|
||||
*(configured_surfaces.lock().unwrap()) += 1;
|
||||
layer.ack_configure(serial);
|
||||
tx.send(Cmd::ForceDraw).unwrap();
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
});
|
||||
|
||||
shell_surface.set_keyboard_interactivity(1);
|
||||
shell_surface.set_size(1, 1);
|
||||
@@ -401,8 +400,7 @@ impl<'a> App<'a> {
|
||||
version,
|
||||
} => {
|
||||
if let "wl_output" = &interface[..] {
|
||||
let output = registry
|
||||
.bind(version, id);
|
||||
let output = registry.bind(std::cmp::min(version, 3), id);
|
||||
inner_global.lock().unwrap().add_output(id, output);
|
||||
}
|
||||
}
|
||||
@@ -415,8 +413,8 @@ impl<'a> App<'a> {
|
||||
|
||||
// double sync to retrieve the global list
|
||||
// and the globals metadata
|
||||
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
|
||||
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
|
||||
|
||||
// wl_compositor
|
||||
let compositor = manager
|
||||
@@ -435,10 +433,8 @@ impl<'a> App<'a> {
|
||||
//
|
||||
// Get our seat
|
||||
//
|
||||
let seat: Main<wl_seat::WlSeat> = manager
|
||||
.instantiate_range(1, 6)
|
||||
.unwrap();
|
||||
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
|
||||
let seat: Main<wl_seat::WlSeat> = manager.instantiate_range(1, 6).unwrap();
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
|
||||
|
||||
//
|
||||
// Keyboard processing
|
||||
@@ -453,7 +449,7 @@ impl<'a> App<'a> {
|
||||
num_lock: false,
|
||||
}));
|
||||
|
||||
let keyboard = Arc::new(Mutex::new(AppKeyboard{
|
||||
let keyboard = Arc::new(Mutex::new(AppKeyboard {
|
||||
current: None,
|
||||
delay: 0,
|
||||
rate: 0,
|
||||
@@ -485,7 +481,10 @@ impl<'a> App<'a> {
|
||||
let mut kbd = kb2.lock().unwrap();
|
||||
kbd.current = Some(ev.clone());
|
||||
kbd.next = if kbd.delay > 0 {
|
||||
Some(Local::now().naive_local() + Duration::milliseconds(kbd.delay.into()))
|
||||
Some(
|
||||
Local::now().naive_local()
|
||||
+ Duration::milliseconds(kbd.delay.into()),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -496,10 +495,10 @@ impl<'a> App<'a> {
|
||||
} else {
|
||||
kb2.lock().unwrap().next = None;
|
||||
}
|
||||
},
|
||||
}
|
||||
KbEvent::Leave { .. } => {
|
||||
kb2.lock().unwrap().next = None;
|
||||
},
|
||||
}
|
||||
KbEvent::RepeatInfo { delay, rate } => {
|
||||
let mut kbd = kb2.lock().unwrap();
|
||||
kbd.delay = delay;
|
||||
@@ -513,15 +512,16 @@ impl<'a> App<'a> {
|
||||
//
|
||||
// Prepare shell so that we can create our shell surface
|
||||
//
|
||||
inner.lock().unwrap().set_shell(Some(
|
||||
if let Ok(layer) = manager.instantiate_exact(1) {
|
||||
inner
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_shell(Some(if let Ok(layer) = manager.instantiate_exact(1) {
|
||||
layer
|
||||
} else {
|
||||
panic!("server didn't advertise `zwlr_layer_shell_v1`");
|
||||
},
|
||||
));
|
||||
}));
|
||||
|
||||
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
|
||||
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
|
||||
|
||||
//
|
||||
// Cursor processing
|
||||
|
||||
+1
-1
@@ -345,6 +345,6 @@ impl Default for Config {
|
||||
fn get_font<'a>(name: &str, map: &'a FontMap) -> FontRef<'a> {
|
||||
match map.get(name) {
|
||||
Some(f) => f,
|
||||
None => panic!(format!("Font {} is missing from the config", name)),
|
||||
None => panic!("Font {} is missing from the config", name),
|
||||
}
|
||||
}
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fs::{create_dir_all, File, OpenOptions};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Data {
|
||||
pub entries: HashMap<String, i64>,
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn load() -> Result<Data, Box<dyn Error>> {
|
||||
Ok(serde_yaml::from_reader(Self::read_file()?)?)
|
||||
}
|
||||
|
||||
pub fn save(&self) -> Result<(), Box<dyn Error>> {
|
||||
Ok(serde_yaml::to_writer(Self::write_file()?, self)?)
|
||||
}
|
||||
|
||||
fn read_file() -> Result<File, Box<dyn Error>> {
|
||||
Ok(OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.read(true)
|
||||
.open(Self::path()?)?)
|
||||
}
|
||||
|
||||
fn write_file() -> Result<File, Box<dyn Error>> {
|
||||
Ok(OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(Self::path()?)?)
|
||||
}
|
||||
|
||||
fn path() -> Result<PathBuf, Box<dyn Error>> {
|
||||
let xdg_cache = match env::var_os("XDG_CACHE_HOME") {
|
||||
Some(s) => s
|
||||
.into_string()
|
||||
.map_err(|_| "Unable to resolve $XDG_CACHE_HOME")?,
|
||||
None => format!(
|
||||
"{}/.cache",
|
||||
env::var_os("HOME")
|
||||
.ok_or("Unable to resolve $HOME")?
|
||||
.into_string()
|
||||
.map_err(|_| "Unable to resolve $HOME")?
|
||||
),
|
||||
};
|
||||
|
||||
let cache_dir = PathBuf::from(xdg_cache).join("wldash");
|
||||
create_dir_all(&cache_dir)?;
|
||||
|
||||
Ok(cache_dir.join("data.yaml"))
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -1,11 +1,12 @@
|
||||
extern crate ini;
|
||||
use ini::{Ini, ParseOption};
|
||||
use itertools::Itertools;
|
||||
use std::cmp::Ordering;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fs;
|
||||
use std::io::Error as io_error;
|
||||
use std::io::ErrorKind;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash)]
|
||||
pub struct Desktop {
|
||||
@@ -56,7 +57,7 @@ impl Desktop {
|
||||
|
||||
fn parse_dir(d: &str) -> Result<Vec<Desktop>, Box<dyn Error>> {
|
||||
let mut files: Vec<Desktop> = Vec::with_capacity(16);
|
||||
for entry in fs::read_dir(d)? {
|
||||
for entry in WalkDir::new(d) {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
@@ -107,5 +108,6 @@ pub fn load_desktop_files() -> Vec<Desktop> {
|
||||
.filter(|d| {
|
||||
!d.hidden && !d.no_display && (d.entry_type == "Application" || d.entry_type == "Link")
|
||||
})
|
||||
.unique_by(|x| x.name.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -209,9 +209,9 @@ fn create_shm_fd() -> io::Result<RawFd> {
|
||||
Err(nix::Error::Sys(errno)) => match unistd::close(fd) {
|
||||
Ok(_) => return Err(io::Error::from(errno)),
|
||||
Err(nix::Error::Sys(errno)) => return Err(io::Error::from(errno)),
|
||||
Err(err) => panic!(err),
|
||||
Err(err) => panic!("{}", err),
|
||||
},
|
||||
Err(err) => panic!(err),
|
||||
Err(err) => panic!("{}", err),
|
||||
},
|
||||
Err(nix::Error::Sys(Errno::EEXIST)) => {
|
||||
// If a file with that handle exists then change the handle
|
||||
@@ -228,7 +228,6 @@ fn create_shm_fd() -> io::Result<RawFd> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct DoubleMemPool {
|
||||
pool1: MemPool,
|
||||
pool2: MemPool,
|
||||
|
||||
+11
-9
@@ -8,16 +8,16 @@ struct CachedGlyph {
|
||||
dimensions: (u32, u32),
|
||||
origin: (i32, i32),
|
||||
render: Vec<f32>,
|
||||
advance: i32,
|
||||
}
|
||||
|
||||
impl CachedGlyph {
|
||||
fn new(font: FontRef, size: f32, ch: char) -> CachedGlyph {
|
||||
let scale = Scale::uniform(size);
|
||||
let v_metrics = font.v_metrics(scale);
|
||||
let glyph = font
|
||||
.glyph(ch)
|
||||
.scaled(scale)
|
||||
.positioned(point(0.0, v_metrics.ascent));
|
||||
let glyph = font.glyph(ch).scaled(scale);
|
||||
let advance = glyph.h_metrics().advance_width as i32;
|
||||
let glyph = glyph.positioned(point(0.0, v_metrics.ascent));
|
||||
|
||||
if let Some(bounding_box) = glyph.pixel_bounding_box() {
|
||||
let origin = (bounding_box.min.x, bounding_box.min.y);
|
||||
@@ -35,12 +35,14 @@ impl CachedGlyph {
|
||||
origin,
|
||||
dimensions,
|
||||
render,
|
||||
advance,
|
||||
}
|
||||
} else {
|
||||
CachedGlyph {
|
||||
origin: (0, 0),
|
||||
dimensions: ((size / 4.0) as u32, 0),
|
||||
dimensions: (0, 0),
|
||||
render: Vec::new(),
|
||||
advance: (size / 4.0) as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +120,7 @@ impl<'a> Font<'a> {
|
||||
}
|
||||
for glyph in glyphs {
|
||||
glyph.draw(buf, (x_off, -off), bg, c);
|
||||
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
|
||||
x_off += glyph.advance;
|
||||
}
|
||||
|
||||
Ok((x_off as u32, self.size as u32))
|
||||
@@ -157,7 +159,7 @@ impl<'a> Font<'a> {
|
||||
self.draw_cursor(buf, c, x_off as u32, height)?;
|
||||
}
|
||||
glyph.draw(buf, (x_off, -off), bg, c);
|
||||
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
|
||||
x_off += glyph.advance;
|
||||
}
|
||||
if cursor == glyphs.len() {
|
||||
self.draw_cursor(buf, c, x_off as u32, height)?;
|
||||
@@ -193,7 +195,7 @@ impl<'a> Font<'a> {
|
||||
))
|
||||
}
|
||||
};
|
||||
let width = glyph.dimensions.0 as i32 + glyph.origin.0;
|
||||
let width = glyph.advance;
|
||||
if width > max {
|
||||
max = width
|
||||
}
|
||||
@@ -285,7 +287,7 @@ impl<'a> Font<'a> {
|
||||
}
|
||||
for (idx, glyph) in glyphs.into_iter().enumerate() {
|
||||
glyph.draw(buf, (x_off, -off), bg, &color[idx]);
|
||||
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
|
||||
x_off += glyph.advance;
|
||||
}
|
||||
|
||||
Ok((x_off as u32, self.size as u32))
|
||||
|
||||
+14
-14
@@ -1,17 +1,17 @@
|
||||
#![allow(missing_docs, non_upper_case_globals, unused_parens, clippy::all)]
|
||||
|
||||
pub const XKB_KEY_BackSpace :u32 = 0xff08; /* Back space, back char */
|
||||
pub const XKB_KEY_Tab :u32 = 0xff09;
|
||||
pub const XKB_KEY_Return :u32 = 0xff0d; /* Return, enter */
|
||||
pub const XKB_KEY_Escape :u32 = 0xff1b;
|
||||
pub const XKB_KEY_Delete :u32 = 0xffff; /* Delete, rubout */
|
||||
pub const XKB_KEY_Home :u32 = 0xff50;
|
||||
pub const XKB_KEY_Left :u32 = 0xff51; /* Move left, left arrow */
|
||||
pub const XKB_KEY_Right :u32 = 0xff53; /* Move right, right arrow */
|
||||
pub const XKB_KEY_End :u32 = 0xff57; /* EOL */
|
||||
pub const XKB_KEY_BackSpace: u32 = 0xff08; /* Back space, back char */
|
||||
pub const XKB_KEY_Tab: u32 = 0xff09;
|
||||
pub const XKB_KEY_Return: u32 = 0xff0d; /* Return, enter */
|
||||
pub const XKB_KEY_Escape: u32 = 0xff1b;
|
||||
pub const XKB_KEY_Delete: u32 = 0xffff; /* Delete, rubout */
|
||||
pub const XKB_KEY_Home: u32 = 0xff50;
|
||||
pub const XKB_KEY_Left: u32 = 0xff51; /* Move left, left arrow */
|
||||
pub const XKB_KEY_Right: u32 = 0xff53; /* Move right, right arrow */
|
||||
pub const XKB_KEY_End: u32 = 0xff57; /* EOL */
|
||||
|
||||
pub const XKB_KEY_ISO_Left_Tab :u32 = 0xfe20;
|
||||
pub const XKB_KEY_e :u32 = 0x0065; /* U+0065 LATIN SMALL LETTER E */
|
||||
pub const XKB_KEY_a :u32 = 0x0061; /* U+0061 LATIN SMALL LETTER A */
|
||||
pub const XKB_KEY_c :u32 = 0x0063; /* U+0063 LATIN SMALL LETTER C */
|
||||
pub const XKB_KEY_u :u32 = 0x0075; /* U+0075 LATIN SMALL LETTER U */
|
||||
pub const XKB_KEY_ISO_Left_Tab: u32 = 0xfe20;
|
||||
pub const XKB_KEY_e: u32 = 0x0065; /* U+0065 LATIN SMALL LETTER E */
|
||||
pub const XKB_KEY_a: u32 = 0x0061; /* U+0061 LATIN SMALL LETTER A */
|
||||
pub const XKB_KEY_c: u32 = 0x0063; /* U+0063 LATIN SMALL LETTER C */
|
||||
pub const XKB_KEY_u: u32 = 0x0075; /* U+0075 LATIN SMALL LETTER U */
|
||||
|
||||
+14
-8
@@ -23,8 +23,8 @@ use wayland_client::{
|
||||
};
|
||||
|
||||
mod ffi;
|
||||
mod state;
|
||||
pub mod keysyms;
|
||||
mod state;
|
||||
|
||||
use self::state::KbState;
|
||||
pub use self::state::{ModifiersState, RMLVO};
|
||||
@@ -118,10 +118,7 @@ where
|
||||
let callback = Rc::new(RefCell::new(callback));
|
||||
|
||||
// prepare the handler
|
||||
let mut kbd_handler = KbdHandler {
|
||||
callback,
|
||||
state,
|
||||
};
|
||||
let mut kbd_handler = KbdHandler { callback, state };
|
||||
|
||||
keyboard.quick_assign(move |keyboard, event, data| {
|
||||
kbd_handler.event(keyboard.detach(), event, data)
|
||||
@@ -331,8 +328,17 @@ impl KbdHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn repeat_info(&mut self, object: wl_keyboard::WlKeyboard, rate: i32, delay: i32, dispatch_data: wayland_client::DispatchData) {
|
||||
(&mut *self.callback.borrow_mut())(Event::RepeatInfo { rate, delay }, object, dispatch_data);
|
||||
fn repeat_info(
|
||||
&mut self,
|
||||
object: wl_keyboard::WlKeyboard,
|
||||
rate: i32,
|
||||
delay: i32,
|
||||
dispatch_data: wayland_client::DispatchData,
|
||||
) {
|
||||
(&mut *self.callback.borrow_mut())(
|
||||
Event::RepeatInfo { rate, delay },
|
||||
object,
|
||||
dispatch_data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -398,4 +398,3 @@ impl Drop for KbState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -12,15 +12,16 @@ use timerfd::{SetTimeFlags, TimerFd, TimerState};
|
||||
|
||||
mod app;
|
||||
mod buffer;
|
||||
mod keyboard;
|
||||
mod cmd;
|
||||
mod color;
|
||||
mod config;
|
||||
mod configfmt;
|
||||
mod data;
|
||||
mod desktop;
|
||||
mod doublemempool;
|
||||
mod draw;
|
||||
mod fonts;
|
||||
mod keyboard;
|
||||
mod widget;
|
||||
mod widgets;
|
||||
|
||||
@@ -206,7 +207,10 @@ fn main() {
|
||||
});
|
||||
|
||||
let mut timer = TimerFd::new().unwrap();
|
||||
let ev_fd = PollFd::new(app.event_queue().display().get_connection_fd(), PollFlags::POLLIN);
|
||||
let ev_fd = PollFd::new(
|
||||
app.event_queue().display().get_connection_fd(),
|
||||
PollFlags::POLLIN,
|
||||
);
|
||||
let rx_fd = PollFd::new(rx_pipe.as_raw_fd(), PollFlags::POLLIN);
|
||||
let tm_fd = PollFd::new(timer.as_raw_fd(), PollFlags::POLLIN);
|
||||
let ipc_fd = PollFd::new(listener.as_raw_fd(), PollFlags::POLLIN);
|
||||
@@ -323,7 +327,7 @@ fn main() {
|
||||
}
|
||||
|
||||
app.event_queue()
|
||||
.dispatch_pending(&mut (), |_, _, _|{})
|
||||
.dispatch_pending(&mut (), |_, _, _| {})
|
||||
.expect("Failed to dispatch all messages.");
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
use crate::buffer::Buffer;
|
||||
use crate::color::Color;
|
||||
pub use crate::keyboard::{KeyState, ModifiersState};
|
||||
use chrono::NaiveDateTime;
|
||||
use nix::poll::PollFd;
|
||||
pub use crate::keyboard::{KeyState, ModifiersState};
|
||||
|
||||
pub struct DrawContext<'a> {
|
||||
pub buf: &'a mut Buffer<'a>,
|
||||
|
||||
@@ -99,7 +99,7 @@ impl BarWidgetImpl for Alsa {
|
||||
fn value(&self) -> f32 {
|
||||
match self.get_master_volume() {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!(e),
|
||||
Err(e) => panic!("{}", e),
|
||||
}
|
||||
}
|
||||
fn color(&self) -> Color {
|
||||
@@ -107,12 +107,12 @@ impl BarWidgetImpl for Alsa {
|
||||
}
|
||||
fn inc(&mut self, diff: f32) {
|
||||
if let Err(e) = self.inc_master_volume(diff) {
|
||||
panic!(e)
|
||||
panic!("{}", e)
|
||||
}
|
||||
}
|
||||
fn set(&mut self, abs: f32) {
|
||||
if let Err(e) = self.set_master_volume(abs) {
|
||||
panic!(e)
|
||||
panic!("{}", e)
|
||||
}
|
||||
}
|
||||
fn toggle(&mut self) {}
|
||||
|
||||
@@ -21,7 +21,7 @@ impl<'a> Clock<'a> {
|
||||
clock_cache.add_str_to_cache("0123456789:");
|
||||
|
||||
let digit = clock_cache.auto_widest("123456789")?;
|
||||
let colon = (clock_cache.auto_widest(":")? as f32 * 1.25) as u32;
|
||||
let colon = clock_cache.auto_widest(":")?;
|
||||
|
||||
Ok(Box::new(Clock {
|
||||
cur_time: time,
|
||||
|
||||
+29
-12
@@ -14,8 +14,10 @@ use std::collections::HashMap;
|
||||
use std::process::Command;
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
use fuzzy_matcher::skim::{fuzzy_indices, fuzzy_match};
|
||||
use crate::data::Data;
|
||||
use crate::keyboard::keysyms;
|
||||
use fuzzy_matcher::skim::SkimMatcherV2;
|
||||
use fuzzy_matcher::FuzzyMatcher;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
pub struct Launcher<'a> {
|
||||
@@ -33,6 +35,7 @@ pub struct Launcher<'a> {
|
||||
length: u32,
|
||||
dirty: bool,
|
||||
tx: Sender<Cmd>,
|
||||
counter: Data,
|
||||
}
|
||||
|
||||
impl<'a> Launcher<'a> {
|
||||
@@ -60,6 +63,7 @@ impl<'a> Launcher<'a> {
|
||||
length,
|
||||
dirty: true,
|
||||
tx: listener,
|
||||
counter: Data::load().unwrap_or_default(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -90,15 +94,17 @@ impl<'a> Launcher<'a> {
|
||||
};
|
||||
|
||||
let mut width_remaining: i32 = (width - x_off) as i32;
|
||||
let fuzzy_matcher = SkimMatcherV2::default();
|
||||
for (idx, m) in self.matches.iter().enumerate() {
|
||||
let mut b = match buf.offset((x_off, 0)) {
|
||||
Ok(b) => b,
|
||||
Err(_) => break,
|
||||
};
|
||||
let size = if idx == self.offset && !self.input.is_empty() {
|
||||
let (_, indices) =
|
||||
fuzzy_indices(&m.name.to_lowercase(), &self.input.to_lowercase())
|
||||
.unwrap_or((0, vec![]));
|
||||
let size = if idx == self.offset {
|
||||
let (_, indices) = fuzzy_matcher
|
||||
.fuzzy_indices(&m.name.to_lowercase(), &self.input.to_lowercase())
|
||||
.unwrap_or((0, vec![]));
|
||||
|
||||
let mut colors = Vec::with_capacity(m.name.len());
|
||||
for pos in 0..m.name.len() {
|
||||
if indices.contains(&pos) {
|
||||
@@ -213,17 +219,20 @@ fn wlcopy(s: &str) -> Result<(), String> {
|
||||
|
||||
struct Matcher {
|
||||
matches: HashMap<Desktop, i64>,
|
||||
counter: Data,
|
||||
}
|
||||
|
||||
impl Matcher {
|
||||
fn new() -> Self {
|
||||
fn new(counter: Data) -> Self {
|
||||
Self {
|
||||
matches: HashMap::new(),
|
||||
counter,
|
||||
}
|
||||
}
|
||||
|
||||
fn try_match(&mut self, dtop: Desktop, val: &str, input: &str, prio: f32) {
|
||||
if let Some(ma) = fuzzy_match(val, input) {
|
||||
let fuzzy_matcher = SkimMatcherV2::default();
|
||||
if let Some(ma) = fuzzy_matcher.fuzzy_match(val, input) {
|
||||
let ma = ((ma as f32) * prio) as i64;
|
||||
if let Some(ma_old) = self.matches.get(&dtop) {
|
||||
// Skip over new matches for the same program that are worse
|
||||
@@ -245,9 +254,12 @@ impl Matcher {
|
||||
.collect::<Vec<(i64, Desktop)>>();
|
||||
|
||||
m.sort_by(|(ma1, d1), (ma2, d2)| {
|
||||
if ma1 > ma2 {
|
||||
let count1 = self.counter.entries.get(&d1.name).unwrap_or(&0);
|
||||
let count2 = self.counter.entries.get(&d2.name).unwrap_or(&0);
|
||||
|
||||
if ma1 + count1 > ma2 + count2 {
|
||||
Ordering::Less
|
||||
} else if ma1 < ma2 {
|
||||
} else if ma1 + count1 < ma2 + count2 {
|
||||
Ordering::Greater
|
||||
} else if d1.name.len() < d2.name.len() {
|
||||
Ordering::Less
|
||||
@@ -303,7 +315,7 @@ impl<'a> Widget for Launcher<'a> {
|
||||
}
|
||||
Some('!') => (),
|
||||
_ => {
|
||||
let mut matcher = Matcher::new();
|
||||
let mut matcher = Matcher::new(self.counter.clone());
|
||||
|
||||
for desktop in self.options.iter() {
|
||||
matcher.try_match(
|
||||
@@ -417,13 +429,18 @@ impl<'a> Widget for Launcher<'a> {
|
||||
&self.app_opener
|
||||
};
|
||||
|
||||
let mut lexed = shlex::split(&exec).unwrap();
|
||||
let lexed = if !prefix.is_empty() {
|
||||
let mut prefix = shlex::split(prefix).unwrap();
|
||||
prefix.push(exec);
|
||||
prefix.append(&mut lexed);
|
||||
prefix
|
||||
} else {
|
||||
shlex::split(&exec).unwrap()
|
||||
lexed
|
||||
};
|
||||
|
||||
*self.counter.entries.entry(d.name.clone()).or_insert(0) += 1;
|
||||
self.counter.save().expect("Unable to save data");
|
||||
|
||||
if !lexed.is_empty() {
|
||||
let _ =
|
||||
Command::new(lexed[0].clone()).args(&lexed[1..]).spawn();
|
||||
|
||||
Reference in New Issue
Block a user