Skip to content

Instantly share code, notes, and snippets.

@jmealo
Last active November 6, 2024 14:02
Show Gist options
  • Save jmealo/f51c6c6267944fda25d59ecc91f6d0eb to your computer and use it in GitHub Desktop.
Save jmealo/f51c6c6267944fda25d59ecc91f6d0eb to your computer and use it in GitHub Desktop.
Workaround for JetBrains and Electron-based Apps not rendering (black, pink or white) screen after waking from sleep on MacOS
brew install sleepwatcher
# write restart_apps.sh to ~/.wakeup
chmod +x ~/.wakeup
brew services start sleepwatcher
# your mileage may vary getting sleepwatcher to run the script, but, the script should work if executed manually
#!/usr/bin/env bash
# Create an array to store running apps
declare -a running_apps
# Array of all JetBrains apps with their display names and executable names
declare -A jetbrains_apps=(
["CLion"]="clion"
["RustRover"]="rustrover"
["DataGrip"]="datagrip"
["WebStorm"]="webstorm"
["Gateway"]="gateway"
["Writerside"]="writerside"
["GoLand"]="goland"
["Fleet"]="fleet"
["DataSpell"]="dataspell"
["PhpStorm"]="phpstorm"
["RubyMine"]="rubymine"
["AppCode"]="appcode"
["MPS"]="mps"
["Android_Studio"]="studio"
["Rider"]="rider"
)
# Array of Electron apps
declare -A electron_apps=(
["Discord"]="Discord"
["WhatsApp"]="WhatsApp"
["Microsoft_Teams"]="Microsoft Teams"
["Microsoft_Teams_-_Preview"]="Microsoft Teams - Preview"
["Microsoft_Teams_-_Beta"]="Microsoft Teams - Beta"
["Microsoft_Teams_-_Insider"]="Microsoft Teams - Insider"
["Telegram"]="Telegram"
)
# Function to check if an app is running and add it to the array
check_and_store_app() {
local display_name=$1
local process_pattern=$2
if pgrep -f "$process_pattern" > /dev/null; then
running_apps+=("$display_name")
echo "Found running: $display_name"
fi
}
# Function to convert display name with spaces
display_name_with_spaces() {
echo "${1//_/ }"
}
# Check JetBrains apps
for app_key in "${!jetbrains_apps[@]}"; do
executable="${jetbrains_apps[$app_key]}"
display_name=$(display_name_with_spaces "$app_key")
# Check for Gateway/JetBrains Client instance
check_and_store_app "${display_name} Gateway" "JetBrainsClient.*${executable}"
# Check for local instance
check_and_store_app "$display_name" "/Applications/${display_name}.app/Contents/MacOS/${executable}"
done
# Check PyCharm instances
mapfile -t pycharm_processes < <(ps aux | grep -i "pycharm" | grep -v "grep" | awk '{print $11}' | sort -u)
for process in "${pycharm_processes[@]}"; do
if [[ "$process" =~ "JetBrainsClient" ]]; then
check_and_store_app "PyCharm Gateway" "$process"
else
app_name=$(echo "$process" | sed -E 's|/[^/]+\.app/Contents/MacOS/pycharm||')
app_name=$(echo "$app_name" | sed -E 's|/[^/]+\.app/Contents/bin/fsnotifier||')
app_name=$(echo "$app_name" | sed -E 's|/[^/]+\.app/Contents/plugins/||')
if [[ "$process" =~ "Professional" ]]; then
check_and_store_app "PyCharm Professional" "$app_name"
elif [[ "$process" =~ "Community" ]]; then
check_and_store_app "PyCharm Community" "$app_name"
else
check_and_store_app "PyCharm" "$app_name"
fi
fi
done
# Check IntelliJ IDEA instances
mapfile -t intellij_processes < <(ps aux | grep -i "intellij" | grep -v "grep" | grep -v "copilot" | awk '{print $11}' | sort -u)
for process in "${intellij_processes[@]}"; do
if [[ "$process" =~ "JetBrainsClient" ]]; then
check_and_store_app "IntelliJ IDEA Gateway" "$process"
else
if [[ "$process" =~ "Ultimate" ]]; then
check_and_store_app "IntelliJ IDEA Ultimate" "$process"
elif [[ "$process" =~ "Community" ]]; then
check_and_store_app "IntelliJ IDEA Community" "$process"
else
# Check the full path for Ultimate/Community if not in process name
if [[ "$process" =~ "Ultimate.app" ]]; then
check_and_store_app "IntelliJ IDEA Ultimate" "$process"
elif [[ "$process" =~ "Community.app" ]]; then
check_and_store_app "IntelliJ IDEA Community" "$process"
else
check_and_store_app "IntelliJ IDEA" "$process"
fi
fi
fi
done
# Check specific Electron apps
for app_key in "${!electron_apps[@]}"; do
app_name="${electron_apps[$app_key]}"
check_and_store_app "$app_name" "$app_name"
done
# Check for other Electron apps
mapfile -t electron_processes < <(ps aux | grep -E "/[^/]+\.app/Contents/Frameworks/Electron Framework" | awk '{print $11}' | sort -u)
for process in "${electron_processes[@]}"; do
app_name=$(echo "$process" | sed -E 's|/[^/]+\.app/Contents/Frameworks/Electron Framework||')
check_and_store_app "$app_name" "$app_name"
done
# Kill non-Electron app processes
for app in "${running_apps[@]}"; do
if ! printf '%s\n' "${electron_apps[@]}" | grep -qxF "$app"; then
echo "Killing $app..."
pkill -f "$app"
fi
done
# Kill Electron apps gracefully
for app in "${running_apps[@]}"; do
if printf '%s\n' "${electron_apps[@]}" | grep -qxF "$app" || [[ " ${electron_processes[@]} " =~ " $app " ]]; then
echo "Closing $app gracefully..."
osascript -e "quit app \"$app\"" || echo "Failed to close $app gracefully"
fi
done
# Wait for processes to close
sleep 2
# Reopen only the apps that were running
for app in "${running_apps[@]}"; do
echo "Reopening $app..."
case "$app" in
"PyCharm Gateway")
open -a "Gateway.app"
;;
"PyCharm Professional")
open -a "PyCharm Professional.app"
;;
"PyCharm Community")
open -a "PyCharm Community Edition.app"
;;
"PyCharm")
open -a "PyCharm.app"
;;
"IntelliJ IDEA Gateway")
open -a "Gateway.app"
;;
"IntelliJ IDEA Ultimate")
open -a "IntelliJ IDEA Ultimate.app"
;;
"IntelliJ IDEA Community")
open -a "IntelliJ IDEA Community Edition.app"
;;
"IntelliJ IDEA")
open -a "IntelliJ IDEA.app"
;;
*)
if printf '%s\n' "${electron_apps[@]}" | grep -qxF "$app" || [[ " ${electron_processes[@]} " =~ " $app " ]]; then
open -a "$app.app"
else
case "$app" in
*"Gateway")
open -a "Gateway.app"
;;
*" "*)
open -a "${app}.app"
;;
*)
open -a "$app.app"
;;
esac
fi
;;
esac
done
@jmealo
Copy link
Author

jmealo commented Nov 6, 2024

I'm having some issues getting sleepwatcher to run this automatically, however, the script works pretty well when you call it manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment