v1.3.3 — the input hold was never actually on
The input hold was never actually on
Install this one. Reported in one sentence, and it undoes an assumption the whole design rested on:
"I could still move my mouse and type while you had my window."
A low-level hook is delivered to the message queue of the thread that installed it. The commands from the server arrive on the overlay's stdin thread — and that thread sits blocked in a read, with no message loop at all. So SetWindowsHookEx succeeded, returned a valid handle, and the callbacks were never dispatched. Windows drops such a hook after LowLevelHooksTimeout and says nothing.
Nothing failed. Nothing was logged. self_test reported the overlay as present, because it checked that the file existed. The pulse drew, the notification appeared, the block opened and closed — and the person's keyboard and mouse were free the entire time, while every layer above was certain they were held.
The fix is one line of architecture
The protocol thread now only records a wish; tick() — which runs on the message-loop thread — installs and removes the hooks. That is the one thread that can receive the callbacks, so it is the only correct place.
And it now says so. The overlay reports hooks:1 / hooks:0 back to the server, and set_guard block:'start' returns input_held. When Windows refuses the hooks, the reply says the screen is shared and to behave accordingly — instead of promising a hold that is not there.
Ending a block now tells you what came back
Found in the same live test: the release wrote its result into _RUECKGABE on every block, with a comment saying tools copy it into their reply. Nothing did. The claim "your focus is restored is a measurement, not a promise" was true of the measurement and false of the reporting.
set_guard block:'end' now returns handed_back:
| field | |
|---|---|
foreground_restored |
did the call succeed |
their_window |
the window this block owed them |
in_front_now |
what is actually in front, measured after the restore |
caret_restored |
did the text cursor come back with it |
attempts |
how many tries it took |
in_front_now is the one that matters. foreground_restored answers whether the call worked; in_front_now answers where the person is looking.
Third defect in this project found by the same rule: a function that does not report whether it worked will eventually stop working, and nobody will notice.
Two downloads — take the one for your AI
| Download | For | How |
|---|---|---|
pc-screen-control.mcpb |
Claude Desktop | Settings → Extensions → Advanced → Install extension |
pc-screen-control-gpt.zip |
ChatGPT desktop, Codex, Cursor, VS Code, Cline, Zed | Extract, double-click INSTALL-FOR-GPT.bat, restart |
Same server.py, same bundled libraries, same 34 tools. Only the wrapper differs.
Install
Claude: remove the old version first (Settings → Extensions), quit Claude completely including the tray icon, install the .mcpb, start twice. Run self_test — it should report 1.3.3, all green.
ChatGPT / Codex: extract the zip, double-click INSTALL-FOR-GPT.bat, restart ChatGPT.
Needs Windows and Python 3.9+ with "Add python.exe to PATH" ticked.
Verify the downloads (optional)
pc-screen-control.mcpb
SHA-256: 4c55954cfd2afa0393cab70f9404ed9bfb4c83b5a6d48e1bdab391101473272e
Size: 7762404 bytes
pc-screen-control-gpt.zip
SHA-256: 4bfe93bea4eb392e690b4487687b375f9fcb996954b3c5e3d096c89ec3cc0655
Size: 7668773 bytes