Skip to content

Commit

Permalink
Feature: Set focus to embedded window when application got focus (#1515)
Browse files Browse the repository at this point in the history
* Feature: Set focus to embedded window when application got focus

* Chore: Code cleanup

* Feature: Set focus to embedded window when application got focus

* Chore: Code cleanup

* Feature: Set focus to embedded window when application got focus

* Docs: Add #1515 to changelog

* Fix: TextBox focus in MainWindow when ContextMenu is opened

* Fix: Don't focus embedded window when ContextMenu is opened or TextBox is focused
  • Loading branch information
BornToBeRoot authored Aug 27, 2022
1 parent c3dbc06 commit da22d17
Show file tree
Hide file tree
Showing 19 changed files with 377 additions and 115 deletions.
6 changes: 6 additions & 0 deletions Source/NETworkManager.Utilities/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public enum WM : uint
#endregion

#region Pinvoke/Win32 Methods
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", SetLastError = true)]
public static extern long SetParent(IntPtr hWndChild, IntPtr hWndParent);

Expand Down Expand Up @@ -72,6 +75,9 @@ public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
#endregion
}
}
2 changes: 1 addition & 1 deletion Source/NETworkManager/Controls/DragablzTabHostWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:wpfHelpers="clr-namespace:NETworkManager.Utilities.WPF;assembly=NETworkManager.Utilities.WPF"
mc:Ignorable="d"
Style="{DynamicResource DefaultWindow}" MinWidth="800" Width="1024" Height="768" MinHeight="600" TitleAlignment="Left"
Style="{DynamicResource DefaultWindow}" MinWidth="800" Width="1024" Height="768" MinHeight="600" TitleAlignment="Left" Activated="MetroWindow_Activated"
d:DataContext="{d:DesignInstance controls:DragablzTabHostWindow}">
<mah:MetroWindow.WindowButtonCommands>
<mah:WindowButtonCommands Template="{DynamicResource MahApps.Templates.WindowButtonCommands.Win10}" />
Expand Down
25 changes: 25 additions & 0 deletions Source/NETworkManager/Controls/DragablzTabHostWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,34 @@ private void WebConsole_RefreshAction(object view)
#endregion
#endregion

private async void FocusEmbeddedWindow()
{
// Delay the focus to prevent blocking the ui
do
{
await Task.Delay(250);
} while (Mouse.LeftButton == MouseButtonState.Pressed);

// Switch by name
switch (ApplicationName)
{
case ApplicationName.PowerShell:
((PowerShellControl)((DragablzTabItem)TabsContainer?.SelectedItem)?.View)?.FocusEmbeddedWindow();
break;
case ApplicationName.PuTTY:
((PuTTYControl)((DragablzTabItem)TabsContainer?.SelectedItem)?.View)?.FocusEmbeddedWindow();
break;
}
}

#region Events
private void SettingsManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
{

}
private void MetroWindow_Activated(object sender, EventArgs e)
{
FocusEmbeddedWindow();
}
#endregion
}
Expand Down
28 changes: 12 additions & 16 deletions Source/NETworkManager/Controls/PowerShellControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
private Process _process;
private IntPtr _appWin;

private readonly DispatcherTimer _resizeTimer = new DispatcherTimer();

private bool _isConnected;
public bool IsConnected
{
Expand Down Expand Up @@ -78,9 +76,6 @@ public PowerShellControl(PowerShellSessionInfo info)

_sessionInfo = info;

_resizeTimer.Tick += ResizeTimer_Tick;
_resizeTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);

Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
}

Expand Down Expand Up @@ -157,7 +152,7 @@ private async Task Connect()
if (IntPtr.Zero != _appWin)
break;

await Task.Delay(50);
await Task.Delay(100);
}
}

Expand All @@ -175,7 +170,9 @@ private async Task Connect()

IsConnected = true;

// Resize embedded application & refresh
// Resize embedded application & refresh
// Requires a short delay because it's not applied immediately
await Task.Delay(250);
ResizeEmbeddedWindow();
}
}
Expand Down Expand Up @@ -209,6 +206,12 @@ private void Process_Exited(object sender, EventArgs e)
IsConnected = false;
}

public void FocusEmbeddedWindow()
{
if (IsConnected)
NativeMethods.SetForegroundWindow(_process.MainWindowHandle);
}

