Add the Programming Layout option

Allow specifying a layout for programming and add a key for switching to
it easily.

The switching key is placed on the top edge of the space bar.

The option has no effect by default because the ergonomic isn't ideal,
it needs to be enabled explicitly.
Users of Latin-script languages certainly prefer to use one layout (for
programming or not). This feature might be removed in favor of a better
language-switching mechanisms in the future.
This commit is contained in:
Jules Aguillon 2022-04-03 17:15:12 +02:00
parent d62e7647e0
commit aa78229b2a
8 changed files with 58 additions and 13 deletions

View File

@ -28,6 +28,16 @@
<item>Bulgarian (Phonetic Traditional)</item>
<item>Dvorak</item>
</string-array>
<string-array name="pref_programming_layout_values">
<item>none</item>
<item>qwerty</item>
<item>dvorak</item>
</string-array>
<string-array name="pref_programming_layout_entries">
<item>@string/pref_programming_layout_none</item>
<item>QWERTY</item>
<item>Dvorak</item>
</string-array>
<string-array name="pref_accents_entries">
<item>@string/pref_accents_e_all_installed</item>
<item>@string/pref_accents_e_selected</item>

View File

@ -11,6 +11,8 @@
<string name="pref_accents_e_selected">Only show accents for the selected language</string>
<string name="pref_accents_e_all">Show all accents</string>
<string name="pref_accents_e_none">Hide accents</string>
<string name="pref_programming_layout_title">Keyboard layout for programming</string>
<string name="pref_programming_layout_none">None</string>
<string name="pref_category_typing">Typing</string>
<string name="pref_swipe_dist_title">Swiping distance</string>
<string name="pref_swipe_dist_summary">Distance of characters in the corners of the keys (%s)</string>

View File

@ -2,7 +2,7 @@
<row height="0.95">
<key width="1.8" key0="switch_numeric" key2="meta" key4="ctrl"/>
<key width="1.2" key0="fn" key1="alt" key2="change_method" key3="switch_emoji" key4="config"/>
<key width="4.0" key0="space"/>
<key width="4.0" key0="space" key1="switch_programming" edgekeys="true"/>
<key width="1.2" key1="up" key2="right" key3="left" key4="down" edgekeys="true"/>
<key width="1.8" key0="enter" key2="action"/>
</row>

View File

@ -3,6 +3,7 @@
<PreferenceCategory android:title="@string/pref_category_layout">
<ListPreference android:key="layout" android:title="@string/pref_layout_title" android:summary="%s" android:defaultValue="system" android:entries="@array/pref_layout_entries" android:entryValues="@array/pref_layout_values"/>
<ListPreference android:key="accents" android:title="@string/pref_accents_title" android:summary="%s" android:defaultValue="1" android:entries="@array/pref_accents_entries" android:entryValues="@array/pref_accents_values"/>
<ListPreference android:key="programming_layout" android:title="@string/pref_programming_layout_title" android:summary="%s" android:defaultValue="none" android:entries="@array/pref_programming_layout_entries" android:entryValues="@array/pref_programming_layout_values"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_category_typing">
<ListPreference android:key="swipe_dist" android:title="@string/pref_swipe_dist_title" android:summary="@string/pref_swipe_dist_summary" android:defaultValue="15" android:entries="@array/pref_swipe_dist_entries" android:entryValues="@array/pref_swipe_dist_values"/>

View File

@ -23,6 +23,7 @@ final class Config
// From preferences
public int layout; // Or '-1' for the system defaults
public int programming_layout; // Or '-1' for none
public float swipe_dist_px;
public boolean vibrateEnabled;
public long vibrateDuration;
@ -41,6 +42,7 @@ final class Config
// Dynamically set
public boolean shouldOfferSwitchingToNextInputMethod;
public boolean shouldOfferSwitchingToProgramming;
public String actionLabel; // Might be 'null'
public int actionId; // Meaningful only when 'actionLabel' isn't 'null'
public boolean swapEnterActionKey; // Swap the "enter" and "action" keys
@ -58,6 +60,7 @@ final class Config
sublabelTextSize = res.getFloat(R.integer.sublabel_text_size);
// default values
layout = -1;
programming_layout = -1;
vibrateEnabled = true;
vibrateDuration = 20;
longPressTimeout = 600;
@ -74,6 +77,7 @@ final class Config
refresh(context);
// initialized later
shouldOfferSwitchingToNextInputMethod = false;
shouldOfferSwitchingToProgramming = false;
actionLabel = null;
actionId = 0;
swapEnterActionKey = false;
@ -101,7 +105,10 @@ final class Config
{
keyboardHeightPercent = prefs.getInt("keyboard_height", 35);
}
layout = layoutId_of_string(prefs.getString("layout", "system"));
String layout_s = prefs.getString("layout", "system");
layout = layout_s.equals("system") ? -1 : layoutId_of_string(layout_s);
String prog_layout_s = prefs.getString("programming_layout", "none");
programming_layout = prog_layout_s.equals("none") ? -1 : layoutId_of_string(prog_layout_s);
// The swipe distance is defined relatively to the "exact physical pixels
// per inch of the screen", which isn't affected by the scaling settings.
// Take the mean of both dimensions as an approximation of the diagonal.
@ -156,6 +163,8 @@ final class Config
case KeyValue.EVENT_ACTION:
return (swapEnterActionKey && action_key != null) ?
KeyValue.getKeyByName("enter") : action_key;
case KeyValue.EVENT_SWITCH_PROGRAMMING:
return shouldOfferSwitchingToProgramming ? key : null;
default:
if (key.flags != 0)
{
@ -214,7 +223,7 @@ final class Config
case "qwerty_sv_se": return R.xml.qwerty_sv_se;
case "qwertz": return R.xml.qwertz;
case "ru_jcuken": return R.xml.local_ru_jcuken;
case "system": default: return -1;
default: throw new IllegalArgumentException("layoutId_of_string: Unknown layout: " + name);
}
}

