| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_ |
| #define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_ |
| #pragma once |
| |
| #import <Cocoa/Cocoa.h> |
| #include <list> |
| |
| #include "base/memory/scoped_nsobject.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time.h" |
| #include "content/browser/accessibility/browser_accessibility_delegate_mac.h" |
| #include "content/browser/renderer_host/accelerated_surface_container_manager_mac.h" |
| #include "content/browser/renderer_host/render_widget_host_view_base.h" |
| #include "content/common/edit_command.h" |
| #import "content/public/browser/render_widget_host_view_mac_base.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h" |
| #include "ui/base/cocoa/base_view.h" |
| #include "webkit/glue/webcursor.h" |
| |
| @class AcceleratedPluginView; |
| class CompositingIOSurfaceMac; |
| @class FullscreenWindowManager; |
| class RenderWidgetHostViewMac; |
| @protocol RenderWidgetHostViewMacDelegate; |
| class RenderWidgetHostViewMacEditCommandHelper; |
| @class ToolTip; |
| |
| namespace content { |
| class RenderWidgetHostImpl; |
| } |
| |
| @protocol RenderWidgetHostViewMacOwner |
| - (RenderWidgetHostViewMac*)renderWidgetHostViewMac; |
| @end |
| |
| // This is the view that lives in the Cocoa view hierarchy. In Windows-land, |
| // RenderWidgetHostViewWin is both the view and the delegate. We split the roles |
| // but that means that the view needs to own the delegate and will dispose of it |
| // when it's removed from the view system. |
| @interface RenderWidgetHostViewCocoa |
| : BaseView <RenderWidgetHostViewMacBase, |
| RenderWidgetHostViewMacOwner, |
| NSTextInputClient, |
| BrowserAccessibilityDelegateCocoa> { |
| @private |
| scoped_ptr<RenderWidgetHostViewMac> renderWidgetHostView_; |
| NSObject<RenderWidgetHostViewMacDelegate>* delegate_; // weak |
| BOOL canBeKeyView_; |
| BOOL takesFocusOnlyOnMouseDown_; |
| BOOL closeOnDeactivate_; |
| scoped_ptr<RenderWidgetHostViewMacEditCommandHelper> editCommand_helper_; |
| |
| // These are part of the magic tooltip code from WebKit's WebHTMLView: |
| id trackingRectOwner_; // (not retained) |
| void *trackingRectUserData_; |
| NSTrackingRectTag lastToolTipTag_; |
| scoped_nsobject<NSString> toolTip_; |
| |
| // Is YES if there was a mouse-down as yet unbalanced with a mouse-up. |
| BOOL hasOpenMouseDown_; |
| |
| NSWindow* lastWindow_; // weak |
| |
| // Variables used by our implementaion of the NSTextInput protocol. |
| // An input method of Mac calls the methods of this protocol not only to |
| // notify an application of its status, but also to retrieve the status of |
| // the application. That is, an application cannot control an input method |
| // directly. |
| // This object keeps the status of a composition of the renderer and returns |
| // it when an input method asks for it. |
| // We need to implement Objective-C methods for the NSTextInput protocol. On |
| // the other hand, we need to implement a C++ method for an IPC-message |
| // handler which receives input-method events from the renderer. |
| |
| // Represents the input-method attributes supported by this object. |
| scoped_nsobject<NSArray> validAttributesForMarkedText_; |
| |
| // Indicates if we are currently handling a key down event. |
| BOOL handlingKeyDown_; |
| |
| // Indicates if there is any marked text. |
| BOOL hasMarkedText_; |
| |
| // Indicates if unmarkText is called or not when handling a keyboard |
| // event. |
| BOOL unmarkTextCalled_; |
| |
| // The range of current marked text inside the whole content of the DOM node |
| // being edited. |
| // TODO(suzhe): This is currently a fake value, as we do not support accessing |
| // the whole content yet. |
| NSRange markedRange_; |
| |
| // The selected range, cached from a message sent by the renderer. |
| NSRange selectedRange_; |
| |
| // Text to be inserted which was generated by handling a key down event. |
| string16 textToBeInserted_; |
| |
| // Marked text which was generated by handling a key down event. |
| string16 markedText_; |
| |
| // Underline information of the |markedText_|. |
| std::vector<WebKit::WebCompositionUnderline> underlines_; |
| |
| // Indicates if doCommandBySelector method receives any edit command when |
| // handling a key down event. |
| BOOL hasEditCommands_; |
| |
| // Contains edit commands received by the -doCommandBySelector: method when |
| // handling a key down event, not including inserting commands, eg. insertTab, |
| // etc. |
| EditCommands editCommands_; |
| |
| // The plugin that currently has focus (-1 if no plugin has focus). |
| int focusedPluginIdentifier_; |
| |
| // Whether or not plugin IME is currently enabled active. |
| BOOL pluginImeActive_; |
| |
| // Whether the previous mouse event was ignored due to hitTest check. |
| BOOL mouseEventWasIgnored_; |
| |
| // Event monitor for gesture-end events. |
| id endGestureMonitor_; |
| |
| // OpenGL Support: |
| |
| // recursive globalFrameDidChange protection: |
| BOOL handlingGlobalFrameDidChange_; |
| } |
| |
| @property(nonatomic, readonly) NSRange selectedRange; |
| |
| - (void)setCanBeKeyView:(BOOL)can; |
| - (void)setTakesFocusOnlyOnMouseDown:(BOOL)b; |
| - (void)setCloseOnDeactivate:(BOOL)b; |
| - (void)setToolTipAtMousePoint:(NSString *)string; |
| // True for always-on-top special windows (e.g. Balloons and Panels). |
| - (BOOL)acceptsMouseEventsWhenInactive; |
| // Cancel ongoing composition (abandon the marked text). |
| - (void)cancelComposition; |
| // Confirm ongoing composition. |
| - (void)confirmComposition; |
| // Enables or disables plugin IME. |
| - (void)setPluginImeActive:(BOOL)active; |
| // Updates the current plugin focus state. |
| - (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId; |
| // Evaluates the event in the context of plugin IME, if plugin IME is enabled. |
| // Returns YES if the event was handled. |
| - (BOOL)postProcessEventForPluginIme:(NSEvent*)event; |
| |
| @end |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // RenderWidgetHostViewMac |
| // |
| // An object representing the "View" of a rendered web page. This object is |
| // responsible for displaying the content of the web page, and integrating with |
| // the Cocoa view system. It is the implementation of the RenderWidgetHostView |
| // that the cross-platform RenderWidgetHost object uses |
| // to display the data. |
| // |
| // Comment excerpted from render_widget_host.h: |
| // |
| // "The lifetime of the RenderWidgetHost* is tied to the render process. |
| // If the render process dies, the RenderWidgetHost* goes away and all |
| // references to it must become NULL." |
| // |
| // RenderWidgetHostView class hierarchy described in render_widget_host_view.h. |
| class RenderWidgetHostViewMac : public content::RenderWidgetHostViewBase { |
| public: |
| virtual ~RenderWidgetHostViewMac(); |
| |
| RenderWidgetHostViewCocoa* cocoa_view() const { return cocoa_view_; } |
| |
| void SetDelegate(NSObject<RenderWidgetHostViewMacDelegate>* delegate); |
| |
| // RenderWidgetHostView implementation. |
| virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE; |
| virtual content::RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE; |
| virtual void SetSize(const gfx::Size& size) OVERRIDE; |
| virtual void SetBounds(const gfx::Rect& rect) OVERRIDE; |
| virtual gfx::NativeView GetNativeView() const OVERRIDE; |
| virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE; |
| virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE; |
| virtual bool HasFocus() const OVERRIDE; |
| virtual void Show() OVERRIDE; |
| virtual void Hide() OVERRIDE; |
| virtual bool IsShowing() OVERRIDE; |
| virtual gfx::Rect GetViewBounds() const OVERRIDE; |
| virtual void SetShowingContextMenu(bool showing) OVERRIDE; |
| virtual void SetActive(bool active) OVERRIDE; |
| virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE; |
| virtual void SetWindowVisibility(bool visible) OVERRIDE; |
| virtual void WindowFrameChanged() OVERRIDE; |
| virtual void SetBackground(const SkBitmap& background) OVERRIDE; |
| |
| // Implementation of RenderWidgetHostViewPort. |
| virtual void InitAsPopup(content::RenderWidgetHostView* parent_host_view, |
| const gfx::Rect& pos) OVERRIDE; |
| virtual void InitAsFullscreen( |
| content::RenderWidgetHostView* reference_host_view) OVERRIDE; |
| virtual void DidBecomeSelected() OVERRIDE; |
| virtual void WasHidden() OVERRIDE; |
| virtual void MovePluginWindows( |
| const std::vector<webkit::npapi::WebPluginGeometry>& moves) OVERRIDE; |
| virtual void Focus() OVERRIDE; |
| virtual void Blur() OVERRIDE; |
| virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE; |
| virtual void SetIsLoading(bool is_loading) OVERRIDE; |
| virtual void TextInputStateChanged(ui::TextInputType state, |
| bool can_compose_inline) OVERRIDE; |
| virtual void SelectionBoundsChanged(const gfx::Rect& start_rect, |
| const gfx::Rect& end_rect) OVERRIDE; |
| virtual void ImeCancelComposition() OVERRIDE; |
| virtual void ImeCompositionRangeChanged(const ui::Range& range) OVERRIDE; |
| virtual void DidUpdateBackingStore( |
| const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, |
| const std::vector<gfx::Rect>& copy_rects) OVERRIDE; |
| virtual void RenderViewGone(base::TerminationStatus status, |
| int error_code) OVERRIDE; |
| virtual void Destroy() OVERRIDE; |
| virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE; |
| virtual void SelectionChanged(const string16& text, |
| size_t offset, |
| const ui::Range& range) OVERRIDE; |
| virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE; |
| virtual bool CopyFromCompositingSurface( |
| const gfx::Size& size, |
| skia::PlatformCanvas* output) OVERRIDE; |
| virtual void AsyncCopyFromCompositingSurface( |
| const gfx::Size& size, |
| skia::PlatformCanvas* output, |
| base::Callback<void(bool)> callback) OVERRIDE; |
| virtual void OnAcceleratedCompositingStateChange() OVERRIDE; |
| // See comment in RenderWidgetHostView! |
| virtual gfx::Rect GetViewCocoaBounds() const OVERRIDE; |
| |
| virtual void OnAccessibilityNotifications( |
| const std::vector<AccessibilityHostMsg_NotificationParams>& params |
| ) OVERRIDE; |
| |
| virtual void PluginFocusChanged(bool focused, int plugin_id) OVERRIDE; |
| virtual void StartPluginIme() OVERRIDE; |
| virtual bool PostProcessEventForPluginIme( |
| const NativeWebKeyboardEvent& event) OVERRIDE; |
| |
| // Methods associated with GPU-accelerated plug-in instances and the |
| // accelerated compositor. |
| virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle( |
| bool opaque, bool root) OVERRIDE; |
| virtual void DestroyFakePluginWindowHandle( |
| gfx::PluginWindowHandle window) OVERRIDE; |
| |
| // Exposed for testing. |
| CONTENT_EXPORT AcceleratedPluginView* ViewForPluginWindowHandle( |
| gfx::PluginWindowHandle window); |
| |
| // Helper to do the actual cleanup after a plugin handle has been destroyed. |
| // Required because DestroyFakePluginWindowHandle() isn't always called for |
| // all handles (it's e.g. not called on navigation, when the RWHVMac gets |
| // destroyed anyway). |
| void DeallocFakePluginWindowHandle(gfx::PluginWindowHandle window); |
| |
| virtual void AcceleratedSurfaceSetIOSurface( |
| gfx::PluginWindowHandle window, |
| int32 width, |
| int32 height, |
| uint64 io_surface_identifier) OVERRIDE; |
| virtual void AcceleratedSurfaceSetTransportDIB( |
| gfx::PluginWindowHandle window, |
| int32 width, |
| int32 height, |
| TransportDIB::Handle transport_dib) OVERRIDE; |
| virtual void AcceleratedSurfaceBuffersSwapped( |
| const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, |
| int gpu_host_id) OVERRIDE; |
| virtual void AcceleratedSurfacePostSubBuffer( |
| const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, |
| int gpu_host_id) OVERRIDE; |
| virtual void AcceleratedSurfaceSuspend() OVERRIDE; |
| virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE; |
| virtual gfx::Rect GetRootWindowBounds() OVERRIDE; |
| virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE; |
| |
| void DrawAcceleratedSurfaceInstance( |
| CGLContextObj context, |
| gfx::PluginWindowHandle plugin_handle, |
| NSSize size); |
| // Forces the textures associated with any accelerated plugin instances |
| // to be reloaded. |
| void ForceTextureReload(); |
| |
| virtual void ProcessTouchAck(WebKit::WebInputEvent::Type type, |
| bool processed) OVERRIDE; |
| virtual void SetHasHorizontalScrollbar( |
| bool has_horizontal_scrollbar) OVERRIDE; |
| virtual void SetScrollOffsetPinning( |
| bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE; |
| virtual bool LockMouse() OVERRIDE; |
| virtual void UnlockMouse() OVERRIDE; |
| virtual void UnhandledWheelEvent( |
| const WebKit::WebMouseWheelEvent& event) OVERRIDE; |
| |
| // Forwards the mouse event to the renderer. |
| void ForwardMouseEvent(const WebKit::WebMouseEvent& event); |
| |
| void KillSelf(); |
| |
| void SetTextInputActive(bool active); |
| |
| // Sends completed plugin IME notification and text back to the renderer. |
| void PluginImeCompositionCompleted(const string16& text, int plugin_id); |
| |
| const std::string& selected_text() const { return selected_text_; } |
| |
| // Call setNeedsDisplay on the cocoa_view_. The IOSurface will be drawn during |
| // the next drawRect. The route_id and gpu_host_id are added to a list to be |
| // acked when the SwapBuffers occurs in drawRect. |
| void CompositorSwapBuffers(uint64 surface_handle, |
| int32 route_id, |
| int32 gpu_host_id); |
| // Ack pending SwapBuffers requests (queued up by CompositorSwapBuffers), if |
| // any, to unblock the GPU process. Has no effect if there are no pending |
| // requests. |
| void AckPendingCompositorSwapBuffers(); |
| |
| // These member variables should be private, but the associated ObjC class |
| // needs access to them and can't be made a friend. |
| |
| // The associated Model. Can be NULL if Destroy() is called when |
| // someone (other than superview) has retained |cocoa_view_|. |
| content::RenderWidgetHostImpl* render_widget_host_; |
| |
| // This is true when we are currently painting and thus should handle extra |
| // paint requests by expanding the invalid rect rather than actually painting. |
| bool about_to_validate_and_paint_; |
| |
| // This is true when we have already scheduled a call to |
| // |-callSetNeedsDisplayInRect:| but it has not been fulfilled yet. Used to |
| // prevent us from scheduling multiple calls. |
| bool call_set_needs_display_in_rect_pending_; |
| |
| // Whether last rendered frame was accelerated. |
| bool last_frame_was_accelerated_; |
| |
| // The invalid rect that needs to be painted by callSetNeedsDisplayInRect. |
| // This value is only meaningful when |
| // |call_set_needs_display_in_rect_pending_| is true. |
| NSRect invalid_rect_; |
| |
| // The time at which this view started displaying white pixels as a result of |
| // not having anything to paint (empty backing store from renderer). This |
| // value returns true for is_null() if we are not recording whiteout times. |
| base::TimeTicks whiteout_start_time_; |
| |
| // The time it took after this view was selected for it to be fully painted. |
| base::TimeTicks web_contents_switch_paint_time_; |
| |
| // Current text input type. |
| ui::TextInputType text_input_type_; |
| bool can_compose_inline_; |
| |
| typedef std::map<gfx::PluginWindowHandle, AcceleratedPluginView*> |
| PluginViewMap; |
| PluginViewMap plugin_views_; // Weak values. |
| |
| // Helper class for managing instances of accelerated plug-ins. |
| AcceleratedSurfaceContainerManagerMac plugin_container_manager_; |
| |
| scoped_ptr<CompositingIOSurfaceMac> compositing_iosurface_; |
| |
| NSWindow* pepper_fullscreen_window() const { |
| return pepper_fullscreen_window_; |
| } |
| |
| private: |
| friend class content::RenderWidgetHostView; |
| |
| // The view will associate itself with the given widget. The native view must |
| // be hooked up immediately to the view hierarchy, or else when it is |
| // deleted it will delete this out from under the caller. |
| explicit RenderWidgetHostViewMac(content::RenderWidgetHost* widget); |
| |
| // Returns whether this render view is a popup (autocomplete window). |
| bool IsPopup() const; |
| |
| // Updates the display cursor if the current event is over the view's window. |
| void UpdateCursorIfNecessary(); |
| |
| // Shuts down the render_widget_host_. This is a separate function so we can |
| // invoke it from the message loop. |
| void ShutdownHost(); |
| |
| // The associated view. This is weak and is inserted into the view hierarchy |
| // to own this RenderWidgetHostViewMac object. |
| RenderWidgetHostViewCocoa* cocoa_view_; |
| |
| // The cursor for the page. This is passed up from the renderer. |
| WebCursor current_cursor_; |
| |
| // Indicates if the page is loading. |
| bool is_loading_; |
| |
| // true if the View is not visible. |
| bool is_hidden_; |
| |
| // The text to be shown in the tooltip, supplied by the renderer. |
| string16 tooltip_text_; |
| |
| // Factory used to safely scope delayed calls to ShutdownHost(). |
| base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_; |
| |
| // selected text on the renderer. |
| std::string selected_text_; |
| |
| gfx::PluginWindowHandle compositing_surface_; |
| |
| // List of pending swaps for deferred acking: |
| // pairs of (route_id, gpu_host_id). |
| std::list<std::pair<int32, int32> > pending_swap_buffers_acks_; |
| |
| // The fullscreen window used for pepper flash. |
| scoped_nsobject<NSWindow> pepper_fullscreen_window_; |
| scoped_nsobject<FullscreenWindowManager> fullscreen_window_manager_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMac); |
| }; |
| |
| #endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_ |