From 99709b2eabc727f8111c905451de8b65c462e353 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 10 Aug 2020 21:52:34 +0000 Subject: Fix [315104a5c10] for 8.6: Inappropriate virtual events sent when accent color is changed. --- macosx/tkMacOSXColor.c | 2 +- macosx/tkMacOSXWindowEvent.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 89bddb9..1dcfdaa 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -211,7 +211,7 @@ GetEntryFromPixel( /* *---------------------------------------------------------------------- * - * GetRGB -- + * GetRGBA -- * * Given a SystemColorDatum and a pointer to an array of 4 CGFloats, store * the associated RGBA color values in the array. In the case of the diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index a23a6d7..db1a406 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -1078,10 +1078,19 @@ ConfigureRestrictProc( NSWindow *w = [self window]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; - + static NSAppearanceName lastAppearanceName = nil; + NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name]; if (!winPtr) { return; } + if (!lastAppearanceName) { + lastAppearanceName = effectiveAppearanceName; + return; + } + if (lastAppearanceName == effectiveAppearanceName) { + return; + } + lastAppearanceName = effectiveAppearanceName; bzero(&event, sizeof(XVirtualEvent)); event.type = VirtualEvent; event.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); @@ -1095,10 +1104,12 @@ ConfigureRestrictProc( &event.x_root, &event.y_root, &x, &y, &event.state); Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y); event.same_screen = true; - if (TkMacOSXInDarkMode(tkwin)) { + if (effectiveAppearanceName == NSAppearanceNameDarkAqua) { event.name = Tk_GetUid("DarkAqua"); - } else { + } else if (effectiveAppearanceName == NSAppearanceNameAqua) { event.name = Tk_GetUid("LightAqua"); + } else { + return; } Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); } -- cgit v0.12 From 152923a55c9a178ccaed5eec573c03271eae1967 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 11 Aug 2020 17:56:33 +0000 Subject: Generate a virtual event <> when the accent or highlight colors are changed in Preferences. --- macosx/tkMacOSXWindowEvent.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index db1a406..8c7561a 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -1080,16 +1080,23 @@ ConfigureRestrictProc( Tk_Window tkwin = (Tk_Window) winPtr; static NSAppearanceName lastAppearanceName = nil; NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name]; + Tk_Uid eventName = NULL; if (!winPtr) { return; } if (!lastAppearanceName) { lastAppearanceName = effectiveAppearanceName; - return; } if (lastAppearanceName == effectiveAppearanceName) { + eventName = Tk_GetUid("NewAccentColor"); + } else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) { + eventName = Tk_GetUid("DarkAqua"); + } else if (effectiveAppearanceName == NSAppearanceNameAqua) { + eventName = Tk_GetUid("LightAqua"); + } else { return; } + lastAppearanceName = effectiveAppearanceName; bzero(&event, sizeof(XVirtualEvent)); event.type = VirtualEvent; @@ -1104,13 +1111,7 @@ ConfigureRestrictProc( &event.x_root, &event.y_root, &x, &y, &event.state); Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y); event.same_screen = true; - if (effectiveAppearanceName == NSAppearanceNameDarkAqua) { - event.name = Tk_GetUid("DarkAqua"); - } else if (effectiveAppearanceName == NSAppearanceNameAqua) { - event.name = Tk_GetUid("LightAqua"); - } else { - return; - } + event.name = eventName; Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); } -- cgit v0.12 From 8ac846412241e0914a4bb279bf586c53835e34ab Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 11 Aug 2020 21:25:17 +0000 Subject: Fix the first event reporting a change in effective appearance --- macosx/tkMacOSXColor.c | 12 ++++++++---- macosx/tkMacOSXWindowEvent.c | 4 +++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 1dcfdaa..fe0cc2a 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -682,6 +682,7 @@ TkpGetColor( TkColor *tkColPtr; XColor color; Colormap colormap = tkwin ? Tk_Colormap(tkwin) : noColormap; + NSView *view = nil; static Bool initialized = NO; static NSColorSpace* sRGB = NULL; @@ -692,6 +693,8 @@ TkpGetColor( } if (tkwin) { display = Tk_Display(tkwin); + MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin); + view = TkMacOSXDrawableView(macWin); } /* @@ -713,12 +716,13 @@ TkpGetColor( CGFloat rgba[4]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 NSAppearance *savedAppearance = [NSAppearance currentAppearance]; - NSAppearance *windowAppearance; - if (TkMacOSXInDarkMode(tkwin)) { - windowAppearance = darkAqua; + NSAppearance *windowAppearance = savedAppearance; + if (view) { + windowAppearance = [view effectiveAppearance]; + } + if ([windowAppearance name] == NSAppearanceNameDarkAqua) { colormap = darkColormap; } else { - windowAppearance = lightAqua; colormap = lightColormap; } [NSAppearance setCurrentAppearance:windowAppearance]; diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 8c7561a..8214731 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -207,6 +207,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TkWindow *winPtr = TkMacOSXGetTkWindow(window); if (winPtr) { TKContentView *view = [window contentView]; + [view viewDidChangeEffectiveAppearance]; [view addTkDirtyRect:[view bounds]]; Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL); Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); @@ -1085,7 +1086,8 @@ ConfigureRestrictProc( return; } if (!lastAppearanceName) { - lastAppearanceName = effectiveAppearanceName; + lastAppearanceName = [[NSAppearance currentAppearance] name]; + return; } if (lastAppearanceName == effectiveAppearanceName) { eventName = Tk_GetUid("NewAccentColor"); -- cgit v0.12 From 8b6c8e84302179205f43165ff8e1ce15d2c8860a Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 15 Aug 2020 10:22:15 +0000 Subject: sync with bug-315104a5c10 --- macosx/README | 36 +++++++++++---- macosx/tkMacOSXColor.c | 9 ++-- macosx/tkMacOSXWindowEvent.c | 105 +++++++++++++++++++++++++++---------------- 3 files changed, 100 insertions(+), 50 deletions(-) diff --git a/macosx/README b/macosx/README index 79025f1..0a02999 100644 --- a/macosx/README +++ b/macosx/README @@ -662,15 +662,35 @@ source and destination rectangles for the scrolling. The embedded windows are redrawn within the DisplayText function by some conditional code which is only used for macOS. -6.0 Virtual events on 10.14 -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +6.0 Virtual events on macOS 10.14 and later +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The 10.14 release added support for system appearance changes, +including a "Dark Mode" that renders all window frames and menus in +dark colors. Tk 8.6.11 provides three virtual events <>, +<> and <>, to allow you to update your Tk +app's appearance when the system appearance changes. These events are +generated in [NSView effectiveAppearanceChanged], which is called by +the Apple window manager when the General Preferences is changed +either by switching between Light Mode and Dark Mode or by changing +the Accent Color or Highlight Color. + +The <> virtual event has a data string which can be +accessed with the %d substitution. The format of the data string is +that it consists of 6 words: + "Appearance XXXX Accent YYYY Highlight ZZZZ" +For example, the following code will print the current appearance +name, accent color and highlight color when the <> +virtual event fires: + +bind . <> { + array set data [split %d] + puts " Appearance: $data(Appearance)" + puts " Accent: $data(Accent)" + puts " Highlight: $data(Highlight)\n" +} + -10.14 supports system appearance changes, and has added a "Dark Mode" -that casts all window frames and menus as black. Tk 8.6.9 has added two -virtual events, <> and <>, to allow you to update -your Tk app's appearance when the system appearance changes. Just bind -your appearance-updating code to these virtual events and you will see -it triggered when the system appearance toggles between dark and light. 7.0 Mac Services ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index fe0cc2a..974978f 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -378,23 +378,24 @@ SetCGColorComponents( MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin) { - int result = false; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 if (@available(macOS 10.14, *)) { TkWindow *winPtr = (TkWindow*) tkwin; + NSAppearanceName name; NSView *view = nil; if (winPtr && winPtr->privatePtr) { view = TkMacOSXDrawableView(winPtr->privatePtr); } if (view) { - result = (view.effectiveAppearance == darkAqua); + name = [[view effectiveAppearance] name]; } else { - result = ([NSAppearance currentAppearance] == darkAqua); + name = [[NSAppearance currentAppearance] name]; } + return (name == NSAppearanceNameDarkAqua); } #endif - return result; + return false; } /* diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 8214731..35b1b49 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -1067,54 +1067,83 @@ ConfigureRestrictProc( } /* - * This method is called when a user changes between light and dark mode. The - * implementation here generates a Tk virtual event which can be bound to a - * function that redraws the window in an appropriate style. + * In macOS 10.14 and later his method is called when a user changes between + * light and dark mode or changes the accent color. The implementation + * generates two virtual events. The first is either <> or + * <>, depending on the view's current effective appearance. The + * second is <> and has a data string describing the + * effective appearance of the view and the current accent and highlight + * colors. */ +static char *accentNames[] = { + "Graphite", + "Red", + "Orange", + "Yellow", + "Green", + "Blue", + "Purple", + "Pink", +}; + - (void) viewDidChangeEffectiveAppearance { - XVirtualEvent event; - int x, y; - NSWindow *w = [self window]; - TkWindow *winPtr = TkMacOSXGetTkWindow(w); - Tk_Window tkwin = (Tk_Window) winPtr; - static NSAppearanceName lastAppearanceName = nil; - NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name]; - Tk_Uid eventName = NULL; - if (!winPtr) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + + Tk_Window tkwin = (Tk_Window) TkMacOSXGetTkWindow([self window]); + if (!tkwin) { return; } - if (!lastAppearanceName) { - lastAppearanceName = [[NSAppearance currentAppearance] name]; - return; + NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name]; + const char *accentName, *highlightName; + NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; + NSString *accent = [preferences stringForKey:@"AppleAccentColor"]; + NSString *highlight = [[[preferences stringForKey:@"AppleHighlightColor"] + componentsSeparatedByString: @" "] + objectAtIndex:3]; + static char *defaultColor = NULL; + + if (!defaultColor) { + defaultColor = [NSApp macOSVersion] < 110000 ? "Blue" : "Multicolor"; + + /* + * AppKit calls this method when the user changes the Accent Color + * but not when the user changes the Highlight Color. So we register + * to receive KVO notifications for Highlight Color as well. + */ + + [preferences addObserver:self + forKeyPath:@"AppleHighlightColor" + options:NSKeyValueObservingOptionNew + context:NULL]; } - if (lastAppearanceName == effectiveAppearanceName) { - eventName = Tk_GetUid("NewAccentColor"); + accentName = accent ? accentNames[1 + accent.intValue] : defaultColor; + highlightName = highlight ? highlight.UTF8String: defaultColor; + + char data[256]; + snprintf(data, 256, "Appearance %s Accent %s Highlight %s", + effectiveAppearanceName.UTF8String, accentName, + highlightName); + TkSendVirtualEvent(tkwin, "AppearanceChanged", Tcl_NewStringObj(data, -1)); + if (effectiveAppearanceName == NSAppearanceNameAqua) { + TkSendVirtualEvent(tkwin, "LightAqua", NULL); } else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) { - eventName = Tk_GetUid("DarkAqua"); - } else if (effectiveAppearanceName == NSAppearanceNameAqua) { - eventName = Tk_GetUid("LightAqua"); - } else { - return; + TkSendVirtualEvent(tkwin, "DarkAqua", NULL); } - lastAppearanceName = effectiveAppearanceName; - bzero(&event, sizeof(XVirtualEvent)); - event.type = VirtualEvent; - event.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - event.send_event = false; - event.display = Tk_Display(tkwin); - event.event = Tk_WindowId(tkwin); - event.root = XRootWindow(Tk_Display(tkwin), 0); - event.subwindow = None; - event.time = TkpGetMS(); - XQueryPointer(NULL, winPtr->window, NULL, NULL, - &event.x_root, &event.y_root, &x, &y, &event.state); - Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y); - event.same_screen = true; - event.name = eventName; - Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); +#endif +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context +{ + NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; + if (object == preferences && [keyPath isEqualToString:@"AppleHighlightColor"]) { + [self viewDidChangeEffectiveAppearance]; + } } /* -- cgit v0.12 From 8688346cc826e351a4b296686b1b1c0be5712ddc Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 15 Aug 2020 10:37:37 +0000 Subject: Adjustments for 10.6 --- macosx/tkMacOSXWindowEvent.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 35b1b49..8606d84 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -207,7 +207,9 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TkWindow *winPtr = TkMacOSXGetTkWindow(window); if (winPtr) { TKContentView *view = [window contentView]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 [view viewDidChangeEffectiveAppearance]; +#endif [view addTkDirtyRect:[view bounds]]; Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL); Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); @@ -1076,6 +1078,8 @@ ConfigureRestrictProc( * colors. */ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + static char *accentNames[] = { "Graphite", "Red", @@ -1089,8 +1093,6 @@ static char *accentNames[] = { - (void) viewDidChangeEffectiveAppearance { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 - Tk_Window tkwin = (Tk_Window) TkMacOSXGetTkWindow([self window]); if (!tkwin) { return; @@ -1131,9 +1133,9 @@ static char *accentNames[] = { } else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) { TkSendVirtualEvent(tkwin, "DarkAqua", NULL); } +} #endif -} - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object -- cgit v0.12 From 03dc2a80af3462e288ad3d46ff9ea29be67e0a4c Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 15 Aug 2020 11:56:01 +0000 Subject: misplaced #endif --- macosx/tkMacOSXWindowEvent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 8606d84..585589e 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -1135,8 +1135,6 @@ static char *accentNames[] = { } } -#endif - - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change @@ -1148,6 +1146,8 @@ static char *accentNames[] = { } } +#endif + /* * This is no-op on 10.7 and up because Apple has removed this widget, but we * are leaving it here for backwards compatibility. -- cgit v0.12 From 08ea9c49500bc7adc443804d2c8ae91fa7b500b4 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Aug 2020 18:56:18 +0000 Subject: Backport [7510e5a9b9] and add corresponding documentation in ttk_widget.n so that -font and -foreground are now documented in 8.6 in addition to 8.7. See request in [ddac78bd5e]. --- doc/ttk_entry.n | 6 +++--- doc/ttk_widget.n | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/ttk_entry.n b/doc/ttk_entry.n index 0da60d1..4eb67cc 100644 --- a/doc/ttk_entry.n +++ b/doc/ttk_entry.n @@ -23,7 +23,9 @@ with the \fB\-textvariable\fR option. Entry widgets support horizontal scrolling with the standard \fB\-xscrollcommand\fR option and \fBxview\fR widget command. .SO ttk_widget -\-class \-cursor \-style +\-class \-cursor +\-font \-foreground +\-style \-takefocus \-xscrollcommand .SE .SH "WIDGET-SPECIFIC OPTIONS" @@ -34,8 +36,6 @@ If the selection is exported, then selecting in the widget deselects the current X selection, selecting outside the widget deselects any widget selection, and the widget will respond to selection retrieval requests when it has a selection. -.\" MAYBE: .OP \-font font Font -.\" MAYBE: .OP \-foreground foreground Foreground .\" MAYBE: .OP \-insertbackground insertBackground Foreground .\" MAYBE: .OP \-insertwidth insertWidth InsertWidth .OP \-invalidcommand invalidCommand InvalidCommand diff --git a/doc/ttk_widget.n b/doc/ttk_widget.n index 51c0dbd..82a1520 100644 --- a/doc/ttk_widget.n +++ b/doc/ttk_widget.n @@ -93,6 +93,11 @@ Display image above, below, left of, or right of the text, respectively. .IP none Display the image if present, otherwise the text. .RE +.OP \-font font Font +Font to use for the text displayed by the widget. +.OP \-foreground textColor TextColor +The widget's foreground color. +If unspecified, the theme default is used. .OP \-image image Image Specifies an image to display. This is a list of 1 or more elements. -- cgit v0.12 From 4f9bff583b0e119243a0ebf254e1a3bb6f55714d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 17 Aug 2020 06:08:18 +0000 Subject: Disable warnings C4146 and C4305 (last one for 32-bit only) on Microsoft compilers. Tcl already does this, but this was never taken over by Tk --- win/tkWinPort.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/win/tkWinPort.h b/win/tkWinPort.h index 9829af5..1ef90ff 100644 --- a/win/tkWinPort.h +++ b/win/tkWinPort.h @@ -91,11 +91,15 @@ * See ticket [916c1095438eae56]: GetVersionExW triggers warnings */ #if defined(_MSC_VER) +# pragma warning(disable:4146) # pragma warning(disable:4267) # pragma warning(disable:4244) # pragma warning(disable:4311) # pragma warning(disable:4312) # pragma warning(disable:4996) +#if !defined(_WIN64) +# pragma warning(disable:4305) +#endif #endif /* -- cgit v0.12