diff options
author | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-21 19:58:44 +0000 |
---|---|---|
committer | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-21 19:58:44 +0000 |
commit | 3a10aee79d8dc4edecd8d7fae116641f2256dc92 (patch) | |
tree | afa19398b3a1849d63e74a66ef651b49a9b626e8 /content/browser/android/composited_touch_handle_drawable.cc | |
parent | ba5fcf165dfc68a5c04ba397846117789b594d2e (diff) | |
download | chromium_src-3a10aee79d8dc4edecd8d7fae116641f2256dc92.zip chromium_src-3a10aee79d8dc4edecd8d7fae116641f2256dc92.tar.gz chromium_src-3a10aee79d8dc4edecd8d7fae116641f2256dc92.tar.bz2 |
[Android] Composited selection handle rendering
Previously, selection handles on Android were rendered using a PopupWindow
construct. This is problematic for a number of reasons, the chief being poor
performance and responsiveness. As an alternative, support a native, composited
layer rendering pipeline for selection handles using the browser compositor.
Also port selection handle-related logic from Java to C++, using a
PopupWindow rendering fallback for WebView, lacking a proper browser compositor.
This change depends directly on selection update and visibility routing through
the compositor: https://codereview.chromium.org/300323005/
BUG=380781,135959,279489,393948
Review URL: https://codereview.chromium.org/335943002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284491 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/android/composited_touch_handle_drawable.cc')
-rw-r--r-- | content/browser/android/composited_touch_handle_drawable.cc | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/content/browser/android/composited_touch_handle_drawable.cc b/content/browser/android/composited_touch_handle_drawable.cc new file mode 100644 index 0000000..7650e50 --- /dev/null +++ b/content/browser/android/composited_touch_handle_drawable.cc @@ -0,0 +1,165 @@ +// Copyright 2014 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/browser/android/composited_touch_handle_drawable.h" + +#include "base/debug/trace_event.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "cc/layers/ui_resource_layer.h" +#include "jni/HandleViewResources_jni.h" +#include "ui/gfx/android/java_bitmap.h" + +namespace content { + +namespace { + +static SkBitmap CreateSkBitmapFromJavaBitmap( + base::android::ScopedJavaLocalRef<jobject> jbitmap) { + return jbitmap.is_null() + ? SkBitmap() + : CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jbitmap.obj())); +} + +class HandleResources { + public: + HandleResources() : loaded_(false) { + } + + void LoadIfNecessary(jobject context) { + if (loaded_) + return; + + loaded_ = true; + + TRACE_EVENT0("browser", "HandleResources::Create"); + JNIEnv* env = base::android::AttachCurrentThread(); + if (!context) + context = base::android::GetApplicationContext(); + + left_bitmap_ = CreateSkBitmapFromJavaBitmap( + Java_HandleViewResources_getLeftHandleBitmap(env, context)); + right_bitmap_ = CreateSkBitmapFromJavaBitmap( + Java_HandleViewResources_getRightHandleBitmap(env, context)); + center_bitmap_ = CreateSkBitmapFromJavaBitmap( + Java_HandleViewResources_getCenterHandleBitmap(env, context)); + + left_bitmap_.setImmutable(); + right_bitmap_.setImmutable(); + center_bitmap_.setImmutable(); + } + + const SkBitmap& GetBitmap(TouchHandleOrientation orientation) { + DCHECK(loaded_); + switch (orientation) { + case TOUCH_HANDLE_LEFT: + return left_bitmap_; + case TOUCH_HANDLE_RIGHT: + return right_bitmap_; + case TOUCH_HANDLE_CENTER: + return center_bitmap_; + case TOUCH_HANDLE_ORIENTATION_UNDEFINED: + NOTREACHED() << "Invalid touch handle orientation."; + }; + return center_bitmap_; + } + + private: + SkBitmap left_bitmap_; + SkBitmap right_bitmap_; + SkBitmap center_bitmap_; + bool loaded_; + + DISALLOW_COPY_AND_ASSIGN(HandleResources); +}; + +base::LazyInstance<HandleResources>::Leaky g_selection_resources; + +} // namespace + +CompositedTouchHandleDrawable::CompositedTouchHandleDrawable( + cc::Layer* root_layer, + float dpi_scale, + jobject context) + : dpi_scale_(dpi_scale), + orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), + layer_(cc::UIResourceLayer::Create()) { + g_selection_resources.Get().LoadIfNecessary(context); + DCHECK(root_layer); + root_layer->AddChild(layer_.get()); +} + +CompositedTouchHandleDrawable::~CompositedTouchHandleDrawable() { + Detach(); +} + +void CompositedTouchHandleDrawable::SetEnabled(bool enabled) { + layer_->SetIsDrawable(enabled); +} + +void CompositedTouchHandleDrawable::SetOrientation( + TouchHandleOrientation orientation) { + DCHECK(layer_->parent()); + orientation_ = orientation; + + const SkBitmap& bitmap = g_selection_resources.Get().GetBitmap(orientation); + layer_->SetBitmap(bitmap); + layer_->SetBounds(gfx::Size(bitmap.width(), bitmap.height())); + + switch (orientation_) { + case TOUCH_HANDLE_LEFT: + focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.75f, 0); + break; + case TOUCH_HANDLE_RIGHT: + focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.25f, 0); + break; + case TOUCH_HANDLE_CENTER: + focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.5f, 0); + break; + case TOUCH_HANDLE_ORIENTATION_UNDEFINED: + NOTREACHED() << "Invalid touch handle orientation."; + break; + }; + + layer_->SetPosition(focal_position_ - focal_offset_from_origin_); +} + +void CompositedTouchHandleDrawable::SetAlpha(float alpha) { + DCHECK(layer_->parent()); + layer_->SetOpacity(std::max(0.f, std::min(1.f, alpha))); +} + +void CompositedTouchHandleDrawable::SetFocus(const gfx::PointF& position) { + DCHECK(layer_->parent()); + focal_position_ = gfx::ScalePoint(position, dpi_scale_); + layer_->SetPosition(focal_position_ - focal_offset_from_origin_); +} + +void CompositedTouchHandleDrawable::SetVisible(bool visible) { + DCHECK(layer_->parent()); + layer_->SetHideLayerAndSubtree(!visible); +} + +bool CompositedTouchHandleDrawable::ContainsPoint( + const gfx::PointF& point) const { + return BoundingRect().Contains(gfx::ScalePoint(point, dpi_scale_)); +} + +void CompositedTouchHandleDrawable::Detach() { + layer_->RemoveFromParent(); +} + +gfx::RectF CompositedTouchHandleDrawable::BoundingRect() const { + return gfx::RectF(layer_->position().x(), + layer_->position().y(), + layer_->bounds().width(), + layer_->bounds().height()); +} + +// static +bool CompositedTouchHandleDrawable::RegisterHandleViewResources(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace content |