am 601112f2: Merge change I11438c37 into eclair-mr2

Merge commit '601112f213035851a2fa2c2281c7f56cf767b14a' into eclair-mr2-plus-aosp

* commit '601112f213035851a2fa2c2281c7f56cf767b14a':
  Implement the full screen WebView plugin.
This commit is contained in:
Grace Kloba
2009-12-16 14:15:29 -08:00
committed by Android Git Automerger
6 changed files with 223 additions and 99 deletions

View File

@@ -108,8 +108,6 @@ class CallbackProxy extends Handler {
private static final int RECEIVED_TOUCH_ICON_URL = 132; private static final int RECEIVED_TOUCH_ICON_URL = 132;
private static final int GET_VISITED_HISTORY = 133; private static final int GET_VISITED_HISTORY = 133;
private static final int OPEN_FILE_CHOOSER = 134; 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 // Message triggered by the client to resume execution
private static final int NOTIFY = 200; private static final int NOTIFY = 200;
@@ -681,23 +679,6 @@ class CallbackProxy extends Handler {
mWebChromeClient.openFileChooser((UploadFile) msg.obj); mWebChromeClient.openFileChooser((UploadFile) msg.obj);
} }
break; 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(); 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);
}
} }

View File

@@ -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);
}
}

View File

@@ -301,6 +301,9 @@ public class WebView extends AbsoluteLayout
// Used by WebViewCore to create child views. // Used by WebViewCore to create child views.
/* package */ final ViewManager mViewManager; /* package */ final ViewManager mViewManager;
// Used to display in full screen mode
PluginFullScreenHolder mFullScreenHolder;
/** /**
* Position of the last touch event. * 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 INVAL_RECT_MSG_ID = 26;
static final int REQUEST_KEYBOARD = 27; static final int REQUEST_KEYBOARD = 27;
static final int DO_MOTION_UP = 28; static final int DO_MOTION_UP = 28;
static final int SHOW_FULLSCREEN = 29;
static final int HIDE_FULLSCREEN = 30;
static final String[] HandlerDebugString = { static final String[] HandlerDebugString = {
"REMEMBER_PASSWORD", // = 1; "REMEMBER_PASSWORD", // = 1;
@@ -516,7 +521,9 @@ public class WebView extends AbsoluteLayout
"WEBCORE_NEED_TOUCH_EVENTS", // = 25; "WEBCORE_NEED_TOUCH_EVENTS", // = 25;
"INVAL_RECT_MSG_ID", // = 26; "INVAL_RECT_MSG_ID", // = 26;
"REQUEST_KEYBOARD", // = 27; "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, // 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) { || mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS); 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 // if it starts nearly horizontal or vertical, enforce it
int ax = Math.abs(deltaX); int ax = Math.abs(deltaX);
@@ -4147,7 +4159,7 @@ public class WebView extends AbsoluteLayout
ted.mX = viewToContentX((int) x + mScrollX); ted.mX = viewToContentX((int) x + mScrollX);
ted.mY = viewToContentY((int) y + mScrollY); ted.mY = viewToContentY((int) y + mScrollY);
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else { } else if (mFullScreenHolder == null) {
doDoubleTap(); doDoubleTap();
} }
break; break;
@@ -4163,8 +4175,9 @@ public class WebView extends AbsoluteLayout
if ((deltaX * deltaX + deltaY * deltaY) > mTouchSlopSquare) { if ((deltaX * deltaX + deltaY * deltaY) > mTouchSlopSquare) {
Log.w(LOGTAG, "Miss a drag as we are waiting for" + Log.w(LOGTAG, "Miss a drag as we are waiting for" +
" WebCore's response for touch down."); " WebCore's response for touch down.");
if (computeHorizontalScrollExtent() < computeHorizontalScrollRange() if (mFullScreenHolder == null
|| computeVerticalScrollExtent() < computeVerticalScrollRange()) { && (computeHorizontalScrollExtent() < computeHorizontalScrollRange()
|| computeVerticalScrollExtent() < computeVerticalScrollRange())) {
// we will not rewrite drag code here, but we // we will not rewrite drag code here, but we
// will try fling if it applies. // will try fling if it applies.
WebViewCore.pauseUpdate(mWebViewCore); WebViewCore.pauseUpdate(mWebViewCore);
@@ -5115,7 +5128,7 @@ public class WebView extends AbsoluteLayout
// exclude INVAL_RECT_MSG_ID since it is frequently output // exclude INVAL_RECT_MSG_ID since it is frequently output
if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) { if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) {
Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what 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]); : HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
} }
if (mWebViewCore == null) { if (mWebViewCore == null) {
@@ -5146,7 +5159,9 @@ public class WebView extends AbsoluteLayout
mPreventDoubleTap = false; mPreventDoubleTap = false;
} }
if (mTouchMode == TOUCH_INIT_MODE) { if (mTouchMode == TOUCH_INIT_MODE) {
mTouchMode = TOUCH_SHORTPRESS_START_MODE; mTouchMode = mFullScreenHolder == null
? TOUCH_SHORTPRESS_START_MODE
: TOUCH_SHORTPRESS_MODE;
updateSelection(); updateSelection();
} else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) { } else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mTouchMode = TOUCH_DONE_MODE; mTouchMode = TOUCH_DONE_MODE;
@@ -5164,8 +5179,10 @@ public class WebView extends AbsoluteLayout
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mPreventDrag == PREVENT_DRAG_NO) { } else if (mPreventDrag == PREVENT_DRAG_NO) {
mTouchMode = TOUCH_DONE_MODE; mTouchMode = TOUCH_DONE_MODE;
performLongClick(); if (mFullScreenHolder == null) {
rebuildWebTextView(); performLongClick();
rebuildWebTextView();
}
} }
break; break;
} }
@@ -5466,6 +5483,35 @@ public class WebView extends AbsoluteLayout
doMotionUp(msg.arg1, msg.arg2, (Boolean) msg.obj); doMotionUp(msg.arg1, msg.arg2, (Boolean) msg.obj);
break; 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: default:
super.handleMessage(msg); super.handleMessage(msg);
break; break;

View File

@@ -41,7 +41,6 @@ import android.view.KeyEvent;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.webkit.plugin.FullScreenDrawingModel;
import android.webkit.plugin.SurfaceDrawingModel; import android.webkit.plugin.SurfaceDrawingModel;
import android.webkit.plugin.WebkitPlugin; import android.webkit.plugin.WebkitPlugin;
@@ -737,6 +736,15 @@ final class WebViewCore {
boolean mRemember; boolean mRemember;
} }
static class PluginFullScreenData {
View mView;
int mNpp;
int mDocX;
int mDocY;
int mDocWidth;
int mDocHeight;
}
static final String[] HandlerDebugString = { static final String[] HandlerDebugString = {
"UPDATE_FRAME_CACHE_IF_LOADING", // = 98 "UPDATE_FRAME_CACHE_IF_LOADING", // = 98
"SCROLL_TEXT_INPUT", // = 99 "SCROLL_TEXT_INPUT", // = 99
@@ -870,6 +878,8 @@ final class WebViewCore {
static final int POPULATE_VISITED_LINKS = 181; static final int POPULATE_VISITED_LINKS = 181;
static final int HIDE_FULLSCREEN = 182;
// private message ids // private message ids
private static final int DESTROY = 200; private static final int DESTROY = 200;
@@ -1313,6 +1323,10 @@ final class WebViewCore {
message); message);
break; 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 // called by JNI. PluginWidget function to launch a full-screen view using a
// View object provided by the plugin class. // 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) { if (mWebView == null) {
return; return;
} }
final FullScreenDrawingModel surface = webkitPlugin.getFullScreenSurface(); final SurfaceDrawingModel surface = webkitPlugin.getFullScreenSurface();
if(surface == null) { 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; return;
} }
WebChromeClient.CustomViewCallback callback = new WebChromeClient.CustomViewCallback() { PluginFullScreenData data = new PluginFullScreenData();
public void onCustomViewHidden() { data.mView = surface.getSurface();
if (surface != null) { data.mNpp = npp;
surface.onSurfaceRemoved(); data.mDocX = x;
nativeFullScreenPluginHidden(npp); data.mDocY = y;
} data.mDocWidth = width;
} data.mDocHeight = height;
}; mWebView.mPrivateHandler.obtainMessage(WebView.SHOW_FULLSCREEN, data)
.sendToTarget();
mCallbackProxy.showCustomView(surface.getSurface(), callback);
} }
// called by JNI
private void hideFullScreenPlugin() { private void hideFullScreenPlugin() {
if (mWebView == null) { if (mWebView == null) {
return; return;
} }
mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
.sendToTarget();
}
mCallbackProxy.hideCustomView(); // called by JNI
private void updateFullScreenPlugin(int x, int y, int width, int height) {
if (mWebView == null) {
return;
}
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 // called by JNI. PluginWidget functions for creating an embedded View for

View File

@@ -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();
}

View File

@@ -30,7 +30,7 @@ package android.webkit.plugin;
*/ */
public interface WebkitPlugin { public interface WebkitPlugin {
SurfaceDrawingModel getEmbeddedSurface(); SurfaceDrawingModel getEmbeddedSurface();
FullScreenDrawingModel getFullScreenSurface(); SurfaceDrawingModel getFullScreenSurface();
} }