public void ResizeEmbeddedWindow()
{
if (IsConnected)
Expand All @@ -217,7 +220,7 @@ public void ResizeEmbeddedWindow()

public void Disconnect()
{
if (_process != null && !_process.HasExited)
if (IsConnected)
_process.Kill();
}

Expand All @@ -240,16 +243,9 @@ public void CloseTab()
#region Events
private void WindowGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (_process != null)
if (IsConnected)
ResizeEmbeddedWindow();
}

private void ResizeTimer_Tick(object sender, EventArgs e)
{
_resizeTimer.Stop();

ResizeEmbeddedWindow();
}
#endregion
}
}
30 changes: 12 additions & 18 deletions Source/NETworkManager/Controls/PuTTYControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
private Process _process;
private IntPtr _appWin;

private readonly DispatcherTimer _resizeTimer = new DispatcherTimer();

private bool _isConnected;
public bool IsConnected
{
Expand Down Expand Up @@ -79,9 +77,6 @@ public PuTTYControl(PuTTYSessionInfo info)

_sessionInfo = info;

_resizeTimer.Tick += ResizeTimer_Tick;
_resizeTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);

Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
}

Expand Down Expand Up @@ -160,15 +155,15 @@ private async Task Connect()
if (IntPtr.Zero != _appWin)
break;

await Task.Delay(50);
await Task.Delay(100);
}
}

if (_appWin != IntPtr.Zero)
{
while (!_process.HasExited && _process.MainWindowTitle.IndexOf(" - PuTTY", StringComparison.Ordinal) == -1)
{
await Task.Delay(50);
await Task.Delay(100);

_process.Refresh();
}
Expand All @@ -188,8 +183,8 @@ private async Task Connect()
IsConnected = true;

// Resize embedded application & refresh
// Requires a short delay because it'S not applied immediately
await Task.Delay(500);
// Requires a short delay because it's not applied immediately
await Task.Delay(250);

ResizeEmbeddedWindow();
}
Expand Down Expand Up @@ -225,6 +220,12 @@ private void Process_Exited(object sender, EventArgs e)
IsConnected = false;
}

public void FocusEmbeddedWindow()
{
if (IsConnected)
NativeMethods.SetForegroundWindow(_process.MainWindowHandle);
}

public void ResizeEmbeddedWindow()
{
if (IsConnected)
Expand All @@ -233,7 +234,7 @@ public void ResizeEmbeddedWindow()

public void Disconnect()
{
if (_process != null && !_process.HasExited)
if (IsConnected)
_process.Kill();
}

Expand Down Expand Up @@ -262,16 +263,9 @@ public void CloseTab()
#region Events
private void WindowGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (_process != null)
if (IsConnected)
ResizeEmbeddedWindow();
}

private void ResizeTimer_Tick(object sender, EventArgs e)
{
_resizeTimer.Stop();

ResizeEmbeddedWindow();
}
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ private async Task InitiateReconnection()

do // Prevent to many requests
{
await Task.Delay(500);
await Task.Delay(250);

} while (Mouse.LeftButton == MouseButtonState.Pressed);

Expand Down
40 changes: 9 additions & 31 deletions Source/NETworkManager/Controls/TightVNCControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
private Process _process;
private IntPtr _appWin;

private readonly DispatcherTimer _resizeTimer = new DispatcherTimer();

private bool _isConnected;
public bool IsConnected
{
Expand Down Expand Up @@ -78,9 +76,6 @@ public TigerVNCControl(TigerVNCSessionInfo info)

_sessionInfo = info;

_resizeTimer.Tick += ResizeTimer_Tick;
_resizeTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);

Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
}

Expand Down Expand Up @@ -145,18 +140,6 @@ private async Task Connect()

while ((DateTime.Now - startTime).TotalSeconds < 10)
{
// Fix for netcore3.1 https://stackoverflow.com/questions/60342879/process-mainwindowhandle-is-non-zero-in-net-framework-but-zero-in-net-core-unl
/*
try
{
_process = Process.GetProcessById(_process.Id);
}
catch
{
break; // Process has exited
}
*/

_process.Refresh();

if (_process.HasExited)
Expand All @@ -167,15 +150,15 @@ private async Task Connect()
if (IntPtr.Zero != _appWin)
break;

await Task.Delay(50);
await Task.Delay(100);
}
}

