diff options
author | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-14 15:10:57 +0000 |
---|---|---|
committer | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-14 15:10:57 +0000 |
commit | 2d2572e2cb48b11663e16286d4a0c543a00cb308 (patch) | |
tree | 9aa4b4c58d07e2d2a0549b1b17340435997d503e /chrome/browser/tab_contents | |
parent | 1d29268ebd51d80f3dbe32e21bca3c3b77a17a95 (diff) | |
download | chromium_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.h | 4 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_mac.mm | 175 |
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 |