No internet connection
  1. Home
  2. How to

Move window to another screen?

By Dustin Harris @Dustin_Harris
    2020-08-10 04:02:48.574Z

    Is there a method that allows moving a window to another screen? I know how to use .windowMove to move and resize windows, and how to access sizes and coordinates on different screen indexes, but not move from one screen index to another.

    Thanks!

    Solved in post #2, click to view
    • 23 replies

    There are 23 replies. Estimated reading time: 19 minutes

    1. Kitch Membery @Kitch2020-08-10 08:45:15.362Z

      Hi Dustin!

      Try adjusting the "screenIndex" on this one mate!

      const appWindow = sf.ui.app('com.apple.TextEdit').mainWindow;
      const screenIndex = 1;
      
      function centerWindow(window) {
          var screenFrame = sf.ui.screens.allScreens[screenIndex].visibleFrame;
          var windowFrame = window.frame;
      
          window.windowMove({
              position: {
                  x: screenFrame.x + (screenFrame.w / 2) - (windowFrame.w / 2),
                  y: screenFrame.y + (screenFrame.h / 2) - (windowFrame.h / 2),
              },
          });
      }
      
      centerWindow(appWindow);
      

      Hope that helps :-)

      ReplySolution
      1. Kitch Membery @Kitch2020-08-10 08:47:00.116Z

        This will move the front-most Text Edit window to your second screen. But you knew that :-)

        1. Kitch Membery @Kitch2020-08-10 09:44:39.667Z

          There is also a SoundFlow action that does this in the Macro Editor its called "Move Window to Screen". Simply change the delta value.

          sf.window.moveToScreen({delta:1});
          
          1. In reply toKitch:
            Dustin Harris @Dustin_Harris
              2020-08-10 11:37:14.998Z2020-08-10 12:04:43.216Z

              Ahh I had removed the screen frame.x/y, which is likely where the screen index info is contained :)
              (Was doing “x: screenFrame.w/2 - windowFrame.w/2”)

            • In reply toKitch:
              Dustin Harris @Dustin_Harris
                2020-08-10 23:51:15.568Z

                Kitch you perennial legend. Works as advertised. screenFrame.x/.y were the critical components I thought I could live without.

                Simple example: gets the foremost finder window and moves it top-left of the screen of my choice.

                sf.ui.screens.invalidate(); //make SoundFlow check up on your screens and screen properties
                
                sf.ui.finder.windows.first.elementRaise(); //bring the active finder window to the front
                let window = sf.ui.finder.windows.first; //make it a variable because typing long things suck
                
                var bottomScreen = sf.ui.screens.allScreens[0].visibleFrame;
                var topScreen = sf.ui.screens.allScreens[1].visibleFrame;
                
                window.windowMove({position: {x: topScreen.x, y: topScreen.y,}}) // top left of my top screen, change to bottomScreen.x/.y for bottom.
                
                1. Kitch Membery @Kitch2020-08-10 23:57:58.372Z

                  Dustin!!!

                  I've never been called a perennial legend before (Why, thank you!).

                  And yes... "typing long things sucks"

                  SUCCESS!!

              • A
                In reply toDustin_Harris:
                Andrew Sherman @Andrew_Sherman
                  2021-03-01 19:24:51.954Z

                  Greetings... I'm getting errors when I try running either of these scripts, visibleFrame seems to be the culprit. Any ideas?

                  TypeError: Cannot read property 'visibleFrame' of undefined

                  1. Dustin Harris @Dustin_Harris
                      2021-03-01 19:50:01.476Z

                      Heyya Andrew! Do you mind posting your code? (if you don't know this already, you can quote your code but typing 3 back-ticks (key above the tab key on most mac keyboards)) then pasting your code, then ending with 3 more back ticks.

                      Cheers!

                      1. AAndrew Sherman @Andrew_Sherman
                          2021-03-01 20:03:59.738Z

                          Thanks Dustin, it the same as your script - I copied and tried it but it's not running.,

                          sf.ui.screens.invalidate(); //make SoundFlow check up on your screens and screen properties
                          
                          sf.ui.finder.windows.first.elementRaise(); //bring the active finder window to the front
                          let window = sf.ui.finder.windows.first; //make it a variable because typing long things suck
                          
                          var bottomScreen = sf.ui.screens.allScreens[0].visibleFrame;
                          var topScreen = sf.ui.screens.allScreens[1].visibleFrame;
                          
                          window.windowMove({position: {x: topScreen.x, y: topScreen.y,}}) // top left of my top screen, change to bottomScreen.x/.y for bottom.
                          
                          1. Dustin Harris @Dustin_Harris
                              2021-03-01 20:13:28.593Z

                              off the top of my head you'll get an error in var topScreen = sf.ui.screens.allScreens[1].visibleFrame; if you only have one screen... is that the case?

                              1. AAndrew Sherman @Andrew_Sherman
                                  2021-03-01 20:43:22.386Z

                                  Yes, I'm running one screen at the moment; had 2 screens for many years but I'm going with one these days! I'm mainly trying to move windows to specific positions on the screen, but I'm trying to do percentages as opposed to fixed sizes (eg send window to top left quarter).

                                  1. Dustin Harris @Dustin_Harris
                                      2021-03-01 20:45:54.911Z

                                      try it like this:

                                      sf.ui.screens.invalidate(); //make SoundFlow check up on your screens and screen properties
                                      
                                      sf.ui.finder.windows.first.elementRaise(); //bring the active finder window to the front
                                      let window = sf.ui.finder.windows.first; //make it a variable because typing long things suck
                                      
                                      let mainScreen = sf.ui.screens.allScreens[0].visibleFrame;
                                      window.windowMove({position: {x: mainScreen.x, y: mainScreen.y,}}) // top left of my top screen, change to bottomScreen.x/.y for bottom.
                                      
                                      1. AAndrew Sherman @Andrew_Sherman
                                          2021-03-01 21:19:58.255Z

                                          Amazing, thank you Dustin! So is allScreens[0] the first screen (only screen in my case)?

                                          How do I get the window to go to one of the other quarters of the screen, eg bottom right?

                                          1. Dustin Harris @Dustin_Harris
                                              2021-03-02 04:15:22.677Z

                                              ok! so... yes.. allScreens[0] is the 'first screen', computers index things starting at 0. visible frame is is the resolution of your screen, minus the menu bar. I've made a little script that is kind of like a tutorial, check it out, hopefully it's as self explanatory as I think it is :)

                                              sf.ui.screens.invalidate(); //make SoundFlow check up on your screens and screen properties
                                              
                                              let finderWindow = sf.ui.finder.windows.first; //this just shortens the name so I don't have to type "sf.ui.finder.windows.first each time"
                                              
                                              if (finderWindow.exists) {// check if there is a finder window open for us to play with
                                              
                                                  sf.ui.finder.menuClick({ menuPath: ['File', 'New Finder Window'] }) //if not, open one
                                              
                                                  finderWindow.elementWaitFor(); //and wait for it to appear, beacause macOS takes a second to do it.
                                              }
                                              
                                              finderWindow.elementRaise(); //bring the active finder window to the front of other apps.
                                              
                                              let mainScreen = sf.ui.screens.allScreens[0].visibleFrame //define visible screen properties as 'mainScreen'
                                              
                                              //mainScreen.w is the same as sf.ui.screens.allScreens[0].invalidate().visibleFrame.w
                                              alert(`The usable width of your main screen is: ${mainScreen.w} pixels`)
                                              
                                              //mainScreen.h is the same as sf.ui.screens.allScreens[0].invalidate().visibleFrame.w
                                              alert(`The usable heigh of your main screen is: ${mainScreen.h} pixels`)
                                              
                                              alert(`The Finder Window is ${finderWindow.frame.w} pixels wide`);
                                              
                                              alert(`The Finder Windows is ${finderWindow.frame.h} pixes tall`);
                                              
                                              alert(`The Finder window is at the screen coordinates of: ${finderWindow.frame.x}, ${finderWindow.frame.y}`);
                                              
                                              
                                              alert(`The next command will make the finder window half the screen height, and half the screen width`)
                                              finderWindow.windowMove({ size: { x: mainScreen.w / 2, y: mainScreen.h / 2, } });
                                              
                                              
                                              alert(`the next command will make the finder window move to the top left of the screen`)
                                              finderWindow.windowMove({ position: { x: 0, y: 0, } })
                                              
                                              
                                              alert(`the next command will make the finder window move to the bottom right of the screen`)
                                              finderWindow.windowMove({ position: { x: mainScreen.w - finderWindow.frame.w, y: mainScreen.h - finderWindow.frame.h, } })
                                              
                                              
                                              alert(`the next command will make the finder window move to the centre of the screen`)
                                              finderWindow.windowMove({ position: { x: (mainScreen.w / 2) - (finderWindow.frame.w / 2) , y: (mainScreen.h / 2)  - (finderWindow.frame.h / 2), } })
                                              
                                              1. AAndrew Sherman @Andrew_Sherman
                                                  2021-03-02 10:04:10.000Z

                                                  Dustin, I'm voting that you join the perennial legends club...

                                                  1. Dustin Harris @Dustin_Harris
                                                      2021-03-02 12:20:32.127Z

                                                      Hahaha! Not so fast, I just discovered a pretty important typo:

                                                      if (finderWindow.exists) {
                                                      

                                                      Should be:

                                                      if (!finderWindow.exists) {
                                                      

                                                      Note the “!”, it makes the condition you’ve stated the opposite. , !finderWindow.exists is ‘finderWindow does NOT exist’

                                                    • In reply toDustin_Harris:
                                                      AAndrew Sherman @Andrew_Sherman
                                                        2021-03-02 10:08:23.220Z

                                                        That's a great format for a tutorial

                                                        1. In reply toDustin_Harris:
                                                          AAndrew Sherman @Andrew_Sherman
                                                            2021-03-02 14:52:20.180Z

                                                            Hi Dustin,

                                                            The command to send the window to the bottom right places it at the bottom right of the screen, but it's not quite at the bottom, it's a little too high (by the same amount as the height of the menu bar). Do we need to factor that in? I'm on a single monitor with menu bar present on main screen.

                                                            1. Dustin Harris @Dustin_Harris
                                                                2021-03-02 14:59:37.194Z

                                                                that's interesting. It works for me... are you hiding or showing your dock? (mine is hidden)... also I might have to invalidate the window somewhere to refresh the cache in case the window gets resized before being moved. I'll look into it :)

                                                                -D

                                                                EDIT! I TAKE IT BACK. Mine also does not go to the bottom of the screen...

                                                                1. In reply toAndrew_Sherman:
                                                                  Dustin Harris @Dustin_Harris
                                                                    2021-03-02 15:08:41.075Z

                                                                    using .frame instead of .visibleFrame fixes it for me:

                                                                    add this line to your script:

                                                                    let entireMainScreen = sf.ui.screens.allScreens[0].frame;
                                                                    

                                                                    and then use this to move to the bottom right instead:

                                                                    finderWindow.windowMove({ position: { x: entireMainScreen.w - finderWindow.frame.w, y: entireMainScreen.h - finderWindow.frame.h, } })
                                                                    

                                                                    :)

                                                                    1. AAndrew Sherman @Andrew_Sherman
                                                                        2021-03-02 16:03:25.314Z

                                                                        Great Dustin, that works nicely. Thank you so much for your help on this. I'm using similar code to try to manipulate the windows to half screen (and will get to thirds at some point), but I can't get it to work reliably like the quarter screens that we have going now.

                                                                        If you randomly make a few new finder windows and then resize them, and then try to run it again, sometimes it doesn't re-size it properly.

                                                                        Here's the versions of the script I'm working with. You'll see I'm using a variable for the app; ultimately I want to use this on various apps, not just Finder. I'm also setting it up so that it can become a template.

                                                                        
                                                                        // Soundflow checks number of screens, and screen sizes
                                                                        sf.ui.screens.invalidate();
                                                                        
                                                                        // Use 0 for main screen, 1 for second screen etc
                                                                        var screenNumber = 0;
                                                                        
                                                                        // I want to replace this with something that recognises the active foreground application, and gets the name/id of the app so that we can manipulate the windows
                                                                        var app = sf.ui.finder;
                                                                        
                                                                        let appWindow = app.windows.first;
                                                                        
                                                                        // Check if there is a window open
                                                                        if (appWindow.exists) {
                                                                            app.menuClick({ menuPath: ['File', 'New Finder Window'] });
                                                                            appWindow.elementWaitFor(); 
                                                                        }
                                                                        
                                                                        // Bring the active window to the front of other apps
                                                                        appWindow.elementRaise();
                                                                        
                                                                        // Define visible screen properties as 'mainScreen' (excluding menu bar)
                                                                        let mainScreen = sf.ui.screens.allScreens[screenNumber].visibleFrame;
                                                                        
                                                                        // Whole screen size including menu bar
                                                                        let entireMainScreen = sf.ui.screens.allScreens[screenNumber].frame;
                                                                        
                                                                        // Notes:
                                                                        // mainScreen.w is the same as sf.ui.screens.allScreens[screenNumber].invalidate().visibleFrame.w
                                                                        // The usable width of your main screen is: ${mainScreen.w} pixels
                                                                        // mainScreen.h is the same as sf.ui.screens.allScreens[screenNumber].invalidate().visibleFrame.w
                                                                        // The usable heigh of your main screen is: ${mainScreen.h} pixels
                                                                        // The app window is ${appWindow.frame.w} pixels wide
                                                                        // The app window is ${appWindow.frame.h} pixes tall
                                                                        // The window is at the screen coordinates of: ${appWindow.frame.x}, ${appWindow.frame.y}
                                                                        
                                                                        // --------------------------------------------
                                                                        // Quarter-size windows:
                                                                        // First re-size, then move
                                                                        
                                                                        // Resize window, make window half the screen height, and half the screen width
                                                                        // appWindow.windowMove({ size: { x: mainScreen.w / 2, y: mainScreen.h / 2, } });
                                                                        
                                                                        // Move to top left
                                                                        // appWindow.windowMove({ position: { x: 0, y: 0, } });
                                                                        
                                                                        // Move to bottom left
                                                                        // appWindow.windowMove({ position: { x: 0, y: entireMainScreen.h - appWindow.frame.h, } });
                                                                        
                                                                        // Move to top right
                                                                        // appWindow.windowMove({ position: { x: entireMainScreen.w - appWindow.frame.w, y: 0, } });
                                                                        
                                                                        // Move to bottom right
                                                                        // appWindow.windowMove({ position: { x: entireMainScreen.w - appWindow.frame.w, y: entireMainScreen.h - appWindow.frame.h, } });
                                                                        
                                                                        // --------------------------------------------
                                                                        // Half-size windows:
                                                                        // First re-size, then move
                                                                        
                                                                        // Make window full screen height, and half the screen width
                                                                        appWindow.windowMove({ size: { x: entireMainScreen.w / 2, y: entireMainScreen.h, } });
                                                                        
                                                                        // Right - not working reliably yet
                                                                        appWindow.windowMove({ position: { x: entireMainScreen.w - appWindow.frame.w, y: 0, } });
                                                                        
                                                                        // --------------------------------------------
                                                                        // Make the window move to the centre of the screen
                                                                        // appWindow.windowMove({ position: { x: (mainScreen.w / 2) - (appWindow.frame.w / 2) , y: (mainScreen.h / 2)  - (appWindow.frame.h / 2), } });
                                                                        
                                                                        1. Dustin Harris @Dustin_Harris
                                                                            2021-03-02 16:24:14.491Z

                                                                            So yeah, part of the simplification of the tutorial was to get the 'first' finder window, and that can be tricky with multiple windows, especially if you reorder them, resize them, etc and don't inform Sound Flow about what you've done. (side note: the invalidate() method helps mitigate this by essentially telling sound flow to 'forget what you think you know about x property, and go get the values as they are right now, sf.ui.finder.window.invalidate().first will tell Sound Flow to double check what it thinks it know about the first finder window. This info is 'cached' and .invalidate() 'invalidates the cache' forcing a fresh retrieve. This isn't our best approach here. Our best approach is to be more specific about WHAT windows we want to address:

                                                                            take this window:

                                                                            it's my only finder window open at the moment, so I CAN address it as:
                                                                            sf.ui.finder.windows.first //the 'first' window

                                                                            but the more definitive way of addressing this window is:
                                                                            sf.ui.finder.windows.whoseTitle.is("Dustin’s iMac").first //the window titled 'Dustin's iMac'

                                                                            to resize the edit window in pro tools you would address:
                                                                            sf.ui.proTools.mainWindow
                                                                            so as I'm sure you're starting to see, different programs have different window type and names and accessing them in the most precise way can be a bit of a fact-finding mission, there are tools and tips on how to do this though! Maybe @Kitch has a video link handy to look at UI elements?

                                                                            Keep asking questions here though, and we'll try our best to help when you get stuck on something.

                                                                            If it's helpful, here's a script I use all the time to resize my pro tools screen from full screen to half screen (super useful when I need to read documents or emails that reference things in my pro tools session):

                                                                            //This script toggles the ProTools edit window from being fullscreen to half-width
                                                                            
                                                                            sf.ui.screens.invalidate();
                                                                            var screenIndex = 0;
                                                                            var screenFrame = sf.ui.screens.allScreens[screenIndex].visibleFrame;
                                                                            
                                                                            sf.ui.proTools.appActivateMainWindow();
                                                                            
                                                                            var editWindow = sf.ui.proTools.mainWindow;
                                                                            
                                                                            editWindow.windowMove({position: {x: 0, y: 0,}})
                                                                            
                                                                            if (editWindow.frame.w +100 < screenFrame.w) { // to account for rounding errors in division
                                                                                
                                                                            
                                                                                editWindow.windowMove({size: {x: screenFrame.w, y: screenFrame.h}});
                                                                            
                                                                            } else {
                                                                                
                                                                                editWindow.windowMove({size: {x: screenFrame.w / 2, y: screenFrame.h}});
                                                                            }
                                                                            
                                                                            1. AAndrew Sherman @Andrew_Sherman
                                                                                2021-03-02 16:35:43.144Z

                                                                                Thank you Dustin, appreciate it