Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme preference support on macOS. #127

Merged
merged 13 commits into from
Apr 17, 2020
Merged

Theme preference support on macOS. #127

merged 13 commits into from
Apr 17, 2020

Conversation

weisJ
Copy link
Owner

@weisJ weisJ commented Mar 31, 2020

No description provided.

@weisJ
Copy link
Owner Author

weisJ commented Mar 31, 2020

@vlsi What settings are there on macOS for changing font sizes. Apparently there is only a choice between standard medium and large text size (only for retina displays). Am I missing something here?

@weisJ
Copy link
Owner Author

weisJ commented Apr 1, 2020

I'm having trouble finding how to listen to changes for settings on macOS. For example in the documentation of accessibilityDisplayShouldIncreaseContrast it says to listen for accessibilityDisplayOptionsDidChangeNotification but never states how to do so.
I guess it happens through the NSDistributedNotificationCenter but I'm not sure. Haven't found any list of notifications that are broadcasted there.

@vlsi Could you run this snippet to see what values appear? Specifically we're looking for changes to the text scaling, dark mode and high contrast mode.
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(observerMethod:) name:nil object:nil];

@vlsi
Copy link
Contributor

vlsi commented Apr 1, 2020

run this snippet to see what values appear

In practice, I need to figure out the syntax because self is valid only for Objective-C object

@vlsi
Copy link
Contributor

vlsi commented Apr 1, 2020

@interface Tst:NSObject {
}
@end

@implementation Tst
-(id)init {
    NSDistributedNotificationCenter *center = [NSDistributedNotificationCenter defaultCenter];
    NSLog(@"Adding observer to: %@", center);
    [center addObserver:self
               selector:@selector(notificationEvent:)
                   name:nil
                 object:nil];
   return self;
}

