improved ability to determine if external proc has focus

This commit is contained in:
David Sparer
2019-09-01 12:30:11 -05:00
parent 74611e9db6
commit e9838960fa
15 changed files with 321 additions and 186 deletions

View File

@@ -12,7 +12,7 @@ namespace mRemoteNGTests.Connection.Protocol
{
public class IntegratedProgramTests
{
private readonly ExternalTool _extTool = new ExternalTool(new ConnectionInitiator())
private readonly ExternalTool _extTool = new ExternalTool(new ConnectionInitiator(new ProtocolFactory()))
{
DisplayName = "notepad",
FileName = @"%windir%\system32\notepad.exe",
@@ -50,7 +50,7 @@ namespace mRemoteNGTests.Connection.Protocol
private InterfaceControl BuildInterfaceControl(string extAppName, ProtocolBase sut)
{
var connectionWindow = new ConnectionWindow(new DockContent(), new ConnectionInitiator());
var connectionWindow = new ConnectionWindow(new DockContent(), new ConnectionInitiator(new ProtocolFactory()));
var connectionInfo = new ConnectionInfo {ExtApp = extAppName, Protocol = ProtocolType.IntApp};
return new InterfaceControl(connectionWindow, sut, connectionInfo);
}

View File

@@ -1,4 +1,5 @@
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using NUnit.Framework;
using mRemoteNG.UI.Forms;
@@ -16,7 +17,7 @@ namespace mRemoteNGTests.UI.Forms
[SetUp]
public void Setup()
{
_optionsForm = new FrmOptions(new ConnectionInitiator());
_optionsForm = new FrmOptions(new ConnectionInitiator(new ProtocolFactory()));
_optionsForm.Show();
}

View File

@@ -1,5 +1,6 @@
using System.Threading;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.UI.Window;
using NUnit.Framework;
using WeifenLuo.WinFormsUI.Docking;
@@ -14,7 +15,7 @@ namespace mRemoteNGTests.UI.Window
[SetUp]
public void Setup()
{
_connectionTreeWindow = new ConnectionTreeWindow(new DockContent(), new ConnectionInitiator());
_connectionTreeWindow = new ConnectionTreeWindow(new DockContent(), new ConnectionInitiator(new ProtocolFactory()));
}
[TearDown]

View File

@@ -16,12 +16,14 @@ namespace mRemoteNG.Connection
{
public class ConnectionInitiator : IConnectionInitiator
{
private readonly ProtocolFactory _protocolFactory;
private readonly List<ProtocolBase> _activeConnections = new List<ProtocolBase>();
public IEnumerable<ProtocolBase> ActiveConnections => _activeConnections;
public ConnectionInitiator()
public ConnectionInitiator(ProtocolFactory protocolFactory)
{
_protocolFactory = protocolFactory;
}
public bool SwitchToOpenConnection(ConnectionInfo connectionInfo)
@@ -35,6 +37,8 @@ namespace mRemoteNG.Connection
return true;
}
public void OpenConnection(
ContainerInfo containerInfo,
ConnectionInfo.Force force = ConnectionInfo.Force.None,
@@ -77,8 +81,7 @@ namespace mRemoteNG.Connection
return;
}
var protocolFactory = new ProtocolFactory();
var newProtocol = protocolFactory.CreateProtocol(connectionInfo);
var newProtocol = _protocolFactory.CreateProtocol(connectionInfo);
var connectionPanel = SetConnectionPanel(connectionInfo, force);
if (string.IsNullOrEmpty(connectionPanel)) return;
@@ -96,6 +99,7 @@ namespace mRemoteNG.Connection
return;
}
OnConnectionStarting(newProtocol.InterfaceControl.Info, newProtocol);
if (newProtocol.Connect() == false)
{
newProtocol.Close();
@@ -225,11 +229,11 @@ namespace mRemoteNG.Connection
}
Runtime.MessageCollector.AddMessage(msgClass,
string.Format(
Language.strProtocolEventDisconnected,
disconnectedMessage,
prot.InterfaceControl.Info.Hostname,
prot.InterfaceControl.Info.Protocol.ToString()));
string.Format(
Language.strProtocolEventDisconnected,
disconnectedMessage,
prot.InterfaceControl.Info.Hostname,
prot.InterfaceControl.Info.Protocol.ToString()));
}
catch (Exception ex)
{
@@ -271,7 +275,7 @@ namespace mRemoteNG.Connection
}
}
private static void Prot_Event_Connected(object sender)
private void Prot_Event_Connected(object sender)
{
var prot = (ProtocolBase)sender;
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strConnectionEventConnected,
@@ -304,5 +308,11 @@ namespace mRemoteNG.Connection
}
#endregion
public event EventHandler<ConnectionStartingEvent> ConnectionStarting;
protected virtual void OnConnectionStarting(ConnectionInfo connectionInfo, ProtocolBase protocolBase)
{
ConnectionStarting?.Invoke(this, new ConnectionStartingEvent(connectionInfo, protocolBase));
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using mRemoteNG.Connection.Protocol;
namespace mRemoteNG.Connection
{
[Serializable]
public class ConnectionStartingEvent : EventArgs
{
public ConnectionInfo ConnectionInfo { get; }
public ProtocolBase Protocol { get; }
public ConnectionStartingEvent(ConnectionInfo connectionInfo, ProtocolBase protocol)
{
ConnectionInfo = connectionInfo;
Protocol = protocol;
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Container;
using mRemoteNG.UI.Window;
@@ -20,5 +21,7 @@ namespace mRemoteNG.Connection
ConnectionWindow conForm = null);
bool SwitchToOpenConnection(ConnectionInfo connectionInfo);
event EventHandler<ConnectionStartingEvent> ConnectionStarting;
}
}

View File

@@ -5,10 +5,11 @@ using mRemoteNG.Messages;
namespace mRemoteNG.Connection.Protocol
{
public class ExternalProcessProtocolBase : ProtocolBase
public abstract class ExternalProcessProtocolBase : ProtocolBase, IFocusable
{
private IntPtr _winEventHook;
private NativeMethods.WinEventDelegate _setForegroundDelegate;
private bool _hasFocus;
public override bool IsExternalProcess { get; } = true;
@@ -16,6 +17,26 @@ namespace mRemoteNG.Connection.Protocol
protected IntPtr ProcessHandle { get; set; }
public bool HasFocus
{
get => _hasFocus;
private set
{
if (_hasFocus == value)
return;
_hasFocus = value;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg,
string.Format("External protocol window set to {0}. name:'{1}', protocol:'{2}', pid:{3}, hwnd:{4}",
_hasFocus ? "foreground" : "background",
InterfaceControl.Info.Name,
InterfaceControl.Info.Protocol,
ProtocolProcess.Id,
ProcessHandle));
OnFocusChanged();
}
}
public int ThreadId => (int)NativeMethods.GetWindowThreadProcessId(ProcessHandle, IntPtr.Zero);
@@ -27,7 +48,7 @@ namespace mRemoteNG.Connection.Protocol
NativeMethods.EVENT_SYSTEM_FOREGROUND,
IntPtr.Zero,
_setForegroundDelegate,
Convert.ToUInt32(ProtocolProcess.Id),
/*Convert.ToUInt32(ProtocolProcess.Id)*/0,
0,
NativeMethods.WINEVENT_OUTOFCONTEXT);
@@ -63,16 +84,15 @@ namespace mRemoteNG.Connection.Protocol
var setForegroundSuccessful = NativeMethods.SetForegroundWindow(ProcessHandle);
var logMsg = setForegroundSuccessful
? "External protocol window set to foreground. "
: "Failed to set external protocol window to foreground. ";
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg,
logMsg +
$"name:'{InterfaceControl.Info.Name}', " +
$"protocol:'{InterfaceControl.Info.Protocol}', " +
$"pid:{ProtocolProcess.Id}, " +
$"hwnd:{ProcessHandle}");
if (!setForegroundSuccessful)
{
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg,
"Failed to set external protocol window to foreground. " +
$"name:'{InterfaceControl.Info.Name}', " +
$"protocol:'{InterfaceControl.Info.Protocol}', " +
$"pid:{ProtocolProcess.Id}, " +
$"hwnd:{ProcessHandle}");
}
}
/// <summary>
@@ -88,14 +108,13 @@ namespace mRemoteNG.Connection.Protocol
/// <param name="dwmsEventTime"></param>
void OnWinEventSetForeground(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (hwnd != ProtocolProcess.MainWindowHandle)
return;
HasFocus = hwnd == ProcessHandle;
}
//Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg,
// "Exernal protocol window set to foreground. " +
// $"protocol:{InterfaceControl.Info.Protocol} " +
// $"pid:{ProtocolProcess.Id}, " +
// $"hwnd:{ProtocolProcess.MainWindowHandle}");
public event EventHandler FocusChanged;
protected virtual void OnFocusChanged()
{
FocusChanged?.Invoke(this, EventArgs.Empty);
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace mRemoteNG.Connection.Protocol
{
public interface IFocusable
{
bool HasFocus { get; }
void Focus();
event EventHandler FocusChanged;
}
}

View File

@@ -341,8 +341,7 @@ namespace mRemoteNG.Connection.Protocol
{
if (!disposing) return;
if(tmrReconnect != null)
tmrReconnect.Dispose();
tmrReconnect?.Dispose();
}
public void Dispose()

View File

@@ -1,81 +0,0 @@
using System;
using mRemoteNG.App;
using mRemoteNG.Messages;
using System.Windows.Forms;
namespace mRemoteNG.UI.FocusHelpers
{
public class ExternalProcessAltTabFocusHelper : IDisposable
{
private readonly SystemKeyboardHook _keyboardHook;
private bool _currentlyFixingAltTab;
/// <summary>
/// TRUE if any part of mrng has focus - the main window or child processes
/// </summary>
public bool MrngFocused { get; set; }
public bool ChildProcessHeldLastFocus { get; set; }
public Action FocusMainWindowAction { get; }
public Action FocusConnectionAction { get; }
public ExternalProcessAltTabFocusHelper(Action focusMainWindowAction, Action focusConnectionAction)
{
FocusMainWindowAction = focusMainWindowAction;
FocusConnectionAction = focusConnectionAction;
_keyboardHook = new SystemKeyboardHook(KeyboardHookCallback);
}
public int KeyboardHookCallback(int msg, NativeMethods.KBDLLHOOKSTRUCT kbd)
{
var key = (Keys)kbd.vkCode;
if (key.HasFlag(Keys.Tab) && kbd.flags.HasFlag(NativeMethods.KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN))
{
if (msg == NativeMethods.WM_SYSKEYDOWN || msg == NativeMethods.WM_KEYDOWN)
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"ALT-TAB PRESSED (CHILDPROC_FOCUSED={ChildProcessHeldLastFocus}, MRNG_FOCUSED={MrngFocused}, CURR_FIXING={_currentlyFixingAltTab})");
if (ChildProcessHeldLastFocus && MrngFocused && !_currentlyFixingAltTab)
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "FIXING ALT-TAB FOR EXTAPP");
_currentlyFixingAltTab = true;
// simulate an extra TAB key press. This skips focus of the mrng main window.
NativeMethods.keybd_event((byte)Keys.Tab, 0, (uint)NativeMethods.KEYEVENTF.KEYUP, 0);
NativeMethods.keybd_event((byte)Keys.Tab, 0, 0, 0);
// WndProc will never get an event when we switch from a child proc to a completely different program since the main mrng window never had focus to begin with.
// Assume mrng as a whole will lose focus, even though the user could choose to retain focus on us. When Alt-tab completes, the mrng main window will
// receive the focus event and we will handle the child process focusing as necessary.
MrngFocused = false;
_currentlyFixingAltTab = false;
}
}
}
// alt + right-shift
if (key.HasFlag(Keys.RShiftKey) && kbd.flags.HasFlag(NativeMethods.KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN))
{
if (msg != NativeMethods.WM_SYSKEYUP && msg != NativeMethods.WM_KEYUP)
return 0;
if (!MrngFocused)
return 0;
if (ChildProcessHeldLastFocus)
{
FocusMainWindowAction();
return 1;
}
FocusConnectionAction();
return 1;
}
return 0;
}
public void Dispose()
{
_keyboardHook?.Dispose();
}
}
}

View File

@@ -0,0 +1,199 @@
using System;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Messages;
using mRemoteNG.UI.Tabs;
namespace mRemoteNG.UI.FocusHelpers
{
public class ExternalProcessFocusHelper : IDisposable
{
private readonly IntPtr _mainWindowHandle;
private int _extFocusCount;
private readonly SystemKeyboardHook _keyboardHook;
private bool _currentlyFixingAltTab;
private bool _childProcessHeldLastFocus;
private bool _mainWindowFocused;
private bool _connectionReleasingFocus;
/// <summary>
/// TRUE if any part of mrng has focus - the main window or child processes
/// </summary>
public bool MrngFocused => MainWindowFocused || ChildProcessFocused;
public bool FixingMainWindowFocus { get; private set; }
public bool MainWindowFocused
{
get => _mainWindowFocused;
set
{
if (_mainWindowFocused == value)
return;
_mainWindowFocused = value;
// main window is receiving focus
if (ChildProcessHeldLastFocus && _mainWindowFocused && !_connectionReleasingFocus)
ActivateConnection();
}
}
public bool ChildProcessFocused => _extFocusCount > 0;
public bool ChildProcessHeldLastFocus
{
get => _childProcessHeldLastFocus;
private set
{
_childProcessHeldLastFocus = value;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"_childProcessHeldLastFocus={_childProcessHeldLastFocus}");
}
}
public ExternalProcessFocusHelper(
IConnectionInitiator connectionInitiator,
IntPtr mainWindowHandle)
{
connectionInitiator.ConnectionStarting += ConnectionInitiatorOnConnectionStarting;
_mainWindowHandle = mainWindowHandle;
_keyboardHook = new SystemKeyboardHook(KeyboardHookCallback);
}
private void ConnectionInitiatorOnConnectionStarting(object sender, ConnectionStartingEvent e)
{
if (!(e.Protocol is ExternalProcessProtocolBase extProc))
return;
extProc.FocusChanged += ExtProcOnFocusChanged;
extProc.Disconnected += ProtocolOnDisconnected;
}
private void ExtProcOnFocusChanged(object sender, EventArgs e)
{
if (!(sender is IFocusable extProc))
return;
if (extProc.HasFocus)
ExternalWindowFocused();
else
ExternalWindowDefocused();
}
private void ProtocolOnDisconnected(object sender, string disconnectedmessage, int? reasoncode)
{
if (!(sender is ExternalProcessProtocolBase prot))
return;
prot.FocusChanged -= ExtProcOnFocusChanged;
prot.Disconnected -= ProtocolOnDisconnected;
}
public void ActivateConnection()
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Performing special connection focus logic");
//var cw = pnlDock.ActiveDocument as ConnectionWindow;
//var dp = cw?.ActiveControl as DockPane;
//if (!(dp?.ActiveContent is ConnectionTab tab))
//{
// Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Active content is not a tab. We won't focus a specific connection.");
// return;
//}
//var ifc = InterfaceControl.FindInterfaceControl(tab);
var tab = TabHelper.Instance.CurrentTab;
if (tab == null)
return;
var ifc = tab.InterfaceControl;
if (ifc == null)
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg,
$"InterfaceControl for tab '{tab.Name}' was not found. We won't focus that connection.");
return;
}
//FixingMainWindowFocus = true;
//_focusMainWindowAction();
//FixingMainWindowFocus = false;
ifc.Protocol.Focus();
//var conFormWindow = ifc.FindForm();
//((ConnectionTab) conFormWindow)?.RefreshInterfaceController();
}
public int KeyboardHookCallback(int msg, NativeMethods.KBDLLHOOKSTRUCT kbd)
{
var key = (Keys)kbd.vkCode;
// Alt + Tab
if (key.HasFlag(Keys.Tab) && kbd.flags.HasFlag(NativeMethods.KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN))
{
if (msg == NativeMethods.WM_SYSKEYDOWN || msg == NativeMethods.WM_KEYDOWN)
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"ALT-TAB PRESSED (CHILDPROC_FOCUSED={ChildProcessFocused}, CHILDPROC_LAST_FOCUSED={ChildProcessHeldLastFocus}, MRNG_FOCUSED={MrngFocused}, CURR_FIXING={_currentlyFixingAltTab})");
if (ChildProcessHeldLastFocus && MrngFocused && !_currentlyFixingAltTab)
{
FixExternalAppAltTab();
}
}
}
// Alt + `
if (key.HasFlag(Keys.Oem3) && kbd.flags.HasFlag(NativeMethods.KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN))
{
if (msg != NativeMethods.WM_SYSKEYUP && msg != NativeMethods.WM_KEYUP)
return 0;
if (ChildProcessFocused)
{
_connectionReleasingFocus = true;
var focused = NativeMethods.SetForegroundWindow(_mainWindowHandle);
_connectionReleasingFocus = false;
return 1;
}
if (!MainWindowFocused)
return 0;
ActivateConnection();
return 1;
}
return 0;
}
private void FixExternalAppAltTab()
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "FIXING ALT-TAB FOR EXTAPP");
_currentlyFixingAltTab = true;
// simulate an extra TAB key press. This skips focus of the mrng main window.
NativeMethods.keybd_event((byte) Keys.Tab, 0, (uint) NativeMethods.KEYEVENTF.KEYUP, 0);
NativeMethods.keybd_event((byte) Keys.Tab, 0, 0, 0);
// WndProc will never get an event when we switch from a child proc to a completely different program since the main mrng window never had focus to begin with.
// Assume mrng as a whole will lose focus, even though the user could choose to retain focus on us. When Alt-tab completes, the mrng main window will
// receive the focus event and we will handle the child process focusing as necessary.
MainWindowFocused = false;
_currentlyFixingAltTab = false;
}
public void Dispose()
{
_keyboardHook?.Dispose();
}
private void ExternalWindowFocused()
{
_extFocusCount++;
}
private void ExternalWindowDefocused()
{
_extFocusCount--;
ChildProcessHeldLastFocus = !MainWindowFocused && !ChildProcessFocused;
}
}
}

