Skip to content

Commit 6ecd752

Browse files
committed
Dark mode improve docs for v:os_appearance and add tests
Make sure docs for v:os_appearance make it clear that it is reflecting MacVim's appearance, not the OS, which matters when not using "automatic" in dark mode appearance. Also add some unit tests to test this part of the functionality to add test coverage. Also see #1479
1 parent 52550fc commit 6ecd752

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

runtime/doc/eval.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,9 +2439,12 @@ v:operator The last operator given in Normal mode. This is a single
24392439
Read-only.
24402440

24412441
*v:os_appearance* *os-appearance-variable*
2442-
v:os_appearance The current OS appearance mode. Useful if you want to change
2442+
v:os_appearance The current OS appearance mode. Useful if you want to change
24432443
options |background| or |colorscheme| according to the
2444-
appearance of the GUI frontend. See also |OSAppearanceChanged|.
2444+
appearance of the GUI frontend. See also
2445+
|OSAppearanceChanged|. If the "Dark mode selection" setting
2446+
is not set to "Automatic", then this value will reflect that
2447+
setting instead.
24452448
value description ~
24462449
0 Light Mode (always 0 on unsupported platforms)
24472450
1 Dark Mode

src/MacVim/MacVimTests/MacVimTests.m

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,83 @@ - (void) testGuifontSystemMonospace {
458458
[self waitForVimClose];
459459
}
460460

461+
/// Test that dark mode settings work and the corresponding Vim bindings are functional.
462+
///
463+
/// Note that `v:os_appearance` and OSAppearanceChanged respond to the view's appearance
464+
/// rather than the OS setting. When using manual light/dark or "use background" settings,
465+
/// they do not reflect the current OS dark mode setting.
466+
- (void) testDarkMode {
467+
NSUserDefaults *ud = NSUserDefaults.standardUserDefaults;
468+
469+
MMAppController *app = MMAppController.sharedInstance;
470+
471+
[app openNewWindow:NewWindowClean activate:YES];
472+
[self waitForVimOpenAndMessages];
473+
474+
MMVimView *vimView = [[[app keyVimController] windowController] vimView];
475+
476+
// We just use the system appearance to determine the initial state. Otherwise
477+
// we have to change the system appearance to light mode first which we don't
478+
// have permission to do.
479+
const BOOL systemUsingDarkMode = [[ud stringForKey:@"AppleInterfaceStyle"] isEqualToString:@"Dark"];
480+
const NSAppearance *systemAppearance = systemUsingDarkMode ?
481+
[NSAppearance appearanceNamed: NSAppearanceNameDarkAqua] : [NSAppearance appearanceNamed: NSAppearanceNameAqua];
482+
483+
// Default setting uses system appearance
484+
XCTAssertEqualObjects(vimView.effectiveAppearance, systemAppearance);
485+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"v:os_appearance"], systemUsingDarkMode ? @"1" : @"0");
486+
487+
// Cache original settings / set up setting overrides
488+
NSDictionary<NSString *, id> *defaults = [ud volatileDomainForName:NSArgumentDomain];
489+
NSMutableDictionary<NSString *, id> *newDefaults = [defaults mutableCopy];
490+
491+
// Manual Light / Dark mode setting
492+
newDefaults[MMAppearanceModeSelectionKey] = [NSNumber numberWithInt:MMAppearanceModeSelectionLight];
493+
[ud setVolatileDomain:newDefaults forName:NSArgumentDomain];
494+
[app refreshAllAppearances];
495+
XCTAssertEqualObjects(vimView.effectiveAppearance, [NSAppearance appearanceNamed: NSAppearanceNameAqua]);
496+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"v:os_appearance"], @"0");
497+
498+
// Set up a listener for OSAppearanceChanged event to make sure it's called
499+
// when the view appearance changes.
500+
[self sendStringToVim:@":let g:os_appearance_changed_called=0\n" withMods:0];
501+
[self sendStringToVim:@":autocmd OSAppearanceChanged * let g:os_appearance_changed_called+=1\n" withMods:0];
502+
[self waitForEventHandlingAndVimProcess];
503+
504+
newDefaults[MMAppearanceModeSelectionKey] = [NSNumber numberWithInt:MMAppearanceModeSelectionDark];
505+
[ud setVolatileDomain:newDefaults forName:NSArgumentDomain];
506+
[app refreshAllAppearances];
507+
XCTAssertEqualObjects(vimView.effectiveAppearance, [NSAppearance appearanceNamed: NSAppearanceNameDarkAqua]);
508+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"v:os_appearance"], @"1");
509+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"g:os_appearance_changed_called"], @"1");
510+
511+
// "Use background" setting
512+
[self sendStringToVim:@":set background=dark\n" withMods:0];
513+
[self waitForEventHandlingAndVimProcess];
514+
515+
newDefaults[MMAppearanceModeSelectionKey] = [NSNumber numberWithInt:MMAppearanceModeSelectionBackgroundOption];
516+
[NSUserDefaults.standardUserDefaults setVolatileDomain:newDefaults forName:NSArgumentDomain];
517+
[app refreshAllAppearances];
518+
XCTAssertEqualObjects(vimView.effectiveAppearance, [NSAppearance appearanceNamed: NSAppearanceNameDarkAqua]);
519+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"v:os_appearance"], @"1");
520+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"g:os_appearance_changed_called"], @"1"); // we stayed in dark mode, so OSAppearnceChanged didn't trigger
521+
522+
[self sendStringToVim:@":set background=light\n" withMods:0];
523+
[self waitForEventHandlingAndVimProcess];
524+
XCTAssertEqualObjects(vimView.effectiveAppearance, [NSAppearance appearanceNamed: NSAppearanceNameAqua]);
525+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"v:os_appearance"], @"0");
526+
XCTAssertEqualObjects([[app keyVimController] evaluateVimExpression:@"g:os_appearance_changed_called"], @"2");
527+
528+
// Restore original settings and make sure it's reset
529+
[NSUserDefaults.standardUserDefaults setVolatileDomain:defaults forName:NSArgumentDomain];
530+
[app refreshAllAppearances];
531+
XCTAssertEqualObjects(vimView.effectiveAppearance, systemAppearance);
532+
533+
// Clean up
534+
[[app keyVimController] sendMessage:VimShouldCloseMsgID data:nil];
535+
[self waitForVimClose];
536+
}
537+
461538
/// Test that document icon is shown in title bar when enabled.
462539
- (void) testTitlebarDocumentIcon {
463540
MMAppController *app = MMAppController.sharedInstance;

0 commit comments

Comments
 (0)