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

Key modifier state after a modifier is pressed or released #49

Open
quaternic opened this issue Sep 15, 2022 · 2 comments
Open

Key modifier state after a modifier is pressed or released #49

quaternic opened this issue Sep 15, 2022 · 2 comments

Comments

@quaternic
Copy link

The modifier key state changes are only reaching egui on the next key event. For example, if you press and hold Ctrl and don't press any other key, egui will not know about it. If you then release it, egui will now think it is being held down, until some future key event.

As I understand it, miniquad is passing through (from X11) key up/down events whose modifier state does not include the effect of that event itself. Next, egui-miniquad stores that pre-event modifier state and discards the key event since egui doesn't care about those. It then sends that incorrect state to egui for new frames and with events where miniquad doesn't include the modifier state (e.g. mouse events).

Test program (using egui-miniquad v0.12.0 and miniquad v0.3.13)
use {egui_miniquad as egui_mq, miniquad as mq};

struct Stage {
    egui_mq: egui_mq::EguiMq,
}

impl Stage {
    pub fn new(ctx: &mut mq::Context) -> Stage {
        Stage {
            egui_mq: egui_mq::EguiMq::new(ctx),
        }
    }
}

impl mq::EventHandler for Stage {
    fn update(&mut self, _ctx: &mut mq::Context) {}

    fn draw(&mut self, ctx: &mut mq::Context) {
        self.egui_mq.run(ctx, |mq_ctx, egui_ctx| {
            egui::CentralPanel::default().show(&egui_ctx, |ui| {
                ui.label(format!("{:#?}",ui.input().modifiers));
            });
        });
        self.egui_mq.draw(ctx);
        ctx.commit_frame();
    }

    fn mouse_motion_event(&mut self, _: &mut mq::Context, x: f32, y: f32) {
        self.egui_mq.mouse_motion_event(x, y);
    }

    fn mouse_wheel_event(&mut self, _: &mut mq::Context, dx: f32, dy: f32) {
        self.egui_mq.mouse_wheel_event(dx, dy);
    }

    fn mouse_button_down_event(
        &mut self,
        ctx: &mut mq::Context,
        mb: mq::MouseButton,
        x: f32,
        y: f32,
    ) {
        self.egui_mq.mouse_button_down_event(ctx, mb, x, y);
    }

    fn mouse_button_up_event(
        &mut self,
        ctx: &mut mq::Context,
        mb: mq::MouseButton,
        x: f32,
        y: f32,
    ) {
        self.egui_mq.mouse_button_up_event(ctx, mb, x, y);
    }

    fn char_event(
        &mut self,
        _ctx: &mut mq::Context,
        character: char,
        _keymods: mq::KeyMods,
        _repeat: bool,
    ) {
        self.egui_mq.char_event(character);
    }

    fn key_down_event(
        &mut self,
        ctx: &mut mq::Context,
        keycode: mq::KeyCode,
        keymods: mq::KeyMods,
        _repeat: bool,
    ) {
        if keycode == mq::KeyCode::Q {
            std::process::exit(0);
        }
        println!("---KEY DOWN---");
        dbg!(keycode);
        dbg!(keymods);
        println!("calling egui_mq.key_down_event");
        self.egui_mq.key_down_event(ctx, keycode, keymods);
        println!("---END---");
    }

    fn key_up_event(&mut self, _ctx: &mut mq::Context, keycode: mq::KeyCode, keymods: mq::KeyMods) {
        println!("---KEY UP---");
        dbg!(keycode);
        dbg!(keymods);
        println!("calling egui_mq.key_up_event");
        self.egui_mq.key_up_event(keycode, keymods);
        println!("---END---");
    }
}

fn main() {
    mq::start(Default::default(), |mut ctx| Box::new(Stage::new(&mut ctx)));
}
@quaternic
Copy link
Author

This similar issue in glfw has some informative discussion: glfw/glfw#1630

I've realized I can easily work around it by changing the keymods in my event handlers, but it's not a general solution since it doesn't properly account for keymaps and likely a bunch of other cases. It now seems that this will need changes in miniquad instead.

Workaround
    fn key_down_event(
        &mut self,
        ctx: &mut mq::Context,
        keycode: mq::KeyCode,
        mut keymods: mq::KeyMods,
        _repeat: bool,
    ) {
        match keycode {
            mq::KeyCode::LeftShift | mq::KeyCode::RightShift => keymods.shift = true,
            mq::KeyCode::LeftControl | mq::KeyCode::RightControl => keymods.ctrl = true,
            mq::KeyCode::LeftAlt /*| mq::KeyCode::RightAlt*/ => keymods.alt = true,
            mq::KeyCode::LeftSuper | mq::KeyCode::RightSuper => keymods.logo = true,
            _ => (),
        }
        self.egui_mq.key_down_event(ctx, keycode, keymods);

    }

    fn key_up_event(&mut self, _ctx: &mut mq::Context, keycode: mq::KeyCode, mut keymods: mq::KeyMods) {
        match keycode {
            mq::KeyCode::LeftShift | mq::KeyCode::RightShift => keymods.shift = false,
            mq::KeyCode::LeftControl | mq::KeyCode::RightControl => keymods.ctrl = false,
            mq::KeyCode::LeftAlt /*| mq::KeyCode::RightAlt*/ => keymods.alt = false,
            mq::KeyCode::LeftSuper | mq::KeyCode::RightSuper => keymods.logo = false,
            _ => (),
        }
        self.egui_mq.key_up_event(keycode, keymods);
    }

@skydig
Copy link

skydig commented Sep 18, 2022

use this PR not-fl3/miniquad#313
you can capture the key modifer,
@quaternic

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

No branches or pull requests

2 participants