From d03a63e1b7cb3e78bb9c427fac7f5e9fef0b7859 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 12 Jun 2025 23:03:34 +1000 Subject: [PATCH] fix: Implement robust cross-platform window visibility fallback for issue #2861 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the issue where application windows fail to show on Windows 10 Pro due to efficiency mode preventing WebView2 NavigationCompleted events. ## Changes Made ### Windows (webview_window_windows.go) - **Decouple window container from WebView state**: Window now shows immediately - **Add timeout fallback**: 3-second timeout to show WebView if navigation is delayed - **Prevent efficiency mode**: Set WebView2 IsVisible=true per Microsoft recommendation - **Enhanced state tracking**: Added showRequested, visibilityTimeout, windowShown fields - **Robust navigation completion**: Improved handler to work with new visibility logic ### macOS (webview_window_darwin.go) - **Documentation**: Added comment noting macOS already follows best practices - **No functional changes**: macOS implementation already robust ### Linux (webview_window_linux.go, linux_cgo.go, linux_purego.go) - **Add missing methods**: Implemented show()/hide() methods in main Linux file - **CGO implementation**: Added windowShow()/windowHide() delegation methods - **Purego implementation**: Added windowShow()/windowHide() methods for purego builds - **Consistent behavior**: Matches CGO implementation with position saving ## Implementation Pattern Adopts the following pattern: 1. **Separate concerns**: Window container vs WebView content readiness 2. **Immediate visibility**: Show window container immediately 3. **Progressive enhancement**: Show WebView content when ready 4. **Robust fallbacks**: Timeout and multiple strategies for edge cases ## Testing Considerations - Windows 10 Pro efficiency mode scenarios - WebView2 navigation delays or failures - Cross-platform consistency - Performance impact of timeout mechanisms Fixes #2861 πŸ€– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- docs/src/content/docs/changelog.mdx | 2 + v3/go.mod | 2 +- v3/go.sum | 4 +- v3/pkg/application/linux_cgo.go | 11 + v3/pkg/application/linux_purego.go | 15 + v3/pkg/application/webview_window_darwin.go | 2 + v3/pkg/application/webview_window_linux.go | 12 + v3/pkg/application/webview_window_windows.go | 63 ++- v3/tests/window-visibility-test/.gitignore | 19 + v3/tests/window-visibility-test/README.md | 146 ++++++ .../window-visibility-test/TESTING_GUIDE.md | 159 +++++++ .../window-visibility-test/assets/index.html | 431 ++++++++++++++++++ v3/tests/window-visibility-test/go.mod | 55 +++ v3/tests/window-visibility-test/go.sum | 146 ++++++ v3/tests/window-visibility-test/main.go | 308 +++++++++++++ 15 files changed, 1370 insertions(+), 5 deletions(-) create mode 100644 v3/tests/window-visibility-test/.gitignore create mode 100644 v3/tests/window-visibility-test/README.md create mode 100644 v3/tests/window-visibility-test/TESTING_GUIDE.md create mode 100644 v3/tests/window-visibility-test/assets/index.html create mode 100644 v3/tests/window-visibility-test/go.mod create mode 100644 v3/tests/window-visibility-test/go.sum create mode 100644 v3/tests/window-visibility-test/main.go diff --git a/docs/src/content/docs/changelog.mdx b/docs/src/content/docs/changelog.mdx index 67f832ea4..9831f73f7 100644 --- a/docs/src/content/docs/changelog.mdx +++ b/docs/src/content/docs/changelog.mdx @@ -82,6 +82,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ο£Ώ Add File Association support for mac by [@wimaha](https://github.com/wimaha) in [#4177](https://github.com/wailsapp/wails/pull/4177) - Add `wails3 tool version` for semantic version bumping by [@leaanthony](https://github.com/leaanthony) - Add badging support for macOS and Windows by [@popaprozac](https://github.com/popaprozac) in [#](https://github.com/wailsapp/wails/pull/4234) + ### Fixed - Fixed Windows+Linux Edit Menu issues by [@leaanthony](https://github.com/leaanthony) in [#3f78a3a](https://github.com/wailsapp/wails/commit/3f78a3a8ce7837e8b32242c8edbbed431c68c062) @@ -127,6 +128,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed system trays not showing after taskbar restarts by [@leaanthony](https://github.com/leaanthony) based on work by @kron. - Fixed fallbackResponseWriter not implementing Flush() in [#4245](https://github.com/wailsapp/wails/pull/4245) - Fixed fallbackResponseWriter not implementing Flush() by [@superDingda] in [#4236](https://github.com/wailsapp/wails/issues/4236) +- Fixed Windows Efficiency mode startup race condition by [@leaanthony](https://github.com/leaanthony) ### Changed diff --git a/v3/go.mod b/v3/go.mod index 8d0e4935c..3684bbff2 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -18,7 +18,7 @@ require ( github.com/google/uuid v1.6.0 github.com/goreleaser/nfpm/v2 v2.41.3 github.com/jackmordaunt/icns/v2 v2.2.7 - github.com/jaypipes/ghw v0.13.0 + github.com/jaypipes/ghw v0.17.0 github.com/leaanthony/clir v1.7.0 github.com/leaanthony/go-ansi-parser v1.6.1 github.com/leaanthony/gosod v1.0.4 diff --git a/v3/go.sum b/v3/go.sum index 2c07fe6c8..1f4983e7a 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -174,8 +174,8 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/jackmordaunt/icns/v2 v2.2.7 h1:K/RbfvuzjmjVY5y4g+XENRs8ZZatwz4YnLHypa2KwQg= github.com/jackmordaunt/icns/v2 v2.2.7/go.mod h1:ovoTxGguSuoUGKMk5Nn3R7L7BgMQkylsO+bblBuI22A= -github.com/jaypipes/ghw v0.13.0 h1:log8MXuB8hzTNnSktqpXMHc0c/2k/WgjOMSUtnI1RV4= -github.com/jaypipes/ghw v0.13.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51MidlD8= +github.com/jaypipes/ghw v0.17.0 h1:EVLJeNcy5z6GK/Lqby0EhBpynZo+ayl8iJWY0kbEUJA= +github.com/jaypipes/ghw v0.17.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51MidlD8= github.com/jaypipes/pcidb v1.0.1 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic= github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 7dbeaaf5e..369a0e815 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1009,6 +1009,10 @@ func (w *linuxWebviewWindow) hide() { C.gtk_widget_hide(w.gtkWidget()) } +func (w *linuxWebviewWindow) windowHide() { + C.gtk_widget_hide(w.gtkWidget()) +} + func (w *linuxWebviewWindow) isFullscreen() bool { gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) state := C.gdk_window_get_state(gdkWindow) @@ -1123,6 +1127,13 @@ func (w *linuxWebviewWindow) show() { //w.setPosition(w.lastX, w.lastY) } +func (w *linuxWebviewWindow) windowShow() { + if w.gtkWidget() == nil { + return + } + C.gtk_widget_show_all(w.gtkWidget()) +} + func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { var enable C.int if ignore { diff --git a/v3/pkg/application/linux_purego.go b/v3/pkg/application/linux_purego.go index 258eecc94..8e5a3e0dc 100644 --- a/v3/pkg/application/linux_purego.go +++ b/v3/pkg/application/linux_purego.go @@ -1206,3 +1206,18 @@ func runSaveFileDialog(dialog *SaveFileDialogStruct) (string, error) { func isOnMainThread() bool { return mainThreadId == gThreadSelf() } + +// linuxWebviewWindow show/hide methods for purego implementation +func (w *linuxWebviewWindow) windowShow() { + if w.window == 0 { + return + } + windowShow(w.window) +} + +func (w *linuxWebviewWindow) windowHide() { + if w.window == 0 { + return + } + windowHide(w.window) +} diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index 28e693a23..b57fcb095 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -903,6 +903,8 @@ func (w *macosWebviewWindow) getScreen() (*Screen, error) { } func (w *macosWebviewWindow) show() { + // macOS implementation is already robust - window container shows immediately + // This is the preferred pattern that Windows should follow C.windowShow(w.nsWindow) } diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 8c50c6117..acf8a47c9 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -412,6 +412,18 @@ func (w *linuxWebviewWindow) setIgnoreMouseEvents(ignore bool) { w.ignoreMouse(w.ignoreMouseEvents) } +func (w *linuxWebviewWindow) show() { + // Linux implementation is robust - window shows immediately + // This is the preferred pattern that Windows should follow + w.windowShow() +} + +func (w *linuxWebviewWindow) hide() { + // Save position before hiding (consistent with CGO implementation) + w.lastX, w.lastY = w.position() + w.windowHide() +} + func (w *linuxWebviewWindow) showMenuBar() {} func (w *linuxWebviewWindow) hideMenuBar() {} func (w *linuxWebviewWindow) toggleMenuBar() {} diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index a49255dd5..abc0e1e43 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -57,6 +57,11 @@ type windowsWebviewWindow struct { chromium *edge.Chromium webviewNavigationCompleted bool + // Window visibility management - robust fallback for issue #2861 + showRequested bool // Track if show() was called before navigation completed + visibilityTimeout *time.Timer // Timeout to show window if navigation is delayed + windowShown bool // Track if window container has been shown + // resizeBorder* is the width/height of the resize border in pixels. resizeBorderWidth int32 resizeBorderHeight int32 @@ -960,14 +965,45 @@ func (w *windowsWebviewWindow) printStyle() { } func (w *windowsWebviewWindow) show() { + // Always show the window container immediately (decouple from WebView state) + // This fixes issue #2861 where efficiency mode prevents window visibility + w32.ShowWindow(w.hwnd, w32.SW_SHOW) + w.windowShown = true + w.showRequested = true + + // Show WebView if navigation has completed if w.webviewNavigationCompleted { w.chromium.Show() - w32.ShowWindow(w.hwnd, w32.SW_SHOW) + // Cancel timeout since we can show immediately + if w.visibilityTimeout != nil { + w.visibilityTimeout.Stop() + w.visibilityTimeout = nil + } + } else { + // Start timeout to show WebView if navigation is delayed (fallback for efficiency mode) + if w.visibilityTimeout == nil { + w.visibilityTimeout = time.AfterFunc(3*time.Second, func() { + // Show WebView even if navigation hasn't completed + // This prevents permanent invisibility in efficiency mode + if !w.webviewNavigationCompleted && w.chromium != nil { + w.chromium.Show() + } + w.visibilityTimeout = nil + }) + } } } func (w *windowsWebviewWindow) hide() { w32.ShowWindow(w.hwnd, w32.SW_HIDE) + w.windowShown = false + w.showRequested = false + + // Cancel any pending visibility timeout + if w.visibilityTimeout != nil { + w.visibilityTimeout.Stop() + w.visibilityTimeout = nil + } } // Get the screen for the current window @@ -990,6 +1026,10 @@ func newWindowImpl(parent *WebviewWindow) *windowsWebviewWindow { parent: parent, resizeBorderWidth: int32(w32.GetSystemMetrics(w32.SM_CXSIZEFRAME)), resizeBorderHeight: int32(w32.GetSystemMetrics(w32.SM_CYSIZEFRAME)), + // Initialize visibility tracking fields + showRequested: false, + visibilityTimeout: nil, + windowShown: false, } return result @@ -1640,6 +1680,14 @@ func (w *windowsWebviewWindow) setupChromium() { chromium.Embed(w.hwnd) + // Prevent efficiency mode by keeping WebView2 visible (fixes issue #2861) + // Microsoft recommendation: keep IsVisible = true to avoid efficiency mode + // See: https://github.com/MicrosoftEdge/WebView2Feedback/discussions/4021 + err := chromium.PutIsVisible(true) + if err != nil { + globalApplication.error("Failed to set WebView2 visibility for efficiency mode prevention: %v", err) + } + if chromium.HasCapability(edge.SwipeNavigation) { err := chromium.PutIsSwipeNavigationEnabled(opts.EnableSwipeGestures) if err != nil { @@ -1837,6 +1885,12 @@ func (w *windowsWebviewWindow) navigationCompleted(sender *edge.ICoreWebView2, a } w.webviewNavigationCompleted = true + // Cancel any pending visibility timeout since navigation completed + if w.visibilityTimeout != nil { + w.visibilityTimeout.Stop() + w.visibilityTimeout = nil + } + wasFocused := w.isFocused() // Hack to make it visible: https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077#issuecomment-825375026 err := w.chromium.Hide() @@ -1850,8 +1904,13 @@ func (w *windowsWebviewWindow) navigationCompleted(sender *edge.ICoreWebView2, a if wasFocused { w.focus() } + + // Only call parent.Show() if not hidden and show was requested but window wasn't shown yet + // The new robust show() method handles window visibility independently if !w.parent.options.Hidden { - w.parent.Show() + if w.showRequested && !w.windowShown { + w.parent.Show() + } w.update() } } diff --git a/v3/tests/window-visibility-test/.gitignore b/v3/tests/window-visibility-test/.gitignore new file mode 100644 index 000000000..dc734a8b8 --- /dev/null +++ b/v3/tests/window-visibility-test/.gitignore @@ -0,0 +1,19 @@ +# Compiled binary +window-visibility-test +window-visibility-test.exe + +# Build artifacts +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binaries +*.test + +# Output of the go coverage tool +*.out + +# Go workspace file +go.work \ No newline at end of file diff --git a/v3/tests/window-visibility-test/README.md b/v3/tests/window-visibility-test/README.md new file mode 100644 index 000000000..04b4ec49e --- /dev/null +++ b/v3/tests/window-visibility-test/README.md @@ -0,0 +1,146 @@ +# Window Visibility Test - Issue #2861 + +This example demonstrates and tests the fixes implemented for [Wails v3 Issue #2861](https://github.com/wailsapp/wails/issues/2861) regarding application windows not showing on Windows 10 Pro due to efficiency mode. + +## Problem Background + +On Windows systems, the "efficiency mode" feature could prevent Wails applications from displaying windows properly. This occurred because: + +1. **WebView2 NavigationCompleted events** could be delayed or missed in efficiency mode +2. **Window visibility was gated** behind WebView2 navigation completion +3. **No fallback mechanisms** existed for delayed or failed navigation events + +## Solution Implemented + +The fix implements a **robust cross-platform window visibility pattern**: + +### Windows Improvements +- βœ… **Decouple window container from WebView state** - Windows show immediately +- βœ… **3-second timeout fallback** - Shows WebView if navigation is delayed +- βœ… **Efficiency mode prevention** - Sets WebView2 `IsVisible=true` per Microsoft guidance +- βœ… **Enhanced state tracking** - Proper visibility state management + +### Cross-Platform Consistency +- βœ… **macOS** - Already robust, documented best practices +- βœ… **Linux** - Added missing show/hide methods for both CGO and purego builds + +## Test Scenarios + +This example provides comprehensive testing for: + +### 1. **Basic Window Tests** +- **Normal Window**: Standard window creation - should appear immediately +- **Delayed Content Window**: Simulates heavy content loading (like Vue.js apps) +- **Hidden β†’ Show Test**: Tests delayed showing after initial creation + +### 2. **Stress Tests** +- **Multiple Windows**: Creates 3 windows simultaneously +- **Rapid Creation**: Creates windows in quick succession + +### 3. **Critical Issue #2861 Test** +- **Efficiency Mode Test**: Specifically designed to reproduce and verify the fix +- Tests window container vs content loading timing +- Includes heavy content simulation + +## How to Run + +```bash +cd /path/to/wails/v3/examples/window-visibility-test +wails dev +``` + +## Testing Instructions + +### What to Look For +1. **Immediate Window Appearance** - Windows should appear within 100ms of clicking buttons +2. **Progressive Loading** - Content may load progressively, but window container visible immediately +3. **No Efficiency Mode Issues** - Windows appear even if Task Manager shows "efficiency mode" +4. **Consistent Cross-Platform Behavior** - Similar behavior on Windows, macOS, and Linux + +### How to Test +1. **Note the current time** displayed in the app +2. **Click any test button** or use menu items +3. **Immediately observe** if a window appears (should be within 100ms) +4. **Wait for content** to load and check reported timing +5. **Try multiple tests** in sequence to test robustness +6. **Test both buttons and menu items** for comprehensive coverage + +### Expected Results +- βœ… Window containers appear immediately upon button click +- βœ… Content loads progressively within 2-3 seconds +- βœ… No blank or invisible windows, even under efficiency mode +- βœ… Activity log shows sub-100ms window creation times +- βœ… All test scenarios work consistently + +## Manual Testing Checklist + +### Windows 10 Pro (Primary Target) +- [ ] Test with efficiency mode enabled in Task Manager +- [ ] Create windows while system is under load +- [ ] Test rapid window creation scenarios +- [ ] Verify WebView2 content loads after container appears +- [ ] Check activity log for sub-100ms creation times + +### Windows 11 +- [ ] Verify consistent behavior with Windows 10 Pro fixes +- [ ] Test efficiency mode scenarios +- [ ] Validate timeout fallback mechanisms + +### macOS +- [ ] Confirm existing robust behavior maintained +- [ ] Test all window creation scenarios +- [ ] Verify no regressions introduced + +### Linux +- [ ] Test both CGO and purego builds +- [ ] Verify new show/hide methods work correctly +- [ ] Test window positioning and timing + +## Technical Implementation Details + +### Window Creation Flow +``` +1. User clicks button β†’ JavaScript calls Go backend +2. Go creates WebviewWindow β†’ Sets properties +3. Go calls window.Show() β†’ IMMEDIATE window container display +4. WebView2 starts navigation β†’ Progressive content loading +5. Timeout fallback ensures WebView shows even if navigation delayed +``` + +### Key Code Changes +- **Windows**: `/v3/pkg/application/webview_window_windows.go` +- **macOS**: `/v3/pkg/application/webview_window_darwin.go` +- **Linux**: `/v3/pkg/application/webview_window_linux.go`, `linux_cgo.go`, `linux_purego.go` + +## Reporting Test Results + +When testing, please report: + +1. **Platform & OS Version** (e.g., "Windows 10 Pro 21H2", "macOS 13.1", "Ubuntu 22.04") +2. **Window Creation Timing** (from activity log) +3. **Any Delayed or Missing Windows** +4. **Efficiency Mode Status** (Windows only - check Task Manager) +5. **Content Loading Behavior** (immediate container vs progressive content) +6. **Any Error Messages** in activity log or console + +### Sample Test Report Format +``` +Platform: Windows 10 Pro 21H2 +Efficiency Mode: Enabled +Results: +- Normal Window: βœ… Appeared immediately (<50ms) +- Delayed Content: βœ… Container immediate, content loaded in 2.1s +- Multiple Windows: βœ… All 3 appeared simultaneously +- Critical Test: βœ… Window appeared immediately, content progressive +Notes: No issues observed, all windows visible immediately +``` + +## Architecture Notes + +This example demonstrates the **preferred window visibility pattern** for web-based desktop applications: + +1. **Separate Concerns**: Window container vs web content readiness +2. **Immediate Feedback**: Users see window immediately +3. **Progressive Enhancement**: Content loads and appears when ready +4. **Robust Fallbacks**: Multiple strategies for edge cases +5. **Cross-Platform Consistency**: Same behavior on all platforms diff --git a/v3/tests/window-visibility-test/TESTING_GUIDE.md b/v3/tests/window-visibility-test/TESTING_GUIDE.md new file mode 100644 index 000000000..dbb3bfd04 --- /dev/null +++ b/v3/tests/window-visibility-test/TESTING_GUIDE.md @@ -0,0 +1,159 @@ +# Testing Guide - Window Visibility Issue #2861 + +## Quick Start + +1. **Build and run the application:** + ```bash + cd v3/examples/window-visibility-test + ./build.sh + # OR + wails dev + ``` + +2. **Main testing interface:** + - The app opens with a comprehensive testing dashboard + - Contains multiple test scenarios accessible via buttons + - Also provides menu-based testing (File, Tests, Help menus) + - Real-time activity logging with precise timing + +## Critical Test Cases + +### 🎯 **Issue #2861 Reproduction Test** (Most Important) +**Button:** "Efficiency Mode Test" +**Expected:** Window container appears immediately, content loads progressively +**Watch for:** +- Window visible within 100ms of button click +- Content loading message appears initially +- Content completes loading after 2-3 seconds +- No blank or invisible windows + +### ⏳ **Delayed Content Simulation** +**Button:** "Create Delayed Content Window" +**Expected:** Tests navigation completion timing +**Watch for:** +- Window container appears immediately +- Loading spinner visible initially +- Content loads after 3-second delay +- Window remains visible throughout + +### πŸ”„ **Hidden β†’ Show Robustness** +**Button:** "Hidden β†’ Show Test" +**Expected:** Tests delayed show() calls +**Watch for:** +- Initial response in activity log +- Window appears after exactly 2 seconds +- No timing issues or failures + +## Platform-Specific Testing + +### Windows 10 Pro (Primary Target) +**Enable Efficiency Mode Testing:** +1. Open Task Manager β†’ Processes tab +2. Find the test application process +3. Right-click β†’ "Efficiency mode" (if available) +4. Run all test scenarios +5. Verify windows still appear immediately + +**Key Metrics:** +- Window creation: < 100ms +- Content loading: 2-3 seconds +- No invisible windows under any conditions + +### Windows 11 +**Similar to Windows 10 Pro but also test:** +- New Windows 11 efficiency features +- Multiple monitor scenarios +- High DPI scaling + +### macOS +**Focus on consistency:** +- All scenarios should work identical to Windows +- No regressions in existing robust behavior +- Test across different macOS versions if possible + +### Linux +**Test both build variants:** +```bash +# CGO build (default) +wails dev + +# Purego build +CGO_ENABLED=0 wails dev +``` +- Verify both variants behave identically +- Test across different Linux distributions + +## Success Criteria + +### βœ… **Pass Conditions** +- All windows appear within 100ms of button click +- Activity log shows consistent sub-100ms timing +- Content loads progressively without blocking window visibility +- No blank, invisible, or delayed windows under any test scenario +- Efficiency mode (Windows) does not prevent window appearance +- Menu and button testing yield identical results + +### ❌ **Fail Conditions** +- Any window takes >200ms to appear +- Blank or invisible windows under any condition +- Window visibility blocked by content loading +- Efficiency mode prevents window appearance +- Inconsistent behavior between test methods +- Platform-specific failures + +## Reporting Results + +**Please provide this information:** + +``` +Platform: [Windows 10 Pro/Windows 11/macOS/Linux distro + version] +Build Type: [CGO/Purego] (Linux only) +Efficiency Mode: [Enabled/Disabled/N/A] (Windows only) + +Test Results: +- Normal Window: [βœ… Pass / ❌ Fail] - [timing in ms] +- Delayed Content: [βœ… Pass / ❌ Fail] - [container timing / content timing] +- Hiddenβ†’Show: [βœ… Pass / ❌ Fail] - [notes] +- Multiple Windows: [βœ… Pass / ❌ Fail] - [notes] +- Efficiency Mode Test: [βœ… Pass / ❌ Fail] - [critical timing results] + +Notes: +[Any additional observations, error messages, or unexpected behavior] +``` + +## Advanced Testing Scenarios + +### **Rapid Stress Testing** +1. Click "Rapid Creation Test" multiple times quickly +2. Use keyboard shortcuts to rapidly access menu items +3. Create multiple windows then close them rapidly +4. Test system under load (other applications running) + +### **Edge Case Testing** +1. Test during system startup (high load) +2. Test with multiple monitors +3. Test with different DPI scaling settings +4. Test while other WebView2 applications are running + +### **Timing Verification** +1. Use browser dev tools (F12) to check console timing +2. Compare activity log timing with system clock +3. Test on slower/older hardware if available +4. Verify timing consistency across multiple runs + +## Troubleshooting + +### **Common Issues** +- **Blank window**: Check activity log for error messages +- **Slow timing**: Verify system isn't under heavy load +- **Build failures**: Ensure Wails v3 CLI is latest version +- **Import errors**: Run `go mod tidy` in example directory + +### **Debug Information** +The application provides extensive logging: +- Browser console (F12) shows JavaScript timing +- Activity log shows backend call timing +- Go application logs show window creation details +- Check system Task Manager for process efficiency mode status + +This comprehensive testing should validate that the window visibility fixes successfully resolve issue #2861 across all supported platforms. \ No newline at end of file diff --git a/v3/tests/window-visibility-test/assets/index.html b/v3/tests/window-visibility-test/assets/index.html new file mode 100644 index 000000000..22023a5e3 --- /dev/null +++ b/v3/tests/window-visibility-test/assets/index.html @@ -0,0 +1,431 @@ + + + + + + Window Visibility Test - Issue #2861 + + + +
+
+

