github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/darwin/window.go (about)

     1  //go:build darwin
     2  // +build darwin
     3  
     4  package darwin
     5  
     6  /*
     7  #cgo CFLAGS: -x objective-c
     8  #cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
     9  #import <Foundation/Foundation.h>
    10  #import "Application.h"
    11  #import "WailsContext.h"
    12  
    13  #include <stdlib.h>
    14  */
    15  import "C"
    16  
    17  import (
    18  	"log"
    19  	"runtime"
    20  	"strconv"
    21  	"strings"
    22  	"unsafe"
    23  
    24  	"github.com/secoba/wails/v2/pkg/menu"
    25  
    26  	"github.com/secoba/wails/v2/pkg/options"
    27  )
    28  
    29  func init() {
    30  	runtime.LockOSThread()
    31  }
    32  
    33  type Window struct {
    34  	context unsafe.Pointer
    35  }
    36  
    37  func bool2Cint(value bool) C.int {
    38  	if value {
    39  		return C.int(1)
    40  	}
    41  	return C.int(0)
    42  }
    43  
    44  func bool2CboolPtr(value bool) *C.bool {
    45  	v := C.bool(value)
    46  	return &v
    47  }
    48  
    49  func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window {
    50  	c := NewCalloc()
    51  	defer c.Free()
    52  
    53  	frameless := bool2Cint(frontendOptions.Frameless)
    54  	resizable := bool2Cint(!frontendOptions.DisableResize)
    55  	fullscreen := bool2Cint(frontendOptions.Fullscreen)
    56  	alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop)
    57  	hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose)
    58  	startsHidden := bool2Cint(frontendOptions.StartHidden)
    59  	devtoolsEnabled := bool2Cint(devtools)
    60  	defaultContextMenuEnabled := bool2Cint(debug || frontendOptions.EnableDefaultContextMenu)
    61  	singleInstanceEnabled := bool2Cint(frontendOptions.SingleInstanceLock != nil)
    62  
    63  	var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int
    64  	var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int
    65  	var appearance, title *C.char
    66  	var preferences C.struct_Preferences
    67  
    68  	width := C.int(frontendOptions.Width)
    69  	height := C.int(frontendOptions.Height)
    70  	minWidth := C.int(frontendOptions.MinWidth)
    71  	minHeight := C.int(frontendOptions.MinHeight)
    72  	maxWidth := C.int(frontendOptions.MaxWidth)
    73  	maxHeight := C.int(frontendOptions.MaxHeight)
    74  	windowStartState := C.int(int(frontendOptions.WindowStartState))
    75  
    76  	title = c.String(frontendOptions.Title)
    77  
    78  	singleInstanceUniqueIdStr := ""
    79  	if frontendOptions.SingleInstanceLock != nil {
    80  		singleInstanceUniqueIdStr = frontendOptions.SingleInstanceLock.UniqueId
    81  	}
    82  	singleInstanceUniqueId := c.String(singleInstanceUniqueIdStr)
    83  
    84  	enableFraudulentWebsiteWarnings := C.bool(frontendOptions.EnableFraudulentWebsiteDetection)
    85  
    86  	if frontendOptions.Mac != nil {
    87  		mac := frontendOptions.Mac
    88  		if mac.TitleBar != nil {
    89  			fullSizeContent = bool2Cint(mac.TitleBar.FullSizeContent)
    90  			hideTitleBar = bool2Cint(mac.TitleBar.HideTitleBar)
    91  			hideTitle = bool2Cint(mac.TitleBar.HideTitle)
    92  			useToolbar = bool2Cint(mac.TitleBar.UseToolbar)
    93  			titlebarAppearsTransparent = bool2Cint(mac.TitleBar.TitlebarAppearsTransparent)
    94  			hideToolbarSeparator = bool2Cint(mac.TitleBar.HideToolbarSeparator)
    95  		}
    96  
    97  		if mac.Preferences != nil {
    98  			if mac.Preferences.TabFocusesLinks.IsSet() {
    99  				preferences.tabFocusesLinks = bool2CboolPtr(mac.Preferences.TabFocusesLinks.Get())
   100  			}
   101  
   102  			if mac.Preferences.TextInteractionEnabled.IsSet() {
   103  				preferences.textInteractionEnabled = bool2CboolPtr(mac.Preferences.TextInteractionEnabled.Get())
   104  			}
   105  
   106  			if mac.Preferences.FullscreenEnabled.IsSet() {
   107  				preferences.fullscreenEnabled = bool2CboolPtr(mac.Preferences.FullscreenEnabled.Get())
   108  			}
   109  		}
   110  
   111  		windowIsTranslucent = bool2Cint(mac.WindowIsTranslucent)
   112  		webviewIsTransparent = bool2Cint(mac.WebviewIsTransparent)
   113  
   114  		appearance = c.String(string(mac.Appearance))
   115  	}
   116  	var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
   117  		hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
   118  		alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled,
   119  		windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings,
   120  		preferences, singleInstanceEnabled, singleInstanceUniqueId,
   121  	)
   122  
   123  	// Create menu
   124  	result := &Window{
   125  		context: unsafe.Pointer(context),
   126  	}
   127  
   128  	if frontendOptions.BackgroundColour != nil {
   129  		result.SetBackgroundColour(frontendOptions.BackgroundColour.R, frontendOptions.BackgroundColour.G, frontendOptions.BackgroundColour.B, frontendOptions.BackgroundColour.A)
   130  	}
   131  
   132  	if frontendOptions.Mac != nil && frontendOptions.Mac.About != nil {
   133  		title := c.String(frontendOptions.Mac.About.Title)
   134  		description := c.String(frontendOptions.Mac.About.Message)
   135  		var icon unsafe.Pointer
   136  		var length C.int
   137  		if frontendOptions.Mac.About.Icon != nil {
   138  			icon = unsafe.Pointer(&frontendOptions.Mac.About.Icon[0])
   139  			length = C.int(len(frontendOptions.Mac.About.Icon))
   140  		}
   141  		C.SetAbout(result.context, title, description, icon, length)
   142  	}
   143  
   144  	if frontendOptions.Menu != nil {
   145  		result.SetApplicationMenu(frontendOptions.Menu)
   146  	}
   147  
   148  	if debug && frontendOptions.Debug.OpenInspectorOnStartup {
   149  		showInspector(result.context)
   150  	}
   151  	return result
   152  }
   153  
   154  func (w *Window) Center() {
   155  	C.Center(w.context)
   156  }
   157  
   158  func (w *Window) Run(url string) {
   159  	_url := C.CString(url)
   160  	C.Run(w.context, _url)
   161  	C.free(unsafe.Pointer(_url))
   162  }
   163  
   164  func (w *Window) Quit() {
   165  	C.Quit(w.context)
   166  }
   167  
   168  func (w *Window) SetBackgroundColour(r uint8, g uint8, b uint8, a uint8) {
   169  	C.SetBackgroundColour(w.context, C.int(r), C.int(g), C.int(b), C.int(a))
   170  }
   171  
   172  func (w *Window) ExecJS(js string) {
   173  	_js := C.CString(js)
   174  	C.ExecJS(w.context, _js)
   175  	C.free(unsafe.Pointer(_js))
   176  }
   177  
   178  func (w *Window) SetPosition(x int, y int) {
   179  	C.SetPosition(w.context, C.int(x), C.int(y))
   180  }
   181  
   182  func (w *Window) SetSize(width int, height int) {
   183  	C.SetSize(w.context, C.int(width), C.int(height))
   184  }
   185  
   186  func (w *Window) SetAlwaysOnTop(onTop bool) {
   187  	C.SetAlwaysOnTop(w.context, bool2Cint(onTop))
   188  }
   189  
   190  func (w *Window) SetTitle(title string) {
   191  	t := C.CString(title)
   192  	C.SetTitle(w.context, t)
   193  	C.free(unsafe.Pointer(t))
   194  }
   195  
   196  func (w *Window) Maximise() {
   197  	C.Maximise(w.context)
   198  }
   199  
   200  func (w *Window) ToggleMaximise() {
   201  	C.ToggleMaximise(w.context)
   202  }
   203  
   204  func (w *Window) UnMaximise() {
   205  	C.UnMaximise(w.context)
   206  }
   207  
   208  func (w *Window) IsMaximised() bool {
   209  	return (bool)(C.IsMaximised(w.context))
   210  }
   211  
   212  func (w *Window) Minimise() {
   213  	C.Minimise(w.context)
   214  }
   215  
   216  func (w *Window) UnMinimise() {
   217  	C.UnMinimise(w.context)
   218  }
   219  
   220  func (w *Window) IsMinimised() bool {
   221  	return (bool)(C.IsMinimised(w.context))
   222  }
   223  
   224  func (w *Window) IsNormal() bool {
   225  	return !w.IsMaximised() && !w.IsMinimised() && !w.IsFullScreen()
   226  }
   227  
   228  func (w *Window) SetMinSize(width int, height int) {
   229  	C.SetMinSize(w.context, C.int(width), C.int(height))
   230  }
   231  
   232  func (w *Window) SetMaxSize(width int, height int) {
   233  	C.SetMaxSize(w.context, C.int(width), C.int(height))
   234  }
   235  
   236  func (w *Window) Fullscreen() {
   237  	C.Fullscreen(w.context)
   238  }
   239  
   240  func (w *Window) UnFullscreen() {
   241  	C.UnFullscreen(w.context)
   242  }
   243  
   244  func (w *Window) IsFullScreen() bool {
   245  	return (bool)(C.IsFullScreen(w.context))
   246  }
   247  
   248  func (w *Window) Show() {
   249  	C.Show(w.context)
   250  }
   251  
   252  func (w *Window) Hide() {
   253  	C.Hide(w.context)
   254  }
   255  
   256  func (w *Window) ShowApplication() {
   257  	C.ShowApplication(w.context)
   258  }
   259  
   260  func (w *Window) HideApplication() {
   261  	C.HideApplication(w.context)
   262  }
   263  
   264  func parseIntDuo(temp string) (int, int) {
   265  	split := strings.Split(temp, ",")
   266  	x, err := strconv.Atoi(split[0])
   267  	if err != nil {
   268  		log.Fatal(err)
   269  	}
   270  	y, err := strconv.Atoi(split[1])
   271  	if err != nil {
   272  		log.Fatal(err)
   273  	}
   274  	return x, y
   275  }
   276  
   277  func (w *Window) GetPosition() (int, int) {
   278  	var _result *C.char = C.GetPosition(w.context)
   279  	temp := C.GoString(_result)
   280  	return parseIntDuo(temp)
   281  }
   282  
   283  func (w *Window) Size() (int, int) {
   284  	var _result *C.char = C.GetSize(w.context)
   285  	temp := C.GoString(_result)
   286  	return parseIntDuo(temp)
   287  }
   288  
   289  func (w *Window) SetApplicationMenu(inMenu *menu.Menu) {
   290  	mainMenu := NewNSMenu(w.context, "")
   291  	processMenu(mainMenu, inMenu)
   292  	C.SetAsApplicationMenu(w.context, mainMenu.nsmenu)
   293  }
   294  
   295  func (w *Window) UpdateApplicationMenu() {
   296  	C.UpdateApplicationMenu(w.context)
   297  }
   298  
   299  func (w Window) Print() {
   300  	C.WindowPrint(w.context)
   301  }