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 }