Skip to content

Releases: Adstrax/Quicklook-Next

QuickLook-Next 5.5.1

Choose a tag to compare

@Adstrax Adstrax released this 27 Sep 03:01

English-first, including the text you see when a translation is missing

The repository reads English now, not just the README: the changelog, the three research notes under
docs/, every script (test.ps1, bench.ps1, Scripts\*) and the comments that were still Chinese
in the C#/XAML sources. The Chinese changelog and README live on as CHANGELOG.zh-CN.md and
README.zh-CN.md, and the three Chinese screenshots moved to docs/screenshots/zh-CN/.

The user-visible half of that is what this release is really about. Several strings in the app
were Chinese failsafes - the text the translation helper falls back to when a key is missing. That
is exactly the bug reported against 5.0.1, where an English user saw a Chinese update dialog:

  • the update dialog (Software Update, Update now, Skip this version, ...) and the download
    progress panel;
  • the "the WebView2 component failed to initialize" notice;
  • the "this document cannot be read" pages behind the Office and Markdown previews;
  • the DbViewer password prompt, and the font previewer's messages.

They now mirror the en block of Translations.config, so a missing key can no longer drop an
English UI back to Chinese.

Still Chinese, on purpose

  • the ten Translations.config language packs, so switching to Chinese still gives you a Chinese UI;
  • the usage note shipped as Readme.txt;
  • the OCR test data - those strings exist to test Han word joining and full-width punctuation, so
    translating them would delete the coverage.

Verification

  • Unit tests 94/94; the build is clean (0 warnings, 0 errors).
  • No behaviour change outside text: this release touches comments, script output and fallback
    strings. The only functional edits are the fallback values themselves.
  • The packaged build reads version 5.5.1 in its file properties.

Upgrading

Version 5.5.1. Automatic update installs straight over the top; UserData (settings, plugins,
caches) is untouched.

QuickLook-Next 5.5.0

Choose a tag to compare

@Adstrax Adstrax released this 26 Sep 12:22

Mixed-DPI placement is testable now, not just "trusted"

5.0.10 and 5.2.0 fixed two upstream issues —#827
(the preview window spanned several monitors on mixed-scaling setups) and
#1956 (Markdown kept the old scale after a
display-scaling change). The machine in that report has two screens; the development machine has
one, so the evidence stopped at "the maths is right and a single screen behaves as before".

The placement rule is a pure function now. The 9/10 layout in ViewerWindow (grow or shrink
around the old centre, anchor on the old edge, pull back inside) moved to
QuickLookNext/Helpers/WindowPlacement, so mixed-DPI geometry can be tested without a second
screen. Four new unit tests use the geometry from that bug report (4K at 250% next to 1080p at
100%):

  • a window in the left third keeps its left edge;
  • a window in the right/bottom third keeps its right/bottom edge;
  • a window in the middle is pushed back inside;
  • and the full pipeline —clamp the size to the screen, then place it— puts a 2600x1400 DIP
    window clamped to 1920x1080 at (0,0) with all four edges inside.

Writing those tests turned up a real edge case: the right/bottom anchors position the window
from the old right/bottom edge, so a window that grows a lot is pushed off the opposite side
(measured: a window clamped to the width of a 250% panel hung 72 px off the left edge). Placement
now pulls the result back inside once more at the end. It is a no-op whenever the window fits, so
the anchor behaviour is unchanged.

New: /test-monitor-refit (a per-screen report)

For checking on real hardware. It runs the same sizing and placement functions the viewer uses,
once per screen, and writes <smokeDir>\monitor-refit.txt. On the development machine (single
3072x1920 @200%):

monitors=1
primary=\\.\DISPLAY1

[0] \\.\DISPLAY1 primary=True
    boundsPx=(0,0,3072,1920) workPx=(0,0,3072,1920) scale=2 workDip=1536x960
    image 4289x631 @0.8 -> 1228.8x180.8 dip = 2458x362 px
    window 2600x1400 dip -> clamped 1536x960 dip = 3072x1920 px
    placement from (1843,960,768,384) -> (0,0) inside=True

