1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_UI_GTK_FIND_BAR_GTK_H_ 6 #define CHROME_BROWSER_UI_GTK_FIND_BAR_GTK_H_ 7 8 #include <gtk/gtk.h> 9 10 #include "base/basictypes.h" 11 #include "base/compiler_specific.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "chrome/browser/ui/find_bar/find_bar.h" 14 #include "chrome/browser/ui/gtk/slide_animator_gtk.h" 15 #include "content/public/browser/notification_observer.h" 16 #include "content/public/browser/notification_registrar.h" 17 #include "ui/base/gtk/focus_store_gtk.h" 18 #include "ui/base/gtk/gtk_signal.h" 19 #include "ui/base/gtk/owned_widget_gtk.h" 20 #include "ui/gfx/point.h" 21 22 class Browser; 23 class BrowserWindowGtk; 24 class CustomDrawButton; 25 class FindBarController; 26 class GtkThemeService; 27 class NineBox; 28 29 typedef struct _GtkFloatingContainer GtkFloatingContainer; 30 31 // Currently this class contains both a model and a view. We may want to 32 // eventually pull out the model specific bits and share with Windows. 33 class FindBarGtk : public FindBar, 34 public FindBarTesting, 35 public content::NotificationObserver { 36 public: 37 explicit FindBarGtk(BrowserWindowGtk* window); 38 virtual ~FindBarGtk(); 39 widget()40 GtkWidget* widget() const { return slide_widget_->widget(); } 41 42 // Methods from FindBar. 43 virtual FindBarController* GetFindBarController() const OVERRIDE; 44 virtual void SetFindBarController( 45 FindBarController* find_bar_controller) OVERRIDE; 46 virtual void Show(bool animate) OVERRIDE; 47 virtual void Hide(bool animate) OVERRIDE; 48 virtual void SetFocusAndSelection() OVERRIDE; 49 virtual void ClearResults(const FindNotificationDetails& results) OVERRIDE; 50 virtual void StopAnimation() OVERRIDE; 51 virtual void MoveWindowIfNecessary(const gfx::Rect& selection_rect, 52 bool no_redraw) OVERRIDE; 53 virtual void SetFindTextAndSelectedRange( 54 const base::string16& find_text, 55 const gfx::Range& selected_range) OVERRIDE; 56 virtual base::string16 GetFindText() OVERRIDE; 57 virtual gfx::Range GetSelectedRange() OVERRIDE; 58 virtual void UpdateUIForFindResult(const FindNotificationDetails& result, 59 const base::string16& find_text) OVERRIDE; 60 virtual void AudibleAlert() OVERRIDE; 61 virtual bool IsFindBarVisible() OVERRIDE; 62 virtual void RestoreSavedFocus() OVERRIDE; 63 virtual bool HasGlobalFindPasteboard() OVERRIDE; 64 virtual void UpdateFindBarForChangedWebContents() OVERRIDE; 65 virtual FindBarTesting* GetFindBarTesting() OVERRIDE; 66 67 // Methods from FindBarTesting. 68 virtual bool GetFindBarWindowInfo(gfx::Point* position, 69 bool* fully_visible) OVERRIDE; 70 virtual base::string16 GetFindSelectedText() OVERRIDE; 71 virtual base::string16 GetMatchCountText() OVERRIDE; 72 virtual int GetWidth() OVERRIDE; 73 74 // Overridden from content::NotificationObserver: 75 virtual void Observe(int type, 76 const content::NotificationSource& source, 77 const content::NotificationDetails& details) OVERRIDE; 78 79 private: 80 void InitWidgets(); 81 82 // Store the currently focused widget if it is not in the find bar. 83 // This should always be called before we claim focus. 84 void StoreOutsideFocus(); 85 86 // For certain keystrokes, such as up or down, we want to forward the event 87 // to the renderer rather than handling it ourselves. Returns true if the 88 // key event was forwarded. 89 // See similar function in FindBarWin. 90 bool MaybeForwardKeyEventToRenderer(GdkEventKey* event); 91 92 // Searches for another occurrence of the entry text, moving forward if 93 // |forward_search| is true. 94 void FindEntryTextInContents(bool forward_search); 95 96 void UpdateMatchLabelAppearance(bool failure); 97 98 // Asynchronously repositions the dialog. 99 void Reposition(); 100 101 // Returns the rectangle representing where to position the find bar. If 102 // |avoid_overlapping_rect| is specified, the return value will be a rectangle 103 // located immediately to the left of |avoid_overlapping_rect|, as long as 104 // there is enough room for the dialog to draw within the bounds. If not, the 105 // dialog position returned will overlap |avoid_overlapping_rect|. 106 // Note: |avoid_overlapping_rect| is expected to use coordinates relative to 107 // the top of the page area, (it will be converted to coordinates relative to 108 // the top of the browser window, when comparing against the dialog 109 // coordinates). The returned value is relative to the browser window. 110 gfx::Rect GetDialogPosition(const gfx::Rect& avoid_overlapping_rect); 111 112 // Adjust the text alignment according to the text direction of the widget 113 // and |text_entry_|'s content, to make sure the real text alignment is 114 // always in sync with the UI language direction. 115 void AdjustTextAlignment(); 116 117 // Get the position of the findbar within the floating container. 118 gfx::Point GetPosition(); 119 120 static void OnParentSet(GtkWidget* widget, GtkObject* old_parent, 121 FindBarGtk* find_bar); 122 123 static void OnSetFloatingPosition(GtkFloatingContainer* floating_container, 124 GtkAllocation* allocation, 125 FindBarGtk* find_bar); 126 127 // Callback when the entry text changes. 128 static gboolean OnChanged(GtkWindow* window, FindBarGtk* find_bar); 129 130 static gboolean OnKeyPressEvent(GtkWidget* widget, GdkEventKey* event, 131 FindBarGtk* find_bar); 132 static gboolean OnKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event, 133 FindBarGtk* find_bar); 134 135 // Callback for previous, next, and close button. 136 CHROMEGTK_CALLBACK_0(FindBarGtk, void, OnClicked); 137 138 // Handles shapping and drawing the find bar background. 139 static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* event, 140 FindBarGtk* bar); 141 142 // Expose that draws the text entry background in GTK mode. 143 static gboolean OnContentEventBoxExpose(GtkWidget* widget, 144 GdkEventExpose* event, 145 FindBarGtk* bar); 146 147 // These are both used for focus management. 148 static gboolean OnFocus(GtkWidget* text_entry, GtkDirectionType focus, 149 FindBarGtk* find_bar); 150 static gboolean OnButtonPress(GtkWidget* text_entry, GdkEventButton* e, 151 FindBarGtk* find_bar); 152 153 // Forwards ctrl-Home/End key bindings to the renderer. 154 static void OnMoveCursor(GtkEntry* entry, GtkMovementStep step, gint count, 155 gboolean selection, FindBarGtk* bar); 156 157 // Handles Enter key. 158 CHROMEGTK_CALLBACK_0(FindBarGtk, void, OnActivate); 159 OnWidgetDirectionChanged(GtkWidget * widget,GtkTextDirection previous_direction,FindBarGtk * find_bar)160 static void OnWidgetDirectionChanged(GtkWidget* widget, 161 GtkTextDirection previous_direction, 162 FindBarGtk* find_bar) { 163 find_bar->AdjustTextAlignment(); 164 } 165 OnKeymapDirectionChanged(GdkKeymap * keymap,FindBarGtk * find_bar)166 static void OnKeymapDirectionChanged(GdkKeymap* keymap, 167 FindBarGtk* find_bar) { 168 find_bar->AdjustTextAlignment(); 169 } 170 171 CHROMEGTK_CALLBACK_1(FindBarGtk, gboolean, OnFocusIn, GdkEventFocus*); 172 CHROMEGTK_CALLBACK_1(FindBarGtk, gboolean, OnFocusOut, GdkEventFocus*); 173 174 Browser* browser_; 175 BrowserWindowGtk* window_; 176 177 // Provides colors and information about GTK. 178 GtkThemeService* theme_service_; 179 180 // The widget that animates the slide-in and -out of the findbar. 181 scoped_ptr<SlideAnimatorGtk> slide_widget_; 182 183 // A GtkAlignment that is the child of |slide_widget_|. 184 GtkWidget* container_; 185 186 // Cached allocation of |container_|. We keep this on hand so that we can 187 // reset the widget's shape when the width/height change. 188 int container_width_; 189 int container_height_; 190 191 // The widget where text is entered. 192 GtkWidget* text_entry_; 193 194 // An event box and alignment that wrap the entry area and the count label. 195 GtkWidget* content_event_box_; 196 GtkWidget* content_alignment_; 197 198 // The border around the text entry area. 199 GtkWidget* border_bin_; 200 GtkWidget* border_bin_alignment_; 201 202 // The next and previous match buttons. 203 scoped_ptr<CustomDrawButton> find_previous_button_; 204 scoped_ptr<CustomDrawButton> find_next_button_; 205 206 // The GtkLabel listing how many results were found. 207 GtkWidget* match_count_label_; 208 GtkWidget* match_count_event_box_; 209 // Cache whether the match count label is showing failure or not so that 210 // we can update its appearance without changing its semantics. 211 bool match_label_failure_; 212 213 // The X to close the find bar. 214 scoped_ptr<CustomDrawButton> close_button_; 215 216 // The last matchcount number we reported to the user. 217 int last_reported_matchcount_; 218 219 // Pointer back to the owning controller. 220 FindBarController* find_bar_controller_; 221 222 // Saves where the focus used to be whenever we get it. 223 ui::FocusStoreGtk focus_store_; 224 225 // If true, the change signal for the text entry is ignored. 226 bool ignore_changed_signal_; 227 228 // This is the width of widget(). We cache it so we can recognize whether 229 // allocate signals have changed it, and if so take appropriate actions. 230 int current_fixed_width_; 231 232 scoped_ptr<NineBox> dialog_background_; 233 234 // The selection rect we are currently showing. We cache it to avoid covering 235 // it up. 236 gfx::Rect selection_rect_; 237 238 content::NotificationRegistrar registrar_; 239 240 DISALLOW_COPY_AND_ASSIGN(FindBarGtk); 241 }; 242 243 #endif // CHROME_BROWSER_UI_GTK_FIND_BAR_GTK_H_ 244