Skip to content

Commit 486119a

Browse files
Implement button stretch
1 parent a022fed commit 486119a

2 files changed

Lines changed: 76 additions & 31 deletions

File tree

src/config.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::{
44
};
55
use anyhow::Error;
66
use cairo::FontFace;
7-
use crate::{FunctionLayer, Button};
7+
use crate::FunctionLayer;
88
use crate::fonts::{FontConfig, Pattern};
99
use freetype::Library as FtLibrary;
1010
use input_linux::Key;
@@ -43,7 +43,8 @@ pub struct ButtonConfig {
4343
#[serde(alias = "Svg")]
4444
pub icon: Option<String>,
4545
pub text: Option<String>,
46-
pub action: Key
46+
pub action: Key,
47+
pub stretch: Option<usize>,
4748
}
4849

4950
fn load_font(name: &str) -> FontFace {
@@ -75,14 +76,16 @@ fn load_config(width: u16) -> (Config, [FunctionLayer; 2]) {
7576
base.primary_layer_keys = user.primary_layer_keys.or(base.primary_layer_keys);
7677
base.active_brightness = user.active_brightness.or(base.active_brightness);
7778
};
78-
let media_layer = FunctionLayer::with_config(base.media_layer_keys.unwrap());
79-
let fkey_layer = FunctionLayer::with_config(base.primary_layer_keys.unwrap());
80-
let mut layers = if base.media_layer_default.unwrap(){ [media_layer, fkey_layer] } else { [fkey_layer, media_layer] };
79+
let mut media_layer_keys = base.media_layer_keys.unwrap();
80+
let mut primary_layer_keys = base.primary_layer_keys.unwrap();
8181
if width >= 2170 {
82-
for layer in &mut layers {
83-
layer.buttons.insert(0, Button::new_text("esc".to_string(), Key::Esc));
82+
for layer in [&mut media_layer_keys, &mut primary_layer_keys] {
83+
layer.insert(0, ButtonConfig { icon: None, text: Some("esc".into()), action: Key::Esc, stretch: None });
8484
}
8585
}
86+
let media_layer = FunctionLayer::with_config(media_layer_keys);
87+
let fkey_layer = FunctionLayer::with_config(primary_layer_keys);
88+
let layers = if base.media_layer_default.unwrap(){ [media_layer, fkey_layer] } else { [fkey_layer, media_layer] };
8689
let cfg = Config {
8790
show_button_outlines: base.show_button_outlines.unwrap(),
8891
enable_pixel_shift: base.enable_pixel_shift.unwrap(),

src/main.rs

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ struct Button {
6161
image: ButtonImage,
6262
changed: bool,
6363
active: bool,
64-
action: Key
64+
action: Key,
6565
}
6666

6767
fn try_load_svg(path: &str) -> Result<ButtonImage> {
@@ -103,7 +103,7 @@ impl Button {
103103
action,
104104
active: false,
105105
changed: false,
106-
image: ButtonImage::Text(text)
106+
image: ButtonImage::Text(text),
107107
}
108108
}
109109
fn new_icon(path: &str, action: Key) -> Button {
@@ -154,16 +154,29 @@ impl Button {
154154

155155
#[derive(Default)]
156156
pub struct FunctionLayer {
157-
buttons: Vec<Button>
157+
buttons: Vec<(usize, Button)>,
158+
virtual_button_count: usize,
158159
}
159160

160161
impl FunctionLayer {
161162
fn with_config(cfg: Vec<ButtonConfig>) -> FunctionLayer {
162163
if cfg.is_empty() {
163164
panic!("Invalid configuration, layer has 0 buttons");
164165
}
166+
167+
let mut virtual_button_count = 0;
165168
FunctionLayer {
166-
buttons: cfg.into_iter().map(Button::with_config).collect()
169+
buttons: cfg.into_iter().scan(&mut virtual_button_count, |state, cfg| {
170+
let i = **state;
171+
let mut stretch = cfg.stretch.unwrap_or(1);
172+
if stretch < 1 {
173+
println!("Stretch value must be at least 1, setting to 1.");
174+
stretch = 1;
175+
}
176+
**state += stretch;
177+
Some((i, Button::with_config(cfg)))
178+
}).collect(),
179+
virtual_button_count,
167180
}
168181
}
169182
fn draw(&mut self, config: &Config, width: i32, height: i32, surface: &Surface, pixel_shift: (f64, f64), complete_redraw: bool) -> Vec<ClipRect> {
@@ -176,7 +189,7 @@ impl FunctionLayer {
176189
c.translate(height as f64, 0.0);
177190
c.rotate((90.0f64).to_radians());
178191
let pixel_shift_width = if config.enable_pixel_shift { PIXEL_SHIFT_WIDTH_PX } else { 0 };
179-
let button_width = ((width - pixel_shift_width as i32) - (BUTTON_SPACING_PX * (self.buttons.len() - 1) as i32)) as f64 / self.buttons.len() as f64;
192+
let virtual_button_width = ((width - pixel_shift_width as i32) - (BUTTON_SPACING_PX * (self.virtual_button_count - 1) as i32)) as f64 / self.virtual_button_count as f64;
180193
let radius = 8.0f64;
181194
let bot = (height as f64) * 0.15;
182195
let top = (height as f64) * 0.85;
@@ -188,12 +201,24 @@ impl FunctionLayer {
188201
}
189202
c.set_font_face(&config.font_face);
190203
c.set_font_size(32.0);
191-
for (i, button) in self.buttons.iter_mut().enumerate() {
204+
205+
for i in 0..self.buttons.len() {
206+
let end = if i + 1 < self.buttons.len() {
207+
self.buttons[i + 1].0
208+
} else {
209+
self.virtual_button_count
210+
};
211+
let (start, button) = &mut self.buttons[i];
212+
let start = *start;
213+
192214
if !button.changed && !complete_redraw {
193215
continue;
194216
};
195217

196-
let left_edge = (i as f64 * (button_width + BUTTON_SPACING_PX as f64)).floor() + pixel_shift_x + (pixel_shift_width / 2) as f64;
218+
let left_edge = (start as f64 * (virtual_button_width + BUTTON_SPACING_PX as f64)).floor() + pixel_shift_x + (pixel_shift_width / 2) as f64;
219+
220+
let button_width = virtual_button_width + ((end - start - 1) as f64 * (virtual_button_width + BUTTON_SPACING_PX as f64)).floor();
221+
197222
let color = if button.active {
198223
BUTTON_COLOR_ACTIVE
199224
} else if config.show_button_outlines {
@@ -259,6 +284,33 @@ impl FunctionLayer {
259284

260285
modified_regions
261286
}
287+
288+
fn hit(&self, width: u16, height: u16, x: f64, y: f64, i: Option<usize>) -> Option<usize> {
289+
let virtual_button_width = (width as i32 - (BUTTON_SPACING_PX * (self.virtual_button_count - 1) as i32)) as f64 / self.virtual_button_count as f64;
290+
291+
let i = i.unwrap_or_else(|| {
292+
let virtual_i = (x / (width as f64 / self.virtual_button_count as f64)) as usize;
293+
self.buttons.iter().position(|(start, _)| *start > virtual_i).unwrap_or(self.buttons.len()) - 1
294+
});
295+
296+
let start = self.buttons[i].0;
297+
let end = if i + 1 < self.buttons.len() {
298+
self.buttons[i + 1].0
299+
} else {
300+
self.virtual_button_count
301+
};
302+
303+
let left_edge = (start as f64 * (virtual_button_width + BUTTON_SPACING_PX as f64)).floor();
304+
305+
let button_width = virtual_button_width + ((end - start - 1) as f64 * (virtual_button_width + BUTTON_SPACING_PX as f64)).floor();
306+
307+
if x < left_edge || x > (left_edge + button_width)
308+
|| y < 0.1 * height as f64 || y > 0.9 * height as f64 {
309+
return None;
310+
}
311+
312+
Some(i)
313+
}
262314
}
263315

264316
struct Interface;
@@ -281,15 +333,6 @@ impl LibinputInterface for Interface {
281333
}
282334

283335

284-
fn button_hit(num: u32, idx: u32, width: u16, height: u16, x: f64, y: f64) -> bool {
285-
let button_width = (width as i32 - (BUTTON_SPACING_PX * (num - 1) as i32)) as f64 / num as f64;
286-
let left_edge = idx as f64 * (button_width + BUTTON_SPACING_PX as f64);
287-
if x < left_edge || x > (left_edge + button_width) {
288-
return false
289-
}
290-
y > 0.1 * height as f64 && y < 0.9 * height as f64
291-
}
292-
293336
fn emit<F>(uinput: &mut UInputHandle<F>, ty: EventKind, code: u16, value: i32) where F: AsRawFd {
294337
uinput.write(&[input_event {
295338
value: value,
@@ -368,7 +411,7 @@ fn real_main(drm: &mut DrmBackend) {
368411
uinput.set_evbit(EventKind::Key).unwrap();
369412
for layer in &layers {
370413
for button in &layer.buttons {
371-
uinput.set_keybit(button.action).unwrap();
414+
uinput.set_keybit(button.1.action).unwrap();
372415
}
373416
}
374417
let mut dev_name_c = [0 as c_char; 80];
@@ -405,7 +448,7 @@ fn real_main(drm: &mut DrmBackend) {
405448
next_timeout_ms = min(next_timeout_ms, pixel_shift_next_timeout_ms);
406449
}
407450

408-
if needs_complete_redraw || layers[active_layer].buttons.iter().any(|b| b.changed) {
451+
if needs_complete_redraw || layers[active_layer].buttons.iter().any(|b| b.1.changed) {
409452
let shift = if cfg.enable_pixel_shift {
410453
pixel_shift.get()
411454
} else {
@@ -453,10 +496,9 @@ fn real_main(drm: &mut DrmBackend) {
453496
TouchEvent::Down(dn) => {
454497
let x = dn.x_transformed(width as u32);
455498
let y = dn.y_transformed(height as u32);
456-
let btn = (x / (width as f64 / layers[active_layer].buttons.len() as f64)) as u32;
457-
if button_hit(layers[active_layer].buttons.len() as u32, btn, width, height, x, y) {
499+
if let Some(btn) = layers[active_layer].hit(width, height, x, y, None) {
458500
touches.insert(dn.seat_slot(), (active_layer, btn));
459-
layers[active_layer].buttons[btn as usize].set_active(&mut uinput, true);
501+
layers[active_layer].buttons[btn].1.set_active(&mut uinput, true);
460502
}
461503
},
462504
TouchEvent::Motion(mtn) => {
@@ -467,15 +509,15 @@ fn real_main(drm: &mut DrmBackend) {
467509
let x = mtn.x_transformed(width as u32);
468510
let y = mtn.y_transformed(height as u32);
469511
let (layer, btn) = *touches.get(&mtn.seat_slot()).unwrap();
470-
let hit = button_hit(layers[layer].buttons.len() as u32, btn, width, height, x, y);
471-
layers[layer].buttons[btn as usize].set_active(&mut uinput, hit);
512+
let hit = layers[active_layer].hit(width, height, x, y, Some(btn)).is_some();
513+
layers[layer].buttons[btn].1.set_active(&mut uinput, hit);
472514
},
473515
TouchEvent::Up(up) => {
474516
if !touches.contains_key(&up.seat_slot()) {
475517
continue;
476518
}
477519
let (layer, btn) = *touches.get(&up.seat_slot()).unwrap();
478-
layers[layer].buttons[btn as usize].set_active(&mut uinput, false);
520+
layers[layer].buttons[btn].1.set_active(&mut uinput, false);
479521
}
480522
_ => {}
481523
}

0 commit comments

Comments
 (0)