From 1650e26da77376a739a506b4d296b4a9169a3daf Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 25 Oct 2023 20:03:16 +1100 Subject: [PATCH] [windows] dnd fixes --- v3/pkg/application/webview_window_windows.go | 75 ++++++++++---------- v3/pkg/w32/idroptarget.go | 17 +++-- v3/pkg/w32/ole32.go | 12 ++++ v3/pkg/w32/user32.go | 12 ++++ v3/pkg/w32/window.go | 5 ++ 5 files changed, 79 insertions(+), 42 deletions(-) diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index 35d51806..f62be69d 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -15,6 +15,7 @@ import ( "strconv" "strings" "sync" + "syscall" "time" "unicode/utf16" "unsafe" @@ -924,7 +925,6 @@ func (w *windowsWebviewWindow) isActive() bool { } func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintptr { - w.onceDo.Do(w.onCreate) switch msg { case w32.WM_ACTIVATE: if int(wparam&0xffff) == w32.WA_INACTIVE { @@ -1309,12 +1309,12 @@ func (w *windowsWebviewWindow) setupChromium() { chromium.AdditionalBrowserArgs = append(chromium.AdditionalBrowserArgs, arg) } - if opts.Permissions != nil { - for permission, state := range opts.Permissions { - chromium.SetPermission(edge.CoreWebView2PermissionKind(permission), + //if opts.Permissions != nil { + // for permission, state := range opts.Permissions { + // chromium.SetPermission(edge.CoreWebView2PermissionKind(permission), edge.CoreWebView2PermissionState(state)) - } - } + // } + //} chromium.MessageCallback = w.processMessage chromium.MessageWithAdditionalObjectsCallback = w.processMessageWithAdditionalObjects @@ -1343,31 +1343,46 @@ func (w *windowsWebviewWindow) setupChromium() { if err != nil { globalApplication.fatal(err.Error()) } + } + if w.parent.options.EnableDragAndDrop { + w.dropTarget = w32.NewDropTarget() + w.dropTarget.OnDrop = func(files []string) { + w.parent.emit(events.Windows.WindowDragDrop) + windowDragAndDropBuffer <- &dragAndDropMessage{ + windowId: windowID, + filenames: files, + } + } if opts.OnEnterEffect != 0 { w.dropTarget.OnEnterEffect = convertEffect(opts.OnEnterEffect) } if opts.OnOverEffect != 0 { w.dropTarget.OnOverEffect = convertEffect(opts.OnOverEffect) } - if w.parent.options.EnableDragAndDrop { - w.dropTarget = w32.NewDropTarget() - w.dropTarget.OnDrop = func(files []string) { - w.parent.emit(events.Windows.WindowDragDrop) - windowDragAndDropBuffer <- &dragAndDropMessage{ - windowId: windowID, - filenames: files, - } - } - w.dropTarget.OnEnter = func() { - w.parent.emit(events.Windows.WindowDragEnter) - } - w.dropTarget.OnLeave = func() { - w.parent.emit(events.Windows.WindowDragLeave) - } - w.dropTarget.OnOver = func() { - w.parent.emit(events.Windows.WindowDragOver) - } + w.dropTarget.OnEnter = func() { + w.parent.emit(events.Windows.WindowDragEnter) } + w.dropTarget.OnLeave = func() { + w.parent.emit(events.Windows.WindowDragLeave) + } + w.dropTarget.OnOver = func() { + w.parent.emit(events.Windows.WindowDragOver) + } + // Enumerate all the child windows for this window and register them as drop targets + w32.EnumChildWindows(w.hwnd, func(hwnd w32.HWND, lparam w32.LPARAM) w32.LRESULT { + // Check if the window class is "Chrome_RenderWidgetHostHWND" + // If it is, then we register it as a drop target + //windowName := w32.GetClassName(hwnd) + //println(windowName) + //if windowName == "Chrome_RenderWidgetHostHWND" { + err := w32.RegisterDragDrop(hwnd, w.dropTarget) + if err != nil && err != syscall.Errno(w32.DRAGDROP_E_ALREADYREGISTERED) { + globalApplication.error("Error registering drag and drop: " + err.Error()) + } + //} + return 1 + }) + } // We will get round to this @@ -1613,18 +1628,6 @@ func (w *windowsWebviewWindow) processMessageWithAdditionalObjects(message strin } } -func (w *windowsWebviewWindow) onCreate() { - // Register DnD - InvokeSync(func() { - if w.parent.options.EnableDragAndDrop { - err := w32.RegisterDragDrop(w.hwnd, w.dropTarget) - if err != nil { - globalApplication.error("Error registering drag and drop: " + err.Error()) - } - } - }) -} - func ScaleWithDPI(pixels int, dpi uint) int { return (pixels * int(dpi)) / 96 } diff --git a/v3/pkg/w32/idroptarget.go b/v3/pkg/w32/idroptarget.go index 19621d1e..4c54ba66 100644 --- a/v3/pkg/w32/idroptarget.go +++ b/v3/pkg/w32/idroptarget.go @@ -7,11 +7,16 @@ import ( "golang.org/x/sys/windows" ) +var ( + DROPEFFECT_NONE DWORD = 0 + DROPEFFECT_COPY DWORD = 1 + DROPEFFECT_MOVE DWORD = 2 + DROPEFFECT_LINK DWORD = 4 +) + const ( - DROPEFFECT_NONE = 0 - DROPEFFECT_COPY = 1 - DROPEFFECT_MOVE = 2 - DROPEFFECT_LINK = 4 + DRAGDROP_E_ALREADYREGISTERED = 0x80040101 + DRAGDROP_E_INVALIDHWND = 0x80040102 ) func _NOP(_ uintptr) uintptr { @@ -25,7 +30,6 @@ func init() { _iDropTargetDragOver, _iDropTargetDragLeave, _iDropTargetDrop, - _NOP, ) } @@ -67,10 +71,11 @@ type DropTarget struct { } func NewDropTarget() *DropTarget { - return &DropTarget{ + result := &DropTarget{ OnEnterEffect: DROPEFFECT_COPY, OnOverEffect: DROPEFFECT_COPY, } + return result } func (d *DropTarget) DragEnter(dataObject *IDataObject, grfKeyState DWORD, point POINT, pdfEffect *DWORD) uintptr { diff --git a/v3/pkg/w32/ole32.go b/v3/pkg/w32/ole32.go index 8eb2c3b6..8e7c20d4 100644 --- a/v3/pkg/w32/ole32.go +++ b/v3/pkg/w32/ole32.go @@ -21,6 +21,7 @@ var ( procCoUninitialize = modole32.NewProc("CoUninitialize") procCreateStreamOnHGlobal = modole32.NewProc("CreateStreamOnHGlobal") procRegisterDragDrop = modole32.NewProc("RegisterDragDrop") + procRevokeDragDrop = modole32.NewProc("RevokeDragDrop") ) func CoInitializeEx(coInit uintptr) HRESULT { @@ -83,3 +84,14 @@ func RegisterDragDrop(hwnd HWND, dropTarget *DropTarget) error { } return nil } + +func RevokeDragDrop(hwnd HWND) error { + hr, _, _ := procRevokeDragDrop.Call( + hwnd, + ) + + if hr != S_OK { + return syscall.Errno(hr) + } + return nil +} diff --git a/v3/pkg/w32/user32.go b/v3/pkg/w32/user32.go index 50834d8b..bf4575fb 100644 --- a/v3/pkg/w32/user32.go +++ b/v3/pkg/w32/user32.go @@ -19,6 +19,7 @@ var ( moduser32 = syscall.NewLazyDLL("user32.dll") procRegisterClassEx = moduser32.NewProc("RegisterClassExW") + procGetClassName = moduser32.NewProc("GetClassNameW") procLoadIcon = moduser32.NewProc("LoadIconW") procLoadCursor = moduser32.NewProc("LoadCursorW") procShowWindow = moduser32.NewProc("ShowWindow") @@ -140,6 +141,7 @@ var ( procEnumDisplaySettings = moduser32.NewProc("EnumDisplaySettingsW") procEnumDisplaySettingsEx = moduser32.NewProc("EnumDisplaySettingsExW") procEnumWindows = moduser32.NewProc("EnumWindows") + procEnumChildWindows = moduser32.NewProc("EnumChildWindows") procChangeDisplaySettingsEx = moduser32.NewProc("ChangeDisplaySettingsExW") procSendInput = moduser32.NewProc("SendInput") procSetWindowsHookEx = moduser32.NewProc("SetWindowsHookExW") @@ -358,6 +360,16 @@ func GetDpiForWindow(hwnd HWND) UINT { return uint(dpi) } +func GetClassName(hwnd HWND) string { + var buf [256]uint16 + procGetClassName.Call( + uintptr(hwnd), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(len(buf))) + + return syscall.UTF16ToString(buf[:]) +} + func SetProcessDPIAware() error { status, r, err := procSetProcessDPIAware.Call() if status == 0 { diff --git a/v3/pkg/w32/window.go b/v3/pkg/w32/window.go index b76d049d..545b4213 100644 --- a/v3/pkg/w32/window.go +++ b/v3/pkg/w32/window.go @@ -246,3 +246,8 @@ func FlashWindow(hwnd HWND, enabled bool) { } _, _, _ = procFlashWindowEx.Call(uintptr(unsafe.Pointer(&flashInfo))) } + +func EnumChildWindows(hwnd HWND, callback func(hwnd HWND, lparam LPARAM) LRESULT) LRESULT { + r, _, _ := procEnumChildWindows.Call(hwnd, syscall.NewCallback(callback), 0) + return r +}