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 origin: crate::engine::origin::Origin,
94 permissions: crate::engine::permissions::Permissions,
95 response: Result<BrowserResponse, BrowserNetworkError>,
96 generation: u64,
97 );
98
99 /// Reflects the active tab's URL, if the chrome shows one.
100 fn sync_url(&mut self, url: Option<&str>);
101
102 /// Dispatches a pointer event to the chrome.
103 ///
104 /// The chrome receives every pointer event, including moves over the page
105 /// area, so it can track its own hover state.
106 fn pointer_event(
107 &mut self,
108 width: f32,
109 height: f32,
110 event: PointerEvent,
111 state: ElementState,
112 ) -> ChromeEventResult;
113
114 fn handle_scroll(
115 &mut self,
116 width: f32,
117 height: f32,
118 mouse_x: f32,
119 mouse_y: f32,
120 scroll_x: f32,
121 scroll_y: f32,
122 );
123
124 /// Whether the chrome currently owns keyboard/IME input (e.g. a focused
125 /// address bar). While `true`, key and IME events are routed to the chrome
126 /// instead of the page.
127 fn accepts_text_input(&self) -> bool;
128
129 /// Dispatches a key event while the chrome owns text input.
130 fn key_event(&mut self, event: &KeyEvent, ctrl: bool) -> ChromeAction;
131
132 /// Dispatches an IME event while the chrome owns text input.
133 fn ime_event(&mut self, event: &Ime) -> ChromeAction;
134
135 fn on_devtools_response(&mut self, id: u64, result: String);
136
137 /// Drops any text-input focus held by the chrome (e.g. the user clicked the
138 /// page).
139 fn blur(&mut self);
140
141 /// Whether the chrome changed its visual state since the last check.
142 ///
143 /// Consumes the flag, like [`crate::engine::ui::custom_node::CustomNode::needs_repaint`].
144 fn needs_repaint(&self) -> bool;
145}