| Index: chrome/browser/renderer_host/render_widget_host_view_mac.mm
|
| ===================================================================
|
| --- chrome/browser/renderer_host/render_widget_host_view_mac.mm (revision 19944)
|
| +++ chrome/browser/renderer_host/render_widget_host_view_mac.mm (working copy)
|
| @@ -13,7 +13,6 @@
|
| #include "chrome/browser/renderer_host/render_widget_host.h"
|
| #include "chrome/common/native_web_keyboard_event.h"
|
| #include "skia/ext/platform_canvas.h"
|
| -#import "third_party/mozilla/include/ToolTip.h"
|
| #include "webkit/api/public/mac/WebInputEventFactory.h"
|
| #include "webkit/api/public/WebInputEvent.h"
|
| #include "webkit/glue/webmenurunner_mac.h"
|
| @@ -108,11 +107,6 @@
|
| // everything again when we become selected again.
|
| is_hidden_ = true;
|
|
|
| - // We can't have tooltips floating around after the tools they're tipping
|
| - // about are hidden, can we?
|
| - tooltip_.reset(NULL);
|
| - tooltip_text_.clear();
|
| -
|
| // If we have a renderer, then inform it that we are being hidden so it can
|
| // reduce its resource utilization.
|
| render_widget_host_->WasHidden();
|
| @@ -267,18 +261,7 @@
|
|
|
| // Called from the renderer to tell us what the tooltip text should be. It
|
| // calls us frequently so we need to cache the value to prevent doing a lot
|
| -// of repeat work. We cannot simply use [-NSView setToolTip:] because NSView
|
| -// can't handle the case where the tooltip text changes while the mouse is
|
| -// still inside the view. Since the page elements that get tooltips are all
|
| -// contained within this view (and are unknown to the NSView system), we
|
| -// are forced to implement our own tooltips with child windows.
|
| -// TODO(pinkerton): Do we want these tooltips to time out after a certain time?
|
| -// Gecko does this automatically in the back-end, hence the ToolTip class not
|
| -// needing that functionality. We can either modify ToolTip or add this
|
| -// functionality here with a timer.
|
| -// TODO(pinkerton): This code really needs to live at a higher level because
|
| -// right now it allows multiple views in multiple tabs to each be displaying
|
| -// a tooltip simultaneously (http://crbug.com/14178).
|
| +// of repeat work.
|
| void RenderWidgetHostViewMac::SetTooltipText(const std::wstring& tooltip_text) {
|
| if (tooltip_text != tooltip_text_ && [[cocoa_view_ window] isKeyWindow]) {
|
| tooltip_text_ = tooltip_text;
|
| @@ -292,19 +275,7 @@
|
| display_text = tooltip_text_.substr(0, kMaxTooltipLength);
|
|
|
| NSString* tooltip_nsstring = base::SysWideToNSString(display_text);
|
| - if ([tooltip_nsstring length] == 0) {
|
| - tooltip_.reset(NULL); // The dtor closes the tooltip.
|
| - } else {
|
| - // Get the current mouse location in the window's coordinate system and
|
| - // use that as the point for displaying the tooltip.
|
| - if (!tooltip_.get())
|
| - tooltip_.reset([[ToolTip alloc] init]);
|
| - NSPoint event_point =
|
| - [[cocoa_view_ window] mouseLocationOutsideOfEventStream];
|
| - [tooltip_ showToolTipAtPoint:event_point
|
| - withString:tooltip_nsstring
|
| - overWindow:[cocoa_view_ window]];
|
| - }
|
| + [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring];
|
| }
|
| }
|
|
|
| @@ -367,6 +338,10 @@
|
| // Do not touch any members at this point, |this| has been deleted.
|
| }
|
|
|
| +
|
| +
|
| +// RenderWidgetHostViewCocoa ---------------------------------------------------
|
| +
|
| @implementation RenderWidgetHostViewCocoa
|
|
|
| // Tons of stuff goes here, where we grab events going on in Cocoaland and send
|
| @@ -387,6 +362,7 @@
|
|
|
| - (void)dealloc {
|
| delete renderWidgetHostView_;
|
| + [toolTip_ release];
|
|
|
| [super dealloc];
|
| }
|
| @@ -570,5 +546,192 @@
|
| return renderWidgetHostView_;
|
| }
|
|
|
| +
|
| +// Below is the nasty tooltip stuff -- copied from WebKit's WebHTMLView.mm
|
| +// with minor modifications for code style and commenting.
|
| +//
|
| +// The 'public' interface is -setToolTipAtMousePoint:. This differs from
|
| +// -setToolTip: in that the updated tooltip takes effect immediately,
|
| +// without the user's having to move the mouse out of and back into the view.
|
| +//
|
| +// Unfortunately, doing this requires sending fake mouseEnter/Exit events to
|
| +// the view, which in turn requires overriding some internal tracking-rect
|
| +// methods (to keep track of its owner & userdata, which need to be filled out
|
| +// in the fake events.) --snej 7/6/09
|
| +
|
| +
|
| +/*
|
| + * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
| + * (C) 2006, 2007 Graham Dennis (graham.dennis@gmail.com)
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions
|
| + * are met:
|
| + *
|
| + * 1. Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * 2. Redistributions in binary form must reproduce the above copyright
|
| + * notice, this list of conditions and the following disclaimer in the
|
| + * documentation and/or other materials provided with the distribution.
|
| + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
|
| + * its contributors may be used to endorse or promote products derived
|
| + * from this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
| + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
| + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
| + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
| + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
| + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + */
|
| +
|
| +// Any non-zero value will do, but using something recognizable might help us
|
| +// debug some day.
|
| +static const NSTrackingRectTag kTrackingRectTag = 0xBADFACE;
|
| +
|
| +// Override of a public NSView method, replacing the inherited functionality.
|
| +// See above for rationale.
|
| +- (NSTrackingRectTag)addTrackingRect:(NSRect)rect
|
| + owner:(id)owner
|
| + userData:(void *)data
|
| + assumeInside:(BOOL)assumeInside {
|
| + DCHECK(trackingRectOwner_ == nil);
|
| + trackingRectOwner_ = owner;
|
| + trackingRectUserData_ = data;
|
| + return kTrackingRectTag;
|
| +}
|
| +
|
| +// Override of (apparently) a private NSView method(!) See above for rationale.
|
| +- (NSTrackingRectTag)_addTrackingRect:(NSRect)rect
|
| + owner:(id)owner
|
| + userData:(void *)data
|
| + assumeInside:(BOOL)assumeInside
|
| + useTrackingNum:(int)tag {
|
| + DCHECK(tag == 0 || tag == kTrackingRectTag);
|
| + DCHECK(trackingRectOwner_ == nil);
|
| + trackingRectOwner_ = owner;
|
| + trackingRectUserData_ = data;
|
| + return kTrackingRectTag;
|
| +}
|
| +
|
| +// Override of (apparently) a private NSView method(!) See above for rationale.
|
| +- (void)_addTrackingRects:(NSRect *)rects
|
| + owner:(id)owner
|
| + userDataList:(void **)userDataList
|
| + assumeInsideList:(BOOL *)assumeInsideList
|
| + trackingNums:(NSTrackingRectTag *)trackingNums
|
| + count:(int)count {
|
| + DCHECK(count == 1);
|
| + DCHECK(trackingNums[0] == 0 || trackingNums[0] == kTrackingRectTag);
|
| + DCHECK(trackingRectOwner_ == nil);
|
| + trackingRectOwner_ = owner;
|
| + trackingRectUserData_ = userDataList[0];
|
| + trackingNums[0] = kTrackingRectTag;
|
| +}
|
| +
|
| +// Override of a public NSView method, replacing the inherited functionality.
|
| +// See above for rationale.
|
| +- (void)removeTrackingRect:(NSTrackingRectTag)tag {
|
| + if (tag == 0)
|
| + return;
|
| +
|
| + if (tag == kTrackingRectTag) {
|
| + trackingRectOwner_ = nil;
|
| + return;
|
| + }
|
| +
|
| + if (tag == lastToolTipTag_) {
|
| + [super removeTrackingRect:tag];
|
| + lastToolTipTag_ = 0;
|
| + return;
|
| + }
|
| +
|
| + // If any other tracking rect is being removed, we don't know how it was
|
| + // created and it's possible there's a leak involved (see Radar 3500217).
|
| + NOTREACHED();
|
| +}
|
| +
|
| +// Override of (apparently) a private NSView method(!)
|
| +- (void)_removeTrackingRects:(NSTrackingRectTag *)tags count:(int)count {
|
| + for (int i = 0; i < count; ++i) {
|
| + int tag = tags[i];
|
| + if (tag == 0)
|
| + continue;
|
| + DCHECK(tag == kTrackingRectTag);
|
| + trackingRectOwner_ = nil;
|
| + }
|
| +}
|
| +
|
| +// Sends a fake NSMouseExited event to the view for its current tracking rect.
|
| +- (void)_sendToolTipMouseExited {
|
| + // Nothing matters except window, trackingNumber, and userData.
|
| + int windowNumber = [[self window] windowNumber];
|
| + NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseExited
|
| + location:NSMakePoint(0, 0)
|
| + modifierFlags:0
|
| + timestamp:0
|
| + windowNumber:windowNumber
|
| + context:NULL
|
| + eventNumber:0
|
| + trackingNumber:kTrackingRectTag
|
| + userData:trackingRectUserData_];
|
| + [trackingRectOwner_ mouseExited:fakeEvent];
|
| +}
|
| +
|
| +// Sends a fake NSMouseEntered event to the view for its current tracking rect.
|
| +- (void)_sendToolTipMouseEntered {
|
| + // Nothing matters except window, trackingNumber, and userData.
|
| + int windowNumber = [[self window] windowNumber];
|
| + NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered
|
| + location:NSMakePoint(0, 0)
|
| + modifierFlags:0
|
| + timestamp:0
|
| + windowNumber:windowNumber
|
| + context:NULL
|
| + eventNumber:0
|
| + trackingNumber:kTrackingRectTag
|
| + userData:trackingRectUserData_];
|
| + [trackingRectOwner_ mouseEntered:fakeEvent];
|
| +}
|
| +
|
| +// Sets the view's current tooltip, to be displayed at the current mouse
|
| +// location. (This does not make the tooltip appear -- as usual, it only
|
| +// appears after a delay.) Pass null to remove the tooltip.
|
| +- (void)setToolTipAtMousePoint:(NSString *)string {
|
| + NSString *toolTip = [string length] == 0 ? nil : string;
|
| + NSString *oldToolTip = toolTip_;
|
| + if ((toolTip == nil || oldToolTip == nil) ? toolTip == oldToolTip
|
| + : [toolTip isEqualToString:oldToolTip]) {
|
| + return;
|
| + }
|
| + if (oldToolTip) {
|
| + [self _sendToolTipMouseExited];
|
| + [oldToolTip release];
|
| + }
|
| + toolTip_ = [toolTip copy];
|
| + if (toolTip) {
|
| + // See radar 3500217 for why we remove all tooltips
|
| + // rather than just the single one we created.
|
| + [self removeAllToolTips];
|
| + NSRect wideOpenRect = NSMakeRect(-100000, -100000, 200000, 200000);
|
| + lastToolTipTag_ = [self addToolTipRect:wideOpenRect
|
| + owner:self
|
| + userData:NULL];
|
| + [self _sendToolTipMouseEntered];
|
| + }
|
| +}
|
| +
|
| +// NSView calls this to get the text when displaying the tooltip.
|
| +- (NSString *)view:(NSView *)view
|
| + stringForToolTip:(NSToolTipTag)tag
|
| + point:(NSPoint)point
|
| + userData:(void *)data {
|
| + return [[toolTip_ copy] autorelease];
|
| +}
|
| +
|
| @end
|
|
|
|
|