Skip to content
Snippets Groups Projects
Commit 1e3610f7 authored by George Nachman's avatar George Nachman
Browse files

Refactor code that decides if the hotkey window should be hidden when a window...

Refactor code that decides if the hotkey window should be hidden when a window resigns key. Add a feature to try to detect when spotlight is opened to not auto-close the hotkey window when that happens. The new feature is behind a default-off flag because I'm sure it'll do something unexpected. It should be turned on by default in the 3.1 beta.
parent 3a418f5f
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -20,6 +20,8 @@
// block is called on every element in order.
- (NSArray *)filteredArrayUsingBlock:(BOOL (^)(id anObject))block;
 
- (BOOL)containsObjectBesides:(id)anObject;
@end
 
@interface NSMutableArray (iTerm)
Loading
Loading
Loading
Loading
@@ -52,6 +52,14 @@
return [self objectsAtIndexes:indexes];
}
 
- (BOOL)containsObjectBesides:(id)anObject {
for (id object in self) {
if (![object isEqual:anObject]) {
return YES;
}
}
return NO;
}
 
@end
 
Loading
Loading
Loading
Loading
@@ -7,6 +7,7 @@
//
 
#import "NSWorkspace+iTerm.h"
#import <CoreGraphics/CoreGraphics.h>
 
@implementation NSWorkspace (iTerm)
 