-(void)notificationEvent:(NSNotification *)notif {
    NSLog(@"Notification: %@", notif);
}
@end
JNIEXPORT void JNICALL
Java_com_github_weisj_darklaf_platform_macos_JNIDecorationsMacOS_setTitleEnabled(JNIEnv *env, jclass obj, jlong hwnd,
                                                                                 jboolean enabled) {
JNF_COCOA_ENTER(env);
    NSLog(@"init");
    Tst *tst = [[Tst alloc]init];
    NSLog(@"init: %@", tst);
  • 10.14.6 Mojave

produce the following:

dark-light theme change:

2020-04-01 22:13:19.611 java[57577:17801615] Notification: __CFNotification 0x7fb6c532a1b0 {name = ApplePrivateInterfaceThemeChangedNotification}
2020-04-01 22:13:19.611 java[57577:17801615] Notification: __CFNotification 0x7fb6c5010fc0 {name = AppleInterfaceThemeChangedNotification}

accent color change:

2020-04-01 22:15:35.896 java[57577:17801615] Notification: __CFNotification 0x7fb6c5202b00 {name = AppleAquaColorVariantChanged}
2020-04-01 22:15:35.975 java[57577:17801615] Notification: __CFNotification 0x7fb6c2f4a410 {name = AppleColorPreferencesChangedNotification}

switch to "bigger font resolution":

2020-04-01 22:17:05.016 java[57577:17801615] Notification: __CFNotification 0x7fb6c8b2b000 {name = QueueStoppedNotification; object = x-coredata://C319EF64-80EB-419D-984C-E29E1BAD56DE/ExchangePrincipal/p2}
2020-04-01 22:17:05.017 java[57577:17801615] Notification: __CFNotification 0x7fb6c8b2dfb0 {name = AppleColorSyncPreferencesSyncNeeded; userInfo = {
    HostScope = kCFPreferencesCurrentHost;
    NotifierPID = 57685;
    UserScope = kCFPreferencesCurrentUser;
}}
2020-04-01 22:17:05.017 java[57577:17801615] Notification: __CFNotification 0x7fb6c2d05190 {name = com.apple.ColorSync.DeviceProfilesNotification; userInfo = {
    DeviceClass = mntr;
    DeviceID = "F466F621-B5FA-04A0-0800-CFA6C258DECD";
    NotifierPID = 57685;
}}
2020-04-01 22:17:05.024 java[57577:17801615] Notification: __CFNotification 0x7fb6c8b433e0 {name = com.apple.ColorSync.DisplayProfileNotification; userInfo = {
    DeviceClass = mntr;
    DeviceID = "F466F621-B5FA-04A0-0800-CFA6C258DECD";
    NotifierPID = 57685;
}}
2020-04-01 22:17:33.120 java[57577:17801615] Notification: __CFNotification 0x7fb6c8a05a80 {name = AppleTextInputMenuExtraDidLoadNotification}

activate "inverted screen colors" (in light theme):

2020-04-01 22:20:00.376 java[57577:17801615] Notification: __CFNotification 0x7fb6c898a770 {name = com.apple.universalaccess.screenPolarityDidChange; userInfo = {
    pid = 61123;
    uid = 501;
    whiteOnBlack = 1;
}}

deactivate "inverted screen colors" (in light theme):

2020-04-01 22:21:25.410 java[57577:17801615] Notification: __CFNotification 0x7fb6c8a2c490 {name = com.apple.universalaccess.screenPolarityDidChange; userInfo = {
    pid = 61123;
    uid = 501;
    whiteOnBlack = 0;
}}

@vlsi
Copy link
Contributor

vlsi commented Apr 1, 2020

universal access - increase contrast

2020-04-01 22:21:52.491 java[57577:17801615] Notification: __CFNotification 0x7fb6c8a2d1d0 {name = AXInterfaceIncreaseContrastStatusDidChange}

@weisJ
Copy link
Owner Author

weisJ commented Apr 1, 2020

Thank you very much! Do these names correspond to any named notifications? Or at least: Is accessibilityDisplayShouldIncreaseContrast == "AXInterfaceIncreaseContrastStatusDidChange"?

@vlsi
Copy link
Contributor

vlsi commented Apr 2, 2020

I guess AXInterfaceIncreaseContrastStatusDidChange corresponds to https://developer.apple.com/documentation/appkit/nsworkspace/1534227-accessibilitydisplayoptionsdidch

However, I guess the ids can be coded as string literals.

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

I guess AXInterfaceIncreaseContrastStatusDidChange corresponds to https://developer.apple.com/documentation/appkit/nsworkspace/1534227-accessibilitydisplayoptionsdidch

However, I guess the ids can be coded as string literals.

Yes that would probably work.
One more thing. Can you check if [[NSUserDefaults standardUserDefaults] contains any key-value pair representing the text scaling?

I thin the medium article fits the best although I don't quite understand what the comments mean in this snippet:

if switchesAutomatically == TRUE
   if appleInterfaceStyle == nil
      theme = dark //will switch to light
   else
      theme = light //will switch to dark
   endif
else
   theme = appleInterfaceStyle //Just like Mojave
endif

What does will switch to light/dark mean? I understand that if switchesAutomatically == true the role of nil (in appleInterfaceStyle) is changed. But what does something that "will" happen have to do with the current theme setting.

Ok so I guess it has nothing to do with the current state.

@weisJ weisJ added the macOS Related to the macOS operating system label Apr 2, 2020
@weisJ weisJ force-pushed the macos_preferences branch 2 times, most recently from 29e0321 to fed32f2 Compare April 2, 2020 10:47
@vlsi
Copy link
Contributor

vlsi commented Apr 2, 2020

What does will switch to light/dark mean? I understand that if switchesAutomatically == true the role of nil (in appleInterfaceStyle) is changed. But what does something that "will" happen have to do with the current theme setting.

Frankly speaking, I've no idea. We should probably find someone with 10.15 :) (I've not updated yet :) )

One more thing. Can you check if [[NSUserDefaults standardUserDefaults] contains any key-value pair representing the text scaling?

I do not see UI for adjusting text scaling. Only "resolution".

NSDefaults has the following fonts, however, I don't think they are user-changeable.

value: .SFNSText forKey: NSSystemFont
value: 13 forKey: NSSystemFontSize
value: .SFNSText-Bold forKey: NSBoldSystemFont

value: Menlo-Regular forKey: NSFixedPitchFont
value: 11 forKey: NSFixedPitchFontSize

value: Helvetica forKey: NSFont
value: 12 forKey: NSFontSize

value: 4 forKey: AppleAntiAliasingThreshold

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

Ok I have implemented the notification listener for dark mode and adjusted the function for checking dark mode.
@vlsi Can you check if thw functions work as espected:

// Does it return the correct value?
JNIThemeInfoMacOS.isDarkThemeEnabled(); 

 // Should be != 0 and a creation message is logged. After creation changes in dark mode should be printed:
long listenerPtr = JNIThemeInfoMacOS.createPreferenceChangeListener();

 // A message should be logged that the listener was destroyed:
JNIThemeInfoMacOS.deletePreferenceChangeListener(listenerPtr);

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

Frankly speaking, I've no idea. We should probably find someone with 10.15 :) (I've not updated yet :) )

Definitely needed 👍 If we don't find anyone maybe a github actions script could work (macOS-latest should run on 10.15)

I do not see UI for adjusting text scaling. Only "resolution".

Too bad. Could it be that if the font size is increased [NSFont systemFontSize] simply returns a larger value?

@vlsi
Copy link
Contributor

vlsi commented Apr 2, 2020

Could it be that if the font size is increased [NSFont systemFontSize] simply returns a larger value?

It does not. The values are the same no matter if I increase or decrease "font size".

The font size is adjusted for each monitor individually, so the "font size" is probably reported for each monitor individually as well.

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

What exactly does the larger text...more space settings exactly do? Are only cocoa/system apps affected or is it simply scaling the whole screen? Does a swing application look the same regardless of the setting?

Btw. If bigger text ist selected does the titlebar still have the correct size (as the window buttons get scaled too)?

@vlsi
Copy link
Contributor

vlsi commented Apr 2, 2020

What exactly does the larger text...more space settings exactly do? Are only cocoa/system apps affected or is it simply scaling the whole screen?

