Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {
dependencies {
implementation("androidx.window:window-java:1.3.0")
implementation("androidx.core:core:1.16.0")
implementation("androidx.autofill:autofill:1.3.0")
testImplementation("junit:junit:4.13.2")
}

Expand Down
16 changes: 15 additions & 1 deletion res/layout/keyboard.xml
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<juloo.keyboard2.Keyboard2View xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false" android:background="?attr/colorKeyboard"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:hardwareAccelerated="false" android:background="?attr/colorKeyboard">
<HorizontalScrollView
android:id="@+id/autofill_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<LinearLayout
android:id="@+id/autofill_suggestions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:orientation="horizontal" />
</HorizontalScrollView>
<juloo.keyboard2.Keyboard2View android:id="@+id/keyboard_view" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
</LinearLayout>
2 changes: 1 addition & 1 deletion res/xml/method.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsInlineSuggestions="true" android:supportsSwitchingToNextInputMethod="true">
<!-- The first entry of the list makes latn_qwerty_us the default layout for
unrecognized locales. -->
<subtype android:label="%s" android:languageTag="en" android:imeSubtypeLocale="en" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
Expand Down
89 changes: 89 additions & 0 deletions srcs/juloo.keyboard2/InlineAutofill.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package juloo.keyboard2;

import static juloo.keyboard2.Logs.TAG;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.autofill.inline.UiVersions;
import androidx.autofill.inline.v1.InlineSuggestionUi;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.Size;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InlineSuggestion;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.inline.InlinePresentationSpec;

import java.util.Collections;
import java.util.List;

@RequiresApi(api = Build.VERSION_CODES.R)
public class InlineAutofill {
private HorizontalScrollView _autofillContainer;
private LinearLayout _autofillSuggestions;

public void onInflate(View keyboardViewParent)
{
_autofillContainer = keyboardViewParent.findViewById(R.id.autofill_container);
_autofillSuggestions = keyboardViewParent.findViewById(R.id.autofill_suggestions);
}

@Nullable
public InlineSuggestionsRequest onCreateInlineSuggestionsRequest(@NonNull Bundle uiExtras)
{
Size smallestSize = new Size(0, 0);
Size biggestSize = new Size(Integer.MAX_VALUE, Integer.MAX_VALUE);

UiVersions.StylesBuilder stylesBuilder = UiVersions.newStylesBuilder();

InlineSuggestionUi.Style style = InlineSuggestionUi.newStyleBuilder().build();
stylesBuilder.addStyle(style);

Bundle stylesBundle = stylesBuilder.build();
InlinePresentationSpec spec =
new InlinePresentationSpec.Builder(smallestSize, biggestSize)
.setStyle(stylesBundle)
.build();

return new InlineSuggestionsRequest.Builder(Collections.singletonList(spec)).build();
}

public boolean onInlineSuggestionsResponse(Context context, @NonNull InlineSuggestionsResponse response)
{
List<InlineSuggestion> inlineSuggestions = response.getInlineSuggestions();

float height =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 40, context.getResources().getDisplayMetrics());
Size autofillSize = new Size(ViewGroup.LayoutParams.WRAP_CONTENT, ((int) height));

_autofillSuggestions.removeAllViews();
_autofillContainer.setVisibility(inlineSuggestions.isEmpty() ? View.GONE : View.VISIBLE);

for (InlineSuggestion inlineSuggestion : inlineSuggestions)
{
try
{
inlineSuggestion.inflate(
context,
autofillSize,
context.getMainExecutor(),
_autofillSuggestions::addView);
}
catch (Exception e)
{
Log.e(TAG, "onInlineSuggestionsResponse - inlineSuggestion.infLate - " + e);
}
}
return true;
}
}
48 changes: 37 additions & 11 deletions srcs/juloo.keyboard2/Keyboard2.java
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
package juloo.keyboard2;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.text.InputType;
import android.util.Log;
import android.util.LogPrinter;
import android.view.*;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import java.util.AbstractMap.SimpleEntry;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import juloo.keyboard2.prefs.LayoutsPreference;

