Formatting chores (#1441)

* format_sources: exclude 3rd party sources

* format common project

* format leftovers in runner & settings projects

* move source formatting-related files according to #939
This commit is contained in:
Andrey Nekrasov 2020-03-05 13:07:06 +03:00 committed by GitHub
parent 92f64188d5
commit cf1b53831f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 2602 additions and 2220 deletions

View File

@ -20,7 +20,9 @@ $sourceExtensions.Add(".cpp") | Out-Null
$sourceExtensions.Add(".h") | Out-Null
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

View File

@ -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

View File

@ -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<winrt::hresult_error>(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<winrt::hresult_error>(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<bool>(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<bool>(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<UINT, HotkeyObject> 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<UINT, HotkeyObject> expectedMap = {
std::make_pair(0x4000, HotkeyObject::from_settings(false, false, false, false, 0)),

View File

@ -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);

View File

@ -2,27 +2,33 @@
#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() {
void Animation::reset()
{
start = std::chrono::high_resolution_clock::now();
}
void Animation::reset(double duration) {
void Animation::reset(double duration)
{
this->duration = duration;
reset();
}
void Animation::reset(double duration, double start, double stop) {
void Animation::reset(double duration, double start, double stop)
{
start_value = start;
end_value = stop;
reset(duration);
}
static double ease_out_expo(double 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) {
double Animation::apply_animation_function(double t, AnimFunctions apply_function)
{
switch (apply_function)
{
case EASE_OUT_EXPO:
return ease_out_expo(t);
case LINEAR:
@ -31,13 +37,15 @@ double Animation::apply_animation_function(double t, AnimFunctions apply_functio
}
}
double Animation::value(AnimFunctions apply_function) const {
double Animation::value(AnimFunctions apply_function) const
{
auto anim_duration = std::chrono::high_resolution_clock::now() - start;
double t = std::chrono::duration<double>(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 {
bool Animation::done() const
{
return std::chrono::high_resolution_clock::now() - start >= std::chrono::duration<double>(duration);
}

View File

@ -11,9 +11,11 @@
When redering, call value() to get value from 0 to 1 - depending on animation
progress.
*/
class Animation {
class Animation
{
public:
enum AnimFunctions {
enum AnimFunctions
{
LINEAR = 0,
EASE_OUT_EXPO
};
@ -24,6 +26,7 @@ public:
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;

View File

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

View File

@ -8,7 +8,7 @@ template<typename T>
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;

View File

@ -14,29 +14,41 @@ namespace localized_strings
const wchar_t LAST_ERROR_TITLE_STRING[] = L"Error";
}
std::optional<RECT> get_button_pos(HWND hwnd) {
std::optional<RECT> get_button_pos(HWND hwnd)
{
RECT button;
if (DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, &button, sizeof(RECT)) == S_OK) {
if (DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, &button, sizeof(RECT)) == S_OK)
{
return button;
} else {
}
else
{
return {};
}
}
std::optional<RECT> get_window_pos(HWND hwnd) {
std::optional<RECT> get_window_pos(HWND hwnd)
{
RECT window;
if (DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &window, sizeof(window)) == S_OK) {
if (DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &window, sizeof(window)) == S_OK)
{
return window;
} else {
}
else
{
return {};
}
}
std::optional<POINT> get_mouse_pos() {
std::optional<POINT> get_mouse_pos()
{
POINT point;
if (GetCursorPos(&point) == 0) {
if (GetCursorPos(&point) == 0)
{
return {};
} else {
}
else
{
return point;
}
}
@ -45,16 +57,21 @@ std::optional<POINT> get_mouse_pos() {
// We compare the HWND against HWND of the desktop and shell windows,
// we 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 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) {
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) {
for (const auto& system_class : system_classes)
{
if (strcmp(system_class, class_name) == 0)
{
return true;
}
}
@ -64,14 +81,17 @@ static bool is_system_window(HWND hwnd, const char* class_name) {
static bool no_visible_owner(HWND window) noexcept
{
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,9 +99,11 @@ 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 get_fancyzones_filtered_window(HWND window)
{
FancyZonesFilter result;
if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window)) {
if (GetAncestor(window, GA_ROOT) != window || !IsWindowVisible(window))
{
return result;
}
auto style = GetWindowLong(window, GWL_STYLE);
@ -91,24 +113,28 @@ FancyZonesFilter get_fancyzones_filtered_window(HWND window) {
if ((style & WS_POPUP) == WS_POPUP &&
(style & WS_THICKFRAME) == 0 &&
(style & WS_MINIMIZEBOX) == 0 &&
(style & WS_MAXIMIZEBOX) == 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) {
(exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE)
{
return result;
}
std::array<char, 256> class_name;
GetClassNameA(window, class_name.data(), static_cast<int>(class_name.size()));
if (is_system_window(window, class_name.data())) {
if (is_system_window(window, class_name.data()))
{
return result;
}
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")) {
process_path.ends_with(L"SearchUI.exe"))
{
return result;
}
result.process_path = std::move(process_path);
@ -118,11 +144,13 @@ FancyZonesFilter get_fancyzones_filtered_window(HWND window) {
return result;
}
ShortcutGuideFilter get_shortcutguide_filtered_window() {
ShortcutGuideFilter get_shortcutguide_filtered_window()
{
ShortcutGuideFilter result;
auto active_window = GetForegroundWindow();
active_window = GetAncestor(active_window, GA_ROOT);
if (!IsWindowVisible(active_window)) {
if (!IsWindowVisible(active_window))
{
return result;
}
auto style = GetWindowLong(active_window, GWL_STYLE);
@ -130,22 +158,28 @@ ShortcutGuideFilter get_shortcutguide_filtered_window() {
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) {
(exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE)
{
return result;
}
std::array<char, 256> class_name;
GetClassNameA(active_window, class_name.data(), static_cast<int>(class_name.size()));
if (is_system_window(active_window, class_name.data())) {
if (is_system_window(active_window, class_name.data()))
{
return result;
}
static HWND cortanda_hwnd = nullptr;
if (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")) {
get_process_path(active_window).ends_with(L"SearchUI.exe"))
{
cortanda_hwnd = active_window;
return result;
}
} else if (cortanda_hwnd == active_window) {
}
else if (cortanda_hwnd == active_window)
{
return result;
}
result.hwnd = active_window;
@ -163,115 +197,143 @@ ShortcutGuideFilter get_shortcutguide_filtered_window() {
return result;
}
int width(const RECT& rect) {
int width(const RECT& rect)
{
return rect.right - rect.left;
}
int height(const RECT& rect) {
int height(const RECT& rect)
{
return rect.bottom - rect.top;
}
bool operator<(const RECT& lhs, const RECT& rhs) {
bool operator<(const RECT& lhs, const RECT& rhs)
{
auto lhs_tuple = std::make_tuple(lhs.left, lhs.right, lhs.top, lhs.bottom);
auto 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 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)) {
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) {
}
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;
result.left -= result.right - big_rect.right;
result.right -= result.right - big_rect.right;
}
if (result.left < big_rect.left) {
if (result.left < big_rect.left)
{
// move the rect right.
result.right += big_rect.left-result.left;
result.left += big_rect.left-result.left;
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)) {
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) {
}
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;
result.top -= result.bottom - big_rect.bottom;
result.bottom -= result.bottom - big_rect.bottom;
}
if (result.top < big_rect.top) {
if (result.top < big_rect.top)
{
// move the rect down.
result.bottom += big_rect.top-result.top;
result.top += big_rect.top-result.top;
result.bottom += big_rect.top - result.top;
result.top += big_rect.top - result.top;
}
}
return result;
}
int run_message_loop() {
int run_message_loop()
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
std::optional<std::wstring> get_last_error_message(const DWORD dw) {
std::optional<std::wstring> get_last_error_message(const DWORD dw)
{
std::optional<std::wstring> message;
try {
try
{
const auto msg = std::system_category().message(dw);
message.emplace(begin(msg), end(msg));
}
catch(...) {
catch (...)
{
}
return message;
}
void show_last_error_message(LPCWSTR lpszFunction, DWORD dw) {
void show_last_error_message(LPCWSTR lpszFunction, DWORD dw)
{
const auto system_message = get_last_error_message(dw);
if(!system_message.has_value()) {
if (!system_message.has_value())
{
return;
}
LPWSTR lpDisplayBuf = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (system_message->size() + lstrlenW(lpszFunction) + 40) * sizeof(WCHAR));
if (lpDisplayBuf != NULL) {
if (lpDisplayBuf != NULL)
{
StringCchPrintfW(lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(WCHAR),
localized_strings::LAST_ERROR_FORMAT_STRING,
lpszFunction, dw, system_message->c_str());
lpszFunction,
dw,
system_message->c_str());
MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, localized_strings::LAST_ERROR_TITLE_STRING, MB_OK);
LocalFree(lpDisplayBuf);
}
}
WindowState get_window_state(HWND hwnd) {
WindowState get_window_state(HWND hwnd)
{
WINDOWPLACEMENT placement;
placement.length = sizeof(WINDOWPLACEMENT);
if (GetWindowPlacement(hwnd, &placement) == 0) {
if (GetWindowPlacement(hwnd, &placement) == 0)
{
return UNKNONW;
}
if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_SHOWMINIMIZED || IsIconic(hwnd)) {
if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_SHOWMINIMIZED || IsIconic(hwnd))
{
return MINIMIZED;
}
if (placement.showCmd == SW_MAXIMIZE || placement.showCmd == SW_SHOWMAXIMIZED) {
if (placement.showCmd == SW_MAXIMIZE || placement.showCmd == SW_SHOWMAXIMIZED)
{
return MAXIMIZED;
}
auto rectp = get_window_pos(hwnd);
if (!rectp) {
if (!rectp)
{
return UNKNONW;
}
@ -285,44 +347,57 @@ WindowState get_window_state(HWND hwnd) {
bool top_right = monitor.rcWork.top == rect.top && monitor.rcWork.right == rect.right;
bool 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;
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() {
bool is_process_elevated()
{
HANDLE token = nullptr;
bool elevated = false;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
{
TOKEN_ELEVATION elevation;
DWORD size;
if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) {
if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size))
{
elevated = (elevation.TokenIsElevated != 0);
}
}
if (token) {
if (token)
{
CloseHandle(token);
}
return elevated;
}
bool drop_elevated_privileges() {
bool drop_elevated_privileges()
{
HANDLE token = nullptr;
LPCTSTR lpszPrivilege = SE_SECURITY_NAME;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token)) {
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT | WRITE_OWNER, &token))
{
return false;
}
PSID medium_sid = NULL;
if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) {
if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid))
{
return false;
}
@ -338,13 +413,16 @@ bool drop_elevated_privileges() {
return result;
}
std::wstring get_process_path(DWORD pid) noexcept {
std::wstring get_process_path(DWORD pid) noexcept
{
auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid);
std::wstring name;
if (process != INVALID_HANDLE_VALUE) {
if (process != INVALID_HANDLE_VALUE)
{
name.resize(MAX_PATH);
DWORD name_length = static_cast<DWORD>(name.length());
if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0) {
if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0)
{
name_length = 0;
}
name.resize(name_length);
@ -353,7 +431,8 @@ std::wstring get_process_path(DWORD pid) noexcept {
return name;
}
bool run_elevated(const std::wstring& file, const std::wstring& params) {
bool run_elevated(const std::wstring& file, const std::wstring& params)
{
SHELLEXECUTEINFOW exec_info = { 0 };
exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
exec_info.lpVerb = L"runas";
@ -364,28 +443,35 @@ bool run_elevated(const std::wstring& file, const std::wstring& params) {
exec_info.lpDirectory = 0;
exec_info.hInstApp = 0;
if (ShellExecuteExW(&exec_info)) {
if (ShellExecuteExW(&exec_info))
{
return exec_info.hProcess != nullptr;
} else {
}
else
{
return false;
}
}
bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
bool run_non_elevated(const std::wstring& file, const std::wstring& params)
{
auto executable_args = L"\"" + file + L"\"";
if (!params.empty()) {
if (!params.empty())
{
executable_args += L" " + params;
}
HWND hwnd = GetShellWindow();
if (!hwnd) {
if (!hwnd)
{
return false;
}
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
winrt::handle process{ OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pid) };
if (!process) {
if (!process)
{
return false;
}
@ -395,7 +481,8 @@ bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
auto pproc_buffer = std::make_unique<char[]>(size);
auto pptal = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(pproc_buffer.get());
if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size)) {
if (!InitializeProcThreadAttributeList(pptal, 1, 0, &size))
{
return false;
}
@ -406,7 +493,8 @@ bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
&process_handle,
sizeof(process_handle),
nullptr,
nullptr)) {
nullptr))
{
return false;
}
@ -425,18 +513,22 @@ bool run_non_elevated(const std::wstring& file, const std::wstring& params) {
nullptr,
&siex.StartupInfo,
&process_info);
if (process_info.hProcess) {
if (process_info.hProcess)
{
CloseHandle(process_info.hProcess);
}
if (process_info.hThread) {
if (process_info.hThread)
{
CloseHandle(process_info.hThread);
}
return succedded;
}
bool run_same_elevation(const std::wstring& file, const std::wstring& params) {
bool run_same_elevation(const std::wstring& file, const std::wstring& params)
{
auto executable_args = L"\"" + file + L"\"";
if (!params.empty()) {
if (!params.empty())
{
executable_args += L" " + params;
}
STARTUPINFO si = { 0 };
@ -451,46 +543,56 @@ bool run_same_elevation(const std::wstring& file, const std::wstring& params) {
nullptr,
&si,
&pi);
if (pi.hProcess) {
if (pi.hProcess)
{
CloseHandle(pi.hProcess);
}
if (pi.hThread) {
if (pi.hThread)
{
CloseHandle(pi.hThread);
}
return succedded;
}
std::wstring get_process_path(HWND window) noexcept {
std::wstring get_process_path(HWND window) noexcept
{
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
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) {
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 {
EnumChildWindows(
window, [](HWND hwnd, LPARAM param) -> BOOL {
auto new_pid_ptr = reinterpret_cast<DWORD*>(param);
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
if (pid != *new_pid_ptr) {
if (pid != *new_pid_ptr)
{
*new_pid_ptr = pid;
return FALSE;
} else {
}
else
{
return TRUE;
}
}, reinterpret_cast<LPARAM>(&new_pid));
},
reinterpret_cast<LPARAM>(&new_pid));
// If we have a new pid, get the new name.
if (new_pid != pid) {
if (new_pid != pid)
{
return get_process_path(new_pid);
}
}
return name;
}
std::wstring get_product_version() {
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);
@ -498,12 +600,16 @@ std::wstring get_product_version() {
return version;
}
std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback) {
std::wstring get_resource_string(UINT resource_id, HINSTANCE instance, const wchar_t* fallback)
{
wchar_t* text_ptr;
auto length = LoadStringW(instance, resource_id, reinterpret_cast<wchar_t*>(&text_ptr), 0);
if (length == 0) {
if (length == 0)
{
return fallback;
} else {
}
else
{
return { text_ptr, static_cast<std::size_t>(length) };
}
}
@ -541,7 +647,6 @@ std::wstring get_module_folderpath(HMODULE mod)
return { buffer, (UINT)lstrlenW(buffer) };
}
// 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()

View File

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

View File

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

View File

@ -4,7 +4,8 @@
#include <winrt/base.h>
#include <string>
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);
@ -16,6 +17,7 @@ public:
D2DSVG& toggle_element(const wchar_t* id, bool visible);
winrt::com_ptr<ID2D1SvgElement> find_element(const std::wstring& id);
D2D1_RECT_F rescale(D2D1_RECT_F rect);
protected:
float used_scale = 1.0f;
winrt::com_ptr<ID2D1SvgDocument> svg;

View File

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

View File

@ -2,7 +2,8 @@
#include <winrt/base.h>
#include <dwrite.h>
class D2DText {
class D2DText
{
public:
D2DText(float text_size = 15.0f, float scale = 1.0f);
D2DText& resize(float text_size, float scale);
@ -10,6 +11,7 @@ public:
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<IDWriteFactory> factory;
winrt::com_ptr<IDWriteTextFormat> format;

View File

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

View File

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

View File

@ -11,16 +11,16 @@ namespace json
{
std::wifstream file(file_name.data(), std::ios::binary);
using isbi = std::istreambuf_iterator<wchar_t>;
return JsonValue::Parse(std::wstring{isbi{file}, isbi{}}).GetObjectW();
return JsonValue::Parse(std::wstring{ isbi{ file }, isbi{} }).GetObjectW();
}
catch(...)
catch (...)
{
return std::nullopt;
}
}
void to_file(std::wstring_view file_name, const JsonObject & obj)
void to_file(std::wstring_view file_name, const JsonObject& obj)
{
std::wofstream{file_name.data(), std::ios::binary} << obj.Stringify().c_str();
std::wofstream{ file_name.data(), std::ios::binary } << obj.Stringify().c_str();
}
}

View File

@ -14,7 +14,7 @@ namespace json
void to_file(std::wstring_view file_name, const JsonObject& obj);
inline bool has(
const json::JsonObject & o,
const json::JsonObject& o,
std::wstring_view name,
const json::JsonValueType type = JsonValueType::Object)
{

View File

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

View File

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

View File

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

View File

@ -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)";

View File

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

View File

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

View File

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

View File

@ -3,60 +3,70 @@
#include <filesystem>
#include <fstream>
namespace PTSettingsHelper {
namespace PTSettingsHelper
{
constexpr inline const wchar_t* settings_filename = L"\\settings.json";
constexpr inline const wchar_t * settings_filename = L"\\settings.json";
std::wstring get_root_save_folder_location() {
std::wstring get_root_save_folder_location()
{
PWSTR local_app_path;
winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path));
std::wstring result{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)) {
if (!std::filesystem::exists(save_path))
{
std::filesystem::create_directories(save_path);
}
return result;
}
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name) {
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name)
{
std::wstring result = get_root_save_folder_location();
result += L"\\";
result += powertoy_name;
std::filesystem::path save_path(result);
if (!std::filesystem::exists(save_path)) {
if (!std::filesystem::exists(save_path))
{
std::filesystem::create_directories(save_path);
}
return result;
}
std::wstring get_module_save_file_location(std::wstring_view powertoy_name) {
std::wstring get_module_save_file_location(std::wstring_view powertoy_name)
{
return get_module_save_folder_location(powertoy_name) + settings_filename;
}
std::wstring get_powertoys_general_save_file_location() {
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) {
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) {
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) {
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() {
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{};

View File

@ -4,8 +4,8 @@
#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();

View File

@ -2,41 +2,49 @@
#include "settings_objects.h"
#include "settings_helpers.h"
namespace PowerToysSettings {
Settings::Settings(const HINSTANCE hinstance, std::wstring_view powertoy_name) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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"));
@ -47,11 +55,13 @@ namespace PowerToysSettings {
}
// add_int_spinner overloads.
void Settings::add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step) {
void Settings::add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step)
{
add_int_spinner(name, get_resource(description_resource_id), value, min, max, step);
}
void Settings::add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step) {
void Settings::add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step)
{
json::JsonObject spinner;
spinner.SetNamedValue(L"display_name", json::value(description));
spinner.SetNamedValue(L"editor_type", json::value(L"int_spinner"));
@ -65,11 +75,13 @@ namespace PowerToysSettings {
}
// add_string overloads.
void Settings::add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) {
void Settings::add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value)
{
add_string(name, get_resource(description_resource_id), value);
}
void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) {
void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value)
{
json::JsonObject string;
string.SetNamedValue(L"display_name", json::value(description));
string.SetNamedValue(L"editor_type", json::value(L"string_text"));
@ -80,11 +92,13 @@ namespace PowerToysSettings {
}
// add_multiline_string overloads.
void Settings::add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) {
void Settings::add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value)
{
add_multiline_string(name, get_resource(description_resource_id), value);
}
void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) {
void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value)
{
json::JsonObject ml_string;
ml_string.SetNamedValue(L"display_name", json::value(description));
ml_string.SetNamedValue(L"editor_type", json::value(L"string_text"));
@ -96,11 +110,13 @@ namespace PowerToysSettings {
}
// add_color_picker overloads.
void Settings::add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value) {
void Settings::add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value)
{
add_color_picker(name, get_resource(description_resource_id), value);
}
void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value) {
void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value)
{
json::JsonObject picker;
picker.SetNamedValue(L"display_name", json::value(description));
picker.SetNamedValue(L"editor_type", json::value(L"color_picker"));
@ -110,11 +126,13 @@ namespace PowerToysSettings {
m_json.GetNamedObject(L"properties").SetNamedValue(name, picker);
}
void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey) {
void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey)
{
add_hotkey(name, get_resource(description_resource_id), hotkey);
}
void Settings::add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey_obj) {
void Settings::add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey_obj)
{
json::JsonObject hotkey;
hotkey.SetNamedValue(L"display_name", json::value(description));
hotkey.SetNamedValue(L"editor_type", json::value(L"hotkey"));
@ -124,21 +142,25 @@ namespace PowerToysSettings {
m_json.GetNamedObject(L"properties").SetNamedValue(name, hotkey);
}
void Settings::add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) {
void Settings::add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids)
{
std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts;
keys_and_texts.reserve(keys_and_text_ids.size());
for (const auto& kv : keys_and_text_ids) {
for (const auto& kv : keys_and_text_ids)
{
keys_and_texts.emplace_back(kv.first, get_resource(kv.second));
}
add_choice_group(name, get_resource(description_resource_id), value, keys_and_texts);
}
void Settings::add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) {
void Settings::add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts)
{
json::JsonObject choice_group;
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) {
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));
@ -151,21 +173,25 @@ namespace PowerToysSettings {
m_json.GetNamedObject(L"properties").SetNamedValue(name, choice_group);
}
void Settings::add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) {
void Settings::add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids)
{
std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts;
keys_and_texts.reserve(keys_and_text_ids.size());
for (const auto& kv : keys_and_text_ids) {
for (const auto& kv : keys_and_text_ids)
{
keys_and_texts.emplace_back(kv.first, get_resource(kv.second));
}
add_dropdown(name, get_resource(description_resource_id), value, keys_and_texts);
}
void Settings::add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) {
void Settings::add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts)
{
json::JsonObject dropdown;
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) {
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));
@ -179,15 +205,18 @@ namespace PowerToysSettings {
}
// add_custom_action overloads.
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id) {
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id)
{
add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), get_resource(ext_description_resource_id));
}
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value) {
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value)
{
add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), value);
}
void Settings::add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value) {
void Settings::add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value)
{
json::JsonObject custom_action;
custom_action.SetNamedValue(L"display_name", json::value(description));
custom_action.SetNamedValue(L"button_text", json::value(button_text));
@ -199,101 +228,124 @@ namespace PowerToysSettings {
}
// Serialization methods.
std::wstring Settings::serialize() {
std::wstring Settings::serialize()
{
return m_json.Stringify().c_str();
}
bool Settings::serialize_to_buffer(wchar_t* buffer, int *buffer_size) {
bool Settings::serialize_to_buffer(wchar_t* buffer, int* buffer_size)
{
auto result = m_json.Stringify();
const int result_len = (int)result.size() + 1;
if (buffer == nullptr || *buffer_size < result_len) {
if (buffer == nullptr || *buffer_size < result_len)
{
*buffer_size = result_len;
return false;
} else {
}
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) {
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<wchar_t *>(&res_ptr), 0);
if (resource_length != 0) {
return {*reinterpret_cast<wchar_t **>(&res_ptr), resource_length};
const size_t resource_length = LoadStringW(m_instance, resource_id, reinterpret_cast<wchar_t*>(&res_ptr), 0);
if (resource_length != 0)
{
return { *reinterpret_cast<wchar_t**>(&res_ptr), resource_length };
}
}
return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id);
}
PowerToyValues::PowerToyValues(std::wstring_view powertoy_name) {
PowerToyValues::PowerToyValues(std::wstring_view powertoy_name)
{
_name = powertoy_name;
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 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 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) {
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<bool> PowerToyValues::get_bool_value(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::Boolean)) {
std::optional<bool> 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<int> PowerToyValues::get_int_value(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::Number)) {
std::optional<int> 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<int>(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value"));
}
std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::String)) {
std::optional<std::wstring> 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<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::Object)) {
std::optional<json::JsonObject> 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() {
std::wstring PowerToyValues::serialize()
{
set_version();
return m_json.Stringify().c_str();
}
void PowerToyValues::save_to_settings_file() {
void PowerToyValues::save_to_settings_file()
{
set_version();
PTSettingsHelper::save_module_settings(_name, m_json);
}
void PowerToyValues::set_version() {
void PowerToyValues::set_version()
{
m_json.SetNamedValue(L"version", json::value(m_version));
}
}

View File

@ -2,16 +2,16 @@
#include "json.h"
namespace PowerToysSettings {
namespace PowerToysSettings
{
class HotkeyObject;
class Settings {
class Settings
{
public:
Settings(
const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase'
std::wstring_view powertoy_name
);
std::wstring_view powertoy_name);
// Add additional general information to the PowerToy settings.
void set_description(UINT resource_id);
@ -50,7 +50,6 @@ namespace PowerToysSettings {
void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value);
void add_custom_action(std::wstring_view name, 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.
@ -64,13 +63,14 @@ namespace PowerToysSettings {
std::wstring get_resource(UINT resource_id);
};
class PowerToyValues {
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 <typename T>
template<typename T>
inline void add_property(std::wstring_view name, T value)
{
json::JsonObject prop_value;
@ -94,9 +94,11 @@ namespace PowerToysSettings {
PowerToyValues() {}
};
class CustomActionObject {
class CustomActionObject
{
public:
static CustomActionObject from_json_string(std::wstring_view json) {
static CustomActionObject from_json_string(std::wstring_view json)
{
return CustomActionObject(json::JsonValue::Parse(json).GetObjectW());
}
@ -104,19 +106,24 @@ namespace PowerToysSettings {
std::wstring get_value() { return m_json.GetNamedString(L"value").c_str(); }
protected:
CustomActionObject(json::JsonObject action_json) : m_json(std::move(action_json)) {};
CustomActionObject(json::JsonObject action_json) :
m_json(std::move(action_json)){};
json::JsonObject m_json;
};
class HotkeyObject {
class HotkeyObject
{
public:
static HotkeyObject from_json(json::JsonObject json) {
static HotkeyObject from_json(json::JsonObject json)
{
return HotkeyObject(std::move(json));
}
static HotkeyObject from_json_string(std::wstring_view json) {
static HotkeyObject from_json_string(std::wstring_view json)
{
return HotkeyObject(json::JsonValue::Parse(json).GetObjectW());
}
static HotkeyObject from_settings(bool win_pressed, bool ctrl_pressed, bool alt_pressed, bool shift_pressed, UINT vk_code) {
static HotkeyObject from_settings(bool win_pressed, bool ctrl_pressed, bool alt_pressed, bool shift_pressed, UINT vk_code)
{
json::JsonObject json;
json.SetNamedValue(L"win", json::value(win_pressed));
json.SetNamedValue(L"ctrl", json::value(ctrl_pressed));
@ -134,39 +141,65 @@ namespace PowerToysSettings {
bool ctrl_pressed() const { return m_json.GetNamedBoolean(L"ctrl"); }
bool alt_pressed() const { return m_json.GetNamedBoolean(L"alt"); }
bool shift_pressed() const { return m_json.GetNamedBoolean(L"shift"); }
UINT get_modifiers_repeat() const {
UINT get_modifiers_repeat() const
{
return (win_pressed() ? MOD_WIN : 0) |
(ctrl_pressed() ? MOD_CONTROL : 0) |
(alt_pressed() ? MOD_ALT : 0) |
(shift_pressed() ? MOD_SHIFT : 0);
}
UINT get_modifiers() const {
UINT get_modifiers() const
{
return get_modifiers_repeat() | MOD_NOREPEAT;
}
protected:
static std::wstring key_from_code(UINT key_code) {
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<UINT> 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,
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)) {
if (find(begin(extended_keys), end(extended_keys), key_code) != end(extended_keys))
{
scan_code |= 0x100;
}
std::array<BYTE, 256> key_states{}; // Zero-initialize
std::array<wchar_t, 256> output;
auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, 0, layout);
if (output_bytes <= 0) {
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<int>(output.size()));
}
if (output_bytes > 0) {
if (output_bytes > 0)
{
output[output_bytes] = 0;
if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z') {
if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z')
{
// Make Latin letters keys capital, as it looks better
output[0] = toupper(output[0]);
}
@ -174,8 +207,11 @@ namespace PowerToysSettings {
}
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) {
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())));
}
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,11 +8,12 @@
#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 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"

View File

@ -1,62 +1,76 @@
#include "pch.h"
#include "windows_colors.h"
DWORD WindowsColors::rgb_color(DWORD abgr_color) {
DWORD WindowsColors::rgb_color(DWORD abgr_color)
{
// registry keeps the colors in ABGR format, we want RGB
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) {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
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() {
bool WindowsColors::is_dark_mode()
{
return rgb_color(get_background_color()) == 0;
}
bool WindowsColors::update() {
bool WindowsColors::update()
{
auto new_accent_color_menu = rgb_color(get_accent_color());
auto new_start_color_menu = new_accent_color_menu;
auto new_desktop_fill_color = rgb_color(GetSysColor(COLOR_DESKTOP));

View File

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

View File

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

View File

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

View File

@ -99,7 +99,8 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
// Shell_NotifyIcon can fail when we invoke it during the time explorer.exe isn't present/ready to handle it.
// 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<HINSTANCE>(&__ImageBase), MAKEINTRESOURCE(ID_TRAY_MENU));

View File

@ -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);
}