Merge the volume row, the blue D-pad and the mute on hold

This commit is contained in:
nyra
2026-09-28 02:49:12 +00:00
8 changed files with 66 additions and 3 deletions
+7
View File
@@ -15,6 +15,12 @@
<attr name="colorLabelPressed" format="color"/> <!-- defaults to colorLabel -->
<attr name="colorLabelActivated" format="color"/>
<attr name="colorLabelLocked" format="color"/>
<!-- The Roku page's four direction keys. They carry FLAG_SECONDARY like every
other event key, so without a colour of their own they come out dimmed to
secondaryLabelColor. This is the same cyan the keyboard already uses for
"the blue" (the space bar's io-stall line, the DeepSeek off-peak indicator),
and it is deliberately the same value in every theme. -->
<attr name="colorRokuArrow" format="color"/>
<attr name="secondaryDimming" format="float"/>
<attr name="greyedDimming" format="float"/>
<!-- Corner labels -->
@@ -61,6 +67,7 @@
<item name="clipboard_divider_height">1px</item>
<item name="suggestions_background">?attr/colorKeyboard</item>
<item name="suggestions_border_radius">?attr/keyBorderRadius</item>
<item name="colorRokuArrow">#00E5FF</item>
</style>
<style name="Dark" parent="BaseTheme">
<item name="android:isLightTheme">false</item>
+6 -3
View File
@@ -9,7 +9,10 @@
fill the empty corner slots of these keys. That is why the last row is a
full-width "Keyboard" key instead of the config gear: it fires the same
Event.SWITCH_TEXT as the switch_text key on other pages and is the way back
to the letter keyboard. -->
to the letter keyboard.
Vol- is also the page's mute: holding it sends mute instead of volume-down
(KeyModifier.modify_long_press), so mute is on the page without a slot. -->
<keyboard bottom_row="false">
<row height="0.8">
<key width="3.3" role="action" key0="roku_home"/>
@@ -28,9 +31,9 @@
<key shift="3.3" width="3.3" role="action" key0="roku_down"/>
</row>
<row height="0.8">
<key width="3.3" role="action" key0="roku_rewind"/>
<key width="3.3" role="action" key0="roku_voldown"/>
<key width="3.3" role="action" key0="roku_play"/>
<key width="3.3" role="action" key0="roku_forward"/>
<key width="3.3" role="action" key0="roku_volup"/>
</row>
<row height="1.0">
<key width="9.9" role="action" key0="roku_close"/>
+7
View File
@@ -112,6 +112,13 @@ public final class KeyModifier
return KeyValue.CHANGE_METHOD;
case SWITCH_VOICE_TYPING:
return KeyValue.VOICE_TYPING_CHOOSER;
/* The Roku page's volume-down key: held, it is the TV's mute instead of
volume-down. This is the same path the two keys above take, so [Pointers]
replaces the pointer's value while the finger is still down and the single
[key_up] on release carries the mute - the short press is not sent as well.
Mute therefore lives on the page without taking a slot of its own. */
case ROKU_VOLDOWN:
return KeyValue.ROKU_VOLUME_MUTE;
}
break;
}
+12
View File
@@ -40,6 +40,9 @@ public final class KeyValue implements Comparable<KeyValue>
ROKU_REWIND,
ROKU_FORWARD,
ROKU_POWER,
ROKU_VOLUP,
ROKU_VOLDOWN,
ROKU_VOLMUTE,
}
// Must be evaluated in the reverse order of their values.
@@ -558,6 +561,10 @@ public final class KeyValue implements Comparable<KeyValue>
public static final KeyValue CHANGE_METHOD_PREV = eventKey(0xE009, Event.CHANGE_METHOD_PREV, FLAG_SMALLER_FONT);
public static final KeyValue CHANGE_METHOD_NEXT = eventKey(0xE009, Event.CHANGE_METHOD_NEXT, FLAG_SMALLER_FONT);
public static final KeyValue VOICE_TYPING_CHOOSER = eventKey(0xE015, Event.SWITCH_VOICE_TYPING_CHOOSER, FLAG_SMALLER_FONT);
/** The Roku page's mute key. It is also what a long press on the page's volume-down key
sends (see [KeyModifier.modify_long_press]), so mute lives on the page without
spending a slot on it; both uses share this one key. */
public static final KeyValue ROKU_VOLUME_MUTE = eventKey("Mute", Event.ROKU_VOLMUTE, FLAG_SMALLER_FONT);
public static final KeyValue COMPOSE_CANCEL = placeholderKey(0xE01A, Placeholder.COMPOSE_CANCEL, FLAG_SECONDARY);
public static KeyValue getSpecialKeyByName(String name)
@@ -682,6 +689,11 @@ public final class KeyValue implements Comparable<KeyValue>
case "roku_rewind": return eventKey("Rewind", Event.ROKU_REWIND, FLAG_SMALLER_FONT);
case "roku_forward": return eventKey("Forward", Event.ROKU_FORWARD, FLAG_SMALLER_FONT);
case "roku_power": return eventKey("Power", Event.ROKU_POWER, FLAG_SMALLER_FONT);
/* The TV's volume, same ECP path as the rest of the page (RokuRemote sends the
VolumeUp/VolumeDown/VolumeMute keypresses Harley's own web remote uses). */
case "roku_volup": return eventKey("Vol+", Event.ROKU_VOLUP, FLAG_SMALLER_FONT);
case "roku_voldown": return eventKey("Vol-", Event.ROKU_VOLDOWN, FLAG_SMALLER_FONT);
case "roku_volmute": return ROKU_VOLUME_MUTE;
/* The way back from the Roku page. The same event as "switch_text", which is
unchanged, but labelled: the page has no config key, so this is the only exit
and "ABC" does not read as one on a page full of remote keys. */
+1
View File
@@ -494,6 +494,7 @@ public class Keyboard2 extends InputMethodService
case ROKU_HOME: case ROKU_BACK:
case ROKU_UP: case ROKU_DOWN: case ROKU_LEFT: case ROKU_RIGHT:
case ROKU_SELECT: case ROKU_PLAY: case ROKU_REWIND: case ROKU_FORWARD:
case ROKU_VOLUP: case ROKU_VOLDOWN: case ROKU_VOLMUTE:
case ROKU_POWER:
RokuRemote.press(ev);
break;
+25
View File
@@ -743,6 +743,22 @@ public class Keyboard2View extends View
canvas.restore();
}
/** True for the four direction keys of the Roku page (res/xml/roku.xml), matched by
EVENT and never by glyph: 0xE005-0xE008 are ordinary arrow glyphs that the default
layouts and other pages also use, and those must keep their own colours.
[KeyValue.getEvent()] is only valid for its own kind, so the kind is checked first,
the same guard [RokuRemote.isLit] uses. */
private static boolean isRokuDirection(KeyValue k)
{
if (k.getKind() != KeyValue.Kind.Event)
return false;
switch (k.getEvent())
{
case ROKU_UP: case ROKU_DOWN: case ROKU_LEFT: case ROKU_RIGHT: return true;
default: return false;
}
}
private int labelColor(KeyValue k, boolean isKeyDown, boolean sublabel)
{
if (isKeyDown)
@@ -756,6 +772,15 @@ public class Keyboard2View extends View
}
return _theme.pressedColor;
}
/* The Roku page's four direction keys are event keys, and every event key carries
FLAG_SECONDARY, which dims them to secondaryLabelColor - a muted pink on the
Orchid theme, which reads as "disabled" on the one page where they are the main
controls. They get the theme's blue accent instead. Only these four events are
affected: no other key on any page or layout changes colour. A press is answered
above, and [drawLabel]'s RokuRemote.isLit() still overrides this, so neither the
pressed look nor the sent acknowledgement changes. */
if (isRokuDirection(k))
return _theme.rokuArrowColor;
if (k.hasFlagsAny(KeyValue.FLAG_SECONDARY | KeyValue.FLAG_GREYED))
{
if (k.hasFlagsAny(KeyValue.FLAG_GREYED))
+5
View File
@@ -119,6 +119,11 @@ public final class RokuRemote
case ROKU_REWIND: return "Rev"; // the ECP's name for rewind
case ROKU_FORWARD: return "Fwd"; // ... and for fast forward
case ROKU_POWER: return "Power"; // the ECP's power toggle
/* Volume: the same names Harley's own web remote posts to /keypress/. They only
do something on a Roku TV (the TV's volume keys), which is what this is. */
case ROKU_VOLUP: return "VolumeUp";
case ROKU_VOLDOWN: return "VolumeDown";
case ROKU_VOLMUTE: return "VolumeMute";
default: return null;
}
}
+3
View File
@@ -23,6 +23,8 @@ public class Theme
public final int subLabelColor;
public final int secondaryLabelColor;
public final int greyedLabelColor;
/** Label colour for the Roku page's direction keys (res/values/themes.xml). */
public final int rokuArrowColor;
// Key borders
public final float keyBorderRadius;
@@ -58,6 +60,7 @@ public class Theme
s.getFloat(R.styleable.keyboard_secondaryDimming, 0.25f));
greyedLabelColor = adjustLight(labelColor,
s.getFloat(R.styleable.keyboard_greyedDimming, 0.5f));
rokuArrowColor = s.getColor(R.styleable.keyboard_colorRokuArrow, labelColor);
keyBorderRadius = s.getDimension(R.styleable.keyboard_keyBorderRadius, 0);
keyBorderWidth = s.getDimension(R.styleable.keyboard_keyBorderWidth, 0);
keyBorderWidthActivated = s.getDimension(R.styleable.keyboard_keyBorderWidthActivated, 0);