Skip to content

Commit

Permalink
Notify the embedder when it should display or hide an IME
Browse files Browse the repository at this point in the history
  • Loading branch information
fabricedesre committed Apr 22, 2018
1 parent 05fe8fa commit 4288661
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 2 deletions.
8 changes: 7 additions & 1 deletion components/compositing/compositor_thread.rs
Expand Up @@ -8,7 +8,7 @@ use SendableFrameTree;
use compositor::CompositingReason;
use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId};
use msg::constellation_msg::{InputMethodType, Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId};
use net_traits::image::base::Image;
use profile_traits::mem;
use profile_traits::time;
Expand Down Expand Up @@ -143,6 +143,10 @@ pub enum EmbedderMsg {
Panic(TopLevelBrowsingContextId, String, Option<String>),
/// Open dialog to select bluetooth device.
GetSelectedBluetoothDevice(Vec<String>, IpcSender<Option<String>>),
/// Request to present an IME to the user when an editable element is focused.
ShowIME(TopLevelBrowsingContextId, InputMethodType),
/// Request to hide the IME when the editable element is blurred.
HideIME(TopLevelBrowsingContextId),
/// Servo has shut down
Shutdown,
}
Expand Down Expand Up @@ -244,6 +248,8 @@ impl Debug for EmbedderMsg {
EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"),
EmbedderMsg::Panic(..) => write!(f, "Panic"),
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
EmbedderMsg::ShowIME(..) => write!(f, "ShowIME"),
EmbedderMsg::HideIME(..) => write!(f, "HideIME"),
EmbedderMsg::Shutdown => write!(f, "Shutdown"),
}
}
Expand Down
8 changes: 8 additions & 0 deletions components/constellation/constellation.rs
Expand Up @@ -1247,6 +1247,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::SetFullscreenState(state) => {
self.embedder_proxy.send(EmbedderMsg::SetFullscreenState(source_top_ctx_id, state));
}
FromScriptMsg::ShowIME(kind) => {
debug!("constellation got ShowIME message");
self.embedder_proxy.send(EmbedderMsg::ShowIME(source_top_ctx_id, kind));
}
FromScriptMsg::HideIME => {
debug!("constellation got HideIME message");
self.embedder_proxy.send(EmbedderMsg::HideIME(source_top_ctx_id));
}
}
}

Expand Down
20 changes: 20 additions & 0 deletions components/msg/constellation_msg.rs
Expand Up @@ -401,3 +401,23 @@ pub const TEST_BROWSING_CONTEXT_INDEX: BrowsingContextIndex =
#[cfg(feature = "unstable")]
pub const TEST_BROWSING_CONTEXT_ID: BrowsingContextId =
BrowsingContextId { namespace_id: TEST_NAMESPACE, index: TEST_BROWSING_CONTEXT_INDEX };

// Used to specify the kind of input method editor appropriate to edit a field.
// This is a subset of htmlinputelement::InputType because some variants of InputType
// don't make sense in this context.
#[derive(Deserialize, Serialize)]
pub enum InputMethodType {
Color,
Date,
DatetimeLocal,
Email,
Month,
Number,
Password,
Search,
Tel,
Text,
Time,
Url,
Week,
}
10 changes: 10 additions & 0 deletions components/script/dom/document.rs
Expand Up @@ -812,6 +812,11 @@ impl Document {
elem.set_focus_state(false);
// FIXME: pass appropriate relatedTarget
self.fire_focus_event(FocusEventType::Blur, node, None);

// Notify the embedder to hide the input method.
if elem.input_method_type().is_some() {
self.send_to_constellation(ScriptMsg::HideIME);
}
}

self.focused.set(self.possibly_focused.get().r());
Expand All @@ -826,6 +831,11 @@ impl Document {
if focus_type == FocusType::Element {
self.send_to_constellation(ScriptMsg::Focus);
}

// Notify the embedder to display an input method.
if let Some(kind) = elem.input_method_type() {
self.send_to_constellation(ScriptMsg::ShowIME(kind));
}
}
}

