Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <QuartzCore/QuartzCore.h> | 5 #include <QuartzCore/QuartzCore.h> |
| 6 | 6 |
| 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" | 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 37 #include "content/common/gpu/gpu_messages.h" | 37 #include "content/common/gpu/gpu_messages.h" |
| 38 #include "content/common/native_web_keyboard_event.h" | 38 #include "content/common/native_web_keyboard_event.h" |
| 39 #include "content/common/plugin_messages.h" | 39 #include "content/common/plugin_messages.h" |
| 40 #include "content/common/view_messages.h" | 40 #include "content/common/view_messages.h" |
| 41 #include "skia/ext/platform_canvas.h" | 41 #include "skia/ext/platform_canvas.h" |
| 42 #import "third_party/mozilla/ComplexTextInputPanel.h" | 42 #import "third_party/mozilla/ComplexTextInputPanel.h" |
| 43 #include "third_party/skia/include/core/SkColor.h" | 43 #include "third_party/skia/include/core/SkColor.h" |
| 44 #include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFact ory.h" | 44 #include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFact ory.h" |
| 45 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 45 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| 46 #include "ui/gfx/point.h" | 46 #include "ui/gfx/point.h" |
| 47 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | |
| 47 #include "ui/gfx/surface/io_surface_support_mac.h" | 48 #include "ui/gfx/surface/io_surface_support_mac.h" |
| 48 #include "webkit/glue/webaccessibility.h" | 49 #include "webkit/glue/webaccessibility.h" |
| 49 #include "webkit/plugins/npapi/webplugin.h" | 50 #include "webkit/plugins/npapi/webplugin.h" |
| 50 | 51 |
| 51 using WebKit::WebInputEvent; | 52 using WebKit::WebInputEvent; |
| 52 using WebKit::WebInputEventFactory; | 53 using WebKit::WebInputEventFactory; |
| 53 using WebKit::WebMouseEvent; | 54 using WebKit::WebMouseEvent; |
| 54 using WebKit::WebMouseWheelEvent; | 55 using WebKit::WebMouseWheelEvent; |
| 56 using WebKit::WebGestureEvent; | |
| 55 | 57 |
| 56 static inline int ToWebKitModifiers(NSUInteger flags) { | 58 static inline int ToWebKitModifiers(NSUInteger flags) { |
| 57 int modifiers = 0; | 59 int modifiers = 0; |
| 58 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; | 60 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; |
| 59 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; | 61 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; |
| 60 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; | 62 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; |
| 61 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; | 63 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; |
| 62 return modifiers; | 64 return modifiers; |
| 63 } | 65 } |
| 64 | 66 |
| 65 // Private methods: | 67 // Private methods: |
| 66 @interface RenderWidgetHostViewCocoa () | 68 @interface RenderWidgetHostViewCocoa () |
| 67 @property(nonatomic, assign) NSRange selectedRange; | 69 @property(nonatomic, assign) NSRange selectedRange; |
| 68 @property(nonatomic, assign) NSRange markedRange; | 70 @property(nonatomic, assign) NSRange markedRange; |
| 69 | 71 |
| 70 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event; | 72 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event; |
| 71 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; | 73 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r; |
| 72 - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv; | 74 - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv; |
| 73 - (void)cancelChildPopups; | 75 - (void)cancelChildPopups; |
| 74 - (void)checkForPluginImeCancellation; | 76 - (void)checkForPluginImeCancellation; |
| 75 @end | 77 @end |
| 76 | 78 |
| 77 // This API was published since 10.6. Provide the declaration so it can be | 79 // This API was published since 10.6. Provide the declaration so it can be |
| 78 // // called below when building with the 10.5 SDK. | 80 // called below when building with the 10.5 SDK. |
| 79 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 | 81 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 |
| 80 @class NSTextInputContext; | 82 @class NSTextInputContext; |
| 81 @interface NSResponder (AppKitDetails) | 83 @interface NSResponder (AppKitDetails) |
| 82 - (NSTextInputContext *)inputContext; | 84 - (NSTextInputContext *)inputContext; |
| 83 @end | 85 @end |
| 84 #endif | 86 #endif |
| 85 | 87 |
| 88 // Undocumented Lion method to get the pattern for the over-scroll area. | |
| 89 @interface NSColor (LionSekretAPI) | |
| 90 + (NSImage*)_linenPatternImage; | |
| 91 @end | |
| 92 | |
| 93 // NSEvent subtype for scroll gestures events. | |
| 94 static const short kIOHIDEventTypeScroll = 6; | |
| 95 | |
| 86 namespace { | 96 namespace { |
| 87 | 97 |
| 88 // Maximum number of characters we allow in a tooltip. | 98 // Maximum number of characters we allow in a tooltip. |
| 89 const size_t kMaxTooltipLength = 1024; | 99 const size_t kMaxTooltipLength = 1024; |
| 90 | 100 |
| 91 // TODO(suzhe): Upstream this function. | 101 // TODO(suzhe): Upstream this function. |
| 92 WebKit::WebColor WebColorFromNSColor(NSColor *color) { | 102 WebKit::WebColor WebColorFromNSColor(NSColor *color) { |
| 93 CGFloat r, g, b, a; | 103 CGFloat r, g, b, a; |
| 94 [color getRed:&r green:&g blue:&b alpha:&a]; | 104 [color getRed:&r green:&g blue:&b alpha:&a]; |
| 95 | 105 |
| (...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1202 [self confirmComposition]; | 1212 [self confirmComposition]; |
| 1203 } | 1213 } |
| 1204 | 1214 |
| 1205 const WebMouseEvent& event = | 1215 const WebMouseEvent& event = |
| 1206 WebInputEventFactory::mouseEvent(theEvent, self); | 1216 WebInputEventFactory::mouseEvent(theEvent, self); |
| 1207 | 1217 |
| 1208 if (renderWidgetHostView_->render_widget_host_) | 1218 if (renderWidgetHostView_->render_widget_host_) |
| 1209 renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event); | 1219 renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event); |
| 1210 } | 1220 } |
| 1211 | 1221 |
| 1222 - (void)shortCircuitedEndGestureWithEvent:(NSEvent*)theEvent { | |
| 1223 if ([theEvent subtype] == kIOHIDEventTypeScroll) { | |
|
Nico
2011/08/08 19:44:59
can you DCHECK this instead?
Alexei Svitkine (slow)
2011/08/08 20:06:29
I don't think so, since there might be other types
Nico
2011/08/08 20:11:27
Isn't they only called the one in beginGestureWith
| |
| 1224 WebGestureEvent event = WebInputEventFactory::gestureEvent(theEvent, self); | |
| 1225 | |
| 1226 if (renderWidgetHostView_->render_widget_host_) | |
| 1227 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(event); | |
| 1228 | |
| 1229 if (endGestureMonitor_) { | |
| 1230 [NSEvent removeMonitor:endGestureMonitor_]; | |
| 1231 endGestureMonitor_ = nil; | |
| 1232 } | |
| 1233 } | |
| 1234 } | |
| 1235 | |
| 1236 - (void)beginGestureWithEvent:(NSEvent*)theEvent { | |
| 1237 if ([theEvent subtype] == kIOHIDEventTypeScroll) { | |
| 1238 WebGestureEvent event = WebInputEventFactory::gestureEvent(theEvent, self); | |
| 1239 | |
| 1240 if (renderWidgetHostView_->render_widget_host_) | |
| 1241 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(event); | |
| 1242 | |
| 1243 if (!endGestureMonitor_) { | |
| 1244 endGestureMonitor_ = | |
| 1245 [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskEndGesture | |
| 1246 handler: ^(NSEvent *blockEvent) { | |
| 1247 [self shortCircuitedEndGestureWithEvent:blockEvent]; | |
| 1248 return blockEvent; | |
| 1249 }]; | |
| 1250 } | |
| 1251 } | |
| 1252 | |
| 1253 // Forward the gesture event to the next responder so that the browser window | |
| 1254 // controller has a chance to act on back/forward gesture events. | |
| 1255 [[self nextResponder] beginGestureWithEvent:theEvent]; | |
| 1256 } | |
| 1257 | |
| 1212 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { | 1258 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { |
| 1213 // |performKeyEquivalent:| is sent to all views of a window, not only down the | 1259 // |performKeyEquivalent:| is sent to all views of a window, not only down the |
| 1214 // responder chain (cf. "Handling Key Equivalents" in | 1260 // responder chain (cf. "Handling Key Equivalents" in |
| 1215 // http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Event Overview/HandlingKeyEvents/HandlingKeyEvents.html | 1261 // http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Event Overview/HandlingKeyEvents/HandlingKeyEvents.html |
| 1216 // ). We only want to handle key equivalents if we're first responder. | 1262 // ). We only want to handle key equivalents if we're first responder. |
| 1217 if ([[self window] firstResponder] != self) | 1263 if ([[self window] firstResponder] != self) |
| 1218 return NO; | 1264 return NO; |
| 1219 | 1265 |
| 1220 // If we return |NO| from this function, cocoa will send the key event to | 1266 // If we return |NO| from this function, cocoa will send the key event to |
| 1221 // the menu and only if the menu does not process the event to |keyDown:|. We | 1267 // the menu and only if the menu does not process the event to |keyDown:|. We |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1557 y += height; | 1603 y += height; |
| 1558 height = -height; | 1604 height = -height; |
| 1559 } | 1605 } |
| 1560 | 1606 |
| 1561 NSRect r = [self flipRectToNSRect:gfx::Rect(x, y, width, height)]; | 1607 NSRect r = [self flipRectToNSRect:gfx::Rect(x, y, width, height)]; |
| 1562 [[NSColor whiteColor] set]; | 1608 [[NSColor whiteColor] set]; |
| 1563 NSRectFill(r); | 1609 NSRectFill(r); |
| 1564 } | 1610 } |
| 1565 } | 1611 } |
| 1566 | 1612 |
| 1613 - (void)fillRect:(NSRect)rect withPattern:(NSImage*)patternImage { | |
| 1614 if (NSIsEmptyRect(rect)) | |
| 1615 return; | |
| 1616 | |
| 1617 NSColor* patternColor = [NSColor colorWithPatternImage:patternImage]; | |
| 1618 [patternColor set]; | |
| 1619 NSRectFill(rect); | |
| 1620 } | |
| 1621 | |
| 1622 - (void)drawShadow:(NSShadow*)shadow | |
| 1623 withRect:(NSRect)rect | |
| 1624 clip:(NSRect)clipRect { | |
| 1625 gfx::ScopedNSGraphicsContextSaveGState scopedGState; | |
| 1626 NSBezierPath* drawingPath = [NSBezierPath bezierPathWithRect:rect]; | |
| 1627 [shadow set]; | |
| 1628 [[NSColor blackColor] set]; | |
| 1629 [[NSBezierPath bezierPathWithRect:clipRect] addClip]; | |
| 1630 [drawingPath fill]; | |
| 1631 } | |
| 1632 | |
| 1633 - (NSRect)computeVisibleContentRect { | |
| 1634 const RenderWidgetHost* rwh = renderWidgetHostView_->render_widget_host_; | |
| 1635 gfx::Point offset = rwh->last_scroll_offset(); | |
| 1636 gfx::Size size = rwh->contents_size(); | |
| 1637 NSRect contentRect = | |
| 1638 NSMakeRect(-offset.x(), -offset.y(), size.width(), size.height()); | |
| 1639 NSRect frameRect = [self frame]; | |
| 1640 frameRect.origin = NSMakePoint(0, 0); | |
| 1641 return NSIntersectionRect(frameRect, contentRect); | |
| 1642 } | |
| 1643 | |
| 1644 - (void)fillOverScrollAreas:(NSRect)dirtyRect { | |
| 1645 if (![NSColor respondsToSelector:@selector(_linenPatternImage)]) | |
| 1646 return; | |
| 1647 | |
| 1648 NSRect visibleContentRect = [self computeVisibleContentRect]; | |
| 1649 NSSize frameSize = [self frame].size; | |
| 1650 bool hasHorizontalOverflow = (NSWidth(visibleContentRect) < frameSize.width); | |
| 1651 bool hasVerticalOverflow = (NSHeight(visibleContentRect) < frameSize.height); | |
| 1652 | |
| 1653 if (!hasHorizontalOverflow && !hasVerticalOverflow) | |
| 1654 return; | |
| 1655 | |
| 1656 NSRect xRect = NSMakeRect(0, | |
| 1657 0, | |
| 1658 frameSize.width - NSWidth(visibleContentRect), | |
| 1659 frameSize.height); | |
| 1660 NSRect yRect = NSMakeRect(0, | |
| 1661 0, | |
| 1662 frameSize.width, | |
| 1663 frameSize.height - NSHeight(visibleContentRect)); | |
| 1664 NSImage* background = [NSColor _linenPatternImage]; | |
| 1665 scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); | |
| 1666 [shadow.get() setShadowColor:[NSColor blackColor]]; | |
| 1667 [shadow setShadowBlurRadius:5]; | |
| 1668 | |
| 1669 if (hasHorizontalOverflow) { | |
| 1670 NSRect shadowRect; | |
| 1671 if (visibleContentRect.origin.x > 0) { | |
| 1672 shadowRect = xRect; | |
| 1673 shadowRect.origin.x += NSWidth(shadowRect); | |
| 1674 } else { | |
| 1675 xRect.origin.x = NSWidth(visibleContentRect); | |
| 1676 shadowRect = xRect; | |
| 1677 shadowRect.origin.x -= 1; | |
| 1678 } | |
| 1679 shadowRect.size.width = 1; | |
| 1680 NSRect intersectRect = NSIntersectionRect(dirtyRect, xRect); | |
| 1681 [self fillRect:intersectRect withPattern:background]; | |
| 1682 [self drawShadow:shadow.get() withRect:shadowRect clip:intersectRect]; | |
| 1683 } | |
| 1684 | |
| 1685 if (hasVerticalOverflow) { | |
| 1686 NSRect shadowRect = visibleContentRect; | |
| 1687 if (visibleContentRect.origin.y > 0) { | |
| 1688 yRect.origin.y = NSHeight(visibleContentRect); | |
| 1689 shadowRect.origin.y = yRect.origin.y - 1; | |
| 1690 } else { | |
| 1691 shadowRect.origin.y = yRect.origin.y + NSHeight(yRect); | |
| 1692 } | |
| 1693 shadowRect.size.height = 1; | |
| 1694 NSRect intersectRect = NSIntersectionRect(dirtyRect, yRect); | |
| 1695 [self fillRect:intersectRect withPattern:background]; | |
| 1696 [self drawShadow:shadow.get() withRect:shadowRect clip:intersectRect]; | |
| 1697 } | |
| 1698 } | |
| 1699 | |
| 1567 - (void)drawRect:(NSRect)dirtyRect { | 1700 - (void)drawRect:(NSRect)dirtyRect { |
| 1568 if (!renderWidgetHostView_->render_widget_host_) { | 1701 if (!renderWidgetHostView_->render_widget_host_) { |
| 1569 // TODO(shess): Consider using something more noticable? | 1702 // TODO(shess): Consider using something more noticable? |
| 1570 [[NSColor whiteColor] set]; | 1703 [[NSColor whiteColor] set]; |
| 1571 NSRectFill(dirtyRect); | 1704 NSRectFill(dirtyRect); |
| 1572 return; | 1705 return; |
| 1573 } | 1706 } |
| 1574 | 1707 |
| 1575 const gfx::Rect damagedRect([self flipNSRectToRect:dirtyRect]); | 1708 const gfx::Rect damagedRect([self flipNSRectToRect:dirtyRect]); |
| 1576 | 1709 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1632 CGBitmapContextCreateImage(backingStore->cg_bitmap())); | 1765 CGBitmapContextCreateImage(backingStore->cg_bitmap())); |
| 1633 CGRect imageRect = bitmapRect.ToCGRect(); | 1766 CGRect imageRect = bitmapRect.ToCGRect(); |
| 1634 imageRect.origin.y = yOffset; | 1767 imageRect.origin.y = yOffset; |
| 1635 CGContextDrawImage(context, imageRect, image); | 1768 CGContextDrawImage(context, imageRect, image); |
| 1636 } | 1769 } |
| 1637 } | 1770 } |
| 1638 | 1771 |
| 1639 // Fill the remaining portion of the damagedRect with white | 1772 // Fill the remaining portion of the damagedRect with white |
| 1640 [self fillBottomRightRemainderOfRect:bitmapRect dirtyRect:damagedRect]; | 1773 [self fillBottomRightRemainderOfRect:bitmapRect dirtyRect:damagedRect]; |
| 1641 | 1774 |
| 1775 // Fill the over-scroll areas, if any, with the appropriate pattern. | |
| 1776 [self fillOverScrollAreas:dirtyRect]; | |
| 1777 | |
| 1642 if (!renderWidgetHostView_->whiteout_start_time_.is_null()) { | 1778 if (!renderWidgetHostView_->whiteout_start_time_.is_null()) { |
| 1643 base::TimeDelta whiteout_duration = base::TimeTicks::Now() - | 1779 base::TimeDelta whiteout_duration = base::TimeTicks::Now() - |
| 1644 renderWidgetHostView_->whiteout_start_time_; | 1780 renderWidgetHostView_->whiteout_start_time_; |
| 1645 UMA_HISTOGRAM_TIMES("MPArch.RWHH_WhiteoutDuration", whiteout_duration); | 1781 UMA_HISTOGRAM_TIMES("MPArch.RWHH_WhiteoutDuration", whiteout_duration); |
| 1646 | 1782 |
| 1647 // Reset the start time to 0 so that we start recording again the next | 1783 // Reset the start time to 0 so that we start recording again the next |
| 1648 // time the backing store is NULL... | 1784 // time the backing store is NULL... |
| 1649 renderWidgetHostView_->whiteout_start_time_ = base::TimeTicks(); | 1785 renderWidgetHostView_->whiteout_start_time_ = base::TimeTicks(); |
| 1650 } | 1786 } |
| 1651 if (!renderWidgetHostView_->tab_switch_paint_time_.is_null()) { | 1787 if (!renderWidgetHostView_->tab_switch_paint_time_.is_null()) { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1879 RenderWidgetHost* rwh = renderWidgetHostView_->render_widget_host_; | 2015 RenderWidgetHost* rwh = renderWidgetHostView_->render_widget_host_; |
| 1880 rwh->Send(new ViewMsg_SetAccessibilityFocus( | 2016 rwh->Send(new ViewMsg_SetAccessibilityFocus( |
| 1881 rwh->routing_id(), accessibilityObjectId)); | 2017 rwh->routing_id(), accessibilityObjectId)); |
| 1882 } | 2018 } |
| 1883 } | 2019 } |
| 1884 | 2020 |
| 1885 - (void)performShowMenuAction:(BrowserAccessibilityCocoa*)accessibility { | 2021 - (void)performShowMenuAction:(BrowserAccessibilityCocoa*)accessibility { |
| 1886 // Performs a right click copying WebKit's | 2022 // Performs a right click copying WebKit's |
| 1887 // accessibilityPerformShowMenuAction. | 2023 // accessibilityPerformShowMenuAction. |
| 1888 NSPoint location = [self accessibilityPointInScreen:accessibility]; | 2024 NSPoint location = [self accessibilityPointInScreen:accessibility]; |
| 1889 NSSize size = [[accessibility size] sizeValue]; | 2025 NSSize size = [[accessibility size] sizeValue]; |
| 1890 location = [[self window] convertScreenToBase:location]; | 2026 location = [[self window] convertScreenToBase:location]; |
| 1891 location.x += size.width/2; | 2027 location.x += size.width/2; |
| 1892 location.y += size.height/2; | 2028 location.y += size.height/2; |
| 1893 | 2029 |
| 1894 NSEvent* fakeRightClick = [NSEvent | 2030 NSEvent* fakeRightClick = [NSEvent |
| 1895 mouseEventWithType:NSRightMouseDown | 2031 mouseEventWithType:NSRightMouseDown |
| 1896 location:location | 2032 location:location |
| 1897 modifierFlags:nil | 2033 modifierFlags:nil |
| 1898 timestamp:0 | 2034 timestamp:0 |
| 1899 windowNumber:[[self window] windowNumber] | 2035 windowNumber:[[self window] windowNumber] |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2625 if (!string) return NO; | 2761 if (!string) return NO; |
| 2626 | 2762 |
| 2627 // If the user is currently using an IME, confirm the IME input, | 2763 // If the user is currently using an IME, confirm the IME input, |
| 2628 // and then insert the text from the service, the same as TextEdit and Safari. | 2764 // and then insert the text from the service, the same as TextEdit and Safari. |
| 2629 [self confirmComposition]; | 2765 [self confirmComposition]; |
| 2630 [self insertText:string]; | 2766 [self insertText:string]; |
| 2631 return YES; | 2767 return YES; |
| 2632 } | 2768 } |
| 2633 | 2769 |
| 2634 @end | 2770 @end |
| OLD | NEW |