TIP 750: Consistent dark mode for Windows and macOS

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Author:         Marc Culler
State:          Draft
Type:           Project
Created:        2026-04-14
Tcl-Version:    9.1
Tcl-Branch:     tip_750
Keywords:       dark appearance
Vote:           In progress
Vote-Summary:
Votes-For: HO KW MC
Votes-Against:
Votes-Present:

Abstract

The current MacOS implementation of the appearance attribute is modified to use multi-platform semantics. A new implementation of this attribute for Windows is added. The Windows implementation allows changing the window decoration theme and provides virtual event notfication when the user changes the value of the Registry key AppsUseLightTheme. This is intended to make it possible for Windows Tk apps to update window content to match the theme that the user has chosen for window decorations.

Target

This TIP targets version 9.1 of Tk.

Rationale

The current MacOS implementation of TIP655 adds the following command for setting the EffectiveAppearance attribute of the ContentView of an NSWindow underlying a Tk toplevel:

wm attributes window -appearance ?auto|aqua|darkaqua*?

The proposed new syntax is:

wm attributes window -appearance ?light|dark|auto?

This is more descriptive and less platform-specific than the current macOS command.

On macOS, the value of the attribute does not determine the current appearance of a window, because the "auto" option allows the system to set the appearance. For that reason TIP 655 also added a macOS command for querying the actual current appearance of a window. That command, which has a Boolean result, has the following syntax:

wm attributes window -isdark

Harald Oehlmann observed that this is inconsistent with the expected purpose of the wm attributes command, which is to get or set attributes. Instead it is checking for a state, which may or may not be determined by the value of any attribute. He suggested that it would be more consistent with the Tk language to replace the command above by the command:

winfo isdark window

This TIP removes the -isdark option from the wm attributes command and adds the suggested command. The provided code is based on a snippet written by Emiliano Gavilán which was included at the end of TIP 749.

An additional purpose of this TIP is to clean up detritus left when TIP 655 introduced the appearance attribute for macOS. That TIP introduced several new attributes which replaced commands which had been available for macOS in the ::tk::unsupported namespace. TIP 655 was targeting Tk 8.7 at a time when adding new features to Tk 8.6 was no longer possible. Moreover, there were significant applications, such as the Python tkinter module, which were using commands from the ::tk::unsupported namespace and it seemed unwise to remove them, even though they were no longer needed, since it would introduce backwards incompatibilities. These concerns no longer apply to 9.1. So this TIP removes the unsupported commands.

Specification

The following commands will be made available on macOS and windows.

  • wm attributes window -appearance ?light|dark|auto?

The values may be abbreviated.

On both macOS and Windows the "auto" value means that the appearance will be determined by the system, based on system settings. It is the default value for the attribute.

If no value is supplied the current appearance value will be returned.

The command has no effect on the Linux platform.

  • winfo isdark window

This returns a boolean value which is true if the window is currently displayed in dark mode. On Windows the Windows manager is queried for the value. On macOS it queries the NSAppearanceName of the window's contentView.

This command fails if the value may not be retrieved from the system, which can happen on Windows.

On the Linux platform, this command always returns false.

The following virtual events will be sent on macOS or Windows whenever the appearance of the window is changed due to a Settings change:

  • <<AppearanceChanged>> will be sent to the window when its appearance changes. The data string will indicate either "light" or "dark" as the Appearance value, according to which choice was made in the Settings.
  • <<DarkAppearance>> will be sent when the new appearance is dark.
  • <<LightAppearance>> will be sent when the new appearance is light.

The names of these events are changed from the current names to make them platform neutral. The data string of the <<AppearanceChanged>> event is platform specific, however.

Compatibility

This TIP makes backwards incompatible changes by changing the allowed values for the appearance attribute on macOS. Setting the appearance to either aqua or darkaqua will not work after this tip. Setting it to dark works before and after, as this is an abbreviation for "darkaqua". It also changes the names of the virtual events generated when appearance changes. Finally, the removal of the unsupported commands will mean that software which used those commands will need to be modified to use the supported variant.

Reference Implementation

The TIP is implemented in the branch tip_750 in the Tk fossil repository.

On the Windows platform, the current implementation requires an update idletasks between toplevel creation and appearance setting because the appearance cannot be changed until the HWND is valid.:

toplevel .t
update idletasks
wm attributes .t -appearance dark

Discussion

TIP 749

This TIP supersedes TIP 749. That TIP has been withdrawn but contains a lot of background information, especially for the Windows platform.

Copyright

This document has been placed in the public domain.

History