OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/keyboard/keyboard_controller.h" | 5 #include "ui/keyboard/keyboard_controller.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 30 matching lines...) Expand all Loading... | |
41 // The virtual keyboard show/hide animation duration. | 41 // The virtual keyboard show/hide animation duration. |
42 const int kShowAnimationDurationMs = 350; | 42 const int kShowAnimationDurationMs = 350; |
43 const int kHideAnimationDurationMs = 100; | 43 const int kHideAnimationDurationMs = 100; |
44 | 44 |
45 // The opacity of virtual keyboard container when show animation starts or | 45 // The opacity of virtual keyboard container when show animation starts or |
46 // hide animation finishes. This cannot be zero because we call Show() on the | 46 // hide animation finishes. This cannot be zero because we call Show() on the |
47 // keyboard window before setting the opacity back to 1.0. Since windows are not | 47 // keyboard window before setting the opacity back to 1.0. Since windows are not |
48 // allowed to be shown with zero opacity, we always animate to 0.01 instead. | 48 // allowed to be shown with zero opacity, we always animate to 0.01 instead. |
49 const float kAnimationStartOrAfterHideOpacity = 0.01f; | 49 const float kAnimationStartOrAfterHideOpacity = 0.01f; |
50 | 50 |
51 // Event targeter for the keyboard container. | |
52 class KeyboardContainerTargeter : public wm::MaskedWindowTargeter { | |
53 public: | |
54 KeyboardContainerTargeter(aura::Window* container, | |
55 keyboard::KeyboardControllerProxy* proxy) | |
56 : wm::MaskedWindowTargeter(container), | |
57 proxy_(proxy) { | |
58 } | |
59 | |
60 ~KeyboardContainerTargeter() override {} | |
61 | |
62 private: | |
63 // wm::MaskedWindowTargeter: | |
64 bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const override { | |
65 if (proxy_ && !proxy_->HasKeyboardWindow()) | |
66 return true; | |
67 gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() : | |
68 keyboard::DefaultKeyboardBoundsFromWindowBounds(window->bounds()); | |
69 mask->addRect(RectToSkRect(keyboard_bounds)); | |
70 return true; | |
71 } | |
72 | |
73 keyboard::KeyboardControllerProxy* proxy_; | |
74 | |
75 DISALLOW_COPY_AND_ASSIGN(KeyboardContainerTargeter); | |
76 }; | |
77 | |
78 // The KeyboardWindowDelegate makes sure the keyboard-window does not get focus. | 51 // The KeyboardWindowDelegate makes sure the keyboard-window does not get focus. |
79 // This is necessary to make sure that the synthetic key-events reach the target | 52 // This is necessary to make sure that the synthetic key-events reach the target |
80 // window. | 53 // window. |
81 // The delegate deletes itself when the window is destroyed. | 54 // The delegate deletes itself when the window is destroyed. |
82 class KeyboardWindowDelegate : public aura::WindowDelegate { | 55 class KeyboardWindowDelegate : public aura::WindowDelegate { |
83 public: | 56 public: |
84 explicit KeyboardWindowDelegate(keyboard::KeyboardControllerProxy* proxy) | 57 KeyboardWindowDelegate() {} |
85 : proxy_(proxy) {} | |
86 ~KeyboardWindowDelegate() override {} | 58 ~KeyboardWindowDelegate() override {} |
87 | 59 |
88 private: | 60 private: |
89 // Overridden from aura::WindowDelegate: | 61 // Overridden from aura::WindowDelegate: |
90 gfx::Size GetMinimumSize() const override { return gfx::Size(); } | 62 gfx::Size GetMinimumSize() const override { return gfx::Size(); } |
91 gfx::Size GetMaximumSize() const override { return gfx::Size(); } | 63 gfx::Size GetMaximumSize() const override { return gfx::Size(); } |
92 void OnBoundsChanged(const gfx::Rect& old_bounds, | 64 void OnBoundsChanged(const gfx::Rect& old_bounds, |
93 const gfx::Rect& new_bounds) override { | 65 const gfx::Rect& new_bounds) override {} |
94 bounds_ = new_bounds; | |
95 } | |
96 ui::TextInputClient* GetFocusedTextInputClient() override { | 66 ui::TextInputClient* GetFocusedTextInputClient() override { |
97 return nullptr; | 67 return nullptr; |
98 } | 68 } |
99 gfx::NativeCursor GetCursor(const gfx::Point& point) override { | 69 gfx::NativeCursor GetCursor(const gfx::Point& point) override { |
100 return gfx::kNullCursor; | 70 return gfx::kNullCursor; |
101 } | 71 } |
102 int GetNonClientComponent(const gfx::Point& point) const override { | 72 int GetNonClientComponent(const gfx::Point& point) const override { |
103 return HTNOWHERE; | 73 return HTNOWHERE; |
104 } | 74 } |
105 bool ShouldDescendIntoChildForEventHandling( | 75 bool ShouldDescendIntoChildForEventHandling( |
106 aura::Window* child, | 76 aura::Window* child, |
107 const gfx::Point& location) override { | 77 const gfx::Point& location) override { |
108 return true; | 78 return true; |
109 } | 79 } |
110 bool CanFocus() override { return false; } | 80 bool CanFocus() override { return false; } |
111 void OnCaptureLost() override {} | 81 void OnCaptureLost() override {} |
112 void OnPaint(gfx::Canvas* canvas) override {} | 82 void OnPaint(gfx::Canvas* canvas) override {} |
113 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} | 83 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} |
114 void OnWindowDestroying(aura::Window* window) override {} | 84 void OnWindowDestroying(aura::Window* window) override {} |
115 void OnWindowDestroyed(aura::Window* window) override { delete this; } | 85 void OnWindowDestroyed(aura::Window* window) override { delete this; } |
116 void OnWindowTargetVisibilityChanged(bool visible) override {} | 86 void OnWindowTargetVisibilityChanged(bool visible) override {} |
117 bool HasHitTestMask() const override { | 87 bool HasHitTestMask() const override { return false; } |
118 return !proxy_ || proxy_->HasKeyboardWindow(); | 88 void GetHitTestMask(gfx::Path* mask) const override {} |
119 } | |
120 void GetHitTestMask(gfx::Path* mask) const override { | |
121 if (proxy_ && !proxy_->HasKeyboardWindow()) | |
122 return; | |
123 gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() : | |
124 keyboard::DefaultKeyboardBoundsFromWindowBounds(bounds_); | |
125 mask->addRect(RectToSkRect(keyboard_bounds)); | |
126 } | |
127 | |
128 gfx::Rect bounds_; | |
129 keyboard::KeyboardControllerProxy* proxy_; | |
130 | 89 |
131 DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate); | 90 DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate); |
132 }; | 91 }; |
133 | 92 |
134 void ToggleTouchEventLogging(bool enable) { | 93 void ToggleTouchEventLogging(bool enable) { |
135 #if defined(OS_CHROMEOS) | 94 #if defined(OS_CHROMEOS) |
136 if (!base::SysInfo::IsRunningOnChromeOS()) | 95 if (!base::SysInfo::IsRunningOnChromeOS()) |
137 return; | 96 return; |
138 base::CommandLine command( | 97 base::CommandLine command( |
139 base::FilePath("/opt/google/touchscreen/toggle_touch_event_logging")); | 98 base::FilePath("/opt/google/touchscreen/toggle_touch_event_logging")); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 keyboard_mode_(FULL_WIDTH), | 206 keyboard_mode_(FULL_WIDTH), |
248 type_(ui::TEXT_INPUT_TYPE_NONE), | 207 type_(ui::TEXT_INPUT_TYPE_NONE), |
249 weak_factory_(this) { | 208 weak_factory_(this) { |
250 CHECK(proxy); | 209 CHECK(proxy); |
251 input_method_ = proxy_->GetInputMethod(); | 210 input_method_ = proxy_->GetInputMethod(); |
252 input_method_->AddObserver(this); | 211 input_method_->AddObserver(this); |
253 window_bounds_observer_.reset(new WindowBoundsChangeObserver()); | 212 window_bounds_observer_.reset(new WindowBoundsChangeObserver()); |
254 } | 213 } |
255 | 214 |
256 KeyboardController::~KeyboardController() { | 215 KeyboardController::~KeyboardController() { |
257 if (container_) | 216 if (container_) { |
217 if (container_->GetRootWindow()) | |
218 container_->GetRootWindow()->RemoveObserver(this); | |
258 container_->RemoveObserver(this); | 219 container_->RemoveObserver(this); |
220 } | |
259 if (input_method_) | 221 if (input_method_) |
260 input_method_->RemoveObserver(this); | 222 input_method_->RemoveObserver(this); |
261 ResetWindowInsets(); | 223 ResetWindowInsets(); |
262 } | 224 } |
263 | 225 |
264 // static | 226 // static |
265 void KeyboardController::ResetInstance(KeyboardController* controller) { | 227 void KeyboardController::ResetInstance(KeyboardController* controller) { |
266 if (instance_ && instance_ != controller) | 228 if (instance_ && instance_ != controller) |
267 delete instance_; | 229 delete instance_; |
268 instance_ = controller; | 230 instance_ = controller; |
269 } | 231 } |
270 | 232 |
271 // static | 233 // static |
272 KeyboardController* KeyboardController::GetInstance() { | 234 KeyboardController* KeyboardController::GetInstance() { |
273 return instance_; | 235 return instance_; |
274 } | 236 } |
275 | 237 |
276 aura::Window* KeyboardController::GetContainerWindow() { | 238 aura::Window* KeyboardController::GetContainerWindow() { |
277 if (!container_.get()) { | 239 if (!container_.get()) { |
278 container_.reset(new aura::Window( | 240 container_.reset(new aura::Window(new KeyboardWindowDelegate())); |
279 new KeyboardWindowDelegate(proxy_.get()))); | |
280 container_->SetEventTargeter(scoped_ptr<ui::EventTargeter>( | |
281 new KeyboardContainerTargeter(container_.get(), proxy_.get()))); | |
282 container_->SetName("KeyboardContainer"); | 241 container_->SetName("KeyboardContainer"); |
283 container_->set_owned_by_parent(false); | 242 container_->set_owned_by_parent(false); |
284 container_->Init(aura::WINDOW_LAYER_NOT_DRAWN); | 243 container_->Init(aura::WINDOW_LAYER_NOT_DRAWN); |
285 container_->AddObserver(this); | 244 container_->AddObserver(this); |
286 container_->SetLayoutManager(new KeyboardLayoutManager(this)); | 245 container_->SetLayoutManager(new KeyboardLayoutManager(this)); |
287 } | 246 } |
288 return container_.get(); | 247 return container_.get(); |
289 } | 248 } |
290 | 249 |
291 void KeyboardController::NotifyKeyboardBoundsChanging( | 250 void KeyboardController::NotifyKeyboardBoundsChanging( |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 set_lock_keyboard(lock); | 340 set_lock_keyboard(lock); |
382 ShowKeyboardInternal(); | 341 ShowKeyboardInternal(); |
383 } | 342 } |
384 | 343 |
385 void KeyboardController::OnWindowHierarchyChanged( | 344 void KeyboardController::OnWindowHierarchyChanged( |
386 const HierarchyChangeParams& params) { | 345 const HierarchyChangeParams& params) { |
387 if (params.new_parent && params.target == container_.get()) | 346 if (params.new_parent && params.target == container_.get()) |
388 OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); | 347 OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); |
389 } | 348 } |
390 | 349 |
350 void KeyboardController::OnWindowAddedToRootWindow(aura::Window* window) { | |
351 if (!window->GetRootWindow()->HasObserver(this)) | |
352 window->GetRootWindow()->AddObserver(this); | |
353 } | |
354 | |
355 void KeyboardController::OnWindowRemovingFromRootWindow(aura::Window* window, | |
356 aura::Window* new_root) { | |
357 if (window->GetRootWindow()->HasObserver(this)) | |
358 window->GetRootWindow()->RemoveObserver(this); | |
359 } | |
360 | |
361 void KeyboardController::OnWindowBoundsChanged(aura::Window* window, | |
362 const gfx::Rect& old_bounds, | |
363 const gfx::Rect& new_bounds) { | |
364 if (window->IsRootWindow()) { | |
sadrul
2015/04/07 17:35:51
early return if (!window->IsRootWindow()) instead
bshe
2015/04/07 18:46:15
Done.
| |
365 // Keep the same height when window resize. It gets called when screen | |
366 // rotate. | |
367 if (!keyboard_container_initialized() || !proxy_->HasKeyboardWindow()) | |
368 return; | |
369 | |
370 int container_height = container_->bounds().height(); | |
371 if (keyboard_mode_ == FULL_WIDTH) { | |
372 container_->SetBounds(gfx::Rect(new_bounds.x(), | |
373 new_bounds.bottom() - container_height, | |
374 new_bounds.width(), | |
375 container_height)); | |
376 } else if (keyboard_mode_ == FLOATING) { | |
377 // When screen rotate, horizontally center floating virtual keyboard | |
378 // window and vertically align it to the bottom. | |
379 int container_width = container_->bounds().width(); | |
380 container_->SetBounds(gfx::Rect( | |
381 new_bounds.x() + (new_bounds.width() - container_width) / 2, | |
382 new_bounds.bottom() - container_height, | |
383 container_width, | |
384 container_height)); | |
385 } | |
386 } | |
387 } | |
388 | |
391 void KeyboardController::Reload() { | 389 void KeyboardController::Reload() { |
392 if (proxy_->HasKeyboardWindow()) { | 390 if (proxy_->HasKeyboardWindow()) { |
393 // A reload should never try to show virtual keyboard. If keyboard is not | 391 // A reload should never try to show virtual keyboard. If keyboard is not |
394 // visible before reload, it should keep invisible after reload. | 392 // visible before reload, it should keep invisible after reload. |
395 show_on_resize_ = false; | 393 show_on_resize_ = false; |
396 proxy_->ReloadKeyboardIfNeeded(); | 394 proxy_->ReloadKeyboardIfNeeded(); |
397 } | 395 } |
398 } | 396 } |
399 | 397 |
400 void KeyboardController::OnTextInputStateChanged( | 398 void KeyboardController::OnTextInputStateChanged( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 const ui::InputMethod* input_method) { | 432 const ui::InputMethod* input_method) { |
435 DCHECK_EQ(input_method_, input_method); | 433 DCHECK_EQ(input_method_, input_method); |
436 input_method_ = NULL; | 434 input_method_ = NULL; |
437 } | 435 } |
438 | 436 |
439 void KeyboardController::OnShowImeIfNeeded() { | 437 void KeyboardController::OnShowImeIfNeeded() { |
440 ShowKeyboardInternal(); | 438 ShowKeyboardInternal(); |
441 } | 439 } |
442 | 440 |
443 bool KeyboardController::ShouldEnableInsets(aura::Window* window) { | 441 bool KeyboardController::ShouldEnableInsets(aura::Window* window) { |
444 aura::Window *keyboard_window = proxy_->GetKeyboardWindow(); | 442 aura::Window* keyboard_window = proxy_->GetKeyboardWindow(); |
445 return (keyboard_window->GetRootWindow() == window->GetRootWindow() && | 443 return (keyboard_window->GetRootWindow() == window->GetRootWindow() && |
446 keyboard::IsKeyboardOverscrollEnabled() && | 444 keyboard::IsKeyboardOverscrollEnabled() && |
447 proxy_->GetKeyboardWindow()->IsVisible() && | 445 keyboard_window->IsVisible() && keyboard_visible_); |
448 keyboard_visible_); | |
449 } | 446 } |
450 | 447 |
451 void KeyboardController::UpdateWindowInsets(aura::Window* window) { | 448 void KeyboardController::UpdateWindowInsets(aura::Window* window) { |
452 aura::Window *keyboard_window = proxy_->GetKeyboardWindow(); | 449 aura::Window* keyboard_window = proxy_->GetKeyboardWindow(); |
453 if (window == keyboard_window) | 450 if (window == keyboard_window) |
454 return; | 451 return; |
455 | 452 |
456 scoped_ptr<content::RenderWidgetHostIterator> widgets( | 453 scoped_ptr<content::RenderWidgetHostIterator> widgets( |
457 content::RenderWidgetHost::GetRenderWidgetHosts()); | 454 content::RenderWidgetHost::GetRenderWidgetHosts()); |
458 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) { | 455 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) { |
459 content::RenderWidgetHostView* view = widget->GetView(); | 456 content::RenderWidgetHostView* view = widget->GetView(); |
460 if (view && window->Contains(view->GetNativeView())) { | 457 if (view && window->Contains(view->GetNativeView())) { |
461 gfx::Rect window_bounds = view->GetNativeView()->GetBoundsInScreen(); | 458 gfx::Rect window_bounds = view->GetNativeView()->GetBoundsInScreen(); |
462 gfx::Rect intersect = gfx::IntersectRects(window_bounds, | 459 gfx::Rect intersect = |
463 proxy_->GetKeyboardWindow()->bounds()); | 460 gfx::IntersectRects(window_bounds, keyboard_window->bounds()); |
464 int overlap = ShouldEnableInsets(window) ? intersect.height() : 0; | 461 int overlap = ShouldEnableInsets(window) ? intersect.height() : 0; |
465 if (overlap > 0 && overlap < window_bounds.height()) | 462 if (overlap > 0 && overlap < window_bounds.height()) |
466 view->SetInsets(gfx::Insets(0, 0, overlap, 0)); | 463 view->SetInsets(gfx::Insets(0, 0, overlap, 0)); |
467 else | 464 else |
468 view->SetInsets(gfx::Insets()); | 465 view->SetInsets(gfx::Insets()); |
469 return; | 466 return; |
470 } | 467 } |
471 } | 468 } |
472 } | 469 } |
473 | 470 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 window_bounds_observer_->RemoveAllObservedWindows(); | 554 window_bounds_observer_->RemoveAllObservedWindows(); |
558 } | 555 } |
559 | 556 |
560 bool KeyboardController::WillHideKeyboard() const { | 557 bool KeyboardController::WillHideKeyboard() const { |
561 return weak_factory_.HasWeakPtrs(); | 558 return weak_factory_.HasWeakPtrs(); |
562 } | 559 } |
563 | 560 |
564 void KeyboardController::ShowAnimationFinished() { | 561 void KeyboardController::ShowAnimationFinished() { |
565 // Notify observers after animation finished to prevent reveal desktop | 562 // Notify observers after animation finished to prevent reveal desktop |
566 // background during animation. | 563 // background during animation. |
567 NotifyKeyboardBoundsChanging(proxy_->GetKeyboardWindow()->bounds()); | 564 NotifyKeyboardBoundsChanging(container_->bounds()); |
568 proxy_->EnsureCaretInWorkArea(); | 565 proxy_->EnsureCaretInWorkArea(); |
569 } | 566 } |
570 | 567 |
571 void KeyboardController::HideAnimationFinished() { | 568 void KeyboardController::HideAnimationFinished() { |
572 proxy_->HideKeyboardContainer(container_.get()); | 569 proxy_->HideKeyboardContainer(container_.get()); |
573 } | 570 } |
574 | 571 |
575 void KeyboardController::AddBoundsChangedObserver(aura::Window* window) { | 572 void KeyboardController::AddBoundsChangedObserver(aura::Window* window) { |
576 aura::Window* target_window = window ? window->GetToplevelWindow() : nullptr; | 573 aura::Window* target_window = window ? window->GetToplevelWindow() : nullptr; |
577 if (target_window) | 574 if (target_window) |
578 window_bounds_observer_->AddObservedWindow(target_window); | 575 window_bounds_observer_->AddObservedWindow(target_window); |
579 } | 576 } |
580 | 577 |
581 } // namespace keyboard | 578 } // namespace keyboard |
OLD | NEW |