mirror of
https://github.com/servo/servo.git
synced 2025-08-12 17:05:33 +01:00
script/compositor: Handle cursor updates from script (#38518)
Instead of using WebRender hit testing to update the cursor, base it on layout hit tests. This allows removing the majority of WebRender hit test items and finally opens up the possibility of adding support for custom cursors. In addition, this change fixes an issue where cursors were not set properly on areas of the viewport that extended past the page content. Testing: This is difficult to test as verifying that the cursor changed properly is beyond the capabilities of Servo's test harnesses. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
87538282db
commit
6651f37c05
21 changed files with 279 additions and 259 deletions
|
@ -28,7 +28,7 @@ use data_url::mime::Mime;
|
|||
use devtools_traits::ScriptToDevtoolsControlMsg;
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::{
|
||||
AllowOrDeny, AnimationState, ContextMenuResult, EditingActionEvent, EmbedderMsg,
|
||||
AllowOrDeny, AnimationState, ContextMenuResult, Cursor, EditingActionEvent, EmbedderMsg,
|
||||
FocusSequenceNumber, ImeEvent, InputEvent, LoadStatus, MouseButton, MouseButtonAction,
|
||||
MouseButtonEvent, ScrollEvent, TouchEvent, TouchEventType, TouchId, UntrustedNodeAddress,
|
||||
WheelEvent,
|
||||
|
@ -2008,6 +2008,9 @@ impl Document {
|
|||
return;
|
||||
};
|
||||
|
||||
// Update the cursor when the mouse moves, if it has changed.
|
||||
self.set_cursor(hit_test_result.cursor);
|
||||
|
||||
let Some(new_target) = hit_test_result
|
||||
.node
|
||||
.inclusive_ancestors(ShadowIncluding::No)
|
||||
|
@ -2122,6 +2125,10 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_cursor(&self, cursor: Cursor) {
|
||||
self.send_to_embedder(EmbedderMsg::SetCursor(self.webview_id(), cursor));
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub(crate) fn handle_mouse_leave_event(
|
||||
&self,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::Cursor;
|
||||
use euclid::Point2D;
|
||||
use js::rust::HandleObject;
|
||||
use style_traits::CSSPixel;
|
||||
|
@ -99,6 +100,7 @@ impl InputEventMethods<crate::DomTypeHolder> for InputEvent {
|
|||
/// `CompositorHitTestResult` against our current layout.
|
||||
pub(crate) struct HitTestResult {
|
||||
pub node: DomRoot<Node>,
|
||||
pub cursor: Cursor,
|
||||
pub point_in_node: Point2D<f32, CSSPixel>,
|
||||
pub point_in_frame: Point2D<f32, CSSPixel>,
|
||||
pub point_relative_to_initial_containing_block: Point2D<f32, CSSPixel>,
|
||||
|
|
|
@ -2620,6 +2620,7 @@ impl Window {
|
|||
let address = UntrustedNodeAddress(result.node.0 as *const c_void);
|
||||
Some(HitTestResult {
|
||||
node: unsafe { from_untrusted_node_address(address) },
|
||||
cursor: result.cursor,
|
||||
point_in_node: result.point_in_target,
|
||||
point_in_frame: compositor_hit_test_result.point_in_viewport,
|
||||
point_relative_to_initial_containing_block: compositor_hit_test_result
|
||||
|
@ -3089,6 +3090,20 @@ impl Window {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_refresh_cursor(&self, cursor_position: Point2D<f32, CSSPixel>) {
|
||||
let layout = self.layout.borrow();
|
||||
layout.ensure_stacking_context_tree(self.viewport_details.get());
|
||||
let Some(hit_test_result) = layout
|
||||
.query_elements_from_point(cursor_position.cast_unit(), ElementsFromPointFlags::empty())
|
||||
.into_iter()
|
||||
.nth(0)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.Document().set_cursor(hit_test_result.cursor);
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
|
|
@ -62,6 +62,7 @@ impl MixedMessage {
|
|||
ScriptThreadMessage::ExitPipeline(_webview_id, id, ..) => Some(*id),
|
||||
ScriptThreadMessage::ExitScriptThread => None,
|
||||
ScriptThreadMessage::SendInputEvent(id, ..) => Some(*id),
|
||||
ScriptThreadMessage::RefreshCursor(id, ..) => Some(*id),
|
||||
ScriptThreadMessage::Viewport(id, ..) => Some(*id),
|
||||
ScriptThreadMessage::GetTitle(id) => Some(*id),
|
||||
ScriptThreadMessage::SetDocumentActivity(id, ..) => Some(*id),
|
||||
|
|
|
@ -92,6 +92,7 @@ use script_traits::{
|
|||
use servo_config::opts;
|
||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||
use style::thread_state::{self, ThreadState};
|
||||
use style_traits::CSSPixel;
|
||||
use stylo_atoms::Atom;
|
||||
use timers::{TimerEventRequest, TimerId, TimerScheduler};
|
||||
use url::Position;
|
||||
|
@ -2042,6 +2043,9 @@ impl ScriptThread {
|
|||
);
|
||||
}
|
||||
},
|
||||
ScriptThreadMessage::RefreshCursor(pipeline_id, cursor_position) => {
|
||||
self.handle_refresh_cursor(pipeline_id, cursor_position);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4106,6 +4110,17 @@ impl ScriptThread {
|
|||
ScriptToConstellationMessage::FinishJavaScriptEvaluation(evaluation_id, result),
|
||||
));
|
||||
}
|
||||
|
||||
fn handle_refresh_cursor(
|
||||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
cursor_position: Point2D<f32, CSSPixel>,
|
||||
) {
|
||||
let Some(window) = self.documents.borrow().find_window(pipeline_id) else {
|
||||
return;
|
||||
};
|
||||
window.handle_refresh_cursor(cursor_position);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ScriptThread {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue