[PR #36] [MERGED] feat: clipboard enhancements and hotkey stability improvements #57

Closed
opened 2026-03-03 15:57:34 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/mrgoonie/winshot/pull/36
Author: @Vivusk
Created: 12/11/2025
Status: Merged
Merged: 12/12/2025
Merged by: @mrgoonie

Base: devHead: main


📝 Commits (10+)

  • ab8b183 Merge pull request #11 from mrgoonie/goon
  • bfae77e Merge pull request #18 from mrgoonie/goon
  • 8b82e2c chore(release): 1.1.0 [skip ci]
  • 38e1191 fix(app): restore window position after region capture
  • 03cf0fd feat(capture): add clipboard image paste support
  • 0f1a8d1 feat(capture): add multi-monitor region capture support
  • 1d683cc fix(hotkeys): resolve goroutine thread affinity causing hotkey registration failure
  • 4fbc7d6 chore: update generated bindings and documentation
  • 20ad92b feat(clipboard): auto-copy styled canvas instead of raw screenshot
  • 22da2ac feat(overlay): implement native Win32 region selection overlay

📊 Changes

23 files changed (+2325 additions, -624 deletions)

View changed files

📝 .claude/active-plan (+1 -1)
📝 CHANGELOG.md (+28 -0)
📝 app.go (+123 -101)
docs-manager-251211-clipboard-capture.md (+129 -0)
📝 docs/codebase-summary.md (+138 -15)
📝 docs/system-architecture.md (+169 -18)
📝 frontend/dist/index.html (+2 -2)
📝 frontend/package.json.md5 (+1 -1)
📝 frontend/src/App.tsx (+149 -225)
📝 frontend/src/components/capture-toolbar.tsx (+20 -2)
frontend/src/components/region-selector.tsx (+0 -247)
📝 frontend/wailsjs/go/main/App.d.ts (+4 -0)
📝 frontend/wailsjs/go/main/App.js (+8 -0)
📝 frontend/wailsjs/go/models.ts (+18 -0)
📝 frontend/wailsjs/runtime/runtime.js (+4 -0)
📝 go.mod (+2 -2)
📝 go.sum (+4 -4)
📝 internal/hotkeys/hotkeys.go (+152 -6)
internal/overlay/draw.go (+486 -0)
internal/overlay/overlay.go (+495 -0)

...and 3 more files

📄 Description

Summary

Replace React-based region selector with native Win32 layered window for significantly improved performance and user experience.

Why Native Win32?

The previous React-based overlay had several issues:

  1. Window Manipulation Overhead: Required 6-8 Wails runtime calls (hide, setPosition, setMinSize, setSize, setAlwaysOnTop, show) causing visible window flicker
  2. Slow PNG Encode/Decode Cycle: Full screenshot was encoded to PNG (~200-400ms for 4K), sent to frontend, then decoded for display
  3. React Rendering Latency: Additional delay for React component mount and DOM updates
  4. DPI Scaling Issues: Complex coordinate translation between physical and logical pixels

Native Win32 Solution

  • Zero Window Manipulation: Native overlay is a separate Win32 layered window, main app window stays hidden
  • Direct Pixel Access: GDI DIB (Device Independent Bitmap) with direct pixel manipulation - no encode/decode
  • Thread-Safe Architecture: Dedicated OS thread via runtime.LockOSThread() with channel-based commands
  • Instant Display: Overlay appears in ~150ms (vs ~500ms+ before)
  • Smart Optimization: Skip hide delay if app already minimized to tray

Performance Improvements

Metric Before After Improvement
Overlay display time ~500ms+ ~150ms 3x faster
PNG encode (full 4K) ~300ms ~10ms (cropped) 30x faster
Window operations 6-8 calls 0 calls No flicker

Technical Details

New Package: internal/overlay/

  • types.go - Win32 constants and structures
  • draw.go - GDI drawing utilities with DIB double buffering
  • overlay.go - Thread-safe overlay manager with message loop

Changes:

  • app.go - Integrated overlay manager, added isWindowHidden state tracking
  • frontend/src/App.tsx - Simplified region handling (receives pre-cropped image)
  • Removed frontend/src/components/region-selector.tsx

Test Plan

  • Region capture from visible window
  • Region capture from system tray (hotkey)
  • Multi-monitor support with negative coordinates
  • DPI scaling on high-DPI displays
  • Space key to reposition selection
  • ESC to cancel
  • No flash of previous selection on subsequent captures

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/mrgoonie/winshot/pull/36 **Author:** [@Vivusk](https://github.com/Vivusk) **Created:** 12/11/2025 **Status:** ✅ Merged **Merged:** 12/12/2025 **Merged by:** [@mrgoonie](https://github.com/mrgoonie) **Base:** `dev` ← **Head:** `main` --- ### 📝 Commits (10+) - [`ab8b183`](https://github.com/mrgoonie/winshot/commit/ab8b183cc3bd3e2aa7320148d3a26f0253b3ef85) Merge pull request #11 from mrgoonie/goon - [`bfae77e`](https://github.com/mrgoonie/winshot/commit/bfae77ebd5b2b77fb79569a47d19e62795b11df7) Merge pull request #18 from mrgoonie/goon - [`8b82e2c`](https://github.com/mrgoonie/winshot/commit/8b82e2cbb04938036fae5e8556ada6523ed7019d) chore(release): 1.1.0 [skip ci] - [`38e1191`](https://github.com/mrgoonie/winshot/commit/38e119109376f84e451322ba84a1d8edd0583d34) fix(app): restore window position after region capture - [`03cf0fd`](https://github.com/mrgoonie/winshot/commit/03cf0fd0698e5f199965fa3c923eec469a2c341e) feat(capture): add clipboard image paste support - [`0f1a8d1`](https://github.com/mrgoonie/winshot/commit/0f1a8d123162d701baa35f4b121b505fd069a5d3) feat(capture): add multi-monitor region capture support - [`1d683cc`](https://github.com/mrgoonie/winshot/commit/1d683ccaffa9043b235fdaf8e3e88bd89ca295e0) fix(hotkeys): resolve goroutine thread affinity causing hotkey registration failure - [`4fbc7d6`](https://github.com/mrgoonie/winshot/commit/4fbc7d6db9bf496682d1fed361a418109f98ef9e) chore: update generated bindings and documentation - [`20ad92b`](https://github.com/mrgoonie/winshot/commit/20ad92b2ef56359aff04cdd299f49146d4820474) feat(clipboard): auto-copy styled canvas instead of raw screenshot - [`22da2ac`](https://github.com/mrgoonie/winshot/commit/22da2acdc2ba59b15fbc70098d97729336ef2b0f) feat(overlay): implement native Win32 region selection overlay ### 📊 Changes **23 files changed** (+2325 additions, -624 deletions) <details> <summary>View changed files</summary> 📝 `.claude/active-plan` (+1 -1) 📝 `CHANGELOG.md` (+28 -0) 📝 `app.go` (+123 -101) ➕ `docs-manager-251211-clipboard-capture.md` (+129 -0) 📝 `docs/codebase-summary.md` (+138 -15) 📝 `docs/system-architecture.md` (+169 -18) 📝 `frontend/dist/index.html` (+2 -2) 📝 `frontend/package.json.md5` (+1 -1) 📝 `frontend/src/App.tsx` (+149 -225) 📝 `frontend/src/components/capture-toolbar.tsx` (+20 -2) ➖ `frontend/src/components/region-selector.tsx` (+0 -247) 📝 `frontend/wailsjs/go/main/App.d.ts` (+4 -0) 📝 `frontend/wailsjs/go/main/App.js` (+8 -0) 📝 `frontend/wailsjs/go/models.ts` (+18 -0) 📝 `frontend/wailsjs/runtime/runtime.js` (+4 -0) 📝 `go.mod` (+2 -2) 📝 `go.sum` (+4 -4) 📝 `internal/hotkeys/hotkeys.go` (+152 -6) ➕ `internal/overlay/draw.go` (+486 -0) ➕ `internal/overlay/overlay.go` (+495 -0) _...and 3 more files_ </details> ### 📄 Description ## Summary Replace React-based region selector with native Win32 layered window for significantly improved performance and user experience. ### Why Native Win32? The previous React-based overlay had several issues: 1. **Window Manipulation Overhead**: Required 6-8 Wails runtime calls (hide, setPosition, setMinSize, setSize, setAlwaysOnTop, show) causing visible window flicker 2. **Slow PNG Encode/Decode Cycle**: Full screenshot was encoded to PNG (~200-400ms for 4K), sent to frontend, then decoded for display 3. **React Rendering Latency**: Additional delay for React component mount and DOM updates 4. **DPI Scaling Issues**: Complex coordinate translation between physical and logical pixels ### Native Win32 Solution - **Zero Window Manipulation**: Native overlay is a separate Win32 layered window, main app window stays hidden - **Direct Pixel Access**: GDI DIB (Device Independent Bitmap) with direct pixel manipulation - no encode/decode - **Thread-Safe Architecture**: Dedicated OS thread via `runtime.LockOSThread()` with channel-based commands - **Instant Display**: Overlay appears in ~150ms (vs ~500ms+ before) - **Smart Optimization**: Skip hide delay if app already minimized to tray ### Performance Improvements | Metric | Before | After | Improvement | |--------|--------|-------|-------------| | Overlay display time | ~500ms+ | ~150ms | **3x faster** | | PNG encode (full 4K) | ~300ms | ~10ms (cropped) | **30x faster** | | Window operations | 6-8 calls | 0 calls | **No flicker** | ### Technical Details **New Package:** `internal/overlay/` - `types.go` - Win32 constants and structures - `draw.go` - GDI drawing utilities with DIB double buffering - `overlay.go` - Thread-safe overlay manager with message loop **Changes:** - `app.go` - Integrated overlay manager, added `isWindowHidden` state tracking - `frontend/src/App.tsx` - Simplified region handling (receives pre-cropped image) - Removed `frontend/src/components/region-selector.tsx` ## Test Plan - [x] Region capture from visible window - [x] Region capture from system tray (hotkey) - [x] Multi-monitor support with negative coordinates - [x] DPI scaling on high-DPI displays - [x] Space key to reposition selection - [x] ESC to cancel - [x] No flash of previous selection on subsequent captures --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-03 15:57:34 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/winshot#57
No description provided.