From cf1b53831f66e41b6e08758627bcb011b4b457d2 Mon Sep 17 00:00:00 2001 From: Andrey Nekrasov Date: Thu, 5 Mar 2020 13:07:06 +0300 Subject: [PATCH] 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 --- .../format_sources.ps1 | 9 +- .clang-format => src/.clang-format | 3 +- .../UnitTests-CommonLib/Settings.Tests.cpp | 128 +-- .../UnitTestsVersionHelper.cpp | 23 +- src/common/animation.cpp | 64 +- src/common/animation.h | 31 +- src/common/async_message_queue.h | 73 +- src/common/com_object_factory.h | 4 +- src/common/common.cpp | 967 ++++++++++-------- src/common/common.h | 41 +- src/common/d2d_svg.cpp | 190 ++-- src/common/d2d_svg.h | 32 +- src/common/d2d_text.cpp | 74 +- src/common/d2d_text.h | 20 +- src/common/d2d_window.cpp | 336 +++--- src/common/d2d_window.h | 79 +- src/common/json.cpp | 30 +- src/common/json.h | 64 +- src/common/monitors.cpp | 102 +- src/common/monitors.h | 66 +- src/common/msi_to_msix_upgrade_lib/pch.cpp | 1 - src/common/notifications.cpp | 2 +- src/common/on_thread_executor.cpp | 60 +- src/common/on_thread_executor.h | 23 +- src/common/pch.h | 1 - src/common/settings_helpers.cpp | 104 +- src/common/settings_helpers.h | 16 +- src/common/settings_objects.cpp | 616 ++++++----- src/common/settings_objects.h | 374 ++++--- src/common/start_visible.cpp | 26 +- src/common/start_visible.h | 1 - src/common/tasklist_positions.cpp | 187 ++-- src/common/tasklist_positions.h | 23 +- src/common/two_way_pipe_message_ipc.h | 831 ++++++++------- src/common/version.h | 25 +- src/common/window_helpers.cpp | 2 +- src/common/windows_colors.cpp | 130 +-- src/common/windows_colors.h | 45 +- src/common/winstore.h | 1 - src/runner/main.cpp | 1 - src/runner/tray_icon.cpp | 9 +- src/settings/main.cpp | 8 +- 42 files changed, 2602 insertions(+), 2220 deletions(-) rename format_sources.ps1 => codeAnalysis/format_sources.ps1 (81%) rename .clang-format => src/.clang-format (94%) diff --git a/format_sources.ps1 b/codeAnalysis/format_sources.ps1 similarity index 81% rename from format_sources.ps1 rename to codeAnalysis/format_sources.ps1 index f0ffa30eb..9d31d32dc 100644 --- a/format_sources.ps1 +++ b/codeAnalysis/format_sources.ps1 @@ -20,7 +20,9 @@ $sourceExtensions.Add(".cpp") | Out-Null $sourceExtensions.Add(".h") | Out-Null 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 $untracked = & git ls-files --others --exclude-standard $result = New-Object System.Collections.Generic.List[string] @@ -34,9 +36,10 @@ function Get-Dirty-Files-From-Git() { if($all) { $filesToFormat = - Get-ChildItem -Recurse -File src | + Get-ChildItem -Recurse -File ..\src | 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 { $filesToFormat = Get-Dirty-Files-From-Git diff --git a/.clang-format b/src/.clang-format similarity index 94% rename from .clang-format rename to src/.clang-format index 059a3080d..262aba2a9 100644 --- a/.clang-format +++ b/src/.clang-format @@ -65,7 +65,8 @@ IndentPPDirectives: None IndentWidth: 4 IndentWrappedFunctionNames: 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" MaxEmptyLinesToKeep: 1 NamespaceIndentation: All diff --git a/src/common/UnitTests-CommonLib/Settings.Tests.cpp b/src/common/UnitTests-CommonLib/Settings.Tests.cpp index 6cb0a11e4..853b33030 100644 --- a/src/common/UnitTests-CommonLib/Settings.Tests.cpp +++ b/src/common/UnitTests-CommonLib/Settings.Tests.cpp @@ -48,14 +48,14 @@ namespace UnitTestsCommonLib } } - TEST_CLASS(PowerToyValuesUnitTests) + TEST_CLASS (PowerToyValuesUnitTests) { private: const std::wstring m_json = L"{\"name\":\"Module Name\",\"properties\" : {\"bool_toggle_true\":{\"value\":true},\"bool_toggle_false\":{\"value\":false},\"color_picker\" : {\"value\":\"#ff8d12\"},\"int_spinner\" : {\"value\":10},\"string_text\" : {\"value\":\"a quick fox\"}},\"version\" : \"1.0\" }"; const std::wstring m_moduleName = L"Module Name"; public: - TEST_METHOD(LoadFromJsonBoolTrue) + TEST_METHOD (LoadFromJsonBoolTrue) { PowerToyValues values = PowerToyValues::from_json_string(m_json); auto value = values.get_bool_value(L"bool_toggle_true"); @@ -63,7 +63,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(true, *value); } - TEST_METHOD(LoadFromJsonBoolFalse) + TEST_METHOD (LoadFromJsonBoolFalse) { PowerToyValues values = PowerToyValues::from_json_string(m_json); auto value = values.get_bool_value(L"bool_toggle_false"); @@ -71,7 +71,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, *value); } - TEST_METHOD(LoadFromJsonInt) + TEST_METHOD (LoadFromJsonInt) { PowerToyValues values = PowerToyValues::from_json_string(m_json); auto value = values.get_int_value(L"int_spinner"); @@ -79,7 +79,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(10, *value); } - TEST_METHOD(LoadFromJsonString) + TEST_METHOD (LoadFromJsonString) { PowerToyValues values = PowerToyValues::from_json_string(m_json); auto value = values.get_string_value(L"string_text"); @@ -89,7 +89,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(expected, *value); } - TEST_METHOD(LoadFromJsonColorPicker) + TEST_METHOD (LoadFromJsonColorPicker) { PowerToyValues values = PowerToyValues::from_json_string(m_json); auto value = values.get_string_value(L"color_picker"); @@ -99,19 +99,19 @@ namespace UnitTestsCommonLib Assert::AreEqual(expected, *value); } - TEST_METHOD(LoadFromEmptyString) + TEST_METHOD (LoadFromEmptyString) { auto func = [] { PowerToyValues values = PowerToyValues::from_json_string(L""); }; Assert::ExpectException(func); } - TEST_METHOD(LoadFromInvalidString_NameMissed) + TEST_METHOD (LoadFromInvalidString_NameMissed) { auto func = [] { PowerToyValues values = PowerToyValues::from_json_string(L"{\"properties\" : {\"bool_toggle_true\":{\"value\":true},\"bool_toggle_false\":{\"value\":false},\"color_picker\" : {\"value\":\"#ff8d12\"},\"int_spinner\" : {\"value\":10},\"string_text\" : {\"value\":\"a quick fox\"}},\"version\" : \"1.0\" }"); }; Assert::ExpectException(func); } - TEST_METHOD(LoadFromInvalidString_VersionMissed) + TEST_METHOD (LoadFromInvalidString_VersionMissed) { PowerToyValues values = PowerToyValues::from_json_string(L"{\"name\":\"Module Name\",\"properties\" : {}}"); const std::wstring expectedStr = L"{\"name\" : \"Module Name\", \"properties\" : {},\"version\" : \"1.0\"}"; @@ -121,7 +121,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(LoadFromInvalidString_PropertiesMissed) + TEST_METHOD (LoadFromInvalidString_PropertiesMissed) { PowerToyValues values = PowerToyValues::from_json_string(L"{\"name\":\"Module Name\",\"version\" : \"1.0\" }"); const std::wstring expectedStr = L"{\"name\":\"Module Name\",\"version\" : \"1.0\" }"; @@ -131,7 +131,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(LoadFromValidString_EmptyProperties) + TEST_METHOD (LoadFromValidString_EmptyProperties) { PowerToyValues values = PowerToyValues::from_json_string(L"{\"name\":\"Module Name\",\"properties\" : {}, \"version\" : \"1.0\" }"); const std::wstring expectedStr = L"{\"name\":\"Module Name\",\"properties\" : {},\"version\" : \"1.0\" }"; @@ -141,7 +141,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(LoadFromValidString_ChangedVersion) + TEST_METHOD (LoadFromValidString_ChangedVersion) { PowerToyValues values = PowerToyValues::from_json_string(L"{\"name\":\"Module Name\",\"properties\" : {},\"version\" : \"2.0\"}"); const std::wstring expectedStr = L"{\"name\" : \"Module Name\", \"properties\" : {},\"version\" : \"1.0\"}"; //version from input json is ignored @@ -152,7 +152,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(CreateWithName) + TEST_METHOD (CreateWithName) { PowerToyValues values(m_moduleName); const std::wstring expectedStr = L"{\"name\":\"Module Name\",\"properties\" : {},\"version\" : \"1.0\" }"; @@ -163,7 +163,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(AddPropertyBoolPositive) + TEST_METHOD (AddPropertyBoolPositive) { PowerToyValues values(m_moduleName); values.add_property(L"positive_bool_value", true); @@ -173,7 +173,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(true, *value); } - TEST_METHOD(AddPropertyBoolNegative) + TEST_METHOD (AddPropertyBoolNegative) { PowerToyValues values(m_moduleName); values.add_property(L"negative_bool_value", false); @@ -183,7 +183,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, *value); } - TEST_METHOD(AddPropertyIntPositive) + TEST_METHOD (AddPropertyIntPositive) { PowerToyValues values(m_moduleName); const int intVal = 4392854; @@ -194,7 +194,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(intVal, *value); } - TEST_METHOD(AddPropertyIntNegative) + TEST_METHOD (AddPropertyIntNegative) { PowerToyValues values(m_moduleName); const int intVal = -4392854; @@ -205,7 +205,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(intVal, *value); } - TEST_METHOD(AddPropertyIntZero) + TEST_METHOD (AddPropertyIntZero) { PowerToyValues values(m_moduleName); const int intVal = 0; @@ -216,7 +216,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(intVal, *value); } - TEST_METHOD(AddPropertyStringEmpty) + TEST_METHOD (AddPropertyStringEmpty) { PowerToyValues values(m_moduleName); const std::wstring stringVal = L""; @@ -227,7 +227,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(stringVal, *value); } - TEST_METHOD(AddPropertyString) + TEST_METHOD (AddPropertyString) { PowerToyValues values(m_moduleName); const std::wstring stringVal = L"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; @@ -238,7 +238,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(stringVal, *value); } - TEST_METHOD(AddPropertyJsonEmpty) + TEST_METHOD (AddPropertyJsonEmpty) { PowerToyValues values(m_moduleName); const auto json = json::JsonObject(); @@ -249,7 +249,7 @@ namespace UnitTestsCommonLib compareJsons(json, *value); } - TEST_METHOD(AddPropertyJsonObject) + TEST_METHOD (AddPropertyJsonObject) { PowerToyValues values(m_moduleName); const auto json = json::JsonObject::Parse(m_json); @@ -261,7 +261,7 @@ namespace UnitTestsCommonLib } }; - TEST_CLASS(SettingsUnitTests) + TEST_CLASS (SettingsUnitTests) { private: const std::wstring m_moduleName = L"Module Name"; @@ -279,7 +279,7 @@ namespace UnitTestsCommonLib } public: - TEST_METHOD(SettingsSerialization) + TEST_METHOD (SettingsSerialization) { Settings settings(nullptr, m_moduleName); @@ -288,7 +288,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsSerializationToBuffer) + TEST_METHOD (SettingsSerializationToBuffer) { Settings settings(nullptr, m_moduleName); @@ -307,7 +307,7 @@ namespace UnitTestsCommonLib compareJsons(m_defaultSettingsJson, actualJson); } - TEST_METHOD(SettingsSetDescription) + TEST_METHOD (SettingsSetDescription) { const auto value = L"description value"; Settings settings(nullptr, m_moduleName); @@ -320,7 +320,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsSetIconKey) + TEST_METHOD (SettingsSetIconKey) { const auto value = L"icon key"; Settings settings(nullptr, m_moduleName); @@ -333,7 +333,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsSetOverviewLink) + TEST_METHOD (SettingsSetOverviewLink) { const auto value = L"overview link"; Settings settings(nullptr, m_moduleName); @@ -346,7 +346,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsSetVideoLink) + TEST_METHOD (SettingsSetVideoLink) { const auto value = L"video link"; Settings settings(nullptr, m_moduleName); @@ -359,7 +359,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddBoolTogglePositive) + TEST_METHOD (SettingsAddBoolTogglePositive) { const auto value = true; @@ -376,7 +376,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddBoolToggleNegative) + TEST_METHOD (SettingsAddBoolToggleNegative) { const auto value = false; @@ -393,7 +393,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddSpinner) + TEST_METHOD (SettingsAddSpinner) { const int value = 738543; const int min = 0; @@ -416,7 +416,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddString) + TEST_METHOD (SettingsAddString) { const auto value = L"string text "; @@ -433,7 +433,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddStringMultiline) + TEST_METHOD (SettingsAddStringMultiline) { const auto value = L"Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit,\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident,\nsunt in culpa qui officia deserunt mollit anim id est laborum."; @@ -451,7 +451,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddColorPicker) + TEST_METHOD (SettingsAddColorPicker) { const auto value = L"#ffffff"; @@ -468,7 +468,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddHotkey) + TEST_METHOD (SettingsAddHotkey) { const auto value = PowerToysSettings::HotkeyObject::from_settings(true, true, true, true, 0); @@ -485,7 +485,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddChoiceGroup) + TEST_METHOD (SettingsAddChoiceGroup) { const auto value = L"choice group value"; const auto keysAndTexts = { @@ -516,7 +516,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddChoiceGroupEmpty) + TEST_METHOD (SettingsAddChoiceGroupEmpty) { const auto value = L"choice group value"; @@ -534,7 +534,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddDropdown) + TEST_METHOD (SettingsAddDropdown) { const auto value = L"dropdown value"; const auto keysAndTexts = { @@ -565,7 +565,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddDropdownEmpty) + TEST_METHOD (SettingsAddDropdownEmpty) { const auto value = L"dropdown value"; @@ -582,7 +582,7 @@ namespace UnitTestsCommonLib compareJsons(expected, actual); } - TEST_METHOD(SettingsAddCustomAction) + TEST_METHOD (SettingsAddCustomAction) { const auto value = L"custom action value"; const std::wstring buttonText = L"button text"; @@ -602,17 +602,17 @@ namespace UnitTestsCommonLib } }; - TEST_CLASS(CustomActionObjectUnitTests) + TEST_CLASS (CustomActionObjectUnitTests) { public: - TEST_METHOD(CustomActionObjectName) + TEST_METHOD (CustomActionObjectName) { const std::wstring json = L"{\"action_name\": \"action name\", \"value\": \"action value\"}"; CustomActionObject obj = CustomActionObject::from_json_string(json); Assert::AreEqual(std::wstring(L"action name"), obj.get_name()); } - TEST_METHOD(CustomActionObjectValue) + TEST_METHOD (CustomActionObjectValue) { const std::wstring json = L"{\"action_name\": \"action name\", \"value\": \"action value\"}"; CustomActionObject obj = CustomActionObject::from_json_string(json); @@ -620,44 +620,44 @@ namespace UnitTestsCommonLib } }; - TEST_CLASS(HotkeyObjectUnitTests) + TEST_CLASS (HotkeyObjectUnitTests) { private: json::JsonObject m_defaultHotkeyJson = json::JsonObject::Parse(L"{\"key\":\"(Key 0)\", \"code\": 123, \"win\": true, \"ctrl\": true, \"alt\": true, \"shift\": true}"); json::JsonObject m_defaultHotkeyJsonAlternative = json::JsonObject::Parse(L"{\"key\":\"(Key 0)\", \"code\": 123, \"win\": false, \"ctrl\": false, \"alt\": false, \"shift\": false}"); public: - TEST_METHOD(GetKeyFromJson) + TEST_METHOD (GetKeyFromJson) { HotkeyObject object = HotkeyObject::from_json(m_defaultHotkeyJson); Assert::AreEqual(std::wstring(L"(Key 0)"), object.get_key()); } - TEST_METHOD(GetKeyFromJsonString) + TEST_METHOD (GetKeyFromJsonString) { HotkeyObject object = HotkeyObject::from_json_string(m_defaultHotkeyJson.Stringify()); Assert::AreEqual(std::wstring(L"(Key 0)"), object.get_key()); } - TEST_METHOD(GetCodeFromJson) + TEST_METHOD (GetCodeFromJson) { HotkeyObject object = HotkeyObject::from_json(m_defaultHotkeyJson); Assert::AreEqual(UINT(123), object.get_code()); } - TEST_METHOD(GetCodeFromJsonString) + TEST_METHOD (GetCodeFromJsonString) { HotkeyObject object = HotkeyObject::from_json_string(m_defaultHotkeyJson.Stringify()); Assert::AreEqual(UINT(123), object.get_code()); } - TEST_METHOD(GetCodeFromSettings) + TEST_METHOD (GetCodeFromSettings) { HotkeyObject object = HotkeyObject::from_settings(true, true, true, true, 123); Assert::AreEqual(UINT(123), object.get_code()); } - TEST_METHOD(GetWinPressedFromJson) + TEST_METHOD (GetWinPressedFromJson) { HotkeyObject object = HotkeyObject::from_json(m_defaultHotkeyJson); Assert::AreEqual(true, object.win_pressed()); @@ -666,7 +666,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.win_pressed()); } - TEST_METHOD(GetWinPressedFromJsonString) + TEST_METHOD (GetWinPressedFromJsonString) { HotkeyObject object = HotkeyObject::from_json_string(m_defaultHotkeyJson.Stringify()); Assert::AreEqual(true, object.win_pressed()); @@ -675,7 +675,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.win_pressed()); } - TEST_METHOD(GetWinPressedFromSettings) + TEST_METHOD (GetWinPressedFromSettings) { HotkeyObject object = HotkeyObject::from_settings(true, true, true, true, 123); Assert::AreEqual(true, object.win_pressed()); @@ -684,7 +684,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.win_pressed()); } - TEST_METHOD(GetCtrlPressedFromJson) + TEST_METHOD (GetCtrlPressedFromJson) { HotkeyObject object = HotkeyObject::from_json(m_defaultHotkeyJson); Assert::AreEqual(true, object.ctrl_pressed()); @@ -693,7 +693,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.ctrl_pressed()); } - TEST_METHOD(GetCtrlPressedFromJsonString) + TEST_METHOD (GetCtrlPressedFromJsonString) { HotkeyObject object = HotkeyObject::from_json_string(m_defaultHotkeyJson.Stringify()); Assert::AreEqual(true, object.ctrl_pressed()); @@ -702,7 +702,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.ctrl_pressed()); } - TEST_METHOD(GetCtrlPressedFromSettings) + TEST_METHOD (GetCtrlPressedFromSettings) { HotkeyObject object = HotkeyObject::from_settings(true, true, true, true, 123); Assert::AreEqual(true, object.ctrl_pressed()); @@ -711,7 +711,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.ctrl_pressed()); } - TEST_METHOD(GetAltPressedFromJson) + TEST_METHOD (GetAltPressedFromJson) { HotkeyObject object = HotkeyObject::from_json(m_defaultHotkeyJson); Assert::AreEqual(true, object.alt_pressed()); @@ -720,7 +720,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.alt_pressed()); } - TEST_METHOD(GetAltPressedFromJsonString) + TEST_METHOD (GetAltPressedFromJsonString) { HotkeyObject object = HotkeyObject::from_json_string(m_defaultHotkeyJson.Stringify()); Assert::AreEqual(true, object.alt_pressed()); @@ -729,7 +729,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.alt_pressed()); } - TEST_METHOD(GetAltPressedFromSettings) + TEST_METHOD (GetAltPressedFromSettings) { HotkeyObject object = HotkeyObject::from_settings(true, true, true, true, 123); Assert::AreEqual(true, object.alt_pressed()); @@ -738,7 +738,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.alt_pressed()); } - TEST_METHOD(GetShiftPressedFromJson) + TEST_METHOD (GetShiftPressedFromJson) { HotkeyObject object = HotkeyObject::from_json(m_defaultHotkeyJson); Assert::AreEqual(true, object.shift_pressed()); @@ -747,7 +747,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.shift_pressed()); } - TEST_METHOD(GetShiftPressedFromJsonString) + TEST_METHOD (GetShiftPressedFromJsonString) { HotkeyObject object = HotkeyObject::from_json_string(m_defaultHotkeyJson.Stringify()); Assert::AreEqual(true, object.shift_pressed()); @@ -756,7 +756,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.shift_pressed()); } - TEST_METHOD(GetShiftPressedFromSettings) + TEST_METHOD (GetShiftPressedFromSettings) { HotkeyObject object = HotkeyObject::from_settings(true, true, true, true, 123); Assert::AreEqual(true, object.shift_pressed()); @@ -765,7 +765,7 @@ namespace UnitTestsCommonLib Assert::AreEqual(false, objectNegativeValues.shift_pressed()); } - TEST_METHOD(GetModifiersRepeat) + TEST_METHOD (GetModifiersRepeat) { std::map expectedMap = { std::make_pair(0x0000, HotkeyObject::from_settings(false, false, false, false, 0)), @@ -792,7 +792,7 @@ namespace UnitTestsCommonLib } } - TEST_METHOD(GetModifiers) + TEST_METHOD (GetModifiers) { std::map expectedMap = { std::make_pair(0x4000, HotkeyObject::from_settings(false, false, false, false, 0)), diff --git a/src/common/UnitTests-CommonLib/UnitTestsVersionHelper.cpp b/src/common/UnitTests-CommonLib/UnitTestsVersionHelper.cpp index e408c3547..cbd8cbd72 100644 --- a/src/common/UnitTests-CommonLib/UnitTestsVersionHelper.cpp +++ b/src/common/UnitTests-CommonLib/UnitTestsVersionHelper.cpp @@ -10,10 +10,10 @@ namespace UnitTestsVersionHelper const int MINOR_VERSION_12 = 12; const int REVISION_VERSION_0 = 0; - TEST_CLASS(UnitTestsVersionHelper) + TEST_CLASS (UnitTestsVersionHelper) { public: - TEST_METHOD(integerConstructorShouldProprelyInitializateVersionNumbers) + TEST_METHOD (integerConstructorShouldProprelyInitializateVersionNumbers) { VersionHelper sut(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0); @@ -21,7 +21,7 @@ namespace UnitTestsVersionHelper Assert::AreEqual(MINOR_VERSION_12, sut.minor); Assert::AreEqual(REVISION_VERSION_0, sut.revision); } - TEST_METHOD(integerConstructorShouldProprelyInitializateWithDifferentVersionNumbers) + TEST_METHOD (integerConstructorShouldProprelyInitializateWithDifferentVersionNumbers) { const int testcaseMajor = 2; const int testcaseMinor = 25; @@ -32,16 +32,15 @@ namespace UnitTestsVersionHelper Assert::AreEqual(testcaseMinor, sut.minor); Assert::AreEqual(testcaseRevision, sut.revision); } - TEST_METHOD(stringConstructorShouldProprelyInitializateVersionNumbers) + TEST_METHOD (stringConstructorShouldProprelyInitializateVersionNumbers) { - VersionHelper sut("v0.12.3"); Assert::AreEqual(0, sut.major); Assert::AreEqual(12, sut.minor); Assert::AreEqual(3, sut.revision); } - TEST_METHOD(stringConstructorShouldProprelyInitializateWithDifferentVersionNumbers) + TEST_METHOD (stringConstructorShouldProprelyInitializateWithDifferentVersionNumbers) { VersionHelper sut("v2.25.1"); @@ -49,21 +48,21 @@ namespace UnitTestsVersionHelper Assert::AreEqual(25, sut.minor); Assert::AreEqual(1, sut.revision); } - TEST_METHOD(whenMajorVersionIsGreaterComparationOperatorShouldReturnProperValue) + TEST_METHOD (whenMajorVersionIsGreaterComparationOperatorShouldReturnProperValue) { VersionHelper rhs(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0); VersionHelper lhs(MAJOR_VERSION_0 + 1, MINOR_VERSION_12, REVISION_VERSION_0); Assert::IsTrue(lhs > rhs); } - TEST_METHOD(whenMajorVersionIsLesserComparationOperatorShouldReturnProperValue) + TEST_METHOD (whenMajorVersionIsLesserComparationOperatorShouldReturnProperValue) { VersionHelper rhs(MAJOR_VERSION_0 + 1, MINOR_VERSION_12, REVISION_VERSION_0); VersionHelper lhs(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0); Assert::IsFalse(lhs > rhs); } - TEST_METHOD(whenMajorVersionIsEqualComparationOperatorShouldCompareMinorVersionValue) + TEST_METHOD (whenMajorVersionIsEqualComparationOperatorShouldCompareMinorVersionValue) { VersionHelper rhs(MAJOR_VERSION_0, MINOR_VERSION_12 - 1, REVISION_VERSION_0); @@ -71,7 +70,7 @@ namespace UnitTestsVersionHelper Assert::IsTrue(lhs > rhs); } - TEST_METHOD(whenMajorVersionIsEqualComparationOperatorShouldCompareMinorVersionValue2) + TEST_METHOD (whenMajorVersionIsEqualComparationOperatorShouldCompareMinorVersionValue2) { VersionHelper rhs(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0); VersionHelper lhs(MAJOR_VERSION_0, MINOR_VERSION_12 - 1, REVISION_VERSION_0); @@ -79,14 +78,14 @@ namespace UnitTestsVersionHelper Assert::IsFalse(lhs > rhs); } - TEST_METHOD(whenMajorAndMinorVersionIsEqualComparationOperatorShouldCompareRevisionValue) + TEST_METHOD (whenMajorAndMinorVersionIsEqualComparationOperatorShouldCompareRevisionValue) { VersionHelper rhs(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0); VersionHelper lhs(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0 + 1); Assert::IsTrue(lhs > rhs); } - TEST_METHOD(whenMajorAndMinorVersionIsEqualComparationOperatorShouldCompareRevisionValue2) + TEST_METHOD (whenMajorAndMinorVersionIsEqualComparationOperatorShouldCompareRevisionValue2) { VersionHelper rhs(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0 + 1); VersionHelper lhs(MAJOR_VERSION_0, MINOR_VERSION_12, REVISION_VERSION_0); diff --git a/src/common/animation.cpp b/src/common/animation.cpp index d034d713d..a0e390d50 100644 --- a/src/common/animation.cpp +++ b/src/common/animation.cpp @@ -2,42 +2,50 @@ #include "animation.h" 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() { - start = std::chrono::high_resolution_clock::now(); +void Animation::reset() +{ + start = std::chrono::high_resolution_clock::now(); } -void Animation::reset(double duration) { - this->duration = duration; - reset(); +void Animation::reset(double duration) +{ + this->duration = duration; + reset(); } -void Animation::reset(double duration, double start, double stop) { - start_value = start; - end_value = stop; - reset(duration); +void Animation::reset(double duration, double start, double stop) +{ + start_value = start; + end_value = stop; + reset(duration); } -static double ease_out_expo(double t) { - return 1 - pow(2, -8 * t); +static double ease_out_expo(double t) +{ + return 1 - pow(2, -8 * t); } -double Animation::apply_animation_function(double t, AnimFunctions apply_function) { - switch (apply_function) { - case EASE_OUT_EXPO: - return ease_out_expo(t); - case LINEAR: - default: - return t; - } +double Animation::apply_animation_function(double t, AnimFunctions apply_function) +{ + switch (apply_function) + { + case EASE_OUT_EXPO: + return ease_out_expo(t); + case LINEAR: + default: + return t; + } } -double Animation::value(AnimFunctions apply_function) const { - auto anim_duration = std::chrono::high_resolution_clock::now() - start; - double t = std::chrono::duration(anim_duration).count() / duration; - if (t >= 1) - return end_value; - return start_value + (end_value - start_value) * apply_animation_function(t, apply_function); +double Animation::value(AnimFunctions apply_function) const +{ + auto anim_duration = std::chrono::high_resolution_clock::now() - start; + double t = std::chrono::duration(anim_duration).count() / duration; + if (t >= 1) + return end_value; + return start_value + (end_value - start_value) * apply_animation_function(t, apply_function); } -bool Animation::done() const { - return std::chrono::high_resolution_clock::now() - start >= std::chrono::duration(duration); +bool Animation::done() const +{ + return std::chrono::high_resolution_clock::now() - start >= std::chrono::duration(duration); } diff --git a/src/common/animation.h b/src/common/animation.h index f1068aef0..8054169e2 100644 --- a/src/common/animation.h +++ b/src/common/animation.h @@ -11,21 +11,24 @@ When redering, call value() to get value from 0 to 1 - depending on animation progress. */ -class Animation { +class Animation +{ public: - enum AnimFunctions { - LINEAR = 0, - EASE_OUT_EXPO - }; + enum AnimFunctions + { + LINEAR = 0, + EASE_OUT_EXPO + }; + + Animation(double duration = 1, double start = 0, double stop = 1); + void reset(); + void reset(double duration); + void reset(double duration, double start, double stop); + double value(AnimFunctions apply_function) const; + bool done() const; - Animation(double duration = 1, double start = 0, double stop = 1); - void reset(); - void reset(double duration); - void reset(double duration, double start, double stop); - double value(AnimFunctions apply_function) const; - bool done() const; private: - static double apply_animation_function(double t, AnimFunctions apply_function); - std::chrono::high_resolution_clock::time_point start; - double start_value, end_value, duration; + static double apply_animation_function(double t, AnimFunctions apply_function); + std::chrono::high_resolution_clock::time_point start; + double start_value, end_value, duration; }; diff --git a/src/common/async_message_queue.h b/src/common/async_message_queue.h index a5bfb4570..1ffdaaae5 100644 --- a/src/common/async_message_queue.h +++ b/src/common/async_message_queue.h @@ -5,43 +5,50 @@ #include #include -class AsyncMessageQueue { +class AsyncMessageQueue +{ private: - std::mutex queue_mutex; - std::queue message_queue; - std::condition_variable message_ready; - bool interrupted = false; + std::mutex queue_mutex; + std::queue message_queue; + std::condition_variable message_ready; + bool interrupted = false; - //Disable copy - AsyncMessageQueue(const AsyncMessageQueue&); - AsyncMessageQueue& operator=(const AsyncMessageQueue&); + //Disable copy + AsyncMessageQueue(const AsyncMessageQueue&); + AsyncMessageQueue& operator=(const AsyncMessageQueue&); public: - AsyncMessageQueue() { - } - void queue_message(std::wstring message) { - this->queue_mutex.lock(); - this->message_queue.push(message); - this->queue_mutex.unlock(); - this->message_ready.notify_one(); - } - std::wstring pop_message() { - std::unique_lock lock(this->queue_mutex); - while (message_queue.empty() && !this->interrupted) { - this->message_ready.wait(lock); + AsyncMessageQueue() + { } - if (this->interrupted) { - //Just returns a empty string if the queue was interrupted. - return std::wstring(L""); + void queue_message(std::wstring message) + { + this->queue_mutex.lock(); + this->message_queue.push(message); + this->queue_mutex.unlock(); + this->message_ready.notify_one(); + } + std::wstring pop_message() + { + std::unique_lock lock(this->queue_mutex); + while (message_queue.empty() && !this->interrupted) + { + this->message_ready.wait(lock); + } + if (this->interrupted) + { + //Just returns a empty string if the queue was interrupted. + return std::wstring(L""); + } + std::wstring message = this->message_queue.front(); + this->message_queue.pop(); + return message; + } + void interrupt() + { + this->queue_mutex.lock(); + this->interrupted = true; + this->queue_mutex.unlock(); + this->message_ready.notify_all(); } - std::wstring message = this->message_queue.front(); - this->message_queue.pop(); - return message; - } - void interrupt() { - this->queue_mutex.lock(); - this->interrupted = true; - this->queue_mutex.unlock(); - this->message_ready.notify_all(); - } }; diff --git a/src/common/com_object_factory.h b/src/common/com_object_factory.h index 69b21dd28..8ed984377 100644 --- a/src/common/com_object_factory.h +++ b/src/common/com_object_factory.h @@ -8,7 +8,7 @@ template class com_object_factory : public IClassFactory { public: - HRESULT __stdcall QueryInterface(const IID & riid, void** ppv) override + HRESULT __stdcall QueryInterface(const IID& riid, void** ppv) override { static const QITAB qit[] = { QITABENT(com_object_factory, IClassFactory), @@ -28,7 +28,7 @@ public: return refCount; } - HRESULT __stdcall CreateInstance(IUnknown* punkOuter, const IID & riid, void** ppv) + HRESULT __stdcall CreateInstance(IUnknown* punkOuter, const IID& riid, void** ppv) { *ppv = nullptr; HRESULT hr; diff --git a/src/common/common.cpp b/src/common/common.cpp index 7e60d465a..a30fd90e1 100644 --- a/src/common/common.cpp +++ b/src/common/common.cpp @@ -10,68 +10,88 @@ namespace localized_strings { - const wchar_t LAST_ERROR_FORMAT_STRING[] = L"%s failed with error %d: %s"; - const wchar_t LAST_ERROR_TITLE_STRING[] = L"Error"; + const wchar_t LAST_ERROR_FORMAT_STRING[] = L"%s failed with error %d: %s"; + const wchar_t LAST_ERROR_TITLE_STRING[] = L"Error"; } -std::optional get_button_pos(HWND hwnd) { - RECT button; - if (DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, &button, sizeof(RECT)) == S_OK) { - return button; - } else { - return {}; - } +std::optional get_button_pos(HWND hwnd) +{ + RECT button; + if (DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, &button, sizeof(RECT)) == S_OK) + { + return button; + } + else + { + return {}; + } } -std::optional get_window_pos(HWND hwnd) { - RECT window; - if (DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &window, sizeof(window)) == S_OK) { - return window; - } else { - return {}; - } +std::optional get_window_pos(HWND hwnd) +{ + RECT window; + if (DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &window, sizeof(window)) == S_OK) + { + return window; + } + else + { + return {}; + } } -std::optional get_mouse_pos() { - POINT point; - if (GetCursorPos(&point) == 0) { - return {}; - } else { - return point; - } +std::optional get_mouse_pos() +{ + POINT point; + if (GetCursorPos(&point) == 0) + { + return {}; + } + else + { + return point; + } } // Test if a window is part of the shell or the task bar. // We compare the HWND against HWND of the desktop and shell windows, // we also filter out some window class names know to belong to // the taskbar. -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_hwnds = { GetDesktopWindow(), GetShellWindow() }; - for (auto system_hwnd : system_hwnds) { - if (hwnd == system_hwnd) { - return true; +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_hwnds = { GetDesktopWindow(), GetShellWindow() }; + for (auto system_hwnd : system_hwnds) + { + if (hwnd == system_hwnd) + { + return true; + } } - } - for (const auto& system_class : system_classes) { - if (strcmp(system_class, class_name) == 0) { - return true; + for (const auto& system_class : system_classes) + { + if (strcmp(system_class, class_name) == 0) + { + return true; + } } - } - return false; + return false; } static bool no_visible_owner(HWND window) noexcept { auto owner = GetWindow(window, GW_OWNER); - if (owner == nullptr) { + if (owner == nullptr) + { return true; // There is no owner at all } - if (!IsWindowVisible(owner)) { + if (!IsWindowVisible(owner)) + { return true; // Owner is invisible } 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 (and allow the window to be zonable) if the owner window size is zero @@ -79,433 +99,519 @@ static bool no_visible_owner(HWND window) noexcept return rect.top == rect.bottom || rect.left == rect.right; } -FancyZonesFilter get_fancyzones_filtered_window(HWND window) { - FancyZonesFilter result; - if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window)) { - return result; - } - auto style = GetWindowLong(window, GWL_STYLE); - auto exStyle = GetWindowLong(window, GWL_EXSTYLE); - // WS_POPUP need to have a border or minimize/maximize buttons, - // otherwise the window is "not interesting" - if ((style & WS_POPUP) == WS_POPUP && - (style & WS_THICKFRAME) == 0 && - (style & WS_MINIMIZEBOX) == 0 && - (style & WS_MAXIMIZEBOX) == 0) { - return result; - } - if ((style & WS_CHILD) == WS_CHILD || - (style & WS_DISABLED) == WS_DISABLED || - (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || - (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) { - return result; - } - std::array class_name; - GetClassNameA(window, class_name.data(), static_cast(class_name.size())); - if (is_system_window(window, class_name.data())) { - return result; - } - auto process_path = get_process_path(window); - // Check for Cortana: - if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 && - process_path.ends_with(L"SearchUI.exe")) { - return result; - } - result.process_path = std::move(process_path); - result.standard_window = true; - result.no_visible_owner = no_visible_owner(window); - result.zonable = result.standard_window && result.no_visible_owner; - return result; -} - -ShortcutGuideFilter get_shortcutguide_filtered_window() { - ShortcutGuideFilter result; - auto active_window = GetForegroundWindow(); - active_window = GetAncestor(active_window, GA_ROOT); - if (!IsWindowVisible(active_window)) { - return result; - } - auto style = GetWindowLong(active_window, GWL_STYLE); - auto exStyle = GetWindowLong(active_window, GWL_EXSTYLE); - if ((style & WS_CHILD) == WS_CHILD || - (style & WS_DISABLED) == WS_DISABLED || - (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || - (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) { - return result; - } - std::array class_name; - GetClassNameA(active_window, class_name.data(), static_cast(class_name.size())); - if (is_system_window(active_window, class_name.data())) { - return result; - } - static HWND cortanda_hwnd = nullptr; - if (cortanda_hwnd == nullptr) { +FancyZonesFilter get_fancyzones_filtered_window(HWND window) +{ + FancyZonesFilter result; + if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window)) + { + return result; + } + auto style = GetWindowLong(window, GWL_STYLE); + auto exStyle = GetWindowLong(window, GWL_EXSTYLE); + // WS_POPUP need to have a border or minimize/maximize buttons, + // otherwise the window is "not interesting" + if ((style & WS_POPUP) == WS_POPUP && + (style & WS_THICKFRAME) == 0 && + (style & WS_MINIMIZEBOX) == 0 && + (style & WS_MAXIMIZEBOX) == 0) + { + return result; + } + if ((style & WS_CHILD) == WS_CHILD || + (style & WS_DISABLED) == WS_DISABLED || + (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || + (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) + { + return result; + } + std::array class_name; + GetClassNameA(window, class_name.data(), static_cast(class_name.size())); + if (is_system_window(window, class_name.data())) + { + return result; + } + auto process_path = get_process_path(window); + // Check for Cortana: if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 && - get_process_path(active_window).ends_with(L"SearchUI.exe")) { - cortanda_hwnd = active_window; - return result; + process_path.ends_with(L"SearchUI.exe")) + { + return result; } - } else if (cortanda_hwnd == active_window) { + result.process_path = std::move(process_path); + result.standard_window = true; + result.no_visible_owner = no_visible_owner(window); + result.zonable = result.standard_window && result.no_visible_owner; return result; - } - result.hwnd = active_window; - // In reality, Windows Snap works if even one of those styles is set - // for a window, it is just limited. If there is no WS_MAXIMIZEBOX using - // WinKey + Up just won't maximize the window. Similary, without - // WS_MINIMIZEBOX the window will not get minimized. A "Save As..." dialog - // is a example of such window - it can be snapped to both sides and to - // all screen conrers, but will not get maximized nor minimized. - // For now, since ShortcutGuide can only disable entire "Windows Controls" - // group, we require that the window supports all the options. - result.snappable = ((style & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX) && - ((style & WS_MINIMIZEBOX) == WS_MINIMIZEBOX) && - ((style & WS_THICKFRAME) == WS_THICKFRAME); - return result; } -int width(const RECT& rect) { - return rect.right - rect.left; +ShortcutGuideFilter get_shortcutguide_filtered_window() +{ + ShortcutGuideFilter result; + auto active_window = GetForegroundWindow(); + active_window = GetAncestor(active_window, GA_ROOT); + if (!IsWindowVisible(active_window)) + { + return result; + } + auto style = GetWindowLong(active_window, GWL_STYLE); + auto exStyle = GetWindowLong(active_window, GWL_EXSTYLE); + if ((style & WS_CHILD) == WS_CHILD || + (style & WS_DISABLED) == WS_DISABLED || + (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || + (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) + { + return result; + } + std::array class_name; + GetClassNameA(active_window, class_name.data(), static_cast(class_name.size())); + if (is_system_window(active_window, class_name.data())) + { + return result; + } + static HWND cortanda_hwnd = nullptr; + if (cortanda_hwnd == nullptr) + { + if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 && + get_process_path(active_window).ends_with(L"SearchUI.exe")) + { + cortanda_hwnd = active_window; + return result; + } + } + else if (cortanda_hwnd == active_window) + { + return result; + } + result.hwnd = active_window; + // In reality, Windows Snap works if even one of those styles is set + // for a window, it is just limited. If there is no WS_MAXIMIZEBOX using + // WinKey + Up just won't maximize the window. Similary, without + // WS_MINIMIZEBOX the window will not get minimized. A "Save As..." dialog + // is a example of such window - it can be snapped to both sides and to + // all screen conrers, but will not get maximized nor minimized. + // For now, since ShortcutGuide can only disable entire "Windows Controls" + // group, we require that the window supports all the options. + result.snappable = ((style & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX) && + ((style & WS_MINIMIZEBOX) == WS_MINIMIZEBOX) && + ((style & WS_THICKFRAME) == WS_THICKFRAME); + return result; } -int height(const RECT& rect) { - return rect.bottom - rect.top; +int width(const RECT& rect) +{ + return rect.right - rect.left; } -bool operator<(const RECT& lhs, const RECT& rhs) { - 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); - return lhs_tuple < rhs_tuple; +int height(const RECT& rect) +{ + return rect.bottom - rect.top; } -RECT keep_rect_inside_rect(const RECT& small_rect, const RECT& big_rect) { - RECT result = small_rect; - if ((result.right - result.left) > (big_rect.right - big_rect.left)) { - // small_rect is too big horizontally. resize it. - result.right = big_rect.right; - result.left = big_rect.left; - } else { - if (result.right > big_rect.right) { - // move the rect left. - result.left -= result.right-big_rect.right; - result.right -= result.right-big_rect.right; +bool operator<(const RECT& lhs, const RECT& rhs) +{ + 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); + return lhs_tuple < rhs_tuple; +} + +RECT keep_rect_inside_rect(const RECT& small_rect, const RECT& big_rect) +{ + RECT result = small_rect; + if ((result.right - result.left) > (big_rect.right - big_rect.left)) + { + // small_rect is too big horizontally. resize it. + result.right = big_rect.right; + result.left = big_rect.left; + } + else + { + if (result.right > big_rect.right) + { + // move the rect left. + result.left -= result.right - big_rect.right; + result.right -= result.right - big_rect.right; + } + + if (result.left < big_rect.left) + { + // move the rect right. + result.right += big_rect.left - result.left; + result.left += big_rect.left - result.left; + } } - if (result.left < big_rect.left) { - // move the rect right. - result.right += big_rect.left-result.left; - result.left += big_rect.left-result.left; + if ((result.bottom - result.top) > (big_rect.bottom - big_rect.top)) + { + // small_rect is too big vertically. resize it. + result.bottom = big_rect.bottom; + result.top = big_rect.top; } - } + else + { + if (result.bottom > big_rect.bottom) + { + // move the rect up. + result.top -= result.bottom - big_rect.bottom; + result.bottom -= result.bottom - big_rect.bottom; + } - if ((result.bottom - result.top) > (big_rect.bottom - big_rect.top)) { - // small_rect is too big vertically. resize it. - result.bottom = big_rect.bottom; - result.top = big_rect.top; - } else { - if (result.bottom > big_rect.bottom) { - // move the rect up. - result.top -= result.bottom-big_rect.bottom; - result.bottom -= result.bottom-big_rect.bottom; + if (result.top < big_rect.top) + { + // move the rect down. + result.bottom += big_rect.top - result.top; + result.top += big_rect.top - result.top; + } + } + return result; +} + +int run_message_loop() +{ + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return static_cast(msg.wParam); +} + +std::optional get_last_error_message(const DWORD dw) +{ + std::optional message; + try + { + const auto msg = std::system_category().message(dw); + message.emplace(begin(msg), end(msg)); + } + catch (...) + { + } + return message; +} + +void show_last_error_message(LPCWSTR lpszFunction, DWORD dw) +{ + const auto system_message = get_last_error_message(dw); + if (!system_message.has_value()) + { + return; + } + LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(lpszFunction) + 40) * sizeof(WCHAR)); + if (lpDisplayBuf != NULL) + { + StringCchPrintfW(lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(WCHAR), + localized_strings::LAST_ERROR_FORMAT_STRING, + lpszFunction, + dw, + system_message->c_str()); + MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, localized_strings::LAST_ERROR_TITLE_STRING, MB_OK); + LocalFree(lpDisplayBuf); + } +} + +WindowState get_window_state(HWND hwnd) +{ + WINDOWPLACEMENT placement; + placement.length = sizeof(WINDOWPLACEMENT); + + if (GetWindowPlacement(hwnd, &placement) == 0) + { + return UNKNONW; } - if (result.top < big_rect.top) { - // move the rect down. - result.bottom += big_rect.top-result.top; - result.top += big_rect.top-result.top; + if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_SHOWMINIMIZED || IsIconic(hwnd)) + { + return MINIMIZED; } - } - return result; -} -int run_message_loop() { - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return static_cast(msg.wParam); -} - -std::optional get_last_error_message(const DWORD dw) { - std::optional message; - try { - const auto msg = std::system_category().message(dw); - message.emplace(begin(msg), end(msg)); - } - catch(...) { - - } - return message; -} - -void show_last_error_message(LPCWSTR lpszFunction, DWORD dw) { - const auto system_message = get_last_error_message(dw); - if(!system_message.has_value()) { - return; - } - LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(lpszFunction) + 40) * sizeof(WCHAR)); - if (lpDisplayBuf != NULL) { - StringCchPrintfW(lpDisplayBuf, - LocalSize(lpDisplayBuf) / sizeof(WCHAR), - localized_strings::LAST_ERROR_FORMAT_STRING, - lpszFunction, dw, system_message->c_str()); - MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, localized_strings::LAST_ERROR_TITLE_STRING, MB_OK); - LocalFree(lpDisplayBuf); - } -} - -WindowState get_window_state(HWND hwnd) { - WINDOWPLACEMENT placement; - placement.length = sizeof(WINDOWPLACEMENT); - - if (GetWindowPlacement(hwnd, &placement) == 0) { - return UNKNONW; - } - - if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_SHOWMINIMIZED || IsIconic(hwnd)) { - return MINIMIZED; - } - - if (placement.showCmd == SW_MAXIMIZE || placement.showCmd == SW_SHOWMAXIMIZED) { - return MAXIMIZED; - } - - auto rectp = get_window_pos(hwnd); - if (!rectp) { - return UNKNONW; - } - - auto rect = *rectp; - MONITORINFO monitor; - monitor.cbSize = sizeof(MONITORINFO); - auto h_monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); - GetMonitorInfo(h_monitor, &monitor); - bool top_left = monitor.rcWork.top == rect.top && monitor.rcWork.left == rect.left; - bool bottom_left = monitor.rcWork.bottom == rect.bottom && monitor.rcWork.left == rect.left; - 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; - - if (top_left && bottom_left) return SNAPED_LEFT; - if (top_left) return SNAPED_TOP_LEFT; - if (bottom_left) 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; -} - -bool is_process_elevated() { - HANDLE token = nullptr; - bool elevated = false; - - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { - TOKEN_ELEVATION elevation; - DWORD size; - if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) { - elevated = (elevation.TokenIsElevated != 0); + if (placement.showCmd == SW_MAXIMIZE || placement.showCmd == SW_SHOWMAXIMIZED) + { + return MAXIMIZED; } - } - if (token) { + auto rectp = get_window_pos(hwnd); + if (!rectp) + { + return UNKNONW; + } + + auto rect = *rectp; + MONITORINFO monitor; + monitor.cbSize = sizeof(MONITORINFO); + auto h_monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(h_monitor, &monitor); + bool top_left = monitor.rcWork.top == rect.top && monitor.rcWork.left == rect.left; + bool bottom_left = monitor.rcWork.bottom == rect.bottom && monitor.rcWork.left == rect.left; + 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; + + if (top_left && bottom_left) + return SNAPED_LEFT; + if (top_left) + return SNAPED_TOP_LEFT; + if (bottom_left) + 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; +} + +bool is_process_elevated() +{ + HANDLE token = nullptr; + bool elevated = false; + + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) + { + TOKEN_ELEVATION elevation; + DWORD size; + if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) + { + elevated = (elevation.TokenIsElevated != 0); + } + } + + if (token) + { + CloseHandle(token); + } + + return elevated; +} + +bool drop_elevated_privileges() +{ + HANDLE token = nullptr; + LPCTSTR lpszPrivilege = SE_SECURITY_NAME; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token)) + { + return false; + } + + PSID medium_sid = NULL; + if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) + { + return false; + } + + TOKEN_MANDATORY_LABEL label = { 0 }; + label.Label.Attributes = SE_GROUP_INTEGRITY; + label.Label.Sid = medium_sid; + DWORD size = (DWORD)sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid); + + BOOL result = SetTokenInformation(token, TokenIntegrityLevel, &label, size); + LocalFree(medium_sid); CloseHandle(token); - } - return elevated; + return result; } -bool drop_elevated_privileges() { - HANDLE token = nullptr; - LPCTSTR lpszPrivilege = SE_SECURITY_NAME; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token)) { - return false; - } - - PSID medium_sid = NULL; - if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) { - return false; - } - - TOKEN_MANDATORY_LABEL label = { 0 }; - label.Label.Attributes = SE_GROUP_INTEGRITY; - label.Label.Sid = medium_sid; - DWORD size = (DWORD)sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid); - - BOOL result = SetTokenInformation(token, TokenIntegrityLevel, &label, size); - LocalFree(medium_sid); - CloseHandle(token); - - return result; -} - -std::wstring get_process_path(DWORD pid) noexcept { - auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid); - std::wstring name; - if (process != INVALID_HANDLE_VALUE) { - name.resize(MAX_PATH); - DWORD name_length = static_cast(name.length()); - if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0) { - name_length = 0; +std::wstring get_process_path(DWORD pid) noexcept +{ + auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid); + std::wstring name; + if (process != INVALID_HANDLE_VALUE) + { + name.resize(MAX_PATH); + DWORD name_length = static_cast(name.length()); + if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0) + { + name_length = 0; + } + name.resize(name_length); + CloseHandle(process); } - name.resize(name_length); - CloseHandle(process); - } - return name; + return name; } -bool run_elevated(const std::wstring& file, const std::wstring& params) { - SHELLEXECUTEINFOW exec_info = { 0 }; - exec_info.cbSize = sizeof(SHELLEXECUTEINFOW); - exec_info.lpVerb = L"runas"; - exec_info.lpFile = file.c_str(); - exec_info.lpParameters = params.c_str(); - exec_info.hwnd = 0; - exec_info.fMask = SEE_MASK_NOCLOSEPROCESS; - exec_info.lpDirectory = 0; - exec_info.hInstApp = 0; +bool run_elevated(const std::wstring& file, const std::wstring& params) +{ + SHELLEXECUTEINFOW exec_info = { 0 }; + exec_info.cbSize = sizeof(SHELLEXECUTEINFOW); + exec_info.lpVerb = L"runas"; + exec_info.lpFile = file.c_str(); + exec_info.lpParameters = params.c_str(); + exec_info.hwnd = 0; + exec_info.fMask = SEE_MASK_NOCLOSEPROCESS; + exec_info.lpDirectory = 0; + exec_info.hInstApp = 0; - if (ShellExecuteExW(&exec_info)) { - return exec_info.hProcess != nullptr; - } else { - return false; - } -} - -bool run_non_elevated(const std::wstring& file, const std::wstring& params) { - auto executable_args = L"\"" + file + L"\""; - if (!params.empty()) { - executable_args += L" " + params; - } - - HWND hwnd = GetShellWindow(); - if (!hwnd) { - return false; - } - DWORD pid; - GetWindowThreadProcessId(hwnd, &pid); - - winrt::handle process{ OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pid) }; - if (!process) { - return false; - } - - SIZE_T size = 0; - - InitializeProcThreadAttributeList(nullptr, 1, 0, &size); - auto pproc_buffer = std::make_unique(size); - auto pptal = reinterpret_cast(pproc_buffer.get()); - - if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size)) { - return false; - } - - HANDLE process_handle = process.get(); - if (!pptal || !UpdateProcThreadAttribute(pptal, - 0, - PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, - &process_handle, - sizeof(process_handle), - nullptr, - nullptr)) { - return false; - } - - STARTUPINFOEX siex = { 0 }; - siex.lpAttributeList = pptal; - siex.StartupInfo.cb = sizeof(siex); - - PROCESS_INFORMATION process_info = { 0 }; - auto succedded = CreateProcessW(file.c_str(), - const_cast(executable_args.c_str()), - nullptr, - nullptr, - FALSE, - EXTENDED_STARTUPINFO_PRESENT, - nullptr, - nullptr, - &siex.StartupInfo, - &process_info); - if (process_info.hProcess) { - CloseHandle(process_info.hProcess); - } - if (process_info.hThread) { - CloseHandle(process_info.hThread); - } - return succedded; -} - -bool run_same_elevation(const std::wstring& file, const std::wstring& params) { - auto executable_args = L"\"" + file + L"\""; - if (!params.empty()) { - executable_args += L" " + params; - } - STARTUPINFO si = { 0 }; - PROCESS_INFORMATION pi = { 0 }; - auto succedded = CreateProcessW(file.c_str(), - const_cast(executable_args.c_str()), - nullptr, - nullptr, - FALSE, - 0, - nullptr, - nullptr, - &si, - &pi); - if (pi.hProcess) { - CloseHandle(pi.hProcess); - } - if (pi.hThread) { - CloseHandle(pi.hThread); - } - return succedded; -} - - -std::wstring get_process_path(HWND window) noexcept { - const static std::wstring app_frame_host = L"ApplicationFrameHost.exe"; - DWORD pid{}; - GetWindowThreadProcessId(window, &pid); - auto name = get_process_path(pid); - if (name.length() >= app_frame_host.length() && - 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 - // by something with a different PID - DWORD new_pid = pid; - EnumChildWindows(window, [](HWND hwnd, LPARAM param) -> BOOL { - auto new_pid_ptr = reinterpret_cast(param); - DWORD pid; - GetWindowThreadProcessId(hwnd, &pid); - if (pid != *new_pid_ptr) { - *new_pid_ptr = pid; - return FALSE; - } else { - return TRUE; - } - }, reinterpret_cast(&new_pid)); - // If we have a new pid, get the new name. - if (new_pid != pid) { - return get_process_path(new_pid); + if (ShellExecuteExW(&exec_info)) + { + return exec_info.hProcess != nullptr; + } + else + { + return false; } - } - return name; } -std::wstring get_product_version() { - static std::wstring version = L"v" + std::to_wstring(VERSION_MAJOR) + - L"." + std::to_wstring(VERSION_MINOR) + - L"." + std::to_wstring(VERSION_REVISION); +bool run_non_elevated(const std::wstring& file, const std::wstring& params) +{ + auto executable_args = L"\"" + file + L"\""; + if (!params.empty()) + { + executable_args += L" " + params; + } - return version; + HWND hwnd = GetShellWindow(); + if (!hwnd) + { + return false; + } + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + + winrt::handle process{ OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pid) }; + if (!process) + { + return false; + } + + SIZE_T size = 0; + + InitializeProcThreadAttributeList(nullptr, 1, 0, &size); + auto pproc_buffer = std::make_unique(size); + auto pptal = reinterpret_cast(pproc_buffer.get()); + + if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size)) + { + return false; + } + + HANDLE process_handle = process.get(); + if (!pptal || !UpdateProcThreadAttribute(pptal, + 0, + PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, + &process_handle, + sizeof(process_handle), + nullptr, + nullptr)) + { + return false; + } + + STARTUPINFOEX siex = { 0 }; + siex.lpAttributeList = pptal; + siex.StartupInfo.cb = sizeof(siex); + + PROCESS_INFORMATION process_info = { 0 }; + auto succedded = CreateProcessW(file.c_str(), + const_cast(executable_args.c_str()), + nullptr, + nullptr, + FALSE, + EXTENDED_STARTUPINFO_PRESENT, + nullptr, + nullptr, + &siex.StartupInfo, + &process_info); + if (process_info.hProcess) + { + CloseHandle(process_info.hProcess); + } + if (process_info.hThread) + { + CloseHandle(process_info.hThread); + } + return succedded; } -std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback) { - wchar_t* text_ptr; - auto length = LoadStringW(instance, resource_id, reinterpret_cast(&text_ptr), 0); - if (length == 0) { - return fallback; - } else { - return { text_ptr, static_cast(length) }; - } +bool run_same_elevation(const std::wstring& file, const std::wstring& params) +{ + auto executable_args = L"\"" + file + L"\""; + if (!params.empty()) + { + executable_args += L" " + params; + } + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + auto succedded = CreateProcessW(file.c_str(), + const_cast(executable_args.c_str()), + nullptr, + nullptr, + FALSE, + 0, + nullptr, + nullptr, + &si, + &pi); + if (pi.hProcess) + { + CloseHandle(pi.hProcess); + } + if (pi.hThread) + { + CloseHandle(pi.hThread); + } + return succedded; +} + +std::wstring get_process_path(HWND window) noexcept +{ + const static std::wstring app_frame_host = L"ApplicationFrameHost.exe"; + DWORD pid{}; + GetWindowThreadProcessId(window, &pid); + auto name = get_process_path(pid); + if (name.length() >= app_frame_host.length() && + 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 + // by something with a different PID + DWORD new_pid = pid; + EnumChildWindows( + window, [](HWND hwnd, LPARAM param) -> BOOL { + auto new_pid_ptr = reinterpret_cast(param); + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + if (pid != *new_pid_ptr) + { + *new_pid_ptr = pid; + return FALSE; + } + else + { + return TRUE; + } + }, + reinterpret_cast(&new_pid)); + // If we have a new pid, get the new name. + if (new_pid != pid) + { + return get_process_path(new_pid); + } + } + return name; +} + +std::wstring get_product_version() +{ + static std::wstring version = L"v" + std::to_wstring(VERSION_MAJOR) + + L"." + std::to_wstring(VERSION_MINOR) + + L"." + std::to_wstring(VERSION_REVISION); + + return version; +} + +std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback) +{ + wchar_t* text_ptr; + auto length = LoadStringW(instance, resource_id, reinterpret_cast(&text_ptr), 0); + if (length == 0) + { + return fallback; + } + else + { + return { text_ptr, static_cast(length) }; + } } std::wstring get_module_filename(HMODULE mod) @@ -541,7 +647,6 @@ std::wstring get_module_folderpath(HMODULE mod) return { buffer, (UINT)lstrlenW(buffer) }; } - // 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. bool check_user_is_admin() diff --git a/src/common/common.h b/src/common/common.h index 0ba059d8c..ac5d65df8 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -14,18 +14,20 @@ std::optional get_window_pos(HWND hwnd); std::optional get_mouse_pos(); // Test if window can be zoned by FancyZones -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 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 - std::wstring process_path; // Path to the executable owning the window +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 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 + std::wstring process_path; // Path to the executable owning the window }; FancyZonesFilter get_fancyzones_filtered_window(HWND window); // Gets active foreground window, filtering out all "non standard" windows like the taskbar, etc. -struct ShortcutGuideFilter { - 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 +struct ShortcutGuideFilter +{ + 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 }; ShortcutGuideFilter get_shortcutguide_filtered_window(); @@ -42,17 +44,18 @@ int run_message_loop(); std::optional get_last_error_message(const DWORD dw); void show_last_error_message(LPCWSTR lpszFunction, DWORD dw); -enum WindowState { - UNKNONW, - MINIMIZED, - MAXIMIZED, - SNAPED_TOP_LEFT, - SNAPED_LEFT, - SNAPED_BOTTOM_LEFT, - SNAPED_TOP_RIGHT, - SNAPED_RIGHT, - SNAPED_BOTTOM_RIGHT, - RESTORED +enum WindowState +{ + UNKNONW, + MINIMIZED, + MAXIMIZED, + SNAPED_TOP_LEFT, + SNAPED_LEFT, + SNAPED_BOTTOM_LEFT, + SNAPED_TOP_RIGHT, + SNAPED_RIGHT, + SNAPED_BOTTOM_RIGHT, + RESTORED }; WindowState get_window_state(HWND hwnd); diff --git a/src/common/d2d_svg.cpp b/src/common/d2d_svg.cpp index 86c6c7c81..3e8a9b92e 100644 --- a/src/common/d2d_svg.cpp +++ b/src/common/d2d_svg.cpp @@ -1,105 +1,117 @@ #include "pch.h" #include "d2d_svg.h" -D2DSVG& D2DSVG::load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc) { - svg = nullptr; - winrt::com_ptr svg_stream; - winrt::check_hresult(SHCreateStreamOnFileEx(filename.c_str(), - STGM_READ, FILE_ATTRIBUTE_NORMAL, FALSE, - nullptr, - svg_stream.put())); +D2DSVG& D2DSVG::load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc) +{ + svg = nullptr; + winrt::com_ptr svg_stream; + winrt::check_hresult(SHCreateStreamOnFileEx(filename.c_str(), + STGM_READ, + FILE_ATTRIBUTE_NORMAL, + FALSE, + nullptr, + svg_stream.put())); - winrt::check_hresult(d2d_dc->CreateSvgDocument( - svg_stream.get(), - D2D1::SizeF(1, 1), - svg.put())); + winrt::check_hresult(d2d_dc->CreateSvgDocument( + svg_stream.get(), + D2D1::SizeF(1, 1), + svg.put())); - winrt::com_ptr root; - svg->GetRoot(root.put()); - float tmp; - winrt::check_hresult(root->GetAttributeValue(L"width", &tmp)); - svg_width = (int)tmp; - winrt::check_hresult(root->GetAttributeValue(L"height", &tmp)); - svg_height = (int)tmp; - return *this; + winrt::com_ptr root; + svg->GetRoot(root.put()); + float tmp; + winrt::check_hresult(root->GetAttributeValue(L"width", &tmp)); + svg_width = (int)tmp; + winrt::check_hresult(root->GetAttributeValue(L"height", &tmp)); + svg_height = (int)tmp; + return *this; } -D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float max_scale) { - // Center - transform = D2D1::Matrix3x2F::Identity(); - transform = transform * D2D1::Matrix3x2F::Translation((width - svg_width) / 2.0f, (height - svg_height) / 2.0f); - float h_scale = fill * height / svg_height; - float v_scale = fill * width / svg_width; - used_scale = min(h_scale, v_scale); - if (max_scale > 0) { - 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::Translation((float)x, (float)y); - return *this; +D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float max_scale) +{ + // Center + transform = D2D1::Matrix3x2F::Identity(); + transform = transform * D2D1::Matrix3x2F::Translation((width - svg_width) / 2.0f, (height - svg_height) / 2.0f); + float h_scale = fill * height / svg_height; + float v_scale = fill * width / svg_width; + used_scale = min(h_scale, v_scale); + if (max_scale > 0) + { + 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::Translation((float)x, (float)y); + return *this; } -D2DSVG& D2DSVG::recolor(uint32_t oldcolor, uint32_t newcolor) { - auto new_color = D2D1::ColorF(newcolor & 0xFFFFFF, 1); - auto old_color = D2D1::ColorF(oldcolor & 0xFFFFFF, 1); - std::function recurse = [&](ID2D1SvgElement* element) { +D2DSVG& D2DSVG::recolor(uint32_t oldcolor, uint32_t newcolor) +{ + auto new_color = D2D1::ColorF(newcolor & 0xFFFFFF, 1); + auto old_color = D2D1::ColorF(oldcolor & 0xFFFFFF, 1); + std::function recurse = [&](ID2D1SvgElement* element) { + if (!element) + return; + if (element->IsAttributeSpecified(L"fill")) + { + D2D1_COLOR_F elem_fill; + winrt::com_ptr paint; + element->GetAttributeValue(L"fill", paint.put()); + paint->GetColor(&elem_fill); + 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::com_ptr sub; + element->GetFirstChild(sub.put()); + while (sub) + { + recurse(sub.get()); + winrt::com_ptr next; + element->GetNextChild(sub.get(), next.put()); + sub = next; + } + }; + winrt::com_ptr root; + svg->GetRoot(root.put()); + recurse(root.get()); + return *this; +} + +D2DSVG& D2DSVG::render(ID2D1DeviceContext5* d2d_dc) +{ + D2D1_MATRIX_3X2_F current; + d2d_dc->GetTransform(¤t); + d2d_dc->SetTransform(transform * current); + d2d_dc->DrawSvgDocument(svg.get()); + d2d_dc->SetTransform(current); + return *this; +} + +D2DSVG& D2DSVG::toggle_element(const wchar_t* id, bool visible) +{ + winrt::com_ptr element; + if (svg->FindElementById(id, element.put()) != S_OK) + return *this; if (!element) - return; - if (element->IsAttributeSpecified(L"fill")) { - D2D1_COLOR_F elem_fill; - winrt::com_ptr paint; - element->GetAttributeValue(L"fill", paint.put()); - paint->GetColor(&elem_fill); - 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::com_ptr sub; - element->GetFirstChild(sub.put()); - while (sub) { - recurse(sub.get()); - winrt::com_ptr next; - element->GetNextChild(sub.get(), next.put()); - sub = next; - } - }; - winrt::com_ptr root; - svg->GetRoot(root.put()); - recurse(root.get()); - return *this; -} - - -D2DSVG& D2DSVG::render(ID2D1DeviceContext5* d2d_dc) { - D2D1_MATRIX_3X2_F current; - d2d_dc->GetTransform(¤t); - d2d_dc->SetTransform(transform * current); - d2d_dc->DrawSvgDocument(svg.get()); - d2d_dc->SetTransform(current); - return *this; -} - -D2DSVG& D2DSVG::toggle_element(const wchar_t* id, bool visible) { - winrt::com_ptr element; - if (svg->FindElementById(id, element.put()) != S_OK) + return *this; + element->SetAttributeValue(L"display", visible ? D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_INLINE : D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_NONE); return *this; - if (!element) - return *this; - element->SetAttributeValue(L"display", visible ? D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_INLINE : D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_NONE); - return *this; } -winrt::com_ptr D2DSVG::find_element(const std::wstring& id) { - winrt::com_ptr< ID2D1SvgElement> element; - winrt::check_hresult(svg->FindElementById(id.c_str(), element.put())); - return element; +winrt::com_ptr D2DSVG::find_element(const std::wstring& id) +{ + winrt::com_ptr element; + winrt::check_hresult(svg->FindElementById(id.c_str(), element.put())); + return element; } -D2D1_RECT_F D2DSVG::rescale(D2D1_RECT_F rect) { - D2D1_RECT_F result; - auto src = reinterpret_cast(&rect); - auto dst = reinterpret_cast(&result); - dst[0] = src[0] * transform; - dst[1] = src[1] * transform; - return result; +D2D1_RECT_F D2DSVG::rescale(D2D1_RECT_F rect) +{ + D2D1_RECT_F result; + auto src = reinterpret_cast(&rect); + auto dst = reinterpret_cast(&result); + dst[0] = src[0] * transform; + dst[1] = src[1] * transform; + return result; } diff --git a/src/common/d2d_svg.h b/src/common/d2d_svg.h index b8892a73a..08869b2de 100644 --- a/src/common/d2d_svg.h +++ b/src/common/d2d_svg.h @@ -4,21 +4,23 @@ #include #include -class D2DSVG { +class D2DSVG +{ public: - 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& render(ID2D1DeviceContext5* d2d_dc); - D2DSVG& recolor(uint32_t oldcolor, uint32_t newcolor); - float get_scale() const { return used_scale; } - int width() const { return svg_width; } - int height() const { return svg_height; } - D2DSVG& toggle_element(const wchar_t* id, bool visible); - winrt::com_ptr find_element(const std::wstring& id); - D2D1_RECT_F rescale(D2D1_RECT_F rect); + 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& render(ID2D1DeviceContext5* d2d_dc); + D2DSVG& recolor(uint32_t oldcolor, uint32_t newcolor); + float get_scale() const { return used_scale; } + int width() const { return svg_width; } + int height() const { return svg_height; } + D2DSVG& toggle_element(const wchar_t* id, bool visible); + winrt::com_ptr find_element(const std::wstring& id); + D2D1_RECT_F rescale(D2D1_RECT_F rect); + protected: - float used_scale = 1.0f; - winrt::com_ptr svg; - int svg_width = -1, svg_height = -1; - D2D1::Matrix3x2F transform; + float used_scale = 1.0f; + winrt::com_ptr svg; + int svg_width = -1, svg_height = -1; + D2D1::Matrix3x2F transform; }; diff --git a/src/common/d2d_text.cpp b/src/common/d2d_text.cpp index 439fc4cac..97fba8de7 100644 --- a/src/common/d2d_text.cpp +++ b/src/common/d2d_text.cpp @@ -1,48 +1,54 @@ #include "pch.h" #include "d2d_text.h" -D2DText::D2DText(float text_size, float scale) { - winrt::check_hresult(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), reinterpret_cast(factory.put_void()))); - resize(text_size, scale); - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); - winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); +D2DText::D2DText(float text_size, float scale) +{ + winrt::check_hresult(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), reinterpret_cast(factory.put_void()))); + resize(text_size, scale); + winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); + winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); } -D2DText & D2DText::resize(float text_size, float scale) { - format = nullptr; - winrt::check_hresult(factory->CreateTextFormat(L"Segoe UI", - nullptr, - DWRITE_FONT_WEIGHT_NORMAL, - DWRITE_FONT_STYLE_NORMAL, - DWRITE_FONT_STRETCH_NORMAL, - text_size * scale, - L"en-us", - format.put())); - winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); - return *this; +D2DText& D2DText::resize(float text_size, float scale) +{ + format = nullptr; + winrt::check_hresult(factory->CreateTextFormat(L"Segoe UI", + nullptr, + DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + text_size * scale, + L"en-us", + format.put())); + winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); + return *this; } -D2DText & D2DText::set_aligment_left() { - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING)); - return *this; +D2DText& D2DText::set_aligment_left() +{ + winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING)); + return *this; } -D2DText & D2DText::set_aligment_center() { - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); - return *this; +D2DText& D2DText::set_aligment_center() +{ + winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); + return *this; } -D2DText & D2DText::set_aligment_right() { - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING)); - return *this; +D2DText& D2DText::set_aligment_right() +{ + winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING)); + return *this; } -void D2DText::write(ID2D1DeviceContext5 * d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text) { - winrt::com_ptr brush; - d2d_dc->CreateSolidColorBrush(color, brush.put()); - d2d_dc->DrawText(text.c_str(), - (UINT32)text.length(), - format.get(), - rect, - brush.get()); +void D2DText::write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text) +{ + winrt::com_ptr brush; + d2d_dc->CreateSolidColorBrush(color, brush.put()); + d2d_dc->DrawText(text.c_str(), + (UINT32)text.length(), + format.get(), + rect, + brush.get()); } diff --git a/src/common/d2d_text.h b/src/common/d2d_text.h index c3d0e0ada..e03227cc8 100644 --- a/src/common/d2d_text.h +++ b/src/common/d2d_text.h @@ -2,15 +2,17 @@ #include #include -class D2DText { +class D2DText +{ public: - D2DText(float text_size = 15.0f, float scale = 1.0f); - D2DText& resize(float text_size, float scale); - D2DText& set_aligment_left(); - D2DText& set_aligment_center(); - D2DText& set_aligment_right(); - void write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text); + D2DText(float text_size = 15.0f, float scale = 1.0f); + D2DText& resize(float text_size, float scale); + D2DText& set_aligment_left(); + D2DText& set_aligment_center(); + D2DText& set_aligment_right(); + void write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text); + private: - winrt::com_ptr factory; - winrt::com_ptr format; + winrt::com_ptr factory; + winrt::com_ptr format; }; diff --git a/src/common/d2d_window.cpp b/src/common/d2d_window.cpp index 7ac0761da..fea43b0de 100644 --- a/src/common/d2d_window.cpp +++ b/src/common/d2d_window.cpp @@ -3,182 +3,204 @@ extern "C" IMAGE_DOS_HEADER __ImageBase; -D2DWindow::D2DWindow() { - static const WCHAR* class_name = L"PToyD2DPopup"; - WNDCLASS wc = {}; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hInstance = reinterpret_cast(&__ImageBase); - wc.lpszClassName = class_name; - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = d2d_window_proc; - RegisterClass(&wc); - hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOREDIRECTIONBITMAP | WS_EX_LAYERED, - wc.lpszClassName, - L"PToyD2DPopup", - WS_POPUP| WS_VISIBLE, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - nullptr, nullptr, wc.hInstance, this); - WINRT_VERIFY(hwnd); +D2DWindow::D2DWindow() +{ + static const WCHAR* class_name = L"PToyD2DPopup"; + WNDCLASS wc = {}; + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); + wc.hInstance = reinterpret_cast(&__ImageBase); + wc.lpszClassName = class_name; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = d2d_window_proc; + RegisterClass(&wc); + hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOREDIRECTIONBITMAP | WS_EX_LAYERED, + wc.lpszClassName, + L"PToyD2DPopup", + WS_POPUP | WS_VISIBLE, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + wc.hInstance, + this); + WINRT_VERIFY(hwnd); } -void D2DWindow::show(UINT x, UINT y, UINT width, UINT height) { - if (!initialized) { +void D2DWindow::show(UINT x, UINT y, UINT width, UINT height) +{ + if (!initialized) + { + base_init(); + } + base_resize(width, height); + render_empty(); + on_show(); + SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, 0); + ShowWindow(hwnd, SW_SHOWNORMAL); + UpdateWindow(hwnd); +} + +void D2DWindow::hide() +{ + ShowWindow(hwnd, SW_HIDE); + on_hide(); +} + +void D2DWindow::initialize() +{ base_init(); - } - base_resize(width, height); - render_empty(); - on_show(); - SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, 0); - ShowWindow(hwnd, SW_SHOWNORMAL); - UpdateWindow(hwnd); } -void D2DWindow::hide() { - ShowWindow(hwnd, SW_HIDE); - on_hide(); -} - -void D2DWindow::initialize() { - base_init(); -} - -void D2DWindow::base_init() { - std::unique_lock lock(mutex); - // D2D1Factory is independent from the device, no need to recreate it if we need to recreate the device. - if (!d2d_factory) { +void D2DWindow::base_init() +{ + std::unique_lock lock(mutex); + // D2D1Factory is independent from the device, no need to recreate it if we need to recreate the device. + if (!d2d_factory) + { #ifdef _DEBUG - D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION }; + D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION }; #else - D2D1_FACTORY_OPTIONS options = {}; + D2D1_FACTORY_OPTIONS options = {}; #endif - winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, - __uuidof(d2d_factory), - &options, - d2d_factory.put_void())); - } - // For all other stuff - assing nullptr first to release the object, to reset the com_ptr. - d2d_dc = nullptr; - d2d_device = nullptr; - dxgi_factory = nullptr; - dxgi_device = nullptr; - d3d_device = nullptr; - winrt::check_hresult(D3D11CreateDevice(nullptr, - D3D_DRIVER_TYPE_HARDWARE, - nullptr, - D3D11_CREATE_DEVICE_BGRA_SUPPORT, - nullptr, - 0, - D3D11_SDK_VERSION, - d3d_device.put(), - nullptr, - nullptr)); - winrt::check_hresult(d3d_device->QueryInterface(__uuidof(dxgi_device), dxgi_device.put_void())); - winrt::check_hresult(CreateDXGIFactory2(0, __uuidof(dxgi_factory), dxgi_factory.put_void())); - winrt::check_hresult(d2d_factory->CreateDevice(dxgi_device.get(), d2d_device.put())); - winrt::check_hresult(d2d_device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, d2d_dc.put())); - init(); - initialized = true; + winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, + __uuidof(d2d_factory), + &options, + d2d_factory.put_void())); + } + // For all other stuff - assing nullptr first to release the object, to reset the com_ptr. + d2d_dc = nullptr; + d2d_device = nullptr; + dxgi_factory = nullptr; + dxgi_device = nullptr; + d3d_device = nullptr; + winrt::check_hresult(D3D11CreateDevice(nullptr, + D3D_DRIVER_TYPE_HARDWARE, + nullptr, + D3D11_CREATE_DEVICE_BGRA_SUPPORT, + nullptr, + 0, + D3D11_SDK_VERSION, + d3d_device.put(), + nullptr, + nullptr)); + winrt::check_hresult(d3d_device->QueryInterface(__uuidof(dxgi_device), dxgi_device.put_void())); + winrt::check_hresult(CreateDXGIFactory2(0, __uuidof(dxgi_factory), dxgi_factory.put_void())); + winrt::check_hresult(d2d_factory->CreateDevice(dxgi_device.get(), d2d_device.put())); + winrt::check_hresult(d2d_device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, d2d_dc.put())); + init(); + initialized = true; } -void D2DWindow::base_resize(UINT width, UINT height) { - std::unique_lock lock(mutex); - if (!initialized) { - return; - } - window_width = width; - window_height = height; - if (window_width == 0 || window_height == 0) { - return; - } - DXGI_SWAP_CHAIN_DESC1 sc_description = {}; - sc_description.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - sc_description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sc_description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - sc_description.BufferCount = 2; - sc_description.SampleDesc.Count = 1; - sc_description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; - sc_description.Width = window_width; - sc_description.Height = window_height; - dxgi_swap_chain = nullptr; - winrt::check_hresult(dxgi_factory->CreateSwapChainForComposition(dxgi_device.get(), - &sc_description, - nullptr, - dxgi_swap_chain.put())); - composition_device = nullptr; - winrt::check_hresult(DCompositionCreateDevice(dxgi_device.get(), - __uuidof(composition_device), - composition_device.put_void())); +void D2DWindow::base_resize(UINT width, UINT height) +{ + std::unique_lock lock(mutex); + if (!initialized) + { + return; + } + window_width = width; + window_height = height; + if (window_width == 0 || window_height == 0) + { + return; + } + DXGI_SWAP_CHAIN_DESC1 sc_description = {}; + sc_description.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + sc_description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sc_description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + sc_description.BufferCount = 2; + sc_description.SampleDesc.Count = 1; + sc_description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; + sc_description.Width = window_width; + sc_description.Height = window_height; + dxgi_swap_chain = nullptr; + winrt::check_hresult(dxgi_factory->CreateSwapChainForComposition(dxgi_device.get(), + &sc_description, + nullptr, + dxgi_swap_chain.put())); + composition_device = nullptr; + winrt::check_hresult(DCompositionCreateDevice(dxgi_device.get(), + __uuidof(composition_device), + composition_device.put_void())); - composition_target = nullptr; - winrt::check_hresult(composition_device->CreateTargetForHwnd(hwnd, true, composition_target.put())); - - composition_visual = nullptr; - winrt::check_hresult(composition_device->CreateVisual(composition_visual.put())); - winrt::check_hresult(composition_visual->SetContent(dxgi_swap_chain.get())); - winrt::check_hresult(composition_target->SetRoot(composition_visual.get())); - - dxgi_surface = nullptr; - winrt::check_hresult(dxgi_swap_chain->GetBuffer(0, __uuidof(dxgi_surface), dxgi_surface.put_void())); - D2D1_BITMAP_PROPERTIES1 properties = {}; - properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; - properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; - properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; - - d2d_bitmap = nullptr; - winrt::check_hresult(d2d_dc->CreateBitmapFromDxgiSurface(dxgi_surface.get(), - properties, - d2d_bitmap.put())); - d2d_dc->SetTarget(d2d_bitmap.get()); - resize(); + composition_target = nullptr; + winrt::check_hresult(composition_device->CreateTargetForHwnd(hwnd, true, composition_target.put())); + + composition_visual = nullptr; + winrt::check_hresult(composition_device->CreateVisual(composition_visual.put())); + winrt::check_hresult(composition_visual->SetContent(dxgi_swap_chain.get())); + winrt::check_hresult(composition_target->SetRoot(composition_visual.get())); + + dxgi_surface = nullptr; + winrt::check_hresult(dxgi_swap_chain->GetBuffer(0, __uuidof(dxgi_surface), dxgi_surface.put_void())); + D2D1_BITMAP_PROPERTIES1 properties = {}; + properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; + properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; + + d2d_bitmap = nullptr; + winrt::check_hresult(d2d_dc->CreateBitmapFromDxgiSurface(dxgi_surface.get(), + properties, + d2d_bitmap.put())); + d2d_dc->SetTarget(d2d_bitmap.get()); + resize(); } -void D2DWindow::base_render() { - std::unique_lock lock(mutex); - if (!initialized || !d2d_dc || !d2d_bitmap) - return; - d2d_dc->BeginDraw(); - render(d2d_dc.get()); - winrt::check_hresult(d2d_dc->EndDraw()); - winrt::check_hresult(dxgi_swap_chain->Present(1, 0)); - winrt::check_hresult(composition_device->Commit()); +void D2DWindow::base_render() +{ + std::unique_lock lock(mutex); + if (!initialized || !d2d_dc || !d2d_bitmap) + return; + d2d_dc->BeginDraw(); + render(d2d_dc.get()); + winrt::check_hresult(d2d_dc->EndDraw()); + winrt::check_hresult(dxgi_swap_chain->Present(1, 0)); + winrt::check_hresult(composition_device->Commit()); } -void D2DWindow::render_empty() { - std::unique_lock lock(mutex); - if (!initialized || !d2d_dc || !d2d_bitmap) - return; - d2d_dc->BeginDraw(); - d2d_dc->Clear(); - winrt::check_hresult(d2d_dc->EndDraw()); - winrt::check_hresult(dxgi_swap_chain->Present(1, 0)); - winrt::check_hresult(composition_device->Commit()); +void D2DWindow::render_empty() +{ + std::unique_lock lock(mutex); + if (!initialized || !d2d_dc || !d2d_bitmap) + return; + d2d_dc->BeginDraw(); + d2d_dc->Clear(); + winrt::check_hresult(d2d_dc->EndDraw()); + winrt::check_hresult(dxgi_swap_chain->Present(1, 0)); + winrt::check_hresult(composition_device->Commit()); } -D2DWindow::~D2DWindow() { - ShowWindow(hwnd, SW_HIDE); - DestroyWindow(hwnd); +D2DWindow::~D2DWindow() +{ + ShowWindow(hwnd, SW_HIDE); + DestroyWindow(hwnd); } -D2DWindow* D2DWindow::this_from_hwnd(HWND window) { - return reinterpret_cast(GetWindowLongPtr(window, GWLP_USERDATA)); +D2DWindow* D2DWindow::this_from_hwnd(HWND window) +{ + return reinterpret_cast(GetWindowLongPtr(window, GWLP_USERDATA)); } -LRESULT __stdcall D2DWindow::d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { - switch (message) { - case WM_NCCREATE: { - auto create_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast(create_struct->lpCreateParams)); - return TRUE; - } - case WM_MOVE: - case WM_SIZE: - this_from_hwnd(window)->base_resize((unsigned)lparam & 0xFFFF, (unsigned)lparam >> 16); - // Fall through to call 'base_render()' - case WM_PAINT: - this_from_hwnd(window)->base_render(); - return 0; - default: - return DefWindowProc(window, message, wparam, lparam); - } +LRESULT __stdcall D2DWindow::d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) +{ + switch (message) + { + case WM_NCCREATE: + { + auto create_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast(create_struct->lpCreateParams)); + return TRUE; + } + case WM_MOVE: + case WM_SIZE: + this_from_hwnd(window)->base_resize((unsigned)lparam & 0xFFFF, (unsigned)lparam >> 16); + // Fall through to call 'base_render()' + case WM_PAINT: + this_from_hwnd(window)->base_render(); + return 0; + default: + return DefWindowProc(window, message, wparam, lparam); + } } diff --git a/src/common/d2d_window.h b/src/common/d2d_window.h index 5963acd95..7e7e2ffea 100644 --- a/src/common/d2d_window.h +++ b/src/common/d2d_window.h @@ -14,47 +14,48 @@ class D2DWindow { public: - D2DWindow(); - void show(UINT x, UINT y, UINT width, UINT height); - void hide(); - void initialize(); - virtual ~D2DWindow(); + D2DWindow(); + void show(UINT x, UINT y, UINT width, UINT height); + void hide(); + void initialize(); + virtual ~D2DWindow(); + protected: - // Implement this: + // Implement this: - // Initialization - called when D2D device needs to be created. - // When called all D2DWindow members will be initialized, including d2d_dc - virtual void init() = 0; - // resize - when called, window_width and window_height will have current window size - virtual void resize() = 0; - // render - called on WM_PAIT, BeginPaint/EndPaint is handled by D2DWindow - virtual void render(ID2D1DeviceContext5* d2d_dc) = 0; - // on_show, on_hide - called when the window is about to be shown or about to be hidden - virtual void on_show() = 0; - virtual void on_hide() = 0; + // Initialization - called when D2D device needs to be created. + // When called all D2DWindow members will be initialized, including d2d_dc + virtual void init() = 0; + // resize - when called, window_width and window_height will have current window size + virtual void resize() = 0; + // render - called on WM_PAIT, BeginPaint/EndPaint is handled by D2DWindow + virtual void render(ID2D1DeviceContext5* d2d_dc) = 0; + // on_show, on_hide - called when the window is about to be shown or about to be hidden + virtual void on_show() = 0; + virtual void on_hide() = 0; - static LRESULT __stdcall d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); - static D2DWindow* this_from_hwnd(HWND window); - - void base_init(); - void base_resize(UINT width, UINT height); - void base_render(); - void render_empty(); + static LRESULT __stdcall d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); + static D2DWindow* this_from_hwnd(HWND window); - std::recursive_mutex mutex; - bool initialized = false; - HWND hwnd; - UINT window_width, window_height; - winrt::com_ptr d3d_device; - winrt::com_ptr dxgi_device; - winrt::com_ptr dxgi_factory; - winrt::com_ptr dxgi_swap_chain; - winrt::com_ptr composition_device; - winrt::com_ptr composition_target; - winrt::com_ptr composition_visual; - winrt::com_ptr dxgi_surface; - winrt::com_ptr d2d_bitmap; - winrt::com_ptr d2d_factory; - winrt::com_ptr d2d_device; - winrt::com_ptr d2d_dc; + void base_init(); + void base_resize(UINT width, UINT height); + void base_render(); + void render_empty(); + + std::recursive_mutex mutex; + bool initialized = false; + HWND hwnd; + UINT window_width, window_height; + winrt::com_ptr d3d_device; + winrt::com_ptr dxgi_device; + winrt::com_ptr dxgi_factory; + winrt::com_ptr dxgi_swap_chain; + winrt::com_ptr composition_device; + winrt::com_ptr composition_target; + winrt::com_ptr composition_visual; + winrt::com_ptr dxgi_surface; + winrt::com_ptr d2d_bitmap; + winrt::com_ptr d2d_factory; + winrt::com_ptr d2d_device; + winrt::com_ptr d2d_dc; }; diff --git a/src/common/json.cpp b/src/common/json.cpp index e9d798676..b8c06d73a 100644 --- a/src/common/json.cpp +++ b/src/common/json.cpp @@ -5,22 +5,22 @@ namespace json { - std::optional from_file(std::wstring_view file_name) - { - try + std::optional from_file(std::wstring_view file_name) { - std::wifstream file(file_name.data(), std::ios::binary); - using isbi = std::istreambuf_iterator; - return JsonValue::Parse(std::wstring{isbi{file}, isbi{}}).GetObjectW(); + try + { + std::wifstream file(file_name.data(), std::ios::binary); + using isbi = std::istreambuf_iterator; + return JsonValue::Parse(std::wstring{ isbi{ file }, isbi{} }).GetObjectW(); + } + catch (...) + { + return std::nullopt; + } } - catch(...) - { - return std::nullopt; - } - } - void to_file(std::wstring_view file_name, const JsonObject & obj) - { - std::wofstream{file_name.data(), std::ios::binary} << obj.Stringify().c_str(); - } + void to_file(std::wstring_view file_name, const JsonObject& obj) + { + std::wofstream{ file_name.data(), std::ios::binary } << obj.Stringify().c_str(); + } } diff --git a/src/common/json.h b/src/common/json.h index 30292962d..141cc107a 100644 --- a/src/common/json.h +++ b/src/common/json.h @@ -7,44 +7,44 @@ namespace json { - using namespace winrt::Windows::Data::Json; + using namespace winrt::Windows::Data::Json; - std::optional from_file(std::wstring_view file_name); + std::optional from_file(std::wstring_view file_name); - void to_file(std::wstring_view file_name, const JsonObject& obj); + void to_file(std::wstring_view file_name, const JsonObject& obj); - inline bool has( - const json::JsonObject & o, - std::wstring_view name, - const json::JsonValueType type = JsonValueType::Object) - { - return o.HasKey(name) && o.GetNamedValue(name).ValueType() == type; - } + inline bool has( + const json::JsonObject& o, + std::wstring_view name, + const json::JsonValueType type = JsonValueType::Object) + { + return o.HasKey(name) && o.GetNamedValue(name).ValueType() == type; + } - template - inline std::enable_if_t, JsonValue> value(const T arithmetic) - { - return json::JsonValue::CreateNumberValue(arithmetic); - } + template + inline std::enable_if_t, JsonValue> value(const T arithmetic) + { + return json::JsonValue::CreateNumberValue(arithmetic); + } - template - inline std::enable_if_t, JsonValue> value(T s) - { - return json::JsonValue::CreateStringValue(s); - } + template + inline std::enable_if_t, JsonValue> value(T s) + { + return json::JsonValue::CreateStringValue(s); + } - inline JsonValue value(const bool boolean) - { - return json::JsonValue::CreateBooleanValue(boolean); - } + inline JsonValue value(const bool boolean) + { + return json::JsonValue::CreateBooleanValue(boolean); + } - inline JsonValue value(JsonObject value) - { - return value.as(); - } + inline JsonValue value(JsonObject value) + { + return value.as(); + } - inline JsonValue value(JsonValue value) - { - return value; // identity function overload for convenience - } + inline JsonValue value(JsonValue value) + { + return value; // identity function overload for convenience + } } diff --git a/src/common/monitors.cpp b/src/common/monitors.cpp index dbabc4949..e3b4f766d 100644 --- a/src/common/monitors.cpp +++ b/src/common/monitors.cpp @@ -3,67 +3,77 @@ #include "common.h" #include "monitors.h" -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 rhs_tuple = std::make_tuple(rhs.rect.left, rhs.rect.right, rhs.rect.top, rhs.rect.bottom); - return lhs_tuple == rhs_tuple; +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 rhs_tuple = std::make_tuple(rhs.rect.left, rhs.rect.right, rhs.rect.top, rhs.rect.bottom); + return lhs_tuple == rhs_tuple; } -static BOOL CALLBACK get_displays_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) { - MONITORINFOEX monitor_info; - monitor_info.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(monitor, &monitor_info); - reinterpret_cast*>(data)->emplace_back(monitor, monitor_info.rcWork); - return true; +static BOOL CALLBACK get_displays_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) +{ + MONITORINFOEX monitor_info; + monitor_info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor, &monitor_info); + reinterpret_cast*>(data)->emplace_back(monitor, monitor_info.rcWork); + return true; }; -static BOOL CALLBACK get_displays_enum_cb_with_toolbar(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) { - MONITORINFOEX monitor_info; - monitor_info.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(monitor, &monitor_info); - reinterpret_cast*>(data)->emplace_back(monitor, monitor_info.rcMonitor); - return true; +static BOOL CALLBACK get_displays_enum_cb_with_toolbar(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) +{ + MONITORINFOEX monitor_info; + monitor_info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor, &monitor_info); + reinterpret_cast*>(data)->emplace_back(monitor, monitor_info.rcMonitor); + return true; }; -std::vector MonitorInfo::GetMonitors(bool include_toolbar) { - std::vector monitors; - EnumDisplayMonitors(NULL, NULL, include_toolbar ? get_displays_enum_cb_with_toolbar : get_displays_enum_cb, reinterpret_cast(&monitors)); - std::sort(begin(monitors), end(monitors), [](const MonitorInfo& lhs, const MonitorInfo& rhs) { - return lhs.rect < rhs.rect; +std::vector MonitorInfo::GetMonitors(bool include_toolbar) +{ + std::vector monitors; + EnumDisplayMonitors(NULL, NULL, include_toolbar ? get_displays_enum_cb_with_toolbar : get_displays_enum_cb, reinterpret_cast(&monitors)); + std::sort(begin(monitors), end(monitors), [](const MonitorInfo& lhs, const MonitorInfo& rhs) { + return lhs.rect < rhs.rect; }); - return monitors; + return monitors; } -static BOOL CALLBACK get_primary_display_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) { - MONITORINFOEX monitor_info; - monitor_info.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(monitor, &monitor_info); - if (monitor_info.dwFlags & MONITORINFOF_PRIMARY) { - reinterpret_cast(data)->handle = monitor; - reinterpret_cast(data)->rect = monitor_info.rcWork; - } - return true; +static BOOL CALLBACK get_primary_display_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data) +{ + MONITORINFOEX monitor_info; + monitor_info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor, &monitor_info); + if (monitor_info.dwFlags & MONITORINFOF_PRIMARY) + { + reinterpret_cast(data)->handle = monitor; + reinterpret_cast(data)->rect = monitor_info.rcWork; + } + return true; }; -MonitorInfo MonitorInfo::GetPrimaryMonitor() { - MonitorInfo primary({}, {}); - EnumDisplayMonitors(NULL, NULL, get_primary_display_enum_cb, reinterpret_cast(&primary)); - return primary; +MonitorInfo MonitorInfo::GetPrimaryMonitor() +{ + MonitorInfo primary({}, {}); + EnumDisplayMonitors(NULL, NULL, get_primary_display_enum_cb, reinterpret_cast(&primary)); + return primary; } -MonitorInfo MonitorInfo::GetFromWindow(HWND hwnd) { - auto monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); - return GetFromHandle(monitor); +MonitorInfo MonitorInfo::GetFromWindow(HWND hwnd) +{ + auto monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + return GetFromHandle(monitor); } -MonitorInfo MonitorInfo::GetFromPoint(POINT p) { - auto monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST); - return GetFromHandle(monitor); +MonitorInfo MonitorInfo::GetFromPoint(POINT p) +{ + auto monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST); + return GetFromHandle(monitor); } -MonitorInfo MonitorInfo::GetFromHandle(HMONITOR monitor) { - MONITORINFOEX monitor_info; - monitor_info.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(monitor, &monitor_info); - return MonitorInfo(monitor, monitor_info.rcWork); +MonitorInfo MonitorInfo::GetFromHandle(HMONITOR monitor) +{ + MONITORINFOEX monitor_info; + monitor_info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor, &monitor_info); + return MonitorInfo(monitor, monitor_info.rcWork); } diff --git a/src/common/monitors.h b/src/common/monitors.h index 1b2fb59ef..616656e73 100644 --- a/src/common/monitors.h +++ b/src/common/monitors.h @@ -2,40 +2,44 @@ #include #include -struct ScreenSize { - explicit ScreenSize(RECT rect) : rect(rect) {} - RECT rect; - int left() const { return rect.left; } - int right() const { return rect.right; } - int top() const { return rect.top; } - int bottom() const { return rect.bottom; } - int height() const { return rect.bottom - rect.top; }; - int width() const { return rect.right - rect.left; }; - POINT top_left() const { return { rect.left, rect.top }; }; - POINT top_middle() const { return { rect.left + width() / 2, rect.top }; }; - POINT top_right() const { return { rect.right, rect.top }; }; - POINT middle_left() const { return { rect.left, rect.top + height() / 2 }; }; - POINT middle() const { return { rect.left + width() / 2, rect.top + height() / 2 }; }; - POINT middle_right() const { return { rect.right, rect.top + height() / 2 }; }; - POINT bottom_left() const { return { rect.left, rect.bottom }; }; - POINT bottm_midle() const { return { rect.left + width() / 2, rect.bottom }; }; - POINT bottom_right() const { return { rect.right, rect.bottom }; }; +struct ScreenSize +{ + explicit ScreenSize(RECT rect) : + rect(rect) {} + RECT rect; + int left() const { return rect.left; } + int right() const { return rect.right; } + int top() const { return rect.top; } + int bottom() const { return rect.bottom; } + int height() const { return rect.bottom - rect.top; }; + int width() const { return rect.right - rect.left; }; + POINT top_left() const { return { rect.left, rect.top }; }; + POINT top_middle() const { return { rect.left + width() / 2, rect.top }; }; + POINT top_right() const { return { rect.right, rect.top }; }; + POINT middle_left() const { return { rect.left, rect.top + height() / 2 }; }; + POINT middle() const { return { rect.left + width() / 2, rect.top + height() / 2 }; }; + POINT middle_right() const { return { rect.right, rect.top + height() / 2 }; }; + POINT bottom_left() const { return { rect.left, rect.bottom }; }; + POINT bottm_midle() const { return { rect.left + width() / 2, rect.bottom }; }; + POINT bottom_right() const { return { rect.right, rect.bottom }; }; }; -struct MonitorInfo : ScreenSize { - explicit MonitorInfo(HMONITOR monitor, RECT rect) : handle(monitor), ScreenSize(rect) {} - HMONITOR handle; +struct MonitorInfo : ScreenSize +{ + explicit MonitorInfo(HMONITOR monitor, RECT rect) : + handle(monitor), ScreenSize(rect) {} + HMONITOR handle; - // Returns monitor rects ordered from left to right - static std::vector GetMonitors(bool include_toolbar); - // Return primary display - static MonitorInfo GetPrimaryMonitor(); - // Return monitor on which hwnd window is displayed - static MonitorInfo GetFromWindow(HWND hwnd); - // Return monitor nearest to a point - static MonitorInfo GetFromPoint(POINT p); - // Return monitor info given a HMONITOR - static MonitorInfo GetFromHandle(HMONITOR monitor); + // Returns monitor rects ordered from left to right + static std::vector GetMonitors(bool include_toolbar); + // Return primary display + static MonitorInfo GetPrimaryMonitor(); + // Return monitor on which hwnd window is displayed + static MonitorInfo GetFromWindow(HWND hwnd); + // Return monitor nearest to a point + static MonitorInfo GetFromPoint(POINT p); + // Return monitor info given a HMONITOR + static MonitorInfo GetFromHandle(HMONITOR monitor); }; bool operator==(const ScreenSize& lhs, const ScreenSize& rhs); diff --git a/src/common/msi_to_msix_upgrade_lib/pch.cpp b/src/common/msi_to_msix_upgrade_lib/pch.cpp index ce9b73991..1d9f38c57 100644 --- a/src/common/msi_to_msix_upgrade_lib/pch.cpp +++ b/src/common/msi_to_msix_upgrade_lib/pch.cpp @@ -1,2 +1 @@ #include "pch.h" - diff --git a/src/common/notifications.cpp b/src/common/notifications.cpp index 0aa4d0175..cf500bd7c 100644 --- a/src/common/notifications.cpp +++ b/src/common/notifications.cpp @@ -189,7 +189,7 @@ void notifications::show_toast_with_activations(std::wstring_view message, std:: std::wstring toast_xml; toast_xml.reserve(1024); - std::wstring title{L"PowerToys"}; + std::wstring title{ L"PowerToys" }; if (winstore::running_as_packaged()) { title += L" (Experimental)"; diff --git a/src/common/on_thread_executor.cpp b/src/common/on_thread_executor.cpp index ef212cfb1..e5a55ffe1 100644 --- a/src/common/on_thread_executor.cpp +++ b/src/common/on_thread_executor.cpp @@ -2,38 +2,42 @@ #include "on_thread_executor.h" -OnThreadExecutor::OnThreadExecutor() - : _shutdown_request{false} - , _worker_thread{[this] { worker_thread(); }} -{} - -std::future OnThreadExecutor::submit(task_t task) { - auto future = task.get_future(); - std::lock_guard lock{_task_mutex}; - _task_queue.emplace(std::move(task)); - _task_cv.notify_one(); - return future; +OnThreadExecutor::OnThreadExecutor() : + _shutdown_request{ false }, _worker_thread{ [this] { worker_thread(); } } +{ } -void OnThreadExecutor::worker_thread() { - while(!_shutdown_request) { - task_t task; +std::future OnThreadExecutor::submit(task_t task) +{ + auto future = task.get_future(); + std::lock_guard lock{ _task_mutex }; + _task_queue.emplace(std::move(task)); + _task_cv.notify_one(); + return future; +} + +void OnThreadExecutor::worker_thread() +{ + while (!_shutdown_request) { - std::unique_lock task_lock{_task_mutex}; - _task_cv.wait(task_lock, [this] { return !_task_queue.empty() || _shutdown_request; }); - if(_shutdown_request) { - return; - } - task = std::move(_task_queue.front()); - _task_queue.pop(); + task_t task; + { + std::unique_lock task_lock{ _task_mutex }; + _task_cv.wait(task_lock, [this] { return !_task_queue.empty() || _shutdown_request; }); + if (_shutdown_request) + { + return; + } + task = std::move(_task_queue.front()); + _task_queue.pop(); + } + task(); } - task(); - } } -OnThreadExecutor::~OnThreadExecutor() { - _shutdown_request = true; - _task_cv.notify_one(); - _worker_thread.join(); +OnThreadExecutor::~OnThreadExecutor() +{ + _shutdown_request = true; + _task_cv.notify_one(); + _worker_thread.join(); } - diff --git a/src/common/on_thread_executor.h b/src/common/on_thread_executor.h index c7d29359a..a498afdf7 100644 --- a/src/common/on_thread_executor.h +++ b/src/common/on_thread_executor.h @@ -10,21 +10,22 @@ // This might come in handy if you use the API which sets thread-wide global state and the state needs // to be isolated. -class OnThreadExecutor final { +class OnThreadExecutor final +{ public: - using task_t = std::packaged_task; + using task_t = std::packaged_task; - OnThreadExecutor(); - ~OnThreadExecutor(); - std::future submit(task_t task); + OnThreadExecutor(); + ~OnThreadExecutor(); + std::future submit(task_t task); private: - void worker_thread(); + void worker_thread(); - std::thread _worker_thread; + std::thread _worker_thread; - std::mutex _task_mutex; - std::condition_variable _task_cv; - std::atomic_bool _shutdown_request; - std::queue> _task_queue; + std::mutex _task_mutex; + std::condition_variable _task_cv; + std::atomic_bool _shutdown_request; + std::queue> _task_queue; }; diff --git a/src/common/pch.h b/src/common/pch.h index 7c82c2a64..68a805c03 100644 --- a/src/common/pch.h +++ b/src/common/pch.h @@ -22,4 +22,3 @@ #include #include #include - diff --git a/src/common/settings_helpers.cpp b/src/common/settings_helpers.cpp index 8d3c56779..88bf018ff 100644 --- a/src/common/settings_helpers.cpp +++ b/src/common/settings_helpers.cpp @@ -3,62 +3,72 @@ #include #include -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() + { + PWSTR local_app_path; + winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path)); + std::wstring result{ local_app_path }; + CoTaskMemFree(local_app_path); - std::wstring get_root_save_folder_location() { - PWSTR local_app_path; - winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path)); - std::wstring result{local_app_path}; - CoTaskMemFree(local_app_path); - - result += L"\\Microsoft\\PowerToys"; - std::filesystem::path save_path(result); - if (!std::filesystem::exists(save_path)) { - std::filesystem::create_directories(save_path); + result += L"\\Microsoft\\PowerToys"; + std::filesystem::path save_path(result); + if (!std::filesystem::exists(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 result = get_root_save_folder_location(); - result += L"\\"; - result += powertoy_name; - std::filesystem::path save_path(result); - if (!std::filesystem::exists(save_path)) { - std::filesystem::create_directories(save_path); + std::wstring get_module_save_folder_location(std::wstring_view powertoy_name) + { + std::wstring result = get_root_save_folder_location(); + result += L"\\"; + result += powertoy_name; + std::filesystem::path save_path(result); + if (!std::filesystem::exists(save_path)) + { + std::filesystem::create_directories(save_path); + } + return result; } - return result; - } - std::wstring get_module_save_file_location(std::wstring_view powertoy_name) { - return get_module_save_folder_location(powertoy_name) + settings_filename; - } + std::wstring get_module_save_file_location(std::wstring_view powertoy_name) + { + return get_module_save_folder_location(powertoy_name) + settings_filename; + } - std::wstring get_powertoys_general_save_file_location() { - return get_root_save_folder_location() + settings_filename; - } + std::wstring get_powertoys_general_save_file_location() + { + return get_root_save_folder_location() + settings_filename; + } - 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); - json::to_file(save_file_location, 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); + json::to_file(save_file_location, settings); + } - json::JsonObject load_module_settings(std::wstring_view powertoy_name) { - const std::wstring save_file_location = get_module_save_file_location(powertoy_name); - auto saved_settings = json::from_file(save_file_location); - return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{}; - } + json::JsonObject load_module_settings(std::wstring_view powertoy_name) + { + const std::wstring save_file_location = get_module_save_file_location(powertoy_name); + auto saved_settings = json::from_file(save_file_location); + return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{}; + } - void save_general_settings(const json::JsonObject& settings) { - const std::wstring save_file_location = get_powertoys_general_save_file_location(); - json::to_file(save_file_location, settings); - } + void save_general_settings(const json::JsonObject& settings) + { + const std::wstring save_file_location = get_powertoys_general_save_file_location(); + json::to_file(save_file_location, settings); + } - json::JsonObject load_general_settings() { - const std::wstring save_file_location = get_powertoys_general_save_file_location(); - auto saved_settings = json::from_file(save_file_location); - return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{}; - } + json::JsonObject load_general_settings() + { + const std::wstring save_file_location = get_powertoys_general_save_file_location(); + auto saved_settings = json::from_file(save_file_location); + return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{}; + } } diff --git a/src/common/settings_helpers.h b/src/common/settings_helpers.h index 1678ae883..754ab0237 100644 --- a/src/common/settings_helpers.h +++ b/src/common/settings_helpers.h @@ -4,14 +4,14 @@ #include "json.h" -namespace PTSettingsHelper { +namespace PTSettingsHelper +{ + std::wstring get_module_save_folder_location(std::wstring_view powertoy_name); + std::wstring get_root_save_folder_location(); - std::wstring get_module_save_folder_location(std::wstring_view powertoy_name); - std::wstring get_root_save_folder_location(); - - void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings); - json::JsonObject load_module_settings(std::wstring_view powertoy_name); - void save_general_settings(const json::JsonObject& settings); - json::JsonObject load_general_settings(); + void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings); + json::JsonObject load_module_settings(std::wstring_view powertoy_name); + void save_general_settings(const json::JsonObject& settings); + json::JsonObject load_general_settings(); } diff --git a/src/common/settings_objects.cpp b/src/common/settings_objects.cpp index b2fe76a08..450532116 100644 --- a/src/common/settings_objects.cpp +++ b/src/common/settings_objects.cpp @@ -2,298 +2,350 @@ #include "settings_objects.h" #include "settings_helpers.h" -namespace PowerToysSettings { - - Settings::Settings(const HINSTANCE hinstance, std::wstring_view powertoy_name) { - m_instance = hinstance; - m_json.SetNamedValue(L"version", json::value(L"1.0")); - m_json.SetNamedValue(L"name", json::value(powertoy_name)); - m_json.SetNamedValue(L"properties", json::JsonObject{}); - } - - void Settings::set_description(UINT resource_id) { - m_json.SetNamedValue(L"description", json::value(get_resource(resource_id))); - } - - void Settings::set_description(std::wstring_view description) { - m_json.SetNamedValue(L"description", json::value(description)); - } - - void Settings::set_icon_key(std::wstring_view icon_key) { - m_json.SetNamedValue(L"icon_key", json::value(icon_key)); - } - - void Settings::set_overview_link(std::wstring_view overview_link) { - m_json.SetNamedValue(L"overview_link", json::value(overview_link)); - } - - void Settings::set_video_link(std::wstring_view video_link) { - m_json.SetNamedValue(L"video_link", json::value(video_link)); - } - - // add_bool_toogle overloads. - 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); - } - - void Settings::add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value) { - json::JsonObject toggle; - toggle.SetNamedValue(L"display_name", json::value(description)); - toggle.SetNamedValue(L"editor_type", json::value(L"bool_toggle")); - toggle.SetNamedValue(L"value", json::value(value)); - toggle.SetNamedValue(L"order", json::value(++m_curr_priority)); - - m_json.GetNamedObject(L"properties").SetNamedValue(name, toggle); - } - - // 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) { - 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) { - json::JsonObject spinner; - spinner.SetNamedValue(L"display_name", json::value(description)); - spinner.SetNamedValue(L"editor_type", json::value(L"int_spinner")); - spinner.SetNamedValue(L"value", json::value(value)); - spinner.SetNamedValue(L"min", json::value(min)); - spinner.SetNamedValue(L"max", json::value(max)); - spinner.SetNamedValue(L"step", json::value(step)); - spinner.SetNamedValue(L"order", json::value(++m_curr_priority)); - - m_json.GetNamedObject(L"properties").SetNamedValue(name, spinner); - } - - // add_string overloads. - 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); - } - - void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) { - json::JsonObject string; - string.SetNamedValue(L"display_name", json::value(description)); - string.SetNamedValue(L"editor_type", json::value(L"string_text")); - string.SetNamedValue(L"value", json::value(value)); - string.SetNamedValue(L"order", json::value(++m_curr_priority)); - - m_json.GetNamedObject(L"properties").SetNamedValue(name, string); - } - - // add_multiline_string overloads. - 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); - } - - void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) { - json::JsonObject ml_string; - ml_string.SetNamedValue(L"display_name", json::value(description)); - ml_string.SetNamedValue(L"editor_type", json::value(L"string_text")); - ml_string.SetNamedValue(L"value", json::value(value)); - ml_string.SetNamedValue(L"order", json::value(++m_curr_priority)); - ml_string.SetNamedValue(L"multiline", json::value(true)); - - m_json.GetNamedObject(L"properties").SetNamedValue(name, ml_string); - } - - // add_color_picker overloads. - 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); - } - - void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value) { - json::JsonObject picker; - picker.SetNamedValue(L"display_name", json::value(description)); - picker.SetNamedValue(L"editor_type", json::value(L"color_picker")); - picker.SetNamedValue(L"value", json::value(value)); - picker.SetNamedValue(L"order", json::value(++m_curr_priority)); - - m_json.GetNamedObject(L"properties").SetNamedValue(name, picker); - } - - void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& 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) { - json::JsonObject hotkey; - hotkey.SetNamedValue(L"display_name", json::value(description)); - hotkey.SetNamedValue(L"editor_type", json::value(L"hotkey")); - hotkey.SetNamedValue(L"value", hotkey_obj.get_json()); - hotkey.SetNamedValue(L"order", json::value(++m_curr_priority)); - - 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>& keys_and_text_ids) { - std::vector> keys_and_texts; - keys_and_texts.reserve(keys_and_text_ids.size()); - for (const auto& kv : keys_and_text_ids) { - keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); - } - 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>& keys_and_texts) { - json::JsonObject choice_group; - choice_group.SetNamedValue(L"display_name", json::value(description)); - choice_group.SetNamedValue(L"editor_type", json::value(L"choice_group")); - json::JsonArray options; - for(const auto & [key, text] : keys_and_texts) { - json::JsonObject entry; - entry.SetNamedValue(L"key", json::value(key)); - entry.SetNamedValue(L"text", json::value(text)); - options.Append(std::move(entry)); - } - choice_group.SetNamedValue(L"options", std::move(options)); - choice_group.SetNamedValue(L"value", json::value(value)); - choice_group.SetNamedValue(L"order", json::value(++m_curr_priority)); - - 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>& keys_and_text_ids) { - std::vector> keys_and_texts; - keys_and_texts.reserve(keys_and_text_ids.size()); - for (const auto& kv : keys_and_text_ids) { - keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); - } - 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>& keys_and_texts) { - json::JsonObject dropdown; - dropdown.SetNamedValue(L"display_name", json::value(description)); - dropdown.SetNamedValue(L"editor_type", json::value(L"dropdown")); - json::JsonArray options; - for(const auto & [key, text] : keys_and_texts) { - json::JsonObject entry; - entry.SetNamedValue(L"key", json::value(key)); - entry.SetNamedValue(L"text", json::value(text)); - options.Append(std::move(entry)); - } - dropdown.SetNamedValue(L"options", std::move(options)); - dropdown.SetNamedValue(L"value", json::value(value)); - dropdown.SetNamedValue(L"order", json::value(++m_curr_priority)); - - m_json.GetNamedObject(L"properties").SetNamedValue(name, dropdown); - } - - // 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) { - 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) { - 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) { - json::JsonObject custom_action; - custom_action.SetNamedValue(L"display_name", json::value(description)); - custom_action.SetNamedValue(L"button_text", json::value(button_text)); - custom_action.SetNamedValue(L"editor_type", json::value(L"custom_action")); - custom_action.SetNamedValue(L"value", json::value(value)); - custom_action.SetNamedValue(L"order", json::value(++m_curr_priority)); - - m_json.GetNamedObject(L"properties").SetNamedValue(name, custom_action); - } - - // Serialization methods. - std::wstring Settings::serialize() { - return m_json.Stringify().c_str(); - } - - bool Settings::serialize_to_buffer(wchar_t* buffer, int *buffer_size) { - auto result = m_json.Stringify(); - const int result_len = (int)result.size() + 1; - - if (buffer == nullptr || *buffer_size < result_len) { - *buffer_size = result_len; - return false; - } else { - wcscpy_s(buffer, *buffer_size, result.c_str()); - return true; - } - } - - // Resource helper. - std::wstring Settings::get_resource(UINT resource_id) { - if (resource_id != 0) { - wchar_t* res_ptr; - const size_t resource_length = LoadStringW(m_instance, resource_id, reinterpret_cast(&res_ptr), 0); - if (resource_length != 0) { - return {*reinterpret_cast(&res_ptr), resource_length}; - } +namespace PowerToysSettings +{ + Settings::Settings(const HINSTANCE hinstance, std::wstring_view powertoy_name) + { + m_instance = hinstance; + m_json.SetNamedValue(L"version", json::value(L"1.0")); + m_json.SetNamedValue(L"name", json::value(powertoy_name)); + m_json.SetNamedValue(L"properties", json::JsonObject{}); } - return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id); - } - - PowerToyValues::PowerToyValues(std::wstring_view powertoy_name) { - _name = powertoy_name; - set_version(); - m_json.SetNamedValue(L"name", json::value(powertoy_name)); - m_json.SetNamedValue(L"properties", json::JsonObject{}); - } - - PowerToyValues PowerToyValues::from_json_string(std::wstring_view json) { - PowerToyValues result = PowerToyValues(); - result.m_json = json::JsonValue::Parse(json).GetObjectW(); - result._name = result.m_json.GetNamedString(L"name"); - return result; - } - - PowerToyValues PowerToyValues::load_from_settings_file(std::wstring_view powertoy_name) { - PowerToyValues result = PowerToyValues(); - result.m_json = PTSettingsHelper::load_module_settings(powertoy_name); - result._name = powertoy_name; - return result; - } - - 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{}); - return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type); - } - - std::optional PowerToyValues::get_bool_value(std::wstring_view property_name) { - if (!has_property(m_json, property_name, json::JsonValueType::Boolean)) { - return std::nullopt; + void Settings::set_description(UINT resource_id) + { + m_json.SetNamedValue(L"description", json::value(get_resource(resource_id))); } - return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value"); - } - std::optional PowerToyValues::get_int_value(std::wstring_view property_name) { - if (!has_property(m_json, property_name, json::JsonValueType::Number)) { - return std::nullopt; + void Settings::set_description(std::wstring_view description) + { + m_json.SetNamedValue(L"description", json::value(description)); } - return static_cast(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value")); - } - std::optional PowerToyValues::get_string_value(std::wstring_view property_name) { - if (!has_property(m_json, property_name, json::JsonValueType::String)) { - return std::nullopt; + void Settings::set_icon_key(std::wstring_view icon_key) + { + m_json.SetNamedValue(L"icon_key", json::value(icon_key)); } - return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str(); - } - std::optional PowerToyValues::get_json(std::wstring_view property_name) { - if (!has_property(m_json, property_name, json::JsonValueType::Object)) { - return std::nullopt; + void Settings::set_overview_link(std::wstring_view overview_link) + { + m_json.SetNamedValue(L"overview_link", json::value(overview_link)); } - return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedObject(L"value"); - } - std::wstring PowerToyValues::serialize() { - set_version(); - return m_json.Stringify().c_str(); - } + void Settings::set_video_link(std::wstring_view video_link) + { + m_json.SetNamedValue(L"video_link", json::value(video_link)); + } - void PowerToyValues::save_to_settings_file() { - set_version(); - PTSettingsHelper::save_module_settings(_name, m_json); - } + // add_bool_toogle overloads. + 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); + } - void PowerToyValues::set_version() { - m_json.SetNamedValue(L"version", json::value(m_version)); - } + void Settings::add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value) + { + json::JsonObject toggle; + toggle.SetNamedValue(L"display_name", json::value(description)); + toggle.SetNamedValue(L"editor_type", json::value(L"bool_toggle")); + toggle.SetNamedValue(L"value", json::value(value)); + toggle.SetNamedValue(L"order", json::value(++m_curr_priority)); + + m_json.GetNamedObject(L"properties").SetNamedValue(name, toggle); + } + + // 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) + { + 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) + { + json::JsonObject spinner; + spinner.SetNamedValue(L"display_name", json::value(description)); + spinner.SetNamedValue(L"editor_type", json::value(L"int_spinner")); + spinner.SetNamedValue(L"value", json::value(value)); + spinner.SetNamedValue(L"min", json::value(min)); + spinner.SetNamedValue(L"max", json::value(max)); + spinner.SetNamedValue(L"step", json::value(step)); + spinner.SetNamedValue(L"order", json::value(++m_curr_priority)); + + m_json.GetNamedObject(L"properties").SetNamedValue(name, spinner); + } + + // add_string overloads. + 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); + } + + void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) + { + json::JsonObject string; + string.SetNamedValue(L"display_name", json::value(description)); + string.SetNamedValue(L"editor_type", json::value(L"string_text")); + string.SetNamedValue(L"value", json::value(value)); + string.SetNamedValue(L"order", json::value(++m_curr_priority)); + + m_json.GetNamedObject(L"properties").SetNamedValue(name, string); + } + + // add_multiline_string overloads. + 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); + } + + void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) + { + json::JsonObject ml_string; + ml_string.SetNamedValue(L"display_name", json::value(description)); + ml_string.SetNamedValue(L"editor_type", json::value(L"string_text")); + ml_string.SetNamedValue(L"value", json::value(value)); + ml_string.SetNamedValue(L"order", json::value(++m_curr_priority)); + ml_string.SetNamedValue(L"multiline", json::value(true)); + + m_json.GetNamedObject(L"properties").SetNamedValue(name, ml_string); + } + + // add_color_picker overloads. + 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); + } + + void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value) + { + json::JsonObject picker; + picker.SetNamedValue(L"display_name", json::value(description)); + picker.SetNamedValue(L"editor_type", json::value(L"color_picker")); + picker.SetNamedValue(L"value", json::value(value)); + picker.SetNamedValue(L"order", json::value(++m_curr_priority)); + + m_json.GetNamedObject(L"properties").SetNamedValue(name, picker); + } + + void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& 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) + { + json::JsonObject hotkey; + hotkey.SetNamedValue(L"display_name", json::value(description)); + hotkey.SetNamedValue(L"editor_type", json::value(L"hotkey")); + hotkey.SetNamedValue(L"value", hotkey_obj.get_json()); + hotkey.SetNamedValue(L"order", json::value(++m_curr_priority)); + + 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>& keys_and_text_ids) + { + std::vector> keys_and_texts; + keys_and_texts.reserve(keys_and_text_ids.size()); + for (const auto& kv : keys_and_text_ids) + { + keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); + } + 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>& keys_and_texts) + { + json::JsonObject choice_group; + choice_group.SetNamedValue(L"display_name", json::value(description)); + choice_group.SetNamedValue(L"editor_type", json::value(L"choice_group")); + json::JsonArray options; + for (const auto& [key, text] : keys_and_texts) + { + json::JsonObject entry; + entry.SetNamedValue(L"key", json::value(key)); + entry.SetNamedValue(L"text", json::value(text)); + options.Append(std::move(entry)); + } + choice_group.SetNamedValue(L"options", std::move(options)); + choice_group.SetNamedValue(L"value", json::value(value)); + choice_group.SetNamedValue(L"order", json::value(++m_curr_priority)); + + 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>& keys_and_text_ids) + { + std::vector> keys_and_texts; + keys_and_texts.reserve(keys_and_text_ids.size()); + for (const auto& kv : keys_and_text_ids) + { + keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); + } + 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>& keys_and_texts) + { + json::JsonObject dropdown; + dropdown.SetNamedValue(L"display_name", json::value(description)); + dropdown.SetNamedValue(L"editor_type", json::value(L"dropdown")); + json::JsonArray options; + for (const auto& [key, text] : keys_and_texts) + { + json::JsonObject entry; + entry.SetNamedValue(L"key", json::value(key)); + entry.SetNamedValue(L"text", json::value(text)); + options.Append(std::move(entry)); + } + dropdown.SetNamedValue(L"options", std::move(options)); + dropdown.SetNamedValue(L"value", json::value(value)); + dropdown.SetNamedValue(L"order", json::value(++m_curr_priority)); + + m_json.GetNamedObject(L"properties").SetNamedValue(name, dropdown); + } + + // 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) + { + 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) + { + 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) + { + json::JsonObject custom_action; + custom_action.SetNamedValue(L"display_name", json::value(description)); + custom_action.SetNamedValue(L"button_text", json::value(button_text)); + custom_action.SetNamedValue(L"editor_type", json::value(L"custom_action")); + custom_action.SetNamedValue(L"value", json::value(value)); + custom_action.SetNamedValue(L"order", json::value(++m_curr_priority)); + + m_json.GetNamedObject(L"properties").SetNamedValue(name, custom_action); + } + + // Serialization methods. + std::wstring Settings::serialize() + { + return m_json.Stringify().c_str(); + } + + bool Settings::serialize_to_buffer(wchar_t* buffer, int* buffer_size) + { + auto result = m_json.Stringify(); + const int result_len = (int)result.size() + 1; + + if (buffer == nullptr || *buffer_size < result_len) + { + *buffer_size = result_len; + return false; + } + else + { + wcscpy_s(buffer, *buffer_size, result.c_str()); + return true; + } + } + + // Resource helper. + std::wstring Settings::get_resource(UINT resource_id) + { + if (resource_id != 0) + { + wchar_t* res_ptr; + const size_t resource_length = LoadStringW(m_instance, resource_id, reinterpret_cast(&res_ptr), 0); + if (resource_length != 0) + { + return { *reinterpret_cast(&res_ptr), resource_length }; + } + } + + return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id); + } + + PowerToyValues::PowerToyValues(std::wstring_view powertoy_name) + { + _name = powertoy_name; + set_version(); + m_json.SetNamedValue(L"name", json::value(powertoy_name)); + m_json.SetNamedValue(L"properties", json::JsonObject{}); + } + + PowerToyValues PowerToyValues::from_json_string(std::wstring_view json) + { + PowerToyValues result = PowerToyValues(); + result.m_json = json::JsonValue::Parse(json).GetObjectW(); + result._name = result.m_json.GetNamedString(L"name"); + return result; + } + + PowerToyValues PowerToyValues::load_from_settings_file(std::wstring_view powertoy_name) + { + PowerToyValues result = PowerToyValues(); + result.m_json = PTSettingsHelper::load_module_settings(powertoy_name); + result._name = powertoy_name; + return result; + } + + 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{}); + return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type); + } + + std::optional PowerToyValues::get_bool_value(std::wstring_view property_name) + { + if (!has_property(m_json, property_name, json::JsonValueType::Boolean)) + { + return std::nullopt; + } + return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value"); + } + + std::optional PowerToyValues::get_int_value(std::wstring_view property_name) + { + if (!has_property(m_json, property_name, json::JsonValueType::Number)) + { + return std::nullopt; + } + return static_cast(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value")); + } + + std::optional PowerToyValues::get_string_value(std::wstring_view property_name) + { + if (!has_property(m_json, property_name, json::JsonValueType::String)) + { + return std::nullopt; + } + return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str(); + } + + std::optional PowerToyValues::get_json(std::wstring_view property_name) + { + if (!has_property(m_json, property_name, json::JsonValueType::Object)) + { + return std::nullopt; + } + return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedObject(L"value"); + } + + std::wstring PowerToyValues::serialize() + { + set_version(); + return m_json.Stringify().c_str(); + } + + void PowerToyValues::save_to_settings_file() + { + set_version(); + PTSettingsHelper::save_module_settings(_name, m_json); + } + + void PowerToyValues::set_version() + { + m_json.SetNamedValue(L"version", json::value(m_version)); + } } \ No newline at end of file diff --git a/src/common/settings_objects.h b/src/common/settings_objects.h index a6b1e1779..5001daf92 100644 --- a/src/common/settings_objects.h +++ b/src/common/settings_objects.h @@ -2,184 +2,220 @@ #include "json.h" -namespace PowerToysSettings { +namespace PowerToysSettings +{ + class HotkeyObject; - class HotkeyObject; - - class Settings { - public: - Settings( - const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase' - std::wstring_view powertoy_name - ); - - // Add additional general information to the PowerToy settings. - void set_description(UINT resource_id); - void set_description(std::wstring_view description); - - void set_icon_key(std::wstring_view icon_key); - void set_overview_link(std::wstring_view overview_link); - void set_video_link(std::wstring_view video_link); - - // Add properties to the PowerToy settings. - void add_bool_toogle(std::wstring_view name, UINT description_resource_id, bool value); - void add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value); - - void add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step); - void add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step); - - void add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value); - void add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value); - - void add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value); - void add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value); - - void add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value); - void add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value); - - void add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey); - void add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey); - - void add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector>& keys_and_text_ids); - void add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector>& keys_and_texts); - - void add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector>& keys_and_text_ids); - void add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector>& keys_and_texts); - - void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id); - 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); - - - // Serialize the internal json to a string. - std::wstring serialize(); - // Serialize the internal json to the input buffer. - bool serialize_to_buffer(wchar_t* buffer, int* buffer_size); - - private: - json::JsonObject m_json; - int m_curr_priority = 0; // For keeping order when adding elements. - HINSTANCE m_instance; - - std::wstring get_resource(UINT resource_id); - }; - - class PowerToyValues { - public: - PowerToyValues(std::wstring_view powertoy_name); - static PowerToyValues from_json_string(std::wstring_view json); - static PowerToyValues load_from_settings_file(std::wstring_view powertoy_name); - - template - inline void add_property(std::wstring_view name, T value) + class Settings { - json::JsonObject prop_value; - prop_value.SetNamedValue(L"value", json::value(value)); - m_json.GetNamedObject(L"properties").SetNamedValue(name, prop_value); - } + public: + Settings( + const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase' + std::wstring_view powertoy_name); - std::optional get_bool_value(std::wstring_view property_name); - std::optional get_int_value(std::wstring_view property_name); - std::optional get_string_value(std::wstring_view property_name); - std::optional get_json(std::wstring_view property_name); + // Add additional general information to the PowerToy settings. + void set_description(UINT resource_id); + void set_description(std::wstring_view description); - std::wstring serialize(); - void save_to_settings_file(); + void set_icon_key(std::wstring_view icon_key); + void set_overview_link(std::wstring_view overview_link); + void set_video_link(std::wstring_view video_link); - private: - const std::wstring m_version = L"1.0"; - void set_version(); - json::JsonObject m_json; - std::wstring _name; - PowerToyValues() {} - }; + // Add properties to the PowerToy settings. + void add_bool_toogle(std::wstring_view name, UINT description_resource_id, bool value); + void add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value); - class CustomActionObject { - public: - static CustomActionObject from_json_string(std::wstring_view json) { - return CustomActionObject(json::JsonValue::Parse(json).GetObjectW()); - } + void add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step); + void add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step); - std::wstring get_name() { return m_json.GetNamedString(L"action_name").c_str(); } - std::wstring get_value() { return m_json.GetNamedString(L"value").c_str(); } + void add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value); + void add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value); - protected: - CustomActionObject(json::JsonObject action_json) : m_json(std::move(action_json)) {}; - json::JsonObject m_json; - }; - - class HotkeyObject { - public: - static HotkeyObject from_json(json::JsonObject json) { - return HotkeyObject(std::move(json)); - } - static HotkeyObject from_json_string(std::wstring_view json) { - 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) { - json::JsonObject json; - json.SetNamedValue(L"win", json::value(win_pressed)); - json.SetNamedValue(L"ctrl", json::value(ctrl_pressed)); - json.SetNamedValue(L"alt", json::value(alt_pressed)); - json.SetNamedValue(L"shift", json::value(shift_pressed)); - json.SetNamedValue(L"code", json::value(vk_code)); - json.SetNamedValue(L"key", json::value(key_from_code(vk_code))); - return std::move(json); - } - const json::JsonObject& get_json() const { return m_json; } + void add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value); + void add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value); - std::wstring get_key() const { return m_json.GetNamedString(L"key").c_str(); } - UINT get_code() const { return static_cast(m_json.GetNamedNumber(L"code")); } - bool win_pressed() const { return m_json.GetNamedBoolean(L"win"); } - bool ctrl_pressed() const { return m_json.GetNamedBoolean(L"ctrl"); } - bool alt_pressed() const { return m_json.GetNamedBoolean(L"alt"); } - bool shift_pressed() const { return m_json.GetNamedBoolean(L"shift"); } - UINT get_modifiers_repeat() const { - return (win_pressed() ? MOD_WIN : 0) | - (ctrl_pressed() ? MOD_CONTROL : 0) | - (alt_pressed() ? MOD_ALT : 0) | - (shift_pressed() ? MOD_SHIFT : 0); - } - UINT get_modifiers() const { - return get_modifiers_repeat() | MOD_NOREPEAT; - } - protected: - static std::wstring key_from_code(UINT key_code) { - auto layout = GetKeyboardLayout(0); - 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 - // does not return correct values. - static std::vector extended_keys = { - VK_APPS, VK_CANCEL, 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)) { - scan_code |= 0x100; - } - std::array key_states{}; // Zero-initialize - std::array output; - auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, 0, layout); - if (output_bytes <= 0) { - // If ToUnicodeEx fails (e.g. for F1-F12 keys) use GetKeyNameTextW - output_bytes = GetKeyNameTextW(scan_code << 16, output.data(), static_cast(output.size())); - } - if (output_bytes > 0) { - output[output_bytes] = 0; - if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z') { - // Make Latin letters keys capital, as it looks better - output[0] = toupper(output[0]); - } - return output.data(); - } - return L"(Key " + std::to_wstring(key_code) + L")"; - } - HotkeyObject(json::JsonObject hotkey_json) : 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()))); - } + void add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value); + void add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value); + + void add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey); + void add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey); + + void add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector>& keys_and_text_ids); + void add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector>& keys_and_texts); + + void add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector>& keys_and_text_ids); + void add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector>& keys_and_texts); + + void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id); + 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); + + // Serialize the internal json to a string. + std::wstring serialize(); + // Serialize the internal json to the input buffer. + bool serialize_to_buffer(wchar_t* buffer, int* buffer_size); + + private: + json::JsonObject m_json; + int m_curr_priority = 0; // For keeping order when adding elements. + HINSTANCE m_instance; + + std::wstring get_resource(UINT resource_id); + }; + + class PowerToyValues + { + public: + PowerToyValues(std::wstring_view powertoy_name); + static PowerToyValues from_json_string(std::wstring_view json); + static PowerToyValues load_from_settings_file(std::wstring_view powertoy_name); + + template + inline void add_property(std::wstring_view name, T value) + { + json::JsonObject prop_value; + prop_value.SetNamedValue(L"value", json::value(value)); + m_json.GetNamedObject(L"properties").SetNamedValue(name, prop_value); + } + + std::optional get_bool_value(std::wstring_view property_name); + std::optional get_int_value(std::wstring_view property_name); + std::optional get_string_value(std::wstring_view property_name); + std::optional get_json(std::wstring_view property_name); + + std::wstring serialize(); + void save_to_settings_file(); + + private: + const std::wstring m_version = L"1.0"; + void set_version(); + json::JsonObject m_json; + std::wstring _name; + PowerToyValues() {} + }; + + class CustomActionObject + { + public: + static CustomActionObject from_json_string(std::wstring_view json) + { + return CustomActionObject(json::JsonValue::Parse(json).GetObjectW()); + } + + std::wstring get_name() { return m_json.GetNamedString(L"action_name").c_str(); } + std::wstring get_value() { return m_json.GetNamedString(L"value").c_str(); } + + protected: + CustomActionObject(json::JsonObject action_json) : + m_json(std::move(action_json)){}; + json::JsonObject m_json; + }; + + class HotkeyObject + { + public: + static HotkeyObject from_json(json::JsonObject json) + { + return HotkeyObject(std::move(json)); + } + static HotkeyObject from_json_string(std::wstring_view json) + { + 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) + { + json::JsonObject json; + json.SetNamedValue(L"win", json::value(win_pressed)); + json.SetNamedValue(L"ctrl", json::value(ctrl_pressed)); + json.SetNamedValue(L"alt", json::value(alt_pressed)); + json.SetNamedValue(L"shift", json::value(shift_pressed)); + json.SetNamedValue(L"code", json::value(vk_code)); + json.SetNamedValue(L"key", json::value(key_from_code(vk_code))); + return std::move(json); + } + const json::JsonObject& get_json() const { return m_json; } + + std::wstring get_key() const { return m_json.GetNamedString(L"key").c_str(); } + UINT get_code() const { return static_cast(m_json.GetNamedNumber(L"code")); } + bool win_pressed() const { return m_json.GetNamedBoolean(L"win"); } + bool ctrl_pressed() const { return m_json.GetNamedBoolean(L"ctrl"); } + bool alt_pressed() const { return m_json.GetNamedBoolean(L"alt"); } + bool shift_pressed() const { return m_json.GetNamedBoolean(L"shift"); } + UINT get_modifiers_repeat() const + { + return (win_pressed() ? MOD_WIN : 0) | + (ctrl_pressed() ? MOD_CONTROL : 0) | + (alt_pressed() ? MOD_ALT : 0) | + (shift_pressed() ? MOD_SHIFT : 0); + } + UINT get_modifiers() const + { + return get_modifiers_repeat() | MOD_NOREPEAT; + } + + protected: + static std::wstring key_from_code(UINT key_code) + { + auto layout = GetKeyboardLayout(0); + 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 + // does not return correct values. + static std::vector extended_keys = { + VK_APPS, + VK_CANCEL, + 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)) + { + scan_code |= 0x100; + } + std::array key_states{}; // Zero-initialize + std::array output; + auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, 0, layout); + if (output_bytes <= 0) + { + // If ToUnicodeEx fails (e.g. for F1-F12 keys) use GetKeyNameTextW + output_bytes = GetKeyNameTextW(scan_code << 16, output.data(), static_cast(output.size())); + } + if (output_bytes > 0) + { + output[output_bytes] = 0; + if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z') + { + // Make Latin letters keys capital, as it looks better + output[0] = toupper(output[0]); + } + return output.data(); + } + return L"(Key " + std::to_wstring(key_code) + L")"; + } + HotkeyObject(json::JsonObject hotkey_json) : + 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()))); + } + }; + json::JsonObject m_json; }; - json::JsonObject m_json; - }; } diff --git a/src/common/start_visible.cpp b/src/common/start_visible.cpp index 5c9c8d13b..421d7e420 100644 --- a/src/common/start_visible.cpp +++ b/src/common/start_visible.cpp @@ -1,16 +1,18 @@ #include "pch.h" #include "start_visible.h" -bool is_start_visible() { - static winrt::com_ptr app_visibility; - if (!app_visibility) { - winrt::check_hresult(CoCreateInstance(CLSID_AppVisibility, - nullptr, - CLSCTX_INPROC_SERVER, - __uuidof(app_visibility), - app_visibility.put_void())); - } - BOOL visible; - auto result = app_visibility->IsLauncherVisible(&visible); - return SUCCEEDED(result) && visible; +bool is_start_visible() +{ + static winrt::com_ptr app_visibility; + if (!app_visibility) + { + winrt::check_hresult(CoCreateInstance(CLSID_AppVisibility, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(app_visibility), + app_visibility.put_void())); + } + BOOL visible; + auto result = app_visibility->IsLauncherVisible(&visible); + return SUCCEEDED(result) && visible; } diff --git a/src/common/start_visible.h b/src/common/start_visible.h index 05e8b5b72..a1431086a 100644 --- a/src/common/start_visible.h +++ b/src/common/start_visible.h @@ -1,4 +1,3 @@ #pragma once bool is_start_visible(); - diff --git a/src/common/tasklist_positions.cpp b/src/common/tasklist_positions.cpp index 4332541ef..6a6102b83 100644 --- a/src/common/tasklist_positions.cpp +++ b/src/common/tasklist_positions.cpp @@ -1,93 +1,116 @@ #include "pch.h" #include "tasklist_positions.h" -void Tasklist::update() { - // Get HWND of the tasklist - auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr); - if (!tasklist_hwnd) return; - tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr); - if (!tasklist_hwnd) return; - tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr); - if (!tasklist_hwnd) return; - tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr); - if (!tasklist_hwnd) return; - if (!automation) { - winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IUIAutomation, - automation.put_void())); - winrt::check_hresult(automation->CreateTrueCondition(true_condition.put())); - } - element = nullptr; - winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); +void Tasklist::update() +{ + // Get HWND of the tasklist + auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr); + if (!tasklist_hwnd) + return; + tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr); + if (!tasklist_hwnd) + return; + tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr); + if (!tasklist_hwnd) + return; + tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr); + if (!tasklist_hwnd) + return; + if (!automation) + { + winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IUIAutomation, + automation.put_void())); + winrt::check_hresult(automation->CreateTrueCondition(true_condition.put())); + } + element = nullptr; + winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); } -bool Tasklist::update_buttons(std::vector& buttons) { - if (!automation || !element) { - return false; - } - winrt::com_ptr elements; - if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0) - return false; - if (!elements) - return false; - int count; - if (elements->get_Length(&count) < 0) - return false; - winrt::com_ptr child; - std::vector found_butttons; - found_butttons.reserve(count); - for (int i = 0; i < count; ++i) { - child = nullptr; - if (elements->GetElement(i, child.put()) < 0) - return false; - TasklistButton button; - if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) { - if (var_rect.vt == (VT_R8 | VT_ARRAY)) { - LONG pos; - double value; - pos = 0; SafeArrayGetElement(var_rect.parray, &pos, &value); - button.x = (long)value; - pos = 1; SafeArrayGetElement(var_rect.parray, &pos, &value); - button.y = (long)value; - pos = 2; SafeArrayGetElement(var_rect.parray, &pos, &value); - button.width = (long)value; - pos = 3; SafeArrayGetElement(var_rect.parray, &pos, &value); - button.height = (long)value; - } - VariantClear(&var_rect); - } else { - return false; +bool Tasklist::update_buttons(std::vector& buttons) +{ + if (!automation || !element) + { + return false; } - if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) { - button.name = automation_id; - SysFreeString(automation_id); + winrt::com_ptr elements; + if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0) + return false; + if (!elements) + return false; + int count; + if (elements->get_Length(&count) < 0) + return false; + winrt::com_ptr child; + std::vector found_butttons; + found_butttons.reserve(count); + for (int i = 0; i < count; ++i) + { + child = nullptr; + if (elements->GetElement(i, child.put()) < 0) + return false; + TasklistButton button; + if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) + { + if (var_rect.vt == (VT_R8 | VT_ARRAY)) + { + LONG pos; + double value; + pos = 0; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.x = (long)value; + pos = 1; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.y = (long)value; + pos = 2; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.width = (long)value; + pos = 3; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.height = (long)value; + } + VariantClear(&var_rect); + } + else + { + return false; + } + if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) + { + button.name = automation_id; + SysFreeString(automation_id); + } + found_butttons.push_back(button); } - found_butttons.push_back(button); - } - // assign keynums - buttons.clear(); - for (auto& button : found_butttons) { - if (buttons.empty()) { - button.keynum = 1; - buttons.push_back(std::move(button)); - } else { - if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row - break; - if (button.name == buttons.back().name) - continue; // skip buttons from the same app - button.keynum = buttons.back().keynum + 1; - buttons.push_back(std::move(button)); - if (buttons.back().keynum == 10) - break; // no more than 10 buttons + // assign keynums + buttons.clear(); + for (auto& button : found_butttons) + { + if (buttons.empty()) + { + button.keynum = 1; + buttons.push_back(std::move(button)); + } + else + { + if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row + break; + if (button.name == buttons.back().name) + continue; // skip buttons from the same app + button.keynum = buttons.back().keynum + 1; + buttons.push_back(std::move(button)); + if (buttons.back().keynum == 10) + break; // no more than 10 buttons + } } - } - return true; + return true; } -std::vector Tasklist::get_buttons() { - std::vector buttons; - update_buttons(buttons); - return buttons; +std::vector Tasklist::get_buttons() +{ + std::vector buttons; + update_buttons(buttons); + return buttons; } \ No newline at end of file diff --git a/src/common/tasklist_positions.h b/src/common/tasklist_positions.h index 05fc92d88..a1160fd16 100644 --- a/src/common/tasklist_positions.h +++ b/src/common/tasklist_positions.h @@ -5,18 +5,21 @@ #include #include -struct TasklistButton { - std::wstring name; - long x, y, width, height, keynum; +struct TasklistButton +{ + std::wstring name; + long x, y, width, height, keynum; }; -class Tasklist { +class Tasklist +{ public: - void update(); - std::vector get_buttons(); - bool update_buttons(std::vector& buttons); + void update(); + std::vector get_buttons(); + bool update_buttons(std::vector& buttons); + private: - winrt::com_ptr automation; - winrt::com_ptr element; - winrt::com_ptr true_condition; + winrt::com_ptr automation; + winrt::com_ptr element; + winrt::com_ptr true_condition; }; diff --git a/src/common/two_way_pipe_message_ipc.h b/src/common/two_way_pipe_message_ipc.h index 097060531..762599de1 100644 --- a/src/common/two_way_pipe_message_ipc.h +++ b/src/common/two_way_pipe_message_ipc.h @@ -6,424 +6,471 @@ #include #include -class TwoWayPipeMessageIPC { +class TwoWayPipeMessageIPC +{ public: - typedef void(*callback_function)(const std::wstring&); - void send(std::wstring msg) { - output_queue.queue_message(msg); - } - TwoWayPipeMessageIPC(std::wstring _input_pipe_name, std::wstring _output_pipe_name, callback_function p_func) { - input_pipe_name = _input_pipe_name; - output_pipe_name = _output_pipe_name; - dispatch_inc_message_function = p_func; - } - void start(HANDLE _restricted_pipe_token) { - output_queue_thread = std::thread(&TwoWayPipeMessageIPC::consume_output_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); - } - - void end() { - closed = true; - input_queue.interrupt(); - input_queue_thread.join(); - output_queue.interrupt(); - output_queue_thread.join(); - pipe_connect_handle_mutex.lock(); - if (current_connect_pipe_handle != NULL) { - //Cancels the Pipe currently waiting for a connection. - CancelIoEx(current_connect_pipe_handle,NULL); + typedef void (*callback_function)(const std::wstring&); + void send(std::wstring msg) + { + output_queue.queue_message(msg); + } + TwoWayPipeMessageIPC(std::wstring _input_pipe_name, std::wstring _output_pipe_name, callback_function p_func) + { + input_pipe_name = _input_pipe_name; + output_pipe_name = _output_pipe_name; + dispatch_inc_message_function = p_func; + } + void start(HANDLE _restricted_pipe_token) + { + output_queue_thread = std::thread(&TwoWayPipeMessageIPC::consume_output_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); + } + + void end() + { + closed = true; + input_queue.interrupt(); + input_queue_thread.join(); + output_queue.interrupt(); + output_queue_thread.join(); + pipe_connect_handle_mutex.lock(); + if (current_connect_pipe_handle != NULL) + { + //Cancels the Pipe currently waiting for a connection. + CancelIoEx(current_connect_pipe_handle, NULL); + } + pipe_connect_handle_mutex.unlock(); + input_pipe_thread.join(); } - pipe_connect_handle_mutex.unlock(); - input_pipe_thread.join(); - } private: - AsyncMessageQueue input_queue; - AsyncMessageQueue output_queue; - std::wstring output_pipe_name; - std::wstring input_pipe_name; - std::thread input_queue_thread; - std::thread output_queue_thread; - std::thread input_pipe_thread; - std::mutex pipe_connect_handle_mutex; // For manipulating the current_connect_pipe + AsyncMessageQueue input_queue; + AsyncMessageQueue output_queue; + std::wstring output_pipe_name; + std::wstring input_pipe_name; + std::thread input_queue_thread; + std::thread output_queue_thread; + std::thread input_pipe_thread; + std::mutex pipe_connect_handle_mutex; // For manipulating the current_connect_pipe - HANDLE current_connect_pipe_handle = NULL; - bool closed = false; - TwoWayPipeMessageIPC::callback_function dispatch_inc_message_function; - const DWORD BUFSIZE = 1024; + HANDLE current_connect_pipe_handle = NULL; + bool closed = false; + TwoWayPipeMessageIPC::callback_function dispatch_inc_message_function; + const DWORD BUFSIZE = 1024; - void send_pipe_message(std::wstring message) { - // Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-client - HANDLE output_pipe_handle; - const wchar_t* message_send = message.c_str(); - BOOL fSuccess = FALSE; - DWORD cbToWrite, cbWritten, dwMode; - const wchar_t* lpszPipename = output_pipe_name.c_str(); + void send_pipe_message(std::wstring message) + { + // Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-client + HANDLE output_pipe_handle; + const wchar_t* message_send = message.c_str(); + BOOL fSuccess = FALSE; + DWORD cbToWrite, cbWritten, dwMode; + const wchar_t* lpszPipename = output_pipe_name.c_str(); - // Try to open a named pipe; wait for it, if necessary. + // Try to open a named pipe; wait for it, if necessary. - while (1) { - output_pipe_handle = CreateFile( - lpszPipename, // pipe name - GENERIC_READ | // read and write access - GENERIC_WRITE, - 0, // no sharing - NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - 0, // default attributes - NULL); // no template file + while (1) + { + output_pipe_handle = CreateFile( + lpszPipename, // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + 0, // default attributes + NULL); // no template file - // Break if the pipe handle is valid. + // Break if the pipe handle is valid. - if (output_pipe_handle != INVALID_HANDLE_VALUE) - break; + if (output_pipe_handle != INVALID_HANDLE_VALUE) + break; - // Exit if an error other than ERROR_PIPE_BUSY occurs. - DWORD curr_error = 0; - if ((curr_error = GetLastError()) != ERROR_PIPE_BUSY) { + // Exit if an error other than ERROR_PIPE_BUSY occurs. + DWORD curr_error = 0; + if ((curr_error = GetLastError()) != ERROR_PIPE_BUSY) + { + return; + } + // All pipe instances are busy, so wait for 20 seconds. + + if (!WaitNamedPipe(lpszPipename, 20000)) + { + return; + } + } + dwMode = PIPE_READMODE_MESSAGE; + fSuccess = SetNamedPipeHandleState( + output_pipe_handle, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time + if (!fSuccess) + { + return; + } + + // Send a message to the pipe server. + + cbToWrite = (lstrlen(message_send)) * sizeof(WCHAR); // no need to send final '\0'. Pipe is in message mode. + + fSuccess = WriteFile( + output_pipe_handle, // pipe handle + message_send, // message + cbToWrite, // message length + &cbWritten, // bytes written + NULL); // not overlapped + if (!fSuccess) + { + return; + } + CloseHandle(output_pipe_handle); return; - } - - // All pipe instances are busy, so wait for 20 seconds. - - if (!WaitNamedPipe(lpszPipename, 20000)) { - return; - } - } - dwMode = PIPE_READMODE_MESSAGE; - fSuccess = SetNamedPipeHandleState( - output_pipe_handle, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time - if (!fSuccess) { - return; } - // Send a message to the pipe server. - - cbToWrite = (lstrlen(message_send)) * sizeof(WCHAR); // no need to send final '\0'. Pipe is in message mode. - - fSuccess = WriteFile( - output_pipe_handle, // pipe handle - message_send, // message - cbToWrite, // message length - &cbWritten, // bytes written - NULL); // not overlapped - if (!fSuccess) { - return; - } - CloseHandle(output_pipe_handle); - return; - } - - void consume_output_queue_thread() { - while (!closed) { - std::wstring message = output_queue.pop_message(); - if (message.length() == 0) { - break; - } - send_pipe_message(message); - } - } - - BOOL GetLogonSID(HANDLE hToken, PSID *ppsid) { - // From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85) - BOOL bSuccess = FALSE; - DWORD dwIndex; - DWORD dwLength = 0; - PTOKEN_GROUPS ptg = NULL; - - // Verify the parameter passed in is not NULL. - if (NULL == ppsid) - goto Cleanup; - - // Get required buffer size and allocate the TOKEN_GROUPS buffer. - - if (!GetTokenInformation( - hToken, // handle to the access token - TokenGroups, // get information about the token's groups - (LPVOID)ptg, // pointer to TOKEN_GROUPS buffer - 0, // size of buffer - &dwLength // receives required buffer size - )) { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - goto Cleanup; - - ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, dwLength); - - if (ptg == NULL) - goto Cleanup; - } - - // Get the token group information from the access token. - - if (!GetTokenInformation( - hToken, // handle to the access token - TokenGroups, // get information about the token's groups - (LPVOID)ptg, // pointer to TOKEN_GROUPS buffer - dwLength, // size of buffer - &dwLength // receives required buffer size - )) { - goto Cleanup; - } - - // Loop through the groups to find the logon SID. - - for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) - if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) - == SE_GROUP_LOGON_ID) { - // Found the logon SID; make a copy of it. - - dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid); - *ppsid = (PSID)HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, dwLength); - if (*ppsid == NULL) - goto Cleanup; - if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid)) { - HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); - goto Cleanup; + void consume_output_queue_thread() + { + while (!closed) + { + std::wstring message = output_queue.pop_message(); + if (message.length() == 0) + { + break; + } + send_pipe_message(message); } - break; - } - - bSuccess = TRUE; - - Cleanup: - - // Free the buffer for the token groups. - - if (ptg != NULL) - HeapFree(GetProcessHeap(), 0, (LPVOID)ptg); - - return bSuccess; - } - - VOID FreeLogonSID(PSID *ppsid) { - // From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85) - HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); - } - - - int change_pipe_security_allow_restricted_token(HANDLE handle, HANDLE token) { - PACL old_dacl, new_dacl; - PSECURITY_DESCRIPTOR sd; - EXPLICIT_ACCESS ea; - PSID user_restricted; - int error; - - if (!GetLogonSID(token, &user_restricted)) { - error = 5; // No access error. - goto Ldone; } - if (GetSecurityInfo(handle, - SE_KERNEL_OBJECT, - DACL_SECURITY_INFORMATION, - NULL, - NULL, - &old_dacl, - NULL, - &sd)) { - error = GetLastError(); - goto Lclean_sid; - } + BOOL GetLogonSID(HANDLE hToken, PSID* ppsid) + { + // From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85) + BOOL bSuccess = FALSE; + DWORD dwIndex; + DWORD dwLength = 0; + PTOKEN_GROUPS ptg = NULL; - memset(&ea, 0, sizeof(EXPLICIT_ACCESS)); - ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; - ea.grfAccessPermissions |= GENERIC_WRITE | FILE_READ_ATTRIBUTES; - ea.grfAccessPermissions |= SYNCHRONIZE; - ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance = NO_INHERITANCE; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea.Trustee.TrusteeType = TRUSTEE_IS_USER; - ea.Trustee.ptstrName = (LPTSTR)user_restricted; + // Verify the parameter passed in is not NULL. + if (NULL == ppsid) + goto Cleanup; - if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) { - error = GetLastError(); - goto Lclean_sd; - } + // Get required buffer size and allocate the TOKEN_GROUPS buffer. - if (SetSecurityInfo(handle, - SE_KERNEL_OBJECT, - DACL_SECURITY_INFORMATION, - NULL, - NULL, - new_dacl, - NULL)) { - error = GetLastError(); - goto Lclean_dacl; - } + if (!GetTokenInformation( + hToken, // handle to the access token + TokenGroups, // get information about the token's groups + (LPVOID)ptg, // pointer to TOKEN_GROUPS buffer + 0, // size of buffer + &dwLength // receives required buffer size + )) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto Cleanup; - error = 0; + ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwLength); - Lclean_dacl: - LocalFree((HLOCAL)new_dacl); - Lclean_sd: - LocalFree((HLOCAL)sd); - Lclean_sid: - FreeLogonSID(&user_restricted); - Ldone: - return error; - } - - HANDLE create_medium_integrity_token() { - HANDLE restricted_token_handle; - SAFER_LEVEL_HANDLE level_handle = NULL; - DWORD sid_size = 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)) { - return NULL; - } - if (!SaferComputeTokenFromLevel(level_handle, NULL, &restricted_token_handle, 0, NULL)) { - SaferCloseLevel(level_handle); - return NULL; - } - SaferCloseLevel(level_handle); - - if (!CreateWellKnownSid(WinMediumLabelSid, nullptr, medium_sid, &sid_size)) { - CloseHandle(restricted_token_handle); - return NULL; - } - - TOKEN_MANDATORY_LABEL integrity_level = { 0 }; - integrity_level.Label.Attributes = SE_GROUP_INTEGRITY; - integrity_level.Label.Sid = reinterpret_cast(medium_sid); - - if (!SetTokenInformation(restricted_token_handle, TokenIntegrityLevel, &integrity_level, sizeof(integrity_level))) { - CloseHandle(restricted_token_handle); - return NULL; - } - - return restricted_token_handle; - } - - void handle_pipe_connection(HANDLE input_pipe_handle) { - //Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server - HANDLE hHeap = GetProcessHeap(); - uint8_t* pchRequest = (uint8_t*)HeapAlloc(hHeap, 0, BUFSIZE * sizeof(uint8_t)); - - DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0; - BOOL fSuccess = FALSE; - - // Do some extra error checking since the app will keep running even if this thread fails. - std::list> message_parts; - - if (input_pipe_handle == NULL) { - if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest); - return; - } - - if (pchRequest == NULL) { - return; - } - - // Loop until done reading - do { - // Read client requests from the pipe. This simplistic code only allows messages - // up to BUFSIZE characters in length. - ZeroMemory(pchRequest, BUFSIZE * sizeof(uint8_t)); - fSuccess = ReadFile( - input_pipe_handle, // handle to pipe - pchRequest, // buffer to receive data - BUFSIZE * sizeof(uint8_t), // size of buffer - &cbBytesRead, // number of bytes read - NULL); // not overlapped I/O - - if (!fSuccess && GetLastError() != ERROR_MORE_DATA) { - break; - } - std::vector part_vector; - part_vector.reserve(cbBytesRead); - std::copy(pchRequest, pchRequest + cbBytesRead, std::back_inserter(part_vector)); - message_parts.push_back(part_vector); - } while (!fSuccess); - - if (fSuccess) { - // Reconstruct the total_message. - std::vector reconstructed_message; - size_t total_size = 0; - for (auto& part_vector : message_parts) { - total_size += part_vector.size(); - } - reconstructed_message.reserve(total_size); - for (auto& part_vector : message_parts) { - std::move(part_vector.begin(), part_vector.end(), std::back_inserter(reconstructed_message)); - } - std::wstring unicode_msg; - unicode_msg.assign(reinterpret_cast(reconstructed_message.data()), reconstructed_message.size() / sizeof(std::wstring::value_type)); - input_queue.queue_message(unicode_msg); - } - - // Flush the pipe to allow the client to read the pipe's contents - // before disconnecting. Then disconnect the pipe, and close the - // handle to this pipe instance. - - FlushFileBuffers(input_pipe_handle); - DisconnectNamedPipe(input_pipe_handle); - CloseHandle(input_pipe_handle); - - HeapFree(hHeap, 0, pchRequest); - - printf("InstanceThread exitting.\n"); - } - - void start_named_pipe_server(HANDLE token) { - // Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server - const wchar_t* pipe_name = input_pipe_name.c_str(); - BOOL connected = FALSE; - HANDLE connect_pipe_handle = INVALID_HANDLE_VALUE; - while(!closed) { - { - std::unique_lock lock(pipe_connect_handle_mutex); - connect_pipe_handle = CreateNamedPipe( - pipe_name, - PIPE_ACCESS_DUPLEX | - WRITE_DAC, - PIPE_TYPE_MESSAGE | - PIPE_READMODE_MESSAGE | - PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - BUFSIZE, - BUFSIZE, - 0, - NULL - ); - - if (connect_pipe_handle == INVALID_HANDLE_VALUE) { - return; + if (ptg == NULL) + goto Cleanup; } - if (token != NULL) { - int err = change_pipe_security_allow_restricted_token(connect_pipe_handle, token); + // Get the token group information from the access token. + + if (!GetTokenInformation( + hToken, // handle to the access token + TokenGroups, // get information about the token's groups + (LPVOID)ptg, // pointer to TOKEN_GROUPS buffer + dwLength, // size of buffer + &dwLength // receives required buffer size + )) + { + goto Cleanup; } - current_connect_pipe_handle = connect_pipe_handle; - } - connected = ConnectNamedPipe(connect_pipe_handle, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); - { - std::unique_lock lock(pipe_connect_handle_mutex); - current_connect_pipe_handle = NULL; - } - if (connected) { - std::thread(&TwoWayPipeMessageIPC::handle_pipe_connection, this, connect_pipe_handle).detach(); - } else { - // Client could not connect. - CloseHandle(connect_pipe_handle); - } - } - } - void consume_input_queue_thread() { - while (!closed) { - std::wstring message = input_queue.pop_message(); - if (message.length() == 0) { - break; - } - dispatch_inc_message_function(message); - } - } + // Loop through the groups to find the logon SID. + for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) + if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) + { + // Found the logon SID; make a copy of it. + + dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid); + *ppsid = (PSID)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwLength); + if (*ppsid == NULL) + goto Cleanup; + if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid)) + { + HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); + goto Cleanup; + } + break; + } + + bSuccess = TRUE; + + Cleanup: + + // Free the buffer for the token groups. + + if (ptg != NULL) + HeapFree(GetProcessHeap(), 0, (LPVOID)ptg); + + return bSuccess; + } + + VOID FreeLogonSID(PSID* ppsid) + { + // From https://docs.microsoft.com/en-us/previous-versions/aa446670(v=vs.85) + HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); + } + + int change_pipe_security_allow_restricted_token(HANDLE handle, HANDLE token) + { + PACL old_dacl, new_dacl; + PSECURITY_DESCRIPTOR sd; + EXPLICIT_ACCESS ea; + PSID user_restricted; + int error; + + if (!GetLogonSID(token, &user_restricted)) + { + error = 5; // No access error. + goto Ldone; + } + + if (GetSecurityInfo(handle, + SE_KERNEL_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + &old_dacl, + NULL, + &sd)) + { + error = GetLastError(); + goto Lclean_sid; + } + + memset(&ea, 0, sizeof(EXPLICIT_ACCESS)); + ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; + ea.grfAccessPermissions |= GENERIC_WRITE | FILE_READ_ATTRIBUTES; + ea.grfAccessPermissions |= SYNCHRONIZE; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_USER; + ea.Trustee.ptstrName = (LPTSTR)user_restricted; + + if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) + { + error = GetLastError(); + goto Lclean_sd; + } + + if (SetSecurityInfo(handle, + SE_KERNEL_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + new_dacl, + NULL)) + { + error = GetLastError(); + goto Lclean_dacl; + } + + error = 0; + + Lclean_dacl: + LocalFree((HLOCAL)new_dacl); + Lclean_sd: + LocalFree((HLOCAL)sd); + Lclean_sid: + FreeLogonSID(&user_restricted); + Ldone: + return error; + } + + HANDLE create_medium_integrity_token() + { + HANDLE restricted_token_handle; + SAFER_LEVEL_HANDLE level_handle = NULL; + DWORD sid_size = 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)) + { + return NULL; + } + if (!SaferComputeTokenFromLevel(level_handle, NULL, &restricted_token_handle, 0, NULL)) + { + SaferCloseLevel(level_handle); + return NULL; + } + SaferCloseLevel(level_handle); + + if (!CreateWellKnownSid(WinMediumLabelSid, nullptr, medium_sid, &sid_size)) + { + CloseHandle(restricted_token_handle); + return NULL; + } + + TOKEN_MANDATORY_LABEL integrity_level = { 0 }; + integrity_level.Label.Attributes = SE_GROUP_INTEGRITY; + integrity_level.Label.Sid = reinterpret_cast(medium_sid); + + if (!SetTokenInformation(restricted_token_handle, TokenIntegrityLevel, &integrity_level, sizeof(integrity_level))) + { + CloseHandle(restricted_token_handle); + return NULL; + } + + return restricted_token_handle; + } + + void handle_pipe_connection(HANDLE input_pipe_handle) + { + //Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server + HANDLE hHeap = GetProcessHeap(); + uint8_t* pchRequest = (uint8_t*)HeapAlloc(hHeap, 0, BUFSIZE * sizeof(uint8_t)); + + DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0; + BOOL fSuccess = FALSE; + + // Do some extra error checking since the app will keep running even if this thread fails. + std::list> message_parts; + + if (input_pipe_handle == NULL) + { + if (pchRequest != NULL) + HeapFree(hHeap, 0, pchRequest); + return; + } + + if (pchRequest == NULL) + { + return; + } + + // Loop until done reading + do + { + // Read client requests from the pipe. This simplistic code only allows messages + // up to BUFSIZE characters in length. + ZeroMemory(pchRequest, BUFSIZE * sizeof(uint8_t)); + fSuccess = ReadFile( + input_pipe_handle, // handle to pipe + pchRequest, // buffer to receive data + BUFSIZE * sizeof(uint8_t), // size of buffer + &cbBytesRead, // number of bytes read + NULL); // not overlapped I/O + + if (!fSuccess && GetLastError() != ERROR_MORE_DATA) + { + break; + } + std::vector part_vector; + part_vector.reserve(cbBytesRead); + std::copy(pchRequest, pchRequest + cbBytesRead, std::back_inserter(part_vector)); + message_parts.push_back(part_vector); + } while (!fSuccess); + + if (fSuccess) + { + // Reconstruct the total_message. + std::vector reconstructed_message; + size_t total_size = 0; + for (auto& part_vector : message_parts) + { + total_size += part_vector.size(); + } + reconstructed_message.reserve(total_size); + for (auto& part_vector : message_parts) + { + std::move(part_vector.begin(), part_vector.end(), std::back_inserter(reconstructed_message)); + } + std::wstring unicode_msg; + unicode_msg.assign(reinterpret_cast(reconstructed_message.data()), reconstructed_message.size() / sizeof(std::wstring::value_type)); + input_queue.queue_message(unicode_msg); + } + + // Flush the pipe to allow the client to read the pipe's contents + // before disconnecting. Then disconnect the pipe, and close the + // handle to this pipe instance. + + FlushFileBuffers(input_pipe_handle); + DisconnectNamedPipe(input_pipe_handle); + CloseHandle(input_pipe_handle); + + HeapFree(hHeap, 0, pchRequest); + + printf("InstanceThread exitting.\n"); + } + + void start_named_pipe_server(HANDLE token) + { + // Adapted from https://docs.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server + const wchar_t* pipe_name = input_pipe_name.c_str(); + BOOL connected = FALSE; + HANDLE connect_pipe_handle = INVALID_HANDLE_VALUE; + while (!closed) + { + { + std::unique_lock lock(pipe_connect_handle_mutex); + connect_pipe_handle = CreateNamedPipe( + pipe_name, + PIPE_ACCESS_DUPLEX | + WRITE_DAC, + PIPE_TYPE_MESSAGE | + PIPE_READMODE_MESSAGE | + PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + BUFSIZE, + BUFSIZE, + 0, + NULL); + + if (connect_pipe_handle == INVALID_HANDLE_VALUE) + { + return; + } + + if (token != NULL) + { + int err = change_pipe_security_allow_restricted_token(connect_pipe_handle, token); + } + current_connect_pipe_handle = connect_pipe_handle; + } + connected = ConnectNamedPipe(connect_pipe_handle, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); + { + std::unique_lock lock(pipe_connect_handle_mutex); + current_connect_pipe_handle = NULL; + } + if (connected) + { + std::thread(&TwoWayPipeMessageIPC::handle_pipe_connection, this, connect_pipe_handle).detach(); + } + else + { + // Client could not connect. + CloseHandle(connect_pipe_handle); + } + } + } + + void consume_input_queue_thread() + { + while (!closed) + { + std::wstring message = input_queue.pop_message(); + if (message.length() == 0) + { + break; + } + dispatch_inc_message_function(message); + } + } }; diff --git a/src/common/version.h b/src/common/version.h index 22ef9caa6..f4a377634 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -2,17 +2,18 @@ #define STRINGIZE2(s) #s #define STRINGIZE(s) STRINGIZE2(s) - -#define VERSION_MAJOR 0 -#define VERSION_MINOR 15 -#define VERSION_REVISION 2 - -#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 PRODUCT_VERSION FILE_VERSION -#define PRODUCT_VERSION_STRING FILE_VERSION_STRING +#define VERSION_MAJOR 0 +#define VERSION_MINOR 15 +#define VERSION_REVISION 2 -#define COMPANY_NAME "Microsoft Corporation" -#define COPYRIGHT_NOTE "Copyright (C) 2019 Microsoft Corporation" - +#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 PRODUCT_VERSION FILE_VERSION +#define PRODUCT_VERSION_STRING FILE_VERSION_STRING + +#define COMPANY_NAME "Microsoft Corporation" +#define COPYRIGHT_NOTE "Copyright (C) 2019 Microsoft Corporation" diff --git a/src/common/window_helpers.cpp b/src/common/window_helpers.cpp index 678ebe82e..35b935072 100644 --- a/src/common/window_helpers.cpp +++ b/src/common/window_helpers.cpp @@ -4,7 +4,7 @@ HWND CreateMsgWindow(_In_ HINSTANCE hInst, _In_ WNDPROC pfnWndProc, _In_ void* p) { WNDCLASS wc = { 0 }; - + PCWSTR wndClassName = L"MsgWindow"; wc.lpfnWndProc = DefWindowProc; diff --git a/src/common/windows_colors.cpp b/src/common/windows_colors.cpp index f067aaeb9..a48acc3fd 100644 --- a/src/common/windows_colors.cpp +++ b/src/common/windows_colors.cpp @@ -1,75 +1,89 @@ #include "pch.h" #include "windows_colors.h" -DWORD WindowsColors::rgb_color(DWORD abgr_color) { - // registry keeps the colors in ABGR format, we want RGB - auto r = (abgr_color & 0xFF); - auto g = (abgr_color & 0xFF00) >> 8; - auto b = (abgr_color & 0xFF0000) >> 16; - return (r << 16) | (g << 8) | b; +DWORD WindowsColors::rgb_color(DWORD abgr_color) +{ + // registry keeps the colors in ABGR format, we want RGB + auto r = (abgr_color & 0xFF); + auto g = (abgr_color & 0xFF00) >> 8; + auto b = (abgr_color & 0xFF0000) >> 16; + return (r << 16) | (g << 8) | b; } -DWORD WindowsColors::rgb_color(winrt::Windows::UI::Color color) { - return ((DWORD)color.R << 16) | ((DWORD)color.G << 8) | ((DWORD)color.B); +DWORD WindowsColors::rgb_color(winrt::Windows::UI::Color color) +{ + return ((DWORD)color.R << 16) | ((DWORD)color.G << 8) | ((DWORD)color.B); } -WindowsColors::Color WindowsColors::get_button_face_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace); +WindowsColors::Color WindowsColors::get_button_face_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace); } -WindowsColors::Color WindowsColors::get_button_text_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonText); +WindowsColors::Color WindowsColors::get_button_text_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::ButtonText); } -WindowsColors::Color WindowsColors::get_highlight_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Highlight); +WindowsColors::Color WindowsColors::get_highlight_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Highlight); } -WindowsColors::Color WindowsColors::get_hotlight_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Hotlight); +WindowsColors::Color WindowsColors::get_hotlight_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::Hotlight); } -WindowsColors::Color WindowsColors::get_highlight_text_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::HighlightText); +WindowsColors::Color WindowsColors::get_highlight_text_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.UIElementColor(winrt::Windows::UI::ViewManagement::UIElementType::HighlightText); } -WindowsColors::Color WindowsColors::get_accent_light_1_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight1); +WindowsColors::Color WindowsColors::get_accent_light_1_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight1); } -WindowsColors::Color WindowsColors::get_accent_light_2_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight2); +WindowsColors::Color WindowsColors::get_accent_light_2_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentLight2); } -WindowsColors::Color WindowsColors::get_accent_dark_1_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentDark1); +WindowsColors::Color WindowsColors::get_accent_dark_1_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::AccentDark1); } -WindowsColors::Color WindowsColors::get_accent_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Accent); +WindowsColors::Color WindowsColors::get_accent_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Accent); } -WindowsColors::Color WindowsColors::get_background_color() { - winrt::Windows::UI::ViewManagement::UISettings uiSettings; - return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Background); -} - -bool WindowsColors::is_dark_mode() { - return rgb_color(get_background_color()) == 0; +WindowsColors::Color WindowsColors::get_background_color() +{ + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + return uiSettings.GetColorValue(winrt::Windows::UI::ViewManagement::UIColorType::Background); } -bool WindowsColors::update() { - auto new_accent_color_menu = rgb_color(get_accent_color()); - auto new_start_color_menu = new_accent_color_menu; - auto new_desktop_fill_color = rgb_color(GetSysColor(COLOR_DESKTOP)); - auto new_light_mode = rgb_color(get_background_color()) != 0; //Dark mode will have black as the background color. - - bool changed = new_accent_color_menu != accent_color_menu || - new_start_color_menu != start_color_menu || - new_light_mode != light_mode || - new_desktop_fill_color != desktop_fill_color; - accent_color_menu = new_accent_color_menu; - start_color_menu = new_start_color_menu; - light_mode = new_light_mode; - desktop_fill_color = new_desktop_fill_color; - - return changed; +bool WindowsColors::is_dark_mode() +{ + return rgb_color(get_background_color()) == 0; +} + +bool WindowsColors::update() +{ + auto new_accent_color_menu = rgb_color(get_accent_color()); + auto new_start_color_menu = new_accent_color_menu; + auto new_desktop_fill_color = rgb_color(GetSysColor(COLOR_DESKTOP)); + auto new_light_mode = rgb_color(get_background_color()) != 0; //Dark mode will have black as the background color. + + bool changed = new_accent_color_menu != accent_color_menu || + new_start_color_menu != start_color_menu || + new_light_mode != light_mode || + new_desktop_fill_color != desktop_fill_color; + accent_color_menu = new_accent_color_menu; + start_color_menu = new_start_color_menu; + light_mode = new_light_mode; + desktop_fill_color = new_desktop_fill_color; + + return changed; } diff --git a/src/common/windows_colors.h b/src/common/windows_colors.h index ba87382bd..ec81d08b4 100644 --- a/src/common/windows_colors.h +++ b/src/common/windows_colors.h @@ -1,27 +1,28 @@ #pragma once #include -struct WindowsColors { - using Color = winrt::Windows::UI::Color; - - static DWORD rgb_color(DWORD abgr_color); - static DWORD rgb_color(Color color); - static Color get_button_face_color(); - static Color get_button_text_color(); - static Color get_highlight_color(); - static Color get_hotlight_color(); - static Color get_highlight_text_color(); - static Color get_accent_light_1_color(); - static Color get_accent_light_2_color(); - static Color get_accent_dark_1_color(); - static Color get_accent_color(); - static Color get_background_color(); - static bool is_dark_mode(); - // Update colors - returns true if the values where changed - bool update(); +struct WindowsColors +{ + using Color = winrt::Windows::UI::Color; - DWORD accent_color_menu = 0, - start_color_menu = 0, - desktop_fill_color = 0; - bool light_mode = true; + static DWORD rgb_color(DWORD abgr_color); + static DWORD rgb_color(Color color); + static Color get_button_face_color(); + static Color get_button_text_color(); + static Color get_highlight_color(); + static Color get_hotlight_color(); + static Color get_highlight_text_color(); + static Color get_accent_light_1_color(); + static Color get_accent_light_2_color(); + static Color get_accent_dark_1_color(); + static Color get_accent_color(); + static Color get_background_color(); + static bool is_dark_mode(); + // Update colors - returns true if the values where changed + bool update(); + + DWORD accent_color_menu = 0, + start_color_menu = 0, + desktop_fill_color = 0; + bool light_mode = true; }; diff --git a/src/common/winstore.h b/src/common/winstore.h index 82f832495..3846d3d41 100644 --- a/src/common/winstore.h +++ b/src/common/winstore.h @@ -4,7 +4,6 @@ #include - namespace winstore { using winrt::Windows::ApplicationModel::StartupTaskState; diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 96ceea4fd..8b0ac14f8 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -317,7 +317,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine int result = 0; try { - std::thread{ [] { github_update_checking_worker(); } }.detach(); diff --git a/src/runner/tray_icon.cpp b/src/runner/tray_icon.cpp index 5c3141207..ad5946341 100644 --- a/src/runner/tray_icon.cpp +++ b/src/runner/tray_icon.cpp @@ -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. // 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. - case WM_WINDOWPOSCHANGING: { + case WM_WINDOWPOSCHANGING: + { if (!tray_icon_created) { 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) { - case WM_LBUTTONUP: { + case WM_LBUTTONUP: + { open_settings_window(); break; } case WM_RBUTTONUP: - case WM_CONTEXTMENU: { + case WM_CONTEXTMENU: + { if (!h_menu) { h_menu = LoadMenu(reinterpret_cast(&__ImageBase), MAKEINTRESOURCE(ID_TRAY_MENU)); diff --git a/src/settings/main.cpp b/src/settings/main.cpp index 2b669a7e7..68411bd18 100644 --- a/src/settings/main.cpp +++ b/src/settings/main.cpp @@ -248,7 +248,7 @@ void initialize_webview(int nShowCmd) // WebView doesn't let us to open ms-settings:protocol links directly, so we translate it // from a https placeholder if (uri.AbsoluteUri() == L"https://ms_settings_startupapps/") - uri = Uri{L"ms-settings:startupapps"}; + uri = Uri{ L"ms-settings:startupapps" }; winrt::Windows::System::Launcher::LaunchUriAsync(uri); }); @@ -339,7 +339,8 @@ LRESULT CALLBACK wnd_proc_static(HWND hWnd, UINT message, WPARAM wParam, LPARAM wm_data_for_webview = RegisterWindowMessageW(L"PTSettingsCopyDataWebView"); wm_destroy_window = RegisterWindowMessageW(L"PTSettingsParentTerminated"); break; - case WM_DPICHANGED: { + case WM_DPICHANGED: + { // Resize the window using the suggested rect RECT* const prcNewWindow = (RECT*)lParam; SetWindowPos(hWnd, @@ -351,7 +352,8 @@ LRESULT CALLBACK wnd_proc_static(HWND hWnd, UINT message, WPARAM wParam, LPARAM SWP_NOZORDER | SWP_NOACTIVATE); } break; - case WM_NCCREATE: { + case WM_NCCREATE: + { // Enable auto-resizing the title bar EnableNonClientDpiScaling(hWnd); }