mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-02 18:36:24 +01:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9081bc7438 | ||
|
|
7307242396 | ||
|
|
630ed29700 | ||
|
|
41b0b850e1 | ||
|
|
96dc200324 | ||
|
|
9597f87dc4 | ||
|
|
7572586b4c | ||
|
|
3970e89ee7 | ||
|
|
74214f611e | ||
|
|
908a690316 | ||
|
|
6515374ce9 | ||
|
|
273a45ff1f | ||
|
|
17f3c12a11 | ||
|
|
fa4471a9e6 | ||
|
|
727de3e1fc | ||
|
|
c6f9701818 | ||
|
|
9453e38881 | ||
|
|
a1a02889d5 | ||
|
|
0592e74d3d | ||
|
|
9d148d0a3a | ||
|
|
0a51687b65 | ||
|
|
771fcaba96 | ||
|
|
82e386f63c | ||
|
|
91b53cdc13 | ||
|
|
5c2c74a6c9 | ||
|
|
cb5baad677 | ||
|
|
ec136d7bb7 | ||
|
|
e33efb7f10 | ||
|
|
68afc6623f | ||
|
|
5008d77105 | ||
|
|
58d34087ee | ||
|
|
0c7a1dd316 | ||
|
|
e0cb4018ab | ||
|
|
c19c4b0353 | ||
|
|
cc644b1998 | ||
|
|
33ec492389 | ||
|
|
1205a9d9e0 | ||
|
|
629ca8bd4c | ||
|
|
ab7394f15e | ||
|
|
fd280800cf | ||
|
|
5fe761949f | ||
|
|
2c069ce708 |
6
.github/actions/spell-check/allow/code.txt
vendored
6
.github/actions/spell-check/allow/code.txt
vendored
@@ -263,6 +263,10 @@ onefuzz
|
||||
|
||||
# NameInCode
|
||||
leilzh
|
||||
mengyuanchen
|
||||
|
||||
# DllName
|
||||
testhost
|
||||
|
||||
#Tools
|
||||
OIP
|
||||
OIP
|
||||
|
||||
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@@ -734,6 +734,7 @@ KEYBDINPUT
|
||||
keyboardeventhandlers
|
||||
keyboardmanagercommon
|
||||
KEYBOARDMANAGEREDITOR
|
||||
KEYBOARDMANAGEREDITORLIBRARYWRAPPER
|
||||
keyboardmanagerstate
|
||||
keyboardmanagerui
|
||||
KEYEVENTF
|
||||
@@ -1302,6 +1303,7 @@ regroot
|
||||
regsvr
|
||||
REINSTALLMODE
|
||||
reloadable
|
||||
Relogger
|
||||
remappings
|
||||
REMAPSUCCESSFUL
|
||||
REMAPUNSUCCESSFUL
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
schedules:
|
||||
- cron: "0 0 * * *" # every day at midnight
|
||||
displayName: "Daily midnight Build"
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
always: false # only run if there's code changes!
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
|
||||
@@ -15,7 +8,6 @@ parameters:
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- arm64
|
||||
- name: enableMsBuildCaching
|
||||
type: boolean
|
||||
displayName: "Enable MSBuild Caching"
|
||||
@@ -28,15 +20,6 @@ parameters:
|
||||
type: boolean
|
||||
displayName: "Build Using Visual Studio Preview"
|
||||
default: false
|
||||
- name: useLatestWinAppSDK
|
||||
type: boolean
|
||||
default: true
|
||||
- name: winAppSDKVersionNumber
|
||||
type: string
|
||||
default: 1.6
|
||||
- name: useExperimentalVersion
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
extends:
|
||||
template: templates/pipeline-ci-build.yml
|
||||
@@ -45,6 +28,3 @@ extends:
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
useLatestWinAppSDK: ${{ parameters.useLatestWinAppSDK }}
|
||||
winAppSDKVersionNumber: ${{ parameters.winAppSDKVersionNumber }}
|
||||
useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
|
||||
|
||||
@@ -88,6 +88,8 @@ extends:
|
||||
akvName: $(SigningAKVName)
|
||||
authCertName: $(SigningAuthCertName)
|
||||
signCertName: $(SigningSignCertName)
|
||||
useManagedIdentity: $(SigningUseManagedIdentity)
|
||||
clientId: $(SigningOriginalClientId)
|
||||
# Have msbuild use the release nuget config profile
|
||||
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config"
|
||||
beforeBuildSteps:
|
||||
|
||||
@@ -19,6 +19,7 @@ jobs:
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
SrcPath: $(Build.Repository.LocalPath)
|
||||
TestArtifactsName: build-${{ parameters.platform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
${{ if ne(parameters.platform, 'ARM64') }}:
|
||||
@@ -59,14 +60,19 @@ jobs:
|
||||
- script:
|
||||
reg add "HKLM\Software\Policies\Microsoft\Edge\WebView2\ReleaseChannels" /v PowerToys.exe /t REG_SZ /d "3"
|
||||
displayName: "Enable WebView2 Canary Channel"
|
||||
|
||||
- download: current
|
||||
displayName: Download artifacts
|
||||
artifact: build-${{ parameters.platform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
|
||||
patterns: |-
|
||||
**
|
||||
!**\*.pdb
|
||||
!**\*.lib
|
||||
|
||||
- ${{ if ne(parameters.platform, 'arm64') }}:
|
||||
- download: current
|
||||
displayName: Download artifacts
|
||||
artifact: $(TestArtifactsName)
|
||||
patterns: |-
|
||||
**
|
||||
!**\*.pdb
|
||||
!**\*.lib
|
||||
- ${{ else }}:
|
||||
- template: steps-download-artifacts-with-azure-cli.yml
|
||||
parameters:
|
||||
artifactName: $(TestArtifactsName)
|
||||
|
||||
- template: steps-ensure-dotnet-version.yml
|
||||
parameters:
|
||||
@@ -91,7 +97,7 @@ jobs:
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
testSelector: 'testAssemblies'
|
||||
searchFolder: '$(Pipeline.Workspace)\build-${{ parameters.platform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}'
|
||||
searchFolder: '$(Pipeline.Workspace)\$(TestArtifactsName)'
|
||||
vsTestVersion: 'toolsInstaller'
|
||||
uiTests: true
|
||||
rerunFailedTests: true
|
||||
|
||||
@@ -43,43 +43,11 @@ stages:
|
||||
- template: job-ci-precheck.yml
|
||||
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- stage: Build_${{ platform }}
|
||||
displayName: Build ${{ platform }}
|
||||
${{ if ne(variables['Build.Reason'], 'Manual') }}:
|
||||
dependsOn: [Precheck]
|
||||
condition: and(succeeded(), ne(dependencies.Precheck.outputs['Precheck.verifyBuildRequest.skipBuild'], 'Yes'))
|
||||
${{ else }}:
|
||||
dependsOn: []
|
||||
- stage: Test_${{ platform }}
|
||||
displayName: Test ${{ platform }}
|
||||
jobs:
|
||||
- template: job-build-project.yml
|
||||
- template: job-test-project.yml
|
||||
parameters:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
name: SHINE-INT-L
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
demands: ImageOverride -equals SHINE-VS17-Preview
|
||||
buildPlatforms:
|
||||
- ${{ platform }}
|
||||
buildConfigurations: [Release]
|
||||
enablePackageCaching: true
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
useLatestWinAppSDK: ${{ parameters.useLatestWinAppSDK }}
|
||||
${{ if eq(parameters.useLatestWinAppSDK, true) }}:
|
||||
winAppSDKVersionNumber: ${{ parameters.winAppSDKVersionNumber }}
|
||||
useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
|
||||
|
||||
- ${{ if eq(parameters.runTests, true) }}:
|
||||
- stage: Test_${{ platform }}
|
||||
displayName: Test ${{ platform }}
|
||||
dependsOn:
|
||||
- Build_${{platform}}
|
||||
jobs:
|
||||
- template: job-test-project.yml
|
||||
parameters:
|
||||
platform: ${{ platform }}
|
||||
configuration: Release
|
||||
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
|
||||
platform: ${{ platform }}
|
||||
configuration: Release
|
||||
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
parameters:
|
||||
- name: artifactName
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
# Why use az cli to download? → The ARM agent may run into OutOfMemory issues.
|
||||
# Why use the Azure CLI ZIP version? → It comes with its own Python and works fine under emulation on ARM64.
|
||||
# Why not use AzureCLI@2 task? → It requires azureSubscription, which is unnecessary for downloading artifacts.
|
||||
|
||||
steps:
|
||||
- powershell: |
|
||||
Write-Host "Downloading Azure CLI ZIP..."
|
||||
$azCliUrl = "https://aka.ms/installazurecliwindowszipx64"
|
||||
$azCliZip = "$(Build.ArtifactStagingDirectory)\azure-cli.zip"
|
||||
|
||||
Invoke-WebRequest -Uri $azCliUrl -OutFile $azCliZip
|
||||
displayName: 'Install Azure CLI from ZIP'
|
||||
|
||||
- task: ExtractFiles@1
|
||||
inputs:
|
||||
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)\azure-cli.zip'
|
||||
destinationFolder: '$(Build.ArtifactStagingDirectory)\AzureCLI'
|
||||
|
||||
- pwsh: |
|
||||
$azureCliPath = "$(Build.ArtifactStagingDirectory)\AzureCLI\bin"
|
||||
$env:Path = "$azureCliPath;" + $env:Path
|
||||
Write-Host "Add azure-devops..."
|
||||
az extension add -n azure-devops
|
||||
Write-Host "Configuring Azure DevOps defaults..."
|
||||
az devops configure --defaults organization='$(System.TeamFoundationCollectionUri)' project='$(System.TeamProject)' --use-git-aliases true
|
||||
Write-Host "check permission"
|
||||
az pipelines list --org "$(System.TeamFoundationCollectionUri)" --project "$(System.TeamProject)" --output table
|
||||
Write-Host "Downloading artifacts..."
|
||||
if ($env:AZURE_DEVOPS_EXT_PAT -eq $null -or $env:AZURE_DEVOPS_EXT_PAT -eq "") {
|
||||
Write-Host "Error: AZURE_DEVOPS_EXT_PAT is not set."
|
||||
exit 1
|
||||
}
|
||||
az pipelines runs artifact download --artifact-name ${{parameters.artifactName}} --path "$(Pipeline.Workspace)/${{parameters.artifactName}}" --run-id 116384714 --debug
|
||||
displayName: 'Download artifacts with Azure CLI'
|
||||
env:
|
||||
AZURE_DEVOPS_EXT_PAT: $(System.AccessToken)
|
||||
@@ -19,4 +19,6 @@ steps:
|
||||
AuthAKVName: ${{ parameters.signingIdentity.akvName }}
|
||||
AuthCertName: ${{ parameters.signingIdentity.authCertName }}
|
||||
AuthSignCertName: ${{ parameters.signingIdentity.signCertName }}
|
||||
UseMSIAuthentication: ${{ coalesce(parameters.signingIdentity.useManagedIdentity, 'false') }}
|
||||
EsrpClientId: ${{ parameters.signingIdentity.clientId }}
|
||||
${{ insert }}: ${{ parameters.inputs }}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
$LatestVCToolsVersion = (([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest $env:VCWhereExtraVersionTarget -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml)).instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.CRT.Source" }).version;
|
||||
|
||||
$VSInstances = ([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml))
|
||||
$VSPackages = $VSInstances.instances.instance.packages.package
|
||||
$LatestVCPackage = ($VSInstances.instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.Tools.Core" })
|
||||
$LatestVCToolsVersion = $LatestVCPackage.version;
|
||||
Write-Output "Latest VCToolsVersion: $LatestVCToolsVersion"
|
||||
Write-Output "Updating VCToolsVersion environment variable for job"
|
||||
Write-Output "##vso[task.setvariable variable=VCToolsVersion]$LatestVCToolsVersion"
|
||||
|
||||
@@ -15,7 +15,7 @@ Param(
|
||||
$referencedFileVersionsPerDll = @{}
|
||||
$totalFailures = 0
|
||||
|
||||
Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZones*,MouseJump.Common.UnitTests*,AdvancedPaste.FuzzTests* | ForEach-Object {
|
||||
Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZones*,MouseJump.Common.UnitTests*,*.FuzzTests* | ForEach-Object {
|
||||
# Temporarily exclude FancyZones UI tests because of Appium.WebDriver dependencies
|
||||
$depsJsonFullFileName = $_.FullName
|
||||
$depsJsonFileName = $_.Name
|
||||
@@ -41,10 +41,11 @@ Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZone
|
||||
$dllName = Split-Path $_.Name -leaf
|
||||
if([bool]($_.Value.PSObject.Properties.name -match 'fileVersion')) {
|
||||
$dllFileVersion = $_.Value.fileVersion
|
||||
if ([string]::IsNullOrEmpty($dllFileVersion) -and $dllName.StartsWith('PowerToys.'))` {
|
||||
if (([string]::IsNullOrEmpty($dllFileVersion) -or ($dllFileVersion -eq '0.0.0.0')) -and $dllName.StartsWith('PowerToys.'))` {
|
||||
# After VS 17.11 update some of PowerToys dlls have no fileVersion in deps.json even though the
|
||||
# version is correctly set. This is a workaround to skip our dlls as we are confident that all of
|
||||
# our dlls share the same version across the dependencies.
|
||||
# After VS 17.13 these error versions started appearing as 0.0.0.0 so we've added that case to the condition as well.
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ $versionExceptions = @(
|
||||
"Microsoft.Xaml.Interactions.dll",
|
||||
"Microsoft.Xaml.Interactivity.dll",
|
||||
"hyjiacan.py4n.dll",
|
||||
"TraceReloggerLib.dll",
|
||||
"Microsoft.WindowsAppRuntime.Release.Net.dll",
|
||||
"Microsoft.Windows.Widgets.Projection.dll",
|
||||
"WinRT.Host.Shim.dll") -join '|';
|
||||
@@ -59,6 +60,11 @@ if ($items.Count -eq 0) {
|
||||
}
|
||||
|
||||
$items | ForEach-Object {
|
||||
if ($_.VersionInfo.FileVersion -eq "0.0.0.0" -and $_.Name -notmatch $versionExceptions) {
|
||||
# These items are exceptions that actually have the 0.0.0.0 version.
|
||||
Write-Host "Version set to 0.0.0.0: " + $_.FullName
|
||||
$totalFailure++;
|
||||
}
|
||||
if ($_.VersionInfo.FileVersion -eq "1.0.0.0" -and $_.Name -notmatch $versionExceptions) {
|
||||
# These items are exceptions that actually have the 1.0.0.0 version.
|
||||
Write-Host "Version set to 1.0.0.0: " + $_.FullName
|
||||
|
||||
@@ -27,21 +27,21 @@
|
||||
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
||||
<PackageVersion Include="MessagePack" Version="2.5.187" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.2" />
|
||||
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.15.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2739.15" />
|
||||
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.1" />
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
||||
<!--
|
||||
@@ -67,26 +67,26 @@
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.19.27" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.1" />
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.2" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.2" />
|
||||
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.2" />
|
||||
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.2" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="21.0.29" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="21.0.29" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.1" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.2" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.2" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
|
||||
43
NOTICE.md
43
NOTICE.md
@@ -1318,21 +1318,22 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Mages 3.0.0
|
||||
- Markdig.Signed 0.34.0
|
||||
- MessagePack 2.5.187
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.1
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.2
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
|
||||
- Microsoft.Data.Sqlite 9.0.1
|
||||
- Microsoft.Data.Sqlite 9.0.2
|
||||
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.1
|
||||
- Microsoft.Extensions.Hosting 9.0.1
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.1
|
||||
- Microsoft.Extensions.Logging 9.0.1
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.1
|
||||
- Microsoft.DotNet.ILCompiler (A)
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.2
|
||||
- Microsoft.Extensions.Hosting 9.0.2
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.2
|
||||
- Microsoft.Extensions.Logging 9.0.2
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.2
|
||||
- Microsoft.NET.ILLink.Tasks (A)
|
||||
- Microsoft.SemanticKernel 1.15.0
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2739.15
|
||||
- Microsoft.Win32.SystemEvents 9.0.1
|
||||
- Microsoft.Windows.Compatibility 9.0.1
|
||||
- Microsoft.Win32.SystemEvents 9.0.2
|
||||
- Microsoft.Windows.Compatibility 9.0.2
|
||||
- Microsoft.Windows.CsWin32 0.2.46-beta
|
||||
- Microsoft.Windows.CsWinRT 2.1.5
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
|
||||
@@ -1350,23 +1351,23 @@ EXHIBIT A -Mozilla Public License.
|
||||
- SharpCompress 0.37.2
|
||||
- StreamJsonRpc 2.19.27
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 9.0.1
|
||||
- System.CodeDom 9.0.2
|
||||
- System.CommandLine 2.0.0-beta4.22272.1
|
||||
- System.ComponentModel.Composition 9.0.1
|
||||
- System.Configuration.ConfigurationManager 9.0.1
|
||||
- System.Data.OleDb 9.0.1
|
||||
- System.ComponentModel.Composition 9.0.2
|
||||
- System.Configuration.ConfigurationManager 9.0.2
|
||||
- System.Data.OleDb 9.0.2
|
||||
- System.Data.SqlClient 4.8.6
|
||||
- System.Diagnostics.EventLog 9.0.1
|
||||
- System.Diagnostics.PerformanceCounter 9.0.1
|
||||
- System.Drawing.Common 9.0.1
|
||||
- System.Diagnostics.EventLog 9.0.2
|
||||
- System.Diagnostics.PerformanceCounter 9.0.2
|
||||
- System.Drawing.Common 9.0.2
|
||||
- System.IO.Abstractions 21.0.29
|
||||
- System.IO.Abstractions.TestingHelpers 21.0.29
|
||||
- System.Management 9.0.1
|
||||
- System.Management 9.0.2
|
||||
- System.Reactive 6.0.1
|
||||
- System.Runtime.Caching 9.0.1
|
||||
- System.ServiceProcess.ServiceController 9.0.1
|
||||
- System.Text.Encoding.CodePages 9.0.1
|
||||
- System.Text.Json 9.0.1
|
||||
- System.Runtime.Caching 9.0.2
|
||||
- System.ServiceProcess.ServiceController 9.0.2
|
||||
- System.Text.Encoding.CodePages 9.0.2
|
||||
- System.Text.Json 9.0.2
|
||||
- UnicodeInformation 2.6.0
|
||||
- UnitsNet 5.56.0
|
||||
- UTF.Unknown 2.5.1
|
||||
|
||||
636
PowerToys.sln
636
PowerToys.sln
File diff suppressed because it is too large
Load Diff
174
README.md
174
README.md
@@ -18,7 +18,7 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
| [New+](https://aka.ms/PowerToysOverview_NewPlus) | [Peek](https://aka.ms/PowerToysOverview_Peek) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) |
|
||||
| [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) |
|
||||
| [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
|
||||
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [ZoomIt](https://aka.ms/PowerToysOverview_PowerToysOverview_ZoomIt) |
|
||||
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) |
|
||||
|
||||
## Installing and running Microsoft PowerToys
|
||||
|
||||
@@ -34,19 +34,19 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
Go to the [Microsoft PowerToys GitHub releases page][github-release-link] and click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user.
|
||||
|
||||
<!-- items that need to be updated release to release -->
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.88%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.87%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysUserSetup-0.87.1-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysUserSetup-0.87.1-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysSetup-0.87.1-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysSetup-0.87.1-arm64.exe
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.89%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.88%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysUserSetup-0.88.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysUserSetup-0.88.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysSetup-0.88.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysSetup-0.88.0-arm64.exe
|
||||
|
||||
| Description | Filename | sha256 hash |
|
||||
|----------------|----------|-------------|
|
||||
| Per user - x64 | [PowerToysUserSetup-0.87.1-x64.exe][ptUserX64] | 8EFAF47ED00BF230D2C2CC3CB6765C903A6A47E0AAED0BBB329CEF918207B486 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.87.1-arm64.exe][ptUserArm64] | 212FC8055789BD2DC4DE554B9AEE291A9C077907E263A302939266263A9D512B |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.87.1-x64.exe][ptMachineX64] | 69AD65DDAC6436AEF292D2CC6AB1530021CE98083CB3F5FD3380A52A3B0DBB9A |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.87.1-arm64.exe][ptMachineArm64] | AEC9F1D02F1E23F0C1FCFDF95C337C962902394F44C0568012DF78BEDB45CF19 |
|
||||
| Per user - x64 | [PowerToysUserSetup-0.88.0-x64.exe][ptUserX64] | 5BBA2E06603CAAE0269DFBC991095C6664FD934130335197C1BA3120E19B7CA3 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.88.0-arm64.exe][ptUserArm64] | E79723F9F94068C699E01334C8CC0C85F37818EB4664FC772D2B545A1C37C3FA |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.88.0-x64.exe][ptMachineX64] | C43742DB7AA3F8B01FE7AE1DA591F0342767AFE5BBACB72F2968CE5E8EE1E3AC |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.88.0-arm64.exe][ptMachineArm64] | AEE4A67643C886336F31F86C4117BA5F01BCA5E0E99FF34524217DC91AFA7132 |
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
@@ -92,119 +92,141 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
|
||||
|
||||
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
|
||||
|
||||
### 0.87 - December 2024 Update
|
||||
### 0.88 - January 2025 Update
|
||||
|
||||
In this release, we focused on new features, stability, and improvements.
|
||||
|
||||
**Highlights**
|
||||
|
||||
- Advanced Paste has a new feature called "Advanced AI" that uses Semantic Kernel to allow setting up the orchestration of sequential clipboard transformations.
|
||||
- Workspaces supports Progressive Web Applications.
|
||||
- Workspaces has a new feature to move existing windows instead of creating new ones.
|
||||
- Mouse Jump added new settings to allow customization of screens pop-up. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- New+ now works on Windows 10. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Quick Accent allows selecting the character sets that should appear on the UI. Thanks [@Sirozha1337](https://github.com/Sirozha1337)!
|
||||
- New utility: ZoomIt - a screen zoom, annotation, and recording tool for technical presentations and demos. This utility from Sysinternals has had its source code released and included in PowerToys. ZoomIt will still continue to be updated and shipped by Sysinternals for users who prefer to have it as a standalone utility outside of PowerToys. Thanks [@markrussinovich](https://github.com/markrussinovich), [@foxmsft](https://github.com/foxmsft) and [@johnstep](https://github.com/johnstep) for contributing the original code and reviewing the PowerToys integration!
|
||||
- Video Conference Mute has been deprecated and was removed from PowerToys.
|
||||
- .Net 9.0.1 fixed many issue in WPF, improving stability for PowerToys Run.
|
||||
|
||||
### General
|
||||
- Applied a workaround for the Windows App SDK applications title bar override that was causing accent color to not be shown on the top bar of applications on Windows 10. Thanks [@pingzing](https://github.com/pingzing)!
|
||||
- Improved the "admin application running" notification checking logic to be less demanding on resources. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed an issue causing many utilities to crash when the GPO to disable data diagnostics was applied.
|
||||
|
||||
### Advanced Paste
|
||||
|
||||
- Added a new optional feature allowing using AI to set up the orchestration of sequential clipboard transformations.
|
||||
- Fixed a crash when the application was exiting. (This was a hotfix for 0.87)
|
||||
- Added a Json format validation step to verify if a conversion to Json should be applied.
|
||||
- Fixed accessibility issues when using a screen reader.
|
||||
- Added support for all BitmapDecoder supported image file types to the Image to Text functionality. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed an issue causing Advanced Paste initialization errors to hang the PowerToys main process.
|
||||
|
||||
### Awake
|
||||
### FancyZones
|
||||
|
||||
- Initialization, logging and tray icon setup improvements. Thanks [@dend](https://github.com/dend)!
|
||||
- Removed Workspaces Editor from the exclusions list so it can be snapped by FancyZones.
|
||||
|
||||
### File Explorer add-ons
|
||||
### Keyboard Manager
|
||||
|
||||
- Preview Pane extensions now use the PerMonitorV2 DPI mode to fix errors on different scales. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Keyboard Manager.
|
||||
|
||||
- Added labels to the IME On, IME Off keys. Thanks [@kit494way](https://github.com/kit494way)!
|
||||
- Fixed an issue that caused the Shift key to remain stuck if a numpad key was mapped to the Shift key.
|
||||
- Added an option to make a shortcut remapping only trigger with exact modifiers.
|
||||
|
||||
### Monaco Preview
|
||||
|
||||
- Added support for .ahk files to be shown as a plaintext file in Peek and File Explorer add-ons. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Added support for .ion files to be shown as a plaintext file in Peek and File Explorer add-ons. Thanks [@octastylos-pseudodipteros](https://github.com/octastylos-pseudodipteros)!
|
||||
- Added support for syntax highlighting for .srt files in Peek and File Explorer add-ons. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added support for .resx and .resw files in Peek and File Explorer add-ons. Thanks [@asif4318](https://github.com/asif4318)!
|
||||
- Added a setting to make the code minimap toggle-able in Peek and File Explorer add-ons. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Fixed an issue causing Json format preview setting to not be applied correctly.
|
||||
- Fixed an issue causing the wrong Monaco assets to be used at runtime.
|
||||
|
||||
### Mouse Jump
|
||||
### Mouse Without Borders
|
||||
|
||||
- Allow customizing the appearance of the UI of the Mouse Jump pop-up. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Fixed an issue causing clipboard to stop working after going through a UAC screen when using the Service mode. Thanks [@YDKK](https://github.com/YDKK)!
|
||||
|
||||
### New+
|
||||
|
||||
- Added support for Windows 10. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Fixed an issue causing the renaming of new files to not trigger some times. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Updated the New+ icons. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
- Fixed an issue causing New+ to override the New file or folder creation from the File Explorer Ribbon buttons or keyboard shortcuts on Windows 10.
|
||||
- When creating file or folders through a template, they should now have the current time as the last modified date. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
|
||||
### Peek
|
||||
|
||||
- Peek now checks local capabilities to decide what image formats Image Previewer is able to support. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed an issue causing the Code Files Previewer to not load correctly under certain conditions. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Refactored, improved and fixed logging when loading the user settings file. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed an issue causing Peek to not appear if it was previously minimized. Thanks [@asif4318](https://github.com/asif4318)!
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
- Added a scoring function for proper ordering of the WindowWalker plugin results. Thanks [@andbartol](https://github.com/andbartol)!
|
||||
- Added UUIDv7 support to the ValueGenerator plugin. Thanks [@frederik-hoeft](https://github.com/frederik-hoeft)!
|
||||
- The calculator plugin now allows scientific notation numbers with a lowercase 'e'. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Ported the UI from WPF-UI to .NET 9 WPF, to fix "Desktop composition is disabled" crashes.
|
||||
- Fixed a transparent border issue on Windows 10. (This was a hotfix for 0.87)
|
||||
- Fixed a crash in the OneNote plugin after the .Net 9 update. (This was a hotfix for 0.87)
|
||||
- Fixed an issue causing the Calculator plugin to return division by zero errors when dividing by hexadecimal numbers. Thanks [@plante-msft](https://github.com/plante-msft)!
|
||||
- Updated the Calculator plugin Mages library to 3.0.0 and added support for the random integer function. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Improved handling of non-base 10 numbers to add support for binary and octal numbers in the Calculator plugin. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added a setting to enable selection of which units to use for trigonometric functions. Thanks [@OldUser101](https://github.com/OldUser101)!
|
||||
- Fixed a .NET 9 regression causing the PowerToys Run dialog to not be draggable. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Added context menu buttons for the VS Code Workspaces plugin, for copying the path, opening in File Explorer or in Console. Thanks [@programming-with-ia](https://github.com/programming-with-ia)!
|
||||
- Added some telemetry to gather data on which hotkey is used to trigger PowerToys Run.
|
||||
- Removed the workarounds that were in place to fix some WPF issues that were fixed in .NET 9.0.1.
|
||||
- Fixed a typo in the Value Generator plugin messages. Thanks [@OldUser101](https://github.com/OldUser101)!
|
||||
|
||||
### Quick Accent
|
||||
|
||||
- Added a setting to allow selecting which character sets to show. Thanks [@Sirozha1337](https://github.com/Sirozha1337)!
|
||||
- Added the ć character to the Slovenian character set. Thanks [@dsoklic](https://github.com/dsoklic)!
|
||||
- Added the Proto-Indo-European character set.
|
||||
|
||||
### Screen Ruler
|
||||
### Registry Preview
|
||||
|
||||
- Added a Setting to also allow showing measurements in inches, centimeters or millimeters. Thanks [@Sophanatprime](https://github.com/Sophanatprime)!
|
||||
- Fixed an issue causing line breaks to not be parsed correctly for REG_MULTI_SZ values. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added a tooltip to values to show multiple lines of data. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added a context menu to enable copying type, value and key paths. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
|
||||
### Settings
|
||||
|
||||
- Fixed an issue causing all the links to milestones in the "What's new?" OOBE page to point to the same milestone.
|
||||
- Removed extra space from the Welcome page. Thanks [@agarwalishita](https://github.com/agarwalishita)!
|
||||
- Updated left navigation bar icons. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
- Fixed accessibility issues in the dashboard page. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Made the Advanced Paste paste OpenAI configuration modal scrollable.
|
||||
- Fixed the text on the Quick Accent page to refer to "character sets" instead of "character set". Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added the plugin's dll file version and website to the PowerToys Run plugin settings. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added the Workspaces file to the list of files that gets backed up by the Back up / Restore functionality.
|
||||
- Fixed an issue causing some of the selected character sets to be unselected when opening the character set expander in the Quick Accent page.
|
||||
- Improved GPO logic, icons, info bar layout and enabled state of all modules settings pages. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed some accessibility issues and refactored and improved quality of the code related to image sizes in the Image Resizer page. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed mentions of "Backup" to "Back up" when it should be used as a verb. Thanks [@JackStuart](https://github.com/JackStuart)!
|
||||
- Added a "New" label to Settings to better highlight new utilities that get released. Thanks [@niels9001](https://github.com/niels9001) for the UI tweaks!
|
||||
|
||||
### Text Extractor
|
||||
|
||||
- Fixed many accessibility and UI issues on the overlay UI. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Workspaces
|
||||
|
||||
- Added support for Progressive Web Applications to Workspaces.
|
||||
- Implemented a feature to move existing windows instead of creating new ones.
|
||||
- Fixed a crash when opening the workspaces editor that was caused by passing incorrect encoder parameters when saving Bitmap files.
|
||||
- Workspaces editor position is now saved so that we can start it at the same position when we open it again.
|
||||
- Fixed an issue causing many instances of the same application to be put in the same position instead of the intended position due to timer issues.
|
||||
- Fixed detection of exact application version when many versions of the same application are installed.
|
||||
- Fixed an issue causing the Workspaces Editor to start outside of visible desktop area.
|
||||
- Fixed an issue to maintain command line arguments for applications when trying using the "Launch and Edit" feature.
|
||||
|
||||
### Video Conference Mute
|
||||
|
||||
- The module has been deprecated in 0.88.0, being removed from PowerToys.
|
||||
|
||||
### ZoomIt
|
||||
|
||||
- New utility: Zoom It - a screen zoom, annotation, and recording tool for technical presentations and demos. This utility from Sysinternals has had its source code released and included in PowerToys. ZoomIt will still continue to be updated and shipped by Sysinternals for users who prefer to have it as a standalone utility outside of PowerToys. Thanks [@markrussinovich](https://github.com/markrussinovich), [@foxmsft](https://github.com/foxmsft) and [@johnstep](https://github.com/johnstep) for contributing the original code and reviewing the PowerToys integration!
|
||||
|
||||
### Documentation
|
||||
|
||||
- Improved language in CONTRIBUTE.md. Thanks [@sanskaarz](https://github.com/sanskaarz)!
|
||||
- Added Bilibili plugin mention to thirdPartyRunPlugins.md. Thanks [@Whuihuan](https://github.com/Whuihuan)!
|
||||
- Added CanIUse and TailwindCSS plugins mention to thirdPartyRunPlugins.md. Thanks [@skttl](https://github.com/skttl)!
|
||||
- Added HttpStatusCodes plugin mention to thirdPartyRunPlugins.md. Thanks [@grzhan](https://github.com/grzhan)!
|
||||
- Updated COMMUNITY.md with more contributors.
|
||||
- Updated the PowerToys Run documentation to reflect documentation pages for new plugins.
|
||||
- Added YubicoOauthOTP plugin mention to thirdPartyRunPlugins.md. Thanks [@dlnilsson](https://github.com/dlnilsson)!
|
||||
|
||||
### Development
|
||||
|
||||
- Upgraded to .NET 9. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Fixed building on Visual Studio 17.12.
|
||||
- Upgraded the System.IO.Abstractions dependency to 21.0.29. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Upgraded the WindowsAppSDK dependency to 1.6.241114003. Thanks [@shuaiyuanxx](https://github.com/shuaiyuanxx)!
|
||||
- Upgraded the MSTest dependency to 3.6.3. Thanks [@Youssef1313](https://github.com/Youssef1313)!
|
||||
- Upgraded the check-spelling CI dependency to 0.0.24 and fixed related spell checking issues. Thanks [@jsoref](https://github.com/jsoref)!
|
||||
- Removed duplicate names from the spellcheck allowed names file. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Improved logging of asynchronous methods call stacks when logging an error.
|
||||
- Created a MSBuild props file to be imported by other projects to enable AOT support.
|
||||
- Made the Peek utility source code AOT compatible.
|
||||
- Updated .editorconfig rules to relax squiggly IDE errors in Visual Studio 17.12. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Moved Xaml.Styler from the root to the src folder.
|
||||
- Added fuzz testing for AdvancedPaste, with a new pipeline for OneFuzz.
|
||||
- Added a new CI pipeline to build with the latest WindowsAppSDK.
|
||||
- Added a new CI pipeline to build with the latest webview2 from Edge Canary.
|
||||
- Made the HostsUILib project AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Made FilePreviewCommon and MarkdownPreviewHandler AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Made the PowerAccent.Core project AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Cleaned up some code for AOT compatibility in the Advanced Paste module. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Removed the prerelease flag from the PowerToys development DSC configurations. Thanks [@denelon](https://github.com/denelon)!
|
||||
- Improved Dart CI reliability by improving error messages and retrying to the step that installs the correct dotnet version.
|
||||
- Improved Dart CI reliability by fixing retries when downloading the localization files.
|
||||
- Improved Dart CI build times by removing the steps to build the no longer needed abstracted utility nuget packages.
|
||||
- Removed the solution.props file from the solution root.
|
||||
- Fixed PowerToys Run Calculator plugin tests when running in systems with different number formats. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Updated many .NET packages from .NET 9.0.0 to 9.0.1 for security fixes. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Refactored the Mouse Without Borders Common.Log.cs and Common.Receiver.cs files. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
|
||||
#### What is being planned for version 0.88
|
||||
#### What is being planned for version 0.89
|
||||
|
||||
For [v0.88][github-next-release-work], we'll work on the items below:
|
||||
For [v0.89][github-next-release-work], we'll work on the items below:
|
||||
|
||||
- Stability / bug fixes
|
||||
- New module: File Actions Menu
|
||||
- Integrate Sysinternals ZoomIt
|
||||
- PowerToys Run v2 development work
|
||||
|
||||
## PowerToys Community
|
||||
|
||||
|
||||
91
doc/devdocs/UITests.md
Normal file
91
doc/devdocs/UITests.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# UI tests framework
|
||||
|
||||
A specialized UI test framework for PowerToys that makes it easy to write UI tests for PowerToys modules or settings. Let's start writing UI tests!
|
||||
|
||||
## Before running tests
|
||||
|
||||
- Install Windows Application Driver v1.2.1 from https://github.com/microsoft/WinAppDriver/releases/tag/v1.2.1 to the default directory (`C:\Program Files (x86)\Windows Application Driver`)
|
||||
|
||||
- Enable Developer Mode in Windows settings
|
||||
|
||||
## Running tests
|
||||
|
||||
- Exit PowerToys if it's running.
|
||||
|
||||
- Open `PowerToys.sln` in Visual Studio and build the solution.
|
||||
|
||||
- Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`).
|
||||
|
||||
|
||||
## How to add the first UI tests for your modules
|
||||
|
||||
- Create a new project and add the following references to the project file. Change the OutputPath to your own module's path.
|
||||
```
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<!-- This is a UI test, so don't run as part of MSBuild -->
|
||||
<RunVSTest>false</RunVSTest>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\KeyboardManagerUITests\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MSTest" />
|
||||
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
```
|
||||
- Inherit your test class from UITestBase.
|
||||
>Set Scope: The default scope starts from the PowerToys settings UI. If you want to start from your own module, set the constructor as shown below:
|
||||
|
||||
>Specify Scope:
|
||||
```
|
||||
[TestClass]
|
||||
public class RunFancyZonesTest : UITestBase
|
||||
{
|
||||
public RunFancyZonesTest()
|
||||
: base(PowerToysModule.FancyZone)
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Then you can start using session to perform the UI operations.
|
||||
|
||||
**Example**
|
||||
```
|
||||
using Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UITests_KeyboardManager
|
||||
{
|
||||
[TestClass]
|
||||
public class RunKeyboardManagerUITests : UITestBase
|
||||
{
|
||||
[TestMethod]
|
||||
public void OpenKeyboardManagerEditor()
|
||||
{
|
||||
// Open KeyboardManagerEditor
|
||||
this.Session.Find<Button>(By.Name("Remap a key")).Click();
|
||||
this.Session.Attach("Remap keys");
|
||||
|
||||
// Maximize window
|
||||
var window = Session.Find<Window>(By.Name("Remap keys")).Maximize();
|
||||
|
||||
// Add Key Remapping
|
||||
this.Session.Find<Button>(By.Name("Add key remapping")).Click();
|
||||
window.Close();
|
||||
|
||||
// Back to Settings
|
||||
this.Session.Attach(PowerToysModule.PowerToysSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Extra tools and information
|
||||
|
||||
**Accessibility Tools**:
|
||||
While working on tests, you may need a tool that helps you to view the element's accessibility data, e.g. for finding the button to click. For this purpose, you could use [AccessibilityInsights](https://accessibilityinsights.io/docs/windows/overview)
|
||||
@@ -3,8 +3,9 @@
|
||||
- [ ] The plugin is a project under `modules\launcher\Plugins`
|
||||
- [ ] Microsoft plugin project name pattern: `Microsoft.PowerToys.Run.Plugin.{PluginName}`
|
||||
- [ ] Community plugin project name pattern: `Community.PowerToys.Run.Plugin.{PluginName}`
|
||||
- [ ] The plugin target framework should be `net8.0-windows`
|
||||
- [ ] The plugin target framework should be `net9.0-windows10.0.22621.0`
|
||||
- [ ] If the plugin uses any 3rd party dependencies the project file should import `DynamicPlugin.props`
|
||||
- [ ] 3rd party dependencies must be compatible with .NET 9
|
||||
- [ ] The plugin has to contain a `plugin.json` file of the following format in its root folder:
|
||||
|
||||
```json
|
||||
@@ -35,7 +36,6 @@ public static string PluginID => "xxxxxxx"; // The part xxxxxxx stands for the p
|
||||
- [ ] Plugin's output code and assets have to be included in the installer [`Product.wxs`](/installer/PowerToysSetup/Product.wxs)
|
||||
- [ ] Test the plugin with a local build. Build the installer, install, check that the plugin works as expected
|
||||
- [ ] All plugin's binaries have to be included in the signed build [`pipeline.user.windows.yml`](/.pipelines/pipeline.user.windows.yml)
|
||||
- [ ] The plugin target framework has to be net8.0-windows. All dependencies should be compatible with .NET 8.
|
||||
|
||||
Some localization steps can only be done after the first pass by the localization team to provide the localized resources.
|
||||
In the PR that adds a new plugin, reference a new issue to track the work for fully enabling localization for the new plugin.
|
||||
|
||||
@@ -4,18 +4,10 @@ Contains the executable starting point, initialization code and the list of know
|
||||
#### [`powertoy_module.h`](/src/runner/powertoy_module.h) and [`powertoy_module.cpp`](/src/runner/powertoy_module.cpp)
|
||||
Contains code for initializing and managing the PowerToy modules. `PowertoyModule` is a RAII-style holder for the `PowertoyModuleIface` pointer, which we got by [invoking module DLL's `powertoy_create` function](https://github.com/microsoft/PowerToys/blob/1760af50c8803588cb575167baae0439af38a9c1/src/runner/powertoy_module.cpp#L13-L24).
|
||||
|
||||
#### [`powertoys_events.cpp`](/src/runner/powertoys_events.cpp)
|
||||
Contains code that handles the various events listeners, and forwards those events to the PowerToys modules. You can learn more about the current event architecture in [shared hooks](/doc/devdocs/shared-hooks.md).
|
||||
|
||||
#### [`lowlevel_keyboard_event.cpp`](/src/runner/lowlevel_keyboard_event.cpp)
|
||||
Contains code for registering the low level keyboard event hook that listens for keyboard events. Please note that `signal_event` is called from the main thread for this event.
|
||||
|
||||
#### [`win_hook_event.cpp`](/src/runner/win_hook_event.cpp)
|
||||
Contains code for registering a Windows event hook through `SetWinEventHook`, that listens for various events raised when a window is interacted with. Please note, that `signal_event` is called from a separate `dispatch_thread_proc` worker thread, so you must provide thread-safety for your `signal_event` if you intend to receive it. This is a subject to change.
|
||||
|
||||
#### [`tray_icon.cpp`](/src/runner/tray_icon.cpp)
|
||||
Contains code for managing the PowerToys tray icon and its menu commands. Note that `dispatch_run_on_main_ui_thread` is used to
|
||||
transfer received json message from the [Settings window](/doc/devdocs/settings.md) to the main thread, since we're communicating with it from [a dedicated thread](https://github.com/microsoft/PowerToys/blob/7357e40d3f54de51176efe54fda6d57028837b8c/src/runner/settings_window.cpp#L267-L271).
|
||||
|
||||
#### [`settings_window.cpp`](/src/runner/settings_window.cpp)
|
||||
Contains code for starting the PowerToys settings window and communicating with it. Settings window is a separate process, so we're using [Windows pipes](https://learn.microsoft.com/windows/win32/ipc/pipes) as a transport for json messages.
|
||||
|
||||
@@ -33,3 +25,24 @@ Contains code for telemetry.
|
||||
|
||||
#### [`svgs`](/src/runner/svgs/)
|
||||
Contains the SVG assets used by the PowerToys modules.
|
||||
|
||||
#### [`bug_report.cpp`](/src/runner/bug_report.cpp)
|
||||
Contains logic to start bug report tool.
|
||||
|
||||
#### [`centralized_hotkeys.cpp`](/src/runner/centralized_hotkeys.cpp)
|
||||
Contains hot key logic registration and un-registration.
|
||||
|
||||
#### [`centralized_kb_hook.cpp`](/src/runner/centralized_kb_hook.cpp)
|
||||
Contains logic to handle PowerToys' keyboard shortcut functionality.
|
||||
|
||||
#### [`restart_elevated.cpp`](/src/runner/restart_elevated.cpp)
|
||||
Contains logic for restarting the current process with different elevation levels.
|
||||
|
||||
#### [`RestartManagement.cpp`](/src/runner/RestartManagement.cpp)
|
||||
Contains code for restarting a process.
|
||||
|
||||
#### [`settings_telemetry.cpp`](/src/runner/settings_telemetry.cpp)
|
||||
Contains logic that periodically triggers module-specific setting's telemetry delivery and manages timing and error handling for the process.
|
||||
|
||||
#### [`UpdateUtils.cpp`](/src/runner/UpdateUtils.cpp)
|
||||
Contains code to handle the automatic update checking, notification, and installation process for PowerToys.
|
||||
@@ -3,8 +3,8 @@
|
||||
The Settings v2 process uses two way IPC to communicate with the runner process.
|
||||
|
||||
## Initialization
|
||||
- On the settings' side, the two way IPC delegates are contained with the [`ShellPage.xaml.cs`](/src/settings-ui/Settings.UI/Views/ShellPage.xaml.cs) file. The delegates are static and the views for all the powerToys send the ipc information to the viewmodels as `ShellPage.DefaultSndMSGCallBack`.
|
||||
- These delegates are initialized within the [`MainWindow.xaml.cs`](/src/settings-ui/Settings.UI/MainWindow.xaml.cs) file in the `Settings.Runner` project.
|
||||
- On the settings' side, the two way IPC delegates are contained with the [`ShellPage.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs) file. The delegates are static and the views for all the powerToys send the ipc information to the viewmodels as `ShellPage.DefaultSndMSGCallBack`.
|
||||
- These delegates are initialized within the [`MainWindow.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/MainWindow.xaml.cs) file in the `Settings.Runner` project.
|
||||
|
||||
|
||||
## Types of IPC delegates
|
||||
@@ -14,12 +14,12 @@ The Settings v2 process uses two way IPC to communicate with the runner process.
|
||||
3. `CheckForUpdates`
|
||||
|
||||
## Sending information to runner
|
||||
- The settings process communicates with the runner by using the delegates defined within the [`ShellPage.xaml.cs`](/src/settings-ui/Settings.UI/Views/ShellPage.xaml.cs) file.
|
||||
- The settings process communicates with the runner by using the delegates defined within the [`ShellPage.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs) file.
|
||||
- Depending on the type of object sending the information, the json is created accordingly.
|
||||
- If any information has been modified by the user in the GeneralSettings page, then the json file sent to the runner has the name set to `general`, whereas if any information has been modified by the user in any powertoy related settings page, the name of the json file being communicated with the runner is set to `powertoy`.
|
||||
|
||||
## Receiving information from runner
|
||||
- The `ShellPage`object has a `IPCResponseHandleList` which is a list of functions which handle IPC responses.
|
||||
- The `ShellPage` object has a `IPCResponseHandleList` which is a list of functions which handle IPC responses.
|
||||
|
||||
```csharp
|
||||
// receive IPC Message
|
||||
@@ -43,4 +43,4 @@ Program.IPCMessageReceivedCallback = (string msg) =>
|
||||
```
|
||||
|
||||
- Whenever any information is sent from the runner each of the functions in the handle list perform their action on that json object.
|
||||
- One example of where information sent from the runner is being processed by the settings is in [`GeneralPage.xaml.cs`](/src/settings-ui/Settings.UI/Views/GeneralPage.xaml.cs) when the user clicks the check for updates button. The information displayed after, such as the user has the latest version installed is a result of this handle.
|
||||
- One example of where information sent from the runner is being processed by the settings is in [`GeneralPage.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs) when the user clicks the check for updates button. The information displayed after, such as the user has the latest version installed is a result of this handle.
|
||||
|
||||
@@ -200,6 +200,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbDisallowBlockingScreensaverValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbAllowServiceModeValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbAllowServiceModeValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbSameSubnetOnlyValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbSameSubnetOnlyValue());
|
||||
@@ -228,4 +232,8 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowDataDiagnosticsValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredRunAtStartupValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredRunAtStartupValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,12 +56,14 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredMwbFileTransferEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbUseOriginalUserInterfaceValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisallowBlockingScreensaverValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbAllowServiceModeValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbSameSubnetOnlyValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbValidateRemoteIpValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisableUserDefinedIpMappingRulesValue();
|
||||
static winrt::hstring GPOWrapper::GetConfiguredMwbPolicyDefinedIpMappingRules();
|
||||
static GpoRuleConfigured GetConfiguredNewPlusHideTemplateFilenameExtensionValue();
|
||||
static GpoRuleConfigured GetAllowDataDiagnosticsValue();
|
||||
static GpoRuleConfigured GetConfiguredRunAtStartupValue();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -60,12 +60,14 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredMwbFileTransferEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbUseOriginalUserInterfaceValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisallowBlockingScreensaverValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbAllowServiceModeValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbSameSubnetOnlyValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbValidateRemoteIpValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisableUserDefinedIpMappingRulesValue();
|
||||
static String GetConfiguredMwbPolicyDefinedIpMappingRules();
|
||||
static GpoRuleConfigured GetConfiguredNewPlusHideTemplateFilenameExtensionValue();
|
||||
static GpoRuleConfigured GetAllowDataDiagnosticsValue();
|
||||
static GpoRuleConfigured GetConfiguredRunAtStartupValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
src/common/UITestAutomation/Element/Button.cs
Normal file
20
src/common/UITestAutomation/Element/Button.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// 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 Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
using OpenQA.Selenium.Remote;
|
||||
using OpenQA.Selenium.Support.Events;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a button in the UI test environment.
|
||||
/// </summary>
|
||||
public class Button : Element
|
||||
{
|
||||
}
|
||||
}
|
||||
69
src/common/UITestAutomation/Element/By.cs
Normal file
69
src/common/UITestAutomation/Element/By.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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 static OpenQA.Selenium.By;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a By selector.
|
||||
/// </summary>
|
||||
public class By
|
||||
{
|
||||
private readonly OpenQA.Selenium.By by;
|
||||
|
||||
private By(OpenQA.Selenium.By by)
|
||||
{
|
||||
this.by = by;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the name attribute.
|
||||
/// </summary>
|
||||
/// <param name="name">The name attribute to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By Name(string name) => new By(OpenQA.Selenium.By.Name(name));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the ID attribute.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID attribute to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By Id(string id) => new By(OpenQA.Selenium.By.Id(id));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the XPath expression.
|
||||
/// </summary>
|
||||
/// <param name="xpath">The XPath expression to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By XPath(string xpath) => new By(OpenQA.Selenium.By.XPath(xpath));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the CSS selector.
|
||||
/// </summary>
|
||||
/// <param name="cssSelector">The CSS selector to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By CssSelector(string cssSelector) => new By(OpenQA.Selenium.By.CssSelector(cssSelector));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the link text.
|
||||
/// </summary>
|
||||
/// <param name="linkText">The link text to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By LinkText(string linkText) => new By(OpenQA.Selenium.By.LinkText(linkText));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the tag name.
|
||||
/// </summary>
|
||||
/// <param name="tagName">The tag name to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By TagName(string tagName) => new By(OpenQA.Selenium.By.TagName(tagName));
|
||||
|
||||
/// <summary>
|
||||
/// Converts the By object to an OpenQA.Selenium.By object.
|
||||
/// </summary>
|
||||
/// <returns>An OpenQA.Selenium.By object.</returns>
|
||||
internal OpenQA.Selenium.By ToSeleniumBy() => by;
|
||||
}
|
||||
}
|
||||
185
src/common/UITestAutomation/Element/Element.cs
Normal file
185
src/common/UITestAutomation/Element/Element.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
using OpenQA.Selenium.Remote;
|
||||
using OpenQA.Selenium.Support.Events;
|
||||
using static Microsoft.PowerToys.UITest.UITestBase;
|
||||
|
||||
[assembly: InternalsVisibleTo("Session")]
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a basic UI element in the application.
|
||||
/// </summary>
|
||||
public class Element
|
||||
{
|
||||
private WindowsElement? windowsElement;
|
||||
private WindowsDriver<WindowsElement>? driver;
|
||||
|
||||
internal void SetWindowsElement(WindowsElement windowsElement) => this.windowsElement = windowsElement;
|
||||
|
||||
internal void SetSession(WindowsDriver<WindowsElement> driver) => this.driver = driver;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the UI element.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return GetAttribute("Name"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the text of the UI element.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get { return GetAttribute("Value"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the AutomationID of the UI element.
|
||||
/// </summary>
|
||||
public string AutomationId
|
||||
{
|
||||
get { return GetAttribute("AutomationId"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the class name of the UI element.
|
||||
/// </summary>
|
||||
public string ClassName
|
||||
{
|
||||
get { return GetAttribute("ClassName"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the help text of the UI element.
|
||||
/// </summary>
|
||||
public string HelpText
|
||||
{
|
||||
get { return GetAttribute("HelpText"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the control type of the UI element.
|
||||
/// </summary>
|
||||
public string ControlType
|
||||
{
|
||||
get { return GetAttribute("ControlType"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the UI element is enabled.
|
||||
/// </summary>
|
||||
/// <returns>True if the element is enabled; otherwise, false.</returns>
|
||||
public bool IsEnabled() => GetAttribute("IsEnabled") == "True";
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the UI element is selected.
|
||||
/// </summary>
|
||||
/// <returns>True if the element is selected; otherwise, false.</returns>
|
||||
public bool IsSelected() => GetAttribute("IsSelected") == "True";
|
||||
|
||||
/// <summary>
|
||||
/// Click the UI element.
|
||||
/// </summary>
|
||||
/// <param name="rightClick">If true, performs a right-click; otherwise, performs a left-click.</param>
|
||||
public void Click(bool rightClick = false)
|
||||
{
|
||||
PerformAction(actions =>
|
||||
{
|
||||
if (rightClick)
|
||||
{
|
||||
actions.ContextClick();
|
||||
}
|
||||
else
|
||||
{
|
||||
actions.Click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attribute value of the UI element.
|
||||
/// </summary>
|
||||
/// <param name="attributeName">The name of the attribute to get.</param>
|
||||
/// <returns>The value of the attribute.</returns>
|
||||
public string GetAttribute(string attributeName)
|
||||
{
|
||||
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method GetAttribute with parameter: attributeName = {attributeName}");
|
||||
var attributeValue = this.windowsElement.GetAttribute(attributeName);
|
||||
Assert.IsNotNull(attributeValue, $"Attribute '{attributeName}' is null.");
|
||||
return attributeValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an element by the selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class type of the element to find.</typeparam>
|
||||
/// <param name="by">The selector to use for finding the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public T Find<T>(By by, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method Find<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElement = FindElementHelper.Find<T, AppiumWebElement>(
|
||||
() =>
|
||||
{
|
||||
var element = this.windowsElement.FindElement(by.ToSeleniumBy());
|
||||
Assert.IsNotNull(element, $"Element not found using selector: {by}");
|
||||
return element;
|
||||
},
|
||||
this.driver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElement;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by the selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class type of the elements to find.</typeparam>
|
||||
/// <param name="by">The selector to use for finding the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<T>? FindAll<T>(By by, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method FindAll<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElements = FindElementHelper.FindAll<T, AppiumWebElement>(
|
||||
() =>
|
||||
{
|
||||
var elements = this.windowsElement.FindElements(by.ToSeleniumBy());
|
||||
Assert.IsTrue(elements.Count > 0, $"Elements not found using selector: {by}");
|
||||
return elements;
|
||||
},
|
||||
this.driver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElements;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a manual operation on the element.
|
||||
/// </summary>
|
||||
private void PerformAction(Action<Actions> action)
|
||||
{
|
||||
var element = this.windowsElement;
|
||||
Actions actions = new Actions(this.driver);
|
||||
actions.MoveToElement(element);
|
||||
action(actions);
|
||||
actions.Build().Perform();
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/common/UITestAutomation/Element/FindElementHelper.cs
Normal file
60
src/common/UITestAutomation/Element/FindElementHelper.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
|
||||
[assembly: InternalsVisibleTo("Element")]
|
||||
[assembly: InternalsVisibleTo("Session")]
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class for finding elements.
|
||||
/// </summary>
|
||||
internal static class FindElementHelper
|
||||
{
|
||||
public static T Find<T, TW>(Func<TW> findElementFunc, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
where T : Element, new()
|
||||
{
|
||||
var item = findElementFunc() as WindowsElement;
|
||||
return NewElement<T>(item, driver, timeoutMS);
|
||||
}
|
||||
|
||||
public static ReadOnlyCollection<T>? FindAll<T, TW>(Func<ReadOnlyCollection<TW>> findElementsFunc, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
where T : Element, new()
|
||||
{
|
||||
var items = findElementsFunc();
|
||||
var res = items.Select(item =>
|
||||
{
|
||||
var element = item as WindowsElement;
|
||||
return NewElement<T>(element, driver, timeoutMS);
|
||||
}).ToList();
|
||||
|
||||
return new ReadOnlyCollection<T>(res);
|
||||
}
|
||||
|
||||
public static T NewElement<T>(WindowsElement? element, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(driver, $"New Element {typeof(T).Name} error: driver is null.");
|
||||
Assert.IsNotNull(element, $"New Element {typeof(T).Name} error: element is null.");
|
||||
|
||||
T newElement = new T();
|
||||
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(timeoutMS);
|
||||
newElement.SetSession(driver);
|
||||
newElement.SetWindowsElement(element);
|
||||
return newElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
92
src/common/UITestAutomation/Element/Window.cs
Normal file
92
src/common/UITestAutomation/Element/Window.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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 Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
using OpenQA.Selenium.Remote;
|
||||
using OpenQA.Selenium.Support.Events;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a window in the UI test environment.
|
||||
/// </summary>
|
||||
public class Window : Element
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximizes the window.
|
||||
/// </summary>
|
||||
/// <param name="byClickButton">If true, clicks the Maximize button; otherwise, sets the window state.</param>
|
||||
/// <returns>The current Window instance.</returns>
|
||||
public Window Maximize(bool byClickButton = true)
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Maximize")).Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Implement maximizing the window using an alternative method
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores the window.
|
||||
/// </summary>
|
||||
/// <param name="byClickButton">If true, clicks the Restore button; otherwise, sets the window state.</param>
|
||||
/// <returns>The current Window instance.</returns>
|
||||
public Window Restore(bool byClickButton = true)
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Restore")).Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Implement restoring the window using an alternative method
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimizes the window.
|
||||
/// </summary>
|
||||
/// <param name="byClickButton">If true, clicks the Minimize button; otherwise, sets the window state.</param>
|
||||
/// <returns>The current Window instance.</returns>
|
||||
public Window Minimize(bool byClickButton = true)
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Minimize")).Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Implement minimizing the window using an alternative method
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the window.
|
||||
/// </summary>
|
||||
/// <param name="byClickButton">If true, clicks the Close button; otherwise, closes the window using an alternative method.</param>
|
||||
public void Close(bool byClickButton = true)
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Close")).Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Implement closing the window using an alternative method
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/common/UITestAutomation/ModuleConfigData.cs
Normal file
72
src/common/UITestAutomation/ModuleConfigData.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("UITestBase")]
|
||||
[assembly: InternalsVisibleTo("Session")]
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// This file manages the configuration of modules for UI tests.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// How to add a new module:
|
||||
/// 1. Define the new module in the PowerToysModule enum.
|
||||
/// 2. Add the exe window name to the ModuleWindowName dictionary in the ModuleConfigData constructor.
|
||||
/// 3. Add the exe path to the ModulePath dictionary in the ModuleConfigData constructor.
|
||||
/// </remarks>
|
||||
|
||||
/// <summary>
|
||||
/// Represents the modules in PowerToys.
|
||||
/// </summary>
|
||||
public enum PowerToysModule
|
||||
{
|
||||
PowerToysSettings,
|
||||
FancyZone,
|
||||
Hosts,
|
||||
}
|
||||
|
||||
internal class ModuleConfigData
|
||||
{
|
||||
private Dictionary<PowerToysModule, string> ModulePath { get; }
|
||||
|
||||
// Singleton instance of ModuleConfigData.
|
||||
private static readonly Lazy<ModuleConfigData> SingletonInstance = new Lazy<ModuleConfigData>(() => new ModuleConfigData());
|
||||
|
||||
public static ModuleConfigData Instance => SingletonInstance.Value;
|
||||
|
||||
public const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
|
||||
|
||||
public Dictionary<PowerToysModule, string> ModuleWindowName { get; }
|
||||
|
||||
private ModuleConfigData()
|
||||
{
|
||||
// The exe window name for each module.
|
||||
ModuleWindowName = new Dictionary<PowerToysModule, string>
|
||||
{
|
||||
[PowerToysModule.PowerToysSettings] = "PowerToys Settings",
|
||||
[PowerToysModule.FancyZone] = "FancyZones Layout",
|
||||
[PowerToysModule.Hosts] = "Hosts File Editor",
|
||||
};
|
||||
|
||||
// Exe start path for the module if it exists.
|
||||
ModulePath = new Dictionary<PowerToysModule, string>
|
||||
{
|
||||
[PowerToysModule.PowerToysSettings] = @"\..\..\..\WinUI3Apps\PowerToys.Settings.exe",
|
||||
[PowerToysModule.FancyZone] = @"\..\..\..\PowerToys.FancyZonesEditor.exe",
|
||||
[PowerToysModule.Hosts] = @"\..\..\..\WinUI3Apps\PowerToys.Hosts.exe",
|
||||
};
|
||||
}
|
||||
|
||||
public string GetModulePath(PowerToysModule scope) => ModulePath[scope];
|
||||
|
||||
public string GetWindowsApplicationDriverUrl() => WindowsApplicationDriverUrl;
|
||||
|
||||
public string GetModuleWindowName(PowerToysModule scope) => ModuleWindowName[scope];
|
||||
}
|
||||
}
|
||||
129
src/common/UITestAutomation/Session.cs
Normal file
129
src/common/UITestAutomation/Session.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides interfaces for interacting with UI elements.
|
||||
/// </summary>
|
||||
public class Session
|
||||
{
|
||||
private WindowsDriver<WindowsElement> Root { get; set; }
|
||||
|
||||
private WindowsDriver<WindowsElement> WindowsDriver { get; set; }
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetForegroundWindow(nint hWnd);
|
||||
|
||||
public Session(WindowsDriver<WindowsElement> root, WindowsDriver<WindowsElement> windowsDriver)
|
||||
{
|
||||
this.Root = root;
|
||||
this.WindowsDriver = windowsDriver;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an element by selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the element, should be Element or its derived class.</typeparam>
|
||||
/// <param name="by">The selector to find the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public T Find<T>(By by, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.WindowsDriver, $"WindowsElement is null in method Find<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElement = FindElementHelper.Find<T, WindowsElement>(
|
||||
() =>
|
||||
{
|
||||
var element = this.WindowsDriver.FindElement(by.ToSeleniumBy());
|
||||
Assert.IsNotNull(element, $"Element not found using selector: {by}");
|
||||
return element;
|
||||
},
|
||||
this.WindowsDriver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElement;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the elements, should be Element or its derived class.</typeparam>
|
||||
/// <param name="by">The selector to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<T>? FindAll<T>(By by, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.WindowsDriver, $"WindowsElement is null in method FindAll<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElements = FindElementHelper.FindAll<T, WindowsElement>(
|
||||
() =>
|
||||
{
|
||||
var elements = this.WindowsDriver.FindElements(by.ToSeleniumBy());
|
||||
Assert.IsTrue(elements.Count > 0, $"Elements not found using selector: {by}");
|
||||
return elements;
|
||||
},
|
||||
this.WindowsDriver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElements;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attaches to an existing PowerToys module.
|
||||
/// </summary>
|
||||
/// <param name="module">The PowerToys module to attach to.</param>
|
||||
/// <returns>The attached session.</returns>
|
||||
public Session Attach(PowerToysModule module)
|
||||
{
|
||||
string windowName = ModuleConfigData.Instance.GetModuleWindowName(module);
|
||||
return this.Attach(windowName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attaches to an existing exe by string window name.
|
||||
/// The session should be attached when a new app is started.
|
||||
/// </summary>
|
||||
/// <param name="windowName">The window name to attach to.</param>
|
||||
/// <returns>The attached session.</returns>
|
||||
public Session Attach(string windowName)
|
||||
{
|
||||
if (this.Root != null)
|
||||
{
|
||||
var window = this.Root.FindElementByName(windowName);
|
||||
Assert.IsNotNull(window, $"Failed to attach. Window '{windowName}' not found");
|
||||
|
||||
var windowHandle = new nint(int.Parse(window.GetAttribute("NativeWindowHandle")));
|
||||
SetForegroundWindow(windowHandle);
|
||||
var hexWindowHandle = windowHandle.ToString("x");
|
||||
var appCapabilities = new AppiumOptions();
|
||||
appCapabilities.AddAdditionalCapability("appTopLevelWindow", hexWindowHandle);
|
||||
appCapabilities.AddAdditionalCapability("deviceName", "WindowsPC");
|
||||
this.WindowsDriver = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), appCapabilities);
|
||||
Assert.IsNotNull(this.WindowsDriver, "Attach WindowsDriver is null");
|
||||
|
||||
// Set implicit timeout to make element search retry every 500 ms
|
||||
this.WindowsDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsNotNull(this.Root, $"Failed to attach to the window '{windowName}'. Root driver is null");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/common/UITestAutomation/UITestAutomation.csproj
Normal file
21
src/common/UITestAutomation/UITestAutomation.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PublishAot>true</PublishAot>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Appium.WebDriver" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
130
src/common/UITestAutomation/UITestBase.cs
Normal file
130
src/common/UITestAutomation/UITestBase.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class that should be inherited by all Test Classes.
|
||||
/// </summary>
|
||||
public class UITestBase
|
||||
{
|
||||
public Session Session { get; set; }
|
||||
|
||||
private readonly TestInit testInit = new TestInit();
|
||||
|
||||
public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
this.testInit.SetScope(scope);
|
||||
this.testInit.Init();
|
||||
this.Session = new Session(this.testInit.GetRoot(), this.testInit.GetDriver());
|
||||
}
|
||||
|
||||
~UITestBase()
|
||||
{
|
||||
this.testInit.Cleanup();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nested class for test initialization.
|
||||
/// </summary>
|
||||
private sealed class TestInit
|
||||
{
|
||||
private WindowsDriver<WindowsElement> Root { get; set; }
|
||||
|
||||
private WindowsDriver<WindowsElement>? Driver { get; set; }
|
||||
|
||||
private static Process? appDriver;
|
||||
|
||||
// Default session path is PowerToys settings dashboard
|
||||
private static string sessionPath = ModuleConfigData.Instance.GetModulePath(PowerToysModule.PowerToysSettings);
|
||||
|
||||
public TestInit()
|
||||
{
|
||||
appDriver = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe",
|
||||
Verb = "runas",
|
||||
});
|
||||
|
||||
var desktopCapabilities = new AppiumOptions();
|
||||
desktopCapabilities.AddAdditionalCapability("app", "Root");
|
||||
this.Root = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), desktopCapabilities);
|
||||
|
||||
// Set default timeout to 5 seconds
|
||||
this.Root.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test environment.
|
||||
/// </summary>
|
||||
[UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "<Pending>")]
|
||||
public void Init()
|
||||
{
|
||||
string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
this.StartExe(path + sessionPath);
|
||||
|
||||
Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null.");
|
||||
|
||||
// Set default timeout to 5 seconds
|
||||
this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up the test environment.
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
appDriver?.Kill();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle exceptions if needed
|
||||
Debug.WriteLine($"Exception during Cleanup: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new exe and takes control of it.
|
||||
/// </summary>
|
||||
/// <param name="appPath">The path to the application executable.</param>
|
||||
public void StartExe(string appPath)
|
||||
{
|
||||
var opts = new AppiumOptions();
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
this.Driver = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), opts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets scope to the Test Class.
|
||||
/// </summary>
|
||||
/// <param name="scope">The PowerToys module to start.</param>
|
||||
public void SetScope(PowerToysModule scope)
|
||||
{
|
||||
sessionPath = ModuleConfigData.Instance.GetModulePath(scope);
|
||||
}
|
||||
|
||||
public WindowsDriver<WindowsElement> GetRoot() => this.Root;
|
||||
|
||||
public WindowsDriver<WindowsElement> GetDriver()
|
||||
{
|
||||
Assert.IsNotNull(this.Driver, $"Failed to get driver. Driver is null.");
|
||||
return this.Driver;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,12 +82,20 @@ namespace updating
|
||||
// prevent the warning that may show up depend on the value of the constants (#defines)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4702)
|
||||
#if USE_STD_EXPECTED
|
||||
std::future<std::expected<github_version_info, std::wstring>> get_github_version_info_async(const bool prerelease)
|
||||
#else
|
||||
std::future<nonstd::expected<github_version_info, std::wstring>> get_github_version_info_async(const bool prerelease)
|
||||
#endif
|
||||
{
|
||||
// If the current version starts with 0.0.*, it means we're on a local build from a farm and shouldn't check for updates.
|
||||
if constexpr (VERSION_MAJOR == 0 && VERSION_MINOR == 0)
|
||||
{
|
||||
#if USE_STD_EXPECTED
|
||||
co_return std::unexpected(LOCAL_BUILD_ERROR);
|
||||
#else
|
||||
co_return nonstd::make_unexpected(LOCAL_BUILD_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
try
|
||||
@@ -139,7 +147,11 @@ namespace updating
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#if USE_STD_EXPECTED
|
||||
co_return std::unexpected(NETWORK_ERROR);
|
||||
#else
|
||||
co_return nonstd::make_unexpected(NETWORK_ERROR);
|
||||
#endif
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
@@ -6,7 +6,14 @@
|
||||
#include <filesystem>
|
||||
#include <variant>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
//#if __MSVC_VERSION__ >= 1933 // MSVC begin to support std::unexpected in 19.33
|
||||
#if __has_include(<expected> ) // use the same way with excepted-lite to detect std::unexcepted, as using it as backup
|
||||
#include <expected>
|
||||
#define USE_STD_EXPECTED 1
|
||||
#else
|
||||
#include <expected.hpp>
|
||||
#define USE_STD_EXPECTED 0
|
||||
#endif
|
||||
|
||||
#include <common/version/helper.h>
|
||||
|
||||
@@ -27,7 +34,11 @@ namespace updating
|
||||
|
||||
std::future<std::optional<std::filesystem::path>> download_new_version(const new_version_download_info& new_version);
|
||||
std::filesystem::path get_pending_updates_path();
|
||||
#if USE_STD_EXPECTED
|
||||
std::future<std::expected<github_version_info, std::wstring>> get_github_version_info_async(const bool prerelease = false);
|
||||
#else
|
||||
std::future<nonstd::expected<github_version_info, std::wstring>> get_github_version_info_async(const bool prerelease = false);
|
||||
#endif
|
||||
void cleanup_updates();
|
||||
|
||||
// non-localized
|
||||
|
||||
@@ -73,12 +73,14 @@ namespace powertoys_gpo {
|
||||
// The registry value names for other PowerToys policies.
|
||||
const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation";
|
||||
const std::wstring POLICY_ALLOW_DATA_DIAGNOSTICS = L"AllowDataDiagnostics";
|
||||
const std::wstring POLICY_CONFIGURE_RUN_AT_STARTUP = L"ConfigureRunAtStartup";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS = L"PowerLauncherAllPluginsEnabledState";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS = L"AllowPowerToysAdvancedPasteOnlineAIModels";
|
||||
const std::wstring POLICY_MWB_CLIPBOARD_SHARING_ENABLED = L"MwbClipboardSharingEnabled";
|
||||
const std::wstring POLICY_MWB_FILE_TRANSFER_ENABLED = L"MwbFileTransferEnabled";
|
||||
const std::wstring POLICY_MWB_USE_ORIGINAL_USER_INTERFACE = L"MwbUseOriginalUserInterface";
|
||||
const std::wstring POLICY_MWB_DISALLOW_BLOCKING_SCREENSAVER = L"MwbDisallowBlockingScreensaver";
|
||||
const std::wstring POLICY_MWB_ALLOW_SERVICE_MODE = L"MwbAllowServiceMode";
|
||||
const std::wstring POLICY_MWB_SAME_SUBNET_ONLY = L"MwbSameSubnetOnly";
|
||||
const std::wstring POLICY_MWB_VALIDATE_REMOTE_IP = L"MwbValidateRemoteIp";
|
||||
const std::wstring POLICY_MWB_DISABLE_USER_DEFINED_IP_MAPPING_RULES = L"MwbDisableUserDefinedIpMappingRules";
|
||||
@@ -493,6 +495,11 @@ namespace powertoys_gpo {
|
||||
return getConfiguredValue(POLICY_ALLOW_DATA_DIAGNOSTICS);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredRunAtStartupValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_CONFIGURE_RUN_AT_STARTUP);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getRunPluginEnabledValue(std::string pluginID)
|
||||
{
|
||||
if (pluginID == "" || pluginID == " ")
|
||||
@@ -558,6 +565,11 @@ namespace powertoys_gpo {
|
||||
return getConfiguredValue(POLICY_MWB_DISALLOW_BLOCKING_SCREENSAVER);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbAllowServiceModeValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_MWB_ALLOW_SERVICE_MODE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbSameSubnetOnlyValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_MWB_SAME_SUBNET_ONLY);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
|
||||
#include "../logger/logger.h"
|
||||
#include "../version/version.h"
|
||||
|
||||
namespace package {
|
||||
inline BOOL IsWin11OrGreater()
|
||||
@@ -47,10 +48,14 @@ namespace package {
|
||||
for (auto const& package : packageManager.FindPackagesForUser({}))
|
||||
{
|
||||
const auto& packageFullName = std::wstring{ package.Id().FullName() };
|
||||
const auto& packageVersion = package.Id().Version();
|
||||
|
||||
if (packageFullName.contains(packageDisplayName))
|
||||
{
|
||||
return true;
|
||||
if (packageVersion.Major == VERSION_MAJOR && packageVersion.Minor == VERSION_MINOR && packageVersion.Revision == VERSION_REVISION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +77,7 @@ namespace package {
|
||||
// Declare use of an external location
|
||||
AddPackageOptions options;
|
||||
options.ExternalLocationUri(externalUri);
|
||||
options.ForceUpdateFromAnyVersion(true);
|
||||
|
||||
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);
|
||||
deploymentOperation.get();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.15" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.16" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyNamespaces>
|
||||
<target prefix="powertoys" namespace="Microsoft.Policies.PowerToys" />
|
||||
</policyNamespaces>
|
||||
<resources minRequiredRevision="1.15"/><!-- Last changed with PowerToys v0.88.0 -->
|
||||
<resources minRequiredRevision="1.16"/><!-- Last changed with PowerToys v0.89.0 -->
|
||||
<supportedOn>
|
||||
<definitions>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0)"/>
|
||||
@@ -24,6 +24,7 @@
|
||||
<definition name="SUPPORTED_POWERTOYS_0_85_0" displayName="$(string.SUPPORTED_POWERTOYS_0_85_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_86_0" displayName="$(string.SUPPORTED_POWERTOYS_0_86_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_88_0" displayName="$(string.SUPPORTED_POWERTOYS_0_88_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_89_0" displayName="$(string.SUPPORTED_POWERTOYS_0_89_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1)"/>
|
||||
</definitions>
|
||||
</supportedOn>
|
||||
@@ -535,6 +536,16 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureRunAtStartup" class="Both" displayName="$(string.ConfigureRunAtStartup)" explainText="$(string.ConfigureRunAtStartupDescription)" key="Software\Policies\PowerToys" valueName="ConfigureRunAtStartup">
|
||||
<parentCategory ref="GeneralSettings" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_89_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="PowerToysRunAllPluginsEnabledState" class="Both" displayName="$(string.PowerToysRunAllPluginsEnabledState)" explainText="$(string.PowerToysRunAllPluginsEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="PowerLauncherAllPluginsEnabledState">
|
||||
<parentCategory ref="PowerToysRun" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
|
||||
@@ -602,6 +613,16 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbAllowServiceMode" class="Machine" displayName="$(string.MwbAllowServiceMode)" explainText="$(string.MwbAllowServiceModeDescription)" key="Software\Policies\PowerToys" valueName="MwbAllowServiceMode">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_89_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbSameSubnetOnly" class="Both" displayName="$(string.MwbSameSubnetOnly)" explainText="$(string.MwbSameSubnetOnlyDescription)" key="Software\Policies\PowerToys" valueName="MwbSameSubnetOnly">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.15" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.16" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<displayName>PowerToys</displayName>
|
||||
<description>PowerToys</description>
|
||||
<resources>
|
||||
@@ -31,6 +31,7 @@
|
||||
<string id="SUPPORTED_POWERTOYS_0_85_0">PowerToys version 0.85.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_86_0">PowerToys version 0.86.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_88_0">PowerToys version 0.88.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_89_0">PowerToys version 0.89.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1">From PowerToys version 0.64.0 until PowerToys version 0.87.1</string>
|
||||
|
||||
<string id="ConfigureAllUtilityGlobalEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
@@ -111,6 +112,16 @@ If this setting is disabled, experimentation is not allowed.
|
||||
If this setting is enabled or not configured, the user can control diagnostic data sending in the PowerToys settings menu.
|
||||
|
||||
If this setting is disabled, diagnostic data sending is not allowed.
|
||||
</string>
|
||||
<string id="ConfigureRunAtStartupDescription">This policy configures the "run at startup" setting of PowerToys.
|
||||
|
||||
If you enable this setting, the "run at startup" setting will be always enabled and the user won't be able to disable it.
|
||||
|
||||
If you disable this setting, the "run at startup" setting will be always disabled and the user won't be able to enable it.
|
||||
|
||||
If you don't configure this setting, users are able to enable or disable "run at startup" at will.
|
||||
|
||||
Note: This only controls the PowerToys method that creates a scheduled task to start PowerToys at login. It doesn't control other custom auto-start methods that the user might try to use outside of PowerToys or manually creating/deleting a scheduled task.
|
||||
</string>
|
||||
<string id="PowerToysRunAllPluginsEnabledStateDescription">This policy configures the enabled state for all PowerToys Run plugins. All plugins will have the same state.
|
||||
|
||||
@@ -169,7 +180,14 @@ If you enable this policy, the user won't be able to enable the "block screensav
|
||||
|
||||
If you disable or don't configure this policy, the user takes control over the setting and can block the screensaver.
|
||||
</string>
|
||||
<string id="MwbAllowServiceModeDescription">This policy configures if the user is allowed to use Mouse Without Borders in Service Mode.
|
||||
|
||||
If this setting is enabled or not configured, the user can enable and use Mouse Without Borders in Service Mode.
|
||||
|
||||
If this setting is disabled, the user won't be able to enable or use Mouse Without Borders in Service Mode.
|
||||
|
||||
Note: As most other PowerToys policies, a restart of PowerToys is required for a change in this policy to take full effect.
|
||||
</string>
|
||||
<string id="MwbSameSubnetOnlyDescription">This policy configures if connections are only allowed in the same subnet.
|
||||
|
||||
If you enable this policy, the setting is enabled and only connections in the same subnet are allowed.
|
||||
@@ -264,12 +282,14 @@ If you don't configure this policy, the user takes control over the setting and
|
||||
<string id="MwbFileTransferEnabled">File transfer enabled</string>
|
||||
<string id="MwbUseOriginalUserInterface">Original user interface is available</string>
|
||||
<string id="MwbDisallowBlockingScreensaver">Disallow blocking screensaver on other machines</string>
|
||||
<string id="MwbAllowServiceMode">Allow Service Mode</string>
|
||||
<string id="MwbSameSubnetOnly">Connect only in same subnet</string>
|
||||
<string id="MwbValidateRemoteIp">Validate remote machine IP Address</string>
|
||||
<string id="MwbDisableUserDefinedIpMappingRules">Disable user defined IP Address mapping rules</string>
|
||||
<string id="MwbPolicyDefinedIpMappingRules">Predefined IP Address mapping rules</string>
|
||||
<string id="NewPlusHideTemplateFilenameExtension">Hide template filename extension</string>
|
||||
<string id="AllowDiagnosticData">Allow sending diagnostic data</string>
|
||||
<string id="ConfigureRunAtStartup">Configure the run at startup setting</string>
|
||||
</stringTable>
|
||||
|
||||
<presentationTable>
|
||||
|
||||
35
src/modules/Hosts/Hosts.FuzzTests/Fuzz.md
Normal file
35
src/modules/Hosts/Hosts.FuzzTests/Fuzz.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Create Fuzzing Tests in your .NET Code Project
|
||||
|
||||
This document provides a step-by-step guide for integrating fuzzing tests into your .NET project.
|
||||
|
||||
### Step1: Add a Fuzzing Test Project
|
||||
Create a new test project within your module folder. Ensure the project name follows the format *.FuzzTests*.
|
||||
|
||||
### step2: Add FuzzTests and OneFuzzConfig.json to your fuzzing test project
|
||||
Follow the instructions in [Fuzz.md](https://github.com/microsoft/PowerToys/blob/main/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Fuzz.md) from AdvancedPaste.FuzzTests to properly integrate fuzzing tests into your project.
|
||||
|
||||
Configuring **OneFuzzConfig.json**:
|
||||
1. Update the dll, class, method, and FuzzingTargetBinaries field in the fuzzers list.
|
||||
2. Modify the AssignedTo field in the adoTemplate list.
|
||||
3. Set the jobNotificationEmail to your Microsoft email account.
|
||||
4. Update the projectName and targetName fields in the oneFuzzJobs list.
|
||||
5. Define job dependencies in the following directory:
|
||||
Example:
|
||||
```PowerToys\x64\Debug\tests\Hosts.FuzzTests\net8.0-windows10.0.19041.0```
|
||||
|
||||
|
||||
# step3: Configure the OneFuzz Pipeline
|
||||
Modify the patterns in the job steps within [job-fuzz.yml](https://github.com/microsoft/PowerToys/blob/main/.pipelines/v2/templates/job-fuzz.yml) to match your fuzzing project name.
|
||||
|
||||
Example:
|
||||
```
|
||||
- download: current
|
||||
displayName: Download artifacts
|
||||
artifact: $(ArtifactName)
|
||||
patterns: |-
|
||||
**/tests/Hosts.FuzzTests/**
|
||||
```
|
||||
|
||||
|
||||
# step4: Submit OneFuzz Pipeline and Verify Results on the OneFuzz Platform
|
||||
After executing the tests, check your email for the job link. Click the link to review the fuzzing test results.
|
||||
101
src/modules/Hosts/Hosts.FuzzTests/FuzzTests.cs
Normal file
101
src/modules/Hosts/Hosts.FuzzTests/FuzzTests.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions.TestingHelpers;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Hosts.Tests.Mocks;
|
||||
using HostsUILib.Helpers;
|
||||
using HostsUILib.Models;
|
||||
using HostsUILib.Settings;
|
||||
using Moq;
|
||||
|
||||
namespace Hosts.FuzzTests
|
||||
{
|
||||
public class FuzzTests
|
||||
{
|
||||
private static Mock<IUserSettings> _userSettings;
|
||||
private static Mock<IElevationHelper> _elevationHelper;
|
||||
|
||||
// Case1: Fuzzing method for ValidIPv4
|
||||
public static void FuzzValidIPv4(ReadOnlySpan<byte> input)
|
||||
{
|
||||
try
|
||||
{
|
||||
string address = System.Text.Encoding.UTF8.GetString(input);
|
||||
bool isValid = ValidationHelper.ValidIPv4(address);
|
||||
}
|
||||
catch (Exception ex) when (ex is RegexMatchTimeoutException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Case2: fuzzing method for ValidIPv6
|
||||
public static void FuzzValidIPv6(ReadOnlySpan<byte> input)
|
||||
{
|
||||
try
|
||||
{
|
||||
string address = System.Text.Encoding.UTF8.GetString(input);
|
||||
bool isValid = ValidationHelper.ValidIPv6(address);
|
||||
}
|
||||
catch (Exception ex) when (ex is RegexMatchTimeoutException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Case3: fuzzing method for ValidHosts
|
||||
public static void FuzzValidHosts(ReadOnlySpan<byte> input)
|
||||
{
|
||||
try
|
||||
{
|
||||
string hosts = System.Text.Encoding.UTF8.GetString(input);
|
||||
bool isValid = ValidationHelper.ValidHosts(hosts, true);
|
||||
}
|
||||
catch (Exception ex) when (ex is RegexMatchTimeoutException)
|
||||
{
|
||||
// It's important to filter out any *expected* exceptions from our code here.
|
||||
// However, catching all exceptions is considered an anti-pattern because it may suppress legitimate
|
||||
// issues, such as a NullReferenceException thrown by our code. In this case, we still re-throw
|
||||
// the exception, as the ToJsonFromXmlOrCsvAsync method is not expected to throw any exceptions.
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static void FuzzWriteAsync(ReadOnlySpan<byte> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_userSettings = new Mock<IUserSettings>();
|
||||
_elevationHelper = new Mock<IElevationHelper>();
|
||||
_elevationHelper.Setup(m => m.IsElevated).Returns(true);
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
|
||||
string input = System.Text.Encoding.UTF8.GetString(data);
|
||||
|
||||
// Since the WriteAsync method does not involve content parsing, we won't fuzz the additionalLines in the hosts file.
|
||||
string additionalLines = " ";
|
||||
string hosts = input;
|
||||
string address = input;
|
||||
string comments = input;
|
||||
var entries = new List<Entry>
|
||||
{
|
||||
new Entry(1, hosts, address, comments, true),
|
||||
};
|
||||
|
||||
// fuzzing WriteAsync
|
||||
_ = Task.Run(async () => await service.WriteAsync(additionalLines, entries));
|
||||
}
|
||||
catch (Exception ex) when (ex is ArgumentException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
src/modules/Hosts/Hosts.FuzzTests/Hosts.FuzzTests.csproj
Normal file
51
src/modules/Hosts/Hosts.FuzzTests/Hosts.FuzzTests.csproj
Normal file
@@ -0,0 +1,51 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\Hosts.FuzzTests\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Hosts.Tests\Mocks\CustomMockFileSystem.cs" Link="CustomMockFileSystem.cs" />
|
||||
<Compile Include="..\Hosts.Tests\Mocks\MockFileSystemWatcher.cs" Link="MockFileSystemWatcher.cs" />
|
||||
<Compile Include="..\Hosts.Tests\Mocks\MockFileSystemWatcherFactory.cs" Link="MockFileSystemWatcherFactory.cs" />
|
||||
<Compile Include="..\HostsUILib\Consts.cs" Link="Consts.cs" />
|
||||
<Compile Include="..\HostsUILib\Helpers\ValidationHelper.cs" Link="ValidationHelper.cs" />
|
||||
<Compile Include="..\HostsUILib\Exceptions\NotRunningElevatedException.cs" Link="NotRunningElevatedException.cs" />
|
||||
<Compile Include="..\HostsUILib\Exceptions\ReadOnlyHostsException.cs" Link="ReadOnlyHostsException.cs" />
|
||||
<Compile Include="..\HostsUILib\Helpers\HostsService.cs" Link="HostsService.cs" />
|
||||
<Compile Include="..\HostsUILib\Helpers\IElevationHelper.cs" Link="IElevationHelper.cs" />
|
||||
<Compile Include="..\HostsUILib\Helpers\IHostsService.cs" Link="IHostsService.cs" />
|
||||
<Compile Include="..\HostsUILib\Helpers\ILogger.cs" Link="ILogger.cs" />
|
||||
<Compile Include="..\HostsUILib\Helpers\LoggerInstance.cs" Link="LoggerInstance.cs" />
|
||||
<Compile Include="..\HostsUILib\Models\AddressType.cs" Link="AddressType.cs" />
|
||||
<Compile Include="..\HostsUILib\Models\Entry.cs" Link="Entry.cs" />
|
||||
<Compile Include="..\HostsUILib\Models\HostsData.cs" Link="HostsData.cs" />
|
||||
<Compile Include="..\HostsUILib\Settings\HostsAdditionalLinesPosition.cs" Link="HostsAdditionalLinesPosition.cs" />
|
||||
<Compile Include="..\HostsUILib\Settings\HostsEncoding.cs" Link="HostsEncoding.cs" />
|
||||
<Compile Include="..\HostsUILib\Settings\IUserSettings.cs" Link="IUserSettings.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="System.IO.Abstractions.TestingHelpers" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="OneFuzzConfig.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
5
src/modules/Hosts/Hosts.FuzzTests/MSTestSettings.cs
Normal file
5
src/modules/Hosts/Hosts.FuzzTests/MSTestSettings.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
// 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.
|
||||
|
||||
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
|
||||
178
src/modules/Hosts/Hosts.FuzzTests/OneFuzzConfig.json
Normal file
178
src/modules/Hosts/Hosts.FuzzTests/OneFuzzConfig.json
Normal file
@@ -0,0 +1,178 @@
|
||||
{
|
||||
"configVersion": 3,
|
||||
"entries": [
|
||||
{
|
||||
"fuzzer": {
|
||||
"$type": "libfuzzerDotNet",
|
||||
"dll": "Hosts.FuzzTests.dll",
|
||||
"class": "Hosts.FuzzTests.FuzzTests",
|
||||
"method": "FuzzValidIPv4",
|
||||
"FuzzingTargetBinaries": [
|
||||
"PowerToys.Hosts.dll"
|
||||
]
|
||||
},
|
||||
"adoTemplate": {
|
||||
// supply the values appropriate to your
|
||||
// project, where bugs will be filed
|
||||
"org": "microsoft",
|
||||
"project": "OS",
|
||||
"AssignedTo": "mengyuanchen@microsoft.com",
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
|
||||
"IterationPath": "OS\\Future"
|
||||
},
|
||||
"jobNotificationEmail": "mengyuanchen@microsoft.com",
|
||||
"skip": false,
|
||||
"rebootAfterSetup": false,
|
||||
"oneFuzzJobs": [
|
||||
// at least one job is required
|
||||
{
|
||||
"projectName": "Hosts",
|
||||
"targetName": "Hosts-dotnet-fuzzer-Ipv4"
|
||||
}
|
||||
],
|
||||
"jobDependencies": [
|
||||
// this should contain, at minimum,
|
||||
// the DLL and PDB files
|
||||
// you will need to add any other files required
|
||||
// (globs are supported)
|
||||
"Hosts.FuzzTests.dll",
|
||||
"Hosts.FuzzTests.pdb",
|
||||
"Microsoft.Windows.SDK.NET.dll",
|
||||
"WinRT.Runtime.dll"
|
||||
],
|
||||
"SdlWorkItemId": 49911822
|
||||
},
|
||||
{
|
||||
"fuzzer": {
|
||||
"$type": "libfuzzerDotNet",
|
||||
"dll": "Hosts.FuzzTests.dll",
|
||||
"class": "Hosts.FuzzTests.FuzzTests",
|
||||
"method": "FuzzValidIPv6",
|
||||
"FuzzingTargetBinaries": [
|
||||
"PowerToys.Hosts.dll"
|
||||
]
|
||||
},
|
||||
"adoTemplate": {
|
||||
// supply the values appropriate to your
|
||||
// project, where bugs will be filed
|
||||
"org": "microsoft",
|
||||
"project": "OS",
|
||||
"AssignedTo": "mengyuanchen@microsoft.com",
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
|
||||
"IterationPath": "OS\\Future"
|
||||
},
|
||||
"jobNotificationEmail": "mengyuanchen@microsoft.com",
|
||||
"skip": false,
|
||||
"rebootAfterSetup": false,
|
||||
"oneFuzzJobs": [
|
||||
// at least one job is required
|
||||
{
|
||||
"projectName": "Hosts",
|
||||
"targetName": "Hosts-dotnet-fuzzer-Ipv6"
|
||||
}
|
||||
],
|
||||
"jobDependencies": [
|
||||
// this should contain, at minimum,
|
||||
// the DLL and PDB files
|
||||
// you will need to add any other files required
|
||||
// (globs are supported)
|
||||
"Hosts.FuzzTests.dll",
|
||||
"Hosts.FuzzTests.pdb",
|
||||
"Microsoft.Windows.SDK.NET.dll",
|
||||
"WinRT.Runtime.dll"
|
||||
],
|
||||
"SdlWorkItemId": 49911822
|
||||
},
|
||||
{
|
||||
"fuzzer": {
|
||||
"$type": "libfuzzerDotNet",
|
||||
"dll": "Hosts.FuzzTests.dll",
|
||||
"class": "Hosts.FuzzTests.FuzzTests",
|
||||
"method": "FuzzValidHosts",
|
||||
"FuzzingTargetBinaries": [
|
||||
"PowerToys.Hosts.dll"
|
||||
]
|
||||
},
|
||||
"adoTemplate": {
|
||||
// supply the values appropriate to your
|
||||
// project, where bugs will be filed
|
||||
"org": "microsoft",
|
||||
"project": "OS",
|
||||
"AssignedTo": "mengyuanchen@microsoft.com",
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
|
||||
"IterationPath": "OS\\Future"
|
||||
},
|
||||
"jobNotificationEmail": "mengyuanchen@microsoft.com",
|
||||
"skip": false,
|
||||
"rebootAfterSetup": false,
|
||||
"oneFuzzJobs": [
|
||||
// at least one job is required
|
||||
{
|
||||
"projectName": "Hosts",
|
||||
"targetName": "Hosts-dotnet-fuzzer-hosts"
|
||||
}
|
||||
],
|
||||
"jobDependencies": [
|
||||
// this should contain, at minimum,
|
||||
// the DLL and PDB files
|
||||
// you will need to add any other files required
|
||||
// (globs are supported)
|
||||
"Hosts.FuzzTests.dll",
|
||||
"Hosts.FuzzTests.pdb",
|
||||
"Microsoft.Windows.SDK.NET.dll",
|
||||
"WinRT.Runtime.dll"
|
||||
],
|
||||
"SdlWorkItemId": 49911822
|
||||
},
|
||||
{
|
||||
"fuzzer": {
|
||||
"$type": "libfuzzerDotNet",
|
||||
"dll": "Hosts.FuzzTests.dll",
|
||||
"class": "Hosts.FuzzTests.FuzzTests",
|
||||
"method": "FuzzWriteAsync",
|
||||
"FuzzingTargetBinaries": [
|
||||
"PowerToys.Hosts.dll"
|
||||
]
|
||||
},
|
||||
"adoTemplate": {
|
||||
// supply the values appropriate to your
|
||||
// project, where bugs will be filed
|
||||
"org": "microsoft",
|
||||
"project": "OS",
|
||||
"AssignedTo": "mengyuanchen@microsoft.com",
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
|
||||
"IterationPath": "OS\\Future"
|
||||
},
|
||||
"jobNotificationEmail": "mengyuanchen@microsoft.com",
|
||||
"skip": false,
|
||||
"rebootAfterSetup": false,
|
||||
"oneFuzzJobs": [
|
||||
// at least one job is required
|
||||
{
|
||||
"projectName": "Hosts",
|
||||
"targetName": "Hosts-dotnet-fuzzer-WriteAsync"
|
||||
}
|
||||
],
|
||||
"jobDependencies": [
|
||||
// this should contain, at minimum,
|
||||
// the DLL and PDB files
|
||||
// you will need to add any other files required
|
||||
// (globs are supported)
|
||||
"Hosts.FuzzTests.dll",
|
||||
"Hosts.FuzzTests.pdb",
|
||||
"Microsoft.Windows.SDK.NET.dll",
|
||||
"WinRT.Runtime.dll",
|
||||
"Moq.dll",
|
||||
"testhost.dll",
|
||||
"Castle.Core.dll",
|
||||
"System.IO.Abstractions.dll",
|
||||
"CommunityToolkit.Mvvm.dll",
|
||||
"System.IO.Abstractions.TestingHelpers.dll",
|
||||
"TestableIO.System.IO.Abstractions.dll",
|
||||
"TestableIO.System.IO.Abstractions.TestingHelpers.dll",
|
||||
"TestableIO.System.IO.Abstractions.Wrappers.dll"
|
||||
],
|
||||
"SdlWorkItemId": 49911822
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -233,6 +233,12 @@ void Highlighter::ClearDrawingPoint(MouseButton _button)
|
||||
{
|
||||
winrt::Windows::UI::Composition::CompositionSpriteShape circleShape{ nullptr };
|
||||
|
||||
if (nullptr == m_alwaysPointer)
|
||||
{
|
||||
// Guard against alwaysPointer not being initialized.
|
||||
return;
|
||||
}
|
||||
|
||||
// always
|
||||
circleShape = m_alwaysPointer;
|
||||
|
||||
@@ -265,6 +271,11 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
|
||||
// Clear AlwaysPointer only when it's enabled and RightPointer is not active
|
||||
instance->ClearDrawingPoint(MouseButton::None);
|
||||
}
|
||||
if (instance->m_leftButtonPressed)
|
||||
{
|
||||
// There might be a stray point from the user releasing the mouse button on an elevated window, which wasn't caught by us.
|
||||
instance->StartDrawingPointFading(MouseButton::Left);
|
||||
}
|
||||
instance->AddDrawingPoint(MouseButton::Left);
|
||||
instance->m_leftButtonPressed = true;
|
||||
// start a timer for the scenario, when the user clicks a pinned window which has no focus.
|
||||
@@ -284,6 +295,11 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
|
||||
// Clear AlwaysPointer only when it's enabled and LeftPointer is not active
|
||||
instance->ClearDrawingPoint(MouseButton::None);
|
||||
}
|
||||
if (instance->m_rightButtonPressed)
|
||||
{
|
||||
// There might be a stray point from the user releasing the mouse button on an elevated window, which wasn't caught by us.
|
||||
instance->StartDrawingPointFading(MouseButton::Right);
|
||||
}
|
||||
instance->AddDrawingPoint(MouseButton::Right);
|
||||
instance->m_rightButtonPressed = true;
|
||||
// same as for the left button, start a timer for reposition ourselves to topmost position
|
||||
|
||||
@@ -431,7 +431,7 @@ namespace MouseWithoutBorders
|
||||
if (!IsConnectedByAClientSocketTo(remoteMachine))
|
||||
{
|
||||
Logger.Log($"No potential inbound connection from {MachineName} to {remoteMachine}, ask for a push back instead.");
|
||||
ID machineId = MachinePool.ResolveID(remoteMachine);
|
||||
ID machineId = MachineStuff.MachinePool.ResolveID(remoteMachine);
|
||||
|
||||
if (machineId != ID.NONE)
|
||||
{
|
||||
@@ -840,7 +840,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
Logger.LogDebug($"{nameof(ShakeHand)}: Connection from {name}:{package.Src}");
|
||||
|
||||
if (Common.MachinePool.ResolveID(name) == package.Src && Common.IsConnectedTo(package.Src))
|
||||
if (MachineStuff.MachinePool.ResolveID(name) == package.Src && Common.IsConnectedTo(package.Src))
|
||||
{
|
||||
clientPushData = package.Type == PackageType.ClipboardPush;
|
||||
postAction = package.PostAction;
|
||||
|
||||
@@ -1,409 +0,0 @@
|
||||
// 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.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
// <summary>
|
||||
// Drag/Drop implementation.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
using MouseWithoutBorders.Class;
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
using Thread = MouseWithoutBorders.Core.Thread;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
/* Common.DragDrop.cs
|
||||
* Drag&Drop is one complicated implementation of the tool with some tricks.
|
||||
*
|
||||
* SEQUENCE OF EVENTS:
|
||||
* DragDropStep01: MachineX: Remember mouse down state since it could be a start of a dragging
|
||||
* DragDropStep02: MachineY: Send an message to the MachineX to ask it to check if it is
|
||||
* doing drag/drop
|
||||
* DragDropStep03: MachineX: Got explorerDragDrop, send WM_CHECK_EXPLORER_DRAG_DROP to its mainForm
|
||||
* DragDropStep04: MachineX: Show Mouse Without Borders Helper form at mouse cursor to get DragEnter event.
|
||||
* DragDropStepXX: MachineX: Mouse Without Borders Helper: Called by DragEnter, check if dragging a single file,
|
||||
* remember the file (set as its window caption)
|
||||
* DragDropStep05: MachineX: Get the file name from Mouse Without Borders Helper, hide Mouse Without Borders Helper window
|
||||
* DragDropStep06: MachineX: Broadcast a message saying that it has some drag file.
|
||||
* DragDropStep08: MachineY: Got ClipboardDragDrop, isDropping set, get the MachineX name from the package.
|
||||
* DragDropStep09: MachineY: Since isDropping is true, show up the drop form (looks like an icon).
|
||||
* DragDropStep10: MachineY: MouseUp, set isDropping to false, hide the drop "icon" and get data.
|
||||
* DragDropStep11: MachineX: Mouse move back without drop event, cancelling drag/dop
|
||||
* SendClipboardBeatDragDropEnd
|
||||
* DragDropStep12: MachineY: Hide the drop "icon" when received ClipboardDragDropEnd.
|
||||
*
|
||||
* FROM VERSION 1.6.3: Drag/Drop is temporary removed, Drop action cannot be done from a lower integrity app to a higher one.
|
||||
* We have to run a helper process...
|
||||
* http://forums.microsoft.com/MSDN/ShowPost.aspx?PageIndex=1&SiteID=1&PageID=1&PostID=736086
|
||||
*
|
||||
* 2008.10.28: Trying to restore the Drag/Drop feature by adding the drag/drop helper process. Coming in version
|
||||
* 1.6.5
|
||||
* */
|
||||
|
||||
internal partial class Common
|
||||
{
|
||||
private static bool isDragging;
|
||||
|
||||
internal static bool IsDragging
|
||||
{
|
||||
get => Common.isDragging;
|
||||
set => Common.isDragging = value;
|
||||
}
|
||||
|
||||
internal static void DragDropStep01(int wParam)
|
||||
{
|
||||
if (!Setting.Values.TransferFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (wParam == WM_LBUTTONDOWN)
|
||||
{
|
||||
MouseDown = true;
|
||||
DragMachine = desMachineID;
|
||||
dropMachineID = ID.NONE;
|
||||
Logger.LogDebug("DragDropStep01: MouseDown");
|
||||
}
|
||||
else if (wParam == WM_LBUTTONUP)
|
||||
{
|
||||
MouseDown = false;
|
||||
Logger.LogDebug("DragDropStep01: MouseUp");
|
||||
}
|
||||
|
||||
if (wParam == WM_RBUTTONUP && IsDropping)
|
||||
{
|
||||
IsDropping = false;
|
||||
LastIDWithClipboardData = ID.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DragDropStep02()
|
||||
{
|
||||
if (desMachineID == MachineID)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent to myself");
|
||||
DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
SendCheckExplorerDragDrop();
|
||||
Logger.LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DragDropStep03(DATA package)
|
||||
{
|
||||
if (RunOnLogonDesktop || RunOnScrSaverDesktop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (package.Des == MachineID || package.Des == ID.ALL)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep03: ExplorerDragDrop Received.");
|
||||
dropMachineID = package.Src; // Drop machine is the machine that sent ExplorerDragDrop
|
||||
if (MouseDown || IsDropping)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep03: Mouse is down, check if dragging...sending WM_CHECK_EXPLORER_DRAG_DROP to myself...");
|
||||
DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int dragDropStep05ExCalledByIpc;
|
||||
|
||||
internal static void DragDropStep04()
|
||||
{
|
||||
if (!IsDropping)
|
||||
{
|
||||
IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
|
||||
if (h.ToInt32() > 0)
|
||||
{
|
||||
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 0);
|
||||
|
||||
MainForm.Hide();
|
||||
MainFormVisible = false;
|
||||
|
||||
Point p = default;
|
||||
|
||||
// NativeMethods.SetWindowText(h, "");
|
||||
_ = NativeMethods.SetWindowPos(h, NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, NativeMethods.SWP_SHOWWINDOW);
|
||||
|
||||
for (int i = -10; i < 10; i++)
|
||||
{
|
||||
if (dragDropStep05ExCalledByIpc > 0)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep04: DragDropStep05ExCalledByIpc.");
|
||||
break;
|
||||
}
|
||||
|
||||
_ = NativeMethods.GetCursorPos(ref p);
|
||||
Logger.LogDebug("DragDropStep04: Moving Mouse Without Borders Helper to (" + p.X.ToString(CultureInfo.CurrentCulture) + ", " + p.Y.ToString(CultureInfo.CurrentCulture) + ")");
|
||||
_ = NativeMethods.SetWindowPos(h, NativeMethods.HWND_TOPMOST, p.X - 100 + i, p.Y - 100 + i, 200, 200, 0);
|
||||
_ = NativeMethods.SendMessage(h, 0x000F, IntPtr.Zero, IntPtr.Zero); // WM_PAINT
|
||||
Thread.Sleep(20);
|
||||
Application.DoEvents();
|
||||
|
||||
// if (GetText(h).Length > 1) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep04: Mouse without Borders Helper not found!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep04: IsDropping == true, skip checking");
|
||||
}
|
||||
|
||||
Logger.LogDebug("DragDropStep04: Got WM_CHECK_EXPLORER_DRAG_DROP, done with processing jump to DragDropStep05...");
|
||||
}
|
||||
|
||||
internal static void DragDropStep05Ex(string dragFileName)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep05 called.");
|
||||
|
||||
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 1);
|
||||
|
||||
if (RunOnLogonDesktop || RunOnScrSaverDesktop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsDropping)
|
||||
{
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dragFileName) && (File.Exists(dragFileName) || Directory.Exists(dragFileName)))
|
||||
{
|
||||
Common.LastDragDropFile = dragFileName;
|
||||
/*
|
||||
* possibleDropMachineID is used as desID sent in DragDropStep06();
|
||||
* */
|
||||
if (dropMachineID == ID.NONE)
|
||||
{
|
||||
dropMachineID = newDesMachineID;
|
||||
}
|
||||
|
||||
DragDropStep06();
|
||||
Logger.LogDebug("DragDropStep05: File dragging: " + dragFileName);
|
||||
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_HIDE_DD_HELPER, (IntPtr)1, (IntPtr)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep05: File not found: [" + dragFileName + "]");
|
||||
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_HIDE_DD_HELPER, (IntPtr)0, (IntPtr)0);
|
||||
}
|
||||
|
||||
Logger.LogDebug("DragDropStep05: WM_HIDE_DDHelper sent");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep05: IsDropping == true, change drop machine...");
|
||||
IsDropping = false;
|
||||
MainFormVisible = true; // WM_HIDE_DRAG_DROP
|
||||
SendDropBegin(); // To dropMachineID set in DragDropStep03
|
||||
}
|
||||
|
||||
MouseDown = false;
|
||||
}
|
||||
|
||||
internal static void DragDropStep06()
|
||||
{
|
||||
IsDragging = true;
|
||||
Logger.LogDebug("DragDropStep06: SendClipboardBeatDragDrop");
|
||||
SendClipboardBeatDragDrop();
|
||||
SendDropBegin();
|
||||
}
|
||||
|
||||
internal static void DragDropStep08(DATA package)
|
||||
{
|
||||
Receiver.GetNameOfMachineWithClipboardData(package);
|
||||
Logger.LogDebug("DragDropStep08: ClipboardDragDrop Received. machine with drag file was set");
|
||||
}
|
||||
|
||||
internal static void DragDropStep08_2(DATA package)
|
||||
{
|
||||
if (package.Des == MachineID && !RunOnLogonDesktop && !RunOnScrSaverDesktop)
|
||||
{
|
||||
IsDropping = true;
|
||||
dropMachineID = MachineID;
|
||||
Logger.LogDebug("DragDropStep08_2: ClipboardDragDropOperation Received. IsDropping set");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DragDropStep09(int wParam)
|
||||
{
|
||||
if (wParam == WM_MOUSEMOVE && IsDropping)
|
||||
{
|
||||
// Show/Move form
|
||||
DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_SHOW_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
else if (wParam == WM_LBUTTONUP && (IsDropping || IsDragging))
|
||||
{
|
||||
if (IsDropping)
|
||||
{
|
||||
// Hide form, get data
|
||||
DragDropStep10();
|
||||
}
|
||||
else
|
||||
{
|
||||
IsDragging = false;
|
||||
LastIDWithClipboardData = ID.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DragDropStep10()
|
||||
{
|
||||
Logger.LogDebug("DragDropStep10: Hide the form and get data...");
|
||||
IsDropping = false;
|
||||
IsDragging = false;
|
||||
LastIDWithClipboardData = ID.NONE;
|
||||
|
||||
DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_HIDE_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new MouseWithoutBorders.Telemetry.MouseWithoutBordersDragAndDropEvent());
|
||||
GetRemoteClipboard("desktop");
|
||||
}
|
||||
|
||||
internal static void DragDropStep11()
|
||||
{
|
||||
Logger.LogDebug("DragDropStep11: Mouse drag coming back, canceling drag/drop");
|
||||
SendClipboardBeatDragDropEnd();
|
||||
IsDropping = false;
|
||||
IsDragging = false;
|
||||
DragMachine = (ID)1;
|
||||
LastIDWithClipboardData = ID.NONE;
|
||||
LastDragDropFile = null;
|
||||
MouseDown = false;
|
||||
}
|
||||
|
||||
internal static void DragDropStep12()
|
||||
{
|
||||
Logger.LogDebug("DragDropStep12: ClipboardDragDropEnd received");
|
||||
IsDropping = false;
|
||||
LastIDWithClipboardData = ID.NONE;
|
||||
|
||||
DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(MainForm.Handle, NativeMethods.WM_HIDE_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
|
||||
internal static void SendCheckExplorerDragDrop()
|
||||
{
|
||||
DATA package = new();
|
||||
package.Type = PackageType.ExplorerDragDrop;
|
||||
|
||||
/*
|
||||
* package.src = newDesMachineID:
|
||||
* sent from the master machine but the src must be the
|
||||
* new des machine since the previous des machine will get this and set
|
||||
* to possibleDropMachineID in DragDropStep3()
|
||||
* */
|
||||
package.Src = newDesMachineID;
|
||||
|
||||
package.Des = desMachineID;
|
||||
package.MachineName = MachineName;
|
||||
|
||||
SkSend(package, null, false);
|
||||
}
|
||||
|
||||
private static void ChangeDropMachine()
|
||||
{
|
||||
// desMachineID = current drop machine
|
||||
// newDesMachineID = new drop machine
|
||||
|
||||
// 1. Cancelling dropping in current drop machine
|
||||
if (dropMachineID == MachineID)
|
||||
{
|
||||
// Drag/Drop coming through me
|
||||
IsDropping = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Drag/Drop coming back
|
||||
SendClipboardBeatDragDropEnd();
|
||||
}
|
||||
|
||||
// 2. SendClipboardBeatDragDrop to new drop machine
|
||||
// new drop machine is not me
|
||||
if (newDesMachineID != MachineID)
|
||||
{
|
||||
dropMachineID = newDesMachineID;
|
||||
SendDropBegin();
|
||||
}
|
||||
|
||||
// New drop machine is me
|
||||
else
|
||||
{
|
||||
IsDropping = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SendClipboardBeatDragDrop()
|
||||
{
|
||||
SendPackage(ID.ALL, PackageType.ClipboardDragDrop);
|
||||
}
|
||||
|
||||
internal static void SendDropBegin()
|
||||
{
|
||||
Logger.LogDebug("SendDropBegin...");
|
||||
SendPackage(dropMachineID, PackageType.ClipboardDragDropOperation);
|
||||
}
|
||||
|
||||
internal static void SendClipboardBeatDragDropEnd()
|
||||
{
|
||||
if (desMachineID != MachineID)
|
||||
{
|
||||
SendPackage(desMachineID, PackageType.ClipboardDragDropEnd);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool isDropping;
|
||||
private static ID dragMachine;
|
||||
|
||||
internal static ID DragMachine
|
||||
{
|
||||
get => Common.dragMachine;
|
||||
set => Common.dragMachine = value;
|
||||
}
|
||||
|
||||
internal static bool IsDropping
|
||||
{
|
||||
get => Common.isDropping;
|
||||
set => Common.isDropping = value;
|
||||
}
|
||||
|
||||
internal static bool MouseDown { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
if (switchByMouseEnabled && Sk != null && (DesMachineID == MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == WM_MOUSEMOVE)
|
||||
{
|
||||
Point p = MoveToMyNeighbourIfNeeded(e.X, e.Y, desMachineID);
|
||||
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(e.X, e.Y, MachineStuff.desMachineID);
|
||||
|
||||
if (!p.IsEmpty)
|
||||
{
|
||||
@@ -81,20 +81,20 @@ namespace MouseWithoutBorders
|
||||
Logger.LogDebug(string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"***** Host Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
|
||||
newDesMachineIdEx,
|
||||
MachineStuff.newDesMachineIdEx,
|
||||
e.X,
|
||||
e.Y));
|
||||
|
||||
myLastX = e.X;
|
||||
myLastY = e.Y;
|
||||
|
||||
PrepareToSwitchToMachine(newDesMachineIdEx, p);
|
||||
PrepareToSwitchToMachine(MachineStuff.newDesMachineIdEx, p);
|
||||
}
|
||||
}
|
||||
|
||||
if (desMachineID != MachineID && SwitchLocation.Count <= 0)
|
||||
if (MachineStuff.desMachineID != MachineID && MachineStuff.SwitchLocation.Count <= 0)
|
||||
{
|
||||
MousePackage.Des = desMachineID;
|
||||
MousePackage.Des = MachineStuff.desMachineID;
|
||||
MousePackage.Type = PackageType.Mouse;
|
||||
MousePackage.Md.dwFlags = e.dwFlags;
|
||||
MousePackage.Md.WheelDelta = e.WheelDelta;
|
||||
@@ -107,8 +107,8 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
MousePackage.Md.X = (e.X - primaryScreenBounds.Left) * 65535 / screenWidth;
|
||||
MousePackage.Md.Y = (e.Y - primaryScreenBounds.Top) * 65535 / screenHeight;
|
||||
MousePackage.Md.X = (e.X - MachineStuff.primaryScreenBounds.Left) * 65535 / screenWidth;
|
||||
MousePackage.Md.Y = (e.Y - MachineStuff.primaryScreenBounds.Top) * 65535 / screenHeight;
|
||||
}
|
||||
|
||||
SkSend(MousePackage, null, false);
|
||||
@@ -156,15 +156,15 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Logger.LogDebug($"PrepareToSwitchToMachine: newDesMachineID = {newDesMachineID}, desMachineXY = {desMachineXY}");
|
||||
|
||||
if (((GetTick() - lastJump < 100) && (GetTick() - lastJump > 0)) || desMachineID == ID.ALL)
|
||||
if (((GetTick() - MachineStuff.lastJump < 100) && (GetTick() - MachineStuff.lastJump > 0)) || MachineStuff.desMachineID == ID.ALL)
|
||||
{
|
||||
Logger.LogDebug("PrepareToSwitchToMachine: lastJump");
|
||||
return;
|
||||
}
|
||||
|
||||
lastJump = GetTick();
|
||||
MachineStuff.lastJump = GetTick();
|
||||
|
||||
string newDesMachineName = NameFromID(newDesMachineID);
|
||||
string newDesMachineName = MachineStuff.NameFromID(newDesMachineID);
|
||||
|
||||
if (!IsConnectedTo(newDesMachineID))
|
||||
{// Connection lost, cancel switching
|
||||
@@ -174,46 +174,46 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
Common.newDesMachineID = newDesMachineID;
|
||||
SwitchLocation.X = desMachineXY.X;
|
||||
SwitchLocation.Y = desMachineXY.Y;
|
||||
SwitchLocation.ResetCount();
|
||||
MachineStuff.newDesMachineID = newDesMachineID;
|
||||
MachineStuff.SwitchLocation.X = desMachineXY.X;
|
||||
MachineStuff.SwitchLocation.Y = desMachineXY.Y;
|
||||
MachineStuff.SwitchLocation.ResetCount();
|
||||
_ = EvSwitch.Set();
|
||||
|
||||
// PostMessage(mainForm.Handle, WM_SWITCH, IntPtr.Zero, IntPtr.Zero);
|
||||
if (newDesMachineID != DragMachine)
|
||||
if (newDesMachineID != DragDrop.DragMachine)
|
||||
{
|
||||
if (!IsDragging && !IsDropping)
|
||||
if (!DragDrop.IsDragging && !DragDrop.IsDropping)
|
||||
{
|
||||
if (MouseDown && !RunOnLogonDesktop && !RunOnScrSaverDesktop)
|
||||
if (DragDrop.MouseDown && !RunOnLogonDesktop && !RunOnScrSaverDesktop)
|
||||
{
|
||||
DragDropStep02();
|
||||
DragDrop.DragDropStep02();
|
||||
}
|
||||
}
|
||||
else if (DragMachine != (ID)1)
|
||||
else if (DragDrop.DragMachine != (ID)1)
|
||||
{
|
||||
ChangeDropMachine();
|
||||
DragDrop.ChangeDropMachine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DragDropStep11();
|
||||
DragDrop.DragDropStep11();
|
||||
}
|
||||
|
||||
// Change des machine
|
||||
if (desMachineID != newDesMachineID)
|
||||
if (MachineStuff.desMachineID != newDesMachineID)
|
||||
{
|
||||
Logger.LogDebug("MouseEvent: Switching to new machine:" + newDesMachineName);
|
||||
|
||||
// Ask current machine to hide the Mouse cursor
|
||||
if (newDesMachineID != ID.ALL && desMachineID != MachineID)
|
||||
if (newDesMachineID != ID.ALL && MachineStuff.desMachineID != MachineID)
|
||||
{
|
||||
SendPackage(desMachineID, PackageType.HideMouse);
|
||||
SendPackage(MachineStuff.desMachineID, PackageType.HideMouse);
|
||||
}
|
||||
|
||||
DesMachineID = newDesMachineID;
|
||||
|
||||
if (desMachineID == MachineID)
|
||||
if (MachineStuff.desMachineID == MachineID)
|
||||
{
|
||||
if (GetTick() - clipboardCopiedTime < BIG_CLIPBOARD_DATA_TIMEOUT)
|
||||
{
|
||||
@@ -224,7 +224,7 @@ namespace MouseWithoutBorders
|
||||
else
|
||||
{
|
||||
// Ask the new active machine to get clipboard data (if the data is too big)
|
||||
SendPackage(desMachineID, PackageType.MachineSwitched);
|
||||
SendPackage(MachineStuff.desMachineID, PackageType.MachineSwitched);
|
||||
}
|
||||
|
||||
_ = Interlocked.Increment(ref switchCount);
|
||||
@@ -249,15 +249,15 @@ namespace MouseWithoutBorders
|
||||
try
|
||||
{
|
||||
PaintCount = 0;
|
||||
if (desMachineID != newDesMachineID)
|
||||
if (MachineStuff.desMachineID != MachineStuff.newDesMachineID)
|
||||
{
|
||||
Logger.LogDebug("KeybdEvent: Switching to new machine...");
|
||||
DesMachineID = newDesMachineID;
|
||||
DesMachineID = MachineStuff.newDesMachineID;
|
||||
}
|
||||
|
||||
if (desMachineID != MachineID)
|
||||
if (MachineStuff.desMachineID != MachineID)
|
||||
{
|
||||
KeybdPackage.Des = desMachineID;
|
||||
KeybdPackage.Des = MachineStuff.desMachineID;
|
||||
KeybdPackage.Type = PackageType.Keyboard;
|
||||
KeybdPackage.Kd = e;
|
||||
KeybdPackage.DateTime = GetTick();
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@@ -87,35 +88,35 @@ namespace MouseWithoutBorders
|
||||
break;
|
||||
}
|
||||
|
||||
if (Common.NewDesMachineID != Common.MachineID && Common.NewDesMachineID != ID.ALL)
|
||||
if (MachineStuff.NewDesMachineID != Common.MachineID && MachineStuff.NewDesMachineID != ID.ALL)
|
||||
{
|
||||
HideMouseCursor(false);
|
||||
Common.MainFormDotEx(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Common.SwitchLocation.Count > 0)
|
||||
if (MachineStuff.SwitchLocation.Count > 0)
|
||||
{
|
||||
Common.SwitchLocation.Count--;
|
||||
MachineStuff.SwitchLocation.Count--;
|
||||
|
||||
// When we want to move mouse by pixels, we add 300k to x and y (search for XY_BY_PIXEL for other related code).
|
||||
Logger.LogDebug($"+++++ Moving mouse to {Common.SwitchLocation.X}, {Common.SwitchLocation.Y}");
|
||||
Logger.LogDebug($"+++++ Moving mouse to {MachineStuff.SwitchLocation.X}, {MachineStuff.SwitchLocation.Y}");
|
||||
|
||||
// MaxXY = 65535 so 100k is safe.
|
||||
if (Common.SwitchLocation.X > XY_BY_PIXEL - 100000 || Common.SwitchLocation.Y > XY_BY_PIXEL - 100000)
|
||||
if (MachineStuff.SwitchLocation.X > XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > XY_BY_PIXEL - 100000)
|
||||
{
|
||||
InputSimulation.MoveMouse(Common.SwitchLocation.X - XY_BY_PIXEL, Common.SwitchLocation.Y - XY_BY_PIXEL);
|
||||
InputSimulation.MoveMouse(MachineStuff.SwitchLocation.X - XY_BY_PIXEL, MachineStuff.SwitchLocation.Y - XY_BY_PIXEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
InputSimulation.MoveMouseEx(Common.SwitchLocation.X, Common.SwitchLocation.Y);
|
||||
InputSimulation.MoveMouseEx(MachineStuff.SwitchLocation.X, MachineStuff.SwitchLocation.Y);
|
||||
}
|
||||
|
||||
Common.MainFormDot();
|
||||
}
|
||||
}
|
||||
|
||||
if (Common.NewDesMachineID == Common.MachineID)
|
||||
if (MachineStuff.NewDesMachineID == Common.MachineID)
|
||||
{
|
||||
ReleaseAllKeys();
|
||||
}
|
||||
@@ -136,8 +137,8 @@ namespace MouseWithoutBorders
|
||||
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
int left = Common.PrimaryScreenBounds.Left + ((Common.PrimaryScreenBounds.Right - Common.PrimaryScreenBounds.Left) / 2) - 1;
|
||||
int top = Setting.Values.HideMouse ? 3 : Common.PrimaryScreenBounds.Top + ((Common.PrimaryScreenBounds.Bottom - Common.PrimaryScreenBounds.Top) / 2);
|
||||
int left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
|
||||
int top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
|
||||
|
||||
Common.MainFormVisible = true;
|
||||
|
||||
@@ -197,8 +198,8 @@ namespace MouseWithoutBorders
|
||||
DoSomethingInUIThread(
|
||||
() =>
|
||||
{
|
||||
MainForm.Left = Common.PrimaryScreenBounds.Left + ((Common.PrimaryScreenBounds.Right - Common.PrimaryScreenBounds.Left) / 2) - 2;
|
||||
MainForm.Top = Setting.Values.HideMouse ? 3 : Common.PrimaryScreenBounds.Top + ((Common.PrimaryScreenBounds.Bottom - Common.PrimaryScreenBounds.Top) / 2) - 1;
|
||||
MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 2;
|
||||
MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2) - 1;
|
||||
MainForm.Width = 3;
|
||||
MainForm.Height = 3;
|
||||
MainForm.Opacity = 0.11D;
|
||||
@@ -229,8 +230,8 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
_ = Common.SendMessageToHelper(0x408, IntPtr.Zero, IntPtr.Zero, false);
|
||||
|
||||
MainForm.Left = Common.PrimaryScreenBounds.Left + ((Common.PrimaryScreenBounds.Right - Common.PrimaryScreenBounds.Left) / 2) - 1;
|
||||
MainForm.Top = Setting.Values.HideMouse ? 3 : Common.PrimaryScreenBounds.Top + ((Common.PrimaryScreenBounds.Bottom - Common.PrimaryScreenBounds.Top) / 2);
|
||||
MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
|
||||
MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
|
||||
MainForm.Width = 1;
|
||||
MainForm.Height = 1;
|
||||
MainForm.Opacity = 0.15;
|
||||
@@ -380,7 +381,7 @@ namespace MouseWithoutBorders
|
||||
log += $"{Setting.Values.Username}/{GetDebugInfo(MyKey)}\r\n";
|
||||
log += $"{MachineName}/{MachineID}/{DesMachineID}\r\n";
|
||||
log += $"Id: {Setting.Values.DeviceId}\r\n";
|
||||
log += $"Matrix: {string.Join(",", MachineMatrix)}\r\n";
|
||||
log += $"Matrix: {string.Join(",", MachineStuff.MachineMatrix)}\r\n";
|
||||
log += $"McPool: {Setting.Values.MachinePoolString}\r\n";
|
||||
|
||||
log += "\r\nOPTIONS:\r\n";
|
||||
@@ -443,7 +444,31 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
Setting.Values.Username = WindowsIdentity.GetCurrent(true).Name;
|
||||
// See: https://stackoverflow.com/questions/19487541/how-to-get-windows-user-name-from-sessionid
|
||||
static string GetUsernameBySessionId(int sessionId)
|
||||
{
|
||||
string username = "SYSTEM";
|
||||
if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSUserName, out nint buffer, out int strLen) && strLen > 1)
|
||||
{
|
||||
username = Marshal.PtrToStringAnsi(buffer);
|
||||
NativeMethods.WTSFreeMemory(buffer);
|
||||
|
||||
if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1)
|
||||
{
|
||||
username = @$"{Marshal.PtrToStringAnsi(buffer)}\{username}";
|
||||
NativeMethods.WTSFreeMemory(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return username;
|
||||
}
|
||||
|
||||
// The most direct way to fetch the username is WindowsIdentity.GetCurrent(true).Name
|
||||
// but GetUserName can run within an ExecutionContext.SuppressFlow block, which creates issues
|
||||
// with WindowsIdentity.GetCurrent.
|
||||
// See: https://stackoverflow.com/questions/76998988/exception-when-using-executioncontext-suppressflow-in-net-7
|
||||
// So we use WTSQuerySessionInformation as a workaround.
|
||||
Setting.Values.Username = GetUsernameBySessionId(Process.GetCurrentProcess().SessionId);
|
||||
});
|
||||
}
|
||||
else
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace MouseWithoutBorders
|
||||
internal static void UpdateMachineTimeAndID()
|
||||
{
|
||||
Common.MachineName = Common.MachineName.Trim();
|
||||
_ = Common.MachinePool.TryUpdateMachineID(Common.MachineName, Common.MachineID, true);
|
||||
_ = MachineStuff.MachinePool.TryUpdateMachineID(Common.MachineName, Common.MachineID, true);
|
||||
}
|
||||
|
||||
private static void InitializeMachinePoolFromSettings()
|
||||
@@ -59,13 +59,13 @@ namespace MouseWithoutBorders
|
||||
info[i].Name = info[i].Name.Trim();
|
||||
}
|
||||
|
||||
Common.MachinePool.Initialize(info);
|
||||
Common.MachinePool.ResetIPAddressesForDeadMachines(true);
|
||||
MachineStuff.MachinePool.Initialize(info);
|
||||
MachineStuff.MachinePool.ResetIPAddressesForDeadMachines(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log(ex);
|
||||
Common.MachinePool.Clear();
|
||||
MachineStuff.MachinePool.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,16 +74,16 @@ namespace MouseWithoutBorders
|
||||
try
|
||||
{
|
||||
GetMachineName();
|
||||
DesMachineID = NewDesMachineID = MachineID;
|
||||
DesMachineID = MachineStuff.NewDesMachineID = MachineID;
|
||||
|
||||
// MessageBox.Show(machineID.ToString(CultureInfo.CurrentCulture)); // For test
|
||||
InitializeMachinePoolFromSettings();
|
||||
|
||||
Common.MachineName = Common.MachineName.Trim();
|
||||
_ = Common.MachinePool.LearnMachine(Common.MachineName);
|
||||
_ = Common.MachinePool.TryUpdateMachineID(Common.MachineName, Common.MachineID, true);
|
||||
_ = MachineStuff.MachinePool.LearnMachine(Common.MachineName);
|
||||
_ = MachineStuff.MachinePool.TryUpdateMachineID(Common.MachineName, Common.MachineID, true);
|
||||
|
||||
Common.UpdateMachinePoolStringSetting();
|
||||
MachineStuff.UpdateMachinePoolStringSetting();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -154,7 +154,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Logger.TelemetryLogTrace($"{nameof(SystemEvents_PowerModeChanged)}: {e.Mode}", SeverityLevel.Information);
|
||||
LastResumeSuspendTime = DateTime.UtcNow;
|
||||
SwitchToMultipleMode(false, true);
|
||||
MachineStuff.SwitchToMultipleMode(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
@@ -39,23 +38,31 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
// SuppressFlow fixes an issue on service mode, where WTSQueryUserToken runs successfully once and then fails
|
||||
// on subsequent calls. The reason appears to be an unknown issue with reverting the impersonation,
|
||||
// meaning that subsequent impersonation attempts run as the logged-on user and fail.
|
||||
// This is a workaround.
|
||||
using var asyncFlowControl = System.Threading.ExecutionContext.SuppressFlow();
|
||||
|
||||
uint dwSessionId;
|
||||
IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
dwSessionId = (uint)Process.GetCurrentProcess().SessionId;
|
||||
uint rv = NativeMethods.WTSQueryUserToken(dwSessionId, ref hUserToken);
|
||||
Logger.LogDebug("WTSQueryUserToken returned " + rv.ToString(CultureInfo.CurrentCulture));
|
||||
var lastError = rv == 0 ? Marshal.GetLastWin32Error() : 0;
|
||||
|
||||
Logger.LogDebug($"{nameof(NativeMethods.WTSQueryUserToken)} returned {rv.ToString(CultureInfo.CurrentCulture)}");
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
Logger.LogDebug($"WTSQueryUserToken failed with: {Marshal.GetLastWin32Error()}.");
|
||||
Logger.Log($"{nameof(NativeMethods.WTSQueryUserToken)} failed with: {lastError}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NativeMethods.DuplicateToken(hUserToken, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref hUserTokenDup))
|
||||
{
|
||||
Logger.TelemetryLogTrace($"DuplicateToken Failed! {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
|
||||
Logger.TelemetryLogTrace($"{nameof(NativeMethods.DuplicateToken)} Failed! {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
_ = NativeMethods.CloseHandle(hUserTokenDup);
|
||||
return false;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,7 @@ namespace MouseWithoutBorders
|
||||
GetScreenConfig();
|
||||
}
|
||||
|
||||
private static readonly List<Point> SensitivePoints = new();
|
||||
internal static readonly List<Point> SensitivePoints = new();
|
||||
|
||||
private static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeMethods.RECT lprcMonitor, IntPtr dwData)
|
||||
{
|
||||
@@ -162,21 +162,21 @@ namespace MouseWithoutBorders
|
||||
|
||||
// 1000 calls to EnumDisplayMonitors cost a dozen of milliseconds
|
||||
#endif
|
||||
Interlocked.Exchange(ref desktopBounds, newDesktopBounds);
|
||||
Interlocked.Exchange(ref primaryScreenBounds, newPrimaryScreenBounds);
|
||||
Interlocked.Exchange(ref MachineStuff.desktopBounds, newDesktopBounds);
|
||||
Interlocked.Exchange(ref MachineStuff.primaryScreenBounds, newPrimaryScreenBounds);
|
||||
|
||||
Logger.Log(string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}",
|
||||
Common.RunOnLogonDesktop,
|
||||
Common.PrimaryScreenBounds.Left,
|
||||
Common.PrimaryScreenBounds.Top,
|
||||
Common.PrimaryScreenBounds.Right,
|
||||
Common.PrimaryScreenBounds.Bottom,
|
||||
Common.DesktopBounds.Left,
|
||||
Common.DesktopBounds.Top,
|
||||
Common.DesktopBounds.Right,
|
||||
Common.DesktopBounds.Bottom));
|
||||
MachineStuff.PrimaryScreenBounds.Left,
|
||||
MachineStuff.PrimaryScreenBounds.Top,
|
||||
MachineStuff.PrimaryScreenBounds.Right,
|
||||
MachineStuff.PrimaryScreenBounds.Bottom,
|
||||
MachineStuff.DesktopBounds.Left,
|
||||
MachineStuff.DesktopBounds.Top,
|
||||
MachineStuff.DesktopBounds.Right,
|
||||
MachineStuff.DesktopBounds.Bottom));
|
||||
|
||||
Logger.Log("==================== GetScreenConfig ended");
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace MouseWithoutBorders
|
||||
internal const int JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999;
|
||||
|
||||
internal const int NETWORK_STREAM_BUF_SIZE = 1024 * 1024;
|
||||
private static readonly EventWaitHandle EvSwitch = new(false, EventResetMode.AutoReset);
|
||||
internal static readonly EventWaitHandle EvSwitch = new(false, EventResetMode.AutoReset);
|
||||
private static Point lastPos;
|
||||
private static int switchCount;
|
||||
private static long lastReconnectByHotKeyTime;
|
||||
@@ -236,12 +236,12 @@ namespace MouseWithoutBorders
|
||||
|
||||
internal static ID DesMachineID
|
||||
{
|
||||
get => Common.desMachineID;
|
||||
get => MachineStuff.desMachineID;
|
||||
|
||||
set
|
||||
{
|
||||
Common.desMachineID = value;
|
||||
Common.DesMachineName = Common.NameFromID(Common.desMachineID);
|
||||
MachineStuff.desMachineID = value;
|
||||
MachineStuff.DesMachineName = MachineStuff.NameFromID(MachineStuff.desMachineID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ namespace MouseWithoutBorders
|
||||
Logger.TelemetryLogTrace($"[{actionName}] took more than {(long)timeout.TotalSeconds}, restarting the process.", SeverityLevel.Warning, true);
|
||||
|
||||
string desktop = Common.GetMyDesktop();
|
||||
oneInstanceCheck?.Close();
|
||||
MachineStuff.oneInstanceCheck?.Close();
|
||||
_ = Process.Start(Application.ExecutablePath, desktop);
|
||||
Logger.LogDebug($"Started on desktop {desktop}");
|
||||
|
||||
@@ -619,12 +619,12 @@ namespace MouseWithoutBorders
|
||||
|
||||
internal static void ProcessByeByeMessage(DATA package)
|
||||
{
|
||||
if (package.Src == desMachineID)
|
||||
if (package.Src == MachineStuff.desMachineID)
|
||||
{
|
||||
SwitchToMachine(MachineName.Trim());
|
||||
MachineStuff.SwitchToMachine(MachineName.Trim());
|
||||
}
|
||||
|
||||
_ = RemoveDeadMachines(package.Src);
|
||||
_ = MachineStuff.RemoveDeadMachines(package.Src);
|
||||
}
|
||||
|
||||
internal static long GetTick() // ms
|
||||
@@ -644,12 +644,12 @@ namespace MouseWithoutBorders
|
||||
try
|
||||
{
|
||||
string fileName = GetMyStorageDir() + @"ScreenCaptureByMouseWithoutBorders.png";
|
||||
int w = desktopBounds.Right - desktopBounds.Left;
|
||||
int h = desktopBounds.Bottom - desktopBounds.Top;
|
||||
int w = MachineStuff.desktopBounds.Right - MachineStuff.desktopBounds.Left;
|
||||
int h = MachineStuff.desktopBounds.Bottom - MachineStuff.desktopBounds.Top;
|
||||
Bitmap bm = new(w, h);
|
||||
Graphics g = Graphics.FromImage(bm);
|
||||
Size s = new(w, h);
|
||||
g.CopyFromScreen(desktopBounds.Left, desktopBounds.Top, 0, 0, s);
|
||||
g.CopyFromScreen(MachineStuff.desktopBounds.Left, MachineStuff.desktopBounds.Top, 0, 0, s);
|
||||
bm.Save(fileName, ImageFormat.Png);
|
||||
bm.Dispose();
|
||||
return fileName;
|
||||
@@ -665,7 +665,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
if (!MouseDown && Common.SendMessageToHelper(0x401, IntPtr.Zero, IntPtr.Zero) > 0)
|
||||
if (!DragDrop.MouseDown && Common.SendMessageToHelper(0x401, IntPtr.Zero, IntPtr.Zero) > 0)
|
||||
{
|
||||
Common.MMSleep(0.2);
|
||||
InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT });
|
||||
@@ -675,10 +675,10 @@ namespace MouseWithoutBorders
|
||||
|
||||
_ = NativeMethods.MoveWindow(
|
||||
(IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT),
|
||||
Common.DesktopBounds.Left,
|
||||
Common.DesktopBounds.Top,
|
||||
Common.DesktopBounds.Right - Common.DesktopBounds.Left,
|
||||
Common.DesktopBounds.Bottom - Common.DesktopBounds.Top,
|
||||
MachineStuff.DesktopBounds.Left,
|
||||
MachineStuff.DesktopBounds.Top,
|
||||
MachineStuff.DesktopBounds.Right - MachineStuff.DesktopBounds.Left,
|
||||
MachineStuff.DesktopBounds.Bottom - MachineStuff.DesktopBounds.Top,
|
||||
false);
|
||||
|
||||
_ = Common.SendMessageToHelper(0x406, IntPtr.Zero, IntPtr.Zero, false);
|
||||
@@ -729,7 +729,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
ID id = Common.MachinePool.ResolveID(machine);
|
||||
ID id = MachineStuff.MachinePool.ResolveID(machine);
|
||||
if (id != ID.NONE)
|
||||
{
|
||||
SendPackage(id, PackageType.ClipboardCapture);
|
||||
@@ -753,7 +753,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (Setting.Values.FirstRun)
|
||||
{
|
||||
Common.Settings?.ShowTip(icon, tip, timeOutInMilliseconds);
|
||||
MachineStuff.Settings?.ShowTip(icon, tip, timeOutInMilliseconds);
|
||||
}
|
||||
|
||||
Common.MatrixForm?.ShowTip(icon, tip, timeOutInMilliseconds);
|
||||
@@ -882,7 +882,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
if (updateClientSockets)
|
||||
{
|
||||
UpdateClientSockets(nameof(IsConnectedTo));
|
||||
MachineStuff.UpdateClientSockets(nameof(IsConnectedTo));
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -921,7 +921,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (t != null && t.BackingSocket != null && (t.Status == SocketStatus.Connected || (t.Status == SocketStatus.Handshaking && includeHandShakingSockets)))
|
||||
{
|
||||
if (t.MachineId == (uint)data.Des || (data.Des == ID.ALL && t.MachineId != exceptDes && InMachineMatrix(t.MachineName)))
|
||||
if (t.MachineId == (uint)data.Des || (data.Des == ID.ALL && t.MachineId != exceptDes && MachineStuff.InMachineMatrix(t.MachineName)))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -952,20 +952,20 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Logger.LogDebug("********** No active connection found for the remote machine! **********" + data.Des.ToString());
|
||||
|
||||
if (data.Des == ID.NONE || RemoveDeadMachines(data.Des))
|
||||
if (data.Des == ID.NONE || MachineStuff.RemoveDeadMachines(data.Des))
|
||||
{
|
||||
// SwitchToMachine(MachineName.Trim());
|
||||
NewDesMachineID = DesMachineID = MachineID;
|
||||
SwitchLocation.X = XY_BY_PIXEL + myLastX;
|
||||
SwitchLocation.Y = XY_BY_PIXEL + myLastY;
|
||||
SwitchLocation.ResetCount();
|
||||
MachineStuff.NewDesMachineID = DesMachineID = MachineID;
|
||||
MachineStuff.SwitchLocation.X = XY_BY_PIXEL + myLastX;
|
||||
MachineStuff.SwitchLocation.Y = XY_BY_PIXEL + myLastY;
|
||||
MachineStuff.SwitchLocation.ResetCount();
|
||||
EvSwitch.Set();
|
||||
}
|
||||
}
|
||||
|
||||
if (updateClientSockets)
|
||||
{
|
||||
UpdateClientSockets("SkSend");
|
||||
MachineStuff.UpdateClientSockets("SkSend");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -1203,7 +1203,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
int machineCt = 0;
|
||||
|
||||
foreach (string m in Common.MachineMatrix)
|
||||
foreach (string m in MachineStuff.MachineMatrix)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(m.Trim()))
|
||||
{
|
||||
@@ -1211,15 +1211,15 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
if (machineCt < 2 && Common.Settings != null && (Common.Settings.GetCurrentPage() is SetupPage1 || Common.Settings.GetCurrentPage() is SetupPage2b))
|
||||
if (machineCt < 2 && MachineStuff.Settings != null && (MachineStuff.Settings.GetCurrentPage() is SetupPage1 || MachineStuff.Settings.GetCurrentPage() is SetupPage2b))
|
||||
{
|
||||
Common.MachineMatrix = new string[Common.MAX_MACHINE] { Common.MachineName.Trim(), desMachine, string.Empty, string.Empty };
|
||||
Logger.LogDebug("UpdateSetupMachineMatrix: " + string.Join(",", Common.MachineMatrix));
|
||||
MachineStuff.MachineMatrix = new string[MachineStuff.MAX_MACHINE] { Common.MachineName.Trim(), desMachine, string.Empty, string.Empty };
|
||||
Logger.LogDebug("UpdateSetupMachineMatrix: " + string.Join(",", MachineStuff.MachineMatrix));
|
||||
|
||||
Common.DoSomethingInUIThread(
|
||||
() =>
|
||||
{
|
||||
Common.Settings.SetControlPage(new SetupPage4());
|
||||
MachineStuff.Settings.SetControlPage(new SetupPage4());
|
||||
},
|
||||
true);
|
||||
}
|
||||
@@ -1255,7 +1255,7 @@ namespace MouseWithoutBorders
|
||||
SocketStuff.ClearBadIPs();
|
||||
}
|
||||
|
||||
UpdateClientSockets("ReopenSockets");
|
||||
MachineStuff.UpdateClientSockets("ReopenSockets");
|
||||
}
|
||||
},
|
||||
true);
|
||||
@@ -1473,17 +1473,17 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Logger.LogDebug("+++++ MoveMouseToCenter");
|
||||
InputSimulation.MoveMouse(
|
||||
Common.PrimaryScreenBounds.Left + ((Common.PrimaryScreenBounds.Right - Common.PrimaryScreenBounds.Left) / 2),
|
||||
Common.PrimaryScreenBounds.Top + ((Common.PrimaryScreenBounds.Bottom - Common.PrimaryScreenBounds.Top) / 2));
|
||||
MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2),
|
||||
MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2));
|
||||
}
|
||||
|
||||
internal static void HideMouseCursor(bool byHideMouseMessage)
|
||||
{
|
||||
Common.LastPos = new Point(
|
||||
Common.PrimaryScreenBounds.Left + ((Common.PrimaryScreenBounds.Right - Common.PrimaryScreenBounds.Left) / 2),
|
||||
Setting.Values.HideMouse ? 4 : Common.PrimaryScreenBounds.Top + ((Common.PrimaryScreenBounds.Bottom - Common.PrimaryScreenBounds.Top) / 2));
|
||||
MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2),
|
||||
Setting.Values.HideMouse ? 4 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2));
|
||||
|
||||
if ((desMachineID != MachineID && desMachineID != ID.ALL) || byHideMouseMessage)
|
||||
if ((MachineStuff.desMachineID != MachineID && MachineStuff.desMachineID != ID.ALL) || byHideMouseMessage)
|
||||
{
|
||||
_ = NativeMethods.SetCursorPos(Common.LastPos.X, Common.LastPos.Y);
|
||||
_ = NativeMethods.GetCursorPos(ref Common.lastPos);
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
public void SendDragFile(string fileName)
|
||||
{
|
||||
Common.DragDropStep05Ex(fileName);
|
||||
DragDrop.DragDropStep05Ex(fileName);
|
||||
}
|
||||
|
||||
public void SendClipboardData(ByteArrayOrString data, bool isFilePath)
|
||||
|
||||
@@ -222,10 +222,10 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
Common.RealInputEventCount++;
|
||||
|
||||
if (Common.NewDesMachineID == Common.MachineID || Common.NewDesMachineID == ID.ALL)
|
||||
if (MachineStuff.NewDesMachineID == Common.MachineID || MachineStuff.NewDesMachineID == ID.ALL)
|
||||
{
|
||||
local = true;
|
||||
if (Common.MainFormVisible && !Common.IsDropping)
|
||||
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
||||
{
|
||||
Common.MainFormDot();
|
||||
}
|
||||
@@ -265,19 +265,19 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Common.SwitchLocation.Count > 0 && Common.NewDesMachineID != Common.MachineID && Common.NewDesMachineID != ID.ALL)
|
||||
if (MachineStuff.SwitchLocation.Count > 0 && MachineStuff.NewDesMachineID != Common.MachineID && MachineStuff.NewDesMachineID != ID.ALL)
|
||||
{
|
||||
Common.SwitchLocation.Count--;
|
||||
MachineStuff.SwitchLocation.Count--;
|
||||
|
||||
if (Common.SwitchLocation.X > Common.XY_BY_PIXEL - 100000 || Common.SwitchLocation.Y > Common.XY_BY_PIXEL - 100000)
|
||||
if (MachineStuff.SwitchLocation.X > Common.XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > Common.XY_BY_PIXEL - 100000)
|
||||
{
|
||||
hookCallbackMouseData.X = Common.SwitchLocation.X - Common.XY_BY_PIXEL;
|
||||
hookCallbackMouseData.Y = Common.SwitchLocation.Y - Common.XY_BY_PIXEL;
|
||||
hookCallbackMouseData.X = MachineStuff.SwitchLocation.X - Common.XY_BY_PIXEL;
|
||||
hookCallbackMouseData.Y = MachineStuff.SwitchLocation.Y - Common.XY_BY_PIXEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
hookCallbackMouseData.X = (Common.SwitchLocation.X * Common.ScreenWidth / 65535) + Common.PrimaryScreenBounds.Left;
|
||||
hookCallbackMouseData.Y = (Common.SwitchLocation.Y * Common.ScreenHeight / 65535) + Common.PrimaryScreenBounds.Top;
|
||||
hookCallbackMouseData.X = (MachineStuff.SwitchLocation.X * Common.ScreenWidth / 65535) + MachineStuff.PrimaryScreenBounds.Left;
|
||||
hookCallbackMouseData.Y = (MachineStuff.SwitchLocation.Y * Common.ScreenHeight / 65535) + MachineStuff.PrimaryScreenBounds.Top;
|
||||
}
|
||||
|
||||
Common.HideMouseCursor(false);
|
||||
@@ -290,22 +290,22 @@ namespace MouseWithoutBorders.Class
|
||||
hookCallbackMouseData.X += dx;
|
||||
hookCallbackMouseData.Y += dy;
|
||||
|
||||
if (hookCallbackMouseData.X < Common.PrimaryScreenBounds.Left)
|
||||
if (hookCallbackMouseData.X < MachineStuff.PrimaryScreenBounds.Left)
|
||||
{
|
||||
hookCallbackMouseData.X = Common.PrimaryScreenBounds.Left - 1;
|
||||
hookCallbackMouseData.X = MachineStuff.PrimaryScreenBounds.Left - 1;
|
||||
}
|
||||
else if (hookCallbackMouseData.X > Common.PrimaryScreenBounds.Right)
|
||||
else if (hookCallbackMouseData.X > MachineStuff.PrimaryScreenBounds.Right)
|
||||
{
|
||||
hookCallbackMouseData.X = Common.PrimaryScreenBounds.Right + 1;
|
||||
hookCallbackMouseData.X = MachineStuff.PrimaryScreenBounds.Right + 1;
|
||||
}
|
||||
|
||||
if (hookCallbackMouseData.Y < Common.PrimaryScreenBounds.Top)
|
||||
if (hookCallbackMouseData.Y < MachineStuff.PrimaryScreenBounds.Top)
|
||||
{
|
||||
hookCallbackMouseData.Y = Common.PrimaryScreenBounds.Top - 1;
|
||||
hookCallbackMouseData.Y = MachineStuff.PrimaryScreenBounds.Top - 1;
|
||||
}
|
||||
else if (hookCallbackMouseData.Y > Common.PrimaryScreenBounds.Bottom)
|
||||
else if (hookCallbackMouseData.Y > MachineStuff.PrimaryScreenBounds.Bottom)
|
||||
{
|
||||
hookCallbackMouseData.Y = Common.PrimaryScreenBounds.Bottom + 1;
|
||||
hookCallbackMouseData.Y = MachineStuff.PrimaryScreenBounds.Bottom + 1;
|
||||
}
|
||||
|
||||
dx += dx < 0 ? -Common.MOVE_MOUSE_RELATIVE : Common.MOVE_MOUSE_RELATIVE;
|
||||
@@ -315,8 +315,8 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
MouseEvent(hookCallbackMouseData, dx, dy);
|
||||
|
||||
Common.DragDropStep01(wParam);
|
||||
Common.DragDropStep09(wParam);
|
||||
DragDrop.DragDropStep01(wParam);
|
||||
DragDrop.DragDropStep09(wParam);
|
||||
}
|
||||
|
||||
if (local)
|
||||
@@ -432,7 +432,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (Common.DesMachineID != ID.ALL)
|
||||
{
|
||||
Common.SwitchToMachine(Common.MachineName.Trim());
|
||||
MachineStuff.SwitchToMachine(Common.MachineName.Trim());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -518,7 +518,7 @@ namespace MouseWithoutBorders.Class
|
||||
if (Common.HotkeyMatched(vkCode, winDown, CtrlDown, altDown, shiftDown, Setting.Values.HotKeySwitch2AllPC))
|
||||
{
|
||||
ResetLastSwitchKeys();
|
||||
Common.SwitchToMultipleMode(Common.DesMachineID != ID.ALL, true);
|
||||
MachineStuff.SwitchToMultipleMode(Common.DesMachineID != ID.ALL, true);
|
||||
}
|
||||
|
||||
if (Common.HotkeyMatched(vkCode, winDown, CtrlDown, altDown, shiftDown, Setting.Values.HotKeyToggleEasyMouse))
|
||||
@@ -543,7 +543,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
if (Common.GetTick() - lastHotKeyLockMachine < 500)
|
||||
{
|
||||
Common.SwitchToMultipleMode(true, true);
|
||||
MachineStuff.SwitchToMultipleMode(true, true);
|
||||
|
||||
var codes = GetVkCodesList(Setting.Values.HotKeyLockMachine);
|
||||
|
||||
@@ -561,7 +561,7 @@ namespace MouseWithoutBorders.Class
|
||||
KeyboardEvent(hookCallbackKeybdData);
|
||||
}
|
||||
|
||||
Common.SwitchToMultipleMode(false, true);
|
||||
MachineStuff.SwitchToMultipleMode(false, true);
|
||||
|
||||
_ = NativeMethods.LockWorkStation();
|
||||
}
|
||||
@@ -625,9 +625,9 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
private static bool Switch2(int index)
|
||||
{
|
||||
if (Common.MachineMatrix != null && Common.MachineMatrix.Length > index)
|
||||
if (MachineStuff.MachineMatrix != null && MachineStuff.MachineMatrix.Length > index)
|
||||
{
|
||||
string mcName = Common.MachineMatrix[index].Trim();
|
||||
string mcName = MachineStuff.MachineMatrix[index].Trim();
|
||||
if (!string.IsNullOrEmpty(mcName))
|
||||
{
|
||||
// Common.DoSomethingInUIThread(delegate()
|
||||
@@ -636,7 +636,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
|
||||
// );
|
||||
Common.SwitchToMachine(mcName);
|
||||
MachineStuff.SwitchToMachine(mcName);
|
||||
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
|
||||
@@ -162,10 +162,10 @@ namespace MouseWithoutBorders.Class
|
||||
uint rv = 0;
|
||||
NativeMethods.INPUT mouse_input = default;
|
||||
|
||||
long w65535 = (Common.DesktopBounds.Right - Common.DesktopBounds.Left) * 65535 / Common.ScreenWidth;
|
||||
long h65535 = (Common.DesktopBounds.Bottom - Common.DesktopBounds.Top) * 65535 / Common.ScreenHeight;
|
||||
long l65535 = Common.DesktopBounds.Left * 65535 / Common.ScreenWidth;
|
||||
long t65535 = Common.DesktopBounds.Top * 65535 / Common.ScreenHeight;
|
||||
long w65535 = (MachineStuff.DesktopBounds.Right - MachineStuff.DesktopBounds.Left) * 65535 / Common.ScreenWidth;
|
||||
long h65535 = (MachineStuff.DesktopBounds.Bottom - MachineStuff.DesktopBounds.Top) * 65535 / Common.ScreenHeight;
|
||||
long l65535 = MachineStuff.DesktopBounds.Left * 65535 / Common.ScreenWidth;
|
||||
long t65535 = MachineStuff.DesktopBounds.Top * 65535 / Common.ScreenHeight;
|
||||
mouse_input.type = 0;
|
||||
long dx = (md.X * w65535 / 65535) + l65535;
|
||||
long dy = (md.Y * h65535 / 65535) + t65535;
|
||||
@@ -221,7 +221,7 @@ namespace MouseWithoutBorders.Class
|
||||
rv = SendInputEx(mouse_input);
|
||||
});
|
||||
|
||||
if (Common.MainFormVisible && !Common.IsDropping)
|
||||
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
||||
{
|
||||
Common.MainFormDot();
|
||||
}
|
||||
@@ -233,10 +233,10 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
NativeMethods.INPUT mouse_input = default;
|
||||
|
||||
long w65535 = (Common.DesktopBounds.Right - Common.DesktopBounds.Left) * 65535 / Common.ScreenWidth;
|
||||
long h65535 = (Common.DesktopBounds.Bottom - Common.DesktopBounds.Top) * 65535 / Common.ScreenHeight;
|
||||
long l65535 = Common.DesktopBounds.Left * 65535 / Common.ScreenWidth;
|
||||
long t65535 = Common.DesktopBounds.Top * 65535 / Common.ScreenHeight;
|
||||
long w65535 = (MachineStuff.DesktopBounds.Right - MachineStuff.DesktopBounds.Left) * 65535 / Common.ScreenWidth;
|
||||
long h65535 = (MachineStuff.DesktopBounds.Bottom - MachineStuff.DesktopBounds.Top) * 65535 / Common.ScreenHeight;
|
||||
long l65535 = MachineStuff.DesktopBounds.Left * 65535 / Common.ScreenWidth;
|
||||
long t65535 = MachineStuff.DesktopBounds.Top * 65535 / Common.ScreenHeight;
|
||||
mouse_input.type = 0;
|
||||
long dx = (x * w65535 / 65535) + l65535;
|
||||
long dy = (y * h65535 / 65535) + t65535;
|
||||
|
||||
@@ -12,6 +12,8 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
namespace MouseWithoutBorders.Class
|
||||
{
|
||||
/// <summary>
|
||||
@@ -113,10 +115,10 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
Name = list[i].Name,
|
||||
Id = list[i].Id,
|
||||
Time = list[i].Time > Common.GetTick() - Common.HEARTBEAT_TIMEOUT + 10000 ? Common.GetTick() - Common.HEARTBEAT_TIMEOUT + 10000 : list[i].Time,
|
||||
Time = list[i].Time > Common.GetTick() - MachineStuff.HEARTBEAT_TIMEOUT + 10000 ? Common.GetTick() - MachineStuff.HEARTBEAT_TIMEOUT + 10000 : list[i].Time,
|
||||
};
|
||||
|
||||
foundAndTimedOut = list[i].Time < Common.GetTick() - Common.HEARTBEAT_TIMEOUT + 10000 - 5000;
|
||||
foundAndTimedOut = list[i].Time < Common.GetTick() - MachineStuff.HEARTBEAT_TIMEOUT + 10000 - 5000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +159,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else if (list.Count >= 4)
|
||||
{
|
||||
throw new ArgumentException($"The number of machines exceeded the maximum allowed limit of {Common.MAX_MACHINE}. Actual count: {list.Count}.");
|
||||
throw new ArgumentException($"The number of machines exceeded the maximum allowed limit of {MachineStuff.MAX_MACHINE}. Actual count: {list.Count}.");
|
||||
}
|
||||
|
||||
_ = LearnMachine(name);
|
||||
@@ -179,7 +181,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else if (list.Count >= 4)
|
||||
{
|
||||
throw new ArgumentException($"The number of machines exceeded the maximum allowed limit of {Common.MAX_MACHINE}. Actual count: {list.Count}.");
|
||||
throw new ArgumentException($"The number of machines exceeded the maximum allowed limit of {MachineStuff.MAX_MACHINE}. Actual count: {list.Count}.");
|
||||
}
|
||||
|
||||
_ = LearnMachine(inf.Name);
|
||||
@@ -212,13 +214,13 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
if (list.Count >= Common.MAX_MACHINE)
|
||||
if (list.Count >= MachineStuff.MAX_MACHINE)
|
||||
{
|
||||
int slotFound = -1;
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (!Common.InMachineMatrix(list[i].Name))
|
||||
if (!MachineStuff.InMachineMatrix(list[i].Name))
|
||||
{
|
||||
slotFound = i;
|
||||
break;
|
||||
@@ -289,7 +291,7 @@ namespace MouseWithoutBorders.Class
|
||||
List<MachineInf> machinePool = ListAllMachines();
|
||||
string rv = string.Join(",", machinePool.Select(m => $"{m.Name}:{m.Id}"));
|
||||
|
||||
for (int j = machinePool.Count; j < Common.MAX_MACHINE; j++)
|
||||
for (int j = machinePool.Count; j < MachineStuff.MAX_MACHINE; j++)
|
||||
{
|
||||
rv += ",:";
|
||||
}
|
||||
@@ -301,7 +303,7 @@ namespace MouseWithoutBorders.Class
|
||||
/// <param name="clockSkewInMS_forTesting">When doing unit tests it's nice to be able to fudge with the clock time, adding milliseconds, instead of sleeping.</param>
|
||||
internal static bool IsAlive(MachineInf inf, int clockSkewInMS_forTesting = 0)
|
||||
{
|
||||
return inf.Id != ID.NONE && (Common.GetTick() + clockSkewInMS_forTesting - inf.Time <= Common.HEARTBEAT_TIMEOUT || Common.IsConnectedTo(inf.Id));
|
||||
return inf.Id != ID.NONE && (Common.GetTick() + clockSkewInMS_forTesting - inf.Time <= MachineStuff.HEARTBEAT_TIMEOUT || Common.IsConnectedTo(inf.Id));
|
||||
}
|
||||
|
||||
private static bool NamesAreEqual(string name1, string name2)
|
||||
@@ -326,7 +328,7 @@ namespace MouseWithoutBorders.Class
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((firstLoaded && !Common.InMachineMatrix(list[i].Name)) || (!firstLoaded && (!Common.InMachineMatrix(list[i].Name) || !IsAlive(list[i]))))
|
||||
if ((firstLoaded && !MachineStuff.InMachineMatrix(list[i].Name)) || (!firstLoaded && (!MachineStuff.InMachineMatrix(list[i].Name) || !IsAlive(list[i]))))
|
||||
{
|
||||
list[i] =
|
||||
new MachineInf
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
using System;
|
||||
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
namespace MouseWithoutBorders.Class
|
||||
{
|
||||
internal static class MachinePoolHelpers
|
||||
@@ -20,20 +22,20 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
string[] st = s.Split(Comma);
|
||||
|
||||
if (st.Length < Common.MAX_MACHINE)
|
||||
if (st.Length < MachineStuff.MAX_MACHINE)
|
||||
{
|
||||
throw new ArgumentException("Not enough elements in encoded MachinePool string");
|
||||
}
|
||||
|
||||
MachineInf[] rv = new MachineInf[Common.MAX_MACHINE];
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
MachineInf[] rv = new MachineInf[MachineStuff.MAX_MACHINE];
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
string[] mc = st[i].Split(Colon);
|
||||
if (mc.Length == 2)
|
||||
{
|
||||
rv[i].Name = mc[0];
|
||||
rv[i].Id = uint.TryParse(mc[1], out uint ip) ? (ID)ip : ID.NONE;
|
||||
rv[i].Time = rv[i].Id == ID.NONE ? Common.GetTick() - Common.HEARTBEAT_TIMEOUT : Common.GetTick();
|
||||
rv[i].Time = rv[i].Id == ID.NONE ? Common.GetTick() - MachineStuff.HEARTBEAT_TIMEOUT : Common.GetTick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,41 @@ namespace MouseWithoutBorders.Class
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern uint WTSGetActiveConsoleSessionId();
|
||||
|
||||
[DllImport("Wtsapi32.dll")]
|
||||
internal static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTSInfoClass infoClass, out IntPtr ppBuffer, out int pBytesReturned);
|
||||
|
||||
[DllImport("Wtsapi32.dll")]
|
||||
internal static extern void WTSFreeMemory(IntPtr pointer);
|
||||
|
||||
internal enum WTSInfoClass
|
||||
{
|
||||
WTSInitialProgram,
|
||||
WTSApplicationName,
|
||||
WTSWorkingDirectory,
|
||||
WTSOEMId,
|
||||
WTSSessionId,
|
||||
WTSUserName,
|
||||
WTSWinStationName,
|
||||
WTSDomainName,
|
||||
WTSConnectState,
|
||||
WTSClientBuildNumber,
|
||||
WTSClientName,
|
||||
WTSClientDirectory,
|
||||
WTSClientProductId,
|
||||
WTSClientHardwareId,
|
||||
WTSClientAddress,
|
||||
WTSClientDisplay,
|
||||
WTSClientProtocolType,
|
||||
WTSIdleTime,
|
||||
WTSLogonTime,
|
||||
WTSIncomingBytes,
|
||||
WTSOutgoingBytes,
|
||||
WTSIncomingFrames,
|
||||
WTSOutgoingFrames,
|
||||
WTSClientInfo,
|
||||
WTSSessionInfo,
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
@@ -812,7 +847,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
// [DllImport("kernel32.dll", SetLastError = true)]
|
||||
// internal static extern IntPtr CreateToolhelp32Snapshot(UInt32 dwFlags, UInt32 th32ProcessID);
|
||||
[DllImport("Wtsapi32.dll")]
|
||||
[DllImport("Wtsapi32.dll", SetLastError = true)]
|
||||
internal static extern uint WTSQueryUserToken(uint SessionId, ref IntPtr phToken);
|
||||
|
||||
[SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "1", Justification = "Dotnet port with style preservation")]
|
||||
|
||||
@@ -31,6 +31,7 @@ using System.Xml.Linq;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using MouseWithoutBorders.Core;
|
||||
using Newtonsoft.Json;
|
||||
using StreamJsonRpc;
|
||||
|
||||
@@ -92,6 +93,17 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
bool serviceMode = firstArg == ServiceModeArg;
|
||||
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredMwbAllowServiceModeValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||
{
|
||||
if (runningAsSystem)
|
||||
{
|
||||
Logger.Log("Can't run as a service. It's not allowed according to GPO policy. Please contact your systems administrator.");
|
||||
return;
|
||||
}
|
||||
|
||||
serviceMode = false;
|
||||
}
|
||||
|
||||
// If we're started from the .dll module or from the service process, we should
|
||||
// assume the service mode.
|
||||
if (serviceMode && !runningAsSystem)
|
||||
@@ -124,7 +136,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (firstArg != string.Empty)
|
||||
{
|
||||
if (Common.CheckSecondInstance(Common.RunWithNoAdminRight))
|
||||
if (MachineStuff.CheckSecondInstance(Common.RunWithNoAdminRight))
|
||||
{
|
||||
Logger.Log("*** Second instance, exiting...");
|
||||
return;
|
||||
@@ -154,7 +166,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Common.CheckSecondInstance(true))
|
||||
if (MachineStuff.CheckSecondInstance(true))
|
||||
{
|
||||
Logger.Log("*** Second instance, exiting...");
|
||||
return;
|
||||
@@ -290,20 +302,20 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
Setting.Values.PauseInstantSaving = true;
|
||||
|
||||
Common.ClearComputerMatrix();
|
||||
MachineStuff.ClearComputerMatrix();
|
||||
Setting.Values.MyKey = securityKey;
|
||||
Common.MyKey = securityKey;
|
||||
Common.MagicNumber = Common.Get24BitHash(Common.MyKey);
|
||||
Common.MachineMatrix = new string[Common.MAX_MACHINE] { pcName.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty };
|
||||
MachineStuff.MachineMatrix = new string[MachineStuff.MAX_MACHINE] { pcName.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty };
|
||||
|
||||
string[] machines = Common.MachineMatrix;
|
||||
Common.MachinePool.Initialize(machines);
|
||||
Common.UpdateMachinePoolStringSetting();
|
||||
string[] machines = MachineStuff.MachineMatrix;
|
||||
MachineStuff.MachinePool.Initialize(machines);
|
||||
MachineStuff.UpdateMachinePoolStringSetting();
|
||||
|
||||
SocketStuff.InvalidKeyFound = false;
|
||||
Common.ReopenSocketDueToReadError = true;
|
||||
Common.ReopenSockets(true);
|
||||
Common.SendMachineMatrix();
|
||||
MachineStuff.SendMachineMatrix();
|
||||
|
||||
Setting.Values.PauseInstantSaving = false;
|
||||
Setting.Values.SaveSettings();
|
||||
@@ -314,7 +326,7 @@ namespace MouseWithoutBorders.Class
|
||||
Setting.Values.PauseInstantSaving = true;
|
||||
|
||||
Setting.Values.EasyMouse = (int)EasyMouseOption.Enable;
|
||||
Common.ClearComputerMatrix();
|
||||
MachineStuff.ClearComputerMatrix();
|
||||
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
|
||||
Common.GeneratedKey = true;
|
||||
|
||||
@@ -341,7 +353,7 @@ namespace MouseWithoutBorders.Class
|
||||
Common.MMSleep(0.2);
|
||||
}
|
||||
|
||||
Common.SendMachineMatrix();
|
||||
MachineStuff.SendMachineMatrix();
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace MouseWithoutBorders.Class
|
||||
if (!Enumerable.SequenceEqual(last_properties.MachineMatrixString, _settings.Properties.MachineMatrixString))
|
||||
{
|
||||
_properties.MachineMatrixString = _settings.Properties.MachineMatrixString;
|
||||
Common.MachineMatrix = null; // Forces read next time it's needed.
|
||||
MachineStuff.MachineMatrix = null; // Forces read next time it's needed.
|
||||
shouldSendMachineMatrix = true;
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (shouldSendMachineMatrix)
|
||||
{
|
||||
Common.SendMachineMatrix();
|
||||
MachineStuff.SendMachineMatrix();
|
||||
shouldSaveNewSettingsValues = true;
|
||||
}
|
||||
|
||||
@@ -1090,6 +1090,11 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbAllowServiceModeValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.UseService;
|
||||
@@ -1098,6 +1103,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (AllowServiceModeIsGpoConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.UseService = value;
|
||||
@@ -1109,6 +1119,10 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool AllowServiceModeIsGpoConfigured => GPOWrapper.GetConfiguredMwbAllowServiceModeValue() == GpoRuleConfigured.Disabled;
|
||||
|
||||
// Note(@htcfreek): Settings UI CheckBox is disabled in frmMatrix.cs > FrmMatrix_Load()
|
||||
internal bool SendErrorLogV2
|
||||
{
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
if (Common.DesMachineID != Common.MachineID)
|
||||
{
|
||||
Common.SwitchToMultipleMode(false, true);
|
||||
MachineStuff.SwitchToMultipleMode(false, true);
|
||||
}
|
||||
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
@@ -253,7 +253,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
if (Setting.Values.LastX == Common.JUST_GOT_BACK_FROM_SCREEN_SAVER)
|
||||
{
|
||||
Common.NewDesMachineID = Common.DesMachineID = Common.MachineID;
|
||||
MachineStuff.NewDesMachineID = Common.DesMachineID = Common.MachineID;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -263,11 +263,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (Common.RunOnLogonDesktop && Setting.Values.DesMachineID == (uint)ID.ALL)
|
||||
{
|
||||
Common.SwitchToMultipleMode(true, false);
|
||||
MachineStuff.SwitchToMultipleMode(true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Common.SwitchToMultipleMode(false, false);
|
||||
MachineStuff.SwitchToMultipleMode(false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -804,11 +804,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
try
|
||||
{
|
||||
if (Common.MachineMatrix != null)
|
||||
if (MachineStuff.MachineMatrix != null)
|
||||
{
|
||||
Logger.LogDebug("MachineMatrix = " + string.Join(", ", Common.MachineMatrix));
|
||||
Logger.LogDebug("MachineMatrix = " + string.Join(", ", MachineStuff.MachineMatrix));
|
||||
|
||||
foreach (string st in Common.MachineMatrix)
|
||||
foreach (string st in MachineStuff.MachineMatrix)
|
||||
{
|
||||
string machineName = st.Trim();
|
||||
if (!string.IsNullOrEmpty(machineName) &&
|
||||
@@ -961,7 +961,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
UpdateTcpSockets(dummyTcp, SocketStatus.NA);
|
||||
|
||||
if (!Common.InMachineMatrix(machineName))
|
||||
if (!MachineStuff.InMachineMatrix(machineName))
|
||||
{
|
||||
// While Resolving from name to IP, user may have changed the machine name and clicked on Apply.
|
||||
return;
|
||||
@@ -1449,19 +1449,19 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
Common.SendHeartBeat(initial: true);
|
||||
|
||||
if (Common.MachinePool.TryFindMachineByName(remoteMachine, out MachineInf machineInfo))
|
||||
if (MachineStuff.MachinePool.TryFindMachineByName(remoteMachine, out MachineInf machineInfo))
|
||||
{
|
||||
Logger.LogDebug("Machine updated: " + remoteMachine + "/" + remoteID.ToString());
|
||||
|
||||
if (machineInfo.Name.Equals(Common.DesMachineName, StringComparison.OrdinalIgnoreCase))
|
||||
if (machineInfo.Name.Equals(MachineStuff.DesMachineName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Logger.LogDebug("Des ID updated: " + Common.DesMachineID.ToString() +
|
||||
"/" + remoteID.ToString());
|
||||
Common.NewDesMachineID = Common.DesMachineID = remoteID;
|
||||
MachineStuff.NewDesMachineID = Common.DesMachineID = remoteID;
|
||||
}
|
||||
|
||||
_ = Common.MachinePool.TryUpdateMachineID(remoteMachine, remoteID, true);
|
||||
Common.UpdateMachinePoolStringSetting();
|
||||
_ = MachineStuff.MachinePool.TryUpdateMachineID(remoteMachine, remoteID, true);
|
||||
MachineStuff.UpdateMachinePoolStringSetting();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1475,7 +1475,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (!isClient)
|
||||
{
|
||||
Common.UpdateClientSockets("MainTCPRoutine");
|
||||
MachineStuff.UpdateClientSockets("MainTCPRoutine");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1559,7 +1559,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (remoteID != ID.NONE)
|
||||
{
|
||||
_ = Common.RemoveDeadMachines(remoteID);
|
||||
_ = MachineStuff.RemoveDeadMachines(remoteID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1635,9 +1635,9 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
string remoteEndPoint = s.RemoteEndPoint.ToString();
|
||||
Logger.LogDebug("SendClipboardData: Request accepted: " + s.LocalEndPoint.ToString() + "/" + remoteEndPoint);
|
||||
Common.IsDropping = false;
|
||||
Common.IsDragging = false;
|
||||
Common.DragMachine = (ID)1;
|
||||
DragDrop.IsDropping = false;
|
||||
DragDrop.IsDragging = false;
|
||||
DragDrop.DragMachine = (ID)1;
|
||||
|
||||
bool clientPushData = true;
|
||||
ClipboardPostAction postAction = ClipboardPostAction.Other;
|
||||
@@ -2064,7 +2064,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (string.IsNullOrEmpty(tcp.MachineName) || tcp.MachineName.Contains('.') || tcp.MachineName.Contains(':'))
|
||||
{
|
||||
tcp.MachineName = Common.NameFromID((ID)tcp.MachineId);
|
||||
tcp.MachineName = MachineStuff.NameFromID((ID)tcp.MachineId);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tcp.MachineName) || tcp.MachineName.Contains('.') || tcp.MachineName.Contains(':'))
|
||||
|
||||
404
src/modules/MouseWithoutBorders/App/Core/DragDrop.cs
Normal file
404
src/modules/MouseWithoutBorders/App/Core/DragDrop.cs
Normal file
@@ -0,0 +1,404 @@
|
||||
// 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.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using MouseWithoutBorders.Class;
|
||||
|
||||
// <summary>
|
||||
// Drag/Drop implementation.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
namespace MouseWithoutBorders.Core;
|
||||
|
||||
/* Common.DragDrop.cs
|
||||
* Drag&Drop is one complicated implementation of the tool with some tricks.
|
||||
*
|
||||
* SEQUENCE OF EVENTS:
|
||||
* DragDropStep01: MachineX: Remember mouse down state since it could be a start of a dragging
|
||||
* DragDropStep02: MachineY: Send an message to the MachineX to ask it to check if it is
|
||||
* doing drag/drop
|
||||
* DragDropStep03: MachineX: Got explorerDragDrop, send WM_CHECK_EXPLORER_DRAG_DROP to its mainForm
|
||||
* DragDropStep04: MachineX: Show Mouse Without Borders Helper form at mouse cursor to get DragEnter event.
|
||||
* DragDropStepXX: MachineX: Mouse Without Borders Helper: Called by DragEnter, check if dragging a single file,
|
||||
* remember the file (set as its window caption)
|
||||
* DragDropStep05: MachineX: Get the file name from Mouse Without Borders Helper, hide Mouse Without Borders Helper window
|
||||
* DragDropStep06: MachineX: Broadcast a message saying that it has some drag file.
|
||||
* DragDropStep08: MachineY: Got ClipboardDragDrop, isDropping set, get the MachineX name from the package.
|
||||
* DragDropStep09: MachineY: Since isDropping is true, show up the drop form (looks like an icon).
|
||||
* DragDropStep10: MachineY: MouseUp, set isDropping to false, hide the drop "icon" and get data.
|
||||
* DragDropStep11: MachineX: Mouse move back without drop event, cancelling drag/dop
|
||||
* SendClipboardBeatDragDropEnd
|
||||
* DragDropStep12: MachineY: Hide the drop "icon" when received ClipboardDragDropEnd.
|
||||
*
|
||||
* FROM VERSION 1.6.3: Drag/Drop is temporary removed, Drop action cannot be done from a lower integrity app to a higher one.
|
||||
* We have to run a helper process...
|
||||
* http://forums.microsoft.com/MSDN/ShowPost.aspx?PageIndex=1&SiteID=1&PageID=1&PostID=736086
|
||||
*
|
||||
* 2008.10.28: Trying to restore the Drag/Drop feature by adding the drag/drop helper process. Coming in version
|
||||
* 1.6.5
|
||||
* */
|
||||
|
||||
internal static class DragDrop
|
||||
{
|
||||
private static bool isDragging;
|
||||
|
||||
internal static bool IsDragging
|
||||
{
|
||||
get => DragDrop.isDragging;
|
||||
set => DragDrop.isDragging = value;
|
||||
}
|
||||
|
||||
internal static void DragDropStep01(int wParam)
|
||||
{
|
||||
if (!Setting.Values.TransferFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (wParam == Common.WM_LBUTTONDOWN)
|
||||
{
|
||||
MouseDown = true;
|
||||
DragMachine = MachineStuff.desMachineID;
|
||||
MachineStuff.dropMachineID = ID.NONE;
|
||||
Logger.LogDebug("DragDropStep01: MouseDown");
|
||||
}
|
||||
else if (wParam == Common.WM_LBUTTONUP)
|
||||
{
|
||||
MouseDown = false;
|
||||
Logger.LogDebug("DragDropStep01: MouseUp");
|
||||
}
|
||||
|
||||
if (wParam == Common.WM_RBUTTONUP && IsDropping)
|
||||
{
|
||||
IsDropping = false;
|
||||
Common.LastIDWithClipboardData = ID.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DragDropStep02()
|
||||
{
|
||||
if (MachineStuff.desMachineID == Common.MachineID)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent to myself");
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
SendCheckExplorerDragDrop();
|
||||
Logger.LogDebug("DragDropStep02: SendCheckExplorerDragDrop sent");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DragDropStep03(DATA package)
|
||||
{
|
||||
if (Common.RunOnLogonDesktop || Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (package.Des == Common.MachineID || package.Des == ID.ALL)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep03: ExplorerDragDrop Received.");
|
||||
MachineStuff.dropMachineID = package.Src; // Drop machine is the machine that sent ExplorerDragDrop
|
||||
if (MouseDown || IsDropping)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep03: Mouse is down, check if dragging...sending WM_CHECK_EXPLORER_DRAG_DROP to myself...");
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int dragDropStep05ExCalledByIpc;
|
||||
|
||||
internal static void DragDropStep04()
|
||||
{
|
||||
if (!IsDropping)
|
||||
{
|
||||
IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
|
||||
if (h.ToInt32() > 0)
|
||||
{
|
||||
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 0);
|
||||
|
||||
Common.MainForm.Hide();
|
||||
Common.MainFormVisible = false;
|
||||
|
||||
Point p = default;
|
||||
|
||||
// NativeMethods.SetWindowText(h, "");
|
||||
_ = NativeMethods.SetWindowPos(h, NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, NativeMethods.SWP_SHOWWINDOW);
|
||||
|
||||
for (int i = -10; i < 10; i++)
|
||||
{
|
||||
if (dragDropStep05ExCalledByIpc > 0)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep04: DragDropStep05ExCalledByIpc.");
|
||||
break;
|
||||
}
|
||||
|
||||
_ = NativeMethods.GetCursorPos(ref p);
|
||||
Logger.LogDebug("DragDropStep04: Moving Mouse Without Borders Helper to (" + p.X.ToString(CultureInfo.CurrentCulture) + ", " + p.Y.ToString(CultureInfo.CurrentCulture) + ")");
|
||||
_ = NativeMethods.SetWindowPos(h, NativeMethods.HWND_TOPMOST, p.X - 100 + i, p.Y - 100 + i, 200, 200, 0);
|
||||
_ = NativeMethods.SendMessage(h, 0x000F, IntPtr.Zero, IntPtr.Zero); // WM_PAINT
|
||||
Thread.Sleep(20);
|
||||
Application.DoEvents();
|
||||
|
||||
// if (GetText(h).Length > 1) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep04: Mouse without Borders Helper not found!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep04: IsDropping == true, skip checking");
|
||||
}
|
||||
|
||||
Logger.LogDebug("DragDropStep04: Got WM_CHECK_EXPLORER_DRAG_DROP, done with processing jump to DragDropStep05...");
|
||||
}
|
||||
|
||||
internal static void DragDropStep05Ex(string dragFileName)
|
||||
{
|
||||
Logger.LogDebug("DragDropStep05 called.");
|
||||
|
||||
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 1);
|
||||
|
||||
if (Common.RunOnLogonDesktop || Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsDropping)
|
||||
{
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dragFileName) && (File.Exists(dragFileName) || Directory.Exists(dragFileName)))
|
||||
{
|
||||
Common.LastDragDropFile = dragFileName;
|
||||
/*
|
||||
* possibleDropMachineID is used as desID sent in DragDropStep06();
|
||||
* */
|
||||
if (MachineStuff.dropMachineID == ID.NONE)
|
||||
{
|
||||
MachineStuff.dropMachineID = MachineStuff.newDesMachineID;
|
||||
}
|
||||
|
||||
DragDropStep06();
|
||||
Logger.LogDebug("DragDropStep05: File dragging: " + dragFileName);
|
||||
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_HIDE_DD_HELPER, (IntPtr)1, (IntPtr)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep05: File not found: [" + dragFileName + "]");
|
||||
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_HIDE_DD_HELPER, (IntPtr)0, (IntPtr)0);
|
||||
}
|
||||
|
||||
Logger.LogDebug("DragDropStep05: WM_HIDE_DDHelper sent");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("DragDropStep05: IsDropping == true, change drop machine...");
|
||||
IsDropping = false;
|
||||
Common.MainFormVisible = true; // WM_HIDE_DRAG_DROP
|
||||
SendDropBegin(); // To dropMachineID set in DragDropStep03
|
||||
}
|
||||
|
||||
MouseDown = false;
|
||||
}
|
||||
|
||||
private static void DragDropStep06()
|
||||
{
|
||||
IsDragging = true;
|
||||
Logger.LogDebug("DragDropStep06: SendClipboardBeatDragDrop");
|
||||
SendClipboardBeatDragDrop();
|
||||
SendDropBegin();
|
||||
}
|
||||
|
||||
internal static void DragDropStep08(DATA package)
|
||||
{
|
||||
Receiver.GetNameOfMachineWithClipboardData(package);
|
||||
Logger.LogDebug("DragDropStep08: ClipboardDragDrop Received. machine with drag file was set");
|
||||
}
|
||||
|
||||
internal static void DragDropStep08_2(DATA package)
|
||||
{
|
||||
if (package.Des == Common.MachineID && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
IsDropping = true;
|
||||
MachineStuff.dropMachineID = Common.MachineID;
|
||||
Logger.LogDebug("DragDropStep08_2: ClipboardDragDropOperation Received. IsDropping set");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DragDropStep09(int wParam)
|
||||
{
|
||||
if (wParam == Common.WM_MOUSEMOVE && IsDropping)
|
||||
{
|
||||
// Show/Move form
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_SHOW_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
else if (wParam == Common.WM_LBUTTONUP && (IsDropping || IsDragging))
|
||||
{
|
||||
if (IsDropping)
|
||||
{
|
||||
// Hide form, get data
|
||||
DragDropStep10();
|
||||
}
|
||||
else
|
||||
{
|
||||
IsDragging = false;
|
||||
Common.LastIDWithClipboardData = ID.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DragDropStep10()
|
||||
{
|
||||
Logger.LogDebug("DragDropStep10: Hide the form and get data...");
|
||||
IsDropping = false;
|
||||
IsDragging = false;
|
||||
Common.LastIDWithClipboardData = ID.NONE;
|
||||
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_HIDE_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new MouseWithoutBorders.Telemetry.MouseWithoutBordersDragAndDropEvent());
|
||||
Common.GetRemoteClipboard("desktop");
|
||||
}
|
||||
|
||||
internal static void DragDropStep11()
|
||||
{
|
||||
Logger.LogDebug("DragDropStep11: Mouse drag coming back, canceling drag/drop");
|
||||
SendClipboardBeatDragDropEnd();
|
||||
IsDropping = false;
|
||||
IsDragging = false;
|
||||
DragMachine = (ID)1;
|
||||
Common.LastIDWithClipboardData = ID.NONE;
|
||||
Common.LastDragDropFile = null;
|
||||
MouseDown = false;
|
||||
}
|
||||
|
||||
internal static void DragDropStep12()
|
||||
{
|
||||
Logger.LogDebug("DragDropStep12: ClipboardDragDropEnd received");
|
||||
IsDropping = false;
|
||||
Common.LastIDWithClipboardData = ID.NONE;
|
||||
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_HIDE_DRAG_DROP, (IntPtr)0, (IntPtr)0);
|
||||
});
|
||||
}
|
||||
|
||||
private static void SendCheckExplorerDragDrop()
|
||||
{
|
||||
DATA package = new();
|
||||
package.Type = PackageType.ExplorerDragDrop;
|
||||
|
||||
/*
|
||||
* package.src = newDesMachineID:
|
||||
* sent from the master machine but the src must be the
|
||||
* new des machine since the previous des machine will get this and set
|
||||
* to possibleDropMachineID in DragDropStep3()
|
||||
* */
|
||||
package.Src = MachineStuff.newDesMachineID;
|
||||
|
||||
package.Des = MachineStuff.desMachineID;
|
||||
package.MachineName = Common.MachineName;
|
||||
|
||||
Common.SkSend(package, null, false);
|
||||
}
|
||||
|
||||
internal static void ChangeDropMachine()
|
||||
{
|
||||
// desMachineID = current drop machine
|
||||
// newDesMachineID = new drop machine
|
||||
|
||||
// 1. Cancelling dropping in current drop machine
|
||||
if (MachineStuff.dropMachineID == Common.MachineID)
|
||||
{
|
||||
// Drag/Drop coming through me
|
||||
IsDropping = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Drag/Drop coming back
|
||||
SendClipboardBeatDragDropEnd();
|
||||
}
|
||||
|
||||
// 2. SendClipboardBeatDragDrop to new drop machine
|
||||
// new drop machine is not me
|
||||
if (MachineStuff.newDesMachineID != Common.MachineID)
|
||||
{
|
||||
MachineStuff.dropMachineID = MachineStuff.newDesMachineID;
|
||||
SendDropBegin();
|
||||
}
|
||||
|
||||
// New drop machine is me
|
||||
else
|
||||
{
|
||||
IsDropping = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SendClipboardBeatDragDrop()
|
||||
{
|
||||
Common.SendPackage(ID.ALL, PackageType.ClipboardDragDrop);
|
||||
}
|
||||
|
||||
private static void SendDropBegin()
|
||||
{
|
||||
Logger.LogDebug("SendDropBegin...");
|
||||
Common.SendPackage(MachineStuff.dropMachineID, PackageType.ClipboardDragDropOperation);
|
||||
}
|
||||
|
||||
private static void SendClipboardBeatDragDropEnd()
|
||||
{
|
||||
if (MachineStuff.desMachineID != Common.MachineID)
|
||||
{
|
||||
Common.SendPackage(MachineStuff.desMachineID, PackageType.ClipboardDragDropEnd);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool isDropping;
|
||||
private static ID dragMachine;
|
||||
|
||||
internal static ID DragMachine
|
||||
{
|
||||
get => DragDrop.dragMachine;
|
||||
set => DragDrop.dragMachine = value;
|
||||
}
|
||||
|
||||
internal static bool IsDropping
|
||||
{
|
||||
get => DragDrop.isDropping;
|
||||
set => DragDrop.isDropping = value;
|
||||
}
|
||||
|
||||
internal static bool MouseDown { get; set; }
|
||||
}
|
||||
@@ -199,8 +199,11 @@ internal static class Logger
|
||||
|
||||
_ = Logger.PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
|
||||
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
|
||||
sb.AppendLine("[Logger]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Logger), 0, level);
|
||||
sb.AppendLine("[DragDrop]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(DragDrop), 0, level);
|
||||
sb.AppendLine("[MachineStuff]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(MachineStuff), 0, level);
|
||||
sb.AppendLine("[Receiver]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Receiver), 0, level);
|
||||
|
||||
|
||||
20
src/modules/MouseWithoutBorders/App/Core/MachineInf.cs
Normal file
20
src/modules/MouseWithoutBorders/App/Core/MachineInf.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// 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.
|
||||
|
||||
// <summary>
|
||||
// Machine setup/switching implementation.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
namespace MouseWithoutBorders.Core;
|
||||
|
||||
internal struct MachineInf
|
||||
{
|
||||
internal string Name;
|
||||
internal ID Id;
|
||||
internal long Time;
|
||||
}
|
||||
1122
src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs
Normal file
1122
src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs
Normal file
File diff suppressed because it is too large
Load Diff
21
src/modules/MouseWithoutBorders/App/Core/MyRectangle.cs
Normal file
21
src/modules/MouseWithoutBorders/App/Core/MyRectangle.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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.
|
||||
|
||||
// <summary>
|
||||
// Machine setup/switching implementation.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
namespace MouseWithoutBorders.Core;
|
||||
|
||||
internal sealed class MyRectangle
|
||||
{
|
||||
internal int Left;
|
||||
internal int Top;
|
||||
internal int Right;
|
||||
internal int Bottom;
|
||||
}
|
||||
@@ -120,16 +120,16 @@ internal static class Receiver
|
||||
|
||||
if (package.Des == Common.MachineID || package.Des == ID.ALL)
|
||||
{
|
||||
if (Common.desMachineID != Common.MachineID)
|
||||
if (MachineStuff.desMachineID != Common.MachineID)
|
||||
{
|
||||
Common.NewDesMachineID = Common.DesMachineID = Common.MachineID;
|
||||
MachineStuff.NewDesMachineID = Common.DesMachineID = Common.MachineID;
|
||||
}
|
||||
|
||||
// NOTE(@yuyoyuppe): disabled to drop elevation requirement
|
||||
bool nonElevated = Common.RunWithNoAdminRight && false;
|
||||
if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != Common.WM_MOUSEMOVE)
|
||||
{
|
||||
if (!Common.IsDropping)
|
||||
if (!DragDrop.IsDropping)
|
||||
{
|
||||
if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN)
|
||||
{
|
||||
@@ -138,7 +138,7 @@ internal static class Receiver
|
||||
}
|
||||
else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
|
||||
{
|
||||
Common.IsDropping = false;
|
||||
DragDrop.IsDropping = false;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -153,7 +153,7 @@ internal static class Receiver
|
||||
package.Md.Y < 0 ? package.Md.Y + Common.MOVE_MOUSE_RELATIVE : package.Md.Y - Common.MOVE_MOUSE_RELATIVE);
|
||||
_ = NativeMethods.GetCursorPos(ref lastXY);
|
||||
|
||||
Point p = Common.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID);
|
||||
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID);
|
||||
|
||||
if (!p.IsEmpty)
|
||||
{
|
||||
@@ -162,11 +162,11 @@ internal static class Receiver
|
||||
Logger.LogDebug(string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"***** Controlled Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
|
||||
Common.newDesMachineIdEx,
|
||||
MachineStuff.newDesMachineIdEx,
|
||||
lastXY.X,
|
||||
lastXY.Y));
|
||||
|
||||
Common.SendNextMachine(package.Src, Common.newDesMachineIdEx, p);
|
||||
Common.SendNextMachine(package.Src, MachineStuff.newDesMachineIdEx, p);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -188,8 +188,8 @@ internal static class Receiver
|
||||
CustomCursor.ShowFakeMouseCursor(Common.LastX, Common.LastY);
|
||||
}
|
||||
|
||||
Common.DragDropStep01(package.Md.dwFlags);
|
||||
Common.DragDropStep09(package.Md.dwFlags);
|
||||
DragDrop.DragDropStep01(package.Md.dwFlags);
|
||||
DragDrop.DragDropStep09(package.Md.dwFlags);
|
||||
break;
|
||||
|
||||
case PackageType.NextMachine:
|
||||
@@ -204,7 +204,7 @@ internal static class Receiver
|
||||
|
||||
case PackageType.ExplorerDragDrop:
|
||||
Common.PackageReceived.ExplorerDragDrop++;
|
||||
Common.DragDropStep03(package);
|
||||
DragDrop.DragDropStep03(package);
|
||||
break;
|
||||
|
||||
case PackageType.Heartbeat:
|
||||
@@ -219,12 +219,12 @@ internal static class Receiver
|
||||
Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l2);
|
||||
}
|
||||
|
||||
string desMachine = Common.AddToMachinePool(package);
|
||||
string desMachine = MachineStuff.AddToMachinePool(package);
|
||||
|
||||
if (Setting.Values.FirstRun && !string.IsNullOrEmpty(desMachine))
|
||||
{
|
||||
Common.UpdateSetupMachineMatrix(desMachine);
|
||||
Common.UpdateClientSockets("UpdateSetupMachineMatrix");
|
||||
MachineStuff.UpdateClientSockets("UpdateSetupMachineMatrix");
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -244,14 +244,14 @@ internal static class Receiver
|
||||
|
||||
case PackageType.Awake:
|
||||
Common.PackageReceived.Heartbeat++;
|
||||
_ = Common.AddToMachinePool(package);
|
||||
_ = MachineStuff.AddToMachinePool(package);
|
||||
Common.HumanBeingDetected();
|
||||
break;
|
||||
|
||||
case PackageType.Hello:
|
||||
Common.PackageReceived.Hello++;
|
||||
Common.SendHeartBeat();
|
||||
string newMachine = Common.AddToMachinePool(package);
|
||||
string newMachine = MachineStuff.AddToMachinePool(package);
|
||||
if (Setting.Values.MachineMatrixString == null)
|
||||
{
|
||||
string tip = newMachine + " saying Hello!";
|
||||
@@ -345,17 +345,17 @@ internal static class Receiver
|
||||
|
||||
case PackageType.ClipboardDragDrop:
|
||||
Common.PackageReceived.ClipboardDragDrop++;
|
||||
Common.DragDropStep08(package);
|
||||
DragDrop.DragDropStep08(package);
|
||||
break;
|
||||
|
||||
case PackageType.ClipboardDragDropOperation:
|
||||
Common.PackageReceived.ClipboardDragDrop++;
|
||||
Common.DragDropStep08_2(package);
|
||||
DragDrop.DragDropStep08_2(package);
|
||||
break;
|
||||
|
||||
case PackageType.ClipboardDragDropEnd:
|
||||
Common.PackageReceived.ClipboardDragDropEnd++;
|
||||
Common.DragDropStep12();
|
||||
DragDrop.DragDropStep12();
|
||||
break;
|
||||
|
||||
case PackageType.ClipboardText:
|
||||
@@ -391,7 +391,7 @@ internal static class Receiver
|
||||
if ((package.Type & PackageType.Matrix) == PackageType.Matrix)
|
||||
{
|
||||
Common.PackageReceived.Matrix++;
|
||||
Common.UpdateMachineMatrix(package);
|
||||
MachineStuff.UpdateMachineMatrix(package);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -406,7 +406,7 @@ internal static class Receiver
|
||||
internal static void GetNameOfMachineWithClipboardData(DATA package)
|
||||
{
|
||||
Common.LastIDWithClipboardData = package.Src;
|
||||
List<MachineInf> matchingMachines = Common.MachinePool.TryFindMachineByID(Common.LastIDWithClipboardData);
|
||||
List<MachineInf> matchingMachines = MachineStuff.MachinePool.TryFindMachineByID(Common.LastIDWithClipboardData);
|
||||
if (matchingMachines.Count >= 1)
|
||||
{
|
||||
Common.LastMachineWithClipboardData = matchingMachines[0].Name.Trim();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
Common.Settings = null;
|
||||
MachineStuff.Settings = null;
|
||||
|
||||
if (_currentPage != null)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using MouseWithoutBorders.Class;
|
||||
using MouseWithoutBorders.Core;
|
||||
using MouseWithoutBorders.Form.Settings;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
@@ -59,8 +60,8 @@ namespace MouseWithoutBorders
|
||||
MessageBoxDefaultButton.Button2) == DialogResult.Yes)
|
||||
{
|
||||
Setting.Values.FirstRun = false;
|
||||
Common.CloseSetupForm();
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.CloseSetupForm();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
using System;
|
||||
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
public partial class SetupPage1 : SettingsFormPage
|
||||
@@ -12,7 +14,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Common.ClearComputerMatrix();
|
||||
MachineStuff.ClearComputerMatrix();
|
||||
}
|
||||
|
||||
private void NoButtonClick(object sender, EventArgs e)
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using MouseWithoutBorders.Class;
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
@@ -92,12 +93,12 @@ namespace MouseWithoutBorders
|
||||
SecurityCode = Common.MyKey;
|
||||
}
|
||||
|
||||
Common.MachineMatrix = new string[Common.MAX_MACHINE] { ComputerNameField.Text.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty };
|
||||
MachineStuff.MachineMatrix = new string[MachineStuff.MAX_MACHINE] { ComputerNameField.Text.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty };
|
||||
|
||||
string[] machines = Common.MachineMatrix;
|
||||
Common.MachinePool.Initialize(machines);
|
||||
string[] machines = MachineStuff.MachineMatrix;
|
||||
MachineStuff.MachinePool.Initialize(machines);
|
||||
|
||||
Common.UpdateMachinePoolStringSetting();
|
||||
MachineStuff.UpdateMachinePoolStringSetting();
|
||||
SendNextPage(new SetupPage3a { ReturnToSettings = !Setting.Values.FirstRun });
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
ShowStatus($"Connecting...");
|
||||
|
||||
Common.SwitchToMultipleMode(false, false);
|
||||
MachineStuff.SwitchToMultipleMode(false, false);
|
||||
Common.ReopenSockets(true);
|
||||
|
||||
int timeOut = 0;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
using System;
|
||||
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
public partial class SetupPage5 : SettingsFormPage
|
||||
@@ -16,8 +18,8 @@ namespace MouseWithoutBorders
|
||||
private void DoneButtonClick(object sender, EventArgs e)
|
||||
{
|
||||
// SendNextPage(new SettingsPage1());
|
||||
Common.CloseSetupForm();
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.CloseSetupForm();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ namespace MouseWithoutBorders
|
||||
return;
|
||||
}
|
||||
|
||||
string[] st = new string[Common.MAX_MACHINE];
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
string[] st = new string[MachineStuff.MAX_MACHINE];
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
if (machines[i].MachineEnabled)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
Common.MachineMatrix = st;
|
||||
MachineStuff.MachineMatrix = st;
|
||||
Setting.Values.MatrixOneRow = matrixOneRow = !checkBoxTwoRow.Checked;
|
||||
|
||||
if (Process.GetCurrentProcess().SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
|
||||
@@ -124,7 +124,7 @@ namespace MouseWithoutBorders
|
||||
Common.MMSleep(0.2);
|
||||
}
|
||||
|
||||
Common.SendMachineMatrix();
|
||||
MachineStuff.SendMachineMatrix();
|
||||
}
|
||||
|
||||
buttonOK.Enabled = true;
|
||||
@@ -150,13 +150,13 @@ namespace MouseWithoutBorders
|
||||
bool meAdded = false;
|
||||
string machineName;
|
||||
|
||||
if (Common.MachineMatrix != null && Common.MachineMatrix.Length == Common.MAX_MACHINE)
|
||||
if (MachineStuff.MachineMatrix != null && MachineStuff.MachineMatrix.Length == MachineStuff.MAX_MACHINE)
|
||||
{
|
||||
Logger.LogDebug("LoadMachines: Machine Matrix: " + Setting.Values.MachineMatrixString);
|
||||
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
machineName = Common.MachineMatrix[i].Trim();
|
||||
machineName = MachineStuff.MachineMatrix[i].Trim();
|
||||
machines[i].MachineName = machineName;
|
||||
|
||||
if (string.IsNullOrEmpty(machineName))
|
||||
@@ -168,7 +168,7 @@ namespace MouseWithoutBorders
|
||||
machines[i].MachineEnabled = true;
|
||||
}
|
||||
|
||||
bool found = Common.MachinePool.TryFindMachineByName(machineName, out MachineInf machineInfo);
|
||||
bool found = MachineStuff.MachinePool.TryFindMachineByName(machineName, out MachineInf machineInfo);
|
||||
if (found)
|
||||
{
|
||||
if (machineInfo.Id == Common.MachineID)
|
||||
@@ -340,7 +340,7 @@ namespace MouseWithoutBorders
|
||||
string newMachine;
|
||||
Machine unUsedMachine;
|
||||
|
||||
foreach (MachineInf inf in Common.MachinePool.ListAllMachines())
|
||||
foreach (MachineInf inf in MachineStuff.MachinePool.ListAllMachines())
|
||||
{
|
||||
bool found = false;
|
||||
unUsedMachine = null;
|
||||
@@ -519,7 +519,7 @@ namespace MouseWithoutBorders
|
||||
return true;
|
||||
}
|
||||
|
||||
private readonly Machine[] machines = new Machine[Common.MAX_MACHINE];
|
||||
private readonly Machine[] machines = new Machine[MachineStuff.MAX_MACHINE];
|
||||
private Machine dragDropMachine;
|
||||
private Machine desMachine;
|
||||
private Machine desMachineX;
|
||||
@@ -530,7 +530,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
private void CreateMachines()
|
||||
{
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
Machine m = new();
|
||||
m.MouseDown += Machine_MouseDown;
|
||||
@@ -550,7 +550,7 @@ namespace MouseWithoutBorders
|
||||
int dx = (groupBoxMachineMatrix.Width - 40) / 4;
|
||||
int yOffset = groupBoxMachineMatrix.Height / 3;
|
||||
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
machines[i].Left = matrixOneRow ? 22 + (i * dx) : 22 + dx + ((i % 2) * dx);
|
||||
machines[i].Top = matrixOneRow ? yOffset : (yOffset / 2) + (i / 2 * (machines[i].Width + 2));
|
||||
@@ -649,7 +649,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
desMachineX = desMachineY = desMachine;
|
||||
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
if (machines[i] == dragDropMachine)
|
||||
{
|
||||
@@ -703,9 +703,9 @@ namespace MouseWithoutBorders
|
||||
dragDropMachine.Top = desMachinePos.Y;
|
||||
|
||||
Machine tmp;
|
||||
for (int i = 0; i < Common.MAX_MACHINE - 1; i++)
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE - 1; i++)
|
||||
{
|
||||
for (int j = 0; j < Common.MAX_MACHINE - 1 - i; j++)
|
||||
for (int j = 0; j < MachineStuff.MAX_MACHINE - 1 - i; j++)
|
||||
{
|
||||
if (machines[j + 1].Top < machines[j].Top || (machines[j + 1].Top == machines[j].Top && machines[j + 1].Left < machines[j].Left))
|
||||
{
|
||||
@@ -1041,7 +1041,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Setting.Values.MatrixCircle = checkBoxCircle.Checked;
|
||||
ShowUpdateMessage();
|
||||
Common.SendMachineMatrix();
|
||||
MachineStuff.SendMachineMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,8 +1187,8 @@ namespace MouseWithoutBorders
|
||||
ButtonCancel_Click(this, new EventArgs());
|
||||
Setting.Values.FirstRun = true;
|
||||
Setting.Values.EasyMouse = (int)EasyMouseOption.Enable;
|
||||
Common.ClearComputerMatrix();
|
||||
Common.ShowSetupForm(true);
|
||||
MachineStuff.ClearComputerMatrix();
|
||||
MachineStuff.ShowSetupForm(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace MouseWithoutBorders
|
||||
internal void MenuOnClick(object sender, EventArgs e)
|
||||
{
|
||||
string name = (sender as ToolStripMenuItem).Text;
|
||||
Common.SwitchToMachine(name);
|
||||
MachineStuff.SwitchToMachine(name);
|
||||
}
|
||||
|
||||
internal void UpdateMenu()
|
||||
@@ -199,11 +199,11 @@ namespace MouseWithoutBorders
|
||||
menuGetScreenCapture.DropDown.Items.Count - 1]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
string newMachine = Common.MachineMatrix[i].Trim();
|
||||
string newMachine = MachineStuff.MachineMatrix[i].Trim();
|
||||
|
||||
if (Common.MachinePool.TryFindMachineByName(newMachine, out MachineInf inf) && MachinePool.IsAlive(inf))
|
||||
if (MachineStuff.MachinePool.TryFindMachineByName(newMachine, out MachineInf inf) && MachinePool.IsAlive(inf))
|
||||
{
|
||||
ToolStripMenuItem newItem = new(
|
||||
newMachine,
|
||||
@@ -372,14 +372,14 @@ namespace MouseWithoutBorders
|
||||
Common.MyKey = Setting.Values.MyKey;
|
||||
}
|
||||
|
||||
Common.UpdateMachinePoolStringSetting();
|
||||
MachineStuff.UpdateMachinePoolStringSetting();
|
||||
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && (Setting.Values.FirstRun || Common.KeyCorrupted))
|
||||
{
|
||||
if (!shownSetupFormOneTime)
|
||||
{
|
||||
shownSetupFormOneTime = true;
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
|
||||
if (Common.KeyCorrupted && !Setting.Values.FirstRun)
|
||||
{
|
||||
@@ -439,7 +439,7 @@ namespace MouseWithoutBorders
|
||||
Common.GetMachineName();
|
||||
Logger.LogDebug("Common.pleaseReopenSocket: " + Common.PleaseReopenSocket.ToString(CultureInfo.InvariantCulture));
|
||||
Common.ReopenSockets(false);
|
||||
Common.NewDesMachineID = Common.DesMachineID = Common.MachineID;
|
||||
MachineStuff.NewDesMachineID = Common.DesMachineID = Common.MachineID;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -457,7 +457,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Common.PleaseReopenSocket = 0;
|
||||
Thread.Sleep(1000);
|
||||
Common.UpdateClientSockets("REOPEN_WHEN_WSAECONNRESET");
|
||||
MachineStuff.UpdateClientSockets("REOPEN_WHEN_WSAECONNRESET");
|
||||
}
|
||||
|
||||
if (Common.RunOnLogonDesktop)
|
||||
@@ -496,7 +496,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
|
||||
Common.MatrixForm?.UpdateKeyTextBox();
|
||||
|
||||
@@ -511,7 +511,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
if (myKeyDaysToExpire <= 0)
|
||||
{
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
|
||||
Common.Sk?.Close(false);
|
||||
|
||||
@@ -532,7 +532,7 @@ namespace MouseWithoutBorders
|
||||
// if (Common.RunOnLogonDesktop) ShowMouseWithoutBordersUiOnWinLogonDesktop(false);
|
||||
#endif
|
||||
Common.CheckForDesktopSwitchEvent(true);
|
||||
Common.UpdateClientSockets("helperTimer_Tick"); // Sockets may be closed by the remote host when both machines switch desktop at the same time.
|
||||
MachineStuff.UpdateClientSockets("helperTimer_Tick"); // Sockets may be closed by the remote host when both machines switch desktop at the same time.
|
||||
}
|
||||
|
||||
count++;
|
||||
@@ -553,11 +553,11 @@ namespace MouseWithoutBorders
|
||||
Logger.LogAll();
|
||||
|
||||
// Need to review this code on why it is needed (moved from MoveToMyNeighbourIfNeeded(...))
|
||||
for (int i = 0; i < Common.MachineMatrix.Length; i++)
|
||||
for (int i = 0; i < MachineStuff.MachineMatrix.Length; i++)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Common.MachineMatrix[i]) && !Common.InMachineMatrix(Common.MachineName))
|
||||
if (string.IsNullOrEmpty(MachineStuff.MachineMatrix[i]) && !MachineStuff.InMachineMatrix(Common.MachineName))
|
||||
{
|
||||
Common.MachineMatrix[i] = Common.MachineName;
|
||||
MachineStuff.MachineMatrix[i] = Common.MachineName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ namespace MouseWithoutBorders
|
||||
if (Setting.Values.BlockScreenSaver || count % 3000 == 0)
|
||||
{
|
||||
Common.SendAwakeBeat();
|
||||
Common.RemoveDeadMachines();
|
||||
MachineStuff.RemoveDeadMachines();
|
||||
|
||||
// GC.Collect();
|
||||
// GC.WaitForPendingFinalizers();
|
||||
@@ -601,12 +601,12 @@ namespace MouseWithoutBorders
|
||||
|
||||
private void MenuMachineMatrix_Click(object sender, EventArgs e)
|
||||
{
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
}
|
||||
|
||||
private void FrmScreen_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!Common.IsDropping)
|
||||
if (!Core.DragDrop.IsDropping)
|
||||
{
|
||||
if (Cursor != dotCur)
|
||||
{
|
||||
@@ -702,7 +702,7 @@ namespace MouseWithoutBorders
|
||||
internal void MenuAllPC_Click(object sender, EventArgs e)
|
||||
{
|
||||
Logger.LogDebug("menuAllPC_Click");
|
||||
Common.SwitchToMultipleMode(MenuAllPC.Checked, true);
|
||||
MachineStuff.SwitchToMultipleMode(MenuAllPC.Checked, true);
|
||||
CurIcon = MenuAllPC.Checked ? Common.ICON_ALL : Common.ICON_ONE;
|
||||
ChangeIcon(CurIcon);
|
||||
}
|
||||
@@ -711,7 +711,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
MenuAllPC.Checked = Common.NewDesMachineID == ID.ALL;
|
||||
MenuAllPC.Checked = MachineStuff.NewDesMachineID == ID.ALL;
|
||||
CurIcon = MenuAllPC.Checked ? Common.ICON_ALL : Common.ICON_ONE;
|
||||
ChangeIcon(CurIcon);
|
||||
});
|
||||
@@ -819,7 +819,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
case NativeMethods.WM_CHECK_EXPLORER_DRAG_DROP:
|
||||
Logger.LogDebug("Got WM_CHECK_EXPLORER_DRAG_DROP!");
|
||||
Common.DragDropStep04();
|
||||
Core.DragDrop.DragDropStep04();
|
||||
break;
|
||||
|
||||
case NativeMethods.WM_QUIT:
|
||||
@@ -841,7 +841,7 @@ namespace MouseWithoutBorders
|
||||
case NativeMethods.WM_SHOW_SETTINGS_FORM:
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -856,7 +856,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
Common.ShowMachineMatrix();
|
||||
MachineStuff.ShowMachineMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -872,7 +872,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
internal void UpdateNotifyIcon()
|
||||
{
|
||||
string[] x = Common.MachineMatrix;
|
||||
string[] x = MachineStuff.MachineMatrix;
|
||||
string iconText;
|
||||
if (x != null && (x[0].Length > 0 || x[1].Length > 0 || x[2].Length > 0 || x[3].Length > 0))
|
||||
{
|
||||
@@ -943,13 +943,13 @@ namespace MouseWithoutBorders
|
||||
string menuCaption = (sender as ToolStripMenuItem).Text;
|
||||
|
||||
// Send CaptureScreenCommand
|
||||
ID des = menuCaption.Equals("All", StringComparison.OrdinalIgnoreCase) ? ID.ALL : Common.IdFromName(menuCaption);
|
||||
ID des = menuCaption.Equals("All", StringComparison.OrdinalIgnoreCase) ? ID.ALL : MachineStuff.IdFromName(menuCaption);
|
||||
Common.SendPackage(des, PackageType.CaptureScreenCommand);
|
||||
}
|
||||
|
||||
private void FrmScreen_Shown(object sender, EventArgs e)
|
||||
{
|
||||
Common.AssertOneInstancePerDesktopSession();
|
||||
MachineStuff.AssertOneInstancePerDesktopSession();
|
||||
|
||||
Common.MainForm = this;
|
||||
Hide();
|
||||
@@ -1057,11 +1057,11 @@ namespace MouseWithoutBorders
|
||||
r.Right = Common.ScreenWidth - (Common.ScreenWidth / 5);
|
||||
r.Bottom = 20;
|
||||
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
for (int i = 0; i < MachineStuff.MAX_MACHINE; i++)
|
||||
{
|
||||
string newMachine = Common.MachineMatrix[i].Trim();
|
||||
string newMachine = MachineStuff.MachineMatrix[i].Trim();
|
||||
|
||||
if (Common.MachinePool.TryFindMachineByName(newMachine, out MachineInf inf) && MachinePool.IsAlive(inf))
|
||||
if (MachineStuff.MachinePool.TryFindMachineByName(newMachine, out MachineInf inf) && MachinePool.IsAlive(inf))
|
||||
{
|
||||
machineMatrix += "[" + inf.Name.Trim() + "]";
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace MouseWithoutBordersService
|
||||
[STAThread]
|
||||
private static void Main()
|
||||
{
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled
|
||||
|| PowerToys.GPOWrapper.GPOWrapper.GetConfiguredMwbAllowServiceModeValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled )
|
||||
{
|
||||
// TODO: Add logging.
|
||||
// Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
||||
|
||||
@@ -363,7 +363,11 @@ private:
|
||||
|
||||
void update_state_from_settings(const PowerToysSettings::PowerToyValues& values)
|
||||
{
|
||||
const bool new_run_in_service_mode = values.get_bool_value(USE_SERVICE_PROPERTY_NAME).value_or(false);
|
||||
bool new_run_in_service_mode = values.get_bool_value(USE_SERVICE_PROPERTY_NAME).value_or(false);
|
||||
if (powertoys_gpo::getConfiguredMwbAllowServiceModeValue() == powertoys_gpo::gpo_rule_configured_disabled)
|
||||
{
|
||||
new_run_in_service_mode = false;
|
||||
}
|
||||
|
||||
if (new_run_in_service_mode != run_in_service_mode)
|
||||
{
|
||||
|
||||
@@ -68,11 +68,6 @@ avgSendTime = 0
|
||||
maxSendTime = 0
|
||||
totalSendCount = 0
|
||||
totalSendTime = 0
|
||||
isDragging = False
|
||||
dragDropStep05ExCalledByIpc = 0
|
||||
isDropping = False
|
||||
dragMachine = NONE
|
||||
<MouseDown>k__BackingField = False
|
||||
magicNumber = 0
|
||||
ran = System.Random
|
||||
--_impl = System.Random+XoshiroImpl
|
||||
@@ -163,35 +158,6 @@ ReopenSocketDueToReadError = False
|
||||
--MaxValue = 31/12/9999 23:59:59
|
||||
--UnixEpoch = 01/01/1970 00:00:00
|
||||
lastReleaseAllKeysCall = 0
|
||||
McMatrixLock = Lock
|
||||
--_owningThreadId = 0
|
||||
--_state = 0
|
||||
--_recursionCount = 0
|
||||
--_spinCount = 22
|
||||
--_waiterStartTimeMs = 0
|
||||
--s_contentionCount = 0
|
||||
--s_maxSpinCount = 22
|
||||
--s_minSpinCountForAdaptiveSpin = -100
|
||||
desMachineID = NONE
|
||||
DesMachineName =
|
||||
newDesMachineID = NONE
|
||||
newDesMachineIdEx = NONE
|
||||
dropMachineID = NONE
|
||||
lastJump = ????????????
|
||||
desktopBounds = MouseWithoutBorders.MyRectangle
|
||||
--Left = 0
|
||||
--Top = 0
|
||||
--Right = 0
|
||||
--Bottom = 0
|
||||
primaryScreenBounds = MouseWithoutBorders.MyRectangle
|
||||
--Left = 0
|
||||
--Top = 0
|
||||
--Right = 0
|
||||
--Bottom = 0
|
||||
SwitchLocation = MouseWithoutBorders.Class.MouseLocation
|
||||
--<X>k__BackingField = 0
|
||||
--<Y>k__BackingField = 0
|
||||
--<Count>k__BackingField = 0
|
||||
PackageSent = MouseWithoutBorders.PackageMonitor
|
||||
--Keyboard = 0
|
||||
--Mouse = 0
|
||||
@@ -259,11 +225,6 @@ SymAlBlockSize = 16
|
||||
PW_LENGTH = 16
|
||||
HELPER_FORM_TEXT = Mouse without Borders Helper
|
||||
HelperProcessName = PowerToys.MouseWithoutBordersHelper
|
||||
MAX_MACHINE = 4
|
||||
MAX_SOCKET = 8
|
||||
HEARTBEAT_TIMEOUT = 1500000
|
||||
SKIP_PIXELS = 1
|
||||
JUMP_PIXELS = 2
|
||||
PACKAGE_SIZE = 32
|
||||
PACKAGE_SIZE_EX = 64
|
||||
WP_PACKAGE_SIZE = 6
|
||||
@@ -358,6 +319,49 @@ MAX_LOG = 10000
|
||||
MaxLogExceptionPerHour = 1000
|
||||
HeaderSENT = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13}
|
||||
HeaderRECEIVED = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15}
|
||||
[DragDrop]
|
||||
===============
|
||||
isDragging = False
|
||||
dragDropStep05ExCalledByIpc = 0
|
||||
isDropping = False
|
||||
dragMachine = NONE
|
||||
<MouseDown>k__BackingField = False
|
||||
[MachineStuff]
|
||||
===============
|
||||
McMatrixLock = Lock
|
||||
--_owningThreadId = 0
|
||||
--_state = 0
|
||||
--_recursionCount = 0
|
||||
--_spinCount = 22
|
||||
--_waiterStartTimeMs = 0
|
||||
--s_contentionCount = 0
|
||||
--s_maxSpinCount = 22
|
||||
--s_minSpinCountForAdaptiveSpin = -100
|
||||
desMachineID = NONE
|
||||
DesMachineName =
|
||||
newDesMachineID = NONE
|
||||
newDesMachineIdEx = NONE
|
||||
dropMachineID = NONE
|
||||
lastJump = ????????????
|
||||
desktopBounds = MouseWithoutBorders.Core.MyRectangle
|
||||
--Left = 0
|
||||
--Top = 0
|
||||
--Right = 0
|
||||
--Bottom = 0
|
||||
primaryScreenBounds = MouseWithoutBorders.Core.MyRectangle
|
||||
--Left = 0
|
||||
--Top = 0
|
||||
--Right = 0
|
||||
--Bottom = 0
|
||||
SwitchLocation = MouseWithoutBorders.Class.MouseLocation
|
||||
--<X>k__BackingField = 0
|
||||
--<Y>k__BackingField = 0
|
||||
--<Count>k__BackingField = 0
|
||||
MAX_MACHINE = 4
|
||||
MAX_SOCKET = 8
|
||||
HEARTBEAT_TIMEOUT = 1500000
|
||||
SKIP_PIXELS = 1
|
||||
JUMP_PIXELS = 2
|
||||
[Receiver]
|
||||
===============
|
||||
QUEUE_SIZE = 50
|
||||
|
||||
@@ -120,6 +120,10 @@ public static class LoggerTests
|
||||
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
|
||||
sb.AppendLine("[Logger]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Logger), 0, settingsDumpObjectsLevel);
|
||||
sb.AppendLine("[DragDrop]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(DragDrop), 0, settingsDumpObjectsLevel);
|
||||
sb.AppendLine("[MachineStuff]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(MachineStuff), 0, settingsDumpObjectsLevel);
|
||||
sb.AppendLine("[Receiver]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Receiver), 0, settingsDumpObjectsLevel);
|
||||
var actual = sb.ToString();
|
||||
|
||||
@@ -62,11 +62,10 @@ namespace PlacementHelper
|
||||
else
|
||||
{
|
||||
placement.showCmd = SW_RESTORE;
|
||||
|
||||
ScreenToWorkAreaCoords(window, monitor, rect);
|
||||
placement.rcNormalPosition = rect;
|
||||
}
|
||||
|
||||
ScreenToWorkAreaCoords(window, monitor, rect);
|
||||
placement.rcNormalPosition = rect;
|
||||
placement.flags |= WPF_ASYNCWINDOWPLACEMENT;
|
||||
|
||||
auto result = ::SetWindowPlacement(window, &placement);
|
||||
@@ -430,9 +429,11 @@ bool WindowArranger::moveWindow(HWND window, const WorkspacesData::WorkspacesPro
|
||||
Logger::error(L"No monitor saved for launching the app");
|
||||
return false;
|
||||
}
|
||||
UINT snapDPI = snapMonitorIter->dpi;
|
||||
|
||||
bool launchMinimized = app.isMinimized;
|
||||
bool launchMaximized = app.isMaximized;
|
||||
RECT rect = app.position.toRect();
|
||||
|
||||
HMONITOR currentMonitor{};
|
||||
UINT currentDpi = DPIAware::DEFAULT_DPI;
|
||||
@@ -446,12 +447,18 @@ bool WindowArranger::moveWindow(HWND window, const WorkspacesData::WorkspacesPro
|
||||
{
|
||||
currentMonitor = MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
||||
DPIAware::GetScreenDPIForMonitor(currentMonitor, currentDpi);
|
||||
snapDPI = DPIAware::DEFAULT_DPI;
|
||||
launchMinimized = true;
|
||||
launchMaximized = false;
|
||||
MONITORINFOEX monitorInfo;
|
||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||
if (GetMonitorInfo(currentMonitor, &monitorInfo))
|
||||
{
|
||||
rect = monitorInfo.rcWork;
|
||||
}
|
||||
}
|
||||
|
||||
RECT rect = app.position.toRect();
|
||||
float mult = static_cast<float>(snapMonitorIter->dpi) / currentDpi;
|
||||
float mult = static_cast<float>(snapDPI) / currentDpi;
|
||||
rect.left = static_cast<long>(std::round(rect.left * mult));
|
||||
rect.right = static_cast<long>(std::round(rect.right * mult));
|
||||
rect.top = static_cast<long>(std::round(rect.top * mult));
|
||||
|
||||
@@ -1820,7 +1820,7 @@ INT_PTR CALLBACK OptionsTabProc( HWND hDlg, UINT message,
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
if( (hTextPreview = GetDlgItem( hDlg, IDC_TEXT_FONT ))) {
|
||||
if( (hTextPreview = GetDlgItem( hDlg, IDC_TEXT_FONT )) != 0 ) {
|
||||
|
||||
// 16-pt preview
|
||||
LOGFONT _lf = g_LogFont;
|
||||
|
||||
@@ -83,9 +83,7 @@
|
||||
<Border
|
||||
x:Name="MonitorItem"
|
||||
Width="{Binding DisplayWidth}"
|
||||
Height="{Binding DisplayHeight}"
|
||||
AutomationProperties.HelpText="{Binding Index}"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Monitor}">
|
||||
Height="{Binding DisplayHeight}">
|
||||
<Border.ToolTip>
|
||||
<ToolTip>
|
||||
<StackPanel>
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
using FancyZonesEditor.Properties;
|
||||
using FancyZonesEditor.ViewModels;
|
||||
|
||||
namespace FancyZonesEditor.Utils
|
||||
@@ -14,6 +16,8 @@ namespace FancyZonesEditor.Utils
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private static readonly CompositeFormat MonitorIndexFormat = CompositeFormat.Parse(Resources.Monitor_Index);
|
||||
|
||||
public MonitorInfoModel(int index, int height, int width, int dpi, bool selected = false)
|
||||
{
|
||||
Index = index;
|
||||
@@ -24,6 +28,10 @@ namespace FancyZonesEditor.Utils
|
||||
Selected = selected;
|
||||
}
|
||||
|
||||
public string AccessibleName => string.Format(CultureInfo.CurrentCulture, MonitorIndexFormat, Index);
|
||||
|
||||
public string AccessibleHelpText => $"{Resources.Dimensions} {Dimensions}, {Resources.Scaling} {Scaling}";
|
||||
|
||||
public int Index { get; set; }
|
||||
|
||||
public int ScreenBoundsHeight { get; set; }
|
||||
|
||||
@@ -276,6 +276,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Dimensions.
|
||||
/// </summary>
|
||||
public static string Dimensions {
|
||||
get {
|
||||
return ResourceManager.GetString("Dimensions", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Highlight distance.
|
||||
/// </summary>
|
||||
@@ -539,7 +548,7 @@ namespace FancyZonesEditor.Properties {
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
///• [Shift]+S to split currently focused zone.
|
||||
///• Shift+S to split currently focused zone.
|
||||
///• Ctrl+Tab to focus zones/resizers.
|
||||
///• Tab to cycle zones and resizers.
|
||||
///• Delete to remove the focused resizer.
|
||||
@@ -554,8 +563,8 @@ namespace FancyZonesEditor.Properties {
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to
|
||||
///• Ctrl+Tab to switch focus between dialog and zones.
|
||||
///• [Shift]+Arrows to resize the focused zone by 10px (5px per edge).
|
||||
///• Ctrl+[Shift]+Arrows to resize the focused zone by 2px (1px per edge).
|
||||
///• Shift+Arrows to resize the focused zone by 10px (5px per edge).
|
||||
///• Ctrl+Shift+Arrows to resize the focused zone by 2px (1px per edge).
|
||||
///• Arrows to move the focused zone by 10px.
|
||||
///• Ctrl+Arrows to move the focused zone by 1px..
|
||||
/// </summary>
|
||||
@@ -655,6 +664,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Monitor {0}.
|
||||
/// </summary>
|
||||
public static string Monitor_Index {
|
||||
get {
|
||||
return ResourceManager.GetString("Monitor_Index", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Name.
|
||||
/// </summary>
|
||||
@@ -790,6 +808,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Scaling.
|
||||
/// </summary>
|
||||
public static string Scaling {
|
||||
get {
|
||||
return ResourceManager.GetString("Scaling", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Set layout as a default for horizontal monitor orientation.
|
||||
/// </summary>
|
||||
|
||||
@@ -282,6 +282,15 @@
|
||||
<data name="Monitor" xml:space="preserve">
|
||||
<value>Monitor</value>
|
||||
</data>
|
||||
<data name="Monitor_Index" xml:space="preserve">
|
||||
<value>Monitor {0}</value>
|
||||
</data>
|
||||
<data name="Dimensions" xml:space="preserve">
|
||||
<value>Dimensions</value>
|
||||
</data>
|
||||
<data name="Scaling" xml:space="preserve">
|
||||
<value>Scaling</value>
|
||||
</data>
|
||||
<data name="Settings" xml:space="preserve">
|
||||
<value>Template settings</value>
|
||||
</data>
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
<Style x:Key="MonitorItemContainerStyle" TargetType="ui:GridViewItem">
|
||||
<Setter Property="Background" Value="{DynamicResource LayoutItemBackgroundBrush}" />
|
||||
<Setter Property="IsSelected" Value="{Binding Selected, Mode=OneWay}" />
|
||||
<Setter Property="AutomationProperties.Name" Value="{Binding Index}" />
|
||||
<Setter Property="AutomationProperties.Name" Value="{Binding AccessibleName}" />
|
||||
<Setter Property="AutomationProperties.HelpText" Value="{Binding AccessibleHelpText}" />
|
||||
<Setter Property="KeyboardNavigation.TabNavigation" Value="Local" />
|
||||
<Setter Property="MinWidth" Value="0" />
|
||||
<Setter Property="MinHeight" Value="0" />
|
||||
<!--<Setter Property="IsHoldingEnabled" Value="True" />-->
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
<Setter Property="Margin" Value="8" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{DynamicResource UseSystemFocusVisuals}" />
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<v:SizeTypeToVisibilityConverter x:Key="SizeTypeToVisibilityConverter" />
|
||||
<v:SizeTypeToHelpTextConverter x:Key="SizeTypeToHelpTextConverter" />
|
||||
<v:EnumValueConverter x:Key="EnumValueConverter" />
|
||||
<v:AutoDoubleConverter x:Key="AutoDoubleConverter" />
|
||||
<v:BoolValueConverter x:Key="BoolValueConverter" />
|
||||
|
||||
@@ -254,6 +254,7 @@ namespace ImageResizer.Properties
|
||||
{
|
||||
_selectedSizeIndex = value;
|
||||
NotifyPropertyChanged();
|
||||
NotifyPropertyChanged(nameof(SelectedSize));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,19 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
AutomationProperties.HelpText="{Binding Settings.SelectedSize, Converter={StaticResource SizeTypeToHelpTextConverter}}"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Image_Sizes}"
|
||||
ItemsSource="{Binding Settings.AllSizes}"
|
||||
SelectedIndex="{Binding Settings.SelectedSizeIndex}">
|
||||
<ComboBox.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem">
|
||||
<Setter Property="AutomationProperties.Name" Value="{Binding Name}" />
|
||||
<Setter Property="AutomationProperties.HelpText" Value="{Binding ., Converter={StaticResource SizeTypeToHelpTextConverter}}" />
|
||||
</Style>
|
||||
</ComboBox.ItemContainerStyle>
|
||||
<ComboBox.Resources>
|
||||
<DataTemplate DataType="{x:Type m:ResizeSize}">
|
||||
<Grid VerticalAlignment="Center" AutomationProperties.Name="{Binding Name}">
|
||||
<Grid VerticalAlignment="Center">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -55,7 +62,7 @@
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="{x:Type m:CustomSize}">
|
||||
<Grid VerticalAlignment="Center" AutomationProperties.Name="{Binding Name}">
|
||||
<Grid VerticalAlignment="Center">
|
||||
<TextBlock FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
using ImageResizer.Models;
|
||||
|
||||
namespace ImageResizer.Views;
|
||||
|
||||
[ValueConversion(typeof(ResizeSize), typeof(string))]
|
||||
public sealed partial class SizeTypeToHelpTextConverter : IValueConverter
|
||||
{
|
||||
private const char MultiplicationSign = '\u00D7';
|
||||
|
||||
private readonly EnumValueConverter _enumConverter = new();
|
||||
private readonly AutoDoubleConverter _autoDoubleConverter = new();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not ResizeSize size)
|
||||
{
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
string EnumToString(Enum value, string parameter = null) =>
|
||||
_enumConverter.Convert(value, typeof(string), parameter, culture) as string;
|
||||
|
||||
string DoubleToString(double value) =>
|
||||
_autoDoubleConverter.Convert(value, typeof(string), null, culture) as string;
|
||||
|
||||
var fit = EnumToString(size.Fit, "ThirdPersonSingular");
|
||||
var width = DoubleToString(size.Width);
|
||||
var unit = EnumToString(size.Unit);
|
||||
|
||||
return size.ShowHeight ?
|
||||
$"{fit} {width} {MultiplicationSign} {DoubleToString(size.Height)} {unit}" :
|
||||
$"{fit} {width} {unit}";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "pch.h"
|
||||
#include "KeyboardManagerEditorLibraryWrapper.h"
|
||||
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.h>
|
||||
|
||||
// Test function to call the remapping helper function
|
||||
|
||||
bool CheckIfRemappingsAreValid()
|
||||
{
|
||||
RemapBuffer remapBuffer;
|
||||
|
||||
// Mock valid key to key remappings
|
||||
remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x41, (DWORD)0x42 }), std::wstring() });
|
||||
remapBuffer.push_back(RemapBufferRow{ RemapBufferItem({ (DWORD)0x42, (DWORD)0x43 }), std::wstring() });
|
||||
|
||||
auto result = LoadingAndSavingRemappingHelper::CheckIfRemappingsAreValid(remapBuffer);
|
||||
|
||||
return result == ShortcutErrorType::NoError;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <keyboardmanager/common/Helpers.h>
|
||||
#include <keyboardmanager/common/Input.h>
|
||||
#include <keyboardmanager/common/MappingConfiguration.h>
|
||||
|
||||
extern "C" __declspec(dllexport) bool CheckIfRemappingsAreValid();
|
||||
@@ -0,0 +1,260 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{4382a954-179a-4078-92af-715187dfff50}</ProjectGuid>
|
||||
<RootNamespace>KeyboardManagerEditorLibraryWrapper</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<AllProjectBMIsArePublic>true</AllProjectBMIsArePublic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<AllProjectBMIsArePublic>true</AllProjectBMIsArePublic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;KEYBOARDMANAGEREDITORLIBRARYWRAPPER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;KEYBOARDMANAGEREDITORLIBRARYWRAPPER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;KEYBOARDMANAGEREDITORLIBRARYWRAPPER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>./;$(SolutionDir)src\modules\;$(SolutionDir)src\modules\KeyboardManager\KeyboardManagerEditorLibrary\;$(SolutionDir)src\common\Display;$(SolutionDir)src\common\inc;$(SolutionDir)src\common\Telemetry;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(ConfigurationName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;KEYBOARDMANAGEREDITORLIBRARYWRAPPER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>./;$(SolutionDir)src\modules\;$(SolutionDir)src\modules\KeyboardManager\KeyboardManagerEditorLibrary\;$(SolutionDir)src\common\Display;$(SolutionDir)src\common\inc;$(SolutionDir)src\common\Telemetry;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(ConfigurationName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;KEYBOARDMANAGEREDITORLIBRARYWRAPPER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>./;$(SolutionDir)src\modules\;$(SolutionDir)src\modules\KeyboardManager\KeyboardManagerEditorLibrary\;$(SolutionDir)src\common\Display;$(SolutionDir)src\common\inc;$(SolutionDir)src\common\Telemetry;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<SupportJustMyCode>true</SupportJustMyCode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(ConfigurationName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;KEYBOARDMANAGEREDITORLIBRARYWRAPPER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>./;$(SolutionDir)src\modules\;$(SolutionDir)src\modules\KeyboardManager\KeyboardManagerEditorLibrary\;$(SolutionDir)src\common\Display;$(SolutionDir)src\common\inc;$(SolutionDir)src\common\Telemetry;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="KeyboardManagerEditorLibraryWrapper.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="KeyboardManagerEditorLibraryWrapper.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\KeyboardManagerCommon.vcxproj">
|
||||
<Project>{8affa899-0b73-49ec-8c50-0fadda57b2fc}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\KeyboardManagerEditorLibrary\KeyboardManagerEditorLibrary.vcxproj">
|
||||
<Project>{23d2070d-e4ad-4add-85a7-083d9c76ad49}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyboardManagerEditorLibraryWrapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyboardManagerEditorLibraryWrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,19 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
#include <windows.h>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -0,0 +1,5 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
||||
@@ -0,0 +1,18 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#include "framework.h"
|
||||
#include <winrt/base.h>
|
||||
#include "../KeyboardManagerEditorLibrary/LoadingAndSavingRemappingHelper.h"
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/utils/resources.h>
|
||||
|
||||
#endif //PCH_H
|
||||
16
src/modules/keyboardmanager/KeyboardManagerEditorUI/App.xaml
Normal file
16
src/modules/keyboardmanager/KeyboardManagerEditorUI/App.xaml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application
|
||||
x:Class="KeyboardManagerEditorUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:KeyboardManagerEditorUI">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user