#!/bin/bash cat <//")) if [[ "${#gDisplayInf[@]}" -ge 2 ]]; then # Multi monitors detected. Choose target monitor. echo "" echo " "${langMonitors}" " echo "--------------------------------------------------------" echo " "${langIndex}" | "${langVendorID}" | "${langProductID}" | "${langMonitorName}" " echo "--------------------------------------------------------" # Show monitors. for display in "${gDisplayInf[@]}"; do let index++ MonitorName=("$(echo ${display:190:24} | xxd -p -r)") VendorID=${display:16:4} ProductID=${display:22:2}${display:20:2} if [[ ${VendorID} == 0610 ]]; then MonitorName="Apple Display" fi if [[ ${VendorID} == 1e6d ]]; then MonitorName="LG Display" fi printf " %d | ${VendorID} | ${ProductID} | ${MonitorName}\n" ${index} done echo "--------------------------------------------------------" # Let user make a selection. read -p "${langChooseDis}: " selection case $selection in [[:digit:]]*) # Lower selection (arrays start at zero). if ((selection < 1 || selection > index)); then echo "${langEnterError}" exit 1 fi let selection-=1 gMonitor=${gDisplayInf[$selection]} ;; *) echo "${langEnterError}" exit 1 ;; esac else gMonitor=${gDisplayInf} fi EDID=${gMonitor} VendorID=$((0x${gMonitor:16:4})) ProductID=$((0x${gMonitor:22:2}${gMonitor:20:2})) Vid=($(printf '%x\n' ${VendorID})) Pid=($(printf '%x\n' ${ProductID})) # echo ${Vid} # echo ${Pid} # echo $EDID } # For Apple silicon there is no EDID. Get VID/PID in other way function get_vidpid_applesilicon() { local index=0 local prodnamesindex=0 local selection=0 # Apple ioreg display class local appleDisplClass='AppleCLCD2' # XPath as key.val local value="/following-sibling::*[1]" local get="/text()" # XPath keys local displattr="/key[.='DisplayAttributes']" local prodattr="/key[.='ProductAttributes']" local vendid="/key[.='LegacyManufacturerID']" local prodid="/key[.='ProductID']" local prodname="/key[.='ProductName']" # VID/PID/Prodname local prodAttrsQuery="/$displattr$value$prodattr$value" local vendIDQuery="$prodAttrsQuery$vendid$value$get" local prodIDQuery="$prodAttrsQuery$prodid$value$get" local prodNameQuery="$prodAttrsQuery$prodname$value$get" # Get VIDs, PIDs, Prodnames local vends=($(ioreg -arw0 -d1 -c $appleDisplClass | xpath -q -n -e "$vendIDQuery")) local prods=($(ioreg -arw0 -d1 -c $appleDisplClass | xpath -q -n -e "$prodIDQuery")) set -o noglob IFS=$'\n' prodnames=($(ioreg -arw0 -d1 -c $appleDisplClass | xpath -q -n -e "$prodNameQuery")) set +o noglob if [[ "${#prods[@]}" -ge 2 ]]; then # Multi monitors detected. Choose target monitor. echo "" echo " "${langMonitors}" " echo "------------------------------------------------------------" echo " "${langIndex}" | "${langVendorID}" | "${langProductID}" | "${langMonitorName}" " echo "------------------------------------------------------------" # Show monitors. for prod in "${prods[@]}"; do MonitorName=${prodnames[$prodnamesindex]} VendorID=$(printf "%04x" ${vends[$index]}) ProductID=$(printf "%04x" ${prods[$index]}) let index++ let prodnamesindex++ if [[ ${VendorID} == 0610 ]]; then MonitorName="Apple Display" # No name in prodnames variable for internal display let prodnamesindex-- fi if [[ ${VendorID} == 1e6d ]]; then MonitorName="LG Display" fi printf " %-3d | ${VendorID} | %-12s | ${MonitorName}\n" ${index} ${ProductID} done echo "------------------------------------------------------------" # Let user make a selection. read -p "${langChooseDis}: " selection case $selection in [[:digit:]]*) # Lower selection (arrays start at zero). if ((selection < 1 || selection > index)); then echo "${langEnterError}" exit 1 fi let selection-=1 dispid=$selection ;; *) echo "${langEnterError}" exit 1 ;; esac else # One monitor detected dispid=0 fi VendorID=${vends[$dispid]} ProductID=${prods[$dispid]} Vid=($(printf '%x\n' ${VendorID})) Pid=($(printf '%x\n' ${ProductID})) } # init function init() { rm -rf ${currentDir}/tmp/ mkdir -p ${currentDir}/tmp/ libDisplaysDir="/Library/Displays" targetDir="${libDisplaysDir}/Contents/Resources/Overrides" sysDisplayDir="/System${targetDir}" Overrides="\/Library\/Displays\/Contents\/Resources\/Overrides" sysOverrides="\/System${Overrides}" if [[ ! -d "${targetDir}" ]]; then sudo mkdir -p "${targetDir}" fi downloadHost="https://raw.githubusercontent.com/xzhih/one-key-hidpi/master" if [ -d "${currentDir}/displayIcons" ]; then downloadHost="file://${currentDir}" fi DICON="com\.apple\.cinema-display" imacicon=${sysOverrides}"\/DisplayVendorID\-610\/DisplayProductID\-a032\.tiff" mbpicon=${sysOverrides}"\/DisplayVendorID\-610\/DisplayProductID\-a030\-e1e1df\.tiff" mbicon=${sysOverrides}"\/DisplayVendorID\-610\/DisplayProductID\-a028\-9d9da0\.tiff" lgicon=${sysOverrides}"\/DisplayVendorID\-1e6d\/DisplayProductID\-5b11\.tiff" proxdricon=${Overrides}"\/DisplayVendorID\-610\/DisplayProductID\-ae2f\_Landscape\.tiff" if [[ $is_applesilicon == true ]]; then get_vidpid_applesilicon else get_edid fi # Check if monitor was found if [[ -z $VendorID || -z $ProductID || $VendorID == 0 || $ProductID == 0 ]]; then echo "$langNoMonitFound" exit 2 fi echo "$langMonitVIDPID $Vid:$Pid" # Finally generate restore command generate_restore_cmd } # function generate_restore_cmd() { if [[ $is_applesilicon == true ]]; then cat >"$(cd && pwd)/.hidpi-disable" <<-\CCC #!/bin/bash function get_vidpid_applesilicon() { local index=0 local prodnamesindex=0 local selection=0 # Apple ioreg display class local appleDisplClass='AppleCLCD2' # XPath as key.val local value="/following-sibling::*[1]" local get="/text()" # XPath keys local displattr="/key[.='DisplayAttributes']" local prodattr="/key[.='ProductAttributes']" local vendid="/key[.='LegacyManufacturerID']" local prodid="/key[.='ProductID']" local prodname="/key[.='ProductName']" # VID/PID/Prodname local prodAttrsQuery="/$displattr$value$prodattr$value" local vendIDQuery="$prodAttrsQuery$vendid$value$get" local prodIDQuery="$prodAttrsQuery$prodid$value$get" local prodNameQuery="$prodAttrsQuery$prodname$value$get" # Get VIDs, PIDs, Prodnames local vends=($(ioreg -arw0 -d1 -c $appleDisplClass | xpath -q -n -e "$vendIDQuery")) local prods=($(ioreg -arw0 -d1 -c $appleDisplClass | xpath -q -n -e "$prodIDQuery")) set -o noglob IFS=$'\n' prodnames=($(ioreg -arw0 -d1 -c $appleDisplClass | xpath -q -n -e "$prodNameQuery")) set +o noglob if [[ "${#prods[@]}" -ge 2 ]]; then echo ' Monitors ' echo '------------------------------------' echo ' Index | VendorID | ProductID ' echo '------------------------------------' # Show monitors. for prod in "${prods[@]}"; do MonitorName=${prodnames[$prodnamesindex]} VendorID=$(printf "%04x" ${vends[$index]}) ProductID=$(printf "%04x" ${prods[$index]}) let index++ let prodnamesindex++ if [[ ${VendorID} == 0610 ]]; then MonitorName="Apple Display" let prodnamesindex-- fi printf " %d | ${VendorID} | ${ProductID} | ${MonitorName}\n" ${index} done echo "------------------------------------" # Let user make a selection. read -p "Choose the display:" selection case $selection in [[:digit:]]*) if ((selection < 1 || selection > index)); then echo "Enter error, bye" exit 1 fi let selection-=1 dispid=$selection ;; *) echo "Enter error, bye" exit 1 ;; esac else # One monitor detected dispid=0 fi VendorID=${vends[$dispid]} ProductID=${prods[$dispid]} Vid=($(printf '%x\n' ${VendorID})) Pid=($(printf '%x\n' ${ProductID})) } get_vidpid_applesilicon CCC else cat >"$(cd && pwd)/.hidpi-disable" <<-\CCC #!/bin/sh function get_edid() { local index=0 local selection=0 gDisplayInf=($(ioreg -lw0 | grep -i "IODisplayEDID" | sed -e "/[^<]*//")) if [[ "${#gDisplayInf[@]}" -ge 2 ]]; then echo ' Monitors ' echo '------------------------------------' echo ' Index | VendorID | ProductID ' echo '------------------------------------' for display in "${gDisplayInf[@]}"; do let index++ printf " %d | ${display:16:4} | ${display:22:2}${display:20:2}\n" $index done echo '------------------------------------' read -p "Choose the display: " selection case $selection in [[:digit:]]*) if ((selection < 1 || selection > index)); then echo "Enter error, bye" exit 1 fi let selection-=1 gMonitor=${gDisplayInf[$selection]} ;; *) echo "Enter error, bye" exit 1 ;; esac else gMonitor=${gDisplayInf} fi EDID=$gMonitor VendorID=$((0x${gMonitor:16:4})) ProductID=$((0x${gMonitor:22:2}${gMonitor:20:2})) Vid=($(printf '%x\n' ${VendorID})) Pid=($(printf '%x\n' ${ProductID})) } get_edid CCC fi cat >>"$(cd && pwd)/.hidpi-disable" <<-\CCC # Check if monitor was found if [[ -z $VendorID || -z $ProductID || $VendorID == 0 || $ProductID == 0 ]]; then echo "No monitors found. Exiting..." exit 2 fi echo "Your monitor VID/PID: $Vid:$Pid" rootPath="../.." restorePath="${rootPath}/Library/Displays/Contents/Resources/Overrides" echo "" echo "(1) Disable HIDPI on this monitor" echo "(2) Reset all settings to macOS default" echo "" read -p "Enter your choice [1~2]: " input case ${input} in 1) if [[ -f "${restorePath}/Icons.plist" ]]; then ${rootPath}/usr/libexec/plistbuddy -c "Delete :vendors:${Vid}:products:${Pid}" "${restorePath}/Icons.plist" fi if [[ -d "${restorePath}/DisplayVendorID-${Vid}" ]]; then rm -rf "${restorePath}/DisplayVendorID-${Vid}" fi ;; 2) rm -rf "${restorePath}" ;; *) echo "Enter error, bye" exit 1 ;; esac echo "HIDPI Disabled" CCC chmod +x "$(cd && pwd)/.hidpi-disable" } # choose_icon function choose_icon() { rm -rf ${currentDir}/tmp/ mkdir -p ${currentDir}/tmp/ mkdir -p ${currentDir}/tmp/DisplayVendorID-${Vid} curl -fsSL "${downloadHost}/Icons.plist" -o ${currentDir}/tmp/Icons.plist echo "" echo "-------------------------------------" echo "|********** ${langChooseIcon} ***********|" echo "-------------------------------------" echo "" echo "(1) iMac" echo "(2) MacBook" echo "(3) MacBook Pro" echo "(4) LG ${langDisplay}" echo "(5) Pro Display XDR" echo "(6) ${langNotChange}" echo "" read -p "${langInputChoice} [1~6]: " logo case ${logo} in 1) Picon=${imacicon} RP=("33" "68" "160" "90") curl -fsSL "${downloadHost}/displayIcons/iMac.icns" -o ${currentDir}/tmp/DisplayVendorID-${Vid}/DisplayProductID-${Pid}.icns ;; 2) Picon=${mbicon} RP=("52" "66" "122" "76") curl -fsSL "${downloadHost}/displayIcons/MacBook.icns" -o ${currentDir}/tmp/DisplayVendorID-${Vid}/DisplayProductID-${Pid}.icns ;; 3) Picon=${mbpicon} RP=("40" "62" "147" "92") curl -fsSL "${downloadHost}/displayIcons/MacBookPro.icns" -o ${currentDir}/tmp/DisplayVendorID-${Vid}/DisplayProductID-${Pid}.icns ;; 4) Picon=${lgicon} RP=("11" "47" "202" "114") cp ${sysDisplayDir}/DisplayVendorID-1e6d/DisplayProductID-5b11.icns ${currentDir}/tmp/DisplayVendorID-${Vid}/DisplayProductID-${Pid}.icns ;; 5) Picon=${proxdricon} RP=("5" "45" "216" "121") curl -fsSL "${downloadHost}/displayIcons/ProDisplayXDR.icns" -o ${currentDir}/tmp/DisplayVendorID-${Vid}/DisplayProductID-${Pid}.icns if [[ ! -f ${targetDir}/DisplayVendorID-610/DisplayProductID-ae2f_Landscape.tiff ]]; then curl -fsSL "${downloadHost}/displayIcons/ProDisplayXDR.tiff" -o ${currentDir}/tmp/DisplayVendorID-${Vid}/DisplayProductID-${Pid}.tiff Picon=${Overrides}"\/DisplayVendorID\-${Vid}\/DisplayProductID\-${Pid}\.tiff" fi ;; 6) rm -rf ${currentDir}/tmp/Icons.plist ;; *) echo "${langEnterError}" exit 1 ;; esac if [[ ${Picon} ]]; then DICON=${Overrides}"\/DisplayVendorID\-${Vid}\/DisplayProductID\-${Pid}\.icns" /usr/bin/sed -i "" "s/VID/${Vid}/g" ${currentDir}/tmp/Icons.plist /usr/bin/sed -i "" "s/PID/${Pid}/g" ${currentDir}/tmp/Icons.plist /usr/bin/sed -i "" "s/RPX/${RP[0]}/g" ${currentDir}/tmp/Icons.plist /usr/bin/sed -i "" "s/RPY/${RP[1]}/g" ${currentDir}/tmp/Icons.plist /usr/bin/sed -i "" "s/RPW/${RP[2]}/g" ${currentDir}/tmp/Icons.plist /usr/bin/sed -i "" "s/RPH/${RP[3]}/g" ${currentDir}/tmp/Icons.plist /usr/bin/sed -i "" "s/PICON/${Picon}/g" ${currentDir}/tmp/Icons.plist /usr/bin/sed -i "" "s/DICON/${DICON}/g" ${currentDir}/tmp/Icons.plist fi } # main function main() { sudo mkdir -p ${currentDir}/tmp/DisplayVendorID-${Vid} dpiFile=${currentDir}/tmp/DisplayVendorID-${Vid}/DisplayProductID-${Pid} sudo chmod -R 777 ${currentDir}/tmp/ cat >"${dpiFile}" <<-\CCC DisplayProductID PID DisplayVendorID VID IODisplayEDID EDid scale-resolutions CCC echo "" echo "------------------------------------------" echo "|********** "${langChooseRes}" ***********|" echo "------------------------------------------" echo ${langChooseResOp1} echo ${langChooseResOp2} echo ${langChooseResOp3} echo ${langChooseResOp4} echo ${langChooseResOp5} echo ${langChooseResOp6} echo ${langChooseResOpCustom} echo "" read -p "${langInputChoice}: " res case ${res} in 1) create_res_1 1680x945 1440x810 1280x720 1024x576 create_res_2 1280x800 1280x720 960x600 960x540 640x360 create_res_3 840x472 800x450 720x405 640x360 576x324 512x288 420x234 400x225 320x180 create_res_4 1680x945 1440x810 1280x720 1024x576 960x540 840x472 800x450 640x360 ;; 2) create_res_1 1680x945 1424x802 1280x720 1024x576 create_res_2 1280x800 1280x720 960x600 960x540 640x360 create_res_3 840x472 800x450 720x405 640x360 576x324 512x288 420x234 400x225 320x180 create_res_4 1680x945 1440x810 1280x720 1024x576 960x540 840x472 800x450 640x360 ;; 3) create_res_1 1680x1050 1440x900 1280x800 1024x640 create_res_2 1280x800 1280x720 960x600 960x540 640x360 create_res_3 840x472 800x450 720x405 640x360 576x324 512x288 420x234 400x225 320x180 create_res_4 1680x1050 1440x900 1280x800 1024x640 960x540 840x472 800x450 640x360 ;; 4) create_res_1 2560x1440 2048x1152 1920x1080 1760x990 1680x945 1440x810 1360x765 1280x720 create_res_2 1360x765 1280x800 1280x720 1024x576 960x600 960x540 640x360 create_res_3 960x540 840x472 800x450 720x405 640x360 576x324 512x288 420x234 400x225 320x180 create_res_4 2048x1152 1920x1080 1680x945 1440x810 1280x720 1024x576 960x540 840x472 800x450 640x360 ;; 5) create_res_1 3000x2000 2880x1920 2250x1500 1920x1280 1680x1050 1440x900 1280x800 1024x640 create_res_2 1280x800 1280x720 960x600 960x540 640x360 create_res_3 840x472 800x450 720x405 640x360 576x324 512x288 420x234 400x225 320x180 create_res_4 1920x1280 1680x1050 1440x900 1280x800 1024x640 960x540 840x472 800x450 640x360 ;; 6) # Scale factors # res 1 scf: 1 1.25 1.3333 1.4545 1.7777 2 create_res_1 3440x1440 2752x1152 2580x1080 2365x990 1935x810 1720x720 # res 2 scf: 2 2.6666 create_res_2 1720x720 1290x540 # res 3 scf: 2.6666 create_res_3 1290x540 # res 4 scf: 1.25 1.3333 1.4545 1.7777 2 2.6666 create_res_4 2752x1152 2580x1080 2365x990 1935x810 1720x720 1290x540 ;; 7) custom_res create_res_2 1360x765 1280x800 1280x720 960x600 960x540 640x360 create_res_3 840x472 800x450 720x405 640x360 576x324 512x288 420x234 400x225 320x180 create_res_4 1680x945 1440x810 1280x720 1024x576 960x540 840x472 800x450 640x360 ;; *) echo "${langEnterError}" exit 1 ;; esac cat >>"${dpiFile}" <<-\FFF target-default-ppmm 10.0699301 FFF /usr/bin/sed -i "" "s/VID/$VendorID/g" ${dpiFile} /usr/bin/sed -i "" "s/PID/$ProductID/g" ${dpiFile} } # end function end() { sudo chown -R root:wheel ${currentDir}/tmp/ sudo chmod -R 0755 ${currentDir}/tmp/ sudo chmod 0644 ${currentDir}/tmp/DisplayVendorID-${Vid}/* sudo cp -r ${currentDir}/tmp/* ${targetDir}/ sudo rm -rf ${currentDir}/tmp sudo defaults write /Library/Preferences/com.apple.windowserver DisplayResolutionEnabled -bool YES echo "${langEnabled}" echo "${langEnabledLog}" } # custom resolution function custom_res() { echo "${langCustomRes}" read -p ":" res create_res ${res} } # create resolution function create_res() { for res in $@; do width=$(echo ${res} | cut -d x -f 1) height=$(echo ${res} | cut -d x -f 2) hidpi=$(printf '%08x %08x' $((${width} * 2)) $((${height} * 2)) | xxd -r -p | base64) # cat <>${dpiFile} ${hidpi:0:11}AAAAB ${hidpi:0:11}AAAABACAAAA== OOO done } function create_res_1() { for res in $@; do width=$(echo ${res} | cut -d x -f 1) height=$(echo ${res} | cut -d x -f 2) hidpi=$(printf '%08x %08x' $((${width} * 2)) $((${height} * 2)) | xxd -r -p | base64) # cat <>${dpiFile} ${hidpi:0:11}A OOO done } function create_res_2() { for res in $@; do width=$(echo ${res} | cut -d x -f 1) height=$(echo ${res} | cut -d x -f 2) hidpi=$(printf '%08x %08x' $((${width} * 2)) $((${height} * 2)) | xxd -r -p | base64) # cat <>${dpiFile} ${hidpi:0:11}AAAABACAAAA== OOO done } function create_res_3() { for res in $@; do width=$(echo ${res} | cut -d x -f 1) height=$(echo ${res} | cut -d x -f 2) hidpi=$(printf '%08x %08x' $((${width} * 2)) $((${height} * 2)) | xxd -r -p | base64) # cat <>${dpiFile} ${hidpi:0:11}AAAAB OOO done } function create_res_4() { for res in $@; do width=$(echo ${res} | cut -d x -f 1) height=$(echo ${res} | cut -d x -f 2) hidpi=$(printf '%08x %08x' $((${width} * 2)) $((${height} * 2)) | xxd -r -p | base64) # cat <>${dpiFile} ${hidpi:0:11}AAAAJAKAAAA== OOO done } # enable function enable_hidpi() { choose_icon main sed -i "" "/.*IODisplayEDID/d" ${dpiFile} sed -i "" "/.*EDid/d" ${dpiFile} end } # patch function enable_hidpi_with_patch() { choose_icon main version=${EDID:38:2} basicparams=${EDID:40:2} checksum=${EDID:254:2} newchecksum=$(printf '%x' $((0x${checksum} + 0x${version} + 0x${basicparams} - 0x04 - 0x90)) | tail -c 2) newedid=${EDID:0:38}0490${EDID:42:6}e6${EDID:50:204}${newchecksum} EDid=$(printf ${newedid} | xxd -r -p | base64) /usr/bin/sed -i "" "s:EDid:${EDid}:g" ${dpiFile} end } # disable function disable() { echo "" echo "${langDisableOpt1}" echo "${langDisableOpt2}" echo "" read -p "${langInputChoice} [1~2]: " input case ${input} in 1) if [[ -f "${targetDir}/Icons.plist" ]]; then sudo /usr/libexec/plistbuddy -c "Delete :vendors:${Vid}:products:${Pid}" "${targetDir}/Icons.plist" fi if [[ -d "${targetDir}/DisplayVendorID-${Vid}" ]]; then sudo rm -rf "${targetDir}/DisplayVendorID-${Vid}" fi ;; 2) sudo rm -rf "${targetDir}" ;; *) echo "${langEnterError}" exit 1 ;; esac echo "${langDisabled}" } # function start() { init echo "" let opt++; printf "${langEnableHIDPI}\n" $opt if [[ $is_applesilicon == false ]]; then let opt++; printf "${langEnableHIDPIEDID}\n" $opt fi let opt++; printf "${langDisableHIDPI}\n" $opt echo "" read -p "${langInputChoice} [1~$opt]: " input if [[ $is_applesilicon == true ]]; then case ${input} in 1) enable_hidpi ;; 2) disable ;; *) echo "${langEnterError}" exit 1 ;; esac else case ${input} in 1) enable_hidpi ;; 2) enable_hidpi_with_patch ;; 3) disable ;; *) echo "${langEnterError}" exit 1 ;; esac fi } start