Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consume_key and consume_shortcut with input field #5338

Open
nacl42 opened this issue Nov 1, 2024 · 2 comments
Open

consume_key and consume_shortcut with input field #5338

nacl42 opened this issue Nov 1, 2024 · 2 comments
Labels
bug Something is broken

Comments

@nacl42
Copy link

nacl42 commented Nov 1, 2024

Describe the bug
When a keyboard shortcut is consumed, the key will be inserted into an active edit field anyway.

In the below example, there is an edit field to type and independent of this, the keyboard shortcut ALT-B will be intercepted. In the example, the keyboard shortcut is processed before the edit field is displayed. Pressing ALT-B will trigger the action but will also insert the letter 'b' into the edit field.

To Reproduce
Steps to reproduce the behavior:

use eframe::egui;

fn main() -> eframe::Result {
    eframe::run_native(
        "xyz",
        eframe::NativeOptions::default(),
        Box::new(|_cc| Ok(Box::<MyApp>::default())),
    )
}

#[derive(Default)]
pub struct MyApp {
    content: String,
    show_label: bool,
}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            if ctx.input_mut(|i| i.consume_key(egui::Modifiers::ALT, egui::Key::B)) {
                self.show_label = true;
            };
            ui.label("Type a few chars and then press ALT-B:");
            ui.text_edit_singleline(&mut self.content);
            if self.show_label {
                ui.label("You pressed ALT-B. Note that the char 'b' is inserted into the edit field, even though consume_key has been called.");
            }
        });
    }
}

Expected behavior

I would expect that if the key is consumed it will not be interpreted by the text edit. This is also what the function description indicates: "Check for a key press. If found, true is returned and the key pressed is consumed, so that this will only return true once.".

Screenshots

Bildschirmfoto_2024-11-01_16-57-03

Bildschirmfoto_2024-11-01_16-57-32

Desktop (please complete the following information):

  • OS: ArchLinux
@nacl42 nacl42 added the bug Something is broken label Nov 1, 2024
@nacl42
Copy link
Author

nacl42 commented Nov 1, 2024

The issue might be in the following function in input_state/mod.rs:

pub fn count_and_consume_key(&mut self, modifiers: Modifiers, logical_key: Key) -> usize {
        let mut count = 0usize;

        self.events.retain(|event| {
            let is_match = matches!(
                event,
                Event::Key {
                    key: ev_key,
                    modifiers: ev_mods,
                    pressed: true,
                    ..
                } if *ev_key == logical_key && ev_mods.matches_logically(modifiers)
            );

            count += is_match as usize;

            !is_match
        });

        count
    }

It removes the actual event for the modifier (in this case ALT-B), but there seems to be a second event (B without any modifier). This event is then triggered for the input field.

The question is: What is the expected behavior?

@nacl42
Copy link
Author

nacl42 commented Nov 1, 2024

I think I found the cause of the problem:

See crate/egui-winit/src/lib.rs:

 786         if let Some(text) = &text {
 787             // Make sure there is text, and that it is not control characters
 788             // (e.g. delete is sent as "\u{f728}" on macOS).
 789             if !text.is_empty() && text.chars().all(is_printable_char) {
 790                 // On some platforms we get here when the user presses Cmd-C (copy), ctrl-W, etc.
 791                 // We need to ignore these characters that are side-effects of commands.
 792                 // Also make sure the key is pressed (not released). On Linux, text might
 793                 // contain some data even when the key is released.
 794                 let is_cmd = self.egui_input.modifiers.ctrl
 795                     || self.egui_input.modifiers.command
 796                     || self.egui_input.modifiers.mac_cmd;
 797                 if pressed && !is_cmd {
 798                     self.egui_input
 799                         .events
 800                         .push(egui::Event::Text(text.to_string()));
 801                 }
 802             }
 803         }
 804     }

IMHO the alt modifier should be handled similar to ctrl, command and mac_cmd.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is broken
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant