diff --git a/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs b/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs index 779f509..859a859 100644 --- a/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs +++ b/src/Eve-O-Preview/Configuration/Implementation/ThumbnailConfiguration.cs @@ -32,9 +32,11 @@ namespace EveOPreview.Configuration.Implementation this.HideActiveClientThumbnail = false; this.MinimizeInactiveClients = false; this.ShowThumbnailsAlwaysOnTop = true; - this.HideThumbnailsOnLostFocus = false; this.EnablePerClientThumbnailLayouts = false; + this.HideThumbnailsOnLostFocus = false; + this.HideThumbnailsDelay = 2; // 2 thumbnails refresh cycles (1.0 sec) + this.ThumbnailSize = new Size(384, 216); this.ThumbnailMinimumSize = new Size(192, 108); this.ThumbnailMaximumSize = new Size(960, 540); @@ -79,7 +81,6 @@ namespace EveOPreview.Configuration.Implementation public bool HideActiveClientThumbnail { get; set; } public bool MinimizeInactiveClients { get; set; } public bool ShowThumbnailsAlwaysOnTop { get; set; } - public bool HideThumbnailsOnLostFocus { get; set; } public bool EnablePerClientThumbnailLayouts { @@ -95,6 +96,9 @@ namespace EveOPreview.Configuration.Implementation } } + public bool HideThumbnailsOnLostFocus { get; set; } + public int HideThumbnailsDelay { get; set; } + public Size ThumbnailSize { get; set; } public Size ThumbnailMaximumSize { get; set; } public Size ThumbnailMinimumSize { get; set; } diff --git a/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs b/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs index 3cb1158..8b97051 100644 --- a/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs +++ b/src/Eve-O-Preview/Configuration/Interface/IThumbnailConfiguration.cs @@ -16,9 +16,11 @@ namespace EveOPreview.Configuration bool HideActiveClientThumbnail { get; set; } bool MinimizeInactiveClients { get; set; } bool ShowThumbnailsAlwaysOnTop { get; set; } - bool HideThumbnailsOnLostFocus { get; set; } bool EnablePerClientThumbnailLayouts { get; set; } + bool HideThumbnailsOnLostFocus { get; set; } + int HideThumbnailsDelay { get; set; } + Size ThumbnailSize { get; set; } Size ThumbnailMinimumSize { get; set; } Size ThumbnailMaximumSize { get; set; } diff --git a/src/Eve-O-Preview/Services/Implementation/ProcessMonitor.cs b/src/Eve-O-Preview/Services/Implementation/ProcessMonitor.cs index 5c5e057..2bf9008 100644 --- a/src/Eve-O-Preview/Services/Implementation/ProcessMonitor.cs +++ b/src/Eve-O-Preview/Services/Implementation/ProcessMonitor.cs @@ -8,15 +8,21 @@ namespace EveOPreview.Services.Implementation { #region Private constants private const string DEFAULT_PROCESS_NAME = "ExeFile"; + private const string CURRENT_PROCESS_NAME = "EVE-O Preview"; #endregion #region Private fields private readonly IDictionary _processCache; + private IProcessInfo _currentProcessInfo; #endregion public ProcessMonitor() { this._processCache = new Dictionary(512); + + // This field cannot be initialized properly in constructor + // At the moment this code is executed the main application window is not yet initialized + this._currentProcessInfo = new ProcessInfo(IntPtr.Zero, ""); } private bool IsMonitoredProcess(string processName) @@ -25,6 +31,41 @@ namespace EveOPreview.Services.Implementation return String.Equals(processName, ProcessMonitor.DEFAULT_PROCESS_NAME, StringComparison.OrdinalIgnoreCase); } + private IProcessInfo GetCurrentProcessInfo() + { + var currentProcess = Process.GetCurrentProcess(); + return new ProcessInfo(currentProcess.MainWindowHandle, currentProcess.MainWindowTitle); + } + + public IProcessInfo GetMainProcess() + { + if (this._currentProcessInfo.Handle == IntPtr.Zero) + { + var processInfo = this.GetCurrentProcessInfo(); + + // Are we initialized yet? + if (processInfo.Title != "") + { + this._currentProcessInfo = processInfo; + } + } + + return this._currentProcessInfo; + } + + public ICollection GetAllProcesses() + { + ICollection result = new List(this._processCache.Count); + + // TODO Lock list here just in case + foreach (KeyValuePair entry in this._processCache) + { + result.Add(new ProcessInfo(entry.Key, entry.Value)); + } + + return result; + } + public void GetUpdatedProcesses(out ICollection addedProcesses, out ICollection updatedProcesses, out ICollection removedProcesses) { addedProcesses = new List(16); @@ -76,18 +117,5 @@ namespace EveOPreview.Services.Implementation this._processCache.Remove(index); } } - - public ICollection GetAllProcesses() - { - ICollection result = new List(this._processCache.Count); - - // TODO Lock list here just in case - foreach (KeyValuePair entry in this._processCache) - { - result.Add(new ProcessInfo(entry.Key, entry.Value)); - } - - return result; - } } } diff --git a/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs b/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs index ea0904f..9be8cde 100644 --- a/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs +++ b/src/Eve-O-Preview/Services/Implementation/ThumbnailManager.cs @@ -41,6 +41,7 @@ namespace EveOPreview.Services private bool _isHoverEffectActive; private int _refreshCycleCount; + private int _hideThumbnailsDelay; #endregion public ThumbnailManager(IMediator mediator, IThumbnailConfiguration configuration, IProcessMonitor processMonitor, IWindowManager windowManager, IThumbnailViewFactory factory) @@ -66,6 +67,8 @@ namespace EveOPreview.Services this._thumbnailUpdateTimer = new DispatcherTimer(); this._thumbnailUpdateTimer.Tick += ThumbnailUpdateTimerTick; this._thumbnailUpdateTimer.Interval = new TimeSpan(0, 0, 0, 0, configuration.ThumbnailRefreshPeriod); + + this._hideThumbnailsDelay = this._configuration.HideThumbnailsDelay; } public void Start() @@ -180,10 +183,19 @@ namespace EveOPreview.Services { // TODO Split this method IntPtr foregroundWindowHandle = this._windowManager.GetForegroundWindowHandle(); + + // The foreground window can be NULL in certain circumstances, such as when a window is losing activation. + // It is safer to just skip this refresh round than to do something while the system state is undefined + if (foregroundWindowHandle == IntPtr.Zero) + { + return; + } + string foregroundWindowTitle = null; // Check if the foreground window handle is one of the known handles for client windows or their thumbnails bool isClientWindow = this.IsClientWindowActive(foregroundWindowHandle); + bool isMainWindowActive = this.IsMainWindowActive(foregroundWindowHandle); if (foregroundWindowHandle == this._activeClient.Handle) { @@ -196,12 +208,7 @@ namespace EveOPreview.Services } else if (!isClientWindow) { - // Under some circumstances Foreground WindowHandle can be zero - // (f.e. when Thumbnail is silently stealing focus from the currently open app) - if (foregroundWindowHandle != IntPtr.Zero) - { - this._externalApplication = foregroundWindowHandle; - } + this._externalApplication = foregroundWindowHandle; } // No need to minimize EVE clients when switching out to non-EVE window (like thumbnail) @@ -210,7 +217,25 @@ namespace EveOPreview.Services this.SwitchActiveClient(foregroundWindowHandle, foregroundWindowTitle); } - bool hideAllThumbnails = this._configuration.HideThumbnailsOnLostFocus && !isClientWindow; + bool hideAllThumbnails = this._configuration.HideThumbnailsOnLostFocus && !(isClientWindow || isMainWindowActive); + + // Wait for some time before hiding all previews + if (hideAllThumbnails) + { + this._hideThumbnailsDelay--; + if (this._hideThumbnailsDelay > 0) + { + hideAllThumbnails = false; // Postpone the 'hide all' operation + } + else + { + this._hideThumbnailsDelay = 0; // Stop the counter + } + } + else + { + this._hideThumbnailsDelay = this._configuration.HideThumbnailsDelay; // Reset the counter + } this._refreshCycleCount++; @@ -456,6 +481,7 @@ namespace EveOPreview.Services this.EnqueueLocationChange(view); } + // Checks whether currently active window belongs to an EVE client or its thumbnail private bool IsClientWindowActive(IntPtr windowHandle) { if (windowHandle == IntPtr.Zero) @@ -476,6 +502,12 @@ namespace EveOPreview.Services return false; } + // Check whether the currently active window belongs to EVE-O Preview itself + private bool IsMainWindowActive(IntPtr windowHandle) + { + return (this._processMonitor.GetMainProcess().Handle == windowHandle); + } + private void ThumbnailZoomIn(IThumbnailView view) { this.DisableViewEvents(); diff --git a/src/Eve-O-Preview/Services/Interface/IProcessMonitor.cs b/src/Eve-O-Preview/Services/Interface/IProcessMonitor.cs index 1e123bb..22029a4 100644 --- a/src/Eve-O-Preview/Services/Interface/IProcessMonitor.cs +++ b/src/Eve-O-Preview/Services/Interface/IProcessMonitor.cs @@ -4,6 +4,7 @@ namespace EveOPreview.Services { public interface IProcessMonitor { + IProcessInfo GetMainProcess(); ICollection GetAllProcesses(); void GetUpdatedProcesses(out ICollection addedProcesses, out ICollection updatedProcesses, out ICollection removedProcesses); }