OLD | NEW |
---|---|
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/chromeos/login/touch_login_view.h" | 5 #include "chrome/browser/chromeos/login/touch_login_view.h" |
6 | 6 |
7 #include "chrome/browser/renderer_host/render_widget_host_view_views.h" | 7 #include "chrome/browser/ui/touch/keyboard/keyboard_manager.h" |
8 #include "chrome/browser/ui/touch/frame/keyboard_container_view.h" | |
9 #include "chrome/browser/ui/views/tab_contents/tab_contents_view_touch.h" | |
10 #include "chrome/browser/ui/views/dom_view.h" | |
11 #include "content/browser/tab_contents/tab_contents.h" | |
12 #include "content/common/notification_service.h" | |
13 #include "ui/base/animation/slide_animation.h" | |
14 #include "ui/gfx/transform.h" | |
15 #include "views/controls/textfield/textfield.h" | |
16 #include "views/widget/widget.h" | |
17 | |
18 namespace { | |
19 | |
20 const char kViewClassName[] = "browser/chromeos/login/TouchLoginView"; | |
21 const int kDefaultKeyboardHeight = 300; | |
22 const int kKeyboardSlideDuration = 300; // In milliseconds | |
23 | |
24 PropertyAccessor<bool>* GetFocusedStateAccessor() { | |
25 static PropertyAccessor<bool> state; | |
26 return &state; | |
27 } | |
28 | |
29 bool TabContentsHasFocus(const TabContents* contents) { | |
30 views::View* view = static_cast<TabContentsViewTouch*>(contents->view()); | |
31 return view->Contains(view->GetFocusManager()->GetFocusedView()); | |
32 } | |
33 | |
34 } // namespace | |
35 | 8 |
36 namespace chromeos { | 9 namespace chromeos { |
37 | 10 |
38 // TouchLoginView public: ------------------------------------------------------ | 11 // TouchLoginView public: ------------------------------------------------------ |
39 | 12 |
40 TouchLoginView::TouchLoginView() | 13 TouchLoginView::TouchLoginView() |
41 : WebUILoginView(), | 14 : WebUILoginView() { |
42 keyboard_showing_(false), | 15 KeyboardManager::GetInstance(); |
sadrul
2011/07/06 15:41:19
@sky: I agree with the bryeung that having TouchLo
sky
2011/07/06 16:07:01
SGTM
sadrul
2011/07/06 16:40:12
Done. Thanks!
| |
43 keyboard_height_(kDefaultKeyboardHeight), | |
44 focus_listener_added_(false), | |
45 keyboard_(NULL) { | |
46 } | 16 } |
47 | 17 |
48 TouchLoginView::~TouchLoginView() { | 18 TouchLoginView::~TouchLoginView() { |
49 } | 19 } |
50 | 20 |
51 void TouchLoginView::Init() { | |
52 WebUILoginView::Init(); | |
53 InitVirtualKeyboard(); | |
54 | |
55 registrar_.Add(this, | |
56 NotificationType::FOCUS_CHANGED_IN_PAGE, | |
57 NotificationService::AllSources()); | |
58 registrar_.Add(this, | |
59 NotificationType::TAB_CONTENTS_DESTROYED, | |
60 NotificationService::AllSources()); | |
61 registrar_.Add(this, | |
62 NotificationType::HIDE_KEYBOARD_INVOKED, | |
63 NotificationService::AllSources()); | |
64 registrar_.Add(this, | |
65 NotificationType::SET_KEYBOARD_HEIGHT_INVOKED, | |
66 NotificationService::AllSources()); | |
67 } | |
68 | |
69 std::string TouchLoginView::GetClassName() const { | |
70 return kViewClassName; | |
71 } | |
72 | |
73 void TouchLoginView::FocusWillChange(views::View* focused_before, | |
74 views::View* focused_now) { | |
75 VirtualKeyboardType before = DecideKeyboardStateForView(focused_before); | |
76 VirtualKeyboardType now = DecideKeyboardStateForView(focused_now); | |
77 if (before != now) { | |
78 // TODO(varunjain): support other types of keyboard. | |
79 UpdateKeyboardAndLayout(now == GENERIC); | |
80 } | |
81 } | |
82 | |
83 // TouchLoginView protected: --------------------------------------------------- | |
84 | |
85 void TouchLoginView::Layout() { | |
86 WebUILoginView::Layout(); | |
87 if (!keyboard_) | |
88 return; | |
89 | |
90 // We are not resizing the DOMView here, so the keyboard is going to occlude | |
91 // the login screen partially. It is the responsibility of the UX layer to | |
92 // handle this. | |
93 | |
94 // Lastly layout the keyboard | |
95 bool display_keyboard = (keyboard_showing_ || animation_->is_animating()); | |
96 keyboard_->SetVisible(display_keyboard); | |
97 gfx::Rect keyboard_bounds = bounds(); | |
98 int keyboard_height = display_keyboard ? keyboard_height_ : 0; | |
99 keyboard_bounds.set_y(keyboard_bounds.height() - keyboard_height); | |
100 keyboard_bounds.set_height(keyboard_height); | |
101 keyboard_->SetBoundsRect(keyboard_bounds); | |
102 } | |
103 | |
104 // TouchLoginView private: ----------------------------------------------------- | |
105 | |
106 void TouchLoginView::InitVirtualKeyboard() { | |
107 keyboard_ = new KeyboardContainerView(profile_, NULL); | |
108 keyboard_->SetVisible(false); | |
109 AddChildView(keyboard_); | |
110 | |
111 animation_.reset(new ui::SlideAnimation(this)); | |
112 animation_->SetTweenType(ui::Tween::LINEAR); | |
113 animation_->SetSlideDuration(kKeyboardSlideDuration); | |
114 } | |
115 | |
116 void TouchLoginView::UpdateKeyboardAndLayout(bool should_show_keyboard) { | |
117 DCHECK(keyboard_); | |
118 if (should_show_keyboard == keyboard_showing_) | |
119 return; | |
120 keyboard_showing_ = should_show_keyboard; | |
121 if (keyboard_showing_) { | |
122 ui::Transform transform; | |
123 transform.SetTranslateY(-keyboard_height_); | |
124 keyboard_->SetTransform(transform); | |
125 Layout(); | |
126 animation_->Show(); | |
127 } else { | |
128 ui::Transform transform; | |
129 keyboard_->SetTransform(transform); | |
130 animation_->Hide(); | |
131 Layout(); | |
132 } | |
133 } | |
134 | |
135 TouchLoginView::VirtualKeyboardType | |
136 TouchLoginView::DecideKeyboardStateForView(views::View* view) { | |
137 if (!view) | |
138 return NONE; | |
139 | |
140 std::string cname = view->GetClassName(); | |
141 if (cname == views::Textfield::kViewClassName) { | |
142 return GENERIC; | |
143 } else if (cname == RenderWidgetHostViewViews::kViewClassName) { | |
144 TabContents* contents = webui_login_->tab_contents(); | |
145 bool* editable = contents ? GetFocusedStateAccessor()->GetProperty( | |
146 contents->property_bag()) : NULL; | |
147 if (editable && *editable) | |
148 return GENERIC; | |
149 } | |
150 return NONE; | |
151 } | |
152 | |
153 void TouchLoginView::Observe(NotificationType type, | |
154 const NotificationSource& source, | |
155 const NotificationDetails& details) { | |
156 if (type == NotificationType::FOCUS_CHANGED_IN_PAGE) { | |
157 // Only modify the keyboard state if the currently active tab sent the | |
158 // notification. | |
159 const TabContents* current_tab = webui_login_->tab_contents(); | |
160 TabContents* source_tab = Source<TabContents>(source).ptr(); | |
161 const bool editable = *Details<const bool>(details).ptr(); | |
162 | |
163 if (current_tab == source_tab && TabContentsHasFocus(source_tab)) | |
164 UpdateKeyboardAndLayout(editable); | |
165 | |
166 // Save the state of the focused field so that the keyboard visibility | |
167 // can be determined after tab switching. | |
168 GetFocusedStateAccessor()->SetProperty( | |
169 source_tab->property_bag(), editable); | |
170 } else if (type == NotificationType::TAB_CONTENTS_DESTROYED) { | |
171 GetFocusedStateAccessor()->DeleteProperty( | |
172 Source<TabContents>(source).ptr()->property_bag()); | |
173 } else if (type == NotificationType::HIDE_KEYBOARD_INVOKED) { | |
174 UpdateKeyboardAndLayout(false); | |
175 } else if (type == NotificationType::SET_KEYBOARD_HEIGHT_INVOKED) { | |
176 // TODO(penghuang) Allow extension conrtol the virtual keyboard directly | |
177 // instead of using Notification. | |
178 int height = *(Details<int>(details).ptr()); | |
179 if (height != keyboard_height_) { | |
180 DCHECK_GE(height, 0) << "Height of the keyboard is less than 0."; | |
181 DCHECK_LE(height, View::height()) << "Height of the keyboard is greater " | |
182 "than the height of containing view."; | |
183 keyboard_height_ = height; | |
184 Layout(); | |
185 } | |
186 } | |
187 } | |
188 | |
189 // ui::AnimationDelegate implementation ---------------------------------------- | |
190 | |
191 void TouchLoginView::AnimationProgressed(const ui::Animation* anim) { | |
192 ui::Transform transform; | |
193 transform.SetTranslateY( | |
194 ui::Tween::ValueBetween(anim->GetCurrentValue(), keyboard_height_, 0)); | |
195 keyboard_->SetTransform(transform); | |
196 } | |
197 | |
198 void TouchLoginView::AnimationEnded(const ui::Animation* animation) { | |
199 if (keyboard_showing_) { | |
200 Layout(); | |
201 } else { | |
202 // Notify the keyboard that it is hidden now. | |
203 keyboard_->SetVisible(false); | |
204 } | |
205 } | |
206 | |
207 } // namespace chromeos | 21 } // namespace chromeos |
OLD | NEW |