diff --git a/.github/workflows/api-verification.yml b/.github/workflows/api-verification.yml index 786e8ebad2d..443adb471f3 100644 --- a/.github/workflows/api-verification.yml +++ b/.github/workflows/api-verification.yml @@ -67,6 +67,8 @@ jobs: - name: "Verify API for libkeymancore*.so (${{ steps.environment_step.outputs.GIT_BRANCH }}, branch ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}, by ${{ steps.environment_step.outputs.GIT_USER }})" run: | + echo "Verify API for libkeymancore*.so (${{ steps.environment_step.outputs.GIT_BRANCH }}, branch ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}, by ${{ steps.environment_step.outputs.GIT_USER }}):" >> $GITHUB_STEP_SUMMARY + BIN_PACKAGE=$(ls "${GITHUB_WORKSPACE}/artifacts/" | grep "${PKG_NAME}[0-9]*_${{ steps.environment_step.outputs.VERSION }}-1${{ steps.environment_step.outputs.PRERELEASE_TAG }}+$(lsb_release -c -s)1_amd64.deb") cd ${{ github.workspace }}/keyman/linux ./scripts/deb-packaging.sh \ @@ -93,19 +95,19 @@ jobs: if: needs.api_verification.result == 'success' run: | echo "RESULT=success" >> $GITHUB_ENV - echo "MSG=Package build succeeded" >> $GITHUB_ENV + echo "MSG=API verification succeeded" >> $GITHUB_ENV - name: Set cancelled if: needs.api_verification.result == 'cancelled' run: | echo "RESULT=error" >> $GITHUB_ENV - echo "MSG=Package build cancelled" >> $GITHUB_ENV + echo "MSG=API verification cancelled" >> $GITHUB_ENV - name: Set failure if: needs.api_verification.result == 'failure' run: | echo "RESULT=failure" >> $GITHUB_ENV - echo "MSG=Package build failed" >> $GITHUB_ENV + echo "MSG=API verification failed" >> $GITHUB_ENV - name: Set final status run: | diff --git a/.github/workflows/deb-packaging.yml b/.github/workflows/deb-packaging.yml index 9c374f5d050..52c485aa658 100644 --- a/.github/workflows/deb-packaging.yml +++ b/.github/workflows/deb-packaging.yml @@ -116,7 +116,7 @@ jobs: strategy: fail-fast: true matrix: - dist: [focal, jammy, noble] + dist: [focal, jammy, noble, oracular] steps: - name: Checkout @@ -142,7 +142,7 @@ jobs: strategy: fail-fast: true matrix: - dist: [oracular] + dist: [plucky] steps: - name: Checkout diff --git a/.gitignore b/.gitignore index 772784fdb8c..6c8fbfbec84 100644 --- a/.gitignore +++ b/.gitignore @@ -183,3 +183,6 @@ lcov.info /keyman*.buildinfo /keyman*.changes /keyman*.tar.?z + +# flag file for build script +.configured diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ebf41b87d1..6216a806143 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,7 @@ # Contributing to Keyman +(Keyman team members, see also the [onboarding](https://docs.google.com/document/d/1i6fBi9K38-LitcJZiRfAvRu1-7H0iQ_op5kxDMdhSec/edit?usp=sharing) doc) + ⭐ Thank you for your contribution! ⭐ The following is a set of guidelines for contributing to Keyman, Keyman diff --git a/HISTORY.md b/HISTORY.md index 01762fcc2c9..d5ad1a589fd 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,215 @@ # Keyman Version History +## 18.0.153 alpha 2024-12-05 + +* feat(developer,common): verify normalization of strings (#12748) +* chore(core): Add link to Keyman Glossary (#12774) +* test(common/web/types): unit tests for file-types (#12716) + +## 18.0.152 alpha 2024-12-04 + +* refactor(mac): pass kmx data blob to keyman core instead of file path (#12760) +* fix(developer): honour provided script when checking for matching scripts (#12768) +* chore(common): rename test files (#12709) +* fix(common): rename test file (#12770) + +## 18.0.151 alpha 2024-12-03 + +* feat(android): Enhance how ENTER key is handled for FV and KMSample2 (#12745) +* feat(developer): report on mismatching lang tag scripts when building keyboard-info (#12753) + +## 18.0.150 alpha 2024-12-02 + +* fix(core,developer): use `NDEBUG` flag to disable assertions in release build (#12715) + +## 18.0.149 alpha 2024-12-01 + +* refactor(developer): unify test action (#12736) + +## 18.0.148 alpha 2024-11-29 + +* test(common/web/types): unit tests for unicodeset-parser-api (#12714) +* chore(developer): rename test files (#12707) +* feat(core,linux,developer,windows): implement loading KMX from blob (#12721) +* chore(common): add offline support for emscripten (#12740) + +## 18.0.147 alpha 2024-11-28 + +* docs(android): Add android/docs/internal/README (#12717) +* test(common/web/types): unit tests for string-list (#12702) +* docs(common): linux and macOS emscripten setup (#12701) +* refactor(developer): output number of tests when running on TC (#12710) +* refactor(common): output number of tests when running on TC (#12719) +* chore(web): rename file missed in #12704 (#12720) +* fix(core): permanently disable logging (#12724) +* fix(linux): disable assertions in release builds of ibus-keyman (#12725) +* chore(common): improve offline builds (#12739) + +## 18.0.146 alpha 2024-11-27 + +* test(developer): kmcmplib compiler unit tests 5 (#12612) +* refactor(common): move all lexical model types into `LexicalModelTypes` container (#12712) +* refactor(common): move remaining LDML keyboard types into `LdmlKeyboardTypes` (#12713) +* chore(web): rename test files and folders (#12704) +* chore(core): rename test files (#12705) +* chore(linux): rename test files (#12706) + +## 18.0.145 alpha 2024-11-26 + +* docs(windows): update emscripten bash setup (#12700) +* chore(common): Add link to onboarding doc to `CONTRIBUTING.md` (#12697) + +## 18.0.144 alpha 2024-11-25 + +* chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /developer/src/server/src/win32/trayicon/addon-src (#12687) +* chore(developer): make package subfile description fully optional (#12665) +* fix(developer): box package compiler info fields (#12666) +* fix(developer): correct whitespace handling in virtual keys and remove partially implemented virtual key series in kmcmplib compiler (#12604) + +## 18.0.143 alpha 2024-11-22 + +* chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 (#12685) + +## 18.0.142 alpha 2024-11-20 + +* chore(common): Update CODEOWNERS (#12680) + +## 18.0.141 alpha 2024-11-15 + +* chore(linux): add support for Ubuntu 25.04 Plucky Puffin (#12675) + +## 18.0.140 alpha 2024-11-13 + +* chore(common): Add 17.0.330 - 17.0.332 to version history (#12663) +* fix(developer): reconnect `--full-test` in kmcmplib build and enable for CI (#12631) +* docs(developer): kmc-generate (#12647) + +## 18.0.139 alpha 2024-11-12 + +* fix(windows): help links updated (#12646) + +## 18.0.138 alpha 2024-11-08 + +* fix(common): check for invalid markers (#12613) +* chore: update minimum versions (#12632) +* fix(windows): correct path to output file in publish step for fv keyboards (#12637) +* chore(core): move API docs from help.keyman.com (#12642) +* feat(developer): kmc generate (#11014) +* feat(developer): kmc-copy (#12555) +* feat(developer): add GitHub and Cloud support to kmc-copy (#12586) + +## 18.0.137 alpha 2024-11-07 + +* fix(windows): correct engine help source path for upload (#12625) +* fix(developer): use 'N' for nomatch store debug strings (regression in #12107) (#12629) +* chore(developer): skip masaram_gondi in kmcmplib full test (#12630) +* feat(developer): analyze osk-char-use merge with existing mapping file (#12622) +* feat(developer): Report key 'address' in validation failures in layout compiler (#12588) + +## 18.0.136 alpha 2024-11-06 + +* fix(developer): handle merge commits when checking git log date (#12627) + +## 18.0.135 alpha 2024-11-05 + +* fix(developer): handle paste of TSV into Wordlist grid (#12594) +* fix(developer): handle missing files in kmc-kmn (#12595) +* fix(developer): handle missing files in kmc-model (#12596) +* refactor(android): move Android Engine help in-repo (#12598) +* refactor(ios): move ios Engine help in-repo (#12599) +* refactor(windows): move windows Engine help in-repo (#12600) +* refactor(web): move web engine help to app repo (#12601) +* docs: Update websites readme with debug info (#12602) +* fix(developer): create Server config directory before options save (#12608) +* chore(linux): add support for Ubuntu 25.04 Plucky Puffin (#12614) +* fix(linux): properly check for missing dependencies (#12615) +* fix(linux): set environment variable for rendering of downloads dialog (#12616) + +## 18.0.134 alpha 2024-11-04 + +* (#12606) + +## 18.0.133 alpha 2024-11-01 + +* test(developer): kmcmplib compiler unit tests 4 (#12489) + +## 18.0.132 alpha 2024-10-30 + +* feat(windows): kmdevlink app (#12552) + +## 18.0.131 alpha 2024-10-25 + +* chore(android,windows): Update Crowdin strings for Khmer (#12574) +* refactor(developer): add kps-file-reader and kps-file-writer (#12545) +* fix(mac): make modifiers operational in OSK (#12556) +* fix(mac): support missing alt layers in OSK (#12565) + +## 18.0.130 alpha 2024-10-24 + +* fix(android/engine): Increase robustness when checking package kmp.json languages (#12567) +* chore(ios): support xcode 16 build (#12570) + +## 18.0.129 alpha 2024-10-21 + +* chore(mac): support Xcode 16 build (#12554) + +## 18.0.128 alpha 2024-10-14 + +* docs(developer): add refs to Keyman MIME types (#12540) + +## 18.0.127 alpha 2024-10-12 + +* fix(developer): use TextDecoder to convert Uint8Array to string (#12537) + +## 18.0.126 alpha 2024-10-11 + +* test(common): add markdown link check test for product documentation (#12472) +* chore(linux): improve output if `dpkg-gensymbols` fails and run other tests (#12527) + +## 18.0.125 alpha 2024-10-10 + +* chore(common): allow to run `build.sh` scripts in `bashdb` debugger (#12518) +* chore(linux): Improve output of API Verification (#12522) +* chore(linux): allow to skip API change (#12519) +* fix(linux): fix problem with API checks with merge commits (#12520) +* refactor(web): move `KeyboardObject` type to `common/web/types` (#12514) + +## 18.0.124 alpha 2024-10-09 + +* chore(common): fix links in minimum-versions.md (#12507) +* fix(developer): use richedit in debug memo to support Egyptian cartouches (#12464) +* feat(android): Add controls for auto-correct (#12443) + +## 18.0.123 alpha 2024-10-08 + +* chore(developer,common): deps: replace xml2js with fast-xml-parser (#12502) +* chore(ios): renew certificate (#12512) + +## 18.0.122 alpha 2024-10-07 + +* feat(mac): both option keys generate right alt if no left alt mapping (#12458) +* chore(common): improve configuration detection for hextobin (#12481) + +## 18.0.121 alpha 2024-10-03 + +* docs(developer): Fix image links in help (#12488) +* fix(oem/fv): Update keyboard versions and names for fv_all.kmp 13.1 (#12486) +* feat(common): unified XML parser/writer (#12482) + +## 18.0.120 alpha 2024-10-02 + +* chore(common): Add note on troubleshooting website errors (#12487) +* docs(common): mention `KEYMAN_USE_NVM` in minimum versions doc (#12490) +* docs(web): fix paths to several help pages (#12491) +* docs(web): fix structure of test document (#12492) + +## 18.0.119 alpha 2024-09-28 + +* refactor(developer): copy dev 17.0 help into repo (#12427) +* fix(developer): warn before importing over touch layout (#12478) +* chore(linux): display branch name with API verification (#12480) +* docs(core): Update kmx-plus-file-format.md (#12479) + ## 18.0.118 alpha 2024-09-26 * chore(developer): add context/options (#11566) @@ -836,6 +1046,27 @@ * chore(common): move to 18.0 alpha (#10713) * chore: move to 18.0 alpha +## 17.0.332 stable 2024-11-06 + +* fix(developer): create Server config directory before options save (#12609) +* fix(developer): handle merge commits when checking git log date (#12628) +* fix(linux): set environment variable for rendering of downloads dialog (#12617) + +## 17.0.331 stable 2024-10-30 + +* fix(android): Hide suggestion banner on password fields (#12466) +* fix(common): declare dep on @keymanapp/ldml-keyboard-constants (#12475) +* fix(oem/fv): Update keyboard versions and names for fv_all.kmp (#12504) +* chore(ios): renew certificate (#12513) +* fix(developer): prevent invalid string ids (#12524) +* fix(developer): ignore excess whitespace in `` attribute (#12523) + +## 17.0.330 stable 2024-09-16 + +* refactor(android): Move Sentry and APK to publish task (#12392) +* fix(developer): rewrite ldml visual keyboard compiler (#12406) +* fix(developer): check vars string usage before definition (#12407) + ## 17.0.329 stable 2024-09-09 * chore(android,ios): Add ojibwa ifinal/rdot keyboards to FirstVoices (#12020) diff --git a/VERSION.md b/VERSION.md index 49dcd615789..153289471d0 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.119 \ No newline at end of file +18.0.154 \ No newline at end of file diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index 4fb1c567922..5ca3de5807f 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -11,6 +11,7 @@ import com.keyman.engine.KMManager; import com.keyman.engine.KMManager.KeyboardType; import com.keyman.engine.KMHardwareKeyboardInterpreter; +import com.keyman.engine.KMManager.SuggestionType; import com.keyman.engine.KeyboardEventHandler.OnKeyboardEventListener; import com.keyman.engine.R; import com.keyman.engine.data.Keyboard; @@ -169,8 +170,9 @@ public void onStartInput(EditorInfo attribute, boolean restarting) { if (kbInfo != null) { String langId = kbInfo.getLanguageID(); SharedPreferences prefs = appContext.getSharedPreferences(appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); - boolean mayPredict = prefs.getBoolean(KMManager.getLanguagePredictionPreferenceKey(langId), true); - KMManager.setBannerOptions(mayPredict); + int maySuggest = prefs.getInt(KMManager.getLanguageAutoCorrectionPreferenceKey(langId), KMManager.KMDefault_Suggestion); + // Enable banner if maySuggest is not SuggestionType.SUGGESTIONS_DISABLED (0) + KMManager.setBannerOptions(maySuggest != SuggestionType.SUGGESTIONS_DISABLED.toInt()); } else { KMManager.setBannerOptions(false); } diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java index 75116bad8cc..977489f40a9 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java @@ -16,9 +16,13 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; @@ -55,50 +59,6 @@ public final class LanguageSettingsActivity extends AppCompatActivity { private final static String TAG = "LanguageSettingsAct"; - private class PreferenceToggleListener implements View.OnClickListener { - String prefsKey; - String lgCode; - - public PreferenceToggleListener(String prefsKey, String lgCode) { - this.prefsKey = prefsKey; - this.lgCode = lgCode; - } - - @Override - public void onClick(View v) { - // For predictions/corrections toggle - SwitchCompat toggle = (SwitchCompat) v; - - SharedPreferences.Editor prefEditor = prefs.edit(); - - // predictionsToggle overrides correctionToggle and correctionsTextView - if (prefsKey.endsWith(KMManager.predictionPrefSuffix)) { - boolean override = toggle.isChecked(); - overrideCorrectionsToggle(override); - } - - // This will allow preemptively making settings for languages without models. - // Seems more trouble than it's worth to block this. - prefEditor.putBoolean(prefsKey, toggle.isChecked()); - prefEditor.apply(); - - // Don't use/apply language modeling settings for languages without models. - if (associatedLexicalModel.isEmpty()) { - return; - } - - Keyboard kbInfo = KMManager.getCurrentKeyboardInfo(context); - if(kbInfo != null) { - // If the active keyboard is for this language, immediately enact the new pref setting. - String kbdLgCode = kbInfo.getLanguageID(); - if (kbdLgCode.equals(lgCode)) { - // Not only registers the model but also applies our modeling preferences. - KMManager.registerAssociatedLexicalModel(lgCode); - } - } - } - } - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -139,33 +99,48 @@ public void onCreate(Bundle savedInstanceState) { FilteredKeyboardsAdapter adapter = new FilteredKeyboardsAdapter(context, KeyboardPickerActivity.getInstalledDataset(context), lgCode); - // The following two layouts/toggles will need to link with these objects. + // The following radio group will need to link with these objects. Context appContext = this.getApplicationContext(); prefs = appContext.getSharedPreferences(appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); - boolean mayPredict = prefs.getBoolean(KMManager.getLanguagePredictionPreferenceKey(lgCode), true); - boolean mayCorrect = prefs.getBoolean(KMManager.getLanguageCorrectionPreferenceKey(lgCode), true); - - RelativeLayout layout = (RelativeLayout)findViewById(R.id.corrections_toggle); + int maySuggest = prefs.getInt(KMManager.getLanguageAutoCorrectionPreferenceKey(lgCode), KMManager.KMDefault_Suggestion); - correctionsTextView = (TextView) layout.findViewById(R.id.text1); - correctionsTextView.setText(getString(R.string.enable_corrections)); - correctionsToggle = layout.findViewById(R.id.toggle); - correctionsToggle.setChecked(mayCorrect); // Link to persistent option storage! Also needs handler. - String prefsKey = KMManager.getLanguageCorrectionPreferenceKey(lgCode); - correctionsToggle.setOnClickListener(new PreferenceToggleListener(prefsKey, lgCode)); + // Initialize Radio button group change listeners + RadioGroup radioGroup = (RadioGroup) findViewById(R.id.suggestion_radio_group); + radioGroup.clearCheck(); - layout = (RelativeLayout)findViewById(R.id.predictions_toggle); + int[] RadioButtonArray = { + R.id.suggestion_radio_0, + R.id.suggestion_radio_1, + R.id.suggestion_radio_2, + R.id.suggestion_radio_3}; + RadioButton radioButton = (RadioButton)radioGroup.findViewById(RadioButtonArray[maySuggest]); + radioButton.setChecked(true); - textView = (TextView) layout.findViewById(R.id.text1); - textView.setText(getString(R.string.enable_predictions)); - SwitchCompat predictionsToggle = layout.findViewById(R.id.toggle); - predictionsToggle.setChecked(mayPredict); // Link to persistent option storage! Also needs handler. - prefsKey = KMManager.getLanguagePredictionPreferenceKey(lgCode); - predictionsToggle.setOnClickListener(new PreferenceToggleListener(prefsKey, lgCode)); + radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, @IdRes int checkId) { + RadioButton checkedButton = (RadioButton)radioGroup.findViewById(checkId); + int index = radioGroup.indexOfChild(checkedButton); + KMManager.setMaySuggest(lgCode, KMManager.SuggestionType.fromInt(index)); + + // Don't use/apply language modeling settings for languages without models. + if (associatedLexicalModel.isEmpty()) { + return; + } - overrideCorrectionsToggle(mayPredict); + Keyboard kbInfo = KMManager.getCurrentKeyboardInfo(context); + if(kbInfo != null) { + // If the active keyboard is for this language, immediately enact the new pref setting. + String kbdLgCode = kbInfo.getLanguageID(); + if (kbdLgCode.equals(lgCode)) { + // Not only registers the model but also applies our modeling preferences. + KMManager.registerAssociatedLexicalModel(lgCode); + } + } + } + }); - layout = (RelativeLayout)findViewById(R.id.model_picker); + RelativeLayout layout = (RelativeLayout)findViewById(R.id.model_picker); textView = (TextView) layout.findViewById(R.id.text1); textView.setText(getString(R.string.model_label)); diff --git a/android/KMAPro/kMAPro/src/main/res/values-it-rIT/strings.xml b/android/KMAPro/kMAPro/src/main/res/values-it-rIT/strings.xml index a475ae37255..de474402c06 100644 --- a/android/KMAPro/kMAPro/src/main/res/values-it-rIT/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values-it-rIT/strings.xml @@ -68,7 +68,7 @@ Regola altezza tastiera - Adjust longpress delay + Regola ritardo pressione prolungata Didascalia barra spaziatrice @@ -89,11 +89,11 @@ Non mostrare la didascalia sulla barra spaziatrice Vibra durante la digitazione - + Mostra sempre il banner - + Da attuare - + Quando è spento, mostrato solo quando il testo predittivo è abilitato Consenti l\'invio di segnalazioni di crash attraverso la rete @@ -126,13 +126,13 @@ Ripristina impostazioni predefinite - Delay Time: %1$.1f seconds + Tempo ritardo: %1$.1f secondi - Delay time longer + Tempo ritardo maggiore - Delay time shorter + Tempo ritardo minore - Longpress delay time slider + Cursore tempo ritardo pressione prolungata Cerca o digita URL diff --git a/android/KMAPro/kMAPro/src/main/res/values-km-rKH/strings.xml b/android/KMAPro/kMAPro/src/main/res/values-km-rKH/strings.xml index f465074f8ba..c1363c161ad 100644 --- a/android/KMAPro/kMAPro/src/main/res/values-km-rKH/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values-km-rKH/strings.xml @@ -67,6 +67,8 @@ កែកម្ពស់ក្ដារចុច + កែសម្រួលការពន្យារពេលរបស់ longpress + ពាក្យលើគ្រាប់ចុចដកឃ្លា ក្តារចុច @@ -86,11 +88,11 @@ កុំបង្ហាញពាក្យនៅលើគ្រាប់ចុចដកឃ្លា ញ័រពេលវាយអក្សរ​ - + បង្ហាញ​បដា​ជានិច្ច - + ត្រូវ​អនុវត្ត - + បើ​បិទ បដា​នឹង​បង្ហាញ​តែ​នៅ​ពេលបើក​ការណែនាំ​ពាក្យស្វ័យប្រវត្តិប៉ុណ្ណោះ អនុញ្ញាត​ឱ្យ​ផ្ញើ​របាយការណ៍​អំពី​ការគាំង​តាម​បណ្ដាញ @@ -122,6 +124,14 @@ បង្វិលឧបករណ៍ដើម្បីកែបញ្ឈ និងផ្ដេក ប្ដូរ​កំណត់​ទៅលំនាំដើម + + រយៈពេលពន្យារ: %1$.1f វិនាទី + + ពន្យារពេលយូរជាងមុន + + ពន្យារពេលតិចជាងមុន + + របារំកិលពន្យារពេល longpress ស្វែងរក ឬវាយ​បញ្ចូល URL diff --git a/android/KMEA/app/src/main/assets/android-host.js b/android/KMEA/app/src/main/assets/android-host.js index 5e5d7241235..21f783ffc55 100644 --- a/android/KMEA/app/src/main/assets/android-host.js +++ b/android/KMEA/app/src/main/assets/android-host.js @@ -229,11 +229,23 @@ function deregisterModel(modelID) { keyman.removeModel(modelID); } -function enableSuggestions(model, mayPredict, mayCorrect) { +function enableSuggestions(model, suggestionType) { // Set the options first so that KMW's ModelManager can properly handle model enablement states // the moment we actually register the new model. - keyman.core.languageProcessor.mayPredict = mayPredict; - keyman.core.languageProcessor.mayCorrect = mayCorrect; + // Use console_debug + console_debug('enableSuggestions(model, maySuggest='+suggestionType+')'); + const suggestionSettings = [ + // mayPredict, mayCorrect, mayAutoCorrect + [false, false, false], // 0 = SuggestionType.SUGGESTIONS_DISABLED + [true, false, false], // 1 = SuggestionType.PREDICTIONS_ONLY + [true, true, false], // 2 = SuggestionType.PREDICTIONS_WITH_CORRECTIONS + [true, true, true], // 3 = SuggestionType.PREDICTIONS_WITH_AUTO_CORRECT + ]; + const t = suggestionSettings[suggestionType] + ? suggestionSettings[suggestionType] : suggestionSettings[0]; + keyman.core.languageProcessor.mayPredict = t[0]; + keyman.core.languageProcessor.maySuggest = t[1]; + // keyman.core.languageProcessor.mayAutoCorrect = t[2]; registerModel(model); } diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java index 1e28e4af0b3..5ce294909c1 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java @@ -16,6 +16,7 @@ import com.keyman.engine.KeyboardEventHandler.EventType; import com.keyman.engine.KMManager; import com.keyman.engine.KMManager.KeyboardType; +import com.keyman.engine.KMManager.SuggestionType; import com.keyman.engine.util.KMLog; import com.keyman.engine.data.Keyboard; @@ -165,7 +166,9 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); boolean modelPredictionPref = false; if (!KMManager.getMayPredictOverride() && KMManager.currentLexicalModel != null) { - modelPredictionPref = prefs.getBoolean(KMManager.getLanguagePredictionPreferenceKey(KMManager.currentLexicalModel.get(KMManager.KMKey_LanguageID)), true); + modelPredictionPref = prefs.getInt(KMManager.getLanguageAutoCorrectionPreferenceKey( + KMManager.currentLexicalModel.get(KMManager.KMKey_LanguageID)), KMManager.KMDefault_Suggestion) + != SuggestionType.SUGGESTIONS_DISABLED.toInt(); } KMManager.setBannerOptions(modelPredictionPref); RelativeLayout.LayoutParams params = KMManager.getKeyboardLayoutParams(); diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index 592f4be2a15..e776476aff6 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -192,6 +192,35 @@ public enum EnterModeType { DEFAULT, // Default ENTER action } + // Enum for whether the suggestion banner allows predictions, corrections, auto-corrections + public enum SuggestionType { + // Suggestion Disabled - No Predictions, No corrections, No auto-corrections + SUGGESTIONS_DISABLED, + + // Suggestions Enabled + PREDICTIONS_ONLY, // Predictions with no corrections + PREDICTIONS_WITH_CORRECTIONS, // Predictions with corrections + PREDICTIONS_WITH_AUTO_CORRECT; // Predictions with auto-corrections + + public static SuggestionType fromInt(int mode) { + switch (mode) { + case 0: + return SUGGESTIONS_DISABLED; + case 1: + return PREDICTIONS_ONLY; + case 2: + return PREDICTIONS_WITH_CORRECTIONS; + case 3: + return PREDICTIONS_WITH_AUTO_CORRECT; + } + return SUGGESTIONS_DISABLED; + } + + public int toInt() { + return this.ordinal(); + } + } + protected static InputMethodService IMService; private static boolean debugMode = false; @@ -220,6 +249,7 @@ public enum EnterModeType { public final static String predictionPrefSuffix = ".mayPredict"; public final static String correctionPrefSuffix = ".mayCorrect"; + public final static String autoCorrectionPrefSuffix = ".mayAutoCorect"; // Special override for when the keyboard may have haptic feedback when typing. // haptic feedback disabled for hardware keystrokes @@ -315,6 +345,8 @@ public enum EnterModeType { public static final int KMMinimum_LongpressDelay = 300; public static final int KMMaximum_LongpressDelay = 1500; + // Default prediction/correction setting + public static final int KMDefault_Suggestion = SuggestionType.PREDICTIONS_WITH_CORRECTIONS.toInt(); // Keyman files protected static final String KMFilename_KeyboardHtml = "keyboard.html"; @@ -707,6 +739,10 @@ public static String getLanguageCorrectionPreferenceKey(String langID) { return langID + correctionPrefSuffix; } + public static String getLanguageAutoCorrectionPreferenceKey(String langID) { + return langID + autoCorrectionPrefSuffix; + } + public static void hideSystemKeyboard() { if (SystemKeyboard != null) { SystemKeyboard.hideKeyboard(); @@ -1350,6 +1386,18 @@ public static boolean getMayPredictOverride() { return mayPredictOverride; } + /** + * Store SuggestionType as int in preference + * @param languageID as String + * @param suggestType SuggestionType + */ + public static void setMaySuggest(String languageID, SuggestionType suggestType) { + SharedPreferences prefs = appContext.getSharedPreferences(appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(KMManager.getLanguageAutoCorrectionPreferenceKey(languageID), suggestType.toInt()); + editor.commit(); + } + /** * Determines if the InputType field is a numeric field * @param inputType @@ -1462,24 +1510,23 @@ public static boolean registerLexicalModel(HashMap lexicalModelI model = model.replaceAll("\'", "\\\\'"); // Double-escaped-backslash b/c regex. model = model.replaceAll("\"", "'"); - // When entering password field, mayPredict should override to false + // When entering password field, maySuggest should override to disabled SharedPreferences prefs = appContext.getSharedPreferences(appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); - boolean mayPredict = (mayPredictOverride) ? false : - prefs.getBoolean(getLanguagePredictionPreferenceKey(languageID), true); - boolean mayCorrect = prefs.getBoolean(getLanguageCorrectionPreferenceKey(languageID), true); + int maySuggest = mayPredictOverride ? SuggestionType.SUGGESTIONS_DISABLED.toInt() : + prefs.getInt(getLanguageAutoCorrectionPreferenceKey(languageID), KMDefault_Suggestion); RelativeLayout.LayoutParams params; if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP) && !InAppKeyboard.shouldIgnoreTextChange() && modelFileExists) { params = getKeyboardLayoutParams(); // Do NOT re-layout here; it'll be triggered once the banner loads. - InAppKeyboard.loadJavascript(KMString.format("enableSuggestions(%s, %s, %s)", model, mayPredict, mayCorrect)); + InAppKeyboard.loadJavascript(KMString.format("enableSuggestions(%s, %d)", model, maySuggest)); } if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_SYSTEM) && !SystemKeyboard.shouldIgnoreTextChange() && modelFileExists) { params = getKeyboardLayoutParams(); // Do NOT re-layout here; it'll be triggered once the banner loads. - SystemKeyboard.loadJavascript(KMString.format("enableSuggestions(%s, %s, %s)", model, mayPredict, mayCorrect)); + SystemKeyboard.loadJavascript(KMString.format("enableSuggestions(%s, %d)", model, maySuggest)); } return true; } diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/packages/JSONUtils.java b/android/KMEA/app/src/main/java/com/keyman/engine/packages/JSONUtils.java index d7645052172..80fa18bc882 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/packages/JSONUtils.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/packages/JSONUtils.java @@ -38,6 +38,9 @@ public static JSONArray getLanguages() { return new JSONArray(); } File[] packages = resourceRoot.listFiles(); + if (packages == null) { + return new JSONArray(); + } JSONArray languagesArray = new JSONArray(); JSONParser parser = new JSONParser(); @@ -60,6 +63,9 @@ public static JSONArray getLanguages() { String kbdFilename = pkg.getName() + "/" + kbdID + ".js"; // Merge languages + if (!kmpKeyboardObj.has("languages")) { + continue; + } JSONArray kmpLanguageArray = kmpKeyboardObj.getJSONArray("languages"); for (int j=0; j - - - + + + + + + + + + + + + - - - - diff --git a/android/KMEA/app/src/main/res/values-it-rIT/strings.xml b/android/KMEA/app/src/main/res/values-it-rIT/strings.xml index da1e3531a2b..7dce8252b27 100644 --- a/android/KMEA/app/src/main/res/values-it-rIT/strings.xml +++ b/android/KMEA/app/src/main/res/values-it-rIT/strings.xml @@ -133,10 +133,15 @@ %1$s tastiera installata Tastiera eliminata - + Abilita correzioni - + Abilita previsioni + + Disabilita suggerimenti + Solo previsioni + Previsioni con correzioni + Previsioni con correzioni automatiche Dizionario diff --git a/android/KMEA/app/src/main/res/values-km-rKH/strings.xml b/android/KMEA/app/src/main/res/values-km-rKH/strings.xml index 8763efa4701..a687e6d3770 100644 --- a/android/KMEA/app/src/main/res/values-km-rKH/strings.xml +++ b/android/KMEA/app/src/main/res/values-km-rKH/strings.xml @@ -131,10 +131,15 @@ បានដំឡើង​ក្ដារចុច %1$s ក្ដារចុចត្រូវបានលុប - + បើក​ការកែពាក្យ - + បើក​ការណែនាំពាក្យ​ស្វ័យប្រវត្តិ + + បិទការព្យាករណ៍ពាក្យ + អនុញ្ញាតតែមុខងារព្យាករណ៍ពាក្យ + អនុញ្ញាតមុខងារព្យាករណ៍ពាក្យ និងកែពាក្យ + អនុញ្ញាតមុខងារព្យាករណ៍ពាក្យ និងកែពាក្យដោយស្វ័យប្រវត្តិ បញ្ជី​ពាក្យ diff --git a/android/KMEA/app/src/main/res/values/strings.xml b/android/KMEA/app/src/main/res/values/strings.xml index 506626cd244..5c5d6f3173e 100644 --- a/android/KMEA/app/src/main/res/values/strings.xml +++ b/android/KMEA/app/src/main/res/values/strings.xml @@ -211,12 +211,21 @@ Keyboard deleted - + Enable corrections - + Enable predictions + + Disable suggestions + + Predictions only + + Predictions with corrections + + Predictions with auto-corrections + Dictionary diff --git a/android/KMEA/app/src/test/java/com/keyman/engine/packages/JSONUtilsTest.java b/android/KMEA/app/src/test/java/com/keyman/engine/packages/JSONUtilsTest.java index cf8ddadfbe3..689dd72e400 100644 --- a/android/KMEA/app/src/test/java/com/keyman/engine/packages/JSONUtilsTest.java +++ b/android/KMEA/app/src/test/java/com/keyman/engine/packages/JSONUtilsTest.java @@ -19,6 +19,7 @@ @RunWith(RobolectricTestRunner.class) public class JSONUtilsTest { private static final File TEST_RESOURCE_ROOT = new File("test_resources", "packages"); + private static final File TEST_INVALID_RESOURCE_ROOT = new File("test_resources", "invalid_packages"); private static final String TAG = "JSONUtilsTest"; @Before @@ -52,6 +53,18 @@ public void test_getLanguages() { } } + /** + * Test parsing null_languages/kmp.json which has no languages + */ + @Test + public void test_invalid_getLanguages() { + JSONUtils.initialize(TEST_INVALID_RESOURCE_ROOT); + JSONArray result = JSONUtils.getLanguages(); + final int EXPECTED_NUM_LANGUAGES = 0; + + Assert.assertEquals(EXPECTED_NUM_LANGUAGES, result.length()); + } + @Test public void test_findID() { JSONParser parser = new JSONParser(); diff --git a/android/KMEA/test_resources/invalid_packages/null_languages/kmp.json b/android/KMEA/test_resources/invalid_packages/null_languages/kmp.json new file mode 100644 index 00000000000..65e6e1e0073 --- /dev/null +++ b/android/KMEA/test_resources/invalid_packages/null_languages/kmp.json @@ -0,0 +1,127 @@ +{ + "system": { + "keymanDeveloperVersion": "11.0.1304.0", + "fileVersion": "7.0" + }, + "options": { + "graphicFile": "splash.bmp" + }, + "info": { + "name": { + "description": "Cameroon QWERTY" + }, + "version": { + "description": "6.0.2" + }, + "copyright": { + "description": "\u00A92018 SIL Cameroon" + }, + "author": { + "description": "Matthew Lee", + "url": "mailto:keyboards_cameroon@sil.org" + }, + "website": { + "description": "LangTechCameroon.info", + "url": "LangTechCameroon.info" + } + }, + "files": [ + { + "name": "Cameroon.ico", + "description": "File Cameroon.ico" + }, + { + "name": "sil_cameroon_qwerty.css", + "description": "File sil_cameroon_qwerty.css" + }, + { + "name": "AndikaAfr-R.ttf", + "description": "Font Andika Afr" + }, + { + "name": "sil_cameroon_qwerty.kvk", + "description": "File sil_cameroon_qwerty.kvk" + }, + { + "name": "sil_cameroon_qwerty.kmx", + "description": "Keyboard Cameroon QWERTY" + }, + { + "name": "splash.bmp", + "description": "File splash.bmp" + }, + { + "name": "welcome.htm", + "description": "File welcome.htm" + }, + { + "name": "e_chart.png", + "description": "File e_chart.png" + }, + { + "name": "e_tableau.png", + "description": "File e_tableau.png" + }, + { + "name": "helpIcon.png", + "description": "File helpIcon.png" + }, + { + "name": "ic_launcher.png", + "description": "File ic_launcher.png" + }, + { + "name": "icon.png", + "description": "File icon.png" + }, + { + "name": "QwertyColor.png", + "description": "File QwertyColor.png" + }, + { + "name": "sil-logo-blue.png", + "description": "File sil-logo-blue.png" + }, + { + "name": "kb.css", + "description": "File kb.css" + }, + { + "name": "sil_cameroon_qwerty.js", + "description": "File sil_cameroon_qwerty.js" + }, + { + "name": "globe.png", + "description": "File globe.png" + }, + { + "name": "longpress-qwerty.png", + "description": "File longpress-qwerty.png" + }, + { + "name": "modkeys-en-q.png", + "description": "File modkeys-en-q.png" + }, + { + "name": "modkeys-fr-q.png", + "description": "File modkeys-fr-q.png" + }, + { + "name": "kmp.inf", + "description": "Package information" + }, + { + "name": "kmp.json", + "description": "Package information (JSON)" + } + ], + "keyboards": [ + { + "name": "Cameroon QWERTY", + "id": "sil_cameroon_qwerty", + "version": "6.0.2", + "oskFont": "AndikaAfr-R.ttf", + "displayFont": "AndikaAfr-R.ttf" + } + ] +} diff --git a/android/README.md b/android/README.md index 2d1090574b1..6abb94161d5 100644 --- a/android/README.md +++ b/android/README.md @@ -27,14 +27,14 @@ yes | ~/Library/Android/sdk/tools/bin/sdkmanager --licenses ### Crash Reporting -Keyman for Android uses [Sentry](https://sentry.io) for crash reporting. The -analytics for Debug are associated with an App Bundle ID +Keyman for Android uses [Sentry](https://sentry.io) for crash reporting. The +analytics for Debug are associated with an App Bundle ID `com.tavultesoft.kmapro.debug`. ### Compiling From Command Line 1. Launch a command prompt and cd to the directory **keyman/android** -2. Run the top level build script `./build.sh configure build --debug` which will: +2. Run the top level build script `./build.sh configure build:engine build:app --debug` which will: * Compile KMEA (and its KMW dependency) * Download default keyboard and dictionary resources as needed * Compile KMAPro @@ -79,7 +79,7 @@ analytics for Debug are associated with an App Bundle ID Replace `SERIAL` with the device serial number listed in step 2. ### Compiling the app's offline help -Keyman for Android help is maintained in the Markdown files in android/help/. +Keyman for Android help is maintained in the Markdown files in android/docs/help. The script `/resources/build/build-help.inc.sh` uses the `pandoc` tool to convert the Markdown files into html. ```bash @@ -121,7 +121,7 @@ Building these projects follow the same steps as KMAPro: ## How to Build Keyman Engine for Android 1. Open a terminal or Git Bash prompt and go to the Android project folder (e.g. `cd ~/keyman/android/`) -2. Run `./build.sh --debug` +2. Run `./build.sh build:engine --debug` Keyman Engine for Android library (**keyman-engine.aar**) is now ready to be imported in any project. @@ -167,3 +167,10 @@ dependencies { ```` 5. include `import com.keyman.engine.*;` to use Keyman Engine in a class. + +### Keyman Engine for Android help content +Keyman Engine for Android help is maintained in the Markdown files in android/docs/engine/. + +## Design Documentation + +Internal design documents about features pertaining to Keyman for Android and Keyman Engine for Android are maintained in the Markdown files in android/docs/internal/. diff --git a/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java b/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java index 4ad462a76c1..438ed237dbc 100644 --- a/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java +++ b/android/Samples/KMSample2/app/src/main/java/com/keyman/kmsample2/SystemKeyboard.java @@ -130,6 +130,11 @@ public void onStartInput(EditorInfo attribute, boolean restarting) { super.onStartInput(attribute, restarting); KMManager.onStartInput(attribute, restarting); KMManager.resetContext(KeyboardType.KEYBOARD_TYPE_SYSTEM); + + // Determine special handling for ENTER key + int inputType = attribute.inputType; + KMManager.setEnterMode(attribute.imeOptions, inputType); + // User switched to a new input field so we should extract the text from input field // and pass it to Keyman Engine together with selection range InputConnection ic = getCurrentInputConnection(); diff --git a/android/build.sh b/android/build.sh index d876d882d77..e6d99278980 100755 --- a/android/build.sh +++ b/android/build.sh @@ -14,6 +14,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" builder_describe \ "Build Keyman Engine for Android, Keyman for Android, and FirstVoices Android app." \ + "@/resources/tools/check-markdown test:help" \ clean \ configure \ build \ @@ -23,6 +24,7 @@ builder_describe \ --upload-sentry+ \ ":engine=KMEA Keyman Engine for Android" \ ":app=KMAPro Keyman for Android" \ + ":help Online documentation" \ ":sample1=Samples/KMSample1 Sample app: KMSample1" \ ":sample2=Samples/KMSample2 Sample app: KMSample2" \ ":keyboardharness=Tests/KeyboardHarness Test app: KeyboardHarness" \ @@ -42,4 +44,13 @@ if builder_start_action clean; then builder_finish_action success clean fi -builder_run_child_actions configure build test publish +builder_run_child_actions configure build test + +function do_test_help() { + check-markdown "$KEYMAN_ROOT/android/docs/help" + check-markdown "$KEYMAN_ROOT/android/docs/engine" +} + +builder_run_action test:help do_test_help + +builder_run_child_actions publish \ No newline at end of file diff --git a/android/docs/engine/KMKeyboard/index.md b/android/docs/engine/KMKeyboard/index.md new file mode 100644 index 00000000000..774d0be6f95 --- /dev/null +++ b/android/docs/engine/KMKeyboard/index.md @@ -0,0 +1,30 @@ +--- +title: KMKeyboard class +--- + +## Summary + +The **`KMKeyboard`** class provides Keyman's methods for extending an Android WebView + +## Syntax + +```java +KMKeyboard.methodName() +``` + +## Description + +The KMKeyboard is the core class which provides most of the methods you will need to develop an in-app or system keyboard with Keyman Engine + + + +## Methods + +`getShouldShowHelpBubble()` +: get the stored preference whether to show the help bubble on the globe key + +`setShouldShowHelpBubble()` +: sets the stored preference whether to show the help bubble on the globe key + +`initKMKeyboard()` +: initialize the KMKeyboard WebView diff --git a/android/docs/engine/KMManager/addKeyboard.md b/android/docs/engine/KMManager/addKeyboard.md new file mode 100644 index 00000000000..f03048da470 --- /dev/null +++ b/android/docs/engine/KMManager/addKeyboard.md @@ -0,0 +1,108 @@ +--- +title: KMManager.addKeyboard() +--- + +## Summary + +The **`addKeyboard()`** method adds a keyboard into the keyboards list. + +## Syntax + +``` javascript +KMManager.addKeyboard(Context context, Keyboard keyboardInfo) +``` + +### Parameters + +`context` +: The context. + +`keyboardInfo` +: A `Keyboard` type of keyboard information. + +### Returns + +Returns `true` if the keyboard was added successfully, `false` +otherwise. + +## Description + +Use this method to include a keyboard in the keyboards list so that it +can be selected from the keyboards menu. If the keyboard with same +keyboard ID and language ID exists, it updates the existing keyboard +info. + + + +------------------------------------------------------------------------ + +## Syntax (Deprecated) + +``` javascript +KMManager.addKeyboard(Context context, HashMap keyboardInfo) +``` + +### Parameters + +`context` +: The context. + +`keyboardInfo` +: A dictionary of keyboard information with keys and values defined as + `HashMap`. + +### Returns + +Returns `true` if the keyboard was added successfully, `false` +otherwise. + +## Description + +Use this method to include a keyboard in the keyboards list so that it +can be selected from the keyboards menu. If the keyboard with same +keyboard ID and language ID exists, it updates the existing keyboard +info. + + + +------------------------------------------------------------------------ + +## Examples + +### Example: Using `addKeyboard()` + +The following script illustrate the use of `addKeyboard()`: + +``` javascript + // Add a custom keyboard + Keyboard kbInfo = new Keyboard( + "basic_kbdtam99", // Package ID - filename of the .kmp file + "basic_kbdtam99", // Keyboard ID - filename of the .js file + "Tamil 99 Basic", // Keyboard Name + "ta", // Language ID + "Tamil", // Language Name + "1.0", // Keyboard Version + null, // URL to help documentation if available + null, // URL to latest .kmp file + true, // Boolean to show this is a new keyboard in the keyboard picker + + // Font information of the .ttf font to use in KMSample2 (for example "aava1.ttf"). + // basic_kbdtam99 doesn't include a font. Can set blank "" or KMManager.KMDefault_KeyboardFont + // KMEA will use the font for the OSK, but the Android device determines the system font used for keyboard output + KMManager.KMDefault_KeyboardFont, // Font for KMSample2 + KMManager.KMDefault_KeyboardFont); // Font for OSK + + KMManager.addKeyboard(this, kbInfo); +``` + +## History + +Added syntax using Keyboard type parameter in Keyman Engine for Android +14.0. + +Deprecated syntax using the HashMap<String key, String value> +parameter in Keyman Engine for Android 14.0 + +## See also + +- [`removeKeyboard()`](removeKeyboard) diff --git a/android/docs/engine/KMManager/addKeyboardDownloadEventListener.md b/android/docs/engine/KMManager/addKeyboardDownloadEventListener.md new file mode 100644 index 00000000000..3b56762d8a2 --- /dev/null +++ b/android/docs/engine/KMManager/addKeyboardDownloadEventListener.md @@ -0,0 +1,46 @@ +--- +title: KMManager.addKeyboardDownloadEventListener() +--- + +## Summary + +The **`addKeyboardDownloadEventListener()`** method adds the specified +listener into the list of keyboard download event listeners. + +## Syntax + +``` javascript +KMManager.addKeyboardDownloadEventListener(OnKeyboardDownloadEventListener listener) +``` + +### Parameters + +`listener` +: The listener to receive keyboard download event notifications. + +## Description + +Use this method to add a listener to receive keyboard download event +notifications. The listener must implement +`KMManager.OnKeyboardDownloadEventListener` interface. + +## Examples + +### Example: Using `addKeyboardDownloadEventListener()` + +The following script illustrate the use of +`addKeyboardDownloadEventListener()`: + +``` javascript + @Override + protected void onResume() { + super.onResume(); + // ... + KMManager.addKeyboardDownloadEventListener(this); + // ... + } +``` + +## See also + +- [`removeKeyboardDownloadEventListener()`](removeKeyboardDownloadEventListener) diff --git a/android/docs/engine/KMManager/addKeyboardEventListener.md b/android/docs/engine/KMManager/addKeyboardEventListener.md new file mode 100644 index 00000000000..b8ee6e84d1a --- /dev/null +++ b/android/docs/engine/KMManager/addKeyboardEventListener.md @@ -0,0 +1,45 @@ +--- +title: KMManager.addKeyboardEventListener() +--- + +## Summary + +The **`addKeyboardEventListener()`** method adds the specified listener +into the list of keyboard event listeners. + +## Syntax + +``` javascript +KMManager.addKeyboardEventListener(OnKeyboardEventListener listener) +``` + +### Parameters + +`listener` +: The listener to receive keyboard event notifications. + +## Description + +Use this method to add a listener to receive keyboard event +notifications. The listener must implement +KMManager.OnKeyboardEventListener interface. + +## Examples + +### Example: Using `addKeyboardEventListener()` + +The following script illustrate the use of `addKeyboardEventListener()`: + +``` javascript + @Override + protected void onResume() { + super.onResume(); + // ... + KMManager.addKeyboardEventListener(this); + // ... + } +``` + +## See also + +- [`removeKeyboardEventListener()`](removeKeyboardEventListener) diff --git a/android/docs/engine/KMManager/addLexicalModel.md b/android/docs/engine/KMManager/addLexicalModel.md new file mode 100644 index 00000000000..72237277d8b --- /dev/null +++ b/android/docs/engine/KMManager/addLexicalModel.md @@ -0,0 +1,49 @@ +--- +title: KMManager.addLexicalModel() +--- + +## Summary +The **addLexicalModel()** method adds a lexical model into the lexical models list. + +## Syntax + +```javascript +KMManager.addLexicalModel(Context context, HashMap lexicalModelInfo) +``` + +### Parameters + +`context` +: The context. + +`lexicalModelInfo` +: A dictionary of lexical model information with keys and values defined as `HashMaplexicalModelInfo = new HashMap(); + lexicalModelInfo.put(KMManager.KMKey_PackageID, "example.ta.wordlist"); + lexicalModelInfo.put(KMManager.KMKey_LanguageID, "ta"); + lexicalModelInfo.put(KMManager.KMKey_LexicalModelID, "example.ta.wordlist"); + lexicalModelInfo.put(KMManager.KMKey_LexicalModelVersion, "1.0"); + KMManager.addLexicalModel(this, lexicalModelInfo); + + KMManager.registerLexicalModel(lexicalModelInfo); +``` + +## See also +* [registerLexicalModel()](registerLexicalModel) diff --git a/android/docs/engine/KMManager/advanceToNextInputMode.md b/android/docs/engine/KMManager/advanceToNextInputMode.md new file mode 100644 index 00000000000..486294b7545 --- /dev/null +++ b/android/docs/engine/KMManager/advanceToNextInputMode.md @@ -0,0 +1,31 @@ +--- +title: KMManager.advanceToNextInputMode() +--- + +## Summary +The **advanceToNextInputMode()** method switches to the next system keyboard input mode. + +## Syntax + +```javascript +KMManager.advanceToNextInputMode() +``` + +## Description +Use this method to switch to the next system keyboard. + + +## Examples + +### Example: Using `advanceToNextInputMode()` + +The following script illustrates the use of `advanceToNextInputMode()`: +```java + // Remove the second keyboard in the list + KMManager.removeKeyboard(this, 1); + + KMManager.advanceToNextInputMode(); +``` + +## See also +* [advanceToPreviousInputMethod()](advanceToPreviousInputMethod) diff --git a/android/docs/engine/KMManager/advanceToPreviousInputMethod.md b/android/docs/engine/KMManager/advanceToPreviousInputMethod.md new file mode 100644 index 00000000000..3d4b248d434 --- /dev/null +++ b/android/docs/engine/KMManager/advanceToPreviousInputMethod.md @@ -0,0 +1,32 @@ +--- +title: KMManager.advanceToPreviousInputMethod() +--- + +## Summary +The **advanceToPreviousInputMethod()** method switches to the previous system keyboard input mode. + +## Syntax + +```javascript +KMManager.advanceToPreviousInputMethod() +``` + +## Description +Use this method to switch to the previous system keyboard. + +When only 1 Keyman keyboard is installed, this is the default action for pressing the globe key. + +## Examples + +### Example: Using `advanceToPreviousInputMethod()` + +The following script illustrates the use of `advanceToPreviousInputMethod()`: +```java + // Remove the second keyboard in the list + KMManager.removeKeyboard(this, 1); + + KMManager.advanceToPreviousInputMethod(); +``` + +## See also +* [advanceToNextInputMode()](advanceToNextInputMode) diff --git a/android/docs/engine/KMManager/applyKeyboardHeight.md b/android/docs/engine/KMManager/applyKeyboardHeight.md new file mode 100644 index 00000000000..2830519c625 --- /dev/null +++ b/android/docs/engine/KMManager/applyKeyboardHeight.md @@ -0,0 +1,54 @@ +--- +title: KMManager.applyKeyboardHeight() +--- + +## Summary +The **applyKeyboardHeight()** method sets the height of the keyboard frame for +the device's current [screen orientation](https://developer.android.com/training/multiscreen/screensizes#TaskUseOriQuali) +(portrait vs landscape). + +## Syntax +```java +KMManager.applyKeyboardHeight(Context context, int height) +``` + +### Parameters + +`context` +: The context + +`height` +: The height of the keyboard frame in *density-independent pixels (dp)* + +## Description +Use this method when you want to increase or decrease the keyboard height for +the device in the current screen orientation. This height is independent from +the height of the suggestion banner frame. + +For reference, here's a table of the default Keyman keyboard heights for various devices and screen orientation. + + Device Type and Screen Orientation | Default height (dp) | +|-----------------------------------|---------------------| +| Default handset in portrait | 205 | +| Default handset in landscape | 150 | +| 7" tablet in portrait | 305 | +| 7" tablet in landscape | 200 | +| 10" tablet in portrait | 405 | +| 10" tablet in landscape | 300 | + +**Note:** This new keyboard height would be applied for all platforms, so an +adjusted keyboard height for a phone would appear too small for a tablet. + +## Examples + +### Example: Using `applyKeyboardHeight()` +The following script illustrates the use of `applyKeyboardHeight()`: + +```java + // Increase the Keyman keyboard height (default Keyman value for most phones is 205dp) + int newKeyboardHeight = 300; + KMManager.applyKeyboardHeight(this, newKeyboardHeight); +``` + +## See also +* [getKeyboardHeight()](getKeyboardHeight) diff --git a/android/docs/engine/KMManager/canAddNewKeyboard.md b/android/docs/engine/KMManager/canAddNewKeyboard.md new file mode 100644 index 00000000000..82c3f5f89c5 --- /dev/null +++ b/android/docs/engine/KMManager/canAddNewKeyboard.md @@ -0,0 +1,40 @@ +--- +title: KMManager.canAddNewKeyboard() +--- + +## Summary + +The **`canAddNewKeyboard()`** method returns whether adding a new +keyboard is enabled. + +## Syntax + +``` javascript +KMManager.canAddNewKeyboard() +``` + +### Returns + +Returns `true` if adding a new keyboard is enabled, `false` otherwise. + +## Description + +Use this method to check if additional keyboards can be added. + +## Examples + +### Example: Using `canAddNewKeyboard()` + +The following script illustrate the use of `canAddNewKeyboard()`: + +``` javascript + Keyboard kbInfo = ...; // Keyboard information + if (KMManager.canAddNewKeyboard()) { + KMManager.addKeyboard(this, kbInfo); + } +``` + +## See also + +- [`canRemoveKeyboard`](canRemoveKeyboard) +- [`setCanAddNewKeyboard`](setCanAddNewKeyboard) diff --git a/android/docs/engine/KMManager/canRemoveKeyboard.md b/android/docs/engine/KMManager/canRemoveKeyboard.md new file mode 100644 index 00000000000..b3217d5ac69 --- /dev/null +++ b/android/docs/engine/KMManager/canRemoveKeyboard.md @@ -0,0 +1,33 @@ +--- +title: KMManager.canRemoveKeyboard() +--- + +## Summary +The **canRemoveKeyboard()** method returns whether removing a keyboard is enabled, like in the keyboard picker menu. + +## Syntax + +```javascript +KMManager.canRemoveKeyboard() +``` +## Returns + +Returns `true` if removing a keyboard is enabled, `false` otherwise. + +## Description +Use this method to check if a keyboard can be removed. If enabled, you can long-press on a row in the keyboard picker menu to remove a keyboard. + +## Examples + +### Example: Using `canRemoveKeyboard()` + +The following script illustrates the use of `canRemoveKeyboard()`: +```java + if (KeyboardController.getInstance().get().size() > 1 && KMManager.canRemoveKeyboard()) { + // Remove the second keyboard + KMManager.removeKeyboard(this, 1); + } +``` + +## See also +* [canAddNewKeyboard()](canAddNewKeyboard) diff --git a/android/docs/engine/KMManager/copyHTMLBannerAssets.md b/android/docs/engine/KMManager/copyHTMLBannerAssets.md new file mode 100644 index 00000000000..d8d51c91820 --- /dev/null +++ b/android/docs/engine/KMManager/copyHTMLBannerAssets.md @@ -0,0 +1,44 @@ +--- +title: KMManager.copyHTMLBannerAssets +--- + +## Summary +The **copyHTMLBannerAssets()** method copies a folder of HTML banner assets so it's available for your keyboard app's resources. + +## Syntax + +```javascript +KMManager.copyHTMLBannerAssets(Context context, String path) +``` + +### Parameters + +`context` +: The context. + +`path` +: Relative to the /assets folder, the folder which contains the HTML assets to display when suggestions aren't available. + +### Returns +Returns `true` if HTML assets were copied, `false` otherwise. + +## Description +When suggestions aren't available for a keyboard, an HTML banner is displayed instead. +Use this method to specify any HTML assets the banner will use to theme your keyboard app. Some examples of assets would be .svg images or .css files used in your banner. + +This can be called towards the end of `SystemKeyboard.onCreate()`. + +You still need to call [setHTMLBanner()](setHTMLBanner) for Keyman Engine to assign the HTML banner for in-app and system keyboards. + +## Examples + +### Example: Using `copyHTMLBannerAssets()` + +The following script illustrates the use of `copyHTMLBannerAssets()`: +```javascript + // Copies HTML banner assets located in /assets/banner/ + KMManager.copyHTMLBannerAssets(this, "banner"); +``` + +## See also +* [setHTMLBanner()](setHTMLBanner) diff --git a/android/docs/engine/KMManager/createInputView.md b/android/docs/engine/KMManager/createInputView.md new file mode 100644 index 00000000000..d59469e8a34 --- /dev/null +++ b/android/docs/engine/KMManager/createInputView.md @@ -0,0 +1,58 @@ +--- +title: KMManager.createInputView() +--- + +## Summary + +The **`createInputView()`** creates the input view to be used in +InputMethodService. + +## Syntax + +``` javascript +KMManager.createInputView(InputMethodService inputMethodService) +``` + +### Parameters + +`inputMethodService` +: The InputMethodService. + +### Returns + +Returns the input view created. + +## Description + +Use this method to create the input view in response to an +InputMethodService's `onCreateInputView()` method. + +## Examples + +### Example: Using `createInputView()` + +The following script illustrate the use of `createInputView()`: + +``` javascript +private static View inputView = null; + +@Override +public View onCreateInputView() { + // create the inputView only once + if (inputView == null) + inputView = KMManager.createInputView(this); + + // we must remove the inputView from its previous parent before returning it + ViewGroup parent = (ViewGroup) inputView.getParent(); + if (parent != null) + parent.removeView(inputView); + + return inputView; +} +``` + +## See also + +- [`onStartInput()`](onStartInput) +- [`onConfigurationChanged()`](onConfigurationChanged) +- [`onDestroy()`](onDestroy) diff --git a/android/docs/engine/KMManager/deregisterLexicalModel.md b/android/docs/engine/KMManager/deregisterLexicalModel.md new file mode 100644 index 00000000000..427fa2f7699 --- /dev/null +++ b/android/docs/engine/KMManager/deregisterLexicalModel.md @@ -0,0 +1,35 @@ +--- +title: KMManager.deregisterLexicalModel() +--- + +## Summary +The **deregisterLexicalModel()** method deregisters the specified lexical model from the LMLayer so it isn't used. + +## Syntax +```javascript +KMManager.degisterLexicalModel(String modelID) +``` + +### Parameters + +`modelID` +: The ID of the lexical model to deregister + +### Returns +`true` + +## Description +Use this method when you want the lexical model to stop generating suggestions. + +## Examples + +### Example: Using `deregisterLexicalModel()` +The following script illustrates the use of `dergisterLexicalModel()`: + +```java + String lexicalModelID = "example.ta.wordlist"; + KMManager.deregisterLexicalModel(lexicalModelID); +``` + +## See also +* [registerLexicalModel()](registerLexicalModel) diff --git a/android/docs/engine/KMManager/executeHardwareKeystroke.md b/android/docs/engine/KMManager/executeHardwareKeystroke.md new file mode 100644 index 00000000000..5ac8ecede53 --- /dev/null +++ b/android/docs/engine/KMManager/executeHardwareKeystroke.md @@ -0,0 +1,63 @@ +--- +title: KMManager.executeHardwareKeystroke() +--- + +## Summary +The **executeHardwareKeystroke()** method passes the keystroke generated from a physical keyboard to the KeymanWeb engine to handle. + +## Syntax +```java +bool KMManager.executeHardwareKeystroke(int code, int shift, KeyboardType keyboard, int lstates, int eventModifiers) +``` + +### Parameters + +`code` +: key identifier + +`shift` +: shift state + +| Flag | Value | Description | +|--------------|----------|----------------------------------------| +| Left Ctrl | `0x01` | Left Control Flag | +| Right Ctrl | `0x02` | Right Control Flag | +| Left Alt | `0x04` | Left Alt Flag | +| Right Alt | `0x08` | Right Alt Flag | +| Shift | `0x10` | Shift Flag | +| Ctrl | `0x20` | Control Flag | +| Alt | `0x40` | Alt Flag | + +`keyboard` +: `KeyboardType.KEYBOARD_TYPE_INAPP` or `KeyboardType.KEYBOARD_TYPE_SYSTEM` + +`lstates` +: lock state. If neither the on or off state is specified for a lock key, then it is treated as unknown state for keyboard rule matching. + +| Value | Description | +|--------|----------------| +| `0x0100` | Caps lock | +| `0x0200` | No caps lock | +| `0x0400` | Num lock | +| `0x0800` | No Num lock | +| `0x1000` | Scroll | +| `0x2000` | No scroll lock | + +`eventModifiers` +: [KeyEvent Flags](https://developer.android.com/reference/android/view/KeyEvent#getMetaState\(\)) indicating which meta keys are currently pressed. + +### Returns +Returns `true` if the keyboard was initialized and executed the keystroke, `false` otherwise. + +## Description +Use this method to pass a hardware keystroke to KeymanWeb Engine to process. The KeymanWeb Engine also factors in modifier and meta keys. + +## Examples + +### Example: Using `executeHardwareKeystroke()` +The following script illustrate the use of `executeHardwareKeystroke()`: + +```java + // Send keystroke to KeymanWeb for processing: will return true to swallow the keystroke + return KMManager.executeHardwareKeystroke(code, keymanModifiers, keyboardType, Lstates, androidModifiers); +``` diff --git a/android/docs/engine/KMManager/getAssociatedLexicalModel.md b/android/docs/engine/KMManager/getAssociatedLexicalModel.md new file mode 100644 index 00000000000..e92e6f3449a --- /dev/null +++ b/android/docs/engine/KMManager/getAssociatedLexicalModel.md @@ -0,0 +1,39 @@ +--- +title: KMManager.getAssociatedLexicalModel() +--- + +## Summary +The **getAssociatedLexicalModel()** method searches the installed lexical models list and see if there's an associated model for a given language + +## Syntax +```java +HashMap getAssociatedLexicalModel(String langId) +``` + +### Parameters + +`langId` +: The language ID + +### Returns +A dictionary of the associated lexical model information with keys and values defined as +`HashMap lexModelMap = KMManager.getAssociatedLexicalModel(langId); +``` + +## See also +* [addLexicalModel()](addLexicalModel) +* [registerLexicalModel()](registerLexicalModel) diff --git a/android/docs/engine/KMManager/getBannerHeight.md b/android/docs/engine/KMManager/getBannerHeight.md new file mode 100644 index 00000000000..d8e9d5e7389 --- /dev/null +++ b/android/docs/engine/KMManager/getBannerHeight.md @@ -0,0 +1,38 @@ +--- +title: KMManager.getBannerHeight() +--- + +## Summary + +The **`getBannerHeight()`** method returns the height of the suggestion +banner. + +## Syntax + +``` javascript +KMManager.getBannerHeight(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns the height of the suggestion banner frame in +*density-independent pixel (dp)*. + +## Description + +Use this method to get the height of the suggestion banner frame. + +## Examples + +### Example: Using `getBannerHeight()` + +The following script illustrate the use of `getBannerHeight()`: + +``` javascript + int bannerHeight = KMManager.getBannerHeight(this); +``` diff --git a/android/docs/engine/KMManager/getCurrentKeyboardIndex.md b/android/docs/engine/KMManager/getCurrentKeyboardIndex.md new file mode 100644 index 00000000000..cbe086b7b44 --- /dev/null +++ b/android/docs/engine/KMManager/getCurrentKeyboardIndex.md @@ -0,0 +1,47 @@ +--- +title: KMManager.getCurrentKeyboardIndex() +--- + +## Summary + +The **`getCurrentKeyboardIndex()`** method returns index number of the +current keyboard in keyboards list. + +## Syntax + +``` javascript +KMManager.getCurrentKeyboardIndex(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns 0-based index number of the current keyboard if exists in +keyboards list, -1 otherwise. + +## Description + +Use this method to get the index number of the currently selected +keyboard if it exists in keyboards list. + +## Examples + +### Example: Using `getCurrentKeyboardIndex()` + +The following script illustrate the use of `getCurrentKeyboardIndex()`: + +``` javascript + int index = KMManager.getCurrentKeyboardIndex(this); +``` + +## See also + +- [`getCurrentKeyboardInfo()`](getCurrentKeyboardInfo) +- [`getKeyboardIndex()`](getKeyboardIndex) +- [`getKeyboardInfo()`](getKeyboardInfo) +- [`getKeyboardsList()`](getKeyboardsList) +- [`keyboardExists()`](keyboardExists) diff --git a/android/docs/engine/KMManager/getCurrentKeyboardInfo.md b/android/docs/engine/KMManager/getCurrentKeyboardInfo.md new file mode 100644 index 00000000000..4eb789e736d --- /dev/null +++ b/android/docs/engine/KMManager/getCurrentKeyboardInfo.md @@ -0,0 +1,96 @@ +--- +title: KMManager.getCurrentKeyboardInfo() +--- + +## Summary + +The **`getCurrentKeyboardInfo()`** method returns keyboard information +of the current keyboard. + +## Syntax + +``` javascript +KMManager.getCurrentKeyboardInfo(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns the current keyboard information of `Keyboard` type. + +## Description + +Use this method to get details of the currently selected keyboard. +Details include package ID, keyboard ID, language ID, keyboard name, +language name and fonts. + + + +------------------------------------------------------------------------ + +## Syntax (Deprecated) + +``` javascript +KMManager.getCurrentKeyboardInfo(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +(Deprecated) Returns an information dictionary of the current keyboard +with keys and values defined as `HashMap`. + +## Description + +Use this method to get details of the currently selected keyboard. +Details include keyboard ID, language ID, keyboard name, language name +and fonts. + + + +------------------------------------------------------------------------ + +## Examples + +### Example: Using `getCurrentKeyboardInfo()` + +The following script illustrate the use of `getCurrentKeyboardInfo()`: + +``` javascript + Keyboard keyboardInfo = KMManager.getCurrentKeyboardInfo(this); + if (keyboardInfo != null) { + String packageID = keyboardInfo.getPackageID(); + String keyboardId = keyboardInfo.getKeyboardID(); + String keyboardName = keyboardInfo.getKeyboardName(); + String languageId = keyboardInfo.getLanguageID(); + String languageName = keyboardInfo.getLanguageName(); + String version = keyboardInfo.getVersion(); + String font = keyboardInfo.getFont(); + String oskFont = keyboardInfo.getOSKFont(); + // + } +``` + +## History + +Added syntax for returning Keyboard type in Keyman Engine for Android +14.0. + +Deprecated syntax for returning HashMap<String key, String value> +in Keyman Engine for Android 14.0 + +## See also + +- [`getCurrentKeyboardIndex()`](getCurrentKeyboardIndex) +- [`getKeyboardIndex()`](getKeyboardIndex) +- [`getKeyboardInfo()`](getKeyboardInfo) +- [`getKeyboardsList()`](getKeyboardsList) +- [`keyboardExists()`](keyboardExists) diff --git a/android/docs/engine/KMManager/getDefaultKeyboard.md b/android/docs/engine/KMManager/getDefaultKeyboard.md new file mode 100644 index 00000000000..ad62af60da8 --- /dev/null +++ b/android/docs/engine/KMManager/getDefaultKeyboard.md @@ -0,0 +1,29 @@ +--- +title: KMManager.getDefaultKeyboard() +--- + +## Summary +The `getDefaultKeyboard()` method returns the keyboard information for the fallback keyboard. + +## Syntax +```java +KMManager.getDefaultKeyboard() +``` + +### Returns +Returns `Keyboard` type for the fallback keyboard. If not specified, this defaults to keyboard information for sil_euro_latin. + +## Description +The `getDefaultKeyboard()` method returns the keyboard information for the fallback keyboard. If Keyman Engine +has issues with a current keyboard, KMManager will switch to this fallback keyboard. + +## Examples + +### Example: Using getDefaultKeyboard() +The following script illustrates the use of `getDefaultKeyboard()`: +```java + Keyboard kbd = KMManager.getDefaultKeyboard(); +``` + +## See also +* [setDefaultKeyboard](setDefaultKeyboard) diff --git a/android/docs/engine/KMManager/getFontTypeface.md b/android/docs/engine/KMManager/getFontTypeface.md new file mode 100644 index 00000000000..4149d92b360 --- /dev/null +++ b/android/docs/engine/KMManager/getFontTypeface.md @@ -0,0 +1,51 @@ +--- +title: KMManager.getFontTypeface() +--- + +## Summary + +The **`getFontTypeface()`** method creates a new typeface from the +specified font filename. + +## Syntax + +``` javascript +KMManager.getFontTypeface(Context context, String fontFilename) +``` + +### Parameters + +`context` +: The context. + +`fontFilename` +: The filename of the font. + +### Returns + +Returns the new typeface created from font file with specified filename +if it exists, `null` otherwise. + +## Description + +Use this method to create a new typeface from the font file with +specified filename if it exists in `assets/fonts/` folder. + +## Examples + +### Example: Using `getFontTypeface()` + +The following script illustrate the use of `getFontTypeface()`: + +``` javascript + KMTextView textView = (KMTextView) findViewById(R.id.kmTextView); + Typeface fontTypeface = KMManager.getFontTypeface(this, "aava1.ttf"); + textView.setTypeface(fontTypeface); +``` + +## See also + +- [`getKeyboardTextFontTypeface()`](getKeyboardTextFontTypeface) +- [`getKeyboardOskFontTypeface()`](getKeyboardOskFontTypeface) +- [`getKeyboardTextFontFilename()`](getKeyboardTextFontFilename) +- [`getKeyboardOskFontFilename()`](getKeyboardOskFontFilename) diff --git a/android/docs/engine/KMManager/getGlobeKeyAction.md b/android/docs/engine/KMManager/getGlobeKeyAction.md new file mode 100644 index 00000000000..398afe1ee5a --- /dev/null +++ b/android/docs/engine/KMManager/getGlobeKeyAction.md @@ -0,0 +1,35 @@ +--- +title: KMManager.getGlobeKeyAction() +--- + +## Summary +The **getGlobeKeyAction()** method returns the short-press action type of the 'Globe' key. + +## Syntax +```java +KMManager.getGlobeKeyAction(KeyboardType kbType) +``` + +### Parameters +kbType +: The keyboard type. `KEYBOARD_TYPE_INAPP` or `KEYBOARD_TYPE_SYSTEM` + +### Returns +Returns the action type of the short-press 'Globe' key as one of + `GLOBE_KEY_ACTION_SHOW_MENU`, `GLOBE_KEY_ACTION_SWITCH_TO_NEXT_KEYBOARD`, + `GLOBE_KEY_ACTION_ADVANCE_TO_PREVIOUS_SYSTEM_KEYBOARD`, `GLOBE_KEY_ACTION_ADVANCE_TO_NEXT_SYSTEM_KEYBOARD`, + `GLOBE_KEY_ACTION_SHOW_SYSTEM_KEYBOARDS`, or `GLOBE_KEY_ACTION_DO_NOTHING`. + +## Description +Use this method to get the short-press action type of the 'Globe' key. + +## Examples + +### Example: Using getGlobeKeyAction() +The following script illustrate the use of `getGlobeKeyAction()`: +```java +GlobeKeyAction action = KMManager.getGlobeKeyAction(KeyboardType.KEYBOARD_TYPE_SYSTEM); +``` + +## See also +* [setGlobeKeyAction()](setGlobeKeyAction) diff --git a/android/docs/engine/KMManager/getHapticFeedback.md b/android/docs/engine/KMManager/getHapticFeedback.md new file mode 100644 index 00000000000..ff428ca2463 --- /dev/null +++ b/android/docs/engine/KMManager/getHapticFeedback.md @@ -0,0 +1,23 @@ +--- +title: KMManager.getHapticFeedback() +--- + +## Summary +The **getHapticFeedback()** method returns whether the device vibrates as the user types. + +## Syntax +```java +KMManager.getHapticFeedback() +``` + +### Returns +Returns `true` if the device vibrates as the user types, `false` otherwise. + +## Description +Use this method to check if the device is currently configured to provide haptic feedback. Default is `false`. + +## History +Keyman Engine for Android 15.0: New function. + +## See also +* [setHapticFeedback](setHapticFeedback) diff --git a/android/docs/engine/KMManager/getKMKeyboard.md b/android/docs/engine/KMManager/getKMKeyboard.md new file mode 100644 index 00000000000..1cdc3cdd503 --- /dev/null +++ b/android/docs/engine/KMManager/getKMKeyboard.md @@ -0,0 +1,28 @@ +--- +title: KMManager.getKMKeyboard() +--- + +## Summary +The `getKMKeyboard()` method returns the [KMKeyboard](../KMKeyboard) type depending whether it's an in-app or system keyboard. + +## Syntax +```java +KMKeyboard KMManager.getKMKeyboard(KeyboardType type) +``` +### Parameters +type +: `KeyboardType.KEYBOARD_TYPE_INAPP` or `KeyboardType.KEYBOARD_TYPE_SYSTEM` + +### Returns +Returns the KMKeyboard object. + +## Description +The `getKMKeyboard()` method returns the KMKeyboard for the specified keyboard type. + +## Examples + +### Example: Using getKMKeyboard() +The following script illustrates the use of `getKMKeyboard()`: +```java + KMKeyboard keyboard = KMManager.getKMKeyboard(KeyboardType.KEYBOARD_TYPE_SYSTEM); +``` diff --git a/android/docs/engine/KMManager/getKeyboardFontFilename.md b/android/docs/engine/KMManager/getKeyboardFontFilename.md new file mode 100644 index 00000000000..086922224d4 --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardFontFilename.md @@ -0,0 +1,38 @@ +--- +title: KMManager.getKeyboardFontFilename() (Deprecated) +--- + +## Summary + +(Deprecated) The **`getKeyboardFontFilename()`** method returns the +selected keyboard's font filename. + +## Syntax + +``` javascript +KMManager.getKeyboardFontFilename() +``` + +### Returns + +Returns the selected keyboard's font filename as `String` if it has any, +empty string otherwise. + +## Description + +Use this method to get the font filename of the selected keyboard. + +## Examples + +### Example: Using `getKeyboardFontFilename()` + +The following script illustrate the use of `getKeyboardFontFilename()`: + +``` javascript + String fontFilename = KMManager.getKeyboardFontFilename(); +``` + +## See also + +- [`getKeyboardFontTypeface()` (Deprecated)](getKeyboardFontTypeface) +- [`getFontTypeface()`](getFontTypeface) diff --git a/android/docs/engine/KMManager/getKeyboardFontTypeface.md b/android/docs/engine/KMManager/getKeyboardFontTypeface.md new file mode 100644 index 00000000000..1f414ce14fd --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardFontTypeface.md @@ -0,0 +1,46 @@ +--- +title: KMManager.getKeyboardFontTypeface() (Deprecated) +--- + +## Summary + +(Deprecated) The **`getKeyboardFontTypeface()`** method creates a new +typeface from the selected keyboard's font. + +## Syntax + +``` javascript +KMManager.getKeyboardFontTypeface(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns the new typeface created from the selected keyboard's font if it +exists, `null` otherwise. + +## Description + +Use this method to create a new typeface from the selected keyboard's +font if it has any. + +## Examples + +### Example: Using `getKeyboardFontTypeface()` + +The following script illustrate the use of `getKeyboardFontTypeface()`: + +``` javascript + KMTextView textView = (KMTextView) findViewById(R.id.kmTextView); + Typeface fontTypeface = KMManager.getKeyboardFontTypeface(this); + textView.setTypeface(fontTypeface); +``` + +## See also + +- [`getFontTypeface()`](getFontTypeface) +- [`getKeyboardFontFilename()` (Deprecated)](getKeyboardFontFilename) diff --git a/android/docs/engine/KMManager/getKeyboardHeight.md b/android/docs/engine/KMManager/getKeyboardHeight.md new file mode 100644 index 00000000000..c459e45ddba --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardHeight.md @@ -0,0 +1,42 @@ +--- +title: KMManager.getKeyboardHeight() +--- + +## Summary + +The **`getKeyboardHeight()`** method returns the height of the keyboard +frame. + +## Syntax + +``` javascript +KMManager.getKeyboardHeight(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns the height of the keyboard frame in *density-independent pixels +(dp)*. + +## Description + +Use this method to get the height of the keyboard frame. + +## Examples + +### Example: Using `getKeyboardHeight()` + +The following script illustrate the use of `getKeyboardHeight()`: + +``` javascript + int keyboardHeight = KMManager.getKeyboardHeight(this); +``` + +## See also + +- [applyKeyboardHeight](applyKeyboardHeight) diff --git a/android/docs/engine/KMManager/getKeyboardIndex.md b/android/docs/engine/KMManager/getKeyboardIndex.md new file mode 100644 index 00000000000..d1f9616350d --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardIndex.md @@ -0,0 +1,53 @@ +--- +title: KMManager.getKeyboardIndex() +--- + +## Summary + +The **`getKeyboardIndex()`** method returns index number of the +specified keyboard in keyboards list. + +## Syntax + +``` javascript +KMManager.getKeyboardIndex(Context context, String keyboardID, String languageID) +``` + +### Parameters + +`context` +: The context. + +`keyboardID` +: ID of the keyboard. + +`languageID` +: ID of the associated language. + +### Returns + +Returns 0-based index number of the specified keyboard if exists in +keyboards list, -1 otherwise. + +## Description + +Use this method to get the index number of the keyboard with given +keyboard ID and language ID if it exists in keyboards list. + +## Examples + +### Example: Using `getKeyboardIndex()` + +The following script illustrate the use of `getKeyboardIndex()`: + +``` javascript + int index = KMManager.getKeyboardIndex(this, "tamil99m", "ta"); +``` + +## See also + +- [`getCurrentKeyboardIndex()`](getCurrentKeyboardIndex) +- [`getCurrentKeyboardInfo()`](getCurrentKeyboardInfo) +- [`getKeyboardInfo()`](getKeyboardInfo) +- [`getKeyboardsList()`](getKeyboardsList) +- [`keyboardExists()`](keyboardExists) diff --git a/android/docs/engine/KMManager/getKeyboardInfo.md b/android/docs/engine/KMManager/getKeyboardInfo.md new file mode 100644 index 00000000000..5838e0ca233 --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardInfo.md @@ -0,0 +1,98 @@ +--- +title: KMManager.getKeyboardInfo() +--- + +## Summary + +The **`getKeyboardInfo()`** method returns information of the specified +keyboard. + +## Syntax + +``` javascript +KMManager.getKeyboardInfo(Context context, int index) +``` + +### Parameters + +`context` +: The context. + +`index` +: 0-based position of the keyboard in keyboards list. + +### Returns + +Returns an information `Keyboard` type of the specified keyboard. + +## Description + +Use this method to get details of the keyboard at given position in +keyboards list. Details include keyboard ID, language ID, keyboard name, +language name and fonts. + + + +------------------------------------------------------------------------ + +## Syntax (Deprecated) + +``` javascript +KMManager.getKeyboardInfo(Context context, int index) +``` + +### Parameters + +`context` +: The context. + +`index` +: 0-based position of the keyboard in keyboards list. + +### Returns + +(Deprecated) Returns an information dictionary of the specified keyboard +with keys and values defined as `HashMap`. + +## Description + +Use this method to get details of the keyboard at given position in +keyboards list. Details include keyboard ID, language ID, keyboard name, +language name and fonts. + +## Examples + +### Example: Using `getKeyboardInfo()` + +The following script illustrate the use of `getKeyboardInfo()`: + +``` javascript + Keyboard keyboardInfo = KMManager.getKeyboardInfo(this, 1); + if (keyboardInfo != null) { + String packageID = keyboardInfo.getPackageID(); + String keyboardId = keyboardInfo.getKeyboardID(); + String keyboardName = keyboardInfo.getKeyboardName(); + String languageId = keyboardInfo.getLanguageID(); + String languageName = keyboardInfo.getLanguageName(); + String version = keyboardInfo.getVersion(); + String font = keyboardInfo.getFont(); + String oskFont = keyboardInfo.getOSKFont(); + // + } +``` + +## History + +Added syntax for returning Keyboard type in Keyman Engine for Android +14.0. + +Deprecated syntax for returning the HashMap<String key, String +value> in Keyman Engine for Android 14.0 + +## See also + +- [`getCurrentKeyboardIndex()`](getCurrentKeyboardIndex) +- [`getCurrentKeyboardInfo()`](getCurrentKeyboardInfo) +- [`getKeyboardIndex()`](getKeyboardIndex) +- [`getKeyboardsList()`](getKeyboardsList) +- [`keyboardExists()`](keyboardExists) diff --git a/android/docs/engine/KMManager/getKeyboardOskFontFilename.md b/android/docs/engine/KMManager/getKeyboardOskFontFilename.md new file mode 100644 index 00000000000..8465ea4e8c4 --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardOskFontFilename.md @@ -0,0 +1,41 @@ +--- +title: KMManager.getKeyboardOskFontFilename() +--- + +## Summary + +The **`getKeyboardOskFontFilename()`** method returns the selected +keyboard's OSK font filename. + +## Syntax + +``` javascript +KMManager.getKeyboardOskFontFilename() +``` + +### Returns + +Returns the selected keyboard's OSK font filename as `String` if it has +any, empty string otherwise. + +## Description + +Use this method to get the OSK font filename of the selected keyboard. + +## Examples + +### Example: Using `getKeyboardOskFontFilename()` + +The following script illustrate the use of +`getKeyboardOskFontFilename()`: + +``` javascript + String oskFontFilename = KMManager.getKeyboardOskFontFilename(); +``` + +## See also + +- [`getKeyboardTextFontFilename()`](getKeyboardTextFontFilename) +- [`getKeyboardOskFontTypeface()`](getKeyboardOskFontTypeface) +- [`getKeyboardTextFontTypeface()`](getKeyboardTextFontTypeface) +- [`getFontTypeface()`](getFontTypeface) diff --git a/android/docs/engine/KMManager/getKeyboardOskFontTypeface.md b/android/docs/engine/KMManager/getKeyboardOskFontTypeface.md new file mode 100644 index 00000000000..4344ab7ce65 --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardOskFontTypeface.md @@ -0,0 +1,47 @@ +--- +title: KMManager.getKeyboardOskFontTypeface() +--- + +## Summary + +The **`getKeyboardOskFontTypeface()`** method creates a new typeface +from the selected keyboard's OSK font. + +## Syntax + +``` javascript +KMManager.getKeyboardOskFontTypeface(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns the new typeface created from the selected keyboard's OSK font +if it exists, `null` otherwise. + +## Description + +Use this method to create a new typeface from the selected keyboard's +OSK font if it has any. + +## Examples + +### Example: Using `getKeyboardOskFontTypeface()` + +The following script illustrate the use of +`getKeyboardOskFontTypeface()`: + +``` javascript + Typeface oskFontTypeface = KMManager.getKeyboardOskFontTypeface(this); +``` + +## See also + +- [`getKeyboardTextFontTypeface()`](getKeyboardTextFontTypeface) +- [`getKeyboardOskFontFilename()`](getKeyboardOskFontFilename) +- [`getKeyboardTextFontFilename()`](getKeyboardTextFontFilename) +- [`getFontTypeface()`](getFontTypeface) diff --git a/android/docs/engine/KMManager/getKeyboardState.md b/android/docs/engine/KMManager/getKeyboardState.md new file mode 100644 index 00000000000..a05353e58cf --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardState.md @@ -0,0 +1,68 @@ +--- +title: KMManager.getKeyboardState() +--- + +## Summary + +The **`getKeyboardState()`** method returns the specified keyboard's +state. + +## Syntax + +``` javascript +KMManager.getKeyboardState(Context context, String keyboardID, String languageID) +``` + +### Parameters + +`context` +: The context. + +`keyboardID` +: ID of the keyboard. + +`languageID` +: ID of the associated language. + +### Returns + +Returns the state of the specified keyboard as one of +`KEYBOARD_STATE_UNDEFINED`, `KEYBOARD_STATE_NEEDS_DOWNLOAD`, +`KEYBOARD_STATE_NEEDS_UPDATE` or `KEYBOARD_STATE_UP_TO_DATE`. + +## Description + +Use this method to get the state of the specified keyboard. It returns +`KEYBOARD_STATE_UNDEFINED` if keyboardID or languageID is not specified +(`null` or empty string). It returns `KEYBOARD_STATE_NEEDS_DOWNLOAD` if +the specified keyboard does not exist in `assets/languages/` folder. In +all other cases it returns either `KEYBOARD_STATE_UP_TO_DATE` or +`KEYBOARD_STATE_NEEDS_UPDATE`. Note: Only keyboards provided by Keyman +may return `KEYBOARD_STATE_NEEDS_UPDATE`. If you have a custom keyboard, +you need to implement your own method to check whether or not it needs +update. `KEYBOARD_STATE_UP_TO_DATE` does not necessarily mean that the +keyboard is in fact up to date, you need to make sure language list has +recently been displayed (see +[`showLanguageList() (Deprecated)`](showLanguageList)) without failure +to access Keyman server to be certain. + +## Examples + +### Example: Using `getKeyboardState()` + +The following script illustrate the use of `getKeyboardState()`: + +``` javascript + KeyboardState keyboardState = KMManager.getKeyboardState(this, "tamil99m", "ta"); + switch (keyboardState) { + case KEYBOARD_STATE_NEEDS_DOWNLOAD: + // We need to download this keyboard or manually add it into assets/languages/ folder. + break; + case KEYBOARD_STATE_UP_TO_DATE: + case KEYBOARD_STATE_NEEDS_UPDATE: + // We can safely use this keyboard since it exists in assets/languages/ folder. + break; + default: + // Undefined state + } +``` diff --git a/android/docs/engine/KMManager/getKeyboardTextFontFilename.md b/android/docs/engine/KMManager/getKeyboardTextFontFilename.md new file mode 100644 index 00000000000..5c381cc23a0 --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardTextFontFilename.md @@ -0,0 +1,41 @@ +--- +title: KMManager.getKeyboardTextFontFilename() +--- + +## Summary + +The **`getKeyboardTextFontFilename()`** method returns the selected +keyboard's text font filename. + +## Syntax + +``` javascript +KMManager.getKeyboardTextFontFilename() +``` + +### Returns + +Returns the selected keyboard's text font filename as `String` if it has +any, empty string otherwise. + +## Description + +Use this method to get the text font filename of the selected keyboard. + +## Examples + +### Example: Using `getKeyboardTextFontFilename()` + +The following script illustrate the use of +`getKeyboardTextFontFilename()`: + +``` javascript + String textFontFilename = KMManager.getKeyboardTextFontFilename(); +``` + +## See also + +- [`getKeyboardOskFontFilename()`](getKeyboardOskFontFilename) +- [`getKeyboardTextFontTypeface()`](getKeyboardTextFontTypeface) +- [`getKeyboardOskFontTypeface()`](getKeyboardOskFontTypeface) +- [`getFontTypeface()`](getFontTypeface) diff --git a/android/docs/engine/KMManager/getKeyboardTextFontTypeface.md b/android/docs/engine/KMManager/getKeyboardTextFontTypeface.md new file mode 100644 index 00000000000..05e5bcd8c99 --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardTextFontTypeface.md @@ -0,0 +1,49 @@ +--- +title: KMManager.getKeyboardTextFontTypeface() +--- + +## Summary + +The **`getKeyboardTextFontTypeface()`** method creates a new typeface +from the selected keyboard's text font. + +## Syntax + +``` javascript +KMManager.getKeyboardTextFontTypeface(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns the new typeface created from the selected keyboard's text font +if it exists, `null` otherwise. + +## Description + +Use this method to create a new typeface from the selected keyboard's +text font if it has any. + +## Examples + +### Example: Using `getKeyboardTextFontTypeface()` + +The following script illustrate the use of +`getKeyboardTextFontTypeface()`: + +``` javascript + KMTextView textView = (KMTextView) findViewById(R.id.kmTextView); + Typeface textFontTypeface = KMManager.getKeyboardTextFontTypeface(this); + textView.setTypeface(textFontTypeface); +``` + +## See also + +- [`getKeyboardOskFontTypeface()`](getKeyboardOskFontTypeface) +- [`getKeyboardTextFontFilename()`](getKeyboardTextFontFilename) +- [`getKeyboardOskFontFilename()`](getKeyboardOskFontFilename) +- [`getFontTypeface()`](getFontTypeface) diff --git a/android/docs/engine/KMManager/getKeyboardsList.md b/android/docs/engine/KMManager/getKeyboardsList.md new file mode 100644 index 00000000000..26c520953b7 --- /dev/null +++ b/android/docs/engine/KMManager/getKeyboardsList.md @@ -0,0 +1,87 @@ +--- +title: KMManager.getKeyboardsList() +--- + +## Summary + +The **`getKeyboardsList()`** method returns the keyboards list. + +## Syntax + +``` javascript +KMManager.getKeyboardsList(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +Returns keyboards list as `List` if it exists, `null` +otherwise. + +## Description + +Use this method to get details of all keyboard's in keyboards menu. + + + +------------------------------------------------------------------------ + +## Syntax (Deprecated) + +``` javascript +KMManager.getKeyboardsList(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns + +(Deprecated) Returns keyboards list as +`ArrayList>` if it exists, `null` +otherwise. + +## Description + +Use this method to get details of all keyboard's in keyboards menu. + + + +------------------------------------------------------------------------ + +## Examples + +### Example: Using `getKeyboardsList()` + +The following script illustrate the use of `getKeyboardsList()`: + +``` javascript + List keyboardsList = KMManager.getKeyboardsList(this); + if ((keyboardsList != null) && keyboardsList.size() < 2) { + // Add another Keyboard + Keyboard kbd = new Keyboard(...); + KMManager.addKeyboard(kbd); + } +``` + +## History + +Added syntax for returning list of Keyboard type in Keyman Engine for +Android 14.0. + +Deprecated syntax for returning the list of HashMap<String key, +String value> in Keyman Engine for Android 14.0 + +## See also + +- [`getCurrentKeyboardIndex()`](getCurrentKeyboardIndex) +- [`getCurrentKeyboardInfo()`](getCurrentKeyboardInfo) +- [`getKeyboardIndex()`](getKeyboardIndex) +- [`getKeyboardInfo()`](getKeyboardInfo) +- [`keyboardExists()`](keyboardExists) diff --git a/android/docs/engine/KMManager/getLanguageCorrectionPreferenceKey.md b/android/docs/engine/KMManager/getLanguageCorrectionPreferenceKey.md new file mode 100644 index 00000000000..42f75f72745 --- /dev/null +++ b/android/docs/engine/KMManager/getLanguageCorrectionPreferenceKey.md @@ -0,0 +1,40 @@ +--- +title: KMManager.getLanguageCorrectionPreferenceKey() +--- + +## Summary +A constant to use as a shared preference key to store whether the LMLayer should enable corrections for a given language. + +## Syntax +```java +KMManager.getLanguageCorrectionPreferenceKey(String langID) +``` + +### Parameters + +`langId` +: The BCP 47 language ID + +### Returns +Returns the language correction preference key as a String. + +## Description +Use this method to get a String that can be used as a shared preference key. + +The usage of this preference key is experimental and likely to be deprecated in a future release of Keyman Engine for Android. + +## Examples + +### Example: Using `getLanguageCorrectionPreferenceKey()` +The following script illustrates the use of `getLanguageCorrectionPreferenceKey()`: + +```java + SharedPreferences prefs = ...; // Get the app's shared preferences + String langID = "ta"; + boolean key = KMManager.getLanguageCorrectionPreferenceKey(langID); + + boolean mayCorrect = prefs.getBoolean(key, true); +``` + +## See also +* [getLanguagePredictionPreferenceKey()](getLanguagePredictionPreferenceKey) diff --git a/android/docs/engine/KMManager/getLanguagePredictionPreferenceKey.md b/android/docs/engine/KMManager/getLanguagePredictionPreferenceKey.md new file mode 100644 index 00000000000..fe5102bcdb9 --- /dev/null +++ b/android/docs/engine/KMManager/getLanguagePredictionPreferenceKey.md @@ -0,0 +1,40 @@ +--- +title: KMManager.getLanguagePredictionPreferenceKey() +--- + +## Summary +A constant to use as a shared preference key to store whether the LMLayer should enable suggestions for a given language. + +## Syntax +```java +KMManager.getLanguagePredictionPreferenceKey(String langID) +``` + +### Parameters + +`langId` +: The BCP 47 language ID + +### Returns +Returns the language prediction preference key as a String. + +## Description +Use this method to get a String that can be used as a shared preference key. + +The usage of this preference key is experimental and likely to be deprecated in a future release of Keyman Engine for Android. + +## Examples + +### Example: Using `getLanguagePredictionPreferenceKey()` +The following script illustrates the use of `getLanguagePredictionPreferenceKey()`: + +```java + SharedPreferences prefs = ...; // Get the app's shared preferences + String langID = "ta"; + boolean key = KMManager.getLanguagePredictionPreferenceKey(langID); + + boolean mayPredict = prefs.getBoolean(key, true); +``` + +## See also +* [getLanguageCorrectionPreferenceKey()](getLanguageCorrectionPreferenceKey) diff --git a/android/docs/engine/KMManager/getLatestKeyboardFileVersion.md b/android/docs/engine/KMManager/getLatestKeyboardFileVersion.md new file mode 100644 index 00000000000..57b227e1b1b --- /dev/null +++ b/android/docs/engine/KMManager/getLatestKeyboardFileVersion.md @@ -0,0 +1,61 @@ +--- +title: KMManager.getLatestKeyboardFileVersion() +--- + +## Summary + +The **`getLatestKeyboardFileVersion()`** method returns the specified +keyboard's latest file version number. + +## Syntax + +``` javascript +KMManager.getLatestKeyboardFileVersion(Context context, String packageID, String keyboardID) +``` + +### Parameters + +`context` +: The context. + +`packageID` +: ID of the package. + +`keyboardID` +: ID of the keyboard. + +### Returns + +Returns the specified keyboard's latest file version number as `String` +if the keyboard exists, `null` otherwise. + +## Description + +Use this method to get the latest file version number of the specified +keyboard if it exists in the `assets/cloud/` or `assets/packages/` +folder. + +If packageID is `cloud`, this method determines the latest file version +by the filename. + +If packageID is something else, the metadata file +assets/packageID/kmp.json is parsed to determine the keyboard version. + +## Examples + +### Example: Using `getLatestKeyboardFileVersion()` + +The following script illustrate the use of +`getLatestKeyboardFileVersion()`: + +``` javascript + String latestVersion = getLatestKeyboardFileVersion(this, "cloud", "tamil99m"); + if (latestVersion != null) { + // If we assume that there are 2 tamil99m keyboard files in assets/cloud/ folder + // with filenames; tamil99m-1.0.js and tamil99m-1.1.js + // then latestVersion = "1.1" + } + else { + // This keyboard does not exist in assets/cloud/ folder! + } +``` diff --git a/android/docs/engine/KMManager/getLexicalModelInfo.md b/android/docs/engine/KMManager/getLexicalModelInfo.md new file mode 100644 index 00000000000..38729696ea8 --- /dev/null +++ b/android/docs/engine/KMManager/getLexicalModelInfo.md @@ -0,0 +1,47 @@ +--- +title: KMManager.getLexicalModelInfo() +--- + +## Summary + +The `getLexicalModelInfo()` method returns returns dictionary information of the specified lexical model. + +## Syntax + +```java +HashMap KMManager.getLexicalModelInfo(Context context, int index) +``` + +### Parameters + +`context` +: The context. + +`index` +: Zero-based index of the installed lexical model + +### Returns +Returns a dictionary `Hashmap` containing information on the specified lexical model. +The keys for the HashMap are: +| Keys | +|---------------------------------------------| +| `KMManager.KMKey_PackageID` | +| `KMManager.KMKey_LexicalModelID` | +| `KMManager.KMKey_LexicalModelName` | +| `KMManager.KMKey_LexicalModelVersion` | +| `KMManager.KMKey_LanguageID` | +| `KMManager.KMKey_LanguageName` | +| `KMManager.KMKey_CustomHelpLink` (optional) | + +## Description +Use this method to get details about a specified lexical model. (language and keyboard information) + +## Examples + +### Example: Using `getLexicalModelInfo()` + +The following code illustrates the use of `getLexicalModelInfo()`: +```java + // Gets information on the first installed lexical model + HashMap lexicalModelInfo = KMManager.getLexicalModelInfo(context, 0); +``` diff --git a/android/docs/engine/KMManager/getLexicalModelsList.md b/android/docs/engine/KMManager/getLexicalModelsList.md new file mode 100644 index 00000000000..979a6620e45 --- /dev/null +++ b/android/docs/engine/KMManager/getLexicalModelsList.md @@ -0,0 +1,32 @@ +--- +title: KMManager.getLexicalModelsList() +--- + +## Summary +The **getLexicalModelsList()** method returns the array of lexical models list. + +## Syntax +```java +ArrayList> KMManager.getLexicalModelsList(Context context) +``` + +### Parameters +`context` +: The context. + +### Returns +Returns a list of all the installed lexical models. + +## Description +Use this method to get details of all the installed lexical models. + +## Examples + +### Example: Using getLexicalModelsList() +The following script illustrate the use of `getLexicalModelsList()`: +```java + ArrayList> lexicalModelList = KMManager.getLexicalModelsList(context); +``` + +## See also +* [getLexicalModelInfo()](getLexicalModelInfo) diff --git a/android/docs/engine/KMManager/getLongpressDelay.md b/android/docs/engine/KMManager/getLongpressDelay.md new file mode 100644 index 00000000000..6fb0e872dcb --- /dev/null +++ b/android/docs/engine/KMManager/getLongpressDelay.md @@ -0,0 +1,38 @@ +--- +title: KMManager.getLongpressDelay() +--- + +## Summary + +The `getLongpressDelay()` method returns from stored preference the number of milliseconds to trigger a longpress gesture. +Defaults to 500 milliseconds. + +## Syntax + +```java +int KMManager.getLongpressDelay() +``` + +### Returns +Returns the number of milliseconds to trigger a longpress gesture. This preference is stored at the app level and is applied to all Keyman keyboards. + +## Description +Use this method to get details about how long to press a key for longpress keys to appear. + +## Examples + +### Example: Using `getLongpressDelay()` + +The following code illustrates the use of `getLongpressDelay()`: +```java + int currentDelayTimeMS = KMManager.getLongpressDelay(); + + currentDelayTimeMS += 250; // ms +``` + +## History +Keyman Engine for Android 18.0: New function. + +## See also +* [sendOptionsToKeyboard](sendOptionsToKeyboard) +* [setLongpressDelay](setLongpressDelay) diff --git a/android/docs/engine/KMManager/getMaySendCrashReport.md b/android/docs/engine/KMManager/getMaySendCrashReport.md new file mode 100644 index 00000000000..84a5ffd5654 --- /dev/null +++ b/android/docs/engine/KMManager/getMaySendCrashReport.md @@ -0,0 +1,23 @@ +--- +title: KMManager.getMaySendCrashReport() +--- + +## Summary +The **getMaySendCrashReport()** method returns whether Keyman Engine is allowed to send crash reports over the network to sentry.keyman.com. + +## Syntax +```java +KMManager.getMaySendCrashReport() +``` + +### Returns +Returns `true` if crash reports can be sent over the network to sentry.keyman.com, `false` otherwise. + +## Description +Use this method to check if Keyman Engine will be accessing the network to send crash reports. + +## History +Added syntax in Keyman Engine for Android 14.0. + +## See also +* [setMaySendCrashReport](setMaySendCrashReport) diff --git a/android/docs/engine/KMManager/getOrientation.md b/android/docs/engine/KMManager/getOrientation.md new file mode 100644 index 00000000000..efdfd63db01 --- /dev/null +++ b/android/docs/engine/KMManager/getOrientation.md @@ -0,0 +1,37 @@ +--- +title: KMManager.getOrientation() +--- + +## Summary + +The `getOrientation()` method returns the current orientation of the device. + +## Syntax + +```java +KMManager.getOrientation(Context context) +``` + +### Parameters + +`context` +: The context. + +### Returns +Returns the device orientation as an int, one of: + +* `Configuration.ORIENTATION_PORTRAIT` (`1`) +* `Configuration.ORIENTATION_LANDSCAPE` (`2`) +* `Configuration.ORIENTATION_UNDEFINED` (`0`) + +## Description +Use this method to get the current orientation of the device + +## Examples + +### Example: Using `getOrientation()` + +The following code illustrates the use of `getOrientation()`: +```java + int orientation = KMManager.getOrientation(context); +``` diff --git a/android/docs/engine/KMManager/getSpacebarText.md b/android/docs/engine/KMManager/getSpacebarText.md new file mode 100644 index 00000000000..3b94ffe3be8 --- /dev/null +++ b/android/docs/engine/KMManager/getSpacebarText.md @@ -0,0 +1,45 @@ +--- +title: KMManager.getSpacebarText() +--- + +## Summary + +The `getSpacebarText()` method returns the current text display pattern for the +spacebar. + +## Syntax + +```java +KMManager.SpacebarText KMManager.getSpacebarText() +``` + +### Returns + +The current text display pattern for the spacebar, one of: + + * `LANGUAGE` - the language name for the keyboard + * `KEYBOARD` - the keyboard name + * `LANGUAGE_KEYBOARD` - both the language name and the keyboard name, + separated by hyphen + * `BLANK` - no text to be displayed + +## Description + +The default text display pattern is `LANGUAGE_KEYBOARD`. The text shown on the +keyboard may be overridden on a per-keyboard basis with the `displayName` +parameter of the `setKeyboard()` function. + +--- + +## Example: Using `getSpacebarText()` + +The following script illustrates the use of `getSpacebarText()`: + +```java +// get the current spacebar text mode +KMManager.SpacebarText mode = KMManager.getSpacebarText(); +``` + +## See also + +* [`setSpacebarText()`](setSpacebarText) diff --git a/android/docs/engine/KMManager/getVersion.md b/android/docs/engine/KMManager/getVersion.md new file mode 100644 index 00000000000..8ac8b33412d --- /dev/null +++ b/android/docs/engine/KMManager/getVersion.md @@ -0,0 +1,32 @@ +--- +title: KMManager.getVersion() +--- + +## Summary + +The **`getVersion()`** method returns the version number of Keyman +Engine. + +## Syntax + +``` javascript +KMManager.getVersion() +``` + +### Returns + +Returns Keyman Engine version number as `String`. + +## Description + +Use this method to get the version number of Keyman Engine. + +## Examples + +### Example: Using `getVersion()` + +The following script illustrate the use of `getVersion()`: + +``` javascript + String version = KMManager.getVersion(); +``` diff --git a/android/docs/engine/KMManager/getWindowDensity.md b/android/docs/engine/KMManager/getWindowDensity.md new file mode 100644 index 00000000000..49ce59e2b21 --- /dev/null +++ b/android/docs/engine/KMManager/getWindowDensity.md @@ -0,0 +1,34 @@ +--- +title: KMManager.getWindowDensity() +--- + +## Summary + +The `getWindowDensity()` method returns the density of the window. + +## Syntax + +```java +KMManager.getWindowDensity(Context context) +``` + +`context` +: The context. + +### Returns +Returns the density + +## Description +Use this method to get the [density](https://developer.android.com/reference/android/util/DisplayMetrics#density) of the window. This is a scaling factor for the Density Independent Pixel (DIP) unit. + +## Examples + +### Example: Using `getWindowDensity()` + +The following code illustrates the use of `getWindowDensity()`: +```java + float density = KMManager.getWindowDensity(context); +``` + +## See Also +* [getWindowSize](getWindowSize) diff --git a/android/docs/engine/KMManager/getWindowSize.md b/android/docs/engine/KMManager/getWindowSize.md new file mode 100644 index 00000000000..f3bd0a87d51 --- /dev/null +++ b/android/docs/engine/KMManager/getWindowSize.md @@ -0,0 +1,39 @@ +--- +title: KMManager.getWindowSize() +--- + +## Summary + +The `getWindowSize()` method returns the size of the area the window would occupy. + +## Syntax + +```java +KMManager.getWindowSize(Context context) +``` + +`context` +: The context. + +### Returns +Returns the window size (native resolution) of the display as (int x, int y). + +## Description +Use this method to get the size of the entire display. + +For API level 29 and below, the size of the [entire display minus system decoration areas](https://developer.android.com/reference/android/view/Display#getSize(android.graphics.Point) is returned. + +For API level 30 and above, it may or may not include [system decoration areas](https://developer.android.com/reference/android/view/Display) + +## Examples + +### Example: Using `getWindowSize()` + +The following code illustrates the use of `getWindowSize()`: +```java + Point size = KMManager.getWindowSize(context); + int screenHeight = size.y; +``` + +## See also +* [getWindowDensity](getWindowDensity) \ No newline at end of file diff --git a/android/docs/engine/KMManager/hasConnection.md b/android/docs/engine/KMManager/hasConnection.md new file mode 100644 index 00000000000..305ed41b09f --- /dev/null +++ b/android/docs/engine/KMManager/hasConnection.md @@ -0,0 +1,38 @@ +--- +title: KMManager.hasConnection() +--- + +## Summary +The **hasConnection()** method returns whether the device has active network connection. + +## Syntax +```java +KMManager.hasConnection(Context context) +``` + +## Parameters + +`context` +: The context + +## Returns +Returns `true` if application's AndroidManifest.xml file has granted +[Manifest.permission.ACCESS_NETWORK_STATE](https://developer.android.com/reference/android/Manifest.permission#ACCESS_NETWORK_STATE) +permission and the device has an active network connection, `false` otherwise. + +## Description +Use this method to check if the device has an active network connection. It is important to make sure there is an active network connection before initiating a download or update. + +## Examples + +### Example: Using `hasConnection()` +The following script illustrate the use of `hasConnection()`: + +```java + if (KMManager.hasConnection(this)) { + // has network connection + } + else { + // no network connection + } +``` diff --git a/android/docs/engine/KMManager/hideSystemKeyboard.md b/android/docs/engine/KMManager/hideSystemKeyboard.md new file mode 100644 index 00000000000..f79996c73cd --- /dev/null +++ b/android/docs/engine/KMManager/hideSystemKeyboard.md @@ -0,0 +1,36 @@ +--- +title: KMManager.hideSystemKeyboard() +--- + +## Summary + +The **`hideSystemKeyboard()`** method hides the system OSK. + +## Syntax + +``` javascript +KMManager.hideSystemKeyboard() +``` + +## Description + +Use this method to hide the system OSK. A common usage is to prevent +your app from displaying both in-app OSK and the system OSK. + +## Examples + +### Example: Using `hideSystemKeyboard()` + +The following script illustrate the use of `hideSystemKeyboard()`: + +``` javascript +protected void onResume() { + super.onResume(); + KMManager.onResume(); + KMManager.hideSystemKeyboard(); + // ... +``` + +## See also + +- [`onResume()`](onResume) diff --git a/android/docs/engine/KMManager/index.md b/android/docs/engine/KMManager/index.md new file mode 100644 index 00000000000..9a8cc4a7969 --- /dev/null +++ b/android/docs/engine/KMManager/index.md @@ -0,0 +1,285 @@ +--- +title: KMManager class +--- + +## Summary + +The **`KMManager`** class provides methods for controlling Keyman Engine + +## Syntax + +```java +KMManager.methodName() +``` +```java +KMManager.CONSTANT +``` + +## Description + +The KMManager is the core class which provides most of the methods and constants you will need to develop your apps with Keyman Engine + + + +## Methods + +[`addKeyboard()`](addKeyboard) +: adds a keyboard into the keyboards list + +[`addKeyboardDownloadEventListener()`](addKeyboardDownloadEventListener) +: adds the specified listener into the list of keyboard download event listeners + +[`addKeyboardEventListener()`](addKeyboardEventListener) +: adds the specified listener into the list of keyboard event listeners + +[`addLexicalModel()`](addLexicalModel) +: adds a lexical model into the lexical models list + +[`advanceToNextInputMode()`](advanceToNextInputMode) +: switch to the next system keyboard input mode + +[`advanceToPreviousInputMethod()`](advanceToPreviousInputMethod) +: switch to the previous system keyboard input mode + +[`applyKeyboardHeight()`](applyKeyboardHeight) +: sets the height of keyboard frame + +[`canAddNewKeyboard()`](canAddNewKeyboard) +: returns whether adding a new keyboard is enabled, like in the keyboard picker menu + +[`canRemoveKeyboard()`](canRemoveKeyboard) +: returns whether removing a keyboard is enabled, like in the keyboard picker menu + +[`copyHTMLBannerAssets()`](copyHTMLBannerAssets) +: copies a folder of HTML banner assets so it's available for your keyboard app's resources + +[`createInputView()`](createInputView) +: creates the input view to be used in InputMethodService + +[`deregisterLexicalModel()`](deregisterLexicalModel) +: deregisters the specified lexical model from the LMLayer so it isn't used + +[`executeHardwareKeystroke()`](executeHardwareKeystroke) +: process the keystroke generated from a physical keyboard + +[`getAssociatedLexicalModel()`](getAssociatedLexicalModel) +: search the installed lexical models list and see if there's an associated model for a given language + +[`getBannerHeight()`](getBannerHeight) +: returns the height of the suggestion banner + +[`getCurrentKeyboardIndex()`](getCurrentKeyboardIndex) +: returns index number of the current keyboard in keyboards list + +[`getCurrentKeyboardInfo()`](getCurrentKeyboardInfo) +: returns information dictionary of the current keyboard + +[`getDefaultKeyboard()`](getDefaultKeyboard) +: returns the keyboard information for the fallback keyboard + +[`getFontTypeface()`](getFontTypeface) +: creates a new typeface from the specified font filename + +[`getGlobeKeyAction()`](getGlobeKeyAction) +: returns the action type of the 'Globe' key + +[`getHapticFeedback()`](getHapticFeedback) +: returns whether the device vibrates as the user types + +~~`getKeyboardFontFilename()`~~ `(Deprecated)` +: use getKeyboardTextFontFilename or getKeyboardOskFontFilename instead + +~~`getKeyboardFontTypeface()`~~ `(Deprecated)` +: use getKeyboardTextFontTypeface or getKeyboardOskFontTypeface instead + +[`getKeyboardHeight()`](getKeyboardHeight) +: returns the height of the keyboard frame + +[`getKeyboardIndex()`](getKeyboardIndex) +: returns index number of the specified keyboard in keyboards list + +[`getKeyboardInfo()`](getKeyboardInfo) +: returns information dictionary of the specified keyboard + +[`getKeyboardsList()`](getKeyboardsList) +: returns the array of keyboards list + +[`getKeyboardOskFontFilename()`](getKeyboardOskFontFilename) +: returns the selected keyboard's OSK font filename + +[`getKeyboardOskFontTypeface()`](getKeyboardOskFontTypeface) +: creates a new typeface from the selected keyboard's OSK font + +[`getKeyboardState()`](getKeyboardState) +: returns the specified keyboard's state + +[`getKeyboardTextFontFilename()`](getKeyboardTextFontFilename) +: returns the selected keyboard's text font filename + +[`getKeyboardTextFontTypeface()`](getKeyboardTextFontTypeface) +: creates a new typeface from the selected keyboard's text font + +[`getKMKeyboard()`](getKMKeyboard) +: returns the KMKeyboard depending whether it's an in-app or system keyboard + +[`getLatestKeyboardFileVersion()`](getLatestKeyboardFileVersion) +: returns the specified keyboard's latest file version number + +[`getLexicalModelInfo()`](getLexicalModelInfo) +: returns dictionary information of the specified lexical model + +[`getLexicalModelsList()`](getLexicalModelsList) +: returns the array of lexical models list + +[`getLanguageCorrectionPreferenceKey()`](getLanguageCorrectionPreferenceKey) +: returns a String to use as a shared preference key to store whether the LMLayer should enable corrections for a given language + +[`getLanguagePredictionPreferenceKey()`](getLanguagePredictionPreferenceKey) +: returns a String to use as a shared preference key to store whether the LMLayer should enable suggestions for a given language. + +[`getLongpressDelay()`](getLongpressDelay) +: returns from stored preference the number of milliseconds to trigger a longpress gesture + +[`getMaySendCrashReport()`](getMaySendCrashReport) +: returns whether Keyman Engine is allowed to send crash reports over the network to sentry.keyman.com + +[`getOrientation()`](getOrientation) +: returns the device's current orientation (Portrait vs Landscape) + +[`getSpacebarText()`](getSpacebarText) +: returns the current text display pattern for the spacebar + +[`getVersion()`](getVersion) +: returns the version number of Keyman Engine + +[`getWindowDensity()`](getWindowDensity) +: returns the density of the window + +[`getWindowSize()`](getWindowSize) +: returns the size of an area the window would occupy + +[`hasConnection()`](hasConnection) +: returns whether the device has active network connection + +[`hideSystemKeyboard()`](hideSystemKeyboard) +: hides the system OSK + +[`initialize()`](initialize) +: initializes the Keyman manager + +[`isDebugMode()`](isDebugMode) +: returns whether debugging of Keyman Engine is enabled + +~~`isHelpBubbleEnabled()`~~ `(Deprecated)` +: returns whether the help bubble is enabled + +[`isKeyboardLoaded()`](isKeyboardLoaded) +: returns whether the specified in-app or system keyboard is loaded + +[`keyboardExists()`](keyboardExists) +: returns whether the specified keyboard exists in keyboards list + +[`lexicalModelExists()`](lexicalModelExists) +: returns whether the specified lexical model exists in lexical models list + +[`onConfigurationChanged()`](onConfigurationChanged) +: performs necessary actions in an InputMethodService's onConfigurationChanged() + +[`onDestroy()`](onDestroy) +: performs necessary actions in an InputMethodService's onDestroy() + +[`onPause()`](onPause) +: performs necessary actions in an Activity's onPause() + +[`onResume()`](onResume) +: performs necessary actions in an Activity's onResume() + +[`onStartInput()`](onStartInput) +: performs necessary actions in an InputMethodService's onStartInput() + +[`registerAssociatedLexicalModel()`](registerAssociatedLexicalModel) +: registers a lexical model with the associated language ID + +[`registerLexicalModel()`](registerLexicalModel) +: registers a lexical model to use with the LMLayer + +[`removeKeyboard()`](removeKeyboard) +: removes the keyboard at specified position from the keyboards list + +[`removeKeyboardDownloadEventListener()`](removeKeyboardDownloadEventListener) +: removes the specified listener from the list of keyboard download event listeners + +[`removeKeyboardEventListener()`](removeKeyboardEventListener) +: removes the specified listener from the list of keyboard event listeners + +[`sendOptionsToKeyboard()`](sendOptionsToKeyboard) +: sends options like longpress delay to the KeymanWeb keyboard + +[`setCanAddNewKeyboard()`](setCanAddNewKeyboard) +: sets whether adding a new keyboard is allowed + +[`setCanRemoveKeyboard()`](setCanRemoveKeyboard) +: sets whether removing a keyboard is allowed, like in the keyboard picker menu + +[`setDebugMode()`](setDebugMode) +: enables or disables debugging of Keyman Engine + +[`setDefaultKeyboard()`](setDefaultKeyboard) +: sets the keyboard information for the fallback keyboard + +[`setGlobeKeyAction()`](setGlobeKeyAction) +: sets an action type for the 'Globe' key + +[`setHapticFeedback()`](setHapticFeedback) +: sets whether the device vibrates as the user types + +~~`setHelpBubbleEnabled()`~~ `(deprecated)` +: enables or disables the help bubble + +[`setHTMLBanner()`](setHTMLBanner) +: sets the contents of an HTML banner for Keyman Engine to display when suggestions aren't available + +[`setKeyboard()`](setKeyboard) +: sets the keyboard to be used + +[`setKeyboardPickerFont()`](setKeyboardPickerFont) +: sets the font for the keyboard picker menu + +~~`setKeymanLicense()`~~ `(Deprecated)` +: sets the developer license/key pair to unlock Keyman Engine + +[`setLongpressDelay()`](setLongpressDelay) +: stores the longpress delay in milliseconds as a preference. + +[`setMaySendCrashReport()`](setMaySendCrashReport) +: sets whether Keyman Engine can send crash reports over the network to sentry.keyman.com + +[`setShouldAllowSetKeyboard()`](setShouldAllowSetKeyboard) +: sets whether Keyman Engine allows setting a keyboard other than the default keyboard + +[`setShouldCheckKeyboardUpdates()`](setShouldCheckKeyboardUpdates) +: sets whether Keyman Engine should check for keyboard updates + +[`setSpacebarText()`](setSpacebarText) +: sets the current text display pattern for the spacebar + +[`shouldAllowSetKeyboard()`](shouldAllowSetKeyboard) +: returns whether Keyman Engine allows setting a keyboard other than the default keyboard + +[`shouldCheckKeyboardUpdates()`](shouldCheckKeyboardUpdates) +: returns whether Keyman Engine should check for keyboard updates + +[`showKeyboardPicker()`](showKeyboardPicker) +: displays the keyboard picker menu + +~~`showLanguageList()`~~ `(Deprecated)` +: displays the language list + +[`switchToNextKeyboard()`](switchToNextKeyboard) +: loads the next available keyboard in keyboards list + +[`updateSelectionRange()`](updateSelectionRange) +: updates the selection range of the current context + +[`updateText()`](updateText) +: updates the current context with the specified text diff --git a/android/docs/engine/KMManager/initialize.md b/android/docs/engine/KMManager/initialize.md new file mode 100644 index 00000000000..e4ddd5327d4 --- /dev/null +++ b/android/docs/engine/KMManager/initialize.md @@ -0,0 +1,47 @@ +--- +title: KMManager.initialize() +--- + +## Summary + +The **`initialize()`** method initializes the Keyman manager. + +## Syntax + +``` javascript +KMManager.initialize(Context context, KeyboardType keyboardType) +``` + +### Parameters + +`context` +: The context that starts the initialization. This is normally an + Activity or the application context of an InputMethodService. + +`keyboardType` +: KeyboardType to be used. `KEYBOARD_TYPE_INAPP` or + `KEYBOARD_TYPE_SYSTEM`. + +## Description + +This method is normally called from `onCreate()` method of an Activity +or InputMethodService. + +## Examples + +### Example: Using `initialize()` + +The following script illustrate the use of `initialize()`: + +``` javascript +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // ... + KMManager.initialize(this, KeyboardType.KEYBOARD_TYPE_INAPP); + // ... + // do not call setContentView before initializing the Keyman manager. + setContentView(R.layout.activity_main); + // ... +} +``` diff --git a/android/docs/engine/KMManager/isDebugMode.md b/android/docs/engine/KMManager/isDebugMode.md new file mode 100644 index 00000000000..5971ef1b9ce --- /dev/null +++ b/android/docs/engine/KMManager/isDebugMode.md @@ -0,0 +1,36 @@ +--- +title: KMManager.isDebugMode() +--- + +## Summary + +The **`isDebugMode()`** method returns whether debugging of Keyman +Engine is enabled. + +## Syntax + +``` javascript +KMManager.isDebugMode() +``` + +### Returns + +Returns `true` if debugging is enabled, `false` otherwise. + +## Description + +Use this method to check if debugging of Keyman Engine is enabled. + +## Examples + +### Example: Using `isDebugMode()` + +The following script illustrate the use of `isDebugMode()`: + +``` javascript + boolean isDebugEnabled = KMManager.isDebugMode(); +``` + +## See also + +- [`setDebugMode()`](setDebugMode) diff --git a/android/docs/engine/KMManager/isHelpBubbleEnabled.md b/android/docs/engine/KMManager/isHelpBubbleEnabled.md new file mode 100644 index 00000000000..a031aee5c91 --- /dev/null +++ b/android/docs/engine/KMManager/isHelpBubbleEnabled.md @@ -0,0 +1,42 @@ +--- +title: KMManager.isHelpBubbleEnabled() (Deprecated) +--- + +## Summary + +The **`isHelpBubbleEnabled()`** method returns whether the help bubble +is enabled. + +## Syntax + +``` javascript +KMManager.isHelpBubbleEnabled() +``` + +### Returns + +Returns `true` if the help bubble is enabled, `false` otherwise. + +## Description + +Use this method to check if the help bubble is enabled. This method only +works for the in-app keyboard since the system-wide keyboard never +displays a help bubble. + +## Examples + +### Example: Using `isHelpBubbleEnabled()` + +The following script illustrate the use of `isHelpBubbleEnabled()`: + +``` javascript + boolean isHelpBubbleEnabled = KMManager.isHelpBubbleEnabled(); +``` + +## History + +Deprecated syntax in Keyman Engine for Android 16.0 + +## See also + +- [`setHelpBubbleEnabled()`](setHelpBubbleEnabled) (Deprecated) diff --git a/android/docs/engine/KMManager/isKeyboardLoaded.md b/android/docs/engine/KMManager/isKeyboardLoaded.md new file mode 100644 index 00000000000..8e390c739ec --- /dev/null +++ b/android/docs/engine/KMManager/isKeyboardLoaded.md @@ -0,0 +1,44 @@ +--- +title: KMManager.isKeyboardLoaded() +--- + +## Summary +The **isKeyboardLoaded()** method returns whether the specified in-app or system keyboard is loaded. + +## Syntax +```java +KMManager.isKeyboardLoaded(KeyboardType type) +``` + +### Parameters +type + +: `KeyboardType.KEYBOARD_TYPE_INAPP` or `KeyboardType.KEYBOARD_TYPE_SYSTEM` + +If type is `KeyboardType.KEYBOARD_TYPE_UNDEFINED`, the function will return `false`. + +### Returns +Returns `true` if the specified keyboard is loaded, `false` otherwise. + +## Description +Use this method to check if a keyboard is loaded and ready to use. + +--- + +## Examples + +### Example: Using isKeyboardLoaded +The following script illustrate the use of `isKeyboardLoaded` + +```java +if (KMManager.isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_SYSTEM) { + // Get the keyboard info at index 0 + Keyboard keyboardInfo = KMManager.getKeyboardInfo(this, 0) +} +``` + +## History +Added syntax in Keyman Engine for Android 14.0. + +## See also +* [setKeyboard](setKeyboard) diff --git a/android/docs/engine/KMManager/keyboardExists.md b/android/docs/engine/KMManager/keyboardExists.md new file mode 100644 index 00000000000..cb27b305f64 --- /dev/null +++ b/android/docs/engine/KMManager/keyboardExists.md @@ -0,0 +1,53 @@ +--- +title: KMManager.keyboardExists() +--- + +## Summary + +The **`keyboardExists()`** method returns whether the specified keyboard +exists in keyboards list. + +## Syntax + +``` javascript +KMManager.keyboardExists(Context context, String keyboardID, String languageID) +``` + +### Parameters + +`context` +: The context. + +`keyboardID` +: ID of the keyboard. + +`languageID` +: ID of the associated language. + +### Returns + +Returns `true` if the keyboard exists in keyboards list, `false` +otherwise. + +## Description + +Use this method to check if the keyboard with given keyboard ID and +language ID exists in keyboards list. + +## Examples + +### Example: Using `keyboardExists()` + +The following script illustrate the use of `keyboardExists()`: + +``` javascript + boolean keyboardExists = KMManager.keyboardExists(this, "tamil99m", "ta"); +``` + +## See also + +- [`getCurrentKeyboardIndex()`](getCurrentKeyboardIndex) +- [`getCurrentKeyboardInfo()`](getCurrentKeyboardInfo) +- [`getKeyboardIndex()`](getKeyboardIndex) +- [`getKeyboardInfo()`](getKeyboardInfo) +- [`getKeyboardsList()`](getKeyboardsList) diff --git a/android/docs/engine/KMManager/lexicalModelExists.md b/android/docs/engine/KMManager/lexicalModelExists.md new file mode 100644 index 00000000000..2ec768e4371 --- /dev/null +++ b/android/docs/engine/KMManager/lexicalModelExists.md @@ -0,0 +1,42 @@ +--- +title: KMManager.lexicalModelExists() +--- + +## Summary +The **lexicalModelExists()** method returns whether the specified lexical model exists in lexical models list. + +## Syntax +```java +bool KMManager.lexicalModelExists(Context context, String packageID, String languageID, String modelID) +``` + +### Parameters +`context` +: The context. + +`packageID` +: ID of the package + +`languageID` +: ID of the associated language + +`modelID` +: ID of the lexical model + +### Returns +Returns `true` if the lexical model exists in the lexical models list, otherwise `false`. + +## Description +Use this method to determine if a lexical model with given package ID, language ID, and model ID exists in the lexical models list. + +## Examples + +### Example: Using lexicalModelExists() +The following script illustrate the use of `lexicalModelExists()`: +```java + // Determine if the specified lexical model exists for English (en) + boolean exists = KMManager.lexicalModelExists(context, "nrc.en.mtnt", "en", "nrc.en.mtnt"); +``` + +## See also +* [`getLexicalModelInfo()`](getLexicalModelInfo) diff --git a/android/docs/engine/KMManager/onConfigurationChanged.md b/android/docs/engine/KMManager/onConfigurationChanged.md new file mode 100644 index 00000000000..f83b9634002 --- /dev/null +++ b/android/docs/engine/KMManager/onConfigurationChanged.md @@ -0,0 +1,45 @@ +--- +title: KMManager.onConfigurationChanged() +--- + +## Summary + +The **`onConfigurationChanged()`** method performs necessary actions in +an InputMethodService's `onConfigurationChanged()`. + +## Syntax + +``` javascript +KMManager.onConfigurationChanged(Configuration newConfig) +``` + +### Parameters + +`newConfig` +: The new device configuration. + +## Description + +To be called from an InputMethodService's `onConfigurationChanged()` +method. + +## Examples + +### Example: Using `onConfigurationChanged()` + +The following script illustrate the use of `onConfigurationChanged()`: + +``` javascript +@Override +public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + KMManager.onConfigurationChanged(newConfig); + // ... +} +``` + +## See also + +- [`createInputView()`](createInputView) +- [`onStartInput()`](onStartInput) +- [`onDestroy()`](onDestroy) diff --git a/android/docs/engine/KMManager/onDestroy.md b/android/docs/engine/KMManager/onDestroy.md new file mode 100644 index 00000000000..84ce45f14fd --- /dev/null +++ b/android/docs/engine/KMManager/onDestroy.md @@ -0,0 +1,39 @@ +--- +title: KMManager.onDestroy() +--- + +## Summary + +The **`onDestroy()`** method performs necessary actions in an +InputMethodService's `onDestroy()`. + +## Syntax + +``` javascript +KMManager.onDestroy() +``` + +## Description + +To be called from an InputMethodService's `onDestroy()` method. + +## Examples + +### Example: Using `onDestroy()` + +The following script illustrate the use of `onDestroy()`: + +``` javascript +@Override +public void onDestroy() { + // ... + KMManager.onDestroy(); + super.onDestroy(); +} +``` + +## See also + +- [`createInputView()`](createInputView) +- [`onStartInput()`](onStartInput) +- [`onConfigurationChanged()`](onConfigurationChanged) diff --git a/android/docs/engine/KMManager/onPause.md b/android/docs/engine/KMManager/onPause.md new file mode 100644 index 00000000000..e2ff7711b81 --- /dev/null +++ b/android/docs/engine/KMManager/onPause.md @@ -0,0 +1,37 @@ +--- +title: KMManager.onPause() +--- + +## Summary + +The **`onPause()`** method performs necessary actions in an Activity's +`onPause()`. + +## Syntax + +``` javascript +KMManager.onPause() +``` + +## Description + +To be called from an Activity's `onPause()` method. + +## Examples + +### Example: Using `onPause()` + +The following script illustrate the use of `onPause()`: + +``` javascript +@Override +protected void onPause() { + super.onPause(); + KMManager.onPause(); + // ... +} +``` + +## See also + +- [`onResume()`](onResume) diff --git a/android/docs/engine/KMManager/onResume.md b/android/docs/engine/KMManager/onResume.md new file mode 100644 index 00000000000..0260756a8ac --- /dev/null +++ b/android/docs/engine/KMManager/onResume.md @@ -0,0 +1,37 @@ +--- +title: KMManager.onResume() +--- + +## Summary + +The **`onResume()`** method performs necessary actions in an Activity's +`onResume()`. + +## Syntax + +``` javascript +KMManager.onResume() +``` + +## Description + +To be called from an Activity's `onResume()` method. + +## Examples + +### Example: Using `onResume()` + +The following script illustrate the use of `onResume()`: + +``` javascript +@Override +protected void onResume() { + super.onResume(); + KMManager.onResume(); + // ... +} +``` + +## See also + +- [`onPause()`](onPause) diff --git a/android/docs/engine/KMManager/onStartInput.md b/android/docs/engine/KMManager/onStartInput.md new file mode 100644 index 00000000000..17e6c986da6 --- /dev/null +++ b/android/docs/engine/KMManager/onStartInput.md @@ -0,0 +1,49 @@ +--- +title: KMManager.onStartInput() +--- + +## Summary + +The **`onStartInput()`** method performs necessary actions in an +InputMethodService's `onStartInput()`. + +## Syntax + +``` javascript +KMManager.onStartInput(EditorInfo attribute, boolean restarting) +``` + +### Parameters + +`attribute` +: Description of the type of text being edited. + +`restarting` +: Set to true if we are restarting input on the same text field as + before. + +## Description + +To be called from an InputMethodService's `onStartInput()` method. + +## Examples + +### Example: Using `onStartInput()` + +The following script illustrate the use of `onStartInput()`: + +``` javascript +@Override +public void onStartInput(EditorInfo attribute, boolean restarting) { + // ... + super.onStartInput(attribute, restarting); + KMManager.onStartInput(attribute, restarting); + // ... +} +``` + +## See also + +- [`createInputView()`](createInputView) +- [`onConfigurationChanged()`](onConfigurationChanged) +- [`onDestroy()`](onDestroy) diff --git a/android/docs/engine/KMManager/registerAssociatedLexicalModel.md b/android/docs/engine/KMManager/registerAssociatedLexicalModel.md new file mode 100644 index 00000000000..32943839d1f --- /dev/null +++ b/android/docs/engine/KMManager/registerAssociatedLexicalModel.md @@ -0,0 +1,36 @@ +--- +title: KMManager.registerAssociatedLexicalModel() +--- + +## Summary +The **registerAssociatedLexicalModel()** method registers a lexical model with the associated language ID. + +## Syntax +```java +KMManager.registerAssociatedLexicalModel(String langId) +``` + +### Parameters + +`langId` +: The BCP 47 language ID + +### Returns +Returns `true` if a new lexical model is loaded (different from the currently loaded lexical model), `false` otherwise. + +## Description +Use this method after switching keyboard languages so the LMLayer will load and use the correct lexical model for generating suggestions. + +## Examples + +### Example: Using `registerAssociatedLexicalModel()` +The following script illustrates the use of `registerAssociatedLexicalModel()`: + +```java + String langId = "ta"; + KMManager.registerAssociatedLexicalModel(langId); +``` + +## See also +* [getAssociatedLexicalModel()](getAssociatedLexicalModel) +* [registerLexicalModel()](registerLexicalModel) diff --git a/android/docs/engine/KMManager/registerLexicalModel.md b/android/docs/engine/KMManager/registerLexicalModel.md new file mode 100644 index 00000000000..3c8a14589d2 --- /dev/null +++ b/android/docs/engine/KMManager/registerLexicalModel.md @@ -0,0 +1,45 @@ +--- +title: KMManager.registerLexicalModel() +--- + +## Summary +The **registerLexicalModel()** method registers a lexical model to use with the LMLayer. + +## Syntax +```java +KMManager.registerLexicalModel(HashMap lexicalModelInfo) +``` + +### Parameters +`lexicalModelInfo` + +: A dictionary of lexical model information with keys and values defined as `HashMaplexicalModelInfo = new HashMap(); + lexicalModelInfo.put(KMManager.KMKey_PackageID, "example.ta.wordlist"); + lexicalModelInfo.put(KMManager.KMKey_LanguageID, "ta"); + lexicalModelInfo.put(KMManager.KMKey_LexicalModelID, "example.ta.wordlist"); + lexicalModelInfo.put(KMManager.KMKey_LexicalModelVersion, "1.0"); + KMManager.addLexicalModel(this, lexicalModelInfo); + + KMManager.registerLexicalModel(lexicalModelInfo); +``` + +## See also +* [addLexicalModel()](addLexicalModel) +* [deregisterLexicalModel()](deregisterLexicalModel) diff --git a/android/docs/engine/KMManager/removeKeyboard.md b/android/docs/engine/KMManager/removeKeyboard.md new file mode 100644 index 00000000000..44bc937126e --- /dev/null +++ b/android/docs/engine/KMManager/removeKeyboard.md @@ -0,0 +1,48 @@ +--- +title: KMManager.removeKeyboard() +--- + +## Summary + +The **`removeKeyboard()`** method removes the keyboard at specified +position from the keyboards list. + +## Syntax + +``` javascript +KMManager.removeKeyboard(Context context, int position) +``` + +### Parameters + +`context` +: The context. + +`position` +: 0-based position of the keyboard in the keyboards list. + +### Returns + +Returns `true` if the keyboard was removed successfully, `false` +otherwise. + +## Description + +Use this method to remove a keyboard from the keyboards list. If the +position is invalid, it will be ignored and the method will return +`false` without altering the keyboards list. + +## Examples + +### Example: Using `removeKeyboard()` + +The following script illustrate the use of `removeKeyboard()`: + +``` javascript + // Remove the second keyboard in the list + KMManager.removeKeyboard(this, 1); +``` + +## See also + +- [`addKeyboard()`](addKeyboard) diff --git a/android/docs/engine/KMManager/removeKeyboardDownloadEventListener.md b/android/docs/engine/KMManager/removeKeyboardDownloadEventListener.md new file mode 100644 index 00000000000..1da041a6125 --- /dev/null +++ b/android/docs/engine/KMManager/removeKeyboardDownloadEventListener.md @@ -0,0 +1,46 @@ +--- +title: KMManager.removeKeyboardDownloadEventListener() +--- + +## Summary + +The **`removeKeyboardDownloadEventListener()`** method removes the +specified listener from the list of keyboard download event listeners. + +## Syntax + +``` javascript +KMManager.removeKeyboardDownloadEventListener(OnKeyboardDownloadEventListener listener) +``` + +### Parameters + +`listener` +: The listener to be removed. + +## Description + +Use this method to remove the listener to stop receiving keyboard +download event notifications. The listener must be removed once you +finished with it. + +## Examples + +### Example: Using `removeKeyboardDownloadEventListener()` + +The following script illustrate the use of +`removeKeyboardDownloadEventListener()`: + +``` javascript + @Override + protected void onPause() { + super.onPause(); + // ... + KMManager.removeKeyboardDownloadEventListener(this); + // ... + } +``` + +## See also + +- [`addKeyboardDownloadEventListener()`](addKeyboardDownloadEventListener) diff --git a/android/docs/engine/KMManager/removeKeyboardEventListener.md b/android/docs/engine/KMManager/removeKeyboardEventListener.md new file mode 100644 index 00000000000..dc999144d27 --- /dev/null +++ b/android/docs/engine/KMManager/removeKeyboardEventListener.md @@ -0,0 +1,45 @@ +--- +title: KMManager.removeKeyboardEventListener() +--- + +## Summary + +The **`removeKeyboardEventListener()`** method removes the specified +listener from the list of keyboard event listeners. + +## Syntax + +``` javascript +KMManager.removeKeyboardEventListener(OnKeyboardEventListener listener) +``` + +### Parameters + +`listener` +: The listener to be removed. + +## Description + +Use this method to remove the listener to stop receiving keyboard event +notifications. The listener must be removed once you finished with it. + +## Examples + +### Example: Using `removeKeyboardEventListener()` + +The following script illustrate the use of +`removeKeyboardEventListener()`: + +``` javascript + @Override + protected void onPause() { + super.onPause(); + // ... + KMManager.removeKeyboardEventListener(this); + // ... + } +``` + +## See also + +- [`addKeyboardEventListener()`](addKeyboardEventListener) diff --git a/android/docs/engine/KMManager/sample_template.md b/android/docs/engine/KMManager/sample_template.md new file mode 100644 index 00000000000..4c013865377 --- /dev/null +++ b/android/docs/engine/KMManager/sample_template.md @@ -0,0 +1,41 @@ +--- +title: Summary +--- + +The **`method()`** method does . . . + +## Syntax + +``` javascript +KMManager.method(Param param1, Param param2) +``` + +### Parameters + +`param1` +: Param details. + +`param2` +: Param details. + +### Returns + +Details of return value if any + +## Description + +Description. + +## Examples + +### Example: Using `method()` + +The following script illustrate the use of `method()`: + +``` javascript +//Code here +``` + +## See also + +- [`...`](sample_template) diff --git a/android/docs/engine/KMManager/sendOptionsToKeyboard.md b/android/docs/engine/KMManager/sendOptionsToKeyboard.md new file mode 100644 index 00000000000..399dfc79123 --- /dev/null +++ b/android/docs/engine/KMManager/sendOptionsToKeyboard.md @@ -0,0 +1,41 @@ +--- +title: KMManager.sendOptionsToKeyboard() +--- + +## Summary + +The `sendOptionsToKeyboard()` method sends options like longpress delay to the KeymanWeb keyboard. + +## Syntax + +```java +KMManager.sendOptionsToKeyboard() +``` + +## Description +Use this method to update options in the KeymanWeb keyboard. +* Number of milliseconds to trigger a longpress gesture + +This method requires a keyboard to be loaded for the values to take effect. + +## Examples + +### Example: Using `sendOptionsToKeyboard()` + +The following code illustrates the use of `sendOptionsToKeyboard()`: +```java + int currentDelayTimeMS = 250; + + // Store currentDelayTimeMS + KMManager.setLongpressDelay(currentDelayTimeMS); + + // Apply the keyboard options + KMManager.sendOptionsToKeyboard(); +``` + +## History +Keyman Engine for Android 18.0: New function. + +## See also +* [getLongpressDelay](getLongpressDelay) +* [setLongpressDelay](setLongpressDelay) diff --git a/android/docs/engine/KMManager/setCanAddNewKeyboard.md b/android/docs/engine/KMManager/setCanAddNewKeyboard.md new file mode 100644 index 00000000000..0b265903b12 --- /dev/null +++ b/android/docs/engine/KMManager/setCanAddNewKeyboard.md @@ -0,0 +1,39 @@ +--- +title: KMManager.setCanAddNewKeyboard() +--- + +## Summary + +The **`setCanAddNewKeyboard()`** method sets whether adding a new +keyboard is allowed. + +## Syntax + +``` javascript +KMManager.setCanAddNewKeyboard(boolean newValue) +``` + +### Parameters + +`newValue` +: If `false`, adding a new keyboard is disabled. + +## Description + +Use this method to enable or disable '+' (add new keyboard) button in +the keyboard picker menu. + +## Examples + +### Example: Using `setCanAddNewKeyboard()` + +The following script illustrate the use of `setCanAddNewKeyboard()`: + +``` javascript + // Disable add new keyboard button. + KMManager.setCanAddNewKeyboard(false); +``` + +## See also + +- [`canAddNewKeyboard`](canAddNewKeyboard) diff --git a/android/docs/engine/KMManager/setCanRemoveKeyboard.md b/android/docs/engine/KMManager/setCanRemoveKeyboard.md new file mode 100644 index 00000000000..cad610bd7cf --- /dev/null +++ b/android/docs/engine/KMManager/setCanRemoveKeyboard.md @@ -0,0 +1,33 @@ +--- +title: KMManager.setCanRemoveKeyboard() +--- + +## Summary +The **setCanRemoveKeyboard()** method sets whether removing a keyboard is allowed, like in the keyboard picker menu. + +## Syntax + +```java + void KMManager.setCanRemoveKeyboard(boolean newValue) +``` + +## Parameters + +`newValue` +: `true` if removing a keyboard is allowed, `false` otherwise. + +## Description +Use this method to grant the end user permission to remove keyboards from the keyboard list. If set to `false`, the installed keyboard list is permanent. + +## Examples + +### Example: Using `setCanRemoveKeyboard()` + +The following script illustrates the use of `setCanRemoveKeyboard()`: +```java + // Disable removing keyboards + KMManager.setCanRemoveKeyboard(false); +``` + +## See also +* [`canRemoveKeyboard()`](canRemoveKeyboard) diff --git a/android/docs/engine/KMManager/setDebugMode.md b/android/docs/engine/KMManager/setDebugMode.md new file mode 100644 index 00000000000..b1b02620eb2 --- /dev/null +++ b/android/docs/engine/KMManager/setDebugMode.md @@ -0,0 +1,39 @@ +--- +title: KMManager.setDebugMode() +--- + +## Summary + +The **`setDebugMode()`** enables or disables debugging of Keyman Engine. + +## Syntax + +``` javascript +KMManager.setDebugMode(boolean value) +``` + +### Parameters + +`value` +: Set `true` to enable debugging, `false` to disable. + +## Description + +Use this method to enable or disable log output generated by Keyman +Engine. By default debugging is disabled. + +## Examples + +### Example: Using `setDebugMode()` + +The following script illustrate the use of `setDebugMode()`: + +``` javascript + KMManager.setDebugMode(true); + // Debugging is now on + // Initialize KMManager here +``` + +## See also + +- [isDebugMode()](isDebugMode) diff --git a/android/docs/engine/KMManager/setDefaultKeyboard.md b/android/docs/engine/KMManager/setDefaultKeyboard.md new file mode 100644 index 00000000000..ac6684dca47 --- /dev/null +++ b/android/docs/engine/KMManager/setDefaultKeyboard.md @@ -0,0 +1,55 @@ +--- +title: KMManager.setDefaultKeyboard() +--- + +## Summary +The **setDefaultKeyboard()** method sets the keyboard information for the fallback keyboard. + +## Syntax +```java +KMManager.setDefaultKeyboard(Keyboard keyboardInfo) +``` + +### Parameters +keyboardInfo + +The keyboard information for the default keyboard. + +## Description +The **setDefaultKeyboard()** method sets the keyboard information for the fallback keyboard. If Keyman Engine +has issues with a current keyboard, KMManager will switch to this fallback keyboard. + +A fallback keyboard should also be defined if an app doesn't automatically add a keyboard (requires user selection). + +**setDefaultKeyboard** should be called after KMManager.initialize(). + +## Examples + +### Example: Using setDefaultKeyboard() +The following script illustrates the use of `setDefaultKeyboard()`: +```java + KMManager.initialize(getApplicationContext(), KMManager.KeyboardType.KEYBOARD_TYPE_INAPP); + + // Set the default (fallback) keyboard if this app doesn't automatically call addKeyboard(). + KMManager.setDefaultKeyboard( + new Keyboard( + "basic_kbdtam99", // Package ID - filename of the .kmp file + "basic_kbdtam99", // Keyboard ID + "Tamil 99 Basic", // Keyboard Name + "ta", // Language ID + "Tamil", // Language Name + "1.0", // Keyboard Version + null, // URL to help documentation if available + "", // URL to latest .kmp file + true, // Boolean to show this is a new keyboard in the keyboard picker + + KMManager.KMDefault_KeyboardFont, // Font for the keyboard + KMManager.KMDefault_KeyboardFont) // Font for OSK + ); +``` + +## History +Added syntax in Keyman Engine for Android 14.0. + +## See also +* [getDefaultKeyboard](getDefaultKeyboard) diff --git a/android/docs/engine/KMManager/setGlobeKeyAction.md b/android/docs/engine/KMManager/setGlobeKeyAction.md new file mode 100644 index 00000000000..4b56dbb4dcb --- /dev/null +++ b/android/docs/engine/KMManager/setGlobeKeyAction.md @@ -0,0 +1,58 @@ +--- +title: KMManager.setGlobeKeyAction() +--- + +## Summary +The **setGlobeKeyAction()** method sets the short-press action type for the 'Globe' key. + +## Syntax +```java +KMManager.setGlobeKeyAction(KeyboardType kbType, int action) +``` + +### Parameters +type + +: `KeyboardType.KEYBOARD_TYPE_INAPP` or `KeyboardType.KEYBOARD_TYPE_SYSTEM` + +action + +: The action type. `GLOBE_KEY_ACTION_SHOW_MENU`, `GLOBE_KEY_ACTION_SWITCH_TO_NEXT_KEYBOARD`, + `GLOBE_KEY_ACTION_ADVANCE_TO_PREVIOUS_SYSTEM_KEYBOARD`, `GLOBE_KEY_ACTION_ADVANCE_TO_NEXT_SYSTEM_KEYBOARD`, + `GLOBE_KEY_ACTION_SHOW_SYSTEM_KEYBOARDS`, `GLOBE_KEY_ACTION_DO_NOTHING`. + +## Description +Use this method to set the short-press action type for the 'Globe' key. Even when the default action type is +set, Keyman Engine will still use the following default action types when only one Keyman keyboard is installed: + +| KeyboardType | # Keyman Keyboards Installed | Globe Key Action Type | +|----------------------|:----------------------------:|------------------------------------------------------| +| KEYBOARD_TYPE_INAPP | 1 | GLOBE_KEY_ACTION_SHOW_MENU | +| KEYBOARD_TYPE_SYSTEM | 1 | GLOBE_KEY_ACTION_ADVANCE_TO_PREVIOUS_SYSTEM_KEYBOARD | + +The action `GLOBE_KEY_ACTION_SHOW_MENU` displays the Keyman keyboard picker menu. +Other enabled system keyboards are also listed at the end of the menu

+ +The action `GLOBE_KEY_ACTION_SWITCH_TO_NEXT_KEYBOARD` switches to the next Keyman keyboard (if more than 1 are installed). +Otherwise, the Keyman keyboard picker menu is displayed. + +The action `GLOBE_KEY_ACTION_ADVANCE_TO_PREVIOUS_SYSTEM_KEYBOARD` switches to the previous system keyboard. + +The action `GLOBE_KEY_ACTION_ADVANCE_TO_NEXT_SYSTEM_KEYBOARD` switches to the next system keyboard. + +The action `GLOBE_KEY_ACTION_SHOW_SYSTEM_KEYBOARDS` brings up the Android input method picker and +can only be set for `KEYBOARD_TYPE_SYSTEM`. + +## Examples + +### Example: Using setGlobeKeyAction +The following script illustrate the use of `setGlobeKeyAction` + +```java +// Tapping 'Globe' key will switch to the next keyboard +KMManager.setGlobeKeyAction(KeyboardType.KEYBOARD_TYPE_SYSTEM, + GlobeKeyAction.GLOBE_KEY_ACTION_SWITCH_TO_NEXT_KEYBOARD); +``` + +## See also +* [getGlobeKeyAction](getGlobeKeyAction) diff --git a/android/docs/engine/KMManager/setHTMLBanner.md b/android/docs/engine/KMManager/setHTMLBanner.md new file mode 100644 index 00000000000..5fcc2c70033 --- /dev/null +++ b/android/docs/engine/KMManager/setHTMLBanner.md @@ -0,0 +1,45 @@ +--- +title: KMManager.setHTMLBanner +--- + +## Summary +The **setHTMLBanner()** method sets the HTML banner content for Keyman Engine to display when suggestions aren't available. + +## Syntax + +```javascript +KMManager.setHTMLBanner(KeyboardType keyboardType, String content) +``` + +### Parameters + +`keyboardType` +: KeyboardType to be used. `KEYBOARD_TYPE_INAPP` or `KEYBOARD_TYPE_SYSTEM`. + +`content` +: HTML content formatted as a string. + +### Returns +Returns `true` if HTML banner is set, `false` otherwise. + +## Description +When suggestions aren't available for a keyboard, an HTML banner is displayed instead. +Use this method to specify the HTML content to display in the banner to theme your keyboard app. + +If the banner theme references assets (like .svg or .css files), ensure you've also called [copyHTMLBannerAssets()](copyHTMLBannerAssets). + +Note: The HTML banner needs to be updated whenever the keyboard is reloaded, so call this in `SystemKeyboard.onInitializeInterface(()`. + +## Examples + +### Example: Using `setHTMLBanner()` + +The following script illustrates the use of `setHTMLBanner()`: +```javascript + String KMGRAY_BANNER = "
"; + // Sets the HTML banner content + KMManager.setHTMLBanner(KeyboardType.KEYBOARD_TYPE_SYSTEM, KMGRAY_BANNER); +``` + +## See also +* [copyHTMLBannerAssets()](copyHTMLBannerAssets) diff --git a/android/docs/engine/KMManager/setHapticFeedback.md b/android/docs/engine/KMManager/setHapticFeedback.md new file mode 100644 index 00000000000..2e3c4422fa8 --- /dev/null +++ b/android/docs/engine/KMManager/setHapticFeedback.md @@ -0,0 +1,35 @@ +--- +title: KMManager.setHapticFeedback() +--- + +## Summary +The **setHapticFeedback()** method sets whether the device vibrates as the user types. + +## Syntax +```java +KMManager.setHapticFeedback(boolean value) +``` + +### Parameters +value + +Set `true` to enable device vibrating as the user types, `false` to disable. + +## Description +Use this method to enable or disable haptic feedback. This determines if the device vibrates as the user types. +By default, haptic feedback is disabled. + +## Examples + +### Example: Using setHapticFeedback() +The following script illustrates the use of `setHapticFeedback()`: +```java + // Enable haptic feeedback + KMManager.setHapticFeedback(true); +``` + +## History +Keyman Engine for Android 15.0: New function. + +## See also +* [getHapticFeedback](getHapticFeedback) diff --git a/android/docs/engine/KMManager/setHelpBubbleEnabled.md b/android/docs/engine/KMManager/setHelpBubbleEnabled.md new file mode 100644 index 00000000000..91839d972f7 --- /dev/null +++ b/android/docs/engine/KMManager/setHelpBubbleEnabled.md @@ -0,0 +1,44 @@ +--- +title: KMManager.setHelpBubbleEnabled() (Deprecated) +--- + +## Summary + +The **`setHelpBubbleEnabled()`** enables or disables the help bubble. + +## Syntax + +``` javascript +KMManager.setHelpBubbleEnabled(boolean newValue) +``` + +### Parameters + +`newValue` +: Set `true` to enable the help bubble, `false` to disable. + +## Description + +Use this method to enable or disable the help bubble which displays "Tap +here to change keyboard" over the 'Globe' key if the user has never used +it yet. By default it is enabled. This method only works for the in-app +keyboard since the system-wide keyboard never displays a help bubble. + +## Examples + +### Example: Using `setHelpBubbleEnabled()` + +The following script illustrate the use of `setHelpBubbleEnabled()`: + +``` javascript + KMManager.setHelpBubbleEnabled(false); + // Help bubble is now disabled +``` + +## History + +Deprecated syntax in Keyman Engine for Android 16.0 + +## See also + +- [isHelpBubbleEnabled()](isHelpBubbleEnabled) (Deprecated) diff --git a/android/docs/engine/KMManager/setKeyboard.md b/android/docs/engine/KMManager/setKeyboard.md new file mode 100644 index 00000000000..4a152f2480d --- /dev/null +++ b/android/docs/engine/KMManager/setKeyboard.md @@ -0,0 +1,155 @@ +--- +title: KMManager.setKeyboard() +--- + +## Summary + +The `setKeyboard()` method sets the active keyboard. + +## Syntax + +```java +KMManager.setKeyboard(Context context, Keyboard keyboardInfo) +``` + +### Parameters + +`context` +: The context. + +`keyboardInfo` +: `Keyboard` type of the keyboard information. + +### Returns + +Returns `true` if the keyboard was set successfully, `false` otherwise. + +## Description + +Selects the keyboard identified by the keyboard information, which is +normally returned by [`getKeyboardInfo()`](getKeyboardInfo). + +--- + +## Syntax + +```java +KMManager.setKeyboard(String packageID, String keyboardID, String languageID) +KMManager.setKeyboard(String packageID, String keyboardID, String languageID, String keyboardName, String languageName, String kFont, String kOskFont) +KMManager.setKeyboard(String packageID, String keyboardID, String languageID, String keyboardName, String languageName, String kFont, String kOskFont, String displayName) +``` + +### Parameters + +`packageID` +: ID of the keyboard package. + +`keyboardID` +: ID of the keyboard. + +`languageID` +: ID of the associated language. + +`keyboardName` +: Name of the keyboard. + +`languageName` +: Name of the associated language. + +`kFont` +: Filename or description of the font to type with the keyboard. Can be `null` + or empty string. + +`kOskFont` +: Filename or description of the font displayed on the keyboard. Can be `null` + or empty string. + +`displayName` +: A text string to display on the spacebar identifying this keyboard; if `null`, + uses engine default from [`setSpacebarText()`](setSpacebarText); if `""`, + shows no text on the spacebar. + +### Returns + +Returns `true` if the keyboard was set successfully, `false` otherwise. + +## Description + +Sets the currently active keyboard, along with font and display details. + +--- + +## Syntax + +``` +KMManager.setKeyboard(Context context, int position) +``` + +### Parameters + +`context` +: The context. + +`position` +: 0-based position of the keyboard in the keyboards list. + +### Returns + +Returns `true` if the keyboard was set successfully, `false` otherwise. + +## Description + +Sets the currently active keyboard by position in the keyboards list, as +returned by [`getKeyboardsList()`](getKeyboardsList) + +--- + +## Examples + +### Example 1: Using `setKeyboard()` + +The following script illustrates the use of `setKeyboard()` with keyboard information: + +```java +// Setting a Keyman keyboard +Keyboard keyboardInfo = KMManager.getDefaultKeyboard(); +KMManager.setKeyboard(getApplicationContext(), keyboardInfo); +``` + +### Example 2: Using `setKeyboard()` + +The following script illustrates the use of `setKeyboard()` with package ID, +keyboard ID, and language ID: + +```java +// Setting a Keyman keyboard +KMManager.setKeyboard("sil_euro_latin", "sil_euro_latin", "en"); +``` + +### Example 3: Using `setKeyboard()` + +The following script illustrates the use of `setKeyboard()`, providing +additional font detail: + +```java +// Setting a custom keyboard from the tamil99m keyboard package +KMManager.setKeyboard("tamil99m", "tamil99m", "ta", "Tamil 99M", "Tamil", "aava1.ttf", "aava1.ttf"); +``` + +### Example 4: Using `setKeyboard()` + +The following script illustrates the use of `setKeyboard()` with keyboard index: + +```java +// Setting a custom keyboard which exists in keyboards list +int kbIndex = KMManager.getKeyboardIndex(this, "tamil99m", "ta"); +KMManager.setKeyboard(this, kbIndex); +``` + +## See also + +* [`addKeyboard()`](addKeyboard) +* [`getDefaultKeyboard()`](getDefaultKeyboard) +* [`getKeyboardInfo()`](getKeyboardInfo) +* [`getKeyboardsList()`](getKeyboardsList) +* [`switchToNextKeyboard()`](switchToNextKeyboard) diff --git a/android/docs/engine/KMManager/setKeyboardPickerFont.md b/android/docs/engine/KMManager/setKeyboardPickerFont.md new file mode 100644 index 00000000000..66f73a8926e --- /dev/null +++ b/android/docs/engine/KMManager/setKeyboardPickerFont.md @@ -0,0 +1,33 @@ +--- +title: KMManager.setKeyboardPickerFont() +--- + +## Summary + +The **`setKeyboardPickerFont()`** sets the font for the keyboard picker +menu. + +## Syntax + +``` javascript +KMManager.setKeyboardPickerFont(Typeface typeface) +``` + +### Parameters + +`typeface` +: The font + +## Description + +Use this method to set a font for the keyboard picker menu. + +## Examples + +### Example: Using `setKeyboardPickerFont()` + +The following script illustrate the use of `setKeyboardPickerFont()`: + +``` javascript + KMManager.setKeyboardPickerFont(Typeface.createFromAsset(getAssets(), "fonts/custom_font.ttf")); +``` diff --git a/android/docs/engine/KMManager/setKeymanLicense.md b/android/docs/engine/KMManager/setKeymanLicense.md new file mode 100644 index 00000000000..37a8980f7bf --- /dev/null +++ b/android/docs/engine/KMManager/setKeymanLicense.md @@ -0,0 +1,47 @@ +--- +title: KMManager.setKeymanLicense() (Deprecated) +--- + +## Summary + +(Deprecated) The **`setKeymanLicense()`** method sets the developer +license/key pair to unlock Keyman Engine. + +## Syntax + +``` javascript +KMManager.setKeymanLicense(String license, String key) +``` + +### Parameters + +`license` +: Your developer license for Keyman Engine for Android. + +`key` +: Your developer key for Keyman Engine for Android. + +## Description + +You must use this method to set the developer license/key pair before +initializing the KMManager. You will receive the license/key pair when +you purchase Keyman Engine for Android. + +## Examples + +### Example: Using `setKeymanLicense()` + +The following script illustrate the use of `setKeymanLicense()`: + +``` javascript + KMManager.setLicense(“YourLicense”,”YourKey”); + // Initialize KMManager here after setting the license +``` + +## History + +Deprecated in Keyman Engine for Android 12.0 + +## See also + +- [`KMManager.initialize()`](initialize) diff --git a/android/docs/engine/KMManager/setLongpressDelay.md b/android/docs/engine/KMManager/setLongpressDelay.md new file mode 100644 index 00000000000..e4666c867bf --- /dev/null +++ b/android/docs/engine/KMManager/setLongpressDelay.md @@ -0,0 +1,42 @@ +--- +title: KMManager.setLongpressDelay() +--- + +## Summary + +The `setLongpressDelay()` method sets the number of milliseconds to trigger a longpress gesture as a stored preference. + +## Syntax + +```java +KMManager.setLongpressDelay(int longpressDelay) +``` +### Parameter +`longpressDelay` +: The number of milliseconds, ranging from 300 ms to 1500 ms. + +## Description +Use this method to store how many milliseconds to trigger a longpress as a preference. +This preference is stored at the Keyman app level, and is applied to all Keyman keyboards. + +## Examples + +### Example: Using `setLongpressDelay()` + +The following code illustrates the use of `setLongpressDelay()`: +```java + int currentDelayTimeMS = 300; + + // Store currentDelayTimeMS + KMManager.setLongpressDelay(currentDelayTimeMS); + + // Apply the keyboard options + KMManager.sendOptionsToKeyboard(); +``` + +## History +Keyman Engine for Android 18.0: New function. + +## See also +* [getLongpressDelay](getLongpressDelay) +* [sendOptionsToKeyboard](sendOptionsToKeyboard) diff --git a/android/docs/engine/KMManager/setMaySendCrashReport.md b/android/docs/engine/KMManager/setMaySendCrashReport.md new file mode 100644 index 00000000000..0c5cf650ede --- /dev/null +++ b/android/docs/engine/KMManager/setMaySendCrashReport.md @@ -0,0 +1,40 @@ +--- +title: KMManager.setMaySendCrashReport() +--- + +## Summary +The **setMaySendCrashReport()** enables or disables whether Keyman Engine can send crash reports over the +network to sentry.keyman.com. + +## Syntax +```java +KMManager.setMaySendCrashReport(boolean value) +``` + +### Parameters +value + +Set `true` to enable crash reports to be sent, `false` to disable. + +## Description +Use this method to enable or disable whether Keyman Engine can send crash reports over the network. +By default sending crash reports is enabled. + +If you don't want crash reports to be sent, your app must disable this before `KMManager.initialize()`. + +## Examples + +### Example: Using setMaySendCrashReport() +The following script illustrates the use of `setMaySendCrashReport()`: +```java + // Disable crash reports from being sent + KMManager.setMaySendCrashReport(false); + // Initialize KMManager + KMManager.initialize(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_INAPP); +``` + +## History +Added syntax in Keyman Engine for Android 14.0. + +## See also +* [getMaySendCrashReport](getMaySendCrashReport) diff --git a/android/docs/engine/KMManager/setShouldAllowSetKeyboard.md b/android/docs/engine/KMManager/setShouldAllowSetKeyboard.md new file mode 100644 index 00000000000..ddec5afae25 --- /dev/null +++ b/android/docs/engine/KMManager/setShouldAllowSetKeyboard.md @@ -0,0 +1,44 @@ +--- +title: KMManager.setShouldAllowSetKeyboard() +--- + +## Summary + +The **`setShouldAllowSetKeyboard()`** method sets whether Keyman Engine +allows setting a keyboard other than the default keyboard. + +## Syntax + +``` javascript +KMManager.setShouldAllowSetKeyboard(boolean value) +``` + +### Parameters + +`value` +: If `false`, Keyman Engine will not allow setting a keyboard. + +## Description + +Use this method to enable or disable setting a keyboard other than the +default keyboard. If set to `false` Keyman Engine will immediately load +the default keyboard, and ignore calls to setKeyboard method. It is +particularly useful if used with Google Play Licensing service in order +to put the Keyman on-screen keyboard in a locked state if the paid app +is unlicensed. + +## Examples + +### Example: Using `setShouldAllowSetKeyboard()` + +The following script illustrate the use of +`setShouldAllowSetKeyboard()`: + +``` javascript + // Put Keyman on-screen keyboard in locked state if the app is unlicensed. + KMManager.setShouldAllowSetKeyboard(false); +``` + +## See also + +- [`shouldAllowSetKeyboard`](shouldAllowSetKeyboard) diff --git a/android/docs/engine/KMManager/setShouldCheckKeyboardUpdates.md b/android/docs/engine/KMManager/setShouldCheckKeyboardUpdates.md new file mode 100644 index 00000000000..91192c59c07 --- /dev/null +++ b/android/docs/engine/KMManager/setShouldCheckKeyboardUpdates.md @@ -0,0 +1,40 @@ +--- +title: KMManager.setShouldCheckKeyboardUpdates() +--- + +## Summary + +The **`setShouldCheckKeyboardUpdates()`** method sets whether Keyman +Engine should check for keyboard updates. + +## Syntax + +``` javascript +KMManager.setShouldCheckKeyboardUpdates(boolean newValue) +``` + +### Parameters + +`newValue` +: If `false`, Keyman Engine will not check for keyboard updates. + +## Description + +Use this method to enable or disable keyboard updates when the keyboard +picker menu is displayed. + +## Examples + +### Example: Using `setShouldCheckKeyboardUpdates()` + +The following script illustrate the use of +`setShouldCheckKeyboardUpdates()`: + +``` javascript + // Disable keyboard updates. + KMManager.setShouldCheckKeyboardUpdates(false); +``` + +## See also + +- [`shouldCheckKeyboardUpdates`](shouldCheckKeyboardUpdates) diff --git a/android/docs/engine/KMManager/setSpacebarText.md b/android/docs/engine/KMManager/setSpacebarText.md new file mode 100644 index 00000000000..63788e77df8 --- /dev/null +++ b/android/docs/engine/KMManager/setSpacebarText.md @@ -0,0 +1,50 @@ +--- +title: KMManager.setSpacebarText() +--- + +## Summary + +The `setSpacebarText()` method sets the text display pattern for the +spacebar. + +## Syntax + +```java +KMManager.setSpacebarText(KMManager.SpacebarText mode) +``` + +### Parameters + +`mode` +: The display pattern to use for the spacebar, one of: + + * `LANGUAGE` - the language name for the keyboard + * `KEYBOARD` - the keyboard name + * `LANGUAGE_KEYBOARD` - both the language name and the keyboard name, + separated by hyphen + * `BLANK` - no text to be displayed + +### Returns + +No return value. + +## Description + +The default text display pattern is `LANGUAGE_KEYBOARD`. The text shown on the +keyboard may be overridden on a per-keyboard basis with the `displayName` +parameter of the `setKeyboard()` function. + +--- + +## Example: Using `setSpacebarText()` + +The following script illustrates the use of `setSpacebarText()`: + +```java +// don't show anything on the spacebar +KMManager.setSpacebarText(KMManager.SpacebarText.BLANK); +``` + +## See also + +* [`getSpacebarText()`](getSpacebarText) diff --git a/android/docs/engine/KMManager/shouldAllowSetKeyboard.md b/android/docs/engine/KMManager/shouldAllowSetKeyboard.md new file mode 100644 index 00000000000..d816d20c213 --- /dev/null +++ b/android/docs/engine/KMManager/shouldAllowSetKeyboard.md @@ -0,0 +1,43 @@ +--- +title: KMManager.shouldAllowSetKeyboard() +--- + +## Summary + +The **`shouldAllowSetKeyboard()`** method returns whether Keyman Engine +allows setting a keyboard other than the default keyboard. + +## Syntax + +``` javascript +KMManager.shouldAllowSetKeyboard() +``` + +### Returns + +Returns `true` if Keyman Engine allows setting a keyboard, `false` +otherwise. + +## Description + +Use this method to check if Keyman Engine allows setting a keyboard +other than the default keyboard. + +## Examples + +### Example: Using `shouldAllowSetKeyboard()` + +The following script illustrate the use of `shouldAllowSetKeyboard()`: + +``` javascript + if (KMManager.shouldAllowSetKeyboard()) { + // setting a keyboard is allowed + } + else { + // setting a keyboard is not allowed + } +``` + +## See also + +- [`setShouldAllowSetKeyboard`](setShouldAllowSetKeyboard) diff --git a/android/docs/engine/KMManager/shouldCheckKeyboardUpdates.md b/android/docs/engine/KMManager/shouldCheckKeyboardUpdates.md new file mode 100644 index 00000000000..717ca7809ed --- /dev/null +++ b/android/docs/engine/KMManager/shouldCheckKeyboardUpdates.md @@ -0,0 +1,41 @@ +--- +title: KMManager.shouldCheckKeyboardUpdates() +--- + +## Summary + +The **`shouldCheckKeyboardUpdates()`** method returns whether Keyman +Engine should check for keyboard updates. + +## Syntax + +``` javascript +KMManager.shouldCheckKeyboardUpdates() +``` + +### Returns + +Returns `true` if Keyman Engine should check for keyboard updates, +`false` otherwise. + +## Description + +Use this method to check if Keyman Engine should check for keyboard +updates when the keyboard picker menu is displayed. + +## Examples + +### Example: Using `shouldCheckKeyboardUpdates()` + +The following script illustrate the use of +`shouldCheckKeyboardUpdates()`: + +``` javascript + if (KMManager.shouldCheckKeyboardUpdates()) { + // checking keyboard updates is enabled + } +``` + +## See also + +- [`setShouldCheckKeyboardUpdates`](setShouldCheckKeyboardUpdates) diff --git a/android/docs/engine/KMManager/showKeyboardPicker.md b/android/docs/engine/KMManager/showKeyboardPicker.md new file mode 100644 index 00000000000..099288dc40c --- /dev/null +++ b/android/docs/engine/KMManager/showKeyboardPicker.md @@ -0,0 +1,51 @@ +--- +title: KMManager.showKeyboardPicker() +--- + +## Summary + +The **`showKeyboardPicker()`** method displays the keyboard picker menu. + +## Syntax + +``` javascript +KMManager.showKeyboardPicker(Context context, KeyboardType kbType) +``` + +### Parameters + +`context` +: The context. + +`kbType` +: The keyboard type. `KEYBOARD_TYPE_INAPP` or `KEYBOARD_TYPE_SYSTEM`. + +## Description + +Use this method to display keyboard picker menu. Normally you do not +need to call this method explicitly since, by default, Keyman on-screen +keyboard calls this method to display the keyboard picker menu whenever +'globe' key is tapped. Multiple calls to this method is unsafe and may +result in multiple instances of keyboard picker menu being displayed at +the same time. + +## Examples + +### Example: Using `showKeyboardPicker()` + +The following script illustrate the use of `showKeyboardPicker()`: + +``` javascript + final Context context = this; + ImageButton globeButton = (ImageButton) findViewById(R.id.globeButton); + globeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + KMManager.showKeyboardPicker(context, KMManager.KeyboardType.KEYBOARD_TYPE_INAPP); + } + }); +``` + +## See also + +- [`showLanguageList() (Deprecated)`](showLanguageList) diff --git a/android/docs/engine/KMManager/showLanguageList.md b/android/docs/engine/KMManager/showLanguageList.md new file mode 100644 index 00000000000..3d9dd0db6c5 --- /dev/null +++ b/android/docs/engine/KMManager/showLanguageList.md @@ -0,0 +1,50 @@ +--- +title: KMManager.showLanguageList() (Deprecated) +--- + +## Summary + +(Deprecated) The **`showLanguageList()`** method displays the language +list. + +## Syntax + +``` javascript +KMManager.showLanguageList(Context context) +``` + +### Parameters + +`context` +: The context. + +## Description + +The Keyman keyboard picker menu used to call this method to display the +language list whenever the '+' button was tapped. As of 14.0, keyboards +are no longer added this way, and this call is removed. + +## Examples + +### Example: Using `showLanguageList()` + +The following script illustrate the use of `showLanguageList()`: + +``` javascript + final Context context = this; + ImageButton languageButton = (ImageButton) findViewById(R.id.languageButton); + languageButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + KMManager.showLanguageList(context); + } + }); +``` + +## History + +Deprecated syntax in Keyman Engine for Android 14.0 + +## See also + +- [`showKeyboardPicker()`](showKeyboardPicker) diff --git a/android/docs/engine/KMManager/switchToNextKeyboard.md b/android/docs/engine/KMManager/switchToNextKeyboard.md new file mode 100644 index 00000000000..dfd7d3328c4 --- /dev/null +++ b/android/docs/engine/KMManager/switchToNextKeyboard.md @@ -0,0 +1,46 @@ +--- +title: KMManager.switchToNextKeyboard() +--- + +## Summary + +The **`switchToNextKeyboard()`** method loads the next available +keyboard in keyboards list. + +## Syntax + +``` javascript +KMManager.switchToNextKeyboard(Context context) +``` + +### Parameters + +`context` +: The context. + +## Description + +Use this method to switch to next keyboard in the keyboards list. If the +next keyboard does not exists, then it loads the first keyboard in the +keyboards list. + +## Examples + +### Example: Using `switchToNextKeyboard()` + +The following script illustrate the use of `switchToNextKeyboard()`: + +``` javascript + final Context context = this; + ImageButton nextButton = (ImageButton) findViewById(R.id.nextButton); + nextButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + KMManager.switchToNextKeyboard(context); + } + }); +``` + +## See also + +- [`setKeyboard()`](setKeyboard) diff --git a/android/docs/engine/KMManager/updateSelectionRange.md b/android/docs/engine/KMManager/updateSelectionRange.md new file mode 100644 index 00000000000..b57f97dad5a --- /dev/null +++ b/android/docs/engine/KMManager/updateSelectionRange.md @@ -0,0 +1,77 @@ +--- +title: KMManager.updateSelectionRange() +--- + +## Summary + +The `updateSelectionRange()` method updates the selection range of the current context. + +## Syntax + + +```java +KMManager.updateSelectionRange(KeyboardType kbType) +``` + +### Parameters + +`kbType` +: Keyboard type requesting the selection range update. `KEYBOARD_TYPE_INAPP` or `KEYBOARD_TYPE_SYSTEM`. + +### Returns + +Returns `true` if the selection range was updated successfully, `false` otherwise. + +## Description + +Use this method to update the selection range of the current context. It must be called in response to InputMethodService's onUpdateSelection method and whenever InputMethodService's onStartInput method has been called. Normally you do not need to call this method for in-app keyboards. + +---- + +## Syntax (Deprecated) + +```javascript +KMManager.updateSelectionRange(KeyboardType kbType, int selStart, int selEnd) +``` + +### Parameters + +`kbType` +: Keyboard type requesting the selection range update. `KEYBOARD_TYPE_INAPP` or `KEYBOARD_TYPE_SYSTEM`. + +`selStart` +: The new selection start location. + +`selEnd` +: The new selection end location. + +### Returns + +(Deprecated) Returns `true` if the selection range was updated successfully, `false` otherwise. + +## Description + +Use this method to update the selection range of the current context. It must be called in response to InputMethodService's onUpdateSelection method and whenever InputMethodService's onStartInput method has been called. Normally you do not need to call this method for in-app keyboards. + +Since this syntax is deprecated, use `KMManager.updateSelectionRange(KeyboardType kbType)` syntax instead. + +## Example: Using `updateSelectionRange()` + +The following script illustrates the use of `updateSelectionRange()`: + +```javascript + @Override + public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) { + super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd); + KMManager.updateSelectionRange(KMManager.KeyboardType.KEYBOARD_TYPE_SYSTEM); + } +``` + +## History + +Deprecated `updateSelectionRange(KeyboardType kbType, int selStart, int selEnd)` syntax in Keyman Engine for Android 17.0 + + +## See also + +* [`updateText()`](updateText) diff --git a/android/docs/engine/KMManager/updateText.md b/android/docs/engine/KMManager/updateText.md new file mode 100644 index 00000000000..05e54f4358f --- /dev/null +++ b/android/docs/engine/KMManager/updateText.md @@ -0,0 +1,62 @@ +--- +title: KMManager.updateText() +--- + +## Summary + +The **`updateText()`** method updates the current context with the +specified text. + +## Syntax + +``` javascript +KMManager.updateText(KeyboardType kbType, String text) +``` + +### Parameters + +`kbType` +: Keyboard type requesting the context update. `KEYBOARD_TYPE_INAPP` + or `KEYBOARD_TYPE_SYSTEM`. + +`text` +: The text to replace the current context. + +### Returns + +Returns `true` if the current context was updated successfully, `false` +otherwise. + +## Description + +Use this method to update the current context. It must be called in +InputMethodService's onStartInput method to match the current context +with the text in the editor. Normally you do not need to call this +method for in-app keyboards. + +## Examples + +### Example: Using `updateText()` + +The following script illustrate the use of `updateText()`: + +``` javascript + @Override + public void onStartInput(EditorInfo attribute, boolean restarting) { + super.onStartInput(attribute, restarting); + // ... + InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0); + if (icText != null) { + KMManager.updateText(KeyboardType.KEYBOARD_TYPE_SYSTEM, icText.text.toString()); + // ... + } + } + // ... + } +``` + +## See also + +- [updateSelectionRange()](updateSelectionRange) diff --git a/android/docs/engine/KeyboardEventHandler/index.md b/android/docs/engine/KeyboardEventHandler/index.md new file mode 100644 index 00000000000..57125e100b0 --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/index.md @@ -0,0 +1,38 @@ +--- +title: KeyboardEventHandler class +--- + +## Description + +The KeyboardEventHandler class provides keyboard events and methods to +notify registered listeners on keyboard and lexical-model events. + +## Events + +### OnKeyboardEventListener Interface + +[`onKeyboardLoaded()`](onKeyboardLoaded) +: is called when the keyboard has been loaded for the first time + +[`onKeyboardChanged()`](onKeyboardChanged) +: is called when another keyboard has been set + +[`onKeyboardShown()`](onKeyboardShown) +: is called when the keyboard has been shown + +[`onKeyboardDismissed()`](onKeyboardDismissed) +: is called when the keyboard has been dismissed + +### OnKeyboardDownloadEventListener Interface + +[`onKeyboardDownloadStarted()`](onKeyboardDownloadStarted) +: is called when a keyboard download has started + +[`onKeyboardDownloadFinished()`](onKeyboardDownloadFinished) +: is called when a keyboard download has finished + +[`onPackageInstalled()`](onPackageInstalled) +: is called when a keyboard package has been installed + +[`onLexicalModelInstalled()`](onLexicalModelInstalled) +: is called when a lexical-model package has been installed diff --git a/android/docs/engine/KeyboardEventHandler/onKeyboardChanged.md b/android/docs/engine/KeyboardEventHandler/onKeyboardChanged.md new file mode 100644 index 00000000000..8be5f6e4745 --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onKeyboardChanged.md @@ -0,0 +1,42 @@ +--- +title: onKeyboardChanged() +--- + +## Summary + +The **`onKeyboardChanged()`** event is called when another keyboard has +been set. + +## Syntax + +``` javascript +public void onKeyboardChanged(String newKeyboard) +``` + +### Parameters + +`newKeyboard` +: New keyboard identifier as languageID_keyboardID (e.g. eng_us). + +## Description + +Implement this method to handle keyboard changed event. + +## Examples + +### Example: Using `onKeyboardChanged()` + +The following script illustrate the use of `onKeyboardChanged()`: + +``` javascript + @Override + public void onKeyboardChanged(String newKeyboard) { + // handle keyboard changed event here + } +``` + +## See also + +- [`onKeyboardDismissed()`](onKeyboardDismissed) +- [`onKeyboardLoaded()`](onKeyboardLoaded) +- [`onKeyboardShown()`](onKeyboardShown) diff --git a/android/docs/engine/KeyboardEventHandler/onKeyboardDismissed.md b/android/docs/engine/KeyboardEventHandler/onKeyboardDismissed.md new file mode 100644 index 00000000000..97a8441c28d --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onKeyboardDismissed.md @@ -0,0 +1,37 @@ +--- +title: onKeyboardDismissed() +--- + +## Summary + +The **`onKeyboardDismissed()`** event is called when the keyboard has +been dismissed. + +## Syntax + +``` javascript +public void onKeyboardDismissed() +``` + +## Description + +Implement this method to handle keyboard dismissed event. + +## Examples + +### Example: Using `onKeyboardDismissed()` + +The following script illustrate the use of `onKeyboardDismissed()`: + +``` javascript + @Override + public void onKeyboardDismissed() { + // handle keyboard dismissed event here + } +``` + +## See also + +- [`onKeyboardChanged()`](onKeyboardChanged) +- [`onKeyboardLoaded()`](onKeyboardLoaded) +- [`onKeyboardShown()`](onKeyboardShown) diff --git a/android/docs/engine/KeyboardEventHandler/onKeyboardDownloadFinished.md b/android/docs/engine/KeyboardEventHandler/onKeyboardDownloadFinished.md new file mode 100644 index 00000000000..d6286f40665 --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onKeyboardDownloadFinished.md @@ -0,0 +1,46 @@ +--- +title: onKeyboardDownloadFinished() +--- + +## Summary + +The **`onKeyboardDownloadFinished()`** event is called when a keyboard +download has finished. + +## Syntax + +``` javascript +public void onKeyboardDownloadFinished(HashMap keyboardInfo, int result) +``` + +### Parameters + +`keyboardInfo` +: The information dictionary of the keyboard with keys and values + defined as `HashMap`. + +`result` +: The result of the download (result > 0 if successful, < 0 if + failed). + +## Description + +Implement this method to handle keyboard download finished event. + +## Examples + +### Example: Using `onKeyboardDownloadFinished()` + +The following script illustrate the use of +`onKeyboardDownloadFinished()`: + +``` javascript + @Override + public void onKeyboardDownloadFinished(HashMap keyboardInfo, int result) { + // handle keyboard download finished event here + } +``` + +## See also + +- [`onKeyboardDownloadStarted()`](onKeyboardDownloadStarted) diff --git a/android/docs/engine/KeyboardEventHandler/onKeyboardDownloadStarted.md b/android/docs/engine/KeyboardEventHandler/onKeyboardDownloadStarted.md new file mode 100644 index 00000000000..c1a34451bf9 --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onKeyboardDownloadStarted.md @@ -0,0 +1,42 @@ +--- +title: onKeyboardDownloadStarted() +--- + +## Summary + +The **`onKeyboardDownloadStarted()`** event is called when a keyboard +download has started. + +## Syntax + +``` javascript +public void onKeyboardDownloadStarted(HashMap keyboardInfo) +``` + +### Parameters + +`keyboardInfo` +: The information dictionary of the keyboard with keys and values + defined as `HashMap`. + +## Description + +Implement this method to handle keyboard download started event. + +## Examples + +### Example: Using `onKeyboardDownloadStarted()` + +The following script illustrate the use of +`onKeyboardDownloadStarted()`: + +``` javascript + @Override + public void onKeyboardDownloadStarted(HashMap keyboardInfo) { + // handle keyboard download started event here + } +``` + +## See also + +- [`onKeyboardDownloadFinished()`](onKeyboardDownloadFinished) diff --git a/android/docs/engine/KeyboardEventHandler/onKeyboardLoaded.md b/android/docs/engine/KeyboardEventHandler/onKeyboardLoaded.md new file mode 100644 index 00000000000..26622fa87ad --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onKeyboardLoaded.md @@ -0,0 +1,43 @@ +--- +title: onKeyboardLoaded() +--- + +## Summary + +The **`onKeyboardLoaded()`** event is called when the keyboard has been +loaded for the first time. + +## Syntax + +``` javascript +public void onKeyboardLoaded(KeyboardType keyboardType) +``` + +### Parameters + +`keyboardType` +: The keyboard type that has been loaded. `KEYBOARD_TYPE_INAPP` or + `KEYBOARD_TYPE_SYSTEM`. + +## Description + +Implement this method to handle keyboard loaded event. + +## Examples + +### Example: Using `onKeyboardLoaded()` + +The following script illustrate the use of `onKeyboardLoaded()`: + +``` javascript + @Override + public void onKeyboardLoaded(KeyboardType keyboardType) { + // handle keyboard loaded event here + } +``` + +## See also + +- [`onKeyboardChanged()`](onKeyboardChanged) +- [`onKeyboardDismissed()`](onKeyboardDismissed) +- [`onKeyboardShown()`](onKeyboardShown) diff --git a/android/docs/engine/KeyboardEventHandler/onKeyboardShown.md b/android/docs/engine/KeyboardEventHandler/onKeyboardShown.md new file mode 100644 index 00000000000..940c788fae2 --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onKeyboardShown.md @@ -0,0 +1,37 @@ +--- +title: onKeyboardShown() +--- + +## Summary + +The **`onKeyboardShown()`** event is called when the keyboard has been +shown. + +## Syntax + +``` javascript +public void onKeyboardShown() +``` + +## Description + +Implement this method to handle keyboard shown event. + +## Examples + +### Example: Using `onKeyboardShown()` + +The following script illustrate the use of `onKeyboardShown()`: + +``` javascript + @Override + public void onKeyboardShown() { + // handle keyboard shown event here + } +``` + +## See also + +- [`onKeyboardChanged()`](onKeyboardChanged) +- [`onKeyboardDismissed()`](onKeyboardDismissed) +- [`onKeyboardLoaded()`](onKeyboardLoaded) diff --git a/android/docs/engine/KeyboardEventHandler/onLexicalModelInstalled.md b/android/docs/engine/KeyboardEventHandler/onLexicalModelInstalled.md new file mode 100644 index 00000000000..7a3ee582578 --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onLexicalModelInstalled.md @@ -0,0 +1,34 @@ +--- +title: onLexicalModelInstalled() +--- + +## Summary +The `onLexicalModelInstalled()` event is called when a lexical-model package has been installed. + +## Syntax +```java +onLexicalModelInstalled(List> lexicalModelsInstalled) +``` + +### Parameters +`lexicalModelsInstalled` + +The information dictionaries of the lexical-models installed from a lexical-model package with keys and values defined as `List>`. + + +## Description +Implement this method to handle lexical-model package installed event. + +## Examples + +### Example: Using `onLexicalModelInstalled()` +The following script illustrate the use of `onLexicalModelInstalled()`: +```java + @Override + public void onLexicalModelInstalled(List> lexicalModelsInstalled) { + // handle lexical-model package installed event here + } +``` + +## See also +* [onPackageInstalled()](onPackageInstalled) diff --git a/android/docs/engine/KeyboardEventHandler/onPackageInstalled.md b/android/docs/engine/KeyboardEventHandler/onPackageInstalled.md new file mode 100644 index 00000000000..3653dfc8186 --- /dev/null +++ b/android/docs/engine/KeyboardEventHandler/onPackageInstalled.md @@ -0,0 +1,35 @@ +--- +title: onPackageInstalled() +--- + +## Summary +The `onPackageInstalled()` is called when a keyboard package has been installed. + +## Syntax +```java +onPackageInstalled(List> keyboardsInstalled) +``` + +### Parameters +`keyboardsInstalled` + +The information dictionaries of the keyboards installed from a keyboard package with keys and values defined as `List>`. + +## Description +Implement this method to handle keyboard package installed event. + +## Examples ## + +### Example: Using `onPackageInstalled()` ### +The following script illustrate the use of `onPackageInstalled()`: + +```java + @Override + public void onPackageInstalled(List> keyboardsInstalled) { + // handle keyboard package installed event here + } +``` + +## See also +* [onLexicalModelInstalled()](onLexicalModelInstalled) + diff --git a/android/docs/engine/guides/in-app/index.md b/android/docs/engine/guides/in-app/index.md new file mode 100644 index 00000000000..bfa37d46227 --- /dev/null +++ b/android/docs/engine/guides/in-app/index.md @@ -0,0 +1,135 @@ +--- +title: Guide: build an in-app keyboard +--- + +Keyman Engine for Android allows you to use any Keyman touch keyboard in your Android app, or even to create your own +system keyboard app for purchase in the Play Store.
+This guide will walk you through the steps for creating your first Android app with Keyman Engine for Android. + +If you are not familiar with Android development, you will find the +[Android Developer online training](https://developer.android.com/training/index.html) an invaluable +resource, and working through some of their tutorials first will help you with the rest of this guide. + +### 1. Install Free Tools +* Install [Keyman Developer 17 or later](https://keyman.com/developer/). +* Install [OpenJDK 11](https://learn.microsoft.com/en-us/java/openjdk/download#openjdk-11). +* Install [Android Studio](https://developer.android.com/studio/index.html). + Android Studio runs on several platforms. Keyman Developer runs on Windows 10 or later. + +### 2. Configure Android Studio +* For Windows users, from **Control Panel>System>System Properties>Environment Variables**,
+ create a system variable **ANDROID_HOME** to the location of your Android SDK. The default + installation location is
+ c:\Users\[USER]\AppData\Local\Android\sdk where [USER] is your Windows username. +* For Linux users, add the following to ~/.bashrc +```bash +export ANDROID_HOME=$HOME/Android/Sdk +export PATH=$PATH:$ANDROID_HOME/tools +``` +* In a command prompt or terminal, accept all the SDK license agreements +```bash +cd c:\Users\[USER]\AppData\Local\Android\sdk\tools\bin +yes | ./sdkmanager.bat --licenses +``` + +### 3. Download Keyman Engine for Android and Build Sample projects +* Download the [Keyman for Android SDK](https://keyman.com/engine) + and extract the files to a new folder. + +The archive includes two sample projects and an Android .aar library file. This guide will use the first + example project, **KMSample1**. + +* If **KMSample1.zip** exists, extract it to a new folder. Otherwise, the KMSample1 project + can be found at **Samples/KMSample1** +* In Android Studio, select **File>Open** and choose the KMSample1 project folder from + the previous step. + +* When the project loads, you may be prompted to install Android SDKs; go ahead and follow the prompts to + fixup any missing SDK dependencies. + +### 4. Create a keyboard layout +Use Keyman Developer to build a touch layout. The following blog posts walk through some of the development and + testing for creating a touch keyboard layout: + +* [Creating a Touch Keyboard Layout for Amharic with Keyman Developer 13](/developer/13.0/guides/develop/creating-a-touch-keyboard-layout-for-amharic-with-keyman-developer-10") +* [Creating A Touch Keyboard Layout For Amharic — The Nitty Gritty](/developer/13.0/guides/develop/creating-a-touch-keyboard-layout-for-amharic-the-nitty-gritty) +* [How to test your keyboard layout with Keyman Developer 13 — touch and desktop](/developer/13.0/guides/test/how-to-test-your-keyboard-layout-with-keyman-developer-10-touch-and-desktop) +* [How to test your touch layout in the Google Chrome mobile emulator](/developer/13.0/guides/test/how-to-test-your-touch-layout-in-the-google-chrome-mobile-emulator) + +When your keyboard is ready, you should have a compiled keyboard package file. The example below shows the + Tamil 99 Basic touch layout. +[Keyman-developer](/cdn/dev/img/engine/android/14.0/guides/in-app/touch-layout.png) + +From the package editor, open the containing folder for the keyboard package to find the .kmp file to copy over; its name will be based on + your source keyboard name. If your keyboard project settings is configured to output to **$PROJECTPATH\build**, + you may need to navigate up a folder and into the build folder. + +[Keyman-developer-open-containing-folder](/cdn/dev/img/engine/android/14.0/guides/in-app/open-containing-folder.png) + +[Compiled-keyboard-file](/cdn/dev/img/engine/android/14.0/guides/in-app/compiled-keyboard-file.png) + +### 5. Add your keyboard package to the project +Copy your compiled keyboard package file (in this example **basic_kbdtam99.kmp**) to the + **KMSample1\app\src\main\assets\** folder. If you have an associated dictionary, then copy that to the + same **assets** folder. This example uses **example.ta.wordlist.model.kmp**. +[Copy-keyboard-file](/cdn/dev/img/engine/android/14.0/guides/in-app/copy-keyboard-file.png) + +When you switch back into Android Studio, you should see the assets folder + with your keyboard and dictionary files: + +[Android-studio-assets](/cdn/dev/img/engine/android/14.0/guides/in-app/android-studio-assets.png) + +Next, edit `MainActivity.onCreate()` to add the keyboard (tamil99m) with `KMManager`. + If your keyboard package is not using a custom font, you can set KMKey_Font to the default font: +```java + // Add a custom keyboard + Keyboard kbInfo = new Keyboard( + "basic_kbdtam99", // Package ID - filename of the .kmp file + "basic_kbdtam99", // Keyboard ID + "Tamil 99 Basic", // Keyboard Name + "ta", // Language ID + "Tamil", // Language Name + "1.0", // Keyboard Version + null, // URL to help documentation if available + "", // URL to latest .kmp file + true, // Boolean to show this is a new keyboard in the keyboard picker + + // Font information of the .ttf font to use in KMSample1 (for example "aava1.ttf"). + // basic_kbdtam99 doesn't include a font. Can set blank "" or KMManager.KMDefault_KeyboardFont + KMManager.KMDefault_KeyboardFont, // Font for KMSample1 text field + KMManager.KMDefault_KeyboardFont); // Font for OSK + KMManager.addKeyboard(this, kbInfo); +``` +If you included a dictionary in the sample app, add and register it with `KMManager`. +```java + // Add a dictionary + HashMaplexicalModelInfo = new HashMap(); + lexicalModelInfo.put(KMManager.KMKey_PackageID, "example.ta.wordlist"); + lexicalModelInfo.put(KMManager.KMKey_LanguageID, "ta"); + lexicalModelInfo.put(KMManager.KMKey_LexicalModelID, "example.ta.wordlist"); + lexicalModelInfo.put(KMManager.KMKey_LexicalModelVersion, "1.0"); + KMManager.addLexicalModel(context, lexicalModelInfo); + KMManager.registerAssociatedLexicalModel("ta"); +``` + +[Android-studio-adding-keyboard](/cdn/dev/img/engine/android/14.0/guides/in-app/android-studio-adding-keyboard.png) + +### 6. Build and run the app +You can run your app on a [created Virtual Device](https://developer.android.com/studio/run/managing-avds.html), + or connect an Android device via USB to your computer to test. In either case, click the green Run button to start + the app. The steps below show how to create a new Virtual Device + +[Android-studio-starting-debug](/cdn/dev/img/engine/android/14.0/guides/in-app/android-studio-starting-debug.png) + +Click the **[Create Virtual Device]** button to add a new virtual device, and follow the prompts. Any recent emulated + device should work fine. You will be prompted to download additional resources for the emulator when this runs. + +[Android-emulator-tamil](/cdn/dev/img/engine/android/14.0/guides/in-app/android-emulator-tamil.png) + +And there you have it: your first Keyman Engine for Android app! + +## See Also +* [Guide: Build a system keyboard app](../system-keyboard/) +* [Keyman Developer Documentation](/developer/17.0/) +* [Keyman Engine for Android Documentation](/developer/engine/android/18.0/) +* [Android Developer Home](https://developer.android.com/index.html) diff --git a/android/docs/engine/guides/index.md b/android/docs/engine/guides/index.md new file mode 100644 index 00000000000..43a7c3e6efb --- /dev/null +++ b/android/docs/engine/guides/index.md @@ -0,0 +1,6 @@ +--- +title: Keyman Engine for Android Developer Guides +--- + +- [Build an in-app keyboard](in-app/) +- [Build a system keyboard app](system-keyboard/) diff --git a/android/docs/engine/guides/system-keyboard/index.md b/android/docs/engine/guides/system-keyboard/index.md new file mode 100644 index 00000000000..227bb4f33ca --- /dev/null +++ b/android/docs/engine/guides/system-keyboard/index.md @@ -0,0 +1,69 @@ +--- +title: Guide: build a system keyboard app +--- + +In [part 1](../in-app/) of this series, we looked at the steps involved +in creating a basic Android app which included a Keyman in-app keyboard. +In this post, we'll work with the second sample included in the Keyman +Engine for Android package, which is a very basic System Keyboard app. +This post builds on concepts and setup from the first post, so be sure +you are familiar with that before you start on this one. + +### 1. Basic configuration + +If **KMSample2.zip** exists from the downloaded **Keyman Engine for +Android**, extract it to a new folder. Otherwise, the KMSample2 project +can be found at **Samples/KMSample2** + +### 2. Run the sample app + +The KMSample2 app includes the Tamil 99 Basic keyboard as an example +keyboard. Without any further modifications, the app should run and +you'll be able to configure your device to use your app as the system +keyboard. + +[Emulator](/cdn/dev/img/engine/android/14.0/guides/system-keyboard/emulator-800wi.png) + +### 3. Extending the app + +From here, you will no doubt want to replace the keyboard with your own +one; again, follow the instructions from Part 1 to make this change. + +You can also customise the look and feel of the on screen keyboard by +including a custom CSS file in your keyboard through Keyman Developer. + +[AddEmbeddedCSS](/cdn/dev/img/engine/android/10.0/guides/system-keyboard/add-embedded-css.png) + +The CSS rules required to style your keyboard are beyond the scope of +this post, but the **kmwosk.css** file included in the Keyman Developer +16.0 distribution and in the [KeymanWeb 16.0 +source](https://github.com/keymanapp/keyman/blob/master/web/source/resources/osk/kmwosk.css) is +a good place to start. See this +[reference](/developer/engine/web/15.0/reference/osk/classes) for more +information about the On-Screen Keyboard. + +Do take the time to read through the source of **KMSample2**, as it +includes some boilerplate code required to link Keyman Engine through to +the Android Input Method services and vice versa. + +Finally, you will want to improve the style and branding of the main +activity in KMSample2. The sample includes just two buttons to link to +the Android Input Method Settings and Input Method Menu, as a pointer to +the two configuration steps that your users will need to undertake in +order to start using your keyboard. + +[MainActivityLayout](/cdn/dev/img/engine/android/14.0/guides/system-keyboard/main-activity-layout-800wi.png) + +You will probably want to make that a lot prettier, and include more +detailed instructions! + +That's all there is to creating a System Keyboard with Keyman Engine for +Android. We've taken care of all the complex details of keyboarding in +the Keyman Engine, so you can focus on the look and feel and the layout +of your keyboard. + +### Further links + +- [Part 1 of this series](../in-app/) +- [Keyman Developer Documentation](/developer/16.0/) +- [Android Developer Home](http://developer.android.com/index.html) diff --git a/android/docs/engine/index.md b/android/docs/engine/index.md new file mode 100644 index 00000000000..fa549e4b345 --- /dev/null +++ b/android/docs/engine/index.md @@ -0,0 +1,43 @@ +--- +title: Keyman Engine for Android +--- + +## Overview + +Keyman Engine for Android 18.0 is a Java library for Android 5.0 and later versions which enables a fully customisable keyboard layout, both within an app and system-wide. +Keyboard layouts for Keyman Engine can be created with [Keyman Developer](/developer/17.0), and a [library of existing keyboard layouts](http://keyman.com/developer/keymanweb/keyboards) +is also available.

+ +For keyboard developers updating from an older versions of Keyman Engine for Android, +see [What's New](whatsnew) for breaking changes + +## [Guides](guides/) + +* [Build an in-app keyboard](guides/in-app/) +* [Build a system keyboard app](guides/system-keyboard/) + +## Classes + +[KMManager](KMManager/) +: The core class for controlling Keyman Engine + +[KMKeyboard](KMKeyboard/) +: Keyman's child class of an Android [WebView](https://developer.android.com/reference/android/webkit/WebView) for a keyboard + +[KeyboardEventHandler](KeyboardEventHandler/) +: Provides keyboard and lexical-model events and methods to notify registered listeners + +## See also + +* [Keyman Engine for Android 17.0](/developer/engine/android/17.0/) +* [Keyman Engine for Android 16.0](/developer/engine/android/16.0/) +* [Keyman Engine for Android 15.0](/developer/engine/android/15.0/) +* [Keyman Engine for Android 14.0](/developer/engine/android/14.0/) +* [Keyman Engine for Android 13.0](/developer/engine/android/13.0/) +* [Keyman Engine for Android 12.0](/developer/engine/android/12.0/) +* [Keyman Engine for Android 11.0](/developer/engine/android/11.0/) +* [Keyman Engine for Android 10.0](/developer/engine/android/10.0/) +* [Keyman Engine for Android 2.0](/developer/engine/android/2.0) +* [Keyman Developer 17.0](/developer/17.0/) +* [Keyboard Library](http://keyman.com/developer/keymanweb/keyboards) +* [Keyman Engine for iPhone and iPad](/developer/engine/iphone-and-ipad/current-version/) diff --git a/android/docs/engine/whatsnew.md b/android/docs/engine/whatsnew.md new file mode 100644 index 00000000000..e8c2a3d694a --- /dev/null +++ b/android/docs/engine/whatsnew.md @@ -0,0 +1,11 @@ +--- +title: What's New +--- + +## Keyman Engine for Android Breaking Changes: ## + +* Change package name from `com.tavultesoft.kmea` to `com.keyman.engine` #7881 +* Update to Java 11 #8543 + +## See Also +* [Keyman Engine for Android Documentation](index) \ No newline at end of file diff --git a/android/docs/help/about/system-requirements.md b/android/docs/help/about/system-requirements.md index 8badb875755..16efbf28af6 100644 --- a/android/docs/help/about/system-requirements.md +++ b/android/docs/help/about/system-requirements.md @@ -9,7 +9,10 @@ Keyman for Android will run on Android phones and tablets that have a minimum ve [Android 5.0 (Lollipop)](https://developer.android.com/about/versions/lollipop). ### Minimum Chrome Version -Keyman for Android requires a minimum version of [Google Chrome](https://play.google.com/store/apps/details?id=com.android.chrome) 37.0. +Keyman for Android requires a minimum version 53.0 of [Google +Chrome](https://play.google.com/store/apps/details?id=com.android.chrome). +If you have an older device, you may need to upgrade Chrome before you can use +Keyman, e.g. through the Play Store. ### Device Permissions Network and [external storage permissions](../troubleshooting/grant-storage-permission) are required to download and install keyboards/dictionaries from the Keyman servers. diff --git a/android/docs/internal/README.md b/android/docs/internal/README.md new file mode 100644 index 00000000000..ef51df7f60f --- /dev/null +++ b/android/docs/internal/README.md @@ -0,0 +1,5 @@ +# Keyman for Android and Keyman Engine for Android + +## Internal Documents + +This folder is for storing design documents of new features pertaining to Keyman for Android and Keyman Engine for Android diff --git a/common/include/test_assert.h b/common/include/test_assert.h index 75c586bcc67..9669c16a022 100644 --- a/common/include/test_assert.h +++ b/common/include/test_assert.h @@ -12,10 +12,10 @@ #include #include "test_color.h" -#ifdef _assert_failed -#undef _assert_failed +#ifdef _test_assert_failed +#undef _test_assert_failed #endif -#define _assert_failed(result, exprText) { \ +#define _test_assert_failed(result, exprText) { \ std::wcerr << console_color::fg(console_color::BRIGHT_RED) \ << "Test failed with " << (result) \ << " at " << __FILE__ << ":" << __LINE__ << ":" \ @@ -31,23 +31,23 @@ #define try_status(expr) { \ auto __s = (expr); \ if (__s != KM_CORE_STATUS_OK) { \ - _assert_failed(__s, u ## #expr); \ + _test_assert_failed(__s, u ## #expr); \ } \ } -#ifdef assert -#undef assert +#ifdef test_assert +#undef test_assert #endif -#define assert(expr) { \ +#define test_assert(expr) { \ if (!(expr)) { \ - _assert_failed(0, u ## #expr); \ + _test_assert_failed(0, u ## #expr); \ } \ } -#ifdef assert_equal -#undef assert_equal +#ifdef test_assert_equal +#undef test_assert_equal #endif -#define assert_equal(actual, expected) { \ +#define test_assert_equal(actual, expected) { \ if ((actual) != (expected)) { \ std::wcerr << console_color::fg(console_color::BRIGHT_RED) \ << "Test failed at " << __FILE__ << ":" << __LINE__ << ":" \ @@ -59,10 +59,10 @@ } \ } -#ifdef assert_string_equal -#undef assert_string_equal +#ifdef test_assert_string_equal +#undef test_assert_string_equal #endif -#define assert_string_equal(actual, expected) { \ +#define test_assert_string_equal(actual, expected) { \ if (u16cmp((actual), (expected)) != 0) { \ std::wcerr << console_color::fg(console_color::BRIGHT_RED) \ << "Test failed at " << __FILE__ << ":" << __LINE__ << ":" \ diff --git a/common/include/test_color.h b/common/include/test_color.h index f06f94c562f..71267dc3a94 100644 --- a/common/include/test_color.h +++ b/common/include/test_color.h @@ -8,6 +8,12 @@ #include +#ifdef _MSC_VER +#include +#else +#include +#endif + namespace console_color { enum ansi_code { @@ -65,12 +71,10 @@ __define_ansi_code__(reversed, "7"); #undef __define_ansi_code__ #ifdef _MSC_VER -#include inline bool isaterminal() { return _isatty(_fileno(stdout)); } #else -#include inline bool isaterminal() { return isatty(STDOUT_FILENO); } diff --git a/common/tools/hextobin/build.sh b/common/tools/hextobin/build.sh index 9e73f8c4101..073b008bf2e 100755 --- a/common/tools/hextobin/build.sh +++ b/common/tools/hextobin/build.sh @@ -11,7 +11,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" builder_describe "Build hextobin" clean configure build builder_describe_outputs \ - configure /common/tools/hextobin/node_modules/commander \ + configure /common/tools/hextobin/.configured \ build /common/tools/hextobin/build/index.js builder_parse "$@" diff --git a/common/tools/hextobin/package.json b/common/tools/hextobin/package.json index fb651481f7a..708dace5028 100644 --- a/common/tools/hextobin/package.json +++ b/common/tools/hextobin/package.json @@ -15,5 +15,8 @@ "main": "build/index.js", "bin": { "hextobin": "build/hextobin.js" + }, + "scripts": { + "postinstall": "echo configured > .configured" } } diff --git a/common/web/types/.c8rc.json b/common/web/types/.c8rc.json new file mode 100644 index 00000000000..f7137ed999b --- /dev/null +++ b/common/web/types/.c8rc.json @@ -0,0 +1,12 @@ +{ + "exclude": [ + "src/keyboard-object.ts", + "src/lexical-model-types.ts", + "src/outputTarget.interface.ts", + "src/*.d.ts", + "src/main.ts", + "src/schemas/*", + "src/schema-validators.ts", + "src/schemas.ts" + ] +} diff --git a/common/web/types/.eslintrc.cjs b/common/web/types/.eslintrc.cjs index b28ba0941b1..4fd5954e495 100644 --- a/common/web/types/.eslintrc.cjs +++ b/common/web/types/.eslintrc.cjs @@ -1,13 +1,13 @@ module.exports = { parserOptions: { - project: ["./tsconfig.json", "./test/tsconfig.json"], + project: ["./tsconfig.json", "./tests/tsconfig.json"], }, ignorePatterns: [ ".*/*", "build/*", "coverage/*", "node_modules/*", - "test/fixtures/*", + "tests/fixtures/*", "tools/*", "src/schemas/*" ], diff --git a/common/web/types/.gitignore b/common/web/types/.gitignore index 2f943a2f4e9..dcb567b832b 100644 --- a/common/web/types/.gitignore +++ b/common/web/types/.gitignore @@ -1,2 +1,3 @@ src/schemas/ -obj/ \ No newline at end of file +obj/ +coverage/ diff --git a/common/web/types/build.sh b/common/web/types/build.sh index 7141bc10720..418840d1a85 100755 --- a/common/web/types/build.sh +++ b/common/web/types/build.sh @@ -80,17 +80,27 @@ function do_configure() { } function do_test() { + local MOCHA_FLAGS= + + if [[ "${TEAMCITY_GIT_PATH:-}" != "" ]]; then + # we're running in TeamCity + MOCHA_FLAGS="-reporter mocha-teamcity-reporter" + fi + eslint . - tsc --build test - readonly C8_THRESHOLD=50 - c8 -skip-full --reporter=lcov --reporter=text --lines $C8_THRESHOLD --statements $C8_THRESHOLD --branches $C8_THRESHOLD --functions $C8_THRESHOLD mocha "${builder_extra_params[@]}" + tsc --build tests + + readonly C8_THRESHOLD=60 + + # Excludes are defined in .c8rc.json + c8 -skip-full --reporter=lcov --reporter=text --lines $C8_THRESHOLD --statements $C8_THRESHOLD --branches $C8_THRESHOLD --functions $C8_THRESHOLD mocha ${MOCHA_FLAGS} "${builder_extra_params[@]}" builder_echo warning "Coverage thresholds are currently $C8_THRESHOLD%, which is lower than ideal." builder_echo warning "Please increase threshold in build.sh as test coverage improves." } #------------------------------------------------------------------------------------------------------------------- -builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo +builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo ./src/schemas/ ./node_modules/ ./obj/ builder_run_action configure do_configure builder_run_action build tsc --build builder_run_action test do_test diff --git a/common/web/types/package.json b/common/web/types/package.json index 1ba487aafdf..d6efc635039 100644 --- a/common/web/types/package.json +++ b/common/web/types/package.json @@ -23,7 +23,7 @@ "build": "tsc -b", "build:schema": "ajv compile", "lint": "eslint .", - "test": "npm run lint && cd test && tsc -b && cd .. && c8 --skip-full --reporter=lcov --reporter=text mocha" + "test": "npm run lint && cd tests && tsc -b && cd .. && c8 --skip-full --reporter=lcov --reporter=text mocha" }, "author": "Marc Durdin (https://github.com/mcdurdin)", "license": "MIT", @@ -36,7 +36,6 @@ "restructure": "3.0.1" }, "devDependencies": { - "@types/chai": "^4.1.7", "@types/mocha": "^5.2.7", "@types/node": "^20.4.1", "ajv": "^8.12.0", @@ -49,7 +48,7 @@ "typescript": "^5.4.5" }, "mocha": { - "spec": "build/test/**/test-*.js", + "spec": "build/tests/**/*.tests.js", "require": [ "source-map-support/register" ] @@ -77,7 +76,7 @@ "src/keyman-touch-layout/keyman-touch-layout-file-writer.ts", "src/osk/osk.ts", "src/schemas/*", - "test/" + "tests/" ] }, "sideEffects": false diff --git a/common/web/types/src/keyboard-object.ts b/common/web/types/src/keyboard-object.ts new file mode 100644 index 00000000000..afd0029af0d --- /dev/null +++ b/common/web/types/src/keyboard-object.ts @@ -0,0 +1,180 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ +import { TouchLayoutPlatform as LayoutFormFactorSpec } from './keyman-touch-layout/keyman-touch-layout-file.js'; + +export type ComplexKeyboardStore = (string | { t: 'd', d: number } | { ['t']: 'b' })[]; + +// A stub for KeyEvent which is properly defined in KeymanWeb +type KeyEventStub = {}; + +// A stub for OutputTarget which is properly defined in KeymanWeb +type OutputTargetStub = {}; + +export interface EncodedVisualKeyboard { + /** Represents CSS font styling to use for VisualKeyboard text */ + F: string; + /** Should there be a 102nd key? */ + K102?: boolean, + /** + * Keyboard Layer Specification: an object-based map of layer name to the keycaps for its + * 65 keys. The 65 keys are ordered from left to right, then top to bottom. + * + * The key ID corresponding to each index of the array is specified within `Codes.dfltCodes`. + * Entries corresponding to `K_*` in `Codes.dfltCodes` are reserved for future use. + */ + KLS?: { [layerName: string]: string[] }, + /** + * @deprecated + * The older form for data in KLS - defines keycaps for 'default' keys, then 'shift' keys, + * in a single concatenated array. + */ + BK?: string[]; +} + +export type LayoutSpec = { + "desktop"?: LayoutFormFactorSpec, + "phone"?: LayoutFormFactorSpec, + "tablet"?: LayoutFormFactorSpec +} + +export type KeyboardObject = { + /** + * group-start: the function triggering processing for the keyboard's + * "Unicode" start group, corresponding to `begin Unicode > use(_____)` in + * Keyman keyboard language. + * @param outputTarget The context to which the keystroke applies + * @param keystroke The full, pre-processed keystroke triggering + * keyboard-rule application. + */ + gs(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; + + /** + * group-newcontext: the function triggering processing for the keyboard's + * "NewContext" start group, corresponding to `begin NewContext > use(_____)` + * in Keyman keyboard language. + * @param outputTarget The new context to be used with future keystrokes + * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. + */ + gn?(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; + + /** + * group-postkeystroke: the function triggering processing for the keyboard's + * "PostKeystroke" start group, corresponding to `begin PostKeystroke > + * use(_____)` in Keyman keyboard language. + * @param outputTarget The context altered by a recent keystroke. As a + * precondition, all changes due to `gs` / `begin Unicode` should already be + * applied. + * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. + */ + gpk?(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; + + /** + * Keyboard ID: the uniquely-identifying name for this keyboard. Includes the standard + * `Keyboard_` prefix. May be 'namespaced' with a prefix corresponding to a package name + * within app/webview. + */ + KI: string; + /** + * Keyboard Name: the human-readable name of the keyboard. + */ + KN: string; + /** + * Encoded data usable to construct a desktop/hardware-oriented on-screen keyboard. + */ + KV: EncodedVisualKeyboard; + /** + * Keyboard Language Code: set within select keyboards. + * + * Currently, it's only used to determine the need for CJK-picker support. Is missing + * in most compiled keyboards. + */ + KLC?: string; + /** + * @deprecated + * Keyboard Language Code: set within select keyboards. + * + * Currently, it's only used to determine the need for CJK-picker support. + * Is (probably) an older name of KLC with the identical purpose. Is missing + * in most compiled keyboards. + */ + LanguageCode?: string; + /** + * Keyboard CSS: provides the definition for custom keyboard style sheets + */ + KCSS?: string; + /** + * Keyboard is RTL: a simple flag noting if the keyboard's script is RTL. + */ + KRTL?: boolean; + /** + * Keyboard Modifier BitMask: a set of bitflags indicating which modifiers + * the keyboard's rules utilize. See also: `ModifierKeyConstants`. + */ + KMBM?: number; + /** + * Keyboard Supplementary plane: set to 1 if the keyboard uses non-BMP Unicode + * characters. + */ + KS?: number; + /** + * Keyman Visual Keyboard Layout: defines the touch-layout definitions used for + * 'phone' and 'tablet' form-factors. + */ + KVKL?: LayoutSpec; + /** + * Keyboard is Mnemonic: set to 1 if the keyboard uses a mnemonic layout. + */ + KM?: number; + /** + * KeyBoard VERsion: the version of this keyboard. + */ + KBVER?: string; + /** + * Keyman VERsion: the version of Keyman Developer used to compile this keyboard. + */ + KVER?: string; + /** + * Keyman Variable Stores: an array of the names of all variable stores used by the + * keyboard. + */ + KVS?: (`s${number}`)[]; + /** + * Keyboard Help: HTML help text, as specified by either the &kmw_helptext or &kmw_helpfile system stores. + * + * Reference: https://help.keyman.com/developer/language/reference/kmw_helptext, + * https://help.keyman.com/developer/language/reference/kmw_helpfile + */ + KH?: string; + /** + * Keyboard Virtual Key Dictionary: the Developer-compiled, minified dictionary of virtual-key codes + */ + KVKD?: string; + /** + * Keyboard Display Underlying: set to 1 if the desktop form of the keyboard + * should show the US QWERTY underlying keycaps. These may also appear on + * touch layouts if set and no touch-layout information is available. + */ + KDU?: number; + /** + * Keyboard Help File: Embedded JS script designed for use with a keyboard's + * HTML help text. Always defined within the file referenced by &kmw_embedjs + * in a keyboard's source, though that file may also contain _other_ script + * definitions as well. (`KHF` must be explicitly defined within that file.) + * @param e Will be provided with the root element (a
) of the On-Screen Keyboard. + * @returns + */ + KHF?: (e: any) => string; + + /** + * Keyboard Notify Shift: Provided by CJK-picker keyboards to properly + * interface them with Keyman Engine for Web. + * @param {number} _PCommand event code (16,17,18) or 0; 16-18 + * correspond to modifier codes when pressed, while 0 corresponds to loss of focus + * @param {Object} _PTarget target element + * @param {number} _PData 1 or 0 + * @returns + */ + KNS?: (_PCommand: number, _PTarget: OutputTargetStub, _PData: number) => void; +} & Record<`s${number}`, string> + diff --git a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts index 0cb49e527c7..a88688f7ab7 100644 --- a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts +++ b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts @@ -174,12 +174,7 @@ export class Strs extends Section { */ allocString(s?: string, opts?: StrsOptions, sections?: DependencySections): StrsItem { // Run the string processing pipeline - s = Strs.processString(s, opts, sections); - - // add to the set, for testing - if (s) { - this.allProcessedStrings.add(s); - } + s = this.processString(s, opts, sections); // if it's a single char, don't push it into the strs table if (opts?.singleOk && isOneChar(s)) { @@ -196,8 +191,8 @@ export class Strs extends Section { return result; } - /** process everything according to opts */ - static processString(s: string, opts: StrsOptions, sections: DependencySections) { + /** process everything according to opts, and add the string to this.allProcessedStrings */ + private processString(s: string, opts: StrsOptions, sections: DependencySections) { s = s ?? ''; // type check everything else if (typeof s !== 'string') { @@ -215,6 +210,12 @@ export class Strs extends Section { if (opts?.unescape) { s = unescapeString(s); } + + if (s) { + // add all processed strings here, so that we catch denormalized strings in the input + this.allProcessedStrings.add(s); + } + // nfd if (opts?.nfd) { if (!sections?.meta?.normalizationDisabled) { diff --git a/common/web/types/src/ldml-keyboard/pattern-parser.ts b/common/web/types/src/ldml-keyboard/pattern-parser.ts index 3e56096ec67..1f1be6b3d92 100644 --- a/common/web/types/src/ldml-keyboard/pattern-parser.ts +++ b/common/web/types/src/ldml-keyboard/pattern-parser.ts @@ -81,7 +81,12 @@ export class MarkerParser { /** * Pattern for matching a marker reference, OR the special marker \m{.} */ - public static readonly REFERENCE = /\\m{([0-9A-Za-z_]{1,32}|\.)}/g; + public static readonly REFERENCE = /(?= Uni_PUA_16_START && ch <= Uni_PUA_16_END)); } +/** @returns false if s is NEITHER NFC nor NFD. (Returns true for falsy) */ +export function isNormalized(s: string) : boolean { + if(!s) return true; // empty or null + const nfc = s.normalize("NFC"); + const nfd = s.normalize("NFD"); + if (s !== nfc && s !== nfd) return false; + return true; +} + class BadStringMap extends Map> { public toString() : string { if (!this.size) { diff --git a/common/web/types/test/lexical-model-types.tests.ts b/common/web/types/test/lexical-model-types.tests.ts deleted file mode 100644 index 8944342ed6e..00000000000 --- a/common/web/types/test/lexical-model-types.tests.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file "tests" the exports from the main module. - * - * Since the exports are all types, the "test" here is that the type can be - * imported and compiled without any compiler errors. - */ - -import { USVString, Transform, Suggestion, SuggestionTag, Context, Capabilities, Configuration, Distribution, WordBreakingFunction, Span, LexicalModelPunctuation, ElementString, KMXPlus } from '@keymanapp/common-types'; - -export let u: USVString; -export let l: Transform -export let s: Suggestion; -export let st: SuggestionTag; -export let c: Context; -export let cap: Capabilities; -export let conf: Configuration; -export let d: Distribution; -export let wbf: WordBreakingFunction; -export let sp: Span; -export let lmp: LexicalModelPunctuation; - - -// try some of the other types - that should still work -export let elemString: ElementString; -export let section: KMXPlus.Section; diff --git a/common/web/types/test/fixtures/kmx/khmer_angkor.kmx b/common/web/types/tests/fixtures/kmx/khmer_angkor.kmx similarity index 100% rename from common/web/types/test/fixtures/kmx/khmer_angkor.kmx rename to common/web/types/tests/fixtures/kmx/khmer_angkor.kmx diff --git a/common/web/types/test/fixtures/kvk/balochi_inpage.kvk b/common/web/types/tests/fixtures/kvk/balochi_inpage.kvk similarity index 100% rename from common/web/types/test/fixtures/kvk/balochi_inpage.kvk rename to common/web/types/tests/fixtures/kvk/balochi_inpage.kvk diff --git a/common/web/types/test/fixtures/kvk/khmer_angkor.kvk b/common/web/types/tests/fixtures/kvk/khmer_angkor.kvk similarity index 100% rename from common/web/types/test/fixtures/kvk/khmer_angkor.kvk rename to common/web/types/tests/fixtures/kvk/khmer_angkor.kvk diff --git a/common/web/types/tests/helpers/index.ts b/common/web/types/tests/helpers/index.ts new file mode 100644 index 00000000000..717b2e75191 --- /dev/null +++ b/common/web/types/tests/helpers/index.ts @@ -0,0 +1,13 @@ +import * as path from "path"; +import { fileURLToPath } from "url"; + +/** + * Builds a path to the fixture with the given path components. + * + * e.g., makePathToFixture('basic.xml') + * + * @param components One or more path components. + */ +export function makePathToFixture(...components: string[]): string { + return fileURLToPath(new URL(path.join('..', '..', '..', 'tests', 'fixtures', ...components), import.meta.url)); +} diff --git a/common/web/types/test/kmx/test-keyman-targets.ts b/common/web/types/tests/kmx/keyman-targets.tests.ts similarity index 100% rename from common/web/types/test/kmx/test-keyman-targets.ts rename to common/web/types/tests/kmx/keyman-targets.tests.ts diff --git a/common/web/types/test/kmx/test-kmx-file.ts b/common/web/types/tests/kmx/kmx-file.tests.ts similarity index 100% rename from common/web/types/test/kmx/test-kmx-file.ts rename to common/web/types/tests/kmx/kmx-file.tests.ts diff --git a/common/web/types/test/kvk/test-kvk-file.ts b/common/web/types/tests/kvk/kvk-file.tests.ts similarity index 90% rename from common/web/types/test/kvk/test-kvk-file.ts rename to common/web/types/tests/kvk/kvk-file.tests.ts index 8a1179b67b2..8e0387fefe3 100644 --- a/common/web/types/test/kvk/test-kvk-file.ts +++ b/common/web/types/tests/kvk/kvk-file.tests.ts @@ -2,7 +2,7 @@ import * as fs from 'fs'; import 'mocha'; import { makePathToFixture } from '../helpers/index.js'; import KvkFileReader from "../../src/kvk/kvk-file-reader.js"; -import { verify_balochi_inpage, verify_khmer_angkor } from './test-kvk-utils.js'; +import { verify_balochi_inpage, verify_khmer_angkor } from './kvk-utils.tests.js'; describe('kvk-file-reader', function () { it('kvk-file-reader should read a valid file', function() { diff --git a/common/web/types/test/kvk/test-kvk-utils.ts b/common/web/types/tests/kvk/kvk-utils.tests.ts similarity index 100% rename from common/web/types/test/kvk/test-kvk-utils.ts rename to common/web/types/tests/kvk/kvk-utils.tests.ts diff --git a/common/web/types/test/ldml-keyboard/test-pattern-parser.ts b/common/web/types/tests/ldml-keyboard/pattern-parser.tests.ts similarity index 95% rename from common/web/types/test/ldml-keyboard/test-pattern-parser.ts rename to common/web/types/tests/ldml-keyboard/pattern-parser.tests.ts index 01d5a183c25..bf45933d158 100644 --- a/common/web/types/test/ldml-keyboard/test-pattern-parser.ts +++ b/common/web/types/tests/ldml-keyboard/pattern-parser.tests.ts @@ -33,7 +33,7 @@ describe('Test of Pattern Parsers', () => { // indirectly tests REFERENCE it('should match reference strings', () => { const cases: string[][] = [ - ['\\m{acute}', 'acute'], + ['\\m{acute} but not \\\\m{chronic}', 'acute'], // second marker is escaped ['\\m{acute}≈\\m{acute}', 'acute acute'], // not deduped ['\\m{grave}≠\\m{acute}', 'grave acute'], [MarkerParser.ANY_MARKER, MarkerParser.ANY_MARKER_ID], @@ -55,6 +55,19 @@ describe('Test of Pattern Parsers', () => { assert.deepEqual(MarkerParser.allReferences(str), [], `expected no markers: ${str}`); } }); + it('should match broken reference strings', () => { + const cases: string[][] = [ + // hyphenated marker id - illegal + ['\\m{chronic} \\m{a-cute} \\\\m{a-choo}', 'a-cute'], // \\m{a-choo} is literal + // marker through end of line + ['\\m{chronic} \\m{oopsIforGot to terminate it', 'oopsIforGot to terminate it'], + // marker terminated by other valid marker + ['\\m{chronic} \\m{what \\m{does} \\m{this button do?', 'what ', 'this button do?'], + ]; + for (const [str, ...reflist] of cases) { + assert.sameDeepMembers(MarkerParser.allBrokenReferences(str), reflist, `for ${str}`); + } + }); it('should be able to emit sentinel values', () => { assert.equal(MarkerParser.markerOutput(295), '\uFFFF\u0008\u0127', 'Wrong sentinel value emitted'); assert.equal(MarkerParser.markerOutput(MarkerParser.ANY_MARKER_INDEX), '\uFFFF\u0008\uD7FF', 'Wrong sentinel value emitted for ANY_MARKER_INDEX'); diff --git a/common/web/types/tests/ldml-keyboard/string-list.tests.ts b/common/web/types/tests/ldml-keyboard/string-list.tests.ts new file mode 100644 index 00000000000..58365bda66b --- /dev/null +++ b/common/web/types/tests/ldml-keyboard/string-list.tests.ts @@ -0,0 +1,216 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by Dr Mark C. Sinclair on 2024-11-28 + * + * Test code for string-lists.ts + */ + +import 'mocha'; +import { assert } from 'chai'; +import { StrsItem, StrsOptions, DependencySections, Strs } from '../../src/kmx/kmx-plus/kmx-plus.js'; +import { ListIndex, ListItem } from '../../src/ldml-keyboard/string-list.js'; + +describe('Test of String-List', () => { + describe('Test ListIndex', () => { + it('can construct a ListIndex', () => { + const strsItem = new StrsItem("abc"); + const actual = new ListIndex(strsItem); + assert.deepEqual(actual.value, strsItem); + }); + it('can check two ListIndex for equality', () => { + const listItemOne = new ListIndex(new StrsItem("abc")); + const listItemTwo = new ListIndex(new StrsItem("abc")); + assert.isTrue(listItemOne.isEqual(listItemTwo)); + }); + it('can check two different ListIndex are not equal', () => { + const listItemOne = new ListIndex(new StrsItem("abc")); + const listItemTwo = new ListIndex(new StrsItem("def")); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('can check a ListIndex and string for equality', () => { + const listItem = new ListIndex(new StrsItem("abc")); + const aString = "abc"; + assert.isTrue(listItem.isEqual(aString)); + }); + it('can check a ListIndex and string for inequality', () => { + const listItem = new ListIndex(new StrsItem("abc")); + const aString = "def"; + assert.isFalse(listItem.isEqual(aString)); + }); + it('can provide a correct string representation', () => { + const strsItem = new StrsItem("abc"); + const listItem = new ListIndex(strsItem); + const expected = "abc"; + assert.deepEqual(listItem.toString(), expected); + }); + }); + describe('Test ListItem', () => { + describe('Test fromStrings()', () => { + it('should return an empty ListItem if source is null', () => { + const actual = ListItem.fromStrings(null, null, null); + const expected = new ListItem(); + assert.deepEqual(actual, expected); + }); + it('should return a valid ListItem from a single source string', () => { + const source = ["abc"]; + const sections = { strs: new Strs }; + sections.strs.allocString = stubSectionsStrsAllocString; + const actual = ListItem.fromStrings(source, null, sections); + const expected = initListItem(source); + assert.deepEqual(actual, expected); + }); + it('should return a valid ListItem from a longer source', () => { + const source = ["abc", "def", "ghi"]; + const sections = { strs: new Strs }; + sections.strs.allocString = stubSectionsStrsAllocString; + const actual = ListItem.fromStrings(source, null, sections); + const expected = initListItem(source); + assert.deepEqual(actual, expected); + }); + }); + describe('Test getItemOrder()', () => { + it('should return a valid index for the first item', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + const index = listItem.getItemOrder("abc"); + assert.equal(index, 0); + }); + it('should return a valid index for a later item', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + const index = listItem.getItemOrder("ghi"); + assert.equal(index, 2); + }); + it('should return -1 for a missing item', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + const index = listItem.getItemOrder("jkl"); + assert.equal(index, -1); + }); + }); + describe('Test isEqual()', () => { + it('should return true for two empty ListItems', () => { + const listItemOne = new ListItem(); + const listItemTwo = new ListItem(); + assert.isTrue(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for empty and non-empty ListItems', () => { + const listItemOne = new ListItem(); + const listItemTwo = initListItem(["abc"]); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for non-empty and empty ListItems', () => { + const listItemOne = initListItem(["abc"]); + const listItemTwo = new ListItem(); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return true for identical ListItems', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.isTrue(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for different ListItems', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abd", "def", "ghi"]); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for different length ListItems', () => { + const listItemOne = initListItem(["abc", "def"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return true for empty ListItem and string[]', () => { + const listItem = new ListItem(); + assert.isTrue(listItem.isEqual([])); + }); + it('should return false for empty ListItem and non-empty string[]', () => { + const listItem = new ListItem(); + assert.isFalse(listItem.isEqual(["abc"])); + }); + it('should return false for non-empty ListItem and empty string[]', () => { + const listItem = initListItem(["abc"]);; + assert.isFalse(listItem.isEqual([])); + }); + it('should return true for identical ListItem and string[]', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + assert.isTrue(listItem.isEqual(["abc", "def", "ghi"])); + }); + it('should return false for different ListItem and string[]', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + assert.isFalse(listItem.isEqual(["abd", "def", "ghi"])); + }); + it('should return false for different length ListItem and string[]', () => { + const listItem = initListItem(["abc", "def"]); + assert.isFalse(listItem.isEqual(["abc", "def", "ghi"])); + }); + }); + describe('Test compareTo()', () => { + it('should return 0 for identical ListItems', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 0); + }); + it('should return -1 for ListItems with different first items (smallest first)', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abd", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), -1); + }); + it('should return 1 for ListItems with different first items (smallest second)', () => { + const listItemOne = initListItem(["abd", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 1); + }); + it('should return -1 for ListItems with different later items (smallest first)', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghj"]); + assert.equal(listItemOne.compareTo(listItemTwo), -1); + }); + it('should return 1 for ListItems with different later items (smallest second)', () => { + const listItemOne = initListItem(["abc", "def", "ghj"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 1); + }); + it('should return -1 for identical ListItems, except shorter first', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi", "jkl"]); + assert.equal(listItemOne.compareTo(listItemTwo), -1); + }); + it('should return 1 for identical ListItems, except longer first', () => { + const listItemOne = initListItem(["abc", "def", "ghi", "jkl"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 1); + }); + }); + describe('Test toString()', () => { + it('should return correct string', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + assert.deepEqual(listItem.toString(), "abc def ghi"); + }); + it('should return correct string for empty ListItem', () => { + const listItem = new ListItem; + assert.deepEqual(listItem.toString(), ""); + }); + }); + describe('Test toStringArray()', () => { + it('should return correct string[]', () => { + const source = ["abc", "def", "ghi"]; + const listItem = initListItem(source); + assert.deepEqual(listItem.toStringArray(), source); + }); + it('should return correct string[] for empty ListItem', () => { + const listItem = new ListItem; + assert.deepEqual(listItem.toStringArray(), []); + }); + }); + }); +}); + +function stubSectionsStrsAllocString(s?: string, opts?: StrsOptions, sections?: DependencySections): StrsItem { + return new StrsItem(s); +} + +function initListItem(source: Array): ListItem { + const listItem = new ListItem(); + for (const s of source) { + listItem.push(new ListIndex(new StrsItem(s))); + } + return listItem; +} diff --git a/common/web/types/tests/ldml-keyboard/unicodeset-parser-api.tests.ts b/common/web/types/tests/ldml-keyboard/unicodeset-parser-api.tests.ts new file mode 100644 index 00000000000..763bc6d5bb9 --- /dev/null +++ b/common/web/types/tests/ldml-keyboard/unicodeset-parser-api.tests.ts @@ -0,0 +1,24 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by Dr Mark C. Sinclair on 2024-11-29 + * + * Test code for unicodeset-parser-api.ts + */ + +import 'mocha'; +import { assert } from 'chai'; +import { UnicodeSet } from '../../src/ldml-keyboard/unicodeset-parser-api.js'; + +describe('Test of Unicode-Parser-API', () => { + describe('Test UnicodeSet', () => { + it('can provide a correct ranges length', () => { + const unicodeSet = new UnicodeSet("[ħa-z]", [[0x41, 0x7A], [0x0127, 0x0127]]); + assert.equal(unicodeSet.length, 2); + }); + it('can provide a correct string representation', () => { + const unicodeSet = new UnicodeSet("[ħa-z]", [[0x41, 0x7A], [0x0127, 0x0127]]); + assert.deepEqual(unicodeSet.toString(), "[ħa-z]"); + }); + }); +}); diff --git a/common/web/types/tests/lexical-model-types.tests.ts b/common/web/types/tests/lexical-model-types.tests.ts new file mode 100644 index 00000000000..ef8bed28a50 --- /dev/null +++ b/common/web/types/tests/lexical-model-types.tests.ts @@ -0,0 +1,25 @@ +/** + * This file "tests" the exports from the main module. + * + * Since the exports are all types, the "test" here is that the type can be + * imported and compiled without any compiler errors. + */ + +import { KMXPlus, LdmlKeyboardTypes, LexicalModelTypes } from "@keymanapp/common-types"; + +export let u: LexicalModelTypes.USVString; +export let l: LexicalModelTypes.Transform; +export let s: LexicalModelTypes.Suggestion; +export let st: LexicalModelTypes.SuggestionTag; +export let c: LexicalModelTypes.Context; +export let cap: LexicalModelTypes.Capabilities; +export let conf: LexicalModelTypes.Configuration; +export let d: LexicalModelTypes.Distribution; +export let wbf: LexicalModelTypes.WordBreakingFunction; +export let sp: LexicalModelTypes.Span; +export let lmp: LexicalModelTypes.LexicalModelPunctuation; + + +// try some of the other types - that should still work +export let elemString: LdmlKeyboardTypes.ElementString; +export let section: KMXPlus.Section; diff --git a/common/web/types/test/tsconfig.json b/common/web/types/tests/tsconfig.json similarity index 90% rename from common/web/types/test/tsconfig.json rename to common/web/types/tests/tsconfig.json index 9678c49945f..45e5311fdc0 100644 --- a/common/web/types/test/tsconfig.json +++ b/common/web/types/tests/tsconfig.json @@ -4,13 +4,12 @@ "compilerOptions": { "rootDir": ".", "rootDirs": ["./", "../src/"], - "outDir": "../build/test", + "outDir": "../build/tests", "baseUrl": ".", "strictNullChecks": false, // TODO: get rid of this as some point "allowSyntheticDefaultImports": true }, "include": [ - "**/test-*.ts", "**/*.tests.ts", "./helpers/*.ts", ], diff --git a/common/web/types/tests/util/file-types.tests.ts b/common/web/types/tests/util/file-types.tests.ts new file mode 100644 index 00000000000..3f4d6870918 --- /dev/null +++ b/common/web/types/tests/util/file-types.tests.ts @@ -0,0 +1,234 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by Dr Mark C. Sinclair on 2024-11-29 + * + * Test code for file-types.ts + */ + +import 'mocha'; +import { assert } from 'chai'; +import { + ALL, + ALL_SOURCE, + ALL_BINARY, + Binary, + fromFilename, + removeExtension, + sourceOrBinaryTypeFromFilename, + sourceTypeFromFilename, + binaryTypeFromFilename, + filenameIs, + replaceExtension, +} from '../../src/util/file-types.js'; + +describe('Test of File-Types', () => { + describe('Test of fromFilename()', () => { + it('can extract Source file extension', () => { + ALL_SOURCE.forEach((ext) => { + const filename = `file${ext}`; + const actual = fromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + it('can extract Binary file extension', () => { + ALL_BINARY.forEach((ext) => { + const filename = `file${ext}`; + const actual = fromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + it('can extract unmatched file extension', () => { + const ext = ".cpp"; + assert.isFalse((Object.values(ALL_SOURCE) as string[]).includes(ext)); + const filename = `file${ext}`; + const actual = fromFilename(filename); + assert.deepEqual(actual, ext); + }); + it('returns empty string for no file extension', () => { + const filename = `file`; + const actual = fromFilename(filename); + assert.deepEqual(actual, ""); + }); + it('can extract upper case file extension', () => { + const ext = ALL_SOURCE[0]; + const upperCaseExt = ext.toUpperCase(); + const filename = `file${upperCaseExt}`; + const actual = fromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + describe('Test of removeExtension()', () => { + it('can remove Source file extension', () => { + ALL_SOURCE.forEach((ext) => { + const filename = `file${ext}`; + const actual = removeExtension(filename); + assert.deepEqual(actual, "file"); + }); + }); + it('can remove Binary file extension', () => { + ALL_BINARY.forEach((ext) => { + const filename = `file${ext}`; + const actual = removeExtension(filename); + assert.deepEqual(actual, "file"); + }); + }); + it('can handle no file extension', () => { + const filename = removeExtension("file"); + assert.deepEqual(filename, "file"); + }); + }); + describe('Test of sourceOrBinaryTypeFromFilename()', () => { + it('can extract Source file extension', () => { + ALL_SOURCE.forEach((ext) => { + const filename = `file${ext}`; + const actual = sourceOrBinaryTypeFromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + it('can extract Binary file extension', () => { + ALL_BINARY.forEach((ext) => { + const filename = `file${ext}`; + const actual = sourceOrBinaryTypeFromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + it('returns null for unmatched file extension', () => { + const ext = ".cpp"; + assert.isFalse((Object.values(ALL) as string[]).includes(ext)); + const filename = `file${ext}`; + const actual = sourceOrBinaryTypeFromFilename(filename); + assert.isNull(actual); + }); + it('can extract upper case file extension', () => { + const ext = ALL[0]; + const upperCaseExt = ext.toUpperCase(); + const filename = `file${upperCaseExt}`; + const actual = sourceOrBinaryTypeFromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + describe('Test of sourceTypeFromFilename()', () => { + it('can extract Source file extension', () => { + ALL_SOURCE.forEach((ext) => { + const filename = `file${ext}`; + const actual = sourceTypeFromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + it('returns null for a Binary file extension', () => { + ALL_BINARY.forEach((ext) => { + const filename = `file${ext}`; + const actual = sourceTypeFromFilename(filename); + assert.isNull(actual); + }); + }); + it('returns null for unmatched file extension', () => { + const ext = ".cpp"; + assert.isFalse((Object.values(ALL_SOURCE) as string[]).includes(ext)); + const filename = `file${ext}`; + const actual = sourceTypeFromFilename(filename); + assert.isNull(actual); + }); + it('can extract upper case file extension', () => { + const ext = ALL_SOURCE[0]; + const upperCaseExt = ext.toUpperCase(); + const filename = `file${upperCaseExt}`; + const actual = sourceTypeFromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + describe('Test of binaryTypeFromFilename()', () => { + it('returns null for a Source file extension', () => { + ALL_SOURCE.forEach((ext) => { + const filename = `file${ext}`; + const actual = binaryTypeFromFilename(filename); + assert.isNull(actual); + }); + }); + it('can extract Binary file extension', () => { + ALL_BINARY.forEach((ext) => { + const filename = `file${ext}`; + const actual = binaryTypeFromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + it('returns null for unmatched file extension', () => { + const ext = ".cpp"; + assert.isFalse((Object.values(ALL_BINARY) as string[]).includes(ext)); + const filename = `file${ext}`; + const actual = binaryTypeFromFilename(filename); + assert.isNull(actual); + }); + it('can extract upper case file extension', () => { + const ext = ALL_BINARY[0]; + const upperCaseExt = ext.toUpperCase(); + const filename = `file${upperCaseExt}`; + const actual = binaryTypeFromFilename(filename); + assert.deepEqual(actual, ext); + }); + }); + describe('Test of filenameIs()', () => { + it('can identify Source file extension', () => { + ALL_SOURCE.forEach((ext) => { + const filename = `file${ext}`; + const actual = filenameIs(filename, ext); + assert.isTrue(actual); + }); + }); + it('can identify Binary file extension', () => { + ALL_BINARY.forEach((ext) => { + const filename = `file${ext}`; + if (ext == Binary.Model) { // Special case for .model.js + const actual = filenameIs(filename, Binary.WebKeyboard); + assert.isFalse(actual); + } + const actual = filenameIs(filename, ext); + assert.isTrue(actual); + }); + }); + it('can identify upper case file extension', () => { + const ext = ALL[0]; + const upperCaseExt = ext.toUpperCase(); + const filename = `file${upperCaseExt}`; + const actual = filenameIs(filename, ext); + assert.isTrue(actual); + }); + }); + describe('Test of replaceExtension()', () => { + it('can replace an extension', () => { + const oldExt = ".cpp"; + const newExt = ".js"; + const oldFilename = `file${oldExt}`; + const newFilename = `file${newExt}`; + const actual = replaceExtension(oldFilename, oldExt, newExt); + assert.deepEqual(actual, newFilename); + }); + it('should return null for incorrect old extension (too short)', () => { + const oldExt = ".ts"; + const newExt = ".js"; + const oldFilename = `file.c`; + const actual = replaceExtension(oldFilename, oldExt, newExt); + assert.isNull(actual); + }); + it('should return null for incorrect old extension (too long)', () => { + const oldExt = ".ts"; + const newExt = ".js"; + const oldFilename = `file.cpp`; + const actual = replaceExtension(oldFilename, oldExt, newExt); + assert.isNull(actual); + }); + // it('should return null for null old extension', () => { + // const newExt = ".js"; + // const oldFilename = `file.ts`; + // const actual = replaceExtension(oldFilename, null, newExt); + // assert.isNull(actual); + // }); + // it('should return null for null new extension', () => { + // const oldExt = ".ts"; + // const oldFilename = `file.ts`; + // const actual = replaceExtension(oldFilename, oldExt, null); + // assert.isNull(actual); + // }); + }); +}); diff --git a/common/web/types/test/util/test-unescape.ts b/common/web/types/tests/util/unescape.tests.ts similarity index 94% rename from common/web/types/test/util/test-unescape.ts rename to common/web/types/tests/util/unescape.tests.ts index 8c75b491824..3eaafd7150f 100644 --- a/common/web/types/test/util/test-unescape.ts +++ b/common/web/types/tests/util/unescape.tests.ts @@ -1,6 +1,6 @@ import 'mocha'; import {assert} from 'chai'; -import {unescapeString, UnescapeError, isOneChar, toOneChar, unescapeOneQuadString, BadStringAnalyzer, isValidUnicode, describeCodepoint, isPUA, BadStringType, unescapeStringToRegex, unescapeQuadString, NFDAnalyzer} from '../../src/util/util.js'; +import {unescapeString, UnescapeError, isOneChar, toOneChar, unescapeOneQuadString, BadStringAnalyzer, isValidUnicode, describeCodepoint, isPUA, BadStringType, unescapeStringToRegex, unescapeQuadString, NFDAnalyzer, isNormalized} from '../../src/util/util.js'; describe('test UTF32 functions()', function() { it('should properly categorize strings', () => { @@ -186,6 +186,24 @@ describe('test bad char functions', () => { assert.isTrue(isPUA(ch), describeCodepoint(ch)); } }); + describe('test isDenormalized()', () => { + it('should correctly categorize strings', () => { + [ + undefined, + null, + '', + 'ABC', + 'fa\u1E69cinating', // NFC + 'fas\u0323\u0307cinating', // NFD + 'd\u0323\u0307', // NFD + '\u1e0d\u0307', // NFC + ].map(s => assert.isTrue(isNormalized(s), `for string ${s}`)); + [ + 'd\u0307\u0323', // NFD but reversed marks + 'fas\u0307\u0323cinating', // not-NFD + ].map(s => assert.isFalse(isNormalized(s), `for string ${s}`)); + }); + }); }); describe('test BadStringAnalyzer', () => { diff --git a/common/windows/delphi/general/KeymanPaths.pas b/common/windows/delphi/general/KeymanPaths.pas index bc534b9f526..fbfa9961d70 100644 --- a/common/windows/delphi/general/KeymanPaths.pas +++ b/common/windows/delphi/general/KeymanPaths.pas @@ -436,12 +436,18 @@ class function TKeymanPaths.RunningFromSource(var keyman_root: string): Boolean; class function TKeymanPaths.KeymanCoreLibraryPath(const Filename: string): string; var keyman_root: string; + configuration: string; begin // Look up KEYMAN_ROOT development variable -- if found and executable // within that path then use that as source path if TKeymanPaths.RunningFromSource(keyman_root) then begin - Exit(keyman_root + 'core\build\x86\debug\src\' + Filename); +{$IFDEF DEBUG} + configuration := 'debug'; +{$ELSE} + configuration := 'release'; +{$ENDIF} + Exit(keyman_root + 'core\build\x86\'+configuration+'\src\' + Filename); end; Result := GetDebugPath('KeymanCoreLibraryPath', ''); diff --git a/core/doc/BUILDING.md b/core/docs/BUILDING.md similarity index 100% rename from core/doc/BUILDING.md rename to core/docs/BUILDING.md diff --git a/core/docs/api/background.md b/core/docs/api/background.md new file mode 100644 index 00000000000..d4c638f0ce7 --- /dev/null +++ b/core/docs/api/background.md @@ -0,0 +1,417 @@ +--- +title: Background - Keyman Core API +--- + +## Namespace +All calls, types and enums are prefixed with the namespace identifier `km_core_` + +## API idioms + +### Error Handling + +Error handling and success failure notification are communicated through a +general mechanism similar to COM’s `HRESULT` scheme (unlike COM, any non-zero +value is an error). Any functions that can fail will always return a status +value and all results are returned via outparams passed to the function. + +### Passing variable length data out + +Almost all calls marshalling variable length aggregate data in or out of an API +object take the form: + +```c +km_core_status fn_name(object_ref, buffer_ptr, size_ptr) +``` +where the `buffer_ptr` is nullable and all other arguments are required (will +result in an [`KM_CORE_STATUS_INVALID_ARGUMENT`](#km_core_status_codes) +status being returned if nulled). When `buffer_ptr` is `nullptr` or `0` the +function will place the size of the required buffer in the variable pointed to +by `size_ptr`. + +### Resource management + +Calls which result in the allocation of resources, regardless of resulting +ownership, are of the form: +```c +km_core_status fn_name(object_ref, handle_out_ptr) +``` +where `handle_out_ptr` is a valid pointer to a caller allocated variable to hold +the resulting resource handle. This is often a reference to a created object. +Unless stated all arguments are required (will result in an +[`KM_CORE_STATUS_INVALID_ARGUMENT`](#km_core_status_codes) status being +returned if nulled). + +All dispose calls are designed to accept `nullptr` or `0` as a valid value and +will do nothing in that event. + +### Fixed size attribute access + +For accessors to fixed size attributes of an object these will take the form: +```c +attr_value fn_name(object_ref) +``` +`object_ref` is required to be valid and will result in a nonsense value being returned if `nullptr` or `0`. + +### Versioning scheme + +This follows the libtool interface versioning scheme of `current.age.revision`: + +`current` + +The most recent interface number that the engine implements. + +`age` + +How many interface numbers back from current the library implements. E.g. 5.2.0 +would mean the library provides interface versions 3-5 and 5.0.0 would mean just +interface version 5 and nothing older. + +`revision` + +The implementation version of the current interface. This represents +improvements to the code that don't change the intended behaviour of the +interface such as bug fixes and optimisations. + +For Linux and other OS which support this scheme the dynamic linker will +automatically choose the most updated version if more than one implementation is +available. For Windows or dynamic loaded shared objects on Linux you can use the +[km_core_get_engine_attrs] call and [Library version +macros](#lib-version-macros) to check the loaded DLL supplies the correct +interface. + +------------------------------------------------------------------------------- + +# Common functions, types, and macros + + +## Basic types + +Fundamental types for representing data passed across the API. + +### km_core_cp type {#km_core_cp} + +`uint16_t/char16_t` + +Represents a UTF16 codepoint, most strings are passed as UTF16. + +### km_core_usv type {#km_core_usv} + +`uint32_t/char32_t` + +An integral type capable of holding a single Unicode Scalar Value, a decoded UTF +codepoint. + +### km_core_virtual_key type {#km_core_virtual_key} + +`uint16_t` + +An integral type capable of holding a platform specific virtual key code. + +### km_core_status type {#km_core_status} + +`uint32_t` + +An integral 32 bit wide type capable of holding any valid status code as defined +by the `enum` [km_core_status_codes]. + +### km_core_modifier_state type {#km_core_modifier_state} + +`uint16_t` + +An integral type bitmask representing the state of each modifier key. + + + +## Resource types + +Opaque types for representing resources provided or created by the keyboard +processor implementation. + +### km_core_keyboard struct {#km_core_keyboard} + +Represents a keyboard loaded from disk, that can be executed by the keyboard +processor to consume events, update state associated with an insertion point and +produce action items. A keyboard object may be referenced by any number of state +objects but must be disposed of after all state objects referencing it have +first been disposed of. + +### km_core_state struct {#km_core_state} + +Represents all state associated with an insertion point using a keyboard. This +tracks context, and current action items resulting from a processed keyboard +event. There can be many state objects using the same keyboard. A state object +may not live longer than the keyboard it manages state for. + +### km_core_options struct {#km_core_options} + +Represents a set of option items for environmental state and keyboard state. + + + + + + +------------------------------------------------------------------------------- + +# km_core_status_codes enum {#km_core_status_codes} + +## Description + +An error code mechanism similar to COM’s `HRESULT` scheme (unlike COM, any +non-zero value is an error). + +## Specification + +```c +enum km_core_status_codes { + KM_CORE_STATUS_OK = 0, + KM_CORE_STATUS_NO_MEM = 1, + KM_CORE_STATUS_IO_ERROR = 2, + KM_CORE_STATUS_INVALID_ARGUMENT = 3, + KM_CORE_STATUS_KEY_ERROR = 4, + KM_CORE_STATUS_INSUFFICENT_BUFFER = 5, + KM_CORE_STATUS_INVALID_UTF = 6, + KM_CORE_STATUS_INVALID_KEYBOARD = 7, + KM_CORE_STATUS_NOT_IMPLEMENTED = 8, + KM_CORE_STATUS_OS_ERROR = 0x80000000 +}; + +``` + +## Values + +`KM_CORE_STATUS_OK` + +: Success code. Call completed as documented. + +`KM_CORE_STATUS_NO_MEM` + +: The call failed to allocate memory during its execution, causing it to fail. + +`KM_CORE_STATUS_IO_ERROR` + +: The call performed an I/O operation which failed, causing it to fail. + +`KM_CORE_STATUS_INVALID_ARGUMENT` + +: The call detected one of its parameters was invalid or unsafe. + +`KM_CORE_STATUS_KEY_ERROR` + +: The provided key or index into a collection object was not present. + +`KM_CORE_STATUS_INSUFFICENT_BUFFER` + +: The provided buffer did not contain enough space to fully encode or copy the +result of this call. + +`KM_CORE_STATUS_INVALID_UTF` + +: A malformed or partial UTF sequence prevented complete decoding of a unicode +string. + +`KM_CORE_STATUS_INVALID_KEYBOARD` + +: An attempt to decode a keyboard file failed. + +`KM_CORE_STATUS_OS_ERROR` + +: This allows encapsulating a platform error code: the remaining 31 low bits are +the error code returned by the OS for cases where the failure mode is platform +specific. For HRESULT codes this only permits failure codes to be passed and not +success codes. + +------------------------------------------------------------------------------- + +# km_core_attr struct {#km_core_attr} + +## Description + +A structure describing information about Keyman Core implementing this API. + +## Specification + +```c + +typedef struct { + size_t max_context; + uint16_t current; + uint16_t revision; + uint16_t age; + uint16_t technology; + char const *vendor; +} km_core_attr; + +``` +## Members + +`max_context` +: Maximum context size supported by processor. + +`current` +: Current API number supported. + +`revision` +: Implementation number of current API. + +`age` +: current - age == Oldest API number supported. + +`technology` +: A bit field of [km_core_tech_value] values, +specifiying which Keyboard technologies the engine supports. + +`vendor` +: A UTF-8 encoded string identifying the implementer of the processor. + +------------------------------------------------------------------------------- + +# km_core_tech_value enum {#km_core_tech_value} + +## Description + +Values for a bit field indicating which keyboarding technologies a keyboard +processor supports. + +## Specification + +```c + +enum km_core_tech_value { + KM_CORE_TECH_UNSPECIFIED = 0, + KM_CORE_TECH_MOCK = 1 << 0, + KM_CORE_TECH_KMX = 1 << 1, + KM_CORE_TECH_LDML = 1 << 2 +}; + +``` +## Values + +`KM_CORE_TECH_UNSPECIFIED` +: The keyboard processor implementation does not disclose which technologies it +implements. + +`KM_CORE_TECH_MOCK` +: The keyboard processor implements a simple en-US keyboard for the purposes of +testing the API. + +`KM_CORE_TECH_UNSPECIFIED` +: The keyboard processor implements a Keyman KMX compatible engine. + +`KM_CORE_TECH_UNSPECIFIED` +: The keyboard processor implements a LDML capable processing engine. + +------------------------------------------------------------------------------- + +# km_core_get_engine_attrs() {#km_core_get_engine_attrs} + +## Description + +Get access processors attributes describing version and technology implemented. + +## Specification + +```c +KMN_API +km_core_attr const * +km_core_get_engine_attrs(km_core_state const *state); + +``` + +## Parameters + +`state` +: An opaque pointer to a [km_core_state]. + +## Returns +A pointer to a [km_core_attr] structure. Do not modify the contents of this +structure. + +------------------------------------------------------------------------------- + +# km_core_bool enum {#km_core_bool} + +## Description + +Defines a boolean state. + +## Specification +```c +typedef enum { KM_CORE_FALSE = 0, KM_CORE_TRUE = 1 } km_core_bool; + +``` +------------------------------------------------------------------------------- + + +[km_core_cp]: background#km_core_cp "km_core_cp type" +[km_core_usv]: background#km_core_usv "km_core_usv type" +[km_core_virtual_key]: background#km_core_virtual_key "km_core_virtual_key type" +[km_core_status]: background#km_core_status "km_core_status type" +[km_core_modifier_state]: background#km_core_modifier_state "km_core_modifier_state type" +[km_core_keyboard]: background#km_core_keyboard "km_core_keyboard struct" +[km_core_state]: background#km_core_state "km_core_state struct" +[km_core_options]: background#km_core_options "km_core_options struct" +[km_core_status_codes]: background#km_core_status_codes "km_core_status_codes enum" +[km_core_attr]: background#km_core_attr "km_core_attr struct" +[km_core_tech_value]: background#km_core_tech_value "km_core_tech_value enum" +[km_core_get_engine_attrs]: background#km_core_get_engine_attrs "km_core_get_engine_attrs function" +[km_core_bool]: background#km_core_bool "km_core_bool enum" +[km_core_caps_state]: state#km_core_caps_state "km_core_caps_state enum" +[km_core_actions]: state#km_core_actions "km_core_actions struct" +[km_core_state_get_actions]: state#km_core_state_get_actions "km_core_state_get_actions function" +[km_core_context_status]: state#km_core_context_status "km_core_context_status enum" +[km_core_state_context_set_if_needed]: state#km_core_state_context_set_if_needed "km_core_state_context_set_if_needed function" +[km_core_state_context_clear]: state#km_core_state_context_clear "km_core_state_context_clear function" +[km_core_option_scope]: options#km_core_option_scope "km_core_option_scope enum" +[km_core_option_item]: options#km_core_option_item "km_core_option_item struct" +[km_core_options_list_size]: options#km_core_options_list_size "km_core_options_list_size function" +[km_core_state_options_update]: options#km_core_state_options_update "km_core_state_options_update function" +[km_core_state_options_to_json]: options#km_core_state_options_to_json "km_core_state_options_to_json function" +[km_core_keyboard_attrs]: keyboards#km_core_keyboard_attrs "km_core_keyboard_attrs struct" +[km_core_keyboard_key]: keyboards#km_core_keyboard_key "km_core_keyboard_key struct" +[km_core_keyboard_imx]: keyboards#km_core_keyboard_imx "km_core_keyboard_imx struct" +[km_core_keyboard_load_from_blob]: keyboards#km_core_keyboard_load_from_blob "km_core_keyboard_load_from_blob function" +[km_core_keyboard_dispose]: keyboards#km_core_keyboard_dispose "km_core_keyboard_dispose function" +[km_core_keyboard_get_attrs]: keyboards#km_core_keyboard_get_attrs "km_core_keyboard_get_attrs function" +[km_core_keyboard_get_key_list]: keyboards#km_core_keyboard_get_key_list "km_core_keyboard_get_key_list function" +[km_core_keyboard_key_list_dispose]: keyboards#km_core_keyboard_key_list_dispose "km_core_keyboard_key_list_dispose function" +[km_core_keyboard_imx_list_dispose]: keyboards#km_core_keyboard_imx_list_dispose "km_core_keyboard_imx_list_dispose function" +[km_core_state_imx_register_callback]: keyboards#km_core_state_imx_register_callback "km_core_state_imx_register_callback function" +[km_core_state_imx_deregister_callback]: keyboards#km_core_state_imx_deregister_callback "km_core_state_imx_deregister_callback function" +[km_core_state_create]: keyboards#km_core_state_create "km_core_state_create function" +[km_core_state_clone]: keyboards#km_core_state_clone "km_core_state_clone function" +[km_core_state_dispose]: keyboards#km_core_state_dispose "km_core_state_dispose function" +[km_core_debug_context_type]: keyboards#km_core_debug_context_type "km_core_debug_context_type enum" +[km_core_state_context_debug]: keyboards#km_core_state_context_debug "km_core_state_context_debug function" +[km_core_cp_dispose]: keyboards#km_core_cp_dispose "km_core_cp_dispose function" +[km_core_state_to_json]: keyboards#km_core_state_to_json "km_core_state_to_json function" +[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" +[km_core_process_event]: processor#km_core_process_event "km_core_process_event function" +[km_core_event]: processor#km_core_event "km_core_event function" +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file diff --git a/core/docs/api/building.md b/core/docs/api/building.md new file mode 100644 index 00000000000..65ca558670a --- /dev/null +++ b/core/docs/api/building.md @@ -0,0 +1,63 @@ +--- +title: How to build Keyman Core +--- + +## Prerequisites + +### To build + +* Python 3 +* Meson build system. +* C++17 or later compiler. + +### Optional + +* [kmc](https://keyman.com/developer/download) (for testing) + +## Installing Python3 + +### Linux + +You will be able to install a python3 package in any reputable recent version of +linux using its package manager if it's not already installed. + +### macOS + +You can get the official installer from the official Python site: +[https://www.python.org/downloads/mac-osx](https://www.python.org/downloads/mac-osx/) + +### Windows + +You can get the official installer from the official Python site: +[https://www.python.org/downloads/windows](https://www.python.org/downloads/windows/) + +## Installing Meson + +Ensure you have Python3 correctly installed and can run the command `pip3`. + + $> python3 -m pip install meson + +## Building + +In your source directory do the following: + + $> cd core + $> ./build.sh configure build test + +## Note on kmc + +kmc is node.js-based the command-line compiler from Keyman Developer, available +from [keyman.com](https://keyman.com/developer/) or on npm at +[@keymanapp/kmc](https://npmjs.com/package/@keymanapp/kmc). + +### Windows + +The search path can be edited through System settings / Advanced system settings +/ Environment Variables / User environment variables. + +If you have Keyman Developer installed, kmc should already be on your path. +Otherwise, add the path where you extracted the kmcomp archive. + +### Linux & MacOS + +Install kmc from the NPM package. diff --git a/core/docs/api/changes.md b/core/docs/api/changes.md new file mode 100644 index 00000000000..e5736494abc --- /dev/null +++ b/core/docs/api/changes.md @@ -0,0 +1,64 @@ +--- +title: Changes - Keyman Core API +--- + +## Changes between 16.0 and 17.0 + +* The namespace identifier has changed from `km_kbp_` to `km_core_`. +* Most context APIs are now private, and [km_core_state_context_set_if_needed] is the + primary context function. Private APIs are available in + `keyman_core_api_context.h`. +* The action queue APIs are now private and deprecated. Instead, use + [km_core_state_get_actions]. Private APIs are available in + `keyman_core_api_actions.h`. +* Debug APIs are available in `keyman_core_api_debug.h`. + +------------------------------------------------------------------------------- + + +[km_core_cp]: background#km_core_cp "km_core_cp type" +[km_core_usv]: background#km_core_usv "km_core_usv type" +[km_core_virtual_key]: background#km_core_virtual_key "km_core_virtual_key type" +[km_core_status]: background#km_core_status "km_core_status type" +[km_core_modifier_state]: background#km_core_modifier_state "km_core_modifier_state type" +[km_core_keyboard]: background#km_core_keyboard "km_core_keyboard struct" +[km_core_state]: background#km_core_state "km_core_state struct" +[km_core_options]: background#km_core_options "km_core_options struct" +[km_core_status_codes]: background#km_core_status_codes "km_core_status_codes enum" +[km_core_attr]: background#km_core_attr "km_core_attr struct" +[km_core_tech_value]: background#km_core_tech_value "km_core_tech_value enum" +[km_core_get_engine_attrs]: background#km_core_get_engine_attrs "km_core_get_engine_attrs function" +[km_core_bool]: background#km_core_bool "km_core_bool enum" +[km_core_caps_state]: state#km_core_caps_state "km_core_caps_state enum" +[km_core_actions]: state#km_core_actions "km_core_actions struct" +[km_core_state_get_actions]: state#km_core_state_get_actions "km_core_state_get_actions function" +[km_core_context_status]: state#km_core_context_status "km_core_context_status enum" +[km_core_state_context_set_if_needed]: state#km_core_state_context_set_if_needed "km_core_state_context_set_if_needed function" +[km_core_state_context_clear]: state#km_core_state_context_clear "km_core_state_context_clear function" +[km_core_option_scope]: options#km_core_option_scope "km_core_option_scope enum" +[km_core_option_item]: options#km_core_option_item "km_core_option_item struct" +[km_core_options_list_size]: options#km_core_options_list_size "km_core_options_list_size function" +[km_core_state_options_update]: options#km_core_state_options_update "km_core_state_options_update function" +[km_core_state_options_to_json]: options#km_core_state_options_to_json "km_core_state_options_to_json function" +[km_core_keyboard_attrs]: keyboards#km_core_keyboard_attrs "km_core_keyboard_attrs struct" +[km_core_keyboard_key]: keyboards#km_core_keyboard_key "km_core_keyboard_key struct" +[km_core_keyboard_imx]: keyboards#km_core_keyboard_imx "km_core_keyboard_imx struct" +[km_core_keyboard_load_from_blob]: keyboards#km_core_keyboard_load_from_blob "km_core_keyboard_load_from_blob function" +[km_core_keyboard_dispose]: keyboards#km_core_keyboard_dispose "km_core_keyboard_dispose function" +[km_core_keyboard_get_attrs]: keyboards#km_core_keyboard_get_attrs "km_core_keyboard_get_attrs function" +[km_core_keyboard_get_key_list]: keyboards#km_core_keyboard_get_key_list "km_core_keyboard_get_key_list function" +[km_core_keyboard_key_list_dispose]: keyboards#km_core_keyboard_key_list_dispose "km_core_keyboard_key_list_dispose function" +[km_core_keyboard_imx_list_dispose]: keyboards#km_core_keyboard_imx_list_dispose "km_core_keyboard_imx_list_dispose function" +[km_core_state_imx_register_callback]: keyboards#km_core_state_imx_register_callback "km_core_state_imx_register_callback function" +[km_core_state_imx_deregister_callback]: keyboards#km_core_state_imx_deregister_callback "km_core_state_imx_deregister_callback function" +[km_core_state_create]: keyboards#km_core_state_create "km_core_state_create function" +[km_core_state_clone]: keyboards#km_core_state_clone "km_core_state_clone function" +[km_core_state_dispose]: keyboards#km_core_state_dispose "km_core_state_dispose function" +[km_core_debug_context_type]: keyboards#km_core_debug_context_type "km_core_debug_context_type enum" +[km_core_state_context_debug]: keyboards#km_core_state_context_debug "km_core_state_context_debug function" +[km_core_cp_dispose]: keyboards#km_core_cp_dispose "km_core_cp_dispose function" +[km_core_state_to_json]: keyboards#km_core_state_to_json "km_core_state_to_json function" +[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" +[km_core_process_event]: processor#km_core_process_event "km_core_process_event function" +[km_core_event]: processor#km_core_event "km_core_event function" +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file diff --git a/core/docs/api/index.md b/core/docs/api/index.md new file mode 100644 index 00000000000..94bb517654c --- /dev/null +++ b/core/docs/api/index.md @@ -0,0 +1,125 @@ +--- +title: Keyman Core API +--- + +## Overview +Keyman Core is the component of Keyman Engine that implements keyboarding rules. +It is platform independent and allows support for different keyboard formats to +be implemented within Keyman Engine. Eventually, Keyman Core will be used in +Keyman on all platforms. As of writing, Keyman for Linux, Keyman for Windows, +Keyman for macOS, and Keyman Developer use Keyman Core. + +This is an internal API intended for use only within Keyman Engine. + +## Reference + +* [Background](background) +* [Changes from earlier versions](changes) +* [Keyboards](keyboards) +* [Options](options) +* [Processor](processor) +* [State and Actions](state) +* [JSON introspection Schema](json-schema) +* [Building Keyman Core](building) + +## Requirements +1. Cross platform. +2. Cross language. +3. Facilitate stateless operation of the Engine. +4. Keyboard format agnostic -- support both KMN and future LDML based keyboards. +5. Support querying Engine attributes. +6. Support querying Keyboard attributes. +7. Idempotent + + +## Design decisions in support of requirements +- Use C or C99 types and calling convention for the interface, it has the + broadest language FFI support. [1,2] +- Have client (Platform layer) code load keyboards, manage & pass state. [3,4,7] +- Provide query calls to return static attributes data for keyboards and + engine [5,6] +- Provide get/set calls for client accessible keyboard state information [3,4] + + +## Glossary +- __Platform layer:__ +The code that consumes the Keyman Core API, and provides the +operating system-specific handling of keystroke events and integration with +applications. +- __Client Application:__ +The application that has the focus and receives text events from the Platform +layer. +- __Context:__ Text preceding the insertion point +- __Marker:__ Positional state that can be placed in the Context. +- __Keyboard:__ A set of rules for execution by an Engine +- __Option:__ A variable in a dynamic or static key value store. +- __Processor:__ +The component that implements this API and can parse and execute a particular +keyboard. +- __State:__ An object that holds internal state of the Processor for a given +insertion point +- __Action:__ +A directive output by the processor detailing how the Platform layer should +transform the Client Application's text buffer. There may be several items +produced by a single keyboard event. +- __Keyboard Event:__ +A virtual key event and modifier map received from the Platform layer to be +processed with the state object for this Client application. +- __Virtual Key:__ +A code based on the US English layout, with values matching the Windows +virtual key codes. See `keyman_core_api_vkeys.h` for definitions. +- __Modifier Key:__ +The set of Control, Shift, Alt, Caps Lock keys. On some platforms these may +have other names (e.g. Alt is called Option on macOS); other platform-specific +modifiers such as Windows key are excluded from this set. Some modifiers are +transient, such as Control, and others have long-lasting state, such as +Caps Lock. + +- __See more in__ [Keyman Glossary](https://github.com/keymanapp/keyman/wiki/Keyman-glossary) + +[km_core_cp]: background#km_core_cp "km_core_cp type" +[km_core_usv]: background#km_core_usv "km_core_usv type" +[km_core_virtual_key]: background#km_core_virtual_key "km_core_virtual_key type" +[km_core_status]: background#km_core_status "km_core_status type" +[km_core_modifier_state]: background#km_core_modifier_state "km_core_modifier_state type" +[km_core_keyboard]: background#km_core_keyboard "km_core_keyboard struct" +[km_core_state]: background#km_core_state "km_core_state struct" +[km_core_options]: background#km_core_options "km_core_options struct" +[km_core_status_codes]: background#km_core_status_codes "km_core_status_codes enum" +[km_core_attr]: background#km_core_attr "km_core_attr struct" +[km_core_tech_value]: background#km_core_tech_value "km_core_tech_value enum" +[km_core_get_engine_attrs]: background#km_core_get_engine_attrs "km_core_get_engine_attrs function" +[km_core_bool]: background#km_core_bool "km_core_bool enum" +[km_core_caps_state]: state#km_core_caps_state "km_core_caps_state enum" +[km_core_actions]: state#km_core_actions "km_core_actions struct" +[km_core_state_get_actions]: state#km_core_state_get_actions "km_core_state_get_actions function" +[km_core_context_status]: state#km_core_context_status "km_core_context_status enum" +[km_core_state_context_set_if_needed]: state#km_core_state_context_set_if_needed "km_core_state_context_set_if_needed function" +[km_core_state_context_clear]: state#km_core_state_context_clear "km_core_state_context_clear function" +[km_core_option_scope]: options#km_core_option_scope "km_core_option_scope enum" +[km_core_option_item]: options#km_core_option_item "km_core_option_item struct" +[km_core_options_list_size]: options#km_core_options_list_size "km_core_options_list_size function" +[km_core_state_options_update]: options#km_core_state_options_update "km_core_state_options_update function" +[km_core_state_options_to_json]: options#km_core_state_options_to_json "km_core_state_options_to_json function" +[km_core_keyboard_attrs]: keyboards#km_core_keyboard_attrs "km_core_keyboard_attrs struct" +[km_core_keyboard_key]: keyboards#km_core_keyboard_key "km_core_keyboard_key struct" +[km_core_keyboard_imx]: keyboards#km_core_keyboard_imx "km_core_keyboard_imx struct" +[km_core_keyboard_load_from_blob]: keyboards#km_core_keyboard_load_from_blob "km_core_keyboard_load_from_blob function" +[km_core_keyboard_dispose]: keyboards#km_core_keyboard_dispose "km_core_keyboard_dispose function" +[km_core_keyboard_get_attrs]: keyboards#km_core_keyboard_get_attrs "km_core_keyboard_get_attrs function" +[km_core_keyboard_get_key_list]: keyboards#km_core_keyboard_get_key_list "km_core_keyboard_get_key_list function" +[km_core_keyboard_key_list_dispose]: keyboards#km_core_keyboard_key_list_dispose "km_core_keyboard_key_list_dispose function" +[km_core_keyboard_imx_list_dispose]: keyboards#km_core_keyboard_imx_list_dispose "km_core_keyboard_imx_list_dispose function" +[km_core_state_imx_register_callback]: keyboards#km_core_state_imx_register_callback "km_core_state_imx_register_callback function" +[km_core_state_imx_deregister_callback]: keyboards#km_core_state_imx_deregister_callback "km_core_state_imx_deregister_callback function" +[km_core_state_create]: keyboards#km_core_state_create "km_core_state_create function" +[km_core_state_clone]: keyboards#km_core_state_clone "km_core_state_clone function" +[km_core_state_dispose]: keyboards#km_core_state_dispose "km_core_state_dispose function" +[km_core_debug_context_type]: keyboards#km_core_debug_context_type "km_core_debug_context_type enum" +[km_core_state_context_debug]: keyboards#km_core_state_context_debug "km_core_state_context_debug function" +[km_core_cp_dispose]: keyboards#km_core_cp_dispose "km_core_cp_dispose function" +[km_core_state_to_json]: keyboards#km_core_state_to_json "km_core_state_to_json function" +[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" +[km_core_process_event]: processor#km_core_process_event "km_core_process_event function" +[km_core_event]: processor#km_core_event "km_core_event function" +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file diff --git a/core/docs/api/json-schema.md b/core/docs/api/json-schema.md new file mode 100644 index 00000000000..756d5c4969d --- /dev/null +++ b/core/docs/api/json-schema.md @@ -0,0 +1,77 @@ +--- +title: JSON Introspection Schema +--- + +The [`km_core_state_to_json()`](state#km_core_state_to_json) call +generates a JSON document describing the internal state of the keyboard +processor, this is the schema describing that document. + +**WARNING**: The structure and format of the JSON document is independently +versioned is not considered part of C API. It is intended solely for use in +diagnostics or by development and debugging tools which may need to be aware of +keyboard processor engine implementation details. + +```json +{"$schema": "http://json-schema.org/draft-06/schema#", + "$id": "@replace_me_with_introspection_schema_uri@", + "$comment": "© 2018 SIL International. MIT Licensed", + "title": "Keyboard Processor State object introspection", + "description": "Internal data from a Keyboard Processor State object, sufficient for debugging and diagnostics", + "type": "object", + + "definitions": { + "options": { + "type": "object", + "properties": { + "scope": { "enum": ["unknown", "environment", "keyboard"] }, + "options": { + "type": "object", + "default": {} + } + }, + "required": ["scope", "options"] + }, + "rule": { + "type": "object" + }, + "keyboard" : { + "type": "object", + "properties": { + "id": { "type": "string" }, + "version": { "type": "string" }, + "folder": { "type": "string"}, + "options": { "$ref": "#definitions/options" }, + "rules": { + "type":"array", + "items": { "$ref": "#/definitions/rule" } + } + }, + "required": ["id", "version", "folder", "options", "rules"] + }, + "context": { + "type":"array", + "items": {"$ref": "#/definitions/context_item"}, + "default": [] + }, + "context_item": { + "oneOf": [ + {"type": "string", "minLength": 1, "maxLength": 4}, + {"type": "number"} + ] + } + }, + "properties": { + "$schema": { "const": "keyman/core/docs/introspection.schema" }, + "keyboard": { "$ref": "#/definitions/keyboard" }, + "options": { + "type": "object", + "properties": { + "enviroment": { "$ref": "#/definitions/options" }, + "dynamic": { "$ref": "#/definitions/options" } + }, + "required": [ "enviroment","dynamic"] + }, + "context": { "$ref": "#/definitions/context" } + } +} +``` \ No newline at end of file diff --git a/core/docs/api/keyboards.md b/core/docs/api/keyboards.md new file mode 100644 index 00000000000..3439e20722b --- /dev/null +++ b/core/docs/api/keyboards.md @@ -0,0 +1,665 @@ +--- +title: Keyboards - Keyman Core API +--- + +A keyboard is a set of rules and transforms in a Processor specific format for +transforming key events into action items. The keyboard is parsed and loaded by +the processsor and made available in an immutable fashion for use with any number +of state objects. + +------------------------------------------------------------------------------- + +# km_core_keyboard_attrs struct {#km_core_keyboard_attrs} + +## Description + +Provides read-only information about a keyboard. + +## Specification +```c +typedef struct { + km_core_cp const * version_string; + km_core_cp const * id; + km_core_path_name folder_path; + km_core_option_item const * default_options; +} km_core_keyboard_attrs; + +``` +## Members + +`version_string` +: Processor specific version string. + +`id` +: Keyman keyboard ID string. + +`folder_path` +: Path to the unpacked folder containing the keyboard and associated resources. + +`default_options` +: Set of default values for any options included in the keyboard. + +------------------------------------------------------------------------------- + +# km_core_keyboard_key struct {#km_core_keyboard_key} + +## Description + +Describes a single key and modifier combination that a keyboard handles, for +use by the Platform layer. This is used when the Platform layer must know in +advance which keys are used by a given keyboard. + +## Specification + +```c +typedef struct { + km_core_virtual_key key; + uint32_t modifier_flag; +} km_core_keyboard_key; + +#define KM_CORE_KEYBOARD_KEY_LIST_END { 0, 0 } + +``` + +## Members + +`key` +: A virtual key. + +`modifier_flag` +: A [km_core_modifier_state] bitmask. + +------------------------------------------------------------------------------- + +# km_core_keyboard_imx struct {#km_core_keyboard_imx} + +## Description + +Describes a single Input Method eXtension library and entry point. + +## Specification + +```c +typedef struct { + km_core_cp const * library_name; + km_core_cp const * function_name; + uint32_t imx_id; +} km_core_keyboard_imx; + +#define KM_CORE_KEYBOARD_IMX_END { 0, 0, 0 } + +``` +## Members + +`library_name` +: The fully-qualified path and filename of the dynamically loaded library file. + +`function_name` +: The entry point for the IMX. + +`imx_id` +: unique identifier used to call this function + +------------------------------------------------------------------------------- + +# km_core_keyboard_load_from_blob() {#km_core_keyboard_load_from_blob} + +## Description + +Parse and load a keyboard from the supplied blob and return a pointer to the +loaded keyboard in the out parameter. + +## Specification + +```c +KMN_API +km_core_status +km_core_keyboard_load_from_blob(const km_core_path_name kb_name, + const void* blob, + const size_t blob_size, + km_core_keyboard** keyboard); + +``` + +## Parameters + +`kb_name` +: a string with the name of the keyboard. + +`blob` +: a byte array containing the content of a KMX/KMX+ file. + +`blob_size` +: a size_t variable with the size of the blob in bytes. + +`keyboard` +: A pointer to result variable: A pointer to the opaque keyboard + object returned by the Processor. This memory must be freed with a + call to [km_core_keyboard_dispose]. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_NO_MEM` +: In the event an internal memory allocation fails. + +`KM_CORE_STATUS_IO_ERROR` +: In the event the keyboard file is unparseable for any reason + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: In the event the file doesn't exist or is inaccesible or `keyboard` is null. + +`KM_CORE_STATUS_OS_ERROR` +: Bit 31 (high bit) set, bits 0-30 are an OS-specific error code. + +------------------------------------------------------------------------------- + +# km_core_keyboard_dispose() {#km_core_keyboard_dispose} + +## Description + +Free the allocated memory belonging to an opaque keyboard object previously +returned by [km_core_keyboard_load_from_blob]. + +## Specification + +```c +KMN_API +void +km_core_keyboard_dispose(km_core_keyboard *keyboard); + +``` +## Parameters +`keyboard` +: A pointer to the opaque keyboard object to be disposed of. + +------------------------------------------------------------------------------- + +# km_core_keyboard_get_attrs() {#km_core_keyboard_get_attrs} + +## Description + +Returns the const internal attributes of the keyboard. This structure is valid +for the lifetime of the opaque keyboard object. Do not modify the returned data. + +## Specification + +```c +KMN_API +km_core_status +km_core_keyboard_get_attrs(km_core_keyboard const *keyboard, + km_core_keyboard_attrs const **out); + +``` +## Parameters + +`keyboard` +: A pointer to the opaque keyboard object to be queried. + +`out` +: A pointer to the result: A pointer to a [km_core_keyboard_attrs] structure. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: If non-optional parameters are null. + +------------------------------------------------------------------------------- + +# km_core_keyboard_get_key_list() {#km_core_keyboard_get_key_list} + +## Description + +Returns the unordered full set of modifier+virtual keys that are handled by the +keyboard. The matching dispose call needs to be called to free the memory. + +## Specification + +```c +KMN_API +km_core_status +km_core_keyboard_get_key_list(km_core_keyboard const *keyboard, + km_core_keyboard_key **out); + +``` +## Parameters + +`keyboard` +: A pointer to the opaque keyboard object to be queried. + +`out` +: A pointer to an array of [km_core_keyboard_key] structures, + terminated by `KM_CORE_KEYBOARD_KEY_LIST_END`. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: If non-optional parameters are null. + +------------------------------------------------------------------------------- + +# km_core_keyboard_key_list_dispose() {#km_core_keyboard_key_list_dispose} + +## Description + +Free the allocated memory belonging to a keyboard key list previously +returned by [km_core_keyboard_get_key_list]. + +## Specification + +```c +KMN_API +void km_core_keyboard_key_list_dispose(km_core_keyboard_key *key_list); + +``` +## Parameters + +`key_list` +: A pointer to the keyboard key list to be disposed of. + +------------------------------------------------------------------------------- + +# km_core_keyboard_get_imx_list + +## Description + +Returns the list of IMX libraries and function names that are referenced by +the keyboard. The matching dispose call needs to be called to free the memory. + +## Specification + +```c +KMN_API +km_core_status km_core_keyboard_get_imx_list(km_core_keyboard const *keyboard, km_core_keyboard_imx **imx_list); + +``` +## Parameters + +`keyboard` +: A pointer to the keyboard + +`imx_list` +: A pointer to a variable that will contain a pointer to the IMX list. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: If non-optional parameters are null. + +------------------------------------------------------------------------------- + +# km_core_keyboard_imx_list_dispose() {#km_core_keyboard_imx_list_dispose} + +## Description + +Disposes of the IMX list. + +## Specification + +```c +KMN_API +void km_core_keyboard_imx_list_dispose(km_core_keyboard_imx *imx_list); + +``` +## Parameters + +`imx_list` +: A pointer to the IMX list. + +------------------------------------------------------------------------------- + +# km_core_state_imx_register_callback() {#km_core_state_imx_register_callback} + +## Description + +Register the IMX callback endpoint for the client. + +## Specification + +```c +KMN_API +void km_core_state_imx_register_callback(km_core_state *state, km_core_keyboard_imx_platform imx_callback, void *callback_object); + +``` +## Parameters + +`state` +: A pointer to the opaque state object + +`imx_callback` +: pointer to a function that implements the IMX callback + +`callback_object` +: TODO + +------------------------------------------------------------------------------- + +# km_core_state_imx_deregister_callback() {#km_core_state_imx_deregister_callback} + +## Description + +De-register IMX callback endpoint for the client. + +## Specification + +```c +KMN_API +void km_core_state_imx_deregister_callback(km_core_state *state); + +``` +## Parameters + +`state` +: A pointer to the opaque state object + +------------------------------------------------------------------------------- + +# km_core_state_create() {#km_core_state_create} + +## Description + +Create a keyboard processor state object, maintaining state for the keyboard in +the environment passed. + +## Specification + +```c +KMN_API +km_core_status +km_core_state_create(km_core_keyboard *keyboard, + km_core_option_item const *env, + km_core_state **out); + +``` +## Parameters + +`keyboard` +: A pointer to the opaque keyboard object this object will hold state for. + +`env` +: The array of [km_core_option_item] key/value pairs used to initialise the + environment, terminated by `KM_CORE_OPTIONS_END`. + +`out` +: A pointer to result variable: A pointer to the opaque state object + returned by the Processor, initalised to maintain state for `keyboard`. + This must be disposed of by a call to [km_core_state_dispose]. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_NO_MEM` +: In the event memory is unavailable to allocate a state object. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: In the event the `keyboard` or `out` pointer are null. + +------------------------------------------------------------------------------- + +# km_core_state_clone() {#km_core_state_clone} + +## Description + +Clone an existing opaque state object. + +## Specification + +```c +KMN_API +km_core_status +km_core_state_clone(km_core_state const *state, + km_core_state **out); + +``` +## Parameters + +`state` +: A pointer to the opaque statea object to be cloned. + +`out` +: A pointer to result variable: A pointer to the opaque state object + returned by the Processor, cloned from the existing object `state`. This + must be disposed of by a call to [km_core_state_dispose]. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_NO_MEM` +: In the event memory is unavailable to allocate a state object. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: In the event the `state` or `out` pointer are null. + +------------------------------------------------------------------------------- + +# km_core_state_dispose() {#km_core_state_dispose} + +## Description + +Free the allocated resources belonging to a [km_core_state] object previously +returned by [km_core_state_create] or [km_core_state_clone]. After this all +pointers previously returned by any [km_core_state] family of calls will become +invalid. + +## Specification + +```c +KMN_API +void +km_core_state_dispose(km_core_state *state); + +``` +## Parameters + +`state` +: A pointer to the opaque state object to be disposed. + +------------------------------------------------------------------------------- + +# km_core_debug_context_type enum {#km_core_debug_context_type} + +As of version 17, the cached context is an internal property of the +state, not exposed to the consumer of the API -- apart from the +Keyman Developer Keyboard Debugger. However, for other debug +purposes, it is helpful to be able to examine the cached context, so +a debug-formatted version of the context is made available with +[km_core_state_context_debug]. This is not intended to be parsed for +reading the context for other purposes, and the format may change. + +The three context types are: cached, intermediate, and app. + +## Specification + +```c +typedef enum { + KM_CORE_DEBUG_CONTEXT_CACHED = 0, + KM_CORE_DEBUG_CONTEXT_INTERMEDIATE = 1, + KM_CORE_DEBUG_CONTEXT_APP = 2 +} km_core_debug_context_type; + +``` +## Values + +`KM_CORE_DEBUG_CONTEXT_CACHED` +: the internal context used by Core, which may be normalized + and may contain markers. This is set via + [km_core_state_context_set_if_needed], and will be modified + during keystroke event processing. + +`KM_CORE_DEBUG_CONTEXT_INTERMEDIATE` +: internal context used by IMX, only valid during + keystroke event processing. + +`KM_CORE_DEBUG_CONTEXT_APP` +: an exact copy of the current context passed in to + [km_core_state_context_set_if_needed], which is used to verify + the precise text manipulations required when emitted changes. + This input context is in "NFU" -- normalization form unknown, + and may be mixed normalization so may require fixups when + it is manipulated by keyboard processors that support + normalization, such as the LDML keyboard processor. + +------------------------------------------------------------------------------- + +# km_core_state_context_debug() {#km_core_state_context_debug} + +## Description + +Returns a debug formatted string of the context from the state. + +## Specification + +```c +KMN_API +km_core_cp * +km_core_state_context_debug(km_core_state *state, km_core_debug_context_type context_type); + +``` +## Parameters + +`state` +: A pointer to the opaque state object to be queried. + +`context_type` +: The type of context to retrieve from the state. + +## Returns + +A pointer to a [km_core_cp] UTF-16 string. Must be disposed of by a call +to [km_core_cp_dispose]. + +------------------------------------------------------------------------------- + +# km_core_cp_dispose() {#km_core_cp_dispose} + +## Description + +Free the allocated memory belonging to a [km_core_cp] array previously +returned by [km_core_state_context_debug]. May be `nullptr`. + +## Specification + +```c +KMN_API +void +km_core_cp_dispose(km_core_cp *cp); + +``` +## Parameters + +`cp` +: A pointer to the start of the [km_core_cp] array to be disposed of. + +------------------------------------------------------------------------------- + +# km_core_state_to_json() {#km_core_state_to_json} + +## Description + +Export the internal state of a [km_core_state] object to a JSON format document +and place it in the supplied buffer, reporting how much space was used. If null +is passed as the buffer the number of bytes required is returned. If there is +insufficent space to hold the document, the contents of the buffer is undefined. +The encoding of the returned data is UTF-8. + +__WARNING__: The structure and format of the JSON document while independently +versioned is not part of this API and is intended solely for use in diagnostics +or by development and debugging tools which are aware of processor +implementation details. + +## Specification + +```c +KMN_API +km_core_status +km_core_state_to_json(km_core_state const *state, + char *buf, + size_t *space); + +``` +## Parameters + +`state` +: An pointer to an opaque state object. + +`buf` +: A pointer to the buffer to place the C string containing the JSON + document into. May be null. + +`space` +: A pointer to a size_t variable. This variable must contain the + number of bytes available in the buffer pointed to by `buf`, unless `buf` is + null. On return it will hold how many bytes were used. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_NO_MEM` +: In the event an internal memory allocation fails. + +------------------------------------------------------------------------------- + + +[km_core_cp]: background#km_core_cp "km_core_cp type" +[km_core_usv]: background#km_core_usv "km_core_usv type" +[km_core_virtual_key]: background#km_core_virtual_key "km_core_virtual_key type" +[km_core_status]: background#km_core_status "km_core_status type" +[km_core_modifier_state]: background#km_core_modifier_state "km_core_modifier_state type" +[km_core_keyboard]: background#km_core_keyboard "km_core_keyboard struct" +[km_core_state]: background#km_core_state "km_core_state struct" +[km_core_options]: background#km_core_options "km_core_options struct" +[km_core_status_codes]: background#km_core_status_codes "km_core_status_codes enum" +[km_core_attr]: background#km_core_attr "km_core_attr struct" +[km_core_tech_value]: background#km_core_tech_value "km_core_tech_value enum" +[km_core_get_engine_attrs]: background#km_core_get_engine_attrs "km_core_get_engine_attrs function" +[km_core_bool]: background#km_core_bool "km_core_bool enum" +[km_core_caps_state]: state#km_core_caps_state "km_core_caps_state enum" +[km_core_actions]: state#km_core_actions "km_core_actions struct" +[km_core_state_get_actions]: state#km_core_state_get_actions "km_core_state_get_actions function" +[km_core_context_status]: state#km_core_context_status "km_core_context_status enum" +[km_core_state_context_set_if_needed]: state#km_core_state_context_set_if_needed "km_core_state_context_set_if_needed function" +[km_core_state_context_clear]: state#km_core_state_context_clear "km_core_state_context_clear function" +[km_core_option_scope]: options#km_core_option_scope "km_core_option_scope enum" +[km_core_option_item]: options#km_core_option_item "km_core_option_item struct" +[km_core_options_list_size]: options#km_core_options_list_size "km_core_options_list_size function" +[km_core_state_options_update]: options#km_core_state_options_update "km_core_state_options_update function" +[km_core_state_options_to_json]: options#km_core_state_options_to_json "km_core_state_options_to_json function" +[km_core_keyboard_attrs]: keyboards#km_core_keyboard_attrs "km_core_keyboard_attrs struct" +[km_core_keyboard_key]: keyboards#km_core_keyboard_key "km_core_keyboard_key struct" +[km_core_keyboard_imx]: keyboards#km_core_keyboard_imx "km_core_keyboard_imx struct" +[km_core_keyboard_load_from_blob]: keyboards#km_core_keyboard_load_from_blob "km_core_keyboard_load_from_blob function" +[km_core_keyboard_dispose]: keyboards#km_core_keyboard_dispose "km_core_keyboard_dispose function" +[km_core_keyboard_get_attrs]: keyboards#km_core_keyboard_get_attrs "km_core_keyboard_get_attrs function" +[km_core_keyboard_get_key_list]: keyboards#km_core_keyboard_get_key_list "km_core_keyboard_get_key_list function" +[km_core_keyboard_key_list_dispose]: keyboards#km_core_keyboard_key_list_dispose "km_core_keyboard_key_list_dispose function" +[km_core_keyboard_imx_list_dispose]: keyboards#km_core_keyboard_imx_list_dispose "km_core_keyboard_imx_list_dispose function" +[km_core_state_imx_register_callback]: keyboards#km_core_state_imx_register_callback "km_core_state_imx_register_callback function" +[km_core_state_imx_deregister_callback]: keyboards#km_core_state_imx_deregister_callback "km_core_state_imx_deregister_callback function" +[km_core_state_create]: keyboards#km_core_state_create "km_core_state_create function" +[km_core_state_clone]: keyboards#km_core_state_clone "km_core_state_clone function" +[km_core_state_dispose]: keyboards#km_core_state_dispose "km_core_state_dispose function" +[km_core_debug_context_type]: keyboards#km_core_debug_context_type "km_core_debug_context_type enum" +[km_core_state_context_debug]: keyboards#km_core_state_context_debug "km_core_state_context_debug function" +[km_core_cp_dispose]: keyboards#km_core_cp_dispose "km_core_cp_dispose function" +[km_core_state_to_json]: keyboards#km_core_state_to_json "km_core_state_to_json function" +[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" +[km_core_process_event]: processor#km_core_process_event "km_core_process_event function" +[km_core_event]: processor#km_core_event "km_core_event function" +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file diff --git a/core/docs/api/options.md b/core/docs/api/options.md new file mode 100644 index 00000000000..41d5fe28c9a --- /dev/null +++ b/core/docs/api/options.md @@ -0,0 +1,284 @@ +--- +title: Options - Keyman Core API +--- + +A state’s default options are set from the keyboard at creation time and the +environment. The Platform layer is then is expected to apply any persisted +options it is maintaining. Options are passed into and out of API functions as +simple C arrays of [km_core_option_item] terminated with a `KM_CORE_OPTIONS_END` +sentinel value. A state's options are exposed and manipulatable via the +[km_core_options] API. All option values are of type C string. + +During processing when the Platform layer finds a PERSIST action type it should +store the updated option in the appropriate place, based on its scope. +For RESET the processor will apply the pristine value from the original scope, +the Platform layer should update that only if it manages a previously persisted +value. + +------------------------------------------------------------------------------- + +# km_core_option_scope enum {#km_core_option_scope} + +## Description + +## Specification + +```c +enum km_core_option_scope { + KM_CORE_OPT_UNKNOWN = 0, + KM_CORE_OPT_KEYBOARD = 1, + KM_CORE_OPT_ENVIRONMENT = 2, + KM_CORE_OPT_MAX_SCOPES +}; + +``` +## Values + +`KM_CORE_OPT_UNKNOWN` +: An unknown option type. Reserved. + +`KM_CORE_OPT_KEYBOARD` +: An option that is defined for the currently active keyboard; + not all processors support this type of option. These options + are specific to the active keyboard. + +`KM_CORE_OPT_ENVIRONMENT` +: Properties of the current environment, often but not necessarily + always read-only. + +------------------------------------------------------------------------------- + +# km_core_option_item struct {#km_core_option_item} + +## Description + +Defines a single option to be passed into the Keyman Core from the +Platform layer. + +## Specification +```c +struct km_core_option_item { + km_core_cp const * key; + km_core_cp const * value; + uint8_t scope; +}; + +#define KM_CORE_OPTIONS_END { 0, 0, 0 } +``` +## Members + +`key` +: Null-terminated string key for the option + +`value` +: Null-terminated string value for the option + +`scope` +: Scope which an option belongs to, from [km_core_option_scope]. + +------------------------------------------------------------------------------- + +# km_core_options_list_size() {#km_core_options_list_size} + +## Description +Return the length of a terminated [km_core_option_item] array (options +list). + +## Specification +```c +KMN_API +size_t +km_core_options_list_size(km_core_option_item const *opts); + +``` +## Parameters + +`opts` +: A pointer to a `KM_CORE_OPTIONS_END` terminated array of + [km_core_option_item] values. + +## Returns + +The number of items in the list, not including terminating item, +or 0 if `opts` is null. + +------------------------------------------------------------------------------- + +# km_core_state_option_lookup + +## Description + +Lookup an option based on its key, in an options list. + +## Specification +```c +KMN_API +km_core_status +km_core_state_option_lookup(km_core_state const *state, + uint8_t scope, + km_core_cp const *key, + km_core_cp const **value); + +``` +## Parameters + +`state` +: An opaque pointer to a state object. + +`scope` +: Which key-value store to interrogate. + +`key` +: A UTF-16 string that matches the key in the target [km_core_option_item]. + +`value` +: A pointer to the result variable: A pointer to a UTF-16 string value owned + by the state or keyboard object at the time of the call. This pointer is + only valid *until* the next call to any function on this API and should be + used immediately. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: If non-optional parameters are null, or if the scope is invalid. + +`KM_CORE_STATUS_KEY_ERROR` +: The key cannot be found. + +------------------------------------------------------------------------------- + +# km_core_state_options_update() {#km_core_state_options_update} + +## Description + +Adds or updates one or more options from a list of [km_core_option_item]s. + +## Specification +``` */ +KMN_API +km_core_status +km_core_state_options_update(km_core_state *state, + km_core_option_item const *new_opts); + +``` +## Parameters +`state` +: An opaque pointer to a state object. + +`new_opts` +: An array of [km_core_option_item] objects to update or add. Must be + terminated with `KM_CORE_OPTIONS_END`. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: If non-optional parameters are null. + +`KM_CORE_STATUS_NO_MEM` +: In the event an internal memory allocation fails. + +`KM_CORE_STATUS_KEY_ERROR` +: The key cannot be found. + +------------------------------------------------------------------------------- + +# km_core_state_options_to_json() {#km_core_state_options_to_json} + +## Description + +Export the contents of a [km_core_options] array to a JSON formatted document and +place it in the supplied buffer, reporting how much space was used. If null is +passed as the buffer the number of bytes required is returned in `space`. If +there is insufficent space to hold the document the contents of the buffer is +undefined. The returned buffer uses UTF-8 encoding. + +## Specification + +```c +KMN_API +km_core_status +km_core_state_options_to_json(km_core_state const *state, + char *buf, + size_t *space); + +``` +## Parameters + +`state` +: An opaque pointer to a state object. + +`buf` +: A pointer to the buffer to place the C string containing the JSON + document into, can be null. + +`space` +: A pointer to a size_t variable. This variable must contain the + number of bytes available in the buffer pointed to by `buf`, unless `buf` is + null. On return it will hold how many bytes were used. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: If non-optional parameters are null. + +`KM_CORE_STATUS_NO_MEM` +: In the event an internal memory allocation fails. + +------------------------------------------------------------------------------- + + +[km_core_cp]: background#km_core_cp "km_core_cp type" +[km_core_usv]: background#km_core_usv "km_core_usv type" +[km_core_virtual_key]: background#km_core_virtual_key "km_core_virtual_key type" +[km_core_status]: background#km_core_status "km_core_status type" +[km_core_modifier_state]: background#km_core_modifier_state "km_core_modifier_state type" +[km_core_keyboard]: background#km_core_keyboard "km_core_keyboard struct" +[km_core_state]: background#km_core_state "km_core_state struct" +[km_core_options]: background#km_core_options "km_core_options struct" +[km_core_status_codes]: background#km_core_status_codes "km_core_status_codes enum" +[km_core_attr]: background#km_core_attr "km_core_attr struct" +[km_core_tech_value]: background#km_core_tech_value "km_core_tech_value enum" +[km_core_get_engine_attrs]: background#km_core_get_engine_attrs "km_core_get_engine_attrs function" +[km_core_bool]: background#km_core_bool "km_core_bool enum" +[km_core_caps_state]: state#km_core_caps_state "km_core_caps_state enum" +[km_core_actions]: state#km_core_actions "km_core_actions struct" +[km_core_state_get_actions]: state#km_core_state_get_actions "km_core_state_get_actions function" +[km_core_context_status]: state#km_core_context_status "km_core_context_status enum" +[km_core_state_context_set_if_needed]: state#km_core_state_context_set_if_needed "km_core_state_context_set_if_needed function" +[km_core_state_context_clear]: state#km_core_state_context_clear "km_core_state_context_clear function" +[km_core_option_scope]: options#km_core_option_scope "km_core_option_scope enum" +[km_core_option_item]: options#km_core_option_item "km_core_option_item struct" +[km_core_options_list_size]: options#km_core_options_list_size "km_core_options_list_size function" +[km_core_state_options_update]: options#km_core_state_options_update "km_core_state_options_update function" +[km_core_state_options_to_json]: options#km_core_state_options_to_json "km_core_state_options_to_json function" +[km_core_keyboard_attrs]: keyboards#km_core_keyboard_attrs "km_core_keyboard_attrs struct" +[km_core_keyboard_key]: keyboards#km_core_keyboard_key "km_core_keyboard_key struct" +[km_core_keyboard_imx]: keyboards#km_core_keyboard_imx "km_core_keyboard_imx struct" +[km_core_keyboard_load_from_blob]: keyboards#km_core_keyboard_load_from_blob "km_core_keyboard_load_from_blob function" +[km_core_keyboard_dispose]: keyboards#km_core_keyboard_dispose "km_core_keyboard_dispose function" +[km_core_keyboard_get_attrs]: keyboards#km_core_keyboard_get_attrs "km_core_keyboard_get_attrs function" +[km_core_keyboard_get_key_list]: keyboards#km_core_keyboard_get_key_list "km_core_keyboard_get_key_list function" +[km_core_keyboard_key_list_dispose]: keyboards#km_core_keyboard_key_list_dispose "km_core_keyboard_key_list_dispose function" +[km_core_keyboard_imx_list_dispose]: keyboards#km_core_keyboard_imx_list_dispose "km_core_keyboard_imx_list_dispose function" +[km_core_state_imx_register_callback]: keyboards#km_core_state_imx_register_callback "km_core_state_imx_register_callback function" +[km_core_state_imx_deregister_callback]: keyboards#km_core_state_imx_deregister_callback "km_core_state_imx_deregister_callback function" +[km_core_state_create]: keyboards#km_core_state_create "km_core_state_create function" +[km_core_state_clone]: keyboards#km_core_state_clone "km_core_state_clone function" +[km_core_state_dispose]: keyboards#km_core_state_dispose "km_core_state_dispose function" +[km_core_debug_context_type]: keyboards#km_core_debug_context_type "km_core_debug_context_type enum" +[km_core_state_context_debug]: keyboards#km_core_state_context_debug "km_core_state_context_debug function" +[km_core_cp_dispose]: keyboards#km_core_cp_dispose "km_core_cp_dispose function" +[km_core_state_to_json]: keyboards#km_core_state_to_json "km_core_state_to_json function" +[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" +[km_core_process_event]: processor#km_core_process_event "km_core_process_event function" +[km_core_event]: processor#km_core_event "km_core_event function" +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file diff --git a/core/docs/api/processor.md b/core/docs/api/processor.md new file mode 100644 index 00000000000..c72d743bb9c --- /dev/null +++ b/core/docs/api/processor.md @@ -0,0 +1,198 @@ +--- +title: Processor - Keyman Core API +--- + +# km_core_event_flags enum {#km_core_event_flags} + +## Description + +Bit flags to be used with the `event_flags` parameter of [km_core_process_event] + +## Specification + +```c +enum km_core_event_flags { + KM_CORE_EVENT_FLAG_DEFAULT = 0, + KM_CORE_EVENT_FLAG_TOUCH = 1, +}; + +``` +## Values + +`KM_CORE_EVENT_FLAG_DEFAULT` +: default value: hardware + +`KM_CORE_EVENT_FLAG_TOUCH` +: set if the event is touch, otherwise hardware + +------------------------------------------------------------------------------- + +# km_core_process_event() {#km_core_process_event} + +## Description + +Run the keyboard on an opaque state object with the provided virtual key and modifer +key state. Updates the state object as appropriate and fills out its internal set +of actions, which can be retrieved with [km_core_state_get_actions]. + +The state's actions will be cleared at the start of this call; options and context in +the state may also be modified. + +## Specification + +```c +KMN_API +km_core_status +km_core_process_event(km_core_state *state, + km_core_virtual_key vk, + uint16_t modifier_state, + uint8_t is_key_down, + uint16_t event_flags); + +``` +## Parameters + +`state` +: A pointer to the opaque state object. + +`vk` +: A virtual key to be processed. + +`modifier_state` +: The combinations of modifier keys set at the time key `vk` was pressed, bitmask + from the [km_core_modifier_state] enum. + +`event_flags` +: Event level flags, see [km_core_event_flags] + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_NO_MEM` +: In the event memory is unavailable to allocate internal buffers. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: In the event the `state` pointer is null or an invalid virtual key or modifier + state is passed. + +------------------------------------------------------------------------------- + +# km_core_event() {#km_core_event} + +## Description + +Tell the keyboard processor that an external event has occurred, such as a keyboard +being activated through the language switching UI. + +The keyboard processor may generate actions which should be processed by the +consumer of the API. + +The actions will be cleared at the start of this call; options and context in +the state may also be modified. + +## Specification + +```c +KMN_API +km_core_status +km_core_event( + km_core_state *state, + uint32_t event, + void* data +); + +``` +## Parameters + +`state` +: A pointer to the opaque state object. + +`event` +: The event to be processed, from [km_core_event_code] enumeration + +`data` +: Additional event-specific data. Currently unused, must be nullptr. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_NO_MEM` +: In the event memory is unavailable to allocate internal buffers. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: In the event the `state` pointer is null or an invalid event or data is passed. + +------------------------------------------------------------------------------- + +# km_core_event_code enum {#km_core_event_code} + +## Description + +Possible events to be passed into Keyman Core from the Platform layer. + +## Specification + +```c +enum km_core_event_code { + KM_CORE_EVENT_KEYBOARD_ACTIVATED = 1, + //future: KM_CORE_EVENT_KEYBOARD_DEACTIVATED = 2, +}; + +``` +## Values + +`KM_CORE_EVENT_KEYBOARD_ACTIVATED` +: A keyboard has been activated by the user. The processor may use this + event, for example, to switch caps lock state or provide other UX. + + +[km_core_cp]: background#km_core_cp "km_core_cp type" +[km_core_usv]: background#km_core_usv "km_core_usv type" +[km_core_virtual_key]: background#km_core_virtual_key "km_core_virtual_key type" +[km_core_status]: background#km_core_status "km_core_status type" +[km_core_modifier_state]: background#km_core_modifier_state "km_core_modifier_state type" +[km_core_keyboard]: background#km_core_keyboard "km_core_keyboard struct" +[km_core_state]: background#km_core_state "km_core_state struct" +[km_core_options]: background#km_core_options "km_core_options struct" +[km_core_status_codes]: background#km_core_status_codes "km_core_status_codes enum" +[km_core_attr]: background#km_core_attr "km_core_attr struct" +[km_core_tech_value]: background#km_core_tech_value "km_core_tech_value enum" +[km_core_get_engine_attrs]: background#km_core_get_engine_attrs "km_core_get_engine_attrs function" +[km_core_bool]: background#km_core_bool "km_core_bool enum" +[km_core_caps_state]: state#km_core_caps_state "km_core_caps_state enum" +[km_core_actions]: state#km_core_actions "km_core_actions struct" +[km_core_state_get_actions]: state#km_core_state_get_actions "km_core_state_get_actions function" +[km_core_context_status]: state#km_core_context_status "km_core_context_status enum" +[km_core_state_context_set_if_needed]: state#km_core_state_context_set_if_needed "km_core_state_context_set_if_needed function" +[km_core_state_context_clear]: state#km_core_state_context_clear "km_core_state_context_clear function" +[km_core_option_scope]: options#km_core_option_scope "km_core_option_scope enum" +[km_core_option_item]: options#km_core_option_item "km_core_option_item struct" +[km_core_options_list_size]: options#km_core_options_list_size "km_core_options_list_size function" +[km_core_state_options_update]: options#km_core_state_options_update "km_core_state_options_update function" +[km_core_state_options_to_json]: options#km_core_state_options_to_json "km_core_state_options_to_json function" +[km_core_keyboard_attrs]: keyboards#km_core_keyboard_attrs "km_core_keyboard_attrs struct" +[km_core_keyboard_key]: keyboards#km_core_keyboard_key "km_core_keyboard_key struct" +[km_core_keyboard_imx]: keyboards#km_core_keyboard_imx "km_core_keyboard_imx struct" +[km_core_keyboard_load_from_blob]: keyboards#km_core_keyboard_load_from_blob "km_core_keyboard_load_from_blob function" +[km_core_keyboard_dispose]: keyboards#km_core_keyboard_dispose "km_core_keyboard_dispose function" +[km_core_keyboard_get_attrs]: keyboards#km_core_keyboard_get_attrs "km_core_keyboard_get_attrs function" +[km_core_keyboard_get_key_list]: keyboards#km_core_keyboard_get_key_list "km_core_keyboard_get_key_list function" +[km_core_keyboard_key_list_dispose]: keyboards#km_core_keyboard_key_list_dispose "km_core_keyboard_key_list_dispose function" +[km_core_keyboard_imx_list_dispose]: keyboards#km_core_keyboard_imx_list_dispose "km_core_keyboard_imx_list_dispose function" +[km_core_state_imx_register_callback]: keyboards#km_core_state_imx_register_callback "km_core_state_imx_register_callback function" +[km_core_state_imx_deregister_callback]: keyboards#km_core_state_imx_deregister_callback "km_core_state_imx_deregister_callback function" +[km_core_state_create]: keyboards#km_core_state_create "km_core_state_create function" +[km_core_state_clone]: keyboards#km_core_state_clone "km_core_state_clone function" +[km_core_state_dispose]: keyboards#km_core_state_dispose "km_core_state_dispose function" +[km_core_debug_context_type]: keyboards#km_core_debug_context_type "km_core_debug_context_type enum" +[km_core_state_context_debug]: keyboards#km_core_state_context_debug "km_core_state_context_debug function" +[km_core_cp_dispose]: keyboards#km_core_cp_dispose "km_core_cp_dispose function" +[km_core_state_to_json]: keyboards#km_core_state_to_json "km_core_state_to_json function" +[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" +[km_core_process_event]: processor#km_core_process_event "km_core_process_event function" +[km_core_event]: processor#km_core_event "km_core_event function" +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file diff --git a/core/docs/api/state.md b/core/docs/api/state.md new file mode 100644 index 00000000000..0292d9f8a59 --- /dev/null +++ b/core/docs/api/state.md @@ -0,0 +1,285 @@ +--- +title: State and Actions - Keyman Core API +--- + +A State object maintains all per keyboard related state including context +and dynamic options ("option stores" in kmn format). + +When a keystroke is processed by Keyman Core, Core provides back a set of actions +for the Platform layer to emit to the Client application. These actions are +owned by the state object. + +------------------------------------------------------------------------------- + +# km_core_caps_state enum {#km_core_caps_state} + +## Description + +Describes the + +## Specification +```c +typedef enum { KM_CORE_CAPS_UNCHANGED = -1, KM_CORE_CAPS_OFF = 0, KM_CORE_CAPS_ON = 1 } km_core_caps_state; + +``` +## Values + +`KM_CORE_CAPS_UNCHANGED` +: Caps lock state has not changed in this event. + +`KM_CORE_CAPS_OFF` +: As a result of processing this event, the Platform layer should switch off + Caps Lock on the hardware keyboard. + +`KM_CORE_CAPS_ON` +: As a result of processing this event, the Platform layer should switch on + Caps Lock on the hardware keyboard. + +------------------------------------------------------------------------------- + +# km_core_actions struct {#km_core_actions} + +## Description + +This structure provides the results of processing a key event to the Platform layer and +should be processed by the Platform layer to issue commands to the os text +services framework to transform the text store in the Client Application, among +other actions. + +This API replaces the Action items APIs, which are now deprecated and will be +removed in the future. + +## Specification +```c +typedef struct { + unsigned int code_points_to_delete; + const km_core_usv* output; + km_core_option_item * persist_options; + km_core_bool do_alert; + km_core_bool emit_keystroke; + km_core_caps_state new_caps_lock_state; + const km_core_usv* deleted_context; +} km_core_actions; + +``` +## Members + +`code_points_to_delete` +: Number of codepoints (not codeunits!) to delete from app context. + +`output` +: Null-term string of characters to insert into document. + +`persist_options` +: List of options to persist, terminated with `KM_CORE_OPTIONS_END`. + +`do_alert` +: Issue a beep, 0 = no, 1 = yes. + +`emit_keystroke` +: Emit the (unmodified) input keystroke to the application, 0 = no, 1 = yes. + +`new_caps_lock_state` +: -1=unchanged, 0=off, 1=on + +`deleted_context` +: Reference copy of actual UTF32 codepoints deleted from end of context + (closest to caret) exactly code_points_to_delete in length (plus null + terminator). Used to determine encoding conversion differences when + deleting; only set when using [km_core_state_get_actions], otherwise nullptr. + +------------------------------------------------------------------------------- + +# km_core_state_get_actions() {#km_core_state_get_actions} + +## Description + +Returns a pointer to an actions object which details all the actions +that the Platform layer must take after a keystroke. The `code_points_to_delete` +action must be performed before the `output` action, but the other +actions may be performed in any order. + +## Specification +```c +KMN_API +km_core_actions const * +km_core_state_get_actions( + km_core_state const *state +); + +``` +## Parameters + +`state` +: An opaque pointer to a state object. + +## Returns + +A pointer to a [km_core_actions] object. This data becomes invalid +when the state object is destroyed, or after a call to +[km_core_process_event]. Do not modify the contents of this data. + +------------------------------------------------------------------------------- + +# km_core_context_status enum {#km_core_context_status} + +## Description + +Return values for [km_core_state_context_set_if_needed]. + +## Specification + +```c +typedef enum { + KM_CORE_CONTEXT_STATUS_UNCHANGED = 0, + KM_CORE_CONTEXT_STATUS_UPDATED = 1, + KM_CORE_CONTEXT_STATUS_CLEARED = 2, + KM_CORE_CONTEXT_STATUS_ERROR = 3, + KM_CORE_CONTEXT_STATUS_INVALID_ARGUMENT = 4, +} km_core_context_status; + +``` + +## Values + +`KM_CORE_CONTEXT_STATUS_UNCHANGED` +: Cached context change was not needed. + +`KM_CORE_CONTEXT_STATUS_UPDATED` +: Cached context was set to application context. + +`KM_CORE_CONTEXT_STATUS_CLEARED` +: Application context was invalid, perhaps had unpaired surrogates, + and so cached context was cleared instead. + +`KM_CORE_CONTEXT_STATUS_ERROR` +: Internal error. + +`KM_CORE_CONTEXT_STATUS_INVALID_ARGUMENT` +: One or more parameters was null. + +------------------------------------------------------------------------------- + +# km_core_state_context_set_if_needed() {#km_core_state_context_set_if_needed} + +## Description + +Sets the internal cached context for the state object, to the passed-in +application context string, if it differs from the codepoints in the +cached context. For the purposes of comparison, (1) cached markers are +ignored, (2) if the cached context is shorter than the application +context, it is considered identical, but (3) if the cached context is +longer, then it is considered different. + +If a difference is found, then the cached context will be set to the +application context, and thus any cached markers will be cleared. + +[km_core_state_context_set_if_needed] and [km_core_state_context_clear] +will replace most uses of the existing Core context APIs. + +## Specification +```c +KMN_API +km_core_context_status +km_core_state_context_set_if_needed( + km_core_state *state, + km_core_cp const *application_context +); + +``` +## Parameters + +`state` +: An opaque pointer to a state object. + +`application_context` +: A pointer to an null-terminated array of utf16 encoded data representing + the current context from the application. + +## Returns + +A value from the [km_core_context_status] enum. + +------------------------------------------------------------------------------- + +# km_core_state_context_clear() {#km_core_state_context_clear} + +## Description + +Clears the internal cached context for the state. This is the same as +`km_core_context_clear(km_core_state_context(&state))`. + +[km_core_state_context_set_if_needed] and [km_core_state_context_clear] +will replace most uses of the existing Core context APIs. + +## Specification +```c +KMN_API +km_core_status +km_core_state_context_clear( + km_core_state *state +); + +``` +## Parameters + +`state`: +An opaque pointer to a state object. + +## Returns + +`KM_CORE_STATUS_OK` +: On success. + +`KM_CORE_STATUS_INVALID_ARGUMENT` +: If any parameters are null. + +------------------------------------------------------------------------------- + + +[km_core_cp]: background#km_core_cp "km_core_cp type" +[km_core_usv]: background#km_core_usv "km_core_usv type" +[km_core_virtual_key]: background#km_core_virtual_key "km_core_virtual_key type" +[km_core_status]: background#km_core_status "km_core_status type" +[km_core_modifier_state]: background#km_core_modifier_state "km_core_modifier_state type" +[km_core_keyboard]: background#km_core_keyboard "km_core_keyboard struct" +[km_core_state]: background#km_core_state "km_core_state struct" +[km_core_options]: background#km_core_options "km_core_options struct" +[km_core_status_codes]: background#km_core_status_codes "km_core_status_codes enum" +[km_core_attr]: background#km_core_attr "km_core_attr struct" +[km_core_tech_value]: background#km_core_tech_value "km_core_tech_value enum" +[km_core_get_engine_attrs]: background#km_core_get_engine_attrs "km_core_get_engine_attrs function" +[km_core_bool]: background#km_core_bool "km_core_bool enum" +[km_core_caps_state]: state#km_core_caps_state "km_core_caps_state enum" +[km_core_actions]: state#km_core_actions "km_core_actions struct" +[km_core_state_get_actions]: state#km_core_state_get_actions "km_core_state_get_actions function" +[km_core_context_status]: state#km_core_context_status "km_core_context_status enum" +[km_core_state_context_set_if_needed]: state#km_core_state_context_set_if_needed "km_core_state_context_set_if_needed function" +[km_core_state_context_clear]: state#km_core_state_context_clear "km_core_state_context_clear function" +[km_core_option_scope]: options#km_core_option_scope "km_core_option_scope enum" +[km_core_option_item]: options#km_core_option_item "km_core_option_item struct" +[km_core_options_list_size]: options#km_core_options_list_size "km_core_options_list_size function" +[km_core_state_options_update]: options#km_core_state_options_update "km_core_state_options_update function" +[km_core_state_options_to_json]: options#km_core_state_options_to_json "km_core_state_options_to_json function" +[km_core_keyboard_attrs]: keyboards#km_core_keyboard_attrs "km_core_keyboard_attrs struct" +[km_core_keyboard_key]: keyboards#km_core_keyboard_key "km_core_keyboard_key struct" +[km_core_keyboard_imx]: keyboards#km_core_keyboard_imx "km_core_keyboard_imx struct" +[km_core_keyboard_load_from_blob]: keyboards#km_core_keyboard_load_from_blob "km_core_keyboard_load_from_blob function" +[km_core_keyboard_dispose]: keyboards#km_core_keyboard_dispose "km_core_keyboard_dispose function" +[km_core_keyboard_get_attrs]: keyboards#km_core_keyboard_get_attrs "km_core_keyboard_get_attrs function" +[km_core_keyboard_get_key_list]: keyboards#km_core_keyboard_get_key_list "km_core_keyboard_get_key_list function" +[km_core_keyboard_key_list_dispose]: keyboards#km_core_keyboard_key_list_dispose "km_core_keyboard_key_list_dispose function" +[km_core_keyboard_imx_list_dispose]: keyboards#km_core_keyboard_imx_list_dispose "km_core_keyboard_imx_list_dispose function" +[km_core_state_imx_register_callback]: keyboards#km_core_state_imx_register_callback "km_core_state_imx_register_callback function" +[km_core_state_imx_deregister_callback]: keyboards#km_core_state_imx_deregister_callback "km_core_state_imx_deregister_callback function" +[km_core_state_create]: keyboards#km_core_state_create "km_core_state_create function" +[km_core_state_clone]: keyboards#km_core_state_clone "km_core_state_clone function" +[km_core_state_dispose]: keyboards#km_core_state_dispose "km_core_state_dispose function" +[km_core_debug_context_type]: keyboards#km_core_debug_context_type "km_core_debug_context_type enum" +[km_core_state_context_debug]: keyboards#km_core_state_context_debug "km_core_state_context_debug function" +[km_core_cp_dispose]: keyboards#km_core_cp_dispose "km_core_cp_dispose function" +[km_core_state_to_json]: keyboards#km_core_state_to_json "km_core_state_to_json function" +[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" +[km_core_process_event]: processor#km_core_process_event "km_core_process_event function" +[km_core_event]: processor#km_core_event "km_core_event function" +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file diff --git a/core/doc/hotdoc.json b/core/docs/internal/hotdoc.json similarity index 100% rename from core/doc/hotdoc.json rename to core/docs/internal/hotdoc.json diff --git a/core/doc/markdown_files/index.md b/core/docs/internal/markdown_files/index.md similarity index 100% rename from core/doc/markdown_files/index.md rename to core/docs/internal/markdown_files/index.md diff --git a/core/doc/meson.build b/core/docs/internal/meson.build similarity index 100% rename from core/doc/meson.build rename to core/docs/internal/meson.build diff --git a/core/doc/sitemap.txt b/core/docs/internal/sitemap.txt similarity index 100% rename from core/doc/sitemap.txt rename to core/docs/internal/sitemap.txt diff --git a/core/doc/introspection.schema b/core/docs/introspection.schema similarity index 96% rename from core/doc/introspection.schema rename to core/docs/introspection.schema index 3b7684e0e9d..ffccc59f466 100644 --- a/core/doc/introspection.schema +++ b/core/docs/introspection.schema @@ -47,7 +47,7 @@ } }, "properties": { - "$schema": { "const": "keyman/core/doc/introspection.schema" }, + "$schema": { "const": "keyman/core/docs/introspection.schema" }, "keyboard": { "$ref": "#/definitions/keyboard" }, "options": { "type": "object", diff --git a/core/include/keyman/keyman_core_api.h b/core/include/keyman/keyman_core_api.h index 328965e8761..7863689296d 100644 --- a/core/include/keyman/keyman_core_api.h +++ b/core/include/keyman/keyman_core_api.h @@ -1007,7 +1007,11 @@ Provides read-only information about a keyboard. typedef struct { km_core_cu const * version_string; km_core_cu const * id; + + // TODO-web-core: Deprecate this field (#12497) + // KMN_DEPRECATED km_core_path_name folder_path; + km_core_option_item const * default_options; } km_core_keyboard_attrs; @@ -1022,7 +1026,7 @@ typedef struct { : Keyman keyboard ID string. `folder_path` -: Path to the unpacked folder containing the keyboard and associated resources. +: Path to the unpacked folder containing the keyboard and associated resources (deprecated). `default_options` : Set of default values for any options included in the keyboard. @@ -1092,29 +1096,35 @@ typedef struct { ------------------------------------------------------------------------------- -# km_core_keyboard_load() +# km_core_keyboard_load_from_blob() ## Description -Parse and load keyboard from the supplied path and a pointer to the loaded keyboard +Parse and load keyboard from the supplied blob and a pointer to the loaded keyboard into the out paramter. ## Specification ```c */ KMN_API -km_core_status -km_core_keyboard_load(km_core_path_name kb_path, - km_core_keyboard **keyboard); +km_core_status km_core_keyboard_load_from_blob(const km_core_path_name kb_name, + const void* blob, + const size_t blob_size, + km_core_keyboard** keyboard); /* ``` ## Parameters -`kb_path` -: On Windows, a UTF-16 string; on other platforms, a C string: - contains a valid path to the keyboard file. +`kb_name` +: a string with the name of the keyboard. + +`blob` +: a byte array containing the content of a KMX/KMX+ file. + +`blob_size` +: a size_t variable with the size of the blob in bytes. `keyboard` : A pointer to result variable: A pointer to the opaque keyboard @@ -1133,7 +1143,7 @@ km_core_keyboard_load(km_core_path_name kb_path, : In the event the keyboard file is unparseable for any reason `KM_CORE_STATUS_INVALID_ARGUMENT` -: In the event the file doesn't exist or is inaccesible or `keyboard` is null. +: In the event `keyboard` is null. `KM_CORE_STATUS_OS_ERROR` : Bit 31 (high bit) set, bits 0-30 are an OS-specific error code. @@ -1145,7 +1155,7 @@ km_core_keyboard_load(km_core_path_name kb_path, ## Description Free the allocated memory belonging to an opaque keyboard object previously -returned by [km_core_keyboard_load]. +returned by [km_core_keyboard_load_from_blob]. ## Specification diff --git a/core/include/keyman/keyman_core_api_bits.h b/core/include/keyman/keyman_core_api_bits.h index e00f4698a8c..bd1f519bffe 100644 --- a/core/include/keyman/keyman_core_api_bits.h +++ b/core/include/keyman/keyman_core_api_bits.h @@ -23,7 +23,6 @@ #define _kmn_unused(x) UNUSED_ ## x __attribute__((__unused__)) #else #define _kmn_unused(x) UNUSED_ ## x - #endif #if defined _WIN32 || defined __CYGWIN__ @@ -36,7 +35,7 @@ #undef _kmn_static_flag #else // How MSVC sepcifies function level attributes adn deprecation #define _kmn_and - #define _kmn_tag_fn(a) __declspec(a) + #define _kmn_tag_fn(a) __declspec(a) #define _kmn_deprecated_flag deprecated #endif #define _kmn_export_flag dllexport @@ -48,6 +47,8 @@ #define _KM_CORE_EXT_SEPARATOR ('.') #endif +#define KMN_DEPRECATED _kmn_tag_fn(_kmn_deprecated_flag) + #if defined KM_CORE_LIBRARY_STATIC #define KMN_API _kmn_tag_fn(_kmn_static_flag) #define KMN_DEPRECATED_API _kmn_tag_fn(_kmn_deprecated_flag _kmn_and _kmn_static_flag) diff --git a/core/meson.build b/core/meson.build index 4a9ea257ea8..8c6cbfdc61d 100644 --- a/core/meson.build +++ b/core/meson.build @@ -40,7 +40,7 @@ if cpp_compiler.get_id() == 'emscripten' wasm_exported_runtime_methods = '-sEXPORTED_RUNTIME_METHODS=[\'UTF8ToString\',\'stringToNewUTF8\']' endif -subdir('doc') +subdir('docs/internal') subdir('include') subdir('src') subdir('tests') diff --git a/core/src/action.cpp b/core/src/action.cpp index 5f591444091..1ff7917575c 100644 --- a/core/src/action.cpp +++ b/core/src/action.cpp @@ -61,7 +61,9 @@ bool km::core::action_item_list_to_actions_object( if(output.empty()) { actions->code_points_to_delete++; } else { +#ifndef NDEBUG auto last_context_item = output.back(); +#endif output.pop_back(); assert(last_context_item.type == KM_CORE_CT_CHAR); assert(last_context_item.character == action_items->backspace.expected_value); @@ -71,7 +73,9 @@ bool km::core::action_item_list_to_actions_object( if(output.empty()) { // deleting a marker has no effect on the application } else { +#ifndef NDEBUG auto last_context_item = output.back(); +#endif output.pop_back(); assert(last_context_item.type == KM_CORE_CT_MARKER); assert(last_context_item.marker == action_items->backspace.expected_value); diff --git a/core/src/keyboard.cpp b/core/src/keyboard.cpp index 2c3a0c11b2c..0f104f9422a 100644 --- a/core/src/keyboard.cpp +++ b/core/src/keyboard.cpp @@ -17,18 +17,16 @@ void keyboard_attributes::render() // Make attributes point to the stored values above. id = _keyboard_id.c_str(); version_string = _version_string.c_str(); - folder_path = _folder_path.c_str(); default_options = _default_opts.data(); } keyboard_attributes::keyboard_attributes(std::u16string const & kbid, std::u16string const & version, - path_type const & path, options_store const &opts) : _keyboard_id(kbid), _version_string(version), - _folder_path(path), + _folder_path(""), _default_opts(opts) { // Ensure that the default_options array will be properly terminated. @@ -40,7 +38,7 @@ keyboard_attributes::keyboard_attributes(std::u16string const & kbid, keyboard_attributes::keyboard_attributes(keyboard_attributes &&rhs) : _keyboard_id(std::move(rhs._keyboard_id)), _version_string(std::move(rhs._version_string)), - _folder_path(std::move(rhs._folder_path)), + _folder_path(""), _default_opts(std::move(rhs._default_opts)) { rhs.id = rhs.version_string = nullptr; @@ -58,7 +56,6 @@ json & km::core::operator << (json & j, km::core::keyboard_attributes const & kb { j << json::object << "id" << kb.id - << "folder" << kb._folder_path << "version" << kb.version_string << "rules" << json::array << json::close; diff --git a/core/src/keyboard.hpp b/core/src/keyboard.hpp index 142bf40e860..2ca7118d870 100644 --- a/core/src/keyboard.hpp +++ b/core/src/keyboard.hpp @@ -26,6 +26,7 @@ namespace core { std::u16string _keyboard_id; std::u16string _version_string; + // unused and deprecated core::path _folder_path; std::vector