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}