1
//! Focus-target resolver.
2
//!
3
//! A single canonical precedence order governs both key translation and event
4
//! dispatch: **Overlay > CmdLine > ConsoleInput > ViewPane**. Both
5
//! [`crate::keymap::translate`] and [`crate::event::apply`] call
6
//! [`current_focus`] so neither can drift from the other.
7

            
8
use crate::app::App;
9

            
10
#[cfg(test)]
11
mod tests;
12

            
13
/// Which layer currently owns keyboard input.
14
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15
pub enum FocusTarget {
16
    /// An overlay (modal/form) is open and intercepts all input.
17
    Overlay,
18
    /// The command-line palette is active.
19
    CmdLine,
20
    /// The console input prompt has focus.
21
    ConsoleInput,
22
    /// The active view pane owns input (default).
23
    ViewPane,
24
}
25

            
26
/// Canonical focus resolver — both translate and apply must call this.
27
///
28
/// Precedence: Overlay > CmdLine > ConsoleInput > ViewPane.
29
/// States are structurally mutually exclusive for the higher layers:
30
/// opening the cmdline or an overlay is the only way to gain that focus,
31
/// and closing it restores the layer below.
32
#[must_use]
33
464
pub fn current_focus(app: &App) -> FocusTarget {
34
464
    if !app.overlays.is_empty() {
35
69
        FocusTarget::Overlay
36
395
    } else if app.cmdline.active {
37
222
        FocusTarget::CmdLine
38
173
    } else if app.console_focused {
39
108
        FocusTarget::ConsoleInput
40
    } else {
41
65
        FocusTarget::ViewPane
42
    }
43
464
}