From ba9ed841d84a4fc28fc2335c626bb18bd06db615 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 26 Aug 2020 03:30:22 +0200 Subject: [PATCH] Add super and browser back and forward keys Fixes #13 --- backend.go | 3 + backend_windows.go | 11 +- icon_font/U+1FA9F Window.svg | 121 +++++++++++++++++ ...U+2B60 Leftwards Triangle-Headed Arrow.svg | 122 +++++++++++++++++ ...+2B62 Rightwards Triangle-Headed Arrow.svg | 123 ++++++++++++++++++ icon_font/icon.sfd | 109 +++++++++++++++- keysyms.go | 13 ++ webdata/fn.js | 8 +- webdata/icon.woff | Bin 4540 -> 4944 bytes 9 files changed, 503 insertions(+), 7 deletions(-) create mode 100644 icon_font/U+1FA9F Window.svg create mode 100644 icon_font/U+2B60 Leftwards Triangle-Headed Arrow.svg create mode 100644 icon_font/U+2B62 Rightwards Triangle-Headed Arrow.svg diff --git a/backend.go b/backend.go index 4efea54..dfddde3 100644 --- a/backend.go +++ b/backend.go @@ -36,6 +36,9 @@ const ( KeyMediaPlayPause KeyMediaPrevTrack KeyMediaNextTrack + KeyBrowserBack + KeyBrowserForward + KeySuper KeyLimit ) diff --git a/backend_windows.go b/backend_windows.go index 78574e0..4ff3d04 100644 --- a/backend_windows.go +++ b/backend_windows.go @@ -34,6 +34,9 @@ const ( keyeventfKeyup uint32 = 0x2 keyeventfUnicode uint32 = 0x4 + vkLwin uint16 = 0x5B + vkBrowserBack uint16 = 0xA6 + vkBrowserForward uint16 = 0xA7 vkVolumeMute uint16 = 0xAD vkVolumeDown uint16 = 0xAE vkVolumeUp uint16 = 0xAF @@ -119,7 +122,13 @@ func (p *windowsBackend) KeyboardText(text string) error { func (p *windowsBackend) KeyboardKey(key Key) error { input := keybdInput{typ: inputKeyboard} - if key == KeyVolumeMute { + if key == KeySuper { + input.wVk = vkLwin + } else if key == KeyBrowserBack { + input.wVk = vkBrowserBack + } else if key == KeyBrowserForward { + input.wVk = vkBrowserForward + } else if key == KeyVolumeMute { input.wVk = vkVolumeMute } else if key == KeyVolumeDown { input.wVk = vkVolumeDown diff --git a/icon_font/U+1FA9F Window.svg b/icon_font/U+1FA9F Window.svg new file mode 100644 index 0000000..e6c41e9 --- /dev/null +++ b/icon_font/U+1FA9F Window.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/icon_font/U+2B60 Leftwards Triangle-Headed Arrow.svg b/icon_font/U+2B60 Leftwards Triangle-Headed Arrow.svg new file mode 100644 index 0000000..6364869 --- /dev/null +++ b/icon_font/U+2B60 Leftwards Triangle-Headed Arrow.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/icon_font/U+2B62 Rightwards Triangle-Headed Arrow.svg b/icon_font/U+2B62 Rightwards Triangle-Headed Arrow.svg new file mode 100644 index 0000000..f13e555 --- /dev/null +++ b/icon_font/U+2B62 Rightwards Triangle-Headed Arrow.svg @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/icon_font/icon.sfd b/icon_font/icon.sfd index f2a4eb8..5e06aea 100644 --- a/icon_font/icon.sfd +++ b/icon_font/icon.sfd @@ -1,4 +1,4 @@ -SplineFontDB: 3.0 +SplineFontDB: 3.2 FontName: Icon FullName: Icon FamilyName: Icon @@ -21,7 +21,7 @@ OS2Version: 0 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 1 CreationTime: 1535548659 -ModificationTime: 1538075883 +ModificationTime: 1597866573 PfmFamily: 17 TTFWeight: 400 TTFWidth: 5 @@ -51,11 +51,11 @@ NameList: AGL For New Fonts DisplaySize: -48 AntiAlias: 1 FitToEm: 0 -WinInfo: 0 38 14 +WinInfo: 0 35 14 BeginPrivate: 0 EndPrivate TeXData: 1 0 0 346030 173015 115343 0 1048576 115343 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144 -BeginChars: 1114112 11 +BeginChars: 1114112 14 StartChar: uni2328 Encoding: 9000 9000 0 @@ -637,7 +637,106 @@ SplineSet 819.797851562 633.625 l 2 828.08203125 633.624023438 834.796875 626.909179688 834.797851562 618.625 c 2 EndSplineSet -Validated: 524289 +Validated: 1 +EndChar + +StartChar: uni2B60 +Encoding: 11104 11104 11 +Width: 1000 +HStem: 219.932 160.131<434.739 979.995> +LayerCount: 2 +Fore +SplineSet +420.047851562 634.794921875 m 0 + 428.2109375 634.625 434.740234375 627.958984375 434.739257812 619.794921875 c 2 + 434.739257812 395.0625 l 2 + 434.740234375 386.778320312 441.455078125 380.063476562 449.739257812 380.0625 c 2 + 964.995117188 380.0625 l 2 + 973.279296875 380.061523438 979.994140625 373.346679688 979.995117188 365.0625 c 2 + 979.995117188 234.931640625 l 2 + 979.994140625 226.647460938 973.279296875 219.932617188 964.995117188 219.931640625 c 2 + 449.739257812 219.931640625 l 2 + 441.455078125 219.930664062 434.740234375 213.215820312 434.739257812 204.931640625 c 2 + 434.739257812 -19.80078125 l 2 + 434.731445312 -32.408203125 420.120117188 -39.3857421875 410.311523438 -31.46484375 c 2 + 25.4970703125 288.333984375 l 2 + 18.068359375 294.337890625 18.068359375 305.6640625 25.4970703125 311.66796875 c 2 + 410.311523438 631.466796875 l 2 + 413.063476562 633.689453125 416.51171875 634.868164062 420.047851562 634.794921875 c 0 +EndSplineSet +EndChar + +StartChar: uni2B62 +Encoding: 11106 11106 12 +Width: 1000 +HStem: 219.932 160.131<19.9258 565.182> +LayerCount: 2 +Fore +SplineSet +579.873046875 634.794921875 m 0 + 583.409179688 634.868164062 586.857421875 633.689453125 589.609375 631.466796875 c 2 + 974.423828125 311.66796875 l 2 + 981.852539062 305.6640625 981.852539062 294.337890625 974.423828125 288.333984375 c 2 + 589.609375 -31.46484375 l 2 + 579.80078125 -39.3857421875 565.189453125 -32.408203125 565.181640625 -19.80078125 c 2 + 565.181640625 204.931640625 l 2 + 565.180664062 213.215820312 558.465820312 219.930664062 550.181640625 219.931640625 c 2 + 34.92578125 219.931640625 l 2 + 26.6416015625 219.932617188 19.9267578125 226.647460938 19.92578125 234.931640625 c 2 + 19.92578125 365.0625 l 2 + 19.9267578125 373.346679688 26.6416015625 380.061523438 34.92578125 380.0625 c 2 + 550.181640625 380.0625 l 2 + 558.465820312 380.063476562 565.180664062 386.778320312 565.181640625 395.0625 c 2 + 565.181640625 619.794921875 l 2 + 565.180664062 627.958984375 571.7109375 634.625 579.873046875 634.794921875 c 0 +EndSplineSet +EndChar + +StartChar: u1FA9F +Encoding: 129695 129695 13 +Width: 1000 +HStem: -180.002 439.97<20.001 459.968 540.034 980.001> 340.034 439.97<20.001 459.968 540.034 980.001> +VStem: 20.001 439.967<-180.002 259.968 340.034 780.004> 540.034 439.967<-180.002 259.968 340.034 780.004> +LayerCount: 2 +Fore +SplineSet +546.908203125 259.967773438 m 2 + 973.126953125 259.967773438 l 2 + 976.934570312 259.967773438 980.000976562 256.90234375 980.000976562 253.09375 c 2 + 980.000976562 -173.127929688 l 2 + 980.000976562 -176.935546875 976.934570312 -180.001953125 973.126953125 -180.001953125 c 2 + 546.908203125 -180.001953125 l 2 + 543.099609375 -180.001953125 540.034179688 -176.935546875 540.034179688 -173.127929688 c 2 + 540.034179688 253.09375 l 2 + 540.034179688 256.90234375 543.099609375 259.967773438 546.908203125 259.967773438 c 2 +26.8759765625 259.967773438 m 2 + 453.09375 259.967773438 l 2 + 456.901367188 259.967773438 459.967773438 256.90234375 459.967773438 253.09375 c 2 + 459.967773438 -173.127929688 l 2 + 459.967773438 -176.935546875 456.901367188 -180.001953125 453.09375 -180.001953125 c 2 + 26.8759765625 -180.001953125 l 2 + 23.0673828125 -180.001953125 20.0009765625 -176.935546875 20.0009765625 -173.127929688 c 2 + 20.0009765625 253.09375 l 2 + 20.0009765625 256.90234375 23.0673828125 259.967773438 26.8759765625 259.967773438 c 2 +546.908203125 780.00390625 m 2 + 973.126953125 780.00390625 l 2 + 976.934570312 780.00390625 980.000976562 776.9375 980.000976562 773.12890625 c 2 + 980.000976562 346.909179688 l 2 + 980.000976562 343.100585938 976.934570312 340.034179688 973.126953125 340.034179688 c 2 + 546.908203125 340.034179688 l 2 + 543.099609375 340.034179688 540.034179688 343.100585938 540.034179688 346.909179688 c 2 + 540.034179688 773.12890625 l 2 + 540.034179688 776.9375 543.099609375 780.00390625 546.908203125 780.00390625 c 2 +26.8759765625 780.00390625 m 2 + 453.09375 780.00390625 l 2 + 456.901367188 780.00390625 459.967773438 776.9375 459.967773438 773.12890625 c 2 + 459.967773438 346.909179688 l 2 + 459.967773438 343.100585938 456.901367188 340.034179688 453.09375 340.034179688 c 2 + 26.8759765625 340.034179688 l 2 + 23.0673828125 340.034179688 20.0009765625 343.100585938 20.0009765625 346.909179688 c 2 + 20.0009765625 773.12890625 l 2 + 20.0009765625 776.9375 23.0673828125 780.00390625 26.8759765625 780.00390625 c 2 +EndSplineSet EndChar EndChars EndSplineFont diff --git a/keysyms.go b/keysyms.go index dbafa70..497cf02 100644 --- a/keysyms.go +++ b/keysyms.go @@ -26,6 +26,8 @@ import "errors" type Keysym int32 const ( + // X11/keysymdef.h + xkSuperL Keysym = 0xffeb // X11/XF86keysym.h xf86xkAudioLowerVolume Keysym = 0x1008ff11 xf86xkAudioMute Keysym = 0x1008ff12 @@ -33,6 +35,8 @@ const ( xf86xkAudioPlay Keysym = 0x1008ff14 xf86xkAudioPrev Keysym = 0x1008ff16 xf86xkAudioNext Keysym = 0x1008ff17 + xf86xkBack Keysym = 0x1008ff26 + xf86xkForward Keysym = 0x1008ff27 ) func RuneToKeysym(runeValue rune) (Keysym, error) { @@ -51,6 +55,9 @@ func RuneToKeysym(runeValue rune) (Keysym, error) { } func KeyToKeysym(key Key) (Keysym, error) { + if key == KeySuper { + return xkSuperL, nil + } if key == KeyVolumeMute { return xf86xkAudioMute, nil } @@ -69,5 +76,11 @@ func KeyToKeysym(key Key) (Keysym, error) { if key == KeyMediaNextTrack { return xf86xkAudioNext, nil } + if key == KeyBrowserBack { + return xf86xkBack, nil + } + if key == KeyBrowserForward { + return xf86xkForward, nil + } return 0, errors.New("key not mapped to keysym") } diff --git a/webdata/fn.js b/webdata/fn.js index f9f5394..4a60604 100644 --- a/webdata/fn.js +++ b/webdata/fn.js @@ -39,6 +39,9 @@ const KEY_VOLUME_UP = 2; const KEY_MEDIA_PLAY_PAUSE = 3; const KEY_MEDIA_PREV_TRACK = 4; const KEY_MEDIA_NEXT_TRACK = 5; +const KEY_BROWSER_BACK = 6; +const KEY_BROWSER_FORWARD = 7; +const KEY_SUPER = 8; let ws; let pad; @@ -381,7 +384,10 @@ window.addEventListener("load", function() { requestFullscreen(document.documentElement, {navigationUI: "hide"}); } }); - [{id: "prevtrackbutton", key: KEY_MEDIA_PREV_TRACK}, + [{id: "browserbackbutton", key: KEY_BROWSER_BACK}, + {id: "superbutton", key: KEY_SUPER}, + {id: "browserforwardbutton", key: KEY_BROWSER_FORWARD}, + {id: "prevtrackbutton", key: KEY_MEDIA_PREV_TRACK}, {id: "playpausebutton", key: KEY_MEDIA_PLAY_PAUSE}, {id: "nexttrackbutton", key: KEY_MEDIA_NEXT_TRACK}, {id: "volumedownbutton", key: KEY_VOLUME_DOWN}, diff --git a/webdata/icon.woff b/webdata/icon.woff index c485e05bd95a013410ca82744e7a51e1ccd4f9cd..0a6cd81faa77d3ae6e909135215f96789eddc6cc 100644 GIT binary patch delta 4897 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 delta 4485 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