diff --git a/src/common/dpi_aware.cpp b/src/common/dpi_aware.cpp index 55e8f4c9bb..25292d0772 100644 --- a/src/common/dpi_aware.cpp +++ b/src/common/dpi_aware.cpp @@ -14,6 +14,18 @@ HRESULT DPIAware::GetScreenDPIForWindow(HWND hwnd, UINT &dpi_x, UINT &dpi_y) { } } +HRESULT DPIAware::GetScreenDPIForPoint(POINT p, UINT& dpi_x, UINT& dpi_y) { + auto monitor_handle = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST); + dpi_x = 0; + dpi_y = 0; + if (monitor_handle != nullptr) { + return GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y); + } + else { + return E_FAIL; + } +} + void DPIAware::Convert(HMONITOR monitor_handle, int &width, int &height) { if (monitor_handle == NULL) { const POINT ptZero = { 0, 0 }; diff --git a/src/common/dpi_aware.h b/src/common/dpi_aware.h index e4f5eeb3fb..47ba2e6644 100644 --- a/src/common/dpi_aware.h +++ b/src/common/dpi_aware.h @@ -7,5 +7,6 @@ private: public: static HRESULT GetScreenDPIForWindow(HWND hwnd, UINT & dpi_x, UINT & dpi_y); + static HRESULT GetScreenDPIForPoint(POINT p, UINT& dpi_x, UINT& dpi_y); static void Convert(HMONITOR monitor_handle, int &width, int &height); }; diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index efeb224528..1dc7d1a2fc 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -237,75 +237,95 @@ void FancyZones::ToggleEditor() noexcept m_terminateEditorEvent.reset(CreateEvent(nullptr, true, false, nullptr)); } - const HWND foregroundWindow = GetForegroundWindow(); - if (const HMONITOR monitor = MonitorFromWindow(foregroundWindow, MONITOR_DEFAULTTOPRIMARY)) + HMONITOR monitor{}; + UINT dpi_x = 96; + UINT dpi_y = 96; + + if (m_settings->GetSettings().use_cursorpos_editor_startupscreen) { - std::shared_lock readLock(m_lock); - auto iter = m_zoneWindowMap.find(monitor); - if (iter != m_zoneWindowMap.end()) - { - UINT dpi_x = 96; - UINT dpi_y = 96; - DPIAware::GetScreenDPIForWindow(foregroundWindow, dpi_x, dpi_y); + POINT currentCursorPos{}; + GetCursorPos(¤tCursorPos); - MONITORINFOEX mi; - mi.cbSize = sizeof(mi); - GetMonitorInfo(monitor, &mi); - - // X/Y need to start in unscaled screen coordinates to get to the proper top/left of the monitor - // From there, we need to scale the difference between the monitor and workarea rects to get the - // appropriate offset where the overlay should appear. - // This covers the cases where the taskbar is not at the bottom of the screen. - const auto x = mi.rcMonitor.left + MulDiv(mi.rcWork.left - mi.rcMonitor.left, 96, dpi_x); - const auto y = mi.rcMonitor.top + MulDiv(mi.rcWork.top - mi.rcMonitor.top, 96, dpi_y); - - // Location that the editor should occupy, scaled by DPI - std::wstring editorLocation = - std::to_wstring(x) + L"_" + - std::to_wstring(y) + L"_" + - std::to_wstring(MulDiv(mi.rcWork.right - mi.rcWork.left, 96, dpi_x)) + L"_" + - std::to_wstring(MulDiv(mi.rcWork.bottom - mi.rcWork.top, 96, dpi_y)); - - const std::wstring params = - iter->second->UniqueId() + L" " + - std::to_wstring(iter->second->ActiveZoneSet()->LayoutId()) + L" " + - std::to_wstring(reinterpret_cast(monitor)) + L" " + - editorLocation + L" " + - iter->second->WorkAreaKey() + L" " + - std::to_wstring(static_cast(dpi_x) / 96.0f); - - SHELLEXECUTEINFO sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; - sei.lpFile = L"modules\\FancyZonesEditor.exe"; - sei.lpParameters = params.c_str(); - sei.nShow = SW_SHOWNORMAL; - ShellExecuteEx(&sei); - - // Launch the editor on a background thread - // Wait for the editor's process to exit - // Post back to the main thread to update - std::thread waitForEditorThread([window = m_window, processHandle = sei.hProcess, terminateEditorEvent = m_terminateEditorEvent.get()]() - { - HANDLE waitEvents[2] = { processHandle, terminateEditorEvent }; - auto result = WaitForMultipleObjects(2, waitEvents, false, INFINITE); - if (result == WAIT_OBJECT_0 + 0) - { - // Editor exited - // Update any changes it may have made - PostMessage(window, WM_PRIV_EDITOR, 0, static_cast(EditorExitKind::Exit)); - } - 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(EditorExitKind::Terminate)); - } - CloseHandle(processHandle); - }); - waitForEditorThread.detach(); - } + monitor = MonitorFromPoint(currentCursorPos, MONITOR_DEFAULTTOPRIMARY); + DPIAware::GetScreenDPIForPoint(currentCursorPos, dpi_x, dpi_y); } + else + { + const HWND foregroundWindow = GetForegroundWindow(); + monitor = MonitorFromWindow(foregroundWindow, MONITOR_DEFAULTTOPRIMARY); + DPIAware::GetScreenDPIForWindow(foregroundWindow, dpi_x, dpi_y); + } + + + if (!monitor) + { + return; + } + + std::shared_lock readLock(m_lock); + auto iter = m_zoneWindowMap.find(monitor); + if (iter == m_zoneWindowMap.end()) + { + return; + } + + MONITORINFOEX mi; + mi.cbSize = sizeof(mi); + GetMonitorInfo(monitor, &mi); + + // X/Y need to start in unscaled screen coordinates to get to the proper top/left of the monitor + // From there, we need to scale the difference between the monitor and workarea rects to get the + // appropriate offset where the overlay should appear. + // This covers the cases where the taskbar is not at the bottom of the screen. + const auto x = mi.rcMonitor.left + MulDiv(mi.rcWork.left - mi.rcMonitor.left, 96, dpi_x); + const auto y = mi.rcMonitor.top + MulDiv(mi.rcWork.top - mi.rcMonitor.top, 96, dpi_y); + + // Location that the editor should occupy, scaled by DPI + std::wstring editorLocation = + std::to_wstring(x) + L"_" + + std::to_wstring(y) + L"_" + + std::to_wstring(MulDiv(mi.rcWork.right - mi.rcWork.left, 96, dpi_x)) + L"_" + + std::to_wstring(MulDiv(mi.rcWork.bottom - mi.rcWork.top, 96, dpi_y)); + + const std::wstring params = + iter->second->UniqueId() + L" " + + std::to_wstring(iter->second->ActiveZoneSet()->LayoutId()) + L" " + + std::to_wstring(reinterpret_cast(monitor)) + L" " + + editorLocation + L" " + + iter->second->WorkAreaKey() + L" " + + std::to_wstring(static_cast(dpi_x) / 96.0f); + + SHELLEXECUTEINFO sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; + sei.lpFile = L"modules\\FancyZonesEditor.exe"; + sei.lpParameters = params.c_str(); + sei.nShow = SW_SHOWNORMAL; + ShellExecuteEx(&sei); + + // Launch the editor on a background thread + // Wait for the editor's process to exit + // Post back to the main thread to update + std::thread waitForEditorThread([window = m_window, processHandle = sei.hProcess, terminateEditorEvent = m_terminateEditorEvent.get()]() + { + HANDLE waitEvents[2] = { processHandle, terminateEditorEvent }; + auto result = WaitForMultipleObjects(2, waitEvents, false, INFINITE); + if (result == WAIT_OBJECT_0 + 0) + { + // Editor exited + // Update any changes it may have made + PostMessage(window, WM_PRIV_EDITOR, 0, static_cast(EditorExitKind::Exit)); + } + 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(EditorExitKind::Terminate)); + } + CloseHandle(processHandle); + }); + + waitForEditorThread.detach(); } // IZoneWindowHost @@ -723,4 +743,4 @@ void FancyZones::MoveSizeUpdateInternal(HMONITOR monitor, POINT const& ptScreen, winrt::com_ptr MakeFancyZones(HINSTANCE hinstance, IFancyZonesSettings* settings) noexcept { return winrt::make_self(hinstance, settings); -} +} \ No newline at end of file diff --git a/src/modules/fancyzones/lib/Settings.cpp b/src/modules/fancyzones/lib/Settings.cpp index ab35897508..6143324a04 100644 --- a/src/modules/fancyzones/lib/Settings.cpp +++ b/src/modules/fancyzones/lib/Settings.cpp @@ -32,7 +32,7 @@ private: PCWSTR name; bool* value; int resourceId; - } m_configBools[8] = { + } m_configBools[9] = { { L"fancyzones_shiftDrag", &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG }, { L"fancyzones_overrideSnapHotkeys", &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS }, { L"fancyzones_zoneSetChange_flashZones", &m_settings.zoneSetChange_flashZones, IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES }, @@ -41,6 +41,7 @@ private: { L"fancyzones_virtualDesktopChange_moveWindows", &m_settings.virtualDesktopChange_moveWindows, IDS_SETTING_DESCRIPTION_VIRTUALDESKTOPCHANGE_MOVEWINDOWS }, { L"fancyzones_appLastZone_moveWindows", &m_settings.appLastZone_moveWindows, IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS }, { L"fancyzones_use_standalone_editor", &m_settings.use_standalone_editor, IDS_SETTING_DESCRIPTION_USE_STANDALONE_EDITOR }, + { L"use_cursorpos_editor_startupscreen", &m_settings.use_cursorpos_editor_startupscreen, IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN }, }; struct diff --git a/src/modules/fancyzones/lib/Settings.h b/src/modules/fancyzones/lib/Settings.h index 3483db0706..471bcc1988 100644 --- a/src/modules/fancyzones/lib/Settings.h +++ b/src/modules/fancyzones/lib/Settings.h @@ -13,6 +13,7 @@ struct Settings bool overrideSnapHotkeys = false; bool appLastZone_moveWindows = false; bool use_standalone_editor = true; + bool use_cursorpos_editor_startupscreen = true; std::wstring zoneHightlightColor = L"#0078D7"; }; diff --git a/src/modules/fancyzones/lib/fancyzones.rc b/src/modules/fancyzones/lib/fancyzones.rc index f92804df32..b2c2c6bad9 100644 --- a/src/modules/fancyzones/lib/fancyzones.rc +++ b/src/modules/fancyzones/lib/fancyzones.rc @@ -13,6 +13,7 @@ IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES "Flash zones when the active FancyZones layout changes" IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR "Zone Highlight Color (Default #0078D7)" IDS_SETTING_DESCRIPTION_USE_STANDALONE_EDITOR "Use new zone editing experience (Preview)" + IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN "Follow mouse cursor instead of focus when launching editor in a multi screen environment" IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS "Move newly created windows to their last known zone" IDS_SETTING_LAUNCH_EDITOR_LABEL "Zone configuration" IDS_SETTING_LAUNCH_EDITOR_BUTTON "Edit zones" diff --git a/src/modules/fancyzones/lib/resource.h b/src/modules/fancyzones/lib/resource.h index 6b68ee12fe..1b6fa1e798 100644 --- a/src/modules/fancyzones/lib/resource.h +++ b/src/modules/fancyzones/lib/resource.h @@ -7,7 +7,8 @@ #define IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR 107 #define IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS 108 #define IDS_SETTING_DESCRIPTION_USE_STANDALONE_EDITOR 109 -#define IDS_SETTING_DESCRIPTION 110 -#define IDS_SETTING_LAUNCH_EDITOR_LABEL 111 -#define IDS_SETTING_LAUNCH_EDITOR_BUTTON 112 -#define IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION 113 +#define IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN 110 +#define IDS_SETTING_DESCRIPTION 111 +#define IDS_SETTING_LAUNCH_EDITOR_LABEL 112 +#define IDS_SETTING_LAUNCH_EDITOR_BUTTON 113 +#define IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION 114