Permalink
Browse files

Completely avoid moving windows that cannot be moved to a third of th…

…e display.

Previously Spectacle would try to move a window to a third of the display, regardless of whether the window can actually fit. If it couldn't Spectacle tries to move it back to where it came from. This behavior resulted in an annoying "flicker" as the window is moved around.

To prevent this issue Spectacle now attempts to remember which window sizes and positions have posed a problem in the past.

In next iterations Spectacle should persist this "blacklist" to the filesystem.
  • Loading branch information...
1 parent 99b8326 commit 6cd5131c1c660047d60e017fb2674e762f7ef9d7 @eczarny committed Aug 29, 2012
Showing with 36 additions and 1 deletion.
  1. +1 −1 Frameworks/ZeroKit
  2. +4 −0 SpectacleUtilities.h
  3. +1 −0 SpectacleWindowPositionManager.h
  4. +30 −0 SpectacleWindowPositionManager.m
@@ -24,6 +24,10 @@
#pragma mark -
+#define WindowRectToString(windowRect) [NSString stringWithFormat: @"(%f, %f) %fx%f", windowRect.origin.x, windowRect.origin.y, windowRect.size.width, windowRect.size.height]
+
+#pragma mark -
+
@interface SpectacleUtilities : ZeroKitUtilities
+ (void)displayAccessibilityAPIAlert;
@@ -24,6 +24,7 @@ typedef enum {
@interface SpectacleWindowPositionManager : NSObject {
NSMutableDictionary *myUndoHistory;
NSMutableDictionary *myRedoHistory;
+ NSMutableSet *myBlacklistedWindowRects;
}
+ (SpectacleWindowPositionManager *)sharedManager;
@@ -25,12 +25,20 @@
#pragma mark -
+#define BlacklistedWindowRect(applicationName, windowRect) [NSString stringWithFormat: @"%@ - %@", applicationName, WindowRectToString(windowRect)]
+
+#pragma mark -
+
@interface SpectacleWindowPositionManager (SpectacleWindowPositionManagerPrivate)
- (ZeroKitAccessibilityElement *)frontMostWindowElement;
#pragma mark -
+- (NSString *)frontMostApplicationName;
+
+#pragma mark -
+
- (CGRect)rectOfWindowWithAccessibilityElement: (ZeroKitAccessibilityElement *)accessibilityElement;
#pragma mark -
@@ -79,6 +87,7 @@ - (id)init {
if ((self = [super init])) {
myUndoHistory = [[NSMutableDictionary dictionary] retain];
myRedoHistory = [[NSMutableDictionary dictionary] retain];
+ myBlacklistedWindowRects = [[NSMutableSet set] retain];
}
return self;
@@ -177,6 +186,7 @@ - (void)redoLastWindowAction {
- (void)dealloc {
[myUndoHistory release];
[myRedoHistory release];
+ [myBlacklistedWindowRects release];
[super dealloc];
}
@@ -207,6 +217,15 @@ - (ZeroKitAccessibilityElement *)frontMostWindowElement {
#pragma mark -
+- (NSString *)frontMostApplicationName {
+ ZeroKitAccessibilityElement *systemWideElement = [ZeroKitAccessibilityElement systemWideElement];
+ ZeroKitAccessibilityElement *applicationWithFocusElement = [systemWideElement elementWithAttribute: kAXFocusedApplicationAttribute];
+
+ return [applicationWithFocusElement stringValueOfAttribute: kAXTitleAttribute];
+}
+
+#pragma mark -
+
- (CGRect)rectOfWindowWithAccessibilityElement: (ZeroKitAccessibilityElement *)accessibilityElement {
CGRect result = CGRectNull;
@@ -228,6 +247,15 @@ - (CGRect)rectOfWindowWithAccessibilityElement: (ZeroKitAccessibilityElement *)a
#pragma mark -
- (void)moveWindowRect: (CGRect)windowRect frameOfScreen: (CGRect)frameOfScreen visibleFrameOfScreen: (CGRect)visibleFrameOfScreen frontMostWindowElement: (ZeroKitAccessibilityElement *)frontMostWindowElement action: (SpectacleWindowAction)action {
+ NSString *frontMostApplicationName = [self frontMostApplicationName];
+ NSString *blacklistedWindowRect = BlacklistedWindowRect(frontMostApplicationName, windowRect);
+
+ if ([myBlacklistedWindowRects containsObject: blacklistedWindowRect]) {
+ NSBeep();
+
+ return;
+ }
+
CGRect previousWindowRect = [self rectOfWindowWithAccessibilityElement: [self frontMostWindowElement]];
[self moveWindowRect: windowRect frontMostWindowElement: frontMostWindowElement];
@@ -237,6 +265,8 @@ - (void)moveWindowRect: (CGRect)windowRect frameOfScreen: (CGRect)frameOfScreen
if (MovingToThirdOfDisplay(action) && !CGRectEqualToRect(movedWindowRect, windowRect)) {
NSBeep();
+ [myBlacklistedWindowRects addObject: blacklistedWindowRect];
+
[self moveWindowRect: previousWindowRect frontMostWindowElement: frontMostWindowElement];
return;

0 comments on commit 6cd5131

Please sign in to comment.