1 // Copyright 2012 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.
5 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
7 #import <Cocoa/Cocoa.h>
11 #include "base/logging.h"
12 #include "base/mac/scoped_nsobject.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
19 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
20 #import "chrome/browser/ui/cocoa/drag_util.h"
21 #include "components/bookmarks/browser/bookmark_model.h"
22 #include "components/bookmarks/browser/bookmark_node_data.h"
23 #include "ui/base/dragdrop/drag_drop_types.h"
25 using bookmarks::BookmarkModel;
26 using bookmarks::BookmarkNode;
30 // Make a drag image from the drop data.
31 NSImage* MakeDragImage(BookmarkModel* model,
32 const std::vector<const BookmarkNode*>& nodes) {
33 if (nodes.size() == 1) {
34 const BookmarkNode* node = nodes[0];
35 const gfx::Image& favicon = model->GetFavicon(node);
36 return drag_util::DragImageForBookmark(
37 favicon.IsEmpty() ? nil : favicon.ToNSImage(),
39 bookmarks::kDefaultBookmarkWidth);
41 // TODO(feldstein): Do something better than this. Should have badging
42 // and a single drag image.
43 // http://crbug.com/37264
44 return [NSImage imageNamed:NSImageNameMultipleDocuments];
52 void DragBookmarks(Profile* profile,
53 const std::vector<const BookmarkNode*>& nodes,
55 ui::DragDropTypes::DragEventSource source) {
56 DCHECK(!nodes.empty());
58 // Allow nested message loop so we get DnD events as we drag this around.
59 base::MessageLoop::ScopedNestableTaskAllower nestable_task_allower(
60 base::MessageLoop::current());
62 bookmarks::BookmarkNodeData drag_data(nodes);
63 drag_data.SetOriginatingProfilePath(profile->GetPath());
64 drag_data.WriteToClipboard(ui::CLIPBOARD_TYPE_DRAG);
66 // Synthesize an event for dragging, since we can't be sure that
67 // [NSApp currentEvent] will return a valid dragging event.
68 NSWindow* window = [view window];
69 NSPoint position = [window mouseLocationOutsideOfEventStream];
70 NSTimeInterval event_time = [[NSApp currentEvent] timestamp];
71 NSEvent* drag_event = [NSEvent mouseEventWithType:NSLeftMouseDragged
73 modifierFlags:NSLeftMouseDraggedMask
75 windowNumber:[window windowNumber]
81 // TODO(avi): Do better than this offset.
82 NSImage* drag_image = MakeDragImage(
83 BookmarkModelFactory::GetForProfile(profile), nodes);
84 NSSize image_size = [drag_image size];
85 position.x -= std::floor(image_size.width / 2);
86 position.y -= std::floor(image_size.height / 5);
87 [window dragImage:drag_image
91 pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]