From 5f1ed7c5682b2d82a02b0375801751218a7b8728 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 9 Feb 2023 19:11:24 +0000 Subject: Add -appearance and -isdark as options to the wm attributes command. --- doc/wm.n | 36 +++++++++++------ library/demos/mac_styles.tcl | 14 +++---- macosx/tkMacOSXWm.c | 92 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 104 insertions(+), 38 deletions(-) diff --git a/doc/wm.n b/doc/wm.n index cd16d76..e53529c 100644 --- a/doc/wm.n +++ b/doc/wm.n @@ -96,6 +96,13 @@ at \fB{}\fR. .PP On MacOS, the following attributes may be set. .TP +\fB\-appearance\fR +. +Specifies whether the window is rendered in "dark mode". Allowed +values are \fBauto\fR, \fBaqua\fR and \fBdarkaqua\fR. If the setting +is auto then the appearance of the window is controlled by the +System Settings. +.TP \fB\-class\fR . Specifies whether the underlying Aqua window for a toplevel is an @@ -109,6 +116,21 @@ class name to be cached for later use. When a toplevel with that pathname is eventually created, the cached class name will determine which class is used for the underlying Aqua window. .TP +\fB\-isdark\fR +. +Returns a boolean value which is true if the window is currently in +dark mode. +.TP +\fB\-modified\fR +. +Specifies the modification state of the window (determines whether the +window close widget contains the modification indicator and whether the +proxy icon is draggable). +.TP +\fB\-notify\fR +. +Specifies process notification state (bouncing of the application dock icon). +.TP \fB\-stylemask\fR . Specifies an integer to be assigned as the styleMask of the underlying @@ -122,16 +144,6 @@ bits will be set to 0. The allowed bitnames are: \fBtitled\fR, effect of setting the fullsizecontentview bit is that the window title bar becomes transparent. .TP -\fB\-modified\fR -. -Specifies the modification state of the window (determines whether the -window close widget contains the modification indicator and whether the -proxy icon is draggable). -.TP -\fB\-notify\fR -. -Specifies process notification state (bouncing of the application dock icon). -.TP \fB\-tabbingid\fR . Controls how tabbed toplevel windows are grouped together. Two tabs @@ -160,8 +172,8 @@ the toplevel is actually created. .TP \fB\-titlepath\fR . -Specifies the path of the file referenced as the window proxy icon (which -can be dragged and dropped in lieu of the file's finder icon). +Specifies the path of the file referenced as the window proxy icon +(which can be dragged and dropped in lieu of the file's finder icon). .TP \fB\-transparent\fR . diff --git a/library/demos/mac_styles.tcl b/library/demos/mac_styles.tcl index df727df..33fa888 100644 --- a/library/demos/mac_styles.tcl +++ b/library/demos/mac_styles.tcl @@ -34,8 +34,8 @@ image create nsimage starry2 -source $starryImg -as file -width 96 -radius 10 -r image create nsimage field -source $fieldImg -as file -width 96 -radius 10 image create nsimage field1 -source $fieldImg -as file -width 96 -radius 10 -pressed 1 image create nsimage field2 -source $fieldImg -as file -width 96 -radius 10 -ring 3 -image create nsimage add -source NSAddTemplate -width 11 -height 11 -image create nsimage remove -source NSRemoveTemplate -width 11 -height 11 +image create nsimage add -source NSAddTemplate -width 20 -height 20 +image create nsimage remove -source NSRemoveTemplate -width 18 -height 4 # Off state and variables for checkbuttons and radio buttons set off {!selected !alternate} @@ -130,9 +130,9 @@ set feather [ttk::button $buttonFrame.feather -style ImageButton -text Tk \ -image {tkfeather pressed tkfeather1}] set gradient [ttk::frame $buttonFrame.gradient] pack [ttk::button $buttonFrame.gradient.add -style GradientButton \ - -image add -padding 7] -side left + -image add -padding {2 0}] -side left pack [ttk::button $buttonFrame.gradient.remove -style GradientButton \ - -image remove -padding 7] -side left + -image remove -padding {2 8}] -side left set disclosure [ttk::checkbutton $buttonFrame.disclosure -style DisclosureButton] set help [ttk::button $buttonFrame.help -style HelpButton]; @@ -240,20 +240,20 @@ set dark [ttk::button $appearanceFrame.dark -style ImageButton -text Dark \ -image {starry pressed starry1 selected starry2} \ -command "beDark $appearanceFrame $w"] grid $dark -row 1 -column 2 -sticky w -if { [::tk::unsupported::MacWindowStyle isdark $w] } { +if { [wm attributes $w -isdark] } { $dark state selected } else { $light state selected } proc beLight {f w} { - ::tk::unsupported::MacWindowStyle appearance $w aqua + wm attributes $w -appearance aqua $f.dark state !selected $f.light state selected after 10 $f.light state !hover } proc beDark {f w} { - ::tk::unsupported::MacWindowStyle appearance $w darkaqua + wm attributes $w -appearance darkaqua $f.light state !selected $f.dark state selected after 10 $f.dark state !hover diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c8de71e..0fb4fda 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -235,6 +235,13 @@ static const tabbingMode tabbingModes[] = { {NULL, -1} }; +static const char *const appearanceStrings[] = { + "aqua", "auto", "darkaqua", NULL +}; +enum appearances { + APPEARANCE_AQUA, APPEARANCE_AUTO, APPEARANCE_DARKAQUA +}; + static Bool wantsToBeTab(NSWindow *macWindow) { Bool result; switch ([macWindow tabbingMode]) { @@ -288,15 +295,16 @@ static void syncLayout(NSWindow *macWindow) #endif typedef enum { - WMATT_ALPHA, WMATT_BUTTONS, WMATT_FULLSCREEN, WMATT_MODIFIED, WMATT_NOTIFY, - WMATT_TITLEPATH, WMATT_TOPMOST, WMATT_TRANSPARENT, WMATT_STYLEMASK, WMATT_CLASS, - WMATT_TABBINGID, WMATT_TABBINGMODE, _WMATT_LAST_ATTRIBUTE + WMATT_ALPHA, WMATT_APPEARANCE, WMATT_BUTTONS, WMATT_FULLSCREEN, + WMATT_ISDARK, WMATT_MODIFIED, WMATT_NOTIFY, WMATT_TITLEPATH, WMATT_TOPMOST, + WMATT_TRANSPARENT, WMATT_STYLEMASK, WMATT_CLASS, WMATT_TABBINGID, + WMATT_TABBINGMODE, _WMATT_LAST_ATTRIBUTE } WmAttribute; static const char *const WmAttributeNames[] = { - "-alpha", "-buttons", "-fullscreen", "-modified", "-notify", "-titlepath", - "-topmost", "-transparent", "-stylemask", "-class", "-tabbingid", "-tabbingmode", - NULL + "-alpha", "-appearance", "-buttons", "-fullscreen", "-isdark", "-modified", + "-notify", "-titlepath", "-topmost", "-transparent", "-stylemask", "-class", + "-tabbingid", "-tabbingmode", NULL }; /* @@ -1634,6 +1642,30 @@ WmSetAttribute( [macWindow setAlphaValue:dval]; break; } + case WMATT_APPEARANCE: { + int index; + if (Tcl_GetIndexFromObjStruct(interp, value, appearanceStrings, + sizeof(char *), "appearancename", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum appearances) index) { + case APPEARANCE_AQUA: + macWindow.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameAqua]; + break; + case APPEARANCE_DARKAQUA: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if (@available(macOS 10.14, *)) { + macWindow.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameDarkAqua]; + } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + break; + default: + macWindow.appearance = nil; + } + break; + } case WMATT_BUTTONS: { windowButtonState state = {0}; Tcl_Obj **elements; @@ -1798,6 +1830,9 @@ WmSetAttribute( placeAsTab((TKWindow *)macWindow); break; } + case WMATT_ISDARK: { + break; + } case WMATT_TITLEPATH: { const char *path = (const char *)Tcl_FSGetNativePath(value); NSString *filename = @""; @@ -1880,6 +1915,28 @@ WmGetAttribute( case WMATT_ALPHA: result = Tcl_NewDoubleObj([macWindow alphaValue]); break; + case WMATT_APPEARANCE: { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + NSAppearanceName appearance; +#else + NSString *appearance; +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + const char *resultString = "unrecognized"; + appearance = macWindow.appearance.name; + if (appearance == nil) { + resultString = appearanceStrings[APPEARANCE_AUTO]; + } else if (appearance == NSAppearanceNameAqua) { + resultString = appearanceStrings[APPEARANCE_AQUA]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } else if (@available(macOS 10.14, *)) { + if (appearance == NSAppearanceNameDarkAqua) { + resultString = appearanceStrings[APPEARANCE_DARKAQUA]; + } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } + result = Tcl_NewStringObj(resultString, -1); + break; + } case WMATT_BUTTONS: { result = Tcl_NewListObj(3, NULL); if ([macWindow standardWindowButton:NSWindowCloseButton].enabled) { @@ -1893,9 +1950,19 @@ WmGetAttribute( } break; } + case WMATT_CLASS: + if ([macWindow isKindOfClass:[NSPanel class]]) { + result = Tcl_NewStringObj(subclassNames[subclassNSPanel], -1); + } else { + result = Tcl_NewStringObj(subclassNames[subclassNSWindow], -1); + } + break; case WMATT_FULLSCREEN: result = Tcl_NewBooleanObj([macWindow styleMask] & NSFullScreenWindowMask); break; + case WMATT_ISDARK: + result = Tcl_NewBooleanObj(TkMacOSXInDarkMode((Tk_Window)winPtr)); + break; case WMATT_MODIFIED: result = Tcl_NewBooleanObj([macWindow isDocumentEdited]); break; @@ -1940,13 +2007,6 @@ WmGetAttribute( case WMATT_TRANSPARENT: result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT); break; - case WMATT_CLASS: - if ([macWindow isKindOfClass:[NSPanel class]]) { - result = Tcl_NewStringObj(subclassNames[subclassNSPanel], -1); - } else { - result = Tcl_NewStringObj(subclassNames[subclassNSWindow], -1); - } - break; case _WMATT_LAST_ATTRIBUTE: default: break; @@ -6414,12 +6474,6 @@ WmWinAppearance( (void) objv; return TCL_OK; #else - static const char *const appearanceStrings[] = { - "aqua", "auto", "darkaqua", NULL - }; - enum appearances { - APPEARANCE_AQUA, APPEARANCE_AUTO, APPEARANCE_DARKAQUA - }; Tcl_Obj *result = NULL; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 NSAppearanceName appearance; -- cgit v0.12