mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
[FancyZones] Responsive drawing (#7125)
* Made drawing zones not clog message processing * Fixed synchronization bugs * call BufferedPaintInit * Some refactoring, the animation is back * Rename a function * Align parameters
This commit is contained in:
@@ -16,6 +16,14 @@ std::future<void> OnThreadExecutor::submit(task_t task)
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnThreadExecutor::cancel()
|
||||||
|
{
|
||||||
|
std::lock_guard lock{ _task_mutex };
|
||||||
|
_task_queue = {};
|
||||||
|
_task_cv.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OnThreadExecutor::worker_thread()
|
void OnThreadExecutor::worker_thread()
|
||||||
{
|
{
|
||||||
while (!_shutdown_request)
|
while (!_shutdown_request)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
OnThreadExecutor();
|
OnThreadExecutor();
|
||||||
~OnThreadExecutor();
|
~OnThreadExecutor();
|
||||||
std::future<void> submit(task_t task);
|
std::future<void> submit(task_t task);
|
||||||
|
void cancel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void worker_thread();
|
void worker_thread();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include <common/common.h>
|
#include <common/common.h>
|
||||||
|
#include <common/on_thread_executor.h>
|
||||||
|
|
||||||
#include "FancyZonesData.h"
|
#include "FancyZonesData.h"
|
||||||
#include "FancyZonesDataTypes.h"
|
#include "FancyZonesDataTypes.h"
|
||||||
@@ -58,6 +59,56 @@ namespace ZoneWindowUtils
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PaintZoneWindow(HDC hdc,
|
||||||
|
HWND window,
|
||||||
|
bool hasActiveZoneSet,
|
||||||
|
COLORREF hostZoneColor,
|
||||||
|
COLORREF hostZoneBorderColor,
|
||||||
|
COLORREF hostZoneHighlightColor,
|
||||||
|
int hostZoneHighlightOpacity,
|
||||||
|
std::vector<winrt::com_ptr<IZone>> zones,
|
||||||
|
std::vector<size_t> highlightZone,
|
||||||
|
bool flashMode,
|
||||||
|
bool drawHints)
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
HDC oldHdc = hdc;
|
||||||
|
if (!hdc)
|
||||||
|
{
|
||||||
|
hdc = BeginPaint(window, &ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
RECT clientRect;
|
||||||
|
GetClientRect(window, &clientRect);
|
||||||
|
|
||||||
|
wil::unique_hdc hdcMem;
|
||||||
|
HPAINTBUFFER bufferedPaint = BeginBufferedPaint(hdc, &clientRect, BPBF_TOPDOWNDIB, nullptr, &hdcMem);
|
||||||
|
if (bufferedPaint)
|
||||||
|
{
|
||||||
|
ZoneWindowDrawing::DrawBackdrop(hdcMem, clientRect);
|
||||||
|
|
||||||
|
if (hasActiveZoneSet)
|
||||||
|
{
|
||||||
|
ZoneWindowDrawing::DrawActiveZoneSet(hdcMem,
|
||||||
|
hostZoneColor,
|
||||||
|
hostZoneBorderColor,
|
||||||
|
hostZoneHighlightColor,
|
||||||
|
hostZoneHighlightOpacity,
|
||||||
|
zones,
|
||||||
|
highlightZone,
|
||||||
|
flashMode,
|
||||||
|
drawHints);
|
||||||
|
}
|
||||||
|
|
||||||
|
EndBufferedPaint(bufferedPaint, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!oldHdc)
|
||||||
|
{
|
||||||
|
EndPaint(window, &ps);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ZoneWindow : public winrt::implements<ZoneWindow, IZoneWindow>
|
struct ZoneWindow : public winrt::implements<ZoneWindow, IZoneWindow>
|
||||||
@@ -106,7 +157,7 @@ private:
|
|||||||
void CalculateZoneSet() noexcept;
|
void CalculateZoneSet() noexcept;
|
||||||
void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept;
|
void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept;
|
||||||
LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept;
|
LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept;
|
||||||
void OnPaint(wil::unique_hdc& hdc) noexcept;
|
void OnPaint(HDC hdc) noexcept;
|
||||||
void OnKeyUp(WPARAM wparam) noexcept;
|
void OnKeyUp(WPARAM wparam) noexcept;
|
||||||
std::vector<size_t> ZonesFromPoint(POINT pt) noexcept;
|
std::vector<size_t> ZonesFromPoint(POINT pt) noexcept;
|
||||||
void CycleActiveZoneSetInternal(DWORD wparam, Trace::ZoneWindow::InputMode mode) noexcept;
|
void CycleActiveZoneSetInternal(DWORD wparam, Trace::ZoneWindow::InputMode mode) noexcept;
|
||||||
@@ -128,6 +179,8 @@ private:
|
|||||||
static const UINT m_showAnimationDuration = 200; // ms
|
static const UINT m_showAnimationDuration = 200; // ms
|
||||||
static const UINT m_flashDuration = 700; // ms
|
static const UINT m_flashDuration = 700; // ms
|
||||||
|
|
||||||
|
std::atomic<bool> m_animating;
|
||||||
|
OnThreadExecutor m_paintExecutor;
|
||||||
ULONG_PTR gdiplusToken;
|
ULONG_PTR gdiplusToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,11 +196,13 @@ ZoneWindow::ZoneWindow(HINSTANCE hinstance)
|
|||||||
|
|
||||||
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
|
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
|
||||||
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
||||||
|
m_paintExecutor.submit(OnThreadExecutor::task_t{ []() { BufferedPaintInit(); } });
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneWindow::~ZoneWindow()
|
ZoneWindow::~ZoneWindow()
|
||||||
{
|
{
|
||||||
Gdiplus::GdiplusShutdown(gdiplusToken);
|
Gdiplus::GdiplusShutdown(gdiplusToken);
|
||||||
|
m_paintExecutor.submit(OnThreadExecutor::task_t{ []() { BufferedPaintUnInit(); } });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, const std::wstring& parentUniqueId, bool flashZones)
|
bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor, const std::wstring& uniqueId, const std::wstring& parentUniqueId, bool flashZones)
|
||||||
@@ -400,6 +455,7 @@ ZoneWindow::ShowZoneWindow() noexcept
|
|||||||
SetWindowPos(window, windowInsertAfter, 0, 0, 0, 0, flags);
|
SetWindowPos(window, windowInsertAfter, 0, 0, 0, 0, flags);
|
||||||
|
|
||||||
std::thread{ [this, strong_this{ get_strong() }]() {
|
std::thread{ [this, strong_this{ get_strong() }]() {
|
||||||
|
m_animating = true;
|
||||||
auto window = m_window.get();
|
auto window = m_window.get();
|
||||||
AnimateWindow(window, m_showAnimationDuration, AW_BLEND);
|
AnimateWindow(window, m_showAnimationDuration, AW_BLEND);
|
||||||
InvalidateRect(window, nullptr, true);
|
InvalidateRect(window, nullptr, true);
|
||||||
@@ -407,6 +463,7 @@ ZoneWindow::ShowZoneWindow() noexcept
|
|||||||
{
|
{
|
||||||
HideZoneWindow();
|
HideZoneWindow();
|
||||||
}
|
}
|
||||||
|
m_animating = false;
|
||||||
} }.detach();
|
} }.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,23 +598,13 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case WM_PRINTCLIENT:
|
case WM_PRINTCLIENT:
|
||||||
|
{
|
||||||
|
OnPaint(reinterpret_cast<HDC>(wparam));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
{
|
{
|
||||||
PAINTSTRUCT ps;
|
OnPaint(NULL);
|
||||||
wil::unique_hdc hdc{ reinterpret_cast<HDC>(wparam) };
|
|
||||||
if (!hdc)
|
|
||||||
{
|
|
||||||
hdc.reset(BeginPaint(m_window.get(), &ps));
|
|
||||||
}
|
|
||||||
|
|
||||||
OnPaint(hdc);
|
|
||||||
|
|
||||||
if (wparam == 0)
|
|
||||||
{
|
|
||||||
EndPaint(m_window.get(), &ps);
|
|
||||||
}
|
|
||||||
|
|
||||||
hdc.release();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -569,31 +616,51 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneWindow::OnPaint(wil::unique_hdc& hdc) noexcept
|
void ZoneWindow::OnPaint(HDC hdc) noexcept
|
||||||
{
|
{
|
||||||
RECT clientRect;
|
HWND window = m_window.get();
|
||||||
GetClientRect(m_window.get(), &clientRect);
|
bool hasActiveZoneSet = m_activeZoneSet && m_host;
|
||||||
|
COLORREF hostZoneColor{};
|
||||||
|
COLORREF hostZoneBorderColor{};
|
||||||
|
COLORREF hostZoneHighlightColor{};
|
||||||
|
int hostZoneHighlightOpacity{};
|
||||||
|
std::vector<winrt::com_ptr<IZone>> zones{};
|
||||||
|
std::vector<size_t> highlightZone = m_highlightZone;
|
||||||
|
bool flashMode = m_flashMode;
|
||||||
|
bool drawHints = m_drawHints;
|
||||||
|
|
||||||
wil::unique_hdc hdcMem;
|
if (hasActiveZoneSet)
|
||||||
HPAINTBUFFER bufferedPaint = BeginBufferedPaint(hdc.get(), &clientRect, BPBF_TOPDOWNDIB, nullptr, &hdcMem);
|
|
||||||
if (bufferedPaint)
|
|
||||||
{
|
{
|
||||||
ZoneWindowDrawing::DrawBackdrop(hdcMem, clientRect);
|
hostZoneColor = m_host->GetZoneColor();
|
||||||
|
hostZoneBorderColor = m_host->GetZoneBorderColor();
|
||||||
|
hostZoneHighlightColor = m_host->GetZoneHighlightColor();
|
||||||
|
hostZoneHighlightOpacity = m_host->GetZoneHighlightOpacity();
|
||||||
|
zones = m_activeZoneSet->GetZones();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_activeZoneSet && m_host)
|
OnThreadExecutor::task_t task{
|
||||||
{
|
[=]() {
|
||||||
ZoneWindowDrawing::DrawActiveZoneSet(hdcMem,
|
ZoneWindowUtils::PaintZoneWindow(hdc,
|
||||||
m_host->GetZoneColor(),
|
window,
|
||||||
m_host->GetZoneBorderColor(),
|
hasActiveZoneSet,
|
||||||
m_host->GetZoneHighlightColor(),
|
hostZoneColor,
|
||||||
m_host->GetZoneHighlightOpacity(),
|
hostZoneBorderColor,
|
||||||
m_activeZoneSet->GetZones(),
|
hostZoneHighlightColor,
|
||||||
m_highlightZone,
|
hostZoneHighlightOpacity,
|
||||||
m_flashMode,
|
zones,
|
||||||
m_drawHints);
|
highlightZone,
|
||||||
}
|
flashMode,
|
||||||
|
drawHints);
|
||||||
|
} };
|
||||||
|
|
||||||
EndBufferedPaint(bufferedPaint, TRUE);
|
if (m_animating)
|
||||||
|
{
|
||||||
|
task();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_paintExecutor.cancel();
|
||||||
|
m_paintExecutor.submit(std::move(task));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user