mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
fix: Implement robust cross-platform window visibility fallback for issue #2861
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 <noreply@anthropic.com>
This commit is contained in:
parent
1d75dd030f
commit
d03a63e1b7
15 changed files with 1370 additions and 5 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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=
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
19
v3/tests/window-visibility-test/.gitignore
vendored
Normal file
19
v3/tests/window-visibility-test/.gitignore
vendored
Normal file
|
|
@ -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
|
||||
146
v3/tests/window-visibility-test/README.md
Normal file
146
v3/tests/window-visibility-test/README.md
Normal file
|
|
@ -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
|
||||
159
v3/tests/window-visibility-test/TESTING_GUIDE.md
Normal file
159
v3/tests/window-visibility-test/TESTING_GUIDE.md
Normal file
|
|
@ -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.
|
||||
431
v3/tests/window-visibility-test/assets/index.html
Normal file
431
v3/tests/window-visibility-test/assets/index.html
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Window Visibility Test - Issue #2861</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 10px;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.header p {
|
||||
font-size: 1.2em;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 15px;
|
||||
padding: 25px;
|
||||
margin-bottom: 25px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.test-section h2 {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 15px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.test-section p {
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.6;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.button-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 15px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.test-button {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 15px 20px;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.test-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.3);
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.test-button:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.test-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
|
||||
.test-button:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.status-display {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-top: 20px;
|
||||
border-left: 4px solid #4CAF50;
|
||||
}
|
||||
|
||||
.status-display h3 {
|
||||
margin-bottom: 10px;
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
padding: 8px 12px;
|
||||
margin: 5px 0;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 6px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.9em;
|
||||
animation: slideIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.critical-test {
|
||||
border-left: 4px solid #ff6b6b;
|
||||
}
|
||||
|
||||
.critical-test h2 {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: rgba(52, 152, 219, 0.2);
|
||||
border: 1px solid rgba(52, 152, 219, 0.4);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.info-box h4 {
|
||||
color: #3498db;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.timing-display {
|
||||
text-align: center;
|
||||
font-size: 1.1em;
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
font-size: 1.2em;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.menu-note {
|
||||
background: rgba(255, 193, 7, 0.2);
|
||||
border: 1px solid rgba(255, 193, 7, 0.4);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.menu-note strong {
|
||||
color: #ffc107;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🪟 Window Visibility Test</h1>
|
||||
<p>Testing fixes for Wails v3 Issue #2861 - Windows 10 Pro Efficiency Mode</p>
|
||||
<div class="timing-display">
|
||||
<span id="current-time">Current Time: --:--:--</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2><span class="emoji">✅</span>Basic Window Tests</h2>
|
||||
<p>These tests verify that windows appear immediately when requested, regardless of WebView content loading state.</p>
|
||||
<div class="button-grid">
|
||||
<button class="test-button" onclick="createNormalWindow()">
|
||||
Create Normal Window
|
||||
</button>
|
||||
<button class="test-button" onclick="createDelayedContentWindow()">
|
||||
Create Delayed Content Window
|
||||
</button>
|
||||
<button class="test-button" onclick="createHiddenThenShowWindow()">
|
||||
Hidden → Show Test
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2><span class="emoji">⚡</span>Stress Tests</h2>
|
||||
<p>These tests push the window system to verify robustness under load and timing edge cases.</p>
|
||||
<div class="button-grid">
|
||||
<button class="test-button" onclick="createMultipleWindows()">
|
||||
Multiple Windows (3x)
|
||||
</button>
|
||||
<button class="test-button" onclick="rapidWindowCreation()">
|
||||
Rapid Creation Test
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section critical-test">
|
||||
<h2><span class="emoji">🔬</span>Critical Issue #2861 Test</h2>
|
||||
<p>This test specifically targets the Windows efficiency mode bug where WebView2 NavigationCompleted events could be delayed or missed.</p>
|
||||
|
||||
<div class="info-box">
|
||||
<h4>Expected Behavior:</h4>
|
||||
<ul>
|
||||
<li>Window container appears <strong>immediately</strong> upon button click</li>
|
||||
<li>Content loads progressively (may take 2-3 seconds)</li>
|
||||
<li>No blank or invisible windows, even under efficiency mode</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="button-grid">
|
||||
<button class="test-button" onclick="createEfficiencyModeTestWindow()">
|
||||
🎯 Efficiency Mode Test
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2><span class="emoji">📊</span>Test Results & Timing</h2>
|
||||
<p>Monitor window creation timing and behavior. Each button click should result in immediate window visibility.</p>
|
||||
|
||||
<div class="status-display">
|
||||
<h3>Activity Log</h3>
|
||||
<div id="activity-log">
|
||||
<div class="log-entry">Ready for testing... Click any button to begin.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2><span class="emoji">📝</span>Testing Instructions</h2>
|
||||
<div class="info-box">
|
||||
<h4>What to Look For:</h4>
|
||||
<ul>
|
||||
<li><strong>Immediate Window Appearance:</strong> Windows should appear within 100ms of clicking</li>
|
||||
<li><strong>Progressive Loading:</strong> Content may load progressively, but window container should be visible immediately</li>
|
||||
<li><strong>No Efficiency Mode Issues:</strong> On Windows, windows should still appear even if Task Manager shows "efficiency mode"</li>
|
||||
<li><strong>Consistent Behavior:</strong> All platforms (Windows, macOS, Linux) should behave similarly</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<h4>How to Test:</h4>
|
||||
<ol>
|
||||
<li>Note the current time displayed above</li>
|
||||
<li>Click any test button</li>
|
||||
<li>Immediately observe if a window appears (should be within 100ms)</li>
|
||||
<li>Wait for content to load and check the reported timing</li>
|
||||
<li>Try multiple tests in sequence</li>
|
||||
<li>Test both buttons and menu items</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import {WindowTestService} from "./bindings/window-visibility-test";
|
||||
|
||||
let logCounter = 0;
|
||||
|
||||
// Update current time every second
|
||||
function updateCurrentTime() {
|
||||
const now = new Date();
|
||||
document.getElementById('current-time').textContent =
|
||||
'Current Time: ' + now.toLocaleTimeString() + '.' + String(now.getMilliseconds()).padStart(3, '0');
|
||||
}
|
||||
setInterval(updateCurrentTime, 100);
|
||||
updateCurrentTime();
|
||||
|
||||
// Logging function
|
||||
function logActivity(message, isError = false) {
|
||||
const log = document.getElementById('activity-log');
|
||||
const entry = document.createElement('div');
|
||||
entry.className = 'log-entry';
|
||||
if (isError) entry.style.borderLeft = '4px solid #ff6b6b';
|
||||
|
||||
const timestamp = new Date().toLocaleTimeString() + '.' + String(new Date().getMilliseconds()).padStart(3, '0');
|
||||
entry.innerHTML = `<strong>[${timestamp}]</strong> ${message}`;
|
||||
|
||||
log.appendChild(entry);
|
||||
log.scrollTop = log.scrollHeight;
|
||||
|
||||
// Keep only last 10 entries
|
||||
while (log.children.length > 10) {
|
||||
log.removeChild(log.firstChild);
|
||||
}
|
||||
|
||||
console.log(`[Window Test] ${timestamp}: ${message}`);
|
||||
}
|
||||
|
||||
// Window creation functions that call the Go backend
|
||||
async function createNormalWindow() {
|
||||
const startTime = performance.now();
|
||||
logActivity('🚀 Creating normal window...');
|
||||
|
||||
try {
|
||||
const result = await WindowTestService.CreateNormalWindow();
|
||||
const endTime = performance.now();
|
||||
logActivity(`✅ ${result} (${Math.round(endTime - startTime)}ms)`);
|
||||
} catch (error) {
|
||||
logActivity(`❌ Error creating normal window: ${error.message}`, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function createDelayedContentWindow() {
|
||||
const startTime = performance.now();
|
||||
logActivity('⏳ Creating delayed content window...');
|
||||
|
||||
try {
|
||||
const result = await WindowTestService.CreateDelayedContentWindow();
|
||||
const endTime = performance.now();
|
||||
logActivity(`✅ ${result} (${Math.round(endTime - startTime)}ms)`);
|
||||
} catch (error) {
|
||||
logActivity(`❌ Error creating delayed content window: ${error.message}`, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function createHiddenThenShowWindow() {
|
||||
const startTime = performance.now();
|
||||
logActivity('🔄 Creating hidden then show window...');
|
||||
|
||||
try {
|
||||
const result = await WindowTestService.CreateHiddenThenShowWindow();
|
||||
const endTime = performance.now();
|
||||
logActivity(`✅ ${result} (${Math.round(endTime - startTime)}ms)`);
|
||||
logActivity('⏰ Watch for window to appear in 2 seconds...');
|
||||
} catch (error) {
|
||||
logActivity(`❌ Error creating hidden then show window: ${error.message}`, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function createMultipleWindows() {
|
||||
const startTime = performance.now();
|
||||
logActivity('🔢 Creating multiple windows...');
|
||||
|
||||
try {
|
||||
const result = await WindowTestService.CreateMultipleWindows();
|
||||
const endTime = performance.now();
|
||||
logActivity(`✅ ${result} (${Math.round(endTime - startTime)}ms)`);
|
||||
} catch (error) {
|
||||
logActivity(`❌ Error creating multiple windows: ${error.message}`, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function createEfficiencyModeTestWindow() {
|
||||
const startTime = performance.now();
|
||||
logActivity('🎯 Creating efficiency mode test window...');
|
||||
|
||||
try {
|
||||
const result = await WindowTestService.CreateEfficiencyModeTestWindow();
|
||||
const endTime = performance.now();
|
||||
logActivity(`✅ ${result} (${Math.round(endTime - startTime)}ms)`);
|
||||
logActivity('🔍 Check: Did the window appear immediately?');
|
||||
} catch (error) {
|
||||
logActivity(`❌ Error creating efficiency mode test window: ${error.message}`, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function rapidWindowCreation() {
|
||||
logActivity('🚄 Starting rapid window creation test...');
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
await createNormalWindow();
|
||||
logActivity(`✅ Rapid window ${i + 1} created`);
|
||||
} catch (error) {
|
||||
logActivity(`❌ Rapid window ${i + 1} failed: ${error.message}`, true);
|
||||
}
|
||||
}, i * 200); // 200ms intervals
|
||||
}
|
||||
}
|
||||
|
||||
// Make functions globally available for onclick handlers
|
||||
window.createNormalWindow = createNormalWindow;
|
||||
window.createDelayedContentWindow = createDelayedContentWindow;
|
||||
window.createHiddenThenShowWindow = createHiddenThenShowWindow;
|
||||
window.createMultipleWindows = createMultipleWindows;
|
||||
window.createEfficiencyModeTestWindow = createEfficiencyModeTestWindow;
|
||||
window.rapidWindowCreation = rapidWindowCreation;
|
||||
|
||||
// Log when the page loads
|
||||
window.addEventListener('load', function() {
|
||||
logActivity('📱 Main window loaded and ready for testing');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
55
v3/tests/window-visibility-test/go.mod
Normal file
55
v3/tests/window-visibility-test/go.mod
Normal file
|
|
@ -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
|
||||
146
v3/tests/window-visibility-test/go.sum
Normal file
146
v3/tests/window-visibility-test/go.sum
Normal file
|
|
@ -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=
|
||||
308
v3/tests/window-visibility-test/main.go
Normal file
308
v3/tests/window-visibility-test/main.go
Normal file
|
|
@ -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: "<html><head><title>Normal Window</title><style>body{font-family:Arial,sans-serif;padding:20px;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:white;}</style></head><body><h1>✅ Normal Window</h1><p>This window should have appeared immediately after clicking the button.</p><p>Timestamp: " + time.Now().Format("15:04:05") + "</p></body></html>",
|
||||
})
|
||||
|
||||
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 := `
|
||||
<html>
|
||||
<head>
|
||||
<title>Delayed Content</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; padding: 20px; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; }
|
||||
.spinner { border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 40px; height: 40px; animation: spin 2s linear infinite; margin: 20px auto; }
|
||||
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>⏳ Delayed Content Window</h1>
|
||||
<p>This window tests navigation completion timing.</p>
|
||||
<div class="spinner"></div>
|
||||
<p>Loading... (simulates heavy content)</p>
|
||||
<script>
|
||||
// Simulate slow loading content
|
||||
setTimeout(function() {
|
||||
document.querySelector('.spinner').style.display = 'none';
|
||||
document.body.innerHTML += '<h2>✅ Content Loaded!</h2><p>Navigation completed at: ' + new Date().toLocaleTimeString() + '</p>';
|
||||
}, 3000);
|
||||
</script>
|
||||
<p>Window container should be visible immediately, even during load.</p>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
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: "<html><head><title>Hidden Then Show</title><style>body{font-family:Arial,sans-serif;padding:20px;background:linear-gradient(135deg,#a8edea 0%,#fed6e3 100%);color:#333;}</style></head><body><h1>🔄 Hidden Then Show Window</h1><p>This window was created hidden and then shown after 2 seconds.</p><p>Should test the robustness of the show() method.</p><p>Created at: " + time.Now().Format("15:04:05") + "</p></body></html>",
|
||||
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(`
|
||||
<html>
|
||||
<head>
|
||||
<title>Batch Window %d</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; padding: 20px; background: linear-gradient(135deg, %s); color: #333; text-align: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔢 Batch Window %d</h1>
|
||||
<p>Part of multiple windows stress test</p>
|
||||
<p>All windows should appear quickly and simultaneously</p>
|
||||
<p>Created at: %s</p>
|
||||
</body>
|
||||
</html>`, 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 := `
|
||||
<html>
|
||||
<head>
|
||||
<title>Efficiency Mode Test</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; }
|
||||
.test-section { margin: 20px 0; padding: 15px; background: rgba(255,255,255,0.1); border-radius: 8px; }
|
||||
.heavy-content { height: 200px; overflow-y: scroll; background: rgba(0,0,0,0.2); padding: 10px; border-radius: 4px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>⚡ Efficiency Mode Test Window</h1>
|
||||
<p>This window tests the fix for Windows 10 Pro efficiency mode issue #2861</p>
|
||||
|
||||
<div class="test-section">
|
||||
<h3>Window Container Status</h3>
|
||||
<p id="container-status">✅ Window container is visible (this text proves it)</p>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h3>WebView2 Status</h3>
|
||||
<p id="webview-status">⏳ WebView2 navigation in progress...</p>
|
||||
<p id="navigation-time"></p>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h3>Heavy Content (simulates Vue.js app)</h3>
|
||||
<div class="heavy-content" id="heavy-content">
|
||||
Loading heavy content...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Track navigation completion
|
||||
var startTime = performance.now();
|
||||
document.getElementById('navigation-time').textContent = 'Navigation started at: ' + new Date().toLocaleTimeString();
|
||||
|
||||
// Simulate heavy JavaScript processing
|
||||
function heavyProcessing() {
|
||||
var content = '';
|
||||
for (var i = 0; i < 1000; i++) {
|
||||
content += 'Line ' + i + ': Simulated heavy content processing...<br>';
|
||||
}
|
||||
document.getElementById('heavy-content').innerHTML = content;
|
||||
}
|
||||
|
||||
// Simulate WebView2 navigation completion with delay
|
||||
setTimeout(function() {
|
||||
document.getElementById('webview-status').innerHTML = '✅ WebView2 navigation completed successfully';
|
||||
var endTime = performance.now();
|
||||
document.getElementById('navigation-time').innerHTML += '<br>Navigation completed at: ' + new Date().toLocaleTimeString() +
|
||||
'<br>Total time: ' + Math.round(endTime - startTime) + 'ms';
|
||||
heavyProcessing();
|
||||
}, 2000);
|
||||
|
||||
console.log('Window created at:', new Date().toLocaleTimeString());
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
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: "<html><head><title>About</title><style>body{font-family:Arial,sans-serif;padding:20px;background:#f0f0f0;color:#333;text-align:center;}</style></head><body><h1>Window Visibility Test</h1><p>This application tests the fixes for Wails v3 issue #2861</p><p><strong>Windows 10 Pro Efficiency Mode Fix</strong></p><p>Tests window container vs WebView content visibility</p><hr><p><em>Created for testing robust window visibility patterns</em></p></body></html>",
|
||||
})
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue