moby: update improve button mappings

- power + volup: screenshot
- power + voldown: camera
- volup_hold: file browser
- remove modal media controls
This commit is contained in:
2024-04-22 04:05:48 +00:00
parent 82007c9b40
commit 95b21cbed9
3 changed files with 88 additions and 56 deletions

View File

@@ -37,6 +37,18 @@ let
hash = "sha256-gz3N4uo7IWzzqaPHHVhby/e9NbtzcFJRQwgdNYxO/Yw=";
})
];
nativeBuildInputs = (upstream.nativeBuildInputs or []) ++ [
pkgs.copyDesktopItems
];
desktopItems = (upstream.desktopItems or []) ++ [
(pkgs.makeDesktopItem {
name = "rofi-filebrowser";
# alternatively: `rofi -modes filebrowser -show`, however this would require theme tweaking to look good
exec = "rofi -combi-modes filebrowser -show";
desktopName = "rofi filebrowser";
})
];
});
# rofi-emoji = pkgs.rofi-emoji.override {
# # plugins must be compiled against the same rofi they're loaded by

View File

@@ -138,32 +138,27 @@ in
sane.programs.bonsai.config.transitions = lib.mkIf cfg.enabled (friendlyToBonsai {
# map sequences of "events" to an argument to pass to sane-input-handler
# map: power (short), power (short) x2, power (long)
power_pressed.timeout.ms = 900; # press w/o release. this is a long timeout because it's tied to the "kill window" action.
power_pressed.timeout.trigger = "powerhold";
power_pressed.power_released.timeout.trigger = "powerbutton_one";
# map: power (short), power (short) x2
power_pressed.power_released.timeout.trigger = "power_tap_1_final";
power_pressed.power_released.timeout.ms = 300;
power_pressed.power_released.power_pressed.trigger = "powerbutton_two";
# map power (short) -> volup/voldown
power_pressed.power_released.volup_pressed.trigger = "powerbutton_volup";
power_pressed.power_released.voldown_pressed.trigger = "powerbutton_voldown";
power_pressed.power_released.power_pressed.trigger = "power_tap_2_final";
# map: power (short) -> volup/voldown
power_pressed.power_released.volup_pressed.trigger = "power_then_volup";
power_pressed.power_released.voldown_pressed.trigger = "power_then_voldown";
# map: power + volup/voldown
power_pressed.volup_pressed.trigger = "power_and_volup";
power_pressed.voldown_pressed.trigger = "power_and_voldown";
# map: power (long)
power_pressed.timeout.ms = 900; # press w/o release. this is a long timeout because it's tied to the "kill window" action.
power_pressed.timeout.power_released.trigger = "power_hold";
## remap power + volup/voldown on the long power, to decrease accidental "kill window"s
power_pressed.timeout.volup_pressed.trigger = "power_and_volup";
power_pressed.timeout.voldown_pressed.trigger = "power_and_voldown";
# map: volume taps and holds
volup_pressed = (recurseHold "volup" {}) // {
# this either becomes volup_hold_* (via recurseHold, above) or:
# - a short volup_tap_1 followed by:
# - a *finalized* volup_1 (i.e. end of action)
# - more taps/holds, in which case we prefix it with `modal_<action>`
# to denote that we very explicitly entered this state.
#
# it's clunky: i do it this way so that voldown can map to keyboard/terminal in unlock mode
# but trigger media controls in screenoff
# in a way which *still* allows media controls if explicitly entered into via a tap on volup first
volup_released = (volumeActions { prefix = "modal_"; }) // {
trigger = "volup_tap_1";
timeout.ms = 300;
timeout.trigger = "volup_1";
};
volup_pressed = (volumeActions {}).volup_pressed // {
trigger = "volup_start";
};
voldown_pressed = (volumeActions {}).voldown_pressed // {
trigger = "voldown_start";

View File