Loading
Loading
Loading
Loading
@@ -38,10 +38,12 @@
#import "iTermWarning.h"
#import "iTermWindowShortcutLabelTitlebarAccessoryViewController.h"
#import "MovePaneController.h"
#import "NSArray+iTerm.h"
#import "NSScreen+iTerm.h"
#import "NSStringITerm.h"
#import "NSView+iTerm.h"
#import "NSWindow+PSM.h"
#import "NSWorkspace+iTerm.h"
#import "PasteboardHistory.h"
#import "PopupModel.h"
#import "PopupWindow.h"
Loading
Loading
@@ -2637,75 +2639,110 @@ static NSString* TERMINAL_ARRANGEMENT_HIDING_TOOLBELT_SHOULD_RESIZE_WINDOW = @"H
// shouldn't be hidden right now.
- (PseudoTerminal *)hotkeyWindowToHide {
DLog(@"Checking if hotkey window should be hidden.");
BOOL haveMain = NO;
BOOL otherTerminalIsKey = NO;
for (NSWindow *window in [[NSApplication sharedApplication] windows]) {
if ([window isMainWindow]) {
haveMain = YES;
}
if (togglingFullScreen_) {
// I can't get this code path to execute. Candidate for removal.
DLog(@"Currently toggling fullscreen");
return nil;
}
PseudoTerminal *hotkeyTerminal = nil;
for (PseudoTerminal *term in [[iTermController sharedInstance] terminals]) {
PTYWindow *window = [term ptyWindow];
DLog(@"Window %@ key=%d isHotKeyWindow=%d", window, [window isKeyWindow], (int)[term isHotKeyWindow]);
if ([window isKeyWindow] && ![term isHotKeyWindow]) {
DLog(@"Key window is %@", window);
otherTerminalIsKey = YES;
}
if ([term isHotKeyWindow]) {
hotkeyTerminal = term;
}
// Check if a terminal that isn't the hotkey window is the key window.
PseudoTerminal *hotkeyTerminal = [[iTermController sharedInstance] hotkeyWindow];
if (!hotkeyTerminal) {
DLog(@"Failed to find a hotkey window");
return nil;
}
NSArray<PTYWindow *> *keyTerminalWindows = [[iTermController sharedInstance] keyTerminalWindows];
 
DLog(@"%@ haveMain=%d otherTerminalIsKey=%d", self.window, haveMain, otherTerminalIsKey);
if (hotkeyTerminal && (!haveMain || otherTerminalIsKey)) {
DLog(@"Return %@", hotkeyTerminal);
return hotkeyTerminal;
} else {
DLog(@"No need to hide hotkey window");
BOOL nonHotkeyTerminalIsKey = [keyTerminalWindows containsObjectBesides:[hotkeyTerminal ptyWindow]];
BOOL haveMain = [[iTermController sharedInstance] anyWindowIsMain];
if (haveMain && !nonHotkeyTerminalIsKey) {
// Issue 1251: we can take this path when a "clipboard manager" window is open.
DLog(@"Some non-terminal window is now main. Key terminal windows are %@",
[[iTermController sharedInstance] keyTerminalWindows]);
NSLog(@"%@", [[iTermController sharedInstance] terminals]);
return nil;
}
if ([[hotkeyTerminal window] alphaValue] == 0) {
// Hotkey window not visible. This path is taken when there is a hidden hotkey window.
DLog(@"Hotkey window's alpha value is 0.");
return nil;
}
if (![iTermPreferences boolForKey:kPreferenceKeyHotkeyAutoHides]) {
DLog(@"Autohide is disabled");
return nil;
}
if ([[HotkeyWindowController sharedInstance] rollingInHotkeyTerm]) {
DLog(@"Currently rolling in hotkey window");
return nil;
}
DLog(@"windowDidResignKey: is hotkey and hotkey window auto-hides");
// We want to dismiss the hotkey window when some other window
// becomes key. Note that if a popup closes this function shouldn't
// be called at all because it makes us key before closing itself.
// If a popup is opening, though, we shouldn't close ourselves.
if ([[NSApp keyWindow] isKindOfClass:[PopupWindow class]]) {
DLog(@"Key window is a popup");
return nil;
}
if ([[NSApp keyWindow] isKindOfClass:[iTermOpenQuicklyWindow class]]) {
DLog(@"Key window is Open Quickly");
return nil;
}
if ([[NSApp keyWindow] isKindOfClass:[iTermAboutWindow class]]) {
DLog(@"Key window is About");
return nil;
}
if ([[[NSApp keyWindow] windowController] isKindOfClass:[iTermProfilesWindowController class]]) {
DLog(@"Key window is Profiles");
return nil;
}
if ([iTermWarning showingWarning]) {
DLog(@"A warning is showing");
return nil;
}
if ([[[NSApp keyWindow] windowController] isKindOfClass:[PreferencePanel class]]) {
DLog(@"Key window is prefs");
return nil;
}
if ([self.window.sheets containsObject:[NSApp keyWindow]]) {
DLog(@"A sheet is being shown");
return nil;
}
// The hotkey window can co-exist with these apps.
static NSString *kAlfredBundleId = @"com.runningwithcrayons.Alfred-2";
static NSString *kApptivateBundleId = @"se.cocoabeans.apptivate";
NSArray *bundleIdsToNotDismissFor = @[ kAlfredBundleId, kApptivateBundleId ];
if ([bundleIdsToNotDismissFor containsObject:[[[NSWorkspace sharedWorkspace] frontmostApplication] bundleIdentifier]]) {
DLog(@"The frontmost application is whitelisted");
return nil;
}
if ([iTermAdvancedSettingsModel hotkeyWindowIgnoresSpotlight]) {
// This tries to detect if the Spotlight window is open.
if ([[iTermController sharedInstance] keystrokesBeingStolen]) {
DLog(@"Keystrokes being stolen (spotlight open?)");
return nil;
}
}
DLog(@"Should hide hotkey terminal %@", hotkeyTerminal);
return hotkeyTerminal;
}
 
- (void)maybeHideHotkeyWindow {
if (togglingFullScreen_) {
return;
}
PseudoTerminal *hotkeyTerminal = [self hotkeyWindowToHide];
if (hotkeyTerminal) {
DLog(@"Want to hide hotkey window. hotkey window's alpha=%f, autohides=%d, rolling in=%d",
[[hotkeyTerminal window] alphaValue],
(int)[iTermPreferences boolForKey:kPreferenceKeyHotkeyAutoHides],
(int)[[HotkeyWindowController sharedInstance] rollingInHotkeyTerm]);
if ([[hotkeyTerminal window] alphaValue] > 0 &&
[iTermPreferences boolForKey:kPreferenceKeyHotkeyAutoHides] &&
![[HotkeyWindowController sharedInstance] rollingInHotkeyTerm]) {
DLog(@"windowDidResignKey: is hotkey and hotkey window auto-hides");
// The hotkey window can co-exist with these apps.
static NSString *kAlfredBundleId = @"com.runningwithcrayons.Alfred-2";
static NSString *kApptivateBundleId = @"se.cocoabeans.apptivate";
NSArray *bundleIdsToNotDismissFor = @[ kAlfredBundleId, kApptivateBundleId ];
// We want to dismiss the hotkey window when some other window
// becomes key. Note that if a popup closes this function shouldn't
// be called at all because it makes us key before closing itself.
// If a popup is opening, though, we shouldn't close ourselves.
if (![[NSApp keyWindow] isKindOfClass:[PopupWindow class]] &&
![[NSApp keyWindow] isKindOfClass:[iTermOpenQuicklyWindow class]] &&
![[NSApp keyWindow] isKindOfClass:[iTermAboutWindow class]] &&
![[[NSApp keyWindow] windowController] isKindOfClass:[iTermProfilesWindowController class]] &&
![iTermWarning showingWarning] &&
![[[NSApp keyWindow] windowController] isKindOfClass:[PreferencePanel class]] &&
![self.window.sheets containsObject:[NSApp keyWindow]] &&
![bundleIdsToNotDismissFor containsObject:[[[NSWorkspace sharedWorkspace] frontmostApplication] bundleIdentifier]]) {
PtyLog(@"windowDidResignKey: new key window isn't popup so hide myself");
if ([[[NSApp keyWindow] windowController] isKindOfClass:[PseudoTerminal class]]) {
[[HotkeyWindowController sharedInstance] doNotOrderOutWhenHidingHotkeyWindow];
}
[[HotkeyWindowController sharedInstance] hideHotKeyWindow:hotkeyTerminal];
}
PtyLog(@"windowDidResignKey: new key window isn't popup so hide myself");
if ([[[NSApp keyWindow] windowController] isKindOfClass:[PseudoTerminal class]]) {
[[HotkeyWindowController sharedInstance] doNotOrderOutWhenHidingHotkeyWindow];
}
[[HotkeyWindowController sharedInstance] hideHotKeyWindow:hotkeyTerminal];
}
}
 
Loading
Loading
Loading
Loading
@@ -123,5 +123,6 @@
+ (BOOL)focusReportingEnabled;
 
+ (BOOL)hideFromDockAndAppSwitcher;
+ (BOOL)hotkeyWindowIgnoresSpotlight;
 
@end
Loading
Loading
@@ -87,6 +87,7 @@ DEFINE_BOOL(focusReportingEnabled, YES, @"Terminal: Apps may turn on Focus Repor
DEFINE_FLOAT(hotkeyTermAnimationDuration, 0.25, @"Hotkey: Duration in seconds of the hotkey window animation.\nWarning: reducing this value may cause problems if you have multiple displays.");
DEFINE_BOOL(dockIconTogglesWindow, NO, @"Hotkey: If the only window is a hotkey window, then clicking the dock icon shows or hides it.");
DEFINE_BOOL(hotkeyWindowFloatsAboveOtherWindows, NO, @"Hotkey: The hotkey window floats above other windows even when another application is active.\nYou must disable “Prefs > Keys > Hotkey window hides when focus is lost” for this setting to be effective.");
DEFINE_BOOL(hotkeyWindowIgnoresSpotlight, NO, @"Hotkey: Prevent opening Spotlight from auto-closing the hotkey window.\nThis feature is experimental and may have unexpected side-effects.");
 
#pragma mark General
DEFINE_STRING(searchCommand, @"http://google.com/search?q=%@", @"General: Template for URL of search engine.\niTerm2 replaces the string “%@” with the text to search for. Query parameter percent escaping is used.");
Loading
Loading
Loading
Loading
@@ -39,6 +39,7 @@
@class PTYSession;
@class PTYTab;
@class PTYTextView;
@class PTYWindow;
 
@interface iTermController : NSObject
 
Loading
Loading
@@ -53,6 +54,10 @@
@property(nonatomic, nonatomic, assign) PseudoTerminal *currentTerminal;
@property(nonatomic, readonly) int numberOfTerminals;
@property(nonatomic, readonly) BOOL hasRestorableSession;
@property(nonatomic, readonly) BOOL keystrokesBeingStolen;
@property(nonatomic, readonly) BOOL anyWindowIsMain;
@property(nonatomic, readonly) PseudoTerminal *hotkeyWindow;
@property(nonatomic, readonly) NSArray<PTYWindow *> *keyTerminalWindows;
 
+ (iTermController*)sharedInstance;
+ (void)releaseSharedInstance;
Loading
Loading
Loading
Loading
@@ -27,6 +27,7 @@
 
#import "iTermController.h"
 
#import "DebugLogging.h"
#import "FutureMethods.h"
#import "HotkeyWindowController.h"
#import "ITAddressBookMgr.h"
Loading
Loading
@@ -1252,6 +1253,55 @@ static iTermController *gSharedInstance;
}
}
 
- (BOOL)anyOrderedWindowIsKey {
DLog(@"Searching for key window...");
for (NSWindow *window in [NSApp orderedWindows]) {
if (window.isKeyWindow) {
DLog(@"Key ordered window is %@", window);
return YES;
}
}
DLog(@"No key window");
return NO;
}
- (BOOL)keystrokesBeingStolen {
// If we're active and have ordered windows but none of them are key then our keystrokes are
// being stolen by something else. This is meant to detect when Spotlight is open. It might
// also catch other things that act similarly.
return [NSApp isActive] && [[NSApp orderedWindows] count] > 0 && ![self anyOrderedWindowIsKey];
}
- (BOOL)anyWindowIsMain {
for (NSWindow *window in [[NSApplication sharedApplication] windows]) {
if ([window isMainWindow]) {
return YES;
}
}
return NO;
}
- (PseudoTerminal *)hotkeyWindow {
for (PseudoTerminal *term in [[iTermController sharedInstance] terminals]) {
if (term.isHotKeyWindow) {
return term;
}
}
return nil;
}
- (NSArray<PTYWindow *> *)keyTerminalWindows {
NSMutableArray<PTYWindow *> *temp = [NSMutableArray array];
for (PseudoTerminal *term in [[iTermController sharedInstance] terminals]) {
PTYWindow *window = [term ptyWindow];
if ([window isKeyWindow]) {
[temp addObject:window];
}
}
return temp;
}
// accessors for to-many relationships:
- (NSArray*)terminals {
return (_terminalWindows);
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment