mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 07:21:32 +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
|
package windows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
|
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
|
||||||
"github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
|
"github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *Frontend) getHandleForDialog() w32.HWND {
|
func (f *Frontend) getHandleForDialog() w32.HWND {
|
||||||
@ -40,27 +41,20 @@ func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (stri
|
|||||||
Role: "PickFolder",
|
Role: "PickFolder",
|
||||||
Folder: defaultFolder,
|
Folder: defaultFolder,
|
||||||
}
|
}
|
||||||
thisDialog, err := cfd.NewSelectFolderDialog(config)
|
|
||||||
if err != nil {
|
result, err := f.showCfdDialog(
|
||||||
return "", err
|
func() (cfd.Dialog, error) {
|
||||||
}
|
return cfd.NewSelectFolderDialog(config)
|
||||||
thisDialog.SetParentWindowHandle(f.getHandleForDialog())
|
}, false)
|
||||||
defer func(thisDialog cfd.SelectFolderDialog) {
|
|
||||||
err := thisDialog.Release()
|
|
||||||
if err != nil {
|
|
||||||
println("ERROR: Unable to release dialog:", err.Error())
|
|
||||||
}
|
|
||||||
}(thisDialog)
|
|
||||||
result, err := thisDialog.ShowAndGetResult()
|
|
||||||
if err != nil && err != cfd.ErrorCancelled {
|
if err != nil && err != cfd.ErrorCancelled {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return result, nil
|
return result.(string), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFileDialog prompts the user to select a file
|
// OpenFileDialog prompts the user to select a file
|
||||||
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
|
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
|
||||||
|
|
||||||
defaultFolder, err := getDefaultFolder(options.DefaultDirectory)
|
defaultFolder, err := getDefaultFolder(options.DefaultDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -72,22 +66,16 @@ func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, e
|
|||||||
FileName: options.DefaultFilename,
|
FileName: options.DefaultFilename,
|
||||||
Title: options.Title,
|
Title: options.Title,
|
||||||
}
|
}
|
||||||
thisdialog, err := cfd.NewOpenFileDialog(config)
|
|
||||||
if err != nil {
|
result, err := f.showCfdDialog(
|
||||||
return "", err
|
func() (cfd.Dialog, error) {
|
||||||
}
|
return cfd.NewOpenFileDialog(config)
|
||||||
thisdialog.SetParentWindowHandle(f.getHandleForDialog())
|
}, false)
|
||||||
defer func(thisdialog cfd.OpenFileDialog) {
|
|
||||||
err := thisdialog.Release()
|
|
||||||
if err != nil {
|
|
||||||
println("ERROR: Unable to release dialog:", err.Error())
|
|
||||||
}
|
|
||||||
}(thisdialog)
|
|
||||||
result, err := thisdialog.ShowAndGetResult()
|
|
||||||
if err != nil && err != cfd.ErrorCancelled {
|
if err != nil && err != cfd.ErrorCancelled {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return result, nil
|
return result.(string), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenMultipleFilesDialog prompts the user to select a file
|
// OpenMultipleFilesDialog prompts the user to select a file
|
||||||
@ -105,22 +93,16 @@ func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) (
|
|||||||
FileName: options.DefaultFilename,
|
FileName: options.DefaultFilename,
|
||||||
Folder: defaultFolder,
|
Folder: defaultFolder,
|
||||||
}
|
}
|
||||||
thisdialog, err := cfd.NewOpenMultipleFilesDialog(config)
|
|
||||||
if err != nil {
|
result, err := f.showCfdDialog(
|
||||||
return nil, err
|
func() (cfd.Dialog, error) {
|
||||||
}
|
return cfd.NewOpenMultipleFilesDialog(config)
|
||||||
thisdialog.SetParentWindowHandle(f.getHandleForDialog())
|
}, true)
|
||||||
defer func(thisdialog cfd.OpenMultipleFilesDialog) {
|
|
||||||
err := thisdialog.Release()
|
|
||||||
if err != nil {
|
|
||||||
println("ERROR: Unable to release dialog:", err.Error())
|
|
||||||
}
|
|
||||||
}(thisdialog)
|
|
||||||
result, err := thisdialog.ShowAndGetResults()
|
|
||||||
if err != nil && err != cfd.ErrorCancelled {
|
if err != nil && err != cfd.ErrorCancelled {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return result, nil
|
return result.([]string), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveFileDialog prompts the user to select a file
|
// SaveFileDialog prompts the user to select a file
|
||||||
@ -131,26 +113,44 @@ func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, e
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
|
config := cfd.DialogConfig{
|
||||||
Title: options.Title,
|
Title: options.Title,
|
||||||
Role: "SaveFile",
|
Role: "SaveFile",
|
||||||
FileFilters: convertFilters(options.Filters),
|
FileFilters: convertFilters(options.Filters),
|
||||||
FileName: options.DefaultFilename,
|
FileName: options.DefaultFilename,
|
||||||
Folder: defaultFolder,
|
Folder: defaultFolder,
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
saveDialog.SetParentWindowHandle(f.getHandleForDialog())
|
|
||||||
err = saveDialog.Show()
|
result, err := f.showCfdDialog(
|
||||||
if err != nil {
|
func() (cfd.Dialog, error) {
|
||||||
return "", err
|
return cfd.NewSaveFileDialog(config)
|
||||||
}
|
}, false)
|
||||||
result, err := saveDialog.GetResult()
|
|
||||||
if err != nil && err != cfd.ErrorCancelled {
|
if err != nil && err != cfd.ErrorCancelled {
|
||||||
return "", err
|
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 {
|
func calculateMessageDialogFlags(options frontend.MessageDialogOptions) uint32 {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package windows
|
package windows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
|
"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()
|
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 `-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 `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)
|
- 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
|
## v2.4.1 - 2023-03-20
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user