Formatting chores (#1441)

* format_sources: exclude 3rd party sources

* format common project

* format leftovers in runner & settings projects

* move source formatting-related files according to #939
This commit is contained in:
Andrey Nekrasov
2020-03-05 13:07:06 +03:00
committed by GitHub
parent 92f64188d5
commit cf1b53831f
42 changed files with 2602 additions and 2220 deletions

View File

@@ -20,7 +20,9 @@ $sourceExtensions.Add(".cpp") | Out-Null
$sourceExtensions.Add(".h") | Out-Null $sourceExtensions.Add(".h") | Out-Null
function Get-Dirty-Files-From-Git() { function Get-Dirty-Files-From-Git() {
$staged = & git diff --name-only --diff-filter=d --cached $repo_root = & git rev-parse --show-toplevel
$staged = & git diff --name-only --diff-filter=d --cached | % { $repo_root + "/" + $_ }
$unstaged = & git ls-files -m $unstaged = & git ls-files -m
$untracked = & git ls-files --others --exclude-standard $untracked = & git ls-files --others --exclude-standard
$result = New-Object System.Collections.Generic.List[string] $result = New-Object System.Collections.Generic.List[string]
@@ -34,9 +36,10 @@ function Get-Dirty-Files-From-Git() {
if($all) { if($all) {
$filesToFormat = $filesToFormat =
Get-ChildItem -Recurse -File src | Get-ChildItem -Recurse -File ..\src |
Resolve-Path -Relative | Resolve-Path -Relative |
where {$sourceExtensions.Contains((Get-Item $_).Extension)} where { (Get-Item $_).Directory -notmatch "(Generated Files)|node_modules" -And
$sourceExtensions.Contains((Get-Item $_).Extension)}
} }
else { else {
$filesToFormat = Get-Dirty-Files-From-Git $filesToFormat = Get-Dirty-Files-From-Git

View File

@@ -65,7 +65,8 @@ IndentPPDirectives: None
IndentWidth: 4 IndentWidth: 4
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: "BEGIN_TEST_METHOD_PROPERTIES|BEGIN_MODULE|BEGIN_TEST_CLASS|BEGIN_TEST_METHOD" ForEachMacros: ['TEST_CLASS', 'TEST_METHOD']
MacroBlockBegin: "TEST_METHOD|TEST_CLASS|BEGIN_TEST_METHOD_PROPERTIES|BEGIN_MODULE|BEGIN_TEST_CLASS|BEGIN_TEST_METHOD"
MacroBlockEnd: "END_TEST_METHOD_PROPERTIES|END_MODULE|END_TEST_CLASS|END_TEST_METHOD" MacroBlockEnd: "END_TEST_METHOD_PROPERTIES|END_MODULE|END_TEST_CLASS|END_TEST_METHOD"
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: All NamespaceIndentation: All

View File

@@ -34,7 +34,6 @@ namespace UnitTestsVersionHelper
} }
TEST_METHOD (stringConstructorShouldProprelyInitializateVersionNumbers) TEST_METHOD (stringConstructorShouldProprelyInitializateVersionNumbers)
{ {
VersionHelper sut("v0.12.3"); VersionHelper sut("v0.12.3");
Assert::AreEqual(0, sut.major); Assert::AreEqual(0, sut.major);

View File

@@ -4,25 +4,31 @@
Animation::Animation(double duration, double start, double stop) : Animation::Animation(double duration, double start, double stop) :
duration(duration), start_value(start), end_value(stop), start(std::chrono::high_resolution_clock::now()) {} duration(duration), start_value(start), end_value(stop), start(std::chrono::high_resolution_clock::now()) {}
void Animation::reset() { void Animation::reset()
{
start = std::chrono::high_resolution_clock::now(); start = std::chrono::high_resolution_clock::now();
} }
void Animation::reset(double duration) { void Animation::reset(double duration)
{
this->duration = duration; this->duration = duration;
reset(); reset();
} }
void Animation::reset(double duration, double start, double stop) { void Animation::reset(double duration, double start, double stop)
{
start_value = start; start_value = start;
end_value = stop; end_value = stop;
reset(duration); reset(duration);
} }
static double ease_out_expo(double t) { static double ease_out_expo(double t)
{
return 1 - pow(2, -8 * t); return 1 - pow(2, -8 * t);
} }
double Animation::apply_animation_function(double t, AnimFunctions apply_function) { double Animation::apply_animation_function(double t, AnimFunctions apply_function)
switch (apply_function) { {
switch (apply_function)
{
case EASE_OUT_EXPO: case EASE_OUT_EXPO:
return ease_out_expo(t); return ease_out_expo(t);
case LINEAR: case LINEAR:
@@ -31,13 +37,15 @@ double Animation::apply_animation_function(double t, AnimFunctions apply_functio
} }
} }
double Animation::value(AnimFunctions apply_function) const { double Animation::value(AnimFunctions apply_function) const
{
auto anim_duration = std::chrono::high_resolution_clock::now() - start; auto anim_duration = std::chrono::high_resolution_clock::now() - start;
double t = std::chrono::duration<double>(anim_duration).count() / duration; double t = std::chrono::duration<double>(anim_duration).count() / duration;
if (t >= 1) if (t >= 1)
return end_value; return end_value;
return start_value + (end_value - start_value) * apply_animation_function(t, apply_function); return start_value + (end_value - start_value) * apply_animation_function(t, apply_function);
} }
bool Animation::done() const { bool Animation::done() const
{
return std::chrono::high_resolution_clock::now() - start >= std::chrono::duration<double>(duration); return std::chrono::high_resolution_clock::now() - start >= std::chrono::duration<double>(duration);
} }

View File

@@ -11,9 +11,11 @@
When redering, call value() to get value from 0 to 1 - depending on animation When redering, call value() to get value from 0 to 1 - depending on animation
progress. progress.
*/ */
class Animation { class Animation
{
public: public:
enum AnimFunctions { enum AnimFunctions
{
LINEAR = 0, LINEAR = 0,
EASE_OUT_EXPO EASE_OUT_EXPO
}; };
@@ -24,6 +26,7 @@ public:
void reset(double duration, double start, double stop); void reset(double duration, double start, double stop);
double value(AnimFunctions apply_function) const; double value(AnimFunctions apply_function) const;
bool done() const; bool done() const;
private: private:
static double apply_animation_function(double t, AnimFunctions apply_function); static double apply_animation_function(double t, AnimFunctions apply_function);
std::chrono::high_resolution_clock::time_point start; std::chrono::high_resolution_clock::time_point start;

View File

@@ -5,7 +5,8 @@
#include <condition_variable> #include <condition_variable>
#include <string> #include <string>
class AsyncMessageQueue { class AsyncMessageQueue
{
private: private:
std::mutex queue_mutex; std::mutex queue_mutex;
std::queue<std::wstring> message_queue; std::queue<std::wstring> message_queue;
@@ -17,20 +18,25 @@ private:
AsyncMessageQueue& operator=(const AsyncMessageQueue&); AsyncMessageQueue& operator=(const AsyncMessageQueue&);
public: public:
AsyncMessageQueue() { AsyncMessageQueue()
{
} }
void queue_message(std::wstring message) { void queue_message(std::wstring message)
{
this->queue_mutex.lock(); this->queue_mutex.lock();
this->message_queue.push(message); this->message_queue.push(message);
this->queue_mutex.unlock(); this->queue_mutex.unlock();
this->message_ready.notify_one(); this->message_ready.notify_one();
} }
std::wstring pop_message() { std::wstring pop_message()
{
std::unique_lock<std::mutex> lock(this->queue_mutex); std::unique_lock<std::mutex> lock(this->queue_mutex);
while (message_queue.empty() && !this->interrupted) { while (message_queue.empty() && !this->interrupted)
{
this->message_ready.wait(lock); this->message_ready.wait(lock);
} }
if (this->interrupted) { if (this->interrupted)
{
//Just returns a empty string if the queue was interrupted. //Just returns a empty string if the queue was interrupted.
return std::wstring(L""); return std::wstring(L"");
} }
@@ -38,7 +44,8 @@ public:
this->message_queue.pop(); this->message_queue.pop();
return message; return message;
} }
void interrupt() { void interrupt()
{
this->queue_mutex.lock(); this->queue_mutex.lock();
this->interrupted = true; this->interrupted = true;
this->queue_mutex.unlock(); this->queue_mutex.unlock();

View File

@@ -14,29 +14,41 @@ namespace localized_strings
const wchar_t LAST_ERROR_TITLE_STRING[] = L"Error"; const wchar_t LAST_ERROR_TITLE_STRING[] = L"Error";
} }
std::optional<RECT> get_button_pos(HWND hwnd) { std::optional<RECT> get_button_pos(HWND hwnd)
{
RECT button; RECT button;
if (DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, &button, sizeof(RECT)) == S_OK) { if (DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, &button, sizeof(RECT)) == S_OK)
{
return button; return button;
} else { }
else
{
return {}; return {};
} }
} }
std::optional<RECT> get_window_pos(HWND hwnd) { std::optional<RECT> get_window_pos(HWND hwnd)
{
RECT window; RECT window;
if (DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &window, sizeof(window)) == S_OK) { if (DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &window, sizeof(window)) == S_OK)
{
return window; return window;
} else { }
else
{
return {}; return {};
} }
} }
std::optional<POINT> get_mouse_pos() { std::optional<POINT> get_mouse_pos()
{
POINT point; POINT point;
if (GetCursorPos(&point) == 0) { if (GetCursorPos(&point) == 0)
{
return {}; return {};
} else { }
else
{
return point; return point;
} }
} }
@@ -45,16 +57,21 @@ std::optional<POINT> get_mouse_pos() {
// We compare the HWND against HWND of the desktop and shell windows, // We compare the HWND against HWND of the desktop and shell windows,
// we also filter out some window class names know to belong to // we also filter out some window class names know to belong to
// the taskbar. // the taskbar.
static bool is_system_window(HWND hwnd, const char* class_name) { static bool is_system_window(HWND hwnd, const char* class_name)
{
static auto system_classes = { "SysListView32", "WorkerW", "Shell_TrayWnd", "Shell_SecondaryTrayWnd", "Progman" }; static auto system_classes = { "SysListView32", "WorkerW", "Shell_TrayWnd", "Shell_SecondaryTrayWnd", "Progman" };
static auto system_hwnds = { GetDesktopWindow(), GetShellWindow() }; static auto system_hwnds = { GetDesktopWindow(), GetShellWindow() };
for (auto system_hwnd : system_hwnds) { for (auto system_hwnd : system_hwnds)
if (hwnd == system_hwnd) { {
if (hwnd == system_hwnd)
{
return true; return true;
} }
} }
for (const auto& system_class : system_classes) { for (const auto& system_class : system_classes)
if (strcmp(system_class, class_name) == 0) { {
if (strcmp(system_class, class_name) == 0)
{
return true; return true;
} }
} }
@@ -64,14 +81,17 @@ static bool is_system_window(HWND hwnd, const char* class_name) {
static bool no_visible_owner(HWND window) noexcept static bool no_visible_owner(HWND window) noexcept
{ {
auto owner = GetWindow(window, GW_OWNER); auto owner = GetWindow(window, GW_OWNER);
if (owner == nullptr) { if (owner == nullptr)
{
return true; // There is no owner at all return true; // There is no owner at all
} }
if (!IsWindowVisible(owner)) { if (!IsWindowVisible(owner))
{
return true; // Owner is invisible return true; // Owner is invisible
} }
RECT rect; RECT rect;
if (!GetWindowRect(owner, &rect)) { if (!GetWindowRect(owner, &rect))
{
return false; // Could not get the rect, return true (and filter out the window) just in case return false; // Could not get the rect, return true (and filter out the window) just in case
} }
// Return false (and allow the window to be zonable) if the owner window size is zero // Return false (and allow the window to be zonable) if the owner window size is zero
@@ -79,9 +99,11 @@ static bool no_visible_owner(HWND window) noexcept
return rect.top == rect.bottom || rect.left == rect.right; return rect.top == rect.bottom || rect.left == rect.right;
} }
FancyZonesFilter get_fancyzones_filtered_window(HWND window) { FancyZonesFilter get_fancyzones_filtered_window(HWND window)
{
FancyZonesFilter result; FancyZonesFilter result;
if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window)) { if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window))
{
return result; return result;
} }
auto style = GetWindowLong(window, GWL_STYLE); auto style = GetWindowLong(window, GWL_STYLE);
@@ -91,24 +113,28 @@ FancyZonesFilter get_fancyzones_filtered_window(HWND window) {
if ((style & WS_POPUP) == WS_POPUP && if ((style & WS_POPUP) == WS_POPUP &&
(style & WS_THICKFRAME) == 0 && (style & WS_THICKFRAME) == 0 &&
(style & WS_MINIMIZEBOX) == 0 && (style & WS_MINIMIZEBOX) == 0 &&
(style & WS_MAXIMIZEBOX) == 0) { (style & WS_MAXIMIZEBOX) == 0)
{
return result; return result;
} }
if ((style & WS_CHILD) == WS_CHILD || if ((style & WS_CHILD) == WS_CHILD ||
(style & WS_DISABLED) == WS_DISABLED || (style & WS_DISABLED) == WS_DISABLED ||
(exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW ||
(exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) { (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE)
{
return result; return result;
} }
std::array<char, 256> class_name; std::array<char, 256> class_name;
GetClassNameA(window, class_name.data(), static_cast<int>(class_name.size())); GetClassNameA(window, class_name.data(), static_cast<int>(class_name.size()));
if (is_system_window(window, class_name.data())) { if (is_system_window(window, class_name.data()))
{
return result; return result;
} }
auto process_path = get_process_path(window); auto process_path = get_process_path(window);
// Check for Cortana: // Check for Cortana:
if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 && if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 &&
process_path.ends_with(L"SearchUI.exe")) { process_path.ends_with(L"SearchUI.exe"))
{
return result; return result;
} }
result.process_path = std::move(process_path); result.process_path = std::move(process_path);
@@ -118,11 +144,13 @@ FancyZonesFilter get_fancyzones_filtered_window(HWND window) {
return result; return result;
} }
ShortcutGuideFilter get_shortcutguide_filtered_window() { ShortcutGuideFilter get_shortcutguide_filtered_window()
{
ShortcutGuideFilter result; ShortcutGuideFilter result;
auto active_window = GetForegroundWindow(); auto active_window = GetForegroundWindow();
active_window = GetAncestor(active_window, GA_ROOT); active_window = GetAncestor(active_window, GA_ROOT);
if (!IsWindowVisible(active_window)) { if (!IsWindowVisible(active_window))
{
return result; return result;
} }
auto style = GetWindowLong(active_window, GWL_STYLE); auto style = GetWindowLong(active_window, GWL_STYLE);
@@ -130,22 +158,28 @@ ShortcutGuideFilter get_shortcutguide_filtered_window() {
if ((style & WS_CHILD) == WS_CHILD || if ((style & WS_CHILD) == WS_CHILD ||
(style & WS_DISABLED) == WS_DISABLED || (style & WS_DISABLED) == WS_DISABLED ||
(exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW ||
(exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) { (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE)
{
return result; return result;
} }
std::array<char, 256> class_name; std::array<char, 256> class_name;
GetClassNameA(active_window, class_name.data(), static_cast<int>(class_name.size())); GetClassNameA(active_window, class_name.data(), static_cast<int>(class_name.size()));
if (is_system_window(active_window, class_name.data())) { if (is_system_window(active_window, class_name.data()))
{
return result; return result;
} }
static HWND cortanda_hwnd = nullptr; static HWND cortanda_hwnd = nullptr;
if (cortanda_hwnd == nullptr) { if (cortanda_hwnd == nullptr)
{
if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 && if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 &&
get_process_path(active_window).ends_with(L"SearchUI.exe")) { get_process_path(active_window).ends_with(L"SearchUI.exe"))
{
cortanda_hwnd = active_window; cortanda_hwnd = active_window;
return result; return result;
} }
} else if (cortanda_hwnd == active_window) { }
else if (cortanda_hwnd == active_window)
{
return result; return result;
} }
result.hwnd = active_window; result.hwnd = active_window;
@@ -163,52 +197,66 @@ ShortcutGuideFilter get_shortcutguide_filtered_window() {
return result; return result;
} }
int width(const RECT& rect) { int width(const RECT& rect)
{
return rect.right - rect.left; return rect.right - rect.left;
} }
int height(const RECT& rect) { int height(const RECT& rect)
{
return rect.bottom - rect.top; return rect.bottom - rect.top;
} }
bool operator<(const RECT& lhs, const RECT& rhs) { bool operator<(const RECT& lhs, const RECT& rhs)
{
auto lhs_tuple = std::make_tuple(lhs.left, lhs.right, lhs.top, lhs.bottom); auto lhs_tuple = std::make_tuple(lhs.left, lhs.right, lhs.top, lhs.bottom);
auto rhs_tuple = std::make_tuple(rhs.left, rhs.right, rhs.top, rhs.bottom); auto rhs_tuple = std::make_tuple(rhs.left, rhs.right, rhs.top, rhs.bottom);
return lhs_tuple < rhs_tuple; return lhs_tuple < rhs_tuple;
} }
RECT keep_rect_inside_rect(const RECT& small_rect, const RECT& big_rect) { RECT keep_rect_inside_rect(const RECT& small_rect, const RECT& big_rect)
{
RECT result = small_rect; RECT result = small_rect;
if ((result.right - result.left) > (big_rect.right - big_rect.left)) { if ((result.right - result.left) > (big_rect.right - big_rect.left))
{
// small_rect is too big horizontally. resize it. // small_rect is too big horizontally. resize it.
result.right = big_rect.right; result.right = big_rect.right;
result.left = big_rect.left; result.left = big_rect.left;
} else { }
if (result.right > big_rect.right) { else
{
if (result.right > big_rect.right)
{
// move the rect left. // move the rect left.
result.left -= result.right - big_rect.right; result.left -= result.right - big_rect.right;
result.right -= result.right - big_rect.right; result.right -= result.right - big_rect.right;
} }
if (result.left < big_rect.left) { if (result.left < big_rect.left)
{
// move the rect right. // move the rect right.
result.right += big_rect.left - result.left; result.right += big_rect.left - result.left;
result.left += big_rect.left - result.left; result.left += big_rect.left - result.left;
} }
} }
if ((result.bottom - result.top) > (big_rect.bottom - big_rect.top)) { if ((result.bottom - result.top) > (big_rect.bottom - big_rect.top))
{
// small_rect is too big vertically. resize it. // small_rect is too big vertically. resize it.
result.bottom = big_rect.bottom; result.bottom = big_rect.bottom;
result.top = big_rect.top; result.top = big_rect.top;
} else { }
if (result.bottom > big_rect.bottom) { else
{
if (result.bottom > big_rect.bottom)
{
// move the rect up. // move the rect up.
result.top -= result.bottom - big_rect.bottom; result.top -= result.bottom - big_rect.bottom;
result.bottom -= result.bottom - big_rect.bottom; result.bottom -= result.bottom - big_rect.bottom;
} }
if (result.top < big_rect.top) { if (result.top < big_rect.top)
{
// move the rect down. // move the rect down.
result.bottom += big_rect.top - result.top; result.bottom += big_rect.top - result.top;
result.top += big_rect.top - result.top; result.top += big_rect.top - result.top;
@@ -217,61 +265,75 @@ RECT keep_rect_inside_rect(const RECT& small_rect, const RECT& big_rect) {
return result; return result;
} }
int run_message_loop() { int run_message_loop()
{
MSG msg; MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) { while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} }
return static_cast<int>(msg.wParam); return static_cast<int>(msg.wParam);
} }
std::optional<std::wstring> get_last_error_message(const DWORD dw) { std::optional<std::wstring> get_last_error_message(const DWORD dw)
{
std::optional<std::wstring> message; std::optional<std::wstring> message;
try { try
{
const auto msg = std::system_category().message(dw); const auto msg = std::system_category().message(dw);
message.emplace(begin(msg), end(msg)); message.emplace(begin(msg), end(msg));
} }
catch(...) { catch (...)
{
} }
return message; return message;
} }
void show_last_error_message(LPCWSTR lpszFunction, DWORD dw) { void show_last_error_message(LPCWSTR lpszFunction, DWORD dw)
{
const auto system_message = get_last_error_message(dw); const auto system_message = get_last_error_message(dw);
if(!system_message.has_value()) { if (!system_message.has_value())
{
return; return;
} }
LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(lpszFunction) + 40) * sizeof(WCHAR)); LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(lpszFunction) + 40) * sizeof(WCHAR));
if (lpDisplayBuf != NULL) { if (lpDisplayBuf != NULL)
{
StringCchPrintfW(lpDisplayBuf, StringCchPrintfW(lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(WCHAR), LocalSize(lpDisplayBuf) / sizeof(WCHAR),
localized_strings::LAST_ERROR_FORMAT_STRING, localized_strings::LAST_ERROR_FORMAT_STRING,
lpszFunction, dw, system_message->c_str()); lpszFunction,
dw,
system_message->c_str());
MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, localized_strings::LAST_ERROR_TITLE_STRING, MB_OK); MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, localized_strings::LAST_ERROR_TITLE_STRING, MB_OK);
LocalFree(lpDisplayBuf); LocalFree(lpDisplayBuf);
} }
} }
WindowState get_window_state(HWND hwnd) { WindowState get_window_state(HWND hwnd)
{
WINDOWPLACEMENT placement; WINDOWPLACEMENT placement;
placement.length = sizeof(WINDOWPLACEMENT); placement.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(hwnd, &placement) == 0) { if (GetWindowPlacement(hwnd, &placement) == 0)
{
return UNKNONW; return UNKNONW;
} }
if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_SHOWMINIMIZED || IsIconic(hwnd)) { if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_SHOWMINIMIZED || IsIconic(hwnd))
{
return MINIMIZED; return MINIMIZED;
} }
if (placement.showCmd == SW_MAXIMIZE || placement.showCmd == SW_SHOWMAXIMIZED) { if (placement.showCmd == SW_MAXIMIZE || placement.showCmd == SW_SHOWMAXIMIZED)
{
return MAXIMIZED; return MAXIMIZED;
} }
auto rectp = get_window_pos(hwnd); auto rectp = get_window_pos(hwnd);
if (!rectp) { if (!rectp)
{
return UNKNONW; return UNKNONW;
} }
@@ -285,44 +347,57 @@ WindowState get_window_state(HWND hwnd) {
bool top_right = monitor.rcWork.top == rect.top && monitor.rcWork.right == rect.right; bool top_right = monitor.rcWork.top == rect.top && monitor.rcWork.right == rect.right;
bool bottom_right = monitor.rcWork.bottom == rect.bottom && monitor.rcWork.right == rect.right; bool bottom_right = monitor.rcWork.bottom == rect.bottom && monitor.rcWork.right == rect.right;
if (top_left && bottom_left) return SNAPED_LEFT; if (top_left && bottom_left)
if (top_left) return SNAPED_TOP_LEFT; return SNAPED_LEFT;
if (bottom_left) return SNAPED_BOTTOM_LEFT; if (top_left)
if (top_right && bottom_right) return SNAPED_RIGHT; return SNAPED_TOP_LEFT;
if (top_right) return SNAPED_TOP_RIGHT; if (bottom_left)
if (bottom_right) return SNAPED_BOTTOM_RIGHT; return SNAPED_BOTTOM_LEFT;
if (top_right && bottom_right)
return SNAPED_RIGHT;
if (top_right)
return SNAPED_TOP_RIGHT;
if (bottom_right)
return SNAPED_BOTTOM_RIGHT;
return RESTORED; return RESTORED;
} }
bool is_process_elevated() { bool is_process_elevated()
{
HANDLE token = nullptr; HANDLE token = nullptr;
bool elevated = false; bool elevated = false;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
{
TOKEN_ELEVATION elevation; TOKEN_ELEVATION elevation;
DWORD size; DWORD size;
if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) { if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size))
{
elevated = (elevation.TokenIsElevated != 0); elevated = (elevation.TokenIsElevated != 0);
} }
} }
if (token) { if (token)
{
CloseHandle(token); CloseHandle(token);
} }
return elevated; return elevated;
} }
bool drop_elevated_privileges() { bool drop_elevated_privileges()
{
HANDLE token = nullptr; HANDLE token = nullptr;
LPCTSTR lpszPrivilege = SE_SECURITY_NAME; LPCTSTR lpszPrivilege = SE_SECURITY_NAME;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token)) { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token))
{
return false; return false;
} }
PSID medium_sid = NULL; PSID medium_sid = NULL;
if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) { if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid))
{
return false; return false;
} }
@@ -338,13 +413,16 @@ bool drop_elevated_privileges() {
return result; return result;
} }
std::wstring get_process_path(DWORD pid) noexcept { std::wstring get_process_path(DWORD pid) noexcept
{
auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid); auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid);
std::wstring name; std::wstring name;
if (process != INVALID_HANDLE_VALUE) { if (process != INVALID_HANDLE_VALUE)
{
name.resize(MAX_PATH); name.resize(MAX_PATH);
DWORD name_length = static_cast<DWORD>(name.length()); DWORD name_length = static_cast<DWORD>(name.length());
if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0) { if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0)
{
name_length = 0; name_length = 0;
} }
name.resize(name_length); name.resize(name_length);
@@ -353,7 +431,8 @@ std::wstring get_process_path(DWORD pid) noexcept {
return name; return name;
} }
bool run_elevated(const std::wstring& file, const std::wstring& params) { bool run_elevated(const std::wstring& file, const std::wstring& params)
{
SHELLEXECUTEINFOW exec_info = { 0 }; SHELLEXECUTEINFOW exec_info = { 0 };
exec_info.cbSize = sizeof(SHELLEXECUTEINFOW); exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
exec_info.lpVerb = L"runas"; exec_info.lpVerb = L"runas";
@@ -364,28 +443,35 @@ bool run_elevated(const std::wstring& file, const std::wstring& params) {
exec_info.lpDirectory = 0; exec_info.lpDirectory = 0;
exec_info.hInstApp = 0; exec_info.hInstApp = 0;
if (ShellExecuteExW(&exec_info)) { if (ShellExecuteExW(&exec_info))
{
return exec_info.hProcess != nullptr; return exec_info.hProcess != nullptr;
} else { }
else
{
return false; return false;
} }
} }
bool run_non_elevated(const std::wstring& file, const std::wstring& params) { bool run_non_elevated(const std::wstring& file, const std::wstring& params)
{
auto executable_args = L"\"" + file + L"\""; auto executable_args = L"\"" + file + L"\"";
if (!params.empty()) { if (!params.empty())
{
executable_args += L" " + params; executable_args += L" " + params;
} }
HWND hwnd = GetShellWindow(); HWND hwnd = GetShellWindow();
if (!hwnd) { if (!hwnd)
{
return false; return false;
} }
DWORD pid; DWORD pid;
GetWindowThreadProcessId(hwnd, &pid); GetWindowThreadProcessId(hwnd, &pid);
winrt::handle process{ OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pid) }; winrt::handle process{ OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pid) };
if (!process) { if (!process)
{
return false; return false;
} }
@@ -395,7 +481,8 @@ bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
auto pproc_buffer = std::make_unique<char[]>(size); auto pproc_buffer = std::make_unique<char[]>(size);
auto pptal = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(pproc_buffer.get()); auto pptal = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(pproc_buffer.get());
if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size)) { if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size))
{
return false; return false;
} }
@@ -406,7 +493,8 @@ bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
&process_handle, &process_handle,
sizeof(process_handle), sizeof(process_handle),
nullptr, nullptr,
nullptr)) { nullptr))
{
return false; return false;
} }
@@ -425,18 +513,22 @@ bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
nullptr, nullptr,
&siex.StartupInfo, &siex.StartupInfo,
&process_info); &process_info);
if (process_info.hProcess) { if (process_info.hProcess)
{
CloseHandle(process_info.hProcess); CloseHandle(process_info.hProcess);
} }
if (process_info.hThread) { if (process_info.hThread)
{
CloseHandle(process_info.hThread); CloseHandle(process_info.hThread);
} }
return succedded; return succedded;
} }
bool run_same_elevation(const std::wstring& file, const std::wstring& params) { bool run_same_elevation(const std::wstring& file, const std::wstring& params)
{
auto executable_args = L"\"" + file + L"\""; auto executable_args = L"\"" + file + L"\"";
if (!params.empty()) { if (!params.empty())
{
executable_args += L" " + params; executable_args += L" " + params;
} }
STARTUPINFO si = { 0 }; STARTUPINFO si = { 0 };
@@ -451,46 +543,56 @@ bool run_same_elevation(const std::wstring& file, const std::wstring& params) {
nullptr, nullptr,
&si, &si,
&pi); &pi);
if (pi.hProcess) { if (pi.hProcess)
{
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
} }
if (pi.hThread) { if (pi.hThread)
{
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
} }
return succedded; return succedded;
} }
std::wstring get_process_path(HWND window) noexcept
std::wstring get_process_path(HWND window) noexcept { {
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe"; const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
DWORD pid{}; DWORD pid{};
GetWindowThreadProcessId(window, &pid); GetWindowThreadProcessId(window, &pid);
auto name = get_process_path(pid); auto name = get_process_path(pid);
if (name.length() >= app_frame_host.length() && if (name.length() >= app_frame_host.length() &&
name.compare(name.length() - app_frame_host.length(), app_frame_host.length(), app_frame_host) == 0) { name.compare(name.length() - app_frame_host.length(), app_frame_host.length(), app_frame_host) == 0)
{
// It is a UWP app. We will enumarate the windows and look for one created // It is a UWP app. We will enumarate the windows and look for one created
// by something with a different PID // by something with a different PID
DWORD new_pid = pid; DWORD new_pid = pid;
EnumChildWindows(window, [](HWND hwnd, LPARAM param) -> BOOL { EnumChildWindows(
window, [](HWND hwnd, LPARAM param) -> BOOL {
auto new_pid_ptr = reinterpret_cast<DWORD*>(param); auto new_pid_ptr = reinterpret_cast<DWORD*>(param);
DWORD pid; DWORD pid;
GetWindowThreadProcessId(hwnd, &pid); GetWindowThreadProcessId(hwnd, &pid);
if (pid != *new_pid_ptr) { if (pid != *new_pid_ptr)
{
*new_pid_ptr = pid; *new_pid_ptr = pid;
return FALSE; return FALSE;
} else { }
else
{
return TRUE; return TRUE;
} }
}, reinterpret_cast<LPARAM>(&new_pid)); },
reinterpret_cast<LPARAM>(&new_pid));
// If we have a new pid, get the new name. // If we have a new pid, get the new name.
if (new_pid != pid) { if (new_pid != pid)
{
return get_process_path(new_pid); return get_process_path(new_pid);
} }
} }
return name; return name;
} }
std::wstring get_product_version() { std::wstring get_product_version()
{
static std::wstring version = L"v" + std::to_wstring(VERSION_MAJOR) + static std::wstring version = L"v" + std::to_wstring(VERSION_MAJOR) +
L"." + std::to_wstring(VERSION_MINOR) + L"." + std::to_wstring(VERSION_MINOR) +
L"." + std::to_wstring(VERSION_REVISION); L"." + std::to_wstring(VERSION_REVISION);
@@ -498,12 +600,16 @@ std::wstring get_product_version() {
return version; return version;
} }
std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback) { std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback)
{
wchar_t* text_ptr; wchar_t* text_ptr;
auto length = LoadStringW(instance, resource_id, reinterpret_cast<wchar_t*>(&text_ptr), 0); auto length = LoadStringW(instance, resource_id, reinterpret_cast<wchar_t*>(&text_ptr), 0);
if (length == 0) { if (length == 0)
{
return fallback; return fallback;
} else { }
else
{
return { text_ptr, static_cast<std::size_t>(length) }; return { text_ptr, static_cast<std::size_t>(length) };
} }
} }
@@ -541,7 +647,6 @@ std::wstring get_module_folderpath(HMODULE mod)
return { buffer, (UINT)lstrlenW(buffer) }; return { buffer, (UINT)lstrlenW(buffer) };
} }
// The function returns true in case of error since we want to return false // The function returns true in case of error since we want to return false
// only in case of a positive verification that the user is not an admin. // only in case of a positive verification that the user is not an admin.
bool check_user_is_admin() bool check_user_is_admin()

