mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #14291 - fiji-flo:text-input-select, r=pcwalton
Position insertion point in input field with mouse <!-- Please describe your changes on the following line: --> Implements cursor positioning in input elements (text/password) via mouse. The related issue is #10083 but is only covered partly. This PR does **not** cover: * positioning in textarea elements via mouse * text selection in input/textarea elements via mouse --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #10083 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because I can't think of a way to test mouse interaction in the current test pipeline. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/14291) <!-- Reviewable:end -->
This commit is contained in:
commit
68a8e1bf2b
9 changed files with 219 additions and 50 deletions
|
@ -11,6 +11,8 @@ use dom::bindings::codegen::Bindings::FileListBinding::FileListMethods;
|
|||
use dom::bindings::codegen::Bindings::HTMLInputElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
|
||||
use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
|
||||
use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use dom::bindings::error::{Error, ErrorResult};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::js::{JS, LayoutJS, MutNullableJS, Root, RootedReference};
|
||||
|
@ -27,6 +29,7 @@ use dom::htmlfieldsetelement::HTMLFieldSetElement;
|
|||
use dom::htmlformelement::{FormControl, FormDatum, FormDatumValue, FormSubmitter, HTMLFormElement};
|
||||
use dom::htmlformelement::{ResetFrom, SubmittedFrom};
|
||||
use dom::keyboardevent::KeyboardEvent;
|
||||
use dom::mouseevent::MouseEvent;
|
||||
use dom::node::{Node, NodeDamage, UnbindContext};
|
||||
use dom::node::{document_from_node, window_from_node};
|
||||
use dom::nodelist::NodeList;
|
||||
|
@ -39,6 +42,7 @@ use mime_guess;
|
|||
use net_traits::{CoreResourceMsg, IpcSend};
|
||||
use net_traits::blob_url_store::get_blob_origin;
|
||||
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
|
||||
use script_layout_interface::rpc::TextIndexResponse;
|
||||
use script_traits::ScriptMsg as ConstellationMsg;
|
||||
use servo_atoms::Atom;
|
||||
use std::borrow::ToOwned;
|
||||
|
@ -1088,6 +1092,33 @@ impl VirtualMethods for HTMLInputElement {
|
|||
//TODO: set the editing position for text inputs
|
||||
|
||||
document_from_node(self).request_focus(self.upcast());
|
||||
if (self.input_type.get() == InputType::InputText ||
|
||||
self.input_type.get() == InputType::InputPassword) &&
|
||||
// Check if we display a placeholder. Layout doesn't know about this.
|
||||
!self.textinput.borrow().is_empty() {
|
||||
if let Some(mouse_event) = event.downcast::<MouseEvent>() {
|
||||
// dispatch_key_event (document.rs) triggers a click event when releasing
|
||||
// the space key. There's no nice way to catch this so let's use this for
|
||||
// now.
|
||||
if !(mouse_event.ScreenX() == 0 && mouse_event.ScreenY() == 0 &&
|
||||
mouse_event.GetRelatedTarget().is_none()) {
|
||||
let window = window_from_node(self);
|
||||
let translated_x = mouse_event.ClientX() + window.PageXOffset();
|
||||
let translated_y = mouse_event.ClientY() + window.PageYOffset();
|
||||
let TextIndexResponse(index) = window.text_index_query(
|
||||
self.upcast::<Node>().to_trusted_node_address(),
|
||||
translated_x,
|
||||
translated_y
|
||||
);
|
||||
if let Some(i) = index {
|
||||
self.textinput.borrow_mut().edit_point.index = i as usize;
|
||||
// trigger redraw
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
event.PreventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if event.type_() == atom!("keydown") && !event.DefaultPrevented() &&
|
||||
(self.input_type.get() == InputType::InputText ||
|
||||
self.input_type.get() == InputType::InputPassword) {
|
||||
|
|
|
@ -68,7 +68,7 @@ use script_layout_interface::message::{Msg, Reflow, ReflowQueryType, ScriptReflo
|
|||
use script_layout_interface::reporter::CSSErrorReporter;
|
||||
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
|
||||
use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse};
|
||||
use script_layout_interface::rpc::ResolvedStyleResponse;
|
||||
use script_layout_interface::rpc::{ResolvedStyleResponse, TextIndexResponse};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory};
|
||||
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, RunnableWrapper};
|
||||
use script_thread::SendableMainThreadScriptChan;
|
||||
|
@ -1362,6 +1362,15 @@ impl Window {
|
|||
self.layout_rpc.margin_style()
|
||||
}
|
||||
|
||||
pub fn text_index_query(&self, node: TrustedNodeAddress, mouse_x: i32, mouse_y: i32) -> TextIndexResponse {
|
||||
if !self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::TextIndexQuery(node, mouse_x, mouse_y),
|
||||
ReflowReason::Query) {
|
||||
return TextIndexResponse(None);
|
||||
}
|
||||
self.layout_rpc.text_index()
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn init_browsing_context(&self, browsing_context: &BrowsingContext) {
|
||||
assert!(self.browsing_context.get().is_none());
|
||||
|
@ -1710,6 +1719,7 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue
|
|||
ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
|
||||
ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery",
|
||||
ReflowQueryType::MarginStyleQuery(_n) => "\tMarginStyleQuery",
|
||||
ReflowQueryType::TextIndexQuery(..) => "\tTextIndexQuery",
|
||||
});
|
||||
|
||||
debug_msg.push_str(match *reason {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue