mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-01 20:50:43 +08:00
[v2, windows] Make sure to open the CommonFileDialogs on the main thread (#2606)
Otherwise it might have some strange side-effects like blocking the completion of Deferrals in WebView2 when using custom IStreams.
This commit is contained in:
parent
46bcce7566
commit
767bfcff89
@ -4,13 +4,14 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
|
||||
"github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
|
||||
"golang.org/x/sys/windows"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (f *Frontend) getHandleForDialog() w32.HWND {
|
||||
@ -40,27 +41,20 @@ func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (stri
|
||||
Role: "PickFolder",
|
||||
Folder: defaultFolder,
|
||||
}
|
||||
thisDialog, err := cfd.NewSelectFolderDialog(config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
thisDialog.SetParentWindowHandle(f.getHandleForDialog())
|
||||
defer func(thisDialog cfd.SelectFolderDialog) {
|
||||
err := thisDialog.Release()
|
||||
if err != nil {
|
||||
println("ERROR: Unable to release dialog:", err.Error())
|
||||
}
|
||||
}(thisDialog)
|
||||
result, err := thisDialog.ShowAndGetResult()
|
||||
|
||||
result, err := f.showCfdDialog(
|
||||
func() (cfd.Dialog, error) {
|
||||
return cfd.NewSelectFolderDialog(config)
|
||||
}, false)
|
||||
|
||||
if err != nil && err != cfd.ErrorCancelled {
|
||||
return "", err
|
||||
}
|
||||
return result, nil
|
||||
return result.(string), nil
|
||||
}
|
||||
|
||||
// OpenFileDialog prompts the user to select a file
|
||||
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
|
||||
|
||||
defaultFolder, err := getDefaultFolder(options.DefaultDirectory)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -72,22 +66,16 @@ func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, e
|
||||
FileName: options.DefaultFilename,
|
||||
Title: options.Title,
|
||||
}
|
||||
thisdialog, err := cfd.NewOpenFileDialog(config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
thisdialog.SetParentWindowHandle(f.getHandleForDialog())
|
||||
defer func(thisdialog cfd.OpenFileDialog) {
|
||||
err := thisdialog.Release()
|
||||
if err != nil {
|
||||
println("ERROR: Unable to release dialog:", err.Error())
|
||||
}
|
||||
}(thisdialog)
|
||||
result, err := thisdialog.ShowAndGetResult()
|
||||
|
||||
result, err := f.showCfdDialog(
|
||||
func() (cfd.Dialog, error) {
|
||||
return cfd.NewOpenFileDialog(config)
|
||||
}, false)
|
||||
|
||||
if err != nil && err != cfd.ErrorCancelled {
|
||||
return "", err
|
||||
}
|
||||
return result, nil
|
||||
return result.(string), nil
|
||||
}
|
||||
|
||||
// OpenMultipleFilesDialog prompts the user to select a file
|
||||
@ -105,22 +93,16 @@ func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) (
|
||||
FileName: options.DefaultFilename,
|
||||
Folder: defaultFolder,
|
||||
}
|
||||
thisdialog, err := cfd.NewOpenMultipleFilesDialog(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
thisdialog.SetParentWindowHandle(f.getHandleForDialog())
|
||||
defer func(thisdialog cfd.OpenMultipleFilesDialog) {
|
||||
err := thisdialog.Release()
|
||||
if err != nil {
|
||||
println("ERROR: Unable to release dialog:", err.Error())
|
||||
}
|
||||
}(thisdialog)
|
||||
result, err := thisdialog.ShowAndGetResults()
|
||||
|
||||
result, err := f.showCfdDialog(
|
||||
func() (cfd.Dialog, error) {
|
||||
return cfd.NewOpenMultipleFilesDialog(config)
|
||||
}, true)
|
||||
|
||||
if err != nil && err != cfd.ErrorCancelled {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
return result.([]string), nil
|
||||
}
|
||||
|
||||
// SaveFileDialog prompts the user to select a file
|
||||
@ -131,26 +113,44 @@ func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, e
|
||||
return "", err
|
||||
}
|
||||
|
||||
saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
|
||||
config := cfd.DialogConfig{
|
||||
Title: options.Title,
|
||||
Role: "SaveFile",
|
||||
FileFilters: convertFilters(options.Filters),
|
||||
FileName: options.DefaultFilename,
|
||||
Folder: defaultFolder,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
saveDialog.SetParentWindowHandle(f.getHandleForDialog())
|
||||
err = saveDialog.Show()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result, err := saveDialog.GetResult()
|
||||
|
||||
result, err := f.showCfdDialog(
|
||||
func() (cfd.Dialog, error) {
|
||||
return cfd.NewSaveFileDialog(config)
|
||||
}, false)
|
||||
|
||||
if err != nil && err != cfd.ErrorCancelled {
|
||||
return "", err
|
||||
}
|
||||
return result, nil
|
||||
return result.(string), nil
|
||||
}
|
||||
|
||||
func (f *Frontend) showCfdDialog(newDlg func() (cfd.Dialog, error), isMultiSelect bool) (any, error) {
|
||||
return invokeSync(f.mainWindow, func() (any, error) {
|
||||
dlg, err := newDlg()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
err := dlg.Release()
|
||||
if err != nil {
|
||||
println("ERROR: Unable to release dialog:", err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
dlg.SetParentWindowHandle(f.getHandleForDialog())
|
||||
if multi, _ := dlg.(cfd.OpenMultipleFilesDialog); multi != nil && isMultiSelect {
|
||||
return multi.ShowAndGetResults()
|
||||
}
|
||||
return dlg.ShowAndGetResult()
|
||||
})
|
||||
}
|
||||
|
||||
func calculateMessageDialogFlags(options frontend.MessageDialogOptions) uint32 {
|
||||
|
@ -3,6 +3,7 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
|
||||
@ -323,3 +324,14 @@ func (w *Window) SetTheme(theme winoptions.Theme) {
|
||||
w.UpdateTheme()
|
||||
})
|
||||
}
|
||||
|
||||
func invokeSync[T any](cba *Window, fn func() (T, error)) (res T, err error) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
cba.Invoke(func() {
|
||||
res, err = fn()
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
return res, err
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Fixed `-skipbindings` flag in `wails dev`. Fixed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2584)
|
||||
- Fixed `runtime.MenuUpdateApplicationMenu` on macOS. Fixed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2588)
|
||||
- Fixed add package name for `libwebkit`/`pkg-config` and use shell.RunCommandWithENV instead of shell.RunCommand in `zypper.go`. Fixed by @wgjtyu in [PR](https://github.com/wailsapp/wails/pull/2593)
|
||||
- Make sure to start the CommonFileDialogs on Windows on the Main-Thread. Fixed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2606)
|
||||
|
||||
## v2.4.1 - 2023-03-20
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user