jmethodID m_destroySurface;
jmethodID m_getContext;
jmethodID m_sendFindAgain;
+ jmethodID m_showRect;
AutoJObject object(JNIEnv* env) {
return getRealObject(env, m_obj);
}
m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V");
+ m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
int screenWidth, float scale, int realScreenWidth, int screenHeight,
- bool ignoreHeight)
+ int anchorX, int anchorY, bool ignoreHeight)
{
WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
int ow = window->width();
int oh = window->height();
window->setSize(width, height);
int osw = m_screenWidth;
+ int orsw = m_screenWidth * m_screenWidthScale / m_scale;
+ int osh = m_screenHeight;
DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%g) new:(w=%d,h=%d,sw=%d,scale=%g)",
ow, oh, osw, m_scale, width, height, screenWidth, scale);
m_screenWidth = screenWidth;
DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
realScreenWidth, screenHeight);
if (r) {
- // get current screen center position
- WebCore::IntPoint screenCenter = WebCore::IntPoint(
- m_scrollOffsetX + (realScreenWidth >> 1),
- m_scrollOffsetY + (screenHeight >> 1));
+ WebCore::IntPoint anchorPoint;
+ if ((anchorX | anchorY) == 0)
+ // get the current screen center position if anchor is (0, 0)
+ // which implies that it is not defined
+ anchorPoint = WebCore::IntPoint(
+ m_scrollOffsetX + (realScreenWidth >> 1),
+ m_scrollOffsetY + (screenHeight >> 1));
+ else
+ anchorPoint = WebCore::IntPoint(anchorX, anchorY);
WebCore::Node* node = 0;
WebCore::IntRect bounds;
WebCore::IntPoint offset;
// If the screen width changed, it is probably zoom change or
- // orientation change. Try to keep the node in the center of the
- // screen staying at the same place.
- if (osw != screenWidth) {
+ // orientation change. Try to keep the anchor at the same place.
+ if (osw && screenWidth && osw != screenWidth) {
WebCore::HitTestResult hitTestResult =
m_mainFrame->eventHandler()-> hitTestResultAtPoint(
- screenCenter, false);
+ anchorPoint, false);
node = hitTestResult.innerNode();
}
if (node) {
bounds = node->getRect();
DBG_NAV_LOGD("ob:(x=%d,y=%d,w=%d,h=%d)",
bounds.x(), bounds.y(), bounds.width(), bounds.height());
- offset = WebCore::IntPoint(screenCenter.x() - bounds.x(),
- screenCenter.y() - bounds.y());
- if (offset.x() < 0 || offset.x() > realScreenWidth ||
- offset.y() < 0 || offset.y() > screenHeight)
- {
- DBG_NAV_LOGD("offset out of bounds:(x=%d,y=%d)",
- offset.x(), offset.y());
- node = 0;
+ // sites like nytimes.com insert a non-standard tag <nyt_text>
+ // in the html. If it is the HitTestResult, it may have zero
+ // width and height. In this case, use its parent node.
+ if (bounds.width() == 0) {
+ node = node->parent();
+ if (node) {
+ bounds = node->getRect();
+ DBG_NAV_LOGD("found a zero width node and use its parent, whose ob:(x=%d,y=%d,w=%d,h=%d)",
+ bounds.x(), bounds.y(), bounds.width(), bounds.height());
+ }
+ }
+ if ((anchorX | anchorY) == 0) {
+ // if there is no explicit anchor, ignore if it is offscreen
+ offset = WebCore::IntPoint(anchorPoint.x() - bounds.x(),
+ anchorPoint.y() - bounds.y());
+ if (offset.x() < 0 || offset.x() > realScreenWidth ||
+ offset.y() < 0 || offset.y() > screenHeight)
+ {
+ DBG_NAV_LOGD("offset out of bounds:(x=%d,y=%d)",
+ offset.x(), offset.y());
+ node = 0;
+ }
}
}
r->setNeedsLayoutAndPrefWidthsRecalc();
m_mainFrame->view()->forceLayout();
// scroll to restore current screen center
- if (node) {
- const WebCore::IntRect& newBounds = node->getRect();
- DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
- "h=%d,ns=%d)", newBounds.x(), newBounds.y(),
- newBounds.width(), newBounds.height());
- scrollBy(newBounds.x() - bounds.x(), newBounds.y() - bounds.y(),
- false);
+ if (!node)
+ return;
+ const WebCore::IntRect& newBounds = node->getRect();
+ DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
+ "h=%d)", newBounds.x(), newBounds.y(),
+ newBounds.width(), newBounds.height());
+ if ((anchorX | anchorY) == 0)
+ scrollBy(newBounds.x() - bounds.x(),
+ newBounds.y() - bounds.y(), false);
+ else if ((orsw && osh && bounds.width() && bounds.height())
+ && (bounds != newBounds)) {
+ WebCore::FrameView* view = m_mainFrame->view();
+ // force left align if width is not changed while height changed.
+ // the anchorPoint is probably at some white space in the node
+ // which is affected by text wrap around the screen width.
+ bool leftAlign = (osw != m_screenWidth)
+ && (bounds.width() == newBounds.width())
+ && (bounds.height() != newBounds.height());
+ showRect(newBounds.x(), newBounds.y(), newBounds.width(),
+ newBounds.height(), view->contentsWidth(),
+ view->contentsHeight(),
+ leftAlign ? 0.0 : (float) (anchorX - bounds.x()) / bounds.width(),
+ leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / orsw,
+ (float) (anchorY - bounds.y()) / bounds.height(),
+ (float) (anchorY - m_scrollOffsetY) / osh);
}
}
}
return absBounds == originalAbsoluteBounds;
}
+void WebViewCore::showRect(int left, int top, int width, int height,
+ int contentWidth, int contentHeight, float xPercentInDoc,
+ float xPercentInView, float yPercentInDoc, float yPercentInView)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_showRect,
+ left, top, width, height, contentWidth, contentHeight,
+ xPercentInDoc, xPercentInView, yPercentInDoc, yPercentInView);
+ checkException(env);
+}
+
//----------------------------------------------------------------------
// Native JNI methods
//----------------------------------------------------------------------
static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
jint screenWidth, jfloat scale, jint realScreenWidth, jint screenHeight,
- jboolean ignoreHeight)
+ jint anchorX, jint anchorY, jboolean ignoreHeight)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, scale,
- realScreenWidth, screenHeight, ignoreHeight);
+ realScreenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
}
static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y)
(void*) SendListBoxChoices },
{ "nativeSendListBoxChoice", "(I)V",
(void*) SendListBoxChoice },
- { "nativeSetSize", "(IIIFIIZ)V",
+ { "nativeSetSize", "(IIIFIIIIZ)V",
(void*) SetSize },
{ "nativeSetScrollOffset", "(III)V",
(void*) SetScrollOffset },