mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-01 01:49:06 +08:00
Modifying the startup behaviour of the FancyZones Layout Editor
Add setting to allow to choose if the FZ editor opens in the screen where mouse cursor is or where the active windows is.
This commit is contained in:
parent
a8f0d3298f
commit
faf1fae873
@ -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 };
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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<UINT_PTR>(monitor)) + L" " +
|
||||
editorLocation + L" " +
|
||||
iter->second->WorkAreaKey() + L" " +
|
||||
std::to_wstring(static_cast<float>(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<LPARAM>(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<LPARAM>(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<UINT_PTR>(monitor)) + L" " +
|
||||
editorLocation + L" " +
|
||||
iter->second->WorkAreaKey() + L" " +
|
||||
std::to_wstring(static_cast<float>(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<LPARAM>(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<LPARAM>(EditorExitKind::Terminate));
|
||||
}
|
||||
CloseHandle(processHandle);
|
||||
});
|
||||
|
||||
waitForEditorThread.detach();
|
||||
}
|
||||
|
||||
// IZoneWindowHost
|
||||
@ -723,4 +743,4 @@ void FancyZones::MoveSizeUpdateInternal(HMONITOR monitor, POINT const& ptScreen,
|
||||
winrt::com_ptr<IFancyZones> MakeFancyZones(HINSTANCE hinstance, IFancyZonesSettings* settings) noexcept
|
||||
{
|
||||
return winrt::make_self<FancyZones>(hinstance, settings);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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";
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|