Every screen gets a block like that; the only thing to check is inside=True. The full recipe
(including how to read the placement log of /test-preview-diag) is in
docs/research-mixed-dpi.md.

The package usage note is Readme.txt now

Every other file in the extracted package has a Latin name — QuickLook-Next.exe,
Translations.config, lib\, runtimes\, QuickLook.Plugin\ — and the one Chinese filename stood
out in the listing and was awkward to type in a shell. The content is unchanged: how to start it,
the .NET runtime requirement, how updates work, where the data and logs live, and the optional
switches.

Verification

  • Unit tests 94/94 (four new placement cases).
  • Single-screen baseline unchanged: the 6000x4000 image still lands at
    1154x770 DIP / 2308x1540 px @(382,190), pixel for pixel with the 5.0.10 record — this was an
    equivalent refactor, not a behaviour change.
  • The packaged build itself ran /test-monitor-refit and image/PDF/Markdown previews with an empty
    log; the in-package version reads 5.5.0 and the root contains Readme.txt.
  • Known limitation: the real mixed-DPI behaviour still needs a multi-screen machine (use the switch
    above); one screen cannot reproduce it.

Upgrading

Version 5.5.0. Behaviour is identical to 5.4.0 (low memory mode, plugin search, OCR and the
accessibility work are unchanged) — this release is about verifiability and packaging consistency.
Automatic update installs straight over the top.

QuickLook-Next 5.4.0

Choose a tag to compare

@Adstrax Adstrax released this 26 Sep 11:39

Plugin manager: a search box

25 plugins are past the point where scrolling is a search interface. The box sits under the title,
the caret is already in it when the panel opens, and typing filters name and description as you
go:

  • with matches, the status line reads "3 of 25 shown.";
  • with none, "No plugin matches “xxx”.";
  • Esc clears the filter first, closes the panel second;
  • Tab cycles inside the panel instead of walking into the rest of the app.

Fixed: the top bar blinked while the pointer rested on it

Two mechanisms were fighting: the bar's show animation started a "hide after 1 s" when it
finished, while a 100 ms poll re-showed the bar the moment the pointer was inside the top zone —
so with the pointer parked on the bar it faded out and back in forever. It had always done that; it
only became visible now because the scrim added in 5.3.0 makes the fade obvious.

Visibility is one rule again: the bar is shown while the pointer is in the top zone and hidden
once it leaves
(with the ~1 s grace it always had, so brushing past it does not flash). Measured
from the diagnostic log:

scenario shows hides
pointer parked on the bar for 6 s 1 0
pointer moved away for 3 s 1 1

Before the fix it re-showed once per second. The decision lives in Helpers/TopBarVisibility with a
unit test behind it.

Accessibility: keyboard focus, reduced motion, screen-reader names

  • Visible keyboard focus. The panel buttons had no focus state at all (the custom templates ate
    the system focus rectangle); they now draw an accent outline when focused.
  • Reduced motion is honoured. The caption bar fade, the first content fade and the window show
    transition all check Windows' animation setting (Settings → Accessibility → Visual effects). Turn
    it off and they appear instantly; the app's own ShowWindowTransition option still applies on top
    (both have to allow it). The busy spinner is deliberately untouched — that is information, not
    decoration.
  • Screen-reader names. The preview caption is icon-only, so every button carries an
    AutomationName taken from its tooltip; the panel buttons get one from their label (a custom
    template hides the content text from assistive tech), and the plugin manager's uninstall button
    names the plugin it removes.

Also: one button template instead of four

The update prompt, the download panel, data & cache and the OCR panel each carried a copy of the
same button template (20 lines × 4) — which is exactly how they ended up with three hover
treatments and no focus state. They now share Helpers/PanelStyles (hover, press, focus ring and
the opacity helper).

Verification

  • Unit tests 90/90 (three new: the animation-switch combination, the top-bar visibility rule,
    and a wiring check).
  • Search measured: typing mark leaves MarkdownViewer with "1 of 25 shown."; Esc restores the
    full list.
  • Focus ring measured: two Tabs land on the close button with an accent outline.
  • Packaged build ran image and Markdown previews with an empty log; in-package version 5.4.0.

Upgrading

Version 5.4.0. Functional behaviour is the same as 5.3.0 (low memory mode, OCR and the preview
sizing logic are untouched); this release is plugin search, accessibility, and the top-bar flicker
fix. Automatic update installs straight over the top.

QuickLook-Next 5.3.0

Choose a tag to compare

@Adstrax Adstrax released this 26 Sep 10:48

Readability: no more washed-out panels on a bright wallpaper

The material itself is untouched — the tray menu keeps the 30% WCA acrylic it was tuned to. What
changed is the surfaces that are read rather than scanned: the plugin manager, the update prompt,
the download panel, data & cache and the OCR panel move to a 45% panel tint, and text-heavy
areas sit on a content plate (a white card in the light theme, a soft black one in the dark
theme). The plugin list and the OCR text box are the first users.

Secondary text was raised from #9E9E9E / #7A7A7A to #C8C8C8 / #5C5C5C. It used to assume a
solid background, which is exactly why version numbers and dialog body text disappeared on a bright
wallpaper in the dark theme.

One fallback that was always missing is in too: when Windows' transparency effects are off, these
panels become solid.
DWM stops blurring in that state, so an acrylic surface degenerates into a
30–45% tint — worse than having the blur. They now fall back to the theme's own surface colour.

Preview caption bar

  • A gradient scrim behind the bar (theme-aware). The image viewer switches the bar's glass off,
    which left white icons floating directly on the picture — "open with" and "extract text" were
    already hard to see on light content.
  • The two left buttons lost their "big glyph + 0.25-scaled badge" construction and are single
    glyphs whose active state is the accent colour
    (pin to top: the arrow turns accent; prevent
    closing: the pin fills and turns accent). That badge trick was the only place in the app using it
    and it read as noise at 100% scaling.
  • The bar is grouped: file actions (share / open / open with / reload / OCR / more) and window
    actions (theme / maximise / close), separated by a 1 px hairline.
  • The title has a hierarchy: the "6000x4000:" prefix is secondary, the file name primary.
    Button hover went from a square fill to the app's 4 px rounded language.

Plugin manager

  • A glyph per family (image / video / document / PDF / font / archive / table / code /
    certificate / mail …) instead of 25 identical puzzle pieces.
  • The per-row "Built-in" badge is gone (the header already counts them); only user-installed plugins
    are marked "User".
  • ChmViewer 0.0.0.0 is no longer shown — that is a plugin without an AssemblyVersion, and it read
    like a defect in the panel.
  • The list sits on a content plate, and the row icons are quieter (they used to be bright white
    squares with grey glyphs).

Tray menu

  • The icon column is a fixed 16 px grid: every glyph has a different advance width, so the two
    sections used to start a few pixels apart.
  • The version at the top is no longer dimmed to 50% — it was almost invisible on a light wallpaper.

Verification

  • Unit tests 87/87.
  • Six surfaces checked as screenshots: preview window, tray menu, plugin manager, update prompt,
    data & cache, OCR.
  • The packaged build ran image and Markdown previews with an empty log; in-package version 5.3.0.
  • Honest limitation: the machine's wallpaper is dark, so the extreme "bright wallpaper + dark theme"
    case is guaranteed by construction (content plate + 45% panel tint + brighter secondary text)
    rather than observed here.

Upgrading

Version 5.3.0. This is a look-and-feel update; behaviour is identical to 5.2.0 (low memory mode,
OCR and the preview sizing logic are unchanged). Automatic update installs straight over the top.

