[New Utility]Mouse Without Borders

* Integrate Mouse Without Borders into PowerToys

---------

Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
Andrey Nekrasov
2023-05-15 23:32:26 +01:00
committed by Jaime Bernardo
parent a0b9af039d
commit 29eebe16a4
304 changed files with 37234 additions and 133 deletions

View File

@@ -0,0 +1,443 @@
<Page x:Class="Microsoft.PowerToys.Settings.UI.Views.MouseWithoutBordersPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:labs="using:CommunityToolkit.Labs.WinUI" mc:Ignorable="d"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
xmlns:toolkitConverters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:ui="using:CommunityToolkit.WinUI.UI"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:NegativeBoolToVisibilityConverter
x:Key="negativeBoolToVisibilityConverter" />
<toolkitConverters:BoolToObjectConverter
x:Key="OneRowMatrixBoolToNumberOfRowsConverter" TrueValue="4"
FalseValue="2" />
</Page.Resources>
<controls:SettingsPageControl x:Uid="MouseWithoutBorders"
ModuleImageSource="ms-appx:///Assets/Modules/MouseWithoutBorders.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:SettingsGroup
x:Uid="MouseWithoutBorders_ActivationSettings">
<labs:SettingsCard x:Uid="MouseWithoutBorders_Toggle_Enable"
HeaderIcon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsMouseWithoutBorders.png}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.CanBeEnabled}"
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.IsEnabled}" />
</labs:SettingsCard>
<InfoBar x:Uid="GPO_IsSettingForced" IsClosable="False"
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
Severity="Informational" />
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="MouseWithoutBorders_KeySettings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsExpander
x:Uid="MouseWithoutBorders_SecurityKey"
x:Name="MouseWithoutBorders_ConnectSettings"
IsExpanded="{x:Bind Mode=TwoWay, Path=ViewModel.ConnectFieldsVisible}">
<labs:SettingsExpander.Items>
<labs:SettingsCard ContentAlignment="Right">
<StackPanel Orientation="Horizontal" Spacing="4">
<TextBox x:Name="ConnectSecurityKeyTextBox"
Width="250"
PlaceholderText="Security Key" />
<TextBox x:Name="ConnectPCNameTextBox"
Width="250"
PlaceholderText="PC Name" />
<Button x:Uid="MouseWithoutBorders_Connect"
Command="{x:Bind Mode=OneTime, Path=ConnectCommand}"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
</labs:SettingsCard>
</labs:SettingsExpander.Items>
<StackPanel Orientation="Horizontal" Spacing="4">
<TextBox IsReadOnly="True"
Text="{x:Bind Mode=TwoWay, Path=ViewModel.SecurityKey}" />
<Button x:Uid="MouseWithoutBorders_NewKey"
Command="{x:Bind Mode=OneTime, Path=GenerateNewKeyCommand}"
Style="{StaticResource AccentButtonStyle}" />
<Button x:Uid="MouseWithoutBorders_Connect"
Command="{x:Bind Mode=OneTime, Path=ShowConnectFieldsCommand}"
Visibility="{x:Bind Path=ViewModel.ConnectFieldsVisible, Mode=OneWay, Converter={StaticResource negativeBoolToVisibilityConverter}}"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
</labs:SettingsExpander>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="MouseWithoutBorders_ThisMachineNameLabel"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<Button
Command="{x:Bind Mode=OneTime, Path=CopyPCNameCommand}"
Style="{StaticResource AccentButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock
x:Uid="MouseWithoutBorders_CopyMachineName" />
</ToolTipService.ToolTip>
<TextBlock
Text="{x:Bind Mode=OneTime, Path=ViewModel.MachineHostName}" />
</Button>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="MouseWithoutBorders_DeviceLayoutSettings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<InfoBar x:Uid="MouseWithoutBorders_CannotDragDropAsAdmin"
IsClosable="True"
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsElevated}"
IsTabStop="True" Severity="Informational" />
<StackPanel Orientation="Vertical"
HorizontalAlignment="Center">
<StackPanel HorizontalAlignment="Center"
Orientation="Horizontal">
<ItemsControl x:Name="DevicesItemsControl"
ItemsSource="{Binding MachineMatrixString, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal"
MaximumRowsOrColumns="{Binding MatrixOneRow, Mode=OneWay, Converter={StaticResource OneRowMatrixBoolToNumberOfRowsConverter}}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--TODO: colors?-->
<!--BorderBrush="#DFDFDF"
Background="#d4d4d4"-->
<!-- Dragging while elevated crashes on WinUI3: https://github.com/microsoft/microsoft-ui-xaml/issues/7690 -->
<Border
BorderBrush="{Binding Item.StatusBrush}"
Background="{ThemeResource SubtleButtonBackgroundDisabled}"
Width="90" Height="90"
BorderThickness="2" Margin="3"
CanDrag="{Binding Mode=OneWay, Path=Item.CanDragDrop}"
AllowDrop="{Binding Mode=OneWay, Path=Item.CanDragDrop}"
CornerRadius="4"
DragStarting="Device_DragStarting"
DragOver="Device_DragOver"
DataContext="{Binding}"
ToolTipService.ToolTip="{Binding Item.Name, Mode=OneWay}"
Drop="Device_Drop">
<StackPanel
VerticalAlignment="Center"
Orientation="Vertical"
Opacity="0.5">
<FontIcon FontSize="39"
Width="50" Height="50"
FontFamily="Segoe MDL2 Assets"
Glyph="&#xE7F4;" />
<TextBlock Tag="DeviceName"
HorizontalAlignment="Center"
Text="{Binding Item.Name}" />
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<Button
HorizontalAlignment="Center"
Command="{x:Bind Mode=OneTime, Path=ReconnectCommand}"
Style="{StaticResource AccentButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock
x:Uid="MouseWithoutBorders_ReconnectTooltip" />
</ToolTipService.ToolTip>
<TextBlock
x:Uid="MouseWithoutBorders_ReconnectButton" />
</Button>
</StackPanel>
<labs:SettingsCard x:Uid="MouseWithoutBorders_MatrixOneRow">
<ToggleSwitch
x:Uid="MouseWithoutBorders_MatrixOneRow_ToggleSwitch"
IsOn="{x:Bind ViewModel.MatrixOneRow, Mode=TwoWay}" />
</labs:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="MouseWithoutBorders_ServiceSettings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.CanToggleUseService}">
<labs:SettingsCard x:Uid="MouseWithoutBorders_UseService">
<ToggleSwitch
x:Uid="MouseWithoutBorders_UseService_ToggleSwitch"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
IsOn="{x:Bind ViewModel.UseService, Mode=TwoWay}" />
</labs:SettingsCard>
<InfoBar x:Uid="MouseWithoutBorders_RunAsAdminText"
IsClosable="False"
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.CanToggleUseService, Converter={StaticResource BoolNegationConverter}}"
IsTabStop="True" Severity="Informational" />
<InfoBar
x:Uid="MouseWithoutBorders_ServiceUserUninstallWarning"
IsOpen="True" IsClosable="True" IsTabStop="True"
Severity="Warning" />
<labs:SettingsCard
x:Uid="MouseWithoutBorders_UninstallService" ActionIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
FontSize=14,
Glyph=&#xE8A7;}"
Command="{x:Bind ViewModel.UninstallServiceEventHandler}"
IsClickEnabled="{x:Bind Mode=OneWay, Path=ViewModel.CanUninstallService}" />
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="MouseWithoutBorders_Settings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard x:Uid="MouseWithoutBorders_WrapMouse">
<ToggleSwitch
x:Uid="MouseWithoutBorders_WrapMouse_ToggleSwitch"
IsOn="{x:Bind ViewModel.WrapMouse, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_ShareClipboard">
<ToggleSwitch
x:Uid="MouseWithoutBorders_ShareClipboard_ToggleSwitch"
IsOn="{x:Bind ViewModel.ShareClipboard, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard x:Uid="MouseWithoutBorders_TransferFile">
<ToggleSwitch
x:Uid="MouseWithoutBorders_TransferFile_ToggleSwitch"
IsOn="{x:Bind ViewModel.TransferFile, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_HideMouseAtScreenEdge">
<ToggleSwitch
x:Uid="MouseWithoutBorders_HideMouseAtScreenEdge_ToggleSwitch"
IsOn="{x:Bind ViewModel.HideMouseAtScreenEdge, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_DrawMouseCursor">
<ToggleSwitch
x:Uid="MouseWithoutBorders_DrawMouseCursor_ToggleSwitch"
IsOn="{x:Bind ViewModel.DrawMouseCursor, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_ValidateRemoteMachineIP">
<ToggleSwitch
x:Uid="MouseWithoutBorders_ValidateRemoteMachineIP_ToggleSwitch"
IsOn="{x:Bind ViewModel.ValidateRemoteMachineIP, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_SameSubnetOnly">
<ToggleSwitch
x:Uid="MouseWithoutBorders_SameSubnetOnly_ToggleSwitch"
IsOn="{x:Bind ViewModel.SameSubnetOnly, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_BlockScreenSaverOnOtherMachines">
<ToggleSwitch
x:Uid="MouseWithoutBorders_BlockScreenSaverOnOtherMachines_ToggleSwitch"
IsOn="{x:Bind ViewModel.BlockScreenSaverOnOtherMachines, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_MoveMouseRelatively">
<ToggleSwitch
x:Uid="MouseWithoutBorders_MoveMouseRelatively_ToggleSwitch"
IsOn="{x:Bind ViewModel.MoveMouseRelatively, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_BlockMouseAtScreenCorners">
<ToggleSwitch
x:Uid="MouseWithoutBorders_BlockMouseAtScreenCorners_ToggleSwitch"
IsOn="{x:Bind ViewModel.BlockMouseAtScreenCorners, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_ShowClipboardAndNetworkStatusMessages">
<ToggleSwitch
x:Uid="MouseWithoutBorders_ShowClipboardAndNetworkStatusMessages_ToggleSwitch"
IsOn="{x:Bind ViewModel.ShowClipboardAndNetworkStatusMessages, Mode=TwoWay}" />
</labs:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="MouseWithoutBorders_KeyboardShortcuts_Group"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard x:Uid="MouseWithoutBorders_EasyMouseOption">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.EasyMouseOptionIndex, Mode=TwoWay}">
<ComboBoxItem x:Uid="MouseWithoutBorders_EasyMouseOption_Disabled" />
<ComboBoxItem x:Uid="MouseWithoutBorders_EasyMouseOption_Enabled" />
<ComboBoxItem x:Uid="MouseWithoutBorders_EasyMouseOption_Ctrl" />
<ComboBoxItem x:Uid="MouseWithoutBorders_EasyMouseOption_Shift" />
</ComboBox>
</labs:SettingsCard>
<labs:SettingsCard x:Uid="MouseWithoutBorders_ToggleEasyMouseShortcut">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.ToggleEasyMouseShortcutIndex, Mode=TwoWay}"
>
<ComboBoxItem x:Uid="MouseWithoutBorders_ToggleEasyMouseShortcut_Disabled" />
<ComboBoxItem>A</ComboBoxItem>
<ComboBoxItem>B</ComboBoxItem>
<ComboBoxItem>C</ComboBoxItem>
<ComboBoxItem>D</ComboBoxItem>
<ComboBoxItem>E</ComboBoxItem>
<ComboBoxItem>F</ComboBoxItem>
<ComboBoxItem>G</ComboBoxItem>
<ComboBoxItem>H</ComboBoxItem>
<ComboBoxItem>I</ComboBoxItem>
<ComboBoxItem>J</ComboBoxItem>
<ComboBoxItem>K</ComboBoxItem>
<ComboBoxItem>L</ComboBoxItem>
<ComboBoxItem>M</ComboBoxItem>
<ComboBoxItem>N</ComboBoxItem>
<ComboBoxItem>O</ComboBoxItem>
<ComboBoxItem>P</ComboBoxItem>
<ComboBoxItem>Q</ComboBoxItem>
<ComboBoxItem>R</ComboBoxItem>
<ComboBoxItem>S</ComboBoxItem>
<ComboBoxItem>T</ComboBoxItem>
<ComboBoxItem>U</ComboBoxItem>
<ComboBoxItem>V</ComboBoxItem>
<ComboBoxItem>W</ComboBoxItem>
<ComboBoxItem>X</ComboBoxItem>
<ComboBoxItem>Y</ComboBoxItem>
<ComboBoxItem>Z</ComboBoxItem>
</ComboBox>
</labs:SettingsCard>
<labs:SettingsCard x:Uid="MouseWithoutBorders_LockMachinesShortcut">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.LockMachinesShortcutIndex, Mode=TwoWay}"
>
<ComboBoxItem x:Uid="MouseWithoutBorders_LockMachinesShortcut_Disabled" />
<ComboBoxItem>A</ComboBoxItem>
<ComboBoxItem>B</ComboBoxItem>
<ComboBoxItem>C</ComboBoxItem>
<ComboBoxItem>D</ComboBoxItem>
<ComboBoxItem>E</ComboBoxItem>
<ComboBoxItem>F</ComboBoxItem>
<ComboBoxItem>G</ComboBoxItem>
<ComboBoxItem>H</ComboBoxItem>
<ComboBoxItem>I</ComboBoxItem>
<ComboBoxItem>J</ComboBoxItem>
<ComboBoxItem>K</ComboBoxItem>
<ComboBoxItem>L</ComboBoxItem>
<ComboBoxItem>M</ComboBoxItem>
<ComboBoxItem>N</ComboBoxItem>
<ComboBoxItem>O</ComboBoxItem>
<ComboBoxItem>P</ComboBoxItem>
<ComboBoxItem>Q</ComboBoxItem>
<ComboBoxItem>R</ComboBoxItem>
<ComboBoxItem>S</ComboBoxItem>
<ComboBoxItem>T</ComboBoxItem>
<ComboBoxItem>U</ComboBoxItem>
<ComboBoxItem>V</ComboBoxItem>
<ComboBoxItem>W</ComboBoxItem>
<ComboBoxItem>X</ComboBoxItem>
<ComboBoxItem>Y</ComboBoxItem>
<ComboBoxItem>Z</ComboBoxItem>
</ComboBox>
</labs:SettingsCard>
<labs:SettingsCard x:Uid="MouseWithoutBorders_ReconnectShortcut">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.ReconnectShortcutIndex, Mode=TwoWay}"
>
<ComboBoxItem x:Uid="MouseWithoutBorders_ReconnectShortcut_Disabled" />
<ComboBoxItem>A</ComboBoxItem>
<ComboBoxItem>B</ComboBoxItem>
<ComboBoxItem>C</ComboBoxItem>
<ComboBoxItem>D</ComboBoxItem>
<ComboBoxItem>E</ComboBoxItem>
<ComboBoxItem>F</ComboBoxItem>
<ComboBoxItem>G</ComboBoxItem>
<ComboBoxItem>H</ComboBoxItem>
<ComboBoxItem>I</ComboBoxItem>
<ComboBoxItem>J</ComboBoxItem>
<ComboBoxItem>K</ComboBoxItem>
<ComboBoxItem>L</ComboBoxItem>
<ComboBoxItem>M</ComboBoxItem>
<ComboBoxItem>N</ComboBoxItem>
<ComboBoxItem>O</ComboBoxItem>
<ComboBoxItem>P</ComboBoxItem>
<ComboBoxItem>Q</ComboBoxItem>
<ComboBoxItem>R</ComboBoxItem>
<ComboBoxItem>S</ComboBoxItem>
<ComboBoxItem>T</ComboBoxItem>
<ComboBoxItem>U</ComboBoxItem>
<ComboBoxItem>V</ComboBoxItem>
<ComboBoxItem>W</ComboBoxItem>
<ComboBoxItem>X</ComboBoxItem>
<ComboBoxItem>Y</ComboBoxItem>
<ComboBoxItem>Z</ComboBoxItem>
</ComboBox>
</labs:SettingsCard>
<labs:SettingsCard x:Uid="MouseWithoutBorders_Switch2AllPcShortcut">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.Switch2AllPcShortcutIndex, Mode=TwoWay}"
>
<ComboBoxItem x:Uid="MouseWithoutBorders_Switch2AllPcShortcut_Disabled" />
<ComboBoxItem x:Uid="MouseWithoutBorders_Switch2AllPcShortcut_Ctrl3" />
<ComboBoxItem>A</ComboBoxItem>
<ComboBoxItem>B</ComboBoxItem>
<ComboBoxItem>C</ComboBoxItem>
<ComboBoxItem>D</ComboBoxItem>
<ComboBoxItem>E</ComboBoxItem>
<ComboBoxItem>F</ComboBoxItem>
<ComboBoxItem>G</ComboBoxItem>
<ComboBoxItem>H</ComboBoxItem>
<ComboBoxItem>I</ComboBoxItem>
<ComboBoxItem>J</ComboBoxItem>
<ComboBoxItem>K</ComboBoxItem>
<ComboBoxItem>L</ComboBoxItem>
<ComboBoxItem>M</ComboBoxItem>
<ComboBoxItem>N</ComboBoxItem>
<ComboBoxItem>O</ComboBoxItem>
<ComboBoxItem>P</ComboBoxItem>
<ComboBoxItem>Q</ComboBoxItem>
<ComboBoxItem>R</ComboBoxItem>
<ComboBoxItem>S</ComboBoxItem>
<ComboBoxItem>T</ComboBoxItem>
<ComboBoxItem>U</ComboBoxItem>
<ComboBoxItem>V</ComboBoxItem>
<ComboBoxItem>W</ComboBoxItem>
<ComboBoxItem>X</ComboBoxItem>
<ComboBoxItem>Y</ComboBoxItem>
<ComboBoxItem>Z</ComboBoxItem>
</ComboBox>
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="MouseWithoutBorders_SwitchBetweenMachineShortcut"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xE92E;}">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.SelectedSwitchBetweenMachineShortcutOptionsIndex, Mode=TwoWay}">
<!-- These should be in the same order as the array items in MouseWithoutBordersViewModel.cs -->
<ComboBoxItem x:Uid="MouseWithoutBorders_SwitchBetweenMachineShortcut_F1" />
<ComboBoxItem x:Uid="MouseWithoutBorders_SwitchBetweenMachineShortcut_1"/>
<ComboBoxItem x:Uid="MouseWithoutBorders_SwitchBetweenMachineShortcut_Disabled" />
</ComboBox>
</labs:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="MouseWithoutBorders_TroubleShooting"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard
x:Uid="MouseWithoutBorders_AddFirewallRuleButtonControl" ActionIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
FontSize=14,
Glyph=&#xE8A7;}"
Command="{x:Bind ViewModel.AddFirewallRuleEventHandler}"
IsClickEnabled="True" />
<labs:SettingsCard
x:Uid="MouseWithoutBorders_ShowOriginalUI">
<ToggleSwitch
x:Uid="MouseWithoutBorders_ShowOriginalUI_ToggleSwitch"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
IsOn="{x:Bind ViewModel.ShowOriginalUI, Mode=TwoWay}" />
</labs:SettingsCard>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_MouseWithoutBorders"
Link="https://aka.ms/PowerToysOverview_MouseWithoutBorders" />
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Mouse without Borders"
Link="http://aka.ms/mm" />
<controls:PageLink
Link="https://github.com/microsoft/PowerToys/blob/main/COMMUNITY.md#mouse-without-borders-original-contributors"
Text="Truong Do (Đỗ Đức Trường) and other original contributors" />
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View File

