Skip to content

Instantly share code, notes, and snippets.

@akemin-dayo
Last active February 21, 2023 23:49
Show Gist options
  • Save akemin-dayo/44ccf96a892c2219f6c9f12a7bd966cc to your computer and use it in GitHub Desktop.
Save akemin-dayo/44ccf96a892c2219f6c9f12a7bd966cc to your computer and use it in GitHub Desktop.
An extremely simple tool for macOS (Linux version also available) that simply simulates typing out the contents of your clipboard into apps that do not support clipboard sharing, like NVIDIA GeForce NOW.
#!/usr/bin/env bash
# gfnpaste-macos
# Karen/あけみ (akemin_dayo)
# https://gist.github.com/akemin-dayo/44ccf96a892c2219f6c9f12a7bd966cc.git
# This is an extremely simple tool for macOS (Linux version also available) that simply simulates typing out the contents of your clipboard into apps that do not support clipboard sharing, like NVIDIA GeForce NOW.
# Such apps include:
# * NVIDIA GeForce NOW (GeForceNOW.app) - No clipboard sharing support.
# * Parsec (Parsec.app) — Clipboard sharing is only enabled when connecting to your own machine, and is disabled when connecting to someone else's.
# * Moonlight (Moonlight.app) - No clipboard sharing support.
# I pretty much wrote this in like 5 minutes for a friend of mine, since she wanted to play Genshin via GeForce NOW, but found it really annoying to always have to manually type in her long, randomly-generated password for her miHoYo account every single time she launches the game.
# I just thought I'd share this here for anyone else that may also find this useful.
# If I have some more free time, I might consider implementing this in a simple app instead so you can trigger a "paste" with a global keyboard shortcut instead.
# ※ EDIT: … Apparently, for GeForce NOW, you can actually enable a somewhat-hidden "native keyboard input" (Command-K) option if you change your keyboard layout in the settings to "Other (not listed)". Why this feature is disabled otherwise is beyond me.
# If you're using Linux, use gfnpaste-linux from https://gist.github.com/akemin-dayo/d8af6d14f6bf9ffb62549eeb64929b15.git
# If you're using Windows, here's an AutoHotKey implementation (not written by me): https://github.com/AlejandroAkbal/Geforce-Now-Paste-Clipboard
# How to use:
# * Launch a game via NVIDIA GeForce NOW (or connect to another machine via Parsec or Moonlight, whatever app that you're using this tool with.)
# * If you're not using this with GeForce NOW, change the "appName" variable below in the configuration section.
# * Open a Terminal session and run this tool.
# Limitations:
# * Since this tool simulates keystrokes, it can generally only "paste" clipboard content made up of plain ASCII characters that don't require special key combinations or an IME to input.
# * This means it's generally fine for the vast majority of passwords, but it will not work for things like Unicode characters that require an IME (あいうえお) or accented characters that require key combinations (äïüëö).
# * This also won't work for special symbols that require Alt-key combinations, such as ™ (Alt-2), ∞ (Alt-5), etc.
{
# -------------------------------- Configuration -------------------------------- #
# Set this to the name of the macOS app that you would like to paste into.
appName="GeForceNOW.app"
# appName="Parsec.app"
# appName="Moonlight.app"
# Set this to a higher value if you're finding that the first few characters of your pasted text are getting cut off.
delaySecondsBeforePasting=0
# -------------------------------- Actual code starts here -------------------------------- #
export COLOUR_CYANBOLD="\033[36;1m"
export COLOUR_REDBOLD="\033[31;1m"
export COLOUR_GREENBOLD="\033[32;1m"
export COLOUR_YELLOWBOLD="\033[33;1m"
export COLOUR_BOLD="\033[1m"
export COLOUR_RESET="\033[0m"
KarenLog() {
echo -e "${COLOUR_CYANBOLD}[🍍 gfnpaste-macos]${COLOUR_RESET} $@"
}
KarenError() {
echo -e "${COLOUR_CYANBOLD}[🍍 gfnpaste-macos]${COLOUR_RESET} ${COLOUR_REDBOLD}[ERROR]${COLOUR_RESET} $@"
}
# Check platform
if [[ "${OSTYPE}" != "darwin"* ]]; then
KarenError "This version of gfnpaste (gfnpaste-macos) is only compatible with macOS."
if [[ "${OSTYPE}" == "linux-gnu"* ]]; then
KarenError "A Linux-compatible version of gfnpaste (gfnpaste-linux) is available at: https://gist.github.com/akemin-dayo/d8af6d14f6bf9ffb62549eeb64929b15.git"
fi
exit 1
fi
# Check pasteboard contents
pasteboardContents="$(pbpaste)"
if [[ ${#pasteboardContents} == 0 ]]; then
KarenError "The clipboard is either empty, or contains something other than valid text string data!"
exit 1
fi
# Set current focused application to the configured app above
open -a "${appName}"
# I had initially thought a delay would be required in order to compensate for the app switching animation, but it turns out all of the apps above start accepting input immediately after they gain focus.
# Set the delay in the configuration section above if you're finding that the first few characters of your pasted text are getting cut off.
sleep "${delaySecondsBeforePasting}"
for ((i = 0; i < ${#pasteboardContents}; i++)); do
currentPasteboardCharacter="${pasteboardContents:$i:1}"
# We must translate certain characters to Carbon scan codes in order for this to work correctly.
# This is because AppleScript's "keystroke" call will actually use kVK_ANSI_Keypad and kVK_JIS_Keypad scan codes by default.
# As a result, unintended behaviour can occur, such as the number 6 being translated to a right-arrow key.
# Carbon scan code reference from HIToolbox.framework headers: https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.6.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h#L183
# Test string: 0123456789\./-=,*+"'{}[]!@#$%^&*()|:;?<>~`
case "${currentPasteboardCharacter}" in
"0")
# kVK_ANSI_Keypad0 (0x52) → kVK_ANSI_0 (0x1D)
osascript -e "tell application \"System Events\" to key code {29}"
;;
"1")
# kVK_ANSI_Keypad1 (0x53) → kVK_ANSI_1 (0x12)
osascript -e "tell application \"System Events\" to key code {18}"
;;
"2")
# kVK_ANSI_Keypad2 (0x54) → kVK_ANSI_2 (0x13)
osascript -e "tell application \"System Events\" to key code {19}"
;;
"3")
# kVK_ANSI_Keypad3 (0x55) → kVK_ANSI_3 (0x14)
osascript -e "tell application \"System Events\" to key code {20}"
;;
"4")
# kVK_ANSI_Keypad4 (0x56) → kVK_ANSI_4 (0x15)
osascript -e "tell application \"System Events\" to key code {21}"
;;
"5")
# kVK_ANSI_Keypad5 (0x57) → kVK_ANSI_5 (0x17)
osascript -e "tell application \"System Events\" to key code {23}"
;;
"6")
# kVK_ANSI_Keypad6 (0x58) → kVK_ANSI_6 (0x16)
osascript -e "tell application \"System Events\" to key code {22}"
;;
"7")
# kVK_ANSI_Keypad7 (0x59) → kVK_ANSI_7 (0x1A)
osascript -e "tell application \"System Events\" to key code {26}"
;;
"8")
# kVK_ANSI_Keypad8 (0x5B) → kVK_ANSI_8 (0x1C)
osascript -e "tell application \"System Events\" to key code {28}"
;;
"9")
# kVK_ANSI_Keypad9 (0x5C) → kVK_ANSI_9 (0x19)
osascript -e "tell application \"System Events\" to key code {25}"
;;
".")
# kVK_ANSI_KeypadDecimal (0x41) → kVK_ANSI_Period (0x2F)
osascript -e "tell application \"System Events\" to key code {47}"
;;
"/")
# kVK_ANSI_KeypadDivide (0x4B) → kVK_ANSI_Slash (0x2C)
osascript -e "tell application \"System Events\" to key code {44}"
;;
"-")
# kVK_ANSI_KeypadMinus (0x4E) → kVK_ANSI_Minus (0x1B)
osascript -e "tell application \"System Events\" to key code {27}"
;;
"=")
# kVK_ANSI_KeypadEquals (0x51) → kVK_ANSI_Equal (0x18)
osascript -e "tell application \"System Events\" to key code {24}"
;;
",")
# kVK_JIS_KeypadComma (0x5F) → kVK_ANSI_Comma (0x2B)
osascript -e "tell application \"System Events\" to key code {43}"
;;
"\\")
# kVK_ANSI_Backslash (0x2A)
osascript -e "tell application \"System Events\" to key code {42}"
;;
"\"")
# Shift + kVK_ANSI_Quote (0x27)
osascript -e "tell application \"System Events\" to key code {39} using {shift down}"
;;
*)
osascript -e "tell application \"System Events\" to keystroke \"${currentPasteboardCharacter}\""
;;
esac
done
KarenLog "Done!"
exit
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment