Skip to content

Commit 86764c4

Browse files
authored
Feature: Remote Desktop - View Only mode (BornToBeRoot#3482)
* Feature: Remote Desktop - View Only mode * Docs: BornToBeRoot#3482 * Update RemoteDesktopControl.xaml.cs
1 parent f5b2e6a commit 86764c4

24 files changed

Lines changed: 536 additions & 132 deletions

Source/NETworkManager.Localization/Resources/Strings.Designer.cs

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Source/NETworkManager.Localization/Resources/Strings.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,6 +2142,12 @@ is disabled!</value>
21422142
<data name="VisualStyles" xml:space="preserve">
21432143
<value>Visual styles</value>
21442144
</data>
2145+
<data name="ViewOnly" xml:space="preserve">
2146+
<value>View only</value>
2147+
</data>
2148+
<data name="ViewOnlyDescription" xml:space="preserve">
2149+
<value>Block keyboard and mouse input to the remote session</value>
2150+
</data>
21452151
<data name="RemoteAudio" xml:space="preserve">
21462152
<value>Remote audio</value>
21472153
</data>

Source/NETworkManager.Models/RemoteDesktop/RemoteDesktopSessionInfo.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ public class RemoteDesktopSessionInfo
1616
public int DesktopWidth { get; set; }
1717
public int DesktopHeight { get; set; }
1818
public int ColorDepth { get; set; }
19+
20+
// View only (block keyboard and mouse input to the remote session)
21+
public bool ViewOnly { get; set; }
22+
1923
public bool EnableCredSspSupport { get; set; }
2024
public uint AuthenticationLevel { get; set; }
2125
public bool EnableGatewayServer { get; set; }

Source/NETworkManager.Profiles/Application/RemoteDesktop.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ public static RemoteDesktopSessionInfo CreateSessionInfo()
2626
: SettingsManager.Current.RemoteDesktop_ScreenHeight,
2727
ColorDepth = SettingsManager.Current.RemoteDesktop_ColorDepth,
2828

29+
// View only
30+
ViewOnly = SettingsManager.Current.RemoteDesktop_ViewOnly,
31+
2932
// Authentication
3033
EnableCredSspSupport = SettingsManager.Current.RemoteDesktop_EnableCredSspSupport,
3134
AuthenticationLevel = SettingsManager.Current.RemoteDesktop_AuthenticationLevel,
@@ -128,6 +131,12 @@ public static RemoteDesktopSessionInfo CreateSessionInfo(ProfileInfo profile)
128131
info.ColorDepth = group.RemoteDesktop_ColorDepth;
129132
}
130133

134+
// View only
135+
if (profile.RemoteDesktop_OverrideViewOnly)
136+
info.ViewOnly = profile.RemoteDesktop_ViewOnly;
137+
else if (group.RemoteDesktop_OverrideViewOnly)
138+
info.ViewOnly = group.RemoteDesktop_ViewOnly;
139+
131140
// Authentication
132141
if (profile.RemoteDesktop_OverrideCredSspSupport)
133142
info.EnableCredSspSupport = profile.RemoteDesktop_EnableCredSspSupport;

Source/NETworkManager.Profiles/GroupInfo.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public GroupInfo(GroupInfo group) : this(group.Name)
6060
RemoteDesktop_ColorDepth = group.RemoteDesktop_ColorDepth;
6161
RemoteDesktop_OverridePort = group.RemoteDesktop_OverridePort;
6262
RemoteDesktop_Port = group.RemoteDesktop_Port;
63+
RemoteDesktop_OverrideViewOnly = group.RemoteDesktop_OverrideViewOnly;
64+
RemoteDesktop_ViewOnly = group.RemoteDesktop_ViewOnly;
6365
RemoteDesktop_OverrideCredSspSupport = group.RemoteDesktop_OverrideCredSspSupport;
6466
RemoteDesktop_EnableCredSspSupport = group.RemoteDesktop_EnableCredSspSupport;
6567
RemoteDesktop_OverrideAuthenticationLevel = group.RemoteDesktop_OverrideAuthenticationLevel;
@@ -196,6 +198,8 @@ public GroupInfo(GroupInfo group) : this(group.Name)
196198
public int RemoteDesktop_ColorDepth { get; set; } = GlobalStaticConfiguration.RemoteDesktop_ColorDepth;
197199
public bool RemoteDesktop_OverridePort { get; set; }
198200
public int RemoteDesktop_Port { get; set; } = GlobalStaticConfiguration.RemoteDesktop_Port;
201+
public bool RemoteDesktop_OverrideViewOnly { get; set; }
202+
public bool RemoteDesktop_ViewOnly { get; set; } = GlobalStaticConfiguration.RemoteDesktop_ViewOnly;
199203
public bool RemoteDesktop_OverrideCredSspSupport { get; set; }
200204
public bool RemoteDesktop_EnableCredSspSupport { get; set; }
201205
public bool RemoteDesktop_OverrideAuthenticationLevel { get; set; }

Source/NETworkManager.Profiles/ProfileInfo.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ public ProfileInfo(ProfileInfo profile)
100100
RemoteDesktop_ColorDepth = profile.RemoteDesktop_ColorDepth;
101101
RemoteDesktop_OverridePort = profile.RemoteDesktop_OverridePort;
102102
RemoteDesktop_Port = profile.RemoteDesktop_Port;
103+
RemoteDesktop_OverrideViewOnly = profile.RemoteDesktop_OverrideViewOnly;
104+
RemoteDesktop_ViewOnly = profile.RemoteDesktop_ViewOnly;
103105
RemoteDesktop_OverrideCredSspSupport = profile.RemoteDesktop_OverrideCredSspSupport;
104106
RemoteDesktop_EnableCredSspSupport = profile.RemoteDesktop_EnableCredSspSupport;
105107
RemoteDesktop_OverrideAuthenticationLevel = profile.RemoteDesktop_OverrideAuthenticationLevel;
@@ -345,6 +347,8 @@ public ProfileInfo(ProfileInfo profile)
345347
public int RemoteDesktop_ColorDepth { get; set; } = GlobalStaticConfiguration.RemoteDesktop_ColorDepth;
346348
public bool RemoteDesktop_OverridePort { get; set; }
347349
public int RemoteDesktop_Port { get; set; } = GlobalStaticConfiguration.RemoteDesktop_Port;
350+
public bool RemoteDesktop_OverrideViewOnly { get; set; }
351+
public bool RemoteDesktop_ViewOnly { get; set; } = GlobalStaticConfiguration.RemoteDesktop_ViewOnly;
348352
public bool RemoteDesktop_OverrideCredSspSupport { get; set; }
349353
public bool RemoteDesktop_EnableCredSspSupport { get; set; }
350354
public bool RemoteDesktop_OverrideAuthenticationLevel { get; set; }

Source/NETworkManager.Settings/GlobalStaticConfiguration.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ public static class GlobalStaticConfiguration
182182

183183
public static int RemoteDesktop_ColorDepth => 32;
184184
public static int RemoteDesktop_Port => 3389;
185+
public static bool RemoteDesktop_ViewOnly => false;
185186
public static bool RemoteDesktop_GatewayServerBypassLocalAddresses => true;
186187

187188
public static GatewayUserSelectedCredsSource RemoteDesktop_GatewayServerLogonMethod =>

Source/NETworkManager.Settings/SettingsInfo.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,6 +2175,19 @@ public int RemoteDesktop_Port
21752175
}
21762176
} = GlobalStaticConfiguration.RemoteDesktop_Port;
21772177

2178+
public bool RemoteDesktop_ViewOnly
2179+
{
2180+
get;
2181+
set
2182+
{
2183+
if (value == field)
2184+
return;
2185+
2186+
field = value;
2187+
OnPropertyChanged();
2188+
}
2189+
} = GlobalStaticConfiguration.RemoteDesktop_ViewOnly;
2190+
21782191
public bool RemoteDesktop_EnableCredSspSupport
21792192
{
21802193
get;

Source/NETworkManager/Controls/DragablzTabHostWindow.xaml

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
xmlns:dockablz="clr-namespace:Dragablz.Dockablz;assembly=Dragablz"
99
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
1010
xmlns:controls="clr-namespace:NETworkManager.Controls"
11+
xmlns:converters="clr-namespace:NETworkManager.Converters;assembly=NETworkManager.Converters"
1112
xmlns:application="clr-namespace:NETworkManager.Models;assembly=NETworkManager.Models"
1213
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
1314
xmlns:wpfHelpers="clr-namespace:NETworkManager.Utilities.WPF;assembly=NETworkManager.Utilities.WPF"
@@ -18,6 +19,8 @@
1819
d:DataContext="{d:DesignInstance controls:DragablzTabHostWindow}">
1920
<mah:MetroWindow.Resources>
2021
<wpfHelpers:BindingProxy x:Key="BindingProxy" Data="{Binding}" />
22+
<converters:BooleanToVisibilityCollapsedConverter x:Key="BooleanToVisibilityCollapsedConverter" />
23+
<converters:BooleanReverseToVisibilityCollapsedConverter x:Key="BooleanReverseToVisibilityCollapsedConverter" />
2124
</mah:MetroWindow.Resources>
2225
<mah:MetroWindow.WindowButtonCommands>
2326
<mah:WindowButtonCommands Template="{DynamicResource MahApps.Templates.WindowButtonCommands.Win10}" />
@@ -53,7 +56,8 @@
5356
<MenuItem
5457
Header="{x:Static localization:Strings.Reconnect}"
5558
Command="{Binding Data.RemoteDesktop_ReconnectCommand, Source={StaticResource BindingProxy}}"
56-
CommandParameter="{Binding View}">
59+
CommandParameter="{Binding View}"
60+
Visibility="{Binding View.IsConnected, Converter={StaticResource BooleanReverseToVisibilityCollapsedConverter}}">
5761
<MenuItem.Icon>
5862
<Rectangle Width="16" Height="16"
5963
Fill="{DynamicResource MahApps.Brushes.Gray3}">
@@ -67,7 +71,8 @@
6771
<MenuItem
6872
Header="{x:Static localization:Strings.Disconnect}"
6973
Command="{Binding Data.RemoteDesktop_DisconnectCommand, Source={StaticResource BindingProxy}}"
70-
CommandParameter="{Binding View}">
74+
CommandParameter="{Binding View}"
75+
Visibility="{Binding View.IsConnected, Converter={StaticResource BooleanToVisibilityCollapsedConverter}}">
7176
<MenuItem.Icon>
7277
<Rectangle Width="16" Height="16"
7378
Fill="{DynamicResource MahApps.Brushes.Gray3}">
@@ -107,6 +112,38 @@
107112
</Rectangle>
108113
</MenuItem.Icon>
109114
</MenuItem>
115+
<MenuItem
116+
Header="{x:Static localization:Strings.ViewOnly}"
117+
Command="{Binding Data.RemoteDesktop_ViewOnlyCommand, Source={StaticResource BindingProxy}}"
118+
CommandParameter="{Binding View}">
119+
<MenuItem.Icon>
120+
<Rectangle Width="16" Height="16"
121+
Fill="{DynamicResource MahApps.Brushes.Gray3}">
122+
<Rectangle.Resources>
123+
<VisualBrush x:Key="VisualEye"
124+
Stretch="Uniform"
125+
Visual="{iconPacks:Material Kind=Eye}" />
126+
<VisualBrush x:Key="VisualEyeOff"
127+
Stretch="Uniform"
128+
Visual="{iconPacks:Material Kind=EyeOff}" />
129+
</Rectangle.Resources>
130+
<Rectangle.Style>
131+
<Style TargetType="{x:Type Rectangle}">
132+
<Setter Property="OpacityMask"
133+
Value="{StaticResource VisualEyeOff}" />
134+
<Style.Triggers>
135+
<DataTrigger
136+
Binding="{Binding View.IsViewOnly}"
137+
Value="True">
138+
<Setter Property="OpacityMask"
139+
Value="{StaticResource VisualEye}" />
140+
</DataTrigger>
141+
</Style.Triggers>
142+
</Style>
143+
</Rectangle.Style>
144+
</Rectangle>
145+
</MenuItem.Icon>
146+
</MenuItem>
110147
<Separator />
111148
<MenuItem
112149
Header="{x:Static localization:Strings.KeyboardShortcuts}">
@@ -160,6 +197,16 @@
160197
<Thumb Style="{DynamicResource InvisibleThumbStyle}"
161198
dragablz:DragablzItem.IsCustomThumb="True" />
162199
</Grid>
200+
<Rectangle Width="16" Height="16" Margin="0,0,10,0"
201+
VerticalAlignment="Center"
202+
Fill="{DynamicResource MahApps.Brushes.Gray3}"
203+
ToolTip="{x:Static localization:Strings.ViewOnly}"
204+
Visibility="{Binding View.IsViewOnly, Converter={StaticResource BooleanToVisibilityCollapsedConverter}}">
205+
<Rectangle.OpacityMask>
206+
<VisualBrush Stretch="Uniform"
207+
Visual="{iconPacks:Material Kind=Eye}" />
208+
</Rectangle.OpacityMask>
209+
</Rectangle>
163210
<Button Style="{StaticResource CleanButton}"
164211
Command="dragablz:TabablzControl.CloseItemCommand"
165212
ToolTip="{x:Static localization:Strings.Close}"

Source/NETworkManager/Controls/DragablzTabHostWindow.xaml.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ private bool RemoteDesktop_IsDisconnected_CanExecute(object view)
165165
return false;
166166
}
167167

168+
// Used to block actions that would bypass view-only mode (e.g. fullscreen, Ctrl+Alt+Del).
169+
private bool RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute(object view)
170+
{
171+
if (view is RemoteDesktopControl control)
172+
return control.IsConnected && !control.IsViewOnly;
173+
174+
return false;
175+
}
176+
168177
public ICommand RemoteDesktop_DisconnectCommand =>
169178
new RelayCommand(RemoteDesktop_DisconnectAction, RemoteDesktop_IsConnected_CanExecute);
170179

@@ -186,14 +195,23 @@ private void RemoteDesktop_ReconnectAction(object view)
186195
}
187196

188197
public ICommand RemoteDesktop_FullscreenCommand =>
189-
new RelayCommand(RemoteDesktop_FullscreenAction, RemoteDesktop_IsConnected_CanExecute);
198+
new RelayCommand(RemoteDesktop_FullscreenAction, RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
190199

191200
private void RemoteDesktop_FullscreenAction(object view)
192201
{
193202
if (view is RemoteDesktopControl control)
194203
control.FullScreen();
195204
}
196205

206+
public ICommand RemoteDesktop_ViewOnlyCommand =>
207+
new RelayCommand(RemoteDesktop_ViewOnlyAction, RemoteDesktop_IsConnected_CanExecute);
208+
209+
private void RemoteDesktop_ViewOnlyAction(object view)
210+
{
211+
if (view is RemoteDesktopControl control)
212+
control.ToggleViewOnly();
213+
}
214+
197215
public ICommand RemoteDesktop_AdjustScreenCommand =>
198216
new RelayCommand(RemoteDesktop_AdjustScreenAction, RemoteDesktop_IsConnected_CanExecute);
199217

@@ -204,7 +222,7 @@ private void RemoteDesktop_AdjustScreenAction(object view)
204222
}
205223

206224
public ICommand RemoteDesktop_SendCtrlAltDelCommand =>
207-
new RelayCommand(RemoteDesktop_SendCtrlAltDelAction, RemoteDesktop_IsConnected_CanExecute);
225+
new RelayCommand(RemoteDesktop_SendCtrlAltDelAction, RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
208226

209227
private async void RemoteDesktop_SendCtrlAltDelAction(object view)
210228
{

0 commit comments

Comments
 (0)