1 // Copyright 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.
5 package org.chromium.content.browser;
7 import android.content.Context;
8 import android.content.res.Configuration;
9 import android.graphics.Canvas;
10 import android.graphics.Rect;
11 import android.os.Build;
12 import android.os.Bundle;
13 import android.os.Handler;
14 import android.os.Message;
15 import android.util.Log;
16 import android.view.KeyEvent;
17 import android.view.MotionEvent;
18 import android.view.View;
19 import android.view.accessibility.AccessibilityEvent;
20 import android.view.accessibility.AccessibilityNodeInfo;
21 import android.view.inputmethod.EditorInfo;
22 import android.view.inputmethod.InputConnection;
23 import android.widget.FrameLayout;
25 import org.chromium.base.TraceEvent;
28 * The containing view for {@link ContentViewCore} that exists in the Android UI hierarchy and
29 * exposes the various {@link View} functionality to it.
31 public class ContentView extends FrameLayout
32 implements ContentViewCore.InternalAccessDelegate, SmartClipProvider {
34 private static final String TAG = "ContentView";
36 protected final ContentViewCore mContentViewCore;
39 * Creates an instance of a ContentView.
40 * @param context The Context the view is running in, through which it can
41 * access the current theme, resources, etc.
42 * @param cvc A pointer to the content view core managing this content view.
43 * @return A ContentView instance.
45 public static ContentView newInstance(Context context, ContentViewCore cvc) {
46 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
47 return new ContentView(context, cvc);
49 return new JellyBeanContentView(context, cvc);
53 protected ContentView(Context context, ContentViewCore cvc) {
54 super(context, null, android.R.attr.webViewStyle);
56 if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
57 setHorizontalScrollBarEnabled(false);
58 setVerticalScrollBarEnabled(false);
62 setFocusableInTouchMode(true);
64 mContentViewCore = cvc;
67 // Needed by ContentViewCore.InternalAccessDelegate
69 public boolean drawChild(Canvas canvas, View child, long drawingTime) {
70 return super.drawChild(canvas, child, drawingTime);
73 // Needed by ContentViewCore.InternalAccessDelegate
75 public void onScrollChanged(int l, int t, int oldl, int oldt) {
76 super.onScrollChanged(l, t, oldl, oldt);
80 protected void onSizeChanged(int w, int h, int ow, int oh) {
82 super.onSizeChanged(w, h, ow, oh);
83 mContentViewCore.onSizeChanged(w, h, ow, oh);
88 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
89 return mContentViewCore.onCreateInputConnection(outAttrs);
93 public boolean onCheckIsTextEditor() {
94 return mContentViewCore.onCheckIsTextEditor();
98 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
100 super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
101 mContentViewCore.onFocusChanged(gainFocus);
106 public void onWindowFocusChanged(boolean hasWindowFocus) {
107 super.onWindowFocusChanged(hasWindowFocus);
108 mContentViewCore.onWindowFocusChanged(hasWindowFocus);
112 public boolean onKeyUp(int keyCode, KeyEvent event) {
113 return mContentViewCore.onKeyUp(keyCode, event);
117 public boolean dispatchKeyEventPreIme(KeyEvent event) {
118 return mContentViewCore.dispatchKeyEventPreIme(event);
122 public boolean dispatchKeyEvent(KeyEvent event) {
124 return mContentViewCore.dispatchKeyEvent(event);
126 return super.dispatchKeyEvent(event);
131 public boolean onTouchEvent(MotionEvent event) {
132 return mContentViewCore.onTouchEvent(event);
136 * Mouse move events are sent on hover enter, hover move and hover exit.
137 * They are sent on hover exit because sometimes it acts as both a hover
138 * move and hover exit.
141 public boolean onHoverEvent(MotionEvent event) {
142 boolean consumed = mContentViewCore.onHoverEvent(event);
143 if (!mContentViewCore.isTouchExplorationEnabled()) super.onHoverEvent(event);
148 public boolean onGenericMotionEvent(MotionEvent event) {
149 return mContentViewCore.onGenericMotionEvent(event);
153 public boolean performLongClick() {
158 protected void onConfigurationChanged(Configuration newConfig) {
159 mContentViewCore.onConfigurationChanged(newConfig);
163 * Currently the ContentView scrolling happens in the native side. In
164 * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo()
165 * are overridden, so that View's mScrollX and mScrollY will be unchanged at
166 * (0, 0). This is critical for drawing ContentView correctly.
169 public void scrollBy(int x, int y) {
170 mContentViewCore.scrollBy(x, y);
174 public void scrollTo(int x, int y) {
175 mContentViewCore.scrollTo(x, y);
179 protected int computeHorizontalScrollExtent() {
180 // TODO(dtrainor): Need to expose scroll events properly to public. Either make getScroll*
181 // work or expose computeHorizontalScrollOffset()/computeVerticalScrollOffset as public.
182 return mContentViewCore.computeHorizontalScrollExtent();
186 protected int computeHorizontalScrollOffset() {
187 return mContentViewCore.computeHorizontalScrollOffset();
191 protected int computeHorizontalScrollRange() {
192 return mContentViewCore.computeHorizontalScrollRange();
196 protected int computeVerticalScrollExtent() {
197 return mContentViewCore.computeVerticalScrollExtent();
201 protected int computeVerticalScrollOffset() {
202 return mContentViewCore.computeVerticalScrollOffset();
206 protected int computeVerticalScrollRange() {
207 return mContentViewCore.computeVerticalScrollRange();
210 // End FrameLayout overrides.
213 public boolean awakenScrollBars(int startDelay, boolean invalidate) {
214 return mContentViewCore.awakenScrollBars(startDelay, invalidate);
218 public boolean awakenScrollBars() {
219 return super.awakenScrollBars();
223 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
224 super.onInitializeAccessibilityNodeInfo(info);
225 mContentViewCore.onInitializeAccessibilityNodeInfo(info);
229 * Fills in scrolling values for AccessibilityEvents.
230 * @param event Event being fired.
233 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
234 super.onInitializeAccessibilityEvent(event);
235 mContentViewCore.onInitializeAccessibilityEvent(event);
239 protected void onAttachedToWindow() {
240 super.onAttachedToWindow();
241 mContentViewCore.onAttachedToWindow();
245 protected void onDetachedFromWindow() {
246 super.onDetachedFromWindow();
247 mContentViewCore.onDetachedFromWindow();
251 protected void onVisibilityChanged(View changedView, int visibility) {
252 super.onVisibilityChanged(changedView, visibility);
253 mContentViewCore.onVisibilityChanged(changedView, visibility);
256 // Implements SmartClipProvider
258 public void extractSmartClipData(int x, int y, int width, int height) {
259 mContentViewCore.extractSmartClipData(x, y, width, height);
262 // Implements SmartClipProvider
264 public void setSmartClipResultHandler(final Handler resultHandler) {
265 if (resultHandler == null) {
266 mContentViewCore.setSmartClipDataListener(null);
269 mContentViewCore.setSmartClipDataListener(new ContentViewCore.SmartClipDataListener() {
270 public void onSmartClipDataExtracted(String text, String html, Rect clipRect) {
271 Bundle bundle = new Bundle();
272 bundle.putString("url", mContentViewCore.getWebContents().getVisibleUrl());
273 bundle.putString("title", mContentViewCore.getWebContents().getTitle());
274 bundle.putParcelable("rect", clipRect);
275 bundle.putString("text", text);
276 bundle.putString("html", html);
278 Message msg = Message.obtain(resultHandler, 0);
281 } catch (Exception e) {
282 Log.e(TAG, "Error calling handler for smart clip data: ", e);
288 ///////////////////////////////////////////////////////////////////////////////////////////////
289 // Start Implementation of ContentViewCore.InternalAccessDelegate //
290 ///////////////////////////////////////////////////////////////////////////////////////////////
293 public boolean super_onKeyUp(int keyCode, KeyEvent event) {
294 return super.onKeyUp(keyCode, event);
298 public boolean super_dispatchKeyEventPreIme(KeyEvent event) {
299 return super.dispatchKeyEventPreIme(event);
303 public boolean super_dispatchKeyEvent(KeyEvent event) {
304 return super.dispatchKeyEvent(event);
308 public boolean super_onGenericMotionEvent(MotionEvent event) {
309 return super.onGenericMotionEvent(event);
313 public void super_onConfigurationChanged(Configuration newConfig) {
314 super.onConfigurationChanged(newConfig);
318 public boolean super_awakenScrollBars(int startDelay, boolean invalidate) {
319 return super.awakenScrollBars(startDelay, invalidate);
322 ///////////////////////////////////////////////////////////////////////////////////////////////
323 // End Implementation of ContentViewCore.InternalAccessDelegate //
324 ///////////////////////////////////////////////////////////////////////////////////////////////