View File

@@ -14,7 +14,8 @@ std::optional<RECT> get_window_pos(HWND hwnd);
std::optional<POINT> get_mouse_pos(); std::optional<POINT> get_mouse_pos();
// Test if window can be zoned by FancyZones // Test if window can be zoned by FancyZones
struct FancyZonesFilter { struct FancyZonesFilter
{
bool zonable = false; // If the window is zonable by FancyZones by default - true when both standard_window and no_visible_owner are also true bool zonable = false; // If the window is zonable by FancyZones by default - true when both standard_window and no_visible_owner are also true
bool standard_window = false; // True if from the styles the window looks like a standard window bool standard_window = false; // True if from the styles the window looks like a standard window
bool no_visible_owner = false; // True if the window is a top-level window that does not have a visible owner bool no_visible_owner = false; // True if the window is a top-level window that does not have a visible owner
@@ -23,7 +24,8 @@ struct FancyZonesFilter {
FancyZonesFilter get_fancyzones_filtered_window(HWND window); FancyZonesFilter get_fancyzones_filtered_window(HWND window);
// Gets active foreground window, filtering out all "non standard" windows like the taskbar, etc. // Gets active foreground window, filtering out all "non standard" windows like the taskbar, etc.
struct ShortcutGuideFilter { struct ShortcutGuideFilter
{
HWND hwnd = nullptr; // Handle to the top-level foreground window or nullptr if there is no such window HWND hwnd = nullptr; // Handle to the top-level foreground window or nullptr if there is no such window
bool snappable = false; // True, if the window can react to Windows Snap keys bool snappable = false; // True, if the window can react to Windows Snap keys
}; };
@@ -42,7 +44,8 @@ int run_message_loop();
std::optional<std::wstring> get_last_error_message(const DWORD dw); std::optional<std::wstring> get_last_error_message(const DWORD dw);
void show_last_error_message(LPCWSTR lpszFunction, DWORD dw); void show_last_error_message(LPCWSTR lpszFunction, DWORD dw);
enum WindowState { enum WindowState
{
UNKNONW, UNKNONW,
MINIMIZED, MINIMIZED,
MAXIMIZED, MAXIMIZED,

View File

@@ -1,11 +1,14 @@
#include "pch.h" #include "pch.h"
#include "d2d_svg.h" #include "d2d_svg.h"
D2DSVG& D2DSVG::load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc) { D2DSVG& D2DSVG::load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc)
{
svg = nullptr; svg = nullptr;
winrt::com_ptr<IStream> svg_stream; winrt::com_ptr<IStream> svg_stream;
winrt::check_hresult(SHCreateStreamOnFileEx(filename.c_str(), winrt::check_hresult(SHCreateStreamOnFileEx(filename.c_str(),
STGM_READ, FILE_ATTRIBUTE_NORMAL, FALSE, STGM_READ,
FILE_ATTRIBUTE_NORMAL,
FALSE,
nullptr, nullptr,
svg_stream.put())); svg_stream.put()));
@@ -24,14 +27,16 @@ D2DSVG& D2DSVG::load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc)
return *this; return *this;
} }
D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float max_scale) { D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float max_scale)
{
// Center // Center
transform = D2D1::Matrix3x2F::Identity(); transform = D2D1::Matrix3x2F::Identity();
transform = transform * D2D1::Matrix3x2F::Translation((width - svg_width) / 2.0f, (height - svg_height) / 2.0f); transform = transform * D2D1::Matrix3x2F::Translation((width - svg_width) / 2.0f, (height - svg_height) / 2.0f);
float h_scale = fill * height / svg_height; float h_scale = fill * height / svg_height;
float v_scale = fill * width / svg_width; float v_scale = fill * width / svg_width;
used_scale = min(h_scale, v_scale); used_scale = min(h_scale, v_scale);
if (max_scale > 0) { if (max_scale > 0)
{
used_scale = min(used_scale, max_scale); used_scale = min(used_scale, max_scale);
} }
transform = transform * D2D1::Matrix3x2F::Scale(used_scale, used_scale, D2D1::Point2F(width / 2.0f, height / 2.0f)); transform = transform * D2D1::Matrix3x2F::Scale(used_scale, used_scale, D2D1::Point2F(width / 2.0f, height / 2.0f));
@@ -39,24 +44,28 @@ D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float ma
return *this; return *this;
} }
D2DSVG& D2DSVG::recolor(uint32_t oldcolor, uint32_t newcolor) { D2DSVG& D2DSVG::recolor(uint32_t oldcolor, uint32_t newcolor)
{
auto new_color = D2D1::ColorF(newcolor & 0xFFFFFF, 1); auto new_color = D2D1::ColorF(newcolor & 0xFFFFFF, 1);
auto old_color = D2D1::ColorF(oldcolor & 0xFFFFFF, 1); auto old_color = D2D1::ColorF(oldcolor & 0xFFFFFF, 1);
std::function<void(ID2D1SvgElement * element)> recurse = [&](ID2D1SvgElement* element) { std::function<void(ID2D1SvgElement * element)> recurse = [&](ID2D1SvgElement* element) {
if (!element) if (!element)
return; return;
if (element->IsAttributeSpecified(L"fill")) { if (element->IsAttributeSpecified(L"fill"))
{
D2D1_COLOR_F elem_fill; D2D1_COLOR_F elem_fill;
winrt::com_ptr<ID2D1SvgPaint> paint; winrt::com_ptr<ID2D1SvgPaint> paint;
element->GetAttributeValue(L"fill", paint.put()); element->GetAttributeValue(L"fill", paint.put());
paint->GetColor(&elem_fill); paint->GetColor(&elem_fill);
if (elem_fill.r == old_color.r && elem_fill.g == old_color.g && elem_fill.b == old_color.b) { if (elem_fill.r == old_color.r && elem_fill.g == old_color.g && elem_fill.b == old_color.b)
{
winrt::check_hresult(element->SetAttributeValue(L"fill", new_color)); winrt::check_hresult(element->SetAttributeValue(L"fill", new_color));
} }
} }
winrt::com_ptr<ID2D1SvgElement> sub; winrt::com_ptr<ID2D1SvgElement> sub;
element->GetFirstChild(sub.put()); element->GetFirstChild(sub.put());
while (sub) { while (sub)
{
recurse(sub.get()); recurse(sub.get());
winrt::com_ptr<ID2D1SvgElement> next; winrt::com_ptr<ID2D1SvgElement> next;
element->GetNextChild(sub.get(), next.put()); element->GetNextChild(sub.get(), next.put());
@@ -69,8 +78,8 @@ D2DSVG& D2DSVG::recolor(uint32_t oldcolor, uint32_t newcolor) {
return *this; return *this;
} }
D2DSVG& D2DSVG::render(ID2D1DeviceContext5* d2d_dc)
D2DSVG& D2DSVG::render(ID2D1DeviceContext5* d2d_dc) { {
D2D1_MATRIX_3X2_F current; D2D1_MATRIX_3X2_F current;
d2d_dc->GetTransform(&current); d2d_dc->GetTransform(&current);
d2d_dc->SetTransform(transform * current); d2d_dc->SetTransform(transform * current);
@@ -79,7 +88,8 @@ D2DSVG& D2DSVG::render(ID2D1DeviceContext5* d2d_dc) {
return *this; return *this;
} }
D2DSVG& D2DSVG::toggle_element(const wchar_t* id, bool visible) { D2DSVG& D2DSVG::toggle_element(const wchar_t* id, bool visible)
{
winrt::com_ptr<ID2D1SvgElement> element; winrt::com_ptr<ID2D1SvgElement> element;
if (svg->FindElementById(id, element.put()) != S_OK) if (svg->FindElementById(id, element.put()) != S_OK)
return *this; return *this;
@@ -89,13 +99,15 @@ D2DSVG& D2DSVG::toggle_element(const wchar_t* id, bool visible) {
return *this; return *this;
} }
winrt::com_ptr<ID2D1SvgElement> D2DSVG::find_element(const std::wstring& id) { winrt::com_ptr<ID2D1SvgElement> D2DSVG::find_element(const std::wstring& id)
{
winrt::com_ptr<ID2D1SvgElement> element; winrt::com_ptr<ID2D1SvgElement> element;
winrt::check_hresult(svg->FindElementById(id.c_str(), element.put())); winrt::check_hresult(svg->FindElementById(id.c_str(), element.put()));
return element; return element;
} }
D2D1_RECT_F D2DSVG::rescale(D2D1_RECT_F rect) { D2D1_RECT_F D2DSVG::rescale(D2D1_RECT_F rect)
{
D2D1_RECT_F result; D2D1_RECT_F result;
auto src = reinterpret_cast<D2D1_POINT_2F*>(&rect); auto src = reinterpret_cast<D2D1_POINT_2F*>(&rect);
auto dst = reinterpret_cast<D2D1_POINT_2F*>(&result); auto dst = reinterpret_cast<D2D1_POINT_2F*>(&result);

View File

@@ -4,7 +4,8 @@
#include <winrt/base.h> #include <winrt/base.h>
#include <string> #include <string>
class D2DSVG { class D2DSVG
{
public: public:
D2DSVG& load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc); D2DSVG& load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc);
D2DSVG& resize(int x, int y, int width, int height, float fill, float max_scale = -1.0f); D2DSVG& resize(int x, int y, int width, int height, float fill, float max_scale = -1.0f);
@@ -16,6 +17,7 @@ public:
D2DSVG& toggle_element(const wchar_t* id, bool visible); D2DSVG& toggle_element(const wchar_t* id, bool visible);
winrt::com_ptr<ID2D1SvgElement> find_element(const std::wstring& id); winrt::com_ptr<ID2D1SvgElement> find_element(const std::wstring& id);
D2D1_RECT_F rescale(D2D1_RECT_F rect); D2D1_RECT_F rescale(D2D1_RECT_F rect);
protected: protected:
float used_scale = 1.0f; float used_scale = 1.0f;
winrt::com_ptr<ID2D1SvgDocument> svg; winrt::com_ptr<ID2D1SvgDocument> svg;

View File

@@ -1,14 +1,16 @@
#include "pch.h" #include "pch.h"
#include "d2d_text.h" #include "d2d_text.h"
D2DText::D2DText(float text_size, float scale) { D2DText::D2DText(float text_size, float scale)
{
winrt::check_hresult(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), reinterpret_cast<IUnknown**>(factory.put_void()))); winrt::check_hresult(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), reinterpret_cast<IUnknown**>(factory.put_void())));
resize(text_size, scale); resize(text_size, scale);
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER));
winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER));
} }
D2DText & D2DText::resize(float text_size, float scale) { D2DText& D2DText::resize(float text_size, float scale)
{
format = nullptr; format = nullptr;
winrt::check_hresult(factory->CreateTextFormat(L"Segoe UI", winrt::check_hresult(factory->CreateTextFormat(L"Segoe UI",
nullptr, nullptr,
@@ -22,22 +24,26 @@ D2DText & D2DText::resize(float text_size, float scale) {
return *this; return *this;
} }
D2DText & D2DText::set_aligment_left() { D2DText& D2DText::set_aligment_left()
{
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING)); winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING));
return *this; return *this;
} }
D2DText & D2DText::set_aligment_center() { D2DText& D2DText::set_aligment_center()
{
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER));
return *this; return *this;
} }
D2DText & D2DText::set_aligment_right() { D2DText& D2DText::set_aligment_right()
{
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING)); winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING));
return *this; return *this;
} }
void D2DText::write(ID2D1DeviceContext5 * d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text) { void D2DText::write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text)
{
winrt::com_ptr<ID2D1SolidColorBrush> brush; winrt::com_ptr<ID2D1SolidColorBrush> brush;
d2d_dc->CreateSolidColorBrush(color, brush.put()); d2d_dc->CreateSolidColorBrush(color, brush.put());
d2d_dc->DrawText(text.c_str(), d2d_dc->DrawText(text.c_str(),

View File

@@ -2,7 +2,8 @@
#include <winrt/base.h> #include <winrt/base.h>
#include <dwrite.h> #include <dwrite.h>
class D2DText { class D2DText
{
public: public:
D2DText(float text_size = 15.0f, float scale = 1.0f); D2DText(float text_size = 15.0f, float scale = 1.0f);
D2DText& resize(float text_size, float scale); D2DText& resize(float text_size, float scale);
@@ -10,6 +11,7 @@ public:
D2DText& set_aligment_center(); D2DText& set_aligment_center();
D2DText& set_aligment_right(); D2DText& set_aligment_right();
void write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text); void write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text);
private: private:
winrt::com_ptr<IDWriteFactory> factory; winrt::com_ptr<IDWriteFactory> factory;
winrt::com_ptr<IDWriteTextFormat> format; winrt::com_ptr<IDWriteTextFormat> format;

View File

@@ -3,7 +3,8 @@
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
D2DWindow::D2DWindow() { D2DWindow::D2DWindow()
{
static const WCHAR* class_name = L"PToyD2DPopup"; static const WCHAR* class_name = L"PToyD2DPopup";
WNDCLASS wc = {}; WNDCLASS wc = {};
wc.hCursor = LoadCursor(nullptr, IDC_ARROW); wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
@@ -16,14 +17,21 @@ D2DWindow::D2DWindow() {
wc.lpszClassName, wc.lpszClassName,
L"PToyD2DPopup", L"PToyD2DPopup",
WS_POPUP | WS_VISIBLE, WS_POPUP | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
nullptr, nullptr, wc.hInstance, this); CW_USEDEFAULT,
CW_USEDEFAULT,
nullptr,
nullptr,
wc.hInstance,
this);
WINRT_VERIFY(hwnd); WINRT_VERIFY(hwnd);
} }
void D2DWindow::show(UINT x, UINT y, UINT width, UINT height) { void D2DWindow::show(UINT x, UINT y, UINT width, UINT height)
if (!initialized) { {
if (!initialized)
{
base_init(); base_init();
} }
base_resize(width, height); base_resize(width, height);
@@ -34,19 +42,23 @@ void D2DWindow::show(UINT x, UINT y, UINT width, UINT height) {
UpdateWindow(hwnd); UpdateWindow(hwnd);
} }
void D2DWindow::hide() { void D2DWindow::hide()
{
ShowWindow(hwnd, SW_HIDE); ShowWindow(hwnd, SW_HIDE);
on_hide(); on_hide();
} }
void D2DWindow::initialize() { void D2DWindow::initialize()
{
base_init(); base_init();
} }
void D2DWindow::base_init() { void D2DWindow::base_init()
{
std::unique_lock lock(mutex); std::unique_lock lock(mutex);
// D2D1Factory is independent from the device, no need to recreate it if we need to recreate the device. // D2D1Factory is independent from the device, no need to recreate it if we need to recreate the device.
if (!d2d_factory) { if (!d2d_factory)
{
#ifdef _DEBUG #ifdef _DEBUG
D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION }; D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION };
#else #else
@@ -81,14 +93,17 @@ void D2DWindow::base_init() {
initialized = true; initialized = true;
} }
void D2DWindow::base_resize(UINT width, UINT height) { void D2DWindow::base_resize(UINT width, UINT height)
{
std::unique_lock lock(mutex); std::unique_lock lock(mutex);
if (!initialized) { if (!initialized)
{
return; return;
} }
window_width = width; window_width = width;
window_height = height; window_height = height;
if (window_width == 0 || window_height == 0) { if (window_width == 0 || window_height == 0)
{
return; return;
} }
DXGI_SWAP_CHAIN_DESC1 sc_description = {}; DXGI_SWAP_CHAIN_DESC1 sc_description = {};
@@ -133,7 +148,8 @@ void D2DWindow::base_resize(UINT width, UINT height) {
resize(); resize();
} }
void D2DWindow::base_render() { void D2DWindow::base_render()
{
std::unique_lock lock(mutex); std::unique_lock lock(mutex);
if (!initialized || !d2d_dc || !d2d_bitmap) if (!initialized || !d2d_dc || !d2d_bitmap)
return; return;
@@ -144,7 +160,8 @@ void D2DWindow::base_render() {
winrt::check_hresult(composition_device->Commit()); winrt::check_hresult(composition_device->Commit());
} }
void D2DWindow::render_empty() { void D2DWindow::render_empty()
{
std::unique_lock lock(mutex); std::unique_lock lock(mutex);
if (!initialized || !d2d_dc || !d2d_bitmap) if (!initialized || !d2d_dc || !d2d_bitmap)
return; return;
@@ -155,18 +172,23 @@ void D2DWindow::render_empty() {
winrt::check_hresult(composition_device->Commit()); winrt::check_hresult(composition_device->Commit());
} }
D2DWindow::~D2DWindow() { D2DWindow::~D2DWindow()
{
ShowWindow(hwnd, SW_HIDE); ShowWindow(hwnd, SW_HIDE);
DestroyWindow(hwnd); DestroyWindow(hwnd);
} }
D2DWindow* D2DWindow::this_from_hwnd(HWND window) { D2DWindow* D2DWindow::this_from_hwnd(HWND window)
{
return reinterpret_cast<D2DWindow*>(GetWindowLongPtr(window, GWLP_USERDATA)); return reinterpret_cast<D2DWindow*>(GetWindowLongPtr(window, GWLP_USERDATA));
} }
LRESULT __stdcall D2DWindow::d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { LRESULT __stdcall D2DWindow::d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
switch (message) { {
case WM_NCCREATE: { switch (message)
{
case WM_NCCREATE:
{
auto create_struct = reinterpret_cast<CREATESTRUCT*>(lparam); auto create_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(create_struct->lpCreateParams)); SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(create_struct->lpCreateParams));
return TRUE; return TRUE;

View File

@@ -19,6 +19,7 @@ public:
void hide(); void hide();
void initialize(); void initialize();
virtual ~D2DWindow(); virtual ~D2DWindow();
protected: protected:
// Implement this: // Implement this:

View File

@@ -3,13 +3,15 @@
#include "common.h" #include "common.h"
#include "monitors.h" #include "monitors.h"
bool operator==(const ScreenSize& lhs, const ScreenSize& rhs) { bool operator==(const ScreenSize& lhs, const ScreenSize& rhs)
{
auto lhs_tuple = std::make_tuple(lhs.rect.left, lhs.rect.right, lhs.rect.top, lhs.rect.bottom); auto lhs_tuple = std::make_tuple(lhs.rect.left, lhs.rect.right, lhs.rect.top, lhs.rect.bottom);
auto rhs_tuple = std::make_tuple(rhs.rect.left, rhs.rect.right, rhs.rect.top, rhs.rect.bottom); auto rhs_tuple = std::make_tuple(rhs.rect.left, rhs.rect.right, rhs.rect.top, rhs.rect.bottom);
return lhs_tuple == rhs_tuple; return lhs_tuple == rhs_tuple;
} }
static BOOL CALLBACK get_displays_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) { static BOOL CALLBACK get_displays_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
{
MONITORINFOEX monitor_info; MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX); monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info); GetMonitorInfo(monitor, &monitor_info);
@@ -17,7 +19,8 @@ static BOOL CALLBACK get_displays_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect
return true; return true;
}; };
static BOOL CALLBACK get_displays_enum_cb_with_toolbar(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) { static BOOL CALLBACK get_displays_enum_cb_with_toolbar(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
{
MONITORINFOEX monitor_info; MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX); monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info); GetMonitorInfo(monitor, &monitor_info);
@@ -25,7 +28,8 @@ static BOOL CALLBACK get_displays_enum_cb_with_toolbar(HMONITOR monitor, HDC hdc
return true; return true;
}; };
std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool include_toolbar) { std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool include_toolbar)
{
std::vector<MonitorInfo> monitors; std::vector<MonitorInfo> monitors;
EnumDisplayMonitors(NULL, NULL, include_toolbar ? get_displays_enum_cb_with_toolbar : get_displays_enum_cb, reinterpret_cast<LPARAM>(&monitors)); EnumDisplayMonitors(NULL, NULL, include_toolbar ? get_displays_enum_cb_with_toolbar : get_displays_enum_cb, reinterpret_cast<LPARAM>(&monitors));
std::sort(begin(monitors), end(monitors), [](const MonitorInfo& lhs, const MonitorInfo& rhs) { std::sort(begin(monitors), end(monitors), [](const MonitorInfo& lhs, const MonitorInfo& rhs) {
@@ -34,34 +38,40 @@ std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool include_toolbar) {
return monitors; return monitors;
} }
static BOOL CALLBACK get_primary_display_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) { static BOOL CALLBACK get_primary_display_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
{
MONITORINFOEX monitor_info; MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX); monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info); GetMonitorInfo(monitor, &monitor_info);
if (monitor_info.dwFlags & MONITORINFOF_PRIMARY) { if (monitor_info.dwFlags & MONITORINFOF_PRIMARY)
{
reinterpret_cast<MonitorInfo*>(data)->handle = monitor; reinterpret_cast<MonitorInfo*>(data)->handle = monitor;
reinterpret_cast<MonitorInfo*>(data)->rect = monitor_info.rcWork; reinterpret_cast<MonitorInfo*>(data)->rect = monitor_info.rcWork;
} }
return true; return true;
}; };
MonitorInfo MonitorInfo::GetPrimaryMonitor() { MonitorInfo MonitorInfo::GetPrimaryMonitor()
{
MonitorInfo primary({}, {}); MonitorInfo primary({}, {});
EnumDisplayMonitors(NULL, NULL, get_primary_display_enum_cb, reinterpret_cast<LPARAM>(&primary)); EnumDisplayMonitors(NULL, NULL, get_primary_display_enum_cb, reinterpret_cast<LPARAM>(&primary));
return primary; return primary;
} }
MonitorInfo MonitorInfo::GetFromWindow(HWND hwnd) { MonitorInfo MonitorInfo::GetFromWindow(HWND hwnd)
{
auto monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); auto monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
return GetFromHandle(monitor); return GetFromHandle(monitor);
} }
MonitorInfo MonitorInfo::GetFromPoint(POINT p) { MonitorInfo MonitorInfo::GetFromPoint(POINT p)
{
auto monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST); auto monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST);
return GetFromHandle(monitor); return GetFromHandle(monitor);
} }
MonitorInfo MonitorInfo::GetFromHandle(HMONITOR monitor) { MonitorInfo MonitorInfo::GetFromHandle(HMONITOR monitor)
{
MONITORINFOEX monitor_info; MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX); monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info); GetMonitorInfo(monitor, &monitor_info);

View File

@@ -2,8 +2,10 @@
#include <Windows.h> #include <Windows.h>
#include <vector> #include <vector>
struct ScreenSize { struct ScreenSize
explicit ScreenSize(RECT rect) : rect(rect) {} {
explicit ScreenSize(RECT rect) :
rect(rect) {}
RECT rect; RECT rect;
int left() const { return rect.left; } int left() const { return rect.left; }
int right() const { return rect.right; } int right() const { return rect.right; }
@@ -22,8 +24,10 @@ struct ScreenSize {
POINT bottom_right() const { return { rect.right, rect.bottom }; }; POINT bottom_right() const { return { rect.right, rect.bottom }; };
}; };
struct MonitorInfo : ScreenSize { struct MonitorInfo : ScreenSize
explicit MonitorInfo(HMONITOR monitor, RECT rect) : handle(monitor), ScreenSize(rect) {} {
explicit MonitorInfo(HMONITOR monitor, RECT rect) :
handle(monitor), ScreenSize(rect) {}
HMONITOR handle; HMONITOR handle;
// Returns monitor rects ordered from left to right // Returns monitor rects ordered from left to right

View File

@@ -1,2 +1 @@
#include "pch.h" #include "pch.h"

View File

@@ -2,12 +2,13 @@
#include "on_thread_executor.h" #include "on_thread_executor.h"
OnThreadExecutor::OnThreadExecutor() OnThreadExecutor::OnThreadExecutor() :
: _shutdown_request{false} _shutdown_request{ false }, _worker_thread{ [this] { worker_thread(); } }
, _worker_thread{[this] { worker_thread(); }} {
{} }
std::future<void> OnThreadExecutor::submit(task_t task) { std::future<void> OnThreadExecutor::submit(task_t task)
{
auto future = task.get_future(); auto future = task.get_future();
std::lock_guard lock{ _task_mutex }; std::lock_guard lock{ _task_mutex };
_task_queue.emplace(std::move(task)); _task_queue.emplace(std::move(task));
@@ -15,13 +16,16 @@ std::future<void> OnThreadExecutor::submit(task_t task) {
return future; return future;
} }
void OnThreadExecutor::worker_thread() { void OnThreadExecutor::worker_thread()
while(!_shutdown_request) { {
while (!_shutdown_request)
{
task_t task; task_t task;
{ {
std::unique_lock task_lock{ _task_mutex }; std::unique_lock task_lock{ _task_mutex };
_task_cv.wait(task_lock, [this] { return !_task_queue.empty() || _shutdown_request; }); _task_cv.wait(task_lock, [this] { return !_task_queue.empty() || _shutdown_request; });
if(_shutdown_request) { if (_shutdown_request)
{
return; return;
} }
task = std::move(_task_queue.front()); task = std::move(_task_queue.front());
@@ -31,9 +35,9 @@ void OnThreadExecutor::worker_thread() {
} }
} }
OnThreadExecutor::~OnThreadExecutor() { OnThreadExecutor::~OnThreadExecutor()
{
_shutdown_request = true; _shutdown_request = true;
_task_cv.notify_one(); _task_cv.notify_one();
_worker_thread.join(); _worker_thread.join();
} }

View File

@@ -10,7 +10,8 @@
// This might come in handy if you use the API which sets thread-wide global state and the state needs // This might come in handy if you use the API which sets thread-wide global state and the state needs
// to be isolated. // to be isolated.
class OnThreadExecutor final { class OnThreadExecutor final
{
public: public:
using task_t = std::packaged_task<void()>; using task_t = std::packaged_task<void()>;

View File

@@ -22,4 +22,3 @@
#include <unordered_set> #include <unordered_set>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@@ -3,11 +3,12 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
namespace PTSettingsHelper { namespace PTSettingsHelper
{
constexpr inline const wchar_t* settings_filename = L"\\settings.json"; constexpr inline const wchar_t* settings_filename = L"\\settings.json";
std::wstring get_root_save_folder_location() { std::wstring get_root_save_folder_location()
{
PWSTR local_app_path; PWSTR local_app_path;
winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path)); winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path));
std::wstring result{ local_app_path }; std::wstring result{ local_app_path };
@@ -15,48 +16,57 @@ namespace PTSettingsHelper {
result += L"\\Microsoft\\PowerToys"; result += L"\\Microsoft\\PowerToys";
std::filesystem::path save_path(result); std::filesystem::path save_path(result);
if (!std::filesystem::exists(save_path)) { if (!std::filesystem::exists(save_path))
{
std::filesystem::create_directories(save_path); std::filesystem::create_directories(save_path);
} }
return result; return result;
} }
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name) { std::wstring get_module_save_folder_location(std::wstring_view powertoy_name)
{
std::wstring result = get_root_save_folder_location(); std::wstring result = get_root_save_folder_location();
result += L"\\"; result += L"\\";
result += powertoy_name; result += powertoy_name;
std::filesystem::path save_path(result); std::filesystem::path save_path(result);
if (!std::filesystem::exists(save_path)) { if (!std::filesystem::exists(save_path))
{
std::filesystem::create_directories(save_path); std::filesystem::create_directories(save_path);
} }
return result; return result;
} }
std::wstring get_module_save_file_location(std::wstring_view powertoy_name) { std::wstring get_module_save_file_location(std::wstring_view powertoy_name)
{
return get_module_save_folder_location(powertoy_name) + settings_filename; return get_module_save_folder_location(powertoy_name) + settings_filename;
} }
std::wstring get_powertoys_general_save_file_location() { std::wstring get_powertoys_general_save_file_location()
{
return get_root_save_folder_location() + settings_filename; return get_root_save_folder_location() + settings_filename;
} }
void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings) { void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings)
{
const std::wstring save_file_location = get_module_save_file_location(powertoy_name); const std::wstring save_file_location = get_module_save_file_location(powertoy_name);
json::to_file(save_file_location, settings); json::to_file(save_file_location, settings);
} }
json::JsonObject load_module_settings(std::wstring_view powertoy_name) { json::JsonObject load_module_settings(std::wstring_view powertoy_name)
{
const std::wstring save_file_location = get_module_save_file_location(powertoy_name); const std::wstring save_file_location = get_module_save_file_location(powertoy_name);
auto saved_settings = json::from_file(save_file_location); auto saved_settings = json::from_file(save_file_location);
return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{}; return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{};
} }
void save_general_settings(const json::JsonObject& settings) { void save_general_settings(const json::JsonObject& settings)
{
const std::wstring save_file_location = get_powertoys_general_save_file_location(); const std::wstring save_file_location = get_powertoys_general_save_file_location();
json::to_file(save_file_location, settings); json::to_file(save_file_location, settings);
} }
json::JsonObject load_general_settings() { json::JsonObject load_general_settings()
{
const std::wstring save_file_location = get_powertoys_general_save_file_location(); const std::wstring save_file_location = get_powertoys_general_save_file_location();
auto saved_settings = json::from_file(save_file_location); auto saved_settings = json::from_file(save_file_location);
return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{}; return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{};

View File

@@ -4,8 +4,8 @@
#include "json.h" #include "json.h"
namespace PTSettingsHelper { namespace PTSettingsHelper
{
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name); std::wstring get_module_save_folder_location(std::wstring_view powertoy_name);
std::wstring get_root_save_folder_location(); std::wstring get_root_save_folder_location();

View File

@@ -2,41 +2,49 @@
#include "settings_objects.h" #include "settings_objects.h"
#include "settings_helpers.h" #include "settings_helpers.h"
namespace PowerToysSettings { namespace PowerToysSettings
{
Settings::Settings(const HINSTANCE hinstance, std::wstring_view powertoy_name) { Settings::Settings(const HINSTANCE hinstance, std::wstring_view powertoy_name)
{
m_instance = hinstance; m_instance = hinstance;
m_json.SetNamedValue(L"version", json::value(L"1.0")); m_json.SetNamedValue(L"version", json::value(L"1.0"));
m_json.SetNamedValue(L"name", json::value(powertoy_name)); m_json.SetNamedValue(L"name", json::value(powertoy_name));
m_json.SetNamedValue(L"properties", json::JsonObject{}); m_json.SetNamedValue(L"properties", json::JsonObject{});
} }
void Settings::set_description(UINT resource_id) { void Settings::set_description(UINT resource_id)
{
m_json.SetNamedValue(L"description", json::value(get_resource(resource_id))); m_json.SetNamedValue(L"description", json::value(get_resource(resource_id)));
} }
void Settings::set_description(std::wstring_view description) { void Settings::set_description(std::wstring_view description)
{
m_json.SetNamedValue(L"description", json::value(description)); m_json.SetNamedValue(L"description", json::value(description));
} }
void Settings::set_icon_key(std::wstring_view icon_key) { void Settings::set_icon_key(std::wstring_view icon_key)
{
m_json.SetNamedValue(L"icon_key", json::value(icon_key)); m_json.SetNamedValue(L"icon_key", json::value(icon_key));
} }
void Settings::set_overview_link(std::wstring_view overview_link) { void Settings::set_overview_link(std::wstring_view overview_link)
{
m_json.SetNamedValue(L"overview_link", json::value(overview_link)); m_json.SetNamedValue(L"overview_link", json::value(overview_link));
} }
void Settings::set_video_link(std::wstring_view video_link) { void Settings::set_video_link(std::wstring_view video_link)
{
m_json.SetNamedValue(L"video_link", json::value(video_link)); m_json.SetNamedValue(L"video_link", json::value(video_link));
} }
// add_bool_toogle overloads. // add_bool_toogle overloads.
void Settings::add_bool_toogle(std::wstring_view name, UINT description_resource_id, bool value) { void Settings::add_bool_toogle(std::wstring_view name, UINT description_resource_id, bool value)
{
add_bool_toogle(name, get_resource(description_resource_id), value); add_bool_toogle(name, get_resource(description_resource_id), value);
} }
void Settings::add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value) { void Settings::add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value)
{
json::JsonObject toggle; json::JsonObject toggle;
toggle.SetNamedValue(L"display_name", json::value(description)); toggle.SetNamedValue(L"display_name", json::value(description));
toggle.SetNamedValue(L"editor_type", json::value(L"bool_toggle")); toggle.SetNamedValue(L"editor_type", json::value(L"bool_toggle"));
@@ -47,11 +55,13 @@ namespace PowerToysSettings {
} }
// add_int_spinner overloads. // add_int_spinner overloads.
void Settings::add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step) { void Settings::add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step)
{
add_int_spinner(name, get_resource(description_resource_id), value, min, max, step); add_int_spinner(name, get_resource(description_resource_id), value, min, max, step);
} }
void Settings::add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step) { void Settings::add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step)
{
json::JsonObject spinner; json::JsonObject spinner;
spinner.SetNamedValue(L"display_name", json::value(description)); spinner.SetNamedValue(L"display_name", json::value(description));
spinner.SetNamedValue(L"editor_type", json::value(L"int_spinner")); spinner.SetNamedValue(L"editor_type", json::value(L"int_spinner"));
@@ -65,11 +75,13 @@ namespace PowerToysSettings {
} }
// add_string overloads. // add_string overloads.
void Settings::add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) { void Settings::add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value)
{
add_string(name, get_resource(description_resource_id), value); add_string(name, get_resource(description_resource_id), value);
} }
void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) { void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value)
{
json::JsonObject string; json::JsonObject string;
string.SetNamedValue(L"display_name", json::value(description)); string.SetNamedValue(L"display_name", json::value(description));
string.SetNamedValue(L"editor_type", json::value(L"string_text")); string.SetNamedValue(L"editor_type", json::value(L"string_text"));
@@ -80,11 +92,13 @@ namespace PowerToysSettings {
} }
// add_multiline_string overloads. // add_multiline_string overloads.
void Settings::add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) { void Settings::add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value)
{
add_multiline_string(name, get_resource(description_resource_id), value); add_multiline_string(name, get_resource(description_resource_id), value);
} }
void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) { void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value)
{
json::JsonObject ml_string; json::JsonObject ml_string;
ml_string.SetNamedValue(L"display_name", json::value(description)); ml_string.SetNamedValue(L"display_name", json::value(description));
ml_string.SetNamedValue(L"editor_type", json::value(L"string_text")); ml_string.SetNamedValue(L"editor_type", json::value(L"string_text"));
@@ -96,11 +110,13 @@ namespace PowerToysSettings {
} }
// add_color_picker overloads. // add_color_picker overloads.
void Settings::add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value) { void Settings::add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value)
{
add_color_picker(name, get_resource(description_resource_id), value); add_color_picker(name, get_resource(description_resource_id), value);
} }
void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value) { void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value)
{
json::JsonObject picker; json::JsonObject picker;
picker.SetNamedValue(L"display_name", json::value(description)); picker.SetNamedValue(L"display_name", json::value(description));
picker.SetNamedValue(L"editor_type", json::value(L"color_picker")); picker.SetNamedValue(L"editor_type", json::value(L"color_picker"));
@@ -110,11 +126,13 @@ namespace PowerToysSettings {
m_json.GetNamedObject(L"properties").SetNamedValue(name, picker); m_json.GetNamedObject(L"properties").SetNamedValue(name, picker);
} }
void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey) { void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey)
{
add_hotkey(name, get_resource(description_resource_id), hotkey); add_hotkey(name, get_resource(description_resource_id), hotkey);
} }
void Settings::add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey_obj) { void Settings::add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey_obj)
{
json::JsonObject hotkey; json::JsonObject hotkey;
hotkey.SetNamedValue(L"display_name", json::value(description)); hotkey.SetNamedValue(L"display_name", json::value(description));
hotkey.SetNamedValue(L"editor_type", json::value(L"hotkey")); hotkey.SetNamedValue(L"editor_type", json::value(L"hotkey"));
@@ -124,21 +142,25 @@ namespace PowerToysSettings {
m_json.GetNamedObject(L"properties").SetNamedValue(name, hotkey); m_json.GetNamedObject(L"properties").SetNamedValue(name, hotkey);
} }
void Settings::add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) { void Settings::add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids)
{
std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts; std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts;
keys_and_texts.reserve(keys_and_text_ids.size()); keys_and_texts.reserve(keys_and_text_ids.size());
for (const auto& kv : keys_and_text_ids) { for (const auto& kv : keys_and_text_ids)
{
keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); keys_and_texts.emplace_back(kv.first, get_resource(kv.second));
} }
add_choice_group(name, get_resource(description_resource_id), value, keys_and_texts); add_choice_group(name, get_resource(description_resource_id), value, keys_and_texts);
} }
void Settings::add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) { void Settings::add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts)
{
json::JsonObject choice_group; json::JsonObject choice_group;
choice_group.SetNamedValue(L"display_name", json::value(description)); choice_group.SetNamedValue(L"display_name", json::value(description));
choice_group.SetNamedValue(L"editor_type", json::value(L"choice_group")); choice_group.SetNamedValue(L"editor_type", json::value(L"choice_group"));
json::JsonArray options; json::JsonArray options;
for(const auto & [key, text] : keys_and_texts) { for (const auto& [key, text] : keys_and_texts)
{
json::JsonObject entry; json::JsonObject entry;
entry.SetNamedValue(L"key", json::value(key)); entry.SetNamedValue(L"key", json::value(key));
entry.SetNamedValue(L"text", json::value(text)); entry.SetNamedValue(L"text", json::value(text));
@@ -151,21 +173,25 @@ namespace PowerToysSettings {
m_json.GetNamedObject(L"properties").SetNamedValue(name, choice_group); m_json.GetNamedObject(L"properties").SetNamedValue(name, choice_group);
} }
void Settings::add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) { void Settings::add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids)
{
std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts; std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts;
keys_and_texts.reserve(keys_and_text_ids.size()); keys_and_texts.reserve(keys_and_text_ids.size());
for (const auto& kv : keys_and_text_ids) { for (const auto& kv : keys_and_text_ids)
{
keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); keys_and_texts.emplace_back(kv.first, get_resource(kv.second));
} }
add_dropdown(name, get_resource(description_resource_id), value, keys_and_texts); add_dropdown(name, get_resource(description_resource_id), value, keys_and_texts);
} }
void Settings::add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) { void Settings::add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts)
{
json::JsonObject dropdown; json::JsonObject dropdown;
dropdown.SetNamedValue(L"display_name", json::value(description)); dropdown.SetNamedValue(L"display_name", json::value(description));
dropdown.SetNamedValue(L"editor_type", json::value(L"dropdown")); dropdown.SetNamedValue(L"editor_type", json::value(L"dropdown"));
json::JsonArray options; json::JsonArray options;
for(const auto & [key, text] : keys_and_texts) { for (const auto& [key, text] : keys_and_texts)
{
json::JsonObject entry; json::JsonObject entry;
entry.SetNamedValue(L"key", json::value(key)); entry.SetNamedValue(L"key", json::value(key));
entry.SetNamedValue(L"text", json::value(text)); entry.SetNamedValue(L"text", json::value(text));
@@ -179,15 +205,18 @@ namespace PowerToysSettings {
} }
// add_custom_action overloads. // add_custom_action overloads.
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id) { void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id)
{
add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), get_resource(ext_description_resource_id)); add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), get_resource(ext_description_resource_id));
} }
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value) { void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value)
{
add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), value); add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), value);
} }
void Settings::add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value) { void Settings::add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value)
{
json::JsonObject custom_action; json::JsonObject custom_action;
custom_action.SetNamedValue(L"display_name", json::value(description)); custom_action.SetNamedValue(L"display_name", json::value(description));
custom_action.SetNamedValue(L"button_text", json::value(button_text)); custom_action.SetNamedValue(L"button_text", json::value(button_text));
@@ -199,29 +228,37 @@ namespace PowerToysSettings {
} }
// Serialization methods. // Serialization methods.
std::wstring Settings::serialize() { std::wstring Settings::serialize()
{
return m_json.Stringify().c_str(); return m_json.Stringify().c_str();
} }
bool Settings::serialize_to_buffer(wchar_t* buffer, int *buffer_size) { bool Settings::serialize_to_buffer(wchar_t* buffer, int* buffer_size)
{
auto result = m_json.Stringify(); auto result = m_json.Stringify();
const int result_len = (int)result.size() + 1; const int result_len = (int)result.size() + 1;
if (buffer == nullptr || *buffer_size < result_len) { if (buffer == nullptr || *buffer_size < result_len)
{
*buffer_size = result_len; *buffer_size = result_len;
return false; return false;
} else { }
else
{
wcscpy_s(buffer, *buffer_size, result.c_str()); wcscpy_s(buffer, *buffer_size, result.c_str());
return true; return true;
} }
} }
// Resource helper. // Resource helper.
std::wstring Settings::get_resource(UINT resource_id) { std::wstring Settings::get_resource(UINT resource_id)
if (resource_id != 0) { {
if (resource_id != 0)
{
wchar_t* res_ptr; wchar_t* res_ptr;
const size_t resource_length = LoadStringW(m_instance, resource_id, reinterpret_cast<wchar_t*>(&res_ptr), 0); const size_t resource_length = LoadStringW(m_instance, resource_id, reinterpret_cast<wchar_t*>(&res_ptr), 0);
if (resource_length != 0) { if (resource_length != 0)
{
return { *reinterpret_cast<wchar_t**>(&res_ptr), resource_length }; return { *reinterpret_cast<wchar_t**>(&res_ptr), resource_length };
} }
} }
@@ -229,71 +266,86 @@ namespace PowerToysSettings {
return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id); return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id);
} }
PowerToyValues::PowerToyValues(std::wstring_view powertoy_name) { PowerToyValues::PowerToyValues(std::wstring_view powertoy_name)
{
_name = powertoy_name; _name = powertoy_name;
set_version(); set_version();
m_json.SetNamedValue(L"name", json::value(powertoy_name)); m_json.SetNamedValue(L"name", json::value(powertoy_name));
m_json.SetNamedValue(L"properties", json::JsonObject{}); m_json.SetNamedValue(L"properties", json::JsonObject{});
} }
PowerToyValues PowerToyValues::from_json_string(std::wstring_view json) { PowerToyValues PowerToyValues::from_json_string(std::wstring_view json)
{
PowerToyValues result = PowerToyValues(); PowerToyValues result = PowerToyValues();
result.m_json = json::JsonValue::Parse(json).GetObjectW(); result.m_json = json::JsonValue::Parse(json).GetObjectW();
result._name = result.m_json.GetNamedString(L"name"); result._name = result.m_json.GetNamedString(L"name");
return result; return result;
} }
PowerToyValues PowerToyValues::load_from_settings_file(std::wstring_view powertoy_name) { PowerToyValues PowerToyValues::load_from_settings_file(std::wstring_view powertoy_name)
{
PowerToyValues result = PowerToyValues(); PowerToyValues result = PowerToyValues();
result.m_json = PTSettingsHelper::load_module_settings(powertoy_name); result.m_json = PTSettingsHelper::load_module_settings(powertoy_name);
result._name = powertoy_name; result._name = powertoy_name;
return result; return result;
} }
inline bool has_property(const json::JsonObject& o, std::wstring_view name, const json::JsonValueType type) { inline bool has_property(const json::JsonObject& o, std::wstring_view name, const json::JsonValueType type)
{
const json::JsonObject props = o.GetNamedObject(L"properties", json::JsonObject{}); const json::JsonObject props = o.GetNamedObject(L"properties", json::JsonObject{});
return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type); return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type);
} }
std::optional<bool> PowerToyValues::get_bool_value(std::wstring_view property_name) { std::optional<bool> PowerToyValues::get_bool_value(std::wstring_view property_name)
if (!has_property(m_json, property_name, json::JsonValueType::Boolean)) { {
if (!has_property(m_json, property_name, json::JsonValueType::Boolean))
{
return std::nullopt; return std::nullopt;
} }
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value"); return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value");
} }
std::optional<int> PowerToyValues::get_int_value(std::wstring_view property_name) { std::optional<int> PowerToyValues::get_int_value(std::wstring_view property_name)
if (!has_property(m_json, property_name, json::JsonValueType::Number)) { {
if (!has_property(m_json, property_name, json::JsonValueType::Number))
{
return std::nullopt; return std::nullopt;
} }
return static_cast<int>(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value")); return static_cast<int>(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value"));
} }
std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name) { std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name)
if (!has_property(m_json, property_name, json::JsonValueType::String)) { {
if (!has_property(m_json, property_name, json::JsonValueType::String))
{
return std::nullopt; return std::nullopt;
} }
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str(); return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str();
} }
std::optional<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name) { std::optional<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name)
if (!has_property(m_json, property_name, json::JsonValueType::Object)) { {
if (!has_property(m_json, property_name, json::JsonValueType::Object))
{
return std::nullopt; return std::nullopt;
} }
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedObject(L"value"); return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedObject(L"value");
} }
std::wstring PowerToyValues::serialize() { std::wstring PowerToyValues::serialize()
{
set_version(); set_version();
return m_json.Stringify().c_str(); return m_json.Stringify().c_str();
} }
void PowerToyValues::save_to_settings_file() { void PowerToyValues::save_to_settings_file()
{
set_version(); set_version();
PTSettingsHelper::save_module_settings(_name, m_json); PTSettingsHelper::save_module_settings(_name, m_json);
} }
void PowerToyValues::set_version() { void PowerToyValues::set_version()
{
m_json.SetNamedValue(L"version", json::value(m_version)); m_json.SetNamedValue(L"version", json::value(m_version));
} }
} }

