Chromium Code Reviews| Index: content/browser/renderer_host/render_widget_host_view_aura.cc |
| diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc |
| index c33e325cef30eaab1a331b7c0dcf7f6d7f8f6166..25e34d878feed87419356033fdef8e95463a022f 100644 |
| --- a/content/browser/renderer_host/render_widget_host_view_aura.cc |
| +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc |
| @@ -97,10 +97,12 @@ |
| #include "ui/wm/public/window_types.h" |
| #if defined(OS_WIN) |
| +#include "base/time/time.h" |
| #include "content/browser/accessibility/browser_accessibility_manager_win.h" |
| #include "content/browser/accessibility/browser_accessibility_win.h" |
| #include "content/browser/renderer_host/legacy_render_widget_host_win.h" |
| #include "ui/base/win/hidden_window.h" |
| +#include "ui/base/win/osk_display_manager.h" |
| #include "ui/display/win/screen_win.h" |
| #include "ui/gfx/gdi_util.h" |
| #endif |
| @@ -212,6 +214,95 @@ void MarkUnchangedTouchPointsAsStationary( |
| } |
| } |
| +#if defined(OS_WIN) |
| +const int kVirtualKeyboardDisplayWaitTimeoutMs = 100; |
| +const int kMaxVirtualKeyboardDisplayRetries = 5; |
| + |
| +void DismissVirtualKeyboardTask() { |
| + static int virtual_keyboard_display_retries = 0; |
|
ncarter (slow)
2016/05/19 17:45:55
I believe was preexisting behavior, but isn't it p
ananta
2016/05/19 19:33:38
Thanks for identifying this issue.
Added a commen
|
| + // If the virtual keyboard is not yet visible, then we execute the task again |
| + // waiting for it to show up. |
| + if (!ui::DismissVirtualKeyboard()) { |
| + if (virtual_keyboard_display_retries < kMaxVirtualKeyboardDisplayRetries) { |
| + BrowserThread::PostDelayedTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask)), |
| + base::TimeDelta::FromMilliseconds( |
| + kVirtualKeyboardDisplayWaitTimeoutMs)); |
| + ++virtual_keyboard_display_retries; |
| + } |
| + else { |
| + virtual_keyboard_display_retries = 0; |
| + } |
| + } |
| +} |
| + |
| +// This class implements the ui::OnScreenKeyboardObserver interface |
| +// which provides notifications about the on screen keyboard on Windows getting |
| +// displayed or hidden in response to taps on editable fields. |
| +// It provides functionality to request blink to scroll the input field if it |
| +// is obscured by the on screen keyboard. |
| +class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver { |
| + public: |
| + explicit WinScreenKeyboardObserver(RenderWidgetHostImpl* host, |
| + const gfx::Point& location_dips, |
| + float scale_factor) |
| + : host_(host), |
| + location_in_dips_(location_dips), |
| + device_scale_factor_(scale_factor) { |
| + if (host_ && host_->GetView()) |
| + host_->GetView()->SetInsets(gfx::Insets()); |
| + } |
| + |
| + // base::win::OnScreenKeyboardObserver overrides. |
| + void OnKeyboardVisible(const gfx::Rect& keyboard_rect_dips) override { |
| + DCHECK(host_); |
| + if (host_ && host_->GetView()) { |
| + // We use the PtInRect API to determine if the touch occurred in the |
| + // bounds of the OSK. |
| + // The API expects the point and the rectangle in pixels. |
| + gfx::Rect keyboard_rect_pixels = |
| + gfx::ConvertRectToPixel(device_scale_factor_, keyboard_rect_dips); |
| + RECT keyboard_rect_windows = keyboard_rect_pixels.ToRECT(); |
| + |
| + gfx::Point location_in_pixels = gfx::ConvertPointToPixel( |
| + device_scale_factor_, location_in_dips_); |
| + POINT touch_location = location_in_pixels.ToPOINT(); |
| + |
| + if (::PtInRect(&keyboard_rect_windows, touch_location)) { |
| + DVLOG(1) << "OSK covering focus point."; |
| + // Get the intersection of the view rectangle and the OSK. |
| + // The viewport needs to be moved up by the height of the intersection. |
| + gfx::Rect screen_rect = host_->GetView()->GetBoundsInRootWindow(); |
| + gfx::Rect intersect = gfx::IntersectRects(keyboard_rect_dips, |
| + screen_rect); |
| + host_->GetView()->SetInsets(gfx::Insets(0, 0, intersect.height(), 0)); |
| + host_->ScrollFocusedEditableNodeIntoRect(intersect); |
| + } else { |
| + // Restore the viewport. |
| + host_->GetView()->SetInsets(gfx::Insets()); |
| + } |
| + } |
| + } |
| + |
| + void OnKeyboardHidden(const gfx::Rect& keyboard_rect_dips) override { |
| + DCHECK(host_); |
| + // Restore the viewport. |
| + if (host_ && host_->GetView()) |
| + host_->GetView()->SetInsets(gfx::Insets()); |
| + } |
| + |
| + private: |
| + RenderWidgetHostImpl* host_; |
| + // The location in DIPs where the touch occurred. |
| + gfx::Point location_in_dips_; |
| + // The current device scale factor. |
| + float device_scale_factor_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WinScreenKeyboardObserver); |
| +}; |
| +#endif |
| + |
| } // namespace |
| // We need to watch for mouse events outside a Web Popup or its parent |
| @@ -383,6 +474,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host, |
| #if defined(OS_WIN) |
| legacy_render_widget_host_HWND_(nullptr), |
| legacy_window_destroyed_(false), |
| + virtual_keyboard_requested_(false), |
| #endif |
| has_snapped_to_boundary_(false), |
| is_guest_view_hack_(is_guest_view_hack), |
| @@ -864,6 +956,29 @@ void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) { |
| } |
| } |
| +void RenderWidgetHostViewAura::FocusedNodeTouched( |
| + const gfx::Point& location_dips, |
| + bool editable) { |
| +#if defined(OS_WIN) |
| + RenderViewHost* rvh = RenderViewHost::From(host_); |
| + if (rvh && rvh->GetDelegate()) |
| + rvh->GetDelegate()->SetIsVirtualKeyboardRequested(editable); |
| + |
| + ui::OnScreenKeyboardDisplayManager* osk_display_manager = |
| + ui::OnScreenKeyboardDisplayManager::GetInstance(); |
|
ncarter (slow)
2016/05/19 17:45:55
Indent += 2
ananta
2016/05/19 19:33:38
Done.
|
| + DCHECK(osk_display_manager); |
| + if (editable) { |
| + keyboard_observer_.reset(new WinScreenKeyboardObserver(host_, |
| + location_dips, device_scale_factor_)); |
| + virtual_keyboard_requested_ = osk_display_manager->DisplayVirtualKeyboard( |
| + keyboard_observer_.get()); |
| + } else { |
| + virtual_keyboard_requested_ = false; |
| + osk_display_manager->DismissVirtualKeyboard(); |
| + } |
| +#endif |
| +} |
| + |
| void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) { |
| current_cursor_ = cursor; |
| const display::Display display = |
| @@ -2003,6 +2118,23 @@ void RenderWidgetHostViewAura::TransformPointToLocalCoordSpace( |
| gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point); |
| } |
| +void RenderWidgetHostViewAura::FocusedNodeChanged(bool editable) { |
| +#if defined(OS_WIN) |
| + if (!editable && virtual_keyboard_requested_) { |
| + virtual_keyboard_requested_ = false; |
| + |
| + RenderViewHost* rvh = RenderViewHost::From(host_); |
| + if (rvh && rvh->GetDelegate()) |
| + rvh->GetDelegate()->SetIsVirtualKeyboardRequested(false); |
| + |
| + BrowserThread::PostDelayedTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(base::IgnoreResult(&DismissVirtualKeyboardTask)), |
|
ncarter (slow)
2016/05/19 17:45:55
IgnoreResult shouldn't be necessary -- this functi
ananta
2016/05/19 19:33:37
Done.
|
| + base::TimeDelta::FromMilliseconds(kVirtualKeyboardDisplayWaitTimeoutMs)); |
|
ncarter (slow)
2016/05/19 17:45:54
This indentation looks off (git cl format?)
ananta
2016/05/19 19:33:37
Done.
|
| + } |
| +#endif |
| +} |
| + |
| void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) { |
| TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent"); |