Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: chrome/browser/ui/touch/frame/touch_browser_frame_view.cc

Issue 7217008: Use input method to control visibility of virtual keyboard (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Update Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/ui/touch/frame/touch_browser_frame_view.h" 5 #include "chrome/browser/ui/touch/frame/touch_browser_frame_view.h"
6 6
7 #include "chrome/browser/profiles/profile.h" 7 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/browser/renderer_host/render_widget_host_view_views.h" 8 #include "chrome/browser/renderer_host/render_widget_host_view_views.h"
9 #include "chrome/browser/tabs/tab_strip_model.h"
10 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
12 #include "chrome/browser/ui/touch/frame/keyboard_container_view.h" 10 #include "chrome/browser/ui/touch/frame/keyboard_container_view.h"
13 #include "chrome/browser/ui/views/frame/browser_view.h" 11 #include "chrome/browser/ui/views/frame/browser_view.h"
14 #include "chrome/browser/ui/views/tab_contents/tab_contents_view_touch.h"
15 #include "content/browser/renderer_host/render_view_host.h" 12 #include "content/browser/renderer_host/render_view_host.h"
16 #include "content/browser/tab_contents/navigation_controller.h"
17 #include "content/browser/tab_contents/tab_contents.h" 13 #include "content/browser/tab_contents/tab_contents.h"
18 #include "content/browser/tab_contents/tab_contents_view.h"
19 #include "content/common/notification_service.h" 14 #include "content/common/notification_service.h"
20 #include "content/common/notification_type.h" 15 #include "content/common/notification_type.h"
21 #include "content/common/view_messages.h" 16 #include "content/common/view_messages.h"
22 #include "ui/base/animation/slide_animation.h" 17 #include "ui/base/animation/slide_animation.h"
23 #include "ui/gfx/rect.h" 18 #include "ui/gfx/rect.h"
24 #include "ui/gfx/transform.h" 19 #include "ui/gfx/transform.h"
25 #include "views/controls/button/image_button.h" 20 #include "views/controls/button/image_button.h"
26 #include "views/controls/textfield/textfield.h"
27 #include "views/focus/focus_manager.h"
28 21
29 #if defined(OS_CHROMEOS) 22 #if defined(OS_CHROMEOS)
30 #include "chrome/browser/chromeos/cros/cros_library.h" 23 #include "chrome/browser/chromeos/cros/cros_library.h"
31 #include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h" 24 #include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h"
32 #endif 25 #endif
33 26
34 namespace { 27 namespace {
35 28
36 const int kDefaultKeyboardHeight = 300; 29 const int kDefaultKeyboardHeight = 300;
37 const int kKeyboardSlideDuration = 300; // In milliseconds 30 const int kKeyboardSlideDuration = 300; // In milliseconds
38 31
39 PropertyAccessor<bool>* GetFocusedStateAccessor() {
40 static PropertyAccessor<bool> state;
41 return &state;
42 }
43
44 bool TabContentsHasFocus(const TabContents* contents) {
45 views::View* view = static_cast<TabContentsViewTouch*>(contents->view());
46 return view->Contains(view->GetFocusManager()->GetFocusedView());
47 }
48
49 } // namespace 32 } // namespace
50 33
51 // static 34 // static
52 const char TouchBrowserFrameView::kViewClassName[] = 35 const char TouchBrowserFrameView::kViewClassName[] =
53 "browser/ui/touch/frame/TouchBrowserFrameView"; 36 "browser/ui/touch/frame/TouchBrowserFrameView";
54 37
55 /////////////////////////////////////////////////////////////////////////////// 38 ///////////////////////////////////////////////////////////////////////////////
56 // TouchBrowserFrameView, public: 39 // TouchBrowserFrameView, public:
57 40
58 TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame, 41 TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame,
59 BrowserView* browser_view) 42 BrowserView* browser_view)
60 : OpaqueBrowserFrameView(frame, browser_view), 43 : OpaqueBrowserFrameView(frame, browser_view),
61 keyboard_showing_(false), 44 keyboard_showing_(false),
62 keyboard_height_(kDefaultKeyboardHeight), 45 keyboard_height_(kDefaultKeyboardHeight),
63 focus_listener_added_(false), 46 focus_listener_added_(false),
64 keyboard_(NULL) { 47 keyboard_(NULL) {
65 registrar_.Add(this, 48 registrar_.Add(this,
66 NotificationType::NAV_ENTRY_COMMITTED,
67 NotificationService::AllSources());
68 registrar_.Add(this,
69 NotificationType::FOCUS_CHANGED_IN_PAGE,
70 NotificationService::AllSources());
71 registrar_.Add(this,
72 NotificationType::TAB_CONTENTS_DESTROYED,
73 NotificationService::AllSources());
74 registrar_.Add(this,
75 NotificationType::HIDE_KEYBOARD_INVOKED, 49 NotificationType::HIDE_KEYBOARD_INVOKED,
76 NotificationService::AllSources()); 50 NotificationService::AllSources());
77 registrar_.Add(this, 51 registrar_.Add(this,
78 NotificationType::SET_KEYBOARD_HEIGHT_INVOKED, 52 NotificationType::SET_KEYBOARD_HEIGHT_INVOKED,
79 NotificationService::AllSources()); 53 NotificationService::AllSources());
80 54
81 browser_view->browser()->tabstrip_model()->AddObserver(this);
82
83 animation_.reset(new ui::SlideAnimation(this)); 55 animation_.reset(new ui::SlideAnimation(this));
84 animation_->SetTweenType(ui::Tween::LINEAR); 56 animation_->SetTweenType(ui::Tween::LINEAR);
85 animation_->SetSlideDuration(kKeyboardSlideDuration); 57 animation_->SetSlideDuration(kKeyboardSlideDuration);
86 58
87 #if defined(OS_CHROMEOS) 59 #if defined(OS_CHROMEOS)
88 chromeos::InputMethodLibrary* library = 60 chromeos::InputMethodLibrary* library =
89 chromeos::CrosLibrary::Get()->GetInputMethodLibrary(); 61 chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
90 library->AddVirtualKeyboardObserver(this); 62 library->AddVirtualKeyboardObserver(this);
91 #endif 63 #endif
92 } 64 }
93 65
94 TouchBrowserFrameView::~TouchBrowserFrameView() { 66 TouchBrowserFrameView::~TouchBrowserFrameView() {
95 browser_view()->browser()->tabstrip_model()->RemoveObserver(this);
96 } 67 }
97 68
98 std::string TouchBrowserFrameView::GetClassName() const { 69 std::string TouchBrowserFrameView::GetClassName() const {
99 return kViewClassName; 70 return kViewClassName;
100 } 71 }
101 72
102 void TouchBrowserFrameView::Layout() { 73 void TouchBrowserFrameView::Layout() {
103 OpaqueBrowserFrameView::Layout(); 74 OpaqueBrowserFrameView::Layout();
104 75
105 if (!keyboard_) 76 if (!keyboard_)
106 return; 77 return;
107 78
108 keyboard_->SetVisible(keyboard_showing_ || animation_->is_animating()); 79 keyboard_->SetVisible(keyboard_showing_ || animation_->is_animating());
109 gfx::Rect bounds = GetBoundsForReservedArea(); 80 gfx::Rect bounds = GetBoundsForReservedArea();
110 if (animation_->is_animating() && !keyboard_showing_) { 81 if (animation_->is_animating() && !keyboard_showing_) {
111 // The keyboard is in the process of hiding. So pretend it still has the 82 // The keyboard is in the process of hiding. So pretend it still has the
112 // same bounds as when the keyboard is visible. But 83 // same bounds as when the keyboard is visible. But
113 // |GetBoundsForReservedArea| should not take this into account so that the 84 // |GetBoundsForReservedArea| should not take this into account so that the
114 // render view gets the entire area to relayout itself. 85 // render view gets the entire area to relayout itself.
115 bounds.set_y(bounds.y() - keyboard_height_); 86 bounds.set_y(bounds.y() - keyboard_height_);
116 bounds.set_height(keyboard_height_); 87 bounds.set_height(keyboard_height_);
117 } 88 }
118 keyboard_->SetBoundsRect(bounds); 89 keyboard_->SetBoundsRect(bounds);
119 } 90 }
120 91
121 void TouchBrowserFrameView::FocusWillChange(views::View* focused_before,
122 views::View* focused_now) {
123 VirtualKeyboardType before = DecideKeyboardStateForView(focused_before);
124 VirtualKeyboardType now = DecideKeyboardStateForView(focused_now);
125 if (before != now) {
126 // TODO(varunjain): support other types of keyboard.
127 UpdateKeyboardAndLayout(now == GENERIC);
128 }
129 }
130
131 /////////////////////////////////////////////////////////////////////////////// 92 ///////////////////////////////////////////////////////////////////////////////
132 // TouchBrowserFrameView, protected: 93 // TouchBrowserFrameView, protected:
133 94
134 int TouchBrowserFrameView::GetReservedHeight() const { 95 int TouchBrowserFrameView::GetReservedHeight() const {
135 return keyboard_showing_ ? keyboard_height_ : 0; 96 return keyboard_showing_ ? keyboard_height_ : 0;
136 } 97 }
137 98
138 void TouchBrowserFrameView::ViewHierarchyChanged(bool is_add, 99 void TouchBrowserFrameView::ViewHierarchyChanged(bool is_add,
139 View* parent, 100 View* parent,
140 View* child) { 101 View* child) {
141 OpaqueBrowserFrameView::ViewHierarchyChanged(is_add, parent, child); 102 OpaqueBrowserFrameView::ViewHierarchyChanged(is_add, parent, child);
142 if (!GetFocusManager()) 103 views::InputMethod* input_method = GetInputMethod();
104 if (!input_method)
143 return; 105 return;
144 106
145 if (is_add && !focus_listener_added_) { 107 if (is_add && !focus_listener_added_) {
146 // Add focus listener when this view is added to the hierarchy. 108 // Add focus listener when this view is added to the hierarchy.
147 GetFocusManager()->AddFocusChangeListener(this); 109 input_method->AddTextInputTypeChangedListener(this);
148 focus_listener_added_ = true; 110 focus_listener_added_ = true;
111 UpdateKeyboard(input_method->GetTextInputType());
149 } else if (!is_add && focus_listener_added_) { 112 } else if (!is_add && focus_listener_added_) {
150 // Remove focus listener when this view is removed from the hierarchy. 113 // Remove focus listener when this view is removed from the hierarchy.
151 GetFocusManager()->RemoveFocusChangeListener(this); 114 input_method->RemoveTextInputTypeChangedListener(this);
152 focus_listener_added_ = false; 115 focus_listener_added_ = false;
116 UpdateKeyboardAndLayout(false);
153 } 117 }
154 } 118 }
155 119
156 /////////////////////////////////////////////////////////////////////////////// 120 ///////////////////////////////////////////////////////////////////////////////
157 // TouchBrowserFrameView, private: 121 // TouchBrowserFrameView, private:
158 122
159 void TouchBrowserFrameView::InitVirtualKeyboard() { 123 void TouchBrowserFrameView::InitVirtualKeyboard() {
160 if (keyboard_) 124 if (keyboard_)
161 return; 125 return;
162 126
163 Profile* keyboard_profile = browser_view()->browser()->profile(); 127 Profile* keyboard_profile = browser_view()->browser()->profile();
164 DCHECK(keyboard_profile) << "Profile required for virtual keyboard."; 128 DCHECK(keyboard_profile) << "Profile required for virtual keyboard.";
165 129
166 keyboard_ = new KeyboardContainerView(keyboard_profile, 130 keyboard_ = new KeyboardContainerView(keyboard_profile,
167 browser_view()->browser()); 131 browser_view()->browser());
168 keyboard_->SetVisible(false); 132 keyboard_->SetVisible(false);
169 AddChildView(keyboard_); 133 AddChildView(keyboard_);
170 } 134 }
171 135
136 void TouchBrowserFrameView::UpdateKeyboard(ui::TextInputType type) {
137 switch (type) {
138 case ui::TEXT_INPUT_TYPE_NONE:
139 UpdateKeyboardAndLayout(false);
140 return;
141 case ui::TEXT_INPUT_TYPE_TEXT:
142 case ui::TEXT_INPUT_TYPE_PASSWORD:
143 default:
144 // TODO(penghuang): pass the input type to virtual keyboard.
145 UpdateKeyboardAndLayout(true);
146 return;
147 }
148 }
149
172 void TouchBrowserFrameView::UpdateKeyboardAndLayout(bool should_show_keyboard) { 150 void TouchBrowserFrameView::UpdateKeyboardAndLayout(bool should_show_keyboard) {
173 if (should_show_keyboard) 151 if (should_show_keyboard)
174 InitVirtualKeyboard(); 152 InitVirtualKeyboard();
175 153
176 if (should_show_keyboard == keyboard_showing_) 154 if (should_show_keyboard == keyboard_showing_)
177 return; 155 return;
178 156
179 DCHECK(keyboard_); 157 DCHECK(keyboard_);
180 158
181 keyboard_showing_ = should_show_keyboard; 159 keyboard_showing_ = should_show_keyboard;
(...skipping 10 matching lines...) Expand all
192 animation_->Show(); 170 animation_->Show();
193 } else { 171 } else {
194 animation_->Hide(); 172 animation_->Hide();
195 173
196 browser_view()->set_clip_y(ui::Tween::ValueBetween( 174 browser_view()->set_clip_y(ui::Tween::ValueBetween(
197 animation_->GetCurrentValue(), 0, keyboard_height_)); 175 animation_->GetCurrentValue(), 0, keyboard_height_));
198 parent()->Layout(); 176 parent()->Layout();
199 } 177 }
200 } 178 }
201 179
202 TouchBrowserFrameView::VirtualKeyboardType
203 TouchBrowserFrameView::DecideKeyboardStateForView(views::View* view) {
204 if (!view)
205 return NONE;
206
207 std::string cname = view->GetClassName();
208 if (cname == views::Textfield::kViewClassName) {
209 return GENERIC;
210 } else if (cname == RenderWidgetHostViewViews::kViewClassName) {
211 TabContents* contents = browser_view()->browser()->GetSelectedTabContents();
212 bool* editable = contents ? GetFocusedStateAccessor()->GetProperty(
213 contents->property_bag()) : NULL;
214 if (editable && *editable)
215 return GENERIC;
216 }
217 return NONE;
218 }
219
220 bool TouchBrowserFrameView::HitTest(const gfx::Point& point) const { 180 bool TouchBrowserFrameView::HitTest(const gfx::Point& point) const {
221 if (OpaqueBrowserFrameView::HitTest(point)) 181 if (OpaqueBrowserFrameView::HitTest(point))
222 return true; 182 return true;
223 183
224 if (close_button()->IsVisible() && 184 if (close_button()->IsVisible() &&
225 close_button()->GetMirroredBounds().Contains(point)) 185 close_button()->GetMirroredBounds().Contains(point))
226 return true; 186 return true;
227 if (restore_button()->IsVisible() && 187 if (restore_button()->IsVisible() &&
228 restore_button()->GetMirroredBounds().Contains(point)) 188 restore_button()->GetMirroredBounds().Contains(point))
229 return true; 189 return true;
230 if (maximize_button()->IsVisible() && 190 if (maximize_button()->IsVisible() &&
231 maximize_button()->GetMirroredBounds().Contains(point)) 191 maximize_button()->GetMirroredBounds().Contains(point))
232 return true; 192 return true;
233 if (minimize_button()->IsVisible() && 193 if (minimize_button()->IsVisible() &&
234 minimize_button()->GetMirroredBounds().Contains(point)) 194 minimize_button()->GetMirroredBounds().Contains(point))
235 return true; 195 return true;
236 196
237 return false; 197 return false;
238 } 198 }
239 199
240 void TouchBrowserFrameView::ActiveTabChanged(TabContentsWrapper* old_contents,
241 TabContentsWrapper* new_contents,
242 int index,
243 bool user_gesture) {
244 if (new_contents == old_contents)
245 return;
246
247 TabContents* contents = new_contents->tab_contents();
248 if (!TabContentsHasFocus(contents))
249 return;
250
251 bool* editable = GetFocusedStateAccessor()->GetProperty(
252 contents->property_bag());
253 UpdateKeyboardAndLayout(editable ? *editable : false);
254 }
255
256 void TouchBrowserFrameView::TabStripEmpty() {
257 if (animation_->is_animating()) {
258 // Reset the delegate so the AnimationEnded callback doesn't trigger.
259 animation_->set_delegate(NULL);
260 animation_->Stop();
261 }
262 }
263
264 void TouchBrowserFrameView::Observe(NotificationType type, 200 void TouchBrowserFrameView::Observe(NotificationType type,
265 const NotificationSource& source, 201 const NotificationSource& source,
266 const NotificationDetails& details) { 202 const NotificationDetails& details) {
267 Browser* browser = browser_view()->browser(); 203 switch (type.value) {
268 if (type == NotificationType::FOCUS_CHANGED_IN_PAGE) { 204 case NotificationType::HIDE_KEYBOARD_INVOKED:
269 // Only modify the keyboard state if the currently active tab sent the 205 UpdateKeyboardAndLayout(false);
270 // notification. 206 return;
271 const TabContents* current_tab = browser->GetSelectedTabContents(); 207 case NotificationType::SET_KEYBOARD_HEIGHT_INVOKED: {
272 TabContents* source_tab = Source<TabContents>(source).ptr(); 208 // TODO(penghuang) Allow extension conrtol the virtual keyboard directly
273 const bool editable = *Details<const bool>(details).ptr(); 209 // instead of using Notification.
274 210 int height = *reinterpret_cast<int*>(details.map_key());
275 if (current_tab == source_tab && TabContentsHasFocus(source_tab)) 211 if (height != keyboard_height_) {
276 UpdateKeyboardAndLayout(editable); 212 DCHECK_GE(height, 0) << "Height of the keyboard is less than 0.";
277 213 DCHECK_LE(height, View::height()) << "Height of the keyboard is greater"
278 // Save the state of the focused field so that the keyboard visibility 214 " than the height of frame view.";
bryeung 2011/06/22 01:56:02 Is the IME TextInputTypeChanged notification someh
Peng 2011/06/22 04:17:39 Yes. But currently it only supports three types (N
279 // can be determined after tab switching. 215 keyboard_height_ = height;
280 GetFocusedStateAccessor()->SetProperty( 216 parent()->Layout();
281 source_tab->property_bag(), editable);
282 } else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
283 NavigationController* controller =
284 Source<NavigationController>(source).ptr();
285 Browser* source_browser = Browser::GetBrowserForController(
286 controller, NULL);
287
288 // If the Browser for the keyboard has navigated, re-evaluate the visibility
289 // of the keyboard.
290 TouchBrowserFrameView::VirtualKeyboardType keyboard_type = NONE;
291 views::View* view = GetFocusManager()->GetFocusedView();
292 if (view) {
293 if (view->GetClassName() == views::Textfield::kViewClassName)
294 keyboard_type = GENERIC;
295 if (view->GetClassName() == RenderWidgetHostViewViews::kViewClassName) {
296 // Reset the state of the focused field in the current tab.
297 GetFocusedStateAccessor()->SetProperty(
298 controller->tab_contents()->property_bag(), false);
299 } 217 }
218 return;
300 } 219 }
301 if (source_browser == browser) 220 default:
302 UpdateKeyboardAndLayout(keyboard_type == GENERIC); 221 OpaqueBrowserFrameView::Observe(type, source, details);
303 } else if (type == NotificationType::TAB_CONTENTS_DESTROYED) { 222 return;
304 GetFocusedStateAccessor()->DeleteProperty(
305 Source<TabContents>(source).ptr()->property_bag());
306 } else if (type == NotificationType::PREF_CHANGED) {
307 OpaqueBrowserFrameView::Observe(type, source, details);
308 } else if (type == NotificationType::HIDE_KEYBOARD_INVOKED) {
309 TabContents* tab_contents =
310 browser_view()->browser()->GetSelectedTabContents();
311 if (tab_contents) {
312 GetFocusedStateAccessor()->SetProperty(tab_contents->property_bag(),
313 false);
314 }
315 UpdateKeyboardAndLayout(false);
316 } else if (type == NotificationType::SET_KEYBOARD_HEIGHT_INVOKED) {
317 // TODO(penghuang) Allow extension conrtol the virtual keyboard directly
318 // instead of using Notification.
319 int height = *reinterpret_cast<int*>(details.map_key());
320 if (height != keyboard_height_) {
321 DCHECK_GE(height, 0) << "Height of the keyboard is less than 0.";
322 DCHECK_LE(height, View::height()) << "Height of the keyboard is greater "
323 "than the height of frame view.";
324 keyboard_height_ = height;
325 parent()->Layout();
326 }
327 } 223 }
328 } 224 }
329 225
330 /////////////////////////////////////////////////////////////////////////////// 226 ///////////////////////////////////////////////////////////////////////////////
331 // ui::AnimationDelegate implementation 227 // ui::AnimationDelegate implementation
332 void TouchBrowserFrameView::AnimationProgressed(const ui::Animation* anim) { 228 void TouchBrowserFrameView::AnimationProgressed(const ui::Animation* anim) {
333 ui::Transform transform; 229 ui::Transform transform;
334 transform.SetTranslateY( 230 transform.SetTranslateY(
335 ui::Tween::ValueBetween(anim->GetCurrentValue(), keyboard_height_, 0)); 231 ui::Tween::ValueBetween(anim->GetCurrentValue(), keyboard_height_, 0));
336 keyboard_->SetTransform(transform); 232 keyboard_->SetTransform(transform);
(...skipping 28 matching lines...) Expand all
365 const chromeos::input_method::VirtualKeyboard& virtual_keyboard, 261 const chromeos::input_method::VirtualKeyboard& virtual_keyboard,
366 const std::string& virtual_keyboard_layout) { 262 const std::string& virtual_keyboard_layout) {
367 if (!keyboard_) 263 if (!keyboard_)
368 return; 264 return;
369 265
370 const GURL& url = virtual_keyboard.GetURLForLayout(virtual_keyboard_layout); 266 const GURL& url = virtual_keyboard.GetURLForLayout(virtual_keyboard_layout);
371 keyboard_->LoadURL(url); 267 keyboard_->LoadURL(url);
372 VLOG(1) << "VirtualKeyboardChanged: Switched to " << url.spec(); 268 VLOG(1) << "VirtualKeyboardChanged: Switched to " << url.spec();
373 } 269 }
374 #endif 270 #endif
271
272 ///////////////////////////////////////////////////////////////////////////////
273 // views::TextInputTypeChangedListener implementation
274 void TouchBrowserFrameView::TextInputTypeChanged(
275 views::View* view, ui::TextInputType type) {
276 UpdateKeyboard(type);
277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698