fix issue when rotating screen while keyboard is showing on some newer android versions

see https://github.com/Helium314/openboard/pull/33#issuecomment-1650487463
based on commits
  4d464ec07d
  6ae09365a5
  6c752d8eca
This commit is contained in:
Helium314 2023-07-30 08:58:08 +02:00
parent 469088d62f
commit d517709391
3 changed files with 57 additions and 13 deletions

View file

@ -25,6 +25,8 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import androidx.annotation.NonNull;
import org.dslul.openboard.inputmethod.event.Event;
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException;
import org.dslul.openboard.inputmethod.keyboard.clipboard.ClipboardHistoryView;
@ -93,23 +95,24 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mIsHardwareAcceleratedDrawingEnabled = mLatinIME.enableHardwareAcceleration();
}
public void updateKeyboardTheme() {
public void updateKeyboardTheme(@NonNull Context displayContext) {
final boolean themeUpdated = updateKeyboardThemeAndContextThemeWrapper(
mLatinIME, KeyboardTheme.getKeyboardTheme(mLatinIME /* context */));
displayContext, KeyboardTheme.getKeyboardTheme(displayContext /* context */));
if (themeUpdated && mKeyboardView != null) {
mLatinIME.setInputView(onCreateInputView(mIsHardwareAcceleratedDrawingEnabled));
mLatinIME.setInputView(onCreateInputView(displayContext, mIsHardwareAcceleratedDrawingEnabled));
}
}
public void forceUpdateKeyboardTheme() {
mLatinIME.setInputView(onCreateInputView(mIsHardwareAcceleratedDrawingEnabled));
public void forceUpdateKeyboardTheme(@NonNull Context displayContext) {
mLatinIME.setInputView(onCreateInputView(displayContext, mIsHardwareAcceleratedDrawingEnabled));
}
private boolean updateKeyboardThemeAndContextThemeWrapper(final Context context,
final KeyboardTheme keyboardTheme) {
final boolean nightModeChanged = (mCurrentUiMode & Configuration.UI_MODE_NIGHT_MASK)
!= (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK);
if (mThemeContext == null || !keyboardTheme.equals(mKeyboardTheme) || nightModeChanged) {
if (mThemeContext == null || !keyboardTheme.equals(mKeyboardTheme) || nightModeChanged
|| !mThemeContext.getResources().equals(context.getResources())) {
mKeyboardTheme = keyboardTheme;
mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId);
mCurrentUiMode = context.getResources().getConfiguration().uiMode;
@ -530,13 +533,14 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
}
public View onCreateInputView(final boolean isHardwareAcceleratedDrawingEnabled) {
public View onCreateInputView(@NonNull Context displayContext,
final boolean isHardwareAcceleratedDrawingEnabled) {
if (mKeyboardView != null) {
mKeyboardView.closing();
}
updateKeyboardThemeAndContextThemeWrapper(
mLatinIME, KeyboardTheme.getKeyboardTheme(mLatinIME /* context */));
displayContext, KeyboardTheme.getKeyboardTheme(displayContext /* context */));
mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
R.layout.input_view, null);
mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame);

View file

@ -98,11 +98,14 @@ import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
import static org.dslul.openboard.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
import androidx.annotation.NonNull;
/**
* Input method implementation for Qwerty'ish keyboard.
*/
@ -163,6 +166,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// {@link #onEvaluateInputViewShown()}.
private boolean mIsExecutingStartShowingInputView;
// Used for re-initialize keyboard layout after onConfigurationChange.
@Nullable private Context mDisplayContext;
// Object for reacting to adding/removing a dictionary pack.
private final BroadcastReceiver mDictionaryPackInstallReceiver =
new DictionaryPackInstallBroadcastReceiver(this);
@ -620,10 +626,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
DebugFlags.init(DeviceProtectedUtils.getSharedPreferences(this));
RichInputMethodManager.init(this);
mRichImm = RichInputMethodManager.getInstance();
KeyboardSwitcher.init(this);
AudioAndHapticFeedbackManager.init(this);
AccessibilityUtils.init(this);
mStatsUtilsManager.onCreate(this /* context */, mDictionaryFacilitator);
mDisplayContext = getDisplayContext();
KeyboardSwitcher.init(this);
super.onCreate();
mClipboardHistoryManager.onCreate();
@ -816,14 +823,46 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
// KeyboardSwitcher will check by itself if theme update is necessary
mKeyboardSwitcher.updateKeyboardTheme();
mKeyboardSwitcher.updateKeyboardTheme(getDisplayContext());
super.onConfigurationChanged(conf);
}
@Override
public void onInitializeInterface() {
mDisplayContext = getDisplayContext();
mKeyboardSwitcher.updateKeyboardTheme(mDisplayContext);
}
/**
* Returns the context object whose resources are adjusted to match the metrics of the display.
*
* Note that before {@link android.os.Build.VERSION_CODES#KITKAT}, there is no way to support
* multi-display scenarios, so the context object will just return the IME context itself.
*
* With initiating multi-display APIs from {@link android.os.Build.VERSION_CODES#KITKAT}, the
* context object has to return with re-creating the display context according the metrics
* of the display in runtime.
*
* Starts from {@link android.os.Build.VERSION_CODES#S_V2}, the returning context object has
* became to IME context self since it ends up capable of updating its resources internally.
*/
private @NonNull Context getDisplayContext() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
// IME context sources is now managed by WindowProviderService from Android 12L.
return this;
}
// An issue in Q that non-activity components Resources / DisplayMetrics in
// Context doesn't well updated when the IME window moving to external display.
// Currently we do a workaround is to create new display context directly and re-init
// keyboard layout with this context.
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
return createDisplayContext(wm.getDefaultDisplay());
}
@Override
public View onCreateInputView() {
StatsUtils.onCreateInputView();
return mKeyboardSwitcher.onCreateInputView(mIsHardwareAcceleratedDrawingEnabled);
return mKeyboardSwitcher.onCreateInputView(getDisplayContext(), mIsHardwareAcceleratedDrawingEnabled);
}
@Override
@ -906,7 +945,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
mRichImm.refreshSubtypeCaches();
final KeyboardSwitcher switcher = mKeyboardSwitcher;
switcher.updateKeyboardTheme();
switcher.updateKeyboardTheme(mDisplayContext);
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
// If we are starting input in a different text field from before, we'll have to reload
// settings, so currentSettingsValues can't be final.

View file

@ -81,7 +81,8 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
override fun onPause() {
super.onPause()
if (needsReload)
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme()
// todo: is this the correct "displayContext? if not it may cause weird rare issues on some android versions
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(activity)
needsReload = false
}