switchbrew / libnx

Library for Switch Homebrew
https://switchbrew.github.io/libnx/
ISC License
1.27k stars 167 forks source link

setsysSetColorSetId() does not work #412

Closed iUltimateLP closed 4 years ago

iUltimateLP commented 4 years ago

Hi there! I'm working on a sysmodule which should change the console's color scheme based on the time of day (switching light/dark mode).

I came across setsysSetColorSetId(ColorSetId id) and tried to run it in a thread (which is calling the function every 10 seconds) to change the color theme.

Unfortunately, it doesn't seem to work. I can double check using setsysGetColorSetId which returns the correct Color set ID, but I don't see any visual changes on the switch. Any help is greatly appreciated!

yellows8 commented 4 years ago

Code?

Also, for using localtime() etc you need to actually call __libnx_init_time().

iUltimateLP commented 4 years ago

Yea I came across the time thing, weirdly though I didn't find __libnx_init_time() anywhere. I ended up getting the time using timeGetCurrentTime and timeToCalendarTimeWithMyRule.

Here's the full function in my code which should change the color theme:

void Worker::CheckForThemeChange()
{
    // Get the current time of the Nintendo Switch console using libnx
    u64 currentConsoleTime;
    Result getTimeResult = timeGetCurrentTime(TimeType::TimeType_UserSystemClock, &currentConsoleTime);

    // Make sure we were able to get the time
    if (R_FAILED(getTimeResult))
    {
        Logger::get()->logError(getTimeResult);
        return;
    }

    // Make a TimeCalendarTime out of the timestamp using libnx' features
    TimeCalendarTime consoleCalendarTime;
    TimeCalendarAdditionalInfo consoleCalendarInfo;
    timeToCalendarTimeWithMyRule(currentConsoleTime, &consoleCalendarTime, &consoleCalendarInfo);

    // Now perform some logic checks to see if we should change the theme
    bool needsLightThemeChange = consoleCalendarTime.hour >= lightTime.tm_hour 
        && consoleCalendarTime.minute >= lightTime.tm_min
        && ((consoleCalendarTime.hour > darkTime.tm_hour && consoleCalendarTime.minute > darkTime.tm_min) 
            || (consoleCalendarTime.hour == darkTime.tm_hour && consoleCalendarTime.minute > darkTime.tm_min));

    bool needsDarkThemeChange = consoleCalendarTime.hour >= darkTime.tm_hour
        && consoleCalendarTime.minute >= darkTime.tm_min
        && ((consoleCalendarTime.hour < lightTime.tm_hour && consoleCalendarTime.minute < lightTime.tm_min) 
            || (consoleCalendarTime.hour == lightTime.tm_hour && consoleCalendarTime.minute < lightTime.tm_min));

    bool needsThemeChange = needsLightThemeChange || needsDarkThemeChange;

    ColorSetId currentTheme;
    Result sysGetColorSetIdResult = setsysGetColorSetId(&currentTheme);
    if (R_SUCCEEDED(sysGetColorSetIdResult))
    {
        Logger::get()->log("Got color theme");
    }
    else
    {
        Logger::get()->logError(sysGetColorSetIdResult);
    }

    Logger::get()->log("CheckForThemeChange() CurrentTime = %d:%d CurrentTheme = %s NeedsLightThemeChange = %d (%d:%d) NeedsDarkThemeChange = %d (%d:%d)",
        consoleCalendarTime.hour,
        consoleCalendarTime.minute,
        currentTheme == ColorSetId::ColorSetId_Light ? "Light" : "Dark",
        needsLightThemeChange,
        lightTime.tm_hour,
        lightTime.tm_min,
        needsDarkThemeChange,
        darkTime.tm_hour,
        darkTime.tm_min);

    // Do we need to change the theme?
    if (needsThemeChange)
    {
        // What will the new theme be?
        ColorSetId newTheme = needsLightThemeChange ? ColorSetId::ColorSetId_Light : ColorSetId::ColorSetId_Dark;

        // Apply the new theme using libnx
        Result sysSetColorSetIdResult = setsysSetColorSetId(newTheme);

        // Check if it worked
        if (R_SUCCEEDED(sysSetColorSetIdResult))
        {
            Logger::get()->log("Changed theme to %s", newTheme == ColorSetId::ColorSetId_Light ? "Light" : "Dark");
        }
        else
        {
            Logger::get()->logError(sysSetColorSetIdResult);
        }
    }
}

Also, because I forgot: Atmosphere 0.10.4 HOS 9.2.0

yellows8 commented 4 years ago

Are you using setsys Initialize/Exit somewhere?

Add: void __libnx_init_time(void); (and call it from __appInit)

iUltimateLP commented 4 years ago

Yep, here's my appInit and appExit:

extern "C" void __attribute__((weak)) __appInit(void)
{
    // Will hold the result of several service inits
    Result rc;

    // Initialize default Switch services and make sure it was successful
    rc = smInitialize();
    if (R_FAILED(rc))
    {
        fatalThrow(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM));
    }

    // Initialize the time module
    rc = timeInitialize();
    if (R_FAILED(rc))
    {
        fatalThrow(MAKERESULT(Module_Libnx, LibnxError_InitFail_Time));
    }
    __libnx_init_time();

    // Initialize the set module
    rc = setInitialize();
    if (R_FAILED(rc))
    {
        fatalThrow(MAKERESULT(Module_Libnx, LibnxError_NotInitialized));
    }

    // Initialize the setsys module
    rc = setsysInitialize();
    if (R_FAILED(rc))
    {
        fatalThrow(MAKERESULT(Module_Libnx, LibnxError_NotInitialized));
    }

    // Initialize the filesystem service and make sure it was successful
    rc = fsInitialize();
    if (R_FAILED(rc))
    {
        fatalThrow(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS));
    }

    // Mount the SDMC storage
    fsdevMountSdmc();
}

extern "C" void __attribute__((weak)) __appExit(void)
{
    // Cleanup and exit the services we opened
    fsdevUnmountAll();
    fsExit();
    setsysExit();
    setExit();
    timeExit();
    smExit();
}
yellows8 commented 4 years ago

Does the changed ColorSetId show up when you reload hbmenu?

iUltimateLP commented 4 years ago

Yea it does, also as mentioned setsysGetColorSetId does return the correct color scheme, so I think it might be missing an update call to HOS' UI?

iUltimateLP commented 4 years ago

I notice, some modals and widgets are themed, such as the controller window which opens when you click the joycon in the menu bar. Weird

yellows8 commented 4 years ago

"an update call to HOS' UI" That doesn't really exist, it's not a service / whatever.

It's just a matter of when qlaunch loads the color-set - normally nothing non-qlaunch (?) sets this.

iUltimateLP commented 4 years ago

So you don't think it could be possible?

yellows8 commented 4 years ago

With the official qlaunch, no.

iUltimateLP commented 4 years ago

Hm, maybe I could try to find the PID of qlaunch and restart it? I'm pretty new to switch development so I'm just having random guesses.

yellows8 commented 4 years ago

no

iUltimateLP commented 3 years ago

Did this situation change with the new libnx updates? It's been a year, maybe? @yellows8