diff --git a/src/MacVim/MacVimTests/MacVimTests.m b/src/MacVim/MacVimTests/MacVimTests.m index b87978726f..e40d5c4fa3 100644 --- a/src/MacVim/MacVimTests/MacVimTests.m +++ b/src/MacVim/MacVimTests/MacVimTests.m @@ -15,6 +15,8 @@ #import "Miscellaneous.h" #import "MMAppController.h" #import "MMApplication.h" +#import "MMFullScreenWindow.h" +#import "MMWindow.h" #import "MMTextView.h" #import "MMWindowController.h" #import "MMVimController.h" @@ -30,10 +32,6 @@ @end // Test harness -@interface MMAppController (Tests) -- (NSMutableArray*)vimControllers; -@end - @implementation MMAppController (Tests) - (NSMutableArray*)vimControllers { return vimControllers; @@ -50,6 +48,12 @@ static BOOL forceInLiveResize = NO; } @end +@implementation MMWindowController (Tests) +- (BOOL)fullScreenEnabled { + return fullScreenEnabled; +} +@end + @interface MacVimTests : XCTestCase @end @@ -733,4 +737,129 @@ do { \ [self waitForVimClose]; } +- (void)waitForNativeFullscreenEnter { + XCTestExpectation *expectation = [self expectationWithDescription:@"NativeFullscreenEnter"]; + + SEL sel = @selector(windowDidEnterFullScreen:); + Method method = class_getInstanceMethod([MMWindowController class], sel); + + IMP origIMP = method_getImplementation(method); + IMP newIMP = imp_implementationWithBlock(^(id self, id notification) { + typedef void (*fn)(id,SEL,NSNotification*); + ((fn)origIMP)(self, sel, notification); + [expectation fulfill]; + }); + + method_setImplementation(method, newIMP); + [self waitForExpectations:@[expectation] timeout:10]; + method_setImplementation(method, origIMP); +} + +- (void)waitForNativeFullscreenExit { + XCTestExpectation *expectation = [self expectationWithDescription:@"NativeFullscreenExit"]; + + SEL sel = @selector(windowDidExitFullScreen:); + Method method = class_getInstanceMethod([MMWindowController class], sel); + + IMP origIMP = method_getImplementation(method); + IMP newIMP = imp_implementationWithBlock(^(id self, id notification) { + typedef void (*fn)(id,SEL,NSNotification*); + ((fn)origIMP)(self, sel, notification); + [expectation fulfill]; + }); + + method_setImplementation(method, newIMP); + [self waitForExpectations:@[expectation] timeout:10]; + method_setImplementation(method, origIMP); +} + +/// Utility to test full screen functionality in both non-native/native full +/// screen. +- (void) fullScreenTestWithNative:(BOOL)native { + MMAppController *app = MMAppController.sharedInstance; + + // Cache test defaults + NSUserDefaults *ud = NSUserDefaults.standardUserDefaults; + NSDictionary *defaults = [ud volatileDomainForName:NSArgumentDomain]; + NSMutableDictionary *newDefaults = [defaults mutableCopy]; + + // Change native full screen setting + newDefaults[MMNativeFullScreenKey] = [NSNumber numberWithBool:native]; + [ud setVolatileDomain:newDefaults forName:NSArgumentDomain]; + + [app openNewWindow:NewWindowClean activate:YES]; + [self waitForVimOpenAndMessages]; + + MMWindowController *winController = app.keyVimController.windowController; + + // Enter full screen and check that the states are properly changed. + [self sendStringToVim:@":set fu\n" withMods:0]; + if (native) { + [self waitForNativeFullscreenEnter]; + } else { + [self waitForEventHandlingAndVimProcess]; + [self waitForEventHandlingAndVimProcess]; // wait one more cycle to make sure we finished the transition + } + + XCTAssertTrue([winController fullScreenEnabled]); + if (native) { + XCTAssertTrue([winController.window isKindOfClass:[MMWindow class]]); + } else { + XCTAssertTrue([winController.window isKindOfClass:[MMFullScreenWindow class]]); + } + + // Exit full screen + [self sendStringToVim:@":set nofu\n" withMods:0]; + if (native) { + [self waitForNativeFullscreenExit]; + } else { + [self waitForEventHandlingAndVimProcess]; + [self waitForEventHandlingAndVimProcess]; // wait one more cycle to make sure we finished the transition + } + + XCTAssertFalse([winController fullScreenEnabled]); + XCTAssertTrue([winController.window isKindOfClass:[MMWindow class]]); + + // Enter full screen again + [self sendStringToVim:@":set fu\n" withMods:0]; + if (native) { + [self waitForNativeFullscreenEnter]; + } else { + [self waitForEventHandlingAndVimProcess]; + [self waitForEventHandlingAndVimProcess]; // wait one more cycle to make sure we finished the transition + } + + XCTAssertTrue([winController fullScreenEnabled]); + + // Test that resizing the vim view does not work when in full screen as we fix the window size instead + MMTextView *textView = [[[[app keyVimController] windowController] vimView] textView]; + const int fuRows = textView.maxRows; + const int fuCols = textView.maxColumns; + XCTAssertNotEqual(10, fuRows); // just some basic assumptions as full screen should have more rows/cols than this + XCTAssertNotEqual(30, fuCols); + [self sendStringToVim:@":set lines=10\n" withMods:0]; + [self sendStringToVim:@":set columns=30\n" withMods:0]; + [self waitForEventHandlingAndVimProcess]; + [self waitForEventHandlingAndVimProcess]; // need to wait twice to allow full screen to force it back + XCTAssertEqual(fuRows, textView.maxRows); + XCTAssertEqual(fuCols, textView.maxColumns); + + // Clean up + [[app keyVimController] sendMessage:VimShouldCloseMsgID data:nil]; + [self waitForVimClose]; + + XCTAssertEqual(0, [app vimControllers].count); + + // Restore settings to test defaults + [ud setVolatileDomain:defaults forName:NSArgumentDomain]; +} + +- (void) testFullScreenNonNative { + [self fullScreenTestWithNative:NO]; +} + +- (void) testFullScreenNative { + [self fullScreenTestWithNative:YES]; +} + @end