Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 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 <sstream> | 5 #include <sstream> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_util.h" | |
| 8 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 9 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| 10 #include "base/time.h" | 11 #include "base/time.h" |
| 11 #include "base/timer.h" | 12 #include "base/timer.h" |
| 12 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 14 #include "base/win/shortcut.h" | |
| 13 #include "chrome/app/chrome_dll_resource.h" | 15 #include "chrome/app/chrome_dll_resource.h" |
| 14 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
| 15 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 16 #include "chrome/browser/lifetime/application_lifetime.h" | 18 #include "chrome/browser/lifetime/application_lifetime.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/profiles/profile_manager.h" | 20 #include "chrome/browser/profiles/profile_manager.h" |
| 19 #include "chrome/browser/shell_integration.h" | 21 #include "chrome/browser/shell_integration.h" |
| 20 #include "chrome/browser/ui/app_list/app_list_controller.h" | 22 #include "chrome/browser/ui/app_list/app_list_controller.h" |
| 21 #include "chrome/browser/ui/app_list/app_list_view_delegate.h" | 23 #include "chrome/browser/ui/app_list/app_list_view_delegate.h" |
| 22 #include "chrome/browser/ui/extensions/application_launch.h" | 24 #include "chrome/browser/ui/extensions/application_launch.h" |
| 23 #include "chrome/browser/ui/views/browser_dialogs.h" | 25 #include "chrome/browser/ui/views/browser_dialogs.h" |
| 24 #include "chrome/common/chrome_constants.h" | 26 #include "chrome/common/chrome_constants.h" |
| 25 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
| 28 #include "content/public/browser/browser_thread.h" | |
| 26 #include "grit/generated_resources.h" | 29 #include "grit/generated_resources.h" |
| 27 #include "ui/app_list/app_list_view.h" | 30 #include "ui/app_list/app_list_view.h" |
| 28 #include "ui/app_list/pagination_model.h" | 31 #include "ui/app_list/pagination_model.h" |
| 29 #include "ui/base/l10n/l10n_util.h" | 32 #include "ui/base/l10n/l10n_util.h" |
| 30 #include "ui/base/win/shell.h" | 33 #include "ui/base/win/shell.h" |
| 31 #include "ui/gfx/display.h" | 34 #include "ui/gfx/display.h" |
| 32 #include "ui/gfx/screen.h" | 35 #include "ui/gfx/screen.h" |
| 33 #include "ui/views/bubble/bubble_border.h" | 36 #include "ui/views/bubble/bubble_border.h" |
| 34 #include "ui/views/widget/widget.h" | 37 #include "ui/views/widget/widget.h" |
| 35 | 38 |
| 36 namespace { | 39 namespace { |
| 37 | 40 |
| 38 // Offset from the cursor to the point of the bubble arrow. It looks weird | 41 // Offset from the cursor to the point of the bubble arrow. It looks weird |
| 39 // if the arrow comes up right on top of the cursor, so it is offset by this | 42 // if the arrow comes up right on top of the cursor, so it is offset by this |
| 40 // amount. | 43 // amount. |
| 41 static const int kAnchorOffset = 25; | 44 static const int kAnchorOffset = 25; |
| 42 | 45 |
| 46 CommandLine GetAppListCommandLine() { | |
| 47 CommandLine* current = CommandLine::ForCurrentProcess(); | |
| 48 CommandLine command_line(current->GetProgram()); | |
| 49 | |
| 50 if (current->HasSwitch(switches::kUserDataDir)) { | |
| 51 FilePath user_data_dir = current->GetSwitchValuePath( | |
| 52 switches::kUserDataDir); | |
| 53 command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir); | |
| 54 } | |
| 55 | |
| 56 command_line.AppendSwitch(switches::kShowAppList); | |
| 57 return command_line; | |
| 58 } | |
| 59 | |
| 60 string16 GetAppModelId() { | |
| 61 // The AppModelId should be the same for all profiles in a user data directory | |
| 62 // but different for different user data directories, so base it on the | |
| 63 // initial profile in the current user data directory. | |
| 64 FilePath initial_profile_path; | |
| 65 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 66 if (command_line->HasSwitch(switches::kUserDataDir)) { | |
| 67 initial_profile_path = | |
| 68 command_line->GetSwitchValuePath(switches::kUserDataDir).AppendASCII( | |
| 69 chrome::kInitialProfile); | |
| 70 } | |
| 71 return ShellIntegration::GetAppListAppModelIdForProfile(initial_profile_path); | |
| 72 } | |
| 73 | |
| 43 class AppListControllerDelegateWin : public AppListControllerDelegate { | 74 class AppListControllerDelegateWin : public AppListControllerDelegate { |
| 44 public: | 75 public: |
| 45 AppListControllerDelegateWin(); | 76 AppListControllerDelegateWin(); |
| 46 virtual ~AppListControllerDelegateWin(); | 77 virtual ~AppListControllerDelegateWin(); |
| 47 | 78 |
| 48 private: | 79 private: |
| 49 // AppListController overrides: | 80 // AppListController overrides: |
| 50 virtual void CloseView() OVERRIDE; | 81 virtual void CloseView() OVERRIDE; |
| 51 virtual void ViewClosing() OVERRIDE; | 82 virtual void ViewClosing() OVERRIDE; |
| 52 virtual void ViewActivationChanged(bool active) OVERRIDE; | 83 virtual void ViewActivationChanged(bool active) OVERRIDE; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 79 | 110 |
| 80 private: | 111 private: |
| 81 // Utility methods for showing the app list. | 112 // Utility methods for showing the app list. |
| 82 void GetArrowLocationAndUpdateAnchor( | 113 void GetArrowLocationAndUpdateAnchor( |
| 83 const gfx::Rect& work_area, | 114 const gfx::Rect& work_area, |
| 84 int min_space_x, | 115 int min_space_x, |
| 85 int min_space_y, | 116 int min_space_y, |
| 86 views::BubbleBorder::ArrowLocation* arrow, | 117 views::BubbleBorder::ArrowLocation* arrow, |
| 87 gfx::Point* anchor); | 118 gfx::Point* anchor); |
| 88 void UpdateArrowPositionAndAnchorPoint(app_list::AppListView* view); | 119 void UpdateArrowPositionAndAnchorPoint(app_list::AppListView* view); |
| 89 CommandLine GetAppListCommandLine(); | |
| 90 string16 GetAppListIconPath(); | 120 string16 GetAppListIconPath(); |
| 91 string16 GetAppModelId(); | |
| 92 | 121 |
| 93 // Check if the app list or the taskbar has focus. The app list is kept | 122 // Check if the app list or the taskbar has focus. The app list is kept |
| 94 // visible whenever either of these have focus, which allows it to be | 123 // visible whenever either of these have focus, which allows it to be |
| 95 // pinned but will hide it if it otherwise loses focus. This is checked | 124 // pinned but will hide it if it otherwise loses focus. This is checked |
| 96 // periodically whenever the app list does not have focus. | 125 // periodically whenever the app list does not have focus. |
| 97 void CheckTaskbarOrViewHasFocus(); | 126 void CheckTaskbarOrViewHasFocus(); |
| 98 | 127 |
| 99 // Weak pointer. The view manages its own lifetime. | 128 // Weak pointer. The view manages its own lifetime. |
| 100 app_list::AppListView* current_view_; | 129 app_list::AppListView* current_view_; |
| 101 | 130 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 anchor->Offset(kAnchorOffset, 0); | 286 anchor->Offset(kAnchorOffset, 0); |
| 258 return; | 287 return; |
| 259 } | 288 } |
| 260 | 289 |
| 261 *arrow = views::BubbleBorder::RIGHT_TOP; | 290 *arrow = views::BubbleBorder::RIGHT_TOP; |
| 262 anchor->Offset(-kAnchorOffset, 0); | 291 anchor->Offset(-kAnchorOffset, 0); |
| 263 } | 292 } |
| 264 | 293 |
| 265 void AppListController::UpdateArrowPositionAndAnchorPoint( | 294 void AppListController::UpdateArrowPositionAndAnchorPoint( |
| 266 app_list::AppListView* view) { | 295 app_list::AppListView* view) { |
| 267 static const int kArrowSize = 10; | 296 const int kArrowSize = 10; |
| 268 static const int kPadding = 20; | 297 const int kPadding = 20; |
| 269 | 298 |
| 270 gfx::Size preferred = view->GetPreferredSize(); | 299 gfx::Size preferred = view->GetPreferredSize(); |
| 271 // Add the size of the arrow to the space needed, as the preferred size is | 300 // Add the size of the arrow to the space needed, as the preferred size is |
| 272 // of the view excluding the arrow. | 301 // of the view excluding the arrow. |
| 273 int min_space_x = preferred.width() + kAnchorOffset + kPadding + kArrowSize; | 302 int min_space_x = preferred.width() + kAnchorOffset + kPadding + kArrowSize; |
| 274 int min_space_y = preferred.height() + kAnchorOffset + kPadding + kArrowSize; | 303 int min_space_y = preferred.height() + kAnchorOffset + kPadding + kArrowSize; |
| 275 | 304 |
| 276 gfx::Point anchor = view->anchor_point(); | 305 gfx::Point anchor = view->anchor_point(); |
| 277 gfx::Display display = gfx::Screen::GetScreenFor( | 306 gfx::Display display = gfx::Screen::GetScreenFor( |
| 278 view->GetWidget()->GetNativeView())->GetDisplayNearestPoint(anchor); | 307 view->GetWidget()->GetNativeView())->GetDisplayNearestPoint(anchor); |
| 279 const gfx::Rect& display_rect = display.work_area(); | 308 const gfx::Rect& display_rect = display.work_area(); |
| 280 views::BubbleBorder::ArrowLocation arrow; | 309 views::BubbleBorder::ArrowLocation arrow; |
| 281 GetArrowLocationAndUpdateAnchor(display.work_area(), | 310 GetArrowLocationAndUpdateAnchor(display.work_area(), |
| 282 min_space_x, | 311 min_space_x, |
| 283 min_space_y, | 312 min_space_y, |
| 284 &arrow, | 313 &arrow, |
| 285 &anchor); | 314 &anchor); |
| 286 view->SetBubbleArrowLocation(arrow); | 315 view->SetBubbleArrowLocation(arrow); |
| 287 view->SetAnchorPoint(anchor); | 316 view->SetAnchorPoint(anchor); |
| 288 } | 317 } |
| 289 | 318 |
| 290 CommandLine AppListController::GetAppListCommandLine() { | |
| 291 CommandLine* current = CommandLine::ForCurrentProcess(); | |
| 292 CommandLine command_line(current->GetProgram()); | |
| 293 | |
| 294 if (current->HasSwitch(switches::kUserDataDir)) { | |
| 295 FilePath user_data_dir = current->GetSwitchValuePath( | |
| 296 switches::kUserDataDir); | |
| 297 command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir); | |
| 298 } | |
| 299 | |
| 300 command_line.AppendSwitch(switches::kShowAppList); | |
| 301 return command_line; | |
| 302 } | |
| 303 | |
| 304 string16 AppListController::GetAppListIconPath() { | 319 string16 AppListController::GetAppListIconPath() { |
| 305 FilePath icon_path; | 320 FilePath icon_path; |
| 306 if (!PathService::Get(base::DIR_MODULE, &icon_path)) | 321 if (!PathService::Get(base::DIR_MODULE, &icon_path)) |
| 307 return string16(); | 322 return string16(); |
| 308 | 323 |
| 309 icon_path = icon_path.Append(chrome::kBrowserResourcesDll); | 324 icon_path = icon_path.Append(chrome::kBrowserResourcesDll); |
| 310 std::stringstream ss; | 325 std::stringstream ss; |
| 311 ss << ",-" << IDI_APP_LIST; | 326 ss << ",-" << IDI_APP_LIST; |
| 312 string16 result = icon_path.value(); | 327 string16 result = icon_path.value(); |
| 313 result.append(UTF8ToUTF16(ss.str())); | 328 result.append(UTF8ToUTF16(ss.str())); |
| 314 return result; | 329 return result; |
| 315 } | 330 } |
| 316 | 331 |
| 317 string16 AppListController::GetAppModelId() { | |
| 318 static const wchar_t kAppListId[] = L"ChromeAppList"; | |
| 319 // The AppModelId should be the same for all profiles in a user data directory | |
| 320 // but different for different user data directories, so base it on the | |
| 321 // initial profile in the current user data directory. | |
| 322 FilePath initial_profile_path = | |
| 323 g_browser_process->profile_manager()->GetInitialProfileDir(); | |
| 324 return ShellIntegration::GetAppModelIdForProfile(kAppListId, | |
| 325 initial_profile_path); | |
| 326 } | |
| 327 | |
| 328 void AppListController::CheckTaskbarOrViewHasFocus() { | 332 void AppListController::CheckTaskbarOrViewHasFocus() { |
| 329 #if !defined(USE_AURA) | 333 #if !defined(USE_AURA) |
| 330 // Don't bother checking if the view has been closed. | 334 // Don't bother checking if the view has been closed. |
| 331 if (!current_view_) | 335 if (!current_view_) |
| 332 return; | 336 return; |
| 333 | 337 |
| 334 // First get the taskbar and jump lists windows (the jump list is the | 338 // First get the taskbar and jump lists windows (the jump list is the |
| 335 // context menu which the taskbar uses). | 339 // context menu which the taskbar uses). |
| 336 HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL); | 340 HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL); |
| 337 HWND taskbar_hwnd = FindWindow(L"Shell_TrayWnd", NULL); | 341 HWND taskbar_hwnd = FindWindow(L"Shell_TrayWnd", NULL); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 350 } | 354 } |
| 351 focused_hwnd = GetParent(focused_hwnd); | 355 focused_hwnd = GetParent(focused_hwnd); |
| 352 } | 356 } |
| 353 | 357 |
| 354 // If we get here, the focused window is not the taskbar, it's context menu, | 358 // If we get here, the focused window is not the taskbar, it's context menu, |
| 355 // or the app list, so close the app list. | 359 // or the app list, so close the app list. |
| 356 CloseAppList(); | 360 CloseAppList(); |
| 357 #endif | 361 #endif |
| 358 } | 362 } |
| 359 | 363 |
| 364 void DoCheckAppListTaskbarShortcut(const FilePath user_data_dir, | |
|
sky
2012/10/31 14:20:52
Add a description.
benwells
2012/11/01 05:31:05
Done.
| |
| 365 const string16& app_model_id) { | |
| 366 const wchar_t kAppListShortcutFileName[] = L"Chrome Apps Launcher.lnk"; | |
|
sky
2012/10/31 14:20:52
DCHECK file thread.
benwells
2012/11/01 05:31:05
It was down, it's now at the top.
| |
| 367 const wchar_t kAppListDescription[] = L"Chrome Apps Launcher"; | |
| 368 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); | |
| 369 FilePath shortcut_path(user_data_dir.Append(kAppListShortcutFileName)); | |
| 370 bool should_show = CommandLine::ForCurrentProcess()->HasSwitch( | |
| 371 switches::kShowAppListShortcut); | |
| 372 | |
| 373 // This will not reshow a shortcut if it has been unpinned manually by the | |
| 374 // user, as that will not delete the shortcut file. | |
| 375 if (should_show && !file_util::PathExists(shortcut_path)) { | |
| 376 FilePath chrome_exe; | |
| 377 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) | |
| 378 return; | |
| 379 | |
| 380 base::win::ShortcutProperties shortcut_properties; | |
| 381 shortcut_properties.set_target(chrome_exe); | |
| 382 shortcut_properties.set_working_dir(chrome_exe.DirName()); | |
| 383 | |
| 384 string16 wide_switches(GetAppListCommandLine().GetArgumentsString()); | |
| 385 shortcut_properties.set_arguments(wide_switches); | |
| 386 shortcut_properties.set_description(kAppListDescription); | |
| 387 | |
| 388 FilePath icon_path; | |
| 389 if (!PathService::Get(base::DIR_MODULE, &icon_path)) | |
| 390 return; | |
| 391 | |
| 392 icon_path = icon_path.Append(chrome::kBrowserResourcesDll); | |
| 393 | |
| 394 // Icons are added to the resources of the DLL using icon indexes. The | |
| 395 // icon index for the app list icon is in IDI_APP_LIST. Creating shortcuts | |
| 396 // needs to specify a resource index, which are different to icon indexes. | |
| 397 // They are 0 based and contiguous. As Google Chrome builds have an extra | |
| 398 // icon (SXS) the icon for Google Chrome builds need to be one higher. | |
| 399 #if defined(GOOGLE_CHROME_BUILD) | |
| 400 const int kIconIndex = 26; | |
| 401 #else | |
| 402 const int kIconIndex = 25; | |
| 403 #endif | |
| 404 shortcut_properties.set_icon(icon_path, 25); | |
| 405 shortcut_properties.set_app_id(app_model_id); | |
| 406 shortcut_properties.set_dual_mode(false); | |
| 407 | |
| 408 base::win::CreateOrUpdateShortcutLink(shortcut_path, shortcut_properties, | |
| 409 base::win::SHORTCUT_CREATE_ALWAYS); | |
| 410 base::win::TaskbarPinShortcutLink(shortcut_path.value().c_str()); | |
| 411 return; | |
| 412 } | |
| 413 | |
| 414 if (!should_show && file_util::PathExists(shortcut_path)) { | |
| 415 base::win::TaskbarUnpinShortcutLink(shortcut_path.value().c_str()); | |
| 416 file_util::Delete(shortcut_path, false); | |
| 417 } | |
| 418 } | |
| 419 | |
| 360 } // namespace | 420 } // namespace |
| 361 | 421 |
| 362 namespace app_list_controller { | 422 namespace app_list_controller { |
| 363 | 423 |
| 364 void ShowAppList() { | 424 void ShowAppList() { |
| 365 g_app_list_controller.Get().ShowAppList(); | 425 g_app_list_controller.Get().ShowAppList(); |
| 366 } | 426 } |
| 367 | 427 |
| 428 void CheckAppListTaskbarShortcut() { | |
| 429 FilePath user_data_dir(g_browser_process->profile_manager()->user_data_dir()); | |
| 430 string16 app_model_id = GetAppModelId(); | |
| 431 content::BrowserThread::PostTask( | |
| 432 content::BrowserThread::FILE, | |
| 433 FROM_HERE, | |
| 434 base::Bind(&DoCheckAppListTaskbarShortcut, user_data_dir, app_model_id)); | |
| 435 } | |
| 436 | |
| 368 } // namespace app_list_controller | 437 } // namespace app_list_controller |
| OLD | NEW |