Expand Down
17 changes: 17 additions & 0 deletions components/script/dom/element.rs
Expand Up @@ -83,6 +83,7 @@ use html5ever::serialize::TraversalScope;
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
use js::jsapi::Heap;
use js::jsval::JSVal;
use msg::constellation_msg::InputMethodType;
use net_traits::request::CorsSettings;
use ref_filter_map::ref_filter_map;
use script_layout_interface::message::ReflowGoal;
Expand Down Expand Up @@ -1087,6 +1088,22 @@ impl Element {
None
}

// Returns the kind of IME control needed for a focusable element, if any.
pub fn input_method_type(&self) -> Option<InputMethodType> {
if !self.is_focusable_area() {
return None;
}

if let Some(input) = self.downcast::<HTMLInputElement>() {
input.input_type().as_ime_type()
} else if self.is::<HTMLTextAreaElement>() {
Some(InputMethodType::Text)
} else {
// Other focusable elements that are not input fields.
None
}
}

pub fn is_focusable_area(&self) -> bool {
if self.is_actually_disabled() {
return false;
Expand Down
20 changes: 20 additions & 0 deletions components/script/dom/htmlinputelement.rs
Expand Up @@ -40,6 +40,7 @@ use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix};
use mime_guess;
use msg::constellation_msg::InputMethodType;
use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
Expand Down Expand Up @@ -137,6 +138,25 @@ impl InputType {
InputType::Week => "week",
}
}

pub fn as_ime_type(&self) -> Option<InputMethodType> {
match *self {
InputType::Color => Some(InputMethodType::Color),
InputType::Date => Some(InputMethodType::Date),
InputType::DatetimeLocal => Some(InputMethodType::DatetimeLocal),
InputType::Email => Some(InputMethodType::Email),
InputType::Month => Some(InputMethodType::Month),
InputType::Number => Some(InputMethodType::Number),
InputType::Password => Some(InputMethodType::Password),
InputType::Search => Some(InputMethodType::Search),
InputType::Tel => Some(InputMethodType::Tel),
InputType::Text => Some(InputMethodType::Text),
InputType::Time => Some(InputMethodType::Time),
InputType::Url => Some(InputMethodType::Url),
InputType::Week => Some(InputMethodType::Week),
_ => None,
}
}
}

impl<'a> From<&'a Atom> for InputType {
Expand Down
6 changes: 5 additions & 1 deletion components/script_traits/script_msg.rs
Expand Up @@ -17,7 +17,7 @@ use euclid::{Size2D, TypedSize2D};
use gfx_traits::Epoch;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TraversalDirection};
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use msg::constellation_msg::{InputMethodType, Key, KeyModifiers, KeyState};
use net_traits::CoreResourceMsg;
use net_traits::request::RequestInit;
use net_traits::storage_thread::StorageType;
Expand Down Expand Up @@ -163,6 +163,10 @@ pub enum ScriptMsg {
GetScreenSize(IpcSender<(DeviceUintSize)>),
/// Get the available screen size (pixel)
GetScreenAvailSize(IpcSender<(DeviceUintSize)>),
/// Request to present an IME to the user when an editable element is focused.
ShowIME(InputMethodType),
/// Request to hide the IME when the editable element is blurred.
HideIME,
/// Requests that the compositor shut down.
Exit,
}
Expand Down
6 changes: 6 additions & 0 deletions ports/servo/browser.rs
Expand Up @@ -295,6 +295,12 @@ impl Browser {
EmbedderMsg::GetSelectedBluetoothDevice(devices, sender) => {
platform_get_selected_devices(devices, sender);
}
EmbedderMsg::ShowIME(_browser_id, _kind) => {
debug!("ShowIME received");
}
EmbedderMsg::HideIME(_browser_id) => {
debug!("HideIME received");
}
}
}
}
Expand Down

0 comments on commit 4288661

Please sign in to comment.