View File

@ -18,12 +18,13 @@ class KeyEventHandler implements Config.IKeyEventHandler
switch (key.eventCode)
{
case KeyValue.EVENT_CONFIG: _recv.showKeyboardConfig(); return;
case KeyValue.EVENT_SWITCH_TEXT: _recv.setLayout(-1); return;
case KeyValue.EVENT_SWITCH_NUMERIC: _recv.setLayout(R.xml.numeric); return;
case KeyValue.EVENT_SWITCH_TEXT: _recv.switchMain(); return;
case KeyValue.EVENT_SWITCH_NUMERIC: _recv.switchNumeric(); return;
case KeyValue.EVENT_SWITCH_EMOJI: _recv.setPane_emoji(); return;
case KeyValue.EVENT_SWITCH_BACK_EMOJI: _recv.setPane_normal(); return;
case KeyValue.EVENT_CHANGE_METHOD: _recv.switchToNextInputMethod(); return;
case KeyValue.EVENT_ACTION: _recv.performAction(); return;
case KeyValue.EVENT_SWITCH_PROGRAMMING: _recv.switchProgramming(); return;
default:
if ((flags & (KeyValue.FLAG_CTRL | KeyValue.FLAG_ALT | KeyValue.FLAG_META)) != 0)
handleKeyUpWithModifier(key, flags);
@ -91,8 +92,9 @@ class KeyEventHandler implements Config.IKeyEventHandler
public void showKeyboardConfig();
public void performAction();
/** 'res_id' is '-1' for the currently selected layout. */
public void setLayout(int res_id);
public void switchMain();
public void switchNumeric();
public void switchProgramming();
public void sendKeyEvent(int eventAction, int eventCode, int meta);

View File

@ -14,6 +14,7 @@ class KeyValue
public static final int EVENT_SWITCH_BACK_EMOJI = -6;
public static final int EVENT_CHANGE_METHOD = -7;
public static final int EVENT_ACTION = -8;
public static final int EVENT_SWITCH_PROGRAMMING = -9;
public static final char CHAR_NONE = '\0';
// Behavior flags
@ -234,10 +235,11 @@ class KeyValue
addCharKey('£', EVENT_NONE, FLAG_LOCALIZED);
addSpecialKey("config", "\u0004", EVENT_CONFIG, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT | FLAG_SMALLER_FONT);
addSpecialKey("switch_numeric", "123+", EVENT_SWITCH_NUMERIC | FLAG_SMALLER_FONT);
addSpecialKey("switch_text", "ABC", EVENT_SWITCH_TEXT, FLAG_SMALLER_FONT);
addSpecialKey("switch_numeric", "123+", EVENT_SWITCH_NUMERIC, FLAG_SMALLER_FONT);
addSpecialKey("switch_emoji", "\u0001" , EVENT_SWITCH_EMOJI, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addSpecialKey("switch_back_emoji", "ABC", EVENT_SWITCH_BACK_EMOJI);
addSpecialKey("switch_programming", "Prog", EVENT_SWITCH_PROGRAMMING, FLAG_SMALLER_FONT);
addSpecialKey("change_method", "\u0009", EVENT_CHANGE_METHOD, FLAG_KEY_FONT | FLAG_SMALLER_FONT);
addSpecialKey("action", "Action", EVENT_ACTION, FLAG_SMALLER_FONT); // Will always be replaced

View File

@ -139,6 +139,9 @@ public class Keyboard2 extends InputMethodService
refreshSubtypeLayout(subtype);
refreshAccentsOption(imm, subtype);
}
_config.shouldOfferSwitchingToProgramming =
_config.programming_layout != -1 &&
_currentTextLayout != _config.programming_layout;
}
private String actionLabel_of_imeAction(int action)
@ -276,11 +279,27 @@ public class Keyboard2 extends InputMethodService
conn.performEditorAction(_config.actionId);
}
public void setLayout(int res_id)
public void switchMain()
{
if (res_id == -1)
res_id = _currentTextLayout;
_keyboardView.setKeyboard(getLayout(res_id));
_keyboardView.setKeyboard(getLayout(_currentTextLayout));
}
public void switchNumeric()
{
_keyboardView.setKeyboard(getLayout(R.xml.numeric));
}
public void switchProgramming()
{
if (_config.programming_layout == -1)
return;
KeyboardData layout =
getLayout(_config.programming_layout).replaceKeys(key -> {
if (key != null && key.eventCode == KeyValue.EVENT_SWITCH_PROGRAMMING)
return KeyValue.getKeyByName("switch_text");
return key;
});
_keyboardView.setKeyboard(layout);
}
public void sendKeyEvent(int eventAction, int eventCode, int meta)