summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrace Kloba <klobag@google.com>2009-12-16 11:39:12 -0800
committerGrace Kloba <klobag@google.com>2009-12-16 11:39:12 -0800
commit11438c371e5757bde2a5c08eb81aedb794805fc1 (patch)
treef673fd5d885be64f2c96592acab8d24593de2261
parent1cb97eed566014e36a7c2a0b487ec132b7d45e6c (diff)
downloadframeworks_base-11438c371e5757bde2a5c08eb81aedb794805fc1.zip
frameworks_base-11438c371e5757bde2a5c08eb81aedb794805fc1.tar.gz
frameworks_base-11438c371e5757bde2a5c08eb81aedb794805fc1.tar.bz2
Implement the full screen WebView plugin.
Use a NoTitleBar_Fullscreen dialog to implement the full screen plugin. This runs in the same thread as WebView (UI in the Browser case). One catch is that the SurfaceView provided by the plugin needs to be opaque if it doesn't want to see through the WebView. The PluginFullScreenHolder translates the events to the underline WebView. Special treatment in the touch case as it needs to translate the coordinates. WebView can't be panned, or double tap to zoom, or long press to trigger the context menu while having a full screen plugin. Inside webkit, we also give the plugin element focus when it goes to the full screen so that it takes key events. While handling key events, we don't let it loose focus or scroll out. Todo: When a plugin goes to full screen, we should make sure the embedded plugin is fully visible. Otherwise when we translate the touch events back, they will be outside of the visible rect and will be ignored. This is part 1 of 2-project check in.
-rw-r--r--core/java/android/webkit/CallbackProxy.java39
-rw-r--r--core/java/android/webkit/PluginFullScreenHolder.java120
-rw-r--r--core/java/android/webkit/WebView.java62
-rw-r--r--core/java/android/webkit/WebViewCore.java62
-rw-r--r--core/java/android/webkit/plugin/FullScreenDrawingModel.java35
-rw-r--r--core/java/android/webkit/plugin/WebkitPlugin.java4
6 files changed, 223 insertions, 99 deletions
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 7eb42f2..fb369d3 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -108,8 +108,6 @@ class CallbackProxy extends Handler {
private static final int RECEIVED_TOUCH_ICON_URL = 132;
private static final int GET_VISITED_HISTORY = 133;
private static final int OPEN_FILE_CHOOSER = 134;
- private static final int SHOW_CUSTOM_VIEW = 135;
- private static final int HIDE_CUSTOM_VIEW = 136;
// Message triggered by the client to resume execution
private static final int NOTIFY = 200;
@@ -681,23 +679,6 @@ class CallbackProxy extends Handler {
mWebChromeClient.openFileChooser((UploadFile) msg.obj);
}
break;
-
- case SHOW_CUSTOM_VIEW:
- if (mWebChromeClient != null) {
- HashMap<String, Object> map =
- (HashMap<String, Object>) msg.obj;
- View view = (View) map.get("view");
- WebChromeClient.CustomViewCallback callback =
- (WebChromeClient.CustomViewCallback) map.get("callback");
- mWebChromeClient.onShowCustomView(view, callback);
- }
- break;
-
- case HIDE_CUSTOM_VIEW:
- if (mWebChromeClient != null) {
- mWebChromeClient.onHideCustomView();
- }
- break;
}
}
@@ -1404,24 +1385,4 @@ class CallbackProxy extends Handler {
}
return uploadFile.getResult();
}
-
- /* package */ void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
- if (mWebChromeClient == null) {
- return;
- }
- Message msg = obtainMessage(SHOW_CUSTOM_VIEW);
- HashMap<String, Object> map = new HashMap<String, Object>();
- map.put("view", view);
- map.put("callback", callback);
- msg.obj = map;
- sendMessage(msg);
- }
-
- /* package */ void hideCustomView() {
- if (mWebChromeClient == null) {
- return;
- }
- Message msg = obtainMessage(HIDE_CUSTOM_VIEW);
- sendMessage(msg);
- }
}
diff --git a/core/java/android/webkit/PluginFullScreenHolder.java b/core/java/android/webkit/PluginFullScreenHolder.java
new file mode 100644
index 0000000..6a0b145
--- /dev/null
+++ b/core/java/android/webkit/PluginFullScreenHolder.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package android.webkit;
+
+import android.app.Dialog;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+
+class PluginFullScreenHolder extends Dialog {
+
+ private static final String LOGTAG = "FullScreenHolder";
+
+ private final WebView mWebView;
+ private final int mNpp;
+ private int mX;
+ private int mY;
+ private int mWidth;
+ private int mHeight;
+
+ PluginFullScreenHolder(WebView webView, int npp) {
+ super(webView.getContext(), android.R.style.Theme_NoTitleBar_Fullscreen);
+ mWebView = webView;
+ mNpp = npp;
+ }
+
+ Rect getBound() {
+ return new Rect(mX, mY, mWidth, mHeight);
+ }
+
+ /*
+ * x, y, width, height are in the caller's view coordinate system. (x, y) is
+ * relative to the top left corner of the caller's view.
+ */
+ void updateBound(int x, int y, int width, int height) {
+ mX = x;
+ mY = y;
+ mWidth = width;
+ mHeight = height;
+ }
+
+ @Override
+ public void onBackPressed() {
+ mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
+ .sendToTarget();
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (event.isSystem()) {
+ return super.onKeyDown(keyCode, event);
+ }
+ mWebView.onKeyDown(keyCode, event);
+ // always return true as we are the handler
+ return true;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (event.isSystem()) {
+ return super.onKeyUp(keyCode, event);
+ }
+ mWebView.onKeyUp(keyCode, event);
+ // always return true as we are the handler
+ return true;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final float x = event.getX();
+ final float y = event.getY();
+ // TODO: find a way to know when the dialog size changed so that we can
+ // cache the ratio
+ final View decorView = getWindow().getDecorView();
+ event.setLocation(mX + x * mWidth / decorView.getWidth(),
+ mY + y * mHeight / decorView.getHeight());
+ mWebView.onTouchEvent(event);
+ // always return true as we are the handler
+ return true;
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ mWebView.onTrackballEvent(event);
+ // always return true as we are the handler
+ return true;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mWebView.getWebViewCore().sendMessage(
+ WebViewCore.EventHub.HIDE_FULLSCREEN, mNpp, 0);
+ }
+
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7d49cb6..d99f9f2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -301,6 +301,9 @@ public class WebView extends AbsoluteLayout
// Used by WebViewCore to create child views.
/* package */ final ViewManager mViewManager;
+ // Used to display in full screen mode
+ PluginFullScreenHolder mFullScreenHolder;
+
/**
* Position of the last touch event.
*/
@@ -487,6 +490,8 @@ public class WebView extends AbsoluteLayout
static final int INVAL_RECT_MSG_ID = 26;
static final int REQUEST_KEYBOARD = 27;
static final int DO_MOTION_UP = 28;
+ static final int SHOW_FULLSCREEN = 29;
+ static final int HIDE_FULLSCREEN = 30;
static final String[] HandlerDebugString = {
"REMEMBER_PASSWORD", // = 1;
@@ -516,7 +521,9 @@ public class WebView extends AbsoluteLayout
"WEBCORE_NEED_TOUCH_EVENTS", // = 25;
"INVAL_RECT_MSG_ID", // = 26;
"REQUEST_KEYBOARD", // = 27;
- "DO_MOTION_UP" // = 28;
+ "DO_MOTION_UP", // = 28;
+ "SHOW_FULLSCREEN", // = 29;
+ "HIDE_FULLSCREEN" // = 30;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -3993,6 +4000,11 @@ public class WebView extends AbsoluteLayout
|| mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
}
+ if (mFullScreenHolder != null) {
+ // in full screen mode, the WebView can't be panned.
+ mTouchMode = TOUCH_DONE_MODE;
+ break;
+ }
// if it starts nearly horizontal or vertical, enforce it
int ax = Math.abs(deltaX);
@@ -4147,7 +4159,7 @@ public class WebView extends AbsoluteLayout
ted.mX = viewToContentX((int) x + mScrollX);
ted.mY = viewToContentY((int) y + mScrollY);
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
- } else {
+ } else if (mFullScreenHolder == null) {
doDoubleTap();
}
break;
@@ -4163,8 +4175,9 @@ public class WebView extends AbsoluteLayout
if ((deltaX * deltaX + deltaY * deltaY) > mTouchSlopSquare) {
Log.w(LOGTAG, "Miss a drag as we are waiting for" +
" WebCore's response for touch down.");
- if (computeHorizontalScrollExtent() < computeHorizontalScrollRange()
- || computeVerticalScrollExtent() < computeVerticalScrollRange()) {
+ if (mFullScreenHolder == null
+ && (computeHorizontalScrollExtent() < computeHorizontalScrollRange()
+ || computeVerticalScrollExtent() < computeVerticalScrollRange())) {
// we will not rewrite drag code here, but we
// will try fling if it applies.
WebViewCore.pauseUpdate(mWebViewCore);
@@ -5115,7 +5128,7 @@ public class WebView extends AbsoluteLayout
// exclude INVAL_RECT_MSG_ID since it is frequently output
if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) {
Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
- > DO_MOTION_UP ? Integer.toString(msg.what)
+ > HIDE_FULLSCREEN ? Integer.toString(msg.what)
: HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
}
if (mWebViewCore == null) {
@@ -5146,7 +5159,9 @@ public class WebView extends AbsoluteLayout
mPreventDoubleTap = false;
}
if (mTouchMode == TOUCH_INIT_MODE) {
- mTouchMode = TOUCH_SHORTPRESS_START_MODE;
+ mTouchMode = mFullScreenHolder == null
+ ? TOUCH_SHORTPRESS_START_MODE
+ : TOUCH_SHORTPRESS_MODE;
updateSelection();
} else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mTouchMode = TOUCH_DONE_MODE;
@@ -5164,8 +5179,10 @@ public class WebView extends AbsoluteLayout
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mPreventDrag == PREVENT_DRAG_NO) {
mTouchMode = TOUCH_DONE_MODE;
- performLongClick();
- rebuildWebTextView();
+ if (mFullScreenHolder == null) {
+ performLongClick();
+ rebuildWebTextView();
+ }
}
break;
}
@@ -5466,6 +5483,35 @@ public class WebView extends AbsoluteLayout
doMotionUp(msg.arg1, msg.arg2, (Boolean) msg.obj);
break;
+ case SHOW_FULLSCREEN:
+ WebViewCore.PluginFullScreenData data
+ = (WebViewCore.PluginFullScreenData) msg.obj;
+ if (data.mNpp != 0 && data.mView != null) {
+ if (mFullScreenHolder != null) {
+ Log.w(LOGTAG,
+ "Should not have another full screen.");
+ mFullScreenHolder.dismiss();
+ }
+ mFullScreenHolder = new PluginFullScreenHolder(
+ WebView.this, data.mNpp);
+ mFullScreenHolder.setContentView(data.mView);
+ mFullScreenHolder.setCancelable(false);
+ mFullScreenHolder.setCanceledOnTouchOutside(false);
+ }
+ mFullScreenHolder.updateBound(contentToViewX(data.mDocX)
+ - mScrollX, contentToViewY(data.mDocY) - mScrollY,
+ contentToViewDimension(data.mDocWidth),
+ contentToViewDimension(data.mDocHeight));
+ mFullScreenHolder.show();
+ break;
+
+ case HIDE_FULLSCREEN:
+ if (mFullScreenHolder != null) {
+ mFullScreenHolder.dismiss();
+ mFullScreenHolder = null;
+ }
+ break;
+
default:
super.handleMessage(msg);
break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index e198ee8..ce2637b 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -41,7 +41,6 @@ import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
-import android.webkit.plugin.FullScreenDrawingModel;
import android.webkit.plugin.SurfaceDrawingModel;
import android.webkit.plugin.WebkitPlugin;
@@ -737,6 +736,15 @@ final class WebViewCore {
boolean mRemember;
}
+ static class PluginFullScreenData {
+ View mView;
+ int mNpp;
+ int mDocX;
+ int mDocY;
+ int mDocWidth;
+ int mDocHeight;
+ }
+
static final String[] HandlerDebugString = {
"UPDATE_FRAME_CACHE_IF_LOADING", // = 98
"SCROLL_TEXT_INPUT", // = 99
@@ -870,6 +878,8 @@ final class WebViewCore {
static final int POPULATE_VISITED_LINKS = 181;
+ static final int HIDE_FULLSCREEN = 182;
+
// private message ids
private static final int DESTROY = 200;
@@ -1313,6 +1323,10 @@ final class WebViewCore {
message);
break;
}
+
+ case HIDE_FULLSCREEN:
+ nativeFullScreenPluginHidden(msg.arg1);
+ break;
}
}
};
@@ -2236,35 +2250,53 @@ final class WebViewCore {
// called by JNI. PluginWidget function to launch a full-screen view using a
// View object provided by the plugin class.
- private void showFullScreenPlugin(WebkitPlugin webkitPlugin, final int npp) {
+ private void showFullScreenPlugin(WebkitPlugin webkitPlugin, final int npp,
+ int x, int y, int width, int height) {
if (mWebView == null) {
return;
}
- final FullScreenDrawingModel surface = webkitPlugin.getFullScreenSurface();
+ final SurfaceDrawingModel surface = webkitPlugin.getFullScreenSurface();
if(surface == null) {
- Log.e(LOGTAG, "Attempted to create an full-screen surface with a null drawing model");
+ Log.e(LOGTAG, "Attempted to create an full-screen surface with a " +
+ "null drawing model");
return;
}
- WebChromeClient.CustomViewCallback callback = new WebChromeClient.CustomViewCallback() {
- public void onCustomViewHidden() {
- if (surface != null) {
- surface.onSurfaceRemoved();
- nativeFullScreenPluginHidden(npp);
- }
- }
- };
-
- mCallbackProxy.showCustomView(surface.getSurface(), callback);
+ PluginFullScreenData data = new PluginFullScreenData();
+ data.mView = surface.getSurface();
+ data.mNpp = npp;
+ data.mDocX = x;
+ data.mDocY = y;
+ data.mDocWidth = width;
+ data.mDocHeight = height;
+ mWebView.mPrivateHandler.obtainMessage(WebView.SHOW_FULLSCREEN, data)
+ .sendToTarget();
}
+ // called by JNI
private void hideFullScreenPlugin() {
if (mWebView == null) {
return;
}
+ mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
+ .sendToTarget();
+ }
+
+ // called by JNI
+ private void updateFullScreenPlugin(int x, int y, int width, int height) {
+ if (mWebView == null) {
+ return;
+ }
- mCallbackProxy.hideCustomView();
+ PluginFullScreenData data = new PluginFullScreenData();
+ data.mDocX = x;
+ data.mDocY = y;
+ data.mDocWidth = width;
+ data.mDocHeight = height;
+ // null mView and mNpp to indicate it is an update
+ mWebView.mPrivateHandler.obtainMessage(WebView.SHOW_FULLSCREEN, data)
+ .sendToTarget();
}
// called by JNI. PluginWidget functions for creating an embedded View for
diff --git a/core/java/android/webkit/plugin/FullScreenDrawingModel.java b/core/java/android/webkit/plugin/FullScreenDrawingModel.java
deleted file mode 100644
index fe9d197..0000000
--- a/core/java/android/webkit/plugin/FullScreenDrawingModel.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package android.webkit.plugin;
-
-/**
- *
- * @hide pending API solidification
- */
-public interface FullScreenDrawingModel extends SurfaceDrawingModel {
-
- public void onSurfaceRemoved();
-
-}
diff --git a/core/java/android/webkit/plugin/WebkitPlugin.java b/core/java/android/webkit/plugin/WebkitPlugin.java
index af02cdc..3d13c1c 100644
--- a/core/java/android/webkit/plugin/WebkitPlugin.java
+++ b/core/java/android/webkit/plugin/WebkitPlugin.java
@@ -30,7 +30,7 @@ package android.webkit.plugin;
*/
public interface WebkitPlugin {
- SurfaceDrawingModel getEmbeddedSurface();
- FullScreenDrawingModel getFullScreenSurface();
+ SurfaceDrawingModel getEmbeddedSurface();
+ SurfaceDrawingModel getFullScreenSurface();
}