Chromium Code Reviews| Index: ash/launcher/launcher_view.cc | 
| diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc | 
| index 32e20ec1f9db463687d9910e57ccc88b60ffb477..f0b4bf5b47e4b558d61a52b5aa0075d8d104c66f 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); | 
| 
 
xiyuan
2013/05/08 16:43:47
What happens if app list is invoked via shortcut k
 
 | 
| + 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; | 
| } | 
| } |