Merge branch 'master' into users/niels9001/settings-newstyle

This commit is contained in:
Niels Laute
2021-07-27 15:08:31 +02:00
41 changed files with 1946 additions and 1553 deletions

View File

@@ -399,6 +399,7 @@ ddd
ddee ddee
ddf ddf
Deact Deact
DECLAR
declspec declspec
decltype decltype
Dedup Dedup
@@ -663,6 +664,7 @@ Functiondiscoverykeys
fwlink fwlink
fwrite fwrite
fxcop fxcop
FZE
gabime gabime
GAC GAC
gacutil gacutil
@@ -1299,6 +1301,7 @@ MSDN
msedge msedge
mshtmdid mshtmdid
msi msi
MSIFASTINSTALL
MSIHANDLE MSIHANDLE
MSIINSTALLER MSIINSTALLER
MSIL MSIL
@@ -1434,6 +1437,7 @@ ntdll
NTFS NTFS
NTSTATUS NTSTATUS
nuget nuget
null
nullopt nullopt
nullptr nullptr
NUMLOCK NUMLOCK
@@ -2092,6 +2096,7 @@ todo
toggleswitch toggleswitch
toolbar toolbar
Toolchain Toolchain
toolkitconverters
toolset toolset
toolstrip toolstrip
tooltip tooltip
@@ -2311,6 +2316,7 @@ WINDOWPOSCHANGED
WINDOWPOSCHANGING WINDOWPOSCHANGING
Windowsapp Windowsapp
WINDOWSBUILDNUMBER WINDOWSBUILDNUMBER
Windowscodecs
windowsdesktop windowsdesktop
windowssearch windowssearch
windowsx windowsx

View File

@@ -197,7 +197,8 @@
/> />
<!-- Close 'PowerToys.exe' before uninstall--> <!-- Close 'PowerToys.exe' before uninstall-->
<Property Id="MSIRESTARTMANAGERCONTROL" Value="Disable" /> <Property Id="MSIRESTARTMANAGERCONTROL" Value="DisableShutdown" />
<Property Id="MSIFASTINSTALL" Value="DisableShutdown" />
<util:CloseApplication CloseMessage="yes" Target="PowerToys.exe" ElevatedCloseMessage="yes" RebootPrompt="no" TerminateProcess="0" /> <util:CloseApplication CloseMessage="yes" Target="PowerToys.exe" ElevatedCloseMessage="yes" RebootPrompt="no" TerminateProcess="0" />
</Product> </Product>
@@ -791,7 +792,7 @@
<File Source="$(var.BinX64Dir)Settings\PowerToys.Settings.exe"/> <File Source="$(var.BinX64Dir)Settings\PowerToys.Settings.exe"/>
<File Source="$(var.BinX64Dir)Settings\Microsoft.PowerToys.Settings.UI.exe"/> <File Source="$(var.BinX64Dir)Settings\Microsoft.PowerToys.Settings.UI.exe"/>
<!-- dll --> <!-- dll -->
<?foreach File in concrt140_app.dll;Microsoft.Bcl.AsyncInterfaces.dll;System.IO.Abstractions.dll;Microsoft.PowerToys.Settings.UI.Lib.dll;PowerToys.Settings.dll;Microsoft.Toolkit.dll;Microsoft.Toolkit.Uwp.dll;Microsoft.Toolkit.Uwp.UI.dll;Microsoft.Toolkit.Win32.UI.XamlHost.dll;Microsoft.Toolkit.Win32.UI.XamlHost.Managed.dll;Microsoft.Toolkit.Wpf.UI.Controls.dll;Microsoft.Toolkit.Wpf.UI.XamlHost.dll;Microsoft.UI.Xaml.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;msvcp140_1_app.dll;msvcp140_2_app.dll;msvcp140_app.dll;Newtonsoft.Json.dll;PowerToysInterop.dll;System.Runtime.CompilerServices.Unsafe.dll;System.Text.Encodings.Web.dll;System.Text.Json.dll;vcamp140_app.dll;vccorlib140_app.dll;vcomp140_app.dll;vcruntime140_1_app.dll;vcruntime140_app.dll;ManagedTelemetry.dll;ManagedCommon.dll;ColorCode.Core.dll;ColorCode.UWP.dll;Microsoft.Graphics.Canvas.winmd;Microsoft.Toolkit.Parsers.dll;Microsoft.Toolkit.Uwp.UI.Animations.dll;Microsoft.Toolkit.Uwp.UI.Controls.dll;System.Deployment.dll;System.Windows.Forms.dll;System.Runtime.Serialization.Formatters.Soap.dll?> <?foreach File in concrt140_app.dll;Microsoft.Bcl.AsyncInterfaces.dll;System.IO.Abstractions.dll;Microsoft.PowerToys.Settings.UI.Lib.dll;PowerToys.Settings.dll;Microsoft.Toolkit.dll;Microsoft.Toolkit.Uwp.dll;Microsoft.Toolkit.Uwp.UI.dll;Microsoft.Toolkit.Win32.UI.XamlHost.dll;Microsoft.Toolkit.Win32.UI.XamlHost.Managed.dll;Microsoft.Toolkit.Wpf.UI.Controls.dll;Microsoft.Toolkit.Wpf.UI.XamlHost.dll;Microsoft.UI.Xaml.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;msvcp140_1_app.dll;msvcp140_2_app.dll;msvcp140_app.dll;Newtonsoft.Json.dll;PowerToysInterop.dll;System.Runtime.CompilerServices.Unsafe.dll;System.Text.Encodings.Web.dll;System.Text.Json.dll;vcamp140_app.dll;vccorlib140_app.dll;vcomp140_app.dll;vcruntime140_1_app.dll;vcruntime140_app.dll;ManagedTelemetry.dll;ManagedCommon.dll;ColorCode.Core.dll;ColorCode.UWP.dll;Microsoft.Graphics.Canvas.winmd;Microsoft.Toolkit.Parsers.dll;Microsoft.Toolkit.Uwp.UI.Animations.dll;Microsoft.Toolkit.Uwp.UI.Controls.dll?>
<File Id="SettingsV2_$(var.File)" Source="$(var.BinX64Dir)Settings\$(var.File)" /> <File Id="SettingsV2_$(var.File)" Source="$(var.BinX64Dir)Settings\$(var.File)" />
<?endforeach?> <?endforeach?>
<!-- json --> <!-- json -->

View File

@@ -774,10 +774,14 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
} }
processes.resize(bytes / sizeof(processes[0])); processes.resize(bytes / sizeof(processes[0]));
std::array<std::wstring_view, 4> processesToTerminate = { std::array<std::wstring_view, 8> processesToTerminate = {
L"PowerLauncher.exe", L"PowerLauncher.exe",
L"PowerToys.Settings.exe", L"PowerToys.Settings.exe",
L"PowerToys.Awake.exe",
L"PowerToys.FancyZones.exe",
L"Microsoft.PowerToys.Settings.UI.exe", L"Microsoft.PowerToys.Settings.UI.exe",
L"FancyZonesEditor.exe",
L"ColorPickerUI.exe",
L"PowerToys.exe" L"PowerToys.exe"
}; };

View File

@@ -55,7 +55,7 @@
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>Mf.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@@ -179,6 +179,10 @@ public
return gcnew String(CommonSharedConstants::RUN_EXIT_EVENT); return gcnew String(CommonSharedConstants::RUN_EXIT_EVENT);
} }
static String ^ FZEExitEvent() {
return gcnew String(CommonSharedConstants::FZE_EXIT_EVENT);
}
static String ^ ColorPickerSendSettingsTelemetryEvent() { static String ^ ColorPickerSendSettingsTelemetryEvent() {
return gcnew String(CommonSharedConstants::COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT); return gcnew String(CommonSharedConstants::COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT);
} }

View File

@@ -18,6 +18,8 @@ namespace CommonSharedConstants
const wchar_t RUN_SEND_SETTINGS_TELEMETRY_EVENT[] = L"Local\\PowerToysRunInvokeEvent-638ec522-0018-4b96-837d-6bd88e06f0d6"; const wchar_t RUN_SEND_SETTINGS_TELEMETRY_EVENT[] = L"Local\\PowerToysRunInvokeEvent-638ec522-0018-4b96-837d-6bd88e06f0d6";
const wchar_t RUN_EXIT_EVENT[] = L"Local\\PowerToysRunExitEvent-3e38e49d-a762-4ef1-88f2-fd4bc7481516"; const wchar_t RUN_EXIT_EVENT[] = L"Local\\PowerToysRunExitEvent-3e38e49d-a762-4ef1-88f2-fd4bc7481516";
const wchar_t FZE_EXIT_EVENT[] = L"Local\\PowerToys-FZE-ExitEvent-ca8c73de-a52c-4274-b691-46e9592d3b43";
const wchar_t COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT[] = L"Local\\ColorPickerSettingsTelemetryEvent-6c7071d8-4014-46ec-b687-913bd8a422f1"; const wchar_t COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT[] = L"Local\\ColorPickerSettingsTelemetryEvent-6c7071d8-4014-46ec-b687-913bd8a422f1";

View File

@@ -297,6 +297,7 @@
<ui:FlyoutService.Flyout> <ui:FlyoutService.Flyout>
<ui:Flyout x:Name="DetailsFlyout" <ui:Flyout x:Name="DetailsFlyout"
Placement="Bottom" Placement="Bottom"
Opened="DetailsFlyout_Opened"
Closed="DetailsFlyout_Closed"> Closed="DetailsFlyout_Closed">
<Grid Margin="0,4,0,12" <Grid Margin="0,4,0,12"
KeyboardNavigation.TabNavigation="Contained" KeyboardNavigation.TabNavigation="Contained"

View File

@@ -242,6 +242,7 @@ namespace ColorPicker.Controls
#pragma warning restore CA1801 // Review unused parameters #pragma warning restore CA1801 // Review unused parameters
{ {
HideDetails(); HideDetails();
AppStateHandler.BlockEscapeKeyClosingColorPickerEditor = false;
// Revert to original color // Revert to original color
var originalColorBackground = new SolidColorBrush(_originalColor); var originalColorBackground = new SolidColorBrush(_originalColor);
@@ -250,6 +251,15 @@ namespace ColorPicker.Controls
HexCode.Text = ColorToHex(_originalColor); HexCode.Text = ColorToHex(_originalColor);
} }
#pragma warning disable CA1822 // Mark members as static
#pragma warning disable CA1801 // Review unused parameters
private void DetailsFlyout_Opened(object sender, object e)
#pragma warning restore CA1801 // Review unused parameters
#pragma warning restore CA1822 // Mark members as static
{
AppStateHandler.BlockEscapeKeyClosingColorPickerEditor = true;
}
private void ColorVariationButton_Click(object sender, RoutedEventArgs e) private void ColorVariationButton_Click(object sender, RoutedEventArgs e)
{ {
var selectedColor = ((SolidColorBrush)((Button)sender).Background).Color; var selectedColor = ((SolidColorBrush)((Button)sender).Background).Color;

View File

@@ -20,6 +20,9 @@ namespace ColorPicker.Helpers
private bool _colorPickerShown; private bool _colorPickerShown;
private object _colorPickerVisibilityLock = new object(); private object _colorPickerVisibilityLock = new object();
// Blocks using the escape key to close the color picker editor when the adjust color flyout is open.
public static bool BlockEscapeKeyClosingColorPickerEditor { get; set; }
[ImportingConstructor] [ImportingConstructor]
public AppStateHandler(IColorEditorViewModel colorEditorViewModel, IUserSettings userSettings) public AppStateHandler(IColorEditorViewModel colorEditorViewModel, IUserSettings userSettings)
{ {
@@ -36,6 +39,7 @@ namespace ColorPicker.Helpers
public void StartUserSession() public void StartUserSession()
{ {
EndUserSession(); // Ends current user session if there's an active one.
lock (_colorPickerVisibilityLock) lock (_colorPickerVisibilityLock)
{ {
if (!_colorPickerShown && !IsColorPickerEditorVisible()) if (!_colorPickerShown && !IsColorPickerEditorVisible())
@@ -149,7 +153,7 @@ namespace ColorPicker.Helpers
} }
} }
private bool IsColorPickerEditorVisible() public bool IsColorPickerEditorVisible()
{ {
if (_colorEditorWindow != null) if (_colorEditorWindow != null)
{ {
@@ -160,6 +164,11 @@ namespace ColorPicker.Helpers
return false; return false;
} }
public bool IsColorPickerVisible()
{
return _colorPickerShown;
}
private void MainWindow_Closed(object sender, EventArgs e) private void MainWindow_Closed(object sender, EventArgs e)
{ {
AppClosed?.Invoke(this, EventArgs.Empty); AppClosed?.Invoke(this, EventArgs.Empty);

View File

@@ -70,10 +70,17 @@ namespace ColorPicker.Keyboard
var virtualCode = e.KeyboardData.VirtualCode; var virtualCode = e.KeyboardData.VirtualCode;
// ESC pressed // ESC pressed
if (virtualCode == KeyInterop.VirtualKeyFromKey(Key.Escape)) if (virtualCode == KeyInterop.VirtualKeyFromKey(Key.Escape)
&& e.KeyboardState == GlobalKeyboardHook.KeyboardState.KeyDown
)
{ {
e.Handled = _appStateHandler.EndUserSession(); if (_appStateHandler.IsColorPickerVisible()
return; || !AppStateHandler.BlockEscapeKeyClosingColorPickerEditor
)
{
e.Handled = _appStateHandler.EndUserSession();
return;
}
} }
if ((System.Windows.Application.Current as ColorPickerUI.App).IsRunningDetachedFromPowerToys()) if ((System.Windows.Application.Current as ColorPickerUI.App).IsRunningDetachedFromPowerToys())

View File

@@ -163,12 +163,31 @@ private:
m_hProcess = sei.hProcess; m_hProcess = sei.hProcess;
} }
} }
void SendFZECloseEvent()
{
auto exitEvent = CreateEventW(nullptr, false, false, CommonSharedConstants::FZE_EXIT_EVENT);
if (!exitEvent)
{
Logger::warn(L"Failed to create exitEvent. {}", get_last_error_or_default(GetLastError()));
}
else
{
Logger::trace(L"Signaled exitEvent");
if (!SetEvent(exitEvent))
{
Logger::warn(L"Failed to signal exitEvent. {}", get_last_error_or_default(GetLastError()));
}
ResetEvent(exitEvent);
CloseHandle(exitEvent);
}
}
void Disable(bool const traceEvent) void Disable(bool const traceEvent)
{ {
m_enabled = false; m_enabled = false;
// Log telemetry // Log telemetry
if (traceEvent) if (traceEvent)
{ {
Trace::FancyZones::EnableFancyZones(false); Trace::FancyZones::EnableFancyZones(false);
@@ -178,14 +197,15 @@ private:
{ {
ResetEvent(m_toggleEditorEvent); ResetEvent(m_toggleEditorEvent);
} }
if (m_hProcess) if (m_hProcess)
{ {
TerminateProcess(m_hProcess, 0); TerminateProcess(m_hProcess, 0);
SendFZECloseEvent();
m_hProcess = nullptr; m_hProcess = nullptr;
} }
} }
std::wstring app_name; std::wstring app_name;
//contains the non localized key of the powertoy //contains the non localized key of the powertoy
std::wstring app_key; std::wstring app_key;

View File

@@ -80,6 +80,15 @@ namespace FancyZonesEditor
FancyZonesEditorIO = new FancyZonesEditorIO(); FancyZonesEditorIO = new FancyZonesEditorIO();
Overlay = new Overlay(); Overlay = new Overlay();
MainWindowSettings = new MainWindowSettingsModel(); MainWindowSettings = new MainWindowSettingsModel();
new Thread(() =>
{
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, interop.Constants.FZEExitEvent());
if (eventHandle.WaitOne())
{
Environment.Exit(0);
}
}).Start();
} }
private void OnStartup(object sender, StartupEventArgs e) private void OnStartup(object sender, StartupEventArgs e)

View File

@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FancyZonesEditor"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"> d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="Body"> <Grid x:Name="Body">

View File

@@ -34,8 +34,7 @@
<StackPanel Margin="16" <StackPanel Margin="16"
FocusManager.FocusedElement="{Binding ElementName=newZoneButton}"> FocusManager.FocusedElement="{Binding ElementName=newZoneButton}">
<Button x:Name="newZoneButton" <local:ClickAutomationEventButton x:Name="newZoneButton"
AutomationProperties.LabeledBy="{Binding ElementName=newZoneName}"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Height="64" Height="64"
Width="64" Width="64"
@@ -49,7 +48,8 @@
ToolTip="{x:Static props:Resources.Add_zone}" ToolTip="{x:Static props:Resources.Add_zone}"
DataContext="{Binding Path=Model, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" DataContext="{Binding Path=Model, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
IsEnabled="{Binding IsZoneAddingAllowed}" IsEnabled="{Binding IsZoneAddingAllowed}"
Click="OnAddZone" /> Click="OnAddZone"
OnClickAutomationValue="{x:Static props:Resources.New_zone_added}" />
<Grid Margin="0,24,0,0"> <Grid Margin="0,24,0,0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>

View File

@@ -0,0 +1,9 @@
<Button x:Class="FancyZonesEditor.ClickAutomationEventButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FancyZonesEditor"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
</Button>

View File

@@ -0,0 +1,105 @@
// 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.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
namespace FancyZonesEditor
{
public partial class ClickAutomationEventButton : Button
{
public ClickAutomationEventButton()
: base()
{
InitializeComponent();
Click += OnClick;
}
public string OnClickAutomationValue
{
get { return (string)GetValue(OnClickAutomationValueProperty); }
set { SetValue(OnClickAutomationValueProperty, value); }
}
public static readonly DependencyProperty OnClickAutomationValueProperty =
DependencyProperty.Register(
"Value", typeof(string), typeof(ClickAutomationEventButton));
private void OnClick(object sender, RoutedEventArgs e)
{
if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
ClickAutomationEventButtonAutomationPeer peer =
UIElementAutomationPeer.FromElement(this) as ClickAutomationEventButtonAutomationPeer;
if (peer != null)
{
peer.RaisePropertyChangedEvent(
ValuePatternIdentifiers.ValueProperty,
null,
OnClickAutomationValue);
}
}
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new ClickAutomationEventButtonAutomationPeer(this);
}
public class ClickAutomationEventButtonAutomationPeer : FrameworkElementAutomationPeer, IValueProvider
{
public ClickAutomationEventButtonAutomationPeer(ClickAutomationEventButton control)
: base(control)
{
}
protected override string GetClassNameCore()
{
return nameof(ClickAutomationEventButton);
}
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Button;
}
public override object GetPattern(PatternInterface patternInterface)
{
if (patternInterface == PatternInterface.Value)
{
return this;
}
return base.GetPattern(patternInterface);
}
public void SetValue(string value)
{
MyOwner.OnClickAutomationValue = value;
}
private ClickAutomationEventButton MyOwner
{
get
{
return (ClickAutomationEventButton)Owner;
}
}
public string Value
{
get { return MyOwner.OnClickAutomationValue; }
}
public bool IsReadOnly
{
get { return !IsEnabled(); }
}
}
}
}

View File

@@ -81,6 +81,7 @@
<Resource Include="images\FancyZonesEditor.ico" /> <Resource Include="images\FancyZonesEditor.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\..\common\interop\PowerToysInterop.vcxproj" />
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" /> <ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\..\..\common\Microsoft.PowerToys.Common.UI\Microsoft.PowerToys.Common.UI.csproj" /> <ProjectReference Include="..\..\..\..\common\Microsoft.PowerToys.Common.UI\Microsoft.PowerToys.Common.UI.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -528,6 +528,15 @@ namespace FancyZonesEditor.Properties {
} }
} }
/// <summary>
/// Looks up a localized string similar to New zone added.
/// </summary>
public static string New_zone_added {
get {
return ResourceManager.GetString("New_zone_added", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Create or duplicate a layout to get started. /// Looks up a localized string similar to Create or duplicate a layout to get started.
/// </summary> /// </summary>

View File

@@ -120,6 +120,9 @@
<data name="Add_zone" xml:space="preserve"> <data name="Add_zone" xml:space="preserve">
<value>Add new zone</value> <value>Add new zone</value>
</data> </data>
<data name="New_zone_added" xml:space="preserve">
<value>New zone added</value>
</data>
<data name="Apply" xml:space="preserve"> <data name="Apply" xml:space="preserve">
<value>Apply</value> <value>Apply</value>
</data> </data>

View File

@@ -78,7 +78,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>mfplat.lib;mf.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>xcopy /y /I "$(ProjectDir)Icons\*" "$(OutDir)Icons" <Command>xcopy /y /I "$(ProjectDir)Icons\*" "$(OutDir)Icons"
@@ -101,7 +101,7 @@ xcopy /y /I "$(ProjectDir)black.bmp*" "$(OutDir)"</Command>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>mfplat.lib;mf.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>xcopy /y /I "$(ProjectDir)Icons\*" "$(OutDir)Icons" <Command>xcopy /y /I "$(ProjectDir)Icons\*" "$(OutDir)Icons"

View File

@@ -17,7 +17,6 @@
#include <wil/resource.h> #include <wil/resource.h>
#include <wil/com.h> #include <wil/com.h>
#include <mfapi.h>
#include <mfidl.h> #include <mfidl.h>
#include <mftransform.h> #include <mftransform.h>
#include <dshow.h> #include <dshow.h>

View File

@@ -62,7 +62,7 @@
</Lib> </Lib>
<PreBuildEvent Condition="'$(Platform)'=='x64'"> <PreBuildEvent Condition="'$(Platform)'=='x64'">
<Command>call "$(ProjectDir)build_vcm_x86.cmd"</Command> <Command>call "$(ProjectDir)build_vcm_x86.cmd"</Command>
</PreBuildEvent> </PreBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<PropertyGroup Condition="'$(Platform)'!='Win32'"> <PropertyGroup Condition="'$(Platform)'!='Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\VideoConference\</OutDir> <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\VideoConference\</OutDir>
@@ -87,7 +87,7 @@
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MultiThreadedDebug</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>$(OutDir)VideoConferenceShared.lib;mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib;Mf.lib;Shlwapi.lib;Strmiids.lib;%(AdditionalDependencies);</AdditionalDependencies> <AdditionalDependencies>$(OutDir)VideoConferenceShared.lib;Windowscodecs.lib;Wtsapi32.lib;mfplat.lib;WindowsApp.lib;Mfsensorgroup.lib;Mf.lib;Shlwapi.lib;Strmiids.lib;%(AdditionalDependencies);</AdditionalDependencies>
<ModuleDefinitionFile>module.def</ModuleDefinitionFile> <ModuleDefinitionFile>module.def</ModuleDefinitionFile>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>

View File

@@ -0,0 +1,33 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <optional>
#include <functional>
#include <type_traits>
#define DECLARE_DLL_FUNCTION(NAME) \
std::function<decltype(::NAME)> NAME = (std::add_pointer_t<decltype(::NAME)>)GetProcAddress(_library_handle, #NAME);
#define DECLARE_DLL_PROVIDER_BEGIN(DLL_NAME) \
class DLL_NAME##APIProvider final \
{ \
HMODULE _library_handle; \
DLL_NAME##APIProvider(HMODULE h) : _library_handle{ h } {} \
\
public: \
~DLL_NAME##APIProvider() { FreeLibrary(_library_handle); } \
static std::optional<DLL_NAME##APIProvider> create() \
{ \
HMODULE h = LoadLibraryA(#DLL_NAME ".dll"); \
std::optional<DLL_NAME##APIProvider> result; \
if (!h) \
return result; \
result.emplace(DLL_NAME##APIProvider{ h }); \
return result; \
}
#define DECLAR_DLL_PROVIDER_END \
} \
;

View File

@@ -7,6 +7,7 @@
#include <chrono> #include <chrono>
#include <filesystem> #include <filesystem>
#include <initguid.h>
#include <mfapi.h> #include <mfapi.h>
#pragma warning(disable : 4127) #pragma warning(disable : 4127)

View File

@@ -0,0 +1,14 @@
#pragma once
#include <mfapi.h>
#include <mfidl.h>
#include "DLLProviderHelpers.h"
DECLARE_DLL_PROVIDER_BEGIN(mfplat)
DECLARE_DLL_FUNCTION(MFCreateAttributes)
DECLAR_DLL_PROVIDER_END
DECLARE_DLL_PROVIDER_BEGIN(mf)
DECLARE_DLL_FUNCTION(MFEnumDeviceSources)
DECLAR_DLL_PROVIDER_END

View File

@@ -1,5 +1,6 @@
#include "VideoCaptureDeviceList.h" #include "VideoCaptureDeviceList.h"
#include "Logging.h" #include "Logging.h"
#include "MediaFoundationAPIProvider.h"
#include <mfapi.h> #include <mfapi.h>
#include <Mfidl.h> #include <Mfidl.h>
@@ -32,11 +33,17 @@ HRESULT VideoCaptureDeviceList::EnumerateDevices()
HRESULT hr = S_OK; HRESULT hr = S_OK;
wil::com_ptr<IMFAttributes> pAttributes; wil::com_ptr<IMFAttributes> pAttributes;
Clear(); Clear();
auto mfplatAPI = mfplatAPIProvider::create();
auto mfAPI = mfAPIProvider::create();
if (!mfplatAPI || !mfAPI)
{
return ERROR_FILE_NOT_FOUND;
}
// Initialize an attribute store. We will use this to // Initialize an attribute store. We will use this to
// specify the enumeration parameters. // specify the enumeration parameters.
hr = MFCreateAttributes(&pAttributes, 1); hr = mfplatAPI->MFCreateAttributes(&pAttributes, 1);
// Ask for source type = video capture devices // Ask for source type = video capture devices
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@@ -52,14 +59,13 @@ HRESULT VideoCaptureDeviceList::EnumerateDevices()
// Enumerate devices. // Enumerate devices.
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = MFEnumDeviceSources(pAttributes.get(), &m_ppDevices, &m_numberDevices); hr = mfAPI->MFEnumDeviceSources(pAttributes.get(), &m_ppDevices, &m_numberDevices);
} }
else else
{ {
LOG("VideoCaptureDeviceList::EnumerateDevices(): Couldn't SetGUID"); LOG("VideoCaptureDeviceList::EnumerateDevices(): Couldn't SetGUID");
} }
if (FAILED(hr)) if (FAILED(hr))
{ {
LOG("VideoCaptureDeviceList::EnumerateDevices(): MFEnumDeviceSources failed"); LOG("VideoCaptureDeviceList::EnumerateDevices(): MFEnumDeviceSources failed");

View File

@@ -21,7 +21,7 @@
</ItemGroup> </ItemGroup>
<ItemDefinitionGroup> <ItemDefinitionGroup>
<Link> <Link>
<AdditionalDependencies>mfplat.lib;Mfsensorgroup.lib;OneCoreUAP.lib;Mf.lib;Shlwapi.lib;Strmiids.lib;%(AdditionalDependencies);</AdditionalDependencies> <AdditionalDependencies>mfplat.lib;Mfsensorgroup.lib;Mf.lib;Shlwapi.lib;Strmiids.lib;%(AdditionalDependencies);</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
@@ -116,7 +116,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="CameraStateUpdateChannels.h" /> <ClInclude Include="CameraStateUpdateChannels.h" />
<ClInclude Include="DLLProviderHelpers.h" />
<ClInclude Include="Logging.h" /> <ClInclude Include="Logging.h" />
<ClInclude Include="MediaFoundationAPIProvider.h" />
<ClInclude Include="SerializedSharedMemory.h" /> <ClInclude Include="SerializedSharedMemory.h" />
<ClInclude Include="naming.h" /> <ClInclude Include="naming.h" />
<ClInclude Include="MicrophoneDevice.h" /> <ClInclude Include="MicrophoneDevice.h" />

View File

@@ -141,10 +141,16 @@ int runner(bool isProcessElevated, bool openSettings, bool openOobe)
L"modules/PowerRename/PowerRenameExt.dll", L"modules/PowerRename/PowerRenameExt.dll",
L"modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.dll", L"modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.dll",
L"modules/ColorPicker/ColorPicker.dll", L"modules/ColorPicker/ColorPicker.dll",
L"modules/Awake/AwakeModuleInterface.dll", L"modules/Awake/AwakeModuleInterface.dll"
// TODO(yuyoyuppe): uncomment when VCM should be enabled
//L"modules/VideoConference/VideoConferenceModule.dll"
}; };
// TODO(yuyoyuppe): uncomment when VCM should be enabled
//const auto VCM_PATH = L"modules/VideoConference/VideoConferenceModule.dll";
//if (const auto mf = LoadLibraryA("mf.dll"))
//{
// FreeLibrary(mf);
// knownModules.emplace_back(VCM_PATH);
//}
for (const auto& moduleSubdir : knownModules) for (const auto& moduleSubdir : knownModules)
{ {

View File

@@ -59,10 +59,4 @@
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" /> <ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="System.Windows.Forms">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Windows.Forms.dll</HintPath>
</Reference>
</ItemGroup>
</Project> </Project>

View File

@@ -8,7 +8,7 @@ using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Forms; using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers; using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces; using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
@@ -28,10 +28,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private Func<string, int> SendConfigMSG { get; } private Func<string, int> SendConfigMSG { get; }
private Func<Task<string>> PickFileDialog { get; }
private string _settingsConfigFileFolder = string.Empty; private string _settingsConfigFileFolder = string.Empty;
public VideoConferenceViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, string configFileSubfolder = "") public VideoConferenceViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, Func<Task<string>> pickFileDialog, string configFileSubfolder = "")
{ {
PickFileDialog = pickFileDialog;
if (settingsRepository == null) if (settingsRepository == null)
{ {
throw new ArgumentNullException(nameof(settingsRepository)); throw new ArgumentNullException(nameof(settingsRepository));
@@ -161,21 +165,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
RaisePropertyChanged(nameof(CameraImageOverlayPath)); RaisePropertyChanged(nameof(CameraImageOverlayPath));
} }
private void SelectOverlayImageAction() private async void SelectOverlayImageAction()
{ {
try try
{ {
string pickedImage = null; string pickedImage = await PickFileDialog().ConfigureAwait(true);
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "Image Files (*.jpeg;*.jpg;*.png)|*.jpeg;*.jpg;*.png";
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
pickedImage = openFileDialog.FileName;
}
}
if (pickedImage != null) if (pickedImage != null)
{ {
CameraImageOverlayPath = pickedImage; CameraImageOverlayPath = pickedImage;
@@ -417,8 +411,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
OnPropertyChanged(propertyName); OnPropertyChanged(propertyName);
SndVideoConferenceSettings outsettings = new SndVideoConferenceSettings(Settings); SndVideoConferenceSettings outsettings = new SndVideoConferenceSettings(Settings);
SndModuleSettings<SndVideoConferenceSettings> ipcMessage = new SndModuleSettings<SndVideoConferenceSettings>(outsettings); SndModuleSettings<SndVideoConferenceSettings> ipcMessage = new SndModuleSettings<SndVideoConferenceSettings>(outsettings);
SendConfigMSG(ipcMessage.ToJsonString()); SendConfigMSG(ipcMessage.ToJsonString());
_settingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath());
} }
} }

View File

@@ -13,7 +13,7 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
internal static class IIOProviderMocks internal static class IIOProviderMocks
{ {
/// <summary> /// <summary>
/// This method mocks an IO provider to validate tests wich required saving to a file, and then reading the contents of that file, or verifying it exists /// This method mocks an IO provider to validate tests which required saving to a file, and then reading the contents of that file, or verifying it exists
/// </summary> /// </summary>
/// <returns>Mocked IO Provider</returns> /// <returns>Mocked IO Provider</returns>
internal static Mock<IIOProvider> GetMockIOProviderForSaveLoadExists() internal static Mock<IIOProvider> GetMockIOProviderForSaveLoadExists()

View File

@@ -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.Text;
using Windows.ApplicationModel.Resources;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
namespace Microsoft.PowerToys.Settings.UI.Converters
{
public sealed class ImageResizerFitToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var toLower = false;
if ((string)parameter == "ToLower")
{
toLower = true;
}
string targetValue = string.Empty;
switch (value)
{
case 0: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Fit_Fill_ThirdPersonSingular"); break;
case 1: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Fit_Fit_ThirdPersonSingular"); break;
case 2: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Fit_Stretch_ThirdPersonSingular"); break;
}
if (toLower)
{
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
}
return targetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
}

View File

@@ -0,0 +1,44 @@
// 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 Windows.ApplicationModel.Resources;
using Windows.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.Converters
{
public sealed class ImageResizerUnitToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var toLower = false;
if ((string)parameter == "ToLower")
{
toLower = true;
}
string targetValue = string.Empty;
switch (value)
{
case 0: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Centimeter"); break;
case 1: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Inch"); break;
case 2: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Percent"); break;
case 3: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Pixel"); break;
}
if (toLower)
{
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
}
return targetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
}

View File

@@ -110,6 +110,8 @@
</Compile> </Compile>
<Compile Include="Controls\SidePanel\SidePanelLink.cs" /> <Compile Include="Controls\SidePanel\SidePanelLink.cs" />
<Compile Include="Converters\AwakeModeToBoolConverter.cs" /> <Compile Include="Converters\AwakeModeToBoolConverter.cs" />
<Compile Include="Converters\ImageResizerFitToStringConverter.cs" />
<Compile Include="Converters\ImageResizerUnitToStringConverter.cs" />
<Compile Include="Converters\ModuleEnabledToOpacityConverter.cs" /> <Compile Include="Converters\ModuleEnabledToOpacityConverter.cs" />
<Compile Include="Converters\UpdatingStateCannotDownloadToVisibilityConverter.cs" /> <Compile Include="Converters\UpdatingStateCannotDownloadToVisibilityConverter.cs" />
<Compile Include="Converters\UpdatingStateReadyToDownloadToVisibilityConverter.cs" /> <Compile Include="Converters\UpdatingStateReadyToDownloadToVisibilityConverter.cs" />

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Helpers;
@@ -37,11 +38,24 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
set { Set(ref isBackEnabled, value); } set { Set(ref isBackEnabled, value); }
} }
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern bool FreeLibrary(IntPtr hModule);
public bool IsVideoConferenceBuild public bool IsVideoConferenceBuild
{ {
get get
{ {
return this != null && File.Exists("modules/VideoConference/VideoConferenceModule.dll"); var mfHandle = LoadLibrary("mf.dll");
bool mfAvailable = mfHandle != null;
if (mfAvailable)
{
FreeLibrary(mfHandle);
}
return this != null && File.Exists("modules/VideoConference/VideoConferenceModule.dll") && mfAvailable;
} }
} }

View File

@@ -6,11 +6,18 @@
xmlns:models="using:Microsoft.PowerToys.Settings.UI.Library" xmlns:models="using:Microsoft.PowerToys.Settings.UI.Library"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
xmlns:toolkitconverters="using:Microsoft.Toolkit.Uwp.UI.Converters"
mc:Ignorable="d" mc:Ignorable="d"
AutomationProperties.LandmarkType="Main"> AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:ImageResizerFitToStringConverter x:Key="ImageResizerFitToStringConverter" />
<converters:ImageResizerUnitToStringConverter x:Key="ImageResizerUnitToStringConverter" />
<toolkitconverters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" TrueValue="Visible" FalseValue="Collapsed" />
</Page.Resources>
<controls:SettingsPageControl x:Uid="ImageResizer" <controls:SettingsPageControl x:Uid="ImageResizer"
ModuleImageSource="ms-appx:///Assets/Modules/ImageResizer.png" ModuleImageSource="ms-appx:///Assets/Modules/ImageResizer.png"
ModuleImageLink="https://aka.ms/PowerToysOverview_ImageResizer"> ModuleImageLink="https://aka.ms/PowerToysOverview_ImageResizer">
<controls:SettingsPageControl.ModuleContent> <controls:SettingsPageControl.ModuleContent>
@@ -26,7 +33,7 @@
<ListView x:Name="ImagesSizesListView" <ListView x:Name="ImagesSizesListView"
x:Uid="ImagesSizesListView" x:Uid="ImagesSizesListView"
ItemsSource="{x:Bind ViewModel.Sizes, Mode=TwoWay}" ItemsSource="{x:Bind ViewModel.Sizes, Mode=TwoWay}"
Padding="0,0,0,24" Padding="-12,0,0,0"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
SelectionMode="None" SelectionMode="None"
ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.HorizontalScrollMode="Enabled"
@@ -34,142 +41,104 @@
ScrollViewer.IsHorizontalRailEnabled="True" ScrollViewer.IsHorizontalRailEnabled="True"
ContainerContentChanging="ImagesSizesListView_ContainerContentChanging"> ContainerContentChanging="ImagesSizesListView_ContainerContentChanging">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="Background" Value="{ThemeResource ListViewItemBackground}"/>
<Setter Property="Foreground" Value="{ThemeResource ListViewItemForeground}"/>
<Setter Property="TabNavigation" Value="Local"/>
<Setter Property="IsHoldingEnabled" Value="True"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="AllowDrop" Value="False"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="FocusVisualMargin" Value="0"/>
<Setter Property="FocusVisualPrimaryBrush" Value="{ThemeResource ListViewItemFocusVisualPrimaryBrush}"/>
<Setter Property="FocusVisualPrimaryThickness" Value="2"/>
<Setter Property="FocusVisualSecondaryBrush" Value="{ThemeResource ListViewItemFocusVisualSecondaryBrush}"/>
<Setter Property="FocusVisualSecondaryThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter
CheckBrush="{ThemeResource ListViewItemCheckBrush}"
ContentMargin="{TemplateBinding Padding}"
CheckMode="{ThemeResource ListViewItemCheckMode}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}"
DragForeground="{ThemeResource ListViewItemDragForeground}"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
DragBackground="{ThemeResource ListViewItemDragBackground}"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
FocusVisualPrimaryBrush="{TemplateBinding FocusVisualPrimaryBrush}"
FocusVisualSecondaryThickness="{TemplateBinding FocusVisualSecondaryThickness}"
FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
FocusVisualPrimaryThickness="{TemplateBinding FocusVisualPrimaryThickness}"
FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}"
FocusVisualSecondaryBrush="{TemplateBinding FocusVisualSecondaryBrush}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Control.IsTemplateFocusTarget="True"
PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
PressedBackground="{ThemeResource ListViewItemBackgroundPressed}"
PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}"
PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}" ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}"
SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}"
SelectedForeground="{ThemeResource ListViewItemForegroundSelected}"
SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}"
SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate> <ListView.ItemTemplate>
<DataTemplate x:Name="SingleLineDataTemplate" x:DataType="models:ImageSize" > <DataTemplate x:Name="SingleLineDataTemplate" x:DataType="models:ImageSize">
<StackPanel Name="ImageResizer_Configurations" x:Uid="ImageResizer_Configurations" Orientation="Horizontal" Padding="0" Spacing="4"> <Grid Padding="0,12,12,12" Width="420" AutomationProperties.Name="{x:Bind Name, Mode=OneWay}">
<TextBox Name="ImageResizer_Name" <Grid.ColumnDefinitions>
x:Uid="ImageResizer_Name" <ColumnDefinition Width="40" />
Text="{x:Bind Path=Name, Mode=TwoWay}" <ColumnDefinition Width="*" />
Width="90" <ColumnDefinition Width="52" />
VerticalAlignment="Center" </Grid.ColumnDefinitions>
Margin="{StaticResource SmallTopMargin}"/>
<ComboBox Name="ImageResizer_Fit_Property" <FontIcon Glyph="&#xE73F;" FontSize="18" Margin="0,8,0,0" VerticalAlignment="Top" Grid.RowSpan="2" Foreground="{StaticResource SystemColorControlAccentBrush}" />
x:Uid="ImageResizer_Fit_Property" <StackPanel Orientation="Vertical" Grid.Column="1" Margin="0,0,16,0">
SelectedIndex="{x:Bind Path=Fit, Mode=TwoWay}" <TextBlock Text="{x:Bind Name, Mode=OneWay}" FontSize="18" />
Width="90" <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" Margin="0,4,0,0" >
VerticalAlignment="Center" <TextBlock Text="{x:Bind Fit, Mode=OneWay, Converter={StaticResource ImageResizerFitToStringConverter}}" Foreground="{ThemeResource SystemBaseMediumColor}" Margin="0,0,4,0"/>
Margin="{StaticResource SmallTopMargin}"> <TextBlock Text="{x:Bind Width, Mode=OneWay}" FontWeight="SemiBold" Margin="0,0,4,0"/>
<ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Fill" /> <TextBlock Text="&#xE947;" FontFamily="Segoe MDL2 Assets" FontSize="11" AutomationProperties.AccessibilityView="Raw" Visibility="{x:Bind Path=EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" Foreground="{ThemeResource SystemBaseMediumColor}" Margin="0,5,4,0"/>
<ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Fit" /> <TextBlock Text="{x:Bind Height, Mode=OneWay}" Visibility="{x:Bind Path=EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" FontWeight="SemiBold" Margin="0,0,4,0"/>
<ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Stretch" /> <TextBlock Text="{x:Bind Unit, Mode=OneWay, Converter={StaticResource ImageResizerUnitToStringConverter},ConverterParameter=ToLower}" Foreground="{ThemeResource SystemBaseMediumColor}" Margin="0,0,4,0"/>
</ComboBox> </StackPanel>
</StackPanel>
<StackPanel HorizontalAlignment="Right" Grid.Column="2" Orientation="Horizontal">
<Button
x:Uid="EditButton"
Background="Transparent"
FontFamily="Segoe MDL2 Assets"
Width="36"
Height="36"
Content="&#xE70F;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="EditTooltip"/>
</ToolTipService.ToolTip>
<Button.Flyout>
<Flyout>
<StackPanel Spacing="16" Margin="0,12,0,0">
<TextBox
x:Uid="ImageResizer_Name"
Text="{x:Bind Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Width="240"
HorizontalAlignment="Left"/>
<muxc:NumberBox Name="ImageResizer_Width_Property" <ComboBox
x:Uid="ImageResizer_Width_Property" x:Uid="ImageResizer_Fit"
Value="{x:Bind Path=Width, Mode=TwoWay}" SelectedIndex="{x:Bind Path=Fit, Mode=TwoWay}"
Minimum="0" Width="240"
MinWidth="68" HorizontalAlignment="Left">
SpinButtonPlacementMode="Compact" <ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Fill" />
VerticalAlignment="Center" <ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Fit" />
Margin="{StaticResource SmallTopMargin}"/> <ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Stretch" />
</ComboBox>
<TextBlock Name="ImageResizer_Times_Symbol" <StackPanel Spacing="8" Orientation="Horizontal">
x:Uid="ImageResizer_Times_Symbol" <muxc:NumberBox
Text="&#xE711;" x:Uid="ImageResizer_Width"
FontFamily="Segoe MDL2 Assets" Value="{x:Bind Path=Width, Mode=TwoWay}"
TextAlignment="Center" Minimum="0"
VerticalAlignment="Center" Width="116"
Margin="{StaticResource SmallTopMargin}" SpinButtonPlacementMode="Compact"/>
Opacity="{x:Bind Path=ExtraBoxOpacity, Mode=OneWay}"
Width="25"/>
<muxc:NumberBox Name="ImageResizer_Height_Property" <muxc:NumberBox
x:Uid="ImageResizer_Height_Property" x:Uid="ImageResizer_Height"
Value="{x:Bind Path=Height, Mode=TwoWay}" Value="{x:Bind Path=Height, Mode=TwoWay}"
MinWidth="68" Width="116"
Minimum="0" Minimum="0"
VerticalAlignment="Center" SpinButtonPlacementMode="Compact"
SpinButtonPlacementMode="Compact" Visibility="{x:Bind Path=EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"/>
Opacity="{x:Bind Path=ExtraBoxOpacity, Mode=OneWay}"
IsEnabled="{x:Bind Path=EnableEtraBoxes, Mode=OneWay}"
Margin="{StaticResource SmallTopMargin}"/>
<ComboBox Name="ImageResizer_Size_Property" </StackPanel>
x:Uid="ImageResizer_Size_Property" <ComboBox x:Uid="ImageResizer_Size"
SelectedIndex="{Binding Path=Unit, Mode=TwoWay}" SelectedIndex="{Binding Path=Unit, Mode=TwoWay}"
MinWidth="120" Width="240"
VerticalAlignment="Center" Margin="0,0,0,24">
Margin="{StaticResource SmallTopMargin}"> <ComboBoxItem x:Uid="ImageResizer_Sizes_Units_CM" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_CM" /> <ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Inches" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Inches" /> <ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Percent" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Percent" /> <ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Pixels" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Pixels" /> </ComboBox>
</ComboBox> </StackPanel>
<Button x:Name="RemoveButton" </Flyout>
x:Uid="RemoveButton" </Button.Flyout>
Background="Transparent" </Button>
FontFamily="Segoe MDL2 Assets"
Width="34" <Button x:Name="RemoveButton"
Content="&#xE74D;" x:Uid="RemoveButton"
VerticalAlignment="Center" Background="Transparent"
Margin="{StaticResource SmallTopMargin}" FontFamily="Segoe MDL2 Assets"
UseLayoutRounding="False" Width="36"
Click="DeleteCustomSize" Height="36"
CommandParameter="{Binding Id}"> Content="&#xE74D;"
<ToolTipService.ToolTip> Click="DeleteCustomSize"
<TextBlock x:Uid="RemoveTooltip"/> CommandParameter="{Binding Id}">
</ToolTipService.ToolTip> <ToolTipService.ToolTip>
</Button> <TextBlock x:Uid="RemoveTooltip"/>
</StackPanel> </ToolTipService.ToolTip>
</Button>
</StackPanel>
</Grid>
</DataTemplate> </DataTemplate>
</ListView.ItemTemplate> </ListView.ItemTemplate>
</ListView> </ListView>
@@ -259,7 +228,7 @@
x:Uid="ImageResizer_FilenameFormatHeader" x:Uid="ImageResizer_FilenameFormatHeader"
Margin="0,0,0,0" Margin="0,0,0,0"
Opacity="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToOpacityConverter}}"/> Opacity="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToOpacityConverter}}"/>
<TextBlock Text="&#xE946;" <TextBlock Text="&#xE946;" AutomationProperties.AccessibilityView="Raw"
FontFamily="Segoe MDL2 Assets" FontFamily="Segoe MDL2 Assets"
Margin="4,4,0,0"/> Margin="4,4,0,0"/>
</StackPanel> </StackPanel>

View File

@@ -9,6 +9,8 @@ using System.Linq;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Windows.ApplicationModel.Resources;
using Windows.UI.Popups;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
@@ -32,19 +34,36 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel; DataContext = ViewModel;
} }
public void DeleteCustomSize(object sender, RoutedEventArgs e) public async void DeleteCustomSize(object sender, RoutedEventArgs e)
{ {
Button deleteRowButton = (Button)sender; Button deleteRowButton = (Button)sender;
// Using InvariantCulture since this is internal and expected to be numerical if (deleteRowButton != null)
bool success = int.TryParse(deleteRowButton?.CommandParameter?.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out int rowNum);
if (success)
{ {
ViewModel.DeleteImageSize(rowNum); ImageSize x = (ImageSize)deleteRowButton.DataContext;
} ResourceLoader resourceLoader = ResourceLoader.GetForCurrentView();
else
{ ContentDialog dialog = new ContentDialog();
Logger.LogError("Failed to delete custom image size."); dialog.XamlRoot = RootPage.XamlRoot;
dialog.Title = x.Name;
dialog.PrimaryButtonText = resourceLoader.GetString("Yes");
dialog.CloseButtonText = resourceLoader.GetString("No");
dialog.DefaultButton = ContentDialogButton.Primary;
dialog.Content = new TextBlock() { Text = resourceLoader.GetString("Delete_Dialog_Description") };
dialog.PrimaryButtonClick += (s, args) =>
{
// Using InvariantCulture since this is internal and expected to be numerical
bool success = int.TryParse(deleteRowButton?.CommandParameter?.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out int rowNum);
if (success)
{
ViewModel.DeleteImageSize(rowNum);
}
else
{
Logger.LogError("Failed to delete custom image size.");
}
};
var result = await dialog.ShowAsync();
} }
} }

View File

@@ -255,7 +255,8 @@
<ToggleSwitch x:Uid="PowerLauncher_EnablePluginToggle" <ToggleSwitch x:Uid="PowerLauncher_EnablePluginToggle"
x:Name="ToggleSwitch" x:Name="ToggleSwitch"
HorizontalAlignment="Center" OnContent=""
OffContent=""
IsOn="{x:Bind Path=Disabled, Converter={StaticResource BoolNegationConverter}, Mode=TwoWay}" IsOn="{x:Bind Path=Disabled, Converter={StaticResource BoolNegationConverter}, Mode=TwoWay}"
Grid.Column="2" /> Grid.Column="2" />
</Grid> </Grid>

View File

@@ -2,9 +2,12 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.ViewModels; using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views namespace Microsoft.PowerToys.Settings.UI.Views
@@ -13,10 +16,24 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{ {
private VideoConferenceViewModel ViewModel { get; set; } private VideoConferenceViewModel ViewModel { get; set; }
private static async Task<string> PickFileDialog()
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
((IInitializeWithWindow)(object)openPicker).Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
StorageFile file = await openPicker.PickSingleFileAsync();
return file?.Path;
}
public VideoConferencePage() public VideoConferencePage()
{ {
var settingsUtils = new SettingsUtils(); var settingsUtils = new SettingsUtils();
ViewModel = new VideoConferenceViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new VideoConferenceViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, PickFileDialog);
DataContext = ViewModel; DataContext = ViewModel;
InitializeComponent(); InitializeComponent();
} }

View File

@@ -15,6 +15,7 @@ namespace
std::vector<std::wstring> processes = std::vector<std::wstring> processes =
{ {
L"PowerToys.exe", L"PowerToys.exe",
L"PowerToys.Settings.exe",
L"ColorPickerUI.exe", L"ColorPickerUI.exe",
L"PowerToys.Awake.exe", L"PowerToys.Awake.exe",
L"FancyZonesEditor.exe", L"FancyZonesEditor.exe",