Repository navigation
Expand file tree
/
Copy pathDragablzTabHostWindow.xaml.cs
More file actions
473 lines (371 loc) · 13.8 KB
/
Copy pathDragablzTabHostWindow.xaml.cs
File metadata and controls
473 lines (371 loc) · 13.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
using Dragablz;
using NETworkManager.Localization;
using NETworkManager.Localization.Resources;
using NETworkManager.Models;
using NETworkManager.Models.RemoteDesktop;
using NETworkManager.Settings;
using NETworkManager.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
namespace NETworkManager.Controls;
public sealed partial class DragablzTabHostWindow : INotifyPropertyChanged
{
#region Constructor
public DragablzTabHostWindow(ApplicationName applicationName)
{
InitializeComponent();
DataContext = this;
ApplicationName = applicationName;
InterTabClient = new DragablzInterTabClient(applicationName);
InterTabPartition = applicationName.ToString();
Title =
$"NETworkManager {AssemblyManager.Current.Version} - {ResourceTranslator.Translate(ResourceIdentifier.ApplicationName, applicationName)}";
}
#endregion
#region Methods
private async void FocusEmbeddedWindow()
{
// Delay the focus to prevent blocking the ui
// Detect if window is resizing
do
{
await Task.Delay(250);
} while (Control.MouseButtons == MouseButtons.Left);
/* Don't continue if
- Header ContextMenu is opened
*/
if (HeaderContextMenuIsOpen)
return;
// Return if the application is not an embedded window
if (!_embeddedWindowApplicationNames.Contains(ApplicationName))
return;
// Find all TabablzControl in the active window
foreach (var tabablzControl in VisualTreeHelper.FindVisualChildren<TabablzControl>(this))
{
// Skip if no items
if (tabablzControl.Items.Count == 0)
continue;
// Focus embedded window in the selected tab
(((DragablzTabItem)tabablzControl.SelectedItem)?.View as IEmbeddedWindow)?.FocusEmbeddedWindow();
break;
}
}
#endregion
#region PropertyChangedEventHandler
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Variables
public IInterTabClient InterTabClient { get; }
private readonly HashSet<ApplicationName> _embeddedWindowApplicationNames =
[
ApplicationName.PowerShell,
ApplicationName.PuTTY
];
public ApplicationName ApplicationName
{
get;
set
{
if (value == field)
return;
field = value;
OnPropertyChanged();
}
}
public string InterTabPartition
{
get;
set
{
if (value == field)
return;
field = value;
OnPropertyChanged();
}
}
public bool HeaderContextMenuIsOpen
{
get;
set
{
if (value == field)
return;
field = value;
OnPropertyChanged();
}
}
#endregion
#region ICommand & Actions
public ItemActionCallback CloseItemCommand => CloseItemAction;
private void CloseItemAction(ItemActionCallbackArgs<TabablzControl> args)
{
((IDragablzTabItem)((DragablzTabItem)args.DragablzItem.Content).View).CloseTab();
}
#region RemoteDesktop commands
private bool RemoteDesktop_IsConnected_CanExecute(object view)
{
if (view is RemoteDesktopControl control)
return control.IsConnected;
return false;
}
private bool RemoteDesktop_IsDisconnected_CanExecute(object view)
{
if (view is RemoteDesktopControl control)
return !control.IsConnected && !control.IsConnecting;
return false;
}
// Used to block actions that would bypass view-only mode (e.g. fullscreen, Ctrl+Alt+Del).
private bool RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute(object view)
{
if (view is RemoteDesktopControl control)
return control.IsConnected && !control.IsViewOnly;
return false;
}
public ICommand RemoteDesktop_DisconnectCommand =>
new RelayCommand(RemoteDesktop_DisconnectAction, RemoteDesktop_IsConnected_CanExecute);
private void RemoteDesktop_DisconnectAction(object view)
{
if (view is RemoteDesktopControl control)
if (control.DisconnectCommand.CanExecute(null))
control.DisconnectCommand.Execute(null);
}
public ICommand RemoteDesktop_ReconnectCommand =>
new RelayCommand(RemoteDesktop_ReconnectAction, RemoteDesktop_IsDisconnected_CanExecute);
private void RemoteDesktop_ReconnectAction(object view)
{
if (view is RemoteDesktopControl control)
if (control.ReconnectCommand.CanExecute(null))
control.ReconnectCommand.Execute(null);
}
public ICommand RemoteDesktop_FullscreenCommand =>
new RelayCommand(RemoteDesktop_FullscreenAction, RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
private void RemoteDesktop_FullscreenAction(object view)
{
if (view is RemoteDesktopControl control)
control.FullScreen();
}
public ICommand RemoteDesktop_ViewOnlyCommand =>
new RelayCommand(RemoteDesktop_ViewOnlyAction, RemoteDesktop_IsConnected_CanExecute);
private void RemoteDesktop_ViewOnlyAction(object view)
{
if (view is RemoteDesktopControl control)
control.ToggleViewOnly();
}
public ICommand RemoteDesktop_AdjustScreenCommand =>
new RelayCommand(RemoteDesktop_AdjustScreenAction, RemoteDesktop_IsConnected_CanExecute);
private void RemoteDesktop_AdjustScreenAction(object view)
{
if (view is RemoteDesktopControl control)
control.AdjustScreen(force: true);
}
public ICommand RemoteDesktop_SendCtrlAltDelCommand =>
new RelayCommand(RemoteDesktop_SendCtrlAltDelAction, RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
private async void RemoteDesktop_SendCtrlAltDelAction(object view)
{
if (view is not RemoteDesktopControl control)
return;
try
{
control.SendKey(Keystroke.CtrlAltDel);
}
catch (Exception ex)
{
//ConfigurationManager.OnDialogOpen();
// Use built-in message box because we have visual issues in the dragablz window
System.Windows.MessageBox.Show($"{Strings.CouldNotSendKeystroke}\n\nMessage:\n{ex.Message}", Strings.Error, MessageBoxButton.OK, MessageBoxImage.Error);
//ConfigurationManager.OnDialogClose();
}
}
#endregion
#region PowerShell commands
private bool PowerShell_IsConnected_CanExecute(object view)
{
if (view is PowerShellControl control)
return control.IsConnected;
return false;
}
public ICommand PowerShell_ReconnectCommand => new RelayCommand(PowerShell_ReconnectAction);
private void PowerShell_ReconnectAction(object view)
{
if (view is PowerShellControl control)
if (control.ReconnectCommand.CanExecute(null))
control.ReconnectCommand.Execute(null);
}
public ICommand PowerShell_ResizeWindowCommand =>
new RelayCommand(PowerShell_ResizeWindowAction, PowerShell_IsConnected_CanExecute);
private void PowerShell_ResizeWindowAction(object view)
{
if (view is PowerShellControl control)
control.ResizeEmbeddedWindow();
}
#endregion
#region PuTTY commands
private bool PuTTY_IsConnected_CanExecute(object view)
{
if (view is PuTTYControl control)
return control.IsConnected;
return false;
}
public ICommand PuTTY_ReconnectCommand => new RelayCommand(PuTTY_ReconnectAction);
private void PuTTY_ReconnectAction(object view)
{
if (view is PuTTYControl control)
if (control.ReconnectCommand.CanExecute(null))
control.ReconnectCommand.Execute(null);
}
public ICommand PuTTY_ResizeWindowCommand =>
new RelayCommand(PuTTY_ResizeWindowAction, PuTTY_IsConnected_CanExecute);
private void PuTTY_ResizeWindowAction(object view)
{
if (view is PuTTYControl control)
control.ResizeEmbeddedWindow();
}
public ICommand PuTTY_RestartSessionCommand =>
new RelayCommand(PuTTY_RestartSessionAction, PuTTY_IsConnected_CanExecute);
private void PuTTY_RestartSessionAction(object view)
{
if (view is PuTTYControl control)
control.RestartSession();
}
#endregion
#region TigerVNC commands
public ICommand TigerVNC_ReconnectCommand => new RelayCommand(TigerVNC_ReconnectAction);
private void TigerVNC_ReconnectAction(object view)
{
if (view is TigerVNCControl control)
if (control.ReconnectCommand.CanExecute(null))
control.ReconnectCommand.Execute(null);
}
#endregion
#region WebConsole commands
public ICommand WebConsole_ReloadCommand => new RelayCommand(WebConsole_RefreshAction);
private void WebConsole_RefreshAction(object view)
{
if (view is WebConsoleControl control)
if (control.ReloadCommand.CanExecute(null))
control.ReloadCommand.Execute(null);
}
#endregion
#endregion
#region Events
private void MetroWindow_Activated(object sender, EventArgs e)
{
FocusEmbeddedWindow();
}
private void DragablzTabHostWindow_OnClosing(object sender, CancelEventArgs e)
{
// Find all TabablzControl in the active window
foreach (var tabablzControl in VisualTreeHelper.FindVisualChildren<TabablzControl>(this))
foreach (var tabItem in tabablzControl.Items.OfType<DragablzTabItem>())
((IDragablzTabItem)tabItem.View).CloseTab();
// Reset the dragging state
switch (ApplicationName)
{
case ApplicationName.RemoteDesktop:
ConfigurationManager.Current.IsRemoteDesktopWindowDragging = false;
break;
case ApplicationName.PowerShell:
ConfigurationManager.Current.IsPowerShellWindowDragging = false;
break;
case ApplicationName.PuTTY:
ConfigurationManager.Current.IsPuTTYWindowDragging = false;
break;
case ApplicationName.TigerVNC:
ConfigurationManager.Current.IsTigerVNCWindowDragging = false;
break;
case ApplicationName.WebConsole:
ConfigurationManager.Current.IsWebConsoleWindowDragging = false;
break;
}
}
private void TabablzControl_OnIsDraggingWindowChanged(object sender, RoutedPropertyChangedEventArgs<bool> e)
{
// Set the dragging state
switch (ApplicationName)
{
case ApplicationName.RemoteDesktop:
ConfigurationManager.Current.IsRemoteDesktopWindowDragging = e.NewValue;
break;
case ApplicationName.PowerShell:
ConfigurationManager.Current.IsPowerShellWindowDragging = e.NewValue;
break;
case ApplicationName.PuTTY:
ConfigurationManager.Current.IsPuTTYWindowDragging = e.NewValue;
break;
case ApplicationName.TigerVNC:
ConfigurationManager.Current.IsTigerVNCWindowDragging = e.NewValue;
break;
case ApplicationName.WebConsole:
ConfigurationManager.Current.IsWebConsoleWindowDragging = e.NewValue;
break;
}
}
#endregion
#region Handle WndProc messages (handle window size events)
private HwndSource _hwndSource;
private const int WmExitSizeMove = 0x232;
private const int WmSysCommand = 0x0112;
private const int ScMaximize = 0xF030;
private const int ScRestore = 0xF120;
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
_hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
_hwndSource?.AddHook(HwndHook);
}
[DebuggerStepThrough]
private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Window size events
switch (msg)
{
// Handle window resize and move events
case WmExitSizeMove:
UpdateOnWindowResize();
break;
// Handle system commands (like maximize and restore)
case WmSysCommand:
switch (wParam.ToInt32())
{
// Window is maximized
case ScMaximize:
// Window is restored (back to normal size from maximized state)
case ScRestore:
UpdateOnWindowResize();
break;
}
break;
}
handled = false;
return IntPtr.Zero;
}
private void UpdateOnWindowResize()
{
// Find all TabablzControl
foreach (var tabablzControl in VisualTreeHelper.FindVisualChildren<TabablzControl>(this))
{
// Skip if no items
if (tabablzControl.Items.Count == 0)
continue;
foreach (var item in tabablzControl.Items.OfType<DragablzTabItem>())
{
if (item.View is RemoteDesktopControl control)
control.UpdateOnWindowResize();
}
}
}
#endregion
}