172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/find_bar_host.h"
672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <algorithm>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/find_bar/find_bar_controller.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/find_bar/find_tab_helper.h"
1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/view_ids.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/find_bar_view.h"
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_view.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/keycodes/keyboard_codes.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/focus/external_focus_tracker.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/focus/view_storage.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser {
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Declared in browser_dialogs.h so others don't have to depend on our header.
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFindBar* CreateFindBar(BrowserView* browser_view) {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new FindBarHost(browser_view);
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace browser
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// FindBarHost, public:
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFindBarHost::FindBarHost(BrowserView* browser_view)
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : DropdownBarHost(browser_view),
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      find_bar_controller_(NULL) {
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Init(new FindBarView(this));
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFindBarHost::~FindBarHost() {
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool FindBarHost::MaybeForwardKeyEventToWebpage(
463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const views::KeyEvent& key_event) {
473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (!ShouldForwardKeyEventToWebpageNative(key_event)) {
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Native implementation says not to forward these events.
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  switch (key_event.key_code()) {
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case ui::VKEY_DOWN:
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case ui::VKEY_UP:
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case ui::VKEY_PRIOR:
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case ui::VKEY_NEXT:
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case ui::VKEY_HOME:
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case ui::VKEY_END:
603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      if (key_event.IsControlDown())
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Fall through.
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabContentsWrapper* contents = find_bar_controller_->tab_contents();
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!contents)
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  RenderViewHost* render_view_host = contents->render_view_host();
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure we don't have a text field element interfering with keyboard
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom".
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  render_view_host->ClearFocusedNode();
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  NativeWebKeyboardEvent event = GetKeyboardEvent(contents->tab_contents(),
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                  key_event);
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  render_view_host->ForwardKeyboardEvent(event);
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFindBarController* FindBarHost::GetFindBarController() const {
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return find_bar_controller_;
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FindBarHost::SetFindBarController(FindBarController* find_bar_controller) {
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  find_bar_controller_ = find_bar_controller;
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FindBarHost::Show(bool animate) {
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DropdownBarHost::Show(animate);
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::Hide(bool animate) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DropdownBarHost::Hide(animate);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FindBarHost::SetFocusAndSelection() {
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DropdownBarHost::SetFocusAndSelection();
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::ClearResults(const FindNotificationDetails& results) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  find_bar_view()->UpdateForResult(results, string16());
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::StopAnimation() {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DropdownBarHost::StopAnimation();
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::MoveWindowIfNecessary(const gfx::Rect& selection_rect,
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        bool no_redraw) {
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We only move the window if one is active for the current TabContents. If we
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // don't check this, then SetWidgetPosition below will end up making the Find
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bar visible.
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!find_bar_controller_->tab_contents() ||
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      !find_bar_controller_->
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          tab_contents()->find_tab_helper()->find_ui_active()) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect new_pos = GetDialogPosition(selection_rect);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetDialogPosition(new_pos, no_redraw);
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // May need to redraw our frame to accommodate bookmark bar styles.
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  view()->SchedulePaint();
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FindBarHost::SetFindText(const string16& find_text) {
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  find_bar_view()->SetFindText(find_text);
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FindBarHost::UpdateUIForFindResult(const FindNotificationDetails& result,
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                        const string16& find_text) {
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Make sure match count is clear. It may get set again in UpdateForResult
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // if enough data is available.
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  find_bar_view()->ClearMatchCount();
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!find_text.empty())
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    find_bar_view()->UpdateForResult(result, find_text);
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We now need to check if the window is obscuring the search results.
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result.selection_rect().IsEmpty())
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MoveWindowIfNecessary(result.selection_rect(), false);
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Once we find a match we no longer want to keep track of what had
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // focus. EndFindSession will then set the focus to the page content.
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (result.number_of_matches() > 0)
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ResetFocusTracker();
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool FindBarHost::IsFindBarVisible() {
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return DropdownBarHost::IsVisible();
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FindBarHost::RestoreSavedFocus() {
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (focus_tracker() == NULL) {
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // TODO(brettw) Focus() should be on TabContentsView.
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    find_bar_controller_->tab_contents()->tab_contents()->Focus();
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    focus_tracker()->FocusLastFocusedExternalView();
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFindBarTesting* FindBarHost::GetFindBarTesting() {
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return this;
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// FindBarWin, views::AcceleratorTarget implementation:
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool FindBarHost::AcceleratorPressed(const views::Accelerator& accelerator) {
17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::KeyboardCode key = accelerator.GetKeyCode();
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (key == ui::VKEY_RETURN && accelerator.IsCtrlDown()) {
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Ctrl+Enter closes the Find session and navigates any link that is active.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar_controller_->EndFindSession(FindBarController::kActivateSelection);
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (key == ui::VKEY_ESCAPE) {
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This will end the Find session and hide the window, causing it to loose
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // focus and in the process unregister us as the handler for the Escape
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // accelerator through the FocusWillChange event.
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar_controller_->EndFindSession(FindBarController::kKeepSelection);
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Unknown accelerator";
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// FindBarTesting implementation:
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool FindBarHost::GetFindBarWindowInfo(gfx::Point* position,
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      bool* fully_visible) {
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!find_bar_controller_ ||
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !::IsWindow(host()->GetNativeView())) {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      false) {
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // TODO(sky): figure out linux side.
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This is tricky due to asynchronous nature of x11.
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // See bug http://crbug.com/28629.
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (position)
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *position = gfx::Point();
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (fully_visible)
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *fully_visible = false;
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  gfx::Rect window_rect = host()->GetWindowScreenBounds();
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (position)
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *position = window_rect.origin();
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (fully_visible)
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *fully_visible = IsVisible() && !IsAnimating();
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 FindBarHost::GetFindText() {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return find_bar_view()->GetFindText();
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstring16 FindBarHost::GetFindSelectedText() {
22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return find_bar_view()->GetFindSelectedText();
22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstring16 FindBarHost::GetMatchCountText() {
22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return find_bar_view()->GetMatchCountText();
22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick////////////////////////////////////////////////////////////////////////////////
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Overridden from DropdownBarHost:
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect FindBarHost::GetDialogPosition(gfx::Rect avoid_overlapping_rect) {
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Find the area we have to work with (after accounting for scrollbars, etc).
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect widget_bounds;
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetWidgetBounds(&widget_bounds);
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (widget_bounds.IsEmpty())
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return gfx::Rect();
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ask the view how large an area it needs to draw on.
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size prefsize = view()->GetPreferredSize();
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Place the view in the top right corner of the widget boundaries (top left
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // for RTL languages).
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect view_location;
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int x = widget_bounds.x();
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!base::i18n::IsRTL())
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    x += widget_bounds.width() - prefsize.width();
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int y = widget_bounds.y();
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  view_location.SetRect(x, y, prefsize.width(), prefsize.height());
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When we get Find results back, we specify a selection rect, which we
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should strive to avoid overlapping. But first, we need to offset the
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // selection rect (if one was provided).
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!avoid_overlapping_rect.IsEmpty()) {
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // For comparison (with the Intersects function below) we need to account
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // for the fact that we draw the Find widget relative to the Chrome frame,
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // whereas the selection rect is relative to the page.
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GetWidgetPositionNative(&avoid_overlapping_rect);
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect new_pos = FindBarController::GetLocationForFindbarView(
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      view_location, widget_bounds, avoid_overlapping_rect);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // While we are animating, the Find window will grow bottoms up so we need to
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // re-position the widget so that it appears to grow out of the toolbar.
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (animation_offset() > 0)
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_pos.Offset(0, std::min(0, -animation_offset()));
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new_pos;
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw) {
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_pos.IsEmpty())
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure the window edges are clipped to just the visible region. We need
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to do this before changing position, so that when we animate the closure
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of it it doesn't look like the window crumbles into the toolbar.
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateWindowEdges(new_pos);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetWidgetPositionNative(new_pos, no_redraw);
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::GetWidgetBounds(gfx::Rect* bounds) {
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bounds);
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The BrowserView does Layout for the components that we care about
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // positioning relative to, so we ask it to tell us where we should go.
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *bounds = browser_view()->GetFindBarBoundingBox();
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::RegisterAccelerators() {
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DropdownBarHost::RegisterAccelerators();
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Register for Ctrl+Return.
29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  views::Accelerator escape(ui::VKEY_RETURN, false, true, false);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  focus_manager()->RegisterAccelerator(escape, this);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarHost::UnregisterAccelerators() {
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Unregister Ctrl+Return.
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  views::Accelerator escape(ui::VKEY_RETURN, false, true, false);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  focus_manager()->UnregisterAccelerator(escape, this);
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DropdownBarHost::UnregisterAccelerators();
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick////////////////////////////////////////////////////////////////////////////////
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// private:
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFindBarView* FindBarHost::find_bar_view() {
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return static_cast<FindBarView*>(view());
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
313