πŸͺŸ Window Visibility Test

+

Testing fixes for Wails v3 Issue #2861 - Windows 10 Pro Efficiency Mode

+
+ Current Time: --:--:-- +
+
+ +
+

βœ…Basic Window Tests

+

These tests verify that windows appear immediately when requested, regardless of WebView content loading state.

+
+ + + +
+
+ +
+

⚑Stress Tests

+

These tests push the window system to verify robustness under load and timing edge cases.

+
+ + +
+
+ +
+

πŸ”¬Critical Issue #2861 Test

+

This test specifically targets the Windows efficiency mode bug where WebView2 NavigationCompleted events could be delayed or missed.

+ +
+

Expected Behavior:

+
    +
  • Window container appears immediately upon button click
  • +
  • Content loads progressively (may take 2-3 seconds)
  • +
  • No blank or invisible windows, even under efficiency mode
  • +
+
+ +
+ +
+
+ +
+

πŸ“ŠTest Results & Timing

+

Monitor window creation timing and behavior. Each button click should result in immediate window visibility.

+ +
+

Activity Log

+
+
Ready for testing... Click any button to begin.
+
+
+
+ +
+

πŸ“Testing Instructions

+
+

What to Look For:

+
    +
  • Immediate Window Appearance: Windows should appear within 100ms of clicking
  • +
  • Progressive Loading: Content may load progressively, but window container should be visible immediately
  • +
  • No Efficiency Mode Issues: On Windows, windows should still appear even if Task Manager shows "efficiency mode"
  • +
  • Consistent Behavior: All platforms (Windows, macOS, Linux) should behave similarly
  • +