@@ -0,0 +1,176 @@
// 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.IO.Abstractions;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Xml.Linq;
using CommunityToolkit.Labs.WinUI;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Windows.ApplicationModel.DataTransfer;
using WinRT;
using static Microsoft.PowerToys.Settings.UI.ViewModels.MouseWithoutBordersViewModel;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class MouseWithoutBordersPage : Page, IRefreshablePage
{
private const string MouseWithoutBordersDragDropCheckString = "MWB Device Drag Drop";
private const string PowerToyName = "MouseWithoutBorders";
private MouseWithoutBordersViewModel ViewModel { get; set; }
private readonly IFileSystemWatcher watcher;
public MouseWithoutBordersPage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new MouseWithoutBordersViewModel(
settingsUtils,
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),
ShellPage.SendDefaultIPCMessage,
DispatcherQueue);
watcher = Helper.GetFileWatcher(
PowerToyName,
"settings.json",
OnConfigFileUpdate);
DataContext = ViewModel;
InitializeComponent();
}
private void OnConfigFileUpdate()
{
// Note: FileSystemWatcher raise notification multiple times for single update operation.
// Todo: Handle duplicate events either by somehow suppress them or re-read the configuration everytime since we will be updating the UI only if something is changed.
this.DispatcherQueue.TryEnqueue(() =>
{
if (ViewModel.LoadUpdatedSettings())
{
ViewModel.NotifyUpdatedSettings();
}
});
}
private static T GetChildOfType<T>(DependencyObject depObj, string tag)
where T : FrameworkElement
{
if (depObj == null)
{
return null;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = (child as T) ?? GetChildOfType<T>(child, tag);
if (result != null && (string)result.Tag == tag)
{
return result;
}
}
return null;
}
private int GetDeviceIndex(Border b)
{
return b.DataContext.As<IndexedItem<DeviceViewModel>>().Index;
}
private void Device_DragStarting(UIElement sender, DragStartingEventArgs args)
{
args.Data.RequestedOperation = DataPackageOperation.Move;
args.Data.Properties.Add("check-usage", MouseWithoutBordersDragDropCheckString);
args.Data.Properties.Add("index", GetDeviceIndex((Border)sender));
}
private void Device_Drop(object sender, DragEventArgs e)
{
if (e.DataView.Properties.TryGetValue("check-usage", out object checkUsage))
{
// Guard against values dragged from somewhere else
if (!((string)checkUsage).Equals(MouseWithoutBordersDragDropCheckString, StringComparison.Ordinal))
{
return;
}
}
else
{
return;
}
if (!e.DataView.Properties.TryGetValue("index", out object boxIndex))
{
return;
}
var draggedDeviceIndex = (int)boxIndex;
if (draggedDeviceIndex < 0 || draggedDeviceIndex >= ViewModel.MachineMatrixString.Count)
{
return;
}
var targetDeviceIndex = GetDeviceIndex((Border)e.OriginalSource);
ViewModel.MachineMatrixString.Swap(draggedDeviceIndex, targetDeviceIndex);
var itemsControl = (ItemsControl)FindName("DevicesItemsControl");
var binding = itemsControl.GetBindingExpression(ItemsControl.ItemsSourceProperty);
binding.UpdateSource();
}
private void Device_DragOver(object sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Move;
}
public ICommand ShowConnectFieldsCommand => new RelayCommand(ShowConnectFields);
public ICommand ConnectCommand => new AsyncCommand(Connect);
public ICommand GenerateNewKeyCommand => new AsyncCommand(ViewModel.SubmitNewKeyRequestAsync);
public ICommand CopyPCNameCommand => new RelayCommand(ViewModel.CopyMachineNameToClipboard);
public ICommand ReconnectCommand => new AsyncCommand(ViewModel.SubmitReconnectRequestAsync);
private void ShowConnectFields()
{
ViewModel.ConnectFieldsVisible = true;
}
private async Task Connect()
{
if (ConnectPCNameTextBox.Text.Length != 0 && ConnectSecurityKeyTextBox.Text.Length != 0)
{
string pcName = ConnectPCNameTextBox.Text;
string securityKey = ConnectSecurityKeyTextBox.Text.Trim();
await ViewModel.SubmitConnectionRequestAsync(pcName, securityKey);
ConnectPCNameTextBox.Text = string.Empty;
ConnectSecurityKeyTextBox.Text = string.Empty;
}
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@@ -94,6 +94,11 @@
helpers:NavHelper.NavigateTo="views:MouseUtilsPage"
Icon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsMouseUtils.png}" />
<NavigationViewItem
x:Uid="Shell_MouseWithoutBorders"
helpers:NavHelper.NavigateTo="views:MouseWithoutBordersPage"
Icon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsMouseWithoutBorders.png}" />
<NavigationViewItem
x:Uid="Shell_PastePlain"
helpers:NavHelper.NavigateTo="views:PastePlainPage"