WxWidgets Dark Mode on macOS

WxWidgets Dark Mode on macOS

According to the release notes for 3.1.3 () dark mode support has been added to wxWidgets for Mojave+.

For the documentation for wxSysColourChanged, it still states that this is for Windows only but I thought the dark mode support for macOS should include this too? Dark mode is only a recent addition to Windows UWP apps and not Win32 (see dark mode on Windows 10 for a discussion of that on the forum).

In any case I cannot get the event to fire, although switching to dark mode does indeed correctly update the GUI elements eg. wxlistctrl and wxbutton without me having to manually enforce colour changes. I am trying to capture the system colour change event so that I can manually redraw my own "owner-drawn" custom GUI elements correctly dark/light.

I hook up the Bind in the constructor to my event but nothing works:

Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);

void myFrame::OnSystemColourChanged(wxSysColourChangedEvent &event)
{
  wxSystemAppearance s = wxSystemSettings::GetAppearance();
  wxString dark = s.IsDark() ? "it's dark" : "it's light";
  wxString m("System colour changed - ");
  m += dark;
  ::wxMessageBox(m);
  event.Skip();
}

I have got this open as a query on the forum (here) and they recommended the mailing list but I notice that wxWidgets questions are quickly addressed on here, particularly by VZ so here's hoping!

Am I missing some method of detecting colour changes?

2

2 Answers

A lazy but useful method is:

In an OnPaint handler using this method to check the system's dark/light mode. So that you know how to "Paint" your objects:

#include <wx/settings.h>

int main() {
  wxColour color = wxSystemSettingsNative::GetColour(wxSYS_COLOUR_WINDOW);
  // Use the color value to determine whether the system is in day mode or night mode
  return 0;
};

OK, I managed to get the code to hit. I debugged it by adding a wxApp-level HandleEvent override function to see what events were being handled by the application (yes all events go through here):

void myApp::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const
{
  wxApp::HandleEvent(handler, func, event);
}

wxSysColourChanged events are indeed passing through this.

I managed to get my main frame's handler to hit by hooking up differently. Instead of

Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);

I used this instead:

Bind(wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler(myFrame::OnSystemColourChanged), this);

I have no idea why &myFrame::OnSystemColourChanged wouldn't be recognised. Also, I could not get any message boxes to show up in my event handler. ::wxMessageBox and wxMessageDialog did not show. cout output did show up but no popup GUI dialogs. I am not going to be showing message boxes in this handler anyway so it isn't a problem but was trying to show a message for debugging/testing purposes.

3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sarah Jenkins
Author

Sarah Jenkins

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.