OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/views/find_bar_win.h" | 5 #include "chrome/browser/views/find_bar_host.h" |
6 | 6 |
7 #include "app/slide_animation.h" | 7 #include "app/slide_animation.h" |
| 8 #include "base/keyboard_codes.h" |
8 #include "chrome/browser/browser.h" | 9 #include "chrome/browser/browser.h" |
9 #include "chrome/browser/browser_process.h" | 10 #include "chrome/browser/browser_process.h" |
10 #include "chrome/browser/find_bar_controller.h" | 11 #include "chrome/browser/find_bar_controller.h" |
11 #include "chrome/browser/renderer_host/render_view_host.h" | 12 #include "chrome/browser/renderer_host/render_view_host.h" |
12 #include "chrome/browser/view_ids.h" | 13 #include "chrome/browser/view_ids.h" |
13 #include "chrome/browser/views/find_bar_view.h" | 14 #include "chrome/browser/views/find_bar_view.h" |
14 #include "chrome/browser/views/frame/browser_view.h" | 15 #include "chrome/browser/views/frame/browser_view.h" |
15 #include "chrome/browser/tab_contents/tab_contents.h" | 16 #include "chrome/browser/tab_contents/tab_contents.h" |
16 #include "chrome/browser/tab_contents/tab_contents_view.h" | 17 #include "chrome/browser/tab_contents/tab_contents_view.h" |
17 #include "views/focus/external_focus_tracker.h" | 18 #include "views/focus/external_focus_tracker.h" |
18 #include "views/focus/view_storage.h" | 19 #include "views/focus/view_storage.h" |
19 #include "views/controls/scrollbar/native_scroll_bar.h" | 20 #include "views/controls/scrollbar/native_scroll_bar.h" |
20 #include "views/widget/root_view.h" | 21 #include "views/widget/root_view.h" |
21 | 22 |
22 #if defined(OS_WIN) | |
23 #include "views/widget/widget_win.h" | |
24 #else | |
25 #include "views/widget/widget_gtk.h" | |
26 #endif | |
27 | |
28 // static | 23 // static |
29 bool FindBarWin::disable_animations_during_testing_ = false; | 24 bool FindBarHost::disable_animations_during_testing_ = false; |
30 | |
31 // Host is the actual widget containing FindBarView. | |
32 #if defined(OS_WIN) | |
33 class FindBarWin::Host : public views::WidgetWin { | |
34 public: | |
35 explicit Host(FindBarWin* find_bar) : find_bar_(find_bar) { | |
36 // Don't let WidgetWin manage our lifetime. We want our lifetime to | |
37 // coincide with TabContents. | |
38 set_delete_on_destroy(false); | |
39 set_window_style(WS_CHILD | WS_CLIPCHILDREN); | |
40 set_window_ex_style(WS_EX_TOPMOST); | |
41 } | |
42 | |
43 void OnFinalMessage(HWND window) { | |
44 find_bar_->OnFinalMessage(); | |
45 } | |
46 | |
47 private: | |
48 FindBarWin* find_bar_; | |
49 | |
50 DISALLOW_COPY_AND_ASSIGN(Host); | |
51 }; | |
52 #else | |
53 class FindBarWin::Host : public views::WidgetGtk { | |
54 public: | |
55 explicit Host(FindBarWin* find_bar) | |
56 : WidgetGtk(TYPE_CHILD), | |
57 find_bar_(find_bar) { | |
58 // Don't let WidgetWin manage our lifetime. We want our lifetime to | |
59 // coincide with TabContents. | |
60 set_delete_on_destroy(false); | |
61 } | |
62 | |
63 void OnDestroy(GtkWidget* widget) { | |
64 find_bar_->OnFinalMessage(); | |
65 } | |
66 | |
67 private: | |
68 FindBarWin* find_bar_; | |
69 | |
70 DISALLOW_COPY_AND_ASSIGN(Host); | |
71 }; | |
72 #endif | |
73 | 25 |
74 namespace browser { | 26 namespace browser { |
75 | 27 |
76 // Declared in browser_dialogs.h so others don't have to depend on our header. | 28 // Declared in browser_dialogs.h so others don't have to depend on our header. |
77 FindBar* CreateFindBar(BrowserView* browser_view) { | 29 FindBar* CreateFindBar(BrowserView* browser_view) { |
78 return new FindBarWin(browser_view); | 30 return new FindBarHost(browser_view); |
79 } | 31 } |
80 | 32 |
81 } // namespace browser | 33 } // namespace browser |
82 | 34 |
83 //////////////////////////////////////////////////////////////////////////////// | 35 //////////////////////////////////////////////////////////////////////////////// |
84 // FindBarWin, public: | 36 // FindBarHost, public: |
85 | 37 |
86 FindBarWin::FindBarWin(BrowserView* browser_view) | 38 FindBarHost::FindBarHost(BrowserView* browser_view) |
87 : browser_view_(browser_view), | 39 : browser_view_(browser_view), |
88 find_dialog_animation_offset_(0), | 40 find_dialog_animation_offset_(0), |
89 esc_accel_target_registered_(false), | 41 esc_accel_target_registered_(false), |
90 find_bar_controller_(NULL) { | 42 find_bar_controller_(NULL) { |
91 view_ = new FindBarView(this); | 43 view_ = new FindBarView(this); |
92 | 44 |
93 // Initialize the host. | 45 // Initialize the host. |
94 host_.reset(new Host(this)); | 46 host_.reset(CreateHost()); |
95 host_->Init(browser_view->GetWidget()->GetNativeView(), gfx::Rect()); | 47 host_->Init(GetNativeView(browser_view), gfx::Rect()); |
96 host_->SetContentsView(view_); | 48 host_->SetContentsView(view_); |
97 | 49 |
98 // Start listening to focus changes, so we can register and unregister our | 50 // Start listening to focus changes, so we can register and unregister our |
99 // own handler for Escape. | 51 // own handler for Escape. |
100 focus_manager_ = | 52 focus_manager_ = |
101 views::FocusManager::GetFocusManagerForNativeView(host_->GetNativeView()); | 53 views::FocusManager::GetFocusManagerForNativeView(host_->GetNativeView()); |
102 if (focus_manager_) { | 54 if (focus_manager_) { |
103 focus_manager_->AddFocusChangeListener(this); | 55 focus_manager_->AddFocusChangeListener(this); |
104 | 56 |
105 // Stores the currently focused view, and tracks focus changes so that we | 57 // Stores the currently focused view, and tracks focus changes so that we |
106 // can restore focus when the find box is closed. | 58 // can restore focus when the find box is closed. |
107 focus_tracker_.reset(new views::ExternalFocusTracker(view_, | 59 focus_tracker_.reset(new views::ExternalFocusTracker(view_, |
108 focus_manager_)); | 60 focus_manager_)); |
109 } else { | 61 } else { |
110 // In some cases (see bug http://crbug.com/17056) it seems we may not have | 62 // In some cases (see bug http://crbug.com/17056) it seems we may not have |
111 // a focus manager. Please reopen the bug if you hit this. | 63 // a focus manager. Please reopen the bug if you hit this. |
112 NOTREACHED(); | 64 NOTREACHED(); |
113 } | 65 } |
114 | 66 |
115 // Start the process of animating the opening of the window. | 67 // Start the process of animating the opening of the window. |
116 animation_.reset(new SlideAnimation(this)); | 68 animation_.reset(new SlideAnimation(this)); |
117 } | 69 } |
118 | 70 |
119 FindBarWin::~FindBarWin() { | 71 FindBarHost::~FindBarHost() { |
120 } | 72 } |
121 | 73 |
122 // TODO(brettw) this should not be so complicated. The view should really be in | 74 void FindBarHost::Show() { |
123 // charge of these regions. CustomFrameWindow will do this for us. It will also | |
124 // let us set a path for the window region which will avoid some logic here. | |
125 void FindBarWin::UpdateWindowEdges(const gfx::Rect& new_pos) { | |
126 #if defined(OS_WIN) | |
127 // |w| is used to make it easier to create the part of the polygon that curves | |
128 // the right side of the Find window. It essentially keeps track of the | |
129 // x-pixel position of the right-most background image inside the view. | |
130 // TODO(finnur): Let the view tell us how to draw the curves or convert | |
131 // this to a CustomFrameWindow. | |
132 int w = new_pos.width() - 6; // -6 positions us at the left edge of the | |
133 // rightmost background image of the view. | |
134 | |
135 // This polygon array represents the outline of the background image for the | |
136 // dialog. Basically, it encompasses only the visible pixels of the | |
137 // concatenated find_dlg_LMR_bg images (where LMR = [left | middle | right]). | |
138 static const POINT polygon[] = { | |
139 {0, 0}, {0, 1}, {2, 3}, {2, 29}, {4, 31}, | |
140 {4, 32}, {w+0, 32}, | |
141 {w+0, 31}, {w+1, 31}, {w+3, 29}, {w+3, 3}, {w+6, 0} | |
142 }; | |
143 | |
144 // Find the largest x and y value in the polygon. | |
145 int max_x = 0, max_y = 0; | |
146 for (int i = 0; i < arraysize(polygon); i++) { | |
147 max_x = std::max(max_x, static_cast<int>(polygon[i].x)); | |
148 max_y = std::max(max_y, static_cast<int>(polygon[i].y)); | |
149 } | |
150 | |
151 // We then create the polygon and use SetWindowRgn to force the window to draw | |
152 // only within that area. This region may get reduced in size below. | |
153 HRGN region = CreatePolygonRgn(polygon, arraysize(polygon), ALTERNATE); | |
154 | |
155 // Are we animating? | |
156 if (find_dialog_animation_offset_ > 0) { | |
157 // The animation happens in two steps: First, we clip the window and then in | |
158 // GetDialogPosition we offset the window position so that it still looks | |
159 // attached to the toolbar as it grows. We clip the window by creating a | |
160 // rectangle region (that gradually increases as the animation progresses) | |
161 // and find the intersection between the two regions using CombineRgn. | |
162 | |
163 // |y| shrinks as the animation progresses from the height of the view down | |
164 // to 0 (and reverses when closing). | |
165 int y = find_dialog_animation_offset_; | |
166 // |y| shrinking means the animation (visible) region gets larger. In other | |
167 // words: the rectangle grows upward (when the dialog is opening). | |
168 HRGN animation_region = CreateRectRgn(0, y, max_x, max_y); | |
169 // |region| will contain the intersected parts after calling this function: | |
170 CombineRgn(region, animation_region, region, RGN_AND); | |
171 DeleteObject(animation_region); | |
172 | |
173 // Next, we need to increase the region a little bit to account for the | |
174 // curved edges that the view will draw to make it look like grows out of | |
175 // the toolbar. | |
176 POINT left_curve[] = { | |
177 {0, y+0}, {0, y+1}, {2, y+3}, {2, y+0}, {0, y+0} | |
178 }; | |
179 POINT right_curve[] = { | |
180 {w+3, y+3}, {w+6, y+0}, {w+3, y+0}, {w+3, y+3} | |
181 }; | |
182 | |
183 // Combine the region for the curve on the left with our main region. | |
184 HRGN r = CreatePolygonRgn(left_curve, arraysize(left_curve), ALTERNATE); | |
185 CombineRgn(region, r, region, RGN_OR); | |
186 DeleteObject(r); | |
187 | |
188 // Combine the region for the curve on the right with our main region. | |
189 r = CreatePolygonRgn(right_curve, arraysize(right_curve), ALTERNATE); | |
190 CombineRgn(region, r, region, RGN_OR); | |
191 DeleteObject(r); | |
192 } | |
193 | |
194 // Now see if we need to truncate the region because parts of it obscures | |
195 // the main window border. | |
196 gfx::Rect dialog_bounds; | |
197 GetDialogBounds(&dialog_bounds); | |
198 | |
199 // Calculate how much our current position overlaps our boundaries. If we | |
200 // overlap, it means we have too little space to draw the whole dialog and | |
201 // we allow overwriting the scrollbar before we start truncating our dialog. | |
202 // | |
203 // TODO(brettw) this constant is evil. This is the amount of room we've added | |
204 // to the window size, when we set the region, it can change the size. | |
205 static const int kAddedWidth = 7; | |
206 int difference = (new_pos.right() - kAddedWidth) - | |
207 dialog_bounds.width() - | |
208 views::NativeScrollBar::GetVerticalScrollBarWidth() + | |
209 1; | |
210 if (difference > 0) { | |
211 POINT exclude[4] = {0}; | |
212 exclude[0].x = max_x - difference; // Top left corner. | |
213 exclude[0].y = 0; | |
214 | |
215 exclude[1].x = max_x; // Top right corner. | |
216 exclude[1].y = 0; | |
217 | |
218 exclude[2].x = max_x; // Bottom right corner. | |
219 exclude[2].y = max_y; | |
220 | |
221 exclude[3].x = max_x - difference; // Bottom left corner. | |
222 exclude[3].y = max_y; | |
223 | |
224 // Subtract this region from the original region. | |
225 HRGN exclude_rgn = CreatePolygonRgn(exclude, arraysize(exclude), ALTERNATE); | |
226 int result = CombineRgn(region, region, exclude_rgn, RGN_DIFF); | |
227 DeleteObject(exclude_rgn); | |
228 } | |
229 | |
230 // The system now owns the region, so we do not delete it. | |
231 host_->SetWindowRgn(region, TRUE); // TRUE = Redraw. | |
232 #endif | |
233 } | |
234 | |
235 void FindBarWin::Show() { | |
236 if (disable_animations_during_testing_) { | 75 if (disable_animations_during_testing_) { |
237 animation_->Reset(1); | 76 animation_->Reset(1); |
238 MoveWindowIfNecessary(gfx::Rect(), true); | 77 MoveWindowIfNecessary(gfx::Rect(), true); |
239 } else { | 78 } else { |
240 animation_->Reset(); | 79 animation_->Reset(); |
241 animation_->Show(); | 80 animation_->Show(); |
242 } | 81 } |
243 } | 82 } |
244 | 83 |
245 void FindBarWin::SetFocusAndSelection() { | 84 void FindBarHost::SetFocusAndSelection() { |
246 view_->SetFocusAndSelection(); | 85 view_->SetFocusAndSelection(); |
247 } | 86 } |
248 | 87 |
249 bool FindBarWin::IsAnimating() { | 88 bool FindBarHost::IsAnimating() { |
250 return animation_->IsAnimating(); | 89 return animation_->IsAnimating(); |
251 } | 90 } |
252 | 91 |
253 void FindBarWin::Hide(bool animate) { | 92 void FindBarHost::Hide(bool animate) { |
254 if (animate && !disable_animations_during_testing_) { | 93 if (animate && !disable_animations_during_testing_) { |
255 animation_->Reset(1.0); | 94 animation_->Reset(1.0); |
256 animation_->Hide(); | 95 animation_->Hide(); |
257 } else { | 96 } else { |
258 host_->Hide(); | 97 host_->Hide(); |
259 } | 98 } |
260 } | 99 } |
261 | 100 |
262 void FindBarWin::ClearResults(const FindNotificationDetails& results) { | 101 void FindBarHost::ClearResults(const FindNotificationDetails& results) { |
263 view_->UpdateForResult(results, string16()); | 102 view_->UpdateForResult(results, string16()); |
264 } | 103 } |
265 | 104 |
266 void FindBarWin::StopAnimation() { | 105 void FindBarHost::StopAnimation() { |
267 animation_->End(); | 106 animation_->End(); |
268 } | 107 } |
269 | 108 |
270 void FindBarWin::SetFindText(const string16& find_text) { | 109 void FindBarHost::SetFindText(const string16& find_text) { |
271 view_->SetFindText(find_text); | 110 view_->SetFindText(find_text); |
272 } | 111 } |
273 | 112 |
274 bool FindBarWin::IsFindBarVisible() { | 113 bool FindBarHost::IsFindBarVisible() { |
275 return host_->IsVisible(); | 114 return host_->IsVisible(); |
276 } | 115 } |
277 | 116 |
278 void FindBarWin::MoveWindowIfNecessary(const gfx::Rect& selection_rect, | 117 void FindBarHost::MoveWindowIfNecessary(const gfx::Rect& selection_rect, |
279 bool no_redraw) { | 118 bool no_redraw) { |
280 // We only move the window if one is active for the current TabContents. If we | 119 // We only move the window if one is active for the current TabContents. If we |
281 // don't check this, then SetDialogPosition below will end up making the Find | 120 // don't check this, then SetDialogPosition below will end up making the Find |
282 // Bar visible. | 121 // Bar visible. |
283 if (!find_bar_controller_->tab_contents() || | 122 if (!find_bar_controller_->tab_contents() || |
284 !find_bar_controller_->tab_contents()->find_ui_active()) { | 123 !find_bar_controller_->tab_contents()->find_ui_active()) { |
285 return; | 124 return; |
286 } | 125 } |
287 | 126 |
288 gfx::Rect new_pos = GetDialogPosition(selection_rect); | 127 gfx::Rect new_pos = GetDialogPosition(selection_rect); |
289 SetDialogPosition(new_pos, no_redraw); | 128 SetDialogPosition(new_pos, no_redraw); |
290 | 129 |
291 // May need to redraw our frame to accommodate bookmark bar styles. | 130 // May need to redraw our frame to accommodate bookmark bar styles. |
292 view_->SchedulePaint(); | 131 view_->SchedulePaint(); |
293 } | 132 } |
294 | 133 |
295 #if defined(OS_WIN) | 134 void FindBarHost::OnFinalMessage() { |
296 bool FindBarWin::MaybeForwardKeystrokeToWebpage( | |
297 UINT message, TCHAR key, UINT flags) { | |
298 // We specifically ignore WM_CHAR. See http://crbug.com/10509. | |
299 if (message != WM_KEYDOWN && message != WM_KEYUP) | |
300 return false; | |
301 | |
302 switch (key) { | |
303 case VK_HOME: | |
304 case VK_END: | |
305 // Ctrl+Home and Ctrl+End should be forwarded to the page. | |
306 if (GetKeyState(VK_CONTROL) >= 0) | |
307 return false; // Ctrl not pressed: Abort. Otherwise fall through. | |
308 case VK_UP: | |
309 case VK_DOWN: | |
310 case VK_PRIOR: // Page up | |
311 case VK_NEXT: // Page down | |
312 break; // The keys above are the ones we want to forward to the page. | |
313 default: | |
314 return false; | |
315 } | |
316 | |
317 TabContents* contents = find_bar_controller_->tab_contents(); | |
318 if (!contents) | |
319 return false; | |
320 | |
321 RenderViewHost* render_view_host = contents->render_view_host(); | |
322 | |
323 // Make sure we don't have a text field element interfering with keyboard | |
324 // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom". | |
325 render_view_host->ClearFocusedNode(); | |
326 | |
327 HWND hwnd = contents->GetContentNativeView(); | |
328 render_view_host->ForwardKeyboardEvent( | |
329 NativeWebKeyboardEvent(hwnd, message, key, 0)); | |
330 return true; | |
331 } | |
332 #endif | |
333 | |
334 void FindBarWin::OnFinalMessage() { | |
335 // TODO(beng): Destroy the RootView before destroying the Focus Manager will | 135 // TODO(beng): Destroy the RootView before destroying the Focus Manager will |
336 // allow us to remove this method. | 136 // allow us to remove this method. |
337 | 137 |
338 // We are exiting, so we no longer need to monitor focus changes. | 138 // We are exiting, so we no longer need to monitor focus changes. |
339 focus_manager_->RemoveFocusChangeListener(this); | 139 focus_manager_->RemoveFocusChangeListener(this); |
340 | 140 |
341 // Destroy the focus tracker now, otherwise by the time we're destroyed the | 141 // Destroy the focus tracker now, otherwise by the time we're destroyed the |
342 // focus manager the focus tracker is referencing may have already been | 142 // focus manager the focus tracker is referencing may have already been |
343 // destroyed resulting in the focus tracker trying to reference a deleted | 143 // destroyed resulting in the focus tracker trying to reference a deleted |
344 // focus manager. | 144 // focus manager. |
345 focus_tracker_.reset(NULL); | 145 focus_tracker_.reset(NULL); |
346 }; | 146 }; |
347 | 147 |
348 bool FindBarWin::IsVisible() { | 148 bool FindBarHost::IsVisible() { |
349 return host_->IsVisible(); | 149 return host_->IsVisible(); |
350 } | 150 } |
351 | 151 |
352 //////////////////////////////////////////////////////////////////////////////// | 152 //////////////////////////////////////////////////////////////////////////////// |
353 // FindBarWin, views::FocusChangeListener implementation: | 153 // FindBarHost, views::FocusChangeListener implementation: |
354 | 154 |
355 void FindBarWin::FocusWillChange(views::View* focused_before, | 155 void FindBarHost::FocusWillChange(views::View* focused_before, |
356 views::View* focused_now) { | 156 views::View* focused_now) { |
357 // First we need to determine if one or both of the views passed in are child | 157 // First we need to determine if one or both of the views passed in are child |
358 // views of our view. | 158 // views of our view. |
359 bool our_view_before = focused_before && view_->IsParentOf(focused_before); | 159 bool our_view_before = focused_before && view_->IsParentOf(focused_before); |
360 bool our_view_now = focused_now && view_->IsParentOf(focused_now); | 160 bool our_view_now = focused_now && view_->IsParentOf(focused_now); |
361 | 161 |
362 // When both our_view_before and our_view_now are false, it means focus is | 162 // When both our_view_before and our_view_now are false, it means focus is |
363 // changing hands elsewhere in the application (and we shouldn't do anything). | 163 // changing hands elsewhere in the application (and we shouldn't do anything). |
364 // Similarly, when both are true, focus is changing hands within the Find | 164 // Similarly, when both are true, focus is changing hands within the Find |
365 // window (and again, we should not do anything). We therefore only need to | 165 // window (and again, we should not do anything). We therefore only need to |
366 // look at when we gain initial focus and when we loose it. | 166 // look at when we gain initial focus and when we loose it. |
367 if (!our_view_before && our_view_now) { | 167 if (!our_view_before && our_view_now) { |
368 // We are gaining focus from outside the Find window so we must register | 168 // We are gaining focus from outside the Find window so we must register |
369 // a handler for Escape. | 169 // a handler for Escape. |
370 RegisterEscAccelerator(); | 170 RegisterEscAccelerator(); |
371 } else if (our_view_before && !our_view_now) { | 171 } else if (our_view_before && !our_view_now) { |
372 // We are losing focus to something outside our window so we restore the | 172 // We are losing focus to something outside our window so we restore the |
373 // original handler for Escape. | 173 // original handler for Escape. |
374 UnregisterEscAccelerator(); | 174 UnregisterEscAccelerator(); |
375 } | 175 } |
376 } | 176 } |
377 | 177 |
378 //////////////////////////////////////////////////////////////////////////////// | 178 //////////////////////////////////////////////////////////////////////////////// |
379 // FindBarWin, views::AcceleratorTarget implementation: | 179 // FindBarWin, views::AcceleratorTarget implementation: |
380 | 180 |
381 bool FindBarWin::AcceleratorPressed(const views::Accelerator& accelerator) { | 181 bool FindBarHost::AcceleratorPressed(const views::Accelerator& accelerator) { |
382 #if defined(OS_WIN) | 182 #if defined(OS_WIN) |
383 DCHECK(accelerator.GetKeyCode() == VK_ESCAPE); // We only expect Escape key. | 183 DCHECK(accelerator.GetKeyCode() == VK_ESCAPE); // We only expect Escape key. |
384 #endif | 184 #endif |
385 // This will end the Find session and hide the window, causing it to loose | 185 // This will end the Find session and hide the window, causing it to loose |
386 // focus and in the process unregister us as the handler for the Escape | 186 // focus and in the process unregister us as the handler for the Escape |
387 // accelerator through the FocusWillChange event. | 187 // accelerator through the FocusWillChange event. |
388 find_bar_controller_->EndFindSession(); | 188 find_bar_controller_->EndFindSession(); |
389 | 189 |
390 return true; | 190 return true; |
391 } | 191 } |
392 | 192 |
393 //////////////////////////////////////////////////////////////////////////////// | 193 //////////////////////////////////////////////////////////////////////////////// |
394 // FindBarWin, AnimationDelegate implementation: | 194 // FindBarHost, AnimationDelegate implementation: |
395 | 195 |
396 void FindBarWin::AnimationProgressed(const Animation* animation) { | 196 void FindBarHost::AnimationProgressed(const Animation* animation) { |
397 // First, we calculate how many pixels to slide the window. | 197 // First, we calculate how many pixels to slide the window. |
398 gfx::Size pref_size = view_->GetPreferredSize(); | 198 gfx::Size pref_size = view_->GetPreferredSize(); |
399 find_dialog_animation_offset_ = | 199 find_dialog_animation_offset_ = |
400 static_cast<int>((1.0 - animation_->GetCurrentValue()) * | 200 static_cast<int>((1.0 - animation_->GetCurrentValue()) * |
401 pref_size.height()); | 201 pref_size.height()); |
402 | 202 |
403 // This call makes sure it appears in the right location, the size and shape | 203 // This call makes sure it appears in the right location, the size and shape |
404 // is correct and that it slides in the right direction. | 204 // is correct and that it slides in the right direction. |
405 gfx::Rect find_dlg_rect = GetDialogPosition(gfx::Rect()); | 205 gfx::Rect find_dlg_rect = GetDialogPosition(gfx::Rect()); |
406 SetDialogPosition(find_dlg_rect, false); | 206 SetDialogPosition(find_dlg_rect, false); |
407 | 207 |
408 // Let the view know if we are animating, and at which offset to draw the | 208 // Let the view know if we are animating, and at which offset to draw the |
409 // edges. | 209 // edges. |
410 view_->animation_offset(find_dialog_animation_offset_); | 210 view_->animation_offset(find_dialog_animation_offset_); |
411 view_->SchedulePaint(); | 211 view_->SchedulePaint(); |
412 } | 212 } |
413 | 213 |
414 void FindBarWin::AnimationEnded(const Animation* animation) { | 214 void FindBarHost::AnimationEnded(const Animation* animation) { |
415 // Place the find bar in its fully opened state. | 215 // Place the find bar in its fully opened state. |
416 find_dialog_animation_offset_ = 0; | 216 find_dialog_animation_offset_ = 0; |
417 | 217 |
418 if (!animation_->IsShowing()) { | 218 if (!animation_->IsShowing()) { |
419 // Animation has finished closing. | 219 // Animation has finished closing. |
420 host_->Hide(); | 220 host_->Hide(); |
421 } else { | 221 } else { |
422 // Animation has finished opening. | 222 // Animation has finished opening. |
423 } | 223 } |
424 } | 224 } |
425 | 225 |
426 void FindBarWin::GetThemePosition(gfx::Rect* bounds) { | 226 void FindBarHost::GetThemePosition(gfx::Rect* bounds) { |
427 *bounds = GetDialogPosition(gfx::Rect()); | 227 *bounds = GetDialogPosition(gfx::Rect()); |
428 gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); | 228 gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds(); |
429 gfx::Rect tab_strip_bounds = browser_view_->GetTabStripBounds(); | 229 gfx::Rect tab_strip_bounds = browser_view_->GetTabStripBounds(); |
430 bounds->Offset(-toolbar_bounds.x(), -tab_strip_bounds.y()); | 230 bounds->Offset(-toolbar_bounds.x(), -tab_strip_bounds.y()); |
431 } | 231 } |
432 | 232 |
433 //////////////////////////////////////////////////////////////////////////////// | 233 //////////////////////////////////////////////////////////////////////////////// |
434 // FindBarTesting implementation: | 234 // FindBarTesting implementation: |
435 | 235 |
436 bool FindBarWin::GetFindBarWindowInfo(gfx::Point* position, | 236 bool FindBarHost::GetFindBarWindowInfo(gfx::Point* position, |
437 bool* fully_visible) { | 237 bool* fully_visible) { |
438 if (!find_bar_controller_ || | 238 if (!find_bar_controller_ || |
439 #if defined(OS_WIN) | 239 #if defined(OS_WIN) |
440 !::IsWindow(host_->GetNativeView())) { | 240 !::IsWindow(host_->GetNativeView())) { |
441 #else | 241 #else |
442 false) { | 242 false) { |
443 // TODO(sky): figure out linux side. | 243 // TODO(sky): figure out linux side. |
444 #endif | 244 #endif |
445 *position = gfx::Point(); | 245 *position = gfx::Point(); |
446 *fully_visible = false; | 246 *fully_visible = false; |
447 return false; | 247 return false; |
448 } | 248 } |
449 | 249 |
450 gfx::Rect window_rect; | 250 gfx::Rect window_rect; |
451 host_->GetBounds(&window_rect, true); | 251 host_->GetBounds(&window_rect, true); |
452 *position = window_rect.origin(); | 252 *position = window_rect.origin(); |
453 *fully_visible = host_->IsVisible() && !IsAnimating(); | 253 *fully_visible = host_->IsVisible() && !IsAnimating(); |
454 return true; | 254 return true; |
455 } | 255 } |
456 | 256 |
457 void FindBarWin::GetDialogBounds(gfx::Rect* bounds) { | 257 void FindBarHost::GetDialogBounds(gfx::Rect* bounds) { |
458 DCHECK(bounds); | 258 DCHECK(bounds); |
459 // The BrowserView does Layout for the components that we care about | 259 // The BrowserView does Layout for the components that we care about |
460 // positioning relative to, so we ask it to tell us where we should go. | 260 // positioning relative to, so we ask it to tell us where we should go. |
461 *bounds = browser_view_->GetFindBarBoundingBox(); | 261 *bounds = browser_view_->GetFindBarBoundingBox(); |
462 } | 262 } |
463 | 263 |
464 gfx::Rect FindBarWin::GetDialogPosition(gfx::Rect avoid_overlapping_rect) { | 264 gfx::Rect FindBarHost::GetDialogPosition(gfx::Rect avoid_overlapping_rect) { |
465 // Find the area we have to work with (after accounting for scrollbars, etc). | 265 // Find the area we have to work with (after accounting for scrollbars, etc). |
466 gfx::Rect dialog_bounds; | 266 gfx::Rect dialog_bounds; |
467 GetDialogBounds(&dialog_bounds); | 267 GetDialogBounds(&dialog_bounds); |
468 if (dialog_bounds.IsEmpty()) | 268 if (dialog_bounds.IsEmpty()) |
469 return gfx::Rect(); | 269 return gfx::Rect(); |
470 | 270 |
471 // Ask the view how large an area it needs to draw on. | 271 // Ask the view how large an area it needs to draw on. |
472 gfx::Size prefsize = view_->GetPreferredSize(); | 272 gfx::Size prefsize = view_->GetPreferredSize(); |
473 | 273 |
474 // Place the view in the top right corner of the dialog boundaries (top left | 274 // Place the view in the top right corner of the dialog boundaries (top left |
475 // for RTL languages). | 275 // for RTL languages). |
476 gfx::Rect view_location; | 276 gfx::Rect view_location; |
477 int x = view_->UILayoutIsRightToLeft() ? | 277 int x = view_->UILayoutIsRightToLeft() ? |
478 dialog_bounds.x() : dialog_bounds.width() - prefsize.width(); | 278 dialog_bounds.x() : dialog_bounds.width() - prefsize.width(); |
479 int y = dialog_bounds.y(); | 279 int y = dialog_bounds.y(); |
480 view_location.SetRect(x, y, prefsize.width(), prefsize.height()); | 280 view_location.SetRect(x, y, prefsize.width(), prefsize.height()); |
481 | 281 |
482 // When we get Find results back, we specify a selection rect, which we | 282 // When we get Find results back, we specify a selection rect, which we |
483 // should strive to avoid overlapping. But first, we need to offset the | 283 // should strive to avoid overlapping. But first, we need to offset the |
484 // selection rect (if one was provided). | 284 // selection rect (if one was provided). |
485 if (!avoid_overlapping_rect.IsEmpty()) { | 285 if (!avoid_overlapping_rect.IsEmpty()) { |
486 // For comparison (with the Intersects function below) we need to account | 286 // For comparison (with the Intersects function below) we need to account |
487 // for the fact that we draw the Find dialog relative to the window, | 287 // for the fact that we draw the Find dialog relative to the window, |
488 // whereas the selection rect is relative to the page. | 288 // whereas the selection rect is relative to the page. |
489 #if defined(OS_WIN) | 289 GetDialogPositionNative(&avoid_overlapping_rect); |
490 RECT frame_rect = {0}, webcontents_rect = {0}; | |
491 ::GetWindowRect(host_->GetParent(), &frame_rect); | |
492 ::GetWindowRect( | |
493 find_bar_controller_->tab_contents()->view()->GetNativeView(), | |
494 &webcontents_rect); | |
495 avoid_overlapping_rect.Offset(0, webcontents_rect.top - frame_rect.top); | |
496 #else | |
497 NOTIMPLEMENTED(); | |
498 #endif | |
499 } | 290 } |
500 | 291 |
501 gfx::Rect new_pos = FindBarController::GetLocationForFindbarView( | 292 gfx::Rect new_pos = FindBarController::GetLocationForFindbarView( |
502 view_location, dialog_bounds, avoid_overlapping_rect); | 293 view_location, dialog_bounds, avoid_overlapping_rect); |
503 | 294 |
504 // While we are animating, the Find window will grow bottoms up so we need to | 295 // While we are animating, the Find window will grow bottoms up so we need to |
505 // re-position the dialog so that it appears to grow out of the toolbar. | 296 // re-position the dialog so that it appears to grow out of the toolbar. |
506 if (find_dialog_animation_offset_ > 0) | 297 if (find_dialog_animation_offset_ > 0) |
507 new_pos.Offset(0, std::min(0, -find_dialog_animation_offset_)); | 298 new_pos.Offset(0, std::min(0, -find_dialog_animation_offset_)); |
508 | 299 |
509 return new_pos; | 300 return new_pos; |
510 } | 301 } |
511 | 302 |
512 void FindBarWin::SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw) { | 303 void FindBarHost::SetDialogPosition(const gfx::Rect& new_pos, bool no_redraw) { |
513 if (new_pos.IsEmpty()) | 304 if (new_pos.IsEmpty()) |
514 return; | 305 return; |
515 | 306 |
516 // Make sure the window edges are clipped to just the visible region. We need | 307 // Make sure the window edges are clipped to just the visible region. We need |
517 // to do this before changing position, so that when we animate the closure | 308 // to do this before changing position, so that when we animate the closure |
518 // of it it doesn't look like the window crumbles into the toolbar. | 309 // of it it doesn't look like the window crumbles into the toolbar. |
519 UpdateWindowEdges(new_pos); | 310 UpdateWindowEdges(new_pos); |
520 | 311 |
521 #if defined(OS_WIN) | 312 SetDialogPositionNative(new_pos, no_redraw); |
522 gfx::Rect window_rect; | |
523 host_->GetBounds(&window_rect, true); | |
524 DWORD swp_flags = SWP_NOOWNERZORDER; | |
525 if (!window_rect.IsEmpty()) | |
526 swp_flags |= SWP_NOSIZE; | |
527 if (no_redraw) | |
528 swp_flags |= SWP_NOREDRAW; | |
529 if (!host_->IsVisible()) | |
530 swp_flags |= SWP_SHOWWINDOW; | |
531 | |
532 ::SetWindowPos(host_->GetNativeView(), HWND_TOP, new_pos.x(), new_pos.y(), | |
533 new_pos.width(), new_pos.height(), swp_flags); | |
534 #else | |
535 host_->SetBounds(new_pos); | |
536 #endif | |
537 } | 313 } |
538 | 314 |
539 void FindBarWin::RestoreSavedFocus() { | 315 void FindBarHost::RestoreSavedFocus() { |
540 if (focus_tracker_.get() == NULL) { | 316 if (focus_tracker_.get() == NULL) { |
541 // TODO(brettw) Focus() should be on TabContentsView. | 317 // TODO(brettw) Focus() should be on TabContentsView. |
542 find_bar_controller_->tab_contents()->Focus(); | 318 find_bar_controller_->tab_contents()->Focus(); |
543 } else { | 319 } else { |
544 focus_tracker_->FocusLastFocusedExternalView(); | 320 focus_tracker_->FocusLastFocusedExternalView(); |
545 } | 321 } |
546 } | 322 } |
547 | 323 |
548 FindBarTesting* FindBarWin::GetFindBarTesting() { | 324 FindBarTesting* FindBarHost::GetFindBarTesting() { |
549 return this; | 325 return this; |
550 } | 326 } |
551 | 327 |
552 void FindBarWin::RegisterEscAccelerator() { | 328 void FindBarHost::UpdateUIForFindResult(const FindNotificationDetails& result, |
553 #if defined(OS_WIN) | |
554 DCHECK(!esc_accel_target_registered_); | |
555 views::Accelerator escape(VK_ESCAPE, false, false, false); | |
556 focus_manager_->RegisterAccelerator(escape, this); | |
557 esc_accel_target_registered_ = true; | |
558 #else | |
559 NOTIMPLEMENTED(); | |
560 #endif | |
561 } | |
562 | |
563 void FindBarWin::UnregisterEscAccelerator() { | |
564 #if defined(OS_WIN) | |
565 DCHECK(esc_accel_target_registered_); | |
566 views::Accelerator escape(VK_ESCAPE, false, false, false); | |
567 focus_manager_->UnregisterAccelerator(escape, this); | |
568 esc_accel_target_registered_ = false; | |
569 #else | |
570 NOTIMPLEMENTED(); | |
571 #endif | |
572 } | |
573 | |
574 void FindBarWin::UpdateUIForFindResult(const FindNotificationDetails& result, | |
575 const string16& find_text) { | 329 const string16& find_text) { |
576 view_->UpdateForResult(result, find_text); | 330 view_->UpdateForResult(result, find_text); |
577 | 331 |
578 // We now need to check if the window is obscuring the search results. | 332 // We now need to check if the window is obscuring the search results. |
579 if (!result.selection_rect().IsEmpty()) | 333 if (!result.selection_rect().IsEmpty()) |
580 MoveWindowIfNecessary(result.selection_rect(), false); | 334 MoveWindowIfNecessary(result.selection_rect(), false); |
581 | 335 |
582 // Once we find a match we no longer want to keep track of what had | 336 // Once we find a match we no longer want to keep track of what had |
583 // focus. EndFindSession will then set the focus to the page content. | 337 // focus. EndFindSession will then set the focus to the page content. |
584 if (result.number_of_matches() > 0) | 338 if (result.number_of_matches() > 0) |
585 focus_tracker_.reset(NULL); | 339 focus_tracker_.reset(NULL); |
586 } | 340 } |
587 | 341 |
588 void FindBarWin::AudibleAlert() { | 342 void FindBarHost::RegisterEscAccelerator() { |
589 #if defined(OS_WIN) | 343 DCHECK(!esc_accel_target_registered_); |
590 MessageBeep(MB_OK); | 344 views::Accelerator escape(base::VKEY_ESCAPE, false, false, false); |
591 #else | 345 focus_manager_->RegisterAccelerator(escape, this); |
592 NOTIMPLEMENTED(); | 346 esc_accel_target_registered_ = true; |
593 #endif | |
594 } | 347 } |
| 348 |
| 349 void FindBarHost::UnregisterEscAccelerator() { |
| 350 DCHECK(esc_accel_target_registered_); |
| 351 views::Accelerator escape(base::VKEY_ESCAPE, false, false, false); |
| 352 focus_manager_->UnregisterAccelerator(escape, this); |
| 353 esc_accel_target_registered_ = false; |
| 354 } |
| 355 |
| 356 bool FindBarHost::MaybeForwardKeystrokeToWebpage( |
| 357 const views::Textfield::Keystroke& key_stroke) { |
| 358 switch (key_stroke.GetKeyboardCode()) { |
| 359 case base::VKEY_DOWN: |
| 360 case base::VKEY_UP: |
| 361 case base::VKEY_PRIOR: |
| 362 case base::VKEY_NEXT: |
| 363 break; |
| 364 case base::VKEY_HOME: |
| 365 case base::VKEY_END: |
| 366 if (key_stroke.IsControlHeld()) |
| 367 break; |
| 368 // Fall through. |
| 369 default: |
| 370 return false; |
| 371 } |
| 372 |
| 373 TabContents* contents = find_bar_controller_->tab_contents(); |
| 374 if (!contents) |
| 375 return false; |
| 376 |
| 377 RenderViewHost* render_view_host = contents->render_view_host(); |
| 378 |
| 379 // Make sure we don't have a text field element interfering with keyboard |
| 380 // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom". |
| 381 render_view_host->ClearFocusedNode(); |
| 382 NativeWebKeyboardEvent event = GetKeyboardEvent(contents, key_stroke); |
| 383 render_view_host->ForwardKeyboardEvent(event); |
| 384 return true; |
| 385 } |
| 386 |
| 387 |
OLD | NEW |