Index: content/child/npapi/webplugin_delegate_impl_mac.mm |
diff --git a/content/child/npapi/webplugin_delegate_impl_mac.mm b/content/child/npapi/webplugin_delegate_impl_mac.mm |
deleted file mode 100644 |
index d17a48e9aeb5e4597a3b95251d26ea5145e894ff..0000000000000000000000000000000000000000 |
--- a/content/child/npapi/webplugin_delegate_impl_mac.mm |
+++ /dev/null |
@@ -1,696 +0,0 @@ |
-// 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. |
- |
-#include "content/child/npapi/webplugin_delegate_impl.h" |
- |
-#import <Cocoa/Cocoa.h> |
-#import <QuartzCore/QuartzCore.h> |
-#include <stdint.h> |
-#include <string.h> |
-#include <unistd.h> |
- |
-#include <set> |
-#include <string> |
- |
-#include "base/macros.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/sys_string_conversions.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "content/child/npapi/plugin_instance.h" |
-#include "content/child/npapi/plugin_lib.h" |
-#include "content/child/npapi/plugin_web_event_converter_mac.h" |
-#include "content/child/npapi/webplugin.h" |
-#include "content/child/npapi/webplugin_accelerated_surface_mac.h" |
-#include "content/common/cursors/webcursor.h" |
-#include "skia/ext/skia_utils_mac.h" |
-#include "third_party/WebKit/public/web/WebInputEvent.h" |
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
- |
-using blink::WebKeyboardEvent; |
-using blink::WebInputEvent; |
-using blink::WebMouseEvent; |
-using blink::WebMouseWheelEvent; |
- |
-// Important implementation notes: The Mac definition of NPAPI, particularly |
-// the distinction between windowed and windowless modes, differs from the |
-// Windows and Linux definitions. Most of those differences are |
-// accomodated by the WebPluginDelegate class. |
- |
-namespace content { |
- |
-namespace { |
- |
-const int kCoreAnimationRedrawPeriodMs = 10; // 100 Hz |
- |
-WebPluginDelegateImpl* g_active_delegate; |
- |
-// Helper to simplify correct usage of g_active_delegate. Instantiating will |
-// set the active delegate to |delegate| for the lifetime of the object, then |
-// NULL when it goes out of scope. |
-class ScopedActiveDelegate { |
- public: |
- explicit ScopedActiveDelegate(WebPluginDelegateImpl* delegate) { |
- g_active_delegate = delegate; |
- } |
- ~ScopedActiveDelegate() { |
- g_active_delegate = NULL; |
- } |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(ScopedActiveDelegate); |
-}; |
- |
-} // namespace |
- |
-// Helper to build and maintain a model of a drag entering the plugin but not |
-// starting there. See explanation in PlatformHandleInputEvent. |
-class ExternalDragTracker { |
- public: |
- ExternalDragTracker() : pressed_buttons_(0) {} |
- |
- // Returns true if an external drag is in progress. |
- bool IsDragInProgress() { return pressed_buttons_ != 0; }; |
- |
- // Returns true if the given event appears to be related to an external drag. |
- bool EventIsRelatedToDrag(const WebInputEvent& event); |
- |
- // Updates the tracking of whether an external drag is in progress--and if |
- // so what buttons it involves--based on the given event. |
- void UpdateDragStateFromEvent(const WebInputEvent& event); |
- |
- private: |
- // Returns the mask for just the button state in a WebInputEvent's modifiers. |
- static int WebEventButtonModifierMask(); |
- |
- // The WebInputEvent modifier flags for any buttons that were down when an |
- // external drag entered the plugin, and which and are still down now. |
- int pressed_buttons_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ExternalDragTracker); |
-}; |
- |
-void ExternalDragTracker::UpdateDragStateFromEvent(const WebInputEvent& event) { |
- switch (event.type) { |
- case WebInputEvent::MouseEnter: |
- pressed_buttons_ = event.modifiers & WebEventButtonModifierMask(); |
- break; |
- case WebInputEvent::MouseUp: { |
- const WebMouseEvent* mouse_event = |
- static_cast<const WebMouseEvent*>(&event); |
- if (mouse_event->button == WebMouseEvent::ButtonLeft) |
- pressed_buttons_ &= ~WebInputEvent::LeftButtonDown; |
- if (mouse_event->button == WebMouseEvent::ButtonMiddle) |
- pressed_buttons_ &= ~WebInputEvent::MiddleButtonDown; |
- if (mouse_event->button == WebMouseEvent::ButtonRight) |
- pressed_buttons_ &= ~WebInputEvent::RightButtonDown; |
- break; |
- } |
- default: |
- break; |
- } |
-} |
- |
-bool ExternalDragTracker::EventIsRelatedToDrag(const WebInputEvent& event) { |
- const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(&event); |
- switch (event.type) { |
- case WebInputEvent::MouseUp: |
- // We only care about release of buttons that were part of the drag. |
- return ((mouse_event->button == WebMouseEvent::ButtonLeft && |
- (pressed_buttons_ & WebInputEvent::LeftButtonDown)) || |
- (mouse_event->button == WebMouseEvent::ButtonMiddle && |
- (pressed_buttons_ & WebInputEvent::MiddleButtonDown)) || |
- (mouse_event->button == WebMouseEvent::ButtonRight && |
- (pressed_buttons_ & WebInputEvent::RightButtonDown))); |
- case WebInputEvent::MouseEnter: |
- return (event.modifiers & WebEventButtonModifierMask()) != 0; |
- case WebInputEvent::MouseLeave: |
- case WebInputEvent::MouseMove: { |
- int event_buttons = (event.modifiers & WebEventButtonModifierMask()); |
- return (pressed_buttons_ && |
- pressed_buttons_ == event_buttons); |
- } |
- default: |
- return false; |
- } |
- return false; |
-} |
- |
-int ExternalDragTracker::WebEventButtonModifierMask() { |
- return WebInputEvent::LeftButtonDown | |
- WebInputEvent::RightButtonDown | |
- WebInputEvent::MiddleButtonDown; |
-} |
- |
-#pragma mark - |
-#pragma mark Core WebPluginDelegate implementation |
- |
-WebPluginDelegateImpl::WebPluginDelegateImpl( |
- WebPlugin* plugin, |
- PluginInstance* instance) |
- : plugin_(plugin), |
- instance_(instance), |
- quirks_(0), |
- use_buffer_context_(true), |
- buffer_context_(NULL), |
- layer_(nil), |
- surface_(NULL), |
- renderer_(nil), |
- containing_window_has_focus_(false), |
- initial_window_focus_(false), |
- container_is_visible_(false), |
- have_called_set_window_(false), |
- ime_enabled_(false), |
- keyup_ignore_count_(0), |
- external_drag_tracker_(new ExternalDragTracker()), |
- handle_event_depth_(0), |
- first_set_window_call_(true), |
- plugin_has_focus_(false), |
- has_webkit_focus_(false), |
- containing_view_has_focus_(true), |
- creation_succeeded_(false) { |
- memset(&window_, 0, sizeof(window_)); |
-} |
- |
-WebPluginDelegateImpl::~WebPluginDelegateImpl() { |
- DestroyInstance(); |
-} |
- |
-bool WebPluginDelegateImpl::PlatformInitialize() { |
- // Don't set a NULL window handle on destroy for Mac plugins. This matches |
- // Safari and other Mac browsers (see PluginView::stop() in PluginView.cpp, |
- // where code to do so is surrounded by an #ifdef that excludes Mac OS X, or |
- // destroyPlugin in WebNetscapePluginView.mm, for examples). |
- quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; |
- |
- // Mac plugins don't expect to be unloaded, and they don't always do so |
- // cleanly, so don't unload them at shutdown. |
- instance()->plugin_lib()->PreventLibraryUnload(); |
- |
-#ifndef NP_NO_CARBON |
- if (instance()->event_model() == NPEventModelCarbon) |
- return false; |
-#endif |
- |
- window_.type = NPWindowTypeDrawable; |
- NPDrawingModel drawing_model = instance()->drawing_model(); |
- switch (drawing_model) { |
-#ifndef NP_NO_QUICKDRAW |
- case NPDrawingModelQuickDraw: |
- return false; |
-#endif |
- case NPDrawingModelCoreGraphics: |
- break; |
- case NPDrawingModelCoreAnimation: |
- case NPDrawingModelInvalidatingCoreAnimation: { |
- // Ask the plugin for the CALayer it created for rendering content. |
- // Create a surface to host it, and request a "window" handle to identify |
- // the surface. |
- CALayer* layer = nil; |
- NPError err = instance()->NPP_GetValue(NPPVpluginCoreAnimationLayer, |
- reinterpret_cast<void*>(&layer)); |
- if (!err) { |
- if (drawing_model == NPDrawingModelCoreAnimation) { |
- // Create the timer; it will be started when we get a window handle. |
- redraw_timer_.reset(new base::RepeatingTimer); |
- } |
- layer_ = layer; |
- |
- gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; |
- // On dual GPU systems, force the use of the discrete GPU for |
- // the CARenderer underlying our Core Animation backend for |
- // all plugins except Flash. For some reason Unity3D's output |
- // doesn't show up if the integrated GPU is used. Safari keeps |
- // even Flash 11 with Stage3D on the integrated GPU, so mirror |
- // that behavior here. |
- const WebPluginInfo& plugin_info = |
- instance_->plugin_lib()->plugin_info(); |
- if (plugin_info.name.find(base::ASCIIToUTF16("Flash")) != |
- base::string16::npos) |
- gpu_preference = gfx::PreferIntegratedGpu; |
- surface_ = plugin_->GetAcceleratedSurface(gpu_preference); |
- |
- // If surface initialization fails for some reason, just continue |
- // without any drawing; returning false would be a more confusing user |
- // experience (since it triggers a missing plugin placeholder). |
- if (surface_ && surface_->context()) { |
- renderer_ = [[CARenderer rendererWithCGLContext:surface_->context() |
- options:NULL] retain]; |
- [renderer_ setLayer:layer_]; |
- plugin_->AcceleratedPluginEnabledRendering(); |
- } |
- } |
- break; |
- } |
- default: |
- NOTREACHED(); |
- break; |
- } |
- |
- return true; |
-} |
- |
-void WebPluginDelegateImpl::PlatformDestroyInstance() { |
- if (redraw_timer_) |
- redraw_timer_->Stop(); |
- [renderer_ release]; |
- renderer_ = nil; |
- layer_ = nil; |
-} |
- |
-void WebPluginDelegateImpl::UpdateGeometryAndContext( |
- const gfx::Rect& window_rect, const gfx::Rect& clip_rect, |
- CGContextRef context) { |
- buffer_context_ = context; |
- UpdateGeometry(window_rect, clip_rect); |
-} |
- |
-void WebPluginDelegateImpl::Paint(SkCanvas* canvas, const gfx::Rect& rect) { |
- skia::SkiaBitLocker bit_locker(canvas); |
- CGContextRef context = bit_locker.cgContext(); |
- CGPaint(context, rect); |
-} |
- |
-void WebPluginDelegateImpl::CGPaint(CGContextRef context, |
- const gfx::Rect& rect) { |
- WindowlessPaint(context, rect); |
-} |
- |
-bool WebPluginDelegateImpl::PlatformHandleInputEvent( |
- const WebInputEvent& event, WebCursor::CursorInfo* cursor_info) { |
- DCHECK(cursor_info != NULL); |
- |
- // If an event comes in before the plugin has been set up, bail. |
- if (!have_called_set_window_) |
- return false; |
- |
- // WebKit sometimes sends spurious mouse move events when the window doesn't |
- // have focus; Cocoa event model plugins don't expect to receive mouse move |
- // events when they are in a background window, so drop those events. |
- if (!containing_window_has_focus_ && |
- (event.type == WebInputEvent::MouseMove || |
- event.type == WebInputEvent::MouseEnter || |
- event.type == WebInputEvent::MouseLeave)) { |
- return false; |
- } |
- |
- if (WebInputEvent::isMouseEventType(event.type) || |
- event.type == WebInputEvent::MouseWheel) { |
- // Check our plugin location before we send the event to the plugin, just |
- // in case we somehow missed a plugin frame change. |
- const WebMouseEvent* mouse_event = |
- static_cast<const WebMouseEvent*>(&event); |
- gfx::Point content_origin( |
- mouse_event->globalX - mouse_event->x - window_rect_.x(), |
- mouse_event->globalY - mouse_event->y - window_rect_.y()); |
- if (content_origin.x() != content_area_origin_.x() || |
- content_origin.y() != content_area_origin_.y()) { |
- DLOG(WARNING) << "Stale plugin content area location: " |
- << content_area_origin_.ToString() << " instead of " |
- << content_origin.ToString(); |
- SetContentAreaOrigin(content_origin); |
- } |
- |
- current_windowless_cursor_.GetCursorInfo(cursor_info); |
- } |
- |
- // Per the Cocoa Plugin IME spec, plugins shoudn't receive keydown or keyup |
- // events while composition is in progress. Treat them as handled, however, |
- // since IME is consuming them on behalf of the plugin. |
- if ((event.type == WebInputEvent::KeyDown && ime_enabled_) || |
- (event.type == WebInputEvent::KeyUp && keyup_ignore_count_)) { |
- // Composition ends on a keydown, so ime_enabled_ will be false at keyup; |
- // because the keydown wasn't sent to the plugin, the keyup shouldn't be |
- // either (per the spec). |
- if (event.type == WebInputEvent::KeyDown) |
- ++keyup_ignore_count_; |
- else |
- --keyup_ignore_count_; |
- return true; |
- } |
- |
- ScopedActiveDelegate active_delegate(this); |
- |
- // Create the plugin event structure. |
- scoped_ptr<PluginWebEventConverter> event_converter( |
- new PluginWebEventConverter); |
- if (!event_converter->InitWithEvent(event)) { |
- // Silently consume any keyboard event types that aren't handled, so that |
- // they don't fall through to the page. |
- if (WebInputEvent::isKeyboardEventType(event.type)) |
- return true; |
- return false; |
- } |
- NPCocoaEvent* plugin_event = event_converter->plugin_event(); |
- |
- // The plugin host receives events related to drags starting outside the |
- // plugin, but the NPAPI Cocoa event model spec says plugins shouldn't receive |
- // them, so filter them out. |
- // If WebKit adds a page capture mode (like the plugin capture mode that |
- // handles drags starting inside) this can be removed. |
- bool drag_related = external_drag_tracker_->EventIsRelatedToDrag(event); |
- external_drag_tracker_->UpdateDragStateFromEvent(event); |
- if (drag_related) { |
- if (event.type == WebInputEvent::MouseUp && |
- !external_drag_tracker_->IsDragInProgress()) { |
- // When an external drag ends, we need to synthesize a MouseEntered. |
- NPCocoaEvent enter_event = *plugin_event; |
- enter_event.type = NPCocoaEventMouseEntered; |
- ScopedCurrentPluginEvent event_scope(instance(), &enter_event); |
- instance()->NPP_HandleEvent(&enter_event); |
- } |
- return false; |
- } |
- |
- // Send the plugin the event. |
- scoped_ptr<ScopedCurrentPluginEvent> event_scope( |
- new ScopedCurrentPluginEvent(instance(), plugin_event)); |
- int16_t handle_response = instance()->NPP_HandleEvent(plugin_event); |
- bool handled = handle_response != kNPEventNotHandled; |
- |
- // Start IME if requested by the plugin. |
- if (handled && handle_response == kNPEventStartIME && |
- event.type == WebInputEvent::KeyDown) { |
- StartIme(); |
- ++keyup_ignore_count_; |
- } |
- |
- // Plugins don't give accurate information about whether or not they handled |
- // events, so browsers on the Mac ignore the return value. |
- // Scroll events are the exception, since the Cocoa spec defines a meaning |
- // for the return value. |
- if (WebInputEvent::isMouseEventType(event.type)) { |
- handled = true; |
- } else if (WebInputEvent::isKeyboardEventType(event.type)) { |
- // For Command-key events, trust the return value since eating all menu |
- // shortcuts is not ideal. |
- // TODO(stuartmorgan): Implement the advanced key handling spec, and trust |
- // trust the key event return value from plugins that implement it. |
- if (!(event.modifiers & WebInputEvent::MetaKey)) |
- handled = true; |
- } |
- |
- return handled; |
-} |
- |
-#pragma mark - |
- |
-void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
- const gfx::Rect& window_rect, |
- const gfx::Rect& clip_rect) { |
- gfx::Rect old_clip_rect = clip_rect_; |
- cached_clip_rect_ = clip_rect; |
- if (container_is_visible_) // Remove check when cached_clip_rect_ is removed. |
- clip_rect_ = clip_rect; |
- bool clip_rect_changed = (clip_rect_ != old_clip_rect); |
- bool window_size_changed = (window_rect.size() != window_rect_.size()); |
- |
- if (window_rect == window_rect_ && !clip_rect_changed) |
- return; |
- |
- if (old_clip_rect.IsEmpty() != clip_rect_.IsEmpty()) { |
- PluginVisibilityChanged(); |
- } |
- |
- SetPluginRect(window_rect); |
- |
- if (window_size_changed || clip_rect_changed) |
- WindowlessSetWindow(); |
-} |
- |
-void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context, |
- const gfx::Rect& damage_rect) { |
- // If we get a paint event before we are completely set up (e.g., a nested |
- // call while the plugin is still in NPP_SetWindow), bail. |
- if (!have_called_set_window_ || (use_buffer_context_ && !buffer_context_)) |
- return; |
- DCHECK(!use_buffer_context_ || buffer_context_ == context); |
- |
- gfx::Rect paint_rect = damage_rect; |
- if (use_buffer_context_) { |
- // Plugin invalidates trigger asynchronous paints with the original |
- // invalidation rect; the plugin may be resized before the paint is handled, |
- // so we need to ensure that the damage rect is still sane. |
- paint_rect.Intersect( |
- gfx::Rect(0, 0, window_rect_.width(), window_rect_.height())); |
- } else { |
- // Use the actual window region when drawing directly to the window context. |
- paint_rect.Intersect(window_rect_); |
- } |
- |
- ScopedActiveDelegate active_delegate(this); |
- |
- CGContextSaveGState(context); |
- |
- if (!use_buffer_context_) { |
- // Reposition the context origin so that plugins will draw at the correct |
- // location in the window. |
- CGContextClipToRect(context, paint_rect.ToCGRect()); |
- CGContextTranslateCTM(context, window_rect_.x(), window_rect_.y()); |
- } |
- |
- NPCocoaEvent paint_event; |
- memset(&paint_event, 0, sizeof(NPCocoaEvent)); |
- paint_event.type = NPCocoaEventDrawRect; |
- paint_event.data.draw.context = context; |
- paint_event.data.draw.x = paint_rect.x(); |
- paint_event.data.draw.y = paint_rect.y(); |
- paint_event.data.draw.width = paint_rect.width(); |
- paint_event.data.draw.height = paint_rect.height(); |
- instance()->NPP_HandleEvent(&paint_event); |
- |
- if (use_buffer_context_) { |
- // The backing buffer can change during the call to NPP_HandleEvent, in |
- // which case the old context is (or is about to be) invalid. |
- if (context == buffer_context_) |
- CGContextRestoreGState(context); |
- } else { |
- // Always restore the context to the saved state. |
- CGContextRestoreGState(context); |
- } |
-} |
- |
-void WebPluginDelegateImpl::WindowlessSetWindow() { |
- if (!instance()) |
- return; |
- |
- window_.x = 0; |
- window_.y = 0; |
- window_.height = window_rect_.height(); |
- window_.width = window_rect_.width(); |
- window_.clipRect.left = clip_rect_.x(); |
- window_.clipRect.top = clip_rect_.y(); |
- window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); |
- window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); |
- |
- NPError err = instance()->NPP_SetWindow(&window_); |
- |
- // Send an appropriate window focus event after the first SetWindow. |
- if (!have_called_set_window_) { |
- have_called_set_window_ = true; |
- SetWindowHasFocus(initial_window_focus_); |
- } |
- |
- DCHECK(err == NPERR_NO_ERROR); |
-} |
- |
-#pragma mark - |
- |
-#pragma mark - |
-#pragma mark Mac Extensions |
- |
-void WebPluginDelegateImpl::PluginDidInvalidate() { |
- if (instance()->drawing_model() == NPDrawingModelInvalidatingCoreAnimation) |
- DrawLayerInSurface(); |
-} |
- |
-WebPluginDelegateImpl* WebPluginDelegateImpl::GetActiveDelegate() { |
- return g_active_delegate; |
-} |
- |
-void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) { |
- // If we get a window focus event before calling SetWindow, just remember the |
- // states (WindowlessSetWindow will then send it on the first call). |
- if (!have_called_set_window_) { |
- initial_window_focus_ = has_focus; |
- return; |
- } |
- |
- if (has_focus == containing_window_has_focus_) |
- return; |
- containing_window_has_focus_ = has_focus; |
- |
- ScopedActiveDelegate active_delegate(this); |
- NPCocoaEvent focus_event; |
- memset(&focus_event, 0, sizeof(focus_event)); |
- focus_event.type = NPCocoaEventWindowFocusChanged; |
- focus_event.data.focus.hasFocus = has_focus; |
- instance()->NPP_HandleEvent(&focus_event); |
-} |
- |
-bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) { |
- if (!have_called_set_window_) |
- return false; |
- |
- plugin_->FocusChanged(focused); |
- |
- ScopedActiveDelegate active_delegate(this); |
- |
- NPCocoaEvent focus_event; |
- memset(&focus_event, 0, sizeof(focus_event)); |
- focus_event.type = NPCocoaEventFocusChanged; |
- focus_event.data.focus.hasFocus = focused; |
- instance()->NPP_HandleEvent(&focus_event); |
- |
- return true; |
-} |
- |
-void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) { |
- if (is_visible == container_is_visible_) |
- return; |
- container_is_visible_ = is_visible; |
- |
- // TODO(stuartmorgan): This is a temporary workarond for |
- // <http://crbug.com/34266>. When that is fixed, the cached_clip_rect_ code |
- // should all be removed. |
- if (is_visible) { |
- clip_rect_ = cached_clip_rect_; |
- } else { |
- clip_rect_.set_width(0); |
- clip_rect_.set_height(0); |
- } |
- |
- // If the plugin is changing visibility, let the plugin know. If it's scrolled |
- // off screen (i.e., cached_clip_rect_ is empty), then container visibility |
- // doesn't change anything. |
- if (!cached_clip_rect_.IsEmpty()) { |
- PluginVisibilityChanged(); |
- WindowlessSetWindow(); |
- } |
- |
- // When the plugin become visible, send an empty invalidate. If there were any |
- // pending invalidations this will trigger a paint event for the damaged |
- // region, and if not it's a no-op. This is necessary since higher levels |
- // that would normally do this weren't responsible for the clip_rect_ change). |
- if (!clip_rect_.IsEmpty()) |
- instance()->webplugin()->InvalidateRect(gfx::Rect()); |
-} |
- |
-void WebPluginDelegateImpl::WindowFrameChanged(const gfx::Rect& window_frame, |
- const gfx::Rect& view_frame) { |
- instance()->set_window_frame(window_frame); |
- SetContentAreaOrigin(gfx::Point(view_frame.x(), view_frame.y())); |
-} |
- |
-void WebPluginDelegateImpl::ImeCompositionCompleted( |
- const base::string16& text) { |
- ime_enabled_ = false; |
- |
- // If |text| is empty this was just called to tell us composition was |
- // cancelled externally (e.g., the user pressed esc). |
- if (!text.empty()) { |
- NPCocoaEvent text_event; |
- memset(&text_event, 0, sizeof(NPCocoaEvent)); |
- text_event.type = NPCocoaEventTextInput; |
- text_event.data.text.text = |
- reinterpret_cast<NPNSString*>(base::SysUTF16ToNSString(text)); |
- instance()->NPP_HandleEvent(&text_event); |
- } |
-} |
- |
-void WebPluginDelegateImpl::SetNSCursor(NSCursor* cursor) { |
- current_windowless_cursor_.InitFromNSCursor(cursor); |
-} |
- |
-void WebPluginDelegateImpl::SetNoBufferContext() { |
- use_buffer_context_ = false; |
-} |
- |
-#pragma mark - |
-#pragma mark Internal Tracking |
- |
-void WebPluginDelegateImpl::SetPluginRect(const gfx::Rect& rect) { |
- bool plugin_size_changed = rect.width() != window_rect_.width() || |
- rect.height() != window_rect_.height(); |
- window_rect_ = rect; |
- PluginScreenLocationChanged(); |
- if (plugin_size_changed) |
- UpdateAcceleratedSurface(); |
-} |
- |
-void WebPluginDelegateImpl::SetContentAreaOrigin(const gfx::Point& origin) { |
- content_area_origin_ = origin; |
- PluginScreenLocationChanged(); |
-} |
- |
-void WebPluginDelegateImpl::PluginScreenLocationChanged() { |
- gfx::Point plugin_origin(content_area_origin_.x() + window_rect_.x(), |
- content_area_origin_.y() + window_rect_.y()); |
- instance()->set_plugin_origin(plugin_origin); |
-} |
- |
-void WebPluginDelegateImpl::PluginVisibilityChanged() { |
- if (instance()->drawing_model() == NPDrawingModelCoreAnimation) { |
- bool plugin_visible = container_is_visible_ && !clip_rect_.IsEmpty(); |
- if (plugin_visible && !redraw_timer_->IsRunning()) { |
- redraw_timer_->Start(FROM_HERE, |
- base::TimeDelta::FromMilliseconds(kCoreAnimationRedrawPeriodMs), |
- this, &WebPluginDelegateImpl::DrawLayerInSurface); |
- } else if (!plugin_visible) { |
- redraw_timer_->Stop(); |
- } |
- } |
-} |
- |
-void WebPluginDelegateImpl::StartIme() { |
- if (ime_enabled_) |
- return; |
- ime_enabled_ = true; |
- plugin_->StartIme(); |
-} |
- |
-#pragma mark - |
-#pragma mark Core Animation Support |
- |
-void WebPluginDelegateImpl::DrawLayerInSurface() { |
- // If we haven't plumbed up the surface yet, don't try to draw. |
- if (!renderer_) |
- return; |
- |
- [renderer_ beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL]; |
- if (CGRectIsEmpty([renderer_ updateBounds])) { |
- // If nothing has changed, we are done. |
- [renderer_ endFrame]; |
- return; |
- } |
- |
- surface_->StartDrawing(); |
- |
- CGRect layerRect = [layer_ bounds]; |
- [renderer_ addUpdateRect:layerRect]; |
- [renderer_ render]; |
- [renderer_ endFrame]; |
- |
- surface_->EndDrawing(); |
-} |
- |
-// Update the size of the surface to match the current size of the plugin. |
-void WebPluginDelegateImpl::UpdateAcceleratedSurface() { |
- if (!surface_ || !layer_) |
- return; |
- |
- [CATransaction begin]; |
- [CATransaction setValue:[NSNumber numberWithInt:0] |
- forKey:kCATransactionAnimationDuration]; |
- [layer_ setFrame:CGRectMake(0, 0, |
- window_rect_.width(), window_rect_.height())]; |
- [CATransaction commit]; |
- |
- [renderer_ setBounds:[layer_ bounds]]; |
- surface_->SetSize(window_rect_.size()); |
- // Kick off the drawing timer, if necessary. |
- PluginVisibilityChanged(); |
-} |
- |
-} // namespace content |