moved a number of focus logic window events out of frmmain

This commit is contained in:
David Sparer
2019-09-01 14:54:49 -05:00
parent e9838960fa
commit 0d727338f0
3 changed files with 137 additions and 110 deletions

View File

@@ -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;
/// <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
{
@@ -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;
}
/// <summary>
/// Give the <see cref="ExternalProcessFocusHelper"/> 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.
/// </summary>
/// <param name="m"></param>
/// <returns>
/// Returns true if an action has been taken which should override the
/// base windows own WndProc handling.
/// </returns>
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;
}
}
}

View File

@@ -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();

View File

@@ -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());