2019-09-05 00:26:26 +08:00
# include "pch.h"
2020-05-04 22:29:48 +08:00
# include <common/dpi_aware.h>
# include <common/on_thread_executor.h>
# include <common/window_helpers.h>
2019-09-05 00:26:26 +08:00
2019-12-17 16:21:46 +08:00
# include "FancyZones.h"
# include "lib/Settings.h"
# include "lib/ZoneWindow.h"
2020-02-10 21:59:51 +08:00
# include "lib/JsonHelpers.h"
# include "lib/ZoneSet.h"
2020-04-30 18:16:08 +08:00
# include "lib/WindowMoveHandler.h"
2020-05-04 22:29:48 +08:00
# include "lib/FancyZonesWinHookEventIDs.h"
# include "lib/util.h"
2019-12-17 16:21:46 +08:00
# include "trace.h"
2020-04-22 01:57:21 +08:00
# include "VirtualDesktopUtils.h"
2020-05-31 18:36:45 +08:00
# include "MonitorWorkAreaHandler.h"
2019-12-17 16:21:46 +08:00
2020-05-04 22:29:48 +08:00
# include <interface/win_hook_event_data.h>
2020-02-10 21:59:51 +08:00
enum class DisplayChangeType
{
WorkArea ,
DisplayChange ,
VirtualDesktop ,
Initialization
} ;
2019-12-12 17:10:55 +08:00
2019-09-05 00:26:26 +08:00
struct FancyZones : public winrt : : implements < FancyZones , IFancyZones , IFancyZonesCallback , IZoneWindowHost >
{
public :
2020-02-10 21:59:51 +08:00
FancyZones ( HINSTANCE hinstance , const winrt : : com_ptr < IFancyZonesSettings > & settings ) noexcept :
m_hinstance ( hinstance ) ,
2020-04-30 18:16:08 +08:00
m_settings ( settings ) ,
m_windowMoveHandler ( settings )
2019-09-05 00:26:26 +08:00
{
m_settings - > SetCallback ( this ) ;
}
// IFancyZones
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
Run ( ) noexcept ;
IFACEMETHODIMP_ ( void )
Destroy ( ) noexcept ;
2019-09-05 00:26:26 +08:00
2020-05-05 02:10:23 +08:00
void MoveSizeStart ( HWND window , HMONITOR monitor , POINT const & ptScreen ) noexcept
2020-04-30 18:16:08 +08:00
{
std : : unique_lock writeLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
m_windowMoveHandler . MoveSizeStart ( window , monitor , ptScreen , m_workAreaHandler . GetWorkAreasByDesktopId ( m_currentDesktopId ) ) ;
2020-04-30 18:16:08 +08:00
}
2020-05-27 22:52:59 +08:00
2020-05-05 02:10:23 +08:00
void MoveSizeUpdate ( HMONITOR monitor , POINT const & ptScreen ) noexcept
2020-04-30 18:16:08 +08:00
{
std : : unique_lock writeLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
m_windowMoveHandler . MoveSizeUpdate ( monitor , ptScreen , m_workAreaHandler . GetWorkAreasByDesktopId ( m_currentDesktopId ) ) ;
2020-04-30 18:16:08 +08:00
}
2020-05-27 22:52:59 +08:00
2020-05-05 02:10:23 +08:00
void MoveSizeEnd ( HWND window , POINT const & ptScreen ) noexcept
2020-04-30 18:16:08 +08:00
{
std : : unique_lock writeLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
m_windowMoveHandler . MoveSizeEnd ( window , ptScreen , m_workAreaHandler . GetWorkAreasByDesktopId ( m_currentDesktopId ) ) ;
2020-05-04 22:29:48 +08:00
}
IFACEMETHODIMP_ ( void )
HandleWinHookEvent ( const WinHookEvent * data ) noexcept
{
const auto wparam = reinterpret_cast < WPARAM > ( data - > hwnd ) ;
const LONG lparam = 0 ;
std : : shared_lock readLock ( m_lock ) ;
switch ( data - > event )
{
case EVENT_SYSTEM_MOVESIZESTART :
PostMessageW ( m_window , WM_PRIV_MOVESIZESTART , wparam , lparam ) ;
break ;
case EVENT_SYSTEM_MOVESIZEEND :
PostMessageW ( m_window , WM_PRIV_MOVESIZEEND , wparam , lparam ) ;
break ;
case EVENT_OBJECT_LOCATIONCHANGE :
PostMessageW ( m_window , WM_PRIV_LOCATIONCHANGE , wparam , lparam ) ;
break ;
case EVENT_OBJECT_NAMECHANGE :
PostMessageW ( m_window , WM_PRIV_NAMECHANGE , wparam , lparam ) ;
break ;
case EVENT_OBJECT_UNCLOAKED :
case EVENT_OBJECT_SHOW :
case EVENT_OBJECT_CREATE :
if ( data - > idObject = = OBJID_WINDOW )
{
PostMessageW ( m_window , WM_PRIV_WINDOWCREATED , wparam , lparam ) ;
}
break ;
}
2020-04-30 18:16:08 +08:00
}
2020-05-04 22:29:48 +08:00
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
VirtualDesktopChanged ( ) noexcept ;
IFACEMETHODIMP_ ( void )
VirtualDesktopInitialize ( ) noexcept ;
IFACEMETHODIMP_ ( bool )
OnKeyDown ( PKBDLLHOOKSTRUCT info ) noexcept ;
IFACEMETHODIMP_ ( void )
ToggleEditor ( ) noexcept ;
IFACEMETHODIMP_ ( void )
SettingsChanged ( ) noexcept ;
2020-05-27 22:52:59 +08:00
2020-05-05 02:10:23 +08:00
void WindowCreated ( HWND window ) noexcept ;
2019-09-05 00:26:26 +08:00
// IZoneWindowHost
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
MoveWindowsOnActiveZoneSetChange ( ) noexcept ;
IFACEMETHODIMP_ ( COLORREF )
2020-03-25 22:38:44 +08:00
GetZoneColor ( ) noexcept
{
// Skip the leading # and convert to long
const auto color = m_settings - > GetSettings ( ) - > zoneColor ;
const auto tmp = std : : stol ( color . substr ( 1 ) , nullptr , 16 ) ;
const auto nR = ( tmp & 0xFF0000 ) > > 16 ;
const auto nG = ( tmp & 0xFF00 ) > > 8 ;
const auto nB = ( tmp & 0xFF ) ;
return RGB ( nR , nG , nB ) ;
}
IFACEMETHODIMP_ ( COLORREF )
GetZoneBorderColor ( ) noexcept
{
// Skip the leading # and convert to long
const auto color = m_settings - > GetSettings ( ) - > zoneBorderColor ;
const auto tmp = std : : stol ( color . substr ( 1 ) , nullptr , 16 ) ;
const auto nR = ( tmp & 0xFF0000 ) > > 16 ;
const auto nG = ( tmp & 0xFF00 ) > > 8 ;
const auto nB = ( tmp & 0xFF ) ;
return RGB ( nR , nG , nB ) ;
}
IFACEMETHODIMP_ ( COLORREF )
2020-02-17 23:28:49 +08:00
GetZoneHighlightColor ( ) noexcept
2019-09-05 00:26:26 +08:00
{
// Skip the leading # and convert to long
2020-05-27 22:55:46 +08:00
const auto color = m_settings - > GetSettings ( ) - > zoneHighlightColor ;
2019-09-05 00:26:26 +08:00
const auto tmp = std : : stol ( color . substr ( 1 ) , nullptr , 16 ) ;
const auto nR = ( tmp & 0xFF0000 ) > > 16 ;
const auto nG = ( tmp & 0xFF00 ) > > 8 ;
const auto nB = ( tmp & 0xFF ) ;
return RGB ( nR , nG , nB ) ;
}
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( int )
GetZoneHighlightOpacity ( ) noexcept
2020-01-07 01:59:18 +08:00
{
2020-03-13 17:55:15 +08:00
return m_settings - > GetSettings ( ) - > zoneHighlightOpacity ;
2020-01-07 01:59:18 +08:00
}
2019-09-05 00:26:26 +08:00
2020-03-25 22:38:44 +08:00
IFACEMETHODIMP_ ( bool )
isMakeDraggedWindowTransparentActive ( ) noexcept
{
return m_settings - > GetSettings ( ) - > makeDraggedWindowTransparent ;
}
2020-05-22 22:42:29 +08:00
IFACEMETHODIMP_ ( bool )
InMoveSize ( ) noexcept
{
std : : shared_lock readLock ( m_lock ) ;
return m_windowMoveHandler . InMoveSize ( ) ;
}
2019-09-05 00:26:26 +08:00
LRESULT WndProc ( HWND , UINT , WPARAM , LPARAM ) noexcept ;
void OnDisplayChange ( DisplayChangeType changeType ) noexcept ;
void AddZoneWindow ( HMONITOR monitor , PCWSTR deviceId ) noexcept ;
2020-03-10 16:59:34 +08:00
2019-09-05 00:26:26 +08:00
protected :
static LRESULT CALLBACK s_WndProc ( HWND , UINT , WPARAM , LPARAM ) noexcept ;
private :
struct require_read_lock
{
template < typename T >
2020-02-10 21:59:51 +08:00
require_read_lock ( const std : : shared_lock < T > & lock )
{
lock ;
}
2019-09-05 00:26:26 +08:00
template < typename T >
2020-02-10 21:59:51 +08:00
require_read_lock ( const std : : unique_lock < T > & lock )
{
lock ;
}
2019-09-05 00:26:26 +08:00
} ;
struct require_write_lock
{
template < typename T >
2020-02-10 21:59:51 +08:00
require_write_lock ( const std : : unique_lock < T > & lock )
{
lock ;
}
2019-09-05 00:26:26 +08:00
} ;
void UpdateZoneWindows ( ) noexcept ;
2020-05-06 23:16:16 +08:00
void UpdateWindowsPositions ( ) noexcept ;
2019-09-05 00:26:26 +08:00
void CycleActiveZoneSet ( DWORD vkCode ) noexcept ;
2020-02-06 20:12:59 +08:00
bool OnSnapHotkey ( DWORD vkCode ) noexcept ;
2020-05-04 22:29:48 +08:00
2020-05-01 22:13:16 +08:00
void RegisterVirtualDesktopUpdates ( std : : vector < GUID > & ids ) noexcept ;
2020-05-27 22:52:59 +08:00
bool IsSplashScreen ( HWND window ) ;
2020-02-10 21:59:51 +08:00
void OnEditorExitEvent ( ) noexcept ;
2020-05-25 16:15:42 +08:00
bool ProcessSnapHotkey ( ) noexcept ;
2019-09-05 00:26:26 +08:00
2020-03-25 01:50:26 +08:00
std : : vector < std : : pair < HMONITOR , RECT > > GetRawMonitorData ( ) noexcept ;
std : : vector < HMONITOR > GetMonitorsSorted ( ) noexcept ;
2019-09-05 00:26:26 +08:00
const HINSTANCE m_hinstance { } ;
mutable std : : shared_mutex m_lock ;
HWND m_window { } ;
2020-04-30 18:16:08 +08:00
WindowMoveHandler m_windowMoveHandler ;
2020-05-31 18:36:45 +08:00
MonitorWorkAreaHandler m_workAreaHandler ;
2020-05-04 22:29:48 +08:00
2020-02-10 21:59:51 +08:00
winrt : : com_ptr < IFancyZonesSettings > m_settings { } ;
2020-05-31 18:36:45 +08:00
GUID m_previousDesktopId { } ; // UUID of previously active virtual desktop.
GUID m_currentDesktopId { } ; // UUID of the current virtual desktop.
2019-11-19 07:29:42 +08:00
wil : : unique_handle m_terminateEditorEvent ; // Handle of FancyZonesEditor.exe we launch and wait on
2019-12-12 17:10:55 +08:00
wil : : unique_handle m_terminateVirtualDesktopTrackerEvent ;
2019-09-05 00:26:26 +08:00
2019-11-08 02:56:32 +08:00
OnThreadExecutor m_dpiUnawareThread ;
2019-12-12 17:10:55 +08:00
OnThreadExecutor m_virtualDesktopTrackerThread ;
2019-11-08 02:56:32 +08:00
2020-05-05 02:10:23 +08:00
static UINT WM_PRIV_VD_INIT ; // Scheduled when FancyZones is initialized
static UINT WM_PRIV_VD_SWITCH ; // Scheduled when virtual desktop switch occurs
static UINT WM_PRIV_VD_UPDATE ; // Scheduled on virtual desktops update (creation/deletion)
static UINT WM_PRIV_EDITOR ; // Scheduled when the editor exits
static UINT WM_PRIV_LOWLEVELKB ; // Scheduled when we receive a key down press
2019-09-05 00:26:26 +08:00
2019-11-19 07:29:42 +08:00
// Did we terminate the editor or was it closed cleanly?
2019-09-05 00:26:26 +08:00
enum class EditorExitKind : byte
{
Exit ,
Terminate
} ;
} ;
2020-05-01 22:13:16 +08:00
UINT FancyZones : : WM_PRIV_VD_INIT = RegisterWindowMessage ( L " {469818a8-00fa-4069-b867-a1da484fcd9a} " ) ;
UINT FancyZones : : WM_PRIV_VD_SWITCH = RegisterWindowMessage ( L " {128c2cb0-6bdf-493e-abbe-f8705e04aa95} " ) ;
UINT FancyZones : : WM_PRIV_VD_UPDATE = RegisterWindowMessage ( L " {b8b72b46-f42f-4c26-9e20-29336cf2f22e} " ) ;
2019-09-05 00:26:26 +08:00
UINT FancyZones : : WM_PRIV_EDITOR = RegisterWindowMessage ( L " {87543824-7080-4e91-9d9c-0404642fc7b6} " ) ;
2020-05-05 02:10:23 +08:00
UINT FancyZones : : WM_PRIV_LOWLEVELKB = RegisterWindowMessage ( L " {763c03a3-03d9-4cde-8d71-f0358b0b4b52} " ) ;
2019-09-05 00:26:26 +08:00
// IFancyZones
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
FancyZones : : Run ( ) noexcept
2019-09-05 00:26:26 +08:00
{
std : : unique_lock writeLock ( m_lock ) ;
WNDCLASSEXW wcex { } ;
wcex . cbSize = sizeof ( WNDCLASSEX ) ;
wcex . lpfnWndProc = s_WndProc ;
wcex . hInstance = m_hinstance ;
wcex . lpszClassName = L " SuperFancyZones " ;
RegisterClassExW ( & wcex ) ;
BufferedPaintInit ( ) ;
m_window = CreateWindowExW ( WS_EX_TOOLWINDOW , L " SuperFancyZones " , L " " , WS_POPUP , 0 , 0 , 0 , 0 , nullptr , nullptr , m_hinstance , this ) ;
2020-02-10 21:59:51 +08:00
if ( ! m_window )
return ;
2019-09-05 00:26:26 +08:00
2020-03-13 17:55:15 +08:00
RegisterHotKey ( m_window , 1 , m_settings - > GetSettings ( ) - > editorHotkey . get_modifiers ( ) , m_settings - > GetSettings ( ) - > editorHotkey . get_code ( ) ) ;
2019-11-19 07:29:42 +08:00
2019-12-24 22:47:28 +08:00
VirtualDesktopInitialize ( ) ;
2019-11-08 02:56:32 +08:00
2020-02-10 21:59:51 +08:00
m_dpiUnawareThread . submit ( OnThreadExecutor : : task_t { [ ] {
SetThreadDpiAwarenessContext ( DPI_AWARENESS_CONTEXT_UNAWARE ) ;
SetThreadDpiHostingBehavior ( DPI_HOSTING_BEHAVIOR_MIXED ) ;
} } )
. wait ( ) ;
2019-12-12 17:10:55 +08:00
2020-05-01 22:13:16 +08:00
m_terminateVirtualDesktopTrackerEvent . reset ( CreateEvent ( nullptr , FALSE , FALSE , nullptr ) ) ;
2020-05-04 22:29:48 +08:00
m_virtualDesktopTrackerThread . submit ( OnThreadExecutor : : task_t { [ & ] { VirtualDesktopUtils : : HandleVirtualDesktopUpdates ( m_window , WM_PRIV_VD_UPDATE , m_terminateVirtualDesktopTrackerEvent . get ( ) ) ; } } ) ;
2019-09-05 00:26:26 +08:00
}
// IFancyZones
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
FancyZones : : Destroy ( ) noexcept
2019-09-05 00:26:26 +08:00
{
std : : unique_lock writeLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
m_workAreaHandler . Clear ( ) ;
2019-09-05 00:26:26 +08:00
BufferedPaintUnInit ( ) ;
if ( m_window )
{
DestroyWindow ( m_window ) ;
m_window = nullptr ;
}
2020-02-10 21:59:51 +08:00
if ( m_terminateVirtualDesktopTrackerEvent )
{
2019-12-12 17:10:55 +08:00
SetEvent ( m_terminateVirtualDesktopTrackerEvent . get ( ) ) ;
}
2019-09-05 00:26:26 +08:00
}
// IFancyZonesCallback
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
FancyZones : : VirtualDesktopChanged ( ) noexcept
2019-09-05 00:26:26 +08:00
{
2020-05-04 22:29:48 +08:00
// VirtualDesktopChanged is called from a reentrant WinHookProc function, therefore we must postpone the actual logic
// until we're in FancyZones::WndProc, which is not reentrant.
2020-05-01 22:13:16 +08:00
PostMessage ( m_window , WM_PRIV_VD_SWITCH , 0 , 0 ) ;
2019-09-05 00:26:26 +08:00
}
2019-12-24 22:47:28 +08:00
// IFancyZonesCallback
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
FancyZones : : VirtualDesktopInitialize ( ) noexcept
2019-12-24 22:47:28 +08:00
{
2020-05-01 22:13:16 +08:00
PostMessage ( m_window , WM_PRIV_VD_INIT , 0 , 0 ) ;
2019-12-24 22:47:28 +08:00
}
2019-09-05 00:26:26 +08:00
// IFancyZonesCallback
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
FancyZones : : WindowCreated ( HWND window ) noexcept
2019-09-05 00:26:26 +08:00
{
2020-04-22 01:57:21 +08:00
std : : shared_lock readLock ( m_lock ) ;
2020-05-27 22:52:59 +08:00
2020-04-30 18:16:08 +08:00
if ( m_settings - > GetSettings ( ) - > appLastZone_moveWindows & & IsInterestingWindow ( window , m_settings - > GetSettings ( ) - > excludedAppsArray ) )
2019-09-05 00:26:26 +08:00
{
2020-05-31 18:36:45 +08:00
auto zoneWindow = m_workAreaHandler . GetWorkArea ( window ) ;
if ( zoneWindow )
2019-09-05 00:26:26 +08:00
{
2020-03-10 16:59:34 +08:00
const auto activeZoneSet = zoneWindow - > ActiveZoneSet ( ) ;
if ( activeZoneSet )
2019-09-05 00:26:26 +08:00
{
2020-05-27 22:52:59 +08:00
auto & fancyZonesData = JSONHelpers : : FancyZonesDataInstance ( ) ;
2020-02-10 21:59:51 +08:00
2020-03-10 16:59:34 +08:00
wil : : unique_cotaskmem_string guidString ;
2020-04-22 01:57:21 +08:00
if ( SUCCEEDED ( StringFromCLSID ( activeZoneSet - > Id ( ) , & guidString ) ) )
2020-03-10 16:59:34 +08:00
{
2020-05-26 22:01:12 +08:00
std : : vector < int > zoneIndexSet = fancyZonesData . GetAppLastZoneIndexSet ( window , zoneWindow - > UniqueId ( ) , guidString . get ( ) ) ;
2020-05-27 22:52:59 +08:00
if ( zoneIndexSet . size ( ) & &
! IsSplashScreen ( window ) & &
! fancyZonesData . IsAnotherWindowOfApplicationInstanceZoned ( window ) )
2020-02-10 21:59:51 +08:00
{
2020-05-31 18:36:45 +08:00
m_windowMoveHandler . MoveWindowIntoZoneByIndexSet ( window , zoneIndexSet , zoneWindow ) ;
2020-05-27 22:52:59 +08:00
fancyZonesData . UpdateProcessIdToHandleMap ( window ) ;
2020-02-10 21:59:51 +08:00
}
}
2019-09-05 00:26:26 +08:00
}
}
}
}
// IFancyZonesCallback
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( bool )
FancyZones : : OnKeyDown ( PKBDLLHOOKSTRUCT info ) noexcept
2019-09-05 00:26:26 +08:00
{
// Return true to swallow the keyboard event
bool const shift = GetAsyncKeyState ( VK_SHIFT ) & 0x8000 ;
2020-05-05 15:21:55 +08:00
bool const win = GetAsyncKeyState ( VK_LWIN ) & 0x8000 | | GetAsyncKeyState ( VK_RWIN ) & 0x8000 ;
2019-09-05 00:26:26 +08:00
if ( win & & ! shift )
{
bool const ctrl = GetAsyncKeyState ( VK_CONTROL ) & 0x8000 ;
if ( ctrl )
{
2020-03-26 01:32:33 +08:00
// Temporarily disable Win+Ctrl+Number functionality
//if ((info->vkCode >= '0') && (info->vkCode <= '9'))
//{
// // Win+Ctrl+Number will cycle through ZoneSets
// Trace::FancyZones::OnKeyDown(info->vkCode, win, ctrl, false /*inMoveSize*/);
// CycleActiveZoneSet(info->vkCode);
// return true;
//}
2019-09-05 00:26:26 +08:00
}
else if ( ( info - > vkCode = = VK_RIGHT ) | | ( info - > vkCode = = VK_LEFT ) )
{
2020-05-25 16:15:42 +08:00
if ( ProcessSnapHotkey ( ) )
2019-11-19 07:29:42 +08:00
{
Trace : : FancyZones : : OnKeyDown ( info - > vkCode , win , ctrl , false /*inMoveSize*/ ) ;
2020-05-05 02:10:23 +08:00
// Win+Left, Win+Right will cycle through Zones in the active ZoneSet when WM_PRIV_LOWLEVELKB's handled
PostMessageW ( m_window , WM_PRIV_LOWLEVELKB , 0 , info - > vkCode ) ;
return true ;
2019-11-19 07:29:42 +08:00
}
2019-09-05 00:26:26 +08:00
}
}
2020-03-26 01:32:33 +08:00
// Temporarily disable Win+Ctrl+Number functionality
//else if (m_inMoveSize && (info->vkCode >= '0') && (info->vkCode <= '9'))
//{
// // This allows you to cycle through ZoneSets while dragging a window
// Trace::FancyZones::OnKeyDown(info->vkCode, win, false /*control*/, true /*inMoveSize*/);
// CycleActiveZoneSet(info->vkCode);
// return false;
//}
2020-04-30 18:16:08 +08:00
if ( m_windowMoveHandler . IsDragEnabled ( ) & & shift )
2020-03-05 15:01:58 +08:00
{
return true ;
}
2019-09-05 00:26:26 +08:00
return false ;
}
// IFancyZonesCallback
void FancyZones : : ToggleEditor ( ) noexcept
{
{
std : : shared_lock readLock ( m_lock ) ;
if ( m_terminateEditorEvent )
{
SetEvent ( m_terminateEditorEvent . get ( ) ) ;
return ;
}
}
{
std : : unique_lock writeLock ( m_lock ) ;
m_terminateEditorEvent . reset ( CreateEvent ( nullptr , true , false , nullptr ) ) ;
}
2019-09-28 22:29:29 +08:00
HMONITOR monitor { } ;
2019-11-08 02:56:32 +08:00
HWND foregroundWindow { } ;
2019-09-28 22:29:29 +08:00
2020-03-13 17:55:15 +08:00
const bool use_cursorpos_editor_startupscreen = m_settings - > GetSettings ( ) - > use_cursorpos_editor_startupscreen ;
2019-11-08 02:56:32 +08:00
POINT currentCursorPos { } ;
if ( use_cursorpos_editor_startupscreen )
2019-09-05 00:26:26 +08:00
{
2019-09-28 22:29:29 +08:00
GetCursorPos ( & currentCursorPos ) ;
monitor = MonitorFromPoint ( currentCursorPos , MONITOR_DEFAULTTOPRIMARY ) ;
}
else
{
2019-11-08 02:56:32 +08:00
foregroundWindow = GetForegroundWindow ( ) ;
2019-09-28 22:29:29 +08:00
monitor = MonitorFromWindow ( foregroundWindow , MONITOR_DEFAULTTOPRIMARY ) ;
}
if ( ! monitor )
{
return ;
}
std : : shared_lock readLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
auto zoneWindow = m_workAreaHandler . GetWorkArea ( m_currentDesktopId , monitor ) ;
if ( ! zoneWindow )
2019-09-28 22:29:29 +08:00
{
return ;
}
MONITORINFOEX mi ;
mi . cbSize = sizeof ( mi ) ;
2020-02-10 21:59:51 +08:00
m_dpiUnawareThread . submit ( OnThreadExecutor : : task_t { [ & ] {
GetMonitorInfo ( monitor , & mi ) ;
} } )
. wait ( ) ;
2019-11-08 02:56:32 +08:00
2020-02-10 21:59:51 +08:00
const auto & fancyZonesData = JSONHelpers : : FancyZonesDataInstance ( ) ;
fancyZonesData . CustomZoneSetsToJsonFile ( ZoneWindowUtils : : GetCustomZoneSetsTmpPath ( ) ) ;
2020-04-07 17:03:57 +08:00
const auto taskbar_x_offset = mi . rcWork . left - mi . rcMonitor . left ;
const auto taskbar_y_offset = mi . rcWork . top - mi . rcMonitor . top ;
2019-11-08 02:56:32 +08:00
const auto x = mi . rcMonitor . left + taskbar_x_offset ;
const auto y = mi . rcMonitor . top + taskbar_y_offset ;
const auto width = mi . rcWork . right - mi . rcWork . left ;
const auto height = mi . rcWork . bottom - mi . rcWork . top ;
2020-02-10 21:59:51 +08:00
const std : : wstring editorLocation =
2019-09-28 22:29:29 +08:00
std : : to_wstring ( x ) + L " _ " +
std : : to_wstring ( y ) + L " _ " +
2019-11-08 02:56:32 +08:00
std : : to_wstring ( width ) + L " _ " +
std : : to_wstring ( height ) ;
2019-09-28 22:29:29 +08:00
2020-02-17 23:28:49 +08:00
const auto deviceInfo = fancyZonesData . FindDeviceInfo ( zoneWindow - > UniqueId ( ) ) ;
if ( ! deviceInfo . has_value ( ) )
{
return ;
}
2020-02-10 21:59:51 +08:00
2020-02-17 23:28:49 +08:00
JSONHelpers : : DeviceInfoJSON deviceInfoJson { zoneWindow - > UniqueId ( ) , * deviceInfo } ;
2020-02-10 21:59:51 +08:00
fancyZonesData . SerializeDeviceInfoToTmpFile ( deviceInfoJson , ZoneWindowUtils : : GetActiveZoneSetTmpPath ( ) ) ;
2019-12-06 22:09:27 +08:00
2019-09-28 22:29:29 +08:00
const std : : wstring params =
2020-02-10 21:59:51 +08:00
/*1*/ std : : to_wstring ( reinterpret_cast < UINT_PTR > ( monitor ) ) + L " " +
/*2*/ editorLocation + L " " +
/*3*/ zoneWindow - > WorkAreaKey ( ) + L " " +
2020-03-18 01:12:32 +08:00
/*4*/ L " \" " + ZoneWindowUtils : : GetActiveZoneSetTmpPath ( ) + L " \" " +
/*5*/ L " \" " + ZoneWindowUtils : : GetAppliedZoneSetTmpPath ( ) + L " \" " +
/*6*/ L " \" " + ZoneWindowUtils : : GetCustomZoneSetsTmpPath ( ) + L " \" " ;
2019-09-28 22:29:29 +08:00
SHELLEXECUTEINFO sei { sizeof ( sei ) } ;
sei . fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI } ;
2020-05-12 02:22:23 +08:00
sei . lpFile = L " modules \\ FancyZones \\ FancyZonesEditor.exe " ;
2019-09-28 22:29:29 +08:00
sei . lpParameters = params . c_str ( ) ;
sei . nShow = SW_SHOWNORMAL ;
ShellExecuteEx ( & sei ) ;
2020-03-26 18:54:12 +08:00
Trace : : FancyZones : : EditorLaunched ( 1 ) ;
2019-09-28 22:29:29 +08:00
// Launch the editor on a background thread
// Wait for the editor's process to exit
// Post back to the main thread to update
2020-02-10 21:59:51 +08:00
std : : thread waitForEditorThread ( [ window = m_window , processHandle = sei . hProcess , terminateEditorEvent = m_terminateEditorEvent . get ( ) ] ( ) {
2019-09-28 22:29:29 +08:00
HANDLE waitEvents [ 2 ] = { processHandle , terminateEditorEvent } ;
auto result = WaitForMultipleObjects ( 2 , waitEvents , false , INFINITE ) ;
if ( result = = WAIT_OBJECT_0 + 0 )
2019-09-05 00:26:26 +08:00
{
2019-09-28 22:29:29 +08:00
// Editor exited
// Update any changes it may have made
PostMessage ( window , WM_PRIV_EDITOR , 0 , static_cast < LPARAM > ( EditorExitKind : : Exit ) ) ;
2019-09-05 00:26:26 +08:00
}
2019-09-28 22:29:29 +08:00
else if ( result = = WAIT_OBJECT_0 + 1 )
{
// User hit Win+~ while editor is already running
// Shut it down
TerminateProcess ( processHandle , 2 ) ;
PostMessage ( window , WM_PRIV_EDITOR , 0 , static_cast < LPARAM > ( EditorExitKind : : Terminate ) ) ;
}
CloseHandle ( processHandle ) ;
} ) ;
waitForEditorThread . detach ( ) ;
2019-09-05 00:26:26 +08:00
}
2019-10-02 23:18:55 +08:00
void FancyZones : : SettingsChanged ( ) noexcept
{
2020-02-10 21:59:51 +08:00
std : : shared_lock readLock ( m_lock ) ;
2019-10-02 23:18:55 +08:00
// Update the hotkey
UnregisterHotKey ( m_window , 1 ) ;
2020-03-13 17:55:15 +08:00
RegisterHotKey ( m_window , 1 , m_settings - > GetSettings ( ) - > editorHotkey . get_modifiers ( ) , m_settings - > GetSettings ( ) - > editorHotkey . get_code ( ) ) ;
2019-10-02 23:18:55 +08:00
}
2019-09-05 00:26:26 +08:00
// IZoneWindowHost
2020-02-17 23:28:49 +08:00
IFACEMETHODIMP_ ( void )
FancyZones : : MoveWindowsOnActiveZoneSetChange ( ) noexcept
2019-09-05 00:26:26 +08:00
{
2020-03-13 17:55:15 +08:00
if ( m_settings - > GetSettings ( ) - > zoneSetChange_moveWindows )
2019-09-05 00:26:26 +08:00
{
2020-05-06 23:16:16 +08:00
UpdateWindowsPositions ( ) ;
2019-09-05 00:26:26 +08:00
}
}
LRESULT FancyZones : : WndProc ( HWND window , UINT message , WPARAM wparam , LPARAM lparam ) noexcept
{
switch ( message )
{
case WM_HOTKEY :
{
if ( wparam = = 1 )
{
2019-11-19 07:29:42 +08:00
ToggleEditor ( ) ;
2019-09-05 00:26:26 +08:00
}
}
break ;
case WM_SETTINGCHANGE :
{
if ( wparam = = SPI_SETWORKAREA )
{
OnDisplayChange ( DisplayChangeType : : WorkArea ) ;
}
}
break ;
case WM_DISPLAYCHANGE :
{
OnDisplayChange ( DisplayChangeType : : DisplayChange ) ;
}
break ;
default :
{
2020-05-04 22:29:48 +08:00
POINT ptScreen ;
GetPhysicalCursorPos ( & ptScreen ) ;
2020-05-05 02:10:23 +08:00
if ( message = = WM_PRIV_LOWLEVELKB )
{
OnSnapHotkey ( static_cast < DWORD > ( lparam ) ) ;
}
else if ( message = = WM_PRIV_VD_INIT )
2020-05-01 22:13:16 +08:00
{
OnDisplayChange ( DisplayChangeType : : Initialization ) ;
}
else if ( message = = WM_PRIV_VD_SWITCH )
2019-09-05 00:26:26 +08:00
{
OnDisplayChange ( DisplayChangeType : : VirtualDesktop ) ;
}
2020-05-01 22:13:16 +08:00
else if ( message = = WM_PRIV_VD_UPDATE )
2019-12-24 22:47:28 +08:00
{
2020-05-01 22:13:16 +08:00
std : : vector < GUID > ids { } ;
2020-05-05 16:13:50 +08:00
if ( VirtualDesktopUtils : : GetVirtualDesktopIds ( ids ) )
2020-05-01 22:13:16 +08:00
{
RegisterVirtualDesktopUpdates ( ids ) ;
}
2019-12-24 22:47:28 +08:00
}
2019-09-05 00:26:26 +08:00
else if ( message = = WM_PRIV_EDITOR )
{
if ( lparam = = static_cast < LPARAM > ( EditorExitKind : : Exit ) )
{
2020-02-10 21:59:51 +08:00
OnEditorExitEvent ( ) ;
2019-09-05 00:26:26 +08:00
}
{
// Clean up the event either way
std : : unique_lock writeLock ( m_lock ) ;
m_terminateEditorEvent . release ( ) ;
}
}
2020-05-04 22:29:48 +08:00
else if ( message = = WM_PRIV_MOVESIZESTART )
{
auto hwnd = reinterpret_cast < HWND > ( wparam ) ;
if ( auto monitor = MonitorFromPoint ( ptScreen , MONITOR_DEFAULTTONULL ) )
{
MoveSizeStart ( hwnd , monitor , ptScreen ) ;
}
}
else if ( message = = WM_PRIV_MOVESIZEEND )
{
auto hwnd = reinterpret_cast < HWND > ( wparam ) ;
MoveSizeEnd ( hwnd , ptScreen ) ;
}
else if ( message = = WM_PRIV_LOCATIONCHANGE & & InMoveSize ( ) )
{
if ( auto monitor = MonitorFromPoint ( ptScreen , MONITOR_DEFAULTTONULL ) )
{
MoveSizeUpdate ( monitor , ptScreen ) ;
}
}
else if ( message = = WM_PRIV_WINDOWCREATED )
{
auto hwnd = reinterpret_cast < HWND > ( wparam ) ;
WindowCreated ( hwnd ) ;
}
2019-09-05 00:26:26 +08:00
else
{
return DefWindowProc ( window , message , wparam , lparam ) ;
}
}
break ;
}
return 0 ;
}
void FancyZones : : OnDisplayChange ( DisplayChangeType changeType ) noexcept
{
2019-12-24 22:47:28 +08:00
if ( changeType = = DisplayChangeType : : VirtualDesktop | |
changeType = = DisplayChangeType : : Initialization )
2019-09-05 00:26:26 +08:00
{
2020-05-31 18:36:45 +08:00
m_previousDesktopId = m_currentDesktopId ;
2019-09-05 00:26:26 +08:00
GUID currentVirtualDesktopId { } ;
2020-04-30 17:16:25 +08:00
if ( VirtualDesktopUtils : : GetCurrentVirtualDesktopId ( & currentVirtualDesktopId ) )
2019-09-05 00:26:26 +08:00
{
2020-05-31 18:36:45 +08:00
m_currentDesktopId = currentVirtualDesktopId ;
2020-05-05 16:13:50 +08:00
}
if ( changeType = = DisplayChangeType : : Initialization )
{
std : : vector < std : : wstring > ids { } ;
if ( VirtualDesktopUtils : : GetVirtualDesktopIds ( ids ) & & ! ids . empty ( ) )
2020-04-30 17:16:25 +08:00
{
2020-05-05 16:13:50 +08:00
JSONHelpers : : FancyZonesDataInstance ( ) . UpdatePrimaryDesktopData ( ids [ 0 ] ) ;
JSONHelpers : : FancyZonesDataInstance ( ) . RemoveDeletedDesktops ( ids ) ;
2020-04-30 17:16:25 +08:00
}
2019-09-05 00:26:26 +08:00
}
}
UpdateZoneWindows ( ) ;
if ( ( changeType = = DisplayChangeType : : WorkArea ) | | ( changeType = = DisplayChangeType : : DisplayChange ) )
{
2020-03-13 17:55:15 +08:00
if ( m_settings - > GetSettings ( ) - > displayChange_moveWindows )
2019-09-05 00:26:26 +08:00
{
2020-05-06 23:16:16 +08:00
UpdateWindowsPositions ( ) ;
2019-09-05 00:26:26 +08:00
}
}
}
void FancyZones : : AddZoneWindow ( HMONITOR monitor , PCWSTR deviceId ) noexcept
{
std : : unique_lock writeLock ( m_lock ) ;
2020-02-10 21:59:51 +08:00
2020-05-31 18:36:45 +08:00
if ( m_workAreaHandler . IsNewWorkArea ( m_currentDesktopId , monitor ) )
{
wil : : unique_cotaskmem_string virtualDesktopId ;
if ( SUCCEEDED ( StringFromCLSID ( m_currentDesktopId , & virtualDesktopId ) ) )
2019-09-05 00:26:26 +08:00
{
2020-05-31 18:36:45 +08:00
std : : wstring uniqueId = ZoneWindowUtils : : GenerateUniqueId ( monitor , deviceId , virtualDesktopId . get ( ) ) ;
2020-03-05 15:01:58 +08:00
2020-05-31 18:36:45 +08:00
// "Turning FLASHING_ZONE option off"
//const bool flash = m_settings->GetSettings()->zoneSetChange_flashZones;
const bool flash = false ;
std : : wstring parentId { } ;
auto parentArea = m_workAreaHandler . GetWorkArea ( m_previousDesktopId , monitor ) ;
if ( parentArea )
{
parentId = parentArea - > UniqueId ( ) ;
}
auto workArea = MakeZoneWindow ( this , m_hinstance , monitor , uniqueId , parentId , flash ) ;
if ( workArea )
{
m_workAreaHandler . AddWorkArea ( m_currentDesktopId , monitor , workArea ) ;
JSONHelpers : : FancyZonesDataInstance ( ) . SaveFancyZonesData ( ) ;
}
2020-02-18 18:55:08 +08:00
}
2019-09-05 00:26:26 +08:00
}
}
LRESULT CALLBACK FancyZones : : s_WndProc ( HWND window , UINT message , WPARAM wparam , LPARAM lparam ) noexcept
{
auto thisRef = reinterpret_cast < FancyZones * > ( GetWindowLongPtr ( window , GWLP_USERDATA ) ) ;
if ( ! thisRef & & ( message = = WM_CREATE ) )
{
const auto createStruct = reinterpret_cast < LPCREATESTRUCT > ( lparam ) ;
thisRef = reinterpret_cast < FancyZones * > ( createStruct - > lpCreateParams ) ;
SetWindowLongPtr ( window , GWLP_USERDATA , reinterpret_cast < LONG_PTR > ( thisRef ) ) ;
}
return thisRef ? thisRef - > WndProc ( window , message , wparam , lparam ) :
2020-02-10 21:59:51 +08:00
DefWindowProc ( window , message , wparam , lparam ) ;
2019-09-05 00:26:26 +08:00
}
void FancyZones : : UpdateZoneWindows ( ) noexcept
{
2020-02-10 21:59:51 +08:00
auto callback = [ ] ( HMONITOR monitor , HDC , RECT * , LPARAM data ) - > BOOL {
2019-09-05 00:26:26 +08:00
MONITORINFOEX mi ;
mi . cbSize = sizeof ( mi ) ;
if ( GetMonitorInfo ( monitor , & mi ) )
{
DISPLAY_DEVICE displayDevice = { sizeof ( displayDevice ) } ;
PCWSTR deviceId = nullptr ;
bool validMonitor = true ;
if ( EnumDisplayDevices ( mi . szDevice , 0 , & displayDevice , 1 ) )
{
if ( WI_IsFlagSet ( displayDevice . StateFlags , DISPLAY_DEVICE_MIRRORING_DRIVER ) )
{
validMonitor = FALSE ;
}
else if ( displayDevice . DeviceID [ 0 ] ! = L ' \0 ' )
{
deviceId = displayDevice . DeviceID ;
}
}
if ( validMonitor )
{
if ( ! deviceId )
{
deviceId = GetSystemMetrics ( SM_REMOTESESSION ) ?
2020-02-10 21:59:51 +08:00
L " \\ \\ ? \\ DISPLAY#REMOTEDISPLAY# " :
L " \\ \\ ? \\ DISPLAY#LOCALDISPLAY# " ;
2019-09-05 00:26:26 +08:00
}
auto strongThis = reinterpret_cast < FancyZones * > ( data ) ;
strongThis - > AddZoneWindow ( monitor , deviceId ) ;
}
}
return TRUE ;
} ;
EnumDisplayMonitors ( nullptr , nullptr , callback , reinterpret_cast < LPARAM > ( this ) ) ;
}
2020-05-06 23:16:16 +08:00
void FancyZones : : UpdateWindowsPositions ( ) noexcept
2019-09-05 00:26:26 +08:00
{
2020-02-10 21:59:51 +08:00
auto callback = [ ] ( HWND window , LPARAM data ) - > BOOL {
2020-05-26 22:01:12 +08:00
size_t bitmask = reinterpret_cast < size_t > ( : : GetProp ( window , MULTI_ZONE_STAMP ) ) ;
if ( bitmask ! = 0 )
2019-09-05 00:26:26 +08:00
{
2020-05-26 22:01:12 +08:00
std : : vector < int > indexSet ;
for ( int i = 0 ; i < std : : numeric_limits < size_t > : : digits ; i + + )
{
if ( ( 1ull < < i ) & bitmask )
{
indexSet . push_back ( i ) ;
}
}
2019-09-05 00:26:26 +08:00
auto strongThis = reinterpret_cast < FancyZones * > ( data ) ;
2020-04-30 18:16:08 +08:00
std : : unique_lock writeLock ( strongThis - > m_lock ) ;
2020-05-31 18:36:45 +08:00
auto zoneWindow = strongThis - > m_workAreaHandler . GetWorkArea ( window ) ;
if ( zoneWindow )
{
strongThis - > m_windowMoveHandler . MoveWindowIntoZoneByIndexSet ( window , indexSet , zoneWindow ) ;
}
2019-09-05 00:26:26 +08:00
}
return TRUE ;
} ;
EnumWindows ( callback , reinterpret_cast < LPARAM > ( this ) ) ;
}
void FancyZones : : CycleActiveZoneSet ( DWORD vkCode ) noexcept
{
2020-02-03 16:32:38 +08:00
auto window = GetForegroundWindow ( ) ;
2020-04-30 18:16:08 +08:00
if ( IsInterestingWindow ( window , m_settings - > GetSettings ( ) - > excludedAppsArray ) )
2019-09-05 00:26:26 +08:00
{
2020-02-10 21:59:51 +08:00
const HMONITOR monitor = MonitorFromWindow ( window , MONITOR_DEFAULTTONULL ) ;
if ( monitor )
2019-09-05 00:26:26 +08:00
{
std : : shared_lock readLock ( m_lock ) ;
2020-02-10 21:59:51 +08:00
2020-05-31 18:36:45 +08:00
auto zoneWindow = m_workAreaHandler . GetWorkArea ( m_currentDesktopId , monitor ) ;
if ( zoneWindow )
2019-09-05 00:26:26 +08:00
{
2020-05-31 18:36:45 +08:00
zoneWindow - > CycleActiveZoneSet ( vkCode ) ;
2019-09-05 00:26:26 +08:00
}
}
}
}
2020-02-06 20:12:59 +08:00
bool FancyZones : : OnSnapHotkey ( DWORD vkCode ) noexcept
2019-09-05 00:26:26 +08:00
{
2020-02-03 16:32:38 +08:00
auto window = GetForegroundWindow ( ) ;
2020-04-30 18:16:08 +08:00
if ( IsInterestingWindow ( window , m_settings - > GetSettings ( ) - > excludedAppsArray ) )
2019-09-05 00:26:26 +08:00
{
2020-03-25 01:50:26 +08:00
const HMONITOR current = MonitorFromWindow ( window , MONITOR_DEFAULTTONULL ) ;
if ( current )
2019-09-05 00:26:26 +08:00
{
2020-03-25 01:50:26 +08:00
std : : vector < HMONITOR > monitorInfo = GetMonitorsSorted ( ) ;
2020-05-01 22:17:16 +08:00
if ( monitorInfo . size ( ) > 1 & & m_settings - > GetSettings ( ) - > moveWindowAcrossMonitors )
2019-09-05 00:26:26 +08:00
{
2020-03-25 01:50:26 +08:00
// Multi monitor environment.
auto currMonitorInfo = std : : find ( std : : begin ( monitorInfo ) , std : : end ( monitorInfo ) , current ) ;
do
{
2020-04-30 18:16:08 +08:00
std : : unique_lock writeLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
if ( m_windowMoveHandler . MoveWindowIntoZoneByDirection ( window , vkCode , false /* cycle through zones */ , m_workAreaHandler . GetWorkArea ( m_currentDesktopId , * currMonitorInfo ) ) )
2020-03-25 01:50:26 +08:00
{
return true ;
}
// We iterated through all zones in current monitor zone layout, move on to next one (or previous depending on direction).
if ( vkCode = = VK_RIGHT )
{
currMonitorInfo = std : : next ( currMonitorInfo ) ;
if ( currMonitorInfo = = std : : end ( monitorInfo ) )
{
currMonitorInfo = std : : begin ( monitorInfo ) ;
}
}
else if ( vkCode = = VK_LEFT )
{
if ( currMonitorInfo = = std : : begin ( monitorInfo ) )
{
currMonitorInfo = std : : end ( monitorInfo ) ;
}
currMonitorInfo = std : : prev ( currMonitorInfo ) ;
}
} while ( * currMonitorInfo ! = current ) ;
}
else
{
// Single monitor environment.
2020-04-30 18:16:08 +08:00
std : : unique_lock writeLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
return m_windowMoveHandler . MoveWindowIntoZoneByDirection ( window , vkCode , true /* cycle through zones */ , m_workAreaHandler . GetWorkArea ( m_currentDesktopId , current ) ) ;
2019-09-05 00:26:26 +08:00
}
}
}
2020-02-06 20:12:59 +08:00
return false ;
2019-09-05 00:26:26 +08:00
}
2020-05-01 22:13:16 +08:00
void FancyZones : : RegisterVirtualDesktopUpdates ( std : : vector < GUID > & ids ) noexcept
2020-02-18 18:55:08 +08:00
{
std : : unique_lock writeLock ( m_lock ) ;
2020-05-31 18:36:45 +08:00
std : : vector < GUID > deleted { } ;
m_workAreaHandler . RegisterUpdates ( ids , deleted ) ;
2020-02-18 18:55:08 +08:00
bool modified { false } ;
2020-05-31 18:36:45 +08:00
for ( const auto & id : deleted )
2020-02-18 18:55:08 +08:00
{
2020-05-31 18:36:45 +08:00
wil : : unique_cotaskmem_string virtualDesktopId ;
if ( SUCCEEDED ( StringFromCLSID ( id , & virtualDesktopId ) ) )
2020-02-10 21:59:51 +08:00
{
2020-05-31 18:36:45 +08:00
modified | = JSONHelpers : : FancyZonesDataInstance ( ) . RemoveDevicesByVirtualDesktopId ( virtualDesktopId . get ( ) ) ;
2019-12-12 17:10:55 +08:00
}
}
2020-02-18 18:55:08 +08:00
if ( modified )
{
JSONHelpers : : FancyZonesDataInstance ( ) . SaveFancyZonesData ( ) ;
}
2019-12-12 17:10:55 +08:00
}
2020-05-27 22:52:59 +08:00
bool FancyZones : : IsSplashScreen ( HWND window )
{
wchar_t splashClassName [ ] = L " MsoSplash " ; // shouldn't be localized
wchar_t className [ MAX_PATH ] ;
if ( GetClassName ( window , className , MAX_PATH ) = = 0 )
{
return false ;
}
return wcscmp ( splashClassName , className ) = = 0 ;
}
2020-02-10 21:59:51 +08:00
void FancyZones : : OnEditorExitEvent ( ) noexcept
{
2020-05-26 22:56:25 +08:00
// Collect information about changes in zone layout after editor exited.
2020-02-10 21:59:51 +08:00
JSONHelpers : : FancyZonesDataInstance ( ) . ParseDeviceInfoFromTmpFile ( ZoneWindowUtils : : GetActiveZoneSetTmpPath ( ) ) ;
JSONHelpers : : FancyZonesDataInstance ( ) . ParseDeletedCustomZoneSetsFromTmpFile ( ZoneWindowUtils : : GetCustomZoneSetsTmpPath ( ) ) ;
JSONHelpers : : FancyZonesDataInstance ( ) . ParseCustomZoneSetFromTmpFile ( ZoneWindowUtils : : GetAppliedZoneSetTmpPath ( ) ) ;
JSONHelpers : : FancyZonesDataInstance ( ) . SaveFancyZonesData ( ) ;
2020-05-31 18:36:45 +08:00
for ( auto workArea : m_workAreaHandler . GetAllWorkAreas ( ) )
2020-05-06 23:16:16 +08:00
{
2020-05-31 18:36:45 +08:00
workArea - > UpdateActiveZoneSet ( ) ;
2020-05-06 23:16:16 +08:00
}
if ( m_settings - > GetSettings ( ) - > zoneSetChange_moveWindows )
{
UpdateWindowsPositions ( ) ;
}
2020-02-10 21:59:51 +08:00
}
2020-05-25 16:15:42 +08:00
bool FancyZones : : ProcessSnapHotkey ( ) noexcept
{
if ( m_settings - > GetSettings ( ) - > overrideSnapHotkeys )
{
const HMONITOR monitor = MonitorFromWindow ( GetForegroundWindow ( ) , MONITOR_DEFAULTTONULL ) ;
if ( monitor )
{
2020-05-31 18:36:45 +08:00
auto zoneWindow = m_workAreaHandler . GetWorkArea ( m_currentDesktopId , monitor ) ;
if ( zoneWindow - > ActiveZoneSet ( ) ! = nullptr )
2020-05-25 16:15:42 +08:00
{
return true ;
}
}
}
return false ;
}
2020-03-25 01:50:26 +08:00
std : : vector < HMONITOR > FancyZones : : GetMonitorsSorted ( ) noexcept
{
std : : shared_lock readLock ( m_lock ) ;
auto monitorInfo = GetRawMonitorData ( ) ;
OrderMonitors ( monitorInfo ) ;
std : : vector < HMONITOR > output ;
std : : transform ( std : : begin ( monitorInfo ) , std : : end ( monitorInfo ) , std : : back_inserter ( output ) , [ ] ( const auto & info ) { return info . first ; } ) ;
return output ;
}
std : : vector < std : : pair < HMONITOR , RECT > > FancyZones : : GetRawMonitorData ( ) noexcept
{
std : : shared_lock readLock ( m_lock ) ;
std : : vector < std : : pair < HMONITOR , RECT > > monitorInfo ;
2020-05-31 18:36:45 +08:00
const auto & activeWorkAreaMap = m_workAreaHandler . GetWorkAreasByDesktopId ( m_currentDesktopId ) ;
for ( const auto & [ monitor , workArea ] : activeWorkAreaMap )
2020-03-25 01:50:26 +08:00
{
2020-05-31 18:36:45 +08:00
if ( workArea - > ActiveZoneSet ( ) ! = nullptr )
2020-03-25 01:50:26 +08:00
{
MONITORINFOEX mi ;
mi . cbSize = sizeof ( mi ) ;
GetMonitorInfo ( monitor , & mi ) ;
monitorInfo . push_back ( { monitor , mi . rcMonitor } ) ;
}
}
return monitorInfo ;
}
2020-02-10 21:59:51 +08:00
winrt : : com_ptr < IFancyZones > MakeFancyZones ( HINSTANCE hinstance , const winrt : : com_ptr < IFancyZonesSettings > & settings ) noexcept
2019-09-05 00:26:26 +08:00
{
2020-02-10 21:59:51 +08:00
if ( ! settings )
{
return nullptr ;
}
2019-09-05 00:26:26 +08:00
return winrt : : make_self < FancyZones > ( hinstance , settings ) ;
2020-03-24 22:17:25 +08:00
}