Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: chrome/browser/chromeos/app_launcher.cc

Issue 1145001: Porting the app launcher to Windows, and adding an experimental flag... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/chromeos/app_launcher.h ('k') | chrome/browser/chromeos/frame/browser_view.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/app_launcher.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "app/gfx/canvas.h"
11 #include "app/resource_bundle.h"
12 #include "base/command_line.h"
13 #include "base/message_loop.h"
14 #include "base/string_util.h"
15 #include "chrome/browser/autocomplete/autocomplete_edit.h"
16 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
17 #include "chrome/browser/browser.h"
18 #include "chrome/browser/browser_list.h"
19 #include "chrome/browser/browser_window.h"
20 #include "chrome/browser/bubble_positioner.h"
21 #include "chrome/browser/chromeos/frame/browser_view.h"
22 #include "chrome/browser/chromeos/status/status_area_view.h"
23 #include "chrome/browser/chromeos/wm_ipc.h"
24 #include "chrome/browser/in_process_webkit/dom_storage_context.h"
25 #include "chrome/browser/in_process_webkit/webkit_context.h"
26 #include "chrome/browser/profile.h"
27 #include "chrome/browser/renderer_host/render_view_host.h"
28 #include "chrome/browser/renderer_host/render_view_host_factory.h"
29 #include "chrome/browser/renderer_host/render_widget_host_view.h"
30 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
31 #include "chrome/browser/renderer_host/site_instance.h"
32 #include "chrome/browser/renderer_preferences_util.h"
33 #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
34 #include "chrome/browser/tab_contents/tab_contents.h"
35 #include "chrome/browser/views/bubble_border.h"
36 #include "gfx/insets.h"
37 #include "gfx/point.h"
38 #include "grit/app_resources.h"
39 #include "grit/generated_resources.h"
40 #include "grit/theme_resources.h"
41 #include "third_party/skia/include/core/SkBitmap.h"
42 #include "views/background.h"
43 #include "views/controls/native/native_view_host.h"
44 #include "views/painter.h"
45 #include "views/screen.h"
46 #include "views/widget/root_view.h"
47 #include "views/widget/widget_gtk.h"
48
49 namespace {
50
51 // Padding & margins for the navigation entry.
52 const int kNavigationEntryPadding = 2;
53 const int kNavigationEntryXMargin = 3;
54 const int kNavigationEntryYMargin = 1;
55
56 // NavigationBar size.
57 const int kNavigationBarHeight = 25;
58
59 // Padding for the bubble info window.
60 const int kBubbleWindowXPadding = 6;
61 const int kBubbleWindowYPadding = 16;
62
63 // Command line switch for specifying url of the page.
64 const wchar_t kURLSwitch[] = L"main-menu-url";
65
66 // Command line switch for specifying the size of the main menu. The default is
67 // full screen.
68 const wchar_t kMenuSizeSwitch[] = L"main-menu-size";
69
70 // URL of the page to load. This is ignored if kURLSwitch is specified.
71 const char kMenuURL[] = "http://goto.ext.google.com/crux-home";
72
73 // Returns the URL of the menu.
74 static GURL GetMenuURL() {
75 std::wstring url_string =
76 CommandLine::ForCurrentProcess()->GetSwitchValue(kURLSwitch);
77 if (!url_string.empty())
78 return GURL(WideToUTF8(url_string));
79 return GURL(kMenuURL);
80 }
81
82 // RenderWidgetHostViewGtk propagates the mouse press events (see
83 // render_widget_host_view_gtk.cc). We subclass to stop the propagation here,
84 // as if the click event was propagated it would reach the TopContainer view and
85 // it would close the popup.
86 class RWHVNativeViewHost : public views::NativeViewHost {
87 public:
88 RWHVNativeViewHost() {}
89
90 virtual bool OnMousePressed(const views::MouseEvent& event) { return true; }
91
92 private:
93 DISALLOW_COPY_AND_ASSIGN(RWHVNativeViewHost);
94 };
95
96 } // namspace
97
98 namespace chromeos {
99
100 ////////////////////////////////////////////////////////////////////////////////
101 // NavigationBar
102 //
103 // A navigation bar that is shown in the app launcher in compact navigation bar
104 // mode.
105
106 class NavigationBar : public views::View,
107 public AutocompleteEditController,
108 public BubblePositioner {
109 public:
110 explicit NavigationBar(AppLauncher* app_launcher)
111 : views::View(),
112 app_launcher_(app_launcher),
113 location_entry_view_(NULL) {
114 SetFocusable(true);
115 location_entry_view_ = new views::NativeViewHost;
116 AddChildView(location_entry_view_);
117 }
118
119 virtual ~NavigationBar() {
120 if (location_entry_view_->native_view())
121 location_entry_view_->Detach();
122 }
123
124 // views::View overrides.
125 virtual void Focus() {
126 location_entry_->SetFocus();
127 location_entry_->SelectAll(true);
128 }
129
130 virtual void Layout() {
131 gfx::Rect bounds = GetLocalBounds(false);
132
133 const int vertical_margin =
134 kNavigationEntryPadding + kNavigationEntryYMargin;
135
136 location_entry_view_->SetBounds(
137 bounds.x() + kNavigationEntryXMargin + kNavigationEntryPadding,
138 bounds.y() + vertical_margin,
139 bounds.width() - 2 * (kNavigationEntryPadding +
140 kNavigationEntryXMargin),
141 bounds.height() - vertical_margin * 2);
142 }
143
144 virtual void Paint(gfx::Canvas* canvas) {
145 const int padding = kNavigationEntryPadding;
146 canvas->FillRectInt(SK_ColorWHITE, 0, 0, width(), height());
147 // Draw border around the entry.
148 gfx::Rect bounds = location_entry_view_->GetBounds(
149 views::View::APPLY_MIRRORING_TRANSFORMATION);
150 canvas->DrawRectInt(SK_ColorGRAY,
151 bounds.x() - padding,
152 bounds.y() - padding,
153 bounds.width() + padding * 2,
154 bounds.height() + padding * 2);
155 }
156
157 // BubblePositioner implementation.
158 virtual gfx::Rect GetLocationStackBounds() const {
159 gfx::Rect bounds = location_entry_view_->GetBounds(
160 views::View::APPLY_MIRRORING_TRANSFORMATION);
161 gfx::Point origin(bounds.x(), bounds.bottom() + kNavigationEntryPadding);
162 views::View::ConvertPointToScreen(this, &origin);
163 gfx::Rect rect = gfx::Rect(origin, gfx::Size(500, 0));
164 if (UILayoutIsRightToLeft()) {
165 // Align the window to the right side of the entry view when
166 // UI is RTL mode.
167 rect.set_x(rect.x() - (rect.width() - location_entry_view_->width()));
168 }
169 return rect;
170 }
171
172 // AutocompleteController implementation.
173 virtual void OnAutocompleteAccept(const GURL& url,
174 WindowOpenDisposition disposition,
175 PageTransition::Type transition,
176 const GURL& alternate_nav_url) {
177 app_launcher_->AddTabWithURL(url, transition);
178 app_launcher_->Hide();
179 }
180 virtual void OnChanged() {}
181 virtual void OnInputInProgress(bool in_progress) {}
182 virtual void OnKillFocus() {}
183 virtual void OnSetFocus() {
184 views::FocusManager* focus_manager = GetFocusManager();
185 if (!focus_manager) {
186 NOTREACHED();
187 return;
188 }
189 focus_manager->SetFocusedView(this);
190 }
191 virtual SkBitmap GetFavIcon() const {
192 return SkBitmap();
193 }
194 virtual std::wstring GetTitle() const {
195 return std::wstring();
196 }
197
198 // AutocompleteEditView depends on the browser instance.
199 // Create new one when the browser instance changes.
200 void Update(Browser* browser) {
201 // Detach the native view if any.
202 if (location_entry_view_ && location_entry_view_->native_view())
203 location_entry_view_->Detach();
204
205 location_entry_.reset(new AutocompleteEditViewGtk(
206 this, browser->toolbar_model(), browser->profile(),
207 browser->command_updater(), false, this));
208 location_entry_->Init();
209 gtk_widget_show_all(location_entry_->widget());
210 gtk_widget_hide(location_entry_->widget());
211
212 location_entry_view_->set_focus_view(this);
213 location_entry_view_->Attach(location_entry_->widget());
214 }
215
216 private:
217 AppLauncher* app_launcher_;
218 views::NativeViewHost* location_entry_view_;
219 scoped_ptr<AutocompleteEditViewGtk> location_entry_;
220
221 DISALLOW_COPY_AND_ASSIGN(NavigationBar);
222 };
223
224 ////////////////////////////////////////////////////////////////////////////////
225 // TopContainer
226 //
227 // A view that grays-out the browser and contains the navigation bar and
228 // renderer view.
229
230 AppLauncher::TopContainer::TopContainer(AppLauncher* app_launcher)
231 : app_launcher_(app_launcher) {
232 // Use a transparent black background so the browser appears grayed-out.
233 set_background(views::Background::CreateSolidBackground(0, 0, 0, 100));
234 }
235
236 void AppLauncher::TopContainer::Layout() {
237 if (bounds().IsEmpty())
238 return;
239
240 // We only expect to contain the BubbleContents.
241 DCHECK(GetChildViewCount() == 1);
242 GetChildViewAt(0)->SetBounds(kBubbleWindowXPadding, kBubbleWindowYPadding,
243 width() * 2 / 3, height() * 4 / 5);
244 }
245
246 bool AppLauncher::TopContainer::OnMousePressed(const views::MouseEvent& event) {
247 // Clicking outside the bubble closes the bubble.
248 app_launcher_->Hide();
249 return false;
250 }
251
252 ////////////////////////////////////////////////////////////////////////////////
253 // BubbleContainer
254 //
255 // The view that contains the navigation bar and render view. It has a bubble
256 // border.
257
258 AppLauncher::BubbleContainer::BubbleContainer(AppLauncher* app_launcher)
259 : app_launcher_(app_launcher) {
260 BubbleBorder* bubble_border = new BubbleBorder();
261 bubble_border->set_arrow_location(BubbleBorder::TOP_LEFT);
262 set_border(bubble_border);
263 set_background(new BubbleBackground(bubble_border));
264 }
265
266 void AppLauncher::BubbleContainer::Layout() {
267 if (bounds().IsEmpty() || GetChildViewCount() == 0)
268 return;
269
270 gfx::Rect bounds = GetLocalBounds(false);
271 // TODO(jcampan): figure-out why we need to inset for the contained view not
272 // to paint over the bubble border.
273 bounds.Inset(2, 2);
274
275 app_launcher_->navigation_bar_->SetBounds(bounds.x(), bounds.y(),
276 bounds.width(),
277 kNavigationBarHeight);
278 int render_y = app_launcher_->navigation_bar_->bounds().bottom();
279 gfx::Size rwhv_size =
280 gfx::Size(bounds.width(),
281 std::max(0, bounds.height() - render_y + bounds.y()));
282 app_launcher_->render_view_container_->SetBounds(bounds.x(), render_y,
283 rwhv_size.width(),
284 rwhv_size.height());
285 app_launcher_->rwhv_->SetSize(rwhv_size);
286 }
287
288 ////////////////////////////////////////////////////////////////////////////////
289 // AppLauncher
290
291 AppLauncher::AppLauncher(Browser* browser)
292 : browser_(browser),
293 popup_(NULL),
294 site_instance_(NULL),
295 contents_rvh_(NULL),
296 rwhv_(NULL),
297 ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_delegate_(this)),
298 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
299 top_container_(NULL),
300 bubble_container_(NULL),
301 navigation_bar_(NULL),
302 render_view_container_(NULL),
303 has_shown_(false) {
304 popup_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
305 // The background image has transparency, so we make the window transparent.
306 popup_->MakeTransparent();
307 popup_->Init(NULL, gfx::Rect());
308 WmIpc::instance()->SetWindowType(
309 popup_->GetNativeView(),
310 WmIpc::WINDOW_TYPE_CHROME_INFO_BUBBLE,
311 NULL);
312
313 // Register Esc as an accelerator for closing the app launcher.
314 views::FocusManager* focus_manager = popup_->GetFocusManager();
315 focus_manager->RegisterAccelerator(views::Accelerator(base::VKEY_ESCAPE,
316 false, false, false),
317 this);
318
319 top_container_ = new TopContainer(this);
320 popup_->SetContentsView(top_container_);
321
322 bubble_container_ = new BubbleContainer(this);
323 top_container_->AddChildView(bubble_container_);
324 navigation_bar_ = new NavigationBar(this);
325 bubble_container_->AddChildView(navigation_bar_);
326
327 GURL menu_url(GetMenuURL());
328 DCHECK(BrowserList::begin() != BrowserList::end());
329 // TODO(sky): this shouldn't pick a random profile to use.
330 Profile* profile = (*BrowserList::begin())->profile();
331 int64 session_storage_namespace_id = profile->GetWebKitContext()->
332 dom_storage_context()->AllocateSessionStorageNamespaceId();
333 site_instance_ = SiteInstance::CreateSiteInstanceForURL(profile, menu_url);
334 contents_rvh_ = new RenderViewHost(site_instance_, this, MSG_ROUTING_NONE,
335 session_storage_namespace_id);
336
337 rwhv_ = new RenderWidgetHostViewGtk(contents_rvh_);
338 rwhv_->InitAsChild();
339 contents_rvh_->CreateRenderView(profile->GetRequestContext());
340
341 render_view_container_ = new RWHVNativeViewHost;
342 bubble_container_->AddChildView(render_view_container_);
343 render_view_container_->Attach(rwhv_->GetNativeView());
344 contents_rvh_->NavigateToURL(menu_url);
345
346 navigation_bar_->Update(browser);
347 // Set the transient window so that ChromeOS WM treat this
348 // as if a popup window.
349 gtk_window_set_transient_for(
350 GTK_WINDOW(popup_->GetNativeView()),
351 GTK_WINDOW(browser_->window()->GetNativeHandle()));
352
353 ActiveWindowWatcherX::AddObserver(this);
354 }
355
356 AppLauncher::~AppLauncher() {
357 contents_rvh_->Shutdown();
358 popup_->CloseNow();
359 ActiveWindowWatcherX::RemoveObserver(this);
360 }
361
362 void AppLauncher::Update() {
363 popup_->SetBounds(browser_->window()->GetRestoredBounds());
364 top_container_->Layout();
365 }
366
367 void AppLauncher::Show() {
368 Cleanup();
369
370 Update();
371 popup_->Show();
372
373 GtkWidget* rwhv_widget = rwhv_->GetNativeView();
374 if (!has_shown_) {
375 has_shown_ = true;
376 gtk_widget_realize(rwhv_widget);
377 }
378 }
379
380 void AppLauncher::ActiveWindowChanged(GdkWindow* active_window) {
381 if (!popup_->IsActive())
382 Hide();
383 else
384 navigation_bar_->RequestFocus();
385 }
386
387 bool AppLauncher::AcceleratorPressed(const views::Accelerator& accelerator) {
388 DCHECK(accelerator.GetKeyCode() == base::VKEY_ESCAPE);
389 popup_->Hide();
390 return true;
391 }
392
393 void AppLauncher::Hide() {
394 popup_->Hide();
395 // The stack may have pending_contents_ on it. Delay deleting the
396 // pending_contents_ as TabContents doesn't deal well with being deleted
397 // while on the stack.
398 MessageLoop::current()->PostTask(FROM_HERE,
399 method_factory_.NewRunnableMethod(&AppLauncher::Cleanup));
400 }
401
402 void AppLauncher::Cleanup() {
403 pending_contents_.reset(NULL);
404 method_factory_.RevokeAll();
405 }
406
407 void AppLauncher::RequestMove(const gfx::Rect& new_bounds) {
408 // Invoking PositionChild results in a gtk signal that triggers attempting to
409 // to resize the window. We need to set the size request so that it resizes
410 // correctly when this happens.
411 gtk_widget_set_size_request(popup_->GetNativeView(),
412 new_bounds.width(), new_bounds.height());
413 popup_->SetBounds(new_bounds);
414 }
415
416 RendererPreferences AppLauncher::GetRendererPrefs(Profile* profile) const {
417 RendererPreferences preferences;
418 renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile);
419 return preferences;
420 }
421
422 void AppLauncher::AddTabWithURL(const GURL& url,
423 PageTransition::Type transition) {
424 switch (StatusAreaView::GetOpenTabsMode()) {
425 case StatusAreaView::OPEN_TABS_ON_LEFT: {
426 // Add the new tab at the first non-pinned location.
427 int index = browser_->tabstrip_model()->IndexOfFirstNonMiniTab();
428 browser_->AddTabWithURL(url, GURL(), transition,
429 true, index, true, NULL);
430 break;
431 }
432 case StatusAreaView::OPEN_TABS_CLOBBER: {
433 browser_->GetSelectedTabContents()->controller().LoadURL(
434 url, GURL(), transition);
435 break;
436 }
437 case StatusAreaView::OPEN_TABS_ON_RIGHT: {
438 browser_->AddTabWithURL(url, GURL(), transition, true, -1, true, NULL);
439 break;
440 }
441 }
442 }
443
444 void AppLauncher::CreateNewWindow(int route_id) {
445 if (pending_contents_.get()) {
446 NOTREACHED();
447 return;
448 }
449
450 helper_.CreateNewWindow(route_id, browser_->profile(), site_instance_,
451 DOMUIFactory::GetDOMUIType(GURL(GetMenuURL())),
452 NULL);
453 pending_contents_.reset(helper_.GetCreatedWindow(route_id));
454 pending_contents_->set_delegate(&tab_contents_delegate_);
455 }
456
457 void AppLauncher::ShowCreatedWindow(int route_id,
458 WindowOpenDisposition disposition,
459 const gfx::Rect& initial_pos,
460 bool user_gesture) {
461 if (disposition == NEW_POPUP) {
462 pending_contents_->set_delegate(NULL);
463 browser_->GetSelectedTabContents()->AddNewContents(
464 pending_contents_.release(), disposition, initial_pos, user_gesture);
465 Hide();
466 }
467 }
468
469 void AppLauncher::StartDragging(const WebDropData& drop_data,
470 WebKit::WebDragOperationsMask allowed_ops,
471 const SkBitmap& image,
472 const gfx::Point& image_offset) {
473 // 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
475 // underway and mouse events won't work.
476 contents_rvh_->DragSourceSystemDragEnded();
477 }
478
479 AppLauncher::TabContentsDelegateImpl::TabContentsDelegateImpl(
480 AppLauncher* app_launcher)
481 : app_launcher_(app_launcher) {
482 }
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
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/app_launcher.h ('k') | chrome/browser/chromeos/frame/browser_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698