diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index dcc08a6e6b6..7b0d18b6329 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -1601,7 +1601,6 @@ impl IOCompositor { .constellation_sender .send(EmbedderToConstellationMessage::RefreshCursor( hit_test_result.pipeline_id, - hit_test_result.point_in_viewport, )) { warn!("Sending event to constellation failed ({:?}).", error); diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index d265678d13a..ebc2d55ce09 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -136,8 +136,8 @@ use embedder_traits::{ MouseButton, MouseButtonAction, MouseButtonEvent, Theme, ViewportDetails, WebDriverCommandMsg, WebDriverCommandResponse, WebDriverLoadStatus, WebDriverScriptCommand, }; +use euclid::Size2D; use euclid::default::Size2D as UntypedSize2D; -use euclid::{Point2D, Size2D}; use fonts::SystemFontServiceProxy; use ipc_channel::Error as IpcError; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; @@ -164,7 +164,6 @@ use servo_config::prefs::{self, PrefValue}; use servo_config::{opts, pref}; use servo_rand::{Rng, ServoRng, SliceRandom, random}; use servo_url::{Host, ImmutableOrigin, ServoUrl}; -use style_traits::CSSPixel; #[cfg(feature = "webgpu")] use webgpu::swapchain::WGPUImageMap; #[cfg(feature = "webgpu")] @@ -1465,8 +1464,8 @@ where EmbedderToConstellationMessage::ForwardInputEvent(webview_id, event, hit_test) => { self.forward_input_event(webview_id, event, hit_test); }, - EmbedderToConstellationMessage::RefreshCursor(pipeline_id, point) => { - self.handle_refresh_cursor(pipeline_id, point) + EmbedderToConstellationMessage::RefreshCursor(pipeline_id) => { + self.handle_refresh_cursor(pipeline_id) }, EmbedderToConstellationMessage::ToggleProfiler(rate, max_duration) => { for background_monitor_control_sender in &self.background_monitor_control_senders { @@ -3440,14 +3439,14 @@ where } #[servo_tracing::instrument(skip_all)] - fn handle_refresh_cursor(&self, pipeline_id: PipelineId, point: Point2D) { + fn handle_refresh_cursor(&self, pipeline_id: PipelineId) { let Some(pipeline) = self.pipelines.get(&pipeline_id) else { return; }; if let Err(error) = pipeline .event_loop - .send(ScriptThreadMessage::RefreshCursor(pipeline_id, point)) + .send(ScriptThreadMessage::RefreshCursor(pipeline_id)) { warn!("Could not send RefreshCursor message to pipeline: {error:?}"); } diff --git a/components/constellation/constellation_webview.rs b/components/constellation/constellation_webview.rs index 67f9bf276ff..f2264ace8cb 100644 --- a/components/constellation/constellation_webview.rs +++ b/components/constellation/constellation_webview.rs @@ -98,45 +98,46 @@ impl ConstellationWebView { return; }; - let mut update_hovered_browsing_context = |newly_hovered_browsing_context_id| { - let old_hovered_context_id = std::mem::replace( - &mut self.hovered_browsing_context_id, - newly_hovered_browsing_context_id, - ); - if old_hovered_context_id == newly_hovered_browsing_context_id { - return; - } - let Some(old_hovered_context_id) = old_hovered_context_id else { - return; - }; - let Some(pipeline) = browsing_contexts - .get(&old_hovered_context_id) - .and_then(|browsing_context| pipelines.get(&browsing_context.pipeline_id)) - else { - return; - }; + let mut update_hovered_browsing_context = + |newly_hovered_browsing_context_id, focus_moving_to_another_iframe: bool| { + let old_hovered_context_id = std::mem::replace( + &mut self.hovered_browsing_context_id, + newly_hovered_browsing_context_id, + ); + if old_hovered_context_id == newly_hovered_browsing_context_id { + return; + } + let Some(old_hovered_context_id) = old_hovered_context_id else { + return; + }; + let Some(pipeline) = browsing_contexts + .get(&old_hovered_context_id) + .and_then(|browsing_context| pipelines.get(&browsing_context.pipeline_id)) + else { + return; + }; - let mut synthetic_mouse_leave_event = event.clone(); - synthetic_mouse_leave_event.event = - InputEvent::MouseLeftViewport(MouseLeftViewportEvent { - focus_moving_to_another_iframe: true, - }); + let mut synthetic_mouse_leave_event = event.clone(); + synthetic_mouse_leave_event.event = + InputEvent::MouseLeftViewport(MouseLeftViewportEvent { + focus_moving_to_another_iframe, + }); - let _ = pipeline - .event_loop - .send(ScriptThreadMessage::SendInputEvent( - pipeline.id, - synthetic_mouse_leave_event, - )); - }; + let _ = pipeline + .event_loop + .send(ScriptThreadMessage::SendInputEvent( + pipeline.id, + synthetic_mouse_leave_event, + )); + }; if let InputEvent::MouseLeftViewport(_) = &event.event { - update_hovered_browsing_context(None); + update_hovered_browsing_context(None, false); return; } if let InputEvent::MouseMove(_) = &event.event { - update_hovered_browsing_context(Some(pipeline.browsing_context_id)); + update_hovered_browsing_context(Some(pipeline.browsing_context_id), true); self.last_mouse_move_point = event .hit_test_result .as_ref() diff --git a/components/script/dom/document_event_handler.rs b/components/script/dom/document_event_handler.rs index a3d09527f4b..54b3f4ba0a9 100644 --- a/components/script/dom/document_event_handler.rs +++ b/components/script/dom/document_event_handler.rs @@ -79,7 +79,7 @@ pub(crate) struct DocumentEventHandler { current_hover_target: MutNullableDom, /// The most recent mouse movement point, used for processing `mouseleave` events. #[no_trace] - most_recent_mousemove_point: Point2D, + most_recent_mousemove_point: Cell>>, /// The currently set [`Cursor`] or `None` if the `Document` isn't being hovered /// by the cursor. #[no_trace] @@ -212,13 +212,15 @@ impl DocumentEventHandler { })); } - pub(crate) fn set_cursor(&self, cursor: Cursor) { - if Some(cursor) == self.current_cursor.get() { + pub(crate) fn set_cursor(&self, cursor: Option) { + if cursor == self.current_cursor.get() { return; } - self.current_cursor.set(Some(cursor)); - self.window - .send_to_embedder(EmbedderMsg::SetCursor(self.window.webview_id(), cursor)); + self.current_cursor.set(cursor); + self.window.send_to_embedder(EmbedderMsg::SetCursor( + self.window.webview_id(), + cursor.unwrap_or_default(), + )); } fn handle_mouse_left_viewport_event( @@ -238,8 +240,9 @@ impl DocumentEventHandler { } if let Some(hit_test_result) = self - .window - .hit_test_from_point_in_viewport(self.most_recent_mousemove_point) + .most_recent_mousemove_point + .get() + .and_then(|point| self.window.hit_test_from_point_in_viewport(point)) { MouseEvent::new_simple( &self.window, @@ -263,15 +266,23 @@ impl DocumentEventHandler { } } - self.current_cursor.set(None); - self.current_hover_target.set(None); - - // If focus is moving to another frame, it will decide what the new status text is, but if - // this mouse leave event is leaving the WebView entirely, then clear it. + // We do not want to always inform the embedder that cursor has been set to the + // default cursor, in order to avoid a timing issue when moving between `