if (_appWin != IntPtr.Zero)
{
while (!_process.HasExited && _process.MainWindowTitle.IndexOf(" - TigerVNC", StringComparison.Ordinal) == -1)
{
await Task.Delay(50);
await Task.Delay(100);

_process.Refresh();
}
Expand All @@ -197,7 +180,9 @@ private async Task Connect()

IsConnected = true;

// Resize embedded application & refresh
// Resize embedded application & refresh
// Requires a short delay because it's not applied immediately
await Task.Delay(250);
ResizeEmbeddedWindow();
}
}
Expand All @@ -212,10 +197,10 @@ private async Task Connect()
if (!_closing)
{
var settings = AppearanceManager.MetroDialog;
settings.AffirmativeButtonText = NETworkManager.Localization.Resources.Strings.OK;
settings.AffirmativeButtonText = Localization.Resources.Strings.OK;
ConfigurationManager.Current.FixAirspace = true;

await _dialogCoordinator.ShowMessageAsync(this, NETworkManager.Localization.Resources.Strings.Error,
await _dialogCoordinator.ShowMessageAsync(this, Localization.Resources.Strings.Error,
ex.Message, MessageDialogStyle.Affirmative, settings);

ConfigurationManager.Current.FixAirspace = false;
Expand All @@ -239,7 +224,7 @@ private void ResizeEmbeddedWindow()

public void Disconnect()
{
if (_process != null && !_process.HasExited)
if (IsConnected)
_process.Kill();
}

Expand All @@ -262,16 +247,9 @@ public void CloseTab()
#region Events
private void TigerVNCGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (_process != null)
if (IsConnected)
ResizeEmbeddedWindow();
}

private void ResizeTimer_Tick(object sender, EventArgs e)
{
_resizeTimer.Stop();

ResizeEmbeddedWindow();
}
#endregion
}
}
12 changes: 6 additions & 6 deletions Source/NETworkManager/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
xmlns:resources="clr-namespace:NETworkManager.Properties"
xmlns:networkManager="clr-namespace:NETworkManager"
mc:Ignorable="d"
Style="{DynamicResource DefaultWindow}" MinWidth="800" Width="1024" Height="768" MinHeight="600" SaveWindowPosition="True" TitleAlignment="Left" Closing="MetroWindowMain_Closing" StateChanged="MetroWindowMain_StateChanged"
Style="{DynamicResource DefaultWindow}" MinWidth="800" Width="1024" Height="768" MinHeight="600" Activated="MetroMainWindow_Activated" SaveWindowPosition="True" TitleAlignment="Left" Closing="MetroWindowMain_Closing" StateChanged="MetroWindowMain_StateChanged"
d:DataContext="{d:DesignInstance networkManager:MainWindow}">
<!-- MetroDialogStyles.xaml must be adjusted if MinWidth/MinHeight is changed -->
<Window.Resources>
Expand Down Expand Up @@ -103,7 +103,7 @@
<TextBlock Text="{x:Static localization:Strings.UnlockProfile}" Style="{StaticResource LinkTextBlock}" Margin="5,0" />
</StackPanel>
</Button>
<ComboBox ItemsSource="{Binding ProfileFiles}" SelectedItem="{Binding SelectedProfileFile, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="{DynamicResource MahApps.Brushes.Gray8}" BorderThickness="0" MinWidth="100" HorizontalAlignment="Left" Margin="0,0,10,0">
<ComboBox ItemsSource="{Binding ProfileFiles}" SelectedItem="{Binding SelectedProfileFile, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="{DynamicResource MahApps.Brushes.Gray8}" IsDropDownOpen="{Binding IsProfileFileDropDownOpened}" BorderThickness="0" MinWidth="100" HorizontalAlignment="Left" Margin="0,0,10,0">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
Expand Down Expand Up @@ -309,11 +309,11 @@
</Style>
</TextBox.Style>
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="GotKeyboardFocus">
<interactivity:InvokeCommandAction Command="{Binding TextBoxSearchGotKeyboardFocusCommand}" />
<interactivity:EventTrigger EventName="GotFocus">
<interactivity:InvokeCommandAction Command="{Binding TextBoxSearchGotFocusCommand}" />
</interactivity:EventTrigger>
<interactivity:EventTrigger EventName="LostKeyboardFocus">
<interactivity:InvokeCommandAction Command="{Binding TextBoxSearchLostKeyboardFocusCommand}" />
<interactivity:EventTrigger EventName="LostFocus">
<interactivity:InvokeCommandAction Command="{Binding TextBoxSearchLostFocusCommand}" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</TextBox>
Expand Down
Loading

0 comments on commit da22d17

Please sign in to comment.