View File

@@ -2,16 +2,16 @@
#include "json.h" #include "json.h"
namespace PowerToysSettings { namespace PowerToysSettings
{
class HotkeyObject; class HotkeyObject;
class Settings { class Settings
{
public: public:
Settings( Settings(
const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase' const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase'
std::wstring_view powertoy_name std::wstring_view powertoy_name);
);
// Add additional general information to the PowerToy settings. // Add additional general information to the PowerToy settings.
void set_description(UINT resource_id); void set_description(UINT resource_id);
@@ -50,7 +50,6 @@ namespace PowerToysSettings {
void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value); void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value);
void add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value); void add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value);
// Serialize the internal json to a string. // Serialize the internal json to a string.
std::wstring serialize(); std::wstring serialize();
// Serialize the internal json to the input buffer. // Serialize the internal json to the input buffer.
@@ -64,7 +63,8 @@ namespace PowerToysSettings {
std::wstring get_resource(UINT resource_id); std::wstring get_resource(UINT resource_id);
}; };
class PowerToyValues { class PowerToyValues
{
public: public:
PowerToyValues(std::wstring_view powertoy_name); PowerToyValues(std::wstring_view powertoy_name);
static PowerToyValues from_json_string(std::wstring_view json); static PowerToyValues from_json_string(std::wstring_view json);
@@ -94,9 +94,11 @@ namespace PowerToysSettings {
PowerToyValues() {} PowerToyValues() {}
}; };
class CustomActionObject { class CustomActionObject
{
public: public:
static CustomActionObject from_json_string(std::wstring_view json) { static CustomActionObject from_json_string(std::wstring_view json)
{
return CustomActionObject(json::JsonValue::Parse(json).GetObjectW()); return CustomActionObject(json::JsonValue::Parse(json).GetObjectW());
} }
@@ -104,19 +106,24 @@ namespace PowerToysSettings {
std::wstring get_value() { return m_json.GetNamedString(L"value").c_str(); } std::wstring get_value() { return m_json.GetNamedString(L"value").c_str(); }
protected: protected:
CustomActionObject(json::JsonObject action_json) : m_json(std::move(action_json)) {}; CustomActionObject(json::JsonObject action_json) :
m_json(std::move(action_json)){};
json::JsonObject m_json; json::JsonObject m_json;
}; };
class HotkeyObject { class HotkeyObject
{
public: public:
static HotkeyObject from_json(json::JsonObject json) { static HotkeyObject from_json(json::JsonObject json)
{
return HotkeyObject(std::move(json)); return HotkeyObject(std::move(json));
} }
static HotkeyObject from_json_string(std::wstring_view json) { static HotkeyObject from_json_string(std::wstring_view json)
{
return HotkeyObject(json::JsonValue::Parse(json).GetObjectW()); return HotkeyObject(json::JsonValue::Parse(json).GetObjectW());
} }
static HotkeyObject from_settings(bool win_pressed, bool ctrl_pressed, bool alt_pressed, bool shift_pressed, UINT vk_code) { static HotkeyObject from_settings(bool win_pressed, bool ctrl_pressed, bool alt_pressed, bool shift_pressed, UINT vk_code)
{
json::JsonObject json; json::JsonObject json;
json.SetNamedValue(L"win", json::value(win_pressed)); json.SetNamedValue(L"win", json::value(win_pressed));
json.SetNamedValue(L"ctrl", json::value(ctrl_pressed)); json.SetNamedValue(L"ctrl", json::value(ctrl_pressed));
@@ -134,39 +141,65 @@ namespace PowerToysSettings {
bool ctrl_pressed() const { return m_json.GetNamedBoolean(L"ctrl"); } bool ctrl_pressed() const { return m_json.GetNamedBoolean(L"ctrl"); }
bool alt_pressed() const { return m_json.GetNamedBoolean(L"alt"); } bool alt_pressed() const { return m_json.GetNamedBoolean(L"alt"); }
bool shift_pressed() const { return m_json.GetNamedBoolean(L"shift"); } bool shift_pressed() const { return m_json.GetNamedBoolean(L"shift"); }
UINT get_modifiers_repeat() const { UINT get_modifiers_repeat() const
{
return (win_pressed() ? MOD_WIN : 0) | return (win_pressed() ? MOD_WIN : 0) |
(ctrl_pressed() ? MOD_CONTROL : 0) | (ctrl_pressed() ? MOD_CONTROL : 0) |
(alt_pressed() ? MOD_ALT : 0) | (alt_pressed() ? MOD_ALT : 0) |
(shift_pressed() ? MOD_SHIFT : 0); (shift_pressed() ? MOD_SHIFT : 0);
} }
UINT get_modifiers() const { UINT get_modifiers() const
{
return get_modifiers_repeat() | MOD_NOREPEAT; return get_modifiers_repeat() | MOD_NOREPEAT;
} }
protected: protected:
static std::wstring key_from_code(UINT key_code) { static std::wstring key_from_code(UINT key_code)
{
auto layout = GetKeyboardLayout(0); auto layout = GetKeyboardLayout(0);
auto scan_code = MapVirtualKeyExW(key_code, MAPVK_VK_TO_VSC_EX, layout); auto scan_code = MapVirtualKeyExW(key_code, MAPVK_VK_TO_VSC_EX, layout);
// Determinate if vk is an extended key. Unfortunatly MAPVK_VK_TO_VSC_EX // Determinate if vk is an extended key. Unfortunatly MAPVK_VK_TO_VSC_EX
// does not return correct values. // does not return correct values.
static std::vector<UINT> extended_keys = { static std::vector<UINT> extended_keys = {
VK_APPS, VK_CANCEL, VK_SNAPSHOT, VK_DIVIDE, VK_NUMLOCK, VK_LWIN, VK_RWIN, VK_RMENU, VK_APPS,
VK_RCONTROL, VK_RSHIFT, VK_RETURN, VK_INSERT, VK_DELETE, VK_PRIOR, VK_NEXT, VK_CANCEL,
VK_HOME, VK_END, VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_SNAPSHOT,
VK_DIVIDE,
VK_NUMLOCK,
VK_LWIN,
VK_RWIN,
VK_RMENU,
VK_RCONTROL,
VK_RSHIFT,
VK_RETURN,
VK_INSERT,
VK_DELETE,
VK_PRIOR,
VK_NEXT,
VK_HOME,
VK_END,
VK_UP,
VK_DOWN,
VK_LEFT,
VK_RIGHT,
}; };
if (find(begin(extended_keys), end(extended_keys), key_code) != end(extended_keys)) { if (find(begin(extended_keys), end(extended_keys), key_code) != end(extended_keys))
{
scan_code |= 0x100; scan_code |= 0x100;
} }
std::array<BYTE, 256> key_states{}; // Zero-initialize std::array<BYTE, 256> key_states{}; // Zero-initialize
std::array<wchar_t, 256> output; std::array<wchar_t, 256> output;
auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, 0, layout); auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, 0, layout);
if (output_bytes <= 0) { if (output_bytes <= 0)
{
// If ToUnicodeEx fails (e.g. for F1-F12 keys) use GetKeyNameTextW // If ToUnicodeEx fails (e.g. for F1-F12 keys) use GetKeyNameTextW
output_bytes = GetKeyNameTextW(scan_code << 16, output.data(), static_cast<int>(output.size())); output_bytes = GetKeyNameTextW(scan_code << 16, output.data(), static_cast<int>(output.size()));
} }
if (output_bytes > 0) { if (output_bytes > 0)
{
output[output_bytes] = 0; output[output_bytes] = 0;
if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z') { if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z')
{
// Make Latin letters keys capital, as it looks better // Make Latin letters keys capital, as it looks better
output[0] = toupper(output[0]); output[0] = toupper(output[0]);
} }
@@ -174,8 +207,11 @@ namespace PowerToysSettings {
} }
return L"(Key " + std::to_wstring(key_code) + L")"; return L"(Key " + std::to_wstring(key_code) + L")";
} }
HotkeyObject(json::JsonObject hotkey_json) : m_json(std::move(hotkey_json)) { HotkeyObject(json::JsonObject hotkey_json) :
if (get_key() == L"~" && get_modifiers_repeat() == MOD_WIN) { m_json(std::move(hotkey_json))
{
if (get_key() == L"~" && get_modifiers_repeat() == MOD_WIN)
{
m_json.SetNamedValue(L"key", json::value(key_from_code(get_code()))); m_json.SetNamedValue(L"key", json::value(key_from_code(get_code())));
} }
}; };

View File

@@ -1,9 +1,11 @@
#include "pch.h" #include "pch.h"
#include "start_visible.h" #include "start_visible.h"
bool is_start_visible() { bool is_start_visible()
{
static winrt::com_ptr<IAppVisibility> app_visibility; static winrt::com_ptr<IAppVisibility> app_visibility;
if (!app_visibility) { if (!app_visibility)
{
winrt::check_hresult(CoCreateInstance(CLSID_AppVisibility, winrt::check_hresult(CoCreateInstance(CLSID_AppVisibility,
nullptr, nullptr,
CLSCTX_INPROC_SERVER, CLSCTX_INPROC_SERVER,

View File

@@ -1,4 +1,3 @@
#pragma once #pragma once
bool is_start_visible(); bool is_start_visible();

View File

@@ -1,17 +1,23 @@
#include "pch.h" #include "pch.h"
#include "tasklist_positions.h" #include "tasklist_positions.h"
void Tasklist::update() { void Tasklist::update()
{
// Get HWND of the tasklist // Get HWND of the tasklist
auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr); auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr);
if (!tasklist_hwnd) return; if (!tasklist_hwnd)
return;
tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr); tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr);
if (!tasklist_hwnd) return; if (!tasklist_hwnd)
return;
tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr); tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr);
if (!tasklist_hwnd) return; if (!tasklist_hwnd)
return;
tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr); tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr);
if (!tasklist_hwnd) return; if (!tasklist_hwnd)
if (!automation) { return;
if (!automation)
{
winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation,
nullptr, nullptr,
CLSCTX_INPROC_SERVER, CLSCTX_INPROC_SERVER,
@@ -23,8 +29,10 @@ void Tasklist::update() {
winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put()));
} }
bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons) { bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons)
if (!automation || !element) { {
if (!automation || !element)
{
return false; return false;
} }
winrt::com_ptr<IUIAutomationElementArray> elements; winrt::com_ptr<IUIAutomationElementArray> elements;
@@ -38,29 +46,39 @@ bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons) {
winrt::com_ptr<IUIAutomationElement> child; winrt::com_ptr<IUIAutomationElement> child;
std::vector<TasklistButton> found_butttons; std::vector<TasklistButton> found_butttons;
found_butttons.reserve(count); found_butttons.reserve(count);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i)
{
child = nullptr; child = nullptr;
if (elements->GetElement(i, child.put()) < 0) if (elements->GetElement(i, child.put()) < 0)
return false; return false;
TasklistButton button; TasklistButton button;
if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) { if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0)
if (var_rect.vt == (VT_R8 | VT_ARRAY)) { {
if (var_rect.vt == (VT_R8 | VT_ARRAY))
{
LONG pos; LONG pos;
double value; double value;
pos = 0; SafeArrayGetElement(var_rect.parray, &pos, &value); pos = 0;
SafeArrayGetElement(var_rect.parray, &pos, &value);
button.x = (long)value; button.x = (long)value;
pos = 1; SafeArrayGetElement(var_rect.parray, &pos, &value); pos = 1;
SafeArrayGetElement(var_rect.parray, &pos, &value);
button.y = (long)value; button.y = (long)value;
pos = 2; SafeArrayGetElement(var_rect.parray, &pos, &value); pos = 2;
SafeArrayGetElement(var_rect.parray, &pos, &value);
button.width = (long)value; button.width = (long)value;
pos = 3; SafeArrayGetElement(var_rect.parray, &pos, &value); pos = 3;
SafeArrayGetElement(var_rect.parray, &pos, &value);
button.height = (long)value; button.height = (long)value;
} }
VariantClear(&var_rect); VariantClear(&var_rect);
} else { }
else
{
return false; return false;
} }
if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) { if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0)
{
button.name = automation_id; button.name = automation_id;
SysFreeString(automation_id); SysFreeString(automation_id);
} }
@@ -68,11 +86,15 @@ bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons) {
} }
// assign keynums // assign keynums
buttons.clear(); buttons.clear();
for (auto& button : found_butttons) { for (auto& button : found_butttons)
if (buttons.empty()) { {
if (buttons.empty())
{
button.keynum = 1; button.keynum = 1;
buttons.push_back(std::move(button)); buttons.push_back(std::move(button));
} else { }
else
{
if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row
break; break;
if (button.name == buttons.back().name) if (button.name == buttons.back().name)
@@ -86,7 +108,8 @@ bool Tasklist::update_buttons(std::vector<TasklistButton>& buttons) {
return true; return true;
} }
std::vector<TasklistButton> Tasklist::get_buttons() { std::vector<TasklistButton> Tasklist::get_buttons()
{
std::vector<TasklistButton> buttons; std::vector<TasklistButton> buttons;
update_buttons(buttons); update_buttons(buttons);
return buttons; return buttons;

View File

@@ -5,16 +5,19 @@
#include <Windows.h> #include <Windows.h>
#include <UIAutomationClient.h> #include <UIAutomationClient.h>
struct TasklistButton { struct TasklistButton
{
std::wstring name; std::wstring name;
long x, y, width, height, keynum; long x, y, width, height, keynum;
}; };
class Tasklist { class Tasklist
{
public: public:
void update(); void update();
std::vector<TasklistButton> get_buttons(); std::vector<TasklistButton> get_buttons();
bool update_buttons(std::vector<TasklistButton>& buttons); bool update_buttons(std::vector<TasklistButton>& buttons);
private: private:
winrt::com_ptr<IUIAutomation> automation; winrt::com_ptr<IUIAutomation> automation;
winrt::com_ptr<IUIAutomationElement> element; winrt::com_ptr<IUIAutomationElement> element;

View File

@@ -6,31 +6,37 @@
#include <accctrl.h> #include <accctrl.h>
#include <aclapi.h> #include <aclapi.h>
class TwoWayPipeMessageIPC { class TwoWayPipeMessageIPC
{
public: public:
typedef void (*callback_function)(const std::wstring&); typedef void (*callback_function)(const std::wstring&);
void send(std::wstring msg) { void send(std::wstring msg)
{
output_queue.queue_message(msg); output_queue.queue_message(msg);
} }
TwoWayPipeMessageIPC(std::wstring _input_pipe_name, std::wstring _output_pipe_name, callback_function p_func) { TwoWayPipeMessageIPC(std::wstring _input_pipe_name, std::wstring _output_pipe_name, callback_function p_func)
{
input_pipe_name = _input_pipe_name; input_pipe_name = _input_pipe_name;
output_pipe_name = _output_pipe_name; output_pipe_name = _output_pipe_name;
dispatch_inc_message_function = p_func; dispatch_inc_message_function = p_func;
} }
void start(HANDLE _restricted_pipe_token) { void start(HANDLE _restricted_pipe_token)
{
output_queue_thread = std::thread(&TwoWayPipeMessageIPC::consume_output_queue_thread, this); output_queue_thread = std::thread(&TwoWayPipeMessageIPC::consume_output_queue_thread, this);
input_queue_thread = std::thread(&TwoWayPipeMessageIPC::consume_input_queue_thread, this); input_queue_thread = std::thread(&TwoWayPipeMessageIPC::consume_input_queue_thread, this);
input_pipe_thread = std::thread(&TwoWayPipeMessageIPC::start_named_pipe_server, this, _restricted_pipe_token); input_pipe_thread = std::thread(&TwoWayPipeMessageIPC::start_named_pipe_server, this, _restricted_pipe_token);
} }
void end() { void end()
{
closed = true; closed = true;
input_queue.interrupt(); input_queue.interrupt();
input_queue_thread.join(); input_queue_thread.join();
output_queue.interrupt(); output_queue.interrupt();
output_queue_thread.join(); output_queue_thread.join();
pipe_connect_handle_mutex.lock(); pipe_connect_handle_mutex.lock();
if (current_connect_pipe_handle != NULL) { if (current_connect_pipe_handle != NULL)
{
//Cancels the Pipe currently waiting for a connection. //Cancels the Pipe currently waiting for a connection.
CancelIoEx(current_connect_pipe_handle, NULL); CancelIoEx(current_connect_pipe_handle, NULL);
} }
@@ -53,7 +59,8 @@ private:
TwoWayPipeMessageIPC::callback_function dispatch_inc_message_function; TwoWayPipeMessageIPC::callback_function dispatch_inc_message_function;
const DWORD BUFSIZE = 1024; const DWORD BUFSIZE = 1024;
void send_pipe_message(std::wstring message) { void send_pipe_message(std::wstring message)
{
// Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-client // Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-client
HANDLE output_pipe_handle; HANDLE output_pipe_handle;
const wchar_t* message_send = message.c_str(); const wchar_t* message_send = message.c_str();
@@ -63,7 +70,8 @@ private:
// Try to open a named pipe; wait for it, if necessary. // Try to open a named pipe; wait for it, if necessary.
while (1) { while (1)
{
output_pipe_handle = CreateFile( output_pipe_handle = CreateFile(
lpszPipename, // pipe name lpszPipename, // pipe name
GENERIC_READ | // read and write access GENERIC_READ | // read and write access
@@ -81,14 +89,15 @@ private:
// Exit if an error other than ERROR_PIPE_BUSY occurs. // Exit if an error other than ERROR_PIPE_BUSY occurs.
DWORD curr_error = 0; DWORD curr_error = 0;
if ((curr_error = GetLastError()) != ERROR_PIPE_BUSY) { if ((curr_error = GetLastError()) != ERROR_PIPE_BUSY)
{
return; return;
} }
// All pipe instances are busy, so wait for 20 seconds. // All pipe instances are busy, so wait for 20 seconds.
if (!WaitNamedPipe(lpszPipename, 20000)) { if (!WaitNamedPipe(lpszPipename, 20000))
{
return; return;
} }
} }
@@ -98,7 +107,8 @@ private:
&dwMode, // new pipe mode &dwMode, // new pipe mode
NULL, // don't set maximum bytes NULL, // don't set maximum bytes
NULL); // don't set maximum time NULL); // don't set maximum time
if (!fSuccess) { if (!fSuccess)
{
return; return;
} }
@@ -112,24 +122,29 @@ private:
cbToWrite, // message length cbToWrite, // message length
&cbWritten, // bytes written &cbWritten, // bytes written
NULL); // not overlapped NULL); // not overlapped
if (!fSuccess) { if (!fSuccess)
{
return; return;
} }
CloseHandle(output_pipe_handle); CloseHandle(output_pipe_handle);
return; return;
} }
void consume_output_queue_thread() { void consume_output_queue_thread()
while (!closed) { {
while (!closed)
{
std::wstring message = output_queue.pop_message(); std::wstring message = output_queue.pop_message();
if (message.length() == 0) { if (message.length() == 0)
{
break; break;
} }
send_pipe_message(message); send_pipe_message(message);
} }
} }
BOOL GetLogonSID(HANDLE hToken, PSID *ppsid) { BOOL GetLogonSID(HANDLE hToken, PSID* ppsid)
{
// From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85) // From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85)
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
DWORD dwIndex; DWORD dwIndex;
@@ -148,12 +163,14 @@ private:
(LPVOID)ptg, // pointer to TOKEN_GROUPS buffer (LPVOID)ptg, // pointer to TOKEN_GROUPS buffer
0, // size of buffer 0, // size of buffer
&dwLength // receives required buffer size &dwLength // receives required buffer size
)) { ))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto Cleanup; goto Cleanup;
ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwLength); HEAP_ZERO_MEMORY,
dwLength);
if (ptg == NULL) if (ptg == NULL)
goto Cleanup; goto Cleanup;
@@ -167,23 +184,26 @@ private:
(LPVOID)ptg, // pointer to TOKEN_GROUPS buffer (LPVOID)ptg, // pointer to TOKEN_GROUPS buffer
dwLength, // size of buffer dwLength, // size of buffer
&dwLength // receives required buffer size &dwLength // receives required buffer size
)) { ))
{
goto Cleanup; goto Cleanup;
} }
// Loop through the groups to find the logon SID. // Loop through the groups to find the logon SID.
for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++)
if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
== SE_GROUP_LOGON_ID) { {
// Found the logon SID; make a copy of it. // Found the logon SID; make a copy of it.
dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid); dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
*ppsid = (PSID)HeapAlloc(GetProcessHeap(), *ppsid = (PSID)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwLength); HEAP_ZERO_MEMORY,
dwLength);
if (*ppsid == NULL) if (*ppsid == NULL)
goto Cleanup; goto Cleanup;
if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid)) { if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid))
{
HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
goto Cleanup; goto Cleanup;
} }
@@ -202,20 +222,22 @@ private:
return bSuccess; return bSuccess;
} }
VOID FreeLogonSID(PSID *ppsid) { VOID FreeLogonSID(PSID* ppsid)
{
// From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85) // From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85)
HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
} }
int change_pipe_security_allow_restricted_token(HANDLE handle, HANDLE token)
int change_pipe_security_allow_restricted_token(HANDLE handle, HANDLE token) { {
PACL old_dacl, new_dacl; PACL old_dacl, new_dacl;
PSECURITY_DESCRIPTOR sd; PSECURITY_DESCRIPTOR sd;
EXPLICIT_ACCESS ea; EXPLICIT_ACCESS ea;
PSID user_restricted; PSID user_restricted;
int error; int error;
if (!GetLogonSID(token, &user_restricted)) { if (!GetLogonSID(token, &user_restricted))
{
error = 5; // No access error. error = 5; // No access error.
goto Ldone; goto Ldone;
} }
@@ -227,7 +249,8 @@ private:
NULL, NULL,
&old_dacl, &old_dacl,
NULL, NULL,
&sd)) { &sd))
{
error = GetLastError(); error = GetLastError();
goto Lclean_sid; goto Lclean_sid;
} }
@@ -242,7 +265,8 @@ private:
ea.Trustee.TrusteeType = TRUSTEE_IS_USER; ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
ea.Trustee.ptstrName = (LPTSTR)user_restricted; ea.Trustee.ptstrName = (LPTSTR)user_restricted;
if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) { if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl))
{
error = GetLastError(); error = GetLastError();
goto Lclean_sd; goto Lclean_sd;
} }
@@ -253,7 +277,8 @@ private:
NULL, NULL,
NULL, NULL,
new_dacl, new_dacl,
NULL)) { NULL))
{
error = GetLastError(); error = GetLastError();
goto Lclean_dacl; goto Lclean_dacl;
} }
@@ -270,21 +295,25 @@ private:
return error; return error;
} }
HANDLE create_medium_integrity_token() { HANDLE create_medium_integrity_token()
{
HANDLE restricted_token_handle; HANDLE restricted_token_handle;
SAFER_LEVEL_HANDLE level_handle = NULL; SAFER_LEVEL_HANDLE level_handle = NULL;
DWORD sid_size = SECURITY_MAX_SID_SIZE; DWORD sid_size = SECURITY_MAX_SID_SIZE;
BYTE medium_sid[SECURITY_MAX_SID_SIZE]; BYTE medium_sid[SECURITY_MAX_SID_SIZE];
if (!SaferCreateLevel(SAFER_SCOPEID_USER, SAFER_LEVELID_NORMALUSER, SAFER_LEVEL_OPEN, &level_handle, NULL)) { if (!SaferCreateLevel(SAFER_SCOPEID_USER, SAFER_LEVELID_NORMALUSER, SAFER_LEVEL_OPEN, &level_handle, NULL))
{
return NULL; return NULL;
} }
if (!SaferComputeTokenFromLevel(level_handle, NULL, &restricted_token_handle, 0, NULL)) { if (!SaferComputeTokenFromLevel(level_handle, NULL, &restricted_token_handle, 0, NULL))
{
SaferCloseLevel(level_handle); SaferCloseLevel(level_handle);
return NULL; return NULL;
} }
SaferCloseLevel(level_handle); SaferCloseLevel(level_handle);
if (!CreateWellKnownSid(WinMediumLabelSid, nullptr, medium_sid, &sid_size)) { if (!CreateWellKnownSid(WinMediumLabelSid, nullptr, medium_sid, &sid_size))
{
CloseHandle(restricted_token_handle); CloseHandle(restricted_token_handle);
return NULL; return NULL;
} }
@@ -293,7 +322,8 @@ private:
integrity_level.Label.Attributes = SE_GROUP_INTEGRITY; integrity_level.Label.Attributes = SE_GROUP_INTEGRITY;
integrity_level.Label.Sid = reinterpret_cast<PSID>(medium_sid); integrity_level.Label.Sid = reinterpret_cast<PSID>(medium_sid);
if (!SetTokenInformation(restricted_token_handle, TokenIntegrityLevel, &integrity_level, sizeof(integrity_level))) { if (!SetTokenInformation(restricted_token_handle, TokenIntegrityLevel, &integrity_level, sizeof(integrity_level)))
{
CloseHandle(restricted_token_handle); CloseHandle(restricted_token_handle);
return NULL; return NULL;
} }
@@ -301,7 +331,8 @@ private:
return restricted_token_handle; return restricted_token_handle;
} }
void handle_pipe_connection(HANDLE input_pipe_handle) { void handle_pipe_connection(HANDLE input_pipe_handle)
{
//Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server //Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server
HANDLE hHeap = GetProcessHeap(); HANDLE hHeap = GetProcessHeap();
uint8_t* pchRequest = (uint8_t*)HeapAlloc(hHeap, 0, BUFSIZE * sizeof(uint8_t)); uint8_t* pchRequest = (uint8_t*)HeapAlloc(hHeap, 0, BUFSIZE * sizeof(uint8_t));
@@ -312,17 +343,21 @@ private:
// Do some extra error checking since the app will keep running even if this thread fails. // Do some extra error checking since the app will keep running even if this thread fails.
std::list<std::vector<uint8_t>> message_parts; std::list<std::vector<uint8_t>> message_parts;
if (input_pipe_handle == NULL) { if (input_pipe_handle == NULL)
if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest); {
if (pchRequest != NULL)
HeapFree(hHeap, 0, pchRequest);
return; return;
} }
if (pchRequest == NULL) { if (pchRequest == NULL)
{
return; return;
} }
// Loop until done reading // Loop until done reading
do { do
{
// Read client requests from the pipe. This simplistic code only allows messages // Read client requests from the pipe. This simplistic code only allows messages
// up to BUFSIZE characters in length. // up to BUFSIZE characters in length.
ZeroMemory(pchRequest, BUFSIZE * sizeof(uint8_t)); ZeroMemory(pchRequest, BUFSIZE * sizeof(uint8_t));
@@ -333,7 +368,8 @@ private:
&cbBytesRead, // number of bytes read &cbBytesRead, // number of bytes read
NULL); // not overlapped I/O NULL); // not overlapped I/O
if (!fSuccess && GetLastError() != ERROR_MORE_DATA) { if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
{
break; break;
} }
std::vector<uint8_t> part_vector; std::vector<uint8_t> part_vector;
@@ -342,15 +378,18 @@ private:
message_parts.push_back(part_vector); message_parts.push_back(part_vector);
} while (!fSuccess); } while (!fSuccess);
if (fSuccess) { if (fSuccess)
{
// Reconstruct the total_message. // Reconstruct the total_message.
std::vector<uint8_t> reconstructed_message; std::vector<uint8_t> reconstructed_message;
size_t total_size = 0; size_t total_size = 0;
for (auto& part_vector : message_parts) { for (auto& part_vector : message_parts)
{
total_size += part_vector.size(); total_size += part_vector.size();
} }
reconstructed_message.reserve(total_size); reconstructed_message.reserve(total_size);
for (auto& part_vector : message_parts) { for (auto& part_vector : message_parts)
{
std::move(part_vector.begin(), part_vector.end(), std::back_inserter(reconstructed_message)); std::move(part_vector.begin(), part_vector.end(), std::back_inserter(reconstructed_message));
} }
std::wstring unicode_msg; std::wstring unicode_msg;
@@ -371,12 +410,14 @@ private:
printf("InstanceThread exitting.\n"); printf("InstanceThread exitting.\n");
} }
void start_named_pipe_server(HANDLE token) { void start_named_pipe_server(HANDLE token)
{
// Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server // Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server
const wchar_t* pipe_name = input_pipe_name.c_str(); const wchar_t* pipe_name = input_pipe_name.c_str();
BOOL connected = FALSE; BOOL connected = FALSE;
HANDLE connect_pipe_handle = INVALID_HANDLE_VALUE; HANDLE connect_pipe_handle = INVALID_HANDLE_VALUE;
while(!closed) { while (!closed)
{
{ {
std::unique_lock lock(pipe_connect_handle_mutex); std::unique_lock lock(pipe_connect_handle_mutex);
connect_pipe_handle = CreateNamedPipe( connect_pipe_handle = CreateNamedPipe(
@@ -390,14 +431,15 @@ private:
BUFSIZE, BUFSIZE,
BUFSIZE, BUFSIZE,
0, 0,
NULL NULL);
);
if (connect_pipe_handle == INVALID_HANDLE_VALUE) { if (connect_pipe_handle == INVALID_HANDLE_VALUE)
{
return; return;
} }
if (token != NULL) { if (token != NULL)
{
int err = change_pipe_security_allow_restricted_token(connect_pipe_handle, token); int err = change_pipe_security_allow_restricted_token(connect_pipe_handle, token);
} }
current_connect_pipe_handle = connect_pipe_handle; current_connect_pipe_handle = connect_pipe_handle;
@@ -407,23 +449,28 @@ private:
std::unique_lock lock(pipe_connect_handle_mutex); std::unique_lock lock(pipe_connect_handle_mutex);
current_connect_pipe_handle = NULL; current_connect_pipe_handle = NULL;
} }
if (connected) { if (connected)
{
std::thread(&TwoWayPipeMessageIPC::handle_pipe_connection, this, connect_pipe_handle).detach(); std::thread(&TwoWayPipeMessageIPC::handle_pipe_connection, this, connect_pipe_handle).detach();
} else { }
else
{
// Client could not connect. // Client could not connect.
CloseHandle(connect_pipe_handle); CloseHandle(connect_pipe_handle);
} }
} }
} }
void consume_input_queue_thread() { void consume_input_queue_thread()
while (!closed) { {
while (!closed)
{
std::wstring message = input_queue.pop_message(); std::wstring message = input_queue.pop_message();
if (message.length() == 0) { if (message.length() == 0)
{
break; break;
} }
dispatch_inc_message_function(message); dispatch_inc_message_function(message);
} }
} }
}; };

View File

@@ -8,11 +8,12 @@
#define VERSION_REVISION 2 #define VERSION_REVISION 2
#define FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, 0 #define FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, 0
#define FILE_VERSION_STRING STRINGIZE(VERSION_MAJOR) "." STRINGIZE(VERSION_MINOR) "." STRINGIZE(VERSION_REVISION) ".0" #define FILE_VERSION_STRING \
STRINGIZE(VERSION_MAJOR) \
"." STRINGIZE(VERSION_MINOR) "." STRINGIZE(VERSION_REVISION) ".0"
#define PRODUCT_VERSION FILE_VERSION #define PRODUCT_VERSION FILE_VERSION
#define PRODUCT_VERSION_STRING FILE_VERSION_STRING #define PRODUCT_VERSION_STRING FILE_VERSION_STRING
#define COMPANY_NAME "Microsoft Corporation" #define COMPANY_NAME "Microsoft Corporation"
#define COPYRIGHT_NOTE "Copyright (C) 2019 Microsoft Corporation" #define COPYRIGHT_NOTE "Copyright (C) 2019 Microsoft Corporation"

View File

@@ -1,62 +1,76 @@
#include "pch.h" #include "pch.h"
#include "windows_colors.h" #include "windows_colors.h"
DWORD WindowsColors::rgb_color(DWORD abgr_color) { DWORD WindowsColors::rgb_color(DWORD abgr_color)
{
// registry keeps the colors in ABGR format, we want RGB // registry keeps the colors in ABGR format, we want RGB
auto r = (abgr_color & 0xFF); auto r = (abgr_color & 0xFF);
auto g = (abgr_color & 0xFF00) >> 8; auto g = (abgr_color & 0xFF00) >> 8;
auto b = (abgr_color & 0xFF0000) >> 16; auto b = (abgr_color & 0xFF0000) >> 16;
return (r << 16) | (g << 8) | b; return (r << 16) | (g << 8) | b;
} }
DWORD WindowsColors::rgb_color(winrt::Windows::UI::Color color) { DWORD WindowsColors::rgb_color(winrt::Windows::UI::Color color)
{
return ((DWORD)color.R << 16) | ((DWORD)color.G << 8) | ((DWORD)color.B); return ((DWORD)color.R << 16) | ((DWORD)color.G << 8) | ((DWORD)color.B);
} }
WindowsColors::Color WindowsColors::get_button_face_color() { WindowsColors::Color WindowsColors::get_button_face_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace); return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace);
} }
WindowsColors::Color WindowsColors::get_button_text_color() { WindowsColors::Color WindowsColors::get_button_text_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonText); return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonText);
} }
WindowsColors::Color WindowsColors::get_highlight_color() { WindowsColors::Color WindowsColors::get_highlight_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Highlight); return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Highlight);
} }
WindowsColors::Color WindowsColors::get_hotlight_color() { WindowsColors::Color WindowsColors::get_hotlight_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Hotlight); return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Hotlight);
} }
WindowsColors::Color WindowsColors::get_highlight_text_color() { WindowsColors::Color WindowsColors::get_highlight_text_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::HighlightText); return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::HighlightText);
} }
WindowsColors::Color WindowsColors::get_accent_light_1_color() { WindowsColors::Color WindowsColors::get_accent_light_1_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight1); return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight1);
} }
WindowsColors::Color WindowsColors::get_accent_light_2_color() { WindowsColors::Color WindowsColors::get_accent_light_2_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight2); return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight2);
} }
WindowsColors::Color WindowsColors::get_accent_dark_1_color() { WindowsColors::Color WindowsColors::get_accent_dark_1_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentDark1); return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentDark1);
} }
WindowsColors::Color WindowsColors::get_accent_color() { WindowsColors::Color WindowsColors::get_accent_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Accent); return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Accent);
} }
WindowsColors::Color WindowsColors::get_background_color() { WindowsColors::Color WindowsColors::get_background_color()
{
winrt::Windows::UI::ViewManagement::UISettings uiSettings; winrt::Windows::UI::ViewManagement::UISettings uiSettings;
return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Background); return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Background);
} }
bool WindowsColors::is_dark_mode() { bool WindowsColors::is_dark_mode()
{
return rgb_color(get_background_color()) == 0; return rgb_color(get_background_color()) == 0;
} }
bool WindowsColors::update() { bool WindowsColors::update()
{
auto new_accent_color_menu = rgb_color(get_accent_color()); auto new_accent_color_menu = rgb_color(get_accent_color());
auto new_start_color_menu = new_accent_color_menu; auto new_start_color_menu = new_accent_color_menu;
auto new_desktop_fill_color = rgb_color(GetSysColor(COLOR_DESKTOP)); auto new_desktop_fill_color = rgb_color(GetSysColor(COLOR_DESKTOP));

View File

@@ -1,7 +1,8 @@
#pragma once #pragma once
#include <winrt/Windows.UI.ViewManagement.h> #include <winrt/Windows.UI.ViewManagement.h>
struct WindowsColors { struct WindowsColors
{
using Color = winrt::Windows::UI::Color; using Color = winrt::Windows::UI::Color;
static DWORD rgb_color(DWORD abgr_color); static DWORD rgb_color(DWORD abgr_color);

View File

@@ -4,7 +4,6 @@
#include <winrt/Windows.ApplicationModel.h> #include <winrt/Windows.ApplicationModel.h>
namespace winstore namespace winstore
{ {
using winrt::Windows::ApplicationModel::StartupTaskState; using winrt::Windows::ApplicationModel::StartupTaskState;

View File

@@ -317,7 +317,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
int result = 0; int result = 0;
try try
{ {
std::thread{ [] { std::thread{ [] {
github_update_checking_worker(); github_update_checking_worker();
} }.detach(); } }.detach();

View File

@@ -99,7 +99,8 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
// Shell_NotifyIcon can fail when we invoke it during the time explorer.exe isn't present/ready to handle it. // Shell_NotifyIcon can fail when we invoke it during the time explorer.exe isn't present/ready to handle it.
// We'll also never receive wm_taskbar_restart message if the first call to Shell_NotifyIcon failed, so we use // We'll also never receive wm_taskbar_restart message if the first call to Shell_NotifyIcon failed, so we use
// WM_WINDOWPOSCHANGING which is always received on explorer startup sequence. // WM_WINDOWPOSCHANGING which is always received on explorer startup sequence.
case WM_WINDOWPOSCHANGING: { case WM_WINDOWPOSCHANGING:
{
if (!tray_icon_created) if (!tray_icon_created)
{ {
tray_icon_created = Shell_NotifyIcon(NIM_ADD, &tray_icon_data) == TRUE; tray_icon_created = Shell_NotifyIcon(NIM_ADD, &tray_icon_data) == TRUE;
@@ -111,12 +112,14 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
{ {
switch (lparam) switch (lparam)
{ {
case WM_LBUTTONUP: { case WM_LBUTTONUP:
{
open_settings_window(); open_settings_window();
break; break;
} }
case WM_RBUTTONUP: case WM_RBUTTONUP:
case WM_CONTEXTMENU: { case WM_CONTEXTMENU:
{
if (!h_menu) if (!h_menu)
{ {
h_menu = LoadMenu(reinterpret_cast<HINSTANCE>(&__ImageBase), MAKEINTRESOURCE(ID_TRAY_MENU)); h_menu = LoadMenu(reinterpret_cast<HINSTANCE>(&__ImageBase), MAKEINTRESOURCE(ID_TRAY_MENU));

View File

@@ -339,7 +339,8 @@ LRESULT CALLBACK wnd_proc_static(HWND hWnd, UINT message, WPARAM wParam, LPARAM
wm_data_for_webview = RegisterWindowMessageW(L"PTSettingsCopyDataWebView"); wm_data_for_webview = RegisterWindowMessageW(L"PTSettingsCopyDataWebView");
wm_destroy_window = RegisterWindowMessageW(L"PTSettingsParentTerminated"); wm_destroy_window = RegisterWindowMessageW(L"PTSettingsParentTerminated");
break; break;
case WM_DPICHANGED: { case WM_DPICHANGED:
{
// Resize the window using the suggested rect // Resize the window using the suggested rect
RECT* const prcNewWindow = (RECT*)lParam; RECT* const prcNewWindow = (RECT*)lParam;
SetWindowPos(hWnd, SetWindowPos(hWnd,
@@ -351,7 +352,8 @@ LRESULT CALLBACK wnd_proc_static(HWND hWnd, UINT message, WPARAM wParam, LPARAM
SWP_NOZORDER | SWP_NOACTIVATE); SWP_NOZORDER | SWP_NOACTIVATE);
} }
break; break;
case WM_NCCREATE: { case WM_NCCREATE:
{
// Enable auto-resizing the title bar // Enable auto-resizing the title bar
EnableNonClientDpiScaling(hWnd); EnableNonClientDpiScaling(hWnd);
} }