Camino only - Bug 377719: Fix cursors behavior when dragging text to the tab bar. r=jeff sr=pink
git-svn-id: svn://10.0.0.236/trunk@250383 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -97,6 +97,7 @@ const int kBookmarksContextMenuArrangeSeparatorTag = 100;
|
||||
|
||||
+ (NSArray*)serializableArrayWithBookmarkItems:(NSArray*)bmArray;
|
||||
+ (NSArray*)bookmarkItemsFromSerializableArray:(NSArray*)bmArray;
|
||||
+ (NSArray*)bookmarkURLsFromSerializableArray:(NSArray*)bmArray;
|
||||
|
||||
// Getters/Setters
|
||||
- (BookmarkFolder *)rootBookmarks;
|
||||
|
||||
@@ -184,6 +184,21 @@ static BookmarkManager* gBookmarkManager = nil;
|
||||
return itemsArray;
|
||||
}
|
||||
|
||||
+ (NSArray*)bookmarkURLsFromSerializableArray:(NSArray*)dataArray
|
||||
{
|
||||
NSArray* bookmarkItems = [self bookmarkItemsFromSerializableArray:dataArray];
|
||||
NSMutableArray* bookmarkURLs = [NSMutableArray arrayWithCapacity:[bookmarkItems count]];
|
||||
NSEnumerator* enumerator = [bookmarkItems objectEnumerator];
|
||||
BookmarkItem* aBookmark;
|
||||
while ((aBookmark = [enumerator nextObject])) {
|
||||
if ([aBookmark isKindOfClass:[Bookmark class]] && ![aBookmark isSeparator])
|
||||
[bookmarkURLs addObject:[(Bookmark*)aBookmark url]];
|
||||
else if ([aBookmark isKindOfClass:[BookmarkFolder class]])
|
||||
[bookmarkURLs addObjectsFromArray:[(BookmarkFolder*)aBookmark childURLs]];
|
||||
}
|
||||
return bookmarkURLs;
|
||||
}
|
||||
|
||||
// return a string with the "canonical" bookmark url (strip trailing slashes, lowercase)
|
||||
+ (NSString*)canonicalBookmarkURL:(NSString*)inBookmarkURL
|
||||
{
|
||||
|
||||
@@ -618,7 +618,7 @@ static const int kBMBarScanningStep = 5;
|
||||
|
||||
// NSDraggingDestination ///////////
|
||||
|
||||
- (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
// we have to set the drag target before we can test for drop validation
|
||||
[self setButtonInsertionPoint:sender];
|
||||
@@ -648,7 +648,7 @@ static const int kBMBarScanningStep = 5;
|
||||
mDragInsertionPosition = CHInsertNone;
|
||||
}
|
||||
|
||||
- (unsigned int)draggingUpdated:(id <NSDraggingInfo>)sender
|
||||
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
if (mDragInsertionPosition)
|
||||
[self setNeedsDisplayInRect:[self insertionHiliteRectForButton:mDragInsertionButton position:mDragInsertionPosition]];
|
||||
|
||||
@@ -719,8 +719,11 @@ static const float kScrollButtonInterval = 0.15; // time (in seconds) between f
|
||||
#pragma mark -
|
||||
|
||||
// NSDraggingDestination destination methods
|
||||
-(unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
if (![mTabView shouldAcceptDrag:sender])
|
||||
return NSDragOperationNone;
|
||||
|
||||
mDragOverBar = YES;
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
@@ -738,7 +741,7 @@ static const float kScrollButtonInterval = 0.15; // time (in seconds) between f
|
||||
|
||||
-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return [mTabView prepareForDragOperation:sender];
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
@@ -746,7 +749,7 @@ static const float kScrollButtonInterval = 0.15; // time (in seconds) between f
|
||||
mDragOverBar = NO;
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
return [mTabView performDragOperation:sender];
|
||||
return [mTabView handleDrop:sender onTab:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -48,8 +48,6 @@ extern NSString* const kTabBarBackgroundDoubleClickedNotification;
|
||||
@interface BrowserTabView : NSTabView
|
||||
{
|
||||
BOOL mBarAlwaysVisible;
|
||||
BOOL mIsDropTarget;
|
||||
BOOL mLastClickIsPotentialDrag;
|
||||
BOOL mVisible; // YES if the view is in the hierarchy
|
||||
IBOutlet BrowserTabBarView * mTabBar;
|
||||
|
||||
@@ -79,6 +77,12 @@ extern NSString* const kTabBarBackgroundDoubleClickedNotification;
|
||||
- (BOOL)windowShouldClose;
|
||||
- (void)windowClosed;
|
||||
|
||||
// Returns YES if |dragInfo| is a valid drag for a tab or the tab bar, NO if not.
|
||||
- (BOOL)shouldAcceptDrag:(id <NSDraggingInfo>)dragInfo;
|
||||
// Handle drag and drop of one or more URLs; returns YES if the drop was valid.
|
||||
// If |targetTab| is nil, then the drop is on the tab bar background.
|
||||
- (BOOL)handleDrop:(id <NSDraggingInfo>)dragInfo onTab:(NSTabViewItem*)targetTab;
|
||||
|
||||
// get and set the "jumpback tab", the tab that is jumped to when the currently
|
||||
// visible tab is closed. Reset automatically when switching tabs or after
|
||||
// jumping back. This isn't designed to be a tab history, it only lives for a very
|
||||
|
||||
@@ -44,8 +44,6 @@
|
||||
#import "BrowserTabViewItem.h"
|
||||
#import "TabButtonView.h"
|
||||
#import "BrowserWrapper.h"
|
||||
#import "BookmarkFolder.h"
|
||||
#import "Bookmark.h"
|
||||
#import "BookmarkManager.h"
|
||||
#import "BrowserTabBarView.h"
|
||||
#import "BrowserWindowController.h"
|
||||
@@ -64,17 +62,11 @@ NSString* const kTabBarBackgroundDoubleClickedNotification = @"kTabBarBackground
|
||||
|
||||
@interface BrowserTabView (Private)
|
||||
- (void)showOrHideTabsAsAppropriate;
|
||||
- (void)handleDropOnTab:(NSTabViewItem*)targetTab withURLs:(NSArray*)urls;
|
||||
- (BrowserTabViewItem*)getTabViewItemFromWindowPoint:(NSPoint)point;
|
||||
- (void)showDragDestinationIndicator;
|
||||
- (void)hideDragDestinationIndicator;
|
||||
|
||||
- (NSArray*)urlsFromPasteboard:(NSPasteboard*)pasteboard;
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
#define kTabDropTargetHeight 18.0
|
||||
|
||||
@implementation BrowserTabView
|
||||
|
||||
/******************************************/
|
||||
@@ -95,9 +87,6 @@ NSString* const kTabBarBackgroundDoubleClickedNotification = @"kTabBarBackground
|
||||
mBarAlwaysVisible = NO;
|
||||
mVisible = YES;
|
||||
[self showOrHideTabsAsAppropriate];
|
||||
[self registerForDraggedTypes:[NSArray arrayWithObjects:
|
||||
kCaminoBookmarkListPBoardType, kWebURLsWithTitlesPboardType,
|
||||
NSStringPboardType, NSFilenamesPboardType, NSURLPboardType, nil]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tabWillChange:)
|
||||
name:kTabWillChangeNotifcation object:nil];
|
||||
}
|
||||
@@ -112,21 +101,6 @@ NSString* const kTabBarBackgroundDoubleClickedNotification = @"kTabBarBackground
|
||||
/*** Overridden Methods ***/
|
||||
/******************************************/
|
||||
|
||||
- (void)drawRect:(NSRect)aRect
|
||||
{
|
||||
if (mIsDropTarget)
|
||||
{
|
||||
NSRect hilightRect = aRect;
|
||||
hilightRect.size.height = kTabDropTargetHeight; // no need to move origin.y; our coords are flipped
|
||||
NSBezierPath* dropTargetOutline = [NSBezierPath bezierPathWithRect:hilightRect];
|
||||
|
||||
[[[NSColor colorForControlTint:NSDefaultControlTint] colorWithAlphaComponent:0.5] set];
|
||||
[dropTargetOutline fill];
|
||||
}
|
||||
|
||||
[super drawRect:aRect];
|
||||
}
|
||||
|
||||
- (void)addTabViewItem:(NSTabViewItem *)tabViewItem
|
||||
{
|
||||
// creating a new tab means clearing the jumpback tab.
|
||||
@@ -344,122 +318,40 @@ NSString* const kTabBarBackgroundDoubleClickedNotification = @"kTabBarBackground
|
||||
[self showOrHideTabsAsAppropriate];
|
||||
}
|
||||
|
||||
- (BrowserTabViewItem*)getTabViewItemFromWindowPoint:(NSPoint)point
|
||||
{
|
||||
NSPoint localPoint = [self convertPoint: point fromView: nil];
|
||||
NSTabViewItem* overTabViewItem = [self tabViewItemAtPoint: localPoint];
|
||||
return (BrowserTabViewItem*)overTabViewItem;
|
||||
}
|
||||
|
||||
- (void)showDragDestinationIndicator
|
||||
{
|
||||
if (!mIsDropTarget)
|
||||
{
|
||||
NSRect invalidRect = [self bounds];
|
||||
invalidRect.size.height = kTabDropTargetHeight;
|
||||
[self setNeedsDisplayInRect:invalidRect];
|
||||
mIsDropTarget = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hideDragDestinationIndicator
|
||||
{
|
||||
if (mIsDropTarget)
|
||||
{
|
||||
NSRect invalidRect = [self bounds];
|
||||
invalidRect.size.height = kTabDropTargetHeight;
|
||||
[self setNeedsDisplayInRect:invalidRect];
|
||||
mIsDropTarget = NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
// Drag helpers for tabs and the tab bar.
|
||||
|
||||
// NSDraggingDestination ///////////
|
||||
|
||||
- (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
// Private method to extract recognized URL types from the pasteboard.
|
||||
- (NSArray*)urlsFromPasteboard:(NSPasteboard*)pasteboard
|
||||
{
|
||||
NSPoint localPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
|
||||
NSTabViewItem* overTabViewItem = [self tabViewItemAtPoint: localPoint];
|
||||
|
||||
if (overTabViewItem)
|
||||
return NSDragOperationNone; // the tab will handle it
|
||||
|
||||
[self showDragDestinationIndicator]; // XXX optimize
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
- (unsigned int)draggingUpdated:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
NSPoint localPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
|
||||
NSTabViewItem* overTabViewItem = [self tabViewItemAtPoint: localPoint];
|
||||
|
||||
if (overTabViewItem)
|
||||
return NSDragOperationNone; // the tab will handle it
|
||||
|
||||
[self showDragDestinationIndicator];
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
- (void)draggingExited:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
[self hideDragDestinationIndicator];
|
||||
}
|
||||
|
||||
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
[self hideDragDestinationIndicator];
|
||||
|
||||
NSArray* urls = nil;
|
||||
NSArray* pasteBoardTypes = [[sender draggingPasteboard] types];
|
||||
NSArray* pasteBoardTypes = [pasteboard types];
|
||||
if ([pasteBoardTypes containsObject:kCaminoBookmarkListPBoardType]) {
|
||||
NSArray* bookmarkUUIDs = [[sender draggingPasteboard] propertyListForType:kCaminoBookmarkListPBoardType];
|
||||
NSArray* draggedItems = [BookmarkManager bookmarkItemsFromSerializableArray:bookmarkUUIDs];
|
||||
|
||||
NSMutableArray* bookmarkURLs = [NSMutableArray arrayWithCapacity:[draggedItems count]];
|
||||
BookmarkItem* aBookmark;
|
||||
NSEnumerator* enumerator = [draggedItems objectEnumerator];
|
||||
while ((aBookmark = [enumerator nextObject])) {
|
||||
if ([aBookmark isKindOfClass:[Bookmark class]] && ![aBookmark isSeparator])
|
||||
[bookmarkURLs addObject:[(Bookmark*)aBookmark url]];
|
||||
else if ([aBookmark isKindOfClass:[BookmarkFolder class]])
|
||||
[bookmarkURLs addObjectsFromArray:[(BookmarkFolder*)aBookmark childURLs]];
|
||||
}
|
||||
urls = bookmarkURLs;
|
||||
NSArray* bookmarkUUIDs = [pasteboard propertyListForType:kCaminoBookmarkListPBoardType];
|
||||
urls = [BookmarkManager bookmarkURLsFromSerializableArray:bookmarkUUIDs];
|
||||
}
|
||||
else if ([[sender draggingPasteboard] containsURLData]) {
|
||||
else if ([pasteboard containsURLData]) {
|
||||
NSArray* titles; // discarded
|
||||
[[sender draggingPasteboard] getURLs:&urls andTitles:&titles];
|
||||
[pasteboard getURLs:&urls andTitles:&titles];
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
if (!urls || [urls count] == 0)
|
||||
- (BOOL)shouldAcceptDrag:(id <NSDraggingInfo>)dragInfo
|
||||
{
|
||||
// This must stay in sync with the behavior of urlsForDrag:; we don't just
|
||||
// call through to it because it does more work than we need for a yes/no.
|
||||
NSArray* pasteBoardTypes = [[dragInfo draggingPasteboard] types];
|
||||
return ([pasteBoardTypes containsObject:kCaminoBookmarkListPBoardType] ||
|
||||
[[dragInfo draggingPasteboard] containsURLData]);
|
||||
}
|
||||
|
||||
- (BOOL)handleDrop:(id <NSDraggingInfo>)dragInfo onTab:(NSTabViewItem*)targetTab
|
||||
{
|
||||
NSArray* urls = [self urlsFromPasteboard:[dragInfo draggingPasteboard]];
|
||||
if ([urls count] == 0)
|
||||
return NO;
|
||||
|
||||
// determine if we are over a tab or the content area
|
||||
NSPoint localPoint = [self convertPoint:[sender draggingLocation] fromView: nil];
|
||||
NSTabViewItem* targetTab;
|
||||
if (NSPointInRect(localPoint, [self contentRect])) // drop is on content area
|
||||
targetTab = [self selectedTabViewItem];
|
||||
else
|
||||
targetTab = [self tabViewItemAtPoint:localPoint];
|
||||
// if there's no tabviewitem at the point within our view, check the tab bar.
|
||||
if (!targetTab)
|
||||
targetTab = [mTabBar tabViewItemAtPoint:[sender draggingLocation]];
|
||||
|
||||
[self handleDropOnTab:targetTab withURLs:urls];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Private method to handle drag and drop of one or more URLs. If |targetTab| is nil,
|
||||
// then the drop is on the tab bar background, as opposed to a tab or its content area.
|
||||
- (void)handleDropOnTab:(NSTabViewItem*)targetTab withURLs:(NSArray*)urls
|
||||
{
|
||||
if ([urls count] == 1) {
|
||||
NSString* url = [urls objectAtIndex:0];
|
||||
BOOL loadInBackground = [BrowserWindowController shouldLoadInBackgroundForDestination:eDestinationNewTab
|
||||
@@ -477,6 +369,7 @@ NSString* const kTabBarBackgroundDoubleClickedNotification = @"kTabBarBackground
|
||||
else {
|
||||
[[[self window] windowController] openURLArray:urls tabOpenPolicy:(targetTab ? eReplaceTabs : eAppendTabs) allowPopups:NO];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@@ -85,4 +85,9 @@ extern NSString* const kTabWillChangeNotifcation;
|
||||
+ (NSImage*)closeIconPressed;
|
||||
+ (NSImage*)closeIconHover;
|
||||
|
||||
// Returns YES if |sender| is a valid drag for a tab, NO if not.
|
||||
- (BOOL)shouldAcceptDrag:(id <NSDraggingInfo>)dragInfo;
|
||||
// Handle drag and drop of one or more URLs; returns YES if the drop was valid.
|
||||
- (BOOL)handleDrop:(id <NSDraggingInfo>)dragInfo;
|
||||
|
||||
@end
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#import "BrowserTabView.h"
|
||||
#import "TabButtonView.h"
|
||||
|
||||
#import "BrowserWindowController.h"
|
||||
#import "BrowserWrapper.h"
|
||||
#import "TruncatingTextAndImageCell.h"
|
||||
|
||||
@@ -211,4 +212,25 @@ const int kMenuTruncationChars = 60;
|
||||
return sCloseIconHover;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)shouldAcceptDrag:(id <NSDraggingInfo>)dragInfo
|
||||
{
|
||||
id dragSource = [dragInfo draggingSource];
|
||||
if ((dragSource == self) || (dragSource == mTabButtonView))
|
||||
return NO;
|
||||
|
||||
// TODO: find another way to do this that doesn't involve knowledge about BWC.
|
||||
BrowserWindowController *windowController = (BrowserWindowController *)[[[self view] window] windowController];
|
||||
if (dragSource == [windowController proxyIconView])
|
||||
return NO;
|
||||
|
||||
return [(BrowserTabView*)[self tabView] shouldAcceptDrag:dragInfo];
|
||||
}
|
||||
|
||||
- (BOOL)handleDrop:(id <NSDraggingInfo>)dragInfo
|
||||
{
|
||||
return [(BrowserTabView*)[self tabView] handleDrop:dragInfo onTab:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#import "NSString+Utils.h"
|
||||
|
||||
#import "BrowserTabViewItem.h"
|
||||
#import "BrowserWindowController.h"
|
||||
#import "BrowserWrapper.h"
|
||||
#import "RolloverImageButton.h"
|
||||
#import "TruncatingTextAndImageCell.h"
|
||||
@@ -360,27 +359,17 @@ static NSImage* sTabButtonDividerImage = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldAcceptDragFrom:(id)sender
|
||||
{
|
||||
if ((sender == self) || (sender == mTabViewItem))
|
||||
return NO;
|
||||
|
||||
NSWindowController *windowController = [[[mTabViewItem view] window] windowController];
|
||||
if ([windowController isMemberOfClass:[BrowserWindowController class]]) {
|
||||
if (sender == [(BrowserWindowController *)windowController proxyIconView])
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// NSDraggingDestination destination methods
|
||||
- (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
if (![self shouldAcceptDragFrom:[sender draggingSource]])
|
||||
if (![mTabViewItem shouldAcceptDrag:sender])
|
||||
return NSDragOperationNone;
|
||||
|
||||
[self setDragTarget:YES];
|
||||
|
||||
if ([sender draggingSourceOperationMask] & NSDragOperationCopy)
|
||||
return NSDragOperationCopy;
|
||||
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
@@ -398,11 +387,7 @@ static NSImage* sTabButtonDividerImage = nil;
|
||||
{
|
||||
[self setDragTarget:NO];
|
||||
|
||||
if (![self shouldAcceptDragFrom:[sender draggingSource]])
|
||||
return NO;
|
||||
|
||||
// let the tab view handle it
|
||||
return [[mTabViewItem tabView] performDragOperation:sender];
|
||||
return [mTabViewItem handleDrop:sender];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
Reference in New Issue
Block a user