diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-19 23:01:29 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-19 23:01:29 +0000 |
commit | ef044ebebc47d4ee9636f25c61ab079411630126 (patch) | |
tree | 6fa321a46fc986900a38c6c8f74d74d0f2a6f04b | |
parent | 2fe2abd25943a2ca01d55cb29bfee5259e707071 (diff) | |
download | chromium_src-ef044ebebc47d4ee9636f25c61ab079411630126.zip chromium_src-ef044ebebc47d4ee9636f25c61ab079411630126.tar.gz chromium_src-ef044ebebc47d4ee9636f25c61ab079411630126.tar.bz2 |
[Mac] Adjust omnibox decoration dragging to keep image under mouse.
LocationBarDecoration::GetDragImageFrame() added to let decorations
specify where their GetDragImage() image is in the decoration. The
mouse-down code ensures that the mouse drags from the expected point
within that area, or centeres the image under the mouse if the drag is
from somewhere else in the decoration.
Additionally tracked down why -isFlipped affected the drag point and
rewrote the code to be -isFlipped agnostic.
BUG=49102, 40771
TEST=Goto https://www.thawte.com/. Drag from ev text, lock icon should be under cursor.
TEST=drag from location or lock icon should drag from point in icon mouse click was in.
Review URL: http://codereview.chromium.org/2870059
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52959 0039d316-1c4b-4281-b951-d872f2087c98
6 files changed, 52 insertions, 16 deletions
diff --git a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm index 83bf1ef..edb9a64 100644 --- a/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm +++ b/chrome/browser/cocoa/location_bar/autocomplete_text_field_cell.mm @@ -331,24 +331,37 @@ size_t CalculatePositionsInFrame( NSPasteboard* pboard = decoration->GetDragPasteboard(); DCHECK(pboard); - // TODO(shess): My understanding is that the -isFlipped - // adjustment should not be necessary. But without it, the - // image is nowhere near the cursor. Perhaps the decorations's - // rect is incorrectly calculated? - // http://crbug.com/40711 - NSPoint dragPoint = decorationRect.origin; - if ([controlView isFlipped]) - dragPoint.y += NSHeight(decorationRect); - NSImage* image = decoration->GetDragImage(); DCHECK(image); - [controlView dragImage:image - at:dragPoint - offset:NSZeroSize - event:event ? event : theEvent - pasteboard:pboard - source:self - slideBack:YES]; + + NSRect dragImageRect = decoration->GetDragImageFrame(decorationRect); + + // If the original click is not within |dragImageRect|, then + // center the image under the mouse. Otherwise, will drag from + // where the click was on the image. + const NSPoint mousePoint = + [controlView convertPoint:[theEvent locationInWindow] fromView:nil]; + if (!NSMouseInRect(mousePoint, dragImageRect, [controlView isFlipped])) { + dragImageRect.origin = + NSMakePoint(mousePoint.x - NSWidth(dragImageRect) / 2.0, + mousePoint.y - NSHeight(dragImageRect) / 2.0); + } + + // -[NSView dragImage:at:*] wants the images lower-left point, + // regardless of -isFlipped. Converting the rect to window base + // coordinates doesn't require any special-casing. Note that + // -[NSView dragFile:fromRect:*] takes a rect rather than a + // point, likely for this exact reason. + const NSPoint dragPoint = + [controlView convertRect:dragImageRect toView:nil].origin; + [[controlView window] dragImage:image + at:dragPoint + offset:NSZeroSize + event:theEvent + pasteboard:pboard + source:self + slideBack:YES]; + return YES; } diff --git a/chrome/browser/cocoa/location_bar/bubble_decoration.h b/chrome/browser/cocoa/location_bar/bubble_decoration.h index 0385845..224050f 100644 --- a/chrome/browser/cocoa/location_bar/bubble_decoration.h +++ b/chrome/browser/cocoa/location_bar/bubble_decoration.h @@ -36,6 +36,10 @@ class BubbleDecoration : public LocationBarDecoration { // assuming |font_| (for sizing text). Arguments can be nil. CGFloat GetWidthForImageAndLabel(NSImage* image, NSString* label); + // Helper to return where the image is drawn, for subclasses to drag + // from. |frame| is the decoration's frame in the containing cell. + NSRect GetImageRectInFrame(NSRect frame); + private: friend class SelectedKeywordDecorationTest; FRIEND_TEST_ALL_PREFIXES(SelectedKeywordDecorationTest, diff --git a/chrome/browser/cocoa/location_bar/bubble_decoration.mm b/chrome/browser/cocoa/location_bar/bubble_decoration.mm index 5a85a9c..5e2a9ad 100644 --- a/chrome/browser/cocoa/location_bar/bubble_decoration.mm +++ b/chrome/browser/cocoa/location_bar/bubble_decoration.mm @@ -43,6 +43,13 @@ CGFloat BubbleDecoration::GetWidthForImageAndLabel(NSImage* image, return kBubblePadding + image_width + label_width; } +NSRect BubbleDecoration::GetImageRectInFrame(NSRect frame) { + NSRect imageRect = NSInsetRect(frame, 0.0, kKeywordYInset); + if (image_) + imageRect.size = [image_ size]; + return imageRect; +} + CGFloat BubbleDecoration::GetWidthForSpace(CGFloat width) { const CGFloat all_width = GetWidthForImageAndLabel(image_, label_); if (all_width <= width) diff --git a/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h b/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h index 0cdd960..ecbdf1d 100644 --- a/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h +++ b/chrome/browser/cocoa/location_bar/ev_bubble_decoration.h @@ -28,6 +28,9 @@ class EVBubbleDecoration : public BubbleDecoration { virtual bool IsDraggable(); virtual NSPasteboard* GetDragPasteboard(); virtual NSImage* GetDragImage(); + virtual NSRect GetDragImageFrame(NSRect frame) { + return GetImageRectInFrame(frame); + } virtual bool OnMousePressed(NSRect frame); virtual bool AcceptsMousePress() { return true; } diff --git a/chrome/browser/cocoa/location_bar/location_bar_decoration.h b/chrome/browser/cocoa/location_bar/location_bar_decoration.h index 51571cc..56a4b83 100644 --- a/chrome/browser/cocoa/location_bar/location_bar_decoration.h +++ b/chrome/browser/cocoa/location_bar/location_bar_decoration.h @@ -59,6 +59,12 @@ class LocationBarDecoration { // The image to drag. virtual NSImage* GetDragImage() { return nil; } + // Return the place within the decoration's frame where the + // |GetDragImage()| comes from. This is used to make sure the image + // appears correctly under the mouse while dragging. |frame| + // matches the frame passed to |DrawInFrame()|. + virtual NSRect GetDragImageFrame(NSRect frame) { return NSZeroRect; } + // The pasteboard to drag. virtual NSPasteboard* GetDragPasteboard() { return nil; } diff --git a/chrome/browser/cocoa/location_bar/location_icon_decoration.h b/chrome/browser/cocoa/location_bar/location_icon_decoration.h index 9d705a8..ec14264 100644 --- a/chrome/browser/cocoa/location_bar/location_icon_decoration.h +++ b/chrome/browser/cocoa/location_bar/location_icon_decoration.h @@ -23,6 +23,9 @@ class LocationIconDecoration : public ImageDecoration { virtual bool IsDraggable(); virtual NSPasteboard* GetDragPasteboard(); virtual NSImage* GetDragImage() { return GetImage(); } + virtual NSRect GetDragImageFrame(NSRect frame) { + return GetDrawRectInFrame(frame); + } // Show the page info panel on click. virtual bool OnMousePressed(NSRect frame); |