diff options
author | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 21:40:08 +0000 |
---|---|---|
committer | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 21:40:08 +0000 |
commit | 00c8469e26c18b47981a92931acbc209efa8c3e4 (patch) | |
tree | 17c1576f6737ce4d49500baf3805b92a6e4e0af0 /ash | |
parent | 993951d6500d51ee010103c7f8727eaa900bd563 (diff) | |
download | chromium_src-00c8469e26c18b47981a92931acbc209efa8c3e4.zip chromium_src-00c8469e26c18b47981a92931acbc209efa8c3e4.tar.gz chromium_src-00c8469e26c18b47981a92931acbc209efa8c3e4.tar.bz2 |
This is the first of two patches to drag and drop items from the app list to the launcher.
Everything basically works with this patch, but two essential things are still missing:
1. The icon which gets dragged should get its own widget so that it can get visually dragged outside the app list.
2. The unit tests.
They will be send as a second patch because of:
a. The patch is already pretty big as it is.
b. I want to make get this "signed off" before continuing this route.
BUG=166429
TEST=visual, tests come with second patch
Review URL: https://chromiumcodereview.appspot.com/14533006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199016 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/ash_switches.cc | 6 | ||||
-rw-r--r-- | ash/ash_switches.h | 1 | ||||
-rw-r--r-- | ash/launcher/launcher_button_host.h | 1 | ||||
-rw-r--r-- | ash/launcher/launcher_delegate.h | 12 | ||||
-rw-r--r-- | ash/launcher/launcher_view.cc | 134 | ||||
-rw-r--r-- | ash/launcher/launcher_view.h | 22 | ||||
-rw-r--r-- | ash/shell.cc | 7 | ||||
-rw-r--r-- | ash/shell.h | 8 | ||||
-rw-r--r-- | ash/shell/launcher_delegate_impl.cc | 11 | ||||
-rw-r--r-- | ash/shell/launcher_delegate_impl.h | 3 | ||||
-rw-r--r-- | ash/test/test_launcher_delegate.cc | 11 | ||||
-rw-r--r-- | ash/test/test_launcher_delegate.h | 3 | ||||
-rw-r--r-- | ash/wm/app_list_controller.cc | 6 | ||||
-rw-r--r-- | ash/wm/app_list_controller.h | 6 |
14 files changed, 205 insertions, 26 deletions
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc index 516fa60..24fef79 100644 --- a/ash/ash_switches.cc +++ b/ash/ash_switches.cc @@ -141,11 +141,15 @@ const char kAuraLegacyPowerButton[] = "aura-legacy-power-button"; // Force Ash to open its root window on the desktop, even on Windows 8 where // it would normally end up in metro. const char kForceAshToDesktop[] = "ash-force-desktop"; + #endif +// Allow items to be dragged from the app launcher list into the launcher. +const char kAshDragAndDropAppListToLauncher[] = + "ash-drag-and-drop-applist-to-launcher"; + // Enables a mode which enforces all browser & application windows to be created // in maximized mode. const char kForcedMaximizeMode[] = "forced-maximize-mode"; - } // namespace switches } // namespace ash diff --git a/ash/ash_switches.h b/ash/ash_switches.h index 003cd35..d11ef8d 100644 --- a/ash/ash_switches.h +++ b/ash/ash_switches.h @@ -35,6 +35,7 @@ ASH_EXPORT extern const char kAshDisableNewNetworkStatusArea[]; ASH_EXPORT extern const char kAshDisablePerAppLauncher[]; ASH_EXPORT extern const char kAshDisableUIScaling[]; ASH_EXPORT extern const char kAshDisableDisplayRotation[]; +ASH_EXPORT extern const char kAshDragAndDropAppListToLauncher[]; ASH_EXPORT extern const char kAshEnableAudioDeviceMenu[]; ASH_EXPORT extern const char kAshEnableAdvancedGestures[]; ASH_EXPORT extern const char kAshEnableBrightnessControl[]; diff --git a/ash/launcher/launcher_button_host.h b/ash/launcher/launcher_button_host.h index ecb76a3..c867a68c 100644 --- a/ash/launcher/launcher_button_host.h +++ b/ash/launcher/launcher_button_host.h @@ -25,6 +25,7 @@ class ASH_EXPORT LauncherButtonHost { public: enum Pointer { NONE, + DRAG_AND_DROP, MOUSE, TOUCH, }; diff --git a/ash/launcher/launcher_delegate.h b/ash/launcher/launcher_delegate.h index 45109e8..0bd8ec6 100644 --- a/ash/launcher/launcher_delegate.h +++ b/ash/launcher/launcher_delegate.h @@ -106,6 +106,18 @@ class ASH_EXPORT LauncherDelegate { // True if the running launcher is the per application launcher. virtual bool IsPerAppLauncher() = 0; + + // Get the launcher ID from an application ID. + virtual LauncherID GetLauncherIDForAppID(const std::string& app_id) = 0; + + // Pins an app with |app_id| to launcher. A running instance will get pinned. + // In case there is no running instance a new launcher item is created and + // pinned. + virtual void PinAppWithID(const std::string& app_id) = 0; + + // Unpins any app item(s) whose id is |app_id|. The new launcher will collect + // all items under one item, the old launcher might have multiple items. + virtual void UnpinAppsWithID(const std::string& app_id) = 0; }; } // namespace ash diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc index 32e20ec..f0b4bf5 100644 --- a/ash/launcher/launcher_view.cc +++ b/ash/launcher/launcher_view.cc @@ -22,6 +22,7 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell_delegate.h" #include "base/auto_reset.h" +#include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" @@ -377,7 +378,9 @@ LauncherView::LauncherView(LauncherModel* model, cancelling_drag_model_changed_(false), last_hidden_index_(0), closing_event_time_(base::TimeDelta()), - got_deleted_(NULL) { + got_deleted_(NULL), + drag_and_drop_item_created_(false), + drag_and_drop_launcher_id_(0) { DCHECK(model_); bounds_animator_.reset(new views::BoundsAnimator(this)); bounds_animator_->AddObserver(this); @@ -523,6 +526,83 @@ View* LauncherView::GetFocusTraversableParentView() { return this; } +bool LauncherView::StartDrag(const std::string& app_id, + const gfx::Point& location_in_screen_coordinates) { + // Bail if an operation is already going on - or the cursor is not inside. + // This could happen if mouse / touch operations overlap. + if (drag_and_drop_launcher_id_ || + !GetBoundsInScreen().Contains(location_in_screen_coordinates)) + return false; + + // If the AppsGridView (which was dispatching this event) was opened by our + // button, LauncherView dragging operations are locked and we have to unlock. + CancelDrag(-1); + drag_and_drop_item_created_ = false; + drag_and_drop_app_id_ = app_id; + drag_and_drop_launcher_id_ = + delegate_->GetLauncherIDForAppID(drag_and_drop_app_id_); + + if (!drag_and_drop_launcher_id_) { + delegate_->PinAppWithID(app_id); + drag_and_drop_launcher_id_ = + delegate_->GetLauncherIDForAppID(drag_and_drop_app_id_); + if (!drag_and_drop_launcher_id_) + return false; + drag_and_drop_item_created_ = true; + } + views::View* drag_and_drop_view = view_model_->view_at( + model_->ItemIndexByID(drag_and_drop_launcher_id_)); + DCHECK(drag_and_drop_view); + + // Since there is already an icon presented, we hide this one for now. + drag_and_drop_view->SetVisible(false); + // First we have to center the mouse cursor over the item. + gfx::Point pt = drag_and_drop_view->GetBoundsInScreen().CenterPoint(); + views::View::ConvertPointFromScreen(drag_and_drop_view, &pt); + ui::MouseEvent event(ui::ET_MOUSE_PRESSED, + pt, location_in_screen_coordinates, 0); + PointerPressedOnButton( + drag_and_drop_view, LauncherButtonHost::DRAG_AND_DROP, event); + + // Drag the item where it really belongs. + Drag(location_in_screen_coordinates); + return true; +} + +bool LauncherView::Drag(const gfx::Point& location_in_screen_coordinates) { + if (!drag_and_drop_launcher_id_ || + !GetBoundsInScreen().Contains(location_in_screen_coordinates)) + return false; + + gfx::Point pt = location_in_screen_coordinates; + views::View* drag_and_drop_view = view_model_->view_at( + model_->ItemIndexByID(drag_and_drop_launcher_id_)); + views::View::ConvertPointFromScreen(drag_and_drop_view, &pt); + + ui::MouseEvent event(ui::ET_MOUSE_DRAGGED, pt, gfx::Point(), 0); + PointerDraggedOnButton( + drag_and_drop_view, LauncherButtonHost::DRAG_AND_DROP, event); + return true; +} + +void LauncherView::EndDrag(bool cancel) { + if (!drag_and_drop_launcher_id_) + return; + + views::View* drag_and_drop_view = view_model_->view_at( + model_->ItemIndexByID(drag_and_drop_launcher_id_)); + PointerReleasedOnButton( + drag_and_drop_view, LauncherButtonHost::DRAG_AND_DROP, cancel); + + if (drag_and_drop_item_created_ && cancel) + delegate_->UnpinAppsWithID(drag_and_drop_app_id_); + + if (drag_and_drop_view) + drag_and_drop_view->SetVisible(true); + + drag_and_drop_launcher_id_ = 0; +} + void LauncherView::LayoutToIdealBounds() { IdealBounds ideal_bounds; CalculateIdealBounds(&ideal_bounds); @@ -1340,31 +1420,37 @@ void LauncherView::ButtonPressed(views::Button* sender, ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); } - // Collect usage statistics before we decide what to do with the click. - switch (model_->items()[view_index].type) { - case TYPE_APP_SHORTCUT: - case TYPE_WINDOWED_APP: - case TYPE_PLATFORM_APP: - Shell::GetInstance()->delegate()->RecordUserMetricsAction( - UMA_LAUNCHER_CLICK_ON_APP); - // Fallthrough - case TYPE_TABBED: - case TYPE_APP_PANEL: - delegate_->ItemSelected(model_->items()[view_index], event); - break; + // Collect usage statistics before we decide what to do with the click. + switch (model_->items()[view_index].type) { + case TYPE_APP_SHORTCUT: + case TYPE_WINDOWED_APP: + case TYPE_PLATFORM_APP: + Shell::GetInstance()->delegate()->RecordUserMetricsAction( + UMA_LAUNCHER_CLICK_ON_APP); + // Fallthrough + case TYPE_TABBED: + case TYPE_APP_PANEL: + delegate_->ItemSelected(model_->items()[view_index], event); + break; - case TYPE_APP_LIST: - Shell::GetInstance()->delegate()->RecordUserMetricsAction( - UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON); - Shell::GetInstance()->ToggleAppList(GetWidget()->GetNativeView()); - break; + case TYPE_APP_LIST: + Shell::GetInstance()->delegate()->RecordUserMetricsAction( + UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON); + Shell::GetInstance()->ToggleAppList(GetWidget()->GetNativeView()); + // By setting us as DnD recipient, the app list knows that we can + // handle items. + // TODO(skuhne): Invert the flag + if (CommandLine::ForCurrentProcess()->HasSwitch( + ash::switches::kAshDragAndDropAppListToLauncher)) + Shell::GetInstance()->SetDragAndDropHostOfCurrentAppList(this); + break; - case TYPE_BROWSER_SHORTCUT: - // Click on browser icon is counted in app clicks. - Shell::GetInstance()->delegate()->RecordUserMetricsAction( - UMA_LAUNCHER_CLICK_ON_APP); - delegate_->OnBrowserShortcutClicked(event.flags()); - break; + case TYPE_BROWSER_SHORTCUT: + // Click on browser icon is counted in app clicks. + Shell::GetInstance()->delegate()->RecordUserMetricsAction( + UMA_LAUNCHER_CLICK_ON_APP); + delegate_->OnBrowserShortcutClicked(event.flags()); + break; } } diff --git a/ash/launcher/launcher_view.h b/ash/launcher/launcher_view.h index 3b1f0f3..b7b8c93 100644 --- a/ash/launcher/launcher_view.h +++ b/ash/launcher/launcher_view.h @@ -12,6 +12,7 @@ #include "ash/launcher/launcher_model_observer.h" #include "ash/wm/gestures/shelf_gesture_handler.h" #include "base/observer_list.h" +#include "ui/app_list/views/app_list_drag_and_drop_host.h" #include "ui/views/animation/bounds_animator_observer.h" #include "ui/views/context_menu_controller.h" #include "ui/views/controls/button/button.h" @@ -50,7 +51,8 @@ class ASH_EXPORT LauncherView : public views::View, public LauncherButtonHost, public views::ContextMenuController, public views::FocusTraversable, - public views::BoundsAnimatorObserver { + public views::BoundsAnimatorObserver, + public app_list::ApplicationDragAndDropHost { public: LauncherView(LauncherModel* model, LauncherDelegate* delegate, @@ -97,6 +99,13 @@ class ASH_EXPORT LauncherView : public views::View, virtual FocusTraversable* GetFocusTraversableParent() OVERRIDE; virtual View* GetFocusTraversableParentView() OVERRIDE; + // Overridden from app_list::ApplicationDragAndDropHost: + virtual bool StartDrag( + const std::string& app_id, + const gfx::Point& location_in_screen_coordinates) OVERRIDE; + virtual bool Drag(const gfx::Point& location_in_screen_coordinates) OVERRIDE; + virtual void EndDrag(bool cancel) OVERRIDE; + private: friend class ash::test::LauncherViewTestAPI; @@ -320,6 +329,17 @@ class ASH_EXPORT LauncherView : public views::View, // element will be set to false. bool* got_deleted_; + // True if a drag and drop operation created the item in the launcher and it + // needs to be deleted again if the operation gets cancelled. + bool drag_and_drop_item_created_; + + // The launcher item which is currently used for a drag and a drop operation + // or 0 otherwise. + LauncherID drag_and_drop_launcher_id_; + + // The application ID of the application which we drag and drop. + std::string drag_and_drop_app_id_; + DISALLOW_COPY_AND_ASSIGN(LauncherView); }; diff --git a/ash/shell.cc b/ash/shell.cc index 4be78a2..4f6e936 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -650,6 +650,13 @@ void Shell::ToggleAppList(aura::Window* window) { app_list_controller_->SetVisible(!app_list_controller_->IsVisible(), window); } +void Shell::SetDragAndDropHostOfCurrentAppList( + app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + if (app_list_controller_.get()) + app_list_controller_->SetDragAndDropHostOfCurrentAppList( + drag_and_drop_host); +} + bool Shell::GetAppListTargetVisibility() const { return app_list_controller_.get() && app_list_controller_->GetTargetVisibility(); diff --git a/ash/shell.h b/ash/shell.h index b8a0ce9..cb96ee6 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -26,6 +26,9 @@ class CommandLine; +namespace app_list { +class ApplicationDragAndDropHost; +} namespace aura { class EventFilter; class RootWindow; @@ -217,6 +220,11 @@ class ASH_EXPORT Shell // will be used. void ToggleAppList(aura::Window* anchor); + // If |drag_and_drop_host| is not NULL it will be called upon drag and drop + // operations outside the application list. + void SetDragAndDropHostOfCurrentAppList( + app_list::ApplicationDragAndDropHost* drag_and_drop_host); + // Returns app list target visibility. bool GetAppListTargetVisibility() const; diff --git a/ash/shell/launcher_delegate_impl.cc b/ash/shell/launcher_delegate_impl.cc index b38dee3..601adac 100644 --- a/ash/shell/launcher_delegate_impl.cc +++ b/ash/shell/launcher_delegate_impl.cc @@ -80,5 +80,16 @@ bool LauncherDelegateImpl::IsPerAppLauncher() { return false; } +LauncherID LauncherDelegateImpl::GetLauncherIDForAppID( + const std::string& app_id) { + return 0; +} + +void LauncherDelegateImpl::PinAppWithID(const std::string& app_id) { +} + +void LauncherDelegateImpl::UnpinAppsWithID(const std::string& app_id) { +} + } // namespace shell } // namespace ash diff --git a/ash/shell/launcher_delegate_impl.h b/ash/shell/launcher_delegate_impl.h index e57b5b4..26b1dfd 100644 --- a/ash/shell/launcher_delegate_impl.h +++ b/ash/shell/launcher_delegate_impl.h @@ -42,6 +42,9 @@ class LauncherDelegateImpl : public ash::LauncherDelegate { virtual void OnLauncherCreated(Launcher* launcher) OVERRIDE; virtual void OnLauncherDestroyed(Launcher* launcher) OVERRIDE; virtual bool IsPerAppLauncher() OVERRIDE; + virtual LauncherID GetLauncherIDForAppID(const std::string& app_id) OVERRIDE; + virtual void PinAppWithID(const std::string& app_id) OVERRIDE; + virtual void UnpinAppsWithID(const std::string& app_id) OVERRIDE; private: // Used to update Launcher. Owned by main. diff --git a/ash/test/test_launcher_delegate.cc b/ash/test/test_launcher_delegate.cc index 16422e3..3a4fccd 100644 --- a/ash/test/test_launcher_delegate.cc +++ b/ash/test/test_launcher_delegate.cc @@ -131,5 +131,16 @@ bool TestLauncherDelegate::IsPerAppLauncher() { return true; } +LauncherID TestLauncherDelegate::GetLauncherIDForAppID( + const std::string& app_id) { + return 0; +} + +void TestLauncherDelegate::PinAppWithID(const std::string& app_id) { +} + +void TestLauncherDelegate::UnpinAppsWithID(const std::string& app_id) { +} + } // namespace test } // namespace ash diff --git a/ash/test/test_launcher_delegate.h b/ash/test/test_launcher_delegate.h index b86b1e1..65dc634 100644 --- a/ash/test/test_launcher_delegate.h +++ b/ash/test/test_launcher_delegate.h @@ -51,6 +51,9 @@ class TestLauncherDelegate : public LauncherDelegate, virtual void OnLauncherCreated(Launcher* launcher) OVERRIDE; virtual void OnLauncherDestroyed(Launcher* launcher) OVERRIDE; virtual bool IsPerAppLauncher() OVERRIDE; + virtual LauncherID GetLauncherIDForAppID(const std::string& app_id) OVERRIDE; + virtual void PinAppWithID(const std::string& app_id) OVERRIDE; + virtual void UnpinAppsWithID(const std::string& app_id) OVERRIDE; private: typedef std::map<aura::Window*, ash::LauncherID> WindowToID; diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc index 7fcf76c..02afc69 100644 --- a/ash/wm/app_list_controller.cc +++ b/ash/wm/app_list_controller.cc @@ -139,6 +139,12 @@ aura::Window* AppListController::GetWindow() { return is_visible_ && view_ ? view_->GetWidget()->GetNativeWindow() : NULL; } +void AppListController::SetDragAndDropHostOfCurrentAppList( + app_list::ApplicationDragAndDropHost* drag_and_drop_host) { + if (view_ && is_visible_) + view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); +} + //////////////////////////////////////////////////////////////////////////////// // AppListController, private: diff --git a/ash/wm/app_list_controller.h b/ash/wm/app_list_controller.h index d2408d8..6f05d6a 100644 --- a/ash/wm/app_list_controller.h +++ b/ash/wm/app_list_controller.h @@ -19,6 +19,7 @@ #include "ui/views/widget/widget_observer.h" namespace app_list { +class ApplicationDragAndDropHost; class AppListView; class PaginationModel; } @@ -61,6 +62,11 @@ class AppListController : public ui::EventHandler, // Returns app list window or NULL if it is not visible. aura::Window* GetWindow(); + // If |drag_and_drop_host| is not NULL it will be called upon drag and drop + // operations outside the application list. + void SetDragAndDropHostOfCurrentAppList( + app_list::ApplicationDragAndDropHost* drag_and_drop_host); + private: // Sets the app list view and attempts to show it. void SetView(app_list::AppListView* view); |