diff options
author | Delan Azabani <dazabani@igalia.com> | 2024-01-24 19:45:54 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-24 11:45:54 +0000 |
commit | eb95703325aeb48d5f56a8da5b258bad608dd632 (patch) | |
tree | e3e636a74578ca431795511a3b30331422fb4a6e /ports/libsimpleservo/api | |
parent | 6baaa828261af49e790938666ee89f156a736821 (diff) | |
download | servo-eb95703325aeb48d5f56a8da5b258bad608dd632.tar.gz servo-eb95703325aeb48d5f56a8da5b258bad608dd632.zip |
constellation: focusing and closing webviews (#30842)
* constellation: focusing, closing, and native window visibility
* rename “browser” to “webview”, “unfocus” to “blur”
* remove native window visibility from constellation
* rename more “browser” to “webview”
* guard clauses
* don’t automatically focus when no webviews are focused
* comment spec steps for window.close()
* use format interpolation
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
* fix formatting
* rename “Webview” to “WebView” in types and type parameters
* remove unused method
* fix libsimpleservo
---------
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'ports/libsimpleservo/api')
-rw-r--r-- | ports/libsimpleservo/api/src/lib.rs | 82 |
1 files changed, 46 insertions, 36 deletions
diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index 5a3d1e4cd74..069e5745ae5 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -31,7 +31,7 @@ use servo::embedder_traits::{ use servo::euclid::{Point2D, Rect, Scale, Size2D, Vector2D}; use servo::keyboard_types::{Key, KeyState, KeyboardEvent}; pub use servo::msg::constellation_msg::InputMethodType; -use servo::msg::constellation_msg::TraversalDirection; +use servo::msg::constellation_msg::{TraversalDirection, WebViewId}; pub use servo::script_traits::{MediaSessionActionType, MouseButton}; use servo::script_traits::{TouchEventType, TouchId}; use servo::servo_config::{opts, pref}; @@ -168,19 +168,25 @@ pub struct ServoGlue { servo: Servo<ServoWindowCallbacks>, batch_mode: bool, callbacks: Rc<ServoWindowCallbacks>, - /// id of the top level browsing context. It is unique as tabs - /// are not supported yet. None until created. - browser_id: Option<BrowserId>, - // A rudimentary stack of "tabs". - // EmbedderMsg::BrowserCreated will push onto it. - // EmbedderMsg::CloseBrowser will pop from it, - // and exit if it is empty afterwards. - browsers: Vec<BrowserId>, events: Vec<EmbedderEvent>, - context_menu_sender: Option<IpcSender<ContextMenuResult>>, + + /// List of top-level browsing contexts. + /// Modified by EmbedderMsg::WebViewOpened and EmbedderMsg::WebViewClosed, + /// and we exit if it ever becomes empty. + webviews: HashMap<WebViewId, WebView>, + + /// The order in which the webviews were created. + creation_order: Vec<WebViewId>, + + /// The webview that is currently focused. + /// Modified by EmbedderMsg::WebViewFocused and EmbedderMsg::WebViewBlurred. + focused_webview_id: Option<WebViewId>, } +#[derive(Debug)] +pub struct WebView {} + pub fn servo_version() -> String { format!( "Servo {}-{}", @@ -312,12 +318,13 @@ pub fn init( servo: servo.servo, batch_mode: false, callbacks: window_callbacks, - browser_id: None, - browsers: vec![], events: vec![], context_menu_sender: None, + webviews: HashMap::default(), + creation_order: vec![], + focused_webview_id: None, }; - let _ = servo_glue.process_event(EmbedderEvent::NewBrowser(url, servo.browser_id)); + let _ = servo_glue.process_event(EmbedderEvent::NewWebView(url, servo.browser_id)); *s.borrow_mut() = Some(servo_glue); }); @@ -330,11 +337,11 @@ pub fn deinit() { impl ServoGlue { fn get_browser_id(&self) -> Result<BrowserId, &'static str> { - let browser_id = match self.browser_id { + let webview_id = match self.focused_webview_id { Some(id) => id, - None => return Err("No BrowserId set yet."), + None => return Err("No focused WebViewId yet."), }; - Ok(browser_id) + Ok(webview_id) } /// Request shutdown. Will call on_shutdown_complete. @@ -604,7 +611,7 @@ impl ServoGlue { pub fn change_visibility(&mut self, visible: bool) -> Result<(), &'static str> { info!("change_visibility"); if let Ok(id) = self.get_browser_id() { - let event = EmbedderEvent::ChangeBrowserVisibility(id, visible); + let event = EmbedderEvent::WebViewVisibilityChanged(id, visible); self.process_event(event) } else { // Ignore visibility change if no browser has been created yet. @@ -714,21 +721,35 @@ impl ServoGlue { .push(EmbedderEvent::SendError(browser_id, reason)); } }, - EmbedderMsg::AllowOpeningBrowser(response_chan) => { + EmbedderMsg::AllowOpeningWebView(response_chan) => { // Note: would be a place to handle pop-ups config. // see Step 7 of #the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name if let Err(e) = response_chan.send(true) { warn!("Failed to send AllowOpeningBrowser response: {}", e); }; }, - EmbedderMsg::BrowserCreated(new_browser_id) => { - // TODO: properly handle a new "tab" - self.browsers.push(new_browser_id); - if self.browser_id.is_none() { - self.browser_id = Some(new_browser_id); - } + EmbedderMsg::WebViewOpened(new_webview_id) => { + self.webviews.insert(new_webview_id, WebView {}); + self.creation_order.push(new_webview_id); self.events - .push(EmbedderEvent::SelectBrowser(new_browser_id)); + .push(EmbedderEvent::FocusWebView(new_webview_id)); + }, + EmbedderMsg::WebViewClosed(webview_id) => { + self.webviews.retain(|&id, _| id != webview_id); + self.creation_order.retain(|&id| id != webview_id); + self.focused_webview_id = None; + if let Some(&newest_webview_id) = self.creation_order.last() { + self.events + .push(EmbedderEvent::FocusWebView(newest_webview_id)); + } else { + self.events.push(EmbedderEvent::Quit); + } + }, + EmbedderMsg::WebViewFocused(webview_id) => { + self.focused_webview_id = Some(webview_id); + }, + EmbedderMsg::WebViewBlurred => { + self.focused_webview_id = None; }, EmbedderMsg::GetClipboardContents(sender) => { let contents = self.callbacks.host_callbacks.get_clipboard_contents(); @@ -737,17 +758,6 @@ impl ServoGlue { EmbedderMsg::SetClipboardContents(text) => { self.callbacks.host_callbacks.set_clipboard_contents(text); }, - EmbedderMsg::CloseBrowser => { - // TODO: close the appropriate "tab". - let _ = self.browsers.pop(); - if let Some(prev_browser_id) = self.browsers.last() { - self.browser_id = Some(*prev_browser_id); - self.events - .push(EmbedderEvent::SelectBrowser(*prev_browser_id)); - } else { - self.events.push(EmbedderEvent::Quit); - } - }, EmbedderMsg::Shutdown => { self.callbacks.host_callbacks.on_shutdown_complete(); }, |