diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 6148ad36e..7d98454f9 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -671,7 +671,11 @@
-
+
+
+
+
+
diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs
index 1e3f496d8..ddb65e86d 100644
--- a/Artemis/Artemis/ArtemisBootstrapper.cs
+++ b/Artemis/Artemis/ArtemisBootstrapper.cs
@@ -10,6 +10,7 @@ using Artemis.DAL;
using Artemis.InjectionModules;
using Artemis.Settings;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Artemis.Utilities.Converters;
using Artemis.Utilities.DataReaders;
using Artemis.ViewModels;
@@ -113,7 +114,7 @@ namespace Artemis
//TODO DarthAffe 17.12.2016: Is this the right location for this?
//TODO Move to Mainmanager and make disposable
- ActiveWindowHelper.Initialize();
+ ActiveWindowHelper.SetActiveWindowDetectionType(SettingsProvider.Load().ActiveWindowDetection);
}
protected override void OnExit(object sender, EventArgs e)
diff --git a/Artemis/Artemis/Managers/PreviewManager.cs b/Artemis/Artemis/Managers/PreviewManager.cs
index 612f2e120..68a7f8aed 100644
--- a/Artemis/Artemis/Managers/PreviewManager.cs
+++ b/Artemis/Artemis/Managers/PreviewManager.cs
@@ -5,6 +5,7 @@ using Artemis.DAL;
using Artemis.Modules.Abstract;
using Artemis.Settings;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Ninject.Extensions.Logging;
namespace Artemis.Managers
diff --git a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
index 56ac83987..dbe22a298 100644
--- a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
+++ b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs
@@ -11,6 +11,7 @@ using Artemis.Events;
using Artemis.Managers;
using Artemis.Modules.Abstract;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using CSCore.CoreAudioAPI;
using Newtonsoft.Json;
using SpotifyAPI.Local;
diff --git a/Artemis/Artemis/Settings/GeneralSettings.cs b/Artemis/Artemis/Settings/GeneralSettings.cs
index b304c114d..13240abee 100644
--- a/Artemis/Artemis/Settings/GeneralSettings.cs
+++ b/Artemis/Artemis/Settings/GeneralSettings.cs
@@ -5,9 +5,11 @@ using System.Windows;
using Artemis.DAL;
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using MahApps.Metro;
using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
using Squirrel;
namespace Artemis.Settings
@@ -68,6 +70,11 @@ namespace Artemis.Settings
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public string LogLevel { get; set; }
+ [DefaultValue(ActiveWindowDetectionType.Events)]
+ [JsonConverter(typeof(StringEnumConverter))]
+ [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
+ public ActiveWindowDetectionType ActiveWindowDetection { get; set; }
+
public Version LastRanVersion { get; set; }
public void Save()
@@ -75,6 +82,7 @@ namespace Artemis.Settings
SettingsProvider.Save(this);
Logging.SetupLogging(LogLevel);
+ ActiveWindowHelper.SetActiveWindowDetectionType(ActiveWindowDetection);
ApplyAutorun();
ApplyTheme();
ApplyGamestatePort();
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowDetectionType.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowDetectionType.cs
new file mode 100644
index 000000000..d567caade
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowDetectionType.cs
@@ -0,0 +1,9 @@
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public enum ActiveWindowDetectionType
+ {
+ Disabled = -1,
+ Events = 0,
+ Timer = 1,
+ }
+}
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowHelper.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowHelper.cs
new file mode 100644
index 000000000..1edaa2f84
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/ActiveWindowHelper.cs
@@ -0,0 +1,48 @@
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public static class ActiveWindowHelper
+ {
+ #region Properties & Fields
+
+ private static ActiveWindowDetectionType _currentDetectionType = ActiveWindowDetectionType.Disabled;
+ private static IActiveWindowDetector _activeWindowDetector;
+
+ public static string ActiveWindowProcessName => _activeWindowDetector?.ActiveWindowProcessName ?? string.Empty;
+ public static string ActiveWindowWindowTitle => _activeWindowDetector?.ActiveWindowWindowTitle ?? string.Empty;
+ public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
+
+ #endregion
+
+ #region Methods
+
+ public static void Dispose()
+ {
+ _activeWindowDetector?.Dispose();
+ }
+
+ public static void SetActiveWindowDetectionType(ActiveWindowDetectionType detectionType)
+ {
+ if (detectionType == _currentDetectionType) return;
+
+ _activeWindowDetector?.Dispose();
+
+ switch (detectionType)
+ {
+ case ActiveWindowDetectionType.Events:
+ _activeWindowDetector = new EventActiveWindowDetector();
+ break;
+ case ActiveWindowDetectionType.Timer:
+ _activeWindowDetector = new TimerActiveWindowDetector();
+ break;
+ case ActiveWindowDetectionType.Disabled:
+ _activeWindowDetector = null;
+ break;
+ }
+
+ _activeWindowDetector?.Initialize();
+ _currentDetectionType = detectionType;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/ActiveWindowHelper.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/EventActiveWindowDetector.cs
similarity index 69%
rename from Artemis/Artemis/Utilities/ActiveWindowHelper.cs
rename to Artemis/Artemis/Utilities/ActiveWindowDetection/EventActiveWindowDetector.cs
index 2c9430ee9..3c25a678b 100644
--- a/Artemis/Artemis/Utilities/ActiveWindowHelper.cs
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/EventActiveWindowDetector.cs
@@ -2,9 +2,9 @@
using System.Runtime.InteropServices;
using System.Text;
-namespace Artemis.Utilities
+namespace Artemis.Utilities.ActiveWindowDetection
{
- public static class ActiveWindowHelper
+ public class EventActiveWindowDetector : IActiveWindowDetector
{
#region DLL-Imports
@@ -14,7 +14,7 @@ namespace Artemis.Utilities
[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc,
- WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
+ WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
@@ -41,47 +41,46 @@ namespace Artemis.Utilities
#region Properties & Fields
// DarthAffe 17.12.2016: We need to keep a reference to this or it might get collected by the garbage collector and cause some random crashes afterwards.
- private static WinEventDelegate _activeWindowChangedDelegate;
- private static IntPtr _activeWindowEventHook;
+ private WinEventDelegate _activeWindowChangedDelegate;
+ private IntPtr _activeWindowEventHook;
- private static WinEventDelegate _windowTitleChangedDelegate;
- private static IntPtr _windowTitleEventHook;
+ private WinEventDelegate _windowTitleChangedDelegate;
+ private IntPtr _windowTitleEventHook;
- private static WinEventDelegate _windowMinimizedChangedDelegate;
- private static IntPtr _windowMinimizedEventHook;
+ private WinEventDelegate _windowMinimizedChangedDelegate;
+ private IntPtr _windowMinimizedEventHook;
- private static IntPtr _activeWindow;
+ private IntPtr _activeWindow;
- public static string ActiveWindowProcessName { get; private set; } = string.Empty;
- public static string ActiveWindowWindowTitle { get; private set; } = string.Empty;
- public static bool MainWindowActive => ActiveWindowProcessName.Contains("Artemis");
+ public string ActiveWindowProcessName { get; private set; } = string.Empty;
+ public string ActiveWindowWindowTitle { get; private set; } = string.Empty;
#endregion
#region Methods
- private static void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
- IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ private void ActiveWindowChanged(IntPtr hWinEventHook, uint eventType,
+ IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
UpdateForWindow(hwnd);
}
- private static void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
- IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ private void WindowTitleChanged(IntPtr hWinEventHook, uint eventType,
+ IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (_activeWindow == hwnd)
UpdateForWindow(hwnd);
}
- private static void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
- IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ private void WindowMinimizedChanged(IntPtr hWinEventHook, uint eventType,
+ IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
// DarthAffe 19.12.2016: We expect currently un-minimized windows to be active.
// DarthAffe 19.12.2016: The result of the API-function GetActiveWindow at this moment is 'idle' so we can't use this to validate this estimation.
UpdateForWindow(hwnd);
}
- private static void UpdateForWindow(IntPtr hwnd)
+ private void UpdateForWindow(IntPtr hwnd)
{
_activeWindow = hwnd;
@@ -89,13 +88,13 @@ namespace Artemis.Utilities
ActiveWindowWindowTitle = GetActiveWindowTitle(hwnd) ?? string.Empty;
}
- private static string GetActiveWindowProcessName(IntPtr hwnd)
+ private string GetActiveWindowProcessName(IntPtr hwnd)
{
try
{
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
- return System.Diagnostics.Process.GetProcessById((int) pid).ProcessName;
+ return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
}
catch
{
@@ -103,7 +102,7 @@ namespace Artemis.Utilities
}
}
- private static string GetActiveWindowTitle(IntPtr hwnd)
+ private string GetActiveWindowTitle(IntPtr hwnd)
{
try
{
@@ -116,7 +115,7 @@ namespace Artemis.Utilities
}
}
- public static void Initialize()
+ public void Initialize()
{
try
{
@@ -124,21 +123,21 @@ namespace Artemis.Utilities
{
_activeWindowChangedDelegate = ActiveWindowChanged;
_activeWindowEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND,
- IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
+ IntPtr.Zero, _activeWindowChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
if (_windowTitleEventHook == IntPtr.Zero)
{
_windowTitleChangedDelegate = WindowTitleChanged;
_windowTitleEventHook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE,
- IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
+ IntPtr.Zero, _windowTitleChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
if (_windowMinimizedEventHook == IntPtr.Zero)
{
_windowMinimizedChangedDelegate = WindowMinimizedChanged;
_windowMinimizedEventHook = SetWinEventHook(EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZEEND,
- IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
+ IntPtr.Zero, _windowMinimizedChangedDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
}
}
catch
@@ -147,7 +146,7 @@ namespace Artemis.Utilities
}
}
- public static void Dispose()
+ public void Dispose()
{
try
{
@@ -180,4 +179,4 @@ namespace Artemis.Utilities
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/IActiveWindowDetector.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/IActiveWindowDetector.cs
new file mode 100644
index 000000000..400ecf4ed
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/IActiveWindowDetector.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public interface IActiveWindowDetector : IDisposable
+ {
+ string ActiveWindowProcessName { get; }
+ string ActiveWindowWindowTitle { get; }
+
+ void Initialize();
+ }
+}
diff --git a/Artemis/Artemis/Utilities/ActiveWindowDetection/TimerActiveWindowDetector.cs b/Artemis/Artemis/Utilities/ActiveWindowDetection/TimerActiveWindowDetector.cs
new file mode 100644
index 000000000..b865a859c
--- /dev/null
+++ b/Artemis/Artemis/Utilities/ActiveWindowDetection/TimerActiveWindowDetector.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Timers;
+
+namespace Artemis.Utilities.ActiveWindowDetection
+{
+ public class TimerActiveWindowDetector : IActiveWindowDetector
+ {
+ #region DLL-Imports
+
+ [DllImport("user32.dll")]
+ static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
+
+ #endregion
+
+ #region Constants
+
+ private const int TIMER_INTERVAL = 1000;
+ private const int MAX_TITLE_LENGTH = 256;
+
+ #endregion
+
+ #region Properties & Fields
+
+ private Timer _timer;
+
+ public string ActiveWindowProcessName { get; private set; }
+ public string ActiveWindowWindowTitle { get; private set; }
+
+ #endregion
+
+ #region Methods
+
+ private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
+ {
+ IntPtr activeWindow = GetForegroundWindow();
+ ActiveWindowProcessName = GetActiveWindowProcessName(activeWindow);
+ ActiveWindowWindowTitle = GetActiveWindowTitle(activeWindow);
+ }
+
+ private string GetActiveWindowProcessName(IntPtr hwnd)
+ {
+ try
+ {
+ uint pid;
+ GetWindowThreadProcessId(hwnd, out pid);
+ return System.Diagnostics.Process.GetProcessById((int)pid).ProcessName;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private string GetActiveWindowTitle(IntPtr hwnd)
+ {
+ try
+ {
+ StringBuilder buffer = new StringBuilder(MAX_TITLE_LENGTH);
+ return GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH) > 0 ? buffer.ToString() : null;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public void Initialize()
+ {
+ _timer = new Timer(TIMER_INTERVAL) { AutoReset = true };
+ _timer.Elapsed += TimerOnElapsed;
+ _timer.Start();
+ }
+
+ public void Dispose()
+ {
+ _timer?.Stop();
+ _timer?.Dispose();
+ _timer = null;
+ }
+
+ #endregion
+ }
+}
diff --git a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
index a6169b985..88394d44b 100644
--- a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
@@ -8,6 +8,7 @@ using Artemis.Events;
using Artemis.Managers;
using Artemis.Services;
using Artemis.Settings;
+using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using MahApps.Metro.Controls;
using NLog;
@@ -37,6 +38,8 @@ namespace Artemis.ViewModels.Flyouts
LogLevels = new BindableCollection();
LogLevels.AddRange(LogLevel.AllLoggingLevels.Select(l => l.Name));
+ ActiveWindowDetections = new BindableCollection(Enum.GetValues(typeof(ActiveWindowDetectionType)).Cast());
+
PropertyChanged += KeyboardUpdater;
mainManager.EnabledChanged += MainManagerEnabledChanged;
mainManager.ModuleManager.EffectChanged += EffectManagerEffectChanged;
@@ -96,6 +99,7 @@ namespace Artemis.ViewModels.Flyouts
public string VersionText => "Artemis " + Assembly.GetExecutingAssembly().GetName().Version;
public BindableCollection LogLevels { get; set; }
+ public BindableCollection ActiveWindowDetections { get; set; }
public string SelectedTheme
{
@@ -130,6 +134,17 @@ namespace Artemis.ViewModels.Flyouts
}
}
+ public ActiveWindowDetectionType SelectedActiveWindowDetection
+ {
+ get { return GeneralSettings.ActiveWindowDetection; }
+ set
+ {
+ if (value == GeneralSettings.ActiveWindowDetection) return;
+ GeneralSettings.ActiveWindowDetection = value;
+ NotifyOfPropertyChange(() => SelectedActiveWindowDetection);
+ }
+ }
+
public string SelectedKeyboardProvider
{
get { return _selectedKeyboardProvider; }
diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
index 570fd5fb7..9916680fa 100644
--- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs
@@ -23,6 +23,7 @@ using Artemis.Properties;
using Artemis.Services;
using Artemis.Styles.DropTargetAdorners;
using Artemis.Utilities;
+using Artemis.Utilities.ActiveWindowDetection;
using Caliburn.Micro;
using Castle.Components.DictionaryAdapter;
using GongSolutions.Wpf.DragDrop;
diff --git a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
index 467284257..a7b50d2e0 100644
--- a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
+++ b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
@@ -6,7 +6,7 @@
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
- d:DesignHeight="600" d:DesignWidth="300">
+ d:DesignHeight="600" d:DesignWidth="310">
@@ -25,6 +25,7 @@
+
@@ -94,30 +95,36 @@
-
-
+
-
+
-