The mirror
A shared window has to stay on screen to keep producing frames. That normally means you cannot work in front of it. The mirror is a second, always-on-top window showing the same page — so the real one can be buried while you carry on.
What it is#
Turn a Chrome window into a second window that floats above everything else. The original stays where it is; the floating copy shows the same page and stays on top while you work in another app.
You would want it when a site is recording your screen. The window it is recording has to stay visible to keep producing frames, so normally you cannot put anything in front of it. With the mirror you can — bury the real window, watch the floating copy, and the site never notices.
What you can do in it#
| Move and resize it | Drag it anywhere, to any size. It stays above other windows. |
| Click and scroll in it | On by default. Clicks and scrolls go to the real page. |
| Type in it | No. Typing is not forwarded — click into the real window for that. |
| Hide the browser chrome | On by default: the tab strip, the address bar and Chrome's "Sharing this tab" indicator are cropped out, so what floats is the page and nothing else. |
| Cover it up | Yes. A covered mirror keeps updating; so does the window it is copying. |
| Mirror more than one window | No. One at a time. |
All three of those switches are in Settings in Perch's own window.
Starting and stopping one#
Open Perch. Every Chrome window it can see is listed with its size; press Mirror on the one you want. That row then shows Mirroring and a Stop.
Only a Chrome that Perch started carries the extension, so that is the Chrome worth mirroring. If the list is empty, Perch has not started one yet and the window tells you so.
How a covered window still produces frames#
Both platforms keep an offscreen surface per window, and the mirror reads from that surface rather than from the screen.
| macOS | Windows | |
|---|---|---|
| Capture API | SCContentFilter(desktopIndependentWindow:) | Windows.Graphics.Capture |
| Covered window | captures | captures |
| Minimised window | captures | cannot capture |
| Permission required | screen recording | none |
So burying the shared window behind a full-screen editor is fine on either platform. Minimising it is not, on Windows — see Limits.
The Chrome throttling problem#
Capture keeping up is not the same as the browser keeping up.
On Windows only, Chrome computes native window occlusion and stops rendering the foreground tab when its window is completely covered — precisely the failure the mirror exists to prevent. The capture stays healthy and delivers the same still frame forever, which looks exactly like a bug in the mirror.
Because Perch launches Chrome itself, it adds two switches:
--disable-backgrounding-occluded-windows
--disable-features=CalculateNativeWinOcclusionmacOS Chrome does not throttle covered windows and needs neither.
Page-only cropping#
The mirror shows the page, not the browser. The crop is stored as fractions of the window rather than pixels:
page: x=0.000 y=0.087 w=1.000 h=0.913Fractions survive a window resize, a display change and a zoom change; pixel offsets do not. The geometry is measured through the browser itself and is zoom-aware, so a page at 150% crops correctly.
On Windows the crop is applied to the window's extended frame bounds rather than GetWindowRect, because the latter includes an invisible resize border several pixels wide and would shift the whole crop.
Clicking and scrolling through it#
The mirror is not a picture. Clicks and scrolls land on the real page, forwarded as protocol input events, so you can drive the shared tab from the mirror while the real window stays buried.
Verifying it yourself#
The Windows build ships a self-test that drives the whole path and prints numbers rather than asking you to look at it:
Perch.exe --selftest-mirrorIt reports frame counts visible, covered and minimised, the crop it computed, and whether scroll forwarding reached the page. A healthy run looks like:
visible: 100 frames, 59 distinct, non-black 100 %
occluded: 102 frames, 60 distinct, scrollY 900 -> 1800
minimised: 0 frames (IsIconic=True)
restored: 83 frames
RESULT: PASSZero frames is not always a failure
Windows capture is change-driven: a completely static window produces no new frames because nothing has changed. The self-test animates its own page for exactly this reason. A frozen mirror on a static page is usually the page, not the mirror.