Advertisement
teadrinker

Virtual desktops

Nov 17th, 2021
1,415
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. if !VD := new VirtualDesktops
  2.    ExitApp
  3. DtCur := VD.GetCurrent()    ; returns current desktop ID
  4.  
  5. Gui, New, +hwndhWnd -Caption
  6. Gui, Color, 0x55AAFF
  7. Gui, Font, s24, Calibri
  8. Gui, Add, Text, center, % "This is the current virtual desktop.`n      Let's create new one and move this window there      "
  9. Gui, Show
  10. Sleep, 4000
  11.  
  12. DtNew := VD.CreateDesktop() ; returns new desktop ID
  13. VD.SwitchTo(DtNew)          ; switch to new desktop
  14. Sleep, 1000
  15.  
  16. VD.MoveWindowTo(hWnd, DtNew)
  17. Sleep, 1000
  18. Gui, Color, 0xFFAA55
  19. GuiControl,, Static1, This is the new virtual desktop.`nNow we'll move this window back to the initial desktop
  20. Sleep, 4000
  21.  
  22. VD.SwitchTo(DtCur)
  23. Sleep, 1000
  24. VD.MoveWindowTo(hWnd, DtCur)
  25. WinActivate, ahk_id %hWnd%
  26. Sleep, 1000
  27. Gui, Color, 0x55AAFF
  28. GuiControl,, Static1, This is the initial virtual desktop.`nLet's make this window pinned
  29. Sleep, 3000
  30.  
  31. VD.TogglePinWindow(hWnd)    ; pins the window, so it appears on all the desktops
  32. Gui, Color, 0xDDCC33
  33. GuiControl,, Static1, Now this window is pinned
  34. Sleep, 3000
  35. VD.SwitchTo(DtNew)
  36. Sleep, 2000
  37. VD.SwitchTo(DtCur)
  38. Sleep, 2000
  39.  
  40. GuiControl,, Static1, Now we'll remove the previously created desktop and terminate the script
  41. Sleep, 3000
  42. Gui, Destroy
  43. VD.Remove(DtNew, DtCur)
  44. ExitApp
  45.  
  46. class VirtualDesktops
  47. {
  48. /*
  49. public methods:
  50.  
  51. CreateDesktop()                                   // returns ID
  52. Remove(ID, ID_fallback := "")
  53. GetCurrent()                                      // returns ID
  54. GetFromWindow(hWnd)                               // returns ID
  55. GetCount()                                        // returns count of existing desktops
  56. GetDesktops()                                     // returns IDs array
  57. GetAdjacent(direction := "right", ID_start := "") // returns ID
  58. Switch(direction := "right")
  59. SwitchTo(ID)
  60. MoveWindow(hWnd, direction := "right")
  61. MoveWindowTo(hWnd, ID)
  62. TogglePinWindow(hWnd)
  63. */
  64.    static CLSID_ImmersiveShell                := "{C2F03A33-21F5-47FA-B4BB-156362A2F239}"
  65.         , CLSID_VirtualDesktopManager         := "{AA509086-5CA9-4C25-8F95-589D3C07B48A}"
  66.         , CLSID_VirtualDesktopPinnedApps      := "{B5A399E7-1C87-46B8-88E9-FC5747B171BD}"
  67.         , CLSID_VirtualDesktopManagerInternal := "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}"
  68.         , IID_IUnknown                        := "{00000000-0000-0000-C000-000000000046}"
  69.         , IID_IServiceProvider                := "{6D5140C1-7436-11CE-8034-00AA006009FA}"
  70.         , IID_IVirtualDesktop                 := "{FF72FFDD-BE7E-43FC-9C03-AD81681E88E4}"
  71.         , IID_IVirtualDesktopManager          := "{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}"
  72.         , IID_IVirtualDesktopPinnedApps       := "{4CE81583-1E4C-4632-A621-07A53543148F}"
  73.         , IID_IVirtualDesktopManagerInternal  := "{F31574D6-B682-4CDC-BD56-1827860ABEC6}"
  74.         , IID_IApplicationViewCollection      := "{1841C6D7-4F9D-42C0-AF41-8747538F10E5}"
  75.         , IID_IApplicationViewCollection_Old  := "{2C08ADF0-A386-4B35-9250-0FE183476FCC}"
  76.      
  77.    __New() {
  78.       if (A_OSVersion ~= "^\D") {
  79.          MsgBox, 48, Class VirtualDesktops, This class requires Windows 10 or later!
  80.          Return
  81.       }
  82.       ImmersiveShell                      := ComObjCreate(this.CLSID_ImmersiveShell, this.IID_IUnknown)
  83.       if !this.IApplicationViewCollection := ComObjQuery(ImmersiveShell, this.IID_IApplicationViewCollection
  84.                                                                        , this.IID_IApplicationViewCollection)
  85.           this.IApplicationViewCollection := ComObjQuery(ImmersiveShell, this.IID_IApplicationViewCollection_Old
  86.                                                                        , this.IID_IApplicationViewCollection_Old)
  87.       if !this.IApplicationViewCollection {
  88.          MsgBox, IApplicationViewCollection interface not supported.
  89.          Return
  90.       }
  91.       this.IVirtualDesktopManager         := ComObjCreate(this.CLSID_VirtualDesktopManager, this.IID_IVirtualDesktopManager)
  92.       IServiceProvider                    := ComObjCreate(this.CLSID_ImmersiveShell, this.IID_IServiceProvider)
  93.       this.IVirtualDesktopManagerInternal := ComObjQuery(IServiceProvider, this.CLSID_VirtualDesktopManagerInternal
  94.                                                                          , this.IID_IVirtualDesktopManagerInternal)
  95.       this.IVirtualDesktopPinnedApps      := ComObjQuery(IServiceProvider, this.CLSID_VirtualDesktopPinnedApps
  96.                                                                          , this.IID_IVirtualDesktopPinnedApps)
  97.       for k, v in [ImmersiveShell, IServiceProvider]
  98.          ObjRelease(v)
  99.    }
  100.    
  101.    __Delete() {
  102.       for k, v in [ "IApplicationViewCollection"    , "IVirtualDesktopManager"
  103.                   , "IVirtualDesktopManagerInternal", "IVirtualDesktopPinnedApps" ]
  104.          ObjRelease(this[v])
  105.    }
  106.  
  107.    CreateDesktop() {
  108.       this._Vtable(this.IVirtualDesktopManagerInternal, CreateDesktop := 10).Call("PtrP", IVirtualDesktop)
  109.       ID := this._GetID(IVirtualDesktop)
  110.       ObjRelease(IVirtualDesktop)
  111.       Return ID
  112.    }
  113.    
  114.    Remove(ID, ID_fallback := "") {
  115.       if !IVirtualDesktop := this._FindDesktop(ID)
  116.          Return false
  117.       if !ID_fallback {
  118.          Arr := this.GetDesktops()
  119.          if (Arr[1] = ID)
  120.             ID_fallback := Arr[2]
  121.          else {
  122.             for k, v in Arr
  123.                if (v = ID && ID_fallback := Arr[k - 1])
  124.                   break
  125.          }
  126.       }
  127.       if IVirtualDesktop_fallback := this._FindDesktop(ID_fallback) {
  128.          res := this._Vtable(this.IVirtualDesktopManagerInternal, RemoveDesktop := 11).Call( "Ptr", IVirtualDesktop
  129.                                                                                            , "Ptr", IVirtualDesktop_fallback )
  130.          ObjRelease(IVirtualDesktop_fallback)
  131.       }
  132.       ObjRelease(IVirtualDesktop)
  133.       Return res = 0
  134.    }
  135.    
  136.    GetCurrent() {
  137.       this._Vtable(this.IVirtualDesktopManagerInternal, GetCurrentDesktop := 6).Call("PtrP", IVirtualDesktop)
  138.       ID := this._GetID(IVirtualDesktop)
  139.       ObjRelease(IVirtualDesktop)
  140.       Return ID
  141.    }
  142.    
  143.    GetFromWindow(hWnd) {
  144.       if !WinExist("ahk_id" hWnd)
  145.          Return false
  146.      
  147.       VarSetCapacity(GUID, 16, 0)
  148.       res := this._Vtable(this.IVirtualDesktopManager, GetWindowDesktopId := 4).Call("Ptr", hWnd, "Ptr", &GUID)
  149.       if (res = 0) {
  150.          VarSetCapacity(sGuid, 78) ; (38 + 1) * 2
  151.          DllCall("ole32\StringFromGUID2", "Ptr", &GUID, "Ptr", &sGuid, "Int", 39)
  152.          ID := StrGet(&sGuid, "UTF-16")
  153.       }
  154.       Return ID ? ID : false
  155.    }
  156.    
  157.    GetCount() {
  158.       this._Vtable(this.IVirtualDesktopManagerInternal, GetCount := 3).Call("UIntP", virtualDesktopCount)
  159.       Return virtualDesktopCount
  160.    }
  161.    
  162.    GetDesktops() {
  163.       this._Vtable(this.IVirtualDesktopManagerInternal, GetDesktops := 7).Call("PtrP", IObjectArray)
  164.       this._Vtable(IObjectArray, GetCount := 3).Call("UIntP", desktopCount)
  165.       Desktops := []
  166.       VarSetCapacity(GUID, 16, 0)
  167.       DllCall("ole32\CLSIDFromString", "Str", this.IID_IVirtualDesktop, "Ptr", &GUID, "UInt")
  168.       Loop % desktopCount {
  169.          this._Vtable(IObjectArray, GetAt := 4).Call("UInt", A_Index - 1, "Ptr", &GUID, "PtrP", IVirtualDesktop)
  170.          ID := this._GetID(IVirtualDesktop)
  171.          ObjRelease(IVirtualDesktop)
  172.          Desktops.Push(ID)
  173.       }
  174.       ObjRelease(IObjectArray)
  175.       Return Desktops
  176.    }
  177.    
  178.    GetAdjacent(direction := "right", ID_start := "") {
  179.       static dirEnum := {left: 3, right: 4}
  180.       ( !ID_start && ID_start := this.GetCurrent() )
  181.       IVirtualDesktopStart := this._FindDesktop(ID_start)
  182.       res := this._Vtable(this.IVirtualDesktopManagerInternal, GetAdjacentDesktop := 8).Call( "Ptr", IVirtualDesktopStart
  183.                                                                                             , "Int", dirEnum[direction]
  184.                                                                                             , "PtrP", IVirtualDesktopOut )
  185.       if (res = 0) {
  186.          ID_Adjacent := this._GetID(IVirtualDesktopOut)
  187.          ObjRelease(IVirtualDesktopOut)
  188.       }
  189.       ObjRelease(IVirtualDesktopStart)
  190.       Return ID_Adjacent
  191.    }
  192.    
  193.    Switch(direction := "right") {
  194.       ID := this.GetAdjacent(direction)
  195.       Return ID ? this.SwitchTo(ID) : false
  196.    }
  197.    
  198.    SwitchTo(ID) {
  199.       IVirtualDesktop := this._FindDesktop(ID)
  200.       res := this._Vtable(this.IVirtualDesktopManagerInternal, SwitchDesktop := 9).Call("Ptr", IVirtualDesktop)
  201.       ObjRelease(IVirtualDesktop)
  202.       Return res = 0
  203.    }
  204.    
  205.    MoveWindow(hWnd, direction := "right") {
  206.       if !WinExist("ahk_id" hWnd)
  207.          Return false
  208.       WinGetClass, WinClass, ahk_id %hWnd%
  209.       if (WinClass ~= "Progman|WorkerW|Shell_TrayWnd")
  210.          Return false
  211.      
  212.       ID_start := this.GetFromWindow(hWnd)
  213.       ID := this.GetAdjacent(direction, ID_start)
  214.       Return this.MoveWindowTo(hWnd, ID)
  215.    }
  216.    
  217.    MoveWindowTo(hWnd, ID) {
  218.       IVirtualDesktop := this._FindDesktop(ID)
  219.       this._Vtable(this.IApplicationViewCollection    , GetViewForHwnd      := 6).Call("Ptr", hWnd, "PtrP", IApplicationView)
  220.       this._Vtable(this.IVirtualDesktopManagerInternal, CanViewMoveDesktops := 5).Call("Ptr", IApplicationView, "UIntP", canMove)
  221.       if canMove
  222.          res := this._Vtable(this.IVirtualDesktopManagerInternal, MoveViewToDesktop := 4).Call( "Ptr", IApplicationView
  223.                                                                                               , "Ptr", IVirtualDesktop )
  224.       ObjRelease(IApplicationView), ObjRelease(IVirtualDesktop)
  225.       Return res = 0
  226.    }
  227.    
  228.    TogglePinWindow(hWnd) {
  229.       if !WinExist("ahk_id" hWnd)
  230.          Return false
  231.       WinGetClass, WinClass, ahk_id %hWnd%
  232.       if (WinClass ~= "Progman|WorkerW|Shell_TrayWnd")
  233.          Return false
  234.       this._Vtable(this.IApplicationViewCollection, GetViewForHwnd := 6).Call("Ptr", hWnd, "PtrP", IApplicationView)
  235.       this._Vtable(this.IVirtualDesktopPinnedApps , IsViewPinned   := 6).Call("Ptr", IApplicationView, "UIntP", isPinned)
  236.       res := this._Vtable(this.IVirtualDesktopPinnedApps, isPinned ? UnpinView := 8 : PinView := 7).Call("Ptr", IApplicationView)
  237.       ObjRelease(IApplicationView)
  238.       Return res = 0
  239.    }
  240.    
  241.    _FindDesktop(ID) {
  242.       VarSetCapacity(GUID, 16, 0)
  243.       DllCall("ole32\CLSIDFromString", "Str", ID, "Ptr", &GUID, "UInt")
  244.       res := this._Vtable(this.IVirtualDesktopManagerInternal, FindDesktop := 12).Call("Ptr", &GUID, "PtrP", IVirtualDesktop)
  245.       Return res = 0 ? IVirtualDesktop : false
  246.    }
  247.    
  248.    _GetID(IVirtualDesktop) {
  249.       VarSetCapacity(GUID, 16, 0)
  250.       this._Vtable(IVirtualDesktop, GetID := 4).Call("Ptr", &GUID)
  251.       VarSetCapacity(sGuid, 78) ; (38 + 1) * 2
  252.       DllCall("ole32\StringFromGUID2", "Ptr", &GUID, "Ptr", &sGuid, "Int", 39)
  253.       Return ID := StrGet(&sGuid, "UTF-16")
  254.    }
  255.    
  256.    _Vtable(ptr, n) {
  257.       return Func("DllCall").Bind(NumGet(NumGet(ptr+0), A_PtrSize*n), "Ptr", ptr)
  258.    }
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement