diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2020-08-17 06:18:14 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2020-08-17 06:18:14 (GMT) |
commit | 560a6b03e7e93607af6c0748938e380f86938b2a (patch) | |
tree | 6815af5291b35a82b44cdaaee8250de57e3e2ec0 | |
parent | e6279912ba852370baf9d434e5985b355430daad (diff) | |
parent | 3429267f021764f4911937b03becd9acf6109cf4 (diff) | |
download | tk-560a6b03e7e93607af6c0748938e380f86938b2a.zip tk-560a6b03e7e93607af6c0748938e380f86938b2a.tar.gz tk-560a6b03e7e93607af6c0748938e380f86938b2a.tar.bz2 |
Merge trunk
-rw-r--r-- | macosx/README | 36 | ||||
-rw-r--r-- | macosx/tkMacOSXColor.c | 12 | ||||
-rw-r--r-- | macosx/tkMacOSXWindowEvent.c | 101 | ||||
-rw-r--r-- | win/tkWinPort.h | 4 |
4 files changed, 113 insertions, 40 deletions
diff --git a/macosx/README b/macosx/README index a3f10b6..9745d14 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 <<LightAqua>>, +<<DarkAqua>> and <<AppearanceChanged>>, 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 <<AppearanceChanged>> 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 <<AppearanceChanged>> +virtual event fires: + +bind . <<AppearanceChanged>> { + 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, <<LightAqua>> and <<DarkAqua>>, 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 01732c0..537290e 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -684,6 +684,7 @@ TkpGetColor( TkColor *tkColPtr; XColor color; Colormap colormap = tkwin ? Tk_Colormap(tkwin) : noColormap; + NSView *view = nil; static Bool initialized = NO; static NSColorSpace* sRGB = NULL; @@ -694,6 +695,8 @@ TkpGetColor( } if (tkwin) { display = Tk_Display(tkwin); + MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin); + view = TkMacOSXDrawableView(macWin); } /* @@ -715,12 +718,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 4ad94ed..d92ab75 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -210,6 +210,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); @@ -1079,43 +1082,85 @@ 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 <<LightAqua>> or + * <<DarkAqua>>, depending on the view's current effective appearance. The + * second is <<AppearnceChanged>> and has a data string describing the + * effective appearance of the view and the current accent and highlight + * colors. */ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + +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; - - if (!winPtr) { + Tk_Window tkwin = (Tk_Window) TkMacOSXGetTkWindow([self window]); + if (!tkwin) { return; } - 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; - if (TkMacOSXInDarkMode(tkwin)) { - event.name = Tk_GetUid("DarkAqua"); - } else { - event.name = Tk_GetUid("LightAqua"); + 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]; + } + 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) { + TkSendVirtualEvent(tkwin, "DarkAqua", NULL); + } +} + +- (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]; } - Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); } +#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. diff --git a/win/tkWinPort.h b/win/tkWinPort.h index 72ca0e0..955e9b8 100644 --- a/win/tkWinPort.h +++ b/win/tkWinPort.h @@ -95,11 +95,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 /* |