+
+ +
+

How to Test:

+
    +
  1. Note the current time displayed above
  2. +
  3. Click any test button
  4. +
  5. Immediately observe if a window appears (should be within 100ms)
  6. +
  7. Wait for content to load and check the reported timing
  8. +
  9. Try multiple tests in sequence
  10. +
  11. Test both buttons and menu items
  12. +
+
+
+
+ + + + \ No newline at end of file diff --git a/v3/tests/window-visibility-test/go.mod b/v3/tests/window-visibility-test/go.mod new file mode 100644 index 000000000..04d244468 --- /dev/null +++ b/v3/tests/window-visibility-test/go.mod @@ -0,0 +1,55 @@ +module window-visibility-test + +go 1.24.0 + +toolchain go1.24.4 + +replace github.com/wailsapp/wails/v3 => ../../ + +require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.1.6 // indirect + github.com/adrg/xdg v0.5.3 // indirect + github.com/bep/debounce v1.2.1 // indirect + github.com/cloudflare/circl v1.6.0 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect + github.com/ebitengine/purego v0.8.2 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect + github.com/go-git/go-git/v5 v5.13.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/leaanthony/go-ansi-parser v1.6.1 // indirect + github.com/leaanthony/u v1.1.1 // indirect + github.com/lmittmann/tint v1.0.7 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/samber/lo v1.49.1 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect + github.com/wailsapp/go-webview2 v1.0.21 // indirect + github.com/wailsapp/mimetype v1.4.1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect +) + +// Add any other dependencies that might be needed +// These will be resolved when the user runs go mod tidy diff --git a/v3/tests/window-visibility-test/go.sum b/v3/tests/window-visibility-test/go.sum new file mode 100644 index 000000000..cbadfe003 --- /dev/null +++ b/v3/tests/window-visibility-test/go.sum @@ -0,0 +1,146 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= +github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= +github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= +github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= +github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= +github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= +github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM= +github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= +github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0= +github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= +github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= +github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= +github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= +github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= +github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= +github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= +github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= +github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/wailsapp/go-webview2 v1.0.21 h1:k3dtoZU4KCoN/AEIbWiPln3P2661GtA2oEgA2Pb+maA= +github.com/wailsapp/go-webview2 v1.0.21/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= +github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= +github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/tests/window-visibility-test/main.go b/v3/tests/window-visibility-test/main.go new file mode 100644 index 000000000..c45d2b1c3 --- /dev/null +++ b/v3/tests/window-visibility-test/main.go @@ -0,0 +1,308 @@ +package main + +import ( + "embed" + "fmt" + "log" + "time" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +// WindowTestService provides methods for testing window visibility scenarios +type WindowTestService struct { + app *application.App +} + +// NewWindowTestService creates a new window test service +func NewWindowTestService() *WindowTestService { + return &WindowTestService{} +} + +// SetApp sets the application reference (internal method, not exposed to frontend) +func (w *WindowTestService) setApp(app *application.App) { + w.app = app +} + +// CreateNormalWindow creates a standard window - should show immediately +func (w *WindowTestService) CreateNormalWindow() string { + log.Println("Creating normal window...") + + w.app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "Normal Window - Should Show Immediately", + Width: 600, + Height: 400, + X: 100, + Y: 100, + HTML: "Normal Window

