diff --git a/samples/MultiClientInputMethod/res/values/config.xml b/samples/MultiClientInputMethod/res/values/config.xml new file mode 100644 index 000000000..b29acec4c --- /dev/null +++ b/samples/MultiClientInputMethod/res/values/config.xml @@ -0,0 +1,35 @@ + + + + + + + \ No newline at end of file diff --git a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/MultiClientInputMethod.java b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/MultiClientInputMethod.java index 0b146ad35..365354a7f 100644 --- a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/MultiClientInputMethod.java +++ b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/MultiClientInputMethod.java @@ -16,7 +16,9 @@ package com.example.android.multiclientinputmethod; +import android.annotation.NonNull; import android.app.Service; +import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; @@ -24,6 +26,7 @@ import android.inputmethodservice.MultiClientInputMethodServiceDelegate; import android.os.IBinder; import android.util.Log; import android.util.SparseIntArray; +import android.view.Display; /** * A {@link Service} that implements multi-client IME protocol. @@ -34,6 +37,9 @@ public final class MultiClientInputMethod extends Service implements DisplayList // last client that had active InputConnection for a given displayId. final SparseIntArray mDisplayToLastClientId = new SparseIntArray(); + // Mapping table from the display where IME is attached to the display where IME window will be + // shown. Assumes that missing display will use the same display for the IME window. + SparseIntArray mInputDisplayToImeDisplay; SoftInputWindowManager mSoftInputWindowManager; MultiClientInputMethodServiceDelegate mDelegate; @@ -44,6 +50,7 @@ public final class MultiClientInputMethod extends Service implements DisplayList if (DEBUG) { Log.v(TAG, "onCreate"); } + mInputDisplayToImeDisplay = buildInputDisplayToImeDisplay(); mDelegate = MultiClientInputMethodServiceDelegate.create(this, new MultiClientInputMethodServiceDelegate.ServiceCallback() { @Override @@ -56,13 +63,17 @@ public final class MultiClientInputMethod extends Service implements DisplayList @Override public void addClient(int clientId, int uid, int pid, int selfReportedDisplayId) { + int imeDisplayId = mInputDisplayToImeDisplay.get(selfReportedDisplayId, + selfReportedDisplayId); final ClientCallbackImpl callback = new ClientCallbackImpl( MultiClientInputMethod.this, mDelegate, - mSoftInputWindowManager, clientId, uid, pid, selfReportedDisplayId); + mSoftInputWindowManager, clientId, uid, pid, imeDisplayId); if (DEBUG) { Log.v(TAG, "addClient clientId=" + clientId + " uid=" + uid - + " pid=" + pid + " displayId=" + selfReportedDisplayId); + + " pid=" + pid + " displayId=" + selfReportedDisplayId + + " imeDisplayId=" + imeDisplayId); } + mDelegate.acceptClient(clientId, callback, callback.getDispatcherState(), callback.getLooper()); } @@ -118,4 +129,38 @@ public final class MultiClientInputMethod extends Service implements DisplayList } mDelegate.onDestroy(); } + + @NonNull + private SparseIntArray buildInputDisplayToImeDisplay() { + // TODO: Support the virtual display after b/137375833 is fixed. + Context context = getApplicationContext(); + String config[] = context.getResources().getStringArray( + R.array.config_inputDisplayToImeDisplay); + + SparseIntArray inputDisplayToImeDisplay = new SparseIntArray(); + Display[] displays = context.getSystemService(DisplayManager.class).getDisplays(); + for (String item: config) { + String[] pair = item.split(","); + if (pair.length != 2) { + Log.w(TAG, "Skip illegal config: " + item); + continue; + } + int inputDisplay = findDisplayId(displays, pair[0]); + int imeDisplay = findDisplayId(displays, pair[1]); + if (inputDisplay != Display.INVALID_DISPLAY && imeDisplay != Display.INVALID_DISPLAY) { + inputDisplayToImeDisplay.put(inputDisplay, imeDisplay); + } + } + return inputDisplayToImeDisplay; + } + + private static int findDisplayId(Display displays[], String uniqueId) { + for (Display display: displays) { + if (uniqueId.equals(display.getUniqueId())) { + return display.getDisplayId(); + } + } + Log.w(TAG, "Can't find the display of " + uniqueId); + return Display.INVALID_DISPLAY; + } }