QuickLook-Next 5.2.0

Choose a tag to compare

@Adstrax Adstrax released this 23 Sep 09:39

New: low memory mode (tray menu → Options)

This release answers "idle memory looks high". Measured, it is not a leak: it is two warm-ups that
trade memory for a fast first preview, and they are a switch now.

Idle memory, measured on one machine (single 200% display, nothing previewed, sampled after the app
had settled):

configuration private bytes working set
both warm-ups off (low memory mode) 64 MB 130 MB
preview window warmed only 112–118 MB 199 MB
plus the two most-used preview families (default) 169–179 MB 258–272 MB

The warm-ups buy ~200 ms on the very first preview (window) and 100–200 ms on the first preview of
each family (measured: text 289 → 96 ms, image 170 → 100 ms). With low memory mode on, neither
runs from the next start, idle memory returns to the 61–64 MB baseline, and the only cost is one
slower first preview per format. Toggling it shows a short note, because the switch only affects
startup.

The two lower-level settings behind it (WarmUpPreviewFamilies, WarmUpFamilyCount) and the table
above are documented in OPTIONS.md.

Something else this investigation turned up (deliberately not changed, reported instead):
memory does not only start high, it also grows with what you have previewed and stays there.
With default settings: 185 MB idle, 249–262 MB after one Markdown preview, and it does not come back
down. Chromium itself exits within a few seconds of the preview closing (the count of
msedgewebview2 processes belonging to this app's profile is 0 after 12 s) — so what stays is
in-process: the managed large object heap (34 MB measured), WPF's text and font caches, and the
plugins' native libraries. Low memory mode behaves the same way: 66 MB idle → 183 MB after
Markdown → 238 MB after an image. It is a "used once, kept" cache rather than a per-preview leak
(the earlier 20 open/close cycles flattened out at 318 → 321 → 320 → 318 MB), and a good part of it
is file mappings the OS can reclaim under pressure. Going lower would mean releasing content when a
preview closes and forcing a collection, which makes the next preview slower — left for a later
release.

Fixed: the preview did not re-measure its content after the window moved to another screen

Two sides of the same thing:

  • dragging the preview to another monitor (same scaling, different resolution) only clamped the
    position, it never re-measured the plugin's content size;
  • upstream #1956: after changing the display
    scaling
    , a Markdown preview laid its content out for the old scale, so the page was smaller than
    the window.

Now:

  1. the plugin's own "fit to the screen" question is asked again — the host remembers the last
    SetPreferredSizeFit request and re-runs it against the new screen whenever the window lands on
    another monitor or the resolution/scaling changes, then clamps to that screen. A size the user
    dragged themselves still wins, and fixed-size plugins (the info panel) are unaffected.
  2. WebView2 follows the new scale — a Chromium control keeps the scaling it was created with
    (that is the cause of #1956), so a scaling change discards every parked control, and the panel
    that is on screen rebuilds and reloads its content.

Honest limitation: this machine has one screen and no mixed-scaling setup, so the multi-screen
behaviour could not be reproduced here. The evidence offered is the code path, the parts that are
unit tested, and the /test-preview-diag placement log (dip/px/at/monitorPx/desktopDip). On a
real machine, change the scaling or drag the preview to another screen and check
preview-rect.txt: the window must stay inside monitorPx and its size must follow the new screen.

Fixed: circled numbers are no longer reported as wrong digits

Measured (clean synthetic page + a real one):

  • the engine cannot read circled glyphs: ①–⑤ and ❶–❺ both come back empty;
  • cropping a single glyph, inverting it, enlarging it to 220 px and recognising it on its own is
    still empty (so recovering the digit is not possible);
  • on a real page, a filled ① was reported as 0 — worse than empty, because it invents a number the
    picture does not contain.

Since it cannot be read back, do not print something wrong: a lone 0/O/o in a disc-shaped
box
is now treated as an unreadable list marker and dropped. Real digit glyphs are taller than
they are wide (aspect 0.4–0.7) and never match. Measured on that page: 4 glyphs filtered, not one
character of the body text lost; English and mixed-language images have zero false positives
(filtered=0 in the diagnostic). /test-ocr now reports a filtered= count.

Look-alike characters ("亲戚" read as "亲威" on that page) are a model limitation: re-running the
same page at 2× made that line worse, so there is no dictionary-based "correction" here — that would
only change the user's own words into something else.

Verification

  • Unit tests 87/87 (nine new: low memory mode 3, plugin re-fit 3, scale broadcast 1, circled
    glyphs 2).
  • End to end: 64 MB idle in low memory mode (179 MB by default) with no warm-up diagnostic written;
    png / pdf / md / mp4 all land correctly; the Markdown (WebView2) path logs nothing; the circled
    glyph page filters 4 and the English/mixed images are untouched.
  • Known limitation: the real multi-screen / mixed-scaling behaviour cannot be reproduced on one
    screen — see above.

Upgrading

Version 5.2.0. Default behaviour matches 5.1.0 (warm-ups on, first-preview speed unchanged).
Users who would rather have the memory back open tray menu → Options → Low memory mode; it applies
from the next start. Automatic update installs straight over the top.

QuickLook-Next 5.1.0

Choose a tag to compare

@Adstrax Adstrax released this 19 Sep 07:27

OCR: mixed-language images no longer lose whole lines

5.0.11 let OCR pick its own language engine, but that was one engine per page: on a page that
has both Chinese and English, the engine with the better overall score won the whole page and the
other language's lines were dropped entirely. Measured on a small bilingual screenshot (English
heading + invoice line + Chinese contact line):

result
before 2 English lines, 67 characters, the Chinese line gone (even though the Chinese engine had read it)
after all 3 lines, 89 characters, the Chinese one being "联系人:张三电话 13800001111"

The rule is now per-line merging: the lines each engine reports are grouped by vertical position
(two boxes overlapping by more than half of the shorter one are the same line), each group keeps the
text that scored best inside it, and the groups are emitted top to bottom. A line that several
engines read appears once, and two stacked lines are never merged just because they are close.

OCR: small images are enlarged before recognition

The engine reads small text badly, and CJK worst of all. Measured on a 560×150 screenshot with 14 px
text:

Chinese line
as-is 联系人:张三电沽 138 佣佣 1 1 1 1
enlarged 2× 联系人:张三电话 13800001111 (identical to the same text rendered at 28 px)

So a picture whose longest side is under 1000 px is enlarged twice before recognition (still
inside the engine's per-side limit and the 16 MP cap); larger pictures are left alone — the
1264×1522 page from the report already reads well and scaling it would only cost time. Recognition
time is unchanged in practice: 1.06 s for the small image and 1.17 s for that page, app start
included.

Fixed: a preview request from Explorer could be dropped silently

The pipe server accepts one connection at a time and there is a real gap between two of them.
Forwarding a preview request used to try once (2 s timeout): hitting the gap meant nothing
happened at all — "I double-clicked and nothing came up" — and the second instance then decided it
was "already running" and showed a message box, for a perfectly valid path (roughly one in three in
automated runs). It now retries four times, 600 ms each (~3 s total), falls back to the message
box only when the running instance is genuinely stuck, and writes the failure to the log.

Fixed: the shipping build was still writing test diagnostics

The preview warm-up wrote warmup.txt into the temp folder on every start — its guard asked "is a
test directory set?", and that value is always true (the same trap as the update prompt fixed in
5.0.11). It is now written only with /test-warmup, and the smoke test passes that switch.

Improved: the log stops growing forever, and data & cache can clear it

  • Rotation: past 1 MB the diagnostic log moves to QuickLookNext.Exception.log.1 (one previous
    file is kept), so the log always holds "this session + the previous one". Measured: after
    injecting 1,064,420 bytes the next write moved the whole file aside and started a 1,296-byte one.
  • Clear log: a new button in the data & cache panel (the log is data, so it is not deleted by
    "clear cache"); a file in use reports "try again later" instead of failing, and the numbers
    refresh immediately. The strings exist in English, Simplified and Traditional Chinese.

Verification

  • Unit tests 78/78 (nine new: per-line merging 4, small-image upscaling 2, log clearing and
    rotation 3).
  • End to end: the bilingual screenshot (all 3 lines), the Chinese page from the report (317
    characters, character-perfect), an English test image (word-perfect).
  • The packaged build itself re-ran the bilingual image with the same result; in-package version
    5.1.0.

Upgrading

Version 5.1.0. Worth taking: screenshots that mix Chinese and English used to lose lines, and
small-text screenshots recognise Chinese noticeably better now. Automatic update installs straight
over the top.

QuickLook-Next 5.0.11

Choose a tag to compare

@Adstrax Adstrax released this 19 Sep 03:08

Fixed: Chinese images came out as gibberish — OCR now picks the right engine

Windows OCR works per language pack. The code used the one engine the user profile points at,
which on a Chinese system with an English UI (or the other way round) is exactly the wrong one: a
full page of Chinese was handed to the English engine. Measured on the page from the report
("不要去回应负能量"):

engine result own-script chars / total
en-US (what was used) aaaaeæa / o / (fifi, / (Räih(+/Åäih, 20 / 27
zh-Hans-CN the whole page, character-perfect 257 / 288

Every installed engine is now tried, and the answer whose characters belong to that language's
script wins (own script +10, foreign script −1, digits and punctuation neutral for everyone). Equal
scores — a picture of nothing but digits, say — keep the user's own language, and a single broken
language pack only writes a log line. English images are unaffected: on the same logic an English
test image scores 1280 for en-US against −126 for zh-Hans-CN.

Pasting improved as a side effect: the engine returns Chinese one glyph per "word" separated by
spaces, so copying used to give "不 要 去 回 应". Lines are now rebuilt by writing system — no
separator between CJK glyphs, full-width punctuation attached, spaces kept everywhere else
("使用 Windows 10 的设置"). Recognition takes about 1.1–1.3 s including app start; an excerpt of
the result:

不要去回应负能量
人生建议:不要去搭理一切负能量,回应就会与之纠缠受其损耗,拒绝自我折磨受罪。
我们不可避免地会遭遇一些带有负能量的人和事。包括朋友、父母、恋人、亲威等等,
如果你身边的人一直给你负能量,负面情绪,你最好的选择就是不要纠缠,不要回应。

Known engine limitations, untouched here: circled numbers ① ② come back as 0, and a few
look-alike characters are confused (the line above reads "亲戚" as "亲威").

Fixed: the update prompt closed itself after a few seconds

Clicking "Check for updates" showed the prompt, and about two seconds later it closed on its own —
without a click, and of course without starting an update.

The cause was a self-answering hook meant for automated tests: it decided "am I being tested?" from
"does a test directory exist?", and that directory always exists (it falls back to the system
temp folder), so the shipping prompt was closed by the timer as "ignore" too. The hook is now
driven only by its dedicated test switch, and the download panel's hook was closed off at the same
time (it has the same trap, it just had not been stepped on yet). The startup diagnostic also
reports update-prompt-hook= / update-progress-hook=, so a misfire is visible at a glance.

Verified with a new hidden switch that takes the real path but leaves the prompt alone: the
prompt was still on screen after 2 s and after 8 s, and the self-answering path used by the smoke
test still works.

Improved: "Extract text" moved from the More menu to the toolbar

With an image preview the toolbar has a scan icon directly (left of "More"), so the feature no
longer hides two clicks deep in a submenu; other formats do not show the button. The More-menu entry
is gone — one feature, one entry point.

Verification

  • Unit tests 69/69 (nine new: language scoring, script detection, Chinese/English/mixed
    joining).
  • End to end on the Chinese page and an English test image (320 characters correct on the first,
    word-perfect on the second).
  • The packaged build (portable layout) re-ran the Chinese recognition with the same result.

Upgrading

Version 5.0.11. Worth taking, especially for Chinese users: "Extract text" used to hand back
gibberish, and the update prompt disappeared before it could be clicked. Automatic update installs
straight over the top.

QuickLook-Next 5.0.10

Choose a tag to compare

@Adstrax Adstrax released this 19 Sep 02:46

Fixed: the preview window spanned several monitors (upstream #827)

On a laptop with a 4K panel at 250% next to an external 1080p screen at 100%, previewing a wide,
large image
on the external screen made the window stretch across all three monitors. Portrait
images and small images were fine, and so was the same image reached with the arrow keys.

The reason was that the monitor used to size the window and the monitor used to place it were not
the same one
:

  • the plugin measured against the monitor of the foreground window (Explorer);
  • the viewer positioned the window on the monitor the preview window itself was on.

A size measured on the foreground screen, once it lands on a screen with a higher scale factor, is
multiplied on the way into pixels (250% means 2.5×) — and a wide image, whose fit is limited by its
width, runs out of screen first. Portrait images are limited by height, which keeps a 10% margin, so
they looked fine. The placement code only ever clamped the position, never the size, which
is how the window ended up covering all three monitors.

Three places now agree on one screen

  1. The target screen is handed to the plugin at the start of every preview
    (ContextObject.HostDesktopSize); SetPreferredSizeFit() prefers it and only falls back to the
    old "current desktop" when it is unavailable.
  2. The size is clamped to the screen it will be placed on before it is applied — including
    hard-coded plugin sizes and size requests that arrive after the preview opened (a PDF measuring
    its page, for example). A size the user dragged themselves is not clamped; that is their
    intent.
  3. A scaling change re-fits the window: Windows keeps a window's physical size when it moves
    between screens, so the size in DIP changes; on a DPI change the window is clamped to the screen
    it is on now (and that correction is not remembered as the user's own size).

The arithmetic lives in the pure helper PreviewWindowSizing: it never enlarges, a ratio above
100% counts as 100%, and a ratio of 0 / negative / NaN or a failed desktop query (0×0) is treated as
"the whole screen" — none of them can collapse the preview to a zero-sized window.

Verification

  • Unit tests: 12 new, covering the two extreme screens from #827 (4K@250% = 1536×864 DIP,
    1080p@100% = 1920×1040 DIP) and the 4289×631 "wide and flat" shape: no enlargement when it
    already fits, no zero-sized window for invalid ratios or an unknown desktop, the clamp only ever
    shrinking, and an end-to-end case where a page measured on a 1080p screen would overflow a 4K
    screen but lands inside after clamping. Suite 60/60 (48 before).
  • No single-screen regression: this machine has one screen (1536×960 DIP @200%) and the
    6000×4000 image still lands at 2308×1540 @(382,190) — pixel for pixel the same as before the
    change, so this was a path replacement rather than a behaviour change. png / pdf / md previews
    keep the process alive and the window centred inside the screen.
  • Honest limitation: with one screen the real mixed-DPI effect cannot be reproduced here. The
    evidence above is "the maths is right + no single-screen regression + a diagnostic switch", not
    "seen fixed on a two-screen machine". The full analysis, a reproduction recipe and that limitation
    are in
    docs/research-mixed-dpi.md.

/test-preview-diag also records every placement into <smokeDir>\preview-rect.txt
(dip / px / at / monitorPx / desktopDip). On a mixed-DPI machine that file answers "is the
window completely inside monitorPx?" in one look; if anything is still off, attaching it to an
issue is enough to locate it.

Upgrading

Version 5.0.10. Recommended, especially for machines with monitors of different resolution or
scaling. Automatic update installs straight over the top.

QuickLook-Next 5.0.9

Choose a tag to compare

@Adstrax Adstrax released this 19 Sep 02:31

修复:打不开的视频会让整个应用崩溃

预览一个"媒体播放器打不开"的视频(损坏文件、0 字节文件、缺少解码器的容器)时,以前是整个 QuickLook 直接退出,而不是提示"这个视频打不开"。

原因很具体:视频插件的失败回调 MediaFailed 是播放器在自己的工作线程上抛出来的,而它开头两行就直接去改界面元素(清空缩略图)。从非 UI 线程碰界面会抛异常,这个异常落在没有捕获的工作线程上,进程就没了。

现在所有界面操作都在窗口的 UI 线程上执行,用户看到的是一句提示——"无法播放此视频。"——完整异常写进日志(顺便不再把原始堆栈糊在面板上)。

顺带做了一轮视频健壮性回归(22 个样本)

用 ffmpeg 生成了一整套样本,逐个预览并记录:出画面耗时、是否崩溃、是否无响应、是否报错。覆盖:

  • 容器/编码:MP4、MOV、MKV、AVI、WMV、WebM、TS、FLV、OGV;H.264、H.265(8-bit 与 10-bit)、AV1、VP9+Opus、MPEG-2、WMV2+WMA、Theora+Vorbis
  • 变体:4K、6 分钟长视频、竖屏、带旋转元数据、可变帧率、无音轨、纯音频(MP3/M4A)、中文+带空格路径、截断文件、0 字节文件

结果:22/22 全部正常出画面(299–1422 ms,中位数约 350 ms),0 崩溃、0 无响应;两个故意损坏的文件优雅报错并写日志。

也就是说,上游那几类"视频打不开"的报障(#1768、#1844、#1968)在我们这条基于 LAVFilters 的路径上没有复现。

回归工具随仓库(需要 ffmpeg):Scripts\make-video-matrix.ps1 生成样本,Scripts\run-video-matrix.ps1 逐个扫描并写结果;它对"应用被某个样本搞崩"的情况会自动重启实例,所以崩一次不会污染后面的样本。完整记录见 docs/research-video-matrix.md。

冒烟测试也加了守卫:把 test.mp4 截断成 test-corrupt.mp4 再预览,断言进程存活、且确实记录了错误日志(不需要 ffmpeg)。

升级说明

版本号 5.0.9。建议升级——之前遇到"文件坏掉 → 整个 QuickLook 消失"的问题就是这里。自动更新可直接覆盖安装。

QuickLook-Next 5.0.8

Choose a tag to compare

@Adstrax Adstrax released this 19 Sep 02:07

图片提取文字(OCR)

预览图片时,标题栏右侧「更多」菜单里新增 「提取文字(OCR)」:识别当前图片里的文字,结果显示在一个可选中、可一键复制的面板里。

OCR 面板

要点:

  • 用 Windows 自带的 OCR 引擎(Windows.Media.Ocr),不新增任何依赖;支持的语言取决于系统已安装的 OCR 语言包(本机实测 en-US 与 zh-Hans-CN 可用)。没装语言包时面板会提示去「设置 → 时间和语言 → 语言和区域」安装
  • 按行保留:识别结果按原图的行输出,方便直接粘贴到文档里
  • 大图自动缩放:单边不超过引擎上限 10000px、总量不超过 16 MP,超过则等比缩放后识别;同时遵循 EXIF 方向,手机照片不会横着识别
  • 只在当前预览由图片插件产出时出现该菜单项

实测:一张 1200×460 的样图,识别出 90 个字符、三行完整正确。新增 4 条单元测试覆盖解码尺寸策略,测试套件 48/48 通过。

升级说明

版本号 5.0.8。只新增一个菜单项与面板,不改动预览行为;自动更新可直接覆盖安装。