diff --git a/Cargo.toml b/Cargo.toml index 83d3655..e3339f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ming-wm" -version = "1.2.1" +version = "1.2.2" repository = "https://github.com/stjet/ming-wm" license = "GPL-3.0-or-later" edition = "2021" @@ -11,6 +11,20 @@ default-run = "ming" [workspace] members = [ "wm", "linux" ] +[workspace.lints.clippy] +len_zero = "allow" +comparison_to_empty = "allow" +manual_saturating_arithmetic = "allow" +result_unit_err = "allow" +needless_borrow = "allow" +needless_borrows_for_generic_args = "allow" +redundant_static_lifetimes = "allow" +collapsible_else_if = "allow" +too_many_arguments = "allow" + +[lints] +workspace = true + [build-dependencies] bmp-rust = "0.5.0" bitcoin_hashes = { version = "0.16.0", default-features = false } @@ -65,4 +79,4 @@ path = "src/bin/reversi.rs" [[bin]] name = "mingUtils_Draw" -path = "src/bin/draw.rs" \ No newline at end of file +path = "src/bin/draw.rs" diff --git a/README.md b/README.md index 999fa84..437730e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -Ming-wm is a keyboard-based, retro-themed window manager for Linux. It is neither for Wayland or the X Window System - it writes directly to the framebuffer. Inspirations include i3, Haiku, SerenityOS, and Windows98, and it is a conceptual successor to my previous projects [ming-de](https://github.com/stjet/mingde) and [ming-os](https://github.com/stjet/ming-os). +Ming-wm is a keyboard-based, retro-themed window manager for Linux. It is neither for Wayland or the X Window System - it writes directly to the framebuffer. Inspirations include i3, Haiku, SerenityOS, and Windows98. ![example 1](/docs/images/ws1.png) ![example 2](/docs/images/ws3.png) +https://github.com/user-attachments/assets/2efc0122-80fa-48dd-8d31-f307217c2961 The [Koxinga web browser](https://github.com/stjet/koxinga) can be separately installed. diff --git a/docs/images/koxinga.png b/docs/images/koxinga.png index d5e0ad0..e6d2e62 100644 Binary files a/docs/images/koxinga.png and b/docs/images/koxinga.png differ diff --git a/linux/Cargo.toml b/linux/Cargo.toml index 3c7f3de..058598c 100644 --- a/linux/Cargo.toml +++ b/linux/Cargo.toml @@ -4,5 +4,18 @@ version = "0.1.0" license = "GPL-3.0-or-later" edition = "2021" +[lints.clippy] +len_zero = "allow" +comparison_to_empty = "allow" +manual_saturating_arithmetic = "allow" +result_unit_err = "allow" +needless_borrow = "allow" +needless_borrows_for_generic_args = "allow" +redundant_static_lifetimes = "allow" +collapsible_else_if = "allow" +too_many_arguments = "allow" +useless_conversion = "allow" +unnecessary_mut_passed = "allow" + [dependencies] libc = "0.2" diff --git a/linux/src/keys.rs b/linux/src/keys.rs index 5e8fc59..448603a 100644 --- a/linux/src/keys.rs +++ b/linux/src/keys.rs @@ -71,9 +71,9 @@ impl Iterator for RawStdin { b'D' => Key::ArrowLeft, _ => Key::Other(n), } - } else if n.is_ok() { + } else if let Ok(n) = n { //Alt+ sends Esc+ - Key::Alt(char::from(n.unwrap())) + Key::Alt(char::from(n)) } else { Key::Esc } diff --git a/ming-wm-lib/Cargo.toml b/ming-wm-lib/Cargo.toml index 2228d4b..f7b4c57 100644 --- a/ming-wm-lib/Cargo.toml +++ b/ming-wm-lib/Cargo.toml @@ -1,10 +1,21 @@ [package] name = "ming-wm-lib" -version = "0.2.2" +version = "0.2.3" repository = "https://github.com/stjet/ming-wm" description = "library for building windows for ming-wm in rust" readme = "README.md" license = "GPL-3.0-or-later" edition = "2021" +[lints.clippy] +len_zero = "allow" +comparison_to_empty = "allow" +manual_saturating_arithmetic = "allow" +result_unit_err = "allow" +needless_borrow = "allow" +needless_borrows_for_generic_args = "allow" +redundant_static_lifetimes = "allow" +collapsible_else_if = "allow" +too_many_arguments = "allow" + [dependencies] diff --git a/ming-wm-lib/src/fonts.rs b/ming-wm-lib/src/fonts.rs index 81cb64f..d2d9a5e 100644 --- a/ming-wm-lib/src/fonts.rs +++ b/ming-wm-lib/src/fonts.rs @@ -20,9 +20,9 @@ fn get_font_char(dir: &str, c: char) -> Option { let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); let lines: Vec<&str> = contents.split("\n").collect(); - for ln in 1..lines.len() { + for ln in lines.iter().skip(1) { //.unwrap_or(0) is important because zeroes are just empty - ch.push(lines[ln].replace(":", ",,,,").replace(";", ",,,").replace(".", ",,").split(",").map(|n| n.parse().unwrap_or(0)).collect()); + ch.push(ln.replace(":", ",,,,").replace(";", ",,,").replace(".", ",,").split(",").map(|n| n.parse().unwrap_or(0)).collect()); } return Some(FontCharInfo { c, @@ -58,8 +58,7 @@ pub struct MeasureInfo { pub width: usize, } -/// Doesn't take into account `horiz_spacing`, which defaults to 1 per character -pub fn measure_text(fonts: &[String], text: String) -> MeasureInfo { +pub fn measure_text(fonts: &[String], text: &str, horiz_spacing: Option) -> MeasureInfo { let mut height = 0; let mut width = 0; for c in text.chars() { @@ -68,8 +67,27 @@ pub fn measure_text(fonts: &[String], text: String) -> MeasureInfo { if c_height > height { height = c_height; } - width += i.width; + width += i.width + horiz_spacing.unwrap_or(1); } + width -= horiz_spacing.unwrap_or(1); + MeasureInfo { + height, + width, + } +} + +pub fn measure_text_with_cache(fc_getter: &mut CachedFontCharGetter, fonts: &[String], text: &str, horiz_spacing: Option) -> MeasureInfo { + let mut height = 0; + let mut width = 0; + for c in text.chars() { + let i = fc_getter.get(fonts, c); + let c_height = i.top_offset as usize + i.height; + if c_height > height { + height = c_height; + } + width += i.width + horiz_spacing.unwrap_or(1); + } + width -= horiz_spacing.unwrap_or(1); MeasureInfo { height, width, @@ -85,9 +103,10 @@ pub struct CachedFontCharGetter { impl CachedFontCharGetter { pub fn new(max_cache_size: usize) -> Self { - let mut s: Self = Default::default(); - s.max_cache_size = max_cache_size; - s + Self { + max_cache_size, + ..Default::default() + } } pub fn get(&mut self, fonts: &[String], c: char) -> FontCharInfo { diff --git a/ming-wm-lib/src/messages.rs b/ming-wm-lib/src/messages.rs index b89a0d7..8677f73 100644 --- a/ming-wm-lib/src/messages.rs +++ b/ming-wm-lib/src/messages.rs @@ -44,11 +44,7 @@ pub enum WindowMessageResponse { impl WindowMessageResponse { pub fn is_key_char_request(&self) -> bool { - if let WindowMessageResponse::Request(WindowManagerRequest::DoKeyChar(_)) = self { - true - } else { - false - } + matches!(self, WindowMessageResponse::Request(WindowManagerRequest::DoKeyChar(_))) } } diff --git a/ming-wm-lib/src/serialize.rs b/ming-wm-lib/src/serialize.rs index e172ad2..d362519 100644 --- a/ming-wm-lib/src/serialize.rs +++ b/ming-wm-lib/src/serialize.rs @@ -83,7 +83,7 @@ impl Serializable for ThemeInfo { } fn deserialize(serialized: &str) -> Result { //strip newline at the end - let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized }; + let serialized = serialized.strip_suffix("\n").unwrap_or(serialized); let mut theme_info: ThemeInfo = Default::default(); let arrays = serialized.split(":"); //won't error or panic if less than 9... rest will just be black by default I guess @@ -162,7 +162,7 @@ impl Serializable for WindowMessageResponse { } fn deserialize(serialized: &str) -> Result { //strip newline at the end - let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized }; + let serialized = serialized.strip_suffix("\n").unwrap_or(serialized); let mut parts = serialized.split("/"); match parts.next().unwrap_or("Invalid") { "JustRedraw" => Ok(WindowMessageResponse::JustRedraw), @@ -444,12 +444,12 @@ impl Serializable for DrawInstructionsVec { if self.len() == 0 { return "empty".to_string(); } - let collected: Vec<_> = self.into_iter().map(|ins| ins.serialize()).collect(); + let collected: Vec<_> = self.iter().map(|ins| ins.serialize()).collect(); collected.join("\x1D") } fn deserialize(serialized: &str) -> Result { //strip newline at the end - let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized }; + let serialized = serialized.strip_suffix("\n").unwrap_or(serialized); if serialized == "empty" { return Ok(Vec::new()); } @@ -504,7 +504,7 @@ impl Serializable for WindowLikeType { } } fn deserialize(serialized: &str) -> Result { - let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized }; + let serialized = serialized.strip_suffix("\n").unwrap_or(serialized); match serialized { "LockScreen" => Ok(WindowLikeType::LockScreen), "Window" => Ok(WindowLikeType::Window), @@ -531,7 +531,7 @@ impl Serializable for Dimensions { } fn deserialize(serialized: &str) -> Result { //strip newline at the end - let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized }; + let serialized = serialized.strip_suffix("\n").unwrap_or(serialized); let d = get_two_array(serialized)?; Ok(d) } @@ -592,7 +592,7 @@ impl Serializable for WindowMessage { } } fn deserialize(serialized: &str) -> Result { - let serialized = if serialized.ends_with("\n") { &serialized[..serialized.len() - 1] } else { serialized }; + let serialized = serialized.strip_suffix("\n").unwrap_or(serialized); let mut parts = serialized.split("/"); match parts.next().unwrap_or("Invalid") { "Init" => { @@ -716,9 +716,9 @@ impl Serializable for WindowMessage { return Err(()); } if let Ok(n) = arg2.unwrap().parse() { - return Ok(WindowMessage::Info(InfoType::WindowsInWorkspace(w_vec, n))); + Ok(WindowMessage::Info(InfoType::WindowsInWorkspace(w_vec, n))) } else { - return Err(()); + Err(()) } }, "Focus" => Ok(WindowMessage::Focus), diff --git a/ming-wm-lib/src/themes.rs b/ming-wm-lib/src/themes.rs index 32fd8b7..012ee14 100644 --- a/ming-wm-lib/src/themes.rs +++ b/ming-wm-lib/src/themes.rs @@ -11,15 +11,17 @@ pub enum Themes { //Parchment, } -impl Themes { - pub fn from_str(name: &str) -> Option { +impl std::str::FromStr for Themes { + type Err = (); + + fn from_str(name: &str) -> Result { match name { - "Standard" => Some(Themes::Standard), - "Night" => Some(Themes::Night), - "Industrial" => Some(Themes::Industrial), - "Forest" => Some(Themes::Forest), - "Royal" => Some(Themes::Royal), - _ => None, + "Standard" => Ok(Themes::Standard), + "Night" => Ok(Themes::Night), + "Industrial" => Ok(Themes::Industrial), + "Forest" => Ok(Themes::Forest), + "Royal" => Ok(Themes::Royal), + _ => Err(()), } } } diff --git a/ming-wm-lib/src/utils.rs b/ming-wm-lib/src/utils.rs index 5a44775..7346f90 100644 --- a/ming-wm-lib/src/utils.rs +++ b/ming-wm-lib/src/utils.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use std::fs::read_dir; +use crate::fonts::measure_text; use crate::framebuffer_types::{ Dimensions, Point }; pub fn min(one: usize, two: usize) -> usize { @@ -96,6 +97,23 @@ pub fn calc_actual_lines<'a>(lines: impl Iterator, max_chars_ actual_lines } +/// truncate to ... if too long (uses `measure_text`) +pub fn trunc_words(fonts: &[String], to_measure: String, horiz_spacing: Option, max_text_width: usize) -> String { + if measure_text(fonts, &to_measure, horiz_spacing).width > max_text_width { + let mut current = String::new(); + for c in to_measure.chars() { + let to_measure = current.clone() + &c.to_string() + "..."; + if measure_text(fonts, &to_measure, horiz_spacing).width > max_text_width { + break; + } + current += &c.to_string(); + } + current + "..." + } else { + to_measure.clone() + } +} + pub fn concat_paths(current_path: &str, add_path: &str) -> Result { let mut new_path = PathBuf::from(current_path); //if current_path is a file, automatically uses it's parent (a directory) diff --git a/src/bin/audio_player.rs b/src/bin/audio_player.rs index 557e04d..2a67f25 100644 --- a/src/bin/audio_player.rs +++ b/src/bin/audio_player.rs @@ -152,11 +152,11 @@ impl WindowLike for AudioPlayer { let current = &queue[queue.len() - sink_len]; let current_name = current.0.file_name().unwrap().to_string_lossy().into_owned(); let fonts = ["nimbus-roman".to_string(), "shippori-mincho".to_string()]; - let cn_width = measure_text(&fonts, current_name.clone()).width; + let cn_width = measure_text(&fonts, ¤t_name, None).width; instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - cn_width / 2, 2], fonts.to_vec(), current_name.clone(), theme_info.text, theme_info.background, Some(0), None)); if let Some(artist) = ¤t.2 { let artist_string = "by ".to_string() + &artist; - let as_width = measure_text(&fonts, artist_string.clone()).width; + let as_width = measure_text(&fonts, &artist_string, None).width; instructions.push(DrawInstructions::Text([self.dimensions[0] / 2 - as_width / 2, LINE_HEIGHT + 2], fonts.to_vec(), artist_string, theme_info.text, theme_info.background, Some(0), None)); } //in this case no chance of mincho so MONO_WIDTH method of calculating width is ok diff --git a/src/bin/draw.rs b/src/bin/draw.rs index 4fa7e5b..2ebdfee 100644 --- a/src/bin/draw.rs +++ b/src/bin/draw.rs @@ -241,9 +241,11 @@ impl WindowLike for Draw { impl Draw { pub fn new() -> Self { - let mut d: Self = Default::default(); - d.current_linewidth = 1; - d + //apparently this is legal. thanks clippy + Self { + current_linewidth: 1, + ..Default::default() //no comma here allowed though?? + } } } diff --git a/src/bin/file_explorer.rs b/src/bin/file_explorer.rs index f9bea30..fc9793f 100644 --- a/src/bin/file_explorer.rs +++ b/src/bin/file_explorer.rs @@ -111,13 +111,12 @@ impl WindowLike for FileExplorer { self.metadata = Some(metadata(&selected_entry.path).unwrap()); } WindowMessageResponse::JustRedraw + } else if self.state == State::Info { + //pressing any key to exit info mode + self.state = State::List; + WindowMessageResponse::JustRedraw } else { - if self.state == State::Info { - self.state = State::List; - WindowMessageResponse::JustRedraw - } else { - WindowMessageResponse::DoNothing - } + WindowMessageResponse::DoNothing } }, _ => WindowMessageResponse::DoNothing, @@ -128,7 +127,7 @@ impl WindowLike for FileExplorer { let mut instructions = Vec::new(); if self.state == State::List { //top bar with path name - instructions.push(DrawInstructions::Text([5, 0], vec!["nimbus-roman".to_string(), "shippori-mincho".to_string()], "Current: ".to_string() + &self.current_path.to_string_lossy().to_string(), theme_info.text, theme_info.background, None, None)); + instructions.push(DrawInstructions::Text([5, 0], vec!["nimbus-roman".to_string(), "shippori-mincho".to_string()], "Current: ".to_string() + self.current_path.to_string_lossy().as_ref(), theme_info.text, theme_info.background, None, None)); //the actual files and directories let mut start_y = HEIGHT; let mut i = self.top_position; @@ -142,10 +141,10 @@ impl WindowLike for FileExplorer { } //unwrap_or not used because "Arguments passed to unwrap_or are eagerly evaluated", apparently let name = entry.override_name.clone(); - let name = if name.is_none() { - entry.path.file_name().unwrap().to_os_string().into_string().unwrap() + let name = if let Some(name) = name { + name } else { - name.unwrap() + entry.path.file_name().unwrap().to_os_string().into_string().unwrap() }; instructions.push(DrawInstructions::Text([5, start_y + 4], vec!["nimbus-roman".to_string(), "shippori-mincho".to_string()], name, if is_selected { theme_info.top_text } else { theme_info.text }, if is_selected { theme_info.top } else { theme_info.background }, None, None)); start_y += HEIGHT; diff --git a/src/bin/malvim.rs b/src/bin/malvim.rs index 53f5b09..e48a447 100644 --- a/src/bin/malvim.rs +++ b/src/bin/malvim.rs @@ -138,8 +138,8 @@ impl WindowLike for Malvim { if key_press.is_enter() { let mut line: Vec = line.chars().collect(); let (left, right) = line.split_at_mut(current_file.cursor_pos); - let left = left.into_iter().map(|c| c.to_string()).collect::>().join(""); - let right = right.into_iter().map(|c| c.to_string()).collect::>().join(""); + let left = left.iter_mut().map(|c| c.to_string()).collect::>().join(""); + let right = right.iter_mut().map(|c| c.to_string()).collect::>().join(""); current_file.content[current_file.line_pos] = left.to_string(); let spaces = Malvim::calc_spaces(self.autoindent, &left); current_file.content.insert(current_file.line_pos + 1, " ".repeat(spaces) + &right); @@ -495,7 +495,7 @@ impl WindowLike for Malvim { if i == 0 { //modify current line let line = ¤t_file.content[current_file.line_pos]; - current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + &cs + line.substring(current_file.cursor_pos, line.chars().count()); + current_file.content[current_file.line_pos] = line.substring(0, current_file.cursor_pos).to_string() + cs + line.substring(current_file.cursor_pos, line.chars().count()); current_file.cursor_pos += copy_string.len(); } else { //insert a new line @@ -750,7 +750,7 @@ impl Malvim { } } else if self.files.len() == 0 { self.bottom_message = Some("No files are open, so can only do :e(dit)".to_string()); - } else if first.starts_with("/") { + } else if let Some(s_first) = first.strip_prefix("/") { let current_file = &mut self.files[self.current_file_index]; if current_file.content.len() > 0 { let p1 = if arg == "" { @@ -764,7 +764,7 @@ impl Malvim { } else { " ".to_string() + &rest }; - let query = first[1..].to_string() + &p1 + &rest; + let query = s_first.to_string() + &p1 + &rest; let mut lines = current_file.content.iter().skip(current_file.line_pos); for i in 0..(current_file.content.len() - current_file.line_pos) { let line = if i == 0 { diff --git a/src/bin/minesweeper.rs b/src/bin/minesweeper.rs index 3e77cfe..b5082c8 100644 --- a/src/bin/minesweeper.rs +++ b/src/bin/minesweeper.rs @@ -256,7 +256,7 @@ impl Minesweeper { self.random_seed as usize % 16 } - pub fn on_adjacent_tiles(&self, x: usize, y: usize, mut action: impl FnMut(usize, usize) -> (), if_mine: bool) { + pub fn on_adjacent_tiles(&self, x: usize, y: usize, mut action: impl FnMut(usize, usize), if_mine: bool) { if y > 0 { //above if self.tiles[y - 1][x].mine == if_mine { diff --git a/src/bin/reversi.rs b/src/bin/reversi.rs index f6a8e13..1beedc4 100644 --- a/src/bin/reversi.rs +++ b/src/bin/reversi.rs @@ -1,5 +1,6 @@ use std::vec::Vec; use std::vec; +use std::cmp::Ordering; use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType }; use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse }; @@ -101,13 +102,11 @@ impl WindowLike for Reversi { } } } - if white_tiles == black_tiles { - self.state = State::Tie; - } else if white_tiles > black_tiles { - self.state = State::WhiteWin; - } else { - self.state = State::BlackWin; - } + self.state = match white_tiles.cmp(&black_tiles) { + Ordering::Equal => State::Tie, + Ordering::Greater => State::WhiteWin, + Ordering::Less => State::BlackWin, + }; } } self.current_number = None; diff --git a/src/bin/terminal.rs b/src/bin/terminal.rs index 2e27db1..5017750 100644 --- a/src/bin/terminal.rs +++ b/src/bin/terminal.rs @@ -149,27 +149,23 @@ impl WindowLike for Terminal { Mode::Running => { //update let mut changed = false; - loop { - if let Ok(ci) = self.pty_outerr_rx.as_mut().unwrap().recv_timeout(Duration::from_millis(5)) { - if char::from(ci) == '\n' { - let append_line = strip_ansi_escape_codes(bytes_to_string(self.process_current_line.clone())); - self.output += &append_line; - self.output += "\n"; - self.lines.push(append_line); - self.process_current_line = Vec::new(); - } else if char::from(ci) == '\r' { - //for now, ignore - // - } else if char::from(ci) == '\t' { - //for now, interpret as space - self.process_current_line.push(b' '); - } else { - self.process_current_line.push(ci); - } - changed = true; + while let Ok(ci) = self.pty_outerr_rx.as_mut().unwrap().recv_timeout(Duration::from_millis(5)) { + if char::from(ci) == '\n' { + let append_line = strip_ansi_escape_codes(bytes_to_string(self.process_current_line.clone())); + self.output += &append_line; + self.output += "\n"; + self.lines.push(append_line); + self.process_current_line = Vec::new(); + } else if char::from(ci) == '\r' { + //for now, ignore + // + } else if char::from(ci) == '\t' { + //for now, interpret as space + self.process_current_line.push(b' '); } else { - break; + self.process_current_line.push(ci); } + changed = true; } let running_process = self.running_process.as_mut().unwrap(); if let Some(_status) = running_process.try_wait().unwrap() { @@ -377,13 +373,9 @@ impl Terminal { let mut stdin = self.running_process.as_mut().unwrap().stdin.take().unwrap(); let (tx2, rx2) = channel(); thread::spawn(move || { - loop { - if let Ok(write_line) = rx2.recv() { - let write_line: String = write_line + "\n"; - stdin.write(write_line.as_bytes()).unwrap(); - } else { - break; - } + while let Ok(write_line) = rx2.recv() { + let write_line: String = write_line + "\n"; + stdin.write_all(write_line.as_bytes()).unwrap(); } }); self.pty_outerr_rx = Some(rx1); diff --git a/wm/Cargo.toml b/wm/Cargo.toml index 4ff3e76..4ce0e51 100644 --- a/wm/Cargo.toml +++ b/wm/Cargo.toml @@ -5,6 +5,9 @@ repository = "https://github.com/stjet/ming-wm" license = "GPL-3.0-or-later" edition = "2021" +[lints] +workspace = true + [dependencies] ming-wm-lib = { path = "../ming-wm-lib" } linux = { path = "../linux" } diff --git a/wm/src/essential/desktop_background.rs b/wm/src/essential/desktop_background.rs index a5431b3..5f8fa66 100644 --- a/wm/src/essential/desktop_background.rs +++ b/wm/src/essential/desktop_background.rs @@ -53,7 +53,7 @@ impl WindowLike for DesktopBackground { } } else if line.len() > 1 { //first character of line is either r or any other character, but is not part of the path - return vec![DrawInstructions::Bmp([0, 0], line[1..].to_string(), line.chars().next().unwrap() == 'r')]; + return vec![DrawInstructions::Bmp([0, 0], line[1..].to_string(), line.starts_with('r'))]; } } } diff --git a/wm/src/essential/taskbar.rs b/wm/src/essential/taskbar.rs index b2f0fd3..e26102a 100644 --- a/wm/src/essential/taskbar.rs +++ b/wm/src/essential/taskbar.rs @@ -6,7 +6,7 @@ use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLik use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType, InfoType, WindowsVec }; use ming_wm_lib::framebuffer_types::Dimensions; use ming_wm_lib::themes::ThemeInfo; -use ming_wm_lib::fonts::measure_text; +use ming_wm_lib::utils::trunc_words; use ming_wm_lib::components::Component; use ming_wm_lib::components::toggle_button::ToggleButton; @@ -80,24 +80,7 @@ impl WindowLike for Taskbar { } let info = &self.windows_in_workspace[wi]; let max_text_width = META_WIDTH - PADDING * 2; - //horiz_spacing is by default 1 per char, which measure_text doesn't take into account - let to_measure = info.1.clone(); - let to_measure_len = to_measure.chars().count(); - let name = if measure_text(&["nimbus-roman".to_string()], to_measure).width + to_measure_len > max_text_width { - let mut current = String::new(); - for c in info.1.chars() { - //horiz_spacing is 1 by default - let to_measure = current.clone() + &c.to_string() + "..."; - let to_measure_len = to_measure.chars().count(); - if measure_text(&["nimbus-roman".to_string()], to_measure).width + to_measure_len > max_text_width { - break; - } - current += &c.to_string(); - } - current + "..." - } else { - info.1.clone() - }; + let name = trunc_words(&["nimbus-roman".to_string()], info.1.clone(), None, max_text_width); let mut b = ToggleButton::new(name.to_string() + "-window", [PADDING * 2 + 44 + (META_WIDTH + PADDING) * wi, PADDING], [META_WIDTH, self.dimensions[1] - (PADDING * 2)], name.to_string(), TaskbarMessage::Nothing, TaskbarMessage::Nothing); b.inverted = info.0 == self.focused_id; instructions.extend(b.draw(theme_info)); diff --git a/wm/src/framebuffer.rs b/wm/src/framebuffer.rs index 26ad89c..0b4a811 100644 --- a/wm/src/framebuffer.rs +++ b/wm/src/framebuffer.rs @@ -133,10 +133,8 @@ impl FramebufferWriter { for row in 0..char_info.height { start_pos = ((top_left[1] + row + char_info.top_offset as usize) * self.info.stride + top_left[0]) * self.info.bytes_per_pixel; for col in &char_info.data[row] { - if col > &0 { - if start_pos + 3 < self.info.byte_len { - self._draw_pixel(start_pos, color_with_alpha(color, bg_color, *col)); - } + if col > &0 && start_pos + 3 < self.info.byte_len { + self._draw_pixel(start_pos, color_with_alpha(color, bg_color, *col)); } start_pos += self.info.bytes_per_pixel; } diff --git a/wm/src/proxy_window_like.rs b/wm/src/proxy_window_like.rs index 9982160..ff12917 100644 --- a/wm/src/proxy_window_like.rs +++ b/wm/src/proxy_window_like.rs @@ -88,7 +88,7 @@ impl ProxyWindowLike { if let Some(buffer) = buffer.stdout.as_mut() { let mut output = String::new(); let mut reader = BufReader::new(buffer); - if let Ok(_) = reader.read_line(&mut output) { + if reader.read_line(&mut output).is_ok() { output } else { String::new() diff --git a/wm/src/window_manager.rs b/wm/src/window_manager.rs index 6fe0a53..7b9703f 100644 --- a/wm/src/window_manager.rs +++ b/wm/src/window_manager.rs @@ -6,11 +6,12 @@ use std::boxed::Box; use std::cell::RefCell; use std::fs::File; use std::io::Read; +use std::str::FromStr; use linux::fb::Framebuffer; use ming_wm_lib::framebuffer_types::{ Point, Dimensions }; use ming_wm_lib::themes::{ Themes, get_theme_info }; -use ming_wm_lib::utils::{ min, point_inside }; +use ming_wm_lib::utils::{ min, point_inside, trunc_words }; use ming_wm_lib::messages::*; use ming_wm_lib::dirs::config_dir; use ming_wm_lib::window_manager_types::*; @@ -168,8 +169,9 @@ impl WindowManager { //if off_only is true, also handle request //written confusingly but it works I promise fn toggle_start_menu(&mut self, off_only: bool) -> WindowMessageResponse { - let start_menu_exists = self.window_infos.iter().find(|w| w.window_like.subtype() == WindowLikeType::StartMenu).is_some(); - if (start_menu_exists && off_only) || !off_only { + let start_menu_exists = self.window_infos.iter().any(|w| w.window_like.subtype() == WindowLikeType::StartMenu); + //if (start_menu_exists && off_only) || !off_only { + if start_menu_exists || !off_only { let taskbar_index = self.window_infos.iter().position(|w| w.window_like.subtype() == WindowLikeType::Taskbar).unwrap(); self.focused_id = self.window_infos[taskbar_index].id; if off_only { @@ -710,13 +712,15 @@ impl WindowManager { //draw window background instructions.push_front(DrawInstructions::Rect([0, 0], window_dimensions, theme_info.background)); //draw window top decorations and what not + let title = trunc_words(&["nimbus-roman".to_string()], window_info.window_like.title(), None, window_dimensions[0]); instructions.extend(vec![ //left top border DrawInstructions::Rect([0, 0], [window_dimensions[0], 1], theme_info.border_left_top), DrawInstructions::Rect([0, 0], [1, window_dimensions[1]], theme_info.border_left_top), //top DrawInstructions::Rect([1, 1], [window_dimensions[0] - 2, WINDOW_TOP_HEIGHT - 3], theme_info.top), - DrawInstructions::Text([4, 4], vec!["nimbus-roman".to_string()], window_info.window_like.title().to_string(), theme_info.top_text, theme_info.top, None, None), + //window title + DrawInstructions::Text([4, 4], vec!["nimbus-roman".to_string()], title, theme_info.top_text, theme_info.top, None, None), //top bottom border DrawInstructions::Rect([1, WINDOW_TOP_HEIGHT - 2], [window_dimensions[0] - 2, 2], theme_info.border_left_top), //right bottom border