It scales everything. Controls, buttons to close Windows, Swing applications, etc, etc.
Icons are scaled as well.

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

Oh so I guess the setting can simply ignored then? As there is no other system setting for font size I’d just always return the default font size on macOS.

As for the other settings:

  • inverted screen colours: I guess this is handled by the os already.
  • accent color change: Maybe I could add a separate accent colour setting which changes the focus/selection highlights accordingly.

@vlsi
Copy link
Contributor

vlsi commented Apr 2, 2020

inverted screen colours: I guess this is handled by the os already.

That is indeed handled by OS. I just mean there might be a case for adjusting colors for a better look with inverted colors. I guess "inverting" colors might make contrast worse.

accent color change: Maybe I could add a separate accent colour setting which changes the focus/selection highlights accordingly.

Well, it can probably be ignored, for now, however, it might be a case for "css-like" themes.
I'm not sure how viable (and/or hard to implement) that is though.

Just a couple of samples:
Снимок экрана 2020-04-02 в 15 32 32
Снимок экрана 2020-04-02 в 15 32 47
Снимок экрана 2020-04-02 в 15 32 52
Снимок экрана 2020-04-02 в 15 33 20

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

inverted screen colours: I guess this is handled by the os already.

That is indeed handled by OS. I just mean there might be a case for adjusting colors for a better look with inverted colors. I guess "inverting" colors might make contrast worse.

For now I'll not handle this situation. I guess it's rather specific case.

accent color change: Maybe I could add a separate accent colour setting which changes the focus/selection highlights accordingly.

Well, it can probably be ignored, for now, however, it might be a case for "css-like" themes.
I'm not sure how viable (and/or hard to implement) that is though.

Just a couple of samples:
...

I was thinking of having themes specify two list of colours that are subject to "personalization".
Accent colours and selection colours (the latter is basically just the text selection foreground most of the time).

These colours could then be hue matched with the current system colours. I think this would be the easiest solution that works in a more cross-platform way (i.e. themes don't have to specify all accent/selection values in multiple colours. For example IntelliJ theme would need to specify 19 different values for all macOS colours) that allows basically all available colours (especially because that is the case for text selection on macOS.)

I'll try it out and post some screenshots of how it looks with the macOS colours.

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

Ok I have implemented the option to have accent colours mapped. They can either be completely replaced or give relative values (w.r.t to the new accent colour) in terms of hsb values.

Working with hsb makes it a lot easier to keep the accent hue and only adjust brightness/saturation for hover/click/disabled colours.
Here is how it looks for the IntelliJ theme (the other themes would still need to be prepared for this, otherwise they simply don't support it and nothing happens so this can be done incrementally):

Annotation 2020-04-02 175744 Annotation 2020-04-01 200843
Annotation 2020-04-02 175713 Annotation 2020-04-02 175639
Annotation 2020-04-02 175856 Annotation 2020-04-02 175818

WDYT?

@weisJ
Copy link
Owner Author

weisJ commented Apr 2, 2020

I guess this could also be done on windows using the accent colour. Though there should probably be a setting to ignore the accent colour (which would also stop it from firing theme preference change events) as there are a lot more accents to choose from some of which might not look that good with some themes (there is no way to guarantee it for arbitrary accents).

In this case a program using darklaf should offer the user to select a custom accent colour or use the default accent colour (provided by the theme). I think that accent colours should also be a feature that is disabled by default and has to be explicitly enabled (I'm not quite certain about how and what part exactly i.e. the system accent isn't taken into consideration or accents are ignored altogether).

High contrast theme should always ignore these settings as it doesn't make much sense there.

@weisJ weisJ force-pushed the macos_preferences branch 3 times, most recently from 7163826 to 900a683 Compare April 10, 2020 20:08
@weisJ weisJ linked an issue Apr 11, 2020 that may be closed by this pull request
@weisJ weisJ force-pushed the macos_preferences branch 11 times, most recently from 631eb8d to dbdb944 Compare April 11, 2020 12:57
@weisJ
Copy link
Owner Author

weisJ commented Apr 11, 2020

Apparently [self listenToKey:@"AppleColorPreferencesChangedNotification" onCenter:center]; does only fire of the system menu loses focus. But [self listenToKey:nil onCenter:center]; does fire even if the the focus is not switched. I could simply listen to everything and filter the messages or simply leave it as is (as selections are shown if the window has focus anyway).

@weisJ
Copy link
Owner Author

weisJ commented Apr 11, 2020

@vlsi The selection colour should now actually change
What is your opinion on my previous comment?

@weisJ
Copy link
Owner Author

weisJ commented Apr 15, 2020

Looks like the check for AppleInterfaceStyleSwitchesAutomatically isn't actually necessary. See here

@weisJ
Copy link
Owner Author

weisJ commented Apr 16, 2020

If there are no more objections I’d merge this PR.

@weisJ weisJ merged commit 6eeb813 into master Apr 17, 2020
@weisJ weisJ deleted the macos_preferences branch May 23, 2020 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
macOS Related to the macOS operating system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Select dark/light theme based on the OS setting
3 participants