Merge revision 1119 changes:

- Mac: Add default tooltip implementation (issue #770).

git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1364@1120 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2013-03-04 22:20:04 +00:00
parent e54fd9ed9f
commit f06e94716b
6 changed files with 236 additions and 5 deletions

View File

@ -812,6 +812,7 @@
'sources': [
'<@(includes_mac)',
'libcef/browser_impl_mac.mm',
'libcef/browser_tooltip_mac.h',
'libcef/browser_webview_delegate_mac.mm',
'libcef/browser_webview_mac.h',
'libcef/browser_webview_mac.mm',

View File

@ -12,6 +12,7 @@
#include "base/memory/scoped_nsobject.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
#include <Vector>
#import "libcef/browser_tooltip_mac.h"
class CefBrowserImpl;
@class WebDragSource;
@ -21,7 +22,7 @@ struct WebDropData;
// A view to wrap the WebCore view and help it live in a Cocoa world. The
// (rough) equivalent of Apple's WebView.
@interface BrowserWebView : NSView<NSTextInputClient> {
@interface BrowserWebView : NSView<NSTextInputClient, BrowserTooltip> {
@private
CefBrowserImpl* browser_; // weak
NSTrackingArea* trackingArea_;
@ -60,6 +61,12 @@ struct WebDropData;
// Underline information of the |markedText_|.
std::vector<WebKit::WebCompositionUnderline> underlines_;
// These are part of the magic tooltip code from WebKit's WebHTMLView:
id trackingRectOwner_; // (not retained)
void* trackingRectUserData_;
NSTrackingRectTag lastToolTipTag_;
scoped_nsobject<NSString> toolTip_;
}
- (void)mouseDown:(NSEvent *)theEvent;

View File

@ -84,6 +84,7 @@ void ExtractUnderlines(
trackingArea_ =
[[NSTrackingArea alloc] initWithRect:frame
options:NSTrackingMouseMoved |
NSTrackingMouseEnteredAndExited |
NSTrackingActiveInActiveApp |
NSTrackingInVisibleRect
owner:self
@ -656,4 +657,196 @@ extern "C" {
hasMarkedText_ = NO;
}
///////////////////////////////////////////////////////////////////////////////
// Tooltip Support
// This code is copied from
// content/browser/renderer_host/render_widget_host_view_mac.mm
// 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;
if ((toolTip && toolTip_ && [toolTip isEqualToString:toolTip_]) ||
(!toolTip && !toolTip_)) {
return;
}
if (toolTip_) {
[self _sendToolTipMouseExited];
}
toolTip_.reset([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_ retain] autorelease];
}
@end

View File

@ -277,6 +277,7 @@ class WebWidgetHost {
#endif // OS_WIN
#if defined(OS_MACOSX)
std::string tooltip_text_;
int mouse_modifiers_;
WebKit::WebMouseEvent::Button mouse_button_down_;
#endif

View File

@ -4,6 +4,7 @@
#import <Cocoa/Cocoa.h>
#import "libcef/browser_tooltip_mac.h"
#include "base/compiler_specific.h"
#include "third_party/WebKit/Source/WebCore/config.h"
MSVC_PUSH_WARNING_LEVEL(0);
@ -16,6 +17,7 @@ MSVC_POP_WARNING();
#include "base/bind.h"
#import "base/logging.h"
#import "base/sys_string_conversions.h"
#import "skia/ext/platform_canvas.h"
#import "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFactory.h"
#import "third_party/WebKit/Source/WebKit/chromium/public/mac/WebScreenInfoFactory.h"
@ -41,6 +43,9 @@ using WebKit::WebWidgetClient;
namespace {
// Maximum number of characters we allow in a tooltip.
const size_t kMaxTooltipLength = 1024;
inline SkIRect convertToSkiaRect(const gfx::Rect& r) {
return SkIRect::MakeLTRB(r.x(), r.y(), r.right(), r.bottom());
}
@ -297,7 +302,28 @@ void WebWidgetHost::Paint(SkRegion& update_rgn) {
}
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
// TODO(port): Implement this method as part of tooltip support.
if (tooltip_text.empty() && !tooltip_text_.empty()) {
tooltip_text_.clear();
if ([view_ respondsToSelector:@selector(setToolTipAtMousePoint:)])
[(id<BrowserTooltip>)view_ setToolTipAtMousePoint:nil];
} else if (tooltip_text != tooltip_text_ && [[view_ window] isKeyWindow]) {
tooltip_text_ = tooltip_text;
if ([view_ respondsToSelector:@selector(setToolTipAtMousePoint:)]) {
// Clamp the tooltip length to kMaxTooltipLength. It's a DOS issue on
// Windows; we're just trying to be polite. Don't persist the trimmed
// string, as then the comparison above will always fail and we'll try to
// set it again every single time the mouse moves.
NSString* tooltip_nsstring;
if (tooltip_text_.length() > kMaxTooltipLength) {
tooltip_nsstring =
base::SysUTF8ToNSString(tooltip_text_.substr(0, kMaxTooltipLength));
} else {
tooltip_nsstring = base::SysUTF8ToNSString(tooltip_text_);
}
[(id<BrowserTooltip>)view_ setToolTipAtMousePoint:tooltip_nsstring];
}
}
}
WebScreenInfo WebWidgetHost::GetScreenInfo() {
@ -308,6 +334,8 @@ void WebWidgetHost::MouseEvent(NSEvent *event) {
const WebMouseEvent& web_event = WebInputEventFactory::mouseEvent(
event, view_);
webwidget_->handleInputEvent(web_event);
if (web_event.type == WebInputEvent::MouseLeave)
SetTooltipText(CefString());
}
void WebWidgetHost::WheelEvent(NSEvent *event) {
@ -342,7 +370,7 @@ void WebWidgetHost::SendKeyEvent(cef_key_type_t type,
event.type = WebInputEvent::Char;
break;
}
event.timeStampSeconds = TickCount();
event.timeStampSeconds = TickCount();
if (modifiers & KEY_SHIFT)
event.modifiers |= WebInputEvent::ShiftKey;
@ -453,7 +481,7 @@ void WebWidgetHost::SendMouseClickEvent(int x, int y,
event.type = WebInputEvent::MouseDown;
event.clickCount = clickCount;
event.timeStampSeconds = TickCount();
event.timeStampSeconds = TickCount();
event.x = x;
event.y = y;
event.windowX = event.x;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.
@ -303,6 +303,7 @@ class ClientOSRHandler : public CefClient,
tracking_area_ =
[[NSTrackingArea alloc] initWithRect:frame
options:NSTrackingMouseMoved |
NSTrackingMouseEnteredAndExited |
NSTrackingActiveInActiveApp |
NSTrackingInVisibleRect
owner:self