mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 19:57:57 +01:00
resolved merge conflicts and validated that it works as expected
This commit is contained in:
@@ -41,7 +41,7 @@ restore:
|
||||
|
||||
build:
|
||||
commands:
|
||||
# Localize the files after the build procedure to avoid existing localized files from getting overwritten. To be moved before the Build PowerToys step once the lcl files have been checked in. Tracked at https://github.com/microsoft/PowerToys/issues/6046
|
||||
# Localize the files before the Build PowerToys step to generate translated resx files from the lcl files
|
||||
- !!buildcommand
|
||||
name: 'Localize Power Toys'
|
||||
command: '.pipelines\build-localization.cmd'
|
||||
|
||||
173
doc/devdocs/localization.md
Normal file
173
doc/devdocs/localization.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Localization
|
||||
|
||||
## Table of Contents
|
||||
1. [Localization on the pipeline (CDPX)](#localization-on-the-pipeline-cdpx)
|
||||
1. [UWP Special case](#uwp-special-case)
|
||||
2. [Enabling localization on a new project](#enabling-localization-on-a-new-project)
|
||||
1. [C++](#c)
|
||||
2. [C#](#c-1)
|
||||
3. [UWP](#uwp)
|
||||
3. [Lcl Files](#lcl-files)
|
||||
4. [Possible Issues in localization PRs (LEGO)](#possible-issues-in-localization-prs-lego)
|
||||
5. [Enabling localized MSI for a new project](#enabling-localized-msi-for-a-new-project)
|
||||
|
||||
## Localization on the pipeline (CDPX)
|
||||
[The localization step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L45-L52) is run on the pipeline before the solution is built. This step runs the [build-localization](https://github.com/microsoft/PowerToys/blob/master/.pipelines/build-localization.cmd) script, which generates resx files for all the projects with localization enabled using the `Localization.XLoc` package.
|
||||
|
||||
The [`Localization.XLoc`](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L24-L25) tool is run on the repo root, and it checks for all occurrences of `LocProject.json`. Each localized project has a `LocProject.json` file in the project root, which contains the location of the English resx file, list of languages for localization, and the output path where the localized resx files are to be copied to. In addition to this, some other parameters can be set, such as whether the language ID should be added as a folder in the file path or in the file name. When the CDPX pipeline is run, the localization team is notified of changes in the English resx files. For each project with localization enabled, a `loc` folder (see [this](https://github.com/microsoft/PowerToys/tree/master/src/modules/launcher/Microsoft.Launcher/loc) for example) is created in the same directory as the `LocProject.json` file. The folder contains language specific folders which in turn have a nested folder path equivalent to `OutputPath` in the `LocProject.json`. Each of these folders contain one `lcl` file. The `lcl` files contain the English resources along with their translation for that language. These are described in more detail [here](#lcl-files). Once the `.resx` files are generated, they will be used during the `Build PowerToys` step for localized versions of the modules.
|
||||
|
||||
Since the localization script requires certain nuget packages, the [`restore-localization`](https://github.com/microsoft/PowerToys/blob/master/.pipelines/restore-localization.cmd) script is run before running `build-localization` to install all the required packages. This script must [run in the `restore` step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L37-L39) of pipeline because [the host is network isolated](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipelinhttps://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipeline?anchor=overview) at the `build` step. The [Toolset package source](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L23) is used for this.
|
||||
|
||||
The process and variables that can be tweaked on the pipeline are described in more detail [here](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/290/Localization).
|
||||
|
||||
The localized resource dlls for C# projects are added to the MSI only for build on the pipeline. This is done by checking if the [`IsPipeline` variable is defined](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L804-L805), which gets defined before building the installer on the pipeline [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/build-installer.cmd#L4). This is done because the localized resx files are only present on the pipeline, and not having this check would result in the installer project failing to build locally.
|
||||
|
||||
### UWP Special case
|
||||
C# projects normally expect localized resource files with the language id in the file name as Resources.`langId`.resx, where `langId` is generally a two character code except for language with specific variants (like zh-Hans or pt-BR):
|
||||
|
||||
For example, `path\Resources.resx` for English and `path\Resources.fr.resx` for French.
|
||||
|
||||
UWP differs from this as it expects the resources to have the same Resources.resw file name, but they should be present in language specific folders, with the full language ID (such as fr-fr, zh-hans, pt-br, etc.)
|
||||
|
||||
For example, `path\en-us\Resources.resw` for English and `path\fr-fr\Resources.resw` for French.
|
||||
|
||||
Since the pipeline generates it in this format, [a script is run](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L29-L31) to move these resw files to the correct format expected by all UWP projects. Currently the only UWP project is [Microsoft.PowerToys.Settings.UI](https://github.com/microsoft/PowerToys/tree/master/src/core/Microsoft.PowerToys.Settings.UI). The script used for moving the resources can be [found here](https://github.com/microsoft/PowerToys/blob/master/tools/localization/move_uwp_resources.ps1). The equivalent full language IDs for each shortened language ID obtained from the pipeline has been hardcoded in the script.
|
||||
|
||||
## Enabling localization on a new project
|
||||
To enable localization on a new project, the first step is to create a file `LocProject.json` in the project root.
|
||||
|
||||
For example, for a project in the folder `src\path` where the resx file is present in `resources\Resources.resx`, the LocProject.json file will contain the following:
|
||||
```
|
||||
{
|
||||
"Projects": [
|
||||
{
|
||||
"LanguageSet": "Azure_Languages",
|
||||
"LocItems": [
|
||||
{
|
||||
"SourceFile": "src\\path\\resources\\Resources.resx",
|
||||
"CopyOption": "LangIDOnName",
|
||||
"OutputPath": "src\\path\\resources"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
The rest of the steps depend on the project type and are covered in the sections below. The steps to add the localized files to the MSI can be found [here](#Enabling-localized-MSI-for-a-new-project).
|
||||
|
||||
### C++
|
||||
C++ projects do not support `resx` files, and instead use `rc` files along with `resource.h` files. The CDPX pipeline however doesn't support localizing `rc` files and the other alternative they support is directly translating the resources from the binary which makes it harder to maintain resources. To avoid this, a custom script has been added which expects a resx file and converts the entries to an rc file with a string table and adds resource declarations to a resource.h file so that the resources can be compiled with the C++ project.
|
||||
|
||||
If you already have a .rc file, copy the string table to a separate txt file and run the [convert-stringtable-to-resx.ps1](https://github.com/microsoft/PowerToys/blob/master/tools/build/convert-stringtable-to-resx.ps1) script on it. This script is not very robust to input, and requires the data in a specific format, where `IDS_ResName L"ResourceValue"` and any number of spaces can be present in between. The script converts this file to the format expected by [`resgen`](https://docs.microsoft.com/en-us/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert), which will convert it to resx. The resource names are changed from all uppercase to title case, and the `IDS_` prefix is removed. Escape characters might have to be manually replaced, for example .rc files would have escaped double quotes as `""`, so this should be replaced with just `"` before converting to the resx files.
|
||||
|
||||
After generating the resx file, rename the existing rc and h files to ProjName.base.rc and resource.base.h. In the rc file remove the string table which is to be localized and in the .h file remove all `#define`s corresponding to localized resources. In the vcxproj of the C++ project, add the following build event:
|
||||
```
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 . resource.base.h resource.h ProjName.base.rc ProjName.rc" />
|
||||
</Target>
|
||||
```
|
||||
|
||||
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script can be found [here](https://github.com/microsoft/PowerToys/blob/master/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://docs.microsoft.com/en-us/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in upper case (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
|
||||
```
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
strings
|
||||
END
|
||||
|
||||
#endif
|
||||
```
|
||||
Since there is no API to identify the `AFX_TARG_*`, `LANG_*` or `SUBLANG_*` values from each langId from the pipeline, these are hardcoded in the script (for each language) as done [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/tools/build/convert-resx-to-rc.ps1#L50-L77). **If any other languages are added in the future, this script will have to be updated.** In order to determine what are the language codes, you can open the rc file in Resource View, right click the string table and press `Insert Copy` and choose the corresponding language. This autogenerates the required code and can be used to figure out the language codes. The files also add the resource declarations to a resource.h file, starting from 101 by default(this can be changed by an optional argument). Since the output files will be generated in `Generated Files`, any includes in these two files will require an additional `..\` and wherever resource.h is used, it will have to be included as `Generated Files\resource.h`. While adding `resource.base.h` and `ProjName.base.rc` to the vcxproj, these should be modified to not participate in the build to avoid build errors:
|
||||
```
|
||||
<None Include="Resources.resx" />
|
||||
```
|
||||
|
||||
Some rc/resource.h files might be used in multiple projects (for example, KBM). To ensure the projects build for these cases, the build event can be added to the entire directory so that the rc files are generated before any project is built. See [Directory.Build.targets](https://github.com/microsoft/PowerToys/blob/master/src/modules/keyboardmanager/Directory.Build.targets) for an example.
|
||||
|
||||
Check [this PR](https://github.com/microsoft/PowerToys/pull/6104) for an example for making these changes for a C++ project.
|
||||
|
||||
### C#
|
||||
Since C# projects natively support `resx` files, the only step required here is to include all the resx files in the build. For .NET Core projects this is done automatically and the .csproj does not need to be modified. For other projects, the following line needs to be added:
|
||||
```
|
||||
<EmbeddedResource Include="Properties\Resources.*.resx" />
|
||||
```
|
||||
|
||||
**Note:** Building with localized resources may cause a build warning `Referenced assembly 'mscorlib.dll' targets a different processor` which is a VS bug. More details can be found [here](https://github.com/microsoft/PowerToys/issues/7269).
|
||||
|
||||
**Note:** If a project needs to be migrated from XAML resources to resx, the easiest way to convert the resources would be to change to format to `=` separates resources by either manually (by Ctrl+H on a text editor), or by a script, and then running [`resgen`](https://docs.microsoft.com/en-us/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) on `Developer Command Prompt for VS` to convert it to resx format.
|
||||
```
|
||||
<system:String x:Key="wox_plugin_calculator_plugin_name">Calculator</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Wox)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
|
||||
```
|
||||
to
|
||||
```
|
||||
wox_plugin_calculator_plugin_name=Calculator
|
||||
wox_plugin_calculator_plugin_description=Allows to do mathematical calculations.(Try 5*3-2 in Wox)
|
||||
wox_plugin_calculator_not_a_number=Not a number (NaN)
|
||||
```
|
||||
After adding the resx file to the project along with the resource generator, references to the strings will have to be replaced with `Properties.Resources.resName` rather than the custom APIs. Check [this PR](https://github.com/microsoft/PowerToys/pull/6165) for an example of the changes required.
|
||||
|
||||
### UWP
|
||||
UWP projects expect `resw` files rather than `resx` (the format is almost the same). Unlike other C# projects, the files are expected in the format `fullLangId\Resources.resw`. To include these files in the build, replace the following line in the csproj:
|
||||
```
|
||||
<PRIResource Include="Strings\en-us\Resources.resw" />
|
||||
```
|
||||
to
|
||||
```
|
||||
<PRIResource Include="Strings\*\Resources.resw" />
|
||||
```
|
||||
|
||||
## Lcl Files
|
||||
Lcl files contain all the resources that are present in the English resx file, along with a translation if it has been added.
|
||||
|
||||
For example, an entry for a resource in the lcl file looks like this:
|
||||
```
|
||||
<Item ItemId=";EditKeyboard_WindowName" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Remap keys]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Remapper des touches]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
```
|
||||
The `<Tgt>` element would not be present in the initial commits of the lcl files, as only the English version of the string would be present.
|
||||
|
||||
**Note:** The CDPX Localization system has a fail-safe check on the lcl files, where if the English string value which is present inside `<Val><![CDATA[*]]></Val>` does not match the value present in the English Resources.resx file then the translated value will not be copied to the localized resx file. This is present so that obsolete translations would not be loaded when the English resource has changed, and the English string will be used rather than the obsolete translation.
|
||||
|
||||
## Possible Issues in localization PRs (LEGO)
|
||||
Since the LEGO PRs update some of the strings in LCL files at a time, there can be multiple PRs which modify the same files, leading to merge conflicts. In most cases this would show up on GitHub as a merge conflict, but sometimes a bad git merge may occur, and the file could end up with incorrect formatting, such as two `<Tgt>` elements for a single resource. These can be fixed by ensuring the elements follow the format described in [this section](#lcl-files). To catch such errors, the build farm should be run for every LEGO PR and if any error occurs in the localization step, we should check the corresponding resx/lcl files for conflicts.
|
||||
|
||||
## Enabling localized MSI for a new project
|
||||
For C++ and UWP projects no additional files are generated with localization that need to be added to the MSI. For C++ projects all the resources are added to the dll/exe, while for UWP projects they are added to the `resources.pri` file (which is present even for an unlocalized project). To verify if the localized resources are added to the `resources.pri` file the following steps can be done:
|
||||
- Open `Developer Command Prompt for VS`
|
||||
- After navigating to the folder containing the pri file, run the following command:
|
||||
|
||||
makepri.exe dump /if .\resources.pri
|
||||
- Check the contents of the `resources.pri.xml` file that is generated from the command. The last section of the file will contain the resources with the strings in all the languages:
|
||||
```
|
||||
<NamedResource name="GeneralSettings_RunningAsAdminText" uri="ms-resource://f4f787a5-f0ae-47a9-be89-5408b1dd2b47/Resources/GeneralSettings_RunningAsAdminText">
|
||||
<Candidate qualifiers="Language-FR" type="String">
|
||||
<Value>Running as administrator</Value>
|
||||
</Candidate>
|
||||
<Candidate qualifiers="Language-EN-US" isDefault="true" type="String">
|
||||
<Value>Running as administrator</Value>
|
||||
</Candidate>
|
||||
</NamedResource>
|
||||
```
|
||||
|
||||
For C# projects, satellite dlls are generated when the project is built. For a project named `ProjName`, files are created in the format `langId\ProjName.resources.dll` where `langId` is in the same format as the lcl files. The satellite dlls need to be included with the MSI, but they must be added only if the solution is built from the build farm, as the localized resx files will not be present on local machines (and that could cause local builds of the installer to fail).
|
||||
This can be done by adding the directory name of the project [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L806) and a resource component for the project can be created [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L845-L847) in this format:
|
||||
```
|
||||
<Component Id="ProjName_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)ProjNameInstallFolder">
|
||||
<File Id="ProjName_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\ProjName\$(var.Language)\ProjName.resources.dll" />
|
||||
</Component>
|
||||
```
|
||||
|
||||
We should also ensure the new dlls are signed by the pipeline. Currently all dlls of the form [`*.resources.dll` are signed](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/pipeline.user.windows.yml#L68).
|
||||
|
||||
**Note:** The resource dlls should be added to the MSI project only after the initial commit with the lcl files has been done by the Localization team. Otherwise the pipeline will fail as there wouldn't be any resx files to generate the dlls.
|
||||
5
doc/images/icons/FancyZones_MDL2.svg
Normal file
5
doc/images/icons/FancyZones_MDL2.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48" viewBox="0 0 48 48">
|
||||
<g>
|
||||
<path d="M45,48H25.5V45H45V25.5H25.5v-3H45V3H25.5V0H48V48ZM22.5,48H3V45H22.5V3H3V0H25.5V48ZM0,48V0H3V48Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 258 B |
@@ -70,24 +70,33 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
if (SettingsExists(powertoy, fileName))
|
||||
{
|
||||
// Given the file already exists, to deserialize the file and read it's content.
|
||||
T deserializedSettings = GetFile<T>(powertoy, fileName);
|
||||
|
||||
// IF the file needs to be modified, to save the new configurations accordingly.
|
||||
if (deserializedSettings.UpgradeSettingsConfiguration())
|
||||
try
|
||||
{
|
||||
SaveSettings(deserializedSettings.ToJsonString(), powertoy, fileName);
|
||||
// Given the file already exists, to deserialize the file and read it's content.
|
||||
T deserializedSettings = GetFile<T>(powertoy, fileName);
|
||||
|
||||
// If the file needs to be modified, to save the new configurations accordingly.
|
||||
if (deserializedSettings.UpgradeSettingsConfiguration())
|
||||
{
|
||||
SaveSettings(deserializedSettings.ToJsonString(), powertoy, fileName);
|
||||
}
|
||||
|
||||
return deserializedSettings;
|
||||
}
|
||||
|
||||
return deserializedSettings;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the settings file does not exist, to create a new object with default parameters and save it to a newly created settings file.
|
||||
T newSettingsItem = new T();
|
||||
SaveSettings(newSettingsItem.ToJsonString(), powertoy, fileName);
|
||||
return newSettingsItem;
|
||||
// Catch json deserialization exceptions when the file is corrupt and has an invalid json.
|
||||
// If there are any deserialization issues like in https://github.com/microsoft/PowerToys/issues/7500, log the error and create a new settings.json file.
|
||||
// This is different from the case where we have trailing zeros following a valid json file, which we have handled by trimming the trailing zeros.
|
||||
catch (JsonException ex)
|
||||
{
|
||||
Logger.LogError($"Exception encountered while loading {powertoy} settings.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// If the settings file does not exist or if the file is corrupt, to create a new object with default parameters and save it to a newly created settings file.
|
||||
T newSettingsItem = new T();
|
||||
SaveSettings(newSettingsItem.ToJsonString(), powertoy, fileName);
|
||||
return newSettingsItem;
|
||||
}
|
||||
|
||||
// Given the powerToy folder name and filename to be accessed, this function deserializes and returns the file.
|
||||
|
||||
@@ -32,6 +32,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
|
||||
Log(message, "INFO");
|
||||
}
|
||||
|
||||
public static void LogError(string message)
|
||||
{
|
||||
Log(message, "ERROR");
|
||||
#if DEBUG
|
||||
Debugger.Break();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void LogError(string message, Exception e)
|
||||
{
|
||||
Log(
|
||||
@@ -42,6 +50,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
|
||||
"Stack trace: " + Environment.NewLine +
|
||||
e?.StackTrace,
|
||||
"ERROR");
|
||||
#if DEBUG
|
||||
Debugger.Break();
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void Log(string message, string type)
|
||||
|
||||
@@ -86,6 +86,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
private bool _keepDateModified;
|
||||
private int _encoderGuidId;
|
||||
|
||||
public bool IsListViewFocusRequested { get; set; }
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get
|
||||
@@ -257,6 +259,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
imageSizes.Add(newSize);
|
||||
_advancedSizes = imageSizes;
|
||||
SavesImageSizes(imageSizes);
|
||||
|
||||
// Set the focus requested flag to indicate that an add operation has occurred during the ContainerContentChanging event
|
||||
IsListViewFocusRequested = true;
|
||||
}
|
||||
|
||||
public void DeleteImageSize(int id)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using Microsoft.PowerLauncher.Telemetry;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.Toolkit.Wpf.UI.XamlHost;
|
||||
@@ -67,16 +68,17 @@ namespace Microsoft.PowerToys.Settings.UI.Runner
|
||||
{
|
||||
if (ShellPage.ShellHandler.IPCResponseHandleList != null)
|
||||
{
|
||||
try
|
||||
var success = JsonObject.TryParse(msg, out JsonObject json);
|
||||
if (success)
|
||||
{
|
||||
JsonObject json = JsonObject.Parse(msg);
|
||||
foreach (Action<JsonObject> handle in ShellPage.ShellHandler.IPCResponseHandleList)
|
||||
{
|
||||
handle(json);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
else
|
||||
{
|
||||
Logger.LogError("Failed to parse JSON from IPC message.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,6 +69,11 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VCRTForwarders.140" Version="1.0.6" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
|
||||
<Version>3.3.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -13,7 +13,7 @@ using Windows.UI.Popups;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Runner
|
||||
{
|
||||
public class Program
|
||||
public static class Program
|
||||
{
|
||||
// Quantity of arguments
|
||||
private const int ArgumentsQty = 5;
|
||||
@@ -37,9 +37,9 @@ namespace Microsoft.PowerToys.Settings.UI.Runner
|
||||
App app = new App();
|
||||
app.InitializeComponent();
|
||||
|
||||
if (args.Length >= ArgumentsQty)
|
||||
if (args != null && args.Length >= ArgumentsQty)
|
||||
{
|
||||
int.TryParse(args[2], out int powerToysPID);
|
||||
_ = int.TryParse(args[2], out int powerToysPID);
|
||||
PowerToysPID = powerToysPID;
|
||||
|
||||
if (args[4] == "true")
|
||||
|
||||
@@ -6,36 +6,25 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
AutomationProperties.Name="{x:Bind Header, Mode=OneTime}"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBox x:Name="HotkeyTextBox"
|
||||
x:Uid="SettingsPage_SetShortcut"
|
||||
AutomationProperties.HelpText="{Binding ElementName=ShortcutWarningLabelText, Path=Text}"
|
||||
IsReadOnly="True">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Uid="ShortcutWarningLabel"/>
|
||||
<TextBlock Text="{x:Bind Keys, Mode=OneTime}" FontWeight="SemiBold"/>
|
||||
</StackPanel>
|
||||
</ToolTip>
|
||||
<TextBlock x:Name="ShortcutWarningLabelText">
|
||||
<Run x:Uid="ShortcutWarningLabel"/>
|
||||
<LineBreak/>
|
||||
<Run Text="{x:Bind Keys, Mode=OneTime}" FontWeight="SemiBold"/>
|
||||
</TextBlock>
|
||||
</ToolTipService.ToolTip>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Name="TitleText"
|
||||
Text="{x:Bind Header, Mode=OneTime}"
|
||||
Foreground="{Binding Path=IsEnabled, ElementName=HotkeyTextBox, Converter={StaticResource ModuleEnabledToForegroundConverter}}"
|
||||
/>
|
||||
|
||||
<TextBlock x:Uid="SettingsPage_SetShortcut_Glyph"
|
||||
x:Name="TitleGlyph" Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Margin="4,4,0,0"
|
||||
Foreground="{Binding Path=IsEnabled, ElementName=HotkeyTextBox, Converter={StaticResource ModuleEnabledToForegroundConverter}}"
|
||||
/>
|
||||
|
||||
</StackPanel>
|
||||
<TextBox x:Uid="SettingsPage_SetShortcut"
|
||||
x:Name="HotkeyTextBox"
|
||||
Margin="0,5,0,0"
|
||||
IsReadOnly="True"
|
||||
/>
|
||||
</StackPanel>
|
||||
<TextBox.Header>
|
||||
<TextBlock>
|
||||
<Run Text="{x:Bind Header, Mode=OneTime}"/>
|
||||
<Run Text="" FontFamily="Segoe MDL2 Assets"/>
|
||||
</TextBlock>
|
||||
</TextBox.Header>
|
||||
</TextBox>
|
||||
</UserControl>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -62,10 +62,10 @@
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=FancyZones_LaunchEditorButtonControl}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Height="12" Width="12">
|
||||
<PathIcon Data="M896 0v896H0V0h896zM768 768V128H128v640h640zM0 1920v-896h1920v896H0zm128-768v640h1664v-640H128zM1024 0h896v896h-896V0zm768 768V128h-640v640h640z"/>
|
||||
<Viewbox Height="14" Width="14" Margin="-1,1,0,0">
|
||||
<PathIcon Data="M45,48H25.5V45H45V25.5H25.5v-3H45V3H25.5V0H48V48ZM22.5,48H3V45H22.5V3H3V0H25.5V48ZM0,48V0H3V48Z"/>
|
||||
</Viewbox>
|
||||
<TextBlock Margin="12,0,0,0"
|
||||
<TextBlock Margin="8,0,0,0"
|
||||
Name="FancyZones_LaunchEditorButtonControl"
|
||||
x:Uid="FancyZones_LaunchEditorButtonControl"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -89,21 +89,19 @@
|
||||
|
||||
<!-- Replaced the Radiobuttons parent control with a StackPanel to mitigate the Tab and Arrow key related keyboard navigation issues due to XAML Islands
|
||||
Tracking issue in the winui repository - https://github.com/microsoft/microsoft-ui-xaml/issues/3156 -->
|
||||
<TextBlock Name="RadioButtons_Name_Theme"
|
||||
x:Uid="RadioButtons_Name_Theme"
|
||||
<TextBlock x:Name="RadioButtons_Name_Theme"
|
||||
x:Uid="ColorModeHeader"
|
||||
Margin="{StaticResource SmallTopMargin}"/>
|
||||
<StackPanel AutomationProperties.LabeledBy="{Binding ElementName=RadioButtons_Name_Theme}">
|
||||
<RadioButton x:Uid="GeneralPage_Radio_Theme_Dark"
|
||||
Content="Dark"
|
||||
<RadioButton x:Uid="Radio_Theme_Dark"
|
||||
IsChecked="{ Binding Mode=TwoWay, Path=IsDarkThemeRadioButtonChecked}"/>
|
||||
|
||||
<RadioButton x:Uid="GeneralPage_Radio_Theme_Light"
|
||||
Content="Light"
|
||||
<RadioButton x:Uid="Radio_Theme_Light"
|
||||
IsChecked="{ Binding Mode=TwoWay, Path=IsLightThemeRadioButtonChecked}"/>
|
||||
|
||||
<RadioButton x:Uid="GeneralPage_Radio_Theme_Default"
|
||||
Content="System default"
|
||||
<RadioButton x:Uid="Radio_Theme_Default"
|
||||
IsChecked="{ Binding Mode=TwoWay, Path=IsSystemThemeRadioButtonChecked}"/>
|
||||
<HyperlinkButton x:Uid="Windows_Color_Settings" NavigateUri="ms-settings:colors"/>
|
||||
</StackPanel>
|
||||
|
||||
<ToggleSwitch x:Uid="GeneralPage_ToggleSwitch_RunAtStartUp"
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
SelectionMode="None"
|
||||
ScrollViewer.HorizontalScrollMode="Enabled"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.IsHorizontalRailEnabled="True">
|
||||
ScrollViewer.IsHorizontalRailEnabled="True"
|
||||
ContainerContentChanging="ImagesSizesListView_ContainerContentChanging">
|
||||
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
@@ -277,7 +278,9 @@
|
||||
x:Uid="ImageResizer_FilenameFormatPlaceholder"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=ImageResizer_FilenameFormatHeader}">
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=ImageResizer_FilenameFormatHeader}"
|
||||
AutomationProperties.HelpText="{Binding ElementName=FileFormatTextBlock, Path=Text}"
|
||||
>
|
||||
<TextBox.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Name="ImageResizer_FilenameFormatHeader"
|
||||
@@ -290,44 +293,34 @@
|
||||
</StackPanel>
|
||||
</TextBox.Header>
|
||||
<ToolTipService.ToolTip>
|
||||
<StackPanel>
|
||||
<TextBlock x:Uid="ImageResizer_FileFormatDescription"/>
|
||||
<TextBlock Margin="{StaticResource SmallTopMargin}">
|
||||
<Run Text="%1" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Filename" />
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%2" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Sizename"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%3" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedWidth"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%4" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedHeight"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%5" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualWidth"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%6" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualHeight"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<TextBlock x:Name="FileFormatTextBlock">
|
||||
<Run x:Uid="ImageResizer_FileFormatDescription"/>
|
||||
<LineBreak/>
|
||||
<LineBreak/>
|
||||
<Run Text="%1" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Filename" />
|
||||
<LineBreak/>
|
||||
<Run Text="%2" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Sizename"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%3" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedWidth"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%4" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedHeight"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%5" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualWidth"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%6" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualHeight"/>
|
||||
</TextBlock>
|
||||
</ToolTipService.ToolTip>
|
||||
</TextBox>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// 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.Linq;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
|
||||
@@ -45,5 +46,18 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void ImagesSizesListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
|
||||
{
|
||||
if (ViewModel.IsListViewFocusRequested)
|
||||
{
|
||||
// Set focus to the last item in the ListView
|
||||
int size = ImagesSizesListView.Items.Count;
|
||||
((ListViewItem)ImagesSizesListView.ContainerFromIndex(size - 1)).Focus(FocusState.Programmatic);
|
||||
|
||||
// Reset the focus requested flag
|
||||
ViewModel.IsListViewFocusRequested = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,19 +146,28 @@
|
||||
<TextBlock x:Uid="Appearance_GroupSettings"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher, Converter={StaticResource ModuleEnabledToForegroundConverter}}" />
|
||||
<TextBlock x:Uid="PowerLauncher_Theme"
|
||||
|
||||
<!-- We cannot navigate to all the radio buttons using the arrow keys because of an XYNavigation issue in the RadioButtons control.
|
||||
The screen reader does not read the heading when we tab into a radio button, even though the LabeledBy automation property is set.
|
||||
Link to the issue in the winui repository - https://github.com/microsoft/microsoft-ui-xaml/issues/3156 -->
|
||||
<TextBlock x:Uid="ColorModeHeader"
|
||||
x:Name="RadioButtons_Name_Theme"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher, Converter={StaticResource ModuleEnabledToForegroundConverter}}" />
|
||||
<muxc:RadioButtons IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}">
|
||||
<RadioButton x:Uid="PowerLauncher_Radio_Theme_Dark"
|
||||
<StackPanel AutomationProperties.LabeledBy="{Binding ElementName=RadioButtons_Name_Theme}">
|
||||
<RadioButton x:Uid="Radio_Theme_Dark"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}"
|
||||
IsChecked="{Binding Mode=TwoWay, Path=IsDarkThemeRadioButtonChecked}" />
|
||||
|
||||
<RadioButton x:Uid="PowerLauncher_Radio_Theme_Light"
|
||||
<RadioButton x:Uid="Radio_Theme_Light"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}"
|
||||
IsChecked="{Binding Mode=TwoWay, Path=IsLightThemeRadioButtonChecked}" />
|
||||
|
||||
<RadioButton x:Uid="PowerLauncher_Radio_Theme_Default"
|
||||
<RadioButton x:Uid="Radio_Theme_Default"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}"
|
||||
IsChecked="{Binding Mode=TwoWay, Path=IsSystemThemeRadioButtonChecked}" />
|
||||
</muxc:RadioButtons>
|
||||
<HyperlinkButton x:Uid="Windows_Color_Settings" NavigateUri="ms-settings:colors"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<RelativePanel x:Name="SidePanel"
|
||||
|
||||
@@ -41,10 +41,9 @@
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_FancyZones" helpers:NavHelper.NavigateTo="views:FancyZonesPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<PathIcon Data="M896 0v896H0V0h896zM768 768V128H128v640h640zM0 1920v-896h1920v896H0zm128-768v640h1664v-640H128zM1024 0h896v896h-896V0zm768 768V128h-640v640h640z"></PathIcon>
|
||||
<PathIcon Data="M45,48H25.5V45H45V25.5H25.5v-3H45V3H25.5V0H48V48ZM22.5,48H3V45H22.5V3H3V0H25.5V48ZM0,48V0H3V48Z"/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
@@ -54,35 +53,30 @@
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_ImageResizer" helpers:NavHelper.NavigateTo="views:ImageResizerPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<PathIcon Data="M0 768h1408v1152H0V768zm128 1024h870l-582-581-288 288v293zm1152 0v-102l-224-223-101 101 223 224h102zM128 896v421l288-287 448 447 192-191 224 224V896H128zm832 256q-26 0-45-19t-19-45q0-26 19-45t45-19q26 0 45 19t19 45q0 26-19 45t-45 19zm960-512V347l-339 338-90-90 338-339h-293V128h512v512h-128zm-768-512h256v128h-256V128zm-128 128H768V128h256v128zm-384 0H384V128h256v128zm-384 0H0V128h256v128zM128 640H0V384h128v256zm1920 128v256h-128V768h128zm-128 384h128v256h-128v-256zm0 384h128v256h-128v-256zm-384 256h256v128h-256v-128z"></PathIcon>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_KeyboardManager" helpers:NavHelper.NavigateTo="views:KeyboardManagerPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_PowerRename" helpers:NavHelper.NavigateTo="views:PowerRenamePage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_PowerLauncher" helpers:NavHelper.NavigateTo="views:PowerLauncherPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_ShortcutGuide" helpers:NavHelper.NavigateTo="views:ShortcutGuidePage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
@@ -94,7 +88,6 @@
|
||||
DefaultHeader="{x:Bind ViewModel.Selected.Content, Mode=OneWay}">
|
||||
<behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
|
||||
<DataTemplate>
|
||||
<!-- TODO: Style clean up-->
|
||||
<Grid Margin="0, -2, 0, 6">
|
||||
<TextBlock
|
||||
Text="{Binding}"
|
||||
|
||||
@@ -90,17 +90,18 @@
|
||||
The screen reader does not read the heading when we tab into a radio button, even though the LabeledBy automation property is set.
|
||||
Link to the issue in the winui repository - https://github.com/microsoft/microsoft-ui-xaml/issues/3156 -->
|
||||
<TextBlock Name="ShortcutGuide_Theme"
|
||||
x:Uid="ShortcutGuide_Theme"
|
||||
x:Uid="ColorModeHeader"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
||||
<muxc:RadioButtons IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
|
||||
SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.ThemeIndex}"
|
||||
Margin="{StaticResource XXSmallTopMargin}"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=ShortcutGuide_Theme}">
|
||||
<RadioButton x:Uid="GeneralPage_Radio_Theme_Dark" />
|
||||
<RadioButton x:Uid="GeneralPage_Radio_Theme_Light" />
|
||||
<RadioButton x:Uid="GeneralPage_Radio_Theme_Default"/>
|
||||
<RadioButton x:Uid="Radio_Theme_Dark" />
|
||||
<RadioButton x:Uid="Radio_Theme_Light" />
|
||||
<RadioButton x:Uid="Radio_Theme_Default"/>
|
||||
</muxc:RadioButtons>
|
||||
<HyperlinkButton x:Uid="Windows_Color_Settings" NavigateUri="ms-settings:colors"/>
|
||||
</StackPanel>
|
||||
|
||||
<RelativePanel x:Name="SidePanel"
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace ColorPicker.Mouse
|
||||
private readonly IUserSettings _userSettings;
|
||||
private System.Windows.Point _previousMousePosition = new System.Windows.Point(-1, 1);
|
||||
private Color _previousColor = Color.Transparent;
|
||||
private bool _colorFormatChanged;
|
||||
|
||||
[ImportingConstructor]
|
||||
public MouseInfoProvider(AppStateHandler appStateMonitor, IUserSettings userSettings)
|
||||
@@ -40,6 +41,7 @@ namespace ColorPicker.Mouse
|
||||
|
||||
_mouseHook = new MouseHook();
|
||||
_userSettings = userSettings;
|
||||
_userSettings.CopiedColorRepresentation.PropertyChanged += CopiedColorRepresentation_PropertyChanged;
|
||||
}
|
||||
|
||||
public event EventHandler<Color> MouseColorChanged;
|
||||
@@ -73,9 +75,10 @@ namespace ColorPicker.Mouse
|
||||
}
|
||||
|
||||
var color = GetPixelColor(mousePosition);
|
||||
if (_previousColor != color)
|
||||
if (_previousColor != color || _colorFormatChanged)
|
||||
{
|
||||
_previousColor = color;
|
||||
_colorFormatChanged = false;
|
||||
MouseColorChanged?.Invoke(this, color);
|
||||
}
|
||||
}
|
||||
@@ -137,6 +140,11 @@ namespace ColorPicker.Mouse
|
||||
OnMouseDown?.Invoke(this, p);
|
||||
}
|
||||
|
||||
private void CopiedColorRepresentation_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
_colorFormatChanged = true;
|
||||
}
|
||||
|
||||
private void DisposeHook()
|
||||
{
|
||||
if (_timer.IsEnabled)
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Canvas_Layout_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Canvas layout editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Layout-Editor für Canvas]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Choose_Layout" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Choose your layout for this desktop]]></Val>
|
||||
@@ -118,6 +127,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Fancy_Zones_Main_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[FancyZones main editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[FancyZones-Haupteditor]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Name" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Name]]></Val>
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Canvas_Layout_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Canvas layout editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Editor de diseño de lienzo]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Choose_Layout" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Choose your layout for this desktop]]></Val>
|
||||
@@ -118,6 +127,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Fancy_Zones_Main_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[FancyZones main editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Editor principal de FancyZones]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Name" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Name]]></Val>
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Canvas_Layout_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Canvas layout editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Éditeur de disposition de canevas]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Choose_Layout" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Choose your layout for this desktop]]></Val>
|
||||
@@ -118,6 +127,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Fancy_Zones_Main_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[FancyZones main editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Éditeur principal de FancyZones]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Name" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Name]]></Val>
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Canvas_Layout_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Canvas layout editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Editor voor canvasindeling]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Choose_Layout" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Choose your layout for this desktop]]></Val>
|
||||
@@ -118,6 +127,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Fancy_Zones_Main_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[FancyZones main editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[FancyZones-hoofdeditor]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Name" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Name]]></Val>
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Canvas_Layout_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Canvas layout editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Editor de layout de tela]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Choose_Layout" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Choose your layout for this desktop]]></Val>
|
||||
@@ -118,6 +127,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Fancy_Zones_Main_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[FancyZones main editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Editor principal do FancyZones]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Name" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Name]]></Val>
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Canvas_Layout_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Canvas layout editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Tuval düzeni düzenleyicisi]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Choose_Layout" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Choose your layout for this desktop]]></Val>
|
||||
@@ -118,6 +127,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Fancy_Zones_Main_Editor" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[FancyZones main editor]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[FancyZones ana düzenleyicisi]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";Name" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Name]]></Val>
|
||||
|
||||
@@ -616,7 +616,7 @@ void FancyZones::ToggleEditor() noexcept
|
||||
winrt::com_ptr<IZoneWindow> zoneWindow;
|
||||
|
||||
std::shared_lock readLock(m_lock);
|
||||
|
||||
|
||||
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
||||
{
|
||||
zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, NULL);
|
||||
@@ -625,7 +625,7 @@ void FancyZones::ToggleEditor() noexcept
|
||||
{
|
||||
zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
||||
}
|
||||
|
||||
|
||||
if (!zoneWindow)
|
||||
{
|
||||
return;
|
||||
@@ -639,7 +639,8 @@ void FancyZones::ToggleEditor() noexcept
|
||||
|
||||
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
|
||||
allMonitors = FancyZonesUtils::GetAllMonitorRects<&MONITORINFOEX::rcWork>();
|
||||
} }).wait();
|
||||
} })
|
||||
.wait();
|
||||
|
||||
UINT currentDpi = 0;
|
||||
for (const auto& monitor : allMonitors)
|
||||
@@ -650,15 +651,15 @@ void FancyZones::ToggleEditor() noexcept
|
||||
{
|
||||
if (currentDpi == 0)
|
||||
{
|
||||
currentDpi = dpiX;
|
||||
continue;
|
||||
currentDpi = dpiX;
|
||||
continue;
|
||||
}
|
||||
if (currentDpi != dpiX)
|
||||
{
|
||||
MessageBoxW(NULL,
|
||||
GET_RESOURCE_STRING(IDS_SPAN_ACROSS_ZONES_WARNING).c_str(),
|
||||
GET_RESOURCE_STRING(IDS_POWERTOYS_FANCYZONES).c_str(),
|
||||
MB_OK | MB_ICONWARNING);
|
||||
GET_RESOURCE_STRING(IDS_SPAN_ACROSS_ZONES_WARNING).c_str(),
|
||||
GET_RESOURCE_STRING(IDS_POWERTOYS_FANCYZONES).c_str(),
|
||||
MB_OK | MB_ICONWARNING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -693,8 +694,9 @@ void FancyZones::ToggleEditor() noexcept
|
||||
mi.cbSize = sizeof(mi);
|
||||
|
||||
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
|
||||
GetMonitorInfo(monitor, &mi);
|
||||
} }).wait();
|
||||
GetMonitorInfo(monitor, &mi);
|
||||
} })
|
||||
.wait();
|
||||
|
||||
const auto x = mi.rcWork.left;
|
||||
const auto y = mi.rcWork.top;
|
||||
@@ -981,7 +983,7 @@ void FancyZones::UpdateZoneWindows() noexcept
|
||||
|
||||
auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL {
|
||||
capture* params = reinterpret_cast<capture*>(data);
|
||||
MONITORINFOEX mi{ { .cbSize = sizeof(mi)} };
|
||||
MONITORINFOEX mi{ { .cbSize = sizeof(mi) } };
|
||||
if (GetMonitorInfoW(monitor, &mi))
|
||||
{
|
||||
auto& displayDeviceIdxMap = *(params->displayDeviceIdx);
|
||||
@@ -1006,8 +1008,8 @@ void FancyZones::UpdateZoneWindows() noexcept
|
||||
if (deviceId.empty())
|
||||
{
|
||||
deviceId = GetSystemMetrics(SM_REMOTESESSION) ?
|
||||
L"\\\\?\\DISPLAY#REMOTEDISPLAY#" :
|
||||
L"\\\\?\\DISPLAY#LOCALDISPLAY#";
|
||||
L"\\\\?\\DISPLAY#REMOTEDISPLAY#" :
|
||||
L"\\\\?\\DISPLAY#LOCALDISPLAY#";
|
||||
|
||||
fancyZones->AddZoneWindow(monitor, deviceId);
|
||||
}
|
||||
@@ -1180,21 +1182,24 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
||||
else
|
||||
{
|
||||
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
if (workArea)
|
||||
{
|
||||
const auto zones = zoneSet->GetZones();
|
||||
for (const auto& [zoneId, zone] : zones)
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
{
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
const auto zones = zoneSet->GetZones();
|
||||
for (const auto& [zoneId, zone] : zones)
|
||||
{
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
|
||||
zoneRect.left += monitorRect.left;
|
||||
zoneRect.right += monitorRect.left;
|
||||
zoneRect.top += monitorRect.top;
|
||||
zoneRect.bottom += monitorRect.top;
|
||||
zoneRect.left += monitorRect.left;
|
||||
zoneRect.right += monitorRect.left;
|
||||
zoneRect.top += monitorRect.top;
|
||||
zoneRect.bottom += monitorRect.top;
|
||||
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(zoneId, workArea);
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(zoneId, workArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1224,21 +1229,24 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
||||
if (currentMonitorRect.top <= currentMonitorRect.bottom)
|
||||
{
|
||||
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, current);
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
if (workArea)
|
||||
{
|
||||
const auto zones = zoneSet->GetZones();
|
||||
for (const auto& [zoneId, zone] : zones)
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
{
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
const auto zones = zoneSet->GetZones();
|
||||
for (const auto& [zoneId, zone] : zones)
|
||||
{
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
|
||||
zoneRect.left += currentMonitorRect.left;
|
||||
zoneRect.right += currentMonitorRect.left;
|
||||
zoneRect.top += currentMonitorRect.top;
|
||||
zoneRect.bottom += currentMonitorRect.top;
|
||||
zoneRect.left += currentMonitorRect.left;
|
||||
zoneRect.right += currentMonitorRect.left;
|
||||
zoneRect.top += currentMonitorRect.top;
|
||||
zoneRect.bottom += currentMonitorRect.top;
|
||||
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(zoneId, workArea);
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(zoneId, workArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1351,9 +1359,9 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
||||
{
|
||||
monitor = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONULL);
|
||||
}
|
||||
|
||||
|
||||
auto zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
||||
if (zoneWindow->ActiveZoneSet() != nullptr)
|
||||
if (zoneWindow && zoneWindow->ActiveZoneSet() != nullptr)
|
||||
{
|
||||
if (vkCode == VK_UP || vkCode == VK_DOWN)
|
||||
{
|
||||
|
||||
@@ -307,9 +307,15 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
// Whenever a remap is added move to the bottom of the screen
|
||||
scrollViewer.ChangeView(nullptr, scrollViewer.ScrollableHeight(), nullptr);
|
||||
});
|
||||
|
||||
// Set accessible name for the addRemapKey button
|
||||
addRemapKey.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON)));
|
||||
|
||||
// Add tooltip for add button which would appear on hover
|
||||
ToolTip addRemapKeytoolTip;
|
||||
addRemapKeytoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON)));
|
||||
ToolTipService::SetToolTip(addRemapKey, addRemapKeytoolTip);
|
||||
|
||||
// Header and example text at the top of the window
|
||||
StackPanel helperText;
|
||||
helperText.Children().Append(keyRemapInfoHeader);
|
||||
|
||||
@@ -294,9 +294,15 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
// Whenever a remap is added move to the bottom of the screen
|
||||
scrollViewer.ChangeView(nullptr, scrollViewer.ScrollableHeight(), nullptr);
|
||||
});
|
||||
|
||||
// Set accessible name for the add shortcut button
|
||||
addShortcut.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON)));
|
||||
|
||||
// Add tooltip for add button which would appear on hover
|
||||
ToolTip addShortcuttoolTip;
|
||||
addShortcuttoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON)));
|
||||
ToolTipService::SetToolTip(addShortcut, addShortcuttoolTip);
|
||||
|
||||
// Header and example text at the top of the window
|
||||
StackPanel helperText;
|
||||
helperText.Children().Append(shortcutRemapInfoHeader);
|
||||
|
||||
@@ -105,6 +105,12 @@ void ShortcutControl::AddNewShortcutControlRow(Grid& parent, std::vector<std::ve
|
||||
targetAppTextBox.PlaceholderText(KeyboardManagerConstants::DefaultAppName);
|
||||
targetAppTextBox.Text(targetAppName);
|
||||
|
||||
// GotFocus handler will be called whenever the user tabs into or clicks on the textbox
|
||||
targetAppTextBox.GotFocus([targetAppTextBox](auto const& sender, auto const& e) {
|
||||
// Select all text for accessible purpose
|
||||
targetAppTextBox.SelectAll();
|
||||
});
|
||||
|
||||
// LostFocus handler will be called whenever text is updated by a user and then they click something else or tab to another control. Does not get called if Text is updated while the TextBox isn't in focus (i.e. from code)
|
||||
targetAppTextBox.LostFocus([&keyboardRemapControlObjects, parent, targetAppTextBox](auto const& sender, auto const& e) {
|
||||
// Get index of targetAppTextBox button
|
||||
@@ -226,8 +232,15 @@ void ShortcutControl::AddNewShortcutControlRow(Grid& parent, std::vector<std::ve
|
||||
// delete the ShortcutControl objects so that they get destructed
|
||||
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + bufferIndex);
|
||||
});
|
||||
|
||||
// To set the accessible name of the delete button
|
||||
deleteShortcut.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_DELETE_REMAPPING_BUTTON)));
|
||||
|
||||
// Add tooltip for delete button which would appear on hover
|
||||
ToolTip deleteShortcuttoolTip;
|
||||
deleteShortcuttoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_DELETE_REMAPPING_BUTTON)));
|
||||
ToolTipService::SetToolTip(deleteShortcut, deleteShortcuttoolTip);
|
||||
|
||||
parent.SetColumn(deleteShortcut, KeyboardManagerConstants::ShortcutTableRemoveColIndex);
|
||||
parent.SetRow(deleteShortcut, parent.RowDefinitions().Size() - 1);
|
||||
parent.Children().Append(deleteShortcut);
|
||||
|
||||
@@ -176,8 +176,15 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(Grid& parent, std::vector<s
|
||||
// delete the SingleKeyRemapControl objects so that they get destructed
|
||||
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + bufferIndex);
|
||||
});
|
||||
|
||||
// To set the accessible name of the delete button
|
||||
deleteRemapKeys.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_DELETE_REMAPPING_BUTTON)));
|
||||
|
||||
// Add tooltip for delete button which would appear on hover
|
||||
ToolTip deleteRemapKeystoolTip;
|
||||
deleteRemapKeystoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_DELETE_REMAPPING_BUTTON)));
|
||||
ToolTipService::SetToolTip(deleteRemapKeys, deleteRemapKeystoolTip);
|
||||
|
||||
parent.SetColumn(deleteRemapKeys, KeyboardManagerConstants::RemapTableRemoveColIndex);
|
||||
parent.SetRow(deleteRemapKeys, parent.RowDefinitions().Size() - 1);
|
||||
parent.Children().Append(deleteRemapKeys);
|
||||
|
||||
@@ -21,12 +21,11 @@ namespace Microsoft.Plugin.Folder.Sources.Result
|
||||
|
||||
public Wox.Plugin.Result Create(IPublicAPI contextApi)
|
||||
{
|
||||
var result = new Wox.Plugin.Result
|
||||
var result = new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Path.GetFileName(FilePath)).MatchData)
|
||||
{
|
||||
Title = Title,
|
||||
SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_file_result_subtitle, FilePath),
|
||||
IcoPath = FilePath,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(Search, Path.GetFileName(FilePath)).MatchData,
|
||||
Action = c => ShellAction.Execute(FilePath, contextApi),
|
||||
ContextData = new SearchResult { Type = ResultType.File, FullPath = FilePath },
|
||||
};
|
||||
|
||||
@@ -33,13 +33,12 @@ namespace Microsoft.Plugin.Folder.Sources.Result
|
||||
|
||||
public Wox.Plugin.Result Create(IPublicAPI contextApi)
|
||||
{
|
||||
return new Wox.Plugin.Result
|
||||
return new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Title).MatchData)
|
||||
{
|
||||
Title = Title,
|
||||
IcoPath = Path,
|
||||
SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_folder_result_subtitle, Subtitle),
|
||||
QueryTextDisplay = Path,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(Search, Title).MatchData,
|
||||
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = Path },
|
||||
Action = c => ShellAction.Execute(Path, contextApi),
|
||||
};
|
||||
|
||||
@@ -24,13 +24,12 @@ namespace Microsoft.Plugin.Folder
|
||||
|
||||
public Result Create(IPublicAPI contextApi)
|
||||
{
|
||||
return new Result
|
||||
return new Result(StringMatcher.FuzzySearch(Search, Title).MatchData)
|
||||
{
|
||||
Title = Title,
|
||||
IcoPath = Path,
|
||||
SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_folder_result_subtitle, Subtitle),
|
||||
QueryTextDisplay = Path,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(Search, Title).MatchData,
|
||||
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = Path },
|
||||
Action = c => _shellAction.Execute(Path, contextApi),
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Plugin.Program.ProgramArgumentParser;
|
||||
using Mono.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Wox.Plugin;
|
||||
|
||||
@@ -34,7 +35,7 @@ namespace Microsoft.Plugin.Program.UnitTests.ProgramArgumentParser
|
||||
// basic version of the Quey parser which can be found at Wox.Core.Plugin.QueryBuilder but did not want to create a project reference
|
||||
var splittedSearchString = inputQuery?.Split(Query.TermSeparator, System.StringSplitOptions.RemoveEmptyEntries);
|
||||
var cleanQuery = string.Join(Query.TermSeparator, splittedSearchString);
|
||||
var query = new Query(cleanQuery, cleanQuery, splittedSearchString, string.Empty);
|
||||
var query = new Query(cleanQuery, cleanQuery, new ReadOnlyCollection<string>(splittedSearchString), string.Empty);
|
||||
|
||||
// Act
|
||||
string program = null, programArguments = null;
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Microsoft.Plugin.Program
|
||||
if (!string.IsNullOrEmpty(query?.Search))
|
||||
{
|
||||
// First Argument is always (part of) the program, 2nd term is possibly a Program Argument
|
||||
if (query.Terms.Length > 1)
|
||||
if (query.Terms.Count > 1)
|
||||
{
|
||||
for (var i = 1; i < query.Terms.Length; i++)
|
||||
for (var i = 1; i < query.Terms.Count; i++)
|
||||
{
|
||||
if (!string.Equals(query.Terms[i], DoubleDash, StringComparison.Ordinal))
|
||||
{
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Microsoft.Plugin.Program
|
||||
if (!string.IsNullOrEmpty(query?.Search))
|
||||
{
|
||||
// First Argument is always (part of) the program, 2nd term is possibly a Program Argument
|
||||
if (query.Terms.Length > 1)
|
||||
if (query.Terms.Count > 1)
|
||||
{
|
||||
for (var i = 1; i < query.Terms.Length; i++)
|
||||
for (var i = 1; i < query.Terms.Count; i++)
|
||||
{
|
||||
if (!ArgumentPrefixRegex.IsMatch(query.Terms[i]))
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
using Accessibility;
|
||||
using Microsoft.Plugin.Program.Logger;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
@@ -131,6 +132,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
public bool HasArguments { get; set; }
|
||||
|
||||
// Retrieve the target path using Shell Link
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "HRESULT E_FAIL is thrown while fetching description and E_FAIL does not relate to any specific exception.")]
|
||||
public string RetrieveTargetPath(string path)
|
||||
{
|
||||
var link = new ShellLink();
|
||||
@@ -160,8 +162,16 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
if (!string.IsNullOrEmpty(target))
|
||||
{
|
||||
buffer = new StringBuilder(MAX_PATH);
|
||||
((IShellLinkW)link).GetDescription(buffer, MAX_PATH);
|
||||
Description = buffer.ToString();
|
||||
try
|
||||
{
|
||||
((IShellLinkW)link).GetDescription(buffer, MAX_PATH);
|
||||
Description = buffer.ToString();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception($"|Failed to fetch description for {target}, {e.Message}", e, GetType());
|
||||
Description = string.Empty;
|
||||
}
|
||||
|
||||
StringBuilder argumentBuffer = new StringBuilder(MAX_PATH);
|
||||
((IShellLinkW)link).GetArguments(argumentBuffer, argumentBuffer.Capacity);
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
|
||||
// To set the title to always be the displayname of the packaged application
|
||||
result.Title = DisplayName;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, Name).MatchData;
|
||||
result.SetTitleHighlightData(StringMatcher.FuzzySearch(query, Name).MatchData);
|
||||
|
||||
var toolTipTitle = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_name, result.Title);
|
||||
var toolTipText = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_path, Package.Location);
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
|
||||
// To set the title for the result to always be the name of the application
|
||||
result.Title = Name;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, Name).MatchData;
|
||||
result.SetTitleHighlightData(StringMatcher.FuzzySearch(query, Name).MatchData);
|
||||
|
||||
var toolTipTitle = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_name, result.Title);
|
||||
var toolTipText = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_path, FullPath);
|
||||
|
||||
@@ -32,5 +32,10 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
|
||||
<Version>3.3.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Microsoft.Plugin.Uri.UnitTests.UriHelper
|
||||
[TestCase("[::]", true, "http://[::]/")]
|
||||
[TestCase("[2001:0DB8::1]", true, "http://[2001:db8::1]/")]
|
||||
[TestCase("[2001:0DB8::1]:80", true, "http://[2001:db8::1]/")]
|
||||
public void TryParse_CanParseHostName(string query, bool expectedSuccess, string expectedResult)
|
||||
public void TryParseCanParseHostName(string query, bool expectedSuccess, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var parser = new ExtendedUriParser();
|
||||
|
||||
@@ -78,10 +78,10 @@ namespace Wox.Core.Plugin
|
||||
metadata.PluginDirectory = pluginDirectory;
|
||||
|
||||
// for plugins which doesn't has ActionKeywords key
|
||||
metadata.ActionKeywords = metadata.ActionKeywords ?? new List<string> { metadata.ActionKeyword };
|
||||
metadata.SetActionKeywords(metadata.GetActionKeywords() ?? new List<string> { metadata.ActionKeyword });
|
||||
|
||||
// for plugin still use old ActionKeyword
|
||||
metadata.ActionKeyword = metadata.ActionKeywords?[0];
|
||||
metadata.ActionKeyword = metadata.GetActionKeywords()?[0];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace Wox.Core.Plugin
|
||||
}
|
||||
|
||||
// Plugins may have multiple ActionKeywords, eg. WebSearch
|
||||
plugin.Metadata.ActionKeywords.Where(x => x != Query.GlobalPluginWildcardSign)
|
||||
plugin.Metadata.GetActionKeywords().Where(x => x != Query.GlobalPluginWildcardSign)
|
||||
.ToList()
|
||||
.ForEach(x => NonGlobalPlugins[x] = plugin);
|
||||
}
|
||||
@@ -244,7 +244,7 @@ namespace Wox.Core.Plugin
|
||||
|
||||
private static bool IsGlobalPlugin(PluginMetadata metadata)
|
||||
{
|
||||
return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign);
|
||||
return metadata.GetActionKeywords().Contains(Query.GlobalPluginWildcardSign);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -258,7 +258,6 @@ namespace Wox.Core.Plugin
|
||||
}
|
||||
|
||||
public static IEnumerable<PluginPair> GetPluginsForInterface<T>()
|
||||
where T : IFeatures
|
||||
{
|
||||
return AllPlugins.Where(p => p.Plugin is T);
|
||||
}
|
||||
@@ -320,7 +319,7 @@ namespace Wox.Core.Plugin
|
||||
NonGlobalPlugins[newActionKeyword] = plugin;
|
||||
}
|
||||
|
||||
plugin.Metadata.ActionKeywords.Add(newActionKeyword);
|
||||
plugin.Metadata.GetActionKeywords().Add(newActionKeyword);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -332,7 +331,7 @@ namespace Wox.Core.Plugin
|
||||
var plugin = GetPluginForId(id);
|
||||
if (oldActionkeyword == Query.GlobalPluginWildcardSign
|
||||
&& // Plugins may have multiple ActionKeywords that are global, eg. WebSearch
|
||||
plugin.Metadata.ActionKeywords
|
||||
plugin.Metadata.GetActionKeywords()
|
||||
.Where(x => x == Query.GlobalPluginWildcardSign)
|
||||
.ToList()
|
||||
.Count == 1)
|
||||
@@ -345,7 +344,7 @@ namespace Wox.Core.Plugin
|
||||
NonGlobalPlugins.Remove(oldActionkeyword);
|
||||
}
|
||||
|
||||
plugin.Metadata.ActionKeywords.Remove(oldActionkeyword);
|
||||
plugin.Metadata.GetActionKeywords().Remove(oldActionkeyword);
|
||||
}
|
||||
|
||||
public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Collections.Generic;
|
||||
using Wox.Plugin;
|
||||
|
||||
namespace Wox.Core.Plugin
|
||||
@@ -63,7 +64,7 @@ namespace Wox.Core.Plugin
|
||||
}
|
||||
|
||||
// A new query is constructed for each plugin as they have different action keywords
|
||||
var query = new Query(rawQuery, search, terms, pluginActionKeyword);
|
||||
var query = new Query(rawQuery, search, new ReadOnlyCollection<string>(terms), pluginActionKeyword);
|
||||
|
||||
pluginQueryPair.TryAdd(pluginPair, query);
|
||||
}
|
||||
@@ -80,7 +81,7 @@ namespace Wox.Core.Plugin
|
||||
{
|
||||
if (!pluginQueryPair.ContainsKey(globalPlugin))
|
||||
{
|
||||
var query = new Query(rawQuery, rawQuery, terms, string.Empty);
|
||||
var query = new Query(rawQuery, rawQuery, new ReadOnlyCollection<string>(terms), string.Empty);
|
||||
pluginQueryPair.Add(globalPlugin, query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Wox.Infrastructure.UserSettings
|
||||
var settings = Plugins[metadata.ID];
|
||||
if (settings.ActionKeywords?.Count > 0)
|
||||
{
|
||||
metadata.ActionKeywords = settings.ActionKeywords;
|
||||
metadata.SetActionKeywords(settings.ActionKeywords);
|
||||
metadata.ActionKeyword = settings.ActionKeywords[0];
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Wox.Infrastructure.UserSettings
|
||||
{
|
||||
ID = metadata.ID,
|
||||
Name = metadata.Name,
|
||||
ActionKeywords = metadata.ActionKeywords,
|
||||
ActionKeywords = metadata.GetActionKeywords(),
|
||||
Disabled = metadata.Disabled,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// 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.Globalization;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public static class AllowedLanguage
|
||||
@@ -18,8 +21,14 @@ namespace Wox.Plugin
|
||||
|
||||
public static bool IsAllowed(string language)
|
||||
{
|
||||
return language.ToUpper() == CSharp.ToUpper()
|
||||
|| language.ToUpper() == Executable.ToUpper();
|
||||
if (language == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(language));
|
||||
}
|
||||
|
||||
// Using InvariantCulture since this is a command line arg
|
||||
return language.ToUpper(CultureInfo.InvariantCulture) == CSharp.ToUpper(CultureInfo.InvariantCulture)
|
||||
|| language.ToUpper(CultureInfo.InvariantCulture) == Executable.ToUpper(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public interface IFeatures
|
||||
{
|
||||
}
|
||||
|
||||
public interface IContextMenu : IFeatures
|
||||
public interface IContextMenu
|
||||
{
|
||||
List<ContextMenuResult> LoadContextMenus(Result selectedResult);
|
||||
}
|
||||
@@ -18,14 +14,14 @@ namespace Wox.Plugin
|
||||
/// <summary>
|
||||
/// Represent plugins that support internationalization
|
||||
/// </summary>
|
||||
public interface IPluginI18n : IFeatures
|
||||
public interface IPluginI18n
|
||||
{
|
||||
string GetTranslatedPluginTitle();
|
||||
|
||||
string GetTranslatedPluginDescription();
|
||||
}
|
||||
|
||||
public interface IResultUpdated : IFeatures
|
||||
public interface IResultUpdated
|
||||
{
|
||||
event ResultUpdatedEventHandler ResultsUpdated;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public interface IDelayedExecutionPlugin : IFeatures
|
||||
public interface IDelayedExecutionPlugin
|
||||
{
|
||||
List<Result> Query(Query query, bool delayedExecution);
|
||||
}
|
||||
|
||||
14
src/modules/launcher/Wox.Plugin/LocProject.json
Normal file
14
src/modules/launcher/Wox.Plugin/LocProject.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"Projects": [
|
||||
{
|
||||
"LanguageSet": "Azure_Languages",
|
||||
"LocItems": [
|
||||
{
|
||||
"SourceFile": "src\\modules\\launcher\\Wox.Plugin\\Properties\\Resources.resx",
|
||||
"CopyOption": "LangIDOnName",
|
||||
"OutputPath": "src\\modules\\launcher\\Wox.Plugin\\Properties"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -14,6 +14,13 @@ namespace Wox.Plugin
|
||||
{
|
||||
private string _pluginDirectory;
|
||||
|
||||
private List<string> _actionKeywords;
|
||||
|
||||
public PluginMetadata(List<string> actionKeywords = null)
|
||||
{
|
||||
_actionKeywords = actionKeywords;
|
||||
}
|
||||
|
||||
public string ID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
@@ -51,7 +58,15 @@ namespace Wox.Plugin
|
||||
|
||||
public string ActionKeyword { get; set; }
|
||||
|
||||
public List<string> ActionKeywords { get; set; }
|
||||
public List<string> GetActionKeywords()
|
||||
{
|
||||
return _actionKeywords;
|
||||
}
|
||||
|
||||
public void SetActionKeywords(List<string> value)
|
||||
{
|
||||
_actionKeywords = value;
|
||||
}
|
||||
|
||||
public string IcoPath { get; set; }
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// 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;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public class PluginPair
|
||||
@@ -19,7 +21,8 @@ namespace Wox.Plugin
|
||||
{
|
||||
if (obj is PluginPair r)
|
||||
{
|
||||
return string.Equals(r.Metadata.ID, Metadata.ID);
|
||||
// Using Ordinal since this is used internally
|
||||
return string.Equals(r.Metadata.ID, Metadata.ID, StringComparison.Ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -29,7 +32,8 @@ namespace Wox.Plugin
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashcode = Metadata.ID?.GetHashCode() ?? 0;
|
||||
// Using Ordinal since this is used internally
|
||||
var hashcode = Metadata.ID?.GetHashCode(StringComparison.Ordinal) ?? 0;
|
||||
return hashcode;
|
||||
}
|
||||
}
|
||||
|
||||
90
src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs
generated
Normal file
90
src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,90 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Wox.Plugin.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wox.Plugin.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copying path {0} has failed, it will now be deleted for consistency.
|
||||
/// </summary>
|
||||
public static string filesfolder_copy_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("filesfolder_copy_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not able to delete folder {0}, please go to the location and manually delete it.
|
||||
/// </summary>
|
||||
public static string filesfolder_removefolder_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("filesfolder_removefolder_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unable to verify folders and files between {0} and {1}.
|
||||
/// </summary>
|
||||
public static string filesfolder_verifybothfolderfilesequal_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("filesfolder_verifybothfolderfilesequal_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
132
src/modules/launcher/Wox.Plugin/Properties/Resources.resx
Normal file
132
src/modules/launcher/Wox.Plugin/Properties/Resources.resx
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="filesfolder_copy_failed" xml:space="preserve">
|
||||
<value>Copying path {0} has failed, it will now be deleted for consistency</value>
|
||||
<comment>parameter: targetPath</comment>
|
||||
</data>
|
||||
<data name="filesfolder_removefolder_failed" xml:space="preserve">
|
||||
<value>Not able to delete folder {0}, please go to the location and manually delete it</value>
|
||||
<comment>parameter: path</comment>
|
||||
</data>
|
||||
<data name="filesfolder_verifybothfolderfilesequal_failed" xml:space="preserve">
|
||||
<value>Unable to verify folders and files between {0} and {1}</value>
|
||||
<comment>paramaters: fromPath, toPath</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
@@ -18,7 +19,7 @@ namespace Wox.Plugin
|
||||
/// Initializes a new instance of the <see cref="Query"/> class.
|
||||
/// to allow unit tests for plug ins
|
||||
/// </summary>
|
||||
public Query(string rawQuery, string search, string[] terms, string actionKeyword = "")
|
||||
public Query(string rawQuery, string search, ReadOnlyCollection<string> terms, string actionKeyword = "")
|
||||
{
|
||||
Search = search;
|
||||
RawQuery = rawQuery;
|
||||
@@ -41,9 +42,9 @@ namespace Wox.Plugin
|
||||
public string Search { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the raw query splited into a string array.
|
||||
/// Gets the raw query splited into a string array.
|
||||
/// </summary>
|
||||
public string[] Terms { get; set; }
|
||||
public ReadOnlyCollection<string> Terms { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Query can be splited into multiple terms by whitespace
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
@@ -16,6 +17,7 @@ namespace Wox.Plugin
|
||||
private ToolTipData _toolTipData;
|
||||
private string _pluginDirectory;
|
||||
private string _icoPath;
|
||||
private IList<int> _titleHighlightData;
|
||||
|
||||
public string Title
|
||||
{
|
||||
@@ -26,7 +28,13 @@ namespace Wox.Plugin
|
||||
|
||||
set
|
||||
{
|
||||
_title = value.Replace("\n", " ");
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
// Using Ordinal since this is used internally
|
||||
_title = value.Replace("\n", " ", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,15 +98,32 @@ namespace Wox.Plugin
|
||||
|
||||
public int Score { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of indexes for the characters to be highlighted in Title
|
||||
/// </summary>
|
||||
public IList<int> TitleHighlightData { get; set; }
|
||||
public Result(IList<int> titleHighlightData = null, IList<int> subTitleHighlightData = null)
|
||||
{
|
||||
_titleHighlightData = titleHighlightData;
|
||||
SubTitleHighlightData = subTitleHighlightData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of indexes for the characters to be highlighted in SubTitle
|
||||
/// Gets a list of indexes for the characters to be highlighted in Title
|
||||
/// </summary>
|
||||
public IList<int> SubTitleHighlightData { get; set; }
|
||||
public IList<int> GetTitleHighlightData()
|
||||
{
|
||||
return _titleHighlightData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a list of indexes for the characters to be highlighted in Title
|
||||
/// </summary>
|
||||
public void SetTitleHighlightData(IList<int> value)
|
||||
{
|
||||
_titleHighlightData = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of indexes for the characters to be highlighted in SubTitle
|
||||
/// </summary>
|
||||
public IList<int> SubTitleHighlightData { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets only results that originQuery match with current query will be displayed in the panel
|
||||
@@ -129,10 +154,11 @@ namespace Wox.Plugin
|
||||
{
|
||||
var r = obj as Result;
|
||||
|
||||
var equality = string.Equals(r?.Title, Title) &&
|
||||
string.Equals(r?.SubTitle, SubTitle) &&
|
||||
string.Equals(r?.IcoPath, IcoPath) &&
|
||||
TitleHighlightData == r.TitleHighlightData &&
|
||||
// Using Ordinal since this is used internally
|
||||
var equality = string.Equals(r?.Title, Title, StringComparison.Ordinal) &&
|
||||
string.Equals(r?.SubTitle, SubTitle, StringComparison.Ordinal) &&
|
||||
string.Equals(r?.IcoPath, IcoPath, StringComparison.Ordinal) &&
|
||||
GetTitleHighlightData() == r.GetTitleHighlightData() &&
|
||||
SubTitleHighlightData == r.SubTitleHighlightData;
|
||||
|
||||
return equality;
|
||||
@@ -140,18 +166,16 @@ namespace Wox.Plugin
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashcode = (Title?.GetHashCode() ?? 0) ^
|
||||
(SubTitle?.GetHashCode() ?? 0);
|
||||
// Using Ordinal since this is used internally
|
||||
var hashcode = (Title?.GetHashCode(StringComparison.Ordinal) ?? 0) ^
|
||||
(SubTitle?.GetHashCode(StringComparison.Ordinal) ?? 0);
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} : {1}", Title, SubTitle);
|
||||
}
|
||||
|
||||
public Result()
|
||||
{
|
||||
// Using CurrentCulture since this is user facing
|
||||
return string.Format(CultureInfo.CurrentCulture, "{0} : {1}", Title, SubTitle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,7 +9,12 @@ namespace Wox.Plugin
|
||||
{
|
||||
public class ResultUpdatedEventArgs : EventArgs
|
||||
{
|
||||
public List<Result> Results { get; set; }
|
||||
public List<Result> Results { get; private set; }
|
||||
|
||||
public ResultUpdatedEventArgs(List<Result> results = null)
|
||||
{
|
||||
Results = results;
|
||||
}
|
||||
|
||||
public Query Query { get; set; }
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Wox.Plugin.Logger;
|
||||
using Wox.Plugin.Properties;
|
||||
|
||||
namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
@@ -56,9 +58,10 @@ namespace Wox.Plugin.SharedCommands
|
||||
string error = $"Copying path {targetPath} has failed";
|
||||
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#if DEBUG
|
||||
throw e;
|
||||
throw;
|
||||
#else
|
||||
System.Windows.MessageBox.Show(string.Format("Copying path {0} has failed, it will now be deleted for consistency", targetPath));
|
||||
// Using CurrentCulture since this is user facing
|
||||
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_copy_failed, targetPath));
|
||||
RemoveFolder(targetPath);
|
||||
#endif
|
||||
}
|
||||
@@ -91,9 +94,10 @@ namespace Wox.Plugin.SharedCommands
|
||||
string error = $"Unable to verify folders and files between {fromPath} and {toPath}";
|
||||
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#if DEBUG
|
||||
throw e;
|
||||
throw;
|
||||
#else
|
||||
System.Windows.MessageBox.Show(string.Format(error));
|
||||
// Using CurrentCulture since this is user facing
|
||||
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_verifybothfolderfilesequal_failed, fromPath, toPath));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -113,12 +117,13 @@ namespace Wox.Plugin.SharedCommands
|
||||
catch (Exception e)
|
||||
#pragma warning restore CS0168 // Variable is declared but never used
|
||||
{
|
||||
string error = $"Not able to delete folder {path}, please go to the location and manually delete it";
|
||||
string error = $"Not able to delete folder {path}";
|
||||
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#if DEBUG
|
||||
throw e;
|
||||
throw;
|
||||
#else
|
||||
System.Windows.MessageBox.Show(string.Format(error));
|
||||
// Using CurrentCulture since this is user facing
|
||||
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_removefolder_failed, path));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using static Wox.Plugin.SharedCommands.ShellCommand;
|
||||
|
||||
namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool EnumThreadWindows(uint threadId, EnumThreadDelegate lpfn, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetWindowTextLength(IntPtr hwnd);
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,13 @@ namespace Wox.Plugin.SharedCommands
|
||||
/// Opens search in a new browser. If no browser path is passed in then Chrome is used.
|
||||
/// Leave browser path blank to use Chrome.
|
||||
/// </summary>
|
||||
public static void NewBrowserWindow(this string url, string browserPath)
|
||||
public static void NewBrowserWindow(this Uri url, string browserPath)
|
||||
{
|
||||
if (url == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(url));
|
||||
}
|
||||
|
||||
var browserExecutableName = browserPath?
|
||||
.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None)
|
||||
.Last();
|
||||
@@ -24,7 +29,7 @@ namespace Wox.Plugin.SharedCommands
|
||||
var browser = string.IsNullOrEmpty(browserExecutableName) ? "chrome" : browserPath;
|
||||
|
||||
// Internet Explorer will open url in new browser window, and does not take the --new-window parameter
|
||||
var browserArguments = browserExecutableName == "iexplore.exe" ? url : "--new-window " + url;
|
||||
var browserArguments = browserExecutableName == "iexplore.exe" ? url.AbsoluteUri : "--new-window " + url.AbsoluteUri;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -34,7 +39,7 @@ namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = url,
|
||||
FileName = url.AbsoluteUri,
|
||||
UseShellExecute = true,
|
||||
};
|
||||
Process.Start(psi);
|
||||
@@ -44,24 +49,29 @@ namespace Wox.Plugin.SharedCommands
|
||||
/// <summary>
|
||||
/// Opens search as a tab in the default browser chosen in Windows settings.
|
||||
/// </summary>
|
||||
public static void NewTabInBrowser(this string url, string browserPath)
|
||||
public static void NewTabInBrowser(this Uri url, string browserPath)
|
||||
{
|
||||
if (url == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(url));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(browserPath))
|
||||
{
|
||||
Process.Start(browserPath, url);
|
||||
Process.Start(browserPath, url.AbsoluteUri);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process.Start(url);
|
||||
Process.Start(url.AbsoluteUri);
|
||||
}
|
||||
}
|
||||
|
||||
// This error may be thrown for Process.Start(browserPath, url)
|
||||
catch (System.ComponentModel.Win32Exception)
|
||||
{
|
||||
Process.Start(url);
|
||||
Process.Start(url.AbsoluteUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
@@ -14,19 +13,15 @@ namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool EnumThreadWindows(uint threadId, EnumThreadDelegate lpfn, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetWindowTextLength(IntPtr hwnd);
|
||||
|
||||
private static bool containsSecurityWindow;
|
||||
|
||||
public static Process RunAsDifferentUser(ProcessStartInfo processStartInfo)
|
||||
{
|
||||
if (processStartInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(processStartInfo));
|
||||
}
|
||||
|
||||
processStartInfo.Verb = "RunAsUser";
|
||||
var process = Process.Start(processStartInfo);
|
||||
|
||||
@@ -55,7 +50,7 @@ namespace Wox.Plugin.SharedCommands
|
||||
ProcessThreadCollection ptc = Process.GetCurrentProcess().Threads;
|
||||
for (int i = 0; i < ptc.Count; i++)
|
||||
{
|
||||
EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero);
|
||||
NativeMethods.EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +66,8 @@ namespace Wox.Plugin.SharedCommands
|
||||
|
||||
private static string GetWindowTitle(IntPtr hwnd)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(GetWindowTextLength(hwnd) + 1);
|
||||
GetWindowText(hwnd, sb, sb.Capacity);
|
||||
StringBuilder sb = new StringBuilder(NativeMethods.GetWindowTextLength(hwnd) + 1);
|
||||
_ = NativeMethods.GetWindowText(hwnd, sb, sb.Capacity);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Wox.Plugin
|
||||
private const string HighContrastWhiteTheme = "HighContrast.Accent5";
|
||||
|
||||
private Theme currentTheme;
|
||||
private bool _disposed = false;
|
||||
private bool _disposed;
|
||||
|
||||
public event ThemeChangedHandler ThemeChanged;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Wox.Plugin
|
||||
{
|
||||
if (string.IsNullOrEmpty(title))
|
||||
{
|
||||
throw new ArgumentException("title cannot be null or empty", "title");
|
||||
throw new ArgumentException("title cannot be null or empty", nameof(title));
|
||||
}
|
||||
|
||||
Title = title;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<Platforms>x64</Platforms>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -68,6 +69,10 @@
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.3.0" />
|
||||
<PackageReference Include="ControlzEx" Version="4.3.2" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.5" />
|
||||
@@ -96,4 +101,17 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Plugin;
|
||||
@@ -26,7 +27,7 @@ namespace Wox.Test
|
||||
// Arrange
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { ">" } } } },
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata(new List<string> { ">" } ) } },
|
||||
};
|
||||
string searchQuery = "> file.txt file2 file3";
|
||||
|
||||
@@ -43,7 +44,7 @@ namespace Wox.Test
|
||||
// Arrange
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { ">" }, Disabled = true } } },
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata(new List<string> { ">" }) { Disabled = true } } },
|
||||
};
|
||||
string searchQuery = "> file.txt file2 file3";
|
||||
|
||||
@@ -72,7 +73,7 @@ namespace Wox.Test
|
||||
{
|
||||
// Arrange
|
||||
string searchQuery = "> query";
|
||||
var firstPlugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { ">" } } };
|
||||
var firstPlugin = new PluginPair { Metadata = new PluginMetadata(new List<string> { ">" } ) };
|
||||
var secondPlugin = new PluginPair { Metadata = new PluginMetadata { ActionKeyword = ">" } };
|
||||
|
||||
var nonGlobalPluginWithActionKeywords = new Dictionary<string, PluginPair>
|
||||
@@ -85,7 +86,7 @@ namespace Wox.Test
|
||||
{ ">", secondPlugin },
|
||||
};
|
||||
string[] terms = { ">", "query" };
|
||||
Query expectedQuery = new Query("> query", "query", terms, ">");
|
||||
Query expectedQuery = new Query("> query", "query", new ReadOnlyCollection<string>(terms), ">");
|
||||
|
||||
// Act
|
||||
var queriesForPluginsWithActionKeywords = QueryBuilder.Build(ref searchQuery, nonGlobalPluginWithActionKeywords);
|
||||
@@ -103,7 +104,7 @@ namespace Wox.Test
|
||||
public void QueryBuilderShouldGenerateCorrectQueriesForPluginsWithMultipleActionKeywords()
|
||||
{
|
||||
// Arrange
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { "a", "b" } } };
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata(new List<string> { "a", "b" } ) };
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ "a", plugin },
|
||||
@@ -129,7 +130,7 @@ namespace Wox.Test
|
||||
public void QueryBuildShouldGenerateSameSearchQueryWithOrWithoutSpaceAfterActionKeyword()
|
||||
{
|
||||
// Arrange
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { "a" } } };
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata(new List<string> { "a" } ) };
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ "a", plugin },
|
||||
@@ -198,8 +199,8 @@ namespace Wox.Test
|
||||
|
||||
// Assert
|
||||
// Using Ordinal since this is used internally
|
||||
Assert.IsTrue(firstQuery.Terms[0].Equals("cd", StringComparison.Ordinal) && firstQuery.Terms[1].Equals("efgh", StringComparison.Ordinal) && firstQuery.Terms.Length == 2);
|
||||
Assert.IsTrue(secondQuery.Terms[0].Equals("efgh", StringComparison.Ordinal) && secondQuery.Terms.Length == 1);
|
||||
Assert.IsTrue(firstQuery.Terms[0].Equals("cd", StringComparison.Ordinal) && firstQuery.Terms[1].Equals("efgh", StringComparison.Ordinal) && firstQuery.Terms.Count == 2);
|
||||
Assert.IsTrue(secondQuery.Terms[0].Equals("efgh", StringComparison.Ordinal) && secondQuery.Terms.Count == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Description" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be turned off/on as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[Einige der Datei-Explorer-Module konnten gemäß Ihren Einstellungen nicht registriert bzw. aus der Registrierung entfernt werden. Starten Sie PowerToys als Administrator neu, damit die Änderungen ausgeführt werden können.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Einige der Datei-Explorer-Module konnten gemäß Ihren Einstellungen nicht aktiviert bzw. deaktiviert werden. Starten Sie PowerToys als Administrator neu, damit die Änderungen ausgeführt werden können.]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be registered/unregistered as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
@@ -70,8 +70,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Title" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Couldn't modify File Explorer modules]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[Fehler beim Ändern der Datei-Explorer-Module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Fehler beim Ändern von Datei-Explorer-Modulen]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Failed to modify File Explorer modules]]></Val>
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Description" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be turned off/on as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[No se pudieron registrar algunos módulos del Explorador de archivos, o no se pudo anular su registro, según la configuración. Reinicie PowerToys como administrador para que los cambios se apliquen.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[No se pudieron activar o desactivar algunos módulos del Explorador de archivos según la configuración. Reinicie PowerToys como administrador para que los cambios se apliquen.]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be registered/unregistered as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
@@ -70,7 +70,7 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Title" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Couldn't modify File Explorer modules]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[No se pudieron modificar los módulos del Explorador de archivos]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Description" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be turned off/on as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[Impossible d'inscrire/de désinscrire certains modules de l'Explorateur de fichiers selon vos paramètres. Redémarrez PowerToys comme administrateur pour appliquer les changements.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Impossible de désactiver/d'activer certains modules de l'Explorateur de fichiers selon vos paramètres. Redémarrez PowerToys comme administrateur pour appliquer les changements.]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be registered/unregistered as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
@@ -70,8 +70,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Title" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Couldn't modify File Explorer modules]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[La modification des modules de l'Explorateur de fichiers a échoué]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Impossible de modifier les modules de l'Explorateur de fichiers]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Failed to modify File Explorer modules]]></Val>
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Description" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be turned off/on as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[Een aantal modules van Bestandenverkenner kunnen niet worden geregistreerd/uitgeschreven vanwege uw instellingen. Start PowerToys opnieuw als beheerder om de wijzigingen door te voeren.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Een aantal modules van Bestandenverkenner kunnen niet worden in-/uitgeschakeld vanwege uw instellingen. Start PowerToys opnieuw als beheerder om de wijzigingen door te voeren.]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be registered/unregistered as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
@@ -70,7 +70,7 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Title" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Couldn't modify File Explorer modules]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Kan de modules van Bestandenverkenner niet wijzigen]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Description" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be turned off/on as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[Não foi possível registrar/cancelar o registro de alguns dos módulos do Explorador de Arquivos de acordo com as configurações. Reinicie os PowerToys como administrador para que as alterações entrem em vigor.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Não foi possível ativar/desativar alguns dos módulos do Explorador de Arquivos de acordo com as configurações. Reinicie o PowerToys como administrador para que as alterações entrem em vigor.]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be registered/unregistered as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
@@ -70,7 +70,7 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Title" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Couldn't modify File Explorer modules]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Falha ao modificar os módulos do Explorador de Arquivos]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Description" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be turned off/on as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Val><![CDATA[Bazı Dosya Gezgini modülleri, ayarlarınıza göre kaydedilemedi/kaydı silinemedi. Değişikliklerin geçerli olması için lütfen PowerToys'u yönetici olarak yeniden başlatın.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Bazı Dosya Gezgini modülleri, ayarlarınıza göre devre dışı bırakılamadı/etkinleştirilemedi. Değişikliklerin geçerli olması için lütfen PowerToys'u yönetici olarak yeniden başlatın.]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
<Val><![CDATA[Some of the File Explorer modules could not be registered/unregistered as per your settings. Please restart PowerToys as admin for the changes to take place.]]></Val>
|
||||
@@ -70,7 +70,7 @@
|
||||
<Item ItemId=";FileExplorer_Admin_Restart_Warning_Title" ItemType="0;.resx" PsrId="211" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Couldn't modify File Explorer modules]]></Val>
|
||||
<Tgt Cat="Text" Stat="Update" Orig="New">
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Dosya Gezgini modülleri değiştirilemedi]]></Val>
|
||||
</Tgt>
|
||||
<Prev Cat="Text">
|
||||
|
||||
Reference in New Issue
Block a user