Compare commits

..

12 Commits

Author SHA1 Message Date
Jaime Bernardo
e7175302c9 [Settings]Fix crash showing non-existent New+ template folder (#35237)
[Settings]Fix crash showing non-existent template folder
2024-10-03 17:24:23 +01:00
Seraphima Zykova
577044163e [Workspaces]Fix launching incorrect workspace via shortcut (#35233)
ensure one launcher instance is running
2024-10-03 15:09:13 +01:00
Jaime Bernardo
bcb5ce895c [New+]Fix call enabled telemetry event (#35236) 2024-10-03 15:08:28 +01:00
Jaime Bernardo
6d69a79c75 0.85 changelog (#35095)
* 0.85 changelog

* Mention ZoomIt

* Update README.md

Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com>

* Address PR feedback

* Update with latest repo changes

* Update binary hashes

* Fix spellcheck

* GPO line in General instead

---------

Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com>
2024-10-01 10:54:01 -07:00
Laszlo Nemeth
ccdfbb0f68 [Workspaces]Fix Workspace icon when installed, move to assets (#35163)
* [Workspaces] fix defaulticon.ico, move it to the Assets directory

* Move assets to single source of truth. Installer logic

---------

Co-authored-by: Stefan Markovic <stefan@janeasystems.com>
2024-10-01 11:52:49 +01:00
Clint Rutkas
6c17fae148 Removed build status from readme (#35113)
Removed build status
2024-09-30 11:04:49 -07:00
Seraphima Zykova
28b90d5f49 [Workspaces]Fix application icons on ARM (#35146)
fixed app path
2024-09-30 17:23:21 +01:00
Jaime Bernardo
77de44fdb4 [NewPlus]Normalize settings infrastructure (#35145) 2024-09-30 16:54:07 +01:00
Stefan Markovic
9b41786c57 [Deps]Revert CommunityToolkit update to fix ARM settings app crash (#35139) 2024-09-30 15:00:50 +01:00
Laszlo Nemeth
d527d9576d [Workspaces]Fix snapshot tool: update capturing windows settings app (#35140)
* [Workspaces] fix snapshot tool: update capturing windows settings app

* spell checker

* spell checker

* minor change in app utils, when the system settings app is captured
2024-09-30 14:37:21 +01:00
Seraphima Zykova
6bab73777b [Workspaces]Fix Steam repositioning (#35101)
* moved and simplified logic

* address PR comment
2024-09-27 23:00:53 +01:00
Den Delimarsky
ff17e3dec9 [Awake]Log error with Logger instead of console (#35100) 2024-09-27 20:38:42 +01:00
36 changed files with 299 additions and 267 deletions

View File

@@ -1590,7 +1590,7 @@ SYSKEYUP
SYSLIB
SYSMENU
SYSTEMAPPS
systemsettings
SYSTEMSETTINGS
SYSTEMTIME
SYSTEMWOW
tapp

View File

@@ -32,7 +32,7 @@ parameters:
- name: enableMsBuildCaching
type: boolean
displayName: "Enable MSBuild Caching"
default: true
default: false
- name: runTests
type: boolean
displayName: "Run Tests"

View File

@@ -6,14 +6,14 @@
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
<PackageVersion Include="Azure.AI.OpenAI" Version="1.0.0-beta.12" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.1.240821" />
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.0.240109" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
<PackageVersion Include="ControlzEx" Version="6.0.0" />

View File

@@ -1299,14 +1299,14 @@ EXHIBIT A -Mozilla Public License.
- Appium.WebDriver 4.4.5
- Azure.AI.OpenAI 1.0.0-beta.12
- CommunityToolkit.Mvvm 8.2.2
- CommunityToolkit.WinUI.Animations 8.1.240821
- CommunityToolkit.WinUI.Collections 8.1.240821
- CommunityToolkit.WinUI.Controls.Primitives 8.1.240821
- CommunityToolkit.WinUI.Controls.Segmented 8.1.240821
- CommunityToolkit.WinUI.Controls.SettingsControls 8.1.240821
- CommunityToolkit.WinUI.Controls.Sizers 8.1.240821
- CommunityToolkit.WinUI.Converters 8.1.240821
- CommunityToolkit.WinUI.Extensions 8.1.240821
- CommunityToolkit.WinUI.Animations 8.0.240109
- CommunityToolkit.WinUI.Collections 8.0.240109
- CommunityToolkit.WinUI.Controls.Primitives 8.0.240109
- CommunityToolkit.WinUI.Controls.Segmented 8.0.240109
- CommunityToolkit.WinUI.Controls.SettingsControls 8.0.240109
- CommunityToolkit.WinUI.Controls.Sizers 8.0.240109
- CommunityToolkit.WinUI.Converters 8.0.240109
- CommunityToolkit.WinUI.Extensions 8.0.240109
- CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2
- CommunityToolkit.WinUI.UI.Controls.Markdown 7.1.2
- ControlzEx 6.0.0

View File

@@ -4,13 +4,6 @@
[How to use PowerToys][usingPowerToys-docs-link] | [Downloads & Release notes][github-release-link] | [Contributing to PowerToys](#contributing) | [What's Happening](#whats-happening) | [Roadmap](#powertoys-roadmap)
## Build status
| Architecture | Solution (Main) | Solution (Stable) | Installer (Main) |
|--------------|-----------------|-------------------|------------------|
| x64 | [![Build Status for Main](https://dev.azure.com/shine-oss/PowerToys/_apis/build/status%2FPowerToys%20CI?branchName=main&jobName=Build%20x64%20Release)](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=main) | [![Build Status for Stable](https://dev.azure.com/shine-oss/PowerToys/_apis/build/status%2FPowerToys%20CI?branchName=stable&jobName=Build%20x64%20Release)](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=stable) | [![Build Status Installer pipeline](https://dev.azure.com/microsoft/Dart/_apis/build/status/PowerToys/PowerToys%20Signed%20YAML%20Release%20Build?branchName=main&jobName=Build&configuration=Build%20Release_x64)](https://dev.azure.com/microsoft/Dart/_build/latest?definitionId=76541&branchName=main) |
| ARM64 | [![Build Status for Main](https://dev.azure.com/shine-oss/PowerToys/_apis/build/status%2FPowerToys%20CI?branchName=main&jobName=Build%20arm64%20Release)](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=main) | [![Build Status for Stable](https://dev.azure.com/shine-oss/PowerToys/_apis/build/status%2FPowerToys%20CI?branchName=main&jobName=Build%20arm64%20Release)](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=main) | [![Build Status Installer pipeline](https://dev.azure.com/microsoft/Dart/_apis/build/status/PowerToys/PowerToys%20Signed%20YAML%20Release%20Build?branchName=main&jobName=Build&configuration=Build%20Release_arm64)](https://dev.azure.com/microsoft/Dart/_build/latest?definitionId=76541&branchName=main) |
## About
Microsoft PowerToys is a set of utilities for power users to tune and streamline their Windows experience for greater productivity. For more info on [PowerToys overviews and how to use the utilities][usingPowerToys-docs-link], or any other tools and resources for [Windows development environments](https://learn.microsoft.com/windows/dev-environment/overview), head over to [learn.microsoft.com][usingPowerToys-docs-link]!

View File

@@ -54,6 +54,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
call move /Y ..\..\..\VideoConference.wxs.bk ..\..\..\VideoConference.wxs
call move /Y ..\..\..\WinAppSDK.wxs.bk ..\..\..\WinAppSDK.wxs
call move /Y ..\..\..\WinUI3Applications.wxs.bk ..\..\..\WinUI3Applications.wxs
call move /Y ..\..\..\Workspaces.wxs.bk ..\..\..\Workspaces.wxs
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
@@ -125,6 +126,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
<Compile Include="Core.wxs" />
<Compile Include="Resources.wxs" />
<Compile Include="WinAppSDK.wxs" />
<Compile Include="Workspaces.wxs" />
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixFirewallExtension">

View File

@@ -79,6 +79,7 @@
<ComponentGroupRef Id="WindowsAppSDKComponentGroup" />
<ComponentGroupRef Id="ToolComponentGroup" />
<ComponentGroupRef Id="MonacoSRCHeatGenerated" />
<ComponentGroupRef Id="WorkspacesComponentGroup" />
</Feature>
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLFOLDER]" After="CostFinalize" />

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" >
<?include $(sys.CURRENTDIR)\Common.wxi?>
<?define WorkspacesImagesComponentFiles=?>
<?define WorkspacesImagesComponentFilesPath=$(var.BinDir)Assets\Workspaces\?>
<Fragment>
<!-- Shortcut guide files -->
<DirectoryRef Id="BaseApplicationsAssetsFolder">
<Directory Id="WorkspacesAssetsInstallFolder" Name="Workspaces" />
</DirectoryRef>
<DirectoryRef Id="WorkspacesAssetsInstallFolder" FileSource="$(var.WorkspacesImagesComponentFilesPath)">
<!-- Generated by generateFileComponents.ps1 -->
<!--WorkspacesImagesComponentFiles_Component_Def-->
</DirectoryRef>
<!-- Workspaces -->
<ComponentGroup Id="WorkspacesComponentGroup" >
<Component Id="RemoveWorkspacesAssetsFolder" Guid="34FC1245-1197-4025-9CF1-A298D509C2CC" Directory="WorkspacesAssetsInstallFolder" >
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="RemoveWorkspacesAssetsFolder" Value="" KeyPath="yes"/>
</RegistryKey>
<RemoveFolder Id="RemoveFolderWorkspacesAssetsFolder" Directory="WorkspacesAssetsInstallFolder" On="uninstall"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>

View File

@@ -317,3 +317,7 @@ Generate-FileComponents -fileListName "SettingsV2AssetsFiles" -wxsFilePath $PSSc
Generate-FileComponents -fileListName "SettingsV2AssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsFluentIconsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
#Workspaces
Generate-FileList -fileDepsJson "" -fileListName WorkspacesImagesComponentFiles -wxsFilePath $PSScriptRoot\Workspaces.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Workspaces\"
Generate-FileComponents -fileListName "WorkspacesImagesComponentFiles" -wxsFilePath $PSScriptRoot\Workspaces.wxs -regroot $registryroot

View File

@@ -76,6 +76,7 @@
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\VideoConference.wxs"" ""$(ProjectDir)..\PowerToysSetup\VideoConference.wxs.bk""""
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\WinAppSDK.wxs"" ""$(ProjectDir)..\PowerToysSetup\WinAppSDK.wxs.bk""""
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\WinUI3Applications.wxs"" ""$(ProjectDir)..\PowerToysSetup\WinUI3Applications.wxs.bk""""
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Workspaces.wxs"" ""$(ProjectDir)..\PowerToysSetup\Workspaces.wxs.bk""""
if not "$(NormalizedPerUserValue)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetup\generateAllFileComponents.ps1 -platform $(Platform)
if "$(NormalizedPerUserValue)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetup\generateAllFileComponents.ps1 -platform $(Platform) -installscopeperuser $(NormalizedPerUserValue)
</Command>

View File

@@ -51,21 +51,30 @@ public:
return true;
}
virtual void set_config(PCWSTR config) override
virtual void set_config(const wchar_t* config) override
{
// The following just checks to see if the Template Location was changed for metrics purposes
// Note: We are not saving the settings here and instead relying on read/write of json in Settings App .cs code paths
try
{
json::JsonObject config_as_json = json::JsonValue::Parse(winrt::to_hstring(config)).GetObjectW();
// Parse the input JSON string.
PowerToysSettings::PowerToyValues values =
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
const auto latest_location_value = config_as_json.GetNamedString(newplus::constants::non_localizable::settings_json_key_template_location).data();
const auto existing_location_value = NewSettingsInstance().GetTemplateLocation();
values.save_to_settings_file();
NewSettingsInstance().Load();
if (!newplus::utilities::wstring_same_when_comparing_ignore_case(latest_location_value, existing_location_value))
auto templateValue = values.get_string_value(newplus::constants::non_localizable::settings_json_key_template_location);
if (templateValue.has_value())
{
Trace::EventChangedTemplateLocation();
const auto latest_location_value = templateValue.value();
const auto existing_location_value = NewSettingsInstance().GetTemplateLocation();
if (!newplus::utilities::wstring_same_when_comparing_ignore_case(latest_location_value, existing_location_value))
{
Trace::EventChangedTemplateLocation();
}
}
}
catch (std::exception& e)
{
@@ -82,6 +91,9 @@ public:
{
Logger::info("New+ enabled via Settings UI");
// Log telemetry
Trace::EventToggleOnOff(true);
newplus::utilities::register_msix_package();
powertoy_new_enabled = true;
@@ -90,8 +102,7 @@ public:
virtual void disable() override
{
Logger::info("New+ disabled via Settings UI");
powertoy_new_enabled = false;
Disable(true);
}
virtual bool is_enabled() override
@@ -116,12 +127,23 @@ public:
virtual void destroy() override
{
Disable(false);
delete this;
}
private:
bool powertoy_new_enabled = false;
void Disable(bool const traceEvent)
{
// Log telemetry
if (traceEvent)
{
Trace::EventToggleOnOff(false);
}
powertoy_new_enabled = false;
}
void init_settings()
{
powertoy_new_enabled = NewSettingsInstance().GetEnabled();

View File

@@ -3,6 +3,7 @@
#include <common/utils/gpo.h>
#include <common/utils/json.h>
#include <common/SettingsAPI/settings_helpers.h>
#include <common/SettingsAPI/settings_objects.h>
#include "settings.h"
#include "constants.h"
@@ -38,18 +39,13 @@ NewSettings::NewSettings()
void NewSettings::Save()
{
json::JsonObject new_settings_json_data;
PowerToysSettings::PowerToyValues values(newplus::constants::non_localizable::powertoy_key, newplus::constants::non_localizable::powertoy_key);
new_settings_json_data.SetNamedValue(newplus::constants::non_localizable::settings_json_key_hide_file_extension,
json::value(new_settings.hide_file_extension));
values.add_property(newplus::constants::non_localizable::settings_json_key_hide_file_extension, new_settings.hide_file_extension);
values.add_property(newplus::constants::non_localizable::settings_json_key_hide_starting_digits, new_settings.hide_starting_digits);
values.add_property(newplus::constants::non_localizable::settings_json_key_template_location, new_settings.template_location);
new_settings_json_data.SetNamedValue(newplus::constants::non_localizable::settings_json_key_hide_starting_digits,
json::value(new_settings.hide_starting_digits));
new_settings_json_data.SetNamedValue(newplus::constants::non_localizable::settings_json_key_template_location,
json::value(new_settings.template_location));
json::to_file(new_settings_json_file_path, new_settings_json_data);
values.save_to_settings_file();
GetSystemTimeAsFileTime(&new_settings_last_loaded_timestamp);
}
@@ -122,35 +118,27 @@ void NewSettings::Reload()
void NewSettings::ParseJson()
{
auto json = json::from_file(new_settings_json_file_path);
if (json)
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(newplus::constants::non_localizable::powertoy_key);
auto templateValue = settings.get_string_value(newplus::constants::non_localizable::settings_json_key_template_location);
if (templateValue.has_value())
{
try
{
const json::JsonObject& new_settings_json = json.value();
if (json::has(new_settings_json, newplus::constants::non_localizable::settings_json_key_hide_file_extension, json::JsonValueType::Boolean))
{
new_settings.hide_file_extension = new_settings_json.GetNamedBoolean(
newplus::constants::non_localizable::settings_json_key_hide_file_extension);
}
if (json::has(new_settings_json, newplus::constants::non_localizable::settings_json_key_hide_starting_digits, json::JsonValueType::Boolean))
{
new_settings.hide_starting_digits = new_settings_json.GetNamedBoolean(
newplus::constants::non_localizable::settings_json_key_hide_starting_digits);
}
if (json::has(new_settings_json, newplus::constants::non_localizable::settings_json_key_template_location, json::JsonValueType::String))
{
new_settings.template_location = new_settings_json.GetNamedString(
newplus::constants::non_localizable::settings_json_key_template_location);
}
}
catch (const winrt::hresult_error&)
{
}
new_settings.template_location = templateValue.value();
}
auto hideFileExtensionValue = settings.get_bool_value(newplus::constants::non_localizable::settings_json_key_hide_file_extension);
if (hideFileExtensionValue.has_value())
{
new_settings.hide_file_extension = hideFileExtensionValue.value();
}
auto hideStartingDigitsValue = settings.get_bool_value(newplus::constants::non_localizable::settings_json_key_hide_starting_digits);
if (hideStartingDigitsValue.has_value())
{
new_settings.hide_starting_digits = hideStartingDigitsValue.value();
}
GetSystemTimeAsFileTime(&new_settings_last_loaded_timestamp);
}

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

Before

Width:  |  Height:  |  Size: 456 KiB

After

Width:  |  Height:  |  Size: 456 KiB

View File

@@ -247,7 +247,7 @@ namespace WorkspacesEditor.Models
{
Logger.LogWarning($"Icon not found on app path: {AppPath}. Using default icon");
IsNotFound = true;
_icon = new Icon(@"images\DefaultIcon.ico");
_icon = new Icon(@"Assets\Workspaces\DefaultIcon.ico");
}
}

View File

@@ -23,16 +23,12 @@
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>images\Workspaces.ico</ApplicationIcon>
<ApplicationIcon>..\Assets\Workspaces\Workspaces.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AssemblyName>PowerToys.WorkspacesEditor</AssemblyName>
</PropertyGroup>
<ItemGroup>
<None Remove="images\DefaultIcon.ico" />
<None Remove="images\Workspaces.ico" />
</ItemGroup>
<ItemGroup>
<COMReference Include="IWshRuntimeLibrary">
<WrapperTool>tlbimp</WrapperTool>
@@ -54,10 +50,10 @@
</COMReference>
</ItemGroup>
<ItemGroup>
<Content Include="images\DefaultIcon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Content Include="..\Assets\**\*.*">
<Link>Assets\Workspaces\%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="images\Workspaces.ico" />
</ItemGroup>
<ItemGroup>
@@ -100,7 +96,4 @@
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<_DeploymentManifestIconFile Remove="images\Workspaces.ico" />
</ItemGroup>
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 KiB

View File

@@ -16,6 +16,7 @@
const std::wstring moduleName = L"Workspaces\\WorkspacesLauncher";
const std::wstring internalPath = L"";
const std::wstring instanceMutexName = L"Local\\PowerToys_WorkspacesLauncher_InstanceMutex";
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cmdShow)
{
@@ -28,6 +29,18 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR cmdline, int cm
return 0;
}
auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str());
if (mutex == nullptr)
{
Logger::error(L"Failed to create mutex. {}", get_last_error_or_default(GetLastError()));
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
Logger::warn(L"WorkspacesLauncher instance is already running");
return 0;
}
std::wstring cmdLineStr{ GetCommandLineW() };
auto cmdArgs = split(cmdLineStr, L" ");
if (cmdArgs.workspaceId.empty())

View File

@@ -58,7 +58,7 @@ namespace WorkspacesLauncherUI.Models
{
Logger.LogWarning($"Icon not found on app path: {Application.ApplicationPath}. Using default icon");
IsNotFound = true;
_icon = new Icon(@"images\DefaultIcon.ico");
_icon = new Icon(@"Assets\Workspaces\DefaultIcon.ico");
}
}

View File

@@ -23,16 +23,20 @@
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>images\Workspaces.ico</ApplicationIcon>
<ApplicationIcon>..\Assets\Workspaces\Workspaces.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AssemblyName>PowerToys.WorkspacesLauncherUI</AssemblyName>
</PropertyGroup>
<ItemGroup>
<None Remove="images\DefaultIcon.ico" />
<None Remove="images\Workspaces.ico" />
<Content Include="..\Assets\**\*.*">
<Link>Assets\Workspaces\%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<COMReference Include="IWshRuntimeLibrary">
<WrapperTool>tlbimp</WrapperTool>
@@ -53,14 +57,6 @@
<EmbedInteropTypes>true</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<Content Include="images\DefaultIcon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="images\Workspaces.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 KiB

View File

@@ -2,8 +2,9 @@
#include "AppUtils.h"
#include <atlbase.h>
#include <ShlObj.h>
#include <propvarutil.h>
#include <ShlObj.h>
#include <TlHelp32.h>
#include <filesystem>
@@ -28,6 +29,8 @@ namespace Utils
constexpr const wchar_t* PowerToys = L"PowerToys.exe";
constexpr const wchar_t* PowerToysSettingsUpper = L"POWERTOYS.SETTINGS.EXE";
constexpr const wchar_t* PowerToysSettings = L"PowerToys.Settings.exe";
constexpr const wchar_t* ApplicationFrameHost = L"APPLICATIONFRAMEHOST.EXE";
constexpr const wchar_t* Exe = L".EXE";
}
AppList IterateAppsFolder()
@@ -184,11 +187,39 @@ namespace Utils
return IterateAppsFolder();
}
std::optional<AppData> GetApp(const std::wstring& appPath, const AppList& apps)
DWORD GetParentPid(DWORD pid)
{
DWORD res = 0;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(h, &pe))
{
do
{
if (pe.th32ProcessID == pid)
{
res = pe.th32ParentProcessID;
}
} while (Process32Next(h, &pe));
}
CloseHandle(h);
return res;
}
std::optional<AppData> GetApp(const std::wstring& appPath, DWORD pid, const AppList& apps)
{
std::wstring appPathUpper(appPath);
std::transform(appPathUpper.begin(), appPathUpper.end(), appPathUpper.begin(), towupper);
// filter out ApplicationFrameHost.exe
if (appPathUpper.ends_with(NonLocalizable::ApplicationFrameHost))
{
return std::nullopt;
}
// edge case, "Windows Software Development Kit" has the same app path as "File Explorer"
if (appPathUpper == NonLocalizable::FileExplorerPath)
{
@@ -217,6 +248,7 @@ namespace Utils
}
}
// search in apps list
for (const auto& appData : apps)
{
if (!appData.installPath.empty())
@@ -226,6 +258,14 @@ namespace Utils
if (appPathUpper.contains(installPathUpper))
{
// Update the install path to keep .exe in the path
if (!installPathUpper.ends_with(NonLocalizable::Exe))
{
auto settingsAppData = appData;
settingsAppData.installPath = appPath;
return settingsAppData;
}
return appData;
}
@@ -251,11 +291,43 @@ namespace Utils
if (appNameUpper == exeNameUpper)
{
return appData;
auto result = appData;
result.installPath = appPath;
return result;
}
}
// try with parent process (fix for Steam)
auto parentPid = GetParentPid(pid);
auto parentProcessPath = get_process_path(parentPid);
if (!parentProcessPath.empty())
{
std::wstring parentDirUpper = std::filesystem::path(parentProcessPath).parent_path().c_str();
std::transform(parentDirUpper.begin(), parentDirUpper.end(), parentDirUpper.begin(), towupper);
if (appPathUpper.starts_with(parentDirUpper))
{
Logger::info(L"original process is in the subfolder of the parent process");
for (const auto& appData : apps)
{
if (!appData.installPath.empty())
{
std::wstring installDirUpper = std::filesystem::path(appData.installPath).parent_path().c_str();
std::transform(installDirUpper.begin(), installDirUpper.end(), installDirUpper.begin(), towupper);
if (installDirUpper == parentDirUpper)
{
return appData;
}
}
}
}
}
return AppData{
.name = std::filesystem::path(appPath).stem(),
.installPath = appPath
};
}
@@ -263,7 +335,11 @@ namespace Utils
std::optional<AppData> GetApp(HWND window, const AppList& apps)
{
std::wstring processPath = get_process_path(window);
return Utils::Apps::GetApp(processPath, apps);
DWORD pid{};
GetWindowThreadProcessId(window, &pid);
return Utils::Apps::GetApp(processPath, pid, apps);
}
}
}

View File

@@ -19,7 +19,7 @@ namespace Utils
const std::wstring& GetCurrentFolderUpper();
AppList GetAppsList();
std::optional<AppData> GetApp(const std::wstring& appPath, const AppList& apps);
std::optional<AppData> GetApp(const std::wstring& appPath, DWORD pid, const AppList& apps);
std::optional<AppData> GetApp(HWND window, const AppList& apps);
}
}

View File

@@ -12,22 +12,12 @@
#include <workspaces-common/WindowFilter.h>
#include <WorkspacesLib/AppUtils.h>
#include <TlHelp32.h>
namespace SnapshotUtils
{
namespace NonLocalizable
{
const std::wstring ApplicationFrameHost = L"ApplicationFrameHost.exe";
namespace FileManagers
{
const std::wstring FileExplorer = L"EXPLORER"; // windows explorer
const std::wstring TotalCommander = L"TOTALCMD"; // total commander
const std::wstring DirectoryOpus = L"DOPUS"; // directory opus
const std::wstring QDir = L"Q-DIR"; // Q-Dir
const std::wstring Xplorer2 = L"XPLORER2"; // Xplorer2
}
}
class WbemHelper
@@ -178,39 +168,6 @@ namespace SnapshotUtils
return false;
}
DWORD GetParentPid(DWORD pid)
{
DWORD res = 0;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(h, &pe))
{
do
{
if (pe.th32ProcessID == pid)
{
res = pe.th32ParentProcessID;
}
} while (Process32Next(h, &pe));
}
CloseHandle(h);
return res;
}
bool IsFileManagerApp(std::wstring processPath)
{
std::wstring appName = std::filesystem::path(processPath).stem();
std::transform(appName.begin(), appName.end(), appName.begin(), towupper);
return ((appName == NonLocalizable::FileManagers::FileExplorer) // windows explorer
|| (appName.starts_with(NonLocalizable::FileManagers::TotalCommander)) // total commander
|| (appName == NonLocalizable::FileManagers::DirectoryOpus) // directory opus
|| (appName == NonLocalizable::FileManagers::QDir) // Q-Dir
|| (appName.starts_with(NonLocalizable::FileManagers::Xplorer2))); // Xplorer2
}
std::vector<WorkspacesData::WorkspacesProject::Application> GetApps(const std::function<unsigned int(HWND)> getMonitorNumberFromWindowHandle)
{
std::vector<WorkspacesData::WorkspacesProject::Application> apps{};
@@ -285,83 +242,17 @@ namespace SnapshotUtils
continue;
}
auto data = Utils::Apps::GetApp(processPath, installedApps);
auto data = Utils::Apps::GetApp(processPath, pid, installedApps);
if (!data.has_value() || data->name.empty())
{
Logger::info(L"Installed app not found: {}, try parent process", processPath);
bool standaloneApp = false;
bool steamLikeApp = false;
// try with parent process (fix for Steam)
auto parentPid = GetParentPid(pid);
auto parentProcessPath = get_process_path(parentPid);
// check if original process is in the subfolder of the parent process which is a sign of an steam-like app
std::wstring processDir = std::filesystem::path(processPath).parent_path().c_str();
std::wstring parentProcessDir = std::filesystem::path(parentProcessPath).parent_path().c_str();
if (parentProcessPath == L"")
{
if (processPath.ends_with(NonLocalizable::ApplicationFrameHost))
{
// filter out ApplicationFrameHost.exe
continue;
}
else
{
Logger::info(L"parent process unknown, the parent app is an already closed file manager app, it is a standalone app");
standaloneApp = true;
}
}
else if (processDir.starts_with(parentProcessDir))
{
Logger::info(L"parent process: {}, original process is in the subfolder of the parent process, it is a steam-like app", parentProcessPath);
steamLikeApp = true;
}
else if (IsFileManagerApp(parentProcessPath))
{
Logger::info(L"parent process: {}, The parent process is a known file manager app, it is a standalone app", parentProcessPath);
standaloneApp = true;
}
else
{
Logger::info(L"parent process: {}, The parent process is NOT a known file manager app, it is a steam-like app", parentProcessPath);
steamLikeApp = true;
}
if (standaloneApp)
{
data = Utils::Apps::AppData{
.name = std::filesystem::path(processPath).stem(),
.installPath = processPath,
};
}
else if (steamLikeApp)
{
if (!parentProcessPath.empty())
{
data = Utils::Apps::GetApp(parentProcessPath, installedApps);
if (!data.has_value() || data->name.empty())
{
Logger::info(L"Installed parent app not found: {}", processPath);
continue;
}
processPath = parentProcessPath;
}
else
{
Logger::info(L"Parent process path not found");
continue;
}
}
Logger::info(L"Installed app not found: {}", processPath);
continue;
}
WorkspacesData::WorkspacesProject::Application app{
.name = data.value().name,
.title = title,
.path = processPath,
.path = data.value().installPath,
.packageFullName = data.value().packageFullName,
.appUserModelId = data.value().appUserModelId,
.commandLineArgs = L"", // GetCommandLineArgs(pid, wbemHelper),

View File

@@ -161,19 +161,16 @@ void WindowArranger::processWindow(HWND window)
return;
}
std::wstring title = WindowUtils::GetWindowTitle(window);
if (title.empty())
{
return;
}
std::wstring processPath = get_process_path(window);
if (processPath.empty())
{
return;
}
auto data = Utils::Apps::GetApp(processPath, m_installedApps);
DWORD pid{};
GetWindowThreadProcessId(window, &pid);
auto data = Utils::Apps::GetApp(processPath, pid, m_installedApps);
if (!data.has_value())
{
return;
@@ -189,7 +186,6 @@ void WindowArranger::processWindow(HWND window)
return;
}
Logger::debug(L"Move {}", title);
iter->second.window = window;
if (moveWindow(window, iter->first))
{

View File

@@ -14,7 +14,6 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading;
using Awake.Core.Models;
using Awake.Core.Native;
using Awake.Properties;

View File

@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using ManagedCommon;
namespace Awake.Core.Threading
{
@@ -49,7 +50,7 @@ namespace Awake.Core.Threading
}
catch (Exception e)
{
Console.WriteLine("Error during execution: " + e.Message);
Logger.LogError("Error during execution of the STS context message loop: " + e.Message);
}
}
}
@@ -58,7 +59,8 @@ namespace Awake.Core.Threading
{
lock (queue)
{
queue.Enqueue(null); // Signal the end of the message loop
// Signal the end of the message loop
queue.Enqueue(null);
Monitor.Pulse(queue);
}
}

View File

@@ -15,7 +15,6 @@ using System.Reflection;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Awake.Core;
using Awake.Core.Models;
using Awake.Core.Native;

View File

@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class NewPlusProperties
{
public const string ModuleName = "NewPlus";
public NewPlusProperties()
{
HideFileExtension = new BoolProperty(true);
HideStartingDigits = new BoolProperty(true);
TemplateLocation = new StringProperty(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "PowerToys", "NewPlus", "Templates"));
}
[JsonPropertyName("HideFileExtension")]
public BoolProperty HideFileExtension { get; set; }
[JsonPropertyName("HideStartingDigits")]
public BoolProperty HideStartingDigits { get; set; }
[JsonPropertyName("TemplateLocation")]
public StringProperty TemplateLocation { get; set; }
public override string ToString() => JsonSerializer.Serialize(this);
}
}

View File

@@ -12,34 +12,27 @@ using Settings.UI.Library.Resources;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class NewPlusSettings : ISettingsConfig
public class NewPlusSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "NewPlus";
public const string ModuleVersion = "1.0";
public void InitializeWithDefaultSettings()
[JsonPropertyName("properties")]
public NewPlusProperties Properties { get; set; }
public NewPlusSettings()
{
// This code path should never happen
Name = ModuleName;
Version = ModuleVersion;
Properties = new NewPlusProperties();
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
[JsonPropertyName("HideFileExtension")]
public bool HideFileExtension { get; set; }
[JsonPropertyName("HideStartingDigits")]
public bool HideStartingDigits { get; set; }
[JsonPropertyName("TemplateLocation")]
public string TemplateLocation { get; set; }
public string GetModuleName()
{
return ModuleName;
return Name;
}
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
return false;

View File

@@ -130,7 +130,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
var settingsUtils = new SettingsUtils();
var settings = NewPlusViewModel.LoadSettings(settingsUtils);
NewPlusViewModel.CopyTemplateExamples(settings.TemplateLocation);
NewPlusViewModel.CopyTemplateExamples(settings.Properties.TemplateLocation.Value);
}
}

View File

@@ -47,9 +47,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
Settings = LoadSettings(settingsUtils);
// Initialize properties
_hideFileExtension = Settings.HideFileExtension;
_hideStartingDigits = Settings.HideStartingDigits;
_templateLocation = Settings.TemplateLocation;
_hideFileExtension = Settings.Properties.HideFileExtension.Value;
_hideStartingDigits = Settings.Properties.HideStartingDigits.Value;
_templateLocation = Settings.Properties.TemplateLocation.Value;
InitializeEnabledValue();
InitializeGpoValues();
@@ -119,12 +119,10 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
if (_templateLocation != value)
{
_templateLocation = value;
Settings.TemplateLocation = value;
Settings.Properties.TemplateLocation.Value = value;
OnPropertyChanged(nameof(TemplateLocation));
NotifySettingsChanged();
SaveSettingsToJson();
}
}
}
@@ -146,12 +144,10 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
if (_hideFileExtension != value && !_hideFileExtensionIsGPOConfigured)
{
_hideFileExtension = value;
Settings.HideFileExtension = value;
Settings.Properties.HideFileExtension.Value = value;
OnPropertyChanged(nameof(HideFileExtension));
NotifySettingsChanged();
SaveSettingsToJson();
}
}
}
@@ -168,12 +164,10 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
if (_hideStartingDigits != value)
{
_hideStartingDigits = value;
Settings.HideStartingDigits = value;
Settings.Properties.HideStartingDigits.Value = value;
OnPropertyChanged(nameof(HideStartingDigits));
NotifySettingsChanged();
SaveSettingsToJson();
}
}
}
@@ -208,10 +202,10 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
settings = settingsUtils.GetSettingsOrDefault<NewPlusSettings>(NewPlusSettings.ModuleName);
if (string.IsNullOrEmpty(settings.TemplateLocation))
if (string.IsNullOrEmpty(settings.Properties.TemplateLocation.Value))
{
// This can happen when running the DEBUG Settings application without first letting the runner create the default settings file.
settings.TemplateLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "PowerToys", "NewPlus", "Templates");
settings.Properties.TemplateLocation.Value = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "PowerToys", "NewPlus", "Templates");
}
}
catch (Exception e)
@@ -256,12 +250,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private void OpenNewTemplateFolder()
{
var process = new ProcessStartInfo()
try
{
FileName = _templateLocation,
UseShellExecute = true,
};
Process.Start(process);
CopyTemplateExamples(_templateLocation);
var process = new ProcessStartInfo()
{
FileName = _templateLocation,
UseShellExecute = true,
};
Process.Start(process);
}
catch (Exception ex)
{
Logger.LogError("Failed to show NewPlus template folder.", ex);
}
}
private async void PickNewTemplateFolder()
@@ -278,10 +281,5 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.GetSettingsWindow());
return await Task.FromResult(GetFolderDialogWithFlags(hwnd, FolderDialogFlags._BIF_NEWDIALOGSTYLE));
}
private void SaveSettingsToJson()
{
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
}
}