Skip to content

Commit

Permalink
Merge pull request #258 from kjrokos/master
Browse files Browse the repository at this point in the history
Keeps the 1/2->1/3->2/3 window behavior, but resets the cycle anytime…
  • Loading branch information
rca committed Feb 7, 2018
2 parents c7824f1 + 28ffd8a commit 3d671b9
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 83 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ If you find any problem not mentioned there, please submit an issue.
The primary development is done on OSX 10.10, but it should be running under OSX 10.7 as well.

## FAQ
##### How do I turn on/off windows cycling sizes with multiple hotkey presses?

If this feature is on, snapping to the left side of the screen (and top, bottom, and right sides) will resize the window to half of the screen. If window is then snapped to the same side of the screen, it will resize to one third of the screen, and then two thirds of the screen.

If the feature is off, additional snappings will have no effect and the window will remain at half of the screen.

Currently, the only way to accomplish this is by running commands on the command line. To turn the feature on, run:
```
defaults write org.shiftitapp.ShiftIt multipleActionsCycleWindowSizes YES
```
To turn it off, run:
```
defaults write org.shiftitapp.ShiftIt multipleActionsCycleWindowSizes NO
```

##### I disabled the _Show Icon in Menu Bar_ in the preferences, how can I get it back?

Expand Down
4 changes: 3 additions & 1 deletion ShiftIt/DefaultShiftItActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#import "ShiftIt.h"

BOOL CloseTo(double a, double b);
BOOL rectCloseTo(NSRect a, NSRect b);

const extern SimpleWindowGeometryChangeBlock shiftItLeft;
const extern SimpleWindowGeometryChangeBlock shiftItRight;
const extern SimpleWindowGeometryChangeBlock shiftItTop;
Expand Down Expand Up @@ -52,4 +54,4 @@ const extern SimpleWindowGeometryChangeBlock shiftItCenter;

- (id) initWithMode:(BOOL)next;

@end
@end
196 changes: 119 additions & 77 deletions ShiftIt/DefaultShiftItActions.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Expand All @@ -22,97 +22,139 @@
#import "ShiftItApp.h"

BOOL CloseTo(double a, double b) {
return fabs(a - b) < 20;
return fabs(a - b) < 20;
}

BOOL rectCloseTo(NSRect a, NSRect b) {
return CloseTo(a.origin.x, b.origin.x) &&
CloseTo(a.origin.y, b.origin.y) &&
CloseTo(a.size.height, b.size.height) &&
CloseTo(a.size.width, b.size.width);
}

