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/gtk/find_bar_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gdk/gdkkeysyms.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/find_bar/find_bar_controller.h"
2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/find_bar/find_bar_state.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/find_bar/find_notification_details.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/find_bar/find_tab_helper.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_window_gtk.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/custom_button.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_floating_container.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/nine_box.h"
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/slide_animator_gtk.h"
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/view_id_util.h"
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/native_web_keyboard_event.h"
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h"
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used as the color of the text in the entry box and the text for the results
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// label for failure searches.
48513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst GdkColor kEntryTextColor = gtk_util::kGdkBlack;
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used as the color of the background of the entry box and the background of
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the find label for successful searches.
52513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst GdkColor kEntryBackgroundColor = gtk_util::kGdkWhite;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst GdkColor kFindFailureBackgroundColor = GDK_COLOR_RGB(255, 102, 102);
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst GdkColor kFindSuccessTextColor = GDK_COLOR_RGB(178, 178, 178);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Padding around the container.
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kBarPaddingTopBottom = 4;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kEntryPaddingLeft = 6;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCloseButtonPaddingLeft = 3;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kBarPaddingRight = 4;
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The height of the findbar dialog, as dictated by the size of the background
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// images.
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kFindBarHeight = 32;
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The width of the text entry field.
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTextEntryWidth = 220;
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The size of the "rounded" corners.
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCornerSize = 3;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum FrameType {
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FRAME_MASK,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FRAME_STROKE,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a list of points that either form the outline of the status bubble
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (|type| == FRAME_MASK) or form the inner border around the inner edge
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (|type| == FRAME_STROKE).
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<GdkPoint> MakeFramePolygonPoints(int width,
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             int height,
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             FrameType type) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  using gtk_util::MakeBidiGdkPoint;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<GdkPoint> points;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ltr = !base::i18n::IsRTL();
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we have a stroke, we have to offset some of our points by 1 pixel.
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We have to inset by 1 pixel when we draw horizontal lines that are on the
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // bottom or when we draw vertical lines that are closer to the end (end is
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // right for ltr).
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int y_off = (type == FRAME_MASK) ? 0 : -1;
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We use this one for LTR.
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x_off_l = ltr ? y_off : 0;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We use this one for RTL.
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x_off_r = !ltr ? -y_off : 0;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Top left corner
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(x_off_r, 0, width, ltr));
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kCornerSize + x_off_r, kCornerSize, width, ltr));
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bottom left corner
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kCornerSize + x_off_r, height - kCornerSize, width, ltr));
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (2 * kCornerSize) + x_off_l, height + y_off,
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width, ltr));
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bottom right corner
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width - (2 * kCornerSize) + x_off_r, height + y_off,
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width, ltr));
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width - kCornerSize + x_off_l, height - kCornerSize, width, ltr));
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Top right corner
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width - kCornerSize + x_off_l, kCornerSize, width, ltr));
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  points.push_back(MakeBidiGdkPoint(width + x_off_l, 0, width, ltr));
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return points;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Give the findbar dialog its unique shape using images.
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetDialogShape(GtkWidget* widget) {
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static NineBox* dialog_shape = NULL;
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!dialog_shape) {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dialog_shape = new NineBox(
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FIND_DLG_LEFT_BACKGROUND,
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FIND_DLG_MIDDLE_BACKGROUND,
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FIND_DLG_RIGHT_BACKGROUND,
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0, 0, 0, 0, 0);
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dialog_shape->ChangeWhiteToTransparent();
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dialog_shape->ContourWidget(widget);
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return a ninebox that will paint the border of the findbar dialog. This is
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// shared across all instances of the findbar. Do not free the returned pointer.
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst NineBox* GetDialogBorder() {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static NineBox* dialog_border = NULL;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!dialog_border) {
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dialog_border = new NineBox(
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FIND_DIALOG_LEFT,
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FIND_DIALOG_MIDDLE,
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FIND_DIALOG_RIGHT,
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0, 0, 0, 0, 0);
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return dialog_border;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Like gtk_util::CreateGtkBorderBin, but allows control over the alignment and
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// returns both the event box and the alignment so we can modify it during its
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// lifetime (i.e. during a theme change).
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BuildBorder(GtkWidget* child,
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 bool center,
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 int padding_top, int padding_bottom, int padding_left,
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 int padding_right,
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 GtkWidget** ebox, GtkWidget** alignment) {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *ebox = gtk_event_box_new();
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (center)
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_alignment_set_padding(GTK_ALIGNMENT(*alignment),
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            padding_top, padding_bottom, padding_left,
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            padding_right);
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(*alignment), child);
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(*ebox), *alignment);
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFindBarGtk::FindBarGtk(Browser* browser)
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : browser_(browser),
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      window_(static_cast<BrowserWindowGtk*>(browser->window())),
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      theme_service_(GtkThemeService::GetFrom(browser->profile())),
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      container_width_(-1),
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      container_height_(-1),
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      match_label_failure_(false),
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ignore_changed_signal_(false) {
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitWidgets();
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ViewIDUtil::SetID(text_entry_, VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Insert the widget into the browser gtk hierarchy.
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_->AddFindBar(this);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Hook up signals after the widget has been added to the hierarchy so the
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // widget will be realized.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "changed",
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnChanged), this);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect_after(text_entry_, "key-press-event",
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         G_CALLBACK(OnKeyPressEvent), this);
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect_after(text_entry_, "key-release-event",
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         G_CALLBACK(OnKeyReleaseEvent), this);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When the user tabs to us or clicks on us, save where the focus used to
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // be.
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "focus",
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnFocus), this);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_add_events(text_entry_, GDK_BUTTON_PRESS_MASK);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "button-press-event",
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnButtonPress), this);
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "move-cursor", G_CALLBACK(OnMoveCursor), this);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "activate", G_CALLBACK(OnActivate), this);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "direction-changed",
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnWidgetDirectionChanged), this);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "focus-in-event",
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnFocusIn), this);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(text_entry_, "focus-out-event",
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnFocusOut), this);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(container_, "expose-event",
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnExpose), this);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFindBarGtk::~FindBarGtk() {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::InitWidgets() {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The find bar is basically an hbox with a gtkentry (text box) followed by 3
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // buttons (previous result, next result, close).  We wrap the hbox in a gtk
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // alignment and a gtk event box to get the padding and light blue
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // background. We put that event box in a fixed in order to control its
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // lateral position. We put that fixed in a SlideAnimatorGtk in order to get
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the slide effect.
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* hbox = gtk_hbox_new(false, 0);
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  container_ = gtk_util::CreateGtkBorderBin(hbox, NULL,
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kBarPaddingTopBottom, kBarPaddingTopBottom,
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kEntryPaddingLeft, kBarPaddingRight);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ViewIDUtil::SetID(container_, VIEW_ID_FIND_IN_PAGE);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_app_paintable(container_, TRUE);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  slide_widget_.reset(new SlideAnimatorGtk(container_,
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           SlideAnimatorGtk::DOWN,
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           0, false, false, NULL));
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  close_button_.reset(CustomDrawButton::CloseButton(theme_service_));
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::CenterWidgetInHBox(hbox, close_button_->widget(), true,
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               kCloseButtonPaddingLeft);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(close_button_->widget(), "clicked",
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnClicked), this);
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_tooltip_text(close_button_->widget(),
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_CLOSE_TOOLTIP).c_str());
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  find_next_button_.reset(new CustomDrawButton(theme_service_,
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FINDINPAGE_NEXT, IDR_FINDINPAGE_NEXT_H, IDR_FINDINPAGE_NEXT_H,
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      IDR_FINDINPAGE_NEXT_P, GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU));
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(find_next_button_->widget(), "clicked",
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnClicked), this);
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_tooltip_text(find_next_button_->widget(),
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_NEXT_TOOLTIP).c_str());
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(hbox), find_next_button_->widget(),
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   FALSE, FALSE, 0);
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  find_previous_button_.reset(new CustomDrawButton(theme_service_,
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_FINDINPAGE_PREV, IDR_FINDINPAGE_PREV_H, IDR_FINDINPAGE_PREV_H,
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      IDR_FINDINPAGE_PREV_P, GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU));
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(find_previous_button_->widget(), "clicked",
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnClicked), this);
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_tooltip_text(find_previous_button_->widget(),
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_PREVIOUS_TOOLTIP).c_str());
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(hbox), find_previous_button_->widget(),
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   FALSE, FALSE, 0);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make a box for the edit and match count widgets. This is fixed size since
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we want the widgets inside to resize themselves rather than making the
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // dialog bigger.
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* content_hbox = gtk_hbox_new(FALSE, 0);
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_size_request(content_hbox, kTextEntryWidth, -1);
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  text_entry_ = gtk_entry_new();
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_entry_set_has_frame(GTK_ENTRY(text_entry_), FALSE);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match_count_label_ = gtk_label_new(NULL);
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This line adds padding on the sides so that the label has even padding on
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // all edges.
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_misc_set_padding(GTK_MISC(match_count_label_), 2, 0);
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match_count_event_box_ = gtk_event_box_new();
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* match_count_centerer = gtk_vbox_new(FALSE, 0);
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(match_count_centerer), match_count_event_box_,
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     TRUE, TRUE, 0);
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_set_border_width(GTK_CONTAINER(match_count_centerer), 1);
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(match_count_event_box_), match_count_label_);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(content_hbox), match_count_centerer,
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   FALSE, FALSE, 0);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(content_hbox), text_entry_, TRUE, TRUE, 0);
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This event box is necessary to color in the area above and below the match
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // count label, and is where we draw the entry background onto in GTK mode.
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BuildBorder(content_hbox, true, 0, 0, 0, 0,
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              &content_event_box_, &content_alignment_);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_app_paintable(content_event_box_, TRUE);
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(content_event_box_, "expose-event",
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnContentEventBoxExpose), this);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This alignment isn't centered and is used for spacing in chrome theme
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // mode. (It's also used in GTK mode for padding because left padding doesn't
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // equal bottom padding naturally.)
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BuildBorder(content_event_box_, false, 2, 2, 2, 0,
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              &border_bin_, &border_bin_alignment_);
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::CenterWidgetInHBox(hbox, border_bin_, true, 0);
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  theme_service_->InitThemesFor(this);
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 NotificationService::AllSources());
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(widget(), "parent-set", G_CALLBACK(OnParentSet), this);
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We take care to avoid showing the slide animator widget.
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(container_);
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show(widget());
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFindBarController* FindBarGtk::GetFindBarController() const {
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return find_bar_controller_;
3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FindBarGtk::SetFindBarController(FindBarController* find_bar_controller) {
3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  find_bar_controller_ = find_bar_controller;
3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::Show(bool animate) {
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (animate) {
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    slide_widget_->Open();
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    selection_rect_ = gfx::Rect();
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Reposition();
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (container_->window)
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_raise(container_->window);
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    slide_widget_->OpenWithoutAnimation();
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::Hide(bool animate) {
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (animate)
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    slide_widget_->Close();
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    slide_widget_->CloseWithoutAnimation();
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::SetFocusAndSelection() {
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StoreOutsideFocus();
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_grab_focus(text_entry_);
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Select all the text.
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_entry_select_region(GTK_ENTRY(text_entry_), 0, -1);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::ClearResults(const FindNotificationDetails& results) {
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateUIForFindResult(results, string16());
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::StopAnimation() {
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  slide_widget_->End();
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::MoveWindowIfNecessary(const gfx::Rect& selection_rect,
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       bool no_redraw) {
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Not moving the window on demand, so do nothing.
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::SetFindText(const string16& find_text) {
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string find_text_utf8 = UTF16ToUTF8(find_text);
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ignore the "changed" signal handler because programatically setting the
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // text should not fire a "changed" event.
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ignore_changed_signal_ = true;
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_entry_set_text(GTK_ENTRY(text_entry_), find_text_utf8.c_str());
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ignore_changed_signal_ = false;
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::UpdateUIForFindResult(const FindNotificationDetails& result,
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       const string16& find_text) {
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!result.selection_rect().IsEmpty()) {
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    selection_rect_ = result.selection_rect();
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int xposition = GetDialogPosition(result.selection_rect()).x();
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (xposition != widget()->allocation.x)
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Reposition();
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Once we find a match we no longer want to keep track of what had
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // focus. EndFindSession will then set the focus to the page content.
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result.number_of_matches() > 0)
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    focus_store_.Store(NULL);
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string find_text_utf8 = UTF16ToUTF8(find_text);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool have_valid_range =
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result.number_of_matches() != -1 && result.active_match_ordinal() != -1;
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string entry_text(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (entry_text != find_text_utf8) {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetFindText(find_text);
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_entry_select_region(GTK_ENTRY(text_entry_), 0, -1);
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!find_text.empty() && have_valid_range) {
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_label_set_text(GTK_LABEL(match_count_label_),
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        l10n_util::GetStringFUTF8(IDS_FIND_IN_PAGE_COUNT,
4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            base::IntToString16(result.active_match_ordinal()),
4013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            base::IntToString16(result.number_of_matches())).c_str());
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    UpdateMatchLabelAppearance(result.number_of_matches() == 0 &&
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               result.final_update());
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If there was no text entered, we don't show anything in the result count
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // area.
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_label_set_text(GTK_LABEL(match_count_label_), "");
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    UpdateMatchLabelAppearance(false);
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::AudibleAlert() {
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This call causes a lot of weird bugs, especially when using the custom
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // frame. TODO(estade): if people complain, re-enable it. See
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // http://crbug.com/27635 and others.
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   gtk_widget_error_bell(widget());
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect FindBarGtk::GetDialogPosition(gfx::Rect avoid_overlapping_rect) {
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ltr = !base::i18n::IsRTL();
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 15 is the size of the scrollbar, copied from ScrollbarThemeChromium.
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The height is not used.
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // At very low browser widths we can wind up with a negative |dialog_bounds|
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // width, so clamp it to 0.
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect dialog_bounds = gfx::Rect(ltr ? 0 : 15, 0,
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::max(0, widget()->parent->allocation.width - (ltr ? 15 : 0)), 0);
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition req;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_size_request(container_, &req);
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size prefsize(req.width, req.height);
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect view_location(
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ltr ? dialog_bounds.width() - prefsize.width() : dialog_bounds.x(),
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dialog_bounds.y(), prefsize.width(), prefsize.height());
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect new_pos = FindBarController::GetLocationForFindbarView(
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      view_location, dialog_bounds, avoid_overlapping_rect);
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new_pos;
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool FindBarGtk::IsFindBarVisible() {
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GTK_WIDGET_VISIBLE(widget());
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::RestoreSavedFocus() {
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This function sometimes gets called when we don't have focus. We should do
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // nothing in this case.
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gtk_widget_is_focus(text_entry_))
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (focus_store_.widget())
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_grab_focus(focus_store_.widget());
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    find_bar_controller_->tab_contents()->tab_contents()->Focus();
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFindBarTesting* FindBarGtk::GetFindBarTesting() {
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return this;
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::Observe(NotificationType type,
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         const NotificationSource& source,
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         const NotificationDetails& details) {
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(type.value, NotificationType::BROWSER_THEME_CHANGED);
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Force reshapings of the find bar window.
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  container_width_ = -1;
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  container_height_ = -1;
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (theme_service_->UseGtkTheme()) {
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_cursor(text_entry_, NULL, NULL);
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL, NULL);
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL, NULL);
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Prevent forced font sizes because it causes the jump up and down
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // character movement (http://crbug.com/22614), and because it will
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // prevent centering of the text entry.
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::UndoForceFontSize(text_entry_);
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::UndoForceFontSize(match_count_label_);
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(content_event_box_, -1, -1);
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_bg(content_event_box_, GTK_STATE_NORMAL, NULL);
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Replicate the normal GtkEntry behaviour by drawing the entry
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // background. We set the fake alignment to be the frame thickness.
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkStyle* style = gtk_rc_get_style(text_entry_);
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint xborder = style->xthickness;
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint yborder = style->ythickness;
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment_),
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              yborder, yborder, xborder, xborder);
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We leave left padding on the left, even in GTK mode, as it's required
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // for the left margin to be equivalent to the bottom margin.
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(border_bin_alignment_),
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              0, 0, 1, 0);
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We need this event box to have its own window in GTK mode for doing the
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // hacky widget rendering.
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_event_box_set_visible_window(GTK_EVENT_BOX(border_bin_), TRUE);
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_app_paintable(border_bin_, TRUE);
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_misc_set_alignment(GTK_MISC(match_count_label_), 0.5, 0.5);
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
505513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_widget_modify_cursor(
506513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        text_entry_, &gtk_util::kGdkBlack, &gtk_util::kGdkGray);
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_base(text_entry_, GTK_STATE_NORMAL,
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &kEntryBackgroundColor);
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_text(text_entry_, GTK_STATE_NORMAL,
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &kEntryTextColor);
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Until we switch to vector graphics, force the font size.
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::ForceFontSizePixels(text_entry_, 13.4);  // 13.4px == 10pt @ 96dpi
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::ForceFontSizePixels(match_count_label_, 13.4);
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Force the text widget height so it lines up with the buttons regardless
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // of font size.
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(content_event_box_, -1, 20);
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_bg(content_event_box_, GTK_STATE_NORMAL,
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &kEntryBackgroundColor);
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment_),
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              0.0, 0.0, 0.0, 0.0);
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(border_bin_alignment_),
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              2, 2, 3, 0);
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We need this event box to be invisible because we're only going to draw
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // on the background (but we can't take it out of the heiarchy entirely
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // because we also need it to take up space).
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_event_box_set_visible_window(GTK_EVENT_BOX(border_bin_), FALSE);
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_app_paintable(border_bin_, FALSE);
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_misc_set_alignment(GTK_MISC(match_count_label_), 0.5, 1.0);
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button_->SetBackground(
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        theme_service_->GetColor(ThemeService::COLOR_TAB_TEXT),
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rb.GetBitmapNamed(IDR_CLOSE_BAR),
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rb.GetBitmapNamed(IDR_CLOSE_BAR_MASK));
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateMatchLabelAppearance(match_label_failure_);
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool FindBarGtk::GetFindBarWindowInfo(gfx::Point* position,
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      bool* fully_visible) {
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (position)
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *position = GetPosition();
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (fully_visible) {
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *fully_visible = !slide_widget_->IsAnimating() &&
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     slide_widget_->IsShowing();
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 FindBarGtk::GetFindText() {
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return UTF8ToUTF16(contents);
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstring16 FindBarGtk::GetFindSelectedText() {
56421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gint cursor_pos;
56521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gint selection_bound;
56621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  g_object_get(G_OBJECT(text_entry_), "cursor-position", &cursor_pos,
56721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen               NULL);
56821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  g_object_get(G_OBJECT(text_entry_), "selection-bound", &selection_bound,
56921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen               NULL);
57021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
57121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return UTF8ToUTF16(contents.substr(cursor_pos, selection_bound));
57221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
57321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
57421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstring16 FindBarGtk::GetMatchCountText() {
57521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string contents(gtk_label_get_text(GTK_LABEL(match_count_label_)));
57621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return UTF8ToUTF16(contents);
57721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
57821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::FindEntryTextInContents(bool forward_search) {
58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabContentsWrapper* tab_contents = find_bar_controller_->tab_contents();
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!tab_contents)
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
583dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FindTabHelper* find_tab_helper = tab_contents->find_tab_helper();
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string new_contents(gtk_entry_get_text(GTK_ENTRY(text_entry_)));
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_contents.length() > 0) {
588dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    find_tab_helper->StartFinding(UTF8ToUTF16(new_contents), forward_search,
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               false);  // Not case sensitive.
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The textbox is empty so we reset.
592dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    find_tab_helper->StopFinding(FindBarController::kClearSelection);
593dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UpdateUIForFindResult(find_tab_helper->find_result(), string16());
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Clearing the text box should also clear the prepopulate state so that
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // when we close and reopen the Find box it doesn't show the search we
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // just deleted.
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FindBarState* find_bar_state = browser_->profile()->GetFindBarState();
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar_state->set_last_prepopulate_text(string16());
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::UpdateMatchLabelAppearance(bool failure) {
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match_label_failure_ = failure;
605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool use_gtk = theme_service_->UseGtkTheme();
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_gtk) {
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkStyle* style = gtk_rc_get_style(text_entry_);
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkColor normal_bg = style->base[GTK_STATE_NORMAL];
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkColor normal_text = gtk_util::AverageColors(
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]);
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_bg(match_count_event_box_, GTK_STATE_NORMAL,
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         failure ? &kFindFailureBackgroundColor :
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &normal_bg);
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_fg(match_count_label_, GTK_STATE_NORMAL,
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         failure ? &kEntryTextColor : &normal_text);
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_bg(match_count_event_box_, GTK_STATE_NORMAL,
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         failure ? &kFindFailureBackgroundColor :
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &kEntryBackgroundColor);
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_fg(match_count_label_, GTK_STATE_NORMAL,
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         failure ? &kEntryTextColor : &kFindSuccessTextColor);
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::Reposition() {
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsFindBarVisible())
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This will trigger an allocate, which allows us to reposition.
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (widget()->parent)
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_queue_resize(widget()->parent);
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::StoreOutsideFocus() {
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |text_entry_| is the only widget in the find bar that can be focused,
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // so it's the only one we have to check.
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(estade): when we make the find bar buttons focusable, we'll have
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to change this (same above in RestoreSavedFocus).
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gtk_widget_is_focus(text_entry_))
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    focus_store_.Store(text_entry_);
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool FindBarGtk::MaybeForwardKeyEventToRenderer(GdkEventKey* event) {
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (event->keyval) {
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Down:
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Up:
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Page_Up:
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Page_Down:
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_Home:
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case GDK_End:
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if ((event->state & gtk_accelerator_get_default_mod_mask()) ==
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          GDK_CONTROL_MASK) {
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Fall through.
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabContentsWrapper* contents = find_bar_controller_->tab_contents();
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!contents)
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RenderViewHost* render_view_host = contents->render_view_host();
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure we don't have a text field element interfering with keyboard
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom".
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  render_view_host->ClearFocusedNode();
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NativeWebKeyboardEvent wke(event);
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  render_view_host->ForwardKeyboardEvent(wke);
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::AdjustTextAlignment() {
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PangoDirection content_dir =
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pango_find_base_dir(gtk_entry_get_text(GTK_ENTRY(text_entry_)), -1);
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTextDirection widget_dir = gtk_widget_get_direction(text_entry_);
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use keymap or widget direction if content does not have strong direction.
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It matches the behavior of GtkEntry.
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (content_dir == PANGO_DIRECTION_NEUTRAL) {
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (GTK_WIDGET_HAS_FOCUS(text_entry_)) {
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content_dir = gdk_keymap_get_direction(
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gdk_keymap_get_for_display(gtk_widget_get_display(text_entry_)));
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (widget_dir == GTK_TEXT_DIR_RTL)
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content_dir = PANGO_DIRECTION_RTL;
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      else
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content_dir = PANGO_DIRECTION_LTR;
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if ((widget_dir == GTK_TEXT_DIR_RTL && content_dir == PANGO_DIRECTION_LTR) ||
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (widget_dir == GTK_TEXT_DIR_LTR && content_dir == PANGO_DIRECTION_RTL)) {
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_entry_set_alignment(GTK_ENTRY(text_entry_), 1.0);
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_entry_set_alignment(GTK_ENTRY(text_entry_), 0.0);
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Point FindBarGtk::GetPosition() {
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point point;
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GValue value = { 0, };
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_init(&value, G_TYPE_INT);
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_child_get_property(GTK_CONTAINER(widget()->parent),
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   widget(), "x", &value);
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  point.set_x(g_value_get_int(&value));
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_child_get_property(GTK_CONTAINER(widget()->parent),
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   widget(), "y", &value);
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  point.set_y(g_value_get_int(&value));
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_unset(&value);
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return point;
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::OnParentSet(GtkWidget* widget, GtkObject* old_parent,
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             FindBarGtk* find_bar) {
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!widget->parent)
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(widget->parent, "set-floating-position",
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnSetFloatingPosition), find_bar);
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::OnSetFloatingPosition(
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkFloatingContainer* floating_container,
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkAllocation* allocation,
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FindBarGtk* find_bar) {
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* findbar = find_bar->widget();
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int xposition = find_bar->GetDialogPosition(find_bar->selection_rect_).x();
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GValue value = { 0, };
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_init(&value, G_TYPE_INT);
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_set_int(&value, xposition);
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   findbar, "x", &value);
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_set_int(&value, 0);
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   findbar, "y", &value);
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_unset(&value);
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnChanged(GtkWindow* window, FindBarGtk* find_bar) {
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  find_bar->AdjustTextAlignment();
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!find_bar->ignore_changed_signal_)
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar->FindEntryTextInContents(true);
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnKeyPressEvent(GtkWidget* widget, GdkEventKey* event,
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     FindBarGtk* find_bar) {
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (find_bar->MaybeForwardKeyEventToRenderer(event)) {
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return TRUE;
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (GDK_Escape == event->keyval) {
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar->find_bar_controller_->EndFindSession(
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FindBarController::kKeepSelection);
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return TRUE;
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (GDK_Return == event->keyval ||
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             GDK_KP_Enter == event->keyval) {
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((event->state & gtk_accelerator_get_default_mod_mask()) ==
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GDK_CONTROL_MASK) {
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      find_bar->find_bar_controller_->EndFindSession(
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          FindBarController::kActivateSelection);
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return TRUE;
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool forward = (event->state & gtk_accelerator_get_default_mod_mask()) !=
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   GDK_SHIFT_MASK;
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar->FindEntryTextInContents(forward);
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return TRUE;
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event,
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       FindBarGtk* find_bar) {
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return find_bar->MaybeForwardKeyEventToRenderer(event);
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::OnClicked(GtkWidget* button, FindBarGtk* find_bar) {
799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (button == find_bar->close_button_->widget()) {
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar->find_bar_controller_->EndFindSession(
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FindBarController::kKeepSelection);
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (button == find_bar->find_previous_button_->widget() ||
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             button == find_bar->find_next_button_->widget()) {
804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    find_bar->FindEntryTextInContents(
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        button == find_bar->find_next_button_->widget());
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnContentEventBoxExpose(GtkWidget* widget,
813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             GdkEventExpose* event,
814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             FindBarGtk* bar) {
815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (bar->theme_service_->UseGtkTheme()) {
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Draw the text entry background around where we input stuff. Note the
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // decrement to |width|. We do this because some theme engines
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // (*cough*Clearlooks*cough*) don't do any blending and use thickness to
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // make sure that widgets never overlap.
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int padding = gtk_widget_get_style(widget)->xthickness;
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle rec = {
822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      widget->allocation.x,
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      widget->allocation.y,
824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      widget->allocation.width - padding,
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      widget->allocation.height
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::DrawTextEntryBackground(bar->text_entry_, widget,
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      &event->area, &rec);
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used to handle custom painting of |container_|.
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e,
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              FindBarGtk* bar) {
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition req;
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_size_request(widget, &req);
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_size_request(bar->widget(), req.width, -1);
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (bar->theme_service_->UseGtkTheme()) {
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (bar->container_width_ != widget->allocation.width ||
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bar->container_height_ != widget->allocation.height) {
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<GdkPoint> mask_points = MakeFramePolygonPoints(
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          widget->allocation.width, widget->allocation.height, FRAME_MASK);
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GdkRegion* mask_region = gdk_region_polygon(&mask_points[0],
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  mask_points.size(),
849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  GDK_EVEN_ODD_RULE);
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Reset the shape.
851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_shape_combine_region(widget->window, NULL, 0, 0);
852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_shape_combine_region(widget->window, mask_region, 0, 0);
853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_region_destroy(mask_region);
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bar->container_width_ = widget->allocation.width;
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bar->container_height_ = widget->allocation.height;
857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkDrawable* drawable = GDK_DRAWABLE(e->window);
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkGC* gc = gdk_gc_new(drawable);
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_gc_set_clip_rectangle(gc, &e->area);
862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GdkColor color = bar->theme_service_->GetBorderColor();
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_gc_set_rgb_fg_color(gc, &color);
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Stroke the frame border.
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<GdkPoint> points = MakeFramePolygonPoints(
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        widget->allocation.width, widget->allocation.height, FRAME_STROKE);
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_draw_lines(drawable, gc, &points[0], points.size());
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_object_unref(gc);
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (bar->container_width_ != widget->allocation.width ||
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bar->container_height_ != widget->allocation.height) {
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Reset the shape.
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_window_shape_combine_region(widget->window, NULL, 0, 0);
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SetDialogShape(bar->container_);
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bar->container_width_ = widget->allocation.width;
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bar->container_height_ = widget->allocation.height;
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_cairo_rectangle(cr, &e->area);
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_clip(cr);
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Point tabstrip_origin =
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bar->window_->tabstrip()->GetTabStripOriginForWidget(widget);
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::DrawThemedToolbarBackground(widget, cr, e, tabstrip_origin,
890ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                          bar->theme_service_);
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // During chrome theme mode, we need to draw the border around content_hbox
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // now instead of when we render |border_bin_|. We don't use stacked event
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // boxes to simulate the effect because we need to blend them with this
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // background.
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkAllocation border_allocation = bar->border_bin_->allocation;
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Blit the left part of the background image once on the left.
8993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CairoCachedSurface* background_left =
900ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        bar->theme_service_->GetRTLEnabledSurfaceNamed(
9013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        IDR_FIND_BOX_BACKGROUND_LEFT, widget);
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    background_left->SetSource(cr, border_allocation.x, border_allocation.y);
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_rectangle(cr, border_allocation.x, border_allocation.y,
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    background_left->Width(), background_left->Height());
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_fill(cr);
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Blit the center part of the background image in all the space between.
909ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CairoCachedSurface* background = bar->theme_service_->GetSurfaceNamed(
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_FIND_BOX_BACKGROUND, widget);
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    background->SetSource(cr,
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          border_allocation.x + background_left->Width(),
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          border_allocation.y);
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_rectangle(cr,
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    border_allocation.x + background_left->Width(),
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    border_allocation.y,
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    border_allocation.width - background_left->Width(),
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    background->Height());
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_fill(cr);
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cairo_destroy(cr);
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Draw the border.
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GetDialogBorder()->RenderToWidget(widget);
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Propagate to the container's child.
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (child)
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e);
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnFocus(GtkWidget* text_entry, GtkDirectionType focus,
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             FindBarGtk* find_bar) {
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  find_bar->StoreOutsideFocus();
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Continue propagating the event.
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnButtonPress(GtkWidget* text_entry, GdkEventButton* e,
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   FindBarGtk* find_bar) {
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  find_bar->StoreOutsideFocus();
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Continue propagating the event.
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::OnMoveCursor(GtkEntry* entry, GtkMovementStep step, gint count,
955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              gboolean selection, FindBarGtk* bar) {
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static guint signal_id = g_signal_lookup("move-cursor", GTK_TYPE_ENTRY);
957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkEvent* event = gtk_get_current_event();
959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event) {
960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE) &&
961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bar->MaybeForwardKeyEventToRenderer(&(event->key))) {
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      g_signal_stop_emission(entry, signal_id, 0);
963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_event_free(event);
966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FindBarGtk::OnActivate(GtkEntry* entry, FindBarGtk* bar) {
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bar->FindEntryTextInContents(true);
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnFocusIn(GtkWidget* entry, GdkEventFocus* event,
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               FindBarGtk* find_bar) {
977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(
978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_keymap_get_for_display(gtk_widget_get_display(entry)),
979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "direction-changed",
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      G_CALLBACK(&OnKeymapDirectionChanged), find_bar);
981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  find_bar->AdjustTextAlignment();
983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;  // Continue propagation.
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean FindBarGtk::OnFocusOut(GtkWidget* entry, GdkEventFocus* event,
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                FindBarGtk* find_bar) {
990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_handlers_disconnect_by_func(
991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gdk_keymap_get_for_display(gtk_widget_get_display(entry)),
992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      reinterpret_cast<gpointer>(&OnKeymapDirectionChanged), find_bar);
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;  // Continue propagation.
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
996