// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Diagnostics;
usingSystem.Runtime.InteropServices;
usingMicrosoft.Win32;
usingWox.Plugin.Common.VirtualDesktop.Interop;
usingWox.Plugin.Common.Win32;
usingWox.Plugin.Logger;
usingWox.Plugin.Properties;
namespaceWox.Plugin.Common.VirtualDesktop.Helper
{
/// <summary>
/// Helper class to work with Virtual Desktops.
/// This helper uses only public available and documented COM-Interfaces or informations from registry.
/// </summary>
/// <remarks>
/// To use this helper you have to create an instance of it and access the method via the helper instance.
/// We are only allowed to use public documented com interfaces.
/// </remarks>
/// <SeeAlso href="https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager">Documentation of IVirtualDesktopManager interface</SeeAlso>
/// <SeeAlso href="https://docs.microsoft.com/en-us/archive/blogs/winsdk/virtual-desktop-switching-in-windows-10">CSharp example code for IVirtualDesktopManager</SeeAlso>
/// Initializes a new instance of the <see cref="VirtualDesktopHelper"/> class.
/// </summary>
/// <param name="desktopListUpdate">Setting to configure if the list of available desktops should update automatically or only when calling <see cref="UpdateDesktopList"/>. Per default this is set to manual update (false) to have less registry queries.</param>
// The registry value is missing when the user hasn't switched the desktop at least one time before reading the registry. In this case we can set it to desktop one.
Log.Debug("Failed to read the id for the current desktop form registry.",typeof(VirtualDesktopHelper));
currentDesktop=availableDesktops[0];
}
}
/// <summary>
/// Returns an ordered list with the ids of all existing desktops. The list is ordered in the same way as the existing desktops.
/// </summary>
/// <returns>List of desktop ids or an empty list on failure.</returns>
publicList<Guid>GetDesktopIdList()
{
if(_desktopListAutoUpdate)
{
UpdateDesktopList();
}
returnavailableDesktops;
}
/// <summary>
/// Returns an ordered list with of all existing desktops and their properties. The list is ordered in the same way as the existing desktops.
/// </summary>
/// <returns>List of desktops or an empty list on failure.</returns>
publicList<VDesktop>GetDesktopList()
{
if(_desktopListAutoUpdate)
{
UpdateDesktopList();
}
List<VDesktop>list=newList<VDesktop>();
foreach(GuiddinavailableDesktops)
{
list.Add(CreateVDesktopInstance(d));
}
returnlist;
}
/// <summary>
/// Returns the count of existing desktops
/// </summary>
/// <returns>Number of existing desktops or zero on failure.</returns>
publicintGetDesktopCount()
{
if(_desktopListAutoUpdate)
{
UpdateDesktopList();
}
returnavailableDesktops.Count;
}
/// <summary>
/// Returns the id of the desktop that is currently visible to the user.
/// </summary>
/// <returns>Guid of the current desktop or an empty guid on failure.</returns>
publicGuidGetCurrentDesktopId()
{
if(_desktopListAutoUpdate)
{
UpdateDesktopList();
}
returncurrentDesktop;
}
/// <summary>
/// Returns an instance of <see cref="VDesktop"/> for the desktop that is currently visible to the user.
/// </summary>
/// <returns>An instance of <see cref="VDesktop"/> for the current desktop, or an empty instance of <see cref="VDesktop"/> on failure.</returns>
publicVDesktopGetCurrentDesktop()
{
if(_desktopListAutoUpdate)
{
UpdateDesktopList();
}
returnCreateVDesktopInstance(currentDesktop);
}
/// <summary>
/// Checks if a desktop is currently visible to the user.
/// </summary>
/// <param name="desktop">The guid of the desktop to check.</param>
/// <returns>A value indicating if the guid belongs to the currently visible desktop.</returns>
publicboolIsDesktopVisible(Guiddesktop)
{
if(_desktopListAutoUpdate)
{
UpdateDesktopList();
}
returncurrentDesktop==desktop;
}
/// <summary>
/// Returns the number (position) of a desktop.
/// </summary>
/// <param name="desktop">The guid of the desktop.</param>
/// <returns>Number of the desktop, if found. Otherwise a value of zero.</returns>
publicintGetDesktopNumber(Guiddesktop)
{
if(_desktopListAutoUpdate)
{
UpdateDesktopList();
}
// Adding +1 because index starts with zero and humans start counting with one.
returnavailableDesktops.IndexOf(desktop)+1;
}
/// <summary>
/// Returns the name of a desktop
/// </summary>
/// <param name="desktop">Guid of the desktop</param>
/// <returns>Returns the name of the desktop or an empty string on failure.</returns>
Log.Debug($"GetDesktopName() failed. Parameter contains an invalid desktop guid ({desktop}) that doesn't belongs to an available desktop. Maybe the guid belongs to the generic 'AllDesktops' view.",typeof(VirtualDesktopHelper));
returnstring.Empty;
}
// If the desktop name was not changed by the user, it isn't saved to the registry. Then we need the default name for the desktop.
/// Returns an instance of <see cref="VDesktop"/> for the desktop where the window is assigned to.
/// </summary>
/// <param name="hWindow">Handle of the window.</param>
/// <returns>An instance of <see cref="VDesktop"/> for the desktop where the window is assigned to, or an empty instance of <see cref="VDesktop"/> on failure.</returns>
publicVDesktopGetWindowDesktop(IntPtrhWindow)
{
if(_virtualDesktopManager==null)
{
Log.Error("GetWindowDesktopId() failed: The instance of <IVirtualDesktopHelper> isn't available.",typeof(VirtualDesktopHelper));
/// Returns a value indicating if the window is assigned to a currently visible desktop.
/// </summary>
/// <param name="hWindow">Handle to the top level window.</param>
/// <returns>True if the desktop with the window is visible or if the window is assigned to all desktops. False if the desktop is not visible and on failure,</returns>
// If a window is hidden because it is moved to an other desktop, then DWM returns type "CloakedShell". If DWM returns an other type the window is not cloaked by shell or VirtualDesktopManager.