/** @hide */ void dispatchTrackballEvent( Context context, int seq, MotionEvent motion, IInputMethodCallback callback) { synchronized (mH) { if (DEBUG) Log.d(TAG, "dispatchTrackballEvent"); if (mCurMethod == null || mCurrentTextBoxAttribute == null) { try { callback.finishedEvent(seq, false); } catch (RemoteException e) { } return; } try { if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod); mCurMethod.dispatchTrackballEvent(seq, motion, callback); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e); try { callback.finishedEvent(seq, false); } catch (RemoteException ex) { } } } }
/** @hide */ public void dispatchKeyEvent( Context context, int seq, KeyEvent key, IInputMethodCallback callback) { synchronized (mH) { if (DEBUG) Log.d(TAG, "dispatchKeyEvent"); if (mCurMethod == null) { try { callback.finishedEvent(seq, false); } catch (RemoteException e) { } return; } if (key.getAction() == KeyEvent.ACTION_DOWN && key.getKeyCode() == KeyEvent.KEYCODE_SYM) { showInputMethodPicker(); try { callback.finishedEvent(seq, true); } catch (RemoteException e) { } return; } try { if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod); mCurMethod.dispatchKeyEvent(seq, key, callback); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e); try { callback.finishedEvent(seq, false); } catch (RemoteException ex) { } } } }
/** Report the current selection range. */ public void updateSelection( View view, int selStart, int selEnd, int candidatesStart, int candidatesEnd) { checkFocus(); synchronized (mH) { if ((mServedView != view && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } if (mCursorSelStart != selStart || mCursorSelEnd != selEnd || mCursorCandStart != candidatesStart || mCursorCandEnd != candidatesEnd) { if (DEBUG) Log.d(TAG, "updateSelection"); try { if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod); mCurMethod.updateSelection( mCursorSelStart, mCursorSelEnd, selStart, selEnd, candidatesStart, candidatesEnd); mCursorSelStart = selStart; mCursorSelEnd = selEnd; mCursorCandStart = candidatesStart; mCursorCandEnd = candidatesEnd; } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } } } }
/* * This method toggles the input method window display. * If the input window is already displayed, it gets hidden. * If not the input window will be displayed. * @param showFlags Provides additional operating flags. May be * 0 or have the {@link #SHOW_IMPLICIT}, * {@link #SHOW_FORCED} bit set. * @param hideFlags Provides additional operating flags. May be * 0 or have the {@link #HIDE_IMPLICIT_ONLY}, * {@link #HIDE_NOT_ALWAYS} bit set. * @hide */ public void toggleSoftInput(int showFlags, int hideFlags) { if (mCurMethod != null) { try { mCurMethod.toggleSoftInput(showFlags, hideFlags); } catch (RemoteException e) { } } }
/** * This method toggles the input method window display. If the input window is already displayed, * it gets hidden. If not the input window will be displayed. * * @param windowToken The token of the window that is making the request, as returned by {@link * View#getWindowToken() View.getWindowToken()}. * @param showFlags Provides additional operating flags. May be 0 or have the {@link * #SHOW_IMPLICIT}, {@link #SHOW_FORCED} bit set. * @param hideFlags Provides additional operating flags. May be 0 or have the {@link * #HIDE_IMPLICIT_ONLY}, {@link #HIDE_NOT_ALWAYS} bit set. */ public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) { synchronized (mH) { if (mServedView == null || mServedView.getWindowToken() != windowToken) { return; } if (mCurMethod != null) { try { mCurMethod.toggleSoftInput(showFlags, hideFlags); } catch (RemoteException e) { } } } }
public void updateExtractedText(View view, int token, ExtractedText text) { checkFocus(); synchronized (mH) { if (mServedView != view && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) { return; } if (mCurMethod != null) { try { mCurMethod.updateExtractedText(token, text); } catch (RemoteException e) { } } } }
public void displayCompletions(View view, CompletionInfo[] completions) { checkFocus(); synchronized (mH) { if (mServedView != view && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) { return; } mCompletions = completions; if (mCurMethod != null) { try { mCurMethod.displayCompletions(mCompletions); } catch (RemoteException e) { } } } }
/** * Call {@link InputMethodSession#appPrivateCommand(String, Bundle) * InputMethodSession.appPrivateCommand()} on the current Input Method. * * @param view Optional View that is sending the command, or null if you want to send the command * regardless of the view that is attached to the input method. * @param action Name of the command to be performed. This <em>must</em> be a scoped name, i.e. * prefixed with a package name you own, so that different developers will not create * conflicting commands. * @param data Any data to include with the command. */ public void sendAppPrivateCommand(View view, String action, Bundle data) { checkFocus(); synchronized (mH) { if ((mServedView != view && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } try { if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data); mCurMethod.appPrivateCommand(action, data); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } } }
/** Report the current cursor location in its window. */ public void updateCursor(View view, int left, int top, int right, int bottom) { checkFocus(); synchronized (mH) { if ((mServedView != view && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } mTmpCursorRect.set(left, top, right, bottom); if (!mCursorRect.equals(mTmpCursorRect)) { if (DEBUG) Log.d(TAG, "updateCursor"); try { if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod); mCurMethod.updateCursor(mTmpCursorRect); mCursorRect.set(mTmpCursorRect); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } } } }
void startInputInner() { final View view; synchronized (mH) { view = mServedView; // Make sure we have a window token for the served view. if (DEBUG) Log.v(TAG, "Starting input: view=" + view); if (view == null) { if (DEBUG) Log.v(TAG, "ABORT input: no served view!"); return; } } // Now we need to get an input connection from the served view. // This is complicated in a couple ways: we can't be holding our lock // when calling out to the view, and we need to make sure we call into // the view on the same thread that is driving its view hierarchy. Handler vh = view.getHandler(); if (vh == null) { // If the view doesn't have a handler, something has changed out // from under us, so just bail. if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!"); return; } if (vh.getLooper() != Looper.myLooper()) { // The view is running on a different thread than our own, so // we need to reschedule our work for over there. if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread"); vh.post( new Runnable() { public void run() { startInputInner(); } }); return; } // Okay we are now ready to call into the served view and have it // do its stuff. // Life is good: let's hook everything up! EditorInfo tba = new EditorInfo(); tba.packageName = view.getContext().getPackageName(); tba.fieldId = view.getId(); InputConnection ic = view.onCreateInputConnection(tba); if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic); synchronized (mH) { // Now that we are locked again, validate that our state hasn't // changed. if (mServedView != view || !mServedConnecting) { // Something else happened, so abort. if (DEBUG) Log.v( TAG, "Starting input: finished by someone else (view=" + mServedView + " conn=" + mServedConnecting + ")"); return; } // If we already have a text box, then this view is already // connected so we want to restart it. final boolean initial = mCurrentTextBoxAttribute == null; // Hook 'em up and let 'er rip. mCurrentTextBoxAttribute = tba; mServedConnecting = false; mServedInputConnection = ic; IInputContext servedContext; if (ic != null) { mCursorSelStart = tba.initialSelStart; mCursorSelEnd = tba.initialSelEnd; mCursorCandStart = -1; mCursorCandEnd = -1; mCursorRect.setEmpty(); servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic); } else { servedContext = null; } try { if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic=" + ic + " tba=" + tba + " initial=" + initial); InputBindResult res = mService.startInput(mClient, servedContext, tba, initial, mCurMethod == null); if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res); if (res != null) { if (res.id != null) { mBindSequence = res.sequence; mCurMethod = res.method; } else { // This means there is no input method available. if (DEBUG) Log.v(TAG, "ABORT input: no input method!"); return; } } if (mCurMethod != null && mCompletions != null) { try { mCurMethod.displayCompletions(mCompletions); } catch (RemoteException e) { } } } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } } }