diff --git a/mRemoteV1/UI/FocusHelpers/ExternalProcessFocusHelper.cs b/mRemoteV1/UI/FocusHelpers/ExternalProcessFocusHelper.cs
index 3ea1614f..85cc9719 100644
--- a/mRemoteV1/UI/FocusHelpers/ExternalProcessFocusHelper.cs
+++ b/mRemoteV1/UI/FocusHelpers/ExternalProcessFocusHelper.cs
@@ -1,10 +1,12 @@
using System;
+using System.Runtime.InteropServices;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Messages;
using mRemoteNG.UI.Tabs;
+using Message = System.Windows.Forms.Message;
namespace mRemoteNG.UI.FocusHelpers
{
@@ -17,13 +19,14 @@ namespace mRemoteNG.UI.FocusHelpers
private bool _childProcessHeldLastFocus;
private bool _mainWindowFocused;
private bool _connectionReleasingFocus;
+ private bool _inSizeMove;
+ private bool _fixingMainWindowFocus;
///
/// TRUE if any part of mrng has focus - the main window or child processes
///
public bool MrngFocused => MainWindowFocused || ChildProcessFocused;
- public bool FixingMainWindowFocus { get; private set; }
public bool MainWindowFocused
{
@@ -81,7 +84,7 @@ namespace mRemoteNG.UI.FocusHelpers
ExternalWindowDefocused();
}
- private void ProtocolOnDisconnected(object sender, string disconnectedmessage, int? reasoncode)
+ private void ProtocolOnDisconnected(object sender, string disconnectedMessage, int? reasonCode)
{
if (!(sender is ExternalProcessProtocolBase prot))
return;
@@ -116,16 +119,16 @@ namespace mRemoteNG.UI.FocusHelpers
return;
}
- //FixingMainWindowFocus = true;
+ _fixingMainWindowFocus = true;
//_focusMainWindowAction();
- //FixingMainWindowFocus = false;
+ _fixingMainWindowFocus = false;
ifc.Protocol.Focus();
//var conFormWindow = ifc.FindForm();
//((ConnectionTab) conFormWindow)?.RefreshInterfaceController();
}
- public int KeyboardHookCallback(int msg, NativeMethods.KBDLLHOOKSTRUCT kbd)
+ private int KeyboardHookCallback(int msg, NativeMethods.KBDLLHOOKSTRUCT kbd)
{
var key = (Keys)kbd.vkCode;
// Alt + Tab
@@ -142,28 +145,37 @@ namespace mRemoteNG.UI.FocusHelpers
}
// 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 (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 (ChildProcessFocused)
+ // {
+ // _connectionReleasingFocus = true;
+ // var focused = NativeMethods.SetForegroundWindow(_mainWindowHandle);
+ // _connectionReleasingFocus = false;
+ // return 1;
+ // }
- if (!MainWindowFocused)
- return 0;
- ActivateConnection();
- return 1;
- }
+ // if (!MainWindowFocused)
+ // return 0;
+ // ActivateConnection();
+ // return 1;
+ //}
return 0;
}
+ private void ForceExtAppToGiveUpFocus()
+ {
+ if (!ChildProcessHeldLastFocus)
+ return;
+
+ Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Forcing extpp to give up focus.");
+ ChildProcessHeldLastFocus = false;
+ }
+
private void FixExternalAppAltTab()
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "FIXING ALT-TAB FOR EXTAPP");
@@ -188,6 +200,7 @@ namespace mRemoteNG.UI.FocusHelpers
private void ExternalWindowFocused()
{
_extFocusCount++;
+ ChildProcessHeldLastFocus = true;
}
private void ExternalWindowDefocused()
@@ -195,5 +208,86 @@ namespace mRemoteNG.UI.FocusHelpers
_extFocusCount--;
ChildProcessHeldLastFocus = !MainWindowFocused && !ChildProcessFocused;
}
+
+ ///
+ /// Give the a chance to
+ /// hook into a system window's WndProc message handler. Returns
+ /// true if an action has been taken which should override the
+ /// base windows own WndProc handling.
+ ///
+ ///
+ ///
+ /// Returns true if an action has been taken which should override the
+ /// base windows own WndProc handling.
+ ///
+ public bool HandleWndProc(ref Message m)
+ {
+ // ReSharper disable once SwitchStatementMissingSomeCases
+ switch (m.Msg)
+ {
+ case NativeMethods.WM_PARENTNOTIFY:
+ var notifyType = m.WParam.ToInt32();
+ // ignore non-click notify events
+ if (notifyType == NativeMethods.WM_CREATE || notifyType == NativeMethods.WM_DESTROY)
+ break;
+
+ Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Main window clicked");
+ // when the main window is clicked, assume the user wants the main window focused
+ ForceExtAppToGiveUpFocus();
+ break;
+ case NativeMethods.WM_ACTIVATEAPP:
+ if (_fixingMainWindowFocus)
+ break;
+
+ // main window is being deactivated
+ if (m.WParam.ToInt32() == 0)
+ {
+ MainWindowFocused = false;
+ Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window lost focus (_childProcessHeldLastFocus={ChildProcessHeldLastFocus})");
+ break;
+ }
+
+ MainWindowFocused = true;
+ Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window received focus (_childProcessHeldLastFocus={ChildProcessHeldLastFocus})");
+
+ break;
+ case NativeMethods.WM_NCACTIVATE:
+ // 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(_mainWindowHandle, Convert.ToUInt32(m.Msg), (IntPtr)1, m.LParam);
+ m.Result = (IntPtr)1;
+ return true;
+
+ // handle re-focusing connection when the main window moves or resizes
+ case NativeMethods.WM_ENTERSIZEMOVE:
+ _inSizeMove = true;
+ Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Begin app window move/resize");
+ break;
+ case NativeMethods.WM_EXITSIZEMOVE:
+ _inSizeMove = false;
+ Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "End app window move/resize");
+ // This handles activations from clicks that started a size/move operation
+ ActivateConnection();
+ break;
+ case NativeMethods.WM_WINDOWPOSCHANGED:
+ // Ignore this message if the window wasn't activated
+ if (!MainWindowFocused)
+ break;
+
+ var windowPos = (NativeMethods.WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(NativeMethods.WINDOWPOS));
+ if ((windowPos.flags & NativeMethods.SWP_NOACTIVATE) == 0)
+ {
+ if (!MainWindowFocused && !_inSizeMove)
+ {
+ Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "WM_WINDOWPOSCHANGED DONE");
+ ActivateConnection();
+ }
+ }
+
+ break;
+ }
+
+ return false;
+ }
}
}
diff --git a/mRemoteV1/UI/Forms/frmMain.Designer.cs b/mRemoteV1/UI/Forms/frmMain.Designer.cs
index de63b224..454aba97 100644
--- a/mRemoteV1/UI/Forms/frmMain.Designer.cs
+++ b/mRemoteV1/UI/Forms/frmMain.Designer.cs
@@ -205,8 +205,6 @@
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmMain_FormClosing);
this.Load += new System.EventHandler(this.frmMain_Load);
this.Shown += new System.EventHandler(this.frmMain_Shown);
- this.ResizeBegin += new System.EventHandler(this.frmMain_ResizeBegin);
- this.ResizeEnd += new System.EventHandler(this.frmMain_ResizeEnd);
this.Resize += new System.EventHandler(this.frmMain_Resize);
this.msMain.ResumeLayout(false);
this.msMain.PerformLayout();
diff --git a/mRemoteV1/UI/Forms/frmMain.cs b/mRemoteV1/UI/Forms/frmMain.cs
index 5e5c8a56..1b86f61e 100644
--- a/mRemoteV1/UI/Forms/frmMain.cs
+++ b/mRemoteV1/UI/Forms/frmMain.cs
@@ -8,11 +8,14 @@ using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Settings;
using mRemoteNG.Connection;
+using mRemoteNG.Connection.Protocol;
using mRemoteNG.Messages;
using mRemoteNG.Messages.MessageWriters;
using mRemoteNG.Themes;
using mRemoteNG.Tools;
+using mRemoteNG.UI.FocusHelpers;
using mRemoteNG.UI.Menu;
+using mRemoteNG.UI.Panels;
using mRemoteNG.UI.Tabs;
using mRemoteNG.UI.TaskDialog;
using mRemoteNG.UI.Window;
@@ -23,13 +26,8 @@ using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
-using mRemoteNG.Connection.Protocol;
-using mRemoteNG.UI.FocusHelpers;
-using mRemoteNG.UI.Panels;
using WeifenLuo.WinFormsUI.Docking;
using Message = System.Windows.Forms.Message;
@@ -42,8 +40,6 @@ namespace mRemoteNG.UI.Forms
public static FrmMain Default { get; } = new FrmMain();
private static ClipboardchangeEventHandler _clipboardChangedEvent;
- private bool _inSizeMove;
- private bool _inMouseActivate;
private IntPtr _fpChainedWindowHandle;
private bool _usingSqlServer;
private string _connectionsFileName;
@@ -457,13 +453,6 @@ namespace mRemoteNG.UI.Forms
#endregion
#region Window Overrides and DockPanel Stuff
-
- private void frmMain_ResizeBegin(object sender, EventArgs e)
- {
- _inSizeMove = true;
- Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Begin app window move/resize");
- }
-
private void frmMain_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
@@ -482,15 +471,6 @@ namespace mRemoteNG.UI.Forms
}
}
- private void frmMain_ResizeEnd(object sender, EventArgs e)
- {
- _inSizeMove = false;
- Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "End app window move/resize");
- // This handles activations from clicks that started a size/move operation
- _focusHelper.ActivateConnection();
- }
-
-
// Maybe after starting putty, remove its ability to show up in alt-tab?
// SetWindowLong(this.Handle, GWL_EXSTYLE, (GetWindowLong(this.Handle,GWL_EXSTYLE) | WS_EX_TOOLWINDOW) & ~WS_EX_APPWINDOW);
protected override void WndProc(ref Message m)
@@ -498,13 +478,13 @@ namespace mRemoteNG.UI.Forms
// Listen for and handle operating system messages
try
{
+ if (_focusHelper?.HandleWndProc(ref m) == true)
+ return;
+
// ReSharper disable once SwitchStatementMissingSomeCases
switch (m.Msg)
{
case NativeMethods.WM_MOUSEACTIVATE:
- _inMouseActivate = true;
- Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"_inMouseActivate = {_inMouseActivate}");
-
var controlThatWasClicked2 = FromChildHandle(NativeMethods.WindowFromPoint(MousePosition))
?? GetChildAtPoint(MousePosition);
@@ -512,29 +492,6 @@ namespace mRemoteNG.UI.Forms
break;
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
- {
- _inMouseActivate = false;
- _focusHelper.MainWindowFocused = false;
- Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window lost focus (_childProcessHeldLastFocus={_focusHelper.ChildProcessHeldLastFocus})");
- break;
- }
-
- _focusHelper.MainWindowFocused = true;
- Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"mRemoteNG main window received focus (_childProcessHeldLastFocus={_focusHelper.ChildProcessHeldLastFocus})");
-
- //var candidateTabToFocus = FromChildHandle(NativeMethods.WindowFromPoint(MousePosition))
- // ?? GetChildAtPoint(MousePosition);
- //if (candidateTabToFocus is InterfaceControl)
- //{
- // candidateTabToFocus.Parent.Focus();
- //}
-
break;
case NativeMethods.WM_ACTIVATE:
if (NativeMethods.LOWORD(m.WParam) == NativeMethods.WA_ACTIVE)
@@ -554,50 +511,28 @@ namespace mRemoteNG.UI.Forms
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"Click activate: {controlThatWasClicked}");
- if (controlThatWasClicked is TreeView ||
- controlThatWasClicked is ComboBox ||
- controlThatWasClicked is TextBox ||
- controlThatWasClicked is FrmMain ||
- controlThatWasClicked is AutoHideStripBase)
- {
- controlThatWasClicked.Focus();
- }
- else if (controlThatWasClicked.CanSelect ||
- controlThatWasClicked is MenuStrip ||
- controlThatWasClicked is ToolStrip)
- {
- // Simulate a mouse event since one wasn't generated by Windows
- SimulateClick(controlThatWasClicked);
- controlThatWasClicked.Focus();
- }
+ //if (controlThatWasClicked is TreeView ||
+ // controlThatWasClicked is ComboBox ||
+ // controlThatWasClicked is TextBox ||
+ // controlThatWasClicked is FrmMain ||
+ // controlThatWasClicked is AutoHideStripBase)
+ //{
+ // controlThatWasClicked.Focus();
+ //}
+ //else if (controlThatWasClicked.CanSelect ||
+ // controlThatWasClicked is MenuStrip ||
+ // controlThatWasClicked is ToolStrip)
+ //{
+ // // Simulate a mouse event since one wasn't generated by Windows
+ // SimulateClick(controlThatWasClicked);
+ // controlThatWasClicked.Focus();
+ //}
//else
//{
// // This handles activations from clicks that did not start a size/move operation
// ActivateConnection();
//}
- break;
- case NativeMethods.WM_NCACTIVATE:
- //// 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;
- return;
- case NativeMethods.WM_WINDOWPOSCHANGED:
- // Ignore this message if the window wasn't activated
- if (!_inMouseActivate)
- break;
-
- var windowPos = (NativeMethods.WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(NativeMethods.WINDOWPOS));
- if ((windowPos.flags & NativeMethods.SWP_NOACTIVATE) == 0)
- {
- if (!_inMouseActivate && !_inSizeMove)
- {
- Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "WM_WINDOWPOSCHANGED DONE");
- _focusHelper.ActivateConnection();
- }
- }
-
break;
case NativeMethods.WM_SYSCOMMAND:
var screen = _screenSystemMenu.GetScreenById(m.WParam.ToInt32());