Auto merge of #28308 - philip-lamb:phil-ime-textentry, r=jdm

Improve IME messaging to embedder with insertion point index and mult…

…iline flag.

<!-- Please describe your changes on the following line: -->
This improves handling of IME requests in the embedder by passing the location of the insertion point along with the current text, and a boolean flag 'multiline' (true for HTML textarea, false otherwise) which allows the embedder to be more clever about handling of the 'enter' or 'return' keys.

Tested and working in an embedding example.

---
<!-- 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 #___ (GitHub issue number if applicable)

<!-- Either: -->
- [x] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2021-03-29 23:10:17 -04:00 committed by GitHub
commit 94e337f22f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 16 deletions

View file

@ -197,7 +197,10 @@ pub enum EmbedderMsg {
/// Open interface to request permission specified by prompt.
PromptPermission(PermissionPrompt, IpcSender<PermissionRequest>),
/// Request to present an IME to the user when an editable element is focused.
ShowIME(InputMethodType, Option<String>, DeviceIntRect),
/// If the input is text, the second parameter defines the pre-existing string
/// text content and the zero-based index into the string locating the insertion point.
/// bool is true for multi-line and false otherwise.
ShowIME(InputMethodType, Option<(String, i32)>, bool, DeviceIntRect),
/// Request to hide the IME when the editable element is blurred.
HideIME,
/// Servo has shut down

View file

@ -1122,16 +1122,29 @@ impl Document {
Point2D::new(rect.origin.x.to_px(), rect.origin.y.to_px()),
Size2D::new(rect.size.width.to_px(), rect.size.height.to_px()),
);
let text = if let Some(input) = elem.downcast::<HTMLInputElement>() {
Some((&input.Value()).to_string())
let (text, multiline) = if let Some(input) = elem.downcast::<HTMLInputElement>() {
(
Some((
(&input.Value()).to_string(),
input.GetSelectionEnd().unwrap_or(0) as i32,
)),
false,
)
} else if let Some(textarea) = elem.downcast::<HTMLTextAreaElement>() {
Some((&textarea.Value()).to_string())
(
Some((
(&textarea.Value()).to_string(),
textarea.GetSelectionEnd().unwrap_or(0) as i32,
)),
true,
)
} else {
None
(None, false)
};
self.send_to_embedder(EmbedderMsg::ShowIME(
kind,
text,
multiline,
DeviceIntRect::from_untyped(&rect),
));
}

View file

@ -416,7 +416,8 @@ impl HostTrait for HostCallbacks {
fn on_ime_show(
&self,
_input_type: InputMethodType,
_text: Option<String>,
_text: Option<(String, i32)>,
_multiline: bool,
_bounds: DeviceIntRect,
) {
if let Some(keyboard) = self.keyboard.0 {

View file

@ -141,7 +141,13 @@ pub trait HostTrait {
/// Servo finished shutting down.
fn on_shutdown_complete(&self);
/// A text input is focused.
fn on_ime_show(&self, input_type: InputMethodType, text: Option<String>, bounds: DeviceIntRect);
fn on_ime_show(
&self,
input_type: InputMethodType,
text: Option<(String, i32)>,
multiline: bool,
bounds: DeviceIntRect,
);
/// Input lost focus
fn on_ime_hide(&self);
/// Gets sytem clipboard contents.
@ -742,10 +748,10 @@ impl ServoGlue {
let _ = sender.send(result);
},
EmbedderMsg::ShowIME(kind, text, bounds) => {
EmbedderMsg::ShowIME(kind, text, multiline, bounds) => {
self.callbacks
.host_callbacks
.on_ime_show(kind, text, bounds);
.on_ime_show(kind, text, multiline, bounds);
},
EmbedderMsg::HideIME => {
self.callbacks.host_callbacks.on_ime_hide();

View file

@ -205,7 +205,15 @@ pub struct CHostCallbacks {
pub on_history_changed: extern "C" fn(can_go_back: bool, can_go_forward: bool),
pub on_animating_changed: extern "C" fn(animating: bool),
pub on_shutdown_complete: extern "C" fn(),
pub on_ime_show: extern "C" fn(text: *const c_char, x: i32, y: i32, width: i32, height: i32),
pub on_ime_show: extern "C" fn(
text: *const c_char,
text_index: i32,
multiline: bool,
x: i32,
y: i32,
width: i32,
height: i32,
),
pub on_ime_hide: extern "C" fn(),
pub get_clipboard_contents: extern "C" fn() -> *const c_char,
pub set_clipboard_contents: extern "C" fn(contents: *const c_char),
@ -808,17 +816,21 @@ impl HostTrait for HostCallbacks {
fn on_ime_show(
&self,
_input_type: InputMethodType,
text: Option<String>,
text: Option<(String, i32)>,
multiline: bool,
bounds: DeviceIntRect,
) {
debug!("on_ime_show");
let text = text.and_then(|s| CString::new(s).ok());
let text_index = text.as_ref().map_or(0, |(_, i)| *i);
let text = text.and_then(|(s, _)| CString::new(s).ok());
let text_ptr = text
.as_ref()
.map(|cstr| cstr.as_ptr())
.unwrap_or(std::ptr::null());
(self.0.on_ime_show)(
text_ptr,
text_index,
multiline,
bounds.origin.x,
bounds.origin.y,
bounds.size.width,

View file

@ -530,7 +530,14 @@ impl HostTrait for HostCallbacks {
.unwrap();
}
fn on_ime_show(&self, _type: InputEncoding, _text: Option<String>, _rect: DeviceIntRect) {}
fn on_ime_show(
&self,
_type: InputEncoding,
_text: Option<(String, i32)>,
_multiline: bool,
_rect: DeviceIntRect,
) {
}
fn on_ime_hide(&self) {}
fn get_clipboard_contents(&self) -> Option<String> {

View file

@ -487,7 +487,7 @@ where
let permission_state = prompt_user(prompt);
let _ = sender.send(permission_state);
},
EmbedderMsg::ShowIME(_kind, _text, _rect) => {
EmbedderMsg::ShowIME(_kind, _text, _multiline, _rect) => {
debug!("ShowIME received");
},
EmbedderMsg::HideIME => {

View file

@ -66,8 +66,8 @@ void on_panic(const char *cbacktrace) {
throw hresult_error(E_FAIL, backtrace);
}
void on_ime_show(const char *text, int32_t x, int32_t y, int32_t width,
int32_t height) {
void on_ime_show(const char *text, int32_t text_index, bool multiline,
int32_t x, int32_t y, int32_t width, int32_t height) {
hstring htext = L"";
if (text != nullptr) {
htext = char2hstring(text);