feat(reload): reload the active tab with Cmd/Ctrl+R

This commit is contained in:
2026-07-10 16:55:25 -04:00
parent a12b8c8bd8
commit c5890058db
16 changed files with 147 additions and 5 deletions
+2
View File
@@ -38,6 +38,7 @@ actions!(
OpenSettings, OpenSettings,
OpenTaskManager, OpenTaskManager,
Quit, Quit,
ReloadTab,
RestoreClosedTab, RestoreClosedTab,
ResetZoom, ResetZoom,
SelectNextSpace, SelectNextSpace,
@@ -105,6 +106,7 @@ fn main() {
MenuItem::action("Zoom Out", ZoomOut), MenuItem::action("Zoom Out", ZoomOut),
MenuItem::action("Reset Zoom", ResetZoom), MenuItem::action("Reset Zoom", ResetZoom),
MenuItem::separator(), MenuItem::separator(),
MenuItem::action("Reload Tab", ReloadTab),
MenuItem::action("Close Tab", CloseCurrentTab), MenuItem::action("Close Tab", CloseCurrentTab),
MenuItem::separator(), MenuItem::separator(),
MenuItem::action("Restore Closed Tab", RestoreClosedTab), MenuItem::action("Restore Closed Tab", RestoreClosedTab),
@@ -177,6 +177,10 @@ impl ServoLiveClient {
}) })
} }
pub fn reload(&mut self, tab_id: String) -> Result<(), ServoLiveError> {
self.request(LiveRequest::Reload { tab_id }).map(|_| ())
}
pub fn close(&mut self, tab_id: String) -> Result<(), ServoLiveError> { pub fn close(&mut self, tab_id: String) -> Result<(), ServoLiveError> {
self.request(LiveRequest::Close { tab_id }).map(|_| ()) self.request(LiveRequest::Close { tab_id }).map(|_| ())
} }
@@ -41,6 +41,9 @@ pub(super) enum LiveRequest {
ready_surface_ids: Vec<u64>, ready_surface_ids: Vec<u64>,
pending_surface_ids: Vec<u64>, pending_surface_ids: Vec<u64>,
}, },
Reload {
tab_id: String,
},
Close { Close {
tab_id: String, tab_id: String,
}, },
+1
View File
@@ -119,6 +119,7 @@ impl ElyShell {
.on_action(cx.listener(Self::on_open_new_tab)) .on_action(cx.listener(Self::on_open_new_tab))
.on_action(cx.listener(Self::on_open_settings)) .on_action(cx.listener(Self::on_open_settings))
.on_action(cx.listener(Self::on_open_task_manager)) .on_action(cx.listener(Self::on_open_task_manager))
.on_action(cx.listener(Self::on_reload_tab))
.on_action(cx.listener(Self::on_reset_zoom)) .on_action(cx.listener(Self::on_reset_zoom))
.on_action(cx.listener(Self::on_restore_closed_tab)) .on_action(cx.listener(Self::on_restore_closed_tab))
.on_action(cx.listener(Self::on_select_next_space)) .on_action(cx.listener(Self::on_select_next_space))
+10 -1
View File
@@ -2,7 +2,7 @@ use gpui::{Context, Window};
use crate::{ use crate::{
CloseCurrentTab, DownloadCurrentPage, FocusAddressBar, FocusCommandMode, OpenDownloads, CloseCurrentTab, DownloadCurrentPage, FocusAddressBar, FocusCommandMode, OpenDownloads,
OpenHistory, OpenNewTab, OpenSettings, OpenTaskManager, ResetZoom, RestoreClosedTab, OpenHistory, OpenNewTab, OpenSettings, OpenTaskManager, ReloadTab, ResetZoom, RestoreClosedTab,
SelectNextTab, SelectPreviousTab, ToggleFavoriteTab, TogglePinnedTab, ZoomIn, ZoomOut, SelectNextTab, SelectPreviousTab, ToggleFavoriteTab, TogglePinnedTab, ZoomIn, ZoomOut,
}; };
@@ -45,6 +45,15 @@ impl ElyShell {
self.open_new_tab(window, cx); self.open_new_tab(window, cx);
} }
pub(super) fn on_reload_tab(
&mut self,
_: &ReloadTab,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.reload_active_tab(window, cx);
}
pub(super) fn on_open_downloads( pub(super) fn on_open_downloads(
&mut self, &mut self,
_: &OpenDownloads, _: &OpenDownloads,
+15
View File
@@ -20,6 +20,21 @@ impl ElyShell {
} }
} }
/// Reload the active tab: recover it to the ready state in `BrowserCore`
/// and, when it hosts a live web surface, tell that surface's Servo
/// sidecar to refetch the page.
pub(super) fn reload_active_tab(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let ShellState::Ready(core) = &mut self.state else {
return;
};
let Ok(tab_id) = core.reload_active_tab() else {
return;
};
self.web_surfaces.reload_tab(&tab_id);
self.sync_address_input(window, cx);
cx.notify();
}
pub(super) fn wake_discarded_tab( pub(super) fn wake_discarded_tab(
&mut self, &mut self,
tab_id: &TabId, tab_id: &TabId,
+4
View File
@@ -353,6 +353,10 @@ impl WebSurfaceStore {
self.surfaces.entry(tab_id.clone()).or_insert_with(PerTabSurface::new) self.surfaces.entry(tab_id.clone()).or_insert_with(PerTabSurface::new)
} }
pub(super) fn reload_tab(&mut self, tab_id: &TabId) {
self.runtime.reload_tab(tab_id);
}
pub(super) fn close_surface(&mut self, tab_id: &TabId) { pub(super) fn close_surface(&mut self, tab_id: &TabId) {
self.runtime.close_tab(tab_id); self.runtime.close_tab(tab_id);
self.surfaces.remove(tab_id); self.surfaces.remove(tab_id);
@@ -78,6 +78,15 @@ impl WebSurfaceRuntime {
self.take_retired_permission_consumptions() self.take_retired_permission_consumptions()
} }
pub(in crate::shell) fn reload_tab(&mut self, tab_id: &TabId) {
let Some(session) = self.sessions.get(tab_id) else {
return;
};
if let Some(scoped) = self.workers.get(&session.scope) {
scoped.worker.submit_reload(tab_id.as_str().to_string());
}
}
pub(in crate::shell) fn close_tab(&mut self, tab_id: &TabId) { pub(in crate::shell) fn close_tab(&mut self, tab_id: &TabId) {
let Some(session) = self.sessions.remove(tab_id) else { let Some(session) = self.sessions.remove(tab_id) else {
return; return;
+41 -3
View File
@@ -29,6 +29,11 @@ pub(super) trait LiveRuntimeClient {
fn poll(&mut self, tab_id: String) -> Result<Option<ServoLiveFrame>, LiveRuntimeClientError>; fn poll(&mut self, tab_id: String) -> Result<Option<ServoLiveFrame>, LiveRuntimeClientError>;
fn reload(&mut self, tab_id: String) -> Result<(), LiveRuntimeClientError> {
let _ = tab_id;
Ok(())
}
fn close(&mut self, tab_id: String) -> Result<(), LiveRuntimeClientError>; fn close(&mut self, tab_id: String) -> Result<(), LiveRuntimeClientError>;
fn take_permission_consumptions(&mut self) -> Vec<ServoLivePermissionGrant> { fn take_permission_consumptions(&mut self) -> Vec<ServoLivePermissionGrant> {
@@ -48,6 +53,10 @@ impl LiveRuntimeClient for ServoLiveClient {
ServoLiveClient::poll(self, tab_id).map_err(LiveRuntimeClientError::from) ServoLiveClient::poll(self, tab_id).map_err(LiveRuntimeClientError::from)
} }
fn reload(&mut self, tab_id: String) -> Result<(), LiveRuntimeClientError> {
ServoLiveClient::reload(self, tab_id).map_err(LiveRuntimeClientError::from)
}
fn close(&mut self, tab_id: String) -> Result<(), LiveRuntimeClientError> { fn close(&mut self, tab_id: String) -> Result<(), LiveRuntimeClientError> {
ServoLiveClient::close(self, tab_id).map_err(LiveRuntimeClientError::from) ServoLiveClient::close(self, tab_id).map_err(LiveRuntimeClientError::from)
} }
@@ -147,6 +156,7 @@ struct WorkerQueue {
pending: BTreeMap<String, VecDeque<WorkerRequest>>, pending: BTreeMap<String, VecDeque<WorkerRequest>>,
/// Round-robin tab order, with each pending tab represented once. /// Round-robin tab order, with each pending tab represented once.
ready_tabs: VecDeque<String>, ready_tabs: VecDeque<String>,
reloads: VecDeque<String>,
closes: VecDeque<String>, closes: VecDeque<String>,
in_flight: bool, in_flight: bool,
in_flight_tab: Option<String>, in_flight_tab: Option<String>,
@@ -170,6 +180,7 @@ impl LiveRuntimeWorker {
Mutex::new(WorkerQueue { Mutex::new(WorkerQueue {
pending: BTreeMap::new(), pending: BTreeMap::new(),
ready_tabs: VecDeque::new(), ready_tabs: VecDeque::new(),
reloads: VecDeque::new(),
closes: VecDeque::new(), closes: VecDeque::new(),
in_flight: false, in_flight: false,
in_flight_tab: None, in_flight_tab: None,
@@ -264,6 +275,21 @@ impl LiveRuntimeWorker {
inserted inserted
} }
pub(super) fn submit_reload(&self, tab_id: String) {
let (lock, cvar) = &*self.queue;
let mut q = match lock.lock() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(),
};
if q.shutdown || q.initialization_failure.is_some() {
return;
}
if !q.reloads.contains(&tab_id) {
q.reloads.push_back(tab_id);
}
cvar.notify_one();
}
pub(super) fn submit_close(&self, tab_id: String) { pub(super) fn submit_close(&self, tab_id: String) {
let (lock, cvar) = &*self.queue; let (lock, cvar) = &*self.queue;
let mut q = match lock.lock() { let mut q = match lock.lock() {
@@ -278,6 +304,7 @@ impl LiveRuntimeWorker {
} }
q.pending.remove(&tab_id); q.pending.remove(&tab_id);
q.ready_tabs.retain(|ready_tab_id| ready_tab_id != &tab_id); q.ready_tabs.retain(|ready_tab_id| ready_tab_id != &tab_id);
q.reloads.retain(|reload_tab_id| reload_tab_id != &tab_id);
q.closes.push_back(tab_id); q.closes.push_back(tab_id);
cvar.notify_one(); cvar.notify_one();
} }
@@ -298,7 +325,8 @@ impl LiveRuntimeWorker {
Ok(guard) => guard, Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(), Err(poisoned) => poisoned.into_inner(),
}; };
while !q.pending.is_empty() || !q.closes.is_empty() || q.in_flight { while !q.pending.is_empty() || !q.reloads.is_empty() || !q.closes.is_empty() || q.in_flight
{
q = match cvar.wait(q) { q = match cvar.wait(q) {
Ok(guard) => guard, Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(), Err(poisoned) => poisoned.into_inner(),
@@ -336,6 +364,7 @@ fn fail_worker_initialization(
}; };
q.initialization_failure = Some(message.clone()); q.initialization_failure = Some(message.clone());
q.ready_tabs.clear(); q.ready_tabs.clear();
q.reloads.clear();
q.closes.clear(); q.closes.clear();
q.in_flight = false; q.in_flight = false;
q.in_flight_tab = None; q.in_flight_tab = None;
@@ -368,7 +397,8 @@ fn run_worker(
q.in_flight = false; q.in_flight = false;
q.in_flight_tab = None; q.in_flight_tab = None;
cvar.notify_all(); cvar.notify_all();
while q.pending.is_empty() && q.closes.is_empty() && !q.shutdown { while q.pending.is_empty() && q.reloads.is_empty() && q.closes.is_empty() && !q.shutdown
{
q = match cvar.wait(q) { q = match cvar.wait(q) {
Ok(guard) => guard, Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(), Err(poisoned) => poisoned.into_inner(),
@@ -379,6 +409,8 @@ fn run_worker(
} }
let next = if let Some(close_id) = q.closes.pop_front() { let next = if let Some(close_id) = q.closes.pop_front() {
Work::Close(close_id) Work::Close(close_id)
} else if let Some(reload_id) = q.reloads.pop_front() {
Work::Reload(reload_id)
} else { } else {
if q.ready_tabs.len() > 1 if q.ready_tabs.len() > 1
&& q.ready_tabs.front() == last_dispatched_tab.as_ref() && q.ready_tabs.front() == last_dispatched_tab.as_ref()
@@ -407,7 +439,7 @@ fn run_worker(
}; };
q.in_flight = true; q.in_flight = true;
q.in_flight_tab = match &next { q.in_flight_tab = match &next {
Work::Close(_) => None, Work::Close(_) | Work::Reload(_) => None,
Work::Request(request) => Some(request.tab_id().to_string()), Work::Request(request) => Some(request.tab_id().to_string()),
}; };
next next
@@ -419,6 +451,11 @@ fn run_worker(
forward_permission_consumptions(&mut *client, &response_tx); forward_permission_consumptions(&mut *client, &response_tx);
false false
} }
Work::Reload(tab_id) => {
let _ = client.reload(tab_id);
forward_permission_consumptions(&mut *client, &response_tx);
false
}
Work::Request(WorkerRequest::Ensure { generation, mut request }) => { Work::Request(WorkerRequest::Ensure { generation, mut request }) => {
let tab_id = request.tab_id.clone(); let tab_id = request.tab_id.clone();
let allow_once_grants = std::mem::take(&mut request.allow_once_grants); let allow_once_grants = std::mem::take(&mut request.allow_once_grants);
@@ -454,6 +491,7 @@ fn run_worker(
enum Work { enum Work {
Close(String), Close(String),
Reload(String),
Request(WorkerRequest), Request(WorkerRequest),
} }
+9 -1
View File
@@ -10,7 +10,7 @@ pub(crate) use profile::{
use crate::{ use crate::{
CloseCurrentTab, FocusAddressBar, FocusCommandMode, OpenDownloads, OpenHistory, OpenNewTab, CloseCurrentTab, FocusAddressBar, FocusCommandMode, OpenDownloads, OpenHistory, OpenNewTab,
OpenPrivateWindow, OpenSettings, OpenTaskManager, Quit, ResetZoom, RestoreClosedTab, OpenPrivateWindow, OpenSettings, OpenTaskManager, Quit, ReloadTab, ResetZoom, RestoreClosedTab,
SelectNextSpace, SelectNextTab, SelectPreviousSpace, SelectPreviousTab, SplitRight, SelectNextSpace, SelectNextTab, SelectPreviousSpace, SelectPreviousTab, SplitRight,
ToggleFavoriteTab, ToggleSidebar, ZoomIn, ZoomOut, ToggleFavoriteTab, ToggleSidebar, ZoomIn, ZoomOut,
}; };
@@ -39,6 +39,7 @@ pub(crate) enum ShortcutAction {
OpenNewTab, OpenNewTab,
OpenPrivateWindow, OpenPrivateWindow,
CloseCurrentTab, CloseCurrentTab,
ReloadTab,
RestoreClosedTab, RestoreClosedTab,
SelectNextSpace, SelectNextSpace,
SelectPreviousSpace, SelectPreviousSpace,
@@ -65,6 +66,7 @@ impl ShortcutAction {
Self::OpenNewTab => "New Tab", Self::OpenNewTab => "New Tab",
Self::OpenPrivateWindow => "New Private Window", Self::OpenPrivateWindow => "New Private Window",
Self::CloseCurrentTab => "Close Tab", Self::CloseCurrentTab => "Close Tab",
Self::ReloadTab => "Reload Tab",
Self::RestoreClosedTab => "Restore Closed Tab", Self::RestoreClosedTab => "Restore Closed Tab",
Self::SelectNextSpace => "Next Space", Self::SelectNextSpace => "Next Space",
Self::SelectPreviousSpace => "Previous Space", Self::SelectPreviousSpace => "Previous Space",
@@ -90,6 +92,7 @@ impl ShortcutAction {
Self::OpenNewTab Self::OpenNewTab
| Self::OpenPrivateWindow | Self::OpenPrivateWindow
| Self::CloseCurrentTab | Self::CloseCurrentTab
| Self::ReloadTab
| Self::RestoreClosedTab | Self::RestoreClosedTab
| Self::SelectNextSpace | Self::SelectNextSpace
| Self::SelectPreviousSpace | Self::SelectPreviousSpace
@@ -114,6 +117,7 @@ impl ShortcutAction {
Self::OpenNewTab => Some(">new-tab"), Self::OpenNewTab => Some(">new-tab"),
Self::OpenPrivateWindow => None, Self::OpenPrivateWindow => None,
Self::CloseCurrentTab => Some(">close-tab"), Self::CloseCurrentTab => Some(">close-tab"),
Self::ReloadTab => None,
Self::RestoreClosedTab => Some(">restore-tab"), Self::RestoreClosedTab => Some(">restore-tab"),
Self::SelectNextSpace => None, Self::SelectNextSpace => None,
Self::SelectPreviousSpace => None, Self::SelectPreviousSpace => None,
@@ -168,6 +172,7 @@ pub(crate) const SHORTCUT_ACTIONS: &[ShortcutAction] = &[
ShortcutAction::OpenNewTab, ShortcutAction::OpenNewTab,
ShortcutAction::OpenPrivateWindow, ShortcutAction::OpenPrivateWindow,
ShortcutAction::CloseCurrentTab, ShortcutAction::CloseCurrentTab,
ShortcutAction::ReloadTab,
ShortcutAction::RestoreClosedTab, ShortcutAction::RestoreClosedTab,
ShortcutAction::SelectNextSpace, ShortcutAction::SelectNextSpace,
ShortcutAction::SelectPreviousSpace, ShortcutAction::SelectPreviousSpace,
@@ -189,6 +194,8 @@ pub(crate) const SHORTCUT_ACTIONS: &[ShortcutAction] = &[
pub(crate) const SHORTCUT_BINDINGS: &[ShortcutBinding] = &[ pub(crate) const SHORTCUT_BINDINGS: &[ShortcutBinding] = &[
shortcut(ShortcutAction::OpenNewTab, ShortcutPlatform::Macos, "cmd-t"), shortcut(ShortcutAction::OpenNewTab, ShortcutPlatform::Macos, "cmd-t"),
shortcut(ShortcutAction::OpenNewTab, ShortcutPlatform::WindowsLinux, "ctrl-t"), shortcut(ShortcutAction::OpenNewTab, ShortcutPlatform::WindowsLinux, "ctrl-t"),
shortcut(ShortcutAction::ReloadTab, ShortcutPlatform::Macos, "cmd-r"),
shortcut(ShortcutAction::ReloadTab, ShortcutPlatform::WindowsLinux, "ctrl-r"),
shortcut(ShortcutAction::OpenPrivateWindow, ShortcutPlatform::Macos, "cmd-shift-n"), shortcut(ShortcutAction::OpenPrivateWindow, ShortcutPlatform::Macos, "cmd-shift-n"),
shortcut(ShortcutAction::OpenPrivateWindow, ShortcutPlatform::WindowsLinux, "ctrl-shift-n"), shortcut(ShortcutAction::OpenPrivateWindow, ShortcutPlatform::WindowsLinux, "ctrl-shift-n"),
shortcut(ShortcutAction::SplitRight, ShortcutPlatform::Macos, "cmd-\\"), shortcut(ShortcutAction::SplitRight, ShortcutPlatform::Macos, "cmd-\\"),
@@ -278,6 +285,7 @@ pub(crate) fn key_binding_for_action(action: ShortcutAction, keystroke: &str) ->
ShortcutAction::OpenSettings => KeyBinding::new(keystroke, OpenSettings, None), ShortcutAction::OpenSettings => KeyBinding::new(keystroke, OpenSettings, None),
ShortcutAction::OpenTaskManager => KeyBinding::new(keystroke, OpenTaskManager, None), ShortcutAction::OpenTaskManager => KeyBinding::new(keystroke, OpenTaskManager, None),
ShortcutAction::Quit => KeyBinding::new(keystroke, Quit, None), ShortcutAction::Quit => KeyBinding::new(keystroke, Quit, None),
ShortcutAction::ReloadTab => KeyBinding::new(keystroke, ReloadTab, None),
ShortcutAction::ResetZoom => KeyBinding::new(keystroke, ResetZoom, None), ShortcutAction::ResetZoom => KeyBinding::new(keystroke, ResetZoom, None),
ShortcutAction::RestoreClosedTab => KeyBinding::new(keystroke, RestoreClosedTab, None), ShortcutAction::RestoreClosedTab => KeyBinding::new(keystroke, RestoreClosedTab, None),
ShortcutAction::SelectNextSpace => KeyBinding::new(keystroke, SelectNextSpace, None), ShortcutAction::SelectNextSpace => KeyBinding::new(keystroke, SelectNextSpace, None),
@@ -50,6 +50,14 @@ impl BrowserCore {
self.mark_tab_ready(tab_id) self.mark_tab_ready(tab_id)
} }
/// Reload the active tab in place: recover a crashed or sleeping tab to
/// the ready state and stamp fresh activity. The shell pairs this with a
/// Servo reload so the page is actually refetched.
pub fn reload_active_tab(&mut self) -> Result<TabId, CoreError> {
let tab_id = self.active_tab_id.clone();
self.refresh_tab(&tab_id)
}
pub fn archive_idle_tabs(&mut self, now: SystemTime) -> Result<usize, CoreError> { pub fn archive_idle_tabs(&mut self, now: SystemTime) -> Result<usize, CoreError> {
let ArchivePolicy::IdleDays(idle_days) = self.active_space()?.archive_policy() else { let ArchivePolicy::IdleDays(idle_days) = self.active_space()?.archive_policy() else {
return Ok(0); return Ok(0);
@@ -53,6 +53,21 @@ fn recover_crashed_tab_marks_tab_ready() -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
#[test]
fn reload_active_tab_recovers_a_crashed_tab() -> Result<(), Box<dyn Error>> {
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
let tab_id = core.open_tab(UrlText::parse("https://example.com/reload")?);
core.crash_active_tab()?;
assert_eq!(core.active_tab()?.state(), &TabState::Crashed);
let reloaded = core.reload_active_tab()?;
assert_eq!(reloaded, tab_id);
assert_eq!(core.active_tab()?.state(), &TabState::Ready);
assert_eq!(core.active_tab()?.url().as_str(), "https://example.com/reload");
Ok(())
}
#[test] #[test]
fn crash_tab_command_marks_active_tab_crashed() -> Result<(), Box<dyn Error>> { fn crash_tab_command_marks_active_tab_crashed() -> Result<(), Box<dyn Error>> {
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?; let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
@@ -297,6 +297,13 @@ fn handle_request(
drop((webview_id, ready_surface_ids, pending_surface_ids)); drop((webview_id, ready_surface_ids, pending_surface_ids));
Ok(outcome) Ok(outcome)
} }
LiveRequest::Reload { tab_id } => {
if let Some(session) = sessions.get_mut(&tab_id) {
session.clear_presented_frame();
host.reload(&session.webview_id)?;
}
Ok(LiveOutcome::empty())
}
LiveRequest::Close { tab_id } => { LiveRequest::Close { tab_id } => {
if let Some(session) = sessions.remove(&tab_id) { if let Some(session) = sessions.remove(&tab_id) {
host.close_webview(&session.webview_id); host.close_webview(&session.webview_id);
@@ -68,6 +68,9 @@ pub(super) enum LiveRequest {
#[serde(default)] #[serde(default)]
pending_surface_ids: Vec<u64>, pending_surface_ids: Vec<u64>,
}, },
Reload {
tab_id: String,
},
Close { Close {
tab_id: String, tab_id: String,
}, },
+5
View File
@@ -372,6 +372,11 @@ pub trait ServoHost {
fn navigate(&mut self, request: NavigationRequest) -> Result<(), ServoHostError>; fn navigate(&mut self, request: NavigationRequest) -> Result<(), ServoHostError>;
/// Reload the current document in place (the URL is unchanged). Servo's
/// load-status transitions drive the loading indicator, so no navigation
/// hold is armed.
fn reload(&mut self, webview_id: &WebViewId) -> Result<(), ServoHostError>;
fn scroll(&mut self, request: ScrollRequest) -> Result<(), ServoHostError>; fn scroll(&mut self, request: ScrollRequest) -> Result<(), ServoHostError>;
fn resize(&mut self, request: ResizeRequest) -> Result<(), ServoHostError>; fn resize(&mut self, request: ResizeRequest) -> Result<(), ServoHostError>;
+11
View File
@@ -227,6 +227,17 @@ impl ServoHost for SoftwareServoHost {
Ok(()) Ok(())
} }
fn reload(&mut self, webview_id: &WebViewId) -> Result<(), ServoHostError> {
self.servo.spin_event_loop();
let webview = self
.webviews
.get_mut(webview_id)
.ok_or_else(|| ServoHostError::WebViewNotFound { id: webview_id.clone() })?;
webview.delegate.set_state(WebViewState::Loading);
webview.webview.reload();
Ok(())
}
fn scroll(&mut self, request: ScrollRequest) -> Result<(), ServoHostError> { fn scroll(&mut self, request: ScrollRequest) -> Result<(), ServoHostError> {
if request.delta_x == 0 && request.delta_y == 0 { if request.delta_x == 0 && request.delta_y == 0 {
return Ok(()); return Ok(());