1use super::*;
9#[allow(unused)] use crate::Events;
10use crate::HasId;
11use crate::event::{Command, Event, FocusSource};
12use crate::geom::{Rect, Size};
13use crate::util::WidgetHierarchy;
14use crate::{Id, Node, Tile, TileExt};
15use winit::dpi::{LogicalPosition, LogicalSize};
16use winit::event::{ElementState, Ime, KeyEvent};
17use winit::keyboard::{Key, ModifiersState, PhysicalKey};
18use winit::window::{
19 ImeCapabilities, ImeEnableRequest, ImeRequest, ImeRequestData, ImeRequestError,
20};
21
22#[derive(Debug)]
23struct LostFocus {
24 id: Id,
25 key: bool,
26 ime: bool,
27}
28
29#[derive(Debug, Default)]
31pub(super) struct Input {
32 focus: Option<Id>,
33 key_focus: bool,
34 ime_focus: bool,
35 lost_focus: Option<LostFocus>,
36 new_sel_focus: Option<FocusSource>,
37 new_key_focus: bool,
38 old_ime_target: Option<Id>,
39 ime_cursor_area: Rect,
41 last_ime_rect: Rect,
42 has_reported_ime_not_supported: bool,
43}
44
45impl Input {
46 #[inline]
47 pub(super) fn sel_focus(&self) -> Option<&Id> {
48 self.focus.as_ref()
49 }
50
51 #[inline]
52 pub(super) fn key_focus(&self) -> Option<&Id> {
53 self.key_focus.then_some(self.focus.as_ref()).flatten()
54 }
55
56 #[inline]
57 pub(super) fn ime_focus(&self) -> Option<&Id> {
58 self.ime_focus.then_some(self.focus.as_ref()).flatten()
59 }
60
61 pub(super) fn clear_sel_socus_on(&mut self, target: &Id) {
63 if *target != self.sel_focus() {
64 return; }
66 let old_focus = self.focus.take().unwrap();
67 let key = std::mem::take(&mut self.key_focus);
68 let ime = std::mem::take(&mut self.ime_focus);
69
70 if let Some(ref mut focus) = self.lost_focus {
71 if focus.id == target {
72 focus.key |= key;
74 focus.ime |= ime;
75 } else {
76 }
79 } else {
80 self.lost_focus = Some(LostFocus {
81 id: old_focus,
82 key,
83 ime,
84 });
85 }
86 }
87
88 #[inline]
89 pub(super) fn has_pending_changes(&self) -> bool {
90 self.lost_focus.is_some() || self.new_sel_focus.is_some() || self.new_key_focus
91 }
92
93 pub(super) fn frame_update(&mut self, window: &dyn WindowDataErased, widget: &dyn Tile) {
94 if let Some(target) = self.ime_focus()
96 && let Some((mut rect, translation)) = widget.find_tile_rect(target)
97 {
98 if self.ime_cursor_area.size != Size::ZERO {
99 rect = self.ime_cursor_area;
100 }
101 rect += translation;
102 if rect != self.last_ime_rect {
103 let data = ImeRequestData::default().with_cursor_area(
104 rect.pos.as_physical().into(),
105 rect.size.as_physical().into(),
106 );
107 let req = winit::window::ImeRequest::Update(data);
108 match window.ime_request(req) {
109 Ok(()) => (),
110 Err(e) => log::warn!("Unexpected IME error: {e}"),
111 }
112 self.last_ime_rect = rect;
113 }
114 }
115 }
116}
117
118impl EventState {
119 pub(crate) fn clear_access_key_bindings(&mut self) {
120 self.access_keys.clear();
121 }
122
123 pub(crate) fn add_access_key_binding(&mut self, id: &Id, key: &Key) -> bool {
124 if !self.modifiers.alt_key() && !self.config.alt_bypass {
125 return false;
126 }
127
128 if self.access_keys.contains_key(key) {
129 false
130 } else {
131 self.access_keys.insert(key.clone(), id.clone());
132 self.modifiers.alt_key()
133 }
134 }
135
136 #[inline]
145 pub fn has_input_focus(&self, w_id: &Id) -> Option<bool> {
146 if *w_id == self.input.focus {
147 Some(self.input.key_focus || self.input.ime_focus)
148 } else {
149 None
150 }
151 }
152
153 #[inline]
155 pub fn modifiers(&self) -> ModifiersState {
156 self.modifiers
157 }
158
159 #[inline]
172 pub fn set_ime_cursor_area(&mut self, target: &Id, rect: Rect) {
173 if *target == self.input.ime_focus() {
174 self.input.ime_cursor_area = rect;
175 }
176 }
177
178 #[inline]
183 pub fn cancel_ime_focus(&mut self, target: &Id) {
184 if *target != self.input.ime_focus() {
185 return;
186 }
187 self.input.ime_focus = false;
188
189 if let Some(ref mut focus) = self.input.lost_focus {
190 if focus.id == target {
191 focus.ime = true;
192 } else {
193 }
196 } else {
197 self.input.lost_focus = Some(LostFocus {
198 id: target.clone(),
199 key: false,
200 ime: true,
201 });
202 }
203 }
204}
205
206impl<'a> EventCx<'a> {
207 #[inline]
219 pub fn request_key_focus(&mut self, target: Id, source: FocusSource) {
220 self.request_sel_focus(target, source);
221 if !self.input.key_focus {
222 self.input.key_focus = true;
223 self.input.new_key_focus = true;
224 }
225 }
226
227 #[inline]
245 pub fn request_sel_focus(&mut self, target: Id, source: FocusSource) {
246 if target == self.input.sel_focus() {
247 return;
248 } else if let Some(id) = self.input.sel_focus().cloned() {
249 self.input.clear_sel_socus_on(&id);
250 }
251
252 self.set_nav_focus(target.clone(), source);
253
254 self.input.focus = Some(target);
255 self.input.new_sel_focus = Some(source);
256 }
257
258 pub fn replace_ime_focus(
271 &mut self,
272 target: Id,
273 hint: ImeHint,
274 purpose: ImePurpose,
275 mut surrounding_text: Option<ImeSurroundingText>,
276 ) {
277 if target != self.input.focus {
278 return;
279 }
280
281 if let Some(id) = self.input.ime_focus().cloned() {
282 self.clear_ime_focus(id);
283 }
284
285 let mut capabilities = ImeCapabilities::new()
286 .with_hint_and_purpose()
287 .with_cursor_area();
288 if surrounding_text.is_some() {
289 capabilities = capabilities.with_surrounding_text();
290 }
291
292 let position = LogicalPosition::new(0, 0);
295 let size = LogicalSize::new(0, 0);
296
297 let mut data = ImeRequestData::default()
298 .with_hint_and_purpose(hint, purpose)
299 .with_cursor_area(position.into(), size.into());
300 if let Some(surrounding) = surrounding_text.take() {
301 data = data.with_surrounding_text(surrounding);
302 }
303
304 let req = ImeEnableRequest::new(capabilities, data).unwrap();
305 match self.window.ime_request(ImeRequest::Enable(req)) {
306 Ok(()) => {
307 self.input.ime_focus = true;
310 }
311 Err(ImeRequestError::NotSupported) => {
312 if !self.input.has_reported_ime_not_supported {
313 log::warn!("Failed to start Input Method Editor: not supported");
314 self.input.has_reported_ime_not_supported = true;
315 }
316 }
317 Err(e) => log::error!("Unexpected IME error: {e}"),
318 }
319 }
320
321 pub fn depress_with_key(&mut self, id: impl HasId, code: impl Into<Option<PhysicalKey>>) {
334 fn inner(state: &mut EventState, id: Id, code: PhysicalKey) {
335 if state
336 .key_depress
337 .get(&code)
338 .map(|target| *target == id)
339 .unwrap_or(false)
340 {
341 return;
342 }
343
344 state.key_depress.insert(code, id.clone());
345 state.redraw(id);
346 }
347
348 if let Some(code) = code.into() {
349 inner(self, id.has_id(), code);
350 }
351 }
352
353 pub fn update_ime_surrounding_text(&self, target: &Id, surrounding_text: ImeSurroundingText) {
355 if *target != self.input.ime_focus() {
356 return;
357 }
358
359 let data = ImeRequestData::default().with_surrounding_text(surrounding_text);
360 let req = ImeRequest::Update(data);
361 match self.window.ime_request(req) {
362 Ok(()) => (),
363 Err(e) => log::error!("Unexpected IME error: {e}"),
364 }
365 }
366
367 pub(super) fn clear_ime_focus(&mut self, id: Id) {
368 self.input.old_ime_target = Some(id);
370 self.window.ime_request(ImeRequest::Disable).unwrap();
371 self.input.ime_focus = false;
372 self.input.ime_cursor_area = Rect::ZERO;
373 }
374
375 pub(super) fn keyboard_input(
376 &mut self,
377 mut widget: Node<'_>,
378 mut event: KeyEvent,
379 is_synthetic: bool,
380 ) {
381 if let Some(id) = self.input.key_focus().cloned() {
382 let mut mods = self.modifiers;
384 mods.remove(ModifiersState::SHIFT);
385 if !mods.is_empty()
386 || event
387 .text
388 .as_ref()
389 .and_then(|t| t.chars().next())
390 .map(|c| c.is_control())
391 .unwrap_or(false)
392 {
393 event.text = None;
394 }
395
396 if self.send_event(widget.re(), id, Event::Key(&event, is_synthetic)) {
397 return;
398 }
399 }
400
401 if event.state == ElementState::Pressed && !is_synthetic {
402 self.start_key_event(widget, event.key_without_modifiers, event.physical_key);
403 } else if event.state == ElementState::Released
404 && self.key_depress.remove(&event.physical_key).is_some()
405 {
406 self.redraw();
407 }
408 }
409
410 pub(super) fn start_key_event(&mut self, mut widget: Node<'_>, vkey: Key, code: PhysicalKey) {
411 let id = widget.id();
412 log::trace!("start_key_event: window={id}, vkey={vkey:?}, physical_key={code:?}");
413
414 let opt_cmd = self.config.shortcuts().try_match(self.modifiers, &vkey);
415
416 if Some(Command::Exit) == opt_cmd {
417 self.runner.exit();
418 return;
419 } else if Some(Command::Close) == opt_cmd {
420 self.handle_close();
421 return;
422 } else if let Some(cmd) = opt_cmd {
423 let mut targets = vec![];
424 let mut send = |_self: &mut Self, id: Id, cmd| -> bool {
425 if !targets.contains(&id) {
426 let event = Event::Command(cmd, Some(code));
427 let used = _self.send_event(widget.re(), id.clone(), event);
428 targets.push(id);
429 used
430 } else {
431 false
432 }
433 };
434
435 if (self.input.key_focus || cmd.suitable_for_sel_focus())
436 && let Some(ref id) = self.input.focus
437 && send(self, id.clone(), cmd)
438 {
439 return;
440 }
441
442 if !self.modifiers.alt_key()
443 && let Some(id) = self.nav_focus().cloned()
444 && send(self, id, cmd)
445 {
446 return;
447 }
448
449 if let Some(id) = self
450 .popups
451 .last()
452 .filter(|popup| popup.is_sized)
453 .map(|popup| popup.desc.id.clone())
454 && send(self, id, cmd)
455 {
456 return;
457 }
458
459 let fallback = self.nav.fallback.clone().unwrap_or(id);
460 if send(self, fallback, cmd) {
461 return;
462 }
463
464 if matches!(cmd, Command::Debug) {
465 let over_id = self.mouse.over_id();
466 let hier = WidgetHierarchy::new(widget.as_tile(), over_id.clone());
467 log::debug!("Widget heirarchy (filter={over_id:?}): {hier}");
468 return;
469 }
470 }
471
472 let target = self.access_keys.get(&vkey).cloned();
474
475 if let Some(id) = target {
476 self.close_non_ancestors_of(Some(&id));
477
478 if let Some(id) = self.nav_next(widget.as_tile(), Some(&id), NavAdvance::None) {
479 self.request_nav_focus(id, FocusSource::Key);
480 }
481
482 let event = Event::Command(Command::Activate, Some(code));
483 self.send_event(widget, id, event);
484 } else if self.config.nav_focus && opt_cmd == Some(Command::Tab) {
485 let shift = self.modifiers.shift_key();
486 self.next_nav_focus(None, shift, FocusSource::Key);
487 }
488 }
489
490 pub(super) fn modifiers_changed(&mut self, state: ModifiersState) {
491 if state.alt_key() != self.modifiers.alt_key() {
492 self.redraw();
494 }
495 self.modifiers = state;
496 }
497
498 pub(super) fn ime_event(&mut self, widget: Node<'_>, ime: Ime) {
499 if ime == Ime::Disabled
500 && let Some(target) = self.input.old_ime_target.take()
501 {
502 self.send_event(widget, target, Event::Ime(super::Ime::Disabled));
504 return;
505 }
506
507 if let Some(id) = self.input.ime_focus().cloned() {
508 let event = match ime {
509 Ime::Enabled => super::Ime::Enabled,
510 Ime::Preedit(ref text, cursor) => super::Ime::Preedit { text, cursor },
511 Ime::Commit(ref text) => super::Ime::Commit { text },
512 Ime::DeleteSurrounding {
513 before_bytes,
514 after_bytes,
515 } => super::Ime::DeleteSurrounding {
516 before_bytes,
517 after_bytes,
518 },
519 Ime::Disabled => {
520 self.input.ime_focus = false;
522 self.input.ime_cursor_area = Rect::ZERO;
523
524 super::Ime::Disabled
525 }
526 };
527
528 self.send_event(widget, id, Event::Ime(event));
529 }
530 }
531
532 pub(super) fn flush_pending_input_focus(&mut self, mut widget: Node<'_>) {
533 if let Some(focus) = self.input.lost_focus.take() {
534 if focus.ime {
535 self.clear_ime_focus(focus.id.clone());
536 }
537
538 if focus.key {
539 self.send_event(widget.re(), focus.id.clone(), Event::LostKeyFocus);
540 }
541
542 if focus.id != self.input.sel_focus() {
543 self.send_event(widget.re(), focus.id, Event::LostSelFocus);
544 }
545 }
546
547 if let Some(source) = self.input.new_sel_focus.take()
548 && let Some(id) = self.input.sel_focus().cloned()
549 {
550 self.send_event(widget.re(), id, Event::SelFocus(source));
551 }
552 if self.input.new_key_focus
553 && let Some(id) = self.input.key_focus().cloned()
554 {
555 self.input.new_key_focus = false;
556 self.send_event(widget.re(), id, Event::KeyFocus);
557 }
558 }
559}