View File

@@ -53,8 +53,8 @@ namespace mRemoteNG.UI.Forms
private readonly IList<IMessageWriter> _messageWriters = new List<IMessageWriter>();
private readonly ThemeManager _themeManager;
private readonly FileBackupPruner _backupPruner = new FileBackupPruner();
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
private readonly ExternalProcessAltTabFocusHelper _altTabFocusHelper;
private readonly IConnectionInitiator _connectionInitiator;
private readonly ExternalProcessFocusHelper _focusHelper;
internal FullscreenHandler Fullscreen { get; set; }
@@ -73,7 +73,11 @@ namespace mRemoteNG.UI.Forms
ApplyTheme();
_screenSystemMenu = new ScreenSelectionSystemMenu(this);
_altTabFocusHelper = new ExternalProcessAltTabFocusHelper(() => Focus(), ActivateConnection);
var protocolFactory = new ProtocolFactory();
_connectionInitiator = new ConnectionInitiator(protocolFactory);
Debug.Assert(IsHandleCreated, "Expected main window handle to be created by now");
_focusHelper = new ExternalProcessFocusHelper(_connectionInitiator, Handle);
}
#region Properties
@@ -218,12 +222,12 @@ namespace mRemoteNG.UI.Forms
private void OnTabClicked(object sender, EventArgs e)
{
ActivateConnection();
_focusHelper.ActivateConnection();
}
private void OnActiveConnectionTabChanged(object sender, EventArgs e)
{
ActivateConnection();
_focusHelper.ActivateConnection();
}
private void ApplyLanguage()
@@ -383,7 +387,7 @@ namespace mRemoteNG.UI.Forms
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
_altTabFocusHelper?.Dispose();
_focusHelper?.Dispose();
if (!(Runtime.WindowList == null || Runtime.WindowList.Count == 0))
{
@@ -483,7 +487,7 @@ namespace mRemoteNG.UI.Forms
_inSizeMove = false;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "End app window move/resize");
// This handles activations from clicks that started a size/move operation
ActivateConnection();
_focusHelper.ActivateConnection();
}
@@ -510,28 +514,19 @@ namespace mRemoteNG.UI.Forms
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"Clicked control: {controlThatWasClicked2}");
break;
case NativeMethods.WM_ACTIVATEAPP:
if (_focusHelper.FixingMainWindowFocus)
break;
if (m.WParam.ToInt32() == 0) // mRemoteNG is being deactivated
{
var threadWhichIsActivating = m.LParam.ToInt32();
_altTabFocusHelper.ChildProcessHeldLastFocus = _connectionInitiator
.ActiveConnections
.OfType<ExternalProcessProtocolBase>()
.Any(proc => proc.ThreadId == threadWhichIsActivating);
_inMouseActivate = false;
_altTabFocusHelper.MrngFocused = _altTabFocusHelper.ChildProcessHeldLastFocus;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window lost focus (_childProcessHeldLastFocus={_altTabFocusHelper.ChildProcessHeldLastFocus})");
_focusHelper.MainWindowFocused = false;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window lost focus (_childProcessHeldLastFocus={_focusHelper.ChildProcessHeldLastFocus})");
break;
}
if (_altTabFocusHelper.ChildProcessHeldLastFocus && !_altTabFocusHelper.MrngFocused)
{
ActivateConnection();
}
_altTabFocusHelper.ChildProcessHeldLastFocus = false;
_altTabFocusHelper.MrngFocused = true;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window received focus (_childProcessHeldLastFocus={_altTabFocusHelper.ChildProcessHeldLastFocus})");
_focusHelper.MainWindowFocused = true;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window received focus (_childProcessHeldLastFocus={_focusHelper.ChildProcessHeldLastFocus})");
//var candidateTabToFocus = FromChildHandle(NativeMethods.WindowFromPoint(MousePosition))
// ?? GetChildAtPoint(MousePosition);
@@ -583,14 +578,10 @@ namespace mRemoteNG.UI.Forms
break;
case NativeMethods.WM_NCACTIVATE:
//if (m.WParam.ToInt32() == 1)
// break;
//// Never allow the mRemoteNG window to display itself as inactive. By doing this,
//// we ensure focus events can propagate to child connection windows
NativeMethods.DefWindowProc(Handle, Convert.ToUInt32(m.Msg), (IntPtr)1, m.LParam);
m.Result = (IntPtr)1;
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Fixed main app NCACTIVATE");
return;
case NativeMethods.WM_WINDOWPOSCHANGED:
// Ignore this message if the window wasn't activated
@@ -603,7 +594,7 @@ namespace mRemoteNG.UI.Forms
if (!_inMouseActivate && !_inSizeMove)
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "WM_WINDOWPOSCHANGED DONE");
ActivateConnection();
_focusHelper.ActivateConnection();
}
}
@@ -643,38 +634,9 @@ namespace mRemoteNG.UI.Forms
clientMousePosition.Y = temp_wHigh;
}
private void ActivateConnection()
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Performing special connection focus logic");
//var cw = pnlDock.ActiveDocument as ConnectionWindow;
//var dp = cw?.ActiveControl as DockPane;
//if (!(dp?.ActiveContent is ConnectionTab tab))
//{
// Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Active content is not a tab. We won't focus a specific connection.");
// return;
//}
//var ifc = InterfaceControl.FindInterfaceControl(tab);
var tab = TabHelper.Instance.CurrentTab;
if (tab == null)
return;
var ifc = tab.InterfaceControl;
if (ifc == null)
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"InterfaceControl for tab '{tab.Name}' was not found. We won't focus that connection.");
return;
}
ifc.Protocol.Focus();
var conFormWindow = ifc.FindForm();
((ConnectionTab)conFormWindow)?.RefreshInterfaceController();
}
private void pnlDock_ActiveDocumentChanged(object sender, EventArgs e)
{
//ActivateConnection();
//_focusHelper.ActivateConnection();
}
internal void UpdateWindowTitle()

