diff options
| author | Grace Kloba <klobag@google.com> | 2009-12-16 11:39:12 -0800 |
|---|---|---|
| committer | Grace Kloba <klobag@google.com> | 2009-12-16 11:39:12 -0800 |
| commit | 11438c371e5757bde2a5c08eb81aedb794805fc1 (patch) | |
| tree | f673fd5d885be64f2c96592acab8d24593de2261 | |
| parent | 1cb97eed566014e36a7c2a0b487ec132b7d45e6c (diff) | |
| download | frameworks_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.java | 39 | ||||
| -rw-r--r-- | core/java/android/webkit/PluginFullScreenHolder.java | 120 | ||||
| -rw-r--r-- | core/java/android/webkit/WebView.java | 62 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewCore.java | 62 | ||||
| -rw-r--r-- | core/java/android/webkit/plugin/FullScreenDrawingModel.java | 35 | ||||
| -rw-r--r-- | core/java/android/webkit/plugin/WebkitPlugin.java | 4 |
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(); } |
