Skip to content
This repository has been archived by the owner on Jun 20, 2021. It is now read-only.

Commit

Permalink
Add hook method option, add polling method
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGuardianWolf committed Apr 27, 2020
1 parent 1d4fe13 commit 7a89b63
Show file tree
Hide file tree
Showing 14 changed files with 283 additions and 57 deletions.
4 changes: 2 additions & 2 deletions lib/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.0.0")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: AssemblyVersion("1.6.0.0")]
[assembly: AssemblyFileVersion("1.6.0.0")]
12 changes: 12 additions & 0 deletions lib/Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/Properties/Settings.settings
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
<Setting Name="MinimiseOnStart" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="HookMethod" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
</Settings>
</SettingsFile>
3 changes: 3 additions & 0 deletions lib/ThunderbirdTray.Lib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
<Reference Include="UIAutomationTypes" />
</ItemGroup>
<ItemGroup>
<Compile Include="WindowStateHooks\IWindowStateHook.cs" />
<Compile Include="WindowStateHooks\Polling.cs" />
<Compile Include="WindowStateHooks\UIAutomation.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
Expand Down
109 changes: 59 additions & 50 deletions lib/TrayBird.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using ThunderbirdTray.Win32;
using System.Text;
using ThunderbirdTray.Views;
using ThunderbirdTray.WindowStateHooks;

namespace ThunderbirdTray
{
Expand All @@ -32,38 +33,9 @@ public partial class TrayBird : ApplicationContext
private Process thunderbirdProcess;
private IntPtr thunderbirdMainWindowHandle;
private bool thunderbirdShown = true;
private WindowVisualState lastVisualState = WindowVisualState.Minimized;
private AutomationElement thunderbirdAutomationElement;
private bool trayLaunched = false; // Was Thunderbird last launched with TrayBird?

private User32.ShowWindowType restoreState
{
get
{
if (lastVisualState == WindowVisualState.Minimized)
{
if (thunderbirdMainWindowHandle != null)
{
if ((User32.GetWindowPlacement(thunderbirdMainWindowHandle).flags & User32.WPF_RESTORETOMAXIMIZED) > 0)
{
return User32.ShowWindowType.SW_MAXIMIZE;
}
else
{
return User32.ShowWindowType.SW_NORMAL;
}
}
else
{
return User32.ShowWindowType.SW_NORMAL;
}
}
else
{
return lastVisualState == WindowVisualState.Maximized ? User32.ShowWindowType.SW_MAXIMIZE : User32.ShowWindowType.SW_NORMAL;
}
}
}
private IWindowStateHook windowStateHook;
private HookMethod currentHookMethod;

public TrayBird(bool debugLog=true)
{
Expand Down Expand Up @@ -152,6 +124,25 @@ private void NotifyIcon_Click(object sender, EventArgs e)
}
}

private User32.ShowWindowType CalculateWindowRestoreState()
{
if (thunderbirdMainWindowHandle != null)
{
if ((User32.GetWindowPlacement(thunderbirdMainWindowHandle).flags & User32.WPF_RESTORETOMAXIMIZED) > 0)
{
return User32.ShowWindowType.SW_MAXIMIZE;
}
else
{
return User32.ShowWindowType.SW_NORMAL;
}
}
else
{
return User32.ShowWindowType.SW_NORMAL;
}
}

private void ToggleShowThunderbird(object sender, EventArgs e)
{
ToggleShowThunderbird();
Expand Down Expand Up @@ -212,8 +203,8 @@ private void ShowThunderbird()
{
if (thunderbirdMainWindowHandle != IntPtr.Zero)
{
log.Debug("Showing Thunderbird with last state as {@lastVisualState}.", lastVisualState);
User32.ShowWindow(thunderbirdMainWindowHandle, restoreState);
log.Debug("Showing Thunderbird.");
User32.ShowWindow(thunderbirdMainWindowHandle, CalculateWindowRestoreState());
User32.SetForegroundWindow(thunderbirdMainWindowHandle);
thunderbirdShown = true;
}
Expand All @@ -223,7 +214,7 @@ private void HideThunderbird()
{
if (thunderbirdMainWindowHandle != IntPtr.Zero)
{
log.Debug("Hiding Thunderbird with last state as {@lastVisualState}.", lastVisualState);
log.Debug("Hiding Thunderbird.");
User32.ShowWindow(thunderbirdMainWindowHandle, User32.ShowWindowType.SW_HIDE);
thunderbirdShown = false;
}
Expand All @@ -238,6 +229,11 @@ private void ShowConfig(object sender, EventArgs e)

private void OptionsForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (currentHookMethod != (HookMethod)Properties.Settings.Default.HookMethod)
{
UnhookThunderbird();
HookThunderbird();
}
optionsForm = null;
}

Expand Down Expand Up @@ -275,12 +271,24 @@ private bool HookThunderbird()

thunderbirdProcess.EnableRaisingEvents = true;
thunderbirdProcess.Exited += Thunderbird_Exited;
thunderbirdAutomationElement = AutomationElement.FromHandle(thunderbirdMainWindowHandle);
Automation.AddAutomationPropertyChangedEventHandler(
thunderbirdAutomationElement,
TreeScope.Element,
Thunderbird_VisualStateChanged,
new AutomationProperty[] { WindowPattern.WindowVisualStateProperty });
switch(Properties.Settings.Default.HookMethod)
{
case (int)HookMethod.UIAutomation:
windowStateHook = new UIAutomation();
break;
case (int)HookMethod.Polling:
default:
windowStateHook = new Polling();
break;
}
currentHookMethod = (HookMethod)Properties.Settings.Default.HookMethod;

if (!windowStateHook.Hook(thunderbirdMainWindowHandle))
{
return false;
}

windowStateHook.WindowStateChange += Thunderbird_VisualStateChanged;

log.Debug("Attached event handlers for window.");

Expand All @@ -298,8 +306,6 @@ private bool HookThunderbird()
log.Information("Thunderbird is already minimised, hiding now. {@thunderbirdShown}, {@isIconic}.", thunderbirdShown, isIconic);
HideThunderbird();
}
lastVisualState = (WindowVisualState)thunderbirdAutomationElement.GetCurrentPropertyValue(WindowPattern.WindowVisualStateProperty);
log.Debug("Setting visual state as {@lastVisualState}.", lastVisualState);

return true;
}
Expand Down Expand Up @@ -349,12 +355,12 @@ private IntPtr FindMainThunderbirdWindow(Process thunderbirdProcess)
return thunderbirdWindow;
}

private void Thunderbird_VisualStateChanged(object sender, AutomationPropertyChangedEventArgs e)
private void Thunderbird_VisualStateChanged(object sender, WindowStateChangeEventArgs e)
{
WindowVisualState visualState = WindowVisualState.Normal;
try
{
visualState = (WindowVisualState)e.NewValue;
visualState = (WindowVisualState)e.WindowState;
}
catch (InvalidCastException)
{
Expand All @@ -370,7 +376,6 @@ private void Thunderbird_VisualStateChanged(object sender, AutomationPropertyCha
else
{
thunderbirdShown = true;
lastVisualState = visualState;
}
}

Expand Down Expand Up @@ -398,11 +403,9 @@ private void UnhookThunderbird()
thunderbirdMainWindowHandle = IntPtr.Zero;
}

if (thunderbirdAutomationElement != null)
{
Automation.RemoveAllEventHandlers();
thunderbirdAutomationElement = null;
}
windowStateHook.Unhook();
windowStateHook.WindowStateChange -= Thunderbird_VisualStateChanged;
windowStateHook = null;
thunderbirdProcess.Dispose();
thunderbirdProcess = null;
initTask = null;
Expand All @@ -429,4 +432,10 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}
}

enum HookMethod : int
{
UIAutomation = 0,
Polling = 1,
}
}
30 changes: 29 additions & 1 deletion lib/Views/UserOptions.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/Views/UserOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ public partial class UserOptions : Form
public UserOptions()
{
InitializeComponent();
HookMethodComboBox.SelectedIndex = Properties.Settings.Default.HookMethod;
}

private void SaveButton_Click(object sender, EventArgs e)
{
Properties.Settings.Default.HookMethod = HookMethodComboBox.SelectedIndex;
Properties.Settings.Default.Save();
Close();
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Win32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public ShowWindowType showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
Expand Down
33 changes: 33 additions & 0 deletions lib/WindowStateHooks/IWindowStateHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ThunderbirdTray.WindowStateHooks
{
public interface IWindowStateHook
{
event EventHandler<WindowStateChangeEventArgs> WindowStateChange;

bool Hook(IntPtr windowHandle);
bool Unhook();
}

public enum WindowState: int
{
Normal = 0,
Maximized = 1,
Minimized = 2
}

public class WindowStateChangeEventArgs : EventArgs
{
public WindowState WindowState { get; }

internal WindowStateChangeEventArgs(WindowState windowState)
{
WindowState = windowState;
}
}
}

0 comments on commit 7a89b63

Please sign in to comment.