Compare commits

...

2 Commits

Author SHA1 Message Date
jory 0309522e25 Add caps lock indicator and keyboard layout support
CI / build-ubuntu (, default) (push) Has been cancelled
CI / build-ubuntu (--features networking, networking) (push) Has been cancelled
CI / build-ubuntu (--no-default-features, no-default-features) (push) Has been cancelled
CI / build-debian (push) Has been cancelled
CI / build-fedora (push) Has been cancelled
CI / build-arch (push) Has been cancelled
CI / build-opensuse (push) Has been cancelled
- Add caps lock ring color change when caps lock is enabled (matching swaylock-effects)
- Add configurable caps lock colors: ring, text, key highlight, backspace highlight
- Add show_caps_lock_text config option (enabled by default)
- Add keyboard layout display with show_keyboard_layout option (disabled by default)
- Change keyboard_layout from u32 to String for proper display
- Add rust-cache to CI and dbus-1-dev dependency
2026-03-16 17:32:54 +01:00
jory 5e47f8a69c Added capslock functionality
Added keyboard layout func
2026-03-16 15:10:23 +01:00
7 changed files with 92 additions and 27 deletions
+10 -5
View File
@@ -24,6 +24,7 @@ jobs:
args: "--no-default-features"
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- name: Install system dependencies
run: |
sudo apt-get update
@@ -31,7 +32,7 @@ jobs:
llvm clang libclang-dev \
pkg-config \
libglib2.0-dev libcairo2-dev libpango1.0-dev libatk1.0-dev \
libpam0g-dev \
libpam0g-dev libdbus-1-dev \
libwayland-dev libxkbcommon-dev
- name: Build (${{ matrix.features }})
run: cargo build --verbose ${{ matrix.args }}
@@ -43,6 +44,7 @@ jobs:
container: debian:stable-slim
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- name: Install system dependencies
run: |
apt-get update
@@ -50,7 +52,7 @@ jobs:
llvm clang libclang-dev \
pkg-config \
libglib2.0-dev libcairo2-dev libpango1.0-dev libatk1.0-dev \
libpam0g-dev \
libpam0g-dev libdbus-1-dev \
libwayland-dev libxkbcommon-dev \
cargo rustc
- name: Build
@@ -61,13 +63,14 @@ jobs:
container: fedora:latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- name: Install system dependencies
run: |
dnf install -y \
llvm clang libclang-devel \
pkg-config \
glib2-devel cairo-devel pango-devel atk-devel \
pam-devel \
pam-devel dbus-devel \
wayland-devel libxkbcommon-devel \
cargo rust
- name: Build
@@ -78,12 +81,13 @@ jobs:
container: archlinux:latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- name: Install system dependencies
run: |
pacman -Sy --noconfirm \
llvm clang pkgconf \
glib2 cairo pango atk \
pam \
pam dbus \
wayland libxkbcommon \
rust cargo
- name: Build
@@ -94,13 +98,14 @@ jobs:
container: opensuse/tumbleweed:latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- name: Install system dependencies
run: |
zypper install -y \
llvm clang \
pkg-config \
glib2-devel cairo-devel pango-devel atk-devel \
pam-devel \
pam-devel dbus-1-devel \
wayland-devel libxkbcommon-devel \
rust cargo
- name: Build
+24 -5
View File
@@ -42,6 +42,21 @@ pub struct Config {
#[arg(long, default_value = "4EAC41", value_parser = util::parse_hex_color)]
pub key_hl_color: (f64, f64, f64, f64),
#[arg(long, default_value = "4EAC41", value_parser = util::parse_hex_color)]
pub caps_lock_key_hl_color: (f64, f64, f64, f64),
#[arg(long, default_value = "DB3300", value_parser = util::parse_hex_color)]
pub caps_lock_bs_hl_color: (f64, f64, f64, f64),
#[arg(long, default_value = "E5A445", value_parser = util::parse_hex_color)]
pub caps_lock_color: (f64, f64, f64, f64),
#[arg(long, default_value = "E5A445", value_parser = util::parse_hex_color)]
pub caps_lock_text_color: (f64, f64, f64, f64),
#[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")]
pub show_caps_lock_text: bool,
#[arg(long, default_value = "00000000", value_parser = util::parse_hex_color)]
pub line_color: (f64, f64, f64, f64),
@@ -85,6 +100,9 @@ pub struct Config {
#[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")]
pub show_album_art: bool,
#[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "false", default_missing_value = "true")]
pub show_keyboard_layout: bool,
#[arg(long)]
pub image: Option<PathBuf>,
@@ -181,11 +199,12 @@ impl Config {
merge_f32(&mut config.grace, "grace");
merge_f32(&mut config.fade_in, "fade_in");
merge_string(&mut config.pam_service, "pam_service");
merge_bool(&mut config.show_media, "show_media");
merge_bool(&mut config.show_battery, "show_battery");
merge_bool(&mut config.show_network, "show_network");
merge_bool(&mut config.show_bluetooth, "show_bluetooth");
merge_bool(&mut config.show_album_art, "show_album_art");
merge_bool(&mut config.show_media, "show_media");
merge_bool(&mut config.show_battery, "show_battery");
merge_bool(&mut config.show_network, "show_network");
merge_bool(&mut config.show_bluetooth, "show_bluetooth");
merge_bool(&mut config.show_album_art, "show_album_art");
merge_bool(&mut config.show_keyboard_layout, "show_keyboard_layout");
if !is_cli("image") {
if let Some(toml::Value::String(s)) = table.get("image") {
+5
View File
@@ -102,6 +102,11 @@ impl InputHandler {
/// Update timers (should be called periodically)
pub fn update(&mut self) {
}
/// Get the current Caps Lock state
pub fn caps_lock(&self) -> bool {
self.caps_lock
}
}
/// Actions that can result from keyboard input
+3
View File
@@ -107,6 +107,9 @@ impl LockedSurface {
self.key_highlight_shown = false;
}
// Update caps lock state in renderer
self.renderer.caps_lock = self.input_handler.caps_lock();
// Set background if available and not already applied
if !self.background_applied {
if let Some(ref background) = self.background {
+1 -2
View File
@@ -5,7 +5,6 @@ mod lock;
mod render;
mod screenshot;
mod system;
mod timer;
mod util;
use config::Config;
@@ -725,7 +724,7 @@ fn main() -> Result<(), Box<dyn Error>> {
}
let mut status = state.system_manager.get_status();
status.keyboard_layout = Some(state.current_layout);
status.keyboard_layout = Some(state.current_layout.to_string());
if let Ok(mut lm) = state.lock_manager.lock() {
lm.set_system_status(status);
+48 -14
View File
@@ -21,7 +21,7 @@ pub struct Renderer {
password_display: String,
uptime_cache: String,
last_uptime_update: Option<Instant>,
caps_lock: bool,
pub caps_lock: bool,
pub system_status: SystemStatus,
media_art_surface: Option<ImageSurface>,
last_art_url: Option<String>,
@@ -230,11 +230,15 @@ impl Renderer {
self.draw_bluetooth();
}
if self.config.show_keyboard_layout {
self.draw_keyboard_layout();
}
if !self.password_display.is_empty() {
self.draw_password_display();
}
if self.caps_lock {
if self.caps_lock && self.config.show_caps_lock_text {
self.draw_caps_lock_indicator();
}
@@ -347,13 +351,18 @@ impl Renderer {
self.context.stroke().unwrap();
}
self.context.new_path();
let (r, g, b, a) = self.config.ring_color;
self.context.set_source_rgba(r, g, b, a * self.fade_alpha);
self.context.set_line_width(thickness);
self.context
.arc(center_x, center_y, radius, 0.0, 2.0 * std::f64::consts::PI);
self.context.stroke().unwrap();
// Use caps lock color when caps lock is on and indicator is enabled, otherwise ring color
let (r, g, b, a) = if self.caps_lock {
self.config.caps_lock_color
} else {
self.config.ring_color
};
self.context.new_path();
self.context.set_source_rgba(r, g, b, a * self.fade_alpha);
self.context.set_line_width(thickness);
self.context
.arc(center_x, center_y, radius, 0.0, 2.0 * std::f64::consts::PI);
self.context.stroke().unwrap();
let (r, g, b, a) = self.config.separator_color;
if a > 0.0 {
@@ -384,12 +393,16 @@ impl Renderer {
let center_y = self.height as f64 / 2.0;
let radius = self.config.indicator_radius as f64;
self.context.new_path();
self.context.set_font_size(12.0);
self.context.set_source_rgba(1.0, 0.5, 0.0, self.fade_alpha);
let text = "CAPS LOCK";
// Use configurable caps lock text color
let (r, g, b, a) = self.config.caps_lock_text_color;
self.context.set_source_rgba(r, g, b, a * self.fade_alpha);
// Increase font size for bigger letters
self.context.set_font_size(24.0);
let text = "Caps Lock";
let te = self.context.text_extents(text).unwrap();
// Position above the ring
self.context
.move_to(center_x - te.width() / 2.0, center_y + radius / 1.1 + 20.0);
.move_to(center_x - te.width() / 2.0, center_y - radius - 10.0);
self.context.show_text(text).unwrap();
}
@@ -439,7 +452,11 @@ impl Renderer {
};
if intensity > 0.0 {
let (r, g, b, a) = self.config.key_hl_color;
let (r, g, b, a) = if self.caps_lock {
self.config.caps_lock_key_hl_color
} else {
self.config.key_hl_color
};
self.context
.set_source_rgba(r, g, b, a * intensity * self.fade_alpha);
self.context.set_line_width(thickness + 1.5);
@@ -703,6 +720,23 @@ impl Renderer {
}
}
fn draw_keyboard_layout(&self) {
if self.config.show_keyboard_layout {
if let Some(ref layout) = self.system_status.keyboard_layout {
let margin = 20.0;
let x = margin;
let y = margin + 80.0;
self.context.new_path();
self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha);
self.context.set_font_size(16.0);
let text = format!("Layout: {}", layout);
self.context.move_to(x, y);
self.context.show_text(&text).unwrap();
}
}
}
fn draw_icon_at(&self, x: f64, y: f64, surface: &ImageSurface) {
self.context.save().unwrap();
let target_size = 24.0;
+1 -1
View File
@@ -17,7 +17,7 @@ pub struct SystemStatus {
pub wifi_strength: Option<u8>,
pub bluetooth_connected: bool,
pub bluetooth_devices: Vec<String>,
pub keyboard_layout: Option<u32>,
pub keyboard_layout: Option<String>,
}
#[derive(Debug, Clone, Copy)]