Merge pull request #1 from microsoft/master

Sync with master
This commit is contained in:
Chris Davis 2019-11-08 12:05:57 -08:00 committed by GitHub
commit b9b60a1346
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 349 additions and 213 deletions

View File

@ -6,11 +6,11 @@
<!-- Please review the items on the PR checklist before submitting--> <!-- Please review the items on the PR checklist before submitting-->
## PR Checklist ## PR Checklist
* [ ] Closes #xxx * [] Applies to #xxx
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/PowerToys) and sign the CLA * [] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/PowerToys) and sign the CLA
* [ ] Tests added/passed * [] Tests added/passed
* [ ] Requires documentation to be updated * [] Requires documentation to be updated
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx * [] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments ## Detailed Description of the Pull Request / Additional comments

View File

@ -6,7 +6,6 @@ The list below is the set of utilities we're considering and the rough priority
* Maximize to new desktop widget - The MTND widget shows a pop-up button when a user hovers over the maximize / restore button on any window. Clicking it creates a new desktop, sends the app to that desktop and maximizes the app on the new desktop. * Maximize to new desktop widget - The MTND widget shows a pop-up button when a user hovers over the maximize / restore button on any window. Clicking it creates a new desktop, sends the app to that desktop and maximizes the app on the new desktop.
* [Process terminate tool](https://github.com/indierawk2k2/PowerToys-1/blob/master/specs/Terminate%20Spec.md) * [Process terminate tool](https://github.com/indierawk2k2/PowerToys-1/blob/master/specs/Terminate%20Spec.md)
* [Batch file renamer](https://github.com/indierawk2k2/PowerToys-1/blob/master/specs/File%20Classification%20Spec.md)
* [Animated gif screen recorder](https://github.com/indierawk2k2/PowerToys-1/blob/master/specs/GIF%20Maker%20Spec.md) * [Animated gif screen recorder](https://github.com/indierawk2k2/PowerToys-1/blob/master/specs/GIF%20Maker%20Spec.md)
## Backlog ## Backlog

View File

@ -98,6 +98,7 @@
<ClInclude Include="d2d_window.h" /> <ClInclude Include="d2d_window.h" />
<ClInclude Include="dpi_aware.h" /> <ClInclude Include="dpi_aware.h" />
<ClInclude Include="monitors.h" /> <ClInclude Include="monitors.h" />
<ClInclude Include="on_thread_executor.h" />
<ClInclude Include="pch.h" /> <ClInclude Include="pch.h" />
<ClInclude Include="settings_helpers.h" /> <ClInclude Include="settings_helpers.h" />
<ClInclude Include="settings_objects.h" /> <ClInclude Include="settings_objects.h" />
@ -117,6 +118,7 @@
<ClCompile Include="d2d_window.cpp" /> <ClCompile Include="d2d_window.cpp" />
<ClCompile Include="dpi_aware.cpp" /> <ClCompile Include="dpi_aware.cpp" />
<ClCompile Include="monitors.cpp" /> <ClCompile Include="monitors.cpp" />
<ClCompile Include="on_thread_executor.cpp" />
<ClCompile Include="pch.cpp"> <ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>

View File

@ -69,6 +69,9 @@
<ClInclude Include="version.h"> <ClInclude Include="version.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="on_thread_executor.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="d2d_svg.cpp"> <ClCompile Include="d2d_svg.cpp">
@ -108,5 +111,8 @@
<ClCompile Include="dpi_aware.cpp"> <ClCompile Include="dpi_aware.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="on_thread_executor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -38,3 +38,7 @@ void DPIAware::Convert(HMONITOR monitor_handle, int &width, int &height) {
height = height * dpi_y / DEFAULT_DPI; height = height * dpi_y / DEFAULT_DPI;
} }
} }
void DPIAware::EnableDPIAwarenessForThisProcess() {
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}

View File