const SimpleWindowGeometryChangeBlock shiftItLeft = ^AnchoredRect(NSRect windowRect, NSSize screenSize) {
NSRect r = NSMakeRect(0, 0, 0, 0);
double screenWidth = screenSize.width;

r.origin.x = 0;
r.origin.y = 0;
NSRect leftHalf = NSMakeRect(0, 0, 0, 0);
leftHalf.origin.x = 0;
leftHalf.origin.y = 0;
leftHalf.size.width = screenSize.width / 2.0;
leftHalf.size.height = screenSize.height;

double w = windowRect.size.width;
double sw = screenSize.width;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL cycle = [defaults boolForKey: kMutipleActionsCycleWindowSizes];
if(!cycle) {
return MakeAnchoredRect(leftHalf, kLeftDirection);
}

r.size.width = screenSize.width / 2.0;
r.size.height = screenSize.height;
NSRect leftThird = NSMakeRect(0, 0, 0, 0);
leftThird.origin.x = 0;
leftThird.origin.y = 0;
leftThird.size.width = floor(screenWidth * 1.0 / 3.0);
leftThird.size.height = screenSize.height;

if (CloseTo(w, sw / 2.0)) {
r.size.width = floor(sw * 1.0 / 3.0);
} else if (CloseTo(w, sw / 3.0)) {
r.size.width = floor(sw * 2.0 / 3.0);
if(rectCloseTo(windowRect, leftHalf)) {
return MakeAnchoredRect(leftThird, kLeftDirection);
} else if (rectCloseTo(windowRect, leftThird)) {
leftHalf.size.width = floor(screenWidth * 2.0 / 3.0);
}

return MakeAnchoredRect(r, kLeftDirection);

return MakeAnchoredRect(leftHalf, kLeftDirection);
};

const SimpleWindowGeometryChangeBlock shiftItRight = ^AnchoredRect(NSRect windowRect, NSSize screenSize) {
NSRect r = NSMakeRect(0, 0, 0, 0);
double screenWidth = screenSize.width;

r.origin.x = screenSize.width / 2;
r.origin.y = 0;
NSRect rightHalf = NSMakeRect(0, 0, 0, 0);
rightHalf.origin.x = screenSize.width / 2;
rightHalf.origin.y = 0;
rightHalf.size.width = screenSize.width / 2.0;
rightHalf.size.height = screenSize.height;

r.size.width = screenSize.width / 2.0;
r.size.height = screenSize.height;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL cycle = [defaults boolForKey: kMutipleActionsCycleWindowSizes];
if(!cycle) {
return MakeAnchoredRect(rightHalf, kRightDirection);
}

double w = windowRect.size.width;
double sw = screenSize.width;
NSRect rightThird = NSMakeRect(0, 0, 0, 0);
rightThird.origin.x = screenWidth - (screenWidth * 1.0 / 3.0);
rightThird.origin.y = 0;
rightThird.size.width = floor(screenWidth * 1.0 / 3.0);
rightThird.size.height = screenSize.height;

if (CloseTo(w, sw / 2.0)) {
r.size.width = floor(sw * 1.0 / 3.0);
r.origin.x = sw - (sw * 1.0 / 3.0);
} else if (CloseTo(w, sw / 3.0)) {
r.size.width = floor(sw * 2.0 / 3.0);
r.origin.x = sw - (sw * 2.0 / 3.0);
if(rectCloseTo(windowRect, rightHalf)) {
FMTLogDebug(@"Close to half!");
return MakeAnchoredRect(rightThird, kRightDirection);
} else if (rectCloseTo(windowRect, rightThird)) {
FMTLogDebug(@"Close to third!");
rightHalf.origin.x = screenWidth - (screenWidth * 2.0 / 3.0);
rightHalf.size.width = floor(screenWidth * 2.0 / 3.0);
}

return MakeAnchoredRect(r, kRightDirection);
return MakeAnchoredRect(rightHalf, kRightDirection);
};

const SimpleWindowGeometryChangeBlock shiftItTop = ^AnchoredRect(NSRect windowRect, NSSize screenSize) {
NSRect r = NSMakeRect(0, 0, 0, 0);
double screenHeight = screenSize.height;

r.origin.x = 0;
r.origin.y = 0;
NSRect topHalf = NSMakeRect(0, 0, 0, 0);
topHalf.origin.x = 0;
topHalf.origin.y = 0;
topHalf.size.width = screenSize.width;
topHalf.size.height = screenSize.height / 2;

r.size.width = screenSize.width;
r.size.height = screenSize.height / 2;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL cycle = [defaults boolForKey: kMutipleActionsCycleWindowSizes];
if(!cycle) {
return MakeAnchoredRect(topHalf, kTopDirection);
}

double windowHeight = windowRect.size.height;
double screenHeight = screenSize.height;
NSRect topThird = NSMakeRect(0, 0, 0, 0);
topThird.origin.x = 0;
topThird.origin.y = 0;
topThird.size.width = screenSize.width;
topThird.size.height = floor(screenHeight * 1.0 / 3.0);

if (CloseTo(windowHeight, screenHeight / 2.0)) {
r.size.height = floor(screenHeight * 1.0 / 3.0);
r.origin.y = screenHeight * 1.0 / 3.0;
} else if (CloseTo(windowHeight, screenHeight / 3.0)) {
r.size.height = floor(screenHeight * 2.0 / 3.0);
r.origin.y = screenHeight * 2.0 / 3.0;
if(rectCloseTo(windowRect, topHalf)) {
return MakeAnchoredRect(topThird, kTopDirection);
} else if (rectCloseTo(windowRect, topThird)) {
topHalf.size.height = floor(screenHeight * 2.0 / 3.0);
}

return MakeAnchoredRect(r, kTopDirection);
return MakeAnchoredRect(topHalf, kTopDirection);
};

const SimpleWindowGeometryChangeBlock shiftItBottom = ^AnchoredRect(NSRect windowRect, NSSize screenSize) {
NSRect r = NSMakeRect(0, 0, 0, 0);
double screenHeight = screenSize.height;

r.origin.x = 0;
r.origin.y = screenSize.height / 2;
NSRect bottomHalf = NSMakeRect(0, 0, 0, 0);
bottomHalf.origin.x = 0;
bottomHalf.origin.y = screenSize.height / 2;
bottomHalf.size.width = screenSize.width;
bottomHalf.size.height = screenSize.height / 2;

r.size.width = screenSize.width;
r.size.height = screenSize.height / 2;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL cycle = [defaults boolForKey: kMutipleActionsCycleWindowSizes];
if(!cycle) {
return MakeAnchoredRect(bottomHalf, kBottomDirection);
}

double windowHeight = windowRect.size.height;
double screenHeight = screenSize.height;
NSRect bottomThird = NSMakeRect(0, 0, 0, 0);
bottomThird.origin.x = 0;
bottomThird.origin.y = screenHeight - (screenHeight * 1.0 / 3.0);
bottomThird.size.width = screenSize.width;
bottomThird.size.height = floor(screenHeight * 1.0 / 3.0);

if (CloseTo(windowHeight, screenHeight / 2.0)) {
r.size.height = floor(screenHeight * 1.0 / 3.0);
r.origin.y = screenHeight - (screenHeight * 1.0 / 3.0);
} else if (CloseTo(windowHeight, screenHeight / 3.0)) {
r.size.height = floor(screenHeight * 2.0 / 3.0);
r.origin.y = screenHeight - (screenHeight * 2.0 / 3.0);
if(rectCloseTo(windowRect, bottomHalf)) {
return MakeAnchoredRect(bottomThird, kBottomDirection);
} else if (rectCloseTo(windowRect, bottomThird)) {
bottomHalf.size.height = floor(screenHeight * 2.0 / 3.0);
bottomHalf.origin.y = screenHeight - (screenHeight * 2.0 / 3.0);
}

return MakeAnchoredRect(r, kBottomDirection);
return MakeAnchoredRect(bottomHalf, kBottomDirection);
};

const SimpleWindowGeometryChangeBlock shiftItTopLeft = ^AnchoredRect(NSRect windowRect, NSSize screenSize) {
Expand Down Expand Up @@ -189,13 +231,13 @@ BOOL CloseTo(double a, double b) {
@implementation IncreaseReduceShiftItAction

- (id)initWithMode:(BOOL)increase {

if (![self init]) {
return nil;
}

increase_ = increase;

return self;
}

Expand Down Expand Up @@ -240,7 +282,7 @@ - (AnchoredRect)shiftWindowRect:(NSRect)windowRect screenSize:(NSSize)screenSize
Margins margins;

[windowContext getAnchorMargins:&margins];

// target window rect
NSRect r = windowRect;
// 1: increase, -1: reduce
Expand Down Expand Up @@ -276,15 +318,15 @@ - (AnchoredRect)shiftWindowRect:(NSRect)windowRect screenSize:(NSSize)screenSize
// directions at the same time we do half to each
int khorz = (int) (inc * kw);
if (directions & kLeftDirection
&& directions & kRightDirection) {
&& directions & kRightDirection) {
khorz /= 2;
}

// max vertical resize at a time is kh, so in case we do resize both
// directions at the same time we do half to each
int kvert = (int) (inc * kh);
if (directions & kTopDirection
&& directions & kBottomDirection) {
&& directions & kBottomDirection) {
kvert /= 2;
}

Expand Down Expand Up @@ -335,16 +377,16 @@ - (BOOL)execute:(id <SIWindowContext>)windowContext error:(NSError **)error {

if (![windowContext getFocusedWindow:&window error:&cause]) {
*error = SICreateErrorWithCause(kShiftItActionFailureErrorCode,
cause,
@"Unable to get active window");
cause,
@"Unable to get active window");
return NO;
}

BOOL flag = NO;
if (![window canZoom:&flag error:&cause]) {
*error = SICreateErrorWithCause(kShiftItActionFailureErrorCode,
cause,
@"Unable to find out if window can zoom");
cause,
@"Unable to find out if window can zoom");
}
if (!flag) {
*error = SICreateError(kShiftItActionFailureErrorCode, @"Window cannot zoom");
Expand All @@ -371,16 +413,16 @@ - (BOOL)execute:(id <SIWindowContext>)windowContext error:(NSError **)error {

if (![windowContext getFocusedWindow:&window error:&cause]) {
*error = SICreateErrorWithCause(kShiftItActionFailureErrorCode,
cause,
@"Unable to get active window");
cause,
@"Unable to get active window");
return NO;
}

BOOL flag = NO;
if (![window canEnterFullScreen:&flag error:&cause]) {
*error = SICreateErrorWithCause(kShiftItActionFailureErrorCode,
cause,
@"Unable to find out if window can enter fullscreen");
cause,
@"Unable to find out if window can enter fullscreen");
}
if (!flag) {
*error = SICreateError(kShiftItActionFailureErrorCode, @"Window cannot enter fullscreen");
Expand Down Expand Up @@ -414,7 +456,7 @@ - (id)initWithMode:(BOOL)next {
- (BOOL)execute:(id <SIWindowContext>)windowContext error:(NSError **)error {
FMTAssertNotNil(windowContext);
FMTAssertNotNil(error);

NSError *cause = nil;
id<SIWindow> window = nil;
BOOL flag = NO;
Expand Down Expand Up @@ -444,7 +486,7 @@ - (BOOL)execute:(id <SIWindowContext>)windowContext error:(NSError **)error {
*error = SICreateErrorWithCause(kShiftItActionFailureErrorCode,
cause,
@"Unable to get window geometry");
return NO;
return NO;
}

FMTLogInfo(@"Current window geometry: %@ screen: %@", RECT_STR(currentGeometry), currentScreen);
Expand All @@ -461,10 +503,10 @@ - (BOOL)execute:(id <SIWindowContext>)windowContext error:(NSError **)error {

CGFloat kw = screenSize.width / currentScreenSize.width;
CGFloat kh = screenSize.height / currentScreenSize.height;

NSRect geometry = {
{ currentGeometry.origin.x * kw , currentGeometry.origin.y * kh },
{ currentGeometry.size.width * kw , currentGeometry.size.height * kh }
{ currentGeometry.origin.x * kw , currentGeometry.origin.y * kh },
{ currentGeometry.size.width * kw , currentGeometry.size.height * kh }
};

FMTLogInfo(@"New window geometry: %@ screen %@", RECT_STR(geometry), screen);
Expand All @@ -482,10 +524,10 @@ - (BOOL)execute:(id <SIWindowContext>)windowContext error:(NSError **)error {
@"Unable to anchor window");
return NO;
}

// TODO: make sure window is always visible

return YES;
}

@end
@end
10 changes: 6 additions & 4 deletions ShiftIt/ShiftIt-defaults.plist
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,16 @@
<key>zoomKeyCode</key>
<integer>6</integer>
<key>zoomModifiers</key>
<integer>1835008</integer>
<key>nextscreenKeyCode</key>
<integer>45</integer>
<key>nextscreenModifiers</key>
<integer>1835008</integer>
<key>nextscreenKeyCode</key>
<integer>45</integer>
<key>nextscreenModifiers</key>
<integer>1835008</integer>
<key>previousscreenKeyCode</key>
<integer>35</integer>
<key>previousscreenModifiers</key>
<real>1835008</real>
<key>mutipleActionsCycleWindowSizes</key>
<true/>
</dict>
</plist>
Loading

0 comments on commit 3d671b9

Please sign in to comment.