βœ… Normal Window

This window should have appeared immediately after clicking the button.

Timestamp: " + time.Now().Format("15:04:05") + "

", + }) + + return "Normal window created" +} + +// CreateDelayedContentWindow creates a window with delayed content to test navigation timing +func (w *WindowTestService) CreateDelayedContentWindow() string { + log.Println("Creating delayed content window...") + + // Use HTML that will take time to load (simulates heavy Vue app) + delayedHTML := ` + + + Delayed Content + + + +

⏳ Delayed Content Window

+

This window tests navigation completion timing.

+
+

Loading... (simulates heavy content)

+ +

Window container should be visible immediately, even during load.

+ + ` + + w.app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "Delayed Content Window - Test Navigation Timing", + Width: 600, + Height: 400, + X: 150, + Y: 150, + HTML: delayedHTML, + }) + + return "Delayed content window created" +} + +// CreateHiddenThenShowWindow creates a hidden window then shows it after delay +func (w *WindowTestService) CreateHiddenThenShowWindow() string { + log.Println("Creating hidden then show window...") + + window := w.app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "Hidden Then Show Window - Test Show() Robustness", + Width: 600, + Height: 400, + X: 200, + Y: 200, + HTML: "Hidden Then Show

πŸ”„ Hidden Then Show Window

This window was created hidden and then shown after 2 seconds.

Should test the robustness of the show() method.

Created at: " + time.Now().Format("15:04:05") + "

", + Hidden: true, // Start hidden + }) + + // Show after 2 seconds to test delayed showing + go func() { + time.Sleep(2 * time.Second) + log.Println("Showing previously hidden window...") + window.Show() + }() + + return "Hidden window created, will show in 2 seconds" +} + +// CreateMultipleWindows creates multiple windows simultaneously to test performance +func (w *WindowTestService) CreateMultipleWindows() string { + log.Println("Creating multiple windows...") + + for i := 0; i < 3; i++ { + bgColors := []string{"#ff9a9e,#fecfef", "#a18cd1,#fbc2eb", "#fad0c4,#ffd1ff"} + content := fmt.Sprintf(` + + + Batch Window %d + + + +

