Unfocus input when virtual keyboard is dismissed

This commit is contained in:
Paul Rouget 2020-07-13 14:04:06 +02:00
parent 967a70bd60
commit 6252d36a14
11 changed files with 91 additions and 2 deletions

View file

@ -109,6 +109,8 @@ pub enum ConstellationMsg {
MediaSessionAction(MediaSessionActionType),
/// Toggle browser visibility.
ChangeBrowserVisibility(TopLevelBrowsingContextId, bool),
/// Virtual keyboard was dismissed
IMEDismissed,
}
impl fmt::Debug for ConstellationMsg {
@ -140,6 +142,7 @@ impl fmt::Debug for ConstellationMsg {
ExitFullScreen(..) => "ExitFullScreen",
MediaSessionAction(..) => "MediaSessionAction",
ChangeBrowserVisibility(..) => "ChangeBrowserVisibility",
IMEDismissed => "IMEDismissed",
};
write!(formatter, "ConstellationMsg::{}", variant)
}

View file

@ -102,6 +102,8 @@ pub enum WindowEvent {
MediaSessionAction(MediaSessionActionType),
/// Set browser visibility. A hidden browser will not tick the animations.
ChangeBrowserVisibility(TopLevelBrowsingContextId, bool),
/// Virtual keyboard was dismissed
IMEDismissed,
}
impl Debug for WindowEvent {
@ -134,6 +136,7 @@ impl Debug for WindowEvent {
WindowEvent::ExitFullScreen(..) => write!(f, "ExitFullScreen"),
WindowEvent::MediaSessionAction(..) => write!(f, "MediaSessionAction"),
WindowEvent::ChangeBrowserVisibility(..) => write!(f, "ChangeBrowserVisibility"),
WindowEvent::IMEDismissed => write!(f, "IMEDismissed"),
}
}
}

View file

@ -1470,6 +1470,9 @@ where
FromCompositorMsg::Keyboard(key_event) => {
self.handle_key_msg(key_event);
},
FromCompositorMsg::IMEDismissed => {
self.handle_ime_dismissed();
},
// Perform a navigation previously requested by script, if approved by the embedder.
// If there is already a pending page (self.pending_changes), it will not be overridden;
// However, if the id is not encompassed by another change, it will be.
@ -4074,6 +4077,39 @@ where
session_history.replace_history_state(pipeline_id, history_state_id, url);
}
fn handle_ime_dismissed(&mut self) {
// Send to the focused browsing contexts' current pipeline.
let focused_browsing_context_id = self
.active_browser_id
.and_then(|browser_id| self.browsers.get(&browser_id))
.map(|browser| browser.focused_browsing_context_id);
if let Some(browsing_context_id) = focused_browsing_context_id {
let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) {
Some(ctx) => ctx.pipeline_id,
None => {
return warn!(
"Got IME dismissed event for nonexistent browsing context {}.",
browsing_context_id,
);
},
};
let msg =
ConstellationControlMsg::SendEvent(pipeline_id, CompositorEvent::IMEDismissedEvent);
let result = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.event_loop.send(msg),
None => {
return debug!(
"Pipeline {:?} got IME dismissed event after closure.",
pipeline_id
);
},
};
if let Err(e) = result {
self.handle_send_error(pipeline_id, e);
}
}
}
fn handle_key_msg(&mut self, event: KeyboardEvent) {
// Send to the focused browsing contexts' current pipeline. If it
// doesn't exist, fall back to sending to the compositor.

View file

@ -1722,6 +1722,13 @@ impl Document {
self.window.reflow(ReflowGoal::Full, ReflowReason::KeyEvent);
}
pub fn ime_dismissed(&self) {
self.request_focus(
self.GetBody().as_ref().map(|e| &*e.upcast()),
FocusType::Element,
)
}
pub fn dispatch_composition_event(
&self,
composition_event: ::keyboard_types::CompositionEvent,

View file

@ -129,8 +129,8 @@ use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
use script_layout_interface::message::{self, LayoutThreadInit, Msg, ReflowGoal};
use script_traits::webdriver_msg::WebDriverScriptCommand;
use script_traits::CompositorEvent::{
CompositionEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent, TouchEvent,
WheelEvent,
CompositionEvent, IMEDismissedEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent,
ResizeEvent, TouchEvent, WheelEvent,
};
use script_traits::{
AnimationTickType, CompositorEvent, ConstellationControlMsg, DiscardBrowsingContext,
@ -3583,6 +3583,14 @@ impl ScriptThread {
document.dispatch_key_event(key_event);
},
IMEDismissedEvent => {
let document = match self.documents.borrow().find_document(pipeline_id) {
Some(document) => document,
None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
};
document.ime_dismissed();
},
CompositionEvent(composition_event) => {
let document = match self.documents.borrow().find_document(pipeline_id) {
Some(document) => document,

View file

@ -570,6 +570,8 @@ pub enum CompositorEvent {
KeyboardEvent(KeyboardEvent),
/// An event from the IME is dispatched.
CompositionEvent(CompositionEvent),
/// Virtual keyboard was dismissed
IMEDismissedEvent,
}
/// Requests a TimerEvent-Message be sent after the given duration.

View file

@ -663,6 +663,16 @@ where
}
},
WindowEvent::IMEDismissed => {
let msg = ConstellationMsg::IMEDismissed;
if let Err(e) = self.constellation_chan.send(msg) {
warn!(
"Sending IMEDismissed event to constellation failed ({:?}).",
e
);
}
},
WindowEvent::Quit => {
self.compositor.maybe_start_shutting_down();
},

View file

@ -560,6 +560,11 @@ impl ServoGlue {
}
}
pub fn ime_dismissed(&mut self) -> Result<(), &'static str> {
info!("ime_dismissed");
self.process_event(WindowEvent::IMEDismissed)
}
pub fn on_context_menu_closed(
&mut self,
result: ContextMenuResult,

View file

@ -766,6 +766,14 @@ pub extern "C" fn change_visibility(visible: bool) {
});
}
#[no_mangle]
pub extern "C" fn ime_dismissed() {
catch_any_panic(|| {
debug!("ime_dismissed");
call(|s| s.ime_dismissed());
});
}
pub struct WakeupCallback(extern "C" fn());
impl WakeupCallback {

View file

@ -88,6 +88,7 @@ public:
void ContextMenuClosed(CContextMenuResult res, unsigned int idx) {
on_context_menu_closed(res, idx);
}
void IMEDismissed() { ime_dismissed(); }
private:
ServoDelegate &mDelegate;

View file

@ -91,6 +91,12 @@ void ServoControl::OnLoaded(IInspectable const &, RoutedEventArgs const &) {
void ServoControl::InitializeTextController() {
mInputPane = Windows::UI::ViewManagement::InputPane::GetForCurrentView();
mInputPane->Hiding([=](const auto &, const auto &) {
if (mLooping) {
RunOnGLThread([=] { mServo->IMEDismissed(); });
}
});
auto manager = CoreTextServicesManager::GetForCurrentView();
mEditContext = manager.CreateEditContext();
mEditContext->InputPaneDisplayPolicy(CoreTextInputPaneDisplayPolicy::Manual);