Release v0.6.38: avoid unnecessary RichEdit and cancel hidden history previews
This commit is contained in:
+2
-1
@@ -252,7 +252,7 @@ DWORD CALLBACK readStream(DWORD_PTR cookie, LPBYTE buffer, LONG size, LONG *read
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
std::string richPreview(const Clip &clip)
|
||||
std::string richPreview(const Clip &clip, bool plainFallback)
|
||||
{
|
||||
for (const auto &f : clip.formats)
|
||||
if (f.name == L"Rich Text Format" && f.data.size() <= 65536)
|
||||
@@ -276,6 +276,7 @@ std::string richPreview(const Clip &clip)
|
||||
{
|
||||
}
|
||||
}
|
||||
if (!plainFallback) return {};
|
||||
auto text = clip.text();
|
||||
if (text.size() > 4096)
|
||||
text.resize(4096);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#include "platform.h"
|
||||
namespace ks
|
||||
{
|
||||
std::string richPreview(const Clip &);
|
||||
std::string richPreview(const Clip &, bool plainFallback = true);
|
||||
HWND createRichText(HWND parent, int id, bool visible);
|
||||
bool setRichText(HWND, const std::string &);
|
||||
} // namespace ks
|
||||
|
||||
+34
-14
@@ -468,12 +468,17 @@ struct SearchResult
|
||||
uint64_t generation;
|
||||
std::vector<Entry> items;
|
||||
};
|
||||
struct TextPreview
|
||||
{
|
||||
std::string rtf;
|
||||
std::wstring plain;
|
||||
};
|
||||
struct PreviewResult
|
||||
{
|
||||
uint64_t generation;
|
||||
std::wstring id;
|
||||
Pixels pixels;
|
||||
std::string rtf;
|
||||
TextPreview text;
|
||||
};
|
||||
struct HistoryView
|
||||
{
|
||||
@@ -481,8 +486,9 @@ struct HistoryView
|
||||
std::vector<Entry> items;
|
||||
std::wstring rememberedSelection, rememberedTop;
|
||||
uint64_t generation{};
|
||||
std::shared_ptr<std::atomic<bool>> previewActive = std::make_shared<std::atomic<bool>>(true);
|
||||
std::map<std::wstring, Pixels> thumbnails;
|
||||
std::map<std::wstring, std::string> richTexts;
|
||||
std::map<std::wstring, TextPreview> richTexts;
|
||||
HWND rich{};
|
||||
std::set<std::wstring> pending;
|
||||
bool scrolling{};
|
||||
@@ -504,6 +510,8 @@ std::wstring selected(HWND w, HistoryView *v)
|
||||
}
|
||||
void search(HWND w, HistoryView *v)
|
||||
{
|
||||
v->previewActive->store(false);
|
||||
v->previewActive = std::make_shared<std::atomic<bool>>(true);
|
||||
v->closed = false;
|
||||
auto q = value(w, 101);
|
||||
auto generation = ++v->generation;
|
||||
@@ -532,23 +540,31 @@ void requestPreview(HWND w, HistoryView *v, const Entry &entry)
|
||||
if (v->thumbnails.contains(id) || v->richTexts.contains(id) || !v->pending.insert(id).second)
|
||||
return;
|
||||
auto generation = v->generation;
|
||||
auto active = v->previewActive;
|
||||
auto *app = v->app;
|
||||
app->enqueue(
|
||||
[w, app, id, generation, image]
|
||||
[w, app, id, generation, image, active]
|
||||
{
|
||||
if (!active->load()) return;
|
||||
auto result = new PreviewResult{generation, id, {}, {}};
|
||||
try
|
||||
{
|
||||
auto clip = app->history->load(id);
|
||||
if (!active->load()) { delete result; return; }
|
||||
if (image)
|
||||
result->pixels = decodeImage(clip, 208, 128);
|
||||
else
|
||||
result->rtf = richPreview(clip);
|
||||
else {
|
||||
result->text.rtf = richPreview(clip, false);
|
||||
if (result->text.rtf.empty()) {
|
||||
result->text.plain = clip.text();
|
||||
if (result->text.plain.size() > 4096) result->text.plain.resize(4096);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
}
|
||||
if (!PostMessageW(w, PreviewMessage, 0, (LPARAM)result))
|
||||
if (!active->load() || !PostMessageW(w, PreviewMessage, 0, (LPARAM)result))
|
||||
delete result;
|
||||
});
|
||||
}
|
||||
@@ -602,9 +618,13 @@ void drawHistoryRow(HWND w, HistoryView *v, const DRAWITEMSTRUCT &draw)
|
||||
if (!entry.image && !entry.files)
|
||||
{
|
||||
auto rich = v->richTexts.find(entry.id);
|
||||
if (rich != v->richTexts.end() && v->rich && !rich->second.empty())
|
||||
if (rich != v->richTexts.end() && rich->second.rtf.empty())
|
||||
text = (entry.pinned ? L"★ " : L"") + rich->second.plain;
|
||||
if (rich != v->richTexts.end() && !rich->second.rtf.empty() && !v->rich)
|
||||
v->rich = createRichText(w, 105, false);
|
||||
if (rich != v->richTexts.end() && v->rich && !rich->second.rtf.empty())
|
||||
{
|
||||
setRichText(v->rich, rich->second);
|
||||
setRichText(v->rich, rich->second.rtf);
|
||||
CHARFORMAT2W format{};
|
||||
format.cbSize = sizeof(format);
|
||||
format.dwMask = CFM_COLOR;
|
||||
@@ -825,14 +845,14 @@ LRESULT CALLBACK historyProc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
|
||||
visible.insert(v->items[i].id);
|
||||
if(v->items[i].id==result->id) { changed=intersection; repaint=true; }
|
||||
}
|
||||
if (!result->rtf.empty())
|
||||
v->richTexts[result->id] = std::move(result->rtf);
|
||||
if (!result->text.rtf.empty() || !result->text.plain.empty())
|
||||
v->richTexts[result->id] = std::move(result->text);
|
||||
else
|
||||
v->thumbnails[result->id] = std::move(result->pixels);
|
||||
trimHistoryPreviews(v->thumbnails,visible,32,HistoryThumbnailBudget,
|
||||
[](const Pixels &p) { return p.bgra.capacity(); });
|
||||
trimHistoryPreviews(v->richTexts,visible,32,HistoryRichTextBudget,
|
||||
[](const std::string &s) { return s.capacity(); });
|
||||
[](const TextPreview &s) { return s.rtf.capacity() + s.plain.capacity() * sizeof(wchar_t); });
|
||||
if(repaint) InvalidateRect(list,&changed,FALSE);
|
||||
return 0;
|
||||
}
|
||||
@@ -889,18 +909,19 @@ LRESULT CALLBACK historyProc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
|
||||
v->rememberedTop = top >= 0 && top < (int)v->items.size() ? v->items[top].id : L"";
|
||||
KillTimer(w, 1);
|
||||
v->closed = true;
|
||||
v->previewActive->store(false);
|
||||
++v->generation; // Discard search/preview results queued before closing.
|
||||
ShowWindow(w, SW_HIDE);
|
||||
SendDlgItemMessageW(w,102,LB_RESETCONTENT,0,0);
|
||||
std::vector<Entry>().swap(v->items);
|
||||
v->thumbnails.clear();
|
||||
v->richTexts.clear();
|
||||
if (v->rich)
|
||||
SetWindowTextW(v->rich, L"");
|
||||
if (v->rich) SetWindowTextW(v->rich, L"");
|
||||
v->pending.clear();
|
||||
return 0;
|
||||
}
|
||||
case WM_NCDESTROY:
|
||||
v->previewActive->store(false);
|
||||
disposeFont(w);
|
||||
v->app->historyWindow = nullptr;
|
||||
delete v;
|
||||
@@ -1702,7 +1723,6 @@ void showHistory(App &app, bool visible)
|
||||
HWND w = makeWindow(app, L"KSwitcher.History", L"Clipboard history", historyProc, 760, 500);
|
||||
app.historyWindow = w;
|
||||
windowLayoutState(w)->history = true;
|
||||
((HistoryView *)GetWindowLongPtrW(w, GWLP_USERDATA))->rich = createRichText(w, 105, false);
|
||||
label(w, L"&Search clipboard history", 16, 12, 500);
|
||||
edit(w, 101, 16, 38, 728);
|
||||
auto list = control(w, L"LISTBOX", L"",
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#include "platform.h"
|
||||
namespace ks
|
||||
{
|
||||
inline constexpr wchar_t AppVersion[] = L"0.6.37";
|
||||
inline constexpr wchar_t AppVersion[] = L"0.6.38";
|
||||
inline constexpr UINT UpdateMessage = WM_APP + 7;
|
||||
inline constexpr UINT UpdateCheckIntervalMs = 6 * 60 * 60 * 1000;
|
||||
inline constexpr UINT UpdateNotificationRetryMs = 5 * 60 * 1000;
|
||||
|
||||
Reference in New Issue
Block a user