1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_ 6 #define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_ 7 8 #import <Cocoa/Cocoa.h> 9 #include <IOSurface/IOSurfaceAPI.h> 10 #include <list> 11 #include <map> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 16 #include "base/mac/scoped_nsobject.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/weak_ptr.h" 19 #include "base/time/time.h" 20 #include "content/browser/compositor/browser_compositor_view_mac.h" 21 #include "content/browser/compositor/delegated_frame_host.h" 22 #include "content/browser/compositor/io_surface_layer_mac.h" 23 #include "content/browser/renderer_host/display_link_mac.h" 24 #include "content/browser/renderer_host/render_widget_host_view_base.h" 25 #include "content/browser/renderer_host/software_frame_manager.h" 26 #include "content/common/content_export.h" 27 #include "content/common/cursors/webcursor.h" 28 #include "content/common/edit_command.h" 29 #import "content/public/browser/render_widget_host_view_mac_base.h" 30 #include "ipc/ipc_sender.h" 31 #include "third_party/WebKit/public/web/WebCompositionUnderline.h" 32 #include "ui/base/cocoa/base_view.h" 33 #include "ui/base/cocoa/remote_layer_api.h" 34 #include "ui/gfx/display_observer.h" 35 36 namespace content { 37 class BrowserCompositorviewMac; 38 class RenderWidgetHostViewMac; 39 class RenderWidgetHostViewMacEditCommandHelper; 40 class WebContents; 41 } 42 43 namespace ui { 44 class Compositor; 45 class Layer; 46 } 47 48 @class FullscreenWindowManager; 49 @protocol RenderWidgetHostViewMacDelegate; 50 @class ToolTip; 51 52 @protocol RenderWidgetHostViewMacOwner 53 - (content::RenderWidgetHostViewMac*)renderWidgetHostViewMac; 54 @end 55 56 // This is the view that lives in the Cocoa view hierarchy. In Windows-land, 57 // RenderWidgetHostViewWin is both the view and the delegate. We split the roles 58 // but that means that the view needs to own the delegate and will dispose of it 59 // when it's removed from the view system. 60 @interface RenderWidgetHostViewCocoa 61 : BaseView <RenderWidgetHostViewMacBase, 62 RenderWidgetHostViewMacOwner, 63 NSTextInputClient> { 64 @private 65 scoped_ptr<content::RenderWidgetHostViewMac> renderWidgetHostView_; 66 // This ivar is the cocoa delegate of the NSResponder. 67 base::scoped_nsobject<NSObject<RenderWidgetHostViewMacDelegate>> 68 responderDelegate_; 69 BOOL canBeKeyView_; 70 BOOL takesFocusOnlyOnMouseDown_; 71 BOOL closeOnDeactivate_; 72 scoped_ptr<content::RenderWidgetHostViewMacEditCommandHelper> 73 editCommand_helper_; 74 75 // These are part of the magic tooltip code from WebKit's WebHTMLView: 76 id trackingRectOwner_; // (not retained) 77 void* trackingRectUserData_; 78 NSTrackingRectTag lastToolTipTag_; 79 base::scoped_nsobject<NSString> toolTip_; 80 81 // Is YES if there was a mouse-down as yet unbalanced with a mouse-up. 82 BOOL hasOpenMouseDown_; 83 84 NSWindow* lastWindow_; // weak 85 86 // The cursor for the page. This is passed up from the renderer. 87 base::scoped_nsobject<NSCursor> currentCursor_; 88 89 // Variables used by our implementaion of the NSTextInput protocol. 90 // An input method of Mac calls the methods of this protocol not only to 91 // notify an application of its status, but also to retrieve the status of 92 // the application. That is, an application cannot control an input method 93 // directly. 94 // This object keeps the status of a composition of the renderer and returns 95 // it when an input method asks for it. 96 // We need to implement Objective-C methods for the NSTextInput protocol. On 97 // the other hand, we need to implement a C++ method for an IPC-message 98 // handler which receives input-method events from the renderer. 99 100 // Represents the input-method attributes supported by this object. 101 base::scoped_nsobject<NSArray> validAttributesForMarkedText_; 102 103 // Indicates if we are currently handling a key down event. 104 BOOL handlingKeyDown_; 105 106 // Indicates if there is any marked text. 107 BOOL hasMarkedText_; 108 109 // Indicates if unmarkText is called or not when handling a keyboard 110 // event. 111 BOOL unmarkTextCalled_; 112 113 // The range of current marked text inside the whole content of the DOM node 114 // being edited. 115 // TODO(suzhe): This is currently a fake value, as we do not support accessing 116 // the whole content yet. 117 NSRange markedRange_; 118 119 // The selected range, cached from a message sent by the renderer. 120 NSRange selectedRange_; 121 122 // Text to be inserted which was generated by handling a key down event. 123 base::string16 textToBeInserted_; 124 125 // Marked text which was generated by handling a key down event. 126 base::string16 markedText_; 127 128 // Underline information of the |markedText_|. 129 std::vector<blink::WebCompositionUnderline> underlines_; 130 131 // Indicates if doCommandBySelector method receives any edit command when 132 // handling a key down event. 133 BOOL hasEditCommands_; 134 135 // Contains edit commands received by the -doCommandBySelector: method when 136 // handling a key down event, not including inserting commands, eg. insertTab, 137 // etc. 138 content::EditCommands editCommands_; 139 140 // The plugin that currently has focus (-1 if no plugin has focus). 141 int focusedPluginIdentifier_; 142 143 // Whether or not plugin IME is currently enabled active. 144 BOOL pluginImeActive_; 145 146 // Whether the previous mouse event was ignored due to hitTest check. 147 BOOL mouseEventWasIgnored_; 148 149 // Event monitor for scroll wheel end event. 150 id endWheelMonitor_; 151 152 // If true then escape key down events are suppressed until the first escape 153 // key up event. (The up event is suppressed as well). This is used by the 154 // flash fullscreen code to avoid sending a key up event without a matching 155 // key down event. 156 BOOL suppressNextEscapeKeyUp_; 157 } 158 159 @property(nonatomic, readonly) NSRange selectedRange; 160 @property(nonatomic, readonly) BOOL suppressNextEscapeKeyUp; 161 162 - (void)setCanBeKeyView:(BOOL)can; 163 - (void)setTakesFocusOnlyOnMouseDown:(BOOL)b; 164 - (void)setCloseOnDeactivate:(BOOL)b; 165 - (void)setToolTipAtMousePoint:(NSString *)string; 166 // True for always-on-top special windows (e.g. Balloons and Panels). 167 - (BOOL)acceptsMouseEventsWhenInactive; 168 // Cancel ongoing composition (abandon the marked text). 169 - (void)cancelComposition; 170 // Confirm ongoing composition. 171 - (void)confirmComposition; 172 // Enables or disables plugin IME. 173 - (void)setPluginImeActive:(BOOL)active; 174 // Updates the current plugin focus state. 175 - (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId; 176 // Evaluates the event in the context of plugin IME, if plugin IME is enabled. 177 // Returns YES if the event was handled. 178 - (BOOL)postProcessEventForPluginIme:(NSEvent*)event; 179 - (void)updateCursor:(NSCursor*)cursor; 180 - (NSRect)firstViewRectForCharacterRange:(NSRange)theRange 181 actualRange:(NSRangePointer)actualRange; 182 @end 183 184 namespace content { 185 class RenderWidgetHostImpl; 186 187 /////////////////////////////////////////////////////////////////////////////// 188 // RenderWidgetHostViewMac 189 // 190 // An object representing the "View" of a rendered web page. This object is 191 // responsible for displaying the content of the web page, and integrating with 192 // the Cocoa view system. It is the implementation of the RenderWidgetHostView 193 // that the cross-platform RenderWidgetHost object uses 194 // to display the data. 195 // 196 // Comment excerpted from render_widget_host.h: 197 // 198 // "The lifetime of the RenderWidgetHost* is tied to the render process. 199 // If the render process dies, the RenderWidgetHost* goes away and all 200 // references to it must become NULL." 201 // 202 // RenderWidgetHostView class hierarchy described in render_widget_host_view.h. 203 class CONTENT_EXPORT RenderWidgetHostViewMac 204 : public RenderWidgetHostViewBase, 205 public DelegatedFrameHostClient, 206 public BrowserCompositorViewMacClient, 207 public IPC::Sender, 208 public gfx::DisplayObserver { 209 public: 210 // The view will associate itself with the given widget. The native view must 211 // be hooked up immediately to the view hierarchy, or else when it is 212 // deleted it will delete this out from under the caller. 213 explicit RenderWidgetHostViewMac(RenderWidgetHost* widget); 214 virtual ~RenderWidgetHostViewMac(); 215 216 RenderWidgetHostViewCocoa* cocoa_view() const { return cocoa_view_; } 217 218 // |delegate| is used to separate out the logic from the NSResponder delegate. 219 // |delegate| is retained by this class. 220 // |delegate| should be set at most once. 221 CONTENT_EXPORT void SetDelegate( 222 NSObject<RenderWidgetHostViewMacDelegate>* delegate); 223 void SetAllowPauseForResizeOrRepaint(bool allow); 224 225 // RenderWidgetHostView implementation. 226 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; 227 virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE; 228 virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE; 229 virtual void SetSize(const gfx::Size& size) OVERRIDE; 230 virtual void SetBounds(const gfx::Rect& rect) OVERRIDE; 231 virtual gfx::Vector2dF GetLastScrollOffset() const OVERRIDE; 232 virtual gfx::NativeView GetNativeView() const OVERRIDE; 233 virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE; 234 virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE; 235 virtual bool HasFocus() const OVERRIDE; 236 virtual bool IsSurfaceAvailableForCopy() const OVERRIDE; 237 virtual void Show() OVERRIDE; 238 virtual void Hide() OVERRIDE; 239 virtual bool IsShowing() OVERRIDE; 240 virtual gfx::Rect GetViewBounds() const OVERRIDE; 241 virtual void SetShowingContextMenu(bool showing) OVERRIDE; 242 virtual void SetActive(bool active) OVERRIDE; 243 virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE; 244 virtual void SetWindowVisibility(bool visible) OVERRIDE; 245 virtual void WindowFrameChanged() OVERRIDE; 246 virtual void ShowDefinitionForSelection() OVERRIDE; 247 virtual bool SupportsSpeech() const OVERRIDE; 248 virtual void SpeakSelection() OVERRIDE; 249 virtual bool IsSpeaking() const OVERRIDE; 250 virtual void StopSpeaking() OVERRIDE; 251 virtual void SetBackgroundOpaque(bool opaque) OVERRIDE; 252 253 // Implementation of RenderWidgetHostViewBase. 254 virtual void InitAsPopup(RenderWidgetHostView* parent_host_view, 255 const gfx::Rect& pos) OVERRIDE; 256 virtual void InitAsFullscreen( 257 RenderWidgetHostView* reference_host_view) OVERRIDE; 258 virtual void WasShown() OVERRIDE; 259 virtual void WasHidden() OVERRIDE; 260 virtual void MovePluginWindows( 261 const std::vector<WebPluginGeometry>& moves) OVERRIDE; 262 virtual void Focus() OVERRIDE; 263 virtual void Blur() OVERRIDE; 264 virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE; 265 virtual void SetIsLoading(bool is_loading) OVERRIDE; 266 virtual void TextInputTypeChanged(ui::TextInputType type, 267 ui::TextInputMode input_mode, 268 bool can_compose_inline) OVERRIDE; 269 virtual void ImeCancelComposition() OVERRIDE; 270 virtual void ImeCompositionRangeChanged( 271 const gfx::Range& range, 272 const std::vector<gfx::Rect>& character_bounds) OVERRIDE; 273 virtual void RenderProcessGone(base::TerminationStatus status, 274 int error_code) OVERRIDE; 275 virtual void RenderWidgetHostGone() OVERRIDE; 276 virtual void Destroy() OVERRIDE; 277 virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; 278 virtual void SelectionChanged(const base::string16& text, 279 size_t offset, 280 const gfx::Range& range) OVERRIDE; 281 virtual void SelectionBoundsChanged( 282 const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE; 283 virtual void CopyFromCompositingSurface( 284 const gfx::Rect& src_subrect, 285 const gfx::Size& dst_size, 286 const base::Callback<void(bool, const SkBitmap&)>& callback, 287 SkColorType color_type) OVERRIDE; 288 virtual void CopyFromCompositingSurfaceToVideoFrame( 289 const gfx::Rect& src_subrect, 290 const scoped_refptr<media::VideoFrame>& target, 291 const base::Callback<void(bool)>& callback) OVERRIDE; 292 virtual bool CanCopyToVideoFrame() const OVERRIDE; 293 virtual bool CanSubscribeFrame() const OVERRIDE; 294 virtual void BeginFrameSubscription( 295 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE; 296 virtual void EndFrameSubscription() OVERRIDE; 297 virtual void OnSwapCompositorFrame( 298 uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) OVERRIDE; 299 virtual void AcceleratedSurfaceInitialized(int host_id, 300 int route_id) OVERRIDE; 301 virtual BrowserAccessibilityManager* CreateBrowserAccessibilityManager( 302 BrowserAccessibilityDelegate* delegate) OVERRIDE; 303 virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds) 304 OVERRIDE; 305 virtual void AccessibilityShowMenu(const gfx::Point& point) OVERRIDE; 306 virtual bool PostProcessEventForPluginIme( 307 const NativeWebKeyboardEvent& event) OVERRIDE; 308 309 virtual void AcceleratedSurfaceBuffersSwapped( 310 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, 311 int gpu_host_id) OVERRIDE; 312 virtual void AcceleratedSurfacePostSubBuffer( 313 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, 314 int gpu_host_id) OVERRIDE; 315 virtual void AcceleratedSurfaceSuspend() OVERRIDE; 316 virtual void AcceleratedSurfaceRelease() OVERRIDE; 317 virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE; 318 virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE; 319 virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE; 320 virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE; 321 322 virtual bool LockMouse() OVERRIDE; 323 virtual void UnlockMouse() OVERRIDE; 324 virtual void WheelEventAck(const blink::WebMouseWheelEvent& event, 325 InputEventAckState ack_result) OVERRIDE; 326 327 // IPC::Sender implementation. 328 virtual bool Send(IPC::Message* message) OVERRIDE; 329 330 virtual SkColorType PreferredReadbackFormat() OVERRIDE; 331 332 // gfx::DisplayObserver implementation. 333 virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE; 334 virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE; 335 virtual void OnDisplayMetricsChanged(const gfx::Display& display, 336 uint32_t metrics) OVERRIDE; 337 338 // Forwards the mouse event to the renderer. 339 void ForwardMouseEvent(const blink::WebMouseEvent& event); 340 341 void KillSelf(); 342 343 void SetTextInputActive(bool active); 344 345 // Sends completed plugin IME notification and text back to the renderer. 346 void PluginImeCompositionCompleted(const base::string16& text, int plugin_id); 347 348 const std::string& selected_text() const { return selected_text_; } 349 350 // Returns true and stores first rectangle for character range if the 351 // requested |range| is already cached, otherwise returns false. 352 // Exposed for testing. 353 CONTENT_EXPORT bool GetCachedFirstRectForCharacterRange( 354 NSRange range, NSRect* rect, NSRange* actual_range); 355 356 // Returns true if there is line break in |range| and stores line breaking 357 // point to |line_breaking_point|. The |line_break_point| is valid only if 358 // this function returns true. 359 bool GetLineBreakIndex(const std::vector<gfx::Rect>& bounds, 360 const gfx::Range& range, 361 size_t* line_break_point); 362 363 // Returns composition character boundary rectangle. The |range| is 364 // composition based range. Also stores |actual_range| which is corresponding 365 // to actually used range for returned rectangle. 366 gfx::Rect GetFirstRectForCompositionRange(const gfx::Range& range, 367 gfx::Range* actual_range); 368 369 // Converts from given whole character range to composition oriented range. If 370 // the conversion failed, return gfx::Range::InvalidRange. 371 gfx::Range ConvertCharacterRangeToCompositionRange( 372 const gfx::Range& request_range); 373 374 WebContents* GetWebContents(); 375 376 // These member variables should be private, but the associated ObjC class 377 // needs access to them and can't be made a friend. 378 379 // The associated Model. Can be NULL if Destroy() is called when 380 // someone (other than superview) has retained |cocoa_view_|. 381 RenderWidgetHostImpl* render_widget_host_; 382 383 // Current text input type. 384 ui::TextInputType text_input_type_; 385 bool can_compose_inline_; 386 387 // The background CoreAnimation layer which is hosted by |cocoa_view_|. 388 base::scoped_nsobject<CALayer> background_layer_; 389 390 // Delegated frame management and compositior. 391 scoped_ptr<DelegatedFrameHost> delegated_frame_host_; 392 scoped_ptr<ui::Layer> root_layer_; 393 394 // Container for the NSView drawn by the browser compositor. 395 scoped_ptr<BrowserCompositorViewMac> browser_compositor_view_; 396 397 // Placeholder that is allocated while browser_compositor_view_ is NULL, 398 // indicating that a BrowserCompositorViewMac may be allocated. This is to 399 // help in recycling the internals of BrowserCompositorViewMac. 400 scoped_ptr<BrowserCompositorViewPlaceholderMac> 401 browser_compositor_view_placeholder_; 402 403 NSWindow* pepper_fullscreen_window() const { 404 return pepper_fullscreen_window_; 405 } 406 407 CONTENT_EXPORT void release_pepper_fullscreen_window_for_testing(); 408 409 RenderWidgetHostViewMac* fullscreen_parent_host_view() const { 410 return fullscreen_parent_host_view_; 411 } 412 413 int window_number() const; 414 415 // The scale factor for the screen that the view is currently on. 416 float ViewScaleFactor() const; 417 418 // Update the scale factor for the backing store and for any CALayers. 419 void UpdateBackingStoreScaleFactor(); 420 421 // Ensure that the display link is associated with the correct display. 422 void UpdateDisplayLink(); 423 424 void PauseForPendingResizeOrRepaintsAndDraw(); 425 426 // DelegatedFrameHostClient implementation. 427 virtual ui::Compositor* GetCompositor() const OVERRIDE; 428 virtual ui::Layer* GetLayer() OVERRIDE; 429 virtual RenderWidgetHostImpl* GetHost() OVERRIDE; 430 virtual bool IsVisible() OVERRIDE; 431 virtual scoped_ptr<ResizeLock> CreateResizeLock( 432 bool defer_compositor_lock) OVERRIDE; 433 virtual gfx::Size DesiredFrameSize() OVERRIDE; 434 virtual float CurrentDeviceScaleFactor() OVERRIDE; 435 virtual gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) OVERRIDE; 436 virtual DelegatedFrameHost* GetDelegatedFrameHost() const OVERRIDE; 437 438 // BrowserCompositorViewMacClient implementation. 439 virtual bool BrowserCompositorViewShouldAckImmediately() const OVERRIDE; 440 virtual void BrowserCompositorViewFrameSwapped( 441 const std::vector<ui::LatencyInfo>& latency_info) OVERRIDE; 442 virtual NSView* BrowserCompositorSuperview() OVERRIDE; 443 virtual ui::Layer* BrowserCompositorRootLayer() OVERRIDE; 444 445 private: 446 friend class RenderWidgetHostViewMacTest; 447 448 // Returns whether this render view is a popup (autocomplete window). 449 bool IsPopup() const; 450 451 // Shuts down the render_widget_host_. This is a separate function so we can 452 // invoke it from the message loop. 453 void ShutdownHost(); 454 455 // Tear down all components of the browser compositor in an order that will 456 // ensure no dangling references. 457 void ShutdownBrowserCompositor(); 458 459 void EnsureBrowserCompositorView(); 460 void DestroyBrowserCompositorView(); 461 462 // IPC message handlers. 463 void OnPluginFocusChanged(bool focused, int plugin_id); 464 void OnStartPluginIme(); 465 void OnGetRenderedTextCompleted(const std::string& text); 466 467 // Send updated vsync parameters to the renderer. 468 void SendVSyncParametersToRenderer(); 469 470 // Dispatches a TTS session. 471 void SpeakText(const std::string& text); 472 473 // The associated view. This is weak and is inserted into the view hierarchy 474 // to own this RenderWidgetHostViewMac object. Set to nil at the start of the 475 // destructor. 476 RenderWidgetHostViewCocoa* cocoa_view_; 477 478 // Indicates if the page is loading. 479 bool is_loading_; 480 481 // Whether it's allowed to pause waiting for a new frame. 482 bool allow_pause_for_resize_or_repaint_; 483 484 // The last scroll offset of the view. 485 gfx::Vector2dF last_scroll_offset_; 486 487 // The text to be shown in the tooltip, supplied by the renderer. 488 base::string16 tooltip_text_; 489 490 // Factory used to safely scope delayed calls to ShutdownHost(). 491 base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_; 492 493 // selected text on the renderer. 494 std::string selected_text_; 495 496 // The window used for popup widgets. 497 base::scoped_nsobject<NSWindow> popup_window_; 498 499 // The fullscreen window used for pepper flash. 500 base::scoped_nsobject<NSWindow> pepper_fullscreen_window_; 501 base::scoped_nsobject<FullscreenWindowManager> fullscreen_window_manager_; 502 // Our parent host view, if this is fullscreen. NULL otherwise. 503 RenderWidgetHostViewMac* fullscreen_parent_host_view_; 504 505 // Display link for getting vsync info. 506 scoped_refptr<DisplayLinkMac> display_link_; 507 508 // The current VSync timebase and interval. This is zero until the first call 509 // to SendVSyncParametersToRenderer(), and refreshed regularly thereafter. 510 base::TimeTicks vsync_timebase_; 511 base::TimeDelta vsync_interval_; 512 513 // The current composition character range and its bounds. 514 gfx::Range composition_range_; 515 std::vector<gfx::Rect> composition_bounds_; 516 517 // The current caret bounds. 518 gfx::Rect caret_rect_; 519 520 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMac); 521 }; 522 523 } // namespace content 524 525 #endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_ 526