Skip to main content

orinium_browser/browser/core/ui/
chrome.rs

1//! Abstraction for the window chrome surrounding the web content.
2//!
3//! The browser core (`BrowserUi` / `BrowserRenderer`) owns the window, the
4//! tabs, and the web content, but knows nothing about the concrete UI a user
5//! draws around that content. Any [`Chrome`] implementation can replace the
6//! default [`super::basic_chrome::BasicChrome`]: draw arbitrary widgets, place
7//! the content area anywhere, and translate user input into [`ChromeAction`]s.
8//!
9//! All coordinates are logical pixels in window space.
10
11use url::Url;
12use winit::event::{ElementState, Ime, KeyEvent};
13
14use crate::browser::core::resource_loader::{BrowserNetworkError, BrowserResponse};
15use crate::browser::core::tab::FetchKind;
16use crate::browser::core::ui::FetchRequest;
17use crate::browser::core::webview::JsPolicy;
18use crate::engine::renderer_model::{DrawCommand, Rect};
19use crate::engine::ui::PointerEvent;
20
21/// An action the chrome wants the browser core to perform on the active tab or
22/// window.
23#[derive(Debug, Clone, PartialEq)]
24pub enum ChromeAction {
25    /// Nothing to do.
26    None,
27    /// The chrome changed visually; repaint the window.
28    Repaint,
29    /// Set the JS policy.
30    SetJsPolicy(JsPolicy),
31    /// Navigate the active tab to this URL (e.g. Enter in the address bar).
32    Navigate(Url),
33    /// Go back in the active tab's history.
34    Back,
35    /// Reload the active tab.
36    Reload,
37    /// The chrome acquired a text field and wants OS-level IME enabled.
38    EnableIme,
39    /// A page asked the DevTools bridge to inspect rendered state.
40    DevToolsRequest {
41        id: u64,
42        method: String,
43        params: String,
44    },
45}
46
47/// The outcome of dispatching a pointer event to the chrome.
48#[derive(Debug, Clone, PartialEq)]
49pub struct ChromeEventResult {
50    /// `true` when the event hit the chrome and must not reach the page.
51    pub consumed: bool,
52    /// Action the browser core should perform.
53    pub action: ChromeAction,
54}
55
56impl ChromeEventResult {
57    /// A result that consumes nothing and requests nothing.
58    pub const fn none() -> Self {
59        Self {
60            consumed: false,
61            action: ChromeAction::None,
62        }
63    }
64}
65
66/// Location of the DevTools frontend served from the bundled resources.
67pub(super) const DEVTOOLS_URL: &str = "resource:///devtools/index.html";
68
69/// The window chrome surrounding the web content.
70///
71/// The core lays out the page area below the chrome, draws the chrome on top of
72/// it, and routes user input through the chrome. Pointer events are delivered
73/// in window coordinates; the chrome answers whether it consumed them and which
74/// [`ChromeAction`] they produced.
75pub trait Chrome: std::fmt::Debug {
76    /// Rect of the content (web view).
77    ///
78    /// # Return:
79    /// - (width, height)
80    fn content_rect(&self, width: f32, height: f32) -> Rect;
81
82    /// Draws the chrome into `cmd_buf` in window coordinates.
83    fn draw(&mut self, cmd_buf: &mut Vec<DrawCommand>, width: f32, height: f32);
84
85    /// Advances chrome-owned tabs and returns their fetch and browser actions.
86    fn tick(&mut self, actions_buf: &mut Vec<ChromeAction>) -> (Vec<FetchRequest>, bool);
87
88    /// Delivers a resource fetch result requested by the chrome itself.
89    fn deliver_fetch(
90        &mut self,
91        kind: FetchKind,
92        url: Url,
93        response: Result<BrowserResponse, BrowserNetworkError>,
94    );
95
96    /// Reflects the active tab's URL, if the chrome shows one.
97    fn sync_url(&mut self, url: Option<&str>);
98
99    /// Dispatches a pointer event to the chrome.
100    ///
101    /// The chrome receives every pointer event, including moves over the page
102    /// area, so it can track its own hover state.
103    fn pointer_event(
104        &mut self,
105        width: f32,
106        height: f32,
107        event: PointerEvent,
108        state: ElementState,
109    ) -> ChromeEventResult;
110
111    fn handle_scroll(
112        &mut self,
113        width: f32,
114        height: f32,
115        mouse_x: f32,
116        mouse_y: f32,
117        scroll_x: f32,
118        scroll_y: f32,
119    );
120
121    /// Whether the chrome currently owns keyboard/IME input (e.g. a focused
122    /// address bar). While `true`, key and IME events are routed to the chrome
123    /// instead of the page.
124    fn accepts_text_input(&self) -> bool;
125
126    /// Dispatches a key event while the chrome owns text input.
127    fn key_event(&mut self, event: &KeyEvent, ctrl: bool) -> ChromeAction;
128
129    /// Dispatches an IME event while the chrome owns text input.
130    fn ime_event(&mut self, event: &Ime) -> ChromeAction;
131
132    fn on_devtools_response(&mut self, id: u64, result: String);
133
134    /// Drops any text-input focus held by the chrome (e.g. the user clicked the
135    /// page).
136    fn blur(&mut self);
137
138    /// Whether the chrome changed its visual state since the last check.
139    ///
140    /// Consumes the flag, like [`crate::engine::ui::custom_node::CustomNode::needs_repaint`].
141    fn needs_repaint(&self) -> bool;
142}