@@ -12,11 +12,16 @@
#
# example of a design which considers these things:
# - when unlocked:
# - volup toggle -> app menu
# - volup tap -> app menu
# - volup hold -> file browser
# - voldown press -> keyboard
# - voldown hold -> terminal
# - power x2 -> screenoff
# - hold power -> kill app
# - power hold -> kill app
# - power,volup -> screen rotate CCW
# - power,voldown -> screen rotate CW
# - power+volup -> screenshot
# - power+voldown -> camera
# - when locked:
# - volup tap -> volume up
# - volup hold -> media seek forward
@@ -24,15 +29,31 @@
# - voldown hold -> media seek backward
# - power x1 -> screen on
# - power x2 -> play/pause media
# some trickiness allows for media controls in unlocked mode:
# - volup tap -> enter media mode
# - i.e. in this state, vol tap/hold is mapped to volume/seek
# - if, after entering media mode, no more taps occur, then we trigger the default app-menu action
# limitations/downsides:
# - power mappings means phone is artificially slow to unlock.
# - media controls when unlocked have quirks:
# - mashing voldown to decrease the volume will leave you with a toggled keyboard.
# - seeking backward isn't possible except by first tapping volup.
# - alternate mapping could resolve this:
# - power_tap_1: screen on (i.e. immediately after releasing power, if not held long)
# - power_hold_1: play/pause media (which now works in any mode)
# - power_tap_2: screen off
# - power_tap_1_hold_1: kill
# - by hiding this behind the tap, it decreases the chance of accidental kills
# - "tap-then-hold" idiom could make sense for keyboard/terminal, too: voldown_tap_1_hold_1: terminal, instead of voldown_hold -- decreases accidental terminal launches
# - power-hold for kill means messing up the compound operations has bad consequences
#
# EXAMPLE EVENT FIRINGS:
# - double-tap voldown:
# - voldown_start
# - voldown_tap_1
# - voldown_tap_2
# - hold voldown:
# - voldown_start
# - voldown_hold_1
# - voldown_hold_2
# - voldown_hold_3
# - hold power:
# - power_hold (notice: it doesn't fire power_start)
# - double-tap power:
# - power_tap_2_final (notice: it doesn't fire power_tap_1)
# increments to use for volume adjustment (in %)
@@ -106,27 +127,26 @@ handleWith() {
dispatchDefault() {
case "$action" in
"powerbutton_one")
"power_tap_1_final")
# power once => unlock
handleWith allOn
;;
"powerbutton_two")
"power_tap_2_final")
# power twice => screenoff
handleWith allOff
;;
# powerbutton_three: intentional no-op because overloading the kill-window handler is risky
volup_tap*|modal_volup_tap*)
volup_tap*)
handleWith wpctl set-volume @DEFAULT_AUDIO_SINK@ "$VOL_INCR"%+
;;
voldown_tap*|modal_voldown_tap*)
voldown_tap*)
handleWith wpctl set-volume @DEFAULT_AUDIO_SINK@ "$VOL_INCR"%-
;;
volup_hold*|modal_volup_hold*)
volup_hold*)
handleWith playerctl position 30+
;;
voldown_hold*|modal_voldown_hold*)
voldown_hold*)
handleWith playerctl position 10-
;;
esac
@@ -134,11 +154,11 @@ dispatchDefault() {
dispatchOff() {
case "$action" in
"powerbutton_two")
"power_tap_2_final")
# power twice => toggle media player
handleWith playerctl play-pause
;;
"powerhold")
"power_hold")
# power toggle during deep sleep often gets misread as power hold, so treat same
handleWith allOn
;;
@@ -147,41 +167,46 @@ dispatchOff() {
dispatchOn() {
case "$action" in
# powerbutton_one: intentional default to no-op
# powerbutton_two: intentional default to screenoff
"powerhold")
# power_tap_1_final: intentional default to no-op
# power_tap_2_final: intentional default to screenoff
"power_hold")
# power thrice: kill active window
# TODO: disable this if locked (with e.g. schlock, swaylock, etc)
handleWith swaymsg kill
;;
"powerbutton_volup")
"power_and_volup")
# power (hold) -> volup: take screenshot
handleWith sane-open-desktop sane-screenshot.desktop
;;
"power_and_voldown")
# power (hold) -> voldown: open camera
handleWith sane-open-desktop org.postmarketos.Megapixels.desktop
;;
"power_then_volup")
# power (tap) -> volup: rotate CCW
handleWith swaymsg -- output '-' transform 90 anticlockwise
;;
"powerbutton_voldown")
"power_then_voldown")
# power (tap) -> voldown: rotate CW
handleWith swaymsg -- output '-' transform 90 clockwise
;;
"volup_tap_1")
# swallow: this could be the start to a media control (multi taps / holds),
# or it could be just a single tap -> release, handled next/below
handleWith ignore
;;
"volup_1")
# volume up once: system menu
handleWith sane-open-desktop rofi.desktop
;;
"volup_hold_1")
# volume up hold: just browse files
handleWith sane-open-desktop rofi-filebrowser.desktop
;;
"voldown_start")
# volume down once: toggle keyboard
handleWith toggleKeyboard
;;
"voldown_hold_2")
"voldown_hold_1")
# hold voldown to launch terminal
# note we already triggered the keyboard; that's fine: usually keyboard + terminal go together :)
# voldown_hold_1 frequently triggers during short taps meant only to reveal the keyboard,
# so prefer a longer hold duration
handleWith sane-open-desktop xdg-terminal-exec.desktop
;;
"voldown_tap_1")
@@ -197,8 +222,8 @@ dispatchOn() {
dispatchInhibited() {
case "$action" in
"powerhold")
# power thrice: escape hatch in case rofi has hung
"power_hold")
# power hold: escape hatch in case rofi has hung
handleWith killall -9 rofi
;;
*)