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:
stuart.morgan%alumni.case.edu
2008-04-17 17:19:15 +00:00
parent 680e30212d
commit 9da2b27305
9 changed files with 89 additions and 161 deletions

View File

@@ -97,6 +97,7 @@ const int kBookmarksContextMenuArrangeSeparatorTag = 100;
+ (NSArray*)serializableArrayWithBookmarkItems:(NSArray*)bmArray;
+ (NSArray*)bookmarkItemsFromSerializableArray:(NSArray*)bmArray;
+ (NSArray*)bookmarkURLsFromSerializableArray:(NSArray*)bmArray;
// Getters/Setters
- (BookmarkFolder *)rootBookmarks;

View File

@@ -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
{

View File

@@ -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]];

View File

@@ -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

View File

@@ -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

View File

@@ -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 -

View File

@@ -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

View File

@@ -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

View File

@@ -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 -