mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-10 21:41:51 +02:00
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:
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(¤t);
|
d2d_dc->GetTransform(¤t);
|
||||||
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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public:
|
|||||||
void hide();
|
void hide();
|
||||||
void initialize();
|
void initialize();
|
||||||
virtual ~D2DWindow();
|
virtual ~D2DWindow();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Implement this:
|
// Implement this:
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()>;
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,3 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
bool is_start_visible();
|
bool is_start_visible();
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user