summaryrefslogtreecommitdiffstats
path: root/core/java/android/app
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-15 16:12:10 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-15 16:12:10 -0800
commit9266c558bf1d21ff647525ff99f7dadbca417309 (patch)
tree1630b1ba80f4793caf39d865528e662bdb1037fe /core/java/android/app
parentb798689749c64baba81f02e10cf2157c747d6b46 (diff)
downloadframeworks_base-9266c558bf1d21ff647525ff99f7dadbca417309.zip
frameworks_base-9266c558bf1d21ff647525ff99f7dadbca417309.tar.gz
frameworks_base-9266c558bf1d21ff647525ff99f7dadbca417309.tar.bz2
auto import from //branches/cupcake/...@126645
Diffstat (limited to 'core/java/android/app')
-rw-r--r--core/java/android/app/ActivityThread.java31
-rw-r--r--core/java/android/app/AlertDialog.java10
-rw-r--r--core/java/android/app/ApplicationThreadNative.java12
-rw-r--r--core/java/android/app/Dialog.java23
-rw-r--r--core/java/android/app/IApplicationThread.java4
-rw-r--r--core/java/android/app/SearchDialog.java129
6 files changed, 142 insertions, 67 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3d448a6..a98e295 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1072,6 +1072,7 @@ public final class ActivityThread {
List<Intent> pendingIntents;
boolean startsNotResumed;
+ boolean isForward;
ActivityRecord() {
parent = null;
@@ -1225,8 +1226,8 @@ public final class ActivityThread {
token);
}
- public final void scheduleResumeActivity(IBinder token) {
- queueOrSendMessage(H.RESUME_ACTIVITY, token);
+ public final void scheduleResumeActivity(IBinder token, boolean isForward) {
+ queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
}
public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
@@ -1240,7 +1241,7 @@ public final class ActivityThread {
// activity itself back to the activity manager. (matters more with ipc)
public final void scheduleLaunchActivity(Intent intent, IBinder token,
ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed) {
+ List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
ActivityRecord r = new ActivityRecord();
r.token = token;
@@ -1252,6 +1253,7 @@ public final class ActivityThread {
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
+ r.isForward = isForward;
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
@@ -1604,7 +1606,8 @@ public final class ActivityThread {
handleWindowVisibility((IBinder)msg.obj, false);
break;
case RESUME_ACTIVITY:
- handleResumeActivity((IBinder)msg.obj, true);
+ handleResumeActivity((IBinder)msg.obj, true,
+ msg.arg1 != 0);
break;
case SEND_RESULT:
handleSendResult((ResultData)msg.obj);
@@ -2167,7 +2170,7 @@ public final class ActivityThread {
Activity a = performLaunchActivity(r);
if (a != null) {
- handleResumeActivity(r.token, false);
+ handleResumeActivity(r.token, false, r.isForward);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out
@@ -2522,7 +2525,7 @@ public final class ActivityThread {
return r;
}
- final void handleResumeActivity(IBinder token, boolean clearHide) {
+ final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -2537,6 +2540,9 @@ public final class ActivityThread {
a.mStartedActivity + ", hideForNow: " + r.hideForNow
+ ", finished: " + a.mFinished);
+ final int forwardBit = isForward ?
+ WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
+
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
@@ -2548,6 +2554,7 @@ public final class ActivityThread {
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+ l.softInputMode |= forwardBit;
wm.addView(decor, l);
// If the window has already been added, but during resume
@@ -2567,6 +2574,18 @@ public final class ActivityThread {
performConfigurationChanged(r.activity, r.newConfig);
r.newConfig = null;
}
+ Log.v(TAG, "Resuming " + r + " with isForward=" + isForward);
+ WindowManager.LayoutParams l = r.window.getAttributes();
+ if ((l.softInputMode
+ & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
+ != forwardBit) {
+ l.softInputMode = (l.softInputMode
+ & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
+ | forwardBit;
+ ViewManager wm = a.getWindowManager();
+ View decor = r.window.getDecorView();
+ wm.updateViewLayout(decor, l);
+ }
r.activity.mDecor.setVisibility(View.VISIBLE);
mNumVisibleActivities++;
}
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index a6981a5..f2b89c3 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -24,6 +24,7 @@ import android.os.Bundle;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
+import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
@@ -41,6 +42,15 @@ import com.android.internal.app.AlertController;
* FrameLayout fl = (FrameLayout) findViewById(R.id.body);
* fl.add(myView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
* </pre>
+ *
+ * <p>The AlertDialog class takes care of automatically setting
+ * {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
+ * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} for you based on whether
+ * any views in the dialog return true from {@link View#onCheckIsTextEditor()
+ * View.onCheckIsTextEditor()}. Generally you want this set for a Dialog
+ * without text editors, so that it will be placed on top of the current
+ * input method UI. You can modify this behavior by forcing the flag to your
+ * desired mode after calling {@link #onCreate}.
*/
public class AlertDialog extends Dialog implements DialogInterface {
private AlertController mAlert;
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 6a70329..54237ae 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -97,7 +97,8 @@ public abstract class ApplicationThreadNative extends Binder
{
data.enforceInterface(IApplicationThread.descriptor);
IBinder b = data.readStrongBinder();
- scheduleResumeActivity(b);
+ boolean isForward = data.readInt() != 0;
+ scheduleResumeActivity(b, isForward);
return true;
}
@@ -120,7 +121,8 @@ public abstract class ApplicationThreadNative extends Binder
List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
boolean notResumed = data.readInt() != 0;
- scheduleLaunchActivity(intent, b, info, state, ri, pi, notResumed);
+ boolean isForward = data.readInt() != 0;
+ scheduleLaunchActivity(intent, b, info, state, ri, pi, notResumed, isForward);
return true;
}
@@ -376,11 +378,12 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle();
}
- public final void scheduleResumeActivity(IBinder token)
+ public final void scheduleResumeActivity(IBinder token, boolean isForward)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
+ data.writeInt(isForward ? 1 : 0);
mRemote.transact(SCHEDULE_RESUME_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
@@ -399,7 +402,7 @@ class ApplicationThreadProxy implements IApplicationThread {
public final void scheduleLaunchActivity(Intent intent, IBinder token,
ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed)
+ List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -410,6 +413,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeTypedList(pendingResults);
data.writeTypedList(pendingNewIntents);
data.writeInt(notResumed ? 1 : 0);
+ data.writeInt(isForward ? 1 : 0);
mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index f1d2e65..951b48d 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -48,13 +48,23 @@ import java.lang.ref.WeakReference;
/**
* Base class for Dialogs.
*
- * Note: Activities provide a facility to manage the creation, saving and
+ * <p>Note: Activities provide a facility to manage the creation, saving and
* restoring of dialogs. See {@link Activity#onCreateDialog(int)},
* {@link Activity#onPrepareDialog(int, Dialog)},
* {@link Activity#showDialog(int)}, and {@link Activity#dismissDialog(int)}. If
* these methods are used, {@link #getOwnerActivity()} will return the Activity
* that managed this dialog.
*
+ * <p>Often you will want to have a Dialog display on top of the current
+ * input method, because there is no reason for it to accept text. You can
+ * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
+ * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
+ * your Dialog takes input focus, as it the default) with the following code:
+ *
+ * <pre>
+ * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ * </pre>
*/
public class Dialog implements DialogInterface, Window.Callback,
KeyEvent.Callback, OnCreateContextMenuListener {
@@ -209,7 +219,16 @@ public class Dialog implements DialogInterface, Window.Callback,
onStart();
mDecor = mWindow.getDecorView();
- mWindowManager.addView(mDecor, mWindow.getAttributes());
+ WindowManager.LayoutParams l = mWindow.getAttributes();
+ if ((l.softInputMode
+ & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
+ WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
+ nl.copyFrom(l);
+ nl.softInputMode |=
+ WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
+ l = nl;
+ }
+ mWindowManager.addView(mDecor, l);
mShowing = true;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index ecd993a..a351581 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -45,11 +45,11 @@ public interface IApplicationThread extends IInterface {
void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) throws RemoteException;
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
- void scheduleResumeActivity(IBinder token) throws RemoteException;
+ void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
void scheduleLaunchActivity(Intent intent, IBinder token,
ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed)
+ List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, int configChanges,
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index f1c604c..495156e 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -38,6 +38,7 @@ import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
@@ -538,7 +539,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
updateWidgetState();
// Only do suggestions if actually typed by user
- if (mSuggestionsAdapter.getNonUserQuery()) {
+ if (!mSuggestionsAdapter.getNonUserQuery()) {
mPreviousSuggestionQuery = s.toString();
mUserQuery = mSearchTextField.getText().toString();
mUserQuerySelStart = mSearchTextField.getSelectionStart();
@@ -640,6 +641,12 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (DBG_LOG_TIMING == 1) {
dbgLogTiming("doTextKey()");
}
+ // dispatch "typing in the list" first
+ if (mSearchTextField.isPopupShowing() &&
+ mSearchTextField.getListSelection() != ListView.INVALID_POSITION) {
+ return onSuggestionsKey(v, keyCode, event);
+ }
+ // otherwise, dispatch an "edit view" key
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
@@ -649,6 +656,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
return true;
}
break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ // capture the EditText state, so we can restore the user entry later
+ mUserQuery = mSearchTextField.getText().toString();
+ mUserQuerySelStart = mSearchTextField.getSelectionStart();
+ mUserQuerySelEnd = mSearchTextField.getSelectionEnd();
+ // pass through - we're just watching here
+ break;
default:
if (event.getAction() == KeyEvent.ACTION_DOWN) {
SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
@@ -668,24 +682,18 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
* React to the user typing while the suggestions are focused. First, check for action
* keys. If not handled, try refocusing regular characters into the EditText. In this case,
* replace the query text (start typing fresh text).
- *
- * TODO: Move this code into mTextKeyListener, testing for a list entry being hilited
*/
- /*
- View.OnKeyListener mSuggestionsKeyListener = new View.OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- boolean handled = false;
- // also guard against possible race conditions (late arrival after dismiss)
- if (mSearchable != null) {
- handled = doSuggestionsKey(v, keyCode, event);
- if (!handled) {
- handled = refocusingKeyListener(v, keyCode, event);
- }
+ private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) {
+ boolean handled = false;
+ // also guard against possible race conditions (late arrival after dismiss)
+ if (mSearchable != null) {
+ handled = doSuggestionsKey(v, keyCode, event);
+ if (!handled) {
+ handled = refocusingKeyListener(v, keyCode, event);
}
- return handled;
}
- };
- */
+ return handled;
+ }
/**
* Per UI design, we're going to "steer" any typed keystrokes back into the EditText
@@ -821,26 +829,26 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
// First, check for enter or search (both of which we'll treat as a "click")
if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) {
- AdapterView<?> av = (AdapterView<?>) v;
- int position = av.getSelectedItemPosition();
- return launchSuggestion(av, position);
+ int position = mSearchTextField.getListSelection();
+ return launchSuggestion(mSuggestionsAdapter, position);
}
- // Next, check for left/right moves while we'll manually grab and shift focus
+ // Next, check for left/right moves, which we use to "return" the user to the edit view
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
- // give focus to text editor
- // but don't restore the user's original query
- mLeaveJammedQueryOnRefocus = true;
- if (mSearchTextField.requestFocus()) {
- mLeaveJammedQueryOnRefocus = false;
- if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
- mSearchTextField.setSelection(0);
- } else {
- mSearchTextField.setSelection(mSearchTextField.length());
- }
- return true;
- }
- mLeaveJammedQueryOnRefocus = false;
+ // give "focus" to text editor, but don't restore the user's original query
+ int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ?
+ 0 : mSearchTextField.length();
+ mSearchTextField.setSelection(selPoint);
+ mSearchTextField.setListSelection(0);
+ mSearchTextField.clearListSelection();
+ return true;
+ }
+
+ // Next, check for an "up and out" move
+ if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mSearchTextField.getListSelection()) {
+ jamSuggestionQuery(false, null, -1);
+ // let ACTV complete the move
+ return false;
}
// Next, check for an "action key"
@@ -849,11 +857,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
((actionKey.mSuggestActionMsg != null) ||
(actionKey.mSuggestActionMsgColumn != null))) {
// launch suggestion using action key column
- ListView lv = (ListView) v;
- int position = lv.getSelectedItemPosition();
+ int position = mSearchTextField.getListSelection();
if (position >= 0) {
- CursorAdapter ca = getSuggestionsAdapter(lv);
- Cursor c = ca.getCursor();
+ Cursor c = mSuggestionsAdapter.getCursor();
if (c.moveToPosition(position)) {
final String actionMsg = getActionKeyMessage(c, actionKey);
if (actionMsg != null && (actionMsg.length() > 0)) {
@@ -977,19 +983,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
/**
* Shared code for launching a query from a suggestion.
- *
- * @param av The AdapterView (really a ListView) containing the suggestions
- * @param position The suggestion we'll be launching from
- *
- * @return Returns true if a successful launch, false if could not (e.g. bad position)
- */
- private boolean launchSuggestion(AdapterView<?> av, int position) {
- CursorAdapter ca = getSuggestionsAdapter(av);
- return launchSuggestion(ca, position);
- }
-
- /**
- * Shared code for launching a query from a suggestion.
* @param ca The cursor adapter containing the suggestions
* @param position The suggestion we'll be launching from
* @return true if a successful launch, false if could not (e.g. bad position)
@@ -1116,6 +1109,36 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
/**
+ * Local subclass for AutoCompleteTextView
+ *
+ * This exists entirely to override the threshold method. Otherwise we just use the class
+ * as-is.
+ */
+ public static class SearchAutoComplete extends AutoCompleteTextView {
+
+ public SearchAutoComplete(Context context) {
+ super(null);
+ }
+
+ public SearchAutoComplete(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * We always return true, so that the effective threshold is "zero". This allows us
+ * to provide "null" suggestions such as "just show me some recent entries".
+ */
+ @Override
+ public boolean enoughToFilter() {
+ return true;
+ }
+ }
+
+ /**
* Support for AutoCompleteTextView-based suggestions
*/
/**
@@ -1391,7 +1414,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
* Implements OnItemClickListener
*/
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-// Log.d(LOG_TAG, "onItemClick() position " + position);
+ // Log.d(LOG_TAG, "onItemClick() position " + position);
launchSuggestion(mSuggestionsAdapter, position);
}
@@ -1399,7 +1422,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
* Implements OnItemSelectedListener
*/
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-// Log.d(LOG_TAG, "onItemSelected() position " + position);
+ // Log.d(LOG_TAG, "onItemSelected() position " + position);
jamSuggestionQuery(true, parent, position);
}
@@ -1407,7 +1430,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
* Implements OnItemSelectedListener
*/
public void onNothingSelected(AdapterView<?> parent) {
-// Log.d(LOG_TAG, "onNothingSelected()");
+ // Log.d(LOG_TAG, "onNothingSelected()");
}
/**