mirror of
https://github.com/Julow/Unexpected-Keyboard.git
synced 2025-08-18 15:59:05 +02:00
Compare commits
6 Commits
settings-h
...
sel-mode-f
Author | SHA1 | Date | |
---|---|---|---|
|
5d62cf7901 | ||
|
f9b844e988 | ||
|
6f0244a29e | ||
|
2a50a4a129 | ||
|
9ab099175d | ||
|
0445c310ad |
91
funding.json
Normal file
91
funding.json
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
{
|
||||||
|
"version": "v1.0.0",
|
||||||
|
"entity": {
|
||||||
|
"type": "individual",
|
||||||
|
"role": "owner",
|
||||||
|
"name": "Julow",
|
||||||
|
"email": "jules@j3s.fr",
|
||||||
|
"description": "Open source developer and maintainer of Unexpected Keyboard.",
|
||||||
|
"webpageUrl": {
|
||||||
|
"url": "https://github.com/Julow"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"projects": [
|
||||||
|
{
|
||||||
|
"guid": "unexpected-keyboard",
|
||||||
|
"name": "Unexpected Keyboard",
|
||||||
|
"description": "Lightweight and privacy-conscious virtual keyboard for Android.",
|
||||||
|
"webpageUrl": {
|
||||||
|
"url": "https://github.com/Julow/Unexpected-Keyboard/"
|
||||||
|
},
|
||||||
|
"repositoryUrl": {
|
||||||
|
"url": "https://github.com/Julow/Unexpected-Keyboard/"
|
||||||
|
},
|
||||||
|
"licenses": [
|
||||||
|
"spdx:GPL-3.0",
|
||||||
|
"spdx:CC0-1.0"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"android",
|
||||||
|
"mobile",
|
||||||
|
"privacy",
|
||||||
|
"productivity",
|
||||||
|
"programming",
|
||||||
|
"user-experience"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"channels": [
|
||||||
|
{
|
||||||
|
"guid": "liberapay",
|
||||||
|
"type": "other",
|
||||||
|
"address": "https://liberapay.com/Julow/",
|
||||||
|
"description": "Recurring donations for funding Unexpected Keyboard."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "github-sponsors",
|
||||||
|
"type": "other",
|
||||||
|
"address": "https://github.com/sponsors/Julow",
|
||||||
|
"description": "Recurring donations for funding Unexpected Keyboard."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "paypal",
|
||||||
|
"type": "other",
|
||||||
|
"address": "https://paypal.me/JulesAguillon",
|
||||||
|
"description": "One-time donations for funding Unexpected-keyboard."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"plans": [
|
||||||
|
{
|
||||||
|
"guid": "fund-maintenance",
|
||||||
|
"status": "active",
|
||||||
|
"name": "Fund developer time",
|
||||||
|
"description": "Help the maintainers spend time on Unexpected Keyboard",
|
||||||
|
"amount": 0,
|
||||||
|
"currency": "EUR",
|
||||||
|
"frequency": "monthly",
|
||||||
|
"channels": [
|
||||||
|
"liberapay",
|
||||||
|
"github-sponsors",
|
||||||
|
"paypal"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "one-time-contribution",
|
||||||
|
"status": "active",
|
||||||
|
"name": "Fund developer time",
|
||||||
|
"description": "Help the maintainers spend time on Unexpected Keyboard",
|
||||||
|
"amount": 0,
|
||||||
|
"currency": "EUR",
|
||||||
|
"frequency": "one-time",
|
||||||
|
"channels": [
|
||||||
|
"liberapay",
|
||||||
|
"github-sponsors",
|
||||||
|
"paypal"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"history": []
|
||||||
|
}
|
||||||
|
}
|
@@ -40,7 +40,7 @@
|
|||||||
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="margin_bottom_landscape_unfolded" android:title="@string/pref_landscape_unfolded" android:summary="%sdp" android:defaultValue="3" min="0" max="100"/>
|
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="margin_bottom_landscape_unfolded" android:title="@string/pref_landscape_unfolded" android:summary="%sdp" android:defaultValue="3" min="0" max="100"/>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
<PreferenceScreen android:title="@string/pref_keyboard_height_title">
|
<PreferenceScreen android:title="@string/pref_keyboard_height_title">
|
||||||
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height" android:title="@string/pref_portrait" android:summary="%s%%" android:defaultValue="35" min="10" max="50"/>
|
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height" android:title="@string/pref_portrait" android:summary="%s%%" android:defaultValue="35" min="10" max="100"/>
|
||||||
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height_landscape" android:title="@string/pref_landscape" android:summary="%s%%" android:defaultValue="50" min="20" max="65"/>
|
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height_landscape" android:title="@string/pref_landscape" android:summary="%s%%" android:defaultValue="50" min="20" max="65"/>
|
||||||
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height_unfolded" android:title="@string/pref_portrait_unfolded" android:summary="%s%%" android:defaultValue="35" min="10" max="50"/>
|
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height_unfolded" android:title="@string/pref_portrait_unfolded" android:summary="%s%%" android:defaultValue="35" min="10" max="50"/>
|
||||||
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height_landscape_unfolded" android:title="@string/pref_landscape_unfolded" android:summary="%s%%" android:defaultValue="50" min="20" max="65"/>
|
<juloo.keyboard2.prefs.IntSlideBarPreference android:key="keyboard_height_landscape_unfolded" android:title="@string/pref_landscape_unfolded" android:summary="%s%%" android:defaultValue="50" min="20" max="65"/>
|
||||||
|
@@ -49,7 +49,7 @@ public final class ClipboardHistoryService
|
|||||||
/** The maximum size limits the amount of user data stored in memory but also
|
/** The maximum size limits the amount of user data stored in memory but also
|
||||||
gives a sense to the user that the history is not persisted and can be
|
gives a sense to the user that the history is not persisted and can be
|
||||||
forgotten as soon as the app stops. */
|
forgotten as soon as the app stops. */
|
||||||
public static final int MAX_HISTORY_SIZE = 3;
|
public static final int MAX_HISTORY_SIZE = 6;
|
||||||
/** Time in ms until history entries expire. */
|
/** Time in ms until history entries expire. */
|
||||||
public static final long HISTORY_TTL_MS = 5 * 60 * 1000;
|
public static final long HISTORY_TTL_MS = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
@@ -42,7 +42,8 @@ public final class Config
|
|||||||
public long longPressInterval;
|
public long longPressInterval;
|
||||||
public boolean keyrepeat_enabled;
|
public boolean keyrepeat_enabled;
|
||||||
public float margin_bottom;
|
public float margin_bottom;
|
||||||
public float keyHeight;
|
public int keyboardHeightPercent;
|
||||||
|
public int screenHeightPixels;
|
||||||
public float horizontal_margin;
|
public float horizontal_margin;
|
||||||
public float key_vertical_margin;
|
public float key_vertical_margin;
|
||||||
public float key_horizontal_margin;
|
public float key_horizontal_margin;
|
||||||
@@ -110,9 +111,6 @@ public final class Config
|
|||||||
orientation_landscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
|
orientation_landscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
|
||||||
foldable_unfolded = foldableUnfolded;
|
foldable_unfolded = foldableUnfolded;
|
||||||
|
|
||||||
// The height of the keyboard is relative to the height of the screen.
|
|
||||||
// This is the height of the keyboard if it have 4 rows.
|
|
||||||
int keyboardHeightPercent;
|
|
||||||
float characterSizeScale = 1.f;
|
float characterSizeScale = 1.f;
|
||||||
String show_numpad_s = _prefs.getString("show_numpad", "never");
|
String show_numpad_s = _prefs.getString("show_numpad", "never");
|
||||||
show_numpad = "always".equals(show_numpad_s);
|
show_numpad = "always".equals(show_numpad_s);
|
||||||
@@ -159,9 +157,7 @@ public final class Config
|
|||||||
borderConfig = _prefs.getBoolean("border_config", false);
|
borderConfig = _prefs.getBoolean("border_config", false);
|
||||||
customBorderRadius = _prefs.getInt("custom_border_radius", 0) / 100.f;
|
customBorderRadius = _prefs.getInt("custom_border_radius", 0) / 100.f;
|
||||||
customBorderLineWidth = get_dip_pref(dm, "custom_border_line_width", 0);
|
customBorderLineWidth = get_dip_pref(dm, "custom_border_line_width", 0);
|
||||||
// Do not substract key_vertical_margin from keyHeight because this is done
|
screenHeightPixels = dm.heightPixels;
|
||||||
// during rendering.
|
|
||||||
keyHeight = dm.heightPixels * keyboardHeightPercent / 100 / 4;
|
|
||||||
horizontal_margin =
|
horizontal_margin =
|
||||||
get_dip_pref_oriented(dm, "horizontal_margin", 3, 28);
|
get_dip_pref_oriented(dm, "horizontal_margin", 3, 28);
|
||||||
double_tap_lock_shift = _prefs.getBoolean("lock_double_tap", false);
|
double_tap_lock_shift = _prefs.getBoolean("lock_double_tap", false);
|
||||||
|
@@ -320,10 +320,16 @@ public final class KeyEventHandler
|
|||||||
{
|
{
|
||||||
int sel_start = et.selectionStart;
|
int sel_start = et.selectionStart;
|
||||||
int sel_end = et.selectionEnd;
|
int sel_end = et.selectionEnd;
|
||||||
if (sel_left == (sel_start <= sel_end))
|
boolean modify_sel_start = sel_left == (sel_start <= sel_end);
|
||||||
sel_start += d;
|
do
|
||||||
else
|
{
|
||||||
sel_end += d;
|
if (modify_sel_start)
|
||||||
|
sel_start += d;
|
||||||
|
else
|
||||||
|
sel_end += d;
|
||||||
|
// Move the cursor twice if moving it once would make the selection
|
||||||
|
// empty and stop selection mode.
|
||||||
|
} while (sel_start == sel_end);
|
||||||
if (conn.setSelection(sel_start, sel_end))
|
if (conn.setSelection(sel_start, sel_end))
|
||||||
return; // Fallback to sending key events if [setSelection] failed
|
return; // Fallback to sending key events if [setSelection] failed
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,8 @@ public class Keyboard2View extends View
|
|||||||
private Config _config;
|
private Config _config;
|
||||||
|
|
||||||
private float _keyWidth;
|
private float _keyWidth;
|
||||||
|
private float _mainLabelSize;
|
||||||
|
private float _subLabelSize;
|
||||||
private float _marginRight;
|
private float _marginRight;
|
||||||
private float _marginLeft;
|
private float _marginLeft;
|
||||||
private float _marginBottom;
|
private float _marginBottom;
|
||||||
@@ -227,7 +229,7 @@ public class Keyboard2View extends View
|
|||||||
return null;
|
return null;
|
||||||
for (KeyboardData.Row row : _keyboard.rows)
|
for (KeyboardData.Row row : _keyboard.rows)
|
||||||
{
|
{
|
||||||
y += (row.shift + row.height) * _config.keyHeight;
|
y += (row.shift + row.height) * _tc.row_height;
|
||||||
if (ty < y)
|
if (ty < y)
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
@@ -307,9 +309,19 @@ public class Keyboard2View extends View
|
|||||||
_marginRight = Math.max(_config.horizontal_margin, insets_right);
|
_marginRight = Math.max(_config.horizontal_margin, insets_right);
|
||||||
_marginBottom = _config.margin_bottom + insets_bottom;
|
_marginBottom = _config.margin_bottom + insets_bottom;
|
||||||
_keyWidth = (width - _marginLeft - _marginRight) / _keyboard.keysWidth;
|
_keyWidth = (width - _marginLeft - _marginRight) / _keyboard.keysWidth;
|
||||||
_tc = new Theme.Computed(_theme, _config, _keyWidth);
|
_tc = new Theme.Computed(_theme, _config, _keyWidth, _keyboard);
|
||||||
|
// Compute the size of labels based on the width or the height of keys. The
|
||||||
|
// margin around keys is taken into account. Keys normal aspect ratio is
|
||||||
|
// assumed to be 3/2. It's generally more, the width computation is useful
|
||||||
|
// when the keyboard is unusually high.
|
||||||
|
float labelBaseSize = Math.min(
|
||||||
|
_tc.row_height - _tc.vertical_margin,
|
||||||
|
_keyWidth * 3/2 - _tc.horizontal_margin
|
||||||
|
) * _config.characterSize;
|
||||||
|
_mainLabelSize = labelBaseSize * _config.labelTextSize;
|
||||||
|
_subLabelSize = labelBaseSize * _config.sublabelTextSize;
|
||||||
int height =
|
int height =
|
||||||
(int)(_config.keyHeight * _keyboard.keysHeight
|
(int)(_tc.row_height * _keyboard.keysHeight
|
||||||
+ _config.marginTop + _marginBottom);
|
+ _config.marginTop + _marginBottom);
|
||||||
setMeasuredDimension(width, height);
|
setMeasuredDimension(width, height);
|
||||||
}
|
}
|
||||||
@@ -352,9 +364,9 @@ public class Keyboard2View extends View
|
|||||||
float y = _tc.margin_top;
|
float y = _tc.margin_top;
|
||||||
for (KeyboardData.Row row : _keyboard.rows)
|
for (KeyboardData.Row row : _keyboard.rows)
|
||||||
{
|
{
|
||||||
y += row.shift * _config.keyHeight;
|
y += row.shift * _tc.row_height;
|
||||||
float x = _marginLeft + _tc.margin_left;
|
float x = _marginLeft + _tc.margin_left;
|
||||||
float keyH = row.height * _config.keyHeight - _tc.vertical_margin;
|
float keyH = row.height * _tc.row_height - _tc.vertical_margin;
|
||||||
for (KeyboardData.Key k : row.keys)
|
for (KeyboardData.Key k : row.keys)
|
||||||
{
|
{
|
||||||
x += k.shift * _keyWidth;
|
x += k.shift * _keyWidth;
|
||||||
@@ -372,7 +384,7 @@ public class Keyboard2View extends View
|
|||||||
drawIndication(canvas, k, x, y, keyW, keyH, _tc);
|
drawIndication(canvas, k, x, y, keyW, keyH, _tc);
|
||||||
x += _keyWidth * k.width;
|
x += _keyWidth * k.width;
|
||||||
}
|
}
|
||||||
y += row.height * _config.keyHeight;
|
y += row.height * _tc.row_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +452,7 @@ public class Keyboard2View extends View
|
|||||||
kv = modifyKey(kv, _mods);
|
kv = modifyKey(kv, _mods);
|
||||||
if (kv == null)
|
if (kv == null)
|
||||||
return;
|
return;
|
||||||
float textSize = scaleTextSize(kv, _config.labelTextSize, keyH);
|
float textSize = scaleTextSize(kv, true);
|
||||||
Paint p = tc.label_paint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT), labelColor(kv, isKeyDown, false), textSize);
|
Paint p = tc.label_paint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT), labelColor(kv, isKeyDown, false), textSize);
|
||||||
canvas.drawText(kv.getString(), x, (keyH - p.ascent() - p.descent()) / 2f + y, p);
|
canvas.drawText(kv.getString(), x, (keyH - p.ascent() - p.descent()) / 2f + y, p);
|
||||||
}
|
}
|
||||||
@@ -454,7 +466,7 @@ public class Keyboard2View extends View
|
|||||||
kv = modifyKey(kv, _mods);
|
kv = modifyKey(kv, _mods);
|
||||||
if (kv == null)
|
if (kv == null)
|
||||||
return;
|
return;
|
||||||
float textSize = scaleTextSize(kv, _config.sublabelTextSize, keyH);
|
float textSize = scaleTextSize(kv, false);
|
||||||
Paint p = tc.sublabel_paint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT), labelColor(kv, isKeyDown, true), textSize, a);
|
Paint p = tc.sublabel_paint(kv.hasFlagsAny(KeyValue.FLAG_KEY_FONT), labelColor(kv, isKeyDown, true), textSize, a);
|
||||||
float subPadding = _config.keyPadding;
|
float subPadding = _config.keyPadding;
|
||||||
if (v == Vertical.CENTER)
|
if (v == Vertical.CENTER)
|
||||||
@@ -479,14 +491,15 @@ public class Keyboard2View extends View
|
|||||||
if (k.indication == null || k.indication.equals(""))
|
if (k.indication == null || k.indication.equals(""))
|
||||||
return;
|
return;
|
||||||
Paint p = tc.indication_paint;
|
Paint p = tc.indication_paint;
|
||||||
p.setTextSize(keyH * _config.sublabelTextSize * _config.characterSize);
|
p.setTextSize(_subLabelSize);
|
||||||
canvas.drawText(k.indication, 0, k.indication.length(),
|
canvas.drawText(k.indication, 0, k.indication.length(),
|
||||||
x + keyW / 2f, (keyH - p.ascent() - p.descent()) * 4/5 + y, p);
|
x + keyW / 2f, (keyH - p.ascent() - p.descent()) * 4/5 + y, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float scaleTextSize(KeyValue k, float rel_size, float keyH)
|
private float scaleTextSize(KeyValue k, boolean main_label)
|
||||||
{
|
{
|
||||||
float smaller_font = k.hasFlagsAny(KeyValue.FLAG_SMALLER_FONT) ? 0.75f : 1.f;
|
float smaller_font = k.hasFlagsAny(KeyValue.FLAG_SMALLER_FONT) ? 0.75f : 1.f;
|
||||||
return keyH * rel_size * smaller_font * _config.characterSize;
|
float label_size = main_label ? _mainLabelSize : _subLabelSize;
|
||||||
|
return label_size * smaller_font;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -94,14 +94,23 @@ public class Theme
|
|||||||
public final float horizontal_margin;
|
public final float horizontal_margin;
|
||||||
public final float margin_top;
|
public final float margin_top;
|
||||||
public final float margin_left;
|
public final float margin_left;
|
||||||
|
public final float row_height;
|
||||||
public final Paint indication_paint;
|
public final Paint indication_paint;
|
||||||
|
|
||||||
public final Key key;
|
public final Key key;
|
||||||
public final Key key_activated;
|
public final Key key_activated;
|
||||||
|
|
||||||
public Computed(Theme theme, Config config, float keyWidth)
|
public Computed(Theme theme, Config config, float keyWidth, KeyboardData layout)
|
||||||
{
|
{
|
||||||
vertical_margin = config.key_vertical_margin * config.keyHeight;
|
// Rows height is proportional to the keyboard height, meaning it doesn't
|
||||||
|
// change for layouts with more or less rows. 3.95 is the usual height of
|
||||||
|
// a layout in KeyboardData unit. The keyboard will be higher if the
|
||||||
|
// layout has more rows and smaller if it has less because rows stay the
|
||||||
|
// same height.
|
||||||
|
row_height = Math.min(
|
||||||
|
config.screenHeightPixels * config.keyboardHeightPercent / 100 / 3.95f,
|
||||||
|
config.screenHeightPixels / layout.keysHeight);
|
||||||
|
vertical_margin = config.key_vertical_margin * row_height;
|
||||||
horizontal_margin = config.key_horizontal_margin * keyWidth;
|
horizontal_margin = config.key_horizontal_margin * keyWidth;
|
||||||
// Add half of the key margin on the left and on the top as it's also
|
// Add half of the key margin on the left and on the top as it's also
|
||||||
// added on the right and on the bottom of every keys.
|
// added on the right and on the bottom of every keys.
|
||||||
|
Reference in New Issue
Block a user