summaryrefslogtreecommitdiffstats
path: root/chrome/browser/tab_contents
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-14 15:10:57 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-14 15:10:57 +0000
commit2d2572e2cb48b11663e16286d4a0c543a00cb308 (patch)
tree9aa4b4c58d07e2d2a0549b1b17340435997d503e /chrome/browser/tab_contents
parent1d29268ebd51d80f3dbe32e21bca3c3b77a17a95 (diff)
downloadchromium_src-2d2572e2cb48b11663e16286d4a0c543a00cb308.zip
chromium_src-2d2572e2cb48b11663e16286d4a0c543a00cb308.tar.gz
chromium_src-2d2572e2cb48b11663e16286d4a0c543a00cb308.tar.bz2
Allow dragging text/url content out of the browser. Dragging back in not yet implemented.
BUG=13155 TEST=dragging urls and selected text to other apps, the desktop, or the Dock should work. Review URL: http://codereview.chromium.org/149565 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20619 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/tab_contents')
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_mac.h4
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_mac.mm175
2 files changed, 162 insertions, 17 deletions
diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.h b/chrome/browser/tab_contents/tab_contents_view_mac.h
index 5b464b9..563fc79 100644
--- a/chrome/browser/tab_contents/tab_contents_view_mac.h
+++ b/chrome/browser/tab_contents/tab_contents_view_mac.h
@@ -74,7 +74,9 @@ class TabContentsViewMac : public TabContentsView,
const NotificationDetails& details);
private:
- // ---------------------------------------------------------------------------
+ // Returns a drag pasteboard filled with the appropriate data. The types are
+ // populated in decending order of richness.
+ NSPasteboard* FillDragData(const WebDropData& drop_data);
// The Cocoa NSView that lives in the view hierarchy.
scoped_nsobject<TabContentsViewCocoa> cocoa_view_;
diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.mm b/chrome/browser/tab_contents/tab_contents_view_mac.mm
index 1731658..fced871 100644
--- a/chrome/browser/tab_contents/tab_contents_view_mac.mm
+++ b/chrome/browser/tab_contents/tab_contents_view_mac.mm
@@ -4,7 +4,9 @@
#include "chrome/browser/tab_contents/tab_contents_view_mac.h"
+#include "base/sys_string_conversions.h"
#include "chrome/browser/browser.h" // TODO(beng): this dependency is awful.
+#include "chrome/browser/cocoa/nsimage_cache.h"
#include "chrome/browser/cocoa/sad_tab_view.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
@@ -13,6 +15,8 @@
#include "chrome/common/notification_type.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/render_messages.h"
+#include "net/base/net_util.h"
+#import "third_party/mozilla/include/NSPasteboard+Utils.h"
#include "chrome/common/temp_scaffolding_stubs.h"
@@ -78,15 +82,100 @@ void TabContentsViewMac::GetContainerBounds(gfx::Rect* out) const {
*out = [cocoa_view_.get() NSRectToRect:[cocoa_view_.get() bounds]];
}
-void TabContentsViewMac::StartDragging(const WebDropData& drop_data) {
- NOTIMPLEMENTED();
+// Returns a drag pasteboard filled with the appropriate data. The types are
+// populated in decending order of richness.
+NSPasteboard* TabContentsViewMac::FillDragData(
+ const WebDropData& drop_data) {
+ NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+ [pasteboard declareTypes:[NSArray array] owner:nil];
+
+ // HTML.
+ if (!drop_data.text_html.empty()) {
+ [pasteboard addTypes:[NSArray arrayWithObject:NSHTMLPboardType]
+ owner:nil];
+ [pasteboard setString:base::SysUTF16ToNSString(drop_data.text_html)
+ forType:NSHTMLPboardType];
+ }
+
+ // URL.
+ if (drop_data.url.is_valid()) {
+ // TODO(pinkerton/jrg): special javascript: handling for bookmark bar. Win
+ // doesn't allow you to drop js: bookmarks on the desktop (since they're
+ // meaningless) but does allow you to drop them on the bookmark bar (where
+ // they're intended to go generally). We need to figure out a private
+ // flavor for Bookmark dragging and then flag this down in the drag source.
+ [pasteboard addTypes:[NSArray arrayWithObject:NSURLPboardType]
+ owner:nil];
+ NSString* url = base::SysUTF8ToNSString(drop_data.url.spec());
+ NSString* title = base::SysUTF16ToNSString(drop_data.url_title);
+ [pasteboard setURLs:[NSArray arrayWithObject:url]
+ withTitles:[NSArray arrayWithObject:title]];
+ }
+
+ // Files.
+ // TODO(pinkerton): Hook up image drags, data is in drop_data.file_contents.
+ if (!drop_data.file_contents.empty()) {
+#if 0
+ // Images without ALT text will only have a file extension so we need to
+ // synthesize one from the provided extension and URL.
+ std::string filename_utf8 =
+ [base::SysUTF16ToNSString(drop_data.file_description_filename)
+ fileSystemRepresentation];
+ FilePath file_name(filename_utf8);
+ file_name = file_name.BaseName().RemoveExtension();
+ if (file_name.value().empty()) {
+ // Retrieve the name from the URL.
+ file_name = FilePath::FromWStringHack(
+ net::GetSuggestedFilename(drop_data.url, "", "", L""));
+ }
+ std::string file_extension_utf8 =
+ [base::SysUTF16ToNSString(drop_data.file_extension)
+ fileSystemRepresentation];
+ file_name = file_name.ReplaceExtension(file_extension_utf8);
+ NSArray* types = [NSArray arrayWithObjects:NSFileContentsPboardType,
+ NSFilenamesPboardType,
+ nil];
+ [pasteboard addTypes:types owner:nil];
+ NSArray* file_name_array =
+ [NSArray arrayWithObject:base::SysUTF8ToNSString(file_name.value())];
+ [pasteboard setPropertyList:file_name_array forType:NSFilenamesPboardType];
+ NSData* data = [NSData dataWithBytes:drop_data.file_contents.data()
+ length:drop_data.file_contents.length()];
+ [pasteboard setData:data forType:NSFileContentsPboardType];
+#endif
+ }
- // Until we have d'n'd implemented, just immediately pretend we're
- // already done with the drag and drop so we don't get stuck
- // thinking we're in mid-drag.
- // TODO(port): remove me when the above NOTIMPLEMENTED is fixed.
- if (tab_contents()->render_view_host())
- tab_contents()->render_view_host()->DragSourceSystemDragEnded();
+ // Plain text.
+ if (!drop_data.plain_text.empty()) {
+ [pasteboard addTypes:[NSArray arrayWithObject:NSStringPboardType]
+ owner:nil];
+ [pasteboard setString:base::SysUTF16ToNSString(drop_data.plain_text)
+ forType:NSStringPboardType];
+ }
+ return pasteboard;
+}
+
+void TabContentsViewMac::StartDragging(const WebDropData& drop_data) {
+ // Create an image to use for the drag.
+ // TODO(pinkerton): Generate the proper image. This one will do in a pinch.
+ NSImage* dragImage = nsimage_cache::ImageNamed(@"nav.pdf");
+
+ NSPasteboard* pasteboard = FillDragData(drop_data);
+
+ // Tell the view to start a drag using |cocoa_view_| as the drag source. The
+ // source will get notified when the drag completes (success or failure) so
+ // it can tell the render view host the drag is done. Windows does this with
+ // a nested event loop, we get called back.
+ NSEvent* currentEvent = [NSApp currentEvent];
+ NSPoint mousePoint = [currentEvent locationInWindow];
+ mousePoint = [cocoa_view_ convertPoint:mousePoint fromView:nil];
+ [cocoa_view_ dragImage:dragImage
+ at:mousePoint
+ offset:NSZeroSize
+ event:currentEvent
+ pasteboard:pasteboard
+ source:cocoa_view_
+ slideBack:YES];
}
void TabContentsViewMac::OnContentsDestroy() {
@@ -246,6 +335,10 @@ void TabContentsViewMac::Observe(NotificationType type,
return self;
}
+- (TabContents*)tabContents {
+ return TabContentsView_->tab_contents();
+}
+
- (void)processKeyboardEvent:(NSEvent*)event {
if ([event type] == NSKeyDown)
[super keyDown:event];
@@ -254,13 +347,12 @@ void TabContentsViewMac::Observe(NotificationType type,
}
- (void)mouseEvent:(NSEvent *)theEvent {
- if (TabContentsView_->tab_contents()->delegate()) {
+ TabContents* tabContents = [self tabContents];
+ if (tabContents->delegate()) {
if ([theEvent type] == NSMouseMoved)
- TabContentsView_->tab_contents()->delegate()->
- ContentsMouseEvent(TabContentsView_->tab_contents(), true);
+ tabContents->delegate()->ContentsMouseEvent(tabContents, true);
if ([theEvent type] == NSMouseExited)
- TabContentsView_->tab_contents()->delegate()->
- ContentsMouseEvent(TabContentsView_->tab_contents(), false);
+ tabContents->delegate()->ContentsMouseEvent(tabContents, false);
}
}
@@ -279,15 +371,66 @@ void TabContentsViewMac::Observe(NotificationType type,
// WebCore.
- (void)cut:(id)sender {
- TabContentsView_->tab_contents()->Cut();
+ [self tabContents]->Cut();
}
- (void)copy:(id)sender {
- TabContentsView_->tab_contents()->Copy();
+ [self tabContents]->Copy();
}
- (void)paste:(id)sender {
- TabContentsView_->tab_contents()->Paste();
+ [self tabContents]->Paste();
+}
+
+// NSDraggingSource methods
+
+// Returns what kind of drag operations are available. This is a required
+// method for NSDraggingSource.
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
+ // TODO(pinkerton): I think this is right...
+ return NSDragOperationCopy;
+}
+
+// Called when a drag initiated in our view ends. We need to make sure that
+// we tell WebCore so that it can go about processing things as normal.
+- (void)draggedImage:(NSImage*)anImage
+ endedAt:(NSPoint)aPoint
+ operation:(NSDragOperation)operation {
+ RenderViewHost* rvh = [self tabContents]->render_view_host();
+ if (rvh)
+ rvh->DragSourceSystemDragEnded();
+}
+
+// NSDraggingDestination methods
+
+- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
+ TabContents* tabContents = [self tabContents];
+ if (tabContents->showing_interstitial_page()) {
+ // TODO(pinkerton): hook up dropping only urls
+ return NSDragOperationNone;
+ }
+
+ // TODO(pinkerton): Fill this in when we're tracking drags w/in the content.
+ // Fill out a WebDropData from pasteboard
+ // Convert event point to gfx::Point
+ // Pass to tabContents->render_view_host()->DragTargetDragEnter(...)
+
+ return NSDragOperationCopy;
+}
+
+- (void)draggingExited:(id<NSDraggingInfo>)sender {
+ // TODO(pinkerton): Fill this in when we're tracking drags w/in the content.
+}
+
+- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender {
+ // TODO(pinkerton): Fill this in when we're tracking drags w/in the content.
+ return NSDragOperationCopy;
+}
+
+- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
+ // TODO(pinkerton): Fill this in when we're tracking drags w/in the content.
+ // Reject all drops until then.
+ return NO;
}
// Tons of stuff goes here, where we grab events going on in Cocoaland and send