mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 17:52:29 +08:00

* Feature/1090 native drag and drop for file and folder (#3203) * implement basic dnd for linux * implemented windows * progress changed linux handling and added coordinates to drop * progress fix drop coordinates on windows * progress remove log from windows * progress move js * update js after merge * fix event listener registration * fix segfault on non file drag * remove logs, fix coordinates * minor changes, simplify to drop only * rename EnableWails -> EnableFileDrop * add documentation (PR id missing) * add PR id to changelog * fix remove casting from malloc * fix nil check for OnFileDrop's callback * fix nil check for OnFileDrop skip event when nil * add error message for nil callback in OnFileDrop --------- Co-authored-by: lyimmi <lelvente.zambo@gmail.com> Co-authored-by: Lea Anthony <lea.anthony@gmail.com> * implement native drag and drop for macOS (#3250) * implement native drag and drop for macOS * update docs * add to changelog * update docs (macOS is supported) * Fix windows DragAndDrop options * Fix class unset on dragleave for full frame elements * improve class unset (nested elements and borders case) * Fix runtime drop target detection and CSS class assignment * Edit changelog * Fix drag-and-drop options in references * Update v2/internal/frontend/desktop/darwin/WailsWebView.m * Update v2/internal/frontend/desktop/darwin/WailsWebView.m --------- Co-authored-by: Zámbó, Levente <levente.zambo@gmail.com> Co-authored-by: lyimmi <lelvente.zambo@gmail.com> Co-authored-by: Lea Anthony <lea.anthony@gmail.com> Co-authored-by: Andrey Pshenkin <andrey.pshenkin@gmail.com> Co-authored-by: Pavel Binar <pavel@beamtransfer.io>
307 lines
8.0 KiB
Go
307 lines
8.0 KiB
Go
//go:build darwin
|
|
// +build darwin
|
|
|
|
package darwin
|
|
|
|
/*
|
|
#cgo CFLAGS: -x objective-c
|
|
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
|
|
#import <Foundation/Foundation.h>
|
|
#import "Application.h"
|
|
#import "WailsContext.h"
|
|
|
|
#include <stdlib.h>
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"log"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
|
|
|
"github.com/wailsapp/wails/v2/pkg/options"
|
|
)
|
|
|
|
func init() {
|
|
runtime.LockOSThread()
|
|
}
|
|
|
|
type Window struct {
|
|
context unsafe.Pointer
|
|
}
|
|
|
|
func bool2Cint(value bool) C.int {
|
|
if value {
|
|
return C.int(1)
|
|
}
|
|
return C.int(0)
|
|
}
|
|
|
|
func bool2CboolPtr(value bool) *C.bool {
|
|
v := C.bool(value)
|
|
return &v
|
|
}
|
|
|
|
func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window {
|
|
c := NewCalloc()
|
|
defer c.Free()
|
|
|
|
frameless := bool2Cint(frontendOptions.Frameless)
|
|
resizable := bool2Cint(!frontendOptions.DisableResize)
|
|
fullscreen := bool2Cint(frontendOptions.Fullscreen)
|
|
alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop)
|
|
hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose)
|
|
startsHidden := bool2Cint(frontendOptions.StartHidden)
|
|
devtoolsEnabled := bool2Cint(devtools)
|
|
defaultContextMenuEnabled := bool2Cint(debug || frontendOptions.EnableDefaultContextMenu)
|
|
singleInstanceEnabled := bool2Cint(frontendOptions.SingleInstanceLock != nil)
|
|
|
|
var fullSizeContent, hideTitleBar, zoomable, hideTitle, useToolbar, webviewIsTransparent C.int
|
|
var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int
|
|
var appearance, title *C.char
|
|
var preferences C.struct_Preferences
|
|
|
|
width := C.int(frontendOptions.Width)
|
|
height := C.int(frontendOptions.Height)
|
|
minWidth := C.int(frontendOptions.MinWidth)
|
|
minHeight := C.int(frontendOptions.MinHeight)
|
|
maxWidth := C.int(frontendOptions.MaxWidth)
|
|
maxHeight := C.int(frontendOptions.MaxHeight)
|
|
windowStartState := C.int(int(frontendOptions.WindowStartState))
|
|
|
|
title = c.String(frontendOptions.Title)
|
|
|
|
singleInstanceUniqueIdStr := ""
|
|
if frontendOptions.SingleInstanceLock != nil {
|
|
singleInstanceUniqueIdStr = frontendOptions.SingleInstanceLock.UniqueId
|
|
}
|
|
singleInstanceUniqueId := c.String(singleInstanceUniqueIdStr)
|
|
|
|
enableFraudulentWebsiteWarnings := C.bool(frontendOptions.EnableFraudulentWebsiteDetection)
|
|
|
|
enableDragAndDrop := C.bool(frontendOptions.DragAndDrop != nil && frontendOptions.DragAndDrop.EnableFileDrop)
|
|
disableWebViewDragAndDrop := C.bool(frontendOptions.DragAndDrop != nil && frontendOptions.DragAndDrop.DisableWebViewDrop)
|
|
|
|
if frontendOptions.Mac != nil {
|
|
mac := frontendOptions.Mac
|
|
if mac.TitleBar != nil {
|
|
fullSizeContent = bool2Cint(mac.TitleBar.FullSizeContent)
|
|
hideTitleBar = bool2Cint(mac.TitleBar.HideTitleBar)
|
|
hideTitle = bool2Cint(mac.TitleBar.HideTitle)
|
|
useToolbar = bool2Cint(mac.TitleBar.UseToolbar)
|
|
titlebarAppearsTransparent = bool2Cint(mac.TitleBar.TitlebarAppearsTransparent)
|
|
hideToolbarSeparator = bool2Cint(mac.TitleBar.HideToolbarSeparator)
|
|
}
|
|
|
|
if mac.Preferences != nil {
|
|
if mac.Preferences.TabFocusesLinks.IsSet() {
|
|
preferences.tabFocusesLinks = bool2CboolPtr(mac.Preferences.TabFocusesLinks.Get())
|
|
}
|
|
|
|
if mac.Preferences.TextInteractionEnabled.IsSet() {
|
|
preferences.textInteractionEnabled = bool2CboolPtr(mac.Preferences.TextInteractionEnabled.Get())
|
|
}
|
|
|
|
if mac.Preferences.FullscreenEnabled.IsSet() {
|
|
preferences.fullscreenEnabled = bool2CboolPtr(mac.Preferences.FullscreenEnabled.Get())
|
|
}
|
|
}
|
|
|
|
zoomable = bool2Cint(!frontendOptions.Mac.DisableZoom)
|
|
|
|
windowIsTranslucent = bool2Cint(mac.WindowIsTranslucent)
|
|
webviewIsTransparent = bool2Cint(mac.WebviewIsTransparent)
|
|
|
|
appearance = c.String(string(mac.Appearance))
|
|
}
|
|
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, zoomable, fullscreen, fullSizeContent,
|
|
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
|
|
alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled,
|
|
windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings,
|
|
preferences, singleInstanceEnabled, singleInstanceUniqueId, enableDragAndDrop, disableWebViewDragAndDrop,
|
|
)
|
|
|
|
// Create menu
|
|
result := &Window{
|
|
context: unsafe.Pointer(context),
|
|
}
|
|
|
|
if frontendOptions.BackgroundColour != nil {
|
|
result.SetBackgroundColour(frontendOptions.BackgroundColour.R, frontendOptions.BackgroundColour.G, frontendOptions.BackgroundColour.B, frontendOptions.BackgroundColour.A)
|
|
}
|
|
|
|
if frontendOptions.Mac != nil && frontendOptions.Mac.About != nil {
|
|
title := c.String(frontendOptions.Mac.About.Title)
|
|
description := c.String(frontendOptions.Mac.About.Message)
|
|
var icon unsafe.Pointer
|
|
var length C.int
|
|
if frontendOptions.Mac.About.Icon != nil {
|
|
icon = unsafe.Pointer(&frontendOptions.Mac.About.Icon[0])
|
|
length = C.int(len(frontendOptions.Mac.About.Icon))
|
|
}
|
|
C.SetAbout(result.context, title, description, icon, length)
|
|
}
|
|
|
|
if frontendOptions.Menu != nil {
|
|
result.SetApplicationMenu(frontendOptions.Menu)
|
|
}
|
|
|
|
if debug && frontendOptions.Debug.OpenInspectorOnStartup {
|
|
showInspector(result.context)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (w *Window) Center() {
|
|
C.Center(w.context)
|
|
}
|
|
|
|
func (w *Window) Run(url string) {
|
|
_url := C.CString(url)
|
|
C.Run(w.context, _url)
|
|
C.free(unsafe.Pointer(_url))
|
|
}
|
|
|
|
func (w *Window) Quit() {
|
|
C.Quit(w.context)
|
|
}
|
|
|
|
func (w *Window) SetBackgroundColour(r uint8, g uint8, b uint8, a uint8) {
|
|
C.SetBackgroundColour(w.context, C.int(r), C.int(g), C.int(b), C.int(a))
|
|
}
|
|
|
|
func (w *Window) ExecJS(js string) {
|
|
_js := C.CString(js)
|
|
C.ExecJS(w.context, _js)
|
|
C.free(unsafe.Pointer(_js))
|
|
}
|
|
|
|
func (w *Window) SetPosition(x int, y int) {
|
|
C.SetPosition(w.context, C.int(x), C.int(y))
|
|
}
|
|
|
|
func (w *Window) SetSize(width int, height int) {
|
|
C.SetSize(w.context, C.int(width), C.int(height))
|
|
}
|
|
|
|
func (w *Window) SetAlwaysOnTop(onTop bool) {
|
|
C.SetAlwaysOnTop(w.context, bool2Cint(onTop))
|
|
}
|
|
|
|
func (w *Window) SetTitle(title string) {
|
|
t := C.CString(title)
|
|
C.SetTitle(w.context, t)
|
|
C.free(unsafe.Pointer(t))
|
|
}
|
|
|
|
func (w *Window) Maximise() {
|
|
C.Maximise(w.context)
|
|
}
|
|
|
|
func (w *Window) ToggleMaximise() {
|
|
C.ToggleMaximise(w.context)
|
|
}
|
|
|
|
func (w *Window) UnMaximise() {
|
|
C.UnMaximise(w.context)
|
|
}
|
|
|
|
func (w *Window) IsMaximised() bool {
|
|
return (bool)(C.IsMaximised(w.context))
|
|
}
|
|
|
|
func (w *Window) Minimise() {
|
|
C.Minimise(w.context)
|
|
}
|
|
|
|
func (w *Window) UnMinimise() {
|
|
C.UnMinimise(w.context)
|
|
}
|
|
|
|
func (w *Window) IsMinimised() bool {
|
|
return (bool)(C.IsMinimised(w.context))
|
|
}
|
|
|
|
func (w *Window) IsNormal() bool {
|
|
return !w.IsMaximised() && !w.IsMinimised() && !w.IsFullScreen()
|
|
}
|
|
|
|
func (w *Window) SetMinSize(width int, height int) {
|
|
C.SetMinSize(w.context, C.int(width), C.int(height))
|
|
}
|
|
|
|
func (w *Window) SetMaxSize(width int, height int) {
|
|
C.SetMaxSize(w.context, C.int(width), C.int(height))
|
|
}
|
|
|
|
func (w *Window) Fullscreen() {
|
|
C.Fullscreen(w.context)
|
|
}
|
|
|
|
func (w *Window) UnFullscreen() {
|
|
C.UnFullscreen(w.context)
|
|
}
|
|
|
|
func (w *Window) IsFullScreen() bool {
|
|
return (bool)(C.IsFullScreen(w.context))
|
|
}
|
|
|
|
func (w *Window) Show() {
|
|
C.Show(w.context)
|
|
}
|
|
|
|
func (w *Window) Hide() {
|
|
C.Hide(w.context)
|
|
}
|
|
|
|
func (w *Window) ShowApplication() {
|
|
C.ShowApplication(w.context)
|
|
}
|
|
|
|
func (w *Window) HideApplication() {
|
|
C.HideApplication(w.context)
|
|
}
|
|
|
|
func parseIntDuo(temp string) (int, int) {
|
|
split := strings.Split(temp, ",")
|
|
x, err := strconv.Atoi(split[0])
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
y, err := strconv.Atoi(split[1])
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return x, y
|
|
}
|
|
|
|
func (w *Window) GetPosition() (int, int) {
|
|
var _result *C.char = C.GetPosition(w.context)
|
|
temp := C.GoString(_result)
|
|
return parseIntDuo(temp)
|
|
}
|
|
|
|
func (w *Window) Size() (int, int) {
|
|
var _result *C.char = C.GetSize(w.context)
|
|
temp := C.GoString(_result)
|
|
return parseIntDuo(temp)
|
|
}
|
|
|
|
func (w *Window) SetApplicationMenu(inMenu *menu.Menu) {
|
|
mainMenu := NewNSMenu(w.context, "")
|
|
processMenu(mainMenu, inMenu)
|
|
C.SetAsApplicationMenu(w.context, mainMenu.nsmenu)
|
|
}
|
|
|
|
func (w *Window) UpdateApplicationMenu() {
|
|
C.UpdateApplicationMenu(w.context)
|
|
}
|
|
|
|
func (w Window) Print() {
|
|
C.WindowPrint(w.context)
|
|
}
|