public class Keyboard2 extends InputMethodService
implements SharedPreferences.OnSharedPreferenceChangeListener
{
private View _keyboardViewParent = null;
private Keyboard2View _keyboardView;
private InlineAutofill _inlineAutofill;
private KeyEventHandler _keyeventhandler;
/** If not 'null', the layout to use instead of [_config.current_layout]. */
private KeyboardData _currentSpecialLayout;
Expand Down Expand Up @@ -116,13 +119,21 @@ public void onCreate()
Config.initGlobalConfig(prefs, getResources(), _keyeventhandler, _foldStateTracker.isUnfolded());
prefs.registerOnSharedPreferenceChangeListener(this);
_config = Config.globalConfig();
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
_inlineAutofill = new InlineAutofill();
inflate_keyboardView();
_keyboardView.reset();
Logs.set_debug_logs(getResources().getBoolean(R.bool.debug_logs));
ClipboardHistoryService.on_startup(this, _keyeventhandler);
_foldStateTracker.setChangedCallback(() -> { refresh_config(); });
}

private void inflate_keyboardView() {
_keyboardViewParent = inflate_view(R.layout.keyboard);
_inlineAutofill.onInflate(_keyboardViewParent);
_keyboardView = _keyboardViewParent.findViewById(R.id.keyboard_view);
_keyboardViewParent.getBackground().setAlpha(_config.keyboardOpacity);
}

@Override
public void onDestroy() {
super.onDestroy();
Expand Down Expand Up @@ -211,10 +222,10 @@ private void refresh_config()
// Refreshing the theme config requires re-creating the views
if (prev_theme != _config.theme)
{
_keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
inflate_keyboardView();
_emojiPane = null;
_clipboard_pane = null;
setInputView(_keyboardView);
setInputView(_keyboardViewParent);
}
_keyboardView.reset();
}
Expand All @@ -240,7 +251,7 @@ public void onStartInputView(EditorInfo info, boolean restarting)
_currentSpecialLayout = refresh_special_layout();
_keyboardView.setKeyboard(current_layout());
_keyeventhandler.started(_config);
setInputView(_keyboardView);
setInputView(_keyboardViewParent);
Logs.debug_startup_input_view(info, _config);
}

Expand Down Expand Up @@ -393,7 +404,7 @@ public void handle_event_key(KeyValue.Event ev)

case SWITCH_BACK_EMOJI:
case SWITCH_BACK_CLIPBOARD:
setInputView(_keyboardView);
setInputView(_keyboardViewParent);
break;

case CHANGE_METHOD_PICKER:
Expand Down Expand Up @@ -477,4 +488,19 @@ private View inflate_view(int layout)
{
return View.inflate(new ContextThemeWrapper(this, _config.theme), layout, null);
}

@RequiresApi(api = Build.VERSION_CODES.R)
@Nullable
@Override
public InlineSuggestionsRequest onCreateInlineSuggestionsRequest(@NonNull Bundle uiExtras)
{
return _inlineAutofill.onCreateInlineSuggestionsRequest(uiExtras);
}

@RequiresApi(api = Build.VERSION_CODES.R)
@Override
public boolean onInlineSuggestionsResponse(@NonNull InlineSuggestionsResponse response)
{
return _inlineAutofill.onInlineSuggestionsResponse(this, response);
}
}
1 change: 0 additions & 1 deletion srcs/juloo.keyboard2/Keyboard2View.java
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ public WindowInsets onApplyWindowInsets(WindowInsets wi)
protected void onDraw(Canvas canvas)
{
// Set keyboard background opacity
getBackground().setAlpha(_config.keyboardOpacity);
float y = _tc.margin_top;
for (KeyboardData.Row row : _keyboard.rows)
{
Expand Down