View File

@@ -48,16 +48,7 @@ namespace mRemoteNG.UI.Tabs
private void ConnectionTab_GotFocus(object sender, EventArgs e)
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"Tab received focused: '{TabText}'");
//TabHelper.Instance.CurrentTab = this;
//if (TabHelper.Instance.FocusConnection)
//{
// Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"Focusing connection in tab: '{TabText}'");
// InterfaceControl?.Protocol.Focus();
//}
//else
//{
// Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Dont focus connection");
//}
TabHelper.Instance.CurrentTab = this;
}
protected override void OnFormClosing(FormClosingEventArgs e)

View File

@@ -134,7 +134,7 @@ namespace mRemoteNG.UI.Window
var conTab = new ConnectionTab
{
Tag = connectionInfo,
Tag = connectionInfo, // BUG: the Tag gets set to an InterfaceControl later on. Is this right?
DockAreas = DockAreas.Document | DockAreas.Float,
Icon = ConnectionIcon.FromString(connectionInfo.Icon),
TabText = titleText,

View File

@@ -252,6 +252,7 @@
<Compile Include="App\ProgramRoot.cs" />
<Compile Include="Connection\ConnectionInitiator.cs" />
<Compile Include="Connection\ConnectionsService.cs" />
<Compile Include="Connection\ConnectionStartingEvent.cs" />
<Compile Include="Connection\Converter.cs" />
<Compile Include="Connection\DefaultConnectionInfo.cs" />
<Compile Include="Connection\DefaultConnectionInheritance.cs" />
@@ -260,6 +261,7 @@
<Compile Include="Connection\IHasParent.cs" />
<Compile Include="Connection\Protocol\ExternalProcessProtocolBase.cs" />
<Compile Include="Connection\Protocol\Http\Connection.Protocol.HTTPS.CertEvent.cs" />
<Compile Include="Connection\Protocol\IFocusable.cs" />
<Compile Include="Connection\Protocol\ProtocolFactory.cs" />
<Compile Include="Connection\Protocol\RDP\AuthenticationLevel.cs" />
<Compile Include="Connection\Protocol\RDP\AzureLoadBalanceInfoEncoder.cs" />
@@ -538,7 +540,7 @@
</Compile>
<Compile Include="UI\DialogFactory.cs" />
<Compile Include="UI\DisplayProperties.cs" />
<Compile Include="UI\FocusHelpers\ExternalProcessAltTabFocusHelper.cs" />
<Compile Include="UI\FocusHelpers\ExternalProcessFocusHelper.cs" />
<Compile Include="UI\FontOverrider.cs" />
<Compile Include="UI\FormExtensions.cs" />
<Compile Include="UI\Forms\FrmOptions.cs">