touch_browser_frame_view.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/touch/frame/touch_browser_frame_view.h"
6
7#include <algorithm>
8
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/renderer_host/render_view_host.h"
11#include "chrome/browser/renderer_host/site_instance.h"
12#include "chrome/browser/tab_contents/navigation_controller.h"
13#include "chrome/browser/tab_contents/tab_contents.h"
14#include "chrome/browser/ui/browser.h"
15#include "chrome/browser/ui/views/dom_view.h"
16#include "chrome/browser/ui/views/frame/browser_view.h"
17#include "chrome/common/notification_service.h"
18#include "chrome/common/notification_type.h"
19#include "chrome/common/url_constants.h"
20#include "gfx/rect.h"
21
22namespace {
23
24const int kKeyboardHeight = 300;
25
26}  // namespace
27
28///////////////////////////////////////////////////////////////////////////////
29// TouchBrowserFrameView, public:
30
31TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame,
32                                             BrowserView* browser_view)
33    : OpaqueBrowserFrameView(frame, browser_view),
34      keyboard_showing_(false),
35      keyboard_(NULL) {
36  registrar_.Add(this,
37                 NotificationType::NAV_ENTRY_COMMITTED,
38                 NotificationService::AllSources());
39  registrar_.Add(this,
40                 NotificationType::FOCUS_CHANGED_IN_PAGE,
41                 NotificationService::AllSources());
42}
43
44TouchBrowserFrameView::~TouchBrowserFrameView() {
45}
46
47void TouchBrowserFrameView::Layout() {
48  OpaqueBrowserFrameView::Layout();
49
50  if (!keyboard_)
51    return;
52
53  keyboard_->SetBounds(GetBoundsForReservedArea());
54  keyboard_->SetVisible(keyboard_showing_);
55  keyboard_->Layout();
56}
57
58///////////////////////////////////////////////////////////////////////////////
59// TouchBrowserFrameView, protected:
60int TouchBrowserFrameView::GetReservedHeight() const {
61  if (keyboard_showing_)
62    return kKeyboardHeight;
63
64  return 0;
65}
66
67///////////////////////////////////////////////////////////////////////////////
68// TouchBrowserFrameView, private:
69
70void TouchBrowserFrameView::InitVirtualKeyboard() {
71  if (keyboard_)
72    return;
73
74  keyboard_ = new DOMView;
75
76  Profile* keyboard_profile = browser_view()->browser()->profile();
77  DCHECK(keyboard_profile) << "Profile required for virtual keyboard.";
78
79  GURL keyboard_url(chrome::kChromeUIKeyboardURL);
80  keyboard_->Init(keyboard_profile,
81      SiteInstance::CreateSiteInstanceForURL(keyboard_profile, keyboard_url));
82  keyboard_->LoadURL(keyboard_url);
83
84  keyboard_->SetVisible(false);
85  AddChildView(keyboard_);
86}
87
88void TouchBrowserFrameView::UpdateKeyboardAndLayout(bool should_show_keyboard) {
89  if (should_show_keyboard)
90    InitVirtualKeyboard();
91
92  if (should_show_keyboard == keyboard_showing_)
93    return;
94
95  DCHECK(keyboard_);
96
97  keyboard_showing_ = should_show_keyboard;
98
99  // Because the NonClientFrameView is a sibling of the ClientView, we rely on
100  // the parent to resize the ClientView instead of resizing it directly.
101  GetParent()->Layout();
102
103  // The keyboard that pops up may end up hiding the text entry. So make sure
104  // the renderer scrolls when necessary to keep the textfield visible.
105  if (keyboard_showing_) {
106    RenderViewHost* host =
107        browser_view()->browser()->GetSelectedTabContents()->render_view_host();
108    host->ScrollFocusedEditableNodeIntoView();
109  }
110}
111
112void TouchBrowserFrameView::Observe(NotificationType type,
113                                    const NotificationSource& source,
114                                    const NotificationDetails& details) {
115  Browser* browser = browser_view()->browser();
116  if (type == NotificationType::FOCUS_CHANGED_IN_PAGE) {
117    // Only modify the keyboard state if the currently active tab sent the
118    // notification.
119    if (browser->GetSelectedTabContents()->render_view_host() ==
120        Source<RenderViewHost>(source).ptr()) {
121      UpdateKeyboardAndLayout(*Details<const bool>(details).ptr());
122    }
123  } else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
124    Browser* source_browser = Browser::GetBrowserForController(
125        Source<NavigationController>(source).ptr(), NULL);
126    // If the Browser for the keyboard has navigated, hide the keyboard.
127    if (source_browser == browser) {
128      UpdateKeyboardAndLayout(false);
129    }
130  }
131}
132