Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_mac.mm

Issue 150188: Use native Cocoa tooltips instead of Mozilla's ToolTip class. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" 5 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
6 6
7 #include "base/histogram.h" 7 #include "base/histogram.h"
8 #include "base/sys_string_conversions.h" 8 #include "base/sys_string_conversions.h"
9 #include "chrome/browser/browser_trial.h" 9 #include "chrome/browser/browser_trial.h"
10 #import "chrome/browser/cocoa/rwhvm_editcommand_helper.h" 10 #import "chrome/browser/cocoa/rwhvm_editcommand_helper.h"
11 #include "chrome/browser/renderer_host/backing_store.h" 11 #include "chrome/browser/renderer_host/backing_store.h"
12 #include "chrome/browser/renderer_host/render_process_host.h" 12 #include "chrome/browser/renderer_host/render_process_host.h"
13 #include "chrome/browser/renderer_host/render_widget_host.h" 13 #include "chrome/browser/renderer_host/render_widget_host.h"
14 #include "chrome/common/native_web_keyboard_event.h" 14 #include "chrome/common/native_web_keyboard_event.h"
15 #include "skia/ext/platform_canvas.h" 15 #include "skia/ext/platform_canvas.h"
16 #import "third_party/mozilla/include/ToolTip.h"
17 #include "webkit/api/public/mac/WebInputEventFactory.h" 16 #include "webkit/api/public/mac/WebInputEventFactory.h"
18 #include "webkit/api/public/WebInputEvent.h" 17 #include "webkit/api/public/WebInputEvent.h"
19 #include "webkit/glue/webmenurunner_mac.h" 18 #include "webkit/glue/webmenurunner_mac.h"
20 19
21 using WebKit::WebInputEventFactory; 20 using WebKit::WebInputEventFactory;
22 using WebKit::WebMouseEvent; 21 using WebKit::WebMouseEvent;
23 using WebKit::WebMouseWheelEvent; 22 using WebKit::WebMouseWheelEvent;
24 23
25 @interface RenderWidgetHostViewCocoa (Private) 24 @interface RenderWidgetHostViewCocoa (Private)
26 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; 25 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 100
102 void RenderWidgetHostViewMac::WasHidden() { 101 void RenderWidgetHostViewMac::WasHidden() {
103 if (is_hidden_) 102 if (is_hidden_)
104 return; 103 return;
105 104
106 // If we receive any more paint messages while we are hidden, we want to 105 // If we receive any more paint messages while we are hidden, we want to
107 // ignore them so we don't re-allocate the backing store. We will paint 106 // ignore them so we don't re-allocate the backing store. We will paint
108 // everything again when we become selected again. 107 // everything again when we become selected again.
109 is_hidden_ = true; 108 is_hidden_ = true;
110 109
111 // We can't have tooltips floating around after the tools they're tipping
112 // about are hidden, can we?
113 tooltip_.reset(NULL);
114 tooltip_text_.clear();
115
116 // If we have a renderer, then inform it that we are being hidden so it can 110 // If we have a renderer, then inform it that we are being hidden so it can
117 // reduce its resource utilization. 111 // reduce its resource utilization.
118 render_widget_host_->WasHidden(); 112 render_widget_host_->WasHidden();
119 } 113 }
120 114
121 void RenderWidgetHostViewMac::SetSize(const gfx::Size& size) { 115 void RenderWidgetHostViewMac::SetSize(const gfx::Size& size) {
122 if (is_hidden_) 116 if (is_hidden_)
123 return; 117 return;
124 118
125 // TODO(avi): the TabContents object uses this method to size the newly 119 // TODO(avi): the TabContents object uses this method to size the newly
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 // We get this call just before |render_widget_host_| deletes 254 // We get this call just before |render_widget_host_| deletes
261 // itself. But we are owned by |cocoa_view_|, which may be retained 255 // itself. But we are owned by |cocoa_view_|, which may be retained
262 // by some other code. Examples are TabContentsViewMac's 256 // by some other code. Examples are TabContentsViewMac's
263 // |latent_focus_view_| and TabWindowController's 257 // |latent_focus_view_| and TabWindowController's
264 // |cachedContentView_|. 258 // |cachedContentView_|.
265 render_widget_host_ = NULL; 259 render_widget_host_ = NULL;
266 } 260 }
267 261
268 // Called from the renderer to tell us what the tooltip text should be. It 262 // Called from the renderer to tell us what the tooltip text should be. It
269 // calls us frequently so we need to cache the value to prevent doing a lot 263 // calls us frequently so we need to cache the value to prevent doing a lot
270 // of repeat work. We cannot simply use [-NSView setToolTip:] because NSView 264 // of repeat work.
271 // can't handle the case where the tooltip text changes while the mouse is
272 // still inside the view. Since the page elements that get tooltips are all
273 // contained within this view (and are unknown to the NSView system), we
274 // are forced to implement our own tooltips with child windows.
275 // TODO(pinkerton): Do we want these tooltips to time out after a certain time?
276 // Gecko does this automatically in the back-end, hence the ToolTip class not
277 // needing that functionality. We can either modify ToolTip or add this
278 // functionality here with a timer.
279 // TODO(pinkerton): This code really needs to live at a higher level because
280 // right now it allows multiple views in multiple tabs to each be displaying
281 // a tooltip simultaneously (http://crbug.com/14178).
282 void RenderWidgetHostViewMac::SetTooltipText(const std::wstring& tooltip_text) { 265 void RenderWidgetHostViewMac::SetTooltipText(const std::wstring& tooltip_text) {
283 if (tooltip_text != tooltip_text_ && [[cocoa_view_ window] isKeyWindow]) { 266 if (tooltip_text != tooltip_text_ && [[cocoa_view_ window] isKeyWindow]) {
284 tooltip_text_ = tooltip_text; 267 tooltip_text_ = tooltip_text;
285 268
286 // Clamp the tooltip length to kMaxTooltipLength. It's a DOS issue on 269 // Clamp the tooltip length to kMaxTooltipLength. It's a DOS issue on
287 // Windows; we're just trying to be polite. Don't persist the trimmed 270 // Windows; we're just trying to be polite. Don't persist the trimmed
288 // string, as then the comparison above will always fail and we'll try to 271 // string, as then the comparison above will always fail and we'll try to
289 // set it again every single time the mouse moves. 272 // set it again every single time the mouse moves.
290 std::wstring display_text = tooltip_text_; 273 std::wstring display_text = tooltip_text_;
291 if (tooltip_text_.length() > kMaxTooltipLength) 274 if (tooltip_text_.length() > kMaxTooltipLength)
292 display_text = tooltip_text_.substr(0, kMaxTooltipLength); 275 display_text = tooltip_text_.substr(0, kMaxTooltipLength);
293 276
294 NSString* tooltip_nsstring = base::SysWideToNSString(display_text); 277 NSString* tooltip_nsstring = base::SysWideToNSString(display_text);
295 if ([tooltip_nsstring length] == 0) { 278 [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring];
296 tooltip_.reset(NULL); // The dtor closes the tooltip.
297 } else {
298 // Get the current mouse location in the window's coordinate system and
299 // use that as the point for displaying the tooltip.
300 if (!tooltip_.get())
301 tooltip_.reset([[ToolTip alloc] init]);
302 NSPoint event_point =
303 [[cocoa_view_ window] mouseLocationOutsideOfEventStream];
304 [tooltip_ showToolTipAtPoint:event_point
305 withString:tooltip_nsstring
306 overWindow:[cocoa_view_ window]];
307 }
308 } 279 }
309 } 280 }
310 281
311 BackingStore* RenderWidgetHostViewMac::AllocBackingStore( 282 BackingStore* RenderWidgetHostViewMac::AllocBackingStore(
312 const gfx::Size& size) { 283 const gfx::Size& size) {
313 return new BackingStore(render_widget_host_, size); 284 return new BackingStore(render_widget_host_, size);
314 } 285 }
315 286
316 // Display a popup menu for WebKit using Cocoa widgets. 287 // Display a popup menu for WebKit using Cocoa widgets.
317 void RenderWidgetHostViewMac::ShowPopupWithItems( 288 void RenderWidgetHostViewMac::ShowPopupWithItems(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 &RenderWidgetHostViewMac::ShutdownHost)); 331 &RenderWidgetHostViewMac::ShutdownHost));
361 } 332 }
362 } 333 }
363 334
364 void RenderWidgetHostViewMac::ShutdownHost() { 335 void RenderWidgetHostViewMac::ShutdownHost() {
365 shutdown_factory_.RevokeAll(); 336 shutdown_factory_.RevokeAll();
366 render_widget_host_->Shutdown(); 337 render_widget_host_->Shutdown();
367 // Do not touch any members at this point, |this| has been deleted. 338 // Do not touch any members at this point, |this| has been deleted.
368 } 339 }
369 340
341
342
343 // RenderWidgetHostViewCocoa ---------------------------------------------------
344
370 @implementation RenderWidgetHostViewCocoa 345 @implementation RenderWidgetHostViewCocoa
371 346
372 // Tons of stuff goes here, where we grab events going on in Cocoaland and send 347 // Tons of stuff goes here, where we grab events going on in Cocoaland and send
373 // them into the C++ system. TODO(avi): all that jazz 348 // them into the C++ system. TODO(avi): all that jazz
374 349
375 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { 350 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
376 self = [super initWithFrame:NSZeroRect]; 351 self = [super initWithFrame:NSZeroRect];
377 if (self != nil) { 352 if (self != nil) {
378 editCommand_helper_.reset(new RWHVMEditCommandHelper); 353 editCommand_helper_.reset(new RWHVMEditCommandHelper);
379 editCommand_helper_->AddEditingSelectorsToClass([self class]); 354 editCommand_helper_->AddEditingSelectorsToClass([self class]);
380 355
381 renderWidgetHostView_ = r; 356 renderWidgetHostView_ = r;
382 canBeKeyView_ = YES; 357 canBeKeyView_ = YES;
383 closeOnDeactivate_ = NO; 358 closeOnDeactivate_ = NO;
384 } 359 }
385 return self; 360 return self;
386 } 361 }
387 362
388 - (void)dealloc { 363 - (void)dealloc {
389 delete renderWidgetHostView_; 364 delete renderWidgetHostView_;
365 [toolTip_ release];
390 366
391 [super dealloc]; 367 [super dealloc];
392 } 368 }
393 369
394 - (void)setCanBeKeyView:(BOOL)can { 370 - (void)setCanBeKeyView:(BOOL)can {
395 canBeKeyView_ = can; 371 canBeKeyView_ = can;
396 } 372 }
397 373
398 - (void)setCloseOnDeactivate:(BOOL)b { 374 - (void)setCloseOnDeactivate:(BOOL)b {
399 closeOnDeactivate_ = b; 375 closeOnDeactivate_ = b;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { 539 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
564 SEL action = [item action]; 540 SEL action = [item action];
565 541
566 return editCommand_helper_->IsMenuItemEnabled(action, self); 542 return editCommand_helper_->IsMenuItemEnabled(action, self);
567 } 543 }
568 544
569 - (RenderWidgetHostViewMac*)renderWidgetHostViewMac { 545 - (RenderWidgetHostViewMac*)renderWidgetHostViewMac {
570 return renderWidgetHostView_; 546 return renderWidgetHostView_;
571 } 547 }
572 548
549
550 // Below is the nasty tooltip stuff -- copied from WebKit's WebHTMLView.mm
551 // with minor modifications for code style and commenting.
552 //
553 // The 'public' interface is -setToolTipAtMousePoint:. This differs from
554 // -setToolTip: in that the updated tooltip takes effect immediately,
555 // without the user's having to move the mouse out of and back into the view.
556 //
557 // Unfortunately, doing this requires sending fake mouseEnter/Exit events to
558 // the view, which in turn requires overriding some internal tracking-rect
559 // methods (to keep track of its owner & userdata, which need to be filled out
560 // in the fake events.) --snej 7/6/09
561
562
563 /*
564 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
565 * (C) 2006, 2007 Graham Dennis (graham.dennis@gmail.com)
566 *
567 * Redistribution and use in source and binary forms, with or without
568 * modification, are permitted provided that the following conditions
569 * are met:
570 *
571 * 1. Redistributions of source code must retain the above copyright
572 * notice, this list of conditions and the following disclaimer.
573 * 2. Redistributions in binary form must reproduce the above copyright
574 * notice, this list of conditions and the following disclaimer in the
575 * documentation and/or other materials provided with the distribution.
576 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
577 * its contributors may be used to endorse or promote products derived
578 * from this software without specific prior written permission.
579 *
580 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
581 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
582 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
583 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
584 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
585 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
586 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
587 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
588 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
589 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
590 */
591
592 // Any non-zero value will do, but using something recognizable might help us
593 // debug some day.
594 static const NSTrackingRectTag kTrackingRectTag = 0xBADFACE;
595
596 // Override of a public NSView method, replacing the inherited functionality.
597 // See above for rationale.
598 - (NSTrackingRectTag)addTrackingRect:(NSRect)rect
599 owner:(id)owner
600 userData:(void *)data
601 assumeInside:(BOOL)assumeInside {
602 DCHECK(trackingRectOwner_ == nil);
603 trackingRectOwner_ = owner;
604 trackingRectUserData_ = data;
605 return kTrackingRectTag;
606 }
607
608 // Override of (apparently) a private NSView method(!) See above for rationale.
609 - (NSTrackingRectTag)_addTrackingRect:(NSRect)rect
610 owner:(id)owner
611 userData:(void *)data
612 assumeInside:(BOOL)assumeInside
613 useTrackingNum:(int)tag {
614 DCHECK(tag == 0 || tag == kTrackingRectTag);
615 DCHECK(trackingRectOwner_ == nil);
616 trackingRectOwner_ = owner;
617 trackingRectUserData_ = data;
618 return kTrackingRectTag;
619 }
620
621 // Override of (apparently) a private NSView method(!) See above for rationale.
622 - (void)_addTrackingRects:(NSRect *)rects
623 owner:(id)owner
624 userDataList:(void **)userDataList
625 assumeInsideList:(BOOL *)assumeInsideList
626 trackingNums:(NSTrackingRectTag *)trackingNums
627 count:(int)count {
628 DCHECK(count == 1);
629 DCHECK(trackingNums[0] == 0 || trackingNums[0] == kTrackingRectTag);
630 DCHECK(trackingRectOwner_ == nil);
631 trackingRectOwner_ = owner;
632 trackingRectUserData_ = userDataList[0];
633 trackingNums[0] = kTrackingRectTag;
634 }
635
636 // Override of a public NSView method, replacing the inherited functionality.
637 // See above for rationale.
638 - (void)removeTrackingRect:(NSTrackingRectTag)tag {
639 if (tag == 0)
640 return;
641
642 if (tag == kTrackingRectTag) {
643 trackingRectOwner_ = nil;
644 return;
645 }
646
647 if (tag == lastToolTipTag_) {
648 [super removeTrackingRect:tag];
649 lastToolTipTag_ = 0;
650 return;
651 }
652
653 // If any other tracking rect is being removed, we don't know how it was
654 // created and it's possible there's a leak involved (see Radar 3500217).
655 NOTREACHED();
656 }
657
658 // Override of (apparently) a private NSView method(!)
659 - (void)_removeTrackingRects:(NSTrackingRectTag *)tags count:(int)count {
660 for (int i = 0; i < count; ++i) {
661 int tag = tags[i];
662 if (tag == 0)
663 continue;
664 DCHECK(tag == kTrackingRectTag);
665 trackingRectOwner_ = nil;
666 }
667 }
668
669 // Sends a fake NSMouseExited event to the view for its current tracking rect.
670 - (void)_sendToolTipMouseExited {
671 // Nothing matters except window, trackingNumber, and userData.
672 int windowNumber = [[self window] windowNumber];
673 NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseExited
674 location:NSMakePoint(0, 0)
675 modifierFlags:0
676 timestamp:0
677 windowNumber:windowNumber
678 context:NULL
679 eventNumber:0
680 trackingNumber:kTrackingRectTag
681 userData:trackingRectUserData_];
682 [trackingRectOwner_ mouseExited:fakeEvent];
683 }
684
685 // Sends a fake NSMouseEntered event to the view for its current tracking rect.
686 - (void)_sendToolTipMouseEntered {
687 // Nothing matters except window, trackingNumber, and userData.
688 int windowNumber = [[self window] windowNumber];
689 NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered
690 location:NSMakePoint(0, 0)
691 modifierFlags:0
692 timestamp:0
693 windowNumber:windowNumber
694 context:NULL
695 eventNumber:0
696 trackingNumber:kTrackingRectTag
697 userData:trackingRectUserData_];
698 [trackingRectOwner_ mouseEntered:fakeEvent];
699 }
700
701 // Sets the view's current tooltip, to be displayed at the current mouse
702 // location. (This does not make the tooltip appear -- as usual, it only
703 // appears after a delay.) Pass null to remove the tooltip.
704 - (void)setToolTipAtMousePoint:(NSString *)string {
705 NSString *toolTip = [string length] == 0 ? nil : string;
706 NSString *oldToolTip = toolTip_;
707 if ((toolTip == nil || oldToolTip == nil) ? toolTip == oldToolTip
708 : [toolTip isEqualToString:oldToolTip]) {
709 return;
710 }
711 if (oldToolTip) {
712 [self _sendToolTipMouseExited];
713 [oldToolTip release];
714 }
715 toolTip_ = [toolTip copy];
716 if (toolTip) {
717 // See radar 3500217 for why we remove all tooltips
718 // rather than just the single one we created.
719 [self removeAllToolTips];
720 NSRect wideOpenRect = NSMakeRect(-100000, -100000, 200000, 200000);
721 lastToolTipTag_ = [self addToolTipRect:wideOpenRect
722 owner:self
723 userData:NULL];
724 [self _sendToolTipMouseEntered];
725 }
726 }
727
728 // NSView calls this to get the text when displaying the tooltip.
729 - (NSString *)view:(NSView *)view
730 stringForToolTip:(NSToolTipTag)tag
731 point:(NSPoint)point
732 userData:(void *)data {
733 return [[toolTip_ copy] autorelease];
734 }
735
573 @end 736 @end
574 737
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698