Fix clipboard action under sta thread issue

This commit is contained in:
Jack251970 2024-12-19 16:34:32 +08:00
parent 532b5dc4c9
commit 3ab1fb15b6
4 changed files with 170 additions and 23 deletions

View file

@ -16,4 +16,7 @@ WM_KEYUP
WM_SYSKEYDOWN
WM_SYSKEYUP
EnumWindows
EnumWindows
OleInitialize
OleUninitialize

View file

@ -230,7 +230,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
[JsonIgnore]
public ObservableCollection<BuiltinShortcutModel> BuiltinShortcuts { get; set; } = new()
{
new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText),
new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", () => Win32Helper.StartSTATaskAsync(Clipboard.GetText).Result),
new BuiltinShortcutModel("{active_explorer_path}", "shortcut_active_explorer_path", FileExplorerHelper.GetActiveExplorerPath)
};

View file

@ -0,0 +1,141 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Windows.Win32;
namespace Flow.Launcher.Infrastructure
{
/// <summary>
/// Provides static helper for Win32.
/// Codes are edited from: https://github.com/files-community/Files.
/// </summary>
public static class Win32Helper
{
public static Task StartSTATaskAsync(Action action)
{
var taskCompletionSource = new TaskCompletionSource();
Thread thread = new(() =>
{
PInvoke.OleInitialize();
try
{
action();
taskCompletionSource.SetResult();
}
catch (System.Exception)
{
taskCompletionSource.SetResult();
}
finally
{
PInvoke.OleUninitialize();
}
})
{
IsBackground = true,
Priority = ThreadPriority.Normal
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return taskCompletionSource.Task;
}
public static Task StartSTATaskAsync(Func<Task> func)
{
var taskCompletionSource = new TaskCompletionSource();
Thread thread = new(async () =>
{
PInvoke.OleInitialize();
try
{
await func();
taskCompletionSource.SetResult();
}
catch (System.Exception)
{
taskCompletionSource.SetResult();
}
finally
{
PInvoke.OleUninitialize();
}
})
{
IsBackground = true,
Priority = ThreadPriority.Normal
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return taskCompletionSource.Task;
}
public static Task<T?> StartSTATaskAsync<T>(Func<T> func)
{
var taskCompletionSource = new TaskCompletionSource<T?>();
Thread thread = new(() =>
{
PInvoke.OleInitialize();
try
{
taskCompletionSource.SetResult(func());
}
catch (System.Exception)
{
taskCompletionSource.SetResult(default);
}
finally
{
PInvoke.OleUninitialize();
}
})
{
IsBackground = true,
Priority = ThreadPriority.Normal
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return taskCompletionSource.Task;
}
public static Task<T?> StartSTATaskAsync<T>(Func<Task<T>> func)
{
var taskCompletionSource = new TaskCompletionSource<T?>();
Thread thread = new(async () =>
{
PInvoke.OleInitialize();
try
{
taskCompletionSource.SetResult(await func());
}
catch (System.Exception)
{
taskCompletionSource.SetResult(default);
}
finally
{
PInvoke.OleUninitialize();
}
})
{
IsBackground = true,
Priority = ThreadPriority.Normal
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return taskCompletionSource.Task;
}
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
@ -117,35 +117,38 @@ namespace Flow.Launcher
ShellCommand.Execute(startInfo);
}
public void CopyToClipboard(string stringToCopy, bool directCopy = false, bool showDefaultNotification = true)
public async void CopyToClipboard(string stringToCopy, bool directCopy = false, bool showDefaultNotification = true)
{
if (string.IsNullOrEmpty(stringToCopy))
return;
var isFile = File.Exists(stringToCopy);
if (directCopy && (isFile || Directory.Exists(stringToCopy)))
await Win32Helper.StartSTATaskAsync(() =>
{
var paths = new StringCollection
var isFile = File.Exists(stringToCopy);
if (directCopy && (isFile || Directory.Exists(stringToCopy)))
{
stringToCopy
};
var paths = new StringCollection
{
stringToCopy
};
Clipboard.SetFileDropList(paths);
Clipboard.SetFileDropList(paths);
if (showDefaultNotification)
ShowMsg(
$"{GetTranslation("copy")} {(isFile ? GetTranslation("fileTitle") : GetTranslation("folderTitle"))}",
GetTranslation("completedSuccessfully"));
}
else
{
Clipboard.SetDataObject(stringToCopy);
if (showDefaultNotification)
ShowMsg(
$"{GetTranslation("copy")} {(isFile ? GetTranslation("fileTitle") : GetTranslation("folderTitle"))}",
GetTranslation("completedSuccessfully"));
}
else
{
Clipboard.SetDataObject(stringToCopy);
if (showDefaultNotification)
ShowMsg(
$"{GetTranslation("copy")} {GetTranslation("textTitle")}",
GetTranslation("completedSuccessfully"));
}
if (showDefaultNotification)
ShowMsg(
$"{GetTranslation("copy")} {GetTranslation("textTitle")}",
GetTranslation("completedSuccessfully"));
}
});
}
public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible;