add support for a hint label in custom keys
this is used in worf-warden to show that shift can be used as additional modifier to send enter
This commit is contained in:
parent
0557593230
commit
340b0fbfea
5 changed files with 179 additions and 67 deletions
|
@ -65,6 +65,9 @@ Styling names and classes are inspired by wofi, so most of the documentation and
|
||||||
| `row` | Row containing the entry, used to control hover effects. |
|
| `row` | Row containing the entry, used to control hover effects. |
|
||||||
| `custom-key-label-text` | The label for custom keys |
|
| `custom-key-label-text` | The label for custom keys |
|
||||||
| `custom-key-label-box` | Box containing the label, can be used for borders etc. |
|
| `custom-key-label-box` | Box containing the label, can be used for borders etc. |
|
||||||
|
| `custom-key-hint-text` | The label for custom keys hint |
|
||||||
|
| `custom-key-hint-box` | Box containing the hint, can be used for borders etc. |
|
||||||
|
|
||||||
|
|
||||||
Checkout more showcases in the [styles directory of this repo](styles).
|
Checkout more showcases in the [styles directory of this repo](styles).
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ use std::env;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use worf_lib::config::Config;
|
use worf_lib::config::{Config, CustomKeyHintLocation};
|
||||||
use worf_lib::desktop::{copy_to_clipboard, spawn_fork};
|
use worf_lib::desktop::{copy_to_clipboard, spawn_fork};
|
||||||
use worf_lib::gui::{ItemProvider, Key, KeyBinding, MenuItem, Modifier};
|
use worf_lib::gui::{CustomKeyHint, CustomKeys, ItemProvider, Key, KeyBinding, MenuItem, Modifier};
|
||||||
use worf_lib::{config, gui};
|
use worf_lib::{config, gui};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -189,6 +189,16 @@ fn key_type_all() -> KeyBinding {
|
||||||
key: Key::Num1,
|
key: Key::Num1,
|
||||||
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
||||||
label: "<b>Alt+1</b> Type All".to_string(),
|
label: "<b>Alt+1</b> Type All".to_string(),
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_type_all_and_enter() -> KeyBinding {
|
||||||
|
KeyBinding {
|
||||||
|
key: Key::Exclamation,
|
||||||
|
modifiers: vec![Modifier::Alt, Modifier::Shift].into_iter().collect(),
|
||||||
|
label: String::new(),
|
||||||
|
visible: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +207,16 @@ fn key_type_user() -> KeyBinding {
|
||||||
key: Key::Num2,
|
key: Key::Num2,
|
||||||
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
||||||
label: "<b>Alt+2</b> Type User".to_string(),
|
label: "<b>Alt+2</b> Type User".to_string(),
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_type_user_and_enter() -> KeyBinding {
|
||||||
|
KeyBinding {
|
||||||
|
key: Key::At,
|
||||||
|
modifiers: vec![Modifier::Alt, Modifier::Shift].into_iter().collect(),
|
||||||
|
label: String::new(),
|
||||||
|
visible: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +225,7 @@ fn key_type_password() -> KeyBinding {
|
||||||
key: Key::Num3,
|
key: Key::Num3,
|
||||||
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
||||||
label: "<b>Alt+3</b> Type Password".to_string(),
|
label: "<b>Alt+3</b> Type Password".to_string(),
|
||||||
|
visible: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +233,8 @@ fn key_type_password_and_enter() -> KeyBinding {
|
||||||
KeyBinding {
|
KeyBinding {
|
||||||
key: Key::Hash,
|
key: Key::Hash,
|
||||||
modifiers: vec![Modifier::Alt, Modifier::Shift].into_iter().collect(),
|
modifiers: vec![Modifier::Alt, Modifier::Shift].into_iter().collect(),
|
||||||
label: "<b>Alt+Shift+3</b> Type Password + Enter".to_string(),
|
label: String::new(),
|
||||||
|
visible: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +243,16 @@ fn key_type_totp() -> KeyBinding {
|
||||||
key: Key::Num4,
|
key: Key::Num4,
|
||||||
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
||||||
label: "<b>Alt+4</b> Type Totp".to_string(),
|
label: "<b>Alt+4</b> Type Totp".to_string(),
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_type_totp_and_enter() -> KeyBinding {
|
||||||
|
KeyBinding {
|
||||||
|
key: Key::Dollar,
|
||||||
|
modifiers: vec![Modifier::Alt, Modifier::Shift].into_iter().collect(),
|
||||||
|
label: String::new(),
|
||||||
|
visible: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +261,7 @@ fn key_sync() -> KeyBinding {
|
||||||
key: Key::R,
|
key: Key::R,
|
||||||
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
||||||
label: "<b>Alt+r</b> Sync".to_string(),
|
label: "<b>Alt+r</b> Sync".to_string(),
|
||||||
|
visible: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +271,7 @@ fn key_totp() -> KeyBinding {
|
||||||
key: Key::T,
|
key: Key::T,
|
||||||
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
||||||
label: "<b>Alt+t</b> Totp".to_string(),
|
label: "<b>Alt+t</b> Totp".to_string(),
|
||||||
|
visible: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +280,7 @@ fn key_lock() -> KeyBinding {
|
||||||
key: Key::L,
|
key: Key::L,
|
||||||
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
modifiers: vec![Modifier::Alt].into_iter().collect(),
|
||||||
label: "<b>Alt+l</b> Lock".to_string(),
|
label: "<b>Alt+l</b> Lock".to_string(),
|
||||||
|
visible: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,16 +290,25 @@ fn show(config: Config, provider: PasswordProvider) -> Result<(), String> {
|
||||||
provider,
|
provider,
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
Some(vec![
|
Some(CustomKeys {
|
||||||
key_type_all(),
|
bindings: vec![
|
||||||
key_type_user(),
|
key_type_all(),
|
||||||
key_type_password(),
|
key_type_all_and_enter(),
|
||||||
key_type_password_and_enter(),
|
key_type_user(),
|
||||||
key_type_totp(),
|
key_type_user_and_enter(),
|
||||||
key_sync(),
|
key_type_password(),
|
||||||
key_totp(),
|
key_type_password_and_enter(),
|
||||||
key_lock(),
|
key_type_totp(),
|
||||||
]),
|
key_type_totp_and_enter(),
|
||||||
|
key_sync(),
|
||||||
|
key_totp(),
|
||||||
|
key_lock(),
|
||||||
|
],
|
||||||
|
hint: Some(CustomKeyHint {
|
||||||
|
label: "Use Shift as additional modifier to send enter".to_string(),
|
||||||
|
location: CustomKeyHintLocation::Top,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
) {
|
) {
|
||||||
Ok(selection) => {
|
Ok(selection) => {
|
||||||
if let Some(meta) = selection.menu.data {
|
if let Some(meta) = selection.menu.data {
|
||||||
|
@ -276,18 +320,15 @@ fn show(config: Config, provider: PasswordProvider) -> Result<(), String> {
|
||||||
|
|
||||||
sleep(Duration::from_millis(500));
|
sleep(Duration::from_millis(500));
|
||||||
if let Some(key) = selection.custom_key {
|
if let Some(key) = selection.custom_key {
|
||||||
if key == key_type_all() {
|
if key == key_type_all() || key == key_type_all_and_enter() {
|
||||||
keyboard_type(&rbw_get_user(id, false)?);
|
keyboard_type(&rbw_get_user(id, false)?);
|
||||||
keyboard_tab();
|
keyboard_tab();
|
||||||
keyboard_type(&rbw_get_password(id, false)?);
|
keyboard_type(&rbw_get_password(id, false)?);
|
||||||
} else if key == key_type_user() {
|
} else if key == key_type_user() || key == key_type_user_and_enter() {
|
||||||
keyboard_type(&rbw_get_user(id, false)?);
|
keyboard_type(&rbw_get_user(id, false)?);
|
||||||
} else if key == key_type_password() {
|
} else if key == key_type_password() || key == key_type_password_and_enter() {
|
||||||
keyboard_type(&rbw_get_password(id, false)?);
|
keyboard_type(&rbw_get_password(id, false)?);
|
||||||
} else if key == key_type_password_and_enter() {
|
} else if key == key_type_totp() || key == key_type_totp_and_enter() {
|
||||||
keyboard_type(&rbw_get_password(id, false)?);
|
|
||||||
keyboard_return();
|
|
||||||
} else if key == key_type_totp() {
|
|
||||||
keyboard_type(&rbw_get_totp(id, false)?);
|
keyboard_type(&rbw_get_totp(id, false)?);
|
||||||
} else if key == key_lock() {
|
} else if key == key_lock() {
|
||||||
rbw("lock", None)?;
|
rbw("lock", None)?;
|
||||||
|
@ -296,6 +337,10 @@ fn show(config: Config, provider: PasswordProvider) -> Result<(), String> {
|
||||||
} else if key == key_totp() {
|
} else if key == key_totp() {
|
||||||
rbw_get_totp(id, true)?;
|
rbw_get_totp(id, true)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if key.modifiers.contains(&Modifier::Shift) {
|
||||||
|
keyboard_return();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let pw = rbw_get_password(id, true)?;
|
let pw = rbw_get_password(id, true)?;
|
||||||
if let Err(e) = copy_to_clipboard(pw, None) {
|
if let Err(e) = copy_to_clipboard(pw, None) {
|
||||||
|
|
|
@ -74,8 +74,15 @@ font-family: DejaVu;
|
||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25em;
|
||||||
border-right: 1px solid rgba(214, 174, 0, 1);
|
border-right: 1px solid rgba(214, 174, 0, 1);
|
||||||
border-left: 1px solid rgba(214, 174, 0, 1);
|
border-left: 1px solid rgba(214, 174, 0, 1);
|
||||||
|
border-bottom: 1px solid rgba(214, 174, 0, 1);
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-key-hint-box {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#custom-key-label-text {
|
#custom-key-label-text {
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,12 @@ pub enum SortOrder {
|
||||||
Alphabetical,
|
Alphabetical,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub enum CustomKeyHintLocation {
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
/// searches `$PATH` for executables and allows them to be run by selecting them.
|
/// searches `$PATH` for executables and allows them to be run by selecting them.
|
||||||
|
|
|
@ -25,7 +25,7 @@ use gtk4_layer_shell::{Edge, KeyboardMode, LayerShell};
|
||||||
use log;
|
use log;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::config::{Anchor, Config, MatchMethod, SortOrder, WrapMode};
|
use crate::config::{Anchor, Config, CustomKeyHintLocation, MatchMethod, SortOrder, WrapMode};
|
||||||
use crate::desktop::known_image_extension_regex_pattern;
|
use crate::desktop::known_image_extension_regex_pattern;
|
||||||
use crate::{Error, config, desktop};
|
use crate::{Error, config, desktop};
|
||||||
|
|
||||||
|
@ -83,17 +83,11 @@ impl From<config::Align> for Align {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_core_order(gtk_order: &Ordering) -> core::cmp::Ordering {
|
fn into_core_order(gtk_order: Ordering) -> core::cmp::Ordering {
|
||||||
match gtk_order {
|
match gtk_order {
|
||||||
Ordering::Smaller => {
|
Ordering::Smaller => core::cmp::Ordering::Less,
|
||||||
core::cmp::Ordering::Less
|
Ordering::Larger => core::cmp::Ordering::Greater,
|
||||||
}
|
_ => core::cmp::Ordering::Equal,
|
||||||
Ordering::Larger => {
|
|
||||||
core::cmp::Ordering::Greater
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
core::cmp::Ordering::Equal
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +380,19 @@ pub struct KeyBinding {
|
||||||
pub key: Key,
|
pub key: Key,
|
||||||
pub modifiers: HashSet<Modifier>,
|
pub modifiers: HashSet<Modifier>,
|
||||||
pub label: String,
|
pub label: String,
|
||||||
|
pub visible: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct CustomKeyHint {
|
||||||
|
pub label: String,
|
||||||
|
pub location: CustomKeyHintLocation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct CustomKeys {
|
||||||
|
pub bindings: Vec<KeyBinding>,
|
||||||
|
pub hint: Option<CustomKeyHint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> MenuItem<T> {
|
impl<T: Clone> MenuItem<T> {
|
||||||
|
@ -445,7 +452,7 @@ pub fn show<T, P>(
|
||||||
item_provider: P,
|
item_provider: P,
|
||||||
new_on_empty: bool,
|
new_on_empty: bool,
|
||||||
search_ignored_words: Option<Vec<Regex>>,
|
search_ignored_words: Option<Vec<Regex>>,
|
||||||
custom_keys: Option<Vec<KeyBinding>>,
|
custom_keys: Option<CustomKeys>,
|
||||||
) -> Result<Selection<T>, Error>
|
) -> Result<Selection<T>, Error>
|
||||||
where
|
where
|
||||||
T: Clone + 'static + Send,
|
T: Clone + 'static + Send,
|
||||||
|
@ -503,7 +510,7 @@ fn build_ui<T, P>(
|
||||||
app: Application,
|
app: Application,
|
||||||
new_on_empty: bool,
|
new_on_empty: bool,
|
||||||
search_ignored_words: Option<Vec<Regex>>,
|
search_ignored_words: Option<Vec<Regex>>,
|
||||||
custom_keys: Option<&Vec<KeyBinding>>,
|
custom_keys: Option<&CustomKeys>,
|
||||||
) where
|
) where
|
||||||
T: Clone + 'static + Send,
|
T: Clone + 'static + Send,
|
||||||
P: ItemProvider<T> + 'static + Send,
|
P: ItemProvider<T> + 'static + Send,
|
||||||
|
@ -569,7 +576,9 @@ fn build_ui<T, P>(
|
||||||
let outer_box = gtk4::Box::new(config.orientation().into(), 0);
|
let outer_box = gtk4::Box::new(config.orientation().into(), 0);
|
||||||
outer_box.set_widget_name("outer-box");
|
outer_box.set_widget_name("outer-box");
|
||||||
outer_box.append(&ui_elements.search);
|
outer_box.append(&ui_elements.search);
|
||||||
build_custom_key_view(custom_keys, &outer_box);
|
if let Some(custom_keys) = custom_keys {
|
||||||
|
build_custom_key_view(custom_keys, &outer_box);
|
||||||
|
}
|
||||||
|
|
||||||
ui_elements.window.set_child(Some(&outer_box));
|
ui_elements.window.set_child(Some(&outer_box));
|
||||||
|
|
||||||
|
@ -595,15 +604,11 @@ fn build_ui<T, P>(
|
||||||
log::debug!("got items after {:?}", wait_for_items.elapsed());
|
log::debug!("got items after {:?}", wait_for_items.elapsed());
|
||||||
|
|
||||||
let active_cfg = config.clone();
|
let active_cfg = config.clone();
|
||||||
//let map_cfg = config.clone();
|
|
||||||
let animate_window = ui_elements.window.clone();
|
let animate_window = ui_elements.window.clone();
|
||||||
|
|
||||||
animate_window.connect_is_active_notify(move |w| {
|
animate_window.connect_is_active_notify(move |w| {
|
||||||
window_show_resize(&active_cfg.clone(), w);
|
window_show_resize(&active_cfg.clone(), w);
|
||||||
});
|
});
|
||||||
// animate_window.connect_map(move |w| {
|
|
||||||
// window_show_resize(&map_cfg.clone(), w);
|
|
||||||
// });
|
|
||||||
|
|
||||||
build_ui_from_menu_items(&ui_elements, &meta, provider_elements);
|
build_ui_from_menu_items(&ui_elements, &meta, provider_elements);
|
||||||
|
|
||||||
|
@ -626,7 +631,6 @@ fn build_main_box<T: Clone + 'static>(config: &Config, ui_elements: &Rc<UiElemen
|
||||||
.main_box
|
.main_box
|
||||||
.set_max_children_per_line(config.columns());
|
.set_max_children_per_line(config.columns());
|
||||||
ui_elements.main_box.set_activate_on_single_click(true);
|
ui_elements.main_box.set_activate_on_single_click(true);
|
||||||
|
|
||||||
ui_elements.main_box.set_halign(config.halign().into());
|
ui_elements.main_box.set_halign(config.halign().into());
|
||||||
ui_elements.main_box.set_valign(config.valign().into());
|
ui_elements.main_box.set_valign(config.valign().into());
|
||||||
if config.orientation() == config::Orientation::Horizontal {
|
if config.orientation() == config::Orientation::Horizontal {
|
||||||
|
@ -664,31 +668,75 @@ fn build_search_entry<T: Clone + Send>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_custom_key_view(custom_keys: Option<&Vec<KeyBinding>>, outer_box: >k4::Box) {
|
fn build_custom_key_view(custom_keys: &CustomKeys, outer_box: >k4::Box) {
|
||||||
let inner_box = FlowBox::new();
|
fn create_label(inner_box: &FlowBox, text: &str, label_css: &str, box_css: &str) {
|
||||||
|
let label_box = FlowBoxChild::new();
|
||||||
|
label_box.set_halign(Align::Fill);
|
||||||
|
inner_box.set_valign(Align::Start);
|
||||||
|
label_box.set_widget_name(box_css);
|
||||||
|
inner_box.append(&label_box);
|
||||||
|
inner_box.set_vexpand(false);
|
||||||
|
inner_box.set_hexpand(false);
|
||||||
|
let label = Label::new(Some(text));
|
||||||
|
label.set_halign(Align::Fill);
|
||||||
|
label.set_valign(Align::Start);
|
||||||
|
label.set_use_markup(true);
|
||||||
|
label.set_hexpand(true);
|
||||||
|
label.set_vexpand(false);
|
||||||
|
label.set_widget_name(label_css);
|
||||||
|
label.set_wrap(false);
|
||||||
|
label.set_xalign(0.0);
|
||||||
|
label_box.set_child(Some(&label));
|
||||||
|
}
|
||||||
|
|
||||||
|
let inner_box = gtk4::Box::new(Orientation::Vertical, 0);
|
||||||
inner_box.set_halign(Align::Fill);
|
inner_box.set_halign(Align::Fill);
|
||||||
inner_box.set_widget_name("custom-key-box");
|
|
||||||
if let Some(custom_keys) = custom_keys {
|
let hint_box = FlowBox::new();
|
||||||
for key in custom_keys {
|
hint_box.set_halign(Align::Fill);
|
||||||
let label_box = FlowBoxChild::new();
|
hint_box.set_widget_name("custom-key-box");
|
||||||
label_box.set_halign(Align::Fill);
|
|
||||||
inner_box.set_valign(Align::Start);
|
let custom_key_box = FlowBox::new();
|
||||||
label_box.set_widget_name("custom-key-label-box");
|
custom_key_box.set_halign(Align::Fill);
|
||||||
inner_box.append(&label_box);
|
custom_key_box.set_widget_name("custom-key-box");
|
||||||
inner_box.set_vexpand(false);
|
inner_box.append(&custom_key_box);
|
||||||
inner_box.set_hexpand(false);
|
|
||||||
let label = Label::new(Some(&key.label));
|
let make_key_labels = || {
|
||||||
label.set_halign(Align::Fill);
|
for key in custom_keys.bindings.iter().filter(|key| key.visible) {
|
||||||
label.set_valign(Align::Start);
|
create_label(
|
||||||
label.set_use_markup(true);
|
&custom_key_box,
|
||||||
label.set_hexpand(true);
|
key.label.as_ref(),
|
||||||
label.set_vexpand(false);
|
"custom-key-label-text",
|
||||||
label.set_widget_name("custom-key-label-text");
|
"custom-key-label-box",
|
||||||
label.set_wrap(false);
|
);
|
||||||
label.set_xalign(0.0);
|
}
|
||||||
label_box.set_child(Some(&label));
|
};
|
||||||
|
|
||||||
|
if let Some(hint) = custom_keys.hint.as_ref() {
|
||||||
|
match hint.location {
|
||||||
|
CustomKeyHintLocation::Top => {
|
||||||
|
inner_box.append(&hint_box);
|
||||||
|
create_label(
|
||||||
|
&hint_box,
|
||||||
|
&hint.label,
|
||||||
|
"custom-key-hint-text",
|
||||||
|
"custom-key-hint-box",
|
||||||
|
);
|
||||||
|
make_key_labels();
|
||||||
|
} // todo this surely can be done better
|
||||||
|
CustomKeyHintLocation::Bottom => {
|
||||||
|
make_key_labels();
|
||||||
|
create_label(
|
||||||
|
&hint_box,
|
||||||
|
&hint.label,
|
||||||
|
"custom-key-hint-text",
|
||||||
|
"custom-key-hint-box",
|
||||||
|
);
|
||||||
|
inner_box.append(&hint_box);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outer_box.append(&inner_box);
|
outer_box.append(&inner_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,7 +819,7 @@ fn build_ui_from_menu_items<T: Clone + 'static + Send>(
|
||||||
fn setup_key_event_handler<T: Clone + 'static + Send>(
|
fn setup_key_event_handler<T: Clone + 'static + Send>(
|
||||||
ui: &Rc<UiElements<T>>,
|
ui: &Rc<UiElements<T>>,
|
||||||
meta: &Rc<MetaData<T>>,
|
meta: &Rc<MetaData<T>>,
|
||||||
custom_keys: Option<&Vec<KeyBinding>>,
|
custom_keys: Option<&CustomKeys>,
|
||||||
) {
|
) {
|
||||||
let key_controller = EventControllerKey::new();
|
let key_controller = EventControllerKey::new();
|
||||||
|
|
||||||
|
@ -797,7 +845,7 @@ fn handle_key_press<T: Clone + 'static + Send>(
|
||||||
meta: &Rc<MetaData<T>>,
|
meta: &Rc<MetaData<T>>,
|
||||||
keyboard_key: gdk4::Key,
|
keyboard_key: gdk4::Key,
|
||||||
modifier_type: gdk4::ModifierType,
|
modifier_type: gdk4::ModifierType,
|
||||||
custom_keys: Option<&Vec<KeyBinding>>,
|
custom_keys: Option<&CustomKeys>,
|
||||||
) -> Propagation {
|
) -> Propagation {
|
||||||
let update_view = |query: &String| {
|
let update_view = |query: &String| {
|
||||||
let mut lock = ui.menu_rows.write().unwrap();
|
let mut lock = ui.menu_rows.write().unwrap();
|
||||||
|
@ -820,7 +868,7 @@ fn handle_key_press<T: Clone + 'static + Send>(
|
||||||
|
|
||||||
if let Some(custom_keys) = custom_keys {
|
if let Some(custom_keys) = custom_keys {
|
||||||
let mods = modifiers_from_mask(modifier_type);
|
let mods = modifiers_from_mask(modifier_type);
|
||||||
for custom_key in custom_keys {
|
for custom_key in &custom_keys.bindings {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"comparing custom key {custom_key:?} to mask {mods:?} and key {keyboard_key}"
|
"comparing custom key {custom_key:?} to mask {mods:?} and key {keyboard_key}"
|
||||||
);
|
);
|
||||||
|
@ -935,7 +983,10 @@ fn sort_flow_box_childs<T: Clone>(
|
||||||
sort_menu_items_by_score(m1, m2)
|
sort_menu_items_by_score(m1, m2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_menu_items_by_score<T: Clone>(m1: Option<&MenuItem<T>>, m2: Option<&MenuItem<T>>) -> Ordering {
|
fn sort_menu_items_by_score<T: Clone>(
|
||||||
|
m1: Option<&MenuItem<T>>,
|
||||||
|
m2: Option<&MenuItem<T>>,
|
||||||
|
) -> Ordering {
|
||||||
match (m1, m2) {
|
match (m1, m2) {
|
||||||
(Some(menu1), Some(menu2)) => {
|
(Some(menu1), Some(menu2)) => {
|
||||||
fn compare(a: f64, b: f64) -> Ordering {
|
fn compare(a: f64, b: f64) -> Ordering {
|
||||||
|
@ -1376,7 +1427,7 @@ pub fn apply_sort<T: Clone>(items: &mut [MenuItem<T>], order: &SortOrder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items.sort_by(|l, r| into_core_order(&sort_menu_items_by_score(Some(l), Some(r))));
|
items.sort_by(|l, r| into_core_order(sort_menu_items_by_score(Some(l), Some(r))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue