OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 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/chromeos/app_launcher.h" | 5 #include "chrome/browser/views/app_launcher.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "app/gfx/canvas.h" | |
11 #include "app/gfx/insets.h" | |
12 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
13 #include "base/command_line.h" | 11 #include "base/command_line.h" |
14 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
15 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "base/task.h" |
16 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 15 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
17 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" | 16 #include "chrome/browser/autocomplete/autocomplete_edit_view.h" |
18 #include "chrome/browser/browser.h" | 17 #include "chrome/browser/browser.h" |
19 #include "chrome/browser/browser_list.h" | |
20 #include "chrome/browser/browser_window.h" | 18 #include "chrome/browser/browser_window.h" |
21 #include "chrome/browser/bubble_positioner.h" | 19 #include "chrome/browser/bubble_positioner.h" |
22 #include "chrome/browser/chromeos/frame/browser_view.h" | |
23 #include "chrome/browser/chromeos/status/status_area_view.h" | |
24 #include "chrome/browser/chromeos/wm_ipc.h" | |
25 #include "chrome/browser/in_process_webkit/dom_storage_context.h" | |
26 #include "chrome/browser/in_process_webkit/webkit_context.h" | 20 #include "chrome/browser/in_process_webkit/webkit_context.h" |
27 #include "chrome/browser/profile.h" | 21 #include "chrome/browser/profile.h" |
28 #include "chrome/browser/renderer_host/render_view_host.h" | 22 #include "chrome/browser/renderer_host/render_view_host.h" |
29 #include "chrome/browser/renderer_host/render_view_host_factory.h" | 23 #include "chrome/browser/renderer_host/render_view_host_factory.h" |
30 #include "chrome/browser/renderer_host/render_widget_host_view.h" | 24 #include "chrome/browser/renderer_host/render_widget_host_view.h" |
31 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" | |
32 #include "chrome/browser/renderer_host/site_instance.h" | 25 #include "chrome/browser/renderer_host/site_instance.h" |
33 #include "chrome/browser/renderer_preferences_util.h" | 26 #include "chrome/browser/renderer_preferences_util.h" |
34 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" | 27 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" |
35 #include "chrome/browser/tab_contents/tab_contents.h" | 28 #include "chrome/browser/tab_contents/tab_contents.h" |
36 #include "chrome/browser/views/bubble_border.h" | 29 #include "chrome/browser/views/info_bubble.h" |
37 #include "grit/app_resources.h" | 30 #include "chrome/browser/views/frame/browser_view.h" |
38 #include "grit/generated_resources.h" | |
39 #include "grit/theme_resources.h" | |
40 #include "third_party/skia/include/core/SkBitmap.h" | |
41 #include "views/background.h" | |
42 #include "views/controls/native/native_view_host.h" | 31 #include "views/controls/native/native_view_host.h" |
43 #include "views/painter.h" | |
44 #include "views/screen.h" | |
45 #include "views/widget/root_view.h" | 32 #include "views/widget/root_view.h" |
46 #include "views/widget/widget_gtk.h" | 33 #include "views/widget/widget.h" |
| 34 |
| 35 #if defined(OS_WIN) |
| 36 #include "chrome/browser/autocomplete/autocomplete_edit_view_win.h" |
| 37 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" |
| 38 #elif defined(OS_LINUX) |
| 39 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" |
| 40 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" |
| 41 #endif |
| 42 #if defined(OS_CHROMEOS) |
| 43 #include "chrome/browser/chromeos/status/status_area_view.h" |
| 44 #endif |
47 | 45 |
48 namespace { | 46 namespace { |
49 | 47 |
50 // Padding & margins for the navigation entry. | 48 // Padding & margins for the navigation entry. |
51 const int kNavigationEntryPadding = 2; | 49 const int kNavigationEntryPadding = 2; |
52 const int kNavigationEntryXMargin = 3; | 50 const int kNavigationEntryXMargin = 3; |
53 const int kNavigationEntryYMargin = 1; | 51 const int kNavigationEntryYMargin = 1; |
54 | 52 |
55 // NavigationBar size. | 53 // NavigationBar size. |
56 const int kNavigationBarHeight = 25; | 54 const int kNavigationBarHeight = 25; |
57 | 55 |
58 // Padding for the bubble info window. | 56 // The delta applied to the default font size for the omnibox. |
59 const int kBubbleWindowXPadding = 6; | 57 const int kAutocompleteEditFontDelta = 3; |
60 const int kBubbleWindowYPadding = 16; | |
61 | 58 |
62 // Command line switch for specifying url of the page. | 59 // Command line switch for specifying url of the page. |
63 const wchar_t kURLSwitch[] = L"main-menu-url"; | 60 const wchar_t kURLSwitch[] = L"main-menu-url"; |
64 | 61 |
65 // Command line switch for specifying the size of the main menu. The default is | |
66 // full screen. | |
67 const wchar_t kMenuSizeSwitch[] = L"main-menu-size"; | |
68 | |
69 // URL of the page to load. This is ignored if kURLSwitch is specified. | 62 // URL of the page to load. This is ignored if kURLSwitch is specified. |
70 const char kMenuURL[] = "http://goto.ext.google.com/crux-home"; | 63 const char kMenuURL[] = "http://goto.ext.google.com/crux-home"; |
71 | 64 |
72 // Returns the URL of the menu. | 65 // Returns the URL of the menu. |
73 static GURL GetMenuURL() { | 66 static GURL GetMenuURL() { |
74 std::wstring url_string = | 67 std::wstring url_string = |
75 CommandLine::ForCurrentProcess()->GetSwitchValue(kURLSwitch); | 68 CommandLine::ForCurrentProcess()->GetSwitchValue(kURLSwitch); |
76 if (!url_string.empty()) | 69 if (!url_string.empty()) |
77 return GURL(WideToUTF8(url_string)); | 70 return GURL(WideToUTF8(url_string)); |
78 return GURL(kMenuURL); | 71 return GURL(kMenuURL); |
79 } | 72 } |
80 | 73 |
81 // RenderWidgetHostViewGtk propagates the mouse press events (see | 74 // RenderWidgetHostViewGtk propagates the mouse press events (see |
82 // render_widget_host_view_gtk.cc). We subclass to stop the propagation here, | 75 // render_widget_host_view_gtk.cc). We subclass to stop the propagation here, |
83 // as if the click event was propagated it would reach the TopContainer view and | 76 // as if the click event was propagated it would reach the TopContainer view and |
84 // it would close the popup. | 77 // it would close the popup. |
85 class RWHVNativeViewHost : public views::NativeViewHost { | 78 class RWHVNativeViewHost : public views::NativeViewHost { |
86 public: | 79 public: |
87 RWHVNativeViewHost() {} | 80 RWHVNativeViewHost() {} |
88 | 81 |
89 virtual bool OnMousePressed(const views::MouseEvent& event) { return true; } | 82 virtual bool OnMousePressed(const views::MouseEvent& event) { return true; } |
90 | 83 |
91 private: | 84 private: |
92 DISALLOW_COPY_AND_ASSIGN(RWHVNativeViewHost); | 85 DISALLOW_COPY_AND_ASSIGN(RWHVNativeViewHost); |
93 }; | 86 }; |
94 | 87 |
95 } // namspace | 88 } // namespace |
96 | 89 |
97 namespace chromeos { | 90 //////////////////////////////////////////////////////////////////////////////// |
| 91 // TabContentsDelegateImpl |
| 92 // |
| 93 // TabContentsDelegate and RenderViewHostDelegate::View have some methods |
| 94 // in common (with differing signatures). The TabContentsDelegate methods are |
| 95 // implemented by this class. |
| 96 |
| 97 class TabContentsDelegateImpl : public TabContentsDelegate { |
| 98 public: |
| 99 explicit TabContentsDelegateImpl(AppLauncher* app_launcher); |
| 100 |
| 101 // TabContentsDelegate. |
| 102 virtual void OpenURLFromTab(TabContents* source, |
| 103 const GURL& url, const GURL& referrer, |
| 104 WindowOpenDisposition disposition, |
| 105 PageTransition::Type transition); |
| 106 virtual void NavigationStateChanged(const TabContents* source, |
| 107 unsigned changed_flags) {} |
| 108 virtual void AddNewContents(TabContents* source, |
| 109 TabContents* new_contents, |
| 110 WindowOpenDisposition disposition, |
| 111 const gfx::Rect& initial_pos, |
| 112 bool user_gesture) {} |
| 113 virtual void ActivateContents(TabContents* contents) {} |
| 114 virtual void LoadingStateChanged(TabContents* source) {} |
| 115 virtual void CloseContents(TabContents* source) {} |
| 116 virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {} |
| 117 virtual bool IsPopup(TabContents* source) { return false; } |
| 118 virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {} |
| 119 virtual void URLStarredChanged(TabContents* source, bool starred) {} |
| 120 virtual void UpdateTargetURL(TabContents* source, const GURL& url) {} |
| 121 |
| 122 private: |
| 123 AppLauncher* app_launcher_; |
| 124 |
| 125 DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl); |
| 126 }; |
| 127 |
| 128 TabContentsDelegateImpl::TabContentsDelegateImpl(AppLauncher* app_launcher) |
| 129 : app_launcher_(app_launcher) { |
| 130 } |
| 131 |
| 132 void TabContentsDelegateImpl::OpenURLFromTab(TabContents* source, |
| 133 const GURL& url, |
| 134 const GURL& referrer, |
| 135 WindowOpenDisposition disposition, |
| 136 PageTransition::Type transition) { |
| 137 app_launcher_->browser()->OpenURL(url, referrer, NEW_FOREGROUND_TAB, |
| 138 PageTransition::LINK); |
| 139 app_launcher_->Hide(); |
| 140 } |
98 | 141 |
99 //////////////////////////////////////////////////////////////////////////////// | 142 //////////////////////////////////////////////////////////////////////////////// |
100 // NavigationBar | 143 // NavigationBar |
101 // | 144 // |
102 // A navigation bar that is shown in the app launcher in compact navigation bar | 145 // A navigation bar that is shown in the app launcher in compact navigation bar |
103 // mode. | 146 // mode. |
104 | 147 |
105 class NavigationBar : public views::View, | 148 class NavigationBar : public views::View, |
106 public AutocompleteEditController, | 149 public AutocompleteEditController, |
107 public BubblePositioner { | 150 public BubblePositioner { |
108 public: | 151 public: |
109 explicit NavigationBar(AppLauncher* app_launcher) | 152 explicit NavigationBar(AppLauncher* app_launcher) |
110 : views::View(), | 153 : app_launcher_(app_launcher), |
111 app_launcher_(app_launcher), | |
112 location_entry_view_(NULL) { | 154 location_entry_view_(NULL) { |
113 SetFocusable(true); | 155 SetFocusable(true); |
114 location_entry_view_ = new views::NativeViewHost; | 156 location_entry_view_ = new views::NativeViewHost; |
115 AddChildView(location_entry_view_); | 157 AddChildView(location_entry_view_); |
| 158 set_border(views::Border::CreateSolidBorder(1, SK_ColorGRAY)); |
116 } | 159 } |
117 | 160 |
118 virtual ~NavigationBar() { | 161 virtual ~NavigationBar() { |
119 if (location_entry_view_->native_view()) | 162 if (location_entry_view_->native_view()) |
120 location_entry_view_->Detach(); | 163 location_entry_view_->Detach(); |
121 } | 164 } |
122 | 165 |
123 // views::View overrides. | 166 // views::View overrides. |
124 virtual void Focus() { | 167 virtual void Focus() { |
125 location_entry_->SetFocus(); | 168 location_entry_->SetFocus(); |
126 location_entry_->SelectAll(true); | 169 location_entry_->SelectAll(true); |
127 } | 170 } |
128 | 171 |
| 172 virtual void ViewHierarchyChanged(bool is_add, |
| 173 views::View* parent, |
| 174 views::View* child) { |
| 175 if (!is_add || child != this) |
| 176 return; |
| 177 |
| 178 DCHECK(!location_entry_.get()); |
| 179 |
| 180 Browser* browser = app_launcher_->browser(); |
| 181 #if defined (OS_WIN) |
| 182 gfx::Font font; |
| 183 font = font.DeriveFont(kAutocompleteEditFontDelta); |
| 184 AutocompleteEditViewWin* autocomplete_view = |
| 185 new AutocompleteEditViewWin(font, this, browser->toolbar_model(), |
| 186 this, GetWidget()->GetNativeView(), |
| 187 browser->profile(), |
| 188 browser->command_updater(), false, this); |
| 189 location_entry_.reset(autocomplete_view); |
| 190 autocomplete_view->Update(NULL); |
| 191 // The Update call above sets the autocomplete text to the current one in |
| 192 // the location bar, make sure to clear it. |
| 193 autocomplete_view->SetUserText(std::wstring()); |
| 194 #elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS) |
| 195 AutocompleteEditViewGtk* autocomplete_view = |
| 196 new AutocompleteEditViewGtk(this, browser->toolbar_model(), |
| 197 browser->profile(), |
| 198 browser->command_updater(), false, this); |
| 199 autocomplete_view->Init(); |
| 200 gtk_widget_show_all(autocomplete_view->widget()); |
| 201 gtk_widget_hide(autocomplete_view->widget()); |
| 202 location_entry_.reset(autocomplete_view); |
| 203 #else |
| 204 NOTIMPLEMENTED(); |
| 205 #endif |
| 206 location_entry_view_->set_focus_view(this); |
| 207 location_entry_view_->Attach(location_entry_->GetNativeView()); |
| 208 } |
| 209 |
129 virtual void Layout() { | 210 virtual void Layout() { |
130 gfx::Rect bounds = GetLocalBounds(false); | 211 gfx::Rect bounds = GetLocalBounds(false); |
131 | |
132 const int vertical_margin = | |
133 kNavigationEntryPadding + kNavigationEntryYMargin; | |
134 | |
135 location_entry_view_->SetBounds( | 212 location_entry_view_->SetBounds( |
136 bounds.x() + kNavigationEntryXMargin + kNavigationEntryPadding, | 213 bounds.x() + kNavigationEntryXMargin + kNavigationEntryPadding, |
137 bounds.y() + vertical_margin, | 214 bounds.y() + kNavigationEntryYMargin, |
138 bounds.width() - 2 * (kNavigationEntryPadding + | 215 bounds.width() - 2 * (kNavigationEntryPadding + |
139 kNavigationEntryXMargin), | 216 kNavigationEntryXMargin), |
140 bounds.height() - vertical_margin * 2); | 217 bounds.height() - kNavigationEntryYMargin * 2); |
141 } | |
142 | |
143 virtual void Paint(gfx::Canvas* canvas) { | |
144 const int padding = kNavigationEntryPadding; | |
145 canvas->FillRectInt(SK_ColorWHITE, 0, 0, width(), height()); | |
146 // Draw border around the entry. | |
147 gfx::Rect bounds = location_entry_view_->GetBounds( | |
148 views::View::APPLY_MIRRORING_TRANSFORMATION); | |
149 canvas->DrawRectInt(SK_ColorGRAY, | |
150 bounds.x() - padding, | |
151 bounds.y() - padding, | |
152 bounds.width() + padding * 2, | |
153 bounds.height() + padding * 2); | |
154 } | 218 } |
155 | 219 |
156 // BubblePositioner implementation. | 220 // BubblePositioner implementation. |
157 virtual gfx::Rect GetLocationStackBounds() const { | 221 virtual gfx::Rect GetLocationStackBounds() const { |
158 gfx::Rect bounds = location_entry_view_->GetBounds( | 222 gfx::Rect bounds = location_entry_view_->GetBounds( |
159 views::View::APPLY_MIRRORING_TRANSFORMATION); | 223 views::View::APPLY_MIRRORING_TRANSFORMATION); |
160 gfx::Point origin(bounds.x(), bounds.bottom() + kNavigationEntryPadding); | 224 gfx::Point origin(bounds.x(), bounds.bottom() + kNavigationEntryPadding); |
161 views::View::ConvertPointToScreen(this, &origin); | 225 views::View::ConvertPointToScreen(this, &origin); |
162 gfx::Rect rect = gfx::Rect(origin, gfx::Size(500, 0)); | 226 gfx::Rect rect = gfx::Rect(origin, gfx::Size(500, 0)); |
163 if (UILayoutIsRightToLeft()) { | 227 if (UILayoutIsRightToLeft()) { |
(...skipping 23 matching lines...) Expand all Loading... |
187 } | 251 } |
188 focus_manager->SetFocusedView(this); | 252 focus_manager->SetFocusedView(this); |
189 } | 253 } |
190 virtual SkBitmap GetFavIcon() const { | 254 virtual SkBitmap GetFavIcon() const { |
191 return SkBitmap(); | 255 return SkBitmap(); |
192 } | 256 } |
193 virtual std::wstring GetTitle() const { | 257 virtual std::wstring GetTitle() const { |
194 return std::wstring(); | 258 return std::wstring(); |
195 } | 259 } |
196 | 260 |
197 // AutocompleteEditView depends on the browser instance. | |
198 // Create new one when the browser instance changes. | |
199 void Update(Browser* browser) { | |
200 // Detach the native view if any. | |
201 if (location_entry_view_ && location_entry_view_->native_view()) | |
202 location_entry_view_->Detach(); | |
203 | |
204 location_entry_.reset(new AutocompleteEditViewGtk( | |
205 this, browser->toolbar_model(), browser->profile(), | |
206 browser->command_updater(), false, this)); | |
207 location_entry_->Init(); | |
208 gtk_widget_show_all(location_entry_->widget()); | |
209 gtk_widget_hide(location_entry_->widget()); | |
210 | |
211 location_entry_view_->set_focus_view(this); | |
212 location_entry_view_->Attach(location_entry_->widget()); | |
213 } | |
214 | |
215 private: | 261 private: |
216 AppLauncher* app_launcher_; | 262 AppLauncher* app_launcher_; |
217 views::NativeViewHost* location_entry_view_; | 263 views::NativeViewHost* location_entry_view_; |
| 264 #if defined(OS_WIN) |
| 265 scoped_ptr<AutocompleteEditViewWin> location_entry_; |
| 266 #elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS) |
218 scoped_ptr<AutocompleteEditViewGtk> location_entry_; | 267 scoped_ptr<AutocompleteEditViewGtk> location_entry_; |
| 268 #else |
| 269 NOTIMPLEMENTED(); |
| 270 #endif |
219 | 271 |
220 DISALLOW_COPY_AND_ASSIGN(NavigationBar); | 272 DISALLOW_COPY_AND_ASSIGN(NavigationBar); |
221 }; | 273 }; |
222 | 274 |
223 //////////////////////////////////////////////////////////////////////////////// | 275 //////////////////////////////////////////////////////////////////////////////// |
224 // TopContainer | 276 // InfoBubbleContentsView |
225 // | 277 // |
226 // A view that grays-out the browser and contains the navigation bar and | 278 // The view that contains the navigation bar and render view. |
227 // renderer view. | 279 // It is displayed in an info-bubble. |
228 | 280 |
229 AppLauncher::TopContainer::TopContainer(AppLauncher* app_launcher) | 281 class InfoBubbleContentsView : public views::View { |
230 : app_launcher_(app_launcher) { | 282 public: |
231 // Use a transparent black background so the browser appears grayed-out. | 283 explicit InfoBubbleContentsView(AppLauncher* app_launcher); |
232 set_background(views::Background::CreateSolidBackground(0, 0, 0, 100)); | 284 ~InfoBubbleContentsView(); |
| 285 |
| 286 // Sets the initial focus. |
| 287 // Should be called when the bubble that contains us is shown. |
| 288 void BubbleShown(); |
| 289 |
| 290 // views::View override: |
| 291 virtual gfx::Size GetPreferredSize(); |
| 292 virtual void Layout(); |
| 293 virtual void ViewHierarchyChanged(bool is_add, |
| 294 views::View* parent, |
| 295 views::View* child); |
| 296 |
| 297 private: |
| 298 // The application launcher displaying this info bubble. |
| 299 AppLauncher* app_launcher_; |
| 300 |
| 301 // The navigation bar. |
| 302 NavigationBar* navigation_bar_; |
| 303 |
| 304 // The view containing the renderer view. |
| 305 views::NativeViewHost* render_view_container_; |
| 306 |
| 307 DISALLOW_COPY_AND_ASSIGN(InfoBubbleContentsView); |
| 308 }; |
| 309 |
| 310 InfoBubbleContentsView::InfoBubbleContentsView(AppLauncher* app_launcher) |
| 311 : app_launcher_(app_launcher), |
| 312 navigation_bar_(NULL), |
| 313 render_view_container_(NULL) { |
233 } | 314 } |
234 | 315 |
235 void AppLauncher::TopContainer::Layout() { | 316 InfoBubbleContentsView::~InfoBubbleContentsView() { |
236 if (bounds().IsEmpty()) | 317 } |
| 318 |
| 319 void InfoBubbleContentsView::BubbleShown() { |
| 320 navigation_bar_->RequestFocus(); |
| 321 } |
| 322 |
| 323 void InfoBubbleContentsView::ViewHierarchyChanged( |
| 324 bool is_add, views::View* parent, views::View* child) { |
| 325 if (!is_add || child != this) |
237 return; | 326 return; |
238 | 327 |
239 // We only expect to contain the BubbleContents. | 328 DCHECK(!render_view_container_); |
240 DCHECK(GetChildViewCount() == 1); | 329 render_view_container_ = new RWHVNativeViewHost; |
241 GetChildViewAt(0)->SetBounds(kBubbleWindowXPadding, kBubbleWindowYPadding, | 330 AddChildView(render_view_container_); |
242 width() * 2 / 3, height() * 4 / 5); | 331 #if defined(OS_WIN) |
| 332 RenderWidgetHostViewWin* view_win = |
| 333 static_cast<RenderWidgetHostViewWin*>(app_launcher_->rwhv_); |
| 334 // Create the HWND now that we are parented. |
| 335 HWND hwnd = view_win->Create(GetWidget()->GetNativeView()); |
| 336 view_win->ShowWindow(SW_SHOW); |
| 337 #endif |
| 338 render_view_container_->Attach(app_launcher_->rwhv_->GetNativeView()); |
| 339 |
| 340 navigation_bar_ = new NavigationBar(app_launcher_); |
| 341 AddChildView(navigation_bar_); |
243 } | 342 } |
244 | 343 |
245 bool AppLauncher::TopContainer::OnMousePressed(const views::MouseEvent& event) { | 344 gfx::Size InfoBubbleContentsView::GetPreferredSize() { |
246 // Clicking outside the bubble closes the bubble. | 345 gfx::Rect bounds = app_launcher_->browser()->window()->GetRestoredBounds(); |
247 app_launcher_->Hide(); | 346 return gfx::Size(bounds.width() * 2 / 3, bounds.width() * 4 / 5); |
248 return false; | |
249 } | 347 } |
250 | 348 |
251 //////////////////////////////////////////////////////////////////////////////// | 349 void InfoBubbleContentsView::Layout() { |
252 // BubbleContainer | |
253 // | |
254 // The view that contains the navigation bar and render view. It has a bubble | |
255 // border. | |
256 | |
257 AppLauncher::BubbleContainer::BubbleContainer(AppLauncher* app_launcher) | |
258 : app_launcher_(app_launcher) { | |
259 BubbleBorder* bubble_border = new BubbleBorder(); | |
260 bubble_border->set_arrow_location(BubbleBorder::TOP_LEFT); | |
261 set_border(bubble_border); | |
262 set_background(new BubbleBackground(bubble_border)); | |
263 } | |
264 | |
265 void AppLauncher::BubbleContainer::Layout() { | |
266 if (bounds().IsEmpty() || GetChildViewCount() == 0) | 350 if (bounds().IsEmpty() || GetChildViewCount() == 0) |
267 return; | 351 return; |
268 | 352 |
269 gfx::Rect bounds = GetLocalBounds(false); | 353 int navigation_bar_height = |
270 // TODO(jcampan): figure-out why we need to inset for the contained view not | 354 kNavigationBarHeight + kNavigationEntryYMargin * 2; |
271 // to paint over the bubble border. | 355 const views::Border* border = navigation_bar_->border(); |
272 bounds.Inset(2, 2); | 356 if (border) { |
273 | 357 gfx::Insets insets; |
274 app_launcher_->navigation_bar_->SetBounds(bounds.x(), bounds.y(), | 358 border->GetInsets(&insets); |
275 bounds.width(), | 359 navigation_bar_height += insets.height(); |
276 kNavigationBarHeight); | 360 } |
277 int render_y = app_launcher_->navigation_bar_->bounds().bottom(); | 361 navigation_bar_->SetBounds(x(), y(), width(), navigation_bar_height); |
| 362 int render_y = navigation_bar_->bounds().bottom(); |
278 gfx::Size rwhv_size = | 363 gfx::Size rwhv_size = |
279 gfx::Size(bounds.width(), | 364 gfx::Size(width(), std::max(0, height() - render_y + y())); |
280 std::max(0, bounds.height() - render_y + bounds.y())); | 365 render_view_container_->SetBounds(x(), render_y, |
281 app_launcher_->render_view_container_->SetBounds(bounds.x(), render_y, | 366 rwhv_size.width(), rwhv_size.height()); |
282 rwhv_size.width(), | |
283 rwhv_size.height()); | |
284 app_launcher_->rwhv_->SetSize(rwhv_size); | 367 app_launcher_->rwhv_->SetSize(rwhv_size); |
285 } | 368 } |
286 | 369 |
287 //////////////////////////////////////////////////////////////////////////////// | 370 //////////////////////////////////////////////////////////////////////////////// |
288 // AppLauncher | 371 // AppLauncher |
289 | 372 |
290 AppLauncher::AppLauncher() | 373 AppLauncher::AppLauncher(Browser* browser) |
291 : browser_(NULL), | 374 : browser_(browser), |
292 popup_(NULL), | 375 info_bubble_(NULL), |
293 site_instance_(NULL), | 376 site_instance_(NULL), |
294 contents_rvh_(NULL), | 377 contents_rvh_(NULL), |
295 rwhv_(NULL), | 378 rwhv_(NULL), |
296 ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_delegate_(this)), | 379 ALLOW_THIS_IN_INITIALIZER_LIST( |
297 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | 380 tab_contents_delegate_(new TabContentsDelegateImpl(this))) { |
298 top_container_(NULL), | 381 info_bubble_content_ = new InfoBubbleContentsView(this); |
299 bubble_container_(NULL), | |
300 navigation_bar_(NULL), | |
301 render_view_container_(NULL), | |
302 has_shown_(false) { | |
303 popup_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); | |
304 // The background image has transparency, so we make the window transparent. | |
305 popup_->MakeTransparent(); | |
306 popup_->Init(NULL, gfx::Rect()); | |
307 WmIpc::instance()->SetWindowType( | |
308 popup_->GetNativeView(), | |
309 WmIpc::WINDOW_TYPE_CHROME_INFO_BUBBLE, | |
310 NULL); | |
311 | 382 |
312 // Register Esc as an accelerator for closing the app launcher. | 383 Profile* profile = browser_->profile(); |
313 views::FocusManager* focus_manager = popup_->GetFocusManager(); | |
314 focus_manager->RegisterAccelerator(views::Accelerator(base::VKEY_ESCAPE, | |
315 false, false, false), | |
316 this); | |
317 | |
318 top_container_ = new TopContainer(this); | |
319 popup_->SetContentsView(top_container_); | |
320 | |
321 bubble_container_ = new BubbleContainer(this); | |
322 top_container_->AddChildView(bubble_container_); | |
323 navigation_bar_ = new NavigationBar(this); | |
324 bubble_container_->AddChildView(navigation_bar_); | |
325 | |
326 GURL menu_url(GetMenuURL()); | |
327 DCHECK(BrowserList::begin() != BrowserList::end()); | |
328 // TODO(sky): this shouldn't pick a random profile to use. | |
329 Profile* profile = (*BrowserList::begin())->profile(); | |
330 int64 session_storage_namespace_id = profile->GetWebKitContext()-> | 384 int64 session_storage_namespace_id = profile->GetWebKitContext()-> |
331 dom_storage_context()->AllocateSessionStorageNamespaceId(); | 385 dom_storage_context()->AllocateSessionStorageNamespaceId(); |
332 site_instance_ = SiteInstance::CreateSiteInstanceForURL(profile, menu_url); | 386 site_instance_ = SiteInstance::CreateSiteInstanceForURL(profile, |
| 387 GetMenuURL()); |
333 contents_rvh_ = new RenderViewHost(site_instance_, this, MSG_ROUTING_NONE, | 388 contents_rvh_ = new RenderViewHost(site_instance_, this, MSG_ROUTING_NONE, |
334 session_storage_namespace_id); | 389 session_storage_namespace_id); |
| 390 rwhv_ = RenderWidgetHostView::CreateViewForWidget(contents_rvh_); |
| 391 contents_rvh_->set_view(rwhv_); |
335 | 392 |
336 rwhv_ = new RenderWidgetHostViewGtk(contents_rvh_); | 393 // On Windows, we'll create the RWHV HWND once we are attached as we need |
337 rwhv_->InitAsChild(); | 394 // to be parented for CreateWindow to work. |
| 395 #if defined(OS_LINUX) |
| 396 RenderWidgetHostViewGtk* view_gtk = |
| 397 static_cast<RenderWidgetHostViewGtk*>(rwhv_); |
| 398 view_gtk->InitAsChild(); |
| 399 #endif |
| 400 |
338 contents_rvh_->CreateRenderView(profile->GetRequestContext()); | 401 contents_rvh_->CreateRenderView(profile->GetRequestContext()); |
339 | 402 DCHECK(contents_rvh_->IsRenderViewLive()); |
340 render_view_container_ = new RWHVNativeViewHost; | 403 contents_rvh_->NavigateToURL(GetMenuURL()); |
341 bubble_container_->AddChildView(render_view_container_); | |
342 render_view_container_->Attach(rwhv_->GetNativeView()); | |
343 contents_rvh_->NavigateToURL(menu_url); | |
344 | |
345 ActiveWindowWatcherX::AddObserver(this); | |
346 } | 404 } |
347 | 405 |
348 AppLauncher::~AppLauncher() { | 406 AppLauncher::~AppLauncher() { |
349 contents_rvh_->Shutdown(); | 407 contents_rvh_->Shutdown(); |
350 popup_->CloseNow(); | |
351 ActiveWindowWatcherX::RemoveObserver(this); | |
352 } | 408 } |
353 | 409 |
354 void AppLauncher::Update(Browser* browser) { | 410 // static |
355 if (browser_ != browser) { | 411 AppLauncher* AppLauncher::Show(Browser* browser) { |
356 browser_ = browser; | 412 AppLauncher* app_launcher = new AppLauncher(browser); |
357 navigation_bar_->Update(browser); | 413 |
358 // Set the transient window so that ChromeOS WM treat this | 414 BrowserView* browser_view = static_cast<BrowserView*>(browser->window()); |
359 // as if a popup window. | 415 TabStrip* tabstrip = browser_view->tabstrip()->AsTabStrip(); |
360 gtk_window_set_transient_for( | 416 if (!tabstrip) { |
361 GTK_WINDOW(popup_->GetNativeView()), | 417 delete app_launcher; |
362 GTK_WINDOW(browser_->window()->GetNativeHandle())); | 418 return NULL; |
363 } | 419 } |
364 | 420 gfx::Rect bounds = tabstrip->GetNewTabButtonBounds(); |
365 popup_->SetBounds(browser_->window()->GetRestoredBounds()); | 421 gfx::Point origin = bounds.origin(); |
366 top_container_->Layout(); | 422 views::RootView::ConvertPointToScreen(tabstrip, &origin); |
367 } | 423 bounds.set_origin(origin); |
368 | 424 app_launcher->info_bubble_ = |
369 void AppLauncher::Show(Browser* browser) { | 425 InfoBubble::Show(browser_view->frame()->GetWindow(), bounds, |
370 Cleanup(); | 426 app_launcher->info_bubble_content_, app_launcher); |
371 | 427 app_launcher->info_bubble_content_->BubbleShown(); |
372 Update(browser); | 428 return app_launcher; |
373 popup_->Show(); | |
374 | |
375 GtkWidget* rwhv_widget = rwhv_->GetNativeView(); | |
376 if (!has_shown_) { | |
377 has_shown_ = true; | |
378 gtk_widget_realize(rwhv_widget); | |
379 } | |
380 } | |
381 | |
382 void AppLauncher::ActiveWindowChanged(GdkWindow* active_window) { | |
383 if (!popup_->IsActive()) | |
384 Hide(); | |
385 else | |
386 navigation_bar_->RequestFocus(); | |
387 } | |
388 | |
389 bool AppLauncher::AcceleratorPressed(const views::Accelerator& accelerator) { | |
390 DCHECK(accelerator.GetKeyCode() == base::VKEY_ESCAPE); | |
391 popup_->Hide(); | |
392 return true; | |
393 } | 429 } |
394 | 430 |
395 void AppLauncher::Hide() { | 431 void AppLauncher::Hide() { |
396 popup_->Hide(); | 432 info_bubble_->Close(); |
| 433 } |
| 434 |
| 435 void AppLauncher::InfoBubbleClosing(InfoBubble* info_bubble, |
| 436 bool closed_by_escape) { |
397 // The stack may have pending_contents_ on it. Delay deleting the | 437 // The stack may have pending_contents_ on it. Delay deleting the |
398 // pending_contents_ as TabContents doesn't deal well with being deleted | 438 // pending_contents_ as TabContents doesn't deal well with being deleted |
399 // while on the stack. | 439 // while on the stack. |
400 MessageLoop::current()->PostTask(FROM_HERE, | 440 MessageLoop::current()->PostTask(FROM_HERE, |
401 method_factory_.NewRunnableMethod(&AppLauncher::Cleanup)); | 441 new DeleteTask<AppLauncher>(this)); |
402 } | |
403 | |
404 void AppLauncher::Cleanup() { | |
405 pending_contents_.reset(NULL); | |
406 method_factory_.RevokeAll(); | |
407 } | 442 } |
408 | 443 |
409 void AppLauncher::RequestMove(const gfx::Rect& new_bounds) { | 444 void AppLauncher::RequestMove(const gfx::Rect& new_bounds) { |
| 445 #if defined(OS_LINUX) |
410 // Invoking PositionChild results in a gtk signal that triggers attempting to | 446 // Invoking PositionChild results in a gtk signal that triggers attempting to |
411 // to resize the window. We need to set the size request so that it resizes | 447 // to resize the window. We need to set the size request so that it resizes |
412 // correctly when this happens. | 448 // correctly when this happens. |
413 gtk_widget_set_size_request(popup_->GetNativeView(), | 449 gtk_widget_set_size_request(info_bubble_->GetNativeView(), |
414 new_bounds.width(), new_bounds.height()); | 450 new_bounds.width(), new_bounds.height()); |
415 popup_->SetBounds(new_bounds); | 451 info_bubble_->SetBounds(new_bounds); |
| 452 #endif |
416 } | 453 } |
417 | 454 |
418 RendererPreferences AppLauncher::GetRendererPrefs(Profile* profile) const { | 455 RendererPreferences AppLauncher::GetRendererPrefs(Profile* profile) const { |
419 RendererPreferences preferences; | 456 RendererPreferences preferences; |
420 renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile); | 457 renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile); |
421 return preferences; | 458 return preferences; |
422 } | 459 } |
423 | 460 |
424 void AppLauncher::AddTabWithURL(const GURL& url, | |
425 PageTransition::Type transition) { | |
426 switch (StatusAreaView::GetOpenTabsMode()) { | |
427 case StatusAreaView::OPEN_TABS_ON_LEFT: { | |
428 // Add the new tab at the first non-pinned location. | |
429 int index = browser_->tabstrip_model()->IndexOfFirstNonMiniTab(); | |
430 browser_->AddTabWithURL(url, GURL(), transition, | |
431 true, index, true, NULL); | |
432 break; | |
433 } | |
434 case StatusAreaView::OPEN_TABS_CLOBBER: { | |
435 browser_->GetSelectedTabContents()->controller().LoadURL( | |
436 url, GURL(), transition); | |
437 break; | |
438 } | |
439 case StatusAreaView::OPEN_TABS_ON_RIGHT: { | |
440 browser_->AddTabWithURL(url, GURL(), transition, true, -1, true, NULL); | |
441 break; | |
442 } | |
443 } | |
444 } | |
445 | |
446 void AppLauncher::CreateNewWindow(int route_id) { | 461 void AppLauncher::CreateNewWindow(int route_id) { |
447 if (pending_contents_.get()) { | 462 if (pending_contents_.get()) { |
448 NOTREACHED(); | 463 NOTREACHED(); |
449 return; | 464 return; |
450 } | 465 } |
451 | 466 |
452 helper_.CreateNewWindow(route_id, browser_->profile(), site_instance_, | 467 helper_.CreateNewWindow(route_id, browser_->profile(), site_instance_, |
453 DOMUIFactory::GetDOMUIType(GURL(GetMenuURL())), | 468 DOMUIFactory::GetDOMUIType(GURL(GetMenuURL())), |
454 NULL); | 469 NULL); |
455 pending_contents_.reset(helper_.GetCreatedWindow(route_id)); | 470 pending_contents_.reset(helper_.GetCreatedWindow(route_id)); |
456 pending_contents_->set_delegate(&tab_contents_delegate_); | 471 pending_contents_->set_delegate(tab_contents_delegate_.get()); |
457 } | 472 } |
458 | 473 |
459 void AppLauncher::ShowCreatedWindow(int route_id, | 474 void AppLauncher::ShowCreatedWindow(int route_id, |
460 WindowOpenDisposition disposition, | 475 WindowOpenDisposition disposition, |
461 const gfx::Rect& initial_pos, | 476 const gfx::Rect& initial_pos, |
462 bool user_gesture) { | 477 bool user_gesture) { |
463 if (disposition == NEW_POPUP) { | 478 if (disposition == NEW_POPUP) { |
464 pending_contents_->set_delegate(NULL); | 479 pending_contents_->set_delegate(NULL); |
465 browser_->GetSelectedTabContents()->AddNewContents( | 480 browser_->GetSelectedTabContents()->AddNewContents( |
466 pending_contents_.release(), disposition, initial_pos, user_gesture); | 481 pending_contents_.release(), disposition, initial_pos, user_gesture); |
467 Hide(); | 482 Hide(); |
468 } | 483 } |
469 } | 484 } |
470 | 485 |
471 void AppLauncher::StartDragging(const WebDropData& drop_data, | 486 void AppLauncher::StartDragging(const WebDropData& drop_data, |
472 WebKit::WebDragOperationsMask allowed_ops) { | 487 WebKit::WebDragOperationsMask allowed_ops, |
| 488 const SkBitmap& image, |
| 489 const gfx::Point& image_offset) { |
473 // We're not going to do any drag & drop, but we have to tell the renderer the | 490 // We're not going to do any drag & drop, but we have to tell the renderer the |
474 // drag & drop ended, othewise the renderer thinks the drag operation is | 491 // drag & drop ended, othewise the renderer thinks the drag operation is |
475 // underway and mouse events won't work. | 492 // underway and mouse events won't work. |
476 contents_rvh_->DragSourceSystemDragEnded(); | 493 contents_rvh_->DragSourceSystemDragEnded(); |
477 } | 494 } |
478 | 495 |
479 AppLauncher::TabContentsDelegateImpl::TabContentsDelegateImpl( | 496 void AppLauncher::AddTabWithURL(const GURL& url, |
480 AppLauncher* app_launcher) | 497 PageTransition::Type transition) { |
481 : app_launcher_(app_launcher) { | 498 #if defined(OS_CHROMEOS) |
| 499 switch (chromeos::StatusAreaView::GetOpenTabsMode()) { |
| 500 case chromeos::StatusAreaView::OPEN_TABS_ON_LEFT: { |
| 501 // Add the new tab at the first non-pinned location. |
| 502 int index = browser_->tabstrip_model()->IndexOfFirstNonMiniTab(); |
| 503 browser_->AddTabWithURL(url, GURL(), transition, |
| 504 true, index, true, NULL); |
| 505 break; |
| 506 } |
| 507 case chromeos::StatusAreaView::OPEN_TABS_CLOBBER: { |
| 508 browser_->GetSelectedTabContents()->controller().LoadURL( |
| 509 url, GURL(), transition); |
| 510 break; |
| 511 } |
| 512 case chromeos::StatusAreaView::OPEN_TABS_ON_RIGHT: { |
| 513 browser_->AddTabWithURL(url, GURL(), transition, true, -1, true, NULL); |
| 514 break; |
| 515 } |
| 516 } |
| 517 #else |
| 518 browser_->AddTabWithURL(url, GURL(), transition, true, -1, true, NULL); |
| 519 #endif |
482 } | 520 } |
483 | |
484 void AppLauncher::TabContentsDelegateImpl::OpenURLFromTab( | |
485 TabContents* source, | |
486 const GURL& url, | |
487 const GURL& referrer, | |
488 WindowOpenDisposition disposition, | |
489 PageTransition::Type transition) { | |
490 app_launcher_->browser_->OpenURL(url, referrer, NEW_FOREGROUND_TAB, | |
491 PageTransition::LINK); | |
492 app_launcher_->Hide(); | |
493 } | |
494 | |
495 } // namespace chromeos | |
OLD | NEW |