πŸ”’ Batch Window %d

+

Part of multiple windows stress test

+

All windows should appear quickly and simultaneously

+

Created at: %s

+ + `, i+1, bgColors[i], i+1, time.Now().Format("15:04:05")) + + w.app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: fmt.Sprintf("Batch Window %d - Stress Test", i+1), + Width: 400, + Height: 300, + X: 250 + (i * 50), + Y: 250 + (i * 50), + HTML: content, + }) + } + + return "Created 3 windows simultaneously" +} + +// CreateEfficiencyModeTestWindow creates a window designed to trigger efficiency mode issues +func (w *WindowTestService) CreateEfficiencyModeTestWindow() string { + log.Println("Creating efficiency mode test window...") + + // Create content that might trigger efficiency mode or WebView2 delays + heavyHTML := ` + + + Efficiency Mode Test + + + +

⚑ Efficiency Mode Test Window

+

This window tests the fix for Windows 10 Pro efficiency mode issue #2861

+ +
+

Window Container Status

+

βœ… Window container is visible (this text proves it)

+
+ +
+

WebView2 Status

+

⏳ WebView2 navigation in progress...

+ +
+ +
+

Heavy Content (simulates Vue.js app)

+
+ Loading heavy content... +
+
+ + + + ` + + w.app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "Efficiency Mode Test - Issue #2861 Reproduction", + Width: 700, + Height: 500, + X: 300, + Y: 300, + HTML: heavyHTML, + }) + + return "Efficiency mode test window created" +} + +// GetWindowCount returns the current number of windows +func (w *WindowTestService) GetWindowCount() int { + // This would need to be implemented based on the app's window tracking + // For now, return a placeholder + return 1 // Main window +} + +//go:embed assets/* +var assets embed.FS + +func main() { + // Create the service + service := NewWindowTestService() + + // Create application with menu + app := application.New(application.Options{ + Name: "Window Visibility Test", + Description: "Test application for window visibility robustness (Issue #2861)", + Services: []application.Service{ + application.NewService(service), + }, + Assets: application.AssetOptions{ + Handler: application.BundledAssetFileServer(assets), + }, + }) + + // Set app reference in service + service.setApp(app) + + // Create application menu + menu := app.NewMenu() + + // File menu + fileMenu := menu.AddSubmenu("File") + fileMenu.Add("New Normal Window").OnClick(func(ctx *application.Context) { + service.CreateNormalWindow() + }) + fileMenu.Add("New Delayed Content Window").OnClick(func(ctx *application.Context) { + service.CreateDelayedContentWindow() + }) + fileMenu.AddSeparator() + fileMenu.Add("Quit").OnClick(func(ctx *application.Context) { + app.Quit() + }) + + // Test menu + testMenu := menu.AddSubmenu("Tests") + testMenu.Add("Hidden Then Show Window").OnClick(func(ctx *application.Context) { + service.CreateHiddenThenShowWindow() + }) + testMenu.Add("Multiple Windows Stress Test").OnClick(func(ctx *application.Context) { + service.CreateMultipleWindows() + }) + testMenu.Add("Efficiency Mode Test").OnClick(func(ctx *application.Context) { + service.CreateEfficiencyModeTestWindow() + }) + + // Help menu + helpMenu := menu.AddSubmenu("Help") + helpMenu.Add("About").OnClick(func(ctx *application.Context) { + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "About Window Visibility Test", + Width: 500, + Height: 400, + X: 400, + Y: 300, + HTML: "About

Window Visibility Test

This application tests the fixes for Wails v3 issue #2861

Windows 10 Pro Efficiency Mode Fix

Tests window container vs WebView content visibility


Created for testing robust window visibility patterns

", + }) + }) + + app.SetMenu(menu) + + // Create main window + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "Window Visibility Test - Issue #2861", + Width: 800, + Height: 600, + X: 50, + Y: 50, + URL: "/index.html", + }) + + err := app.Run() + if err != nil { + log.Fatal(err) + } +}