diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/accounts/ChooseAccountActivity.java | 120 | ||||
-rw-r--r-- | core/java/android/app/FragmentManager.java | 6 | ||||
-rw-r--r-- | core/java/android/app/LoaderManager.java | 2 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothDeviceProfileState.java | 10 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothHeadset.java | 20 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetoothHeadset.aidl | 2 | ||||
-rw-r--r-- | core/java/android/provider/Settings.java | 1 | ||||
-rw-r--r-- | core/java/android/view/View.java | 21 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 6 | ||||
-rw-r--r-- | core/java/android/webkit/WebSettings.java | 2 | ||||
-rw-r--r-- | core/java/android/webkit/WebTextView.java | 8 | ||||
-rw-r--r-- | core/java/android/webkit/WebView.java | 171 | ||||
-rw-r--r-- | core/java/android/widget/AdapterViewAnimator.java | 2 | ||||
-rw-r--r-- | core/java/android/widget/StackView.java | 8 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 59 |
15 files changed, 312 insertions, 126 deletions
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java index 0bbb6fc..293df78 100644 --- a/core/java/android/accounts/ChooseAccountActivity.java +++ b/core/java/android/accounts/ChooseAccountActivity.java @@ -15,23 +15,39 @@ */ package android.accounts; -import android.app.ListActivity; +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.ImageView; import android.widget.ListView; -import android.view.View; -import android.util.Log; +import android.widget.TextView; +import com.android.internal.R; + +import java.util.HashMap; /** * @hide */ -public class ChooseAccountActivity extends ListActivity { +public class ChooseAccountActivity extends Activity { + private static final String TAG = "AccountManager"; + private Parcelable[] mAccounts = null; private AccountManagerResponse mAccountManagerResponse = null; private Bundle mResult; + private HashMap<String, AuthenticatorDescription> mTypeToAuthDescription + = new HashMap<String, AuthenticatorDescription>(); + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -47,16 +63,51 @@ public class ChooseAccountActivity extends ListActivity { return; } - String[] mAccountNames = new String[mAccounts.length]; + getAuthDescriptions(); + + AccountInfo[] mAccountInfos = new AccountInfo[mAccounts.length]; for (int i = 0; i < mAccounts.length; i++) { - mAccountNames[i] = ((Account) mAccounts[i]).name; + mAccountInfos[i] = new AccountInfo(((Account) mAccounts[i]).name, + getDrawableForType(((Account) mAccounts[i]).type)); } - // Use an existing ListAdapter that will map an array - // of strings to TextViews - setListAdapter(new ArrayAdapter<String>(this, - android.R.layout.simple_list_item_1, mAccountNames)); - getListView().setTextFilterEnabled(true); + setContentView(R.layout.choose_account); + + // Setup the list + ListView list = (ListView) findViewById(android.R.id.list); + // Use an existing ListAdapter that will map an array of strings to TextViews + list.setAdapter(new AccountArrayAdapter(this, + android.R.layout.simple_list_item_1, mAccountInfos)); + list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + list.setTextFilterEnabled(true); + list.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView<?> parent, View v, int position, long id) { + onListItemClick((ListView)parent, v, position, id); + } + }); + } + + private void getAuthDescriptions() { + for(AuthenticatorDescription desc : AccountManager.get(this).getAuthenticatorTypes()) { + mTypeToAuthDescription.put(desc.type, desc); + } + } + + private Drawable getDrawableForType(String accountType) { + Drawable icon = null; + if(mTypeToAuthDescription.containsKey(accountType)) { + try { + AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType); + Context authContext = createPackageContext(desc.packageName, 0); + icon = authContext.getResources().getDrawable(desc.iconId); + } catch (PackageManager.NameNotFoundException e) { + // Nothing we can do much here, just log + if (Log.isLoggable(TAG, Log.WARN)) { + Log.w(TAG, "No icon for account type " + accountType); + } + } + } + return icon; } protected void onListItemClick(ListView l, View v, int position, long id) { @@ -79,4 +130,51 @@ public class ChooseAccountActivity extends ListActivity { } super.finish(); } + + private static class AccountInfo { + final String name; + final Drawable drawable; + + AccountInfo(String name, Drawable drawable) { + this.name = name; + this.drawable = drawable; + } + } + + private static class ViewHolder { + ImageView icon; + TextView text; + } + + private static class AccountArrayAdapter extends ArrayAdapter<AccountInfo> { + private LayoutInflater mLayoutInflater; + private AccountInfo[] mInfos; + + public AccountArrayAdapter(Context context, int textViewResourceId, AccountInfo[] infos) { + super(context, textViewResourceId, infos); + mInfos = infos; + mLayoutInflater = (LayoutInflater) context.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + + if (convertView == null) { + convertView = mLayoutInflater.inflate(R.layout.choose_account_row, null); + holder = new ViewHolder(); + holder.text = (TextView) convertView.findViewById(R.id.account_row_text); + holder.icon = (ImageView) convertView.findViewById(R.id.account_row_icon); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + holder.text.setText(mInfos[position].name); + holder.icon.setImageDrawable(mInfos[position].drawable); + + return convertView; + } + } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index bce240f..e729805 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -332,7 +332,7 @@ final class FragmentManagerState implements Parcelable { * Container for fragments associated with an activity. */ final class FragmentManagerImpl extends FragmentManager { - static boolean DEBUG = true; + static boolean DEBUG = false; static final String TAG = "FragmentManager"; static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state"; @@ -747,7 +747,7 @@ final class FragmentManagerImpl extends FragmentManager { f.onActivityCreated(f.mSavedFragmentState); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f - + " did not call through to super.onReady()"); + + " did not call through to super.onActivityCreated()"); } f.mSavedFragmentState = null; } @@ -810,7 +810,7 @@ final class FragmentManagerImpl extends FragmentManager { f.onDestroyView(); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f - + " did not call through to super.onDestroyedView()"); + + " did not call through to super.onDestroyView()"); } if (f.mView != null && f.mContainer != null) { Animator anim = null; diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java index fc5f5fc..431be05 100644 --- a/core/java/android/app/LoaderManager.java +++ b/core/java/android/app/LoaderManager.java @@ -186,7 +186,7 @@ public abstract class LoaderManager { class LoaderManagerImpl extends LoaderManager { static final String TAG = "LoaderManager"; - static boolean DEBUG = true; + static boolean DEBUG = false; // These are the currently active loaders. A loader is here // from the time its load is started until it has been explicitly diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index 3280d39..6ec347f 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -82,6 +82,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine public static final int TRANSITION_TO_STABLE = 102; public static final int CONNECT_OTHER_PROFILES = 103; + private static final int AUTO_CONNECT_DELAY = 6000; // 6 secs private static final int CONNECT_OTHER_PROFILES_DELAY = 4000; // 4 secs private BondedDevice mBondedDevice = new BondedDevice(); @@ -1010,8 +1011,9 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine case CONNECT_HFP_INCOMING: // Connect A2DP if there is no incoming connection // If the priority is OFF - don't auto connect. - // If the priority is AUTO_CONNECT, auto connect code takes care. - if (mA2dpService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON) { + if (mA2dpService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON || + mA2dpService.getPriority(mDevice) == + BluetoothProfile.PRIORITY_AUTO_CONNECT) { Message msg = new Message(); msg.what = CONNECT_OTHER_PROFILES; msg.arg1 = CONNECT_A2DP_OUTGOING; @@ -1023,7 +1025,9 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine // before A2DP, so we should not hit this case. But many devices // don't follow this. if (mHeadsetService != null && - mHeadsetService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON) { + (mHeadsetService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON || + mHeadsetService.getPriority(mDevice) == + BluetoothProfile.PRIORITY_AUTO_CONNECT)) { Message msg = new Message(); msg.what = CONNECT_OTHER_PROFILES; msg.arg1 = CONNECT_HFP_OUTGOING; diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index d5b0042..2959fc0 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -670,6 +670,26 @@ public final class BluetoothHeadset implements BluetoothProfile { return false; } + /** + * Send a AT command message to the headset. + * @param device Remote Bluetooth Device + * @param cmd The String to send. + * @hide + */ + public void sendAtCommand(BluetoothDevice device, String command) { + if (DBG) log("sendAtCommand()"); + if (mService != null && isEnabled() && isValidDevice(device)) { + try { + mService.sendAtCommand(device, command); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl index e952193..3c6cf77 100644 --- a/core/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl @@ -50,4 +50,6 @@ interface IBluetoothHeadset { boolean startVirtualVoiceCall(in BluetoothDevice device); boolean stopVirtualVoiceCall(in BluetoothDevice device); + + void sendAtCommand(in BluetoothDevice device, String urc); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 6f23215..4f21265 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1801,7 +1801,6 @@ public final class Settings { SCREEN_BRIGHTNESS, SCREEN_BRIGHTNESS_MODE, VIBRATE_ON, - NOTIFICATIONS_USE_RING_VOLUME, MODE_RINGER, MODE_RINGER_STREAMS_AFFECTED, MUTE_STREAMS_AFFECTED, diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 811a633..469bbaa 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1813,6 +1813,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility private int mPrevWidth = -1; private int mPrevHeight = -1; + private boolean mLastIsOpaque; + /** * Convenience value to check for float values that are close enough to zero to be considered * zero. @@ -5117,7 +5119,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility removeCallbacks(mPendingCheckForLongPress); } } - + + /** + * Remove the pending click action + */ + private void removePerformClickCallback() { + if (mPerformClick != null) { + removeCallbacks(mPerformClick); + } + } + /** * Remove the prepress detection timer. */ @@ -6717,7 +6728,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility public void invalidate() { invalidate(true); } - + /** * This is where the invalidate() work actually happens. A full invalidate() * causes the drawing cache to be invalidated, but this function can be called with @@ -6734,8 +6745,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); } + boolean opaque = isOpaque(); if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) || - (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID)) { + (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) || + opaque != mLastIsOpaque) { + mLastIsOpaque = opaque; mPrivateFlags &= ~DRAWN; if (invalidateCache) { mPrivateFlags &= ~DRAWING_CACHE_VALID; @@ -7579,6 +7593,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility removeUnsetPressCallback(); removeLongPressCallback(); + removePerformClickCallback(); destroyDrawingCache(); diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 2c6ec71..ad101f8 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -710,8 +710,10 @@ public final class ViewRoot extends Handler implements ViewParent, // object is not initialized to its backing store, but soon it // will be (assuming the window is visible). attachInfo.mSurface = mSurface; - attachInfo.mUse32BitDrawingCache = PixelFormat.formatHasAlpha(lp.format) || - lp.format == PixelFormat.RGBX_8888; + // We used to use the following condition to choose 32 bits drawing caches: + // PixelFormat.hasAlpha(lp.format) || lp.format == PixelFormat.RGBX_8888 + // However, windows are now always 32 bits by default, so choose 32 bits + attachInfo.mUse32BitDrawingCache = true; attachInfo.mHasWindowFocus = false; attachInfo.mWindowVisibility = viewVisibility; attachInfo.mRecomputeGlobalAttributes = false; diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 518ba69..0bf0eab 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -571,7 +571,6 @@ public class WebSettings { * A combination of built in zoom controls enabled * and on screen zoom controls disabled allows for pinch to zoom * to work without the on screen controls - * @hide */ public void setDisplayZoomControls(boolean enabled) { mDisplayZoomControls = enabled; @@ -580,7 +579,6 @@ public class WebSettings { /** * Returns true if the on screen zoom buttons are being used. - * @hide */ public boolean getDisplayZoomControls() { return mDisplayZoomControls; diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 59a239a..6e1a6fc 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -1087,7 +1087,7 @@ import junit.framework.Assert; */ /* package */ void setTextAndKeepSelection(String text) { mPreChange = text.toString(); - Editable edit = (Editable) getText(); + Editable edit = getText(); int selStart = Selection.getSelectionStart(edit); int selEnd = Selection.getSelectionEnd(edit); mInSetTextAndKeepSelection = true; @@ -1097,6 +1097,12 @@ import junit.framework.Assert; if (selEnd > newLength) selEnd = newLength; Selection.setSelection(edit, selStart, selEnd); mInSetTextAndKeepSelection = false; + InputMethodManager imm = InputMethodManager.peekInstance(); + if (imm != null && imm.isActive(this)) { + // Since the text has changed, do not allow the IME to replace the + // existing text as though it were a completion. + imm.restartInput(this); + } updateCachedTextfield(); } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index c1fafa2..3102ee9 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -476,6 +476,7 @@ public class WebView extends AbsoluteLayout private static final int TOUCH_DRAG_LAYER_MODE = 9; // Whether to forward the touch events to WebCore + // Can only be set by WebKit via JNI. private boolean mForwardTouchEvents = false; // Whether to prevent default during touch. The initial value depends on @@ -5358,26 +5359,26 @@ public class WebView extends AbsoluteLayout + " numPointers=" + ev.getPointerCount()); } - // Always pass multi-touch event to WebKit first. - // If WebKit doesn't consume it and set preventDefault to true, - // WebView's private handler will handle it. - if (ev.getPointerCount() > 1) { - if (DebugFlags.WEB_VIEW) { - Log.v(LOGTAG, "passing " + ev.getPointerCount() + " points to webkit"); - } - if (!mIsHandlingMultiTouch) { - mIsHandlingMultiTouch = true; + int action = ev.getActionMasked(); + if (ev.getPointerCount() > 1) { // Multi-touch + mIsHandlingMultiTouch = true; + + // If WebKit already showed no interests in this sequence of events, + // WebView handles them directly. + if (mPreventDefault == PREVENT_DEFAULT_NO && action == MotionEvent.ACTION_MOVE) { + handleMultiTouchInWebView(ev); + } else { + passMultiTouchToWebKit(ev); } - passMultiTouchToWebKit(ev); return true; - } else { - // Skip ACTION_MOVE for single touch if it's still handling multi-touch. - if (mIsHandlingMultiTouch && ev.getActionMasked() == MotionEvent.ACTION_MOVE) { - return false; - } } - return handleTouchEventCommon(ev, ev.getActionMasked(), Math.round(ev.getX()), Math.round(ev.getY())); + // Skip ACTION_MOVE for single touch if it's still handling multi-touch. + if (mIsHandlingMultiTouch && action == MotionEvent.ACTION_MOVE) { + return false; + } + + return handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY())); } /* @@ -7357,75 +7358,85 @@ public class WebView extends AbsoluteLayout if (mPreventDefault == PREVENT_DEFAULT_YES) { mTouchHighlightRegion.setEmpty(); } - } else if (msg.arg2 == 0) { - // prevent default is not called in WebCore, so the - // message needs to be reprocessed in UI + } else { TouchEventData ted = (TouchEventData) msg.obj; - if (ted.mPoints.length > 1) { // for multi-touch. - handleMultiTouchInWebView(ted.mMotionEvent); + if (ted.mPoints.length > 1) { // multi-touch + if (ted.mAction == MotionEvent.ACTION_POINTER_UP) { + mIsHandlingMultiTouch = false; + } + if (msg.arg2 == 0) { + mPreventDefault = PREVENT_DEFAULT_NO; + handleMultiTouchInWebView(ted.mMotionEvent); + } else { + mPreventDefault = PREVENT_DEFAULT_YES; + } break; } - // Following is for single touch. - switch (ted.mAction) { - case MotionEvent.ACTION_DOWN: - mLastDeferTouchX = contentToViewX(ted.mPoints[0].x) - - mScrollX; - mLastDeferTouchY = contentToViewY(ted.mPoints[0].y) - - mScrollY; - mDeferTouchMode = TOUCH_INIT_MODE; - break; - case MotionEvent.ACTION_MOVE: { - // no snapping in defer process - int x = contentToViewX(ted.mPoints[0].x) - mScrollX; - int y = contentToViewY(ted.mPoints[0].y) - mScrollY; - if (mDeferTouchMode != TOUCH_DRAG_MODE) { - mDeferTouchMode = TOUCH_DRAG_MODE; - mLastDeferTouchX = x; - mLastDeferTouchY = y; - startScrollingLayer(x, y); - startDrag(); + // prevent default is not called in WebCore, so the + // message needs to be reprocessed in UI + if (msg.arg2 == 0) { + // Following is for single touch. + switch (ted.mAction) { + case MotionEvent.ACTION_DOWN: + mLastDeferTouchX = contentToViewX(ted.mPoints[0].x) + - mScrollX; + mLastDeferTouchY = contentToViewY(ted.mPoints[0].y) + - mScrollY; + mDeferTouchMode = TOUCH_INIT_MODE; + break; + case MotionEvent.ACTION_MOVE: { + // no snapping in defer process + int x = contentToViewX(ted.mPoints[0].x) - mScrollX; + int y = contentToViewY(ted.mPoints[0].y) - mScrollY; + if (mDeferTouchMode != TOUCH_DRAG_MODE) { + mDeferTouchMode = TOUCH_DRAG_MODE; + mLastDeferTouchX = x; + mLastDeferTouchY = y; + startScrollingLayer(x, y); + startDrag(); + } + int deltaX = pinLocX((int) (mScrollX + + mLastDeferTouchX - x)) + - mScrollX; + int deltaY = pinLocY((int) (mScrollY + + mLastDeferTouchY - y)) + - mScrollY; + doDrag(deltaX, deltaY); + if (deltaX != 0) mLastDeferTouchX = x; + if (deltaY != 0) mLastDeferTouchY = y; + break; } - int deltaX = pinLocX((int) (mScrollX - + mLastDeferTouchX - x)) - - mScrollX; - int deltaY = pinLocY((int) (mScrollY - + mLastDeferTouchY - y)) - - mScrollY; - doDrag(deltaX, deltaY); - if (deltaX != 0) mLastDeferTouchX = x; - if (deltaY != 0) mLastDeferTouchY = y; - break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mDeferTouchMode == TOUCH_DRAG_MODE) { + // no fling in defer process + mScroller.springBack(mScrollX, mScrollY, 0, + computeMaxScrollX(), 0, + computeMaxScrollY()); + invalidate(); + WebViewCore.resumePriority(); + WebViewCore.resumeUpdatePicture(mWebViewCore); + } + mDeferTouchMode = TOUCH_DONE_MODE; + break; + case WebViewCore.ACTION_DOUBLETAP: + // doDoubleTap() needs mLastTouchX/Y as anchor + mLastTouchX = contentToViewX(ted.mPoints[0].x) - mScrollX; + mLastTouchY = contentToViewY(ted.mPoints[0].y) - mScrollY; + mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); + mDeferTouchMode = TOUCH_DONE_MODE; + break; + case WebViewCore.ACTION_LONGPRESS: + HitTestResult hitTest = getHitTestResult(); + if (hitTest != null && hitTest.mType + != HitTestResult.UNKNOWN_TYPE) { + performLongClick(); + } + mDeferTouchMode = TOUCH_DONE_MODE; + break; } - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (mDeferTouchMode == TOUCH_DRAG_MODE) { - // no fling in defer process - mScroller.springBack(mScrollX, mScrollY, 0, - computeMaxScrollX(), 0, - computeMaxScrollY()); - invalidate(); - WebViewCore.resumePriority(); - WebViewCore.resumeUpdatePicture(mWebViewCore); - } - mDeferTouchMode = TOUCH_DONE_MODE; - break; - case WebViewCore.ACTION_DOUBLETAP: - // doDoubleTap() needs mLastTouchX/Y as anchor - mLastTouchX = contentToViewX(ted.mPoints[0].x) - mScrollX; - mLastTouchY = contentToViewY(ted.mPoints[0].y) - mScrollY; - mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); - mDeferTouchMode = TOUCH_DONE_MODE; - break; - case WebViewCore.ACTION_LONGPRESS: - HitTestResult hitTest = getHitTestResult(); - if (hitTest != null && hitTest.mType - != HitTestResult.UNKNOWN_TYPE) { - performLongClick(); - } - mDeferTouchMode = TOUCH_DONE_MODE; - break; } } break; @@ -8174,8 +8185,8 @@ public class WebView extends AbsoluteLayout * @hide This is only used by the webkit layout test. */ public void setDeferMultiTouch(boolean value) { - mDeferMultitouch = value; - Log.v(LOGTAG, "set mDeferMultitouch to " + value); + mDeferMultitouch = value; + Log.v(LOGTAG, "set mDeferMultitouch to " + value); } /** diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java index 6eb06ad..e34a204 100644 --- a/core/java/android/widget/AdapterViewAnimator.java +++ b/core/java/android/widget/AdapterViewAnimator.java @@ -696,6 +696,8 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> mWhichChild = 0; showOnly(mWhichChild, true); + } else if (mOldItemCount != getCount()) { + showOnly(mWhichChild, true); } refreshChildren(); requestLayout(); diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index 9ec4b74..03c073c 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -454,9 +454,13 @@ public class StackView extends AdapterViewAnimator { canvas.getClipBounds(stackInvalidateRect); final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { - LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams(); + final View child = getChildAt(i); + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if ((lp.horizontalOffset == 0 && lp.verticalOffset == 0) || + child.getAlpha() == 0f || child.getVisibility() != VISIBLE) { + lp.resetInvalidateRect(); + } stackInvalidateRect.union(lp.getInvalidateRect()); - lp.resetInvalidateRect(); } canvas.save(Canvas.CLIP_SAVE_FLAG); canvas.clipRect(stackInvalidateRect, Region.Op.UNION); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index fad0a4f..aac57ed 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4791,8 +4791,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return super.onKeyUp(keyCode, event); } - hideControllers(); - switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: mDPadCenterIsDown = false; @@ -7126,6 +7124,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } super.onFocusChanged(focused, direction, previouslyFocusedRect); + + // After super.onFocusChanged so that this TextView is registered and can ask for the IME + // Showing the IME while focus is moved using the D-Pad is a bad idea, however this does + // not happen in that case (using the arrows on a bluetooth keyboard). + if (focused) { + onTouchFinished(null); + } } private int getLastTapPosition() { @@ -7268,6 +7273,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return superResult; } + final boolean touchIsFinished = action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && + isFocused(); + if ((mMovement != null || onCheckIsTextEditor()) && isEnabled() && mText instanceof Spannable && mLayout != null) { boolean handled = false; @@ -7283,8 +7291,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener handled |= mMovement.onTouchEvent(this, (Spannable) mText, event); } - if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable && - action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) { + if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable && touchIsFinished) { // The LinkMovementMethod which should handle taps on links has not been installed // to support text selection. We reproduce its behavior here to open links. ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(), @@ -7306,26 +7313,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mSelectionModifierCursorController.updatePosition(); } } - if (action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) { - InputMethodManager imm = (InputMethodManager) - getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (touchIsFinished) { CommitSelectionReceiver csr = null; if (getSelectionStart() != oldSelStart || getSelectionEnd() != oldSelEnd || didTouchFocusSelect()) { csr = new CommitSelectionReceiver(oldSelStart, oldSelEnd); } - if (!mTextIsSelectable) { - // Show the IME, except when selecting in read-only text. - handled |= imm.showSoftInput(this, 0, csr) && (csr != null); - } - - stopSelectionActionMode(); - boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected; - if (hasInsertionController() && !selectAllGotFocus) { - getInsertionController().show(); - } + handled = onTouchFinished(csr); } } @@ -7337,6 +7333,35 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return superResult; } + /** Shows the IME if applicable, ends selection mode and displays the selection controller. + * + * This method is called at the end of a touch event, when the finger is lifted up. + * It is also called when the TextField gains focus indirectly through a dispatched event from + * one of its parents. We want to have the same behavior in that case. + * + * @param csr A (possibly null) callback called if the IME has been displayed + * @return true if the event was properly sent to the csr + */ + private boolean onTouchFinished(CommitSelectionReceiver csr) { + boolean handled = false; + + // Show the IME, except when selecting in read-only text. + if (!mTextIsSelectable) { + final InputMethodManager imm = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + + handled = imm.showSoftInput(this, 0, csr) && (csr != null); + } + + stopSelectionActionMode(); + boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected; + if (hasInsertionController() && !selectAllGotFocus) { + getInsertionController().show(); + } + + return handled; + } + private void prepareCursorControllers() { boolean windowSupportsHandles = false; |