Last active
November 6, 2024 14:02
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm having some issues getting
sleepwatcher
to run this automatically, however, the script works pretty well when you call it manually.