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
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_
6#define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_
7#pragma once
8
9#import <Cocoa/Cocoa.h>
10
11#include "base/memory/scoped_nsobject.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/task.h"
14#include "base/time.h"
15#include "chrome/browser/accessibility/browser_accessibility_delegate_mac.h"
16#include "chrome/browser/accessibility/browser_accessibility_manager.h"
17#include "chrome/browser/ui/cocoa/base_view.h"
18#include "content/browser/renderer_host/accelerated_surface_container_manager_mac.h"
19#include "content/browser/renderer_host/render_widget_host_view.h"
20#include "content/common/edit_command.h"
21#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
22#include "webkit/glue/webcursor.h"
23
24@class AcceleratedPluginView;
25class RenderWidgetHostViewMac;
26class RWHVMEditCommandHelper;
27@class ToolTip;
28
29@protocol RenderWidgetHostViewMacOwner
30- (RenderWidgetHostViewMac*)renderWidgetHostViewMac;
31@end
32
33// This is the view that lives in the Cocoa view hierarchy. In Windows-land,
34// RenderWidgetHostViewWin is both the view and the delegate. We split the roles
35// but that means that the view needs to own the delegate and will dispose of it
36// when it's removed from the view system.
37// See http://crbug.com/47890 for why we don't use NSTextInputClient yet.
38@interface RenderWidgetHostViewCocoa
39    : BaseView <RenderWidgetHostViewMacOwner,
40                NSTextInput,
41                NSChangeSpelling,
42                BrowserAccessibilityDelegateCocoa> {
43 @private
44  scoped_ptr<RenderWidgetHostViewMac> renderWidgetHostView_;
45  BOOL canBeKeyView_;
46  BOOL takesFocusOnlyOnMouseDown_;
47  BOOL closeOnDeactivate_;
48  scoped_ptr<RWHVMEditCommandHelper> editCommand_helper_;
49
50  // These are part of the magic tooltip code from WebKit's WebHTMLView:
51  id trackingRectOwner_;              // (not retained)
52  void *trackingRectUserData_;
53  NSTrackingRectTag lastToolTipTag_;
54  scoped_nsobject<NSString> toolTip_;
55
56  // Is YES if there was a mouse-down as yet unbalanced with a mouse-up.
57  BOOL hasOpenMouseDown_;
58
59  NSWindow* lastWindow_;  // weak
60
61  // Variables used by our implementaion of the NSTextInput protocol.
62  // An input method of Mac calls the methods of this protocol not only to
63  // notify an application of its status, but also to retrieve the status of
64  // the application. That is, an application cannot control an input method
65  // directly.
66  // This object keeps the status of a composition of the renderer and returns
67  // it when an input method asks for it.
68  // We need to implement Objective-C methods for the NSTextInput protocol. On
69  // the other hand, we need to implement a C++ method for an IPC-message
70  // handler which receives input-method events from the renderer.
71
72  // Represents the input-method attributes supported by this object.
73  scoped_nsobject<NSArray> validAttributesForMarkedText_;
74
75  // Represents the cursor position in this view coordinate.
76  // The renderer sends the cursor position through an IPC message.
77  // We save the latest cursor position here and return it when an input
78  // methods needs it.
79  NSRect caretRect_;
80
81  // Indicates if we are currently handling a key down event.
82  BOOL handlingKeyDown_;
83
84  // Indicates if there is any marked text.
85  BOOL hasMarkedText_;
86
87  // Indicates if unmarkText is called or not when handling a keyboard
88  // event.
89  BOOL unmarkTextCalled_;
90
91  // The range of current marked text inside the whole content of the DOM node
92  // being edited.
93  // TODO(suzhe): This is currently a fake value, as we do not support accessing
94  // the whole content yet.
95  NSRange markedRange_;
96
97  // The selected range inside current marked text.
98  // TODO(suzhe): Currently it's only valid when there is any marked text.
99  // In the future, we may need to support accessing the whole content of the
100  // DOM node being edited, then this should be the selected range inside the
101  // DOM node.
102  NSRange selectedRange_;
103
104  // Text to be inserted which was generated by handling a key down event.
105  string16 textToBeInserted_;
106
107  // Marked text which was generated by handling a key down event.
108  string16 markedText_;
109
110  // Underline information of the |markedText_|.
111  std::vector<WebKit::WebCompositionUnderline> underlines_;
112
113  // Indicates if doCommandBySelector method receives any edit command when
114  // handling a key down event.
115  BOOL hasEditCommands_;
116
117  // Contains edit commands received by the -doCommandBySelector: method when
118  // handling a key down event, not including inserting commands, eg. insertTab,
119  // etc.
120  EditCommands editCommands_;
121
122  // The plugin that currently has focus (-1 if no plugin has focus).
123  int focusedPluginIdentifier_;
124
125  // Whether or not plugin IME is currently enabled active.
126  BOOL pluginImeActive_;
127
128  // Whether the previous mouse event was ignored due to hitTest check.
129  BOOL mouseEventWasIgnored_;
130}
131
132@property(assign, nonatomic) NSRect caretRect;
133
134- (void)setCanBeKeyView:(BOOL)can;
135- (void)setTakesFocusOnlyOnMouseDown:(BOOL)b;
136- (void)setCloseOnDeactivate:(BOOL)b;
137- (void)setToolTipAtMousePoint:(NSString *)string;
138// Set frame, then notify the RenderWidgetHost that the frame has been changed,
139// but do it in a separate task, using |performSelector:withObject:afterDelay:|.
140// This stops the flickering issue in http://crbug.com/31970
141- (void)setFrameWithDeferredUpdate:(NSRect)frame;
142// Notify the RenderWidgetHost that the frame was updated so it can resize
143// its contents.
144- (void)renderWidgetHostWasResized;
145// Cancel ongoing composition (abandon the marked text).
146- (void)cancelComposition;
147// Confirm ongoing composition.
148- (void)confirmComposition;
149// Enables or disables plugin IME.
150- (void)setPluginImeActive:(BOOL)active;
151// Updates the current plugin focus state.
152- (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId;
153// Evaluates the event in the context of plugin IME, if plugin IME is enabled.
154// Returns YES if the event was handled.
155- (BOOL)postProcessEventForPluginIme:(NSEvent*)event;
156
157@end
158
159///////////////////////////////////////////////////////////////////////////////
160// RenderWidgetHostViewMac
161//
162//  An object representing the "View" of a rendered web page. This object is
163//  responsible for displaying the content of the web page, and integrating with
164//  the Cocoa view system. It is the implementation of the RenderWidgetHostView
165//  that the cross-platform RenderWidgetHost object uses
166//  to display the data.
167//
168//  Comment excerpted from render_widget_host.h:
169//
170//    "The lifetime of the RenderWidgetHost* is tied to the render process.
171//     If the render process dies, the RenderWidgetHost* goes away and all
172//     references to it must become NULL."
173//
174class RenderWidgetHostViewMac : public RenderWidgetHostView {
175 public:
176  // The view will associate itself with the given widget. The native view must
177  // be hooked up immediately to the view hierarchy, or else when it is
178  // deleted it will delete this out from under the caller.
179  explicit RenderWidgetHostViewMac(RenderWidgetHost* widget);
180  virtual ~RenderWidgetHostViewMac();
181
182  RenderWidgetHostViewCocoa* native_view() const { return cocoa_view_; }
183
184  // Implementation of RenderWidgetHostView:
185  virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
186                           const gfx::Rect& pos);
187  virtual void InitAsFullscreen();
188  virtual RenderWidgetHost* GetRenderWidgetHost() const;
189  virtual void DidBecomeSelected();
190  virtual void WasHidden();
191  virtual void SetSize(const gfx::Size& size);
192  virtual void SetBounds(const gfx::Rect& rect);
193  virtual gfx::NativeView GetNativeView();
194  virtual void MovePluginWindows(
195      const std::vector<webkit::npapi::WebPluginGeometry>& moves);
196  virtual void Focus();
197  virtual void Blur();
198  virtual bool HasFocus();
199  virtual void Show();
200  virtual void Hide();
201  virtual bool IsShowing();
202  virtual gfx::Rect GetViewBounds() const;
203  virtual void UpdateCursor(const WebCursor& cursor);
204  virtual void SetIsLoading(bool is_loading);
205  virtual void ImeUpdateTextInputState(WebKit::WebTextInputType state,
206                                       const gfx::Rect& caret_rect);
207  virtual void ImeCancelComposition();
208  virtual void DidUpdateBackingStore(
209      const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
210      const std::vector<gfx::Rect>& copy_rects);
211  virtual void RenderViewGone(base::TerminationStatus status,
212                              int error_code);
213  virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {};
214  virtual void Destroy();
215  virtual void SetTooltipText(const std::wstring& tooltip_text);
216  virtual void SelectionChanged(const std::string& text);
217  virtual BackingStore* AllocBackingStore(const gfx::Size& size);
218  virtual void SetTakesFocusOnlyOnMouseDown(bool flag);
219  // See comment in RenderWidgetHostView!
220  virtual gfx::Rect GetViewCocoaBounds() const;
221  virtual gfx::Rect GetRootWindowRect();
222  virtual void SetActive(bool active);
223  virtual void SetWindowVisibility(bool visible);
224  virtual void WindowFrameChanged();
225  virtual void SetBackground(const SkBitmap& background);
226  virtual bool ContainsNativeView(gfx::NativeView native_view) const;
227
228  virtual void OnAccessibilityNotifications(
229      const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params);
230
231  virtual void PluginFocusChanged(bool focused, int plugin_id);
232  virtual void StartPluginIme();
233  virtual bool PostProcessEventForPluginIme(
234      const NativeWebKeyboardEvent& event);
235
236  // Methods associated with GPU-accelerated plug-in instances and the
237  // accelerated compositor.
238  virtual gfx::PluginWindowHandle AllocateFakePluginWindowHandle(bool opaque,
239                                                                 bool root);
240  virtual void DestroyFakePluginWindowHandle(gfx::PluginWindowHandle window);
241
242  // Exposed for testing.
243  AcceleratedPluginView* ViewForPluginWindowHandle(
244      gfx::PluginWindowHandle window);
245
246  // Helper to do the actual cleanup after a plugin handle has been destroyed.
247  // Required because DestroyFakePluginWindowHandle() isn't always called for
248  // all handles (it's e.g. not called on navigation, when the RWHVMac gets
249  // destroyed anyway).
250  void DeallocFakePluginWindowHandle(gfx::PluginWindowHandle window);
251
252  virtual void AcceleratedSurfaceSetIOSurface(gfx::PluginWindowHandle window,
253                                              int32 width,
254                                              int32 height,
255                                              uint64 io_surface_identifier);
256  virtual void AcceleratedSurfaceSetTransportDIB(
257      gfx::PluginWindowHandle window,
258      int32 width,
259      int32 height,
260      TransportDIB::Handle transport_dib);
261  virtual void AcceleratedSurfaceBuffersSwapped(
262      gfx::PluginWindowHandle window,
263      uint64 surface_id,
264      int renderer_id,
265      int32 route_id,
266      int gpu_host_id,
267      uint64 swap_buffers_count);
268  virtual void GpuRenderingStateDidChange();
269
270  virtual gfx::PluginWindowHandle GetCompositingSurface();
271
272  void DrawAcceleratedSurfaceInstance(
273      CGLContextObj context,
274      gfx::PluginWindowHandle plugin_handle,
275      NSSize size);
276  // Forces the textures associated with any accelerated plugin instances
277  // to be reloaded.
278  void ForceTextureReload();
279
280  virtual void SetVisuallyDeemphasized(const SkColor* color, bool animate);
281
282  void KillSelf();
283
284  void SetTextInputActive(bool active);
285
286  // Sends completed plugin IME notification and text back to the renderer.
287  void PluginImeCompositionCompleted(const string16& text, int plugin_id);
288
289  const std::string& selected_text() const { return selected_text_; }
290
291  void UpdateRootGpuViewVisibility(bool show_gpu_widget);
292
293  // When rendering transitions from gpu to software, the gpu widget can't be
294  // hidden until the software backing store has been updated. This method
295  // checks if the GPU view needs to be hidden and hides it if necessary. It
296  // should be called after the software backing store has been painted to.
297  void HandleDelayedGpuViewHiding();
298
299  // This is called from the display link thread, and provides the GPU
300  // process a notion of how quickly the browser is able to keep up with it.
301  void AcknowledgeSwapBuffers(int renderer_id,
302                              int32 route_id,
303                              int gpu_host_id,
304                              uint64 swap_buffers_count);
305
306  // These member variables should be private, but the associated ObjC class
307  // needs access to them and can't be made a friend.
308
309  // The associated Model.  Can be NULL if Destroy() is called when
310  // someone (other than superview) has retained |cocoa_view_|.
311  RenderWidgetHost* render_widget_host_;
312
313  // This is true when we are currently painting and thus should handle extra
314  // paint requests by expanding the invalid rect rather than actually painting.
315  bool about_to_validate_and_paint_;
316
317  scoped_ptr<BrowserAccessibilityManager> browser_accessibility_manager_;
318
319  // This is true when we have already scheduled a call to
320  // |-callSetNeedsDisplayInRect:| but it has not been fulfilled yet.  Used to
321  // prevent us from scheduling multiple calls.
322  bool call_set_needs_display_in_rect_pending_;
323
324  // The invalid rect that needs to be painted by callSetNeedsDisplayInRect.
325  // This value is only meaningful when
326  // |call_set_needs_display_in_rect_pending_| is true.
327  NSRect invalid_rect_;
328
329  // The time at which this view started displaying white pixels as a result of
330  // not having anything to paint (empty backing store from renderer). This
331  // value returns true for is_null() if we are not recording whiteout times.
332  base::TimeTicks whiteout_start_time_;
333
334  // The time it took after this view was selected for it to be fully painted.
335  base::TimeTicks tab_switch_paint_time_;
336
337  // Current text input type.
338  WebKit::WebTextInputType text_input_type_;
339
340  typedef std::map<gfx::PluginWindowHandle, AcceleratedPluginView*>
341      PluginViewMap;
342  PluginViewMap plugin_views_;  // Weak values.
343
344  // Helper class for managing instances of accelerated plug-ins.
345  AcceleratedSurfaceContainerManagerMac plugin_container_manager_;
346
347 private:
348  // Returns whether this render view is a popup (autocomplete window).
349  bool IsPopup() const;
350
351  // Updates the display cursor to the current cursor if the cursor is over this
352  // render view.
353  void UpdateCursorIfOverSelf();
354
355  // Shuts down the render_widget_host_.  This is a separate function so we can
356  // invoke it from the message loop.
357  void ShutdownHost();
358
359  // Used to determine whether or not to enable accessibility.
360  bool IsVoiceOverRunning();
361
362  // The associated view. This is weak and is inserted into the view hierarchy
363  // to own this RenderWidgetHostViewMac object.
364  RenderWidgetHostViewCocoa* cocoa_view_;
365
366  // The cursor for the page. This is passed up from the renderer.
367  WebCursor current_cursor_;
368
369  // Indicates if the page is loading.
370  bool is_loading_;
371
372  // true if the View is not visible.
373  bool is_hidden_;
374
375  // The text to be shown in the tooltip, supplied by the renderer.
376  std::wstring tooltip_text_;
377
378  // Factory used to safely scope delayed calls to ShutdownHost().
379  ScopedRunnableMethodFactory<RenderWidgetHostViewMac> shutdown_factory_;
380
381  // selected text on the renderer.
382  std::string selected_text_;
383
384  // When rendering transitions from gpu to software, the gpu widget can't be
385  // hidden until the software backing store has been updated. This variable is
386  // set when the gpu widget needs to be hidden once a paint is completed.
387  bool needs_gpu_visibility_update_after_repaint_;
388
389  gfx::PluginWindowHandle compositing_surface_;
390
391  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMac);
392};
393
394#endif  // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_MAC_H_
395