summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2020-08-17 06:18:14 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2020-08-17 06:18:14 (GMT)
commit560a6b03e7e93607af6c0748938e380f86938b2a (patch)
tree6815af5291b35a82b44cdaaee8250de57e3e2ec0
parente6279912ba852370baf9d434e5985b355430daad (diff)
parent3429267f021764f4911937b03becd9acf6109cf4 (diff)
downloadtk-560a6b03e7e93607af6c0748938e380f86938b2a.zip
tk-560a6b03e7e93607af6c0748938e380f86938b2a.tar.gz
tk-560a6b03e7e93607af6c0748938e380f86938b2a.tar.bz2
Merge trunk
-rw-r--r--macosx/README36
-rw-r--r--macosx/tkMacOSXColor.c12
-rw-r--r--macosx/tkMacOSXWindowEvent.c101
-rw-r--r--win/tkWinPort.h4
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
/*