mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 14:50:03 -04:00
Update to winit 0.29 (#3649)
* Closes https://github.com/emilk/egui/issues/3542 * Closes https://github.com/emilk/egui/issues/2977 * Closes https://github.com/emilk/egui/issues/3303 --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
@@ -361,8 +361,20 @@ pub enum Event {
|
||||
|
||||
/// A key was pressed or released.
|
||||
Key {
|
||||
/// The logical key, heeding the users keymap.
|
||||
///
|
||||
/// For instance, if the user is using Dvorak keyboard layout,
|
||||
/// this will take that into account.
|
||||
key: Key,
|
||||
|
||||
/// The physical key, corresponding to the actual position on the keyboard.
|
||||
///
|
||||
/// This ignored keymaps, so it is not recommended to use this.
|
||||
/// The only thing it makes sense for is things like games,
|
||||
/// where e.g. the physical location of WSAD on QWERTY should always map to movement,
|
||||
/// even if the user is using Dvorak or AZERTY.
|
||||
physical_key: Option<Key>,
|
||||
|
||||
/// Was it pressed or released?
|
||||
pressed: bool,
|
||||
|
||||
@@ -844,11 +856,8 @@ impl<'a> ModifierNames<'a> {
|
||||
|
||||
/// Keyboard keys.
|
||||
///
|
||||
/// Includes all keys egui is interested in (such as `Home` and `End`)
|
||||
/// plus a few that are useful for detecting keyboard shortcuts.
|
||||
///
|
||||
/// Many keys are omitted because they are not always physical keys (depending on keyboard language), e.g. `;` and `§`,
|
||||
/// and are therefore unsuitable as keyboard shortcuts if you want your app to be portable.
|
||||
/// egui usually uses logical keys, i.e. after applying any user keymap.
|
||||
// TODO(emilk): split into `LogicalKey` and `PhysicalKey`
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub enum Key {
|
||||
@@ -870,12 +879,28 @@ pub enum Key {
|
||||
PageUp,
|
||||
PageDown,
|
||||
|
||||
/// The virtual keycode for the Minus key.
|
||||
// ----------------------------------------------
|
||||
// Punctuation:
|
||||
/// `:`
|
||||
Colon,
|
||||
|
||||
/// `,`
|
||||
Comma,
|
||||
|
||||
/// `-`
|
||||
Minus,
|
||||
|
||||
/// The virtual keycode for the Plus/Equals key.
|
||||
/// `.`
|
||||
Period,
|
||||
|
||||
/// The for the Plus/Equals key.
|
||||
PlusEquals,
|
||||
|
||||
/// `;`
|
||||
Semicolon,
|
||||
|
||||
// ----------------------------------------------
|
||||
// Digits:
|
||||
/// Either from the main row or from the numpad.
|
||||
Num0,
|
||||
|
||||
@@ -906,6 +931,8 @@ pub enum Key {
|
||||
/// Either from the main row or from the numpad.
|
||||
Num9,
|
||||
|
||||
// ----------------------------------------------
|
||||
// Letters:
|
||||
A, // Used for cmd+A (select All)
|
||||
B,
|
||||
C, // |CMD COPY|
|
||||
@@ -933,7 +960,8 @@ pub enum Key {
|
||||
Y,
|
||||
Z, // |CMD UNDO|
|
||||
|
||||
// The function keys:
|
||||
// ----------------------------------------------
|
||||
// Function keys:
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
@@ -954,9 +982,196 @@ pub enum Key {
|
||||
F18,
|
||||
F19,
|
||||
F20,
|
||||
// When adding keys, remember to also update `crates/egui-winit/src/lib.rs`
|
||||
// and [`Self::ALL`].
|
||||
// Also: don't add keys last; add them to the group they best belong to.
|
||||
}
|
||||
|
||||
impl Key {
|
||||
/// All egui keys
|
||||
pub const ALL: &'static [Self] = &[
|
||||
Self::ArrowDown,
|
||||
Self::ArrowLeft,
|
||||
Self::ArrowRight,
|
||||
Self::ArrowUp,
|
||||
Self::Escape,
|
||||
Self::Tab,
|
||||
Self::Backspace,
|
||||
Self::Enter,
|
||||
Self::Space,
|
||||
Self::Insert,
|
||||
Self::Delete,
|
||||
Self::Home,
|
||||
Self::End,
|
||||
Self::PageUp,
|
||||
Self::PageDown,
|
||||
// Punctuation:
|
||||
Self::Colon,
|
||||
Self::Comma,
|
||||
Self::Minus,
|
||||
Self::Period,
|
||||
Self::PlusEquals,
|
||||
Self::Semicolon,
|
||||
// Digits:
|
||||
Self::Num0,
|
||||
Self::Num1,
|
||||
Self::Num2,
|
||||
Self::Num3,
|
||||
Self::Num4,
|
||||
Self::Num5,
|
||||
Self::Num6,
|
||||
Self::Num7,
|
||||
Self::Num8,
|
||||
Self::Num9,
|
||||
// Letters:
|
||||
Self::A,
|
||||
Self::B,
|
||||
Self::C,
|
||||
Self::D,
|
||||
Self::E,
|
||||
Self::F,
|
||||
Self::G,
|
||||
Self::H,
|
||||
Self::I,
|
||||
Self::J,
|
||||
Self::K,
|
||||
Self::L,
|
||||
Self::M,
|
||||
Self::N,
|
||||
Self::O,
|
||||
Self::P,
|
||||
Self::Q,
|
||||
Self::R,
|
||||
Self::S,
|
||||
Self::T,
|
||||
Self::U,
|
||||
Self::V,
|
||||
Self::W,
|
||||
Self::X,
|
||||
Self::Y,
|
||||
Self::Z,
|
||||
// Function keys:
|
||||
Self::F1,
|
||||
Self::F2,
|
||||
Self::F3,
|
||||
Self::F4,
|
||||
Self::F5,
|
||||
Self::F6,
|
||||
Self::F7,
|
||||
Self::F8,
|
||||
Self::F9,
|
||||
Self::F10,
|
||||
Self::F11,
|
||||
Self::F12,
|
||||
Self::F13,
|
||||
Self::F14,
|
||||
Self::F15,
|
||||
Self::F16,
|
||||
Self::F17,
|
||||
Self::F18,
|
||||
Self::F19,
|
||||
Self::F20,
|
||||
];
|
||||
|
||||
/// Converts `"A"` to `Key::A`, `Space` to `Key::Space`, etc.
|
||||
///
|
||||
/// Makes sense for logical keys.
|
||||
///
|
||||
/// This will parse the output of both [`Self::name`] and [`Self::symbol_or_name`],
|
||||
/// but will also parse single characters, so that both `"-"` and `"Minus"` will return `Key::Minus`.
|
||||
///
|
||||
/// This should support both the names generated in a web browser,
|
||||
/// and by winit. Please test on both with `eframe`.
|
||||
pub fn from_name(key: &str) -> Option<Self> {
|
||||
Some(match key {
|
||||
"ArrowDown" | "Down" | "⏷" => Self::ArrowDown,
|
||||
"ArrowLeft" | "Left" | "⏴" => Self::ArrowLeft,
|
||||
"ArrowRight" | "Right" | "⏵" => Self::ArrowRight,
|
||||
"ArrowUp" | "Up" | "⏶" => Self::ArrowUp,
|
||||
|
||||
"Escape" | "Esc" => Self::Escape,
|
||||
"Tab" => Self::Tab,
|
||||
"Backspace" => Self::Backspace,
|
||||
"Enter" | "Return" => Self::Enter,
|
||||
"Space" | " " => Self::Space,
|
||||
|
||||
"Help" | "Insert" => Self::Insert,
|
||||
"Delete" => Self::Delete,
|
||||
"Home" => Self::Home,
|
||||
"End" => Self::End,
|
||||
"PageUp" => Self::PageUp,
|
||||
"PageDown" => Self::PageDown,
|
||||
|
||||
"Colon" | ":" => Self::Colon,
|
||||
"Comma" | "," => Self::Comma,
|
||||
"Minus" | "-" | "−" => Self::Minus,
|
||||
"Period" | "." => Self::Period,
|
||||
"Plus" | "+" | "Equals" | "=" => Self::PlusEquals,
|
||||
"Semicolon" | ";" => Self::Semicolon,
|
||||
|
||||
"0" => Self::Num0,
|
||||
"1" => Self::Num1,
|
||||
"2" => Self::Num2,
|
||||
"3" => Self::Num3,
|
||||
"4" => Self::Num4,
|
||||
"5" => Self::Num5,
|
||||
"6" => Self::Num6,
|
||||
"7" => Self::Num7,
|
||||
"8" => Self::Num8,
|
||||
"9" => Self::Num9,
|
||||
|
||||
"a" | "A" => Self::A,
|
||||
"b" | "B" => Self::B,
|
||||
"c" | "C" => Self::C,
|
||||
"d" | "D" => Self::D,
|
||||
"e" | "E" => Self::E,
|
||||
"f" | "F" => Self::F,
|
||||
"g" | "G" => Self::G,
|
||||
"h" | "H" => Self::H,
|
||||
"i" | "I" => Self::I,
|
||||
"j" | "J" => Self::J,
|
||||
"k" | "K" => Self::K,
|
||||
"l" | "L" => Self::L,
|
||||
"m" | "M" => Self::M,
|
||||
"n" | "N" => Self::N,
|
||||
"o" | "O" => Self::O,
|
||||
"p" | "P" => Self::P,
|
||||
"q" | "Q" => Self::Q,
|
||||
"r" | "R" => Self::R,
|
||||
"s" | "S" => Self::S,
|
||||
"t" | "T" => Self::T,
|
||||
"u" | "U" => Self::U,
|
||||
"v" | "V" => Self::V,
|
||||
"w" | "W" => Self::W,
|
||||
"x" | "X" => Self::X,
|
||||
"y" | "Y" => Self::Y,
|
||||
"z" | "Z" => Self::Z,
|
||||
|
||||
"F1" => Self::F1,
|
||||
"F2" => Self::F2,
|
||||
"F3" => Self::F3,
|
||||
"F4" => Self::F4,
|
||||
"F5" => Self::F5,
|
||||
"F6" => Self::F6,
|
||||
"F7" => Self::F7,
|
||||
"F8" => Self::F8,
|
||||
"F9" => Self::F9,
|
||||
"F10" => Self::F10,
|
||||
"F11" => Self::F11,
|
||||
"F12" => Self::F12,
|
||||
"F13" => Self::F13,
|
||||
"F14" => Self::F14,
|
||||
"F15" => Self::F15,
|
||||
"F16" => Self::F16,
|
||||
"F17" => Self::F17,
|
||||
"F18" => Self::F18,
|
||||
"F19" => Self::F19,
|
||||
"F20" => Self::F20,
|
||||
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Emoji or name representing the key
|
||||
pub fn symbol_or_name(self) -> &'static str {
|
||||
// TODO(emilk): add support for more unicode symbols (see for instance https://wincent.com/wiki/Unicode_representations_of_modifier_keys).
|
||||
@@ -980,19 +1195,27 @@ impl Key {
|
||||
Key::ArrowLeft => "Left",
|
||||
Key::ArrowRight => "Right",
|
||||
Key::ArrowUp => "Up",
|
||||
|
||||
Key::Escape => "Escape",
|
||||
Key::Tab => "Tab",
|
||||
Key::Backspace => "Backspace",
|
||||
Key::Enter => "Enter",
|
||||
Key::Space => "Space",
|
||||
|
||||
Key::Insert => "Insert",
|
||||
Key::Delete => "Delete",
|
||||
Key::Home => "Home",
|
||||
Key::End => "End",
|
||||
Key::PageUp => "PageUp",
|
||||
Key::PageDown => "PageDown",
|
||||
|
||||
Key::Colon => "Colon",
|
||||
Key::Comma => "Comma",
|
||||
Key::Minus => "Minus",
|
||||
Key::Period => "Period",
|
||||
Key::PlusEquals => "Plus",
|
||||
Key::Semicolon => "Semicolon",
|
||||
|
||||
Key::Num0 => "0",
|
||||
Key::Num1 => "1",
|
||||
Key::Num2 => "2",
|
||||
@@ -1003,6 +1226,7 @@ impl Key {
|
||||
Key::Num7 => "7",
|
||||
Key::Num8 => "8",
|
||||
Key::Num9 => "9",
|
||||
|
||||
Key::A => "A",
|
||||
Key::B => "B",
|
||||
Key::C => "C",
|
||||
@@ -1053,6 +1277,31 @@ impl Key {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_key_from_name() {
|
||||
assert_eq!(
|
||||
Key::ALL.len(),
|
||||
Key::F20 as usize + 1,
|
||||
"Some keys are missing in Key::ALL"
|
||||
);
|
||||
|
||||
for &key in Key::ALL {
|
||||
let name = key.name();
|
||||
assert_eq!(
|
||||
Key::from_name(name),
|
||||
Some(key),
|
||||
"Failed to roundtrip {key:?} from name {name:?}"
|
||||
);
|
||||
|
||||
let symbol = key.symbol_or_name();
|
||||
assert_eq!(
|
||||
Key::from_name(symbol),
|
||||
Some(key),
|
||||
"Failed to roundtrip {key:?} from symbol {symbol:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// A keyboard shortcut, e.g. `Ctrl+Alt+W`.
|
||||
|
||||
@@ -64,6 +64,21 @@ impl FullOutput {
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about text being edited.
|
||||
///
|
||||
/// Useful for IME.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct IMEOutput {
|
||||
/// Where the [`crate::TextEdit`] is located on screen.
|
||||
pub rect: crate::Rect,
|
||||
|
||||
/// Where the cursor is.
|
||||
///
|
||||
/// This is a very thin rectangle.
|
||||
pub cursor_rect: crate::Rect,
|
||||
}
|
||||
|
||||
/// The non-rendering part of what egui emits each frame.
|
||||
///
|
||||
/// You can access (and modify) this with [`crate::Context::output`].
|
||||
@@ -98,10 +113,10 @@ pub struct PlatformOutput {
|
||||
/// Use by `eframe` web to show/hide mobile keyboard and IME agent.
|
||||
pub mutable_text_under_cursor: bool,
|
||||
|
||||
/// Screen-space position of text edit cursor (used for IME).
|
||||
/// This is et if, and only if, the user is currently editing text.
|
||||
///
|
||||
/// Iff `Some`, the user is editing text.
|
||||
pub text_cursor_pos: Option<crate::Pos2>,
|
||||
/// Useful for IME.
|
||||
pub ime: Option<IMEOutput>,
|
||||
|
||||
/// The difference in the widget tree since last frame.
|
||||
///
|
||||
@@ -137,7 +152,7 @@ impl PlatformOutput {
|
||||
copied_text,
|
||||
mut events,
|
||||
mutable_text_under_cursor,
|
||||
text_cursor_pos,
|
||||
ime,
|
||||
#[cfg(feature = "accesskit")]
|
||||
accesskit_update,
|
||||
} = newer;
|
||||
@@ -151,7 +166,7 @@ impl PlatformOutput {
|
||||
}
|
||||
self.events.append(&mut events);
|
||||
self.mutable_text_under_cursor = mutable_text_under_cursor;
|
||||
self.text_cursor_pos = text_cursor_pos.or(self.text_cursor_pos);
|
||||
self.ime = ime.or(self.ime);
|
||||
|
||||
#[cfg(feature = "accesskit")]
|
||||
{
|
||||
|
||||
@@ -899,7 +899,8 @@ pub enum ViewportCommand {
|
||||
/// The the window icon.
|
||||
Icon(Option<Arc<IconData>>),
|
||||
|
||||
IMEPosition(Pos2),
|
||||
/// Set the IME cursor editing area.
|
||||
IMERect(crate::Rect),
|
||||
IMEAllowed(bool),
|
||||
IMEPurpose(IMEPurpose),
|
||||
|
||||
|
||||
@@ -683,7 +683,7 @@ impl<'t> TextEdit<'t> {
|
||||
paint_cursor_selection(ui, &painter, text_draw_pos, &galley, &cursor_range);
|
||||
|
||||
if text.is_mutable() {
|
||||
let cursor_pos = paint_cursor_end(
|
||||
let cursor_rect = paint_cursor_end(
|
||||
ui,
|
||||
row_height,
|
||||
&painter,
|
||||
@@ -694,23 +694,14 @@ impl<'t> TextEdit<'t> {
|
||||
|
||||
let is_fully_visible = ui.clip_rect().contains_rect(rect); // TODO: remove this HACK workaround for https://github.com/emilk/egui/issues/1531
|
||||
if (response.changed || selection_changed) && !is_fully_visible {
|
||||
ui.scroll_to_rect(cursor_pos, None); // keep cursor in view
|
||||
ui.scroll_to_rect(cursor_rect, None); // keep cursor in view
|
||||
}
|
||||
|
||||
if interactive {
|
||||
// eframe web uses `text_cursor_pos` when showing IME,
|
||||
// so only set it when text is editable and visible!
|
||||
// But `winit` and `egui_web` differs in how to set the
|
||||
// position of IME.
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
ui.ctx().output_mut(|o| {
|
||||
o.text_cursor_pos = Some(cursor_pos.left_top());
|
||||
});
|
||||
} else {
|
||||
ui.ctx().output_mut(|o| {
|
||||
o.text_cursor_pos = Some(cursor_pos.left_bottom());
|
||||
});
|
||||
}
|
||||
// For IME, so only set it when text is editable and visible!
|
||||
ui.ctx().output_mut(|o| {
|
||||
o.ime = Some(crate::output::IMEOutput { rect, cursor_rect });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user