3

Is there anyway by which one can have grayscale system wide except some selected (by user) apps, on macOS?

3

Yes, this is possible, though my solution is a bit hacky. Note that this method uses some undocumented Objective C APIs, and doesn't go through ordinary accessibility settings, so be careful.

First you need to have developer tools installed so that you can compile Objective C code. Then compile two commands enable-grayscale and disable-grayscale from source (based on this StackOverflow answer which provides some additional ways of doing this).

$  cat enable-grayscale.c 
// https://stackoverflow.com/questions/14163788/how-does-on-screen-color-inversion-work-in-os-x
#include <stdio.h>
#include <ApplicationServices/ApplicationServices.h>

CG_EXTERN bool CGDisplayUsesForceToGray(void);
CG_EXTERN void CGDisplayForceToGray(bool forceToGray);

int
main(int argc, char** argv)
{
    bool isGrayscale = CGDisplayUsesForceToGray();
        if (!isGrayscale) {
                CGDisplayForceToGray(TRUE);
        }

    return 0;
}

$ cat disable-grayscale.c 
// https://stackoverflow.com/questions/14163788/how-does-on-screen-color-inversion-work-in-os-x
#include <stdio.h>
#include <ApplicationServices/ApplicationServices.h>

CG_EXTERN bool CGDisplayUsesForceToGray(void);
CG_EXTERN void CGDisplayForceToGray(bool forceToGray);

int
main(int argc, char** argv)
{
    bool isGrayscale = CGDisplayUsesForceToGray();
        if (isGrayscale) {
        CGDisplayForceToGray(0);
        }

    return 0;
}

Then compile them into commands:

clang -g -O2 -std=c11 -Wall -framework ApplicationServices enable-grayscale.c -o enable-grayscale
clang -g -O2 -std=c11 -Wall -framework ApplicationServices disable-grayscale.c -o disable-grayscale

Put the resulting files somewhere you want to run them, e.g. your home directory.

Now install Hammerspoon. You'll need to give it accessibility access in System Preferences. Within Hammerspoon, select "Open Config", and modify the Lua code to do what you want. My configuration is below, based on this example from their docs:

function applicationWatcher(appName, eventType, appObject)
    if (eventType == hs.application.watcher.activated) then
        if (appName == "Firefox") then
            os.execute('/path/to/scripts/enable-grayscale')
        end
    end
    if (eventType == hs.application.watcher.deactivated) then
        if (appName == "Firefox") then
            os.execute('/path/to/scripts/disable-grayscale')
        end
    end
end
appWatcher = hs.application.watcher.new(applicationWatcher)
appWatcher:start()

That's the configuration I chose (turn on grayscale for Firefox, but leave it off for all other applications). Whenever Firefox is focused, the whole screen becomes grayscale. When other applications are focused, it's color. It sounds like you'd want the opposite: grayscale turned on in System Preferences, with it being disabled when you focus an app from the list you're interested in. Once you've configured it as you want, click "Reload Config" to activate the changes.

  • nice, does this work if the application which triggers this change is maximized while switching to another application? will the switching app trigger the screen to grayscale in that case?. I am trying to get this to work on iTerm, I want terminal app to have color and everything else to be gray, so far I got to the point where c code works, but Hammerspoon does not respond to appName "iTerm". – whitespace Jul 15 at 14:12
  • You might be able to add a logging statement logging the appName, then you can check what the appName it's seeing in the hammerspoon debug console (like maybe it's "iTerm 2" or something). To be honest, I stopped using this a while ago, so I can't help further. – RecursivelyIronic Jul 16 at 18:18
0

No this option is only available as a global option in accessibility options.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .