Skip to content

Screen position based switching. #82

Closed
wants to merge 2 commits into from

3 participants

@Arelius
Arelius commented Dec 15, 2012

Especially since Mac OSX likes to randomly rearrange screens, it was hard to predict which way this would swap, making it based on a constant direction improves behavior a bunch.

There are a few edge cases this won't handle, but would like to start a dialog on how to implement this properly.

@eczarny
Owner
eczarny commented Jan 24, 2013

I'm not sure I understand what this change does. Could you explain the original issue in a bit more detail?

@Arelius
Arelius commented Feb 5, 2013

@eczarny, when you only have two monitors, this doesn't matter since next screen and prev screen both cycle the same way. But if you have three or more, it's very difficult to predict which display the window will cycle to, because the screen order is pretty arbitrarily defined, and may change between reboots and the like. The intent of this change is to take screen position into account while moving a window between screens.

@eczarny
Owner
eczarny commented Feb 5, 2013

Got it. Could you rebase this commit? I'll try and fit it into the upcoming 0.8 release.

@Arelius
Arelius commented Feb 5, 2013

So, I updated it to also take into account screen Y position, so that it works if you have stacked displays... And I rebased this. I'm not in the office so I haven't gotten a chance to fully test it however.

@eczarny
Owner
eczarny commented Feb 5, 2013

Once you test I'll merge. After the merge would you mind testing the change again from my master branch? I don't have the required setup to verify.

@Arelius
Arelius commented Feb 9, 2013

Apologies, I've found a bug in the implementation and haven't had enough time to debug it yet.

@jasonm jasonm referenced this pull request Feb 13, 2013
Closed

Directional change-focus? #97

@eczarny
Owner
eczarny commented Apr 25, 2013

I believe this would address issue #101.

@eczarny
Owner
eczarny commented Sep 1, 2013

@Arelius, have you had a chance to debug the issue you discovered? I would love to get this change into an upcoming release.

@Arelius
Arelius commented Sep 20, 2013

@eczarny Sadly, I don't have a working Mac right now, so am not capable of fixing this.

@eczarny
Owner
eczarny commented Sep 23, 2013

Unfortunately, without the required hardware I can't test this change. If somebody else is able to do so I would love to be able to merge it in.

@eczarny
Owner
eczarny commented Jan 23, 2014

I would love to test this change out somehow. Is anybody able to try it out? If not I'm going to have to close this out.

@eczarny eczarny closed this Jun 12, 2014
@liam-m
liam-m commented Jun 18, 2014

@eczarny I'd be interested in testing this, as I'm experiencing the issue. Could you give me some instructions on how to build?

Arelius added some commits Dec 14, 2012
@Arelius
Arelius commented Jun 18, 2014

@liam-m I just did a rebase on current master, I don't have a machine I can test the build on, but feel free to sync up to my updated branch at https://github.com/Arelius/spectacle and try a build. IIRC, you can just open the xcodeproj in xcode and hit build.

@eczarny
Owner
eczarny commented Jun 18, 2014

Since adding Cocoapods you should open the xcworkspace instead of the xcodeproj.

@liam-m
liam-m commented Jun 19, 2014

I built @arelius's branch and tested with 3 displays - it's a big improvement and has worked as expected in my testing.

It would be good if the displays could wrap around, so pressing 'Previous Display' on the leftmost display would make the window go to the rightmost, but maybe this is worth a separate issue/discussion.

@eczarny eczarny reopened this Jun 20, 2014
@eczarny
Owner
eczarny commented Jun 20, 2014

I merged manually on master.

@eczarny eczarny closed this Jun 20, 2014
@eczarny
Owner
eczarny commented Jun 20, 2014

@Arelius I'm trying to clean up the logic a bit so that's easier to digest. Could you explain each check in the conditional?

NSInteger lastDeltaX = 0;
NSInteger lastDeltaY = 0;

NSInteger screenDeltaX = (frameOfScreen.origin.x - currentFrameOfScreen.origin.x) ;
NSInteger screenDeltaY = (frameOfScreen.origin.y - currentFrameOfScreen.origin.y) ;

NSInteger dir = (action == SpectacleWindowActionNextDisplay) ? -1 : 1;

if ((screenDeltaX * dir > 0 ||
     (screenDeltaX == 0 &&
      screenDeltaY * dir > 0)) &&
    (result == nil ||
     (screenDeltaX * dir) < lastDeltaX ||
     (screenDeltaX == 0 &&
      (screenDeltaY * dir) < lastDeltaY))) {
    result = [screens objectAtIndex: i];
    lastDeltaX = screenDeltaX * dir;
    lastDeltaY = screenDeltaY * dir;
}
@eczarny eczarny reopened this Jun 20, 2014
@eczarny
Owner
eczarny commented Jun 20, 2014

The logic is a bit confusing. I'm wondering if using a stable sort to order the screens by descending X, then descending Y, coordinates would be any easier. This way at least screen selection is consistent?

@eczarny
Owner
eczarny commented Jun 20, 2014

I'm actually going to revert this change until I can fully understand it. The regression in screen wrapping is an unpleasant side effect to the fix.

Sorry about the aggressive merge!

@Arelius
Arelius commented Jun 20, 2014
  if ((screenDeltaX * dir > 0 || // canidate x pos is in switching direction or
     (screenDeltaX == 0 && // canidate has the same x pos and
      screenDeltaY * dir > 0)) && canidate y pos is in switching direction
    (result == nil || // is first possible screen
     (screenDeltaX * dir) < lastDeltaX || smallest delta in x in switching direction or
     (screenDeltaX == 0 && // has no delta in x in switching direction and 
      (screenDeltaY * dir) < lastDeltaY))) { // smallest delta in y in switching direction

With many monitors, this will first try to cycle between monitors that have matching X coords in case they are stacked, and then failing that, cycle to the side. dir specifies if you want to search in positive or negative delta directions, basically switching directions in both axis.

This could be done with a stable sort for sure. just sort by Y position, and then X position.

If you wanted to wrap, you could after the loop, if no screens are found, just find the furthest screen in that direction

@Arelius
Arelius commented Jun 20, 2014

The logic is a bit confusing. I'm wondering if using a stable sort to order the screens by descending X, then descending Y, coordinates would be any easier. This way at least screen selection is consistent?

That's the same order that this selection works in, so if you wanted to sort first, then just cycle through the list, it should have the same effect.

@eczarny
Owner
eczarny commented Jun 20, 2014

Ah, okay. I may play around with that. I'm not terribly concerned about the particular ordering as long as it is consistent. Thanks for all of the work you've done on this!

@Arelius
Arelius commented Jun 20, 2014

Of course, sorry I can't do more work getting it nicer. Not working on a Mac anymore makes that problematic.

@eczarny
Owner
eczarny commented Jun 20, 2014

No problem! I can probably take it from here. I'll probably close out this pull request and go down the stable sort approach. I just wish I had more than two external displays to test with.

@eczarny eczarny closed this Jun 20, 2014
@liam-m
liam-m commented Jun 21, 2014

Let me know if you want me to test anything, I have 3 displays (2 external) too

@eczarny
Owner
eczarny commented Jun 21, 2014

Thanks @liam-m! I should have something to test in a few days.

@eczarny
Owner
eczarny commented Jun 22, 2014

@liam-m I just pushed a change to master that I hope will help. Could you try testing it out? I was only able to verify the changes based on some simple tests of the algorithm. I won't be able to actually try it out until Monday, but would love to get another set of eyes on it.

Thanks!

@liam-m
liam-m commented Jun 29, 2014

@eczarny I've tested it - it seems to work as described, it's now consistent. However, is it possible to make it go from left-to-right and wrap around? In other words:

  • Making 'Next Display' send the window to the display to the right of the display (from System Preferences > Displays > Arrangement) that the window is currently on; opposite for 'Previous Display'
  • Making 'Next Display' on the rightmost display send the window to the leftmost; opposite for 'Previous Display' from leftmost display
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.