diff --git a/QuickLook.Plugin/QuickLook.Plugin.IPreviewHandlers/PreviewPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.IPreviewHandlers/PreviewPanel.xaml.cs
index d3c5601..6eab082 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.IPreviewHandlers/PreviewPanel.xaml.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.IPreviewHandlers/PreviewPanel.xaml.cs
@@ -17,6 +17,7 @@
using System;
using System.Runtime.InteropServices;
+using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
@@ -36,7 +37,7 @@ namespace QuickLook.Plugin.IPreviewHandlers
public void Dispose()
{
- Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
+ Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
presenter.Child = null;
presenter?.Dispose();
@@ -48,7 +49,7 @@ namespace QuickLook.Plugin.IPreviewHandlers
public void PreviewFile(string file, ContextObject context)
{
- Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
+ Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
_control = new PreviewHandlerHost();
presenter.Child = _control;
diff --git a/QuickLook/App.xaml b/QuickLook/App.xaml
index ced5e3a..e0aa916 100644
--- a/QuickLook/App.xaml
+++ b/QuickLook/App.xaml
@@ -10,7 +10,7 @@
- ./Fonts/#Segoe MDL2 Assets
+ ./Fonts/#Segoe MDL2 Assets
\ No newline at end of file
diff --git a/QuickLook/App.xaml.cs b/QuickLook/App.xaml.cs
index 08f8ee9..6677732 100644
--- a/QuickLook/App.xaml.cs
+++ b/QuickLook/App.xaml.cs
@@ -22,7 +22,6 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
-using System.Windows.Threading;
using QuickLook.Helpers;
using QuickLook.Properties;
@@ -103,26 +102,23 @@ namespace QuickLook
private void RemoteCallShowPreview(StartupEventArgs e)
{
- PipeServerManager.SendMessage(e.Args.First());
+ PipeServerManager.SendMessage(PipeMessages.Toggle, e.Args.First());
}
private void RunListener(StartupEventArgs e)
{
TrayIconManager.GetInstance();
if (!e.Args.Contains("/autorun") && !IsUWP)
- TrayIconManager.GetInstance()
- .ShowNotification("", TranslationHelper.GetString("APP_START"));
+ TrayIconManager.ShowNotification("", TranslationHelper.GetString("APP_START"));
if (e.Args.Contains("/first"))
AutoStartupHelper.CreateAutorunShortcut();
NativeMethods.QuickLook.Init();
PluginManager.GetInstance();
+ ViewWindowManager.GetInstance();
BackgroundListener.GetInstance();
- PipeServerManager.GetInstance().MessageReceived +=
- (msg, ea) => Dispatcher.BeginInvoke(
- new Action(() => ViewWindowManager.GetInstance().InvokeViewer(msg as string, true)),
- DispatcherPriority.ApplicationIdle);
+ PipeServerManager.GetInstance();
}
private void App_OnExit(object sender, ExitEventArgs e)
diff --git a/QuickLook/BackgroundListener.cs b/QuickLook/BackgroundListener.cs
index 18f2808..3cbecfc 100644
--- a/QuickLook/BackgroundListener.cs
+++ b/QuickLook/BackgroundListener.cs
@@ -16,8 +16,8 @@
// along with this program. If not, see .
using System;
+using System.Diagnostics;
using System.Windows.Forms;
-using System.Windows.Threading;
using QuickLook.Helpers;
namespace QuickLook
@@ -60,22 +60,50 @@ namespace QuickLook
{
_isKeyDownInDesktopOrShell = NativeMethods.QuickLook.GetFocusedWindowType() !=
NativeMethods.QuickLook.FocusedWindowType.Invalid;
+
_isKeyDownInDesktopOrShell |= WindowHelper.IsForegroundWindowBelongToSelf();
}
// call InvokeRoutine only when the KeyDown is valid
if (_isKeyDownInDesktopOrShell)
- Dispatcher.CurrentDispatcher.BeginInvoke(
- new Action(down =>
- ViewWindowManager.GetInstance().InvokeRoutine(e, down)),
- DispatcherPriority.ApplicationIdle,
- isKeyDown);
+ InvokeRoutine(e.KeyCode, isKeyDown);
// reset variable only when KeyUp
if (!isKeyDown)
_isKeyDownInDesktopOrShell = false;
}
+ private void InvokeRoutine(Keys key, bool isKeyDown)
+ {
+ var path = NativeMethods.QuickLook.GetCurrentSelection();
+
+ Debug.WriteLine($"InvokeRoutine: key={key},down={isKeyDown}");
+
+ if (isKeyDown)
+ switch (key)
+ {
+ case Keys.Enter:
+ PipeServerManager.SendMessage(PipeMessages.RunAndClose);
+ break;
+ }
+ else
+ switch (key)
+ {
+ case Keys.Up:
+ case Keys.Down:
+ case Keys.Left:
+ case Keys.Right:
+ PipeServerManager.SendMessage(PipeMessages.Invoke, path);
+ break;
+ case Keys.Space:
+ PipeServerManager.SendMessage(PipeMessages.Toggle, path);
+ break;
+ case Keys.Escape:
+ PipeServerManager.SendMessage(PipeMessages.Close);
+ break;
+ }
+ }
+
private void InstallKeyHook(KeyEventHandler downHandler, KeyEventHandler upHandler)
{
_hook = GlobalKeyboardHook.GetInstance();
diff --git a/QuickLook/Controls/BusyDecorator/BusyDecorator.xaml b/QuickLook/Controls/BusyDecorator/BusyDecorator.xaml
index 88a103d..1a44713 100644
--- a/QuickLook/Controls/BusyDecorator/BusyDecorator.xaml
+++ b/QuickLook/Controls/BusyDecorator/BusyDecorator.xaml
@@ -10,7 +10,10 @@
-
+
+
+
diff --git a/QuickLook/FocusMonitor.cs b/QuickLook/FocusMonitor.cs
index b90b2e1..df8a99b 100644
--- a/QuickLook/FocusMonitor.cs
+++ b/QuickLook/FocusMonitor.cs
@@ -15,7 +15,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-using System;
using System.Threading;
using System.Threading.Tasks;
@@ -23,20 +22,21 @@ namespace QuickLook
{
internal class FocusMonitor
{
- public delegate void HeartbeatEventHandler(HeartbeatEventArgs e);
-
private static FocusMonitor _instance;
public bool IsRunning { get; private set; }
- public event HeartbeatEventHandler Heartbeat;
-
public void Start()
{
+ if (IsRunning)
+ return;
+
IsRunning = true;
new Task(() =>
{
+ var last = string.Empty;
+
while (IsRunning)
{
Thread.Sleep(500);
@@ -45,8 +45,12 @@ namespace QuickLook
NativeMethods.QuickLook.FocusedWindowType.Invalid)
continue;
- var file = NativeMethods.QuickLook.GetCurrentSelection();
- Heartbeat?.Invoke(new HeartbeatEventArgs(DateTime.Now.Ticks, file));
+ var path = NativeMethods.QuickLook.GetCurrentSelection();
+ if (IsRunning && last != path)
+ {
+ last = path;
+ PipeServerManager.SendMessage(PipeMessages.Invoke, path);
+ }
}
}).Start();
}
@@ -61,16 +65,4 @@ namespace QuickLook
return _instance ?? (_instance = new FocusMonitor());
}
}
-
- internal class HeartbeatEventArgs : EventArgs
- {
- public HeartbeatEventArgs(long tick, string files)
- {
- InvokeTick = tick;
- FocusedFile = files;
- }
-
- public long InvokeTick { get; }
- public string FocusedFile { get; }
- }
}
\ No newline at end of file
diff --git a/QuickLook/Helpers/AutoStartupHelper.cs b/QuickLook/Helpers/AutoStartupHelper.cs
index 4fa2a43..6e80a7e 100644
--- a/QuickLook/Helpers/AutoStartupHelper.cs
+++ b/QuickLook/Helpers/AutoStartupHelper.cs
@@ -50,7 +50,7 @@ namespace QuickLook.Helpers
}
catch (Exception)
{
- TrayIconManager.GetInstance().ShowNotification("", "Failed to add QuickLook to Startup folder.");
+ TrayIconManager.ShowNotification("", "Failed to add QuickLook to Startup folder.");
}
}
diff --git a/QuickLook/Helpers/Updater.cs b/QuickLook/Helpers/Updater.cs
index 9aacabe..f9e287d 100644
--- a/QuickLook/Helpers/Updater.cs
+++ b/QuickLook/Helpers/Updater.cs
@@ -47,7 +47,7 @@ namespace QuickLook.Helpers
{
if (!silent)
Application.Current.Dispatcher.Invoke(
- () => TrayIconManager.GetInstance().ShowNotification("",
+ () => TrayIconManager.ShowNotification("",
TranslationHelper.GetString("Update_NoUpdate")));
return;
}
@@ -57,7 +57,7 @@ namespace QuickLook.Helpers
Application.Current.Dispatcher.Invoke(
() =>
{
- TrayIconManager.GetInstance().ShowNotification("",
+ TrayIconManager.ShowNotification("",
string.Format(TranslationHelper.GetString("Update_Found"), nVersion),
timeout: 20000,
clickEvent:
@@ -69,7 +69,7 @@ namespace QuickLook.Helpers
{
Debug.WriteLine(e.Message);
Application.Current.Dispatcher.Invoke(
- () => TrayIconManager.GetInstance().ShowNotification("",
+ () => TrayIconManager.ShowNotification("",
string.Format(TranslationHelper.GetString("Update_Error"), e.Message)));
}
});
@@ -94,14 +94,13 @@ namespace QuickLook.Helpers
var changeLogPath = Path.GetTempFileName() + ".md";
File.WriteAllText(changeLogPath, notes);
- Application.Current.Dispatcher.Invoke(() => ViewWindowManager.GetInstance()
- .InvokeViewer(changeLogPath));
+ PipeServerManager.SendMessage(PipeMessages.Invoke, changeLogPath);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
Application.Current.Dispatcher.Invoke(
- () => TrayIconManager.GetInstance().ShowNotification("",
+ () => TrayIconManager.ShowNotification("",
string.Format(TranslationHelper.GetString("Update_Error"), e.Message)));
}
});
diff --git a/QuickLook/MainWindowTransparent.xaml b/QuickLook/MainWindowTransparent.xaml
index a7b24c7..c331c6c 100644
--- a/QuickLook/MainWindowTransparent.xaml
+++ b/QuickLook/MainWindowTransparent.xaml
@@ -86,7 +86,8 @@
GlassVisibility="{Binding ContextObject.TitlebarBlurVisibility, ElementName=mainWindow, Converter={StaticResource BooleanToVisibilityConverter}}"
NoiseVisibility="{Binding ContextObject.TitlebarBlurVisibility, ElementName=mainWindow, Converter={StaticResource BooleanToVisibilityConverter}}" />
-
+
-
+
exceptionHandler)
+ internal void BeginShow(IViewer matchedPlugin, string path,
+ Action exceptionHandler)
{
_path = path;
Plugin = matchedPlugin;
@@ -338,7 +337,7 @@ namespace QuickLook
}
catch (Exception e)
{
- exceptionHandler(ExceptionDispatchInfo.Capture(e));
+ exceptionHandler(path, ExceptionDispatchInfo.Capture(e));
}
}),
DispatcherPriority.Input);
diff --git a/QuickLook/PipeServerManager.cs b/QuickLook/PipeServerManager.cs
index 245e620..b603f9b 100644
--- a/QuickLook/PipeServerManager.cs
+++ b/QuickLook/PipeServerManager.cs
@@ -20,13 +20,23 @@ using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Threading;
namespace QuickLook
{
+ internal static class PipeMessages
+ {
+ public const string RunAndClose = "QuickLook.App.PipeMessages.RunAndClose";
+ public const string Invoke = "QuickLook.App.PipeMessages.Invoke";
+ public const string Toggle = "QuickLook.App.PipeMessages.Toggle";
+ public const string Close = "QuickLook.App.PipeMessages.Close";
+ public const string Quit = "QuickLook.App.PipeMessages.Quit";
+ }
+
internal class PipeServerManager : IDisposable
{
private const string PipeName = "QuickLook.App.Pipe";
- private const string PipeCloseMessage = "QuickLook.App.Pipe.QuitSingal";
private static PipeServerManager _instance;
private NamedPipeServerStream _server;
@@ -39,20 +49,18 @@ namespace QuickLook
{
using (var reader = new StreamReader(_server))
{
+ Debug.WriteLine("PipeManager: Ready");
+
while (true)
{
- Debug.WriteLine("PipeManager: WaitForConnection");
-
_server.WaitForConnection();
var msg = reader.ReadLine();
Debug.WriteLine($"PipeManager: {msg}");
- if (msg == PipeCloseMessage)
- return;
-
// dispatch message
- MessageReceived?.Invoke(msg, new EventArgs());
+ if (MessageReceived(msg))
+ return;
_server.Disconnect();
}
@@ -65,15 +73,16 @@ namespace QuickLook
GC.SuppressFinalize(this);
if (_server != null)
- SendMessage(PipeCloseMessage);
+ SendMessage(PipeMessages.Quit);
_server?.Dispose();
_server = null;
}
- public event EventHandler MessageReceived;
-
- public static void SendMessage(string msg)
+ public static void SendMessage(string pipeMessage, string path = null)
{
+ if (path == null)
+ path = "";
+
try
{
using (var client = new NamedPipeClientStream(".", PipeName, PipeDirection.Out))
@@ -82,7 +91,7 @@ namespace QuickLook
using (var writer = new StreamWriter(client))
{
- writer.WriteLine(msg);
+ writer.WriteLine($"{pipeMessage}|{path}");
writer.Flush();
}
}
@@ -93,6 +102,44 @@ namespace QuickLook
}
}
+ private bool MessageReceived(string msg)
+ {
+ var split = msg.IndexOf('|');
+ if (split == -1)
+ return false;
+
+ var wParam = msg.Substring(0, split);
+ var lParam = msg.Substring(split + 1, msg.Length - split - 1);
+
+ switch (wParam)
+ {
+ case PipeMessages.RunAndClose:
+ Application.Current.Dispatcher.BeginInvoke(
+ new Action(() => ViewWindowManager.GetInstance().RunAndClosePreview()),
+ DispatcherPriority.ApplicationIdle);
+ return false;
+ case PipeMessages.Invoke:
+ Application.Current.Dispatcher.BeginInvoke(
+ new Action(() => ViewWindowManager.GetInstance().InvokePreview(lParam)),
+ DispatcherPriority.ApplicationIdle);
+ return false;
+ case PipeMessages.Toggle:
+ Application.Current.Dispatcher.BeginInvoke(
+ new Action(() => ViewWindowManager.GetInstance().TogglePreview(lParam)),
+ DispatcherPriority.ApplicationIdle);
+ return false;
+ case PipeMessages.Close:
+ Application.Current.Dispatcher.BeginInvoke(
+ new Action(() => ViewWindowManager.GetInstance().ClosePreview()),
+ DispatcherPriority.ApplicationIdle);
+ return false;
+ case PipeMessages.Quit:
+ return true;
+ default:
+ return false;
+ }
+ }
+
~PipeServerManager()
{
Dispose();
diff --git a/QuickLook/Plugin/ContextObject.cs b/QuickLook/Plugin/ContextObject.cs
index 67dac49..280e7ee 100644
--- a/QuickLook/Plugin/ContextObject.cs
+++ b/QuickLook/Plugin/ContextObject.cs
@@ -209,7 +209,7 @@ namespace QuickLook.Plugin
/// Is this indicates a error?
public void ShowNotification(string title, string content, bool isError = false)
{
- TrayIconManager.GetInstance().ShowNotification(title, content, isError);
+ TrayIconManager.ShowNotification(title, content, isError);
}
///
diff --git a/QuickLook/TrayIconManager.cs b/QuickLook/TrayIconManager.cs
index 30d3b1a..1c7a416 100644
--- a/QuickLook/TrayIconManager.cs
+++ b/QuickLook/TrayIconManager.cs
@@ -66,25 +66,26 @@ namespace QuickLook
_icon.Visible = false;
}
- public void ShowNotification(string title, string content, bool isError = false, int timeout = 5000,
+ public static void ShowNotification(string title, string content, bool isError = false, int timeout = 5000,
Action clickEvent = null,
Action closeEvent = null)
{
- _icon.ShowBalloonTip(timeout, title, content, isError ? ToolTipIcon.Error : ToolTipIcon.Info);
- _icon.BalloonTipClicked += OnIconOnBalloonTipClicked;
- _icon.BalloonTipClosed += OnIconOnBalloonTipClosed;
+ var icon = GetInstance()._icon;
+ icon.ShowBalloonTip(timeout, title, content, isError ? ToolTipIcon.Error : ToolTipIcon.Info);
+ icon.BalloonTipClicked += OnIconOnBalloonTipClicked;
+ icon.BalloonTipClosed += OnIconOnBalloonTipClosed;
void OnIconOnBalloonTipClicked(object sender, EventArgs e)
{
clickEvent?.Invoke();
- _icon.BalloonTipClicked -= OnIconOnBalloonTipClicked;
+ icon.BalloonTipClicked -= OnIconOnBalloonTipClicked;
}
void OnIconOnBalloonTipClosed(object sender, EventArgs e)
{
closeEvent?.Invoke();
- _icon.BalloonTipClosed -= OnIconOnBalloonTipClosed;
+ icon.BalloonTipClosed -= OnIconOnBalloonTipClosed;
}
}
diff --git a/QuickLook/ViewWindowManager.cs b/QuickLook/ViewWindowManager.cs
index 4918ce8..4a06c98 100644
--- a/QuickLook/ViewWindowManager.cs
+++ b/QuickLook/ViewWindowManager.cs
@@ -20,8 +20,6 @@ using System.Diagnostics;
using System.IO;
using System.Runtime.ExceptionServices;
using System.Windows;
-using System.Windows.Forms;
-using System.Windows.Threading;
using QuickLook.Helpers;
using QuickLook.Plugin;
@@ -32,7 +30,7 @@ namespace QuickLook
private static ViewWindowManager _instance;
private MainWindowTransparent _currentMainWindow;
- private string _path = string.Empty;
+ private string _invokedPath = string.Empty;
private MainWindowNoTransparent _viewWindowNoTransparent;
private MainWindowTransparent _viewWindowTransparent;
@@ -51,37 +49,7 @@ namespace QuickLook
ClosePreview();
}
- internal void InvokeRoutine(KeyEventArgs kea, bool isKeyDown)
- {
- Debug.WriteLine($"InvokeRoutine: key={kea.KeyCode},down={isKeyDown}");
-
-
- if (isKeyDown)
- switch (kea.KeyCode)
- {
- case Keys.Enter:
- RunAndClosePreview();
- break;
- }
- else
- switch (kea.KeyCode)
- {
- case Keys.Up:
- case Keys.Down:
- case Keys.Left:
- case Keys.Right:
- SwitchPreview();
- break;
- case Keys.Space:
- TogglePreview();
- break;
- case Keys.Escape:
- ClosePreview();
- break;
- }
- }
-
- internal void RunAndClosePreview()
+ public void RunAndClosePreview()
{
if (_currentMainWindow.Visibility != Visibility.Visible)
return;
@@ -103,7 +71,7 @@ namespace QuickLook
_currentMainWindow.RunAndHide();
}
- internal void ClosePreview()
+ public void ClosePreview()
{
if (_currentMainWindow.Visibility != Visibility.Visible)
return;
@@ -112,66 +80,22 @@ namespace QuickLook
_currentMainWindow.BeginHide();
}
- private void TogglePreview()
+ public void TogglePreview(string path)
{
if (_currentMainWindow.Visibility == Visibility.Visible)
- {
ClosePreview();
- }
else
- {
- _path = NativeMethods.QuickLook.GetCurrentSelection();
- InvokeViewer();
- }
- }
-
- private void SwitchPreview()
- {
- if (_currentMainWindow.Visibility != Visibility.Visible)
- return;
-
- // if the switch has been done by SwitchPreviewRemoteInvoke, we'll not do anything
- var select = NativeMethods.QuickLook.GetCurrentSelection();
- if (_path == select)
- return;
-
- _path = select;
-
- Debug.WriteLine($"SwitchPreview: {_path}");
-
- InvokeViewer();
- }
-
- private void SwitchPreviewRemoteInvoke(HeartbeatEventArgs e)
- {
- // if the switch has been done by SwitchPreview, we'll not do anything
- if (e.FocusedFile == _path)
- return;
-
- if (string.IsNullOrEmpty(e.FocusedFile))
- return;
-
- Debug.WriteLine($"SwitchPreviewRemoteInvoke: {e.FocusedFile}");
-
- _currentMainWindow?.Dispatcher.BeginInvoke(new Action(SwitchPreview), DispatcherPriority.ApplicationIdle);
+ InvokePreview(path);
}
private void RunFocusMonitor()
{
- if (!FocusMonitor.GetInstance().IsRunning)
- {
- FocusMonitor.GetInstance().Start();
- FocusMonitor.GetInstance().Heartbeat += SwitchPreviewRemoteInvoke;
- }
+ FocusMonitor.GetInstance().Start();
}
private void StopFocusMonitor()
{
- if (FocusMonitor.GetInstance().IsRunning)
- {
- FocusMonitor.GetInstance().Stop();
- FocusMonitor.GetInstance().Heartbeat -= SwitchPreviewRemoteInvoke;
- }
+ FocusMonitor.GetInstance().Stop();
}
internal void ForgetCurrentWindow()
@@ -186,33 +110,27 @@ namespace QuickLook
_currentMainWindow = _viewWindowTransparent;
}
- internal bool InvokeViewer(string path = null, bool closeIfSame = false)
+ public void InvokePreview(string path)
{
- if (closeIfSame)
- if (_currentMainWindow.Visibility == Visibility.Visible && path == _path)
- {
- ClosePreview();
- return false;
- }
+ if (string.IsNullOrEmpty(path))
+ return;
- if (path != null)
- _path = path;
+ if (_currentMainWindow.Visibility == Visibility.Visible && path == _invokedPath)
+ return;
- if (string.IsNullOrEmpty(_path))
- return false;
- if (!Directory.Exists(_path) && !File.Exists(_path))
- return false;
+ if (!Directory.Exists(path) && !File.Exists(path))
+ return;
+
+ _invokedPath = path;
RunFocusMonitor();
- var matchedPlugin = PluginManager.GetInstance().FindMatch(_path);
+ var matchedPlugin = PluginManager.GetInstance().FindMatch(path);
- BeginShowNewWindow(matchedPlugin);
-
- return true;
+ BeginShowNewWindow(path, matchedPlugin);
}
- private void BeginShowNewWindow(IViewer matchedPlugin)
+ private void BeginShowNewWindow(string path, IViewer matchedPlugin)
{
_currentMainWindow.UnloadPlugin();
@@ -224,22 +142,22 @@ namespace QuickLook
if (!ReferenceEquals(oldWindow, _currentMainWindow))
oldWindow.BeginHide();
- _currentMainWindow.BeginShow(matchedPlugin, _path, CurrentPluginFailed);
+ _currentMainWindow.BeginShow(matchedPlugin, path, CurrentPluginFailed);
}
- private void CurrentPluginFailed(ExceptionDispatchInfo e)
+ private void CurrentPluginFailed(string path, ExceptionDispatchInfo e)
{
var plugin = _currentMainWindow.Plugin.GetType();
_currentMainWindow.BeginHide();
- TrayIconManager.GetInstance().ShowNotification("", $"Failed to preview {Path.GetFileName(_path)}", true);
+ TrayIconManager.ShowNotification("", $"Failed to preview {Path.GetFileName(path)}", true);
Debug.WriteLine(e.SourceException.ToString());
Debug.WriteLine(e.SourceException.StackTrace);
if (plugin != PluginManager.GetInstance().DefaultPlugin.GetType())
- BeginShowNewWindow(PluginManager.GetInstance().DefaultPlugin);
+ BeginShowNewWindow(path, PluginManager.GetInstance().DefaultPlugin);
else
e.Throw();
}