@ -1,12 +1,11 @@
#pragma once #pragma once
#include "windef.h" #include "windef.h"
class DPIAware { struct DPIAware {
private: static constexpr int DEFAULT_DPI = 96;
static const int DEFAULT_DPI = 96;
public:
static HRESULT GetScreenDPIForWindow(HWND hwnd, UINT & dpi_x, UINT & dpi_y); static HRESULT GetScreenDPIForWindow(HWND hwnd, UINT & dpi_x, UINT & dpi_y);
static HRESULT GetScreenDPIForPoint(POINT p, 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); static void Convert(HMONITOR monitor_handle, int &width, int &height);
static void EnableDPIAwarenessForThisProcess();
}; };

View File

@ -0,0 +1,38 @@
#include "pch.h"
#include "on_thread_executor.h"
OnThreadExecutor::OnThreadExecutor()
:_worker_thread{[this]() { worker_thread(); }}
{}
std::future<void> OnThreadExecutor::submit(task_t task) {
auto future = task.get_future();
std::lock_guard lock{_task_mutex};
_task_queue.emplace(std::move(task));
_task_cv.notify_one();
return future;
}
void OnThreadExecutor::worker_thread() {
while(_active) {
task_t task;
{
std::unique_lock task_lock{_task_mutex};
_task_cv.wait(task_lock, [this] { return !_task_queue.empty() || !_active; });
if(!_active) {
break;
}
task = std::move(_task_queue.front());
_task_queue.pop();
}
task();
}
}
OnThreadExecutor::~OnThreadExecutor() {
_active = false;
_task_cv.notify_one();
_worker_thread.join();
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <future>
#include <thread>
#include <functional>
#include <queue>
#include <atomic>
// OnThreadExecutor allows its caller to off-load some work to a persistently running background thread.
// This might come in handy if you use the API which sets thread-wide global state and the state needs
// to be isolated.
class OnThreadExecutor final {
public:
using task_t = std::packaged_task<void()>;
OnThreadExecutor();
~OnThreadExecutor();
std::future<void> submit(task_t task);
private:
void worker_thread();
std::thread _worker_thread;
std::mutex _task_mutex;
std::condition_variable _task_cv;
std::atomic_bool _active;
std::queue<std::packaged_task<void()>> _task_queue;
};

View File

@ -220,6 +220,7 @@ private:
void MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept; void MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept;
void MoveSizeUpdate(POINT const& ptScreen) noexcept; void MoveSizeUpdate(POINT const& ptScreen) noexcept;
HANDLE m_movedWindow = nullptr;
winrt::com_ptr<IFancyZones> m_app; winrt::com_ptr<IFancyZones> m_app;
winrt::com_ptr<IFancyZonesSettings> m_settings; winrt::com_ptr<IFancyZonesSettings> m_settings;
}; };
@ -298,6 +299,7 @@ void FancyZonesModule::MoveSizeStart(HWND window, POINT const& ptScreen) noexcep
{ {
if (auto monitor = MonitorFromPoint(ptScreen, MONITOR_DEFAULTTONULL)) if (auto monitor = MonitorFromPoint(ptScreen, MONITOR_DEFAULTTONULL))
{ {
m_movedWindow = window;
m_app.as<IFancyZonesCallback>()->MoveSizeStart(window, monitor, ptScreen); m_app.as<IFancyZonesCallback>()->MoveSizeStart(window, monitor, ptScreen);
} }
} }
@ -305,8 +307,9 @@ void FancyZonesModule::MoveSizeStart(HWND window, POINT const& ptScreen) noexcep
void FancyZonesModule::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept void FancyZonesModule::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcept
{ {
if (IsInterestingWindow(window)) if (IsInterestingWindow(window) || (window != nullptr && window == m_movedWindow))
{ {
m_movedWindow = nullptr;
m_app.as<IFancyZonesCallback>()->MoveSizeEnd(window, ptScreen); m_app.as<IFancyZonesCallback>()->MoveSizeEnd(window, ptScreen);
} }
} }

View File

@ -23,6 +23,9 @@ namespace FancyZonesEditor
/// </summary> /// </summary>
public partial class MainWindow : MetroWindow public partial class MainWindow : MetroWindow
{ {
// TODO: share the constants b/w C# Editor and FancyZoneLib
public static int MAX_ZONES = 40;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
@ -57,7 +60,7 @@ namespace FancyZonesEditor
private void IncrementZones_Click(object sender, RoutedEventArgs e) private void IncrementZones_Click(object sender, RoutedEventArgs e)
{ {
if (_settings.ZoneCount < 40) if (_settings.ZoneCount < MAX_ZONES)
{ {
_settings.ZoneCount++; _settings.ZoneCount++;
} }

View File

@ -279,7 +279,7 @@ namespace FancyZonesEditor
// 1 = unique key for per-monitor settings // 1 = unique key for per-monitor settings
// 2 = layoutid used to generate current layout (used to pick the default layout to show) // 2 = layoutid used to generate current layout (used to pick the default layout to show)
// 3 = handle to monitor (passed back to engine to persist data) // 3 = handle to monitor (passed back to engine to persist data)
// 4 = X_Y_Width_Height (where EditorOverlay shows up) // 4 = X_Y_Width_Height in a dpi-scaled-but-unaware coords (where EditorOverlay shows up)
// 5 = resolution key (passed back to engine to persist data) // 5 = resolution key (passed back to engine to persist data)
// 6 = monitor DPI (float) // 6 = monitor DPI (float)

View File

@ -1,13 +1,14 @@
#include "pch.h" #include "pch.h"
#include "common/dpi_aware.h" #include "common/dpi_aware.h"
#include "common/on_thread_executor.h"
struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZonesCallback, IZoneWindowHost> struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZonesCallback, IZoneWindowHost>
{ {
public: public:
FancyZones(HINSTANCE hinstance, IFancyZonesSettings* settings) noexcept FancyZones(HINSTANCE hinstance, IFancyZonesSettings* settings) noexcept
: m_hinstance(hinstance) : m_hinstance(hinstance)
, m_settings(settings)
{ {
m_settings.attach(settings);
m_settings->SetCallback(this); m_settings->SetCallback(this);
} }
@ -84,10 +85,12 @@ private:
bool m_dragEnabled{}; // True if we should be showing zone hints while dragging bool m_dragEnabled{}; // True if we should be showing zone hints while dragging
std::map<HMONITOR, winrt::com_ptr<IZoneWindow>> m_zoneWindowMap; // Map of monitor to ZoneWindow (one per monitor) std::map<HMONITOR, winrt::com_ptr<IZoneWindow>> m_zoneWindowMap; // Map of monitor to ZoneWindow (one per monitor)
winrt::com_ptr<IZoneWindow> m_zoneWindowMoveSize; // "Active" ZoneWindow, where the move/size is happening. Will update as drag moves between monitors. winrt::com_ptr<IZoneWindow> m_zoneWindowMoveSize; // "Active" ZoneWindow, where the move/size is happening. Will update as drag moves between monitors.
winrt::com_ptr<IFancyZonesSettings> m_settings; IFancyZonesSettings* m_settings{};
GUID m_currentVirtualDesktopId{}; GUID m_currentVirtualDesktopId{};
wil::unique_handle m_terminateEditorEvent; wil::unique_handle m_terminateEditorEvent;
OnThreadExecutor m_dpiUnawareThread;
static UINT WM_PRIV_VDCHANGED; static UINT WM_PRIV_VDCHANGED;
static UINT WM_PRIV_EDITOR; static UINT WM_PRIV_EDITOR;
@ -120,13 +123,18 @@ IFACEMETHODIMP_(void) FancyZones::Run() noexcept
RegisterHotKey(m_window, 1, m_settings->GetSettings().editorHotkey.get_modifiers(), m_settings->GetSettings().editorHotkey.get_code()); RegisterHotKey(m_window, 1, m_settings->GetSettings().editorHotkey.get_modifiers(), m_settings->GetSettings().editorHotkey.get_code());
VirtualDesktopChanged(); VirtualDesktopChanged();
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{[]{
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
SetThreadDpiHostingBehavior(DPI_HOSTING_BEHAVIOR_MIXED);
}}).wait();
} }
// IFancyZones // IFancyZones
IFACEMETHODIMP_(void) FancyZones::Destroy() noexcept IFACEMETHODIMP_(void) FancyZones::Destroy() noexcept
{ {
std::unique_lock writeLock(m_lock); std::unique_lock writeLock(m_lock);
m_zoneWindowMap.clear();
BufferedPaintUnInit(); BufferedPaintUnInit();
if (m_window) if (m_window)
{ {
@ -239,22 +247,22 @@ void FancyZones::ToggleEditor() noexcept
} }
HMONITOR monitor{}; HMONITOR monitor{};
UINT dpi_x = 96; HWND foregroundWindow{};
UINT dpi_y = 96;
if (m_settings->GetSettings().use_cursorpos_editor_startupscreen) UINT dpi_x = DPIAware::DEFAULT_DPI;
{ UINT dpi_y = DPIAware::DEFAULT_DPI;
const bool use_cursorpos_editor_startupscreen = m_settings->GetSettings().use_cursorpos_editor_startupscreen;
POINT currentCursorPos{}; POINT currentCursorPos{};
if (use_cursorpos_editor_startupscreen)
{
GetCursorPos(&currentCursorPos); GetCursorPos(&currentCursorPos);
monitor = MonitorFromPoint(currentCursorPos, MONITOR_DEFAULTTOPRIMARY); monitor = MonitorFromPoint(currentCursorPos, MONITOR_DEFAULTTOPRIMARY);
DPIAware::GetScreenDPIForPoint(currentCursorPos, dpi_x, dpi_y);
} }
else else
{ {
const HWND foregroundWindow = GetForegroundWindow(); foregroundWindow = GetForegroundWindow();
monitor = MonitorFromWindow(foregroundWindow, MONITOR_DEFAULTTOPRIMARY); monitor = MonitorFromWindow(foregroundWindow, MONITOR_DEFAULTTOPRIMARY);
DPIAware::GetScreenDPIForWindow(foregroundWindow, dpi_x, dpi_y);
} }
@ -272,21 +280,33 @@ void FancyZones::ToggleEditor() noexcept
MONITORINFOEX mi; MONITORINFOEX mi;
mi.cbSize = sizeof(mi); mi.cbSize = sizeof(mi);
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{[&]{
GetMonitorInfo(monitor, &mi); GetMonitorInfo(monitor, &mi);
}}).wait();
// X/Y need to start in unscaled screen coordinates to get to the proper top/left of the monitor if(use_cursorpos_editor_startupscreen)
// From there, we need to scale the difference between the monitor and workarea rects to get the {
// appropriate offset where the overlay should appear. DPIAware::GetScreenDPIForPoint(currentCursorPos, dpi_x, dpi_y);
// 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); else
const auto y = mi.rcMonitor.top + MulDiv(mi.rcWork.top - mi.rcMonitor.top, 96, dpi_y); {
DPIAware::GetScreenDPIForWindow(foregroundWindow, dpi_x, dpi_y);
}
// Location that the editor should occupy, scaled by DPI const auto taskbar_x_offset = MulDiv(mi.rcWork.left - mi.rcMonitor.left, DPIAware::DEFAULT_DPI, dpi_x);
std::wstring editorLocation = const auto taskbar_y_offset = MulDiv(mi.rcWork.top - mi.rcMonitor.top, DPIAware::DEFAULT_DPI, dpi_y);
// Do not scale window params by the dpi, that will be done in the editor - see LayoutModel.Apply
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;
const std::wstring editorLocation =
std::to_wstring(x) + L"_" + std::to_wstring(x) + L"_" +
std::to_wstring(y) + L"_" + std::to_wstring(y) + L"_" +
std::to_wstring(MulDiv(mi.rcWork.right - mi.rcWork.left, 96, dpi_x)) + L"_" + std::to_wstring(width) + L"_" +
std::to_wstring(MulDiv(mi.rcWork.bottom - mi.rcWork.top, 96, dpi_y)); std::to_wstring(height);
const std::wstring params = const std::wstring params =
iter->second->UniqueId() + L" " + iter->second->UniqueId() + L" " +
@ -294,7 +314,7 @@ void FancyZones::ToggleEditor() noexcept
std::to_wstring(reinterpret_cast<UINT_PTR>(monitor)) + L" " + std::to_wstring(reinterpret_cast<UINT_PTR>(monitor)) + L" " +
editorLocation + L" " + editorLocation + L" " +
iter->second->WorkAreaKey() + L" " + iter->second->WorkAreaKey() + L" " +
std::to_wstring(static_cast<float>(dpi_x) / 96.0f); std::to_wstring(static_cast<float>(dpi_x) / DPIAware::DEFAULT_DPI);
SHELLEXECUTEINFO sei{ sizeof(sei) }; SHELLEXECUTEINFO sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
@ -652,18 +672,26 @@ void FancyZones::MoveSizeStartInternal(HWND window, HMONITOR monitor, POINT cons
RECT windowRect{}; RECT windowRect{};
::GetWindowRect(window, &windowRect); ::GetWindowRect(window, &windowRect);
windowRect.top += 6; const auto padding_x = 8;
windowRect.left += 8; const auto padding_y = 6;
windowRect.right -= 8; windowRect.top += padding_y;
windowRect.bottom -= 6; windowRect.left += padding_x;
windowRect.right -= padding_x;
windowRect.bottom -= padding_y;
if (PtInRect(&windowRect, ptScreen)) if (PtInRect(&windowRect, ptScreen) == FALSE)
{ {
return;
}
m_inMoveSize = true; m_inMoveSize = true;
auto iter = m_zoneWindowMap.find(monitor); auto iter = m_zoneWindowMap.find(monitor);
if (iter != m_zoneWindowMap.end()) if (iter == end(m_zoneWindowMap))
{ {
return;
}
m_windowMoveSize = window; m_windowMoveSize = window;
// This updates m_dragEnabled depending on if the shift key is being held down. // This updates m_dragEnabled depending on if the shift key is being held down.
@ -679,8 +707,6 @@ void FancyZones::MoveSizeStartInternal(HWND window, HMONITOR monitor, POINT cons
m_zoneWindowMoveSize->MoveSizeCancel(); m_zoneWindowMoveSize->MoveSizeCancel();
m_zoneWindowMoveSize = nullptr; m_zoneWindowMoveSize = nullptr;
} }
}
}
} }
void FancyZones::MoveSizeEndInternal(HWND window, POINT const& ptScreen, require_write_lock) noexcept void FancyZones::MoveSizeEndInternal(HWND window, POINT const& ptScreen, require_write_lock) noexcept

View File

@ -11,7 +11,7 @@ public:
LoadSettings(name, true /*fromFile*/); LoadSettings(name, true /*fromFile*/);
} }
IFACEMETHODIMP_(void) SetCallback(IFancyZonesCallback* callback) { m_callback.attach(callback); } IFACEMETHODIMP_(void) SetCallback(IFancyZonesCallback* callback) { m_callback = callback; }
IFACEMETHODIMP_(bool) GetConfig(_Out_ PWSTR buffer, _Out_ int *buffer_sizeg) noexcept; IFACEMETHODIMP_(bool) GetConfig(_Out_ PWSTR buffer, _Out_ int *buffer_sizeg) noexcept;
IFACEMETHODIMP_(void) SetConfig(PCWSTR config) noexcept; IFACEMETHODIMP_(void) SetConfig(PCWSTR config) noexcept;
IFACEMETHODIMP_(void) CallCustomAction(PCWSTR action) noexcept; IFACEMETHODIMP_(void) CallCustomAction(PCWSTR action) noexcept;
@ -21,7 +21,7 @@ private:
void LoadSettings(PCWSTR config, bool fromFile) noexcept; void LoadSettings(PCWSTR config, bool fromFile) noexcept;
void SaveSettings() noexcept; void SaveSettings() noexcept;
winrt::com_ptr<IFancyZonesCallback> m_callback; IFancyZonesCallback* m_callback{};
const HINSTANCE m_hinstance; const HINSTANCE m_hinstance;
PCWSTR m_name{}; PCWSTR m_name{};

View File

@ -34,13 +34,15 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
#define VERSION_PERSISTEDDATA 0x0000F00D #define VERSION_PERSISTEDDATA 0x0000F00D
struct ZoneSetPersistedData struct ZoneSetPersistedData
{ {
static constexpr inline size_t MAX_ZONES = 40;
DWORD Version{VERSION_PERSISTEDDATA}; DWORD Version{VERSION_PERSISTEDDATA};
WORD LayoutId{}; WORD LayoutId{};
DWORD ZoneCount{}; DWORD ZoneCount{};
ZoneSetLayout Layout{}; ZoneSetLayout Layout{};
DWORD PaddingInner{}; DWORD PaddingInner{};
DWORD PaddingOuter{}; DWORD PaddingOuter{};
RECT Zones[40]{}; RECT Zones[MAX_ZONES]{};
}; };
struct ZoneSetConfig struct ZoneSetConfig

View File

@ -1,4 +1,6 @@
#include "pch.h" #include "pch.h"
#include <common/dpi_aware.h>
#include <ShellScalingApi.h> #include <ShellScalingApi.h>
struct ZoneWindow : public winrt::implements<ZoneWindow, IZoneWindow> struct ZoneWindow : public winrt::implements<ZoneWindow, IZoneWindow>
@ -116,8 +118,10 @@ ZoneWindow::ZoneWindow(
MONITORINFO mi{}; MONITORINFO mi{};
mi.cbSize = sizeof(mi); mi.cbSize = sizeof(mi);
if (GetMonitorInfoW(m_monitor, &mi)) if (!GetMonitorInfoW(m_monitor, &mi))
{ {
return;
}
const UINT dpi = GetDpiForMonitor(); const UINT dpi = GetDpiForMonitor();
const Rect monitorRect(mi.rcMonitor); const Rect monitorRect(mi.rcMonitor);
const Rect workAreaRect(mi.rcWork, dpi); const Rect workAreaRect(mi.rcWork, dpi);
@ -151,13 +155,15 @@ ZoneWindow::ZoneWindow(
FlashZones(); FlashZones();
} }
} }
}
} }
IFACEMETHODIMP ZoneWindow::ShowZoneWindow(bool activate, bool fadeIn) noexcept IFACEMETHODIMP ZoneWindow::ShowZoneWindow(bool activate, bool fadeIn) noexcept
{ {
if (m_window) if (!m_window)
{ {
return E_FAIL;
}
m_flashMode = false; m_flashMode = false;
UINT flags = SWP_NOSIZE | SWP_NOMOVE; UINT flags = SWP_NOSIZE | SWP_NOMOVE;
@ -184,10 +190,7 @@ IFACEMETHODIMP ZoneWindow::ShowZoneWindow(bool activate, bool fadeIn) noexcept
AnimateWindow(m_window.get(), m_showAnimationDuration, AW_BLEND); AnimateWindow(m_window.get(), m_showAnimationDuration, AW_BLEND);
InvalidateRect(m_window.get(), nullptr, true); InvalidateRect(m_window.get(), nullptr, true);
} }
return S_OK; return S_OK;
}
return E_FAIL;
} }
IFACEMETHODIMP ZoneWindow::HideZoneWindow() noexcept IFACEMETHODIMP ZoneWindow::HideZoneWindow() noexcept
@ -356,8 +359,11 @@ void ZoneWindow::InitializeZoneSets() noexcept
void ZoneWindow::LoadZoneSetsFromRegistry() noexcept void ZoneWindow::LoadZoneSetsFromRegistry() noexcept
{ {
if (wil::unique_hkey key{ RegistryHelpers::OpenKey(m_workArea) }) wil::unique_hkey key{RegistryHelpers::OpenKey(m_workArea)};
if (!key)
{ {
return;
}
ZoneSetPersistedData data{}; ZoneSetPersistedData data{};
DWORD dataSize = sizeof(data); DWORD dataSize = sizeof(data);
wchar_t value[256]{}; wchar_t value[256]{};
@ -387,12 +393,12 @@ void ZoneWindow::LoadZoneSetsFromRegistry() noexcept
zoneSet->AddZone(MakeZone(data.Zones[j]), false); zoneSet->AddZone(MakeZone(data.Zones[j]), false);
} }
m_zoneSets.emplace_back(zoneSet);
if (zoneSetId == m_activeZoneSetId) if (zoneSetId == m_activeZoneSetId)
{ {
UpdateActiveZoneSet(zoneSet.get()); UpdateActiveZoneSet(zoneSet.get());
} }
m_zoneSets.emplace_back(std::move(zoneSet));
} }
} }
} }
@ -404,7 +410,6 @@ void ZoneWindow::LoadZoneSetsFromRegistry() noexcept
valueLength = ARRAYSIZE(value); valueLength = ARRAYSIZE(value);
dataSize = sizeof(data); dataSize = sizeof(data);
} }
}
} }
winrt::com_ptr<IZoneSet> ZoneWindow::AddZoneSet(ZoneSetLayout layout, int numZones, int paddingOuter, int paddingInner) noexcept winrt::com_ptr<IZoneSet> ZoneWindow::AddZoneSet(ZoneSetLayout layout, int numZones, int paddingOuter, int paddingInner) noexcept
@ -716,8 +721,10 @@ void ZoneWindow::DrawZone(wil::unique_hdc& hdc, ColorSetting const& colorSetting
} }
FillRectARGB(hdc, &zoneRect, colorSetting.fillAlpha, colorSetting.fill, false); FillRectARGB(hdc, &zoneRect, colorSetting.fillAlpha, colorSetting.fill, false);
if (!m_flashMode) if (m_flashMode)
{ {
return;
}
COLORREF const colorFill = RGB(255, 255, 255); COLORREF const colorFill = RGB(255, 255, 255);
size_t const index = zone->Id(); size_t const index = zone->Id();
@ -746,7 +753,6 @@ void ZoneWindow::DrawZone(wil::unique_hdc& hdc, ColorSetting const& colorSetting
offset.x = zoneRect.left + padding; offset.x = zoneRect.left + padding;
DrawIndex(hdc, offset, index, padding, size, false, true, colorFill); // bottom left DrawIndex(hdc, offset, index, padding, size, false, true, colorFill); // bottom left
}
} }
void ZoneWindow::DrawIndex(wil::unique_hdc& hdc, POINT offset, size_t index, int padding, int size, bool flipX, bool flipY, COLORREF colorFill) void ZoneWindow::DrawIndex(wil::unique_hdc& hdc, POINT offset, size_t index, int padding, int size, bool flipX, bool flipY, COLORREF colorFill)
@ -817,11 +823,15 @@ void ZoneWindow::DrawActiveZoneSet(wil::unique_hdc& hdc, RECT const& clientRect)
ColorSetting const colorFlash { 200, RGB(81, 92, 107), 200, RGB(104, 118, 138), -2 }; ColorSetting const colorFlash { 200, RGB(81, 92, 107), 200, RGB(104, 118, 138), -2 };
auto zones = m_activeZoneSet->GetZones(); auto zones = m_activeZoneSet->GetZones();
size_t colorIndex = zones.size() - 1; const size_t maxColorIndex = min(size(zones) - 1, size(colors) - 1);
size_t colorIndex = maxColorIndex;
for (auto iter = zones.rbegin(); iter != zones.rend(); iter++) for (auto iter = zones.rbegin(); iter != zones.rend(); iter++)
{ {
if (winrt::com_ptr<IZone> zone = iter->try_as<IZone>()) winrt::com_ptr<IZone> zone = iter->try_as<IZone>();
if (!zone)
{ {
continue;
}
if (zone != m_highlightZone) if (zone != m_highlightZone)
{ {
if (m_flashMode) if (m_flashMode)
@ -842,8 +852,7 @@ void ZoneWindow::DrawActiveZoneSet(wil::unique_hdc& hdc, RECT const& clientRect)
DrawZone(hdc, colorViewer, zone); DrawZone(hdc, colorViewer, zone);
} }
} }
colorIndex--; colorIndex = colorIndex != 0 ? colorIndex - 1 : maxColorIndex;
}
} }
if (m_highlightZone) if (m_highlightZone)
@ -930,7 +939,7 @@ void ZoneWindow::OnPaint(wil::unique_hdc& hdc) noexcept
RECT clientRect; RECT clientRect;
GetClientRect(m_window.get(), &clientRect); GetClientRect(m_window.get(), &clientRect);
wil::unique_hdc hdcMem;; wil::unique_hdc hdcMem;
HPAINTBUFFER bufferedPaint = BeginBufferedPaint(hdc.get(), &clientRect, BPBF_TOPDOWNDIB, nullptr, &hdcMem); HPAINTBUFFER bufferedPaint = BeginBufferedPaint(hdc.get(), &clientRect, BPBF_TOPDOWNDIB, nullptr, &hdcMem);
if (bufferedPaint) if (bufferedPaint)
{ {
@ -1284,7 +1293,7 @@ UINT ZoneWindow::GetDpiForMonitor() noexcept
} }
} }
return (dpi == 0) ? 96 : dpi; return (dpi == 0) ? DPIAware::DEFAULT_DPI : dpi;
} }
#pragma endregion #pragma endregion

View File

@ -18,7 +18,16 @@ namespace {
} }
} }
// Prevent system-wide input lagging while paused in the debugger
//#define DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED
void start_lowlevel_keyboard_hook() { void start_lowlevel_keyboard_hook() {
#if defined(_DEBUG) && defined(DISABLE_LOWLEVEL_KBHOOK_WHEN_DEBUGGED)
if(IsDebuggerPresent()) {
return;
}
#endif
if (!hook_handle) { if (!hook_handle) {
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, hook_proc, GetModuleHandle(NULL), NULL); hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, hook_proc, GetModuleHandle(NULL), NULL);
hook_handle_copy = hook_handle; hook_handle_copy = hook_handle;

View File

@ -8,6 +8,8 @@
#include "trace.h" #include "trace.h"
#include "general_settings.h" #include "general_settings.h"
#include <common/dpi_aware.h>
#if _DEBUG && _WIN64 #if _DEBUG && _WIN64
#include "unhandled_exception_handler.h" #include "unhandled_exception_handler.h"
#endif #endif
@ -32,6 +34,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
return 0; return 0;
} }
DPIAware::EnableDPIAwarenessForThisProcess();
#if _DEBUG && _WIN64 #if _DEBUG && _WIN64
//Global error handlers to diagnose errors. //Global error handlers to diagnose errors.
//We prefer this not not show any longer until there's a bug to diagnose. //We prefer this not not show any longer until there's a bug to diagnose.

View File

@ -67,7 +67,7 @@
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link> </Link>
<Manifest> <Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness> <EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest> </Manifest>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -92,7 +92,7 @@
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link> </Link>
<Manifest> <Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness> <EnableDpiAwareness>false</EnableDpiAwareness>
</Manifest> </Manifest>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@ -60,6 +60,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/Zm150 %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
<CustomBuildStep> <CustomBuildStep>
<Command> <Command>
@ -88,6 +89,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/Zm150 %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>