mirror of
https://github.com/servo/servo.git
synced 2025-07-28 01:30:32 +01:00
Forward WebDriver CompositionEvent
Dispatch composition events in JS. Insert characters from composition events to text input. CompositionEvents currently can only be created by WebDriver and not by embedders.
This commit is contained in:
parent
1ac6f435c8
commit
b936fea79d
12 changed files with 118 additions and 26 deletions
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -539,7 +539,7 @@ dependencies = [
|
||||||
"gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
|
@ -576,7 +576,7 @@ dependencies = [
|
||||||
"gfx_traits 0.0.1",
|
"gfx_traits 0.0.1",
|
||||||
"http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"layout_traits 0.0.1",
|
"layout_traits 0.0.1",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"metrics 0.0.1",
|
"metrics 0.0.1",
|
||||||
|
@ -959,7 +959,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-channel 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
|
@ -1913,7 +1913,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "keyboard-types"
|
name = "keyboard-types"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2235,7 +2235,7 @@ dependencies = [
|
||||||
"hashglobe 0.1.0",
|
"hashglobe 0.1.0",
|
||||||
"hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mozjs 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mozjs 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"selectors 0.20.0",
|
"selectors 0.20.0",
|
||||||
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3226,7 +3226,7 @@ dependencies = [
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jstraceable_derive 0.0.1",
|
"jstraceable_derive 0.0.1",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3329,7 +3329,7 @@ name = "script_tests"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"script 0.0.1",
|
"script 0.0.1",
|
||||||
"servo_url 0.0.1",
|
"servo_url 0.0.1",
|
||||||
]
|
]
|
||||||
|
@ -3350,7 +3350,7 @@ dependencies = [
|
||||||
"hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper_serde 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"malloc_size_of 0.0.1",
|
"malloc_size_of 0.0.1",
|
||||||
"malloc_size_of_derive 0.0.1",
|
"malloc_size_of_derive 0.0.1",
|
||||||
|
@ -3433,7 +3433,7 @@ dependencies = [
|
||||||
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libservo 0.0.1",
|
"libservo 0.0.1",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -4496,7 +4496,7 @@ dependencies = [
|
||||||
"hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
"net_traits 0.0.1",
|
"net_traits 0.0.1",
|
||||||
|
@ -4951,7 +4951,7 @@ dependencies = [
|
||||||
"checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
"checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
"checksum jpeg-decoder 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0dfe27a6c0dabd772d0f9b9f8701c4ca12c4d1eebcadf2be1f6f70396f6a1434"
|
"checksum jpeg-decoder 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0dfe27a6c0dabd772d0f9b9f8701c4ca12c4d1eebcadf2be1f6f70396f6a1434"
|
||||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "823bf0e5ec01b80424a318e79a0d1375725281acf311c47543ab3413f704dc25"
|
"checksum keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "53b536dc22c0dabb295e85dbd0c062023885b12b8db24e1d86833f4e50ea7959"
|
||||||
"checksum khronos_api 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62237e6d326bd5871cd21469323bf096de81f1618cd82cbaf5d87825335aeb49"
|
"checksum khronos_api 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62237e6d326bd5871cd21469323bf096de81f1618cd82cbaf5d87825335aeb49"
|
||||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||||
"checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50"
|
"checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50"
|
||||||
|
|
|
@ -13,6 +13,9 @@ click
|
||||||
close
|
close
|
||||||
color
|
color
|
||||||
complete
|
complete
|
||||||
|
compositionend
|
||||||
|
compositionstart
|
||||||
|
compositionupdate
|
||||||
controllerchange
|
controllerchange
|
||||||
cursive
|
cursive
|
||||||
date
|
date
|
||||||
|
|
|
@ -119,6 +119,7 @@ use gfx_traits::Epoch;
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use ipc_channel::Error as IpcError;
|
use ipc_channel::Error as IpcError;
|
||||||
|
use keyboard_types::webdriver::Event as WebDriverInputEvent;
|
||||||
use keyboard_types::KeyboardEvent;
|
use keyboard_types::KeyboardEvent;
|
||||||
use layout_traits::LayoutThreadFactory;
|
use layout_traits::LayoutThreadFactory;
|
||||||
use log::{Level, LevelFilter, Log, Metadata, Record};
|
use log::{Level, LevelFilter, Log, Metadata, Record};
|
||||||
|
@ -3035,7 +3036,14 @@ where
|
||||||
None => return warn!("Pipeline {} SendKeys after closure.", pipeline_id),
|
None => return warn!("Pipeline {} SendKeys after closure.", pipeline_id),
|
||||||
};
|
};
|
||||||
for event in cmd {
|
for event in cmd {
|
||||||
let event = CompositorEvent::KeyboardEvent(event);
|
let event = match event {
|
||||||
|
WebDriverInputEvent::Keyboard(event) => {
|
||||||
|
CompositorEvent::KeyboardEvent(event)
|
||||||
|
},
|
||||||
|
WebDriverInputEvent::Composition(event) => {
|
||||||
|
CompositorEvent::CompositionEvent(event)
|
||||||
|
},
|
||||||
|
};
|
||||||
let control_msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
|
let control_msg = ConstellationControlMsg::SendEvent(pipeline_id, event);
|
||||||
if let Err(e) = event_loop.send(control_msg) {
|
if let Err(e) = event_loop.send(control_msg) {
|
||||||
return self.handle_send_error(pipeline_id, e);
|
return self.handle_send_error(pipeline_id, e);
|
||||||
|
|
|
@ -64,7 +64,7 @@ image = "0.20"
|
||||||
ipc-channel = "0.11"
|
ipc-channel = "0.11"
|
||||||
itertools = "0.7.6"
|
itertools = "0.7.6"
|
||||||
jstraceable_derive = {path = "../jstraceable_derive"}
|
jstraceable_derive = {path = "../jstraceable_derive"}
|
||||||
keyboard-types = "0.4.3"
|
keyboard-types = "0.4.4"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
|
@ -59,6 +59,10 @@ impl CompositionEvent {
|
||||||
);
|
);
|
||||||
Ok(event)
|
Ok(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn data(&self) -> &str {
|
||||||
|
&*self.data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompositionEventMethods for CompositionEvent {
|
impl CompositionEventMethods for CompositionEvent {
|
||||||
|
|
|
@ -38,6 +38,7 @@ use crate::dom::bindings::xmlname::{
|
||||||
};
|
};
|
||||||
use crate::dom::closeevent::CloseEvent;
|
use crate::dom::closeevent::CloseEvent;
|
||||||
use crate::dom::comment::Comment;
|
use crate::dom::comment::Comment;
|
||||||
|
use crate::dom::compositionevent::CompositionEvent;
|
||||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::customelementregistry::CustomElementDefinition;
|
use crate::dom::customelementregistry::CustomElementDefinition;
|
||||||
use crate::dom::customevent::CustomEvent;
|
use crate::dom::customevent::CustomEvent;
|
||||||
|
@ -1465,6 +1466,37 @@ impl Document {
|
||||||
self.window.reflow(ReflowGoal::Full, ReflowReason::KeyEvent);
|
self.window.reflow(ReflowGoal::Full, ReflowReason::KeyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_composition_event(
|
||||||
|
&self,
|
||||||
|
composition_event: ::keyboard_types::CompositionEvent,
|
||||||
|
) {
|
||||||
|
// spec: https://w3c.github.io/uievents/#compositionstart
|
||||||
|
// spec: https://w3c.github.io/uievents/#compositionupdate
|
||||||
|
// spec: https://w3c.github.io/uievents/#compositionend
|
||||||
|
// > Event.target : focused element processing the composition
|
||||||
|
let focused = self.get_focused_element();
|
||||||
|
let target = if let Some(elem) = &focused {
|
||||||
|
elem.upcast()
|
||||||
|
} else {
|
||||||
|
// Event is only dispatched if there is a focused element.
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let cancelable = composition_event.state == keyboard_types::CompositionState::Start;
|
||||||
|
|
||||||
|
let compositionevent = CompositionEvent::new(
|
||||||
|
&self.window,
|
||||||
|
DOMString::from(composition_event.state.to_string()),
|
||||||
|
true,
|
||||||
|
cancelable,
|
||||||
|
Some(&self.window),
|
||||||
|
0,
|
||||||
|
DOMString::from(composition_event.data),
|
||||||
|
);
|
||||||
|
let event = compositionevent.upcast::<Event>();
|
||||||
|
event.fire(target);
|
||||||
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#converting-nodes-into-a-node
|
// https://dom.spec.whatwg.org/#converting-nodes-into-a-node
|
||||||
pub fn node_from_nodes_and_strings(
|
pub fn node_from_nodes_and_strings(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -17,6 +17,7 @@ use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom, RootedReference};
|
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom, RootedReference};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::compositionevent::CompositionEvent;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::element::{
|
use crate::dom::element::{
|
||||||
AttributeMutation, Element, LayoutElementHelpers, RawLayoutElementHelpers,
|
AttributeMutation, Element, LayoutElementHelpers, RawLayoutElementHelpers,
|
||||||
|
@ -1526,6 +1527,23 @@ impl VirtualMethods for HTMLInputElement {
|
||||||
&window,
|
&window,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (event.type_() == atom!("compositionstart") ||
|
||||||
|
event.type_() == atom!("compositionupdate") ||
|
||||||
|
event.type_() == atom!("compositionend")) &&
|
||||||
|
self.input_type().is_textual_or_password()
|
||||||
|
{
|
||||||
|
// TODO: Update DOM on start and continue
|
||||||
|
// and generally do proper CompositionEvent handling.
|
||||||
|
if let Some(compositionevent) = event.downcast::<CompositionEvent>() {
|
||||||
|
if event.type_() == atom!("compositionend") {
|
||||||
|
let _ = self
|
||||||
|
.textinput
|
||||||
|
.borrow_mut()
|
||||||
|
.handle_compositionend(compositionevent);
|
||||||
|
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||||
|
}
|
||||||
|
event.mark_as_handled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::dom::bindings::error::ErrorResult;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
|
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::compositionevent::CompositionEvent;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::element::RawLayoutElementHelpers;
|
use crate::dom::element::RawLayoutElementHelpers;
|
||||||
use crate::dom::element::{AttributeMutation, Element};
|
use crate::dom::element::{AttributeMutation, Element};
|
||||||
|
@ -576,6 +577,22 @@ impl VirtualMethods for HTMLTextAreaElement {
|
||||||
&window,
|
&window,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if event.type_() == atom!("compositionstart") ||
|
||||||
|
event.type_() == atom!("compositionupdate") ||
|
||||||
|
event.type_() == atom!("compositionend")
|
||||||
|
{
|
||||||
|
// TODO: Update DOM on start and continue
|
||||||
|
// and generally do proper CompositionEvent handling.
|
||||||
|
if let Some(compositionevent) = event.downcast::<CompositionEvent>() {
|
||||||
|
if event.type_() == atom!("compositionend") {
|
||||||
|
let _ = self
|
||||||
|
.textinput
|
||||||
|
.borrow_mut()
|
||||||
|
.handle_compositionend(compositionevent);
|
||||||
|
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||||
|
}
|
||||||
|
event.mark_as_handled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
|
||||||
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
|
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
|
||||||
use script_traits::webdriver_msg::WebDriverScriptCommand;
|
use script_traits::webdriver_msg::WebDriverScriptCommand;
|
||||||
use script_traits::CompositorEvent::{
|
use script_traits::CompositorEvent::{
|
||||||
KeyboardEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent, TouchEvent,
|
CompositionEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent, TouchEvent,
|
||||||
};
|
};
|
||||||
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
use script_traits::{CompositorEvent, ConstellationControlMsg};
|
||||||
use script_traits::{DiscardBrowsingContext, DocumentActivity, EventResult};
|
use script_traits::{DiscardBrowsingContext, DocumentActivity, EventResult};
|
||||||
|
@ -2881,6 +2881,14 @@ impl ScriptThread {
|
||||||
};
|
};
|
||||||
document.dispatch_key_event(key_event);
|
document.dispatch_key_event(key_event);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
CompositionEvent(composition_event) => {
|
||||||
|
let document = match { self.documents.borrow().find_document(pipeline_id) } {
|
||||||
|
Some(document) => document,
|
||||||
|
None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
|
||||||
|
};
|
||||||
|
document.dispatch_composition_event(composition_event);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use crate::clipboard_provider::ClipboardProvider;
|
use crate::clipboard_provider::ClipboardProvider;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::compositionevent::CompositionEvent;
|
||||||
use crate::dom::keyboardevent::KeyboardEvent;
|
use crate::dom::keyboardevent::KeyboardEvent;
|
||||||
use keyboard_types::{Key, KeyState, Modifiers, ShortcutMatcher};
|
use keyboard_types::{Key, KeyState, Modifiers, ShortcutMatcher};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
@ -831,6 +832,11 @@ impl<T: ClipboardProvider> TextInput<T> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_compositionend(&mut self, event: &CompositionEvent) -> KeyReaction {
|
||||||
|
self.insert_string(event.data());
|
||||||
|
KeyReaction::DispatchInput
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the content is empty.
|
/// Whether the content is empty.
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.lines.len() <= 1 && self.lines.get(0).map_or(true, |line| line.is_empty())
|
self.lines.len() <= 1 && self.lines.get(0).map_or(true, |line| line.is_empty())
|
||||||
|
|
|
@ -30,7 +30,8 @@ use http::HeaderMap;
|
||||||
use hyper::Method;
|
use hyper::Method;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use ipc_channel::Error as IpcError;
|
use ipc_channel::Error as IpcError;
|
||||||
use keyboard_types::KeyboardEvent;
|
use keyboard_types::webdriver::Event as WebDriverInputEvent;
|
||||||
|
use keyboard_types::{CompositionEvent, KeyboardEvent};
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId};
|
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId};
|
||||||
use msg::constellation_msg::{PipelineNamespaceId, TopLevelBrowsingContextId, TraversalDirection};
|
use msg::constellation_msg::{PipelineNamespaceId, TopLevelBrowsingContextId, TraversalDirection};
|
||||||
|
@ -461,6 +462,8 @@ pub enum CompositorEvent {
|
||||||
),
|
),
|
||||||
/// A key was pressed.
|
/// A key was pressed.
|
||||||
KeyboardEvent(KeyboardEvent),
|
KeyboardEvent(KeyboardEvent),
|
||||||
|
/// An event from the IME is dispatched.
|
||||||
|
CompositionEvent(CompositionEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Requests a TimerEvent-Message be sent after the given duration.
|
/// Requests a TimerEvent-Message be sent after the given duration.
|
||||||
|
@ -691,7 +694,7 @@ pub enum WebDriverCommandMsg {
|
||||||
/// of a browsing context.
|
/// of a browsing context.
|
||||||
ScriptCommand(BrowsingContextId, WebDriverScriptCommand),
|
ScriptCommand(BrowsingContextId, WebDriverScriptCommand),
|
||||||
/// Act as if keys were pressed in the browsing context with the given ID.
|
/// Act as if keys were pressed in the browsing context with the given ID.
|
||||||
SendKeys(BrowsingContextId, Vec<KeyboardEvent>),
|
SendKeys(BrowsingContextId, Vec<WebDriverInputEvent>),
|
||||||
/// Set the window size.
|
/// Set the window size.
|
||||||
SetWindowSize(
|
SetWindowSize(
|
||||||
TopLevelBrowsingContextId,
|
TopLevelBrowsingContextId,
|
||||||
|
|
|
@ -17,7 +17,7 @@ use euclid::TypedSize2D;
|
||||||
use hyper::Method;
|
use hyper::Method;
|
||||||
use image::{DynamicImage, ImageFormat, RgbImage};
|
use image::{DynamicImage, ImageFormat, RgbImage};
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use keyboard_types::webdriver::{send_keys, Event as KeyEvent};
|
use keyboard_types::webdriver::send_keys;
|
||||||
use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection};
|
use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, TraversalDirection};
|
||||||
use net_traits::image::base::PixelFormat;
|
use net_traits::image::base::PixelFormat;
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
|
@ -1036,19 +1036,12 @@ impl Handler {
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// FIXME: Don't discard composition events.
|
let input_events = send_keys(&keys.text);
|
||||||
let keys = send_keys(&keys.text)
|
|
||||||
.drain(..)
|
|
||||||
.filter_map(|event| match event {
|
|
||||||
KeyEvent::Keyboard(v) => Some(v),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// TODO: there's a race condition caused by the focus command and the
|
// TODO: there's a race condition caused by the focus command and the
|
||||||
// send keys command being two separate messages,
|
// send keys command being two separate messages,
|
||||||
// so the constellation may have changed state between them.
|
// so the constellation may have changed state between them.
|
||||||
let cmd_msg = WebDriverCommandMsg::SendKeys(browsing_context_id, keys);
|
let cmd_msg = WebDriverCommandMsg::SendKeys(browsing_context_id, input_events);
|
||||||
self.constellation_chan
|
self.constellation_chan
|
||||||
.send(ConstellationMsg::WebDriverCommand(cmd_msg))
|
.send(ConstellationMsg::WebDriverCommand(cmd_msg))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue