From 54bf8c11427d0ca8e9e8c3b23b593173b0e33fd9 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 18 Apr 2023 21:27:09 +1000 Subject: [PATCH] [windows] Initial commit --- v3/STATUS.md | 60 ++--- v3/pkg/application/application.go | 35 +-- v3/pkg/application/application_windows.go | 89 +++++++ v3/pkg/application/clipboard.go | 2 - v3/pkg/application/clipboard_windows.go | 28 ++ v3/pkg/application/dialogs.go | 1 - v3/pkg/application/dialogs_windows.go | 173 +++++++++++++ v3/pkg/application/menu.go | 2 +- v3/pkg/application/menu_windows.go | 52 ++++ v3/pkg/application/menuitem.go | 2 +- v3/pkg/application/menuitem_darwin.go | 18 +- v3/pkg/application/menuitem_windows.go | 179 +++++++++++++ v3/pkg/application/systemtray_windows.go | 68 +++++ v3/pkg/application/webview_window_windows.go | 253 +++++++++++++++++++ 14 files changed, 904 insertions(+), 58 deletions(-) create mode 100644 v3/pkg/application/application_windows.go create mode 100644 v3/pkg/application/clipboard_windows.go create mode 100644 v3/pkg/application/dialogs_windows.go create mode 100644 v3/pkg/application/menu_windows.go create mode 100644 v3/pkg/application/menuitem_windows.go create mode 100644 v3/pkg/application/systemtray_windows.go create mode 100644 v3/pkg/application/webview_window_windows.go diff --git a/v3/STATUS.md b/v3/STATUS.md index 2b6a1864..148c217b 100644 --- a/v3/STATUS.md +++ b/v3/STATUS.md @@ -19,6 +19,8 @@ Application interface methods | dispatchOnMainThread(id uint) | | | ✅ | | | hide() | | | ✅ | | | show() | | | ✅ | | +| getPrimaryScreen() (*Screen, error) | | | ✅ | | +| getScreens() ([]*Screen, error) | | | ✅ | | ## Webview Window @@ -117,35 +119,35 @@ Webview Window Interface Methods ### Window -| Feature | Windows | Linux | Mac | Notes | -|---------------------|---------|-------|-----|------------------------| -| SetTitle | | | ✅ | | -| SetSize | | | ✅ | | -| Size | | | ✅ | | -| SetPosition | | | ✅ | | -| Position | | | ✅ | | -| FullScreen | | | ✅ | | -| UnFullscreen | | | ✅ | | -| Minimise | | | ✅ | | -| UnMinimise | | | ✅ | | -| Maximise | | | ✅ | | -| UnMaximise | | | ✅ | | -| Show | | | ✅ | | -| Hide | | | ✅ | | -| Center | | | ✅ | | -| SetBackgroundColour | | | ✅ | | -| SetAlwaysOnTop | | | ✅ | | -| SetResizable | | | ✅ | | -| SetMinSize | | | ✅ | | -| SetMaxSize | | | ✅ | | -| Width | | | ✅ | | -| Height | | | ✅ | | -| ZoomIn | | | ✅ | Increase view scale | -| ZoomOut | | | ✅ | Decrease view scale | -| ZoomReset | | | ✅ | Reset view scale | -| GetZoom | | | ✅ | Get current view scale | -| SetZoom | | | ✅ | Set view scale | -| Screen | | | ✅ | Get screen for window | +| Feature | Windows | Linux | Mac | Notes | +|---------------------|---------|-------|-----|--------------------------------------------------------------------------------------| +| SetTitle | | | ✅ | | +| SetSize | | | ✅ | | +| Size | | | ✅ | | +| SetPosition | | | ✅ | | +| Position | | | ✅ | | +| FullScreen | | | ✅ | | +| UnFullscreen | | | ✅ | | +| Minimise | | | ✅ | | +| UnMinimise | | | ✅ | | +| Maximise | | | ✅ | | +| UnMaximise | | | ✅ | | +| Show | | | ✅ | | +| Hide | | | ✅ | | +| Center | | | ✅ | | +| SetBackgroundColour | | | ✅ | https://github.com/MicrosoftEdge/WebView2Feedback/issues/1621#issuecomment-938234294 | +| SetAlwaysOnTop | | | ✅ | | +| SetResizable | | | ✅ | | +| SetMinSize | | | ✅ | | +| SetMaxSize | | | ✅ | | +| Width | | | ✅ | | +| Height | | | ✅ | | +| ZoomIn | | | ✅ | Increase view scale | +| ZoomOut | | | ✅ | Decrease view scale | +| ZoomReset | | | ✅ | Reset view scale | +| GetZoom | | | ✅ | Get current view scale | +| SetZoom | | | ✅ | Set view scale | +| Screen | | | ✅ | Get screen for window | ### Log diff --git a/v3/pkg/application/application.go b/v3/pkg/application/application.go index aa2e0296..b26d6a6f 100644 --- a/v3/pkg/application/application.go +++ b/v3/pkg/application/application.go @@ -1,6 +1,5 @@ package application -import "C" import ( "log" "net/http" @@ -97,19 +96,23 @@ func mergeApplicationDefaults(o *Options) { } -type platformApp interface { - run() error - destroy() - setApplicationMenu(menu *Menu) - name() string - getCurrentWindowID() uint - showAboutDialog(name string, description string, icon []byte) - setIcon(icon []byte) - on(id uint) - dispatchOnMainThread(id uint) - hide() - show() -} +type ( + platformApp interface { + run() error + destroy() + setApplicationMenu(menu *Menu) + name() string + getCurrentWindowID() uint + showAboutDialog(name string, description string, icon []byte) + setIcon(icon []byte) + on(id uint) + dispatchOnMainThread(id uint) + hide() + show() + getPrimaryScreen() (*Screen, error) + getScreens() ([]*Screen, error) + } +) // Messages sent from javascript get routed here type windowMessage struct { @@ -518,11 +521,11 @@ func (a *App) SaveFileDialog() *SaveFileDialog { } func (a *App) GetPrimaryScreen() (*Screen, error) { - return getPrimaryScreen() + return a.impl.getPrimaryScreen() } func (a *App) GetScreens() ([]*Screen, error) { - return getScreens() + return a.impl.getScreens() } func (a *App) Clipboard() *Clipboard { diff --git a/v3/pkg/application/application_windows.go b/v3/pkg/application/application_windows.go new file mode 100644 index 00000000..de791ce5 --- /dev/null +++ b/v3/pkg/application/application_windows.go @@ -0,0 +1,89 @@ +//go:build windows + +package application + +type windowsApp struct { + //applicationMenu unsafe.Pointer + parent *App +} + +func (m *windowsApp) dispatchOnMainThread(id uint) { + //TODO implement me + panic("implement me") +} + +func (m *windowsApp) getPrimaryScreen() (*Screen, error) { + //TODO implement me + panic("implement me") +} + +func (m *windowsApp) getScreens() ([]*Screen, error) { + //TODO implement me + panic("implement me") +} + +func (m *windowsApp) hide() { + //C.hide() +} + +func (m *windowsApp) show() { + //C.show() +} + +func (m *windowsApp) on(eventID uint) { + //C.registerListener(C.uint(eventID)) +} + +func (m *windowsApp) setIcon(icon []byte) { + //C.setApplicationIcon(unsafe.Pointer(&icon[0]), C.int(len(icon))) +} + +func (m *windowsApp) name() string { + //appName := C.getAppName() + //defer C.free(unsafe.Pointer(appName)) + //return C.GoString(appName) + return "" +} + +func (m *windowsApp) getCurrentWindowID() uint { + //return uint(C.getCurrentWindowID()) + return uint(0) +} + +func (m *windowsApp) setApplicationMenu(menu *Menu) { + if menu == nil { + // Create a default menu for mac + menu = defaultApplicationMenu() + } + menu.Update() + + // Convert impl to macosMenu object + //m.applicationMenu = (menu.impl).(*macosMenu).nsMenu + //C.setApplicationMenu(m.applicationMenu) +} + +func (m *windowsApp) run() error { + // Add a hook to the ApplicationDidFinishLaunching event + //m.parent.On(events.Mac.ApplicationDidFinishLaunching, func() { + // C.setApplicationShouldTerminateAfterLastWindowClosed(C.bool(m.parent.options.Mac.ApplicationShouldTerminateAfterLastWindowClosed)) + // C.setActivationPolicy(C.int(m.parent.options.Mac.ActivationPolicy)) + // C.activateIgnoringOtherApps() + //}) + // setup event listeners + for eventID := range m.parent.applicationEventListeners { + m.on(eventID) + } + //C.run() + return nil +} + +func (m *windowsApp) destroy() { + //C.destroyApp() +} + +func newPlatformApp(app *App) *windowsApp { + //C.init() + return &windowsApp{ + parent: app, + } +} diff --git a/v3/pkg/application/clipboard.go b/v3/pkg/application/clipboard.go index e823ace9..0217057e 100644 --- a/v3/pkg/application/clipboard.go +++ b/v3/pkg/application/clipboard.go @@ -1,7 +1,5 @@ package application -import "C" - type clipboardImpl interface { setText(text string) bool text() string diff --git a/v3/pkg/application/clipboard_windows.go b/v3/pkg/application/clipboard_windows.go new file mode 100644 index 00000000..483c5156 --- /dev/null +++ b/v3/pkg/application/clipboard_windows.go @@ -0,0 +1,28 @@ +//go:build windows + +package application + +type windowsClipboard struct{} + +func (m windowsClipboard) setText(text string) bool { + //clipboardLock.Lock() + //defer clipboardLock.Unlock() + //cText := C.CString(text) + //success := C.setClipboardText(cText) + //C.free(unsafe.Pointer(cText)) + //return bool(success) + panic("implement me") +} + +func (m windowsClipboard) text() string { + //clipboardLock.RLock() + //defer clipboardLock.RUnlock() + //clipboardText := C.getClipboardText() + //result := C.GoString(clipboardText) + //return result + panic("implement me") +} + +func newClipboardImpl() *windowsClipboard { + return &windowsClipboard{} +} diff --git a/v3/pkg/application/dialogs.go b/v3/pkg/application/dialogs.go index d7e8d667..b086213e 100644 --- a/v3/pkg/application/dialogs.go +++ b/v3/pkg/application/dialogs.go @@ -1,6 +1,5 @@ package application -import "C" import ( "strings" "sync" diff --git a/v3/pkg/application/dialogs_windows.go b/v3/pkg/application/dialogs_windows.go new file mode 100644 index 00000000..b88e546a --- /dev/null +++ b/v3/pkg/application/dialogs_windows.go @@ -0,0 +1,173 @@ +//go:build windows + +package application + +func (m *windowsApp) showAboutDialog(title string, message string, icon []byte) { + panic("implement me") +} + +type windowsDialog struct { + dialog *MessageDialog + + //dialogImpl unsafe.Pointer +} + +func (m *windowsDialog) show() { + globalApplication.dispatchOnMainThread(func() { + // + //// Mac can only have 4 Buttons on a dialog + //if len(m.dialog.Buttons) > 4 { + // m.dialog.Buttons = m.dialog.Buttons[:4] + //} + // + //if m.nsDialog != nil { + // C.releaseDialog(m.nsDialog) + //} + //var title *C.char + //if m.dialog.Title != "" { + // title = C.CString(m.dialog.Title) + //} + //var message *C.char + //if m.dialog.Message != "" { + // message = C.CString(m.dialog.Message) + //} + //var iconData unsafe.Pointer + //var iconLength C.int + //if m.dialog.Icon != nil { + // iconData = unsafe.Pointer(&m.dialog.Icon[0]) + // iconLength = C.int(len(m.dialog.Icon)) + //} else { + // // if it's an error, use the application Icon + // if m.dialog.DialogType == ErrorDialog { + // iconData = unsafe.Pointer(&globalApplication.options.Icon[0]) + // iconLength = C.int(len(globalApplication.options.Icon)) + // } + //} + // + //alertType, ok := alertTypeMap[m.dialog.DialogType] + //if !ok { + // alertType = C.NSAlertStyleInformational + //} + // + //m.nsDialog = C.createAlert(alertType, title, message, iconData, iconLength) + // + //// Reverse the Buttons so that the default is on the right + //reversedButtons := make([]*Button, len(m.dialog.Buttons)) + //var count = 0 + //for i := len(m.dialog.Buttons) - 1; i >= 0; i-- { + // button := m.dialog.Buttons[i] + // C.alertAddButton(m.nsDialog, C.CString(button.Label), C.bool(button.IsDefault), C.bool(button.IsCancel)) + // reversedButtons[count] = m.dialog.Buttons[i] + // count++ + //} + // + //buttonPressed := int(C.dialogRunModal(m.nsDialog)) + //if len(m.dialog.Buttons) > buttonPressed { + // button := reversedButtons[buttonPressed] + // if button.callback != nil { + // button.callback() + // } + //} + panic("implement me") + }) + +} + +func newDialogImpl(d *MessageDialog) *windowsDialog { + return &windowsDialog{ + dialog: d, + } +} + +type windowOpenFileDialog struct { + dialog *OpenFileDialog +} + +func newOpenFileDialogImpl(d *OpenFileDialog) *windowOpenFileDialog { + return &windowOpenFileDialog{ + dialog: d, + } +} + +func (m *windowOpenFileDialog) show() ([]string, error) { + //openFileResponses[m.dialog.id] = make(chan string) + //nsWindow := unsafe.Pointer(nil) + //if m.dialog.window != nil { + // // get NSWindow from window + // nsWindow = m.dialog.window.impl.(*windowsWebviewWindow).nsWindow + //} + // + //// Massage filter patterns into macOS format + //// We iterate all filter patterns, tidy them up and then join them with a semicolon + //// This should produce a single string of extensions like "png;jpg;gif" + //var filterPatterns string + //if len(m.dialog.filters) > 0 { + // var allPatterns []string + // for _, filter := range m.dialog.filters { + // patternComponents := strings.Split(filter.Pattern, ";") + // for i, component := range patternComponents { + // filterPattern := strings.TrimSpace(component) + // filterPattern = strings.TrimPrefix(filterPattern, "*.") + // patternComponents[i] = filterPattern + // } + // allPatterns = append(allPatterns, strings.Join(patternComponents, ";")) + // } + // filterPatterns = strings.Join(allPatterns, ";") + //} + // + //C.showOpenFileDialog(C.uint(m.dialog.id), + // C.bool(m.dialog.canChooseFiles), + // C.bool(m.dialog.canChooseDirectories), + // C.bool(m.dialog.canCreateDirectories), + // C.bool(m.dialog.showHiddenFiles), + // C.bool(m.dialog.allowsMultipleSelection), + // C.bool(m.dialog.resolvesAliases), + // C.bool(m.dialog.hideExtension), + // C.bool(m.dialog.treatsFilePackagesAsDirectories), + // C.bool(m.dialog.allowsOtherFileTypes), + // toCString(filterPatterns), + // C.uint(len(filterPatterns)), + // toCString(m.dialog.message), + // toCString(m.dialog.directory), + // toCString(m.dialog.buttonText), + // nsWindow) + //var result []string + //for filename := range openFileResponses[m.dialog.id] { + // result = append(result, filename) + //} + //return result, nil + panic("implement me") +} + +type windowSaveFileDialog struct { + dialog *SaveFileDialog +} + +func newSaveFileDialogImpl(d *SaveFileDialog) *windowSaveFileDialog { + return &windowSaveFileDialog{ + dialog: d, + } +} + +func (m *windowSaveFileDialog) show() (string, error) { + //saveFileResponses[m.dialog.id] = make(chan string) + //nsWindow := unsafe.Pointer(nil) + //if m.dialog.window != nil { + // // get NSWindow from window + // nsWindow = m.dialog.window.impl.(*macosWebviewWindow).nsWindow + //} + //C.showSaveFileDialog(C.uint(m.dialog.id), + // C.bool(m.dialog.canCreateDirectories), + // C.bool(m.dialog.showHiddenFiles), + // C.bool(m.dialog.canSelectHiddenExtension), + // C.bool(m.dialog.hideExtension), + // C.bool(m.dialog.treatsFilePackagesAsDirectories), + // C.bool(m.dialog.allowOtherFileTypes), + // toCString(m.dialog.message), + // toCString(m.dialog.directory), + // toCString(m.dialog.buttonText), + // toCString(m.dialog.filename), + // nsWindow) + //return <-saveFileResponses[m.dialog.id], nil + panic("implement me") +} diff --git a/v3/pkg/application/menu.go b/v3/pkg/application/menu.go index 80cf213d..e20f0e3a 100644 --- a/v3/pkg/application/menu.go +++ b/v3/pkg/application/menu.go @@ -22,7 +22,7 @@ func (m *Menu) Add(label string) *MenuItem { } func (m *Menu) AddSeparator() { - result := newMenuItemSeperator() + result := newMenuItemSeparator() m.items = append(m.items, result) } diff --git a/v3/pkg/application/menu_windows.go b/v3/pkg/application/menu_windows.go new file mode 100644 index 00000000..b60c0b35 --- /dev/null +++ b/v3/pkg/application/menu_windows.go @@ -0,0 +1,52 @@ +//go:build windows + +package application + +import "unsafe" + +type windowsMenu struct { + menu *Menu + + menuImpl unsafe.Pointer +} + +func newMenuImpl(menu *Menu) *windowsMenu { + result := &windowsMenu{ + menu: menu, + } + return result +} + +func (m *windowsMenu) update() { + //if m.menuImpl == nil { + // m.menuImpl = C.createNSMenu(C.CString(m.menu.label)) + //} else { + // C.clearMenu(m.menuImpl) + //} + m.processMenu(m.menuImpl, m.menu) +} + +func (m *windowsMenu) processMenu(parent unsafe.Pointer, menu *Menu) { + //for _, item := range menu.items { + // switch item.itemType { + // case submenu: + // submenu := item.submenu + // nsSubmenu := C.createNSMenu(C.CString(item.label)) + // m.processMenu(nsSubmenu, submenu) + // menuItem := newMenuItemImpl(item) + // item.impl = menuItem + // C.addMenuItem(parent, menuItem.nsMenuItem) + // C.setMenuItemSubmenu(menuItem.nsMenuItem, nsSubmenu) + // if item.role == ServicesMenu { + // C.addServicesMenu(nsSubmenu) + // } + // case text, checkbox, radio: + // menuItem := newMenuItemImpl(item) + // item.impl = menuItem + // C.addMenuItem(parent, menuItem.nsMenuItem) + // case separator: + // C.addMenuSeparator(parent) + // } + // + //} +} diff --git a/v3/pkg/application/menuitem.go b/v3/pkg/application/menuitem.go index da943156..9b0ff372 100644 --- a/v3/pkg/application/menuitem.go +++ b/v3/pkg/application/menuitem.go @@ -67,7 +67,7 @@ func newMenuItem(label string) *MenuItem { return result } -func newMenuItemSeperator() *MenuItem { +func newMenuItemSeparator() *MenuItem { result := &MenuItem{ itemType: separator, } diff --git a/v3/pkg/application/menuitem_darwin.go b/v3/pkg/application/menuitem_darwin.go index daee2a52..c918c2ee 100644 --- a/v3/pkg/application/menuitem_darwin.go +++ b/v3/pkg/application/menuitem_darwin.go @@ -1,3 +1,5 @@ +//go:build darwin + package application /* @@ -329,29 +331,29 @@ import ( "unsafe" ) -type macosMenuItem struct { +type windowsMenuItem struct { menuItem *MenuItem nsMenuItem unsafe.Pointer } -func (m macosMenuItem) setTooltip(tooltip string) { +func (m windowsMenuItem) setTooltip(tooltip string) { C.setMenuItemTooltip(m.nsMenuItem, C.CString(tooltip)) } -func (m macosMenuItem) setLabel(s string) { +func (m windowsMenuItem) setLabel(s string) { C.setMenuItemLabel(m.nsMenuItem, C.CString(s)) } -func (m macosMenuItem) setDisabled(disabled bool) { +func (m windowsMenuItem) setDisabled(disabled bool) { C.setMenuItemDisabled(m.nsMenuItem, C.bool(disabled)) } -func (m macosMenuItem) setChecked(checked bool) { +func (m windowsMenuItem) setChecked(checked bool) { C.setMenuItemChecked(m.nsMenuItem, C.bool(checked)) } -func (m macosMenuItem) setAccelerator(accelerator *accelerator) { +func (m windowsMenuItem) setAccelerator(accelerator *accelerator) { // Set the keyboard shortcut of the menu item var modifier C.int var key *C.char @@ -364,8 +366,8 @@ func (m macosMenuItem) setAccelerator(accelerator *accelerator) { C.setMenuItemKeyEquivalent(m.nsMenuItem, key, modifier) } -func newMenuItemImpl(item *MenuItem) *macosMenuItem { - result := &macosMenuItem{ +func newMenuItemImpl(item *MenuItem) *windowsMenuItem { + result := &windowsMenuItem{ menuItem: item, } diff --git a/v3/pkg/application/menuitem_windows.go b/v3/pkg/application/menuitem_windows.go new file mode 100644 index 00000000..c8974c26 --- /dev/null +++ b/v3/pkg/application/menuitem_windows.go @@ -0,0 +1,179 @@ +//go:build windows + +package application + +import ( + "unsafe" +) + +type windowsMenuItem struct { + menuItem *MenuItem + + menuItemImpl unsafe.Pointer +} + +func (m windowsMenuItem) setTooltip(tooltip string) { + //C.setMenuItemTooltip(m.nsMenuItem, C.CString(tooltip)) +} + +func (m windowsMenuItem) setLabel(s string) { + //C.setMenuItemLabel(m.nsMenuItem, C.CString(s)) +} + +func (m windowsMenuItem) setDisabled(disabled bool) { + //C.setMenuItemDisabled(m.nsMenuItem, C.bool(disabled)) +} + +func (m windowsMenuItem) setChecked(checked bool) { + //C.setMenuItemChecked(m.nsMenuItem, C.bool(checked)) +} + +func (m windowsMenuItem) setAccelerator(accelerator *accelerator) { + //// Set the keyboard shortcut of the menu item + //var modifier C.int + //var key *C.char + //if accelerator != nil { + // modifier = C.int(toMacModifier(accelerator.Modifiers)) + // key = C.CString(accelerator.Key) + //} + // + //// Convert the key to a string + //C.setMenuItemKeyEquivalent(m.nsMenuItem, key, modifier) +} + +func newMenuItemImpl(item *MenuItem) *windowsMenuItem { + result := &windowsMenuItem{ + menuItem: item, + } + // + //switch item.itemType { + //case text, checkbox, submenu, radio: + // result.nsMenuItem = unsafe.Pointer(C.newMenuItem(C.uint(item.id), C.CString(item.label), C.bool(item.disabled), C.CString(item.tooltip))) + // if item.itemType == checkbox || item.itemType == radio { + // C.setMenuItemChecked(result.nsMenuItem, C.bool(item.checked)) + // } + // if item.accelerator != nil { + // result.setAccelerator(item.accelerator) + // } + //default: + // panic("WTF") + //} + return result +} + +func newSpeechMenu() *MenuItem { + panic("implement me") +} + +func newHideMenuItem() *MenuItem { + panic("implement me") + +} + +func newHideOthersMenuItem() *MenuItem { + panic("implement me") + +} + +func newUnhideMenuItem() *MenuItem { + panic("implement me") + +} + +func newUndoMenuItem() *MenuItem { + panic("implement me") + +} + +// newRedoMenuItem creates a new menu item for redoing the last action +func newRedoMenuItem() *MenuItem { + panic("implement me") + +} + +func newCutMenuItem() *MenuItem { + panic("implement me") + +} + +func newCopyMenuItem() *MenuItem { + panic("implement me") + +} + +func newPasteMenuItem() *MenuItem { + panic("implement me") + +} + +func newPasteAndMatchStyleMenuItem() *MenuItem { + panic("implement me") + +} + +func newDeleteMenuItem() *MenuItem { + panic("implement me") + +} + +func newQuitMenuItem() *MenuItem { + panic("implement me") + +} + +func newSelectAllMenuItem() *MenuItem { + panic("implement me") + +} + +func newAboutMenuItem() *MenuItem { + panic("implement me") + +} + +func newCloseMenuItem() *MenuItem { + panic("implement me") + +} + +func newReloadMenuItem() *MenuItem { + panic("implement me") + +} + +func newForceReloadMenuItem() *MenuItem { + panic("implement me") + +} + +func newToggleFullscreenMenuItem() *MenuItem { + panic("implement me") + +} + +func newToggleDevToolsMenuItem() *MenuItem { + panic("implement me") +} + +func newZoomResetMenuItem() *MenuItem { + panic("implement me") + +} + +func newZoomInMenuItem() *MenuItem { + panic("implement me") + +} + +func newZoomOutMenuItem() *MenuItem { + panic("implement me") + +} + +func newMinimizeMenuItem() *MenuItem { + panic("implement me") +} + +func newZoomMenuItem() *MenuItem { + panic("implement me") +} diff --git a/v3/pkg/application/systemtray_windows.go b/v3/pkg/application/systemtray_windows.go new file mode 100644 index 00000000..2e11586d --- /dev/null +++ b/v3/pkg/application/systemtray_windows.go @@ -0,0 +1,68 @@ +//go:build windows + +package application + +type windowsSystemTray struct { + id uint + icon []byte + menu *Menu +} + +func (s *windowsSystemTray) setIconPosition(position int) { + // Unsupported - do nothing +} + +func (s *windowsSystemTray) setMenu(menu *Menu) { + s.menu = menu +} + +func (s *windowsSystemTray) run() { + globalApplication.dispatchOnMainThread(func() { + //if s.nsStatusItem != nil { + // Fatal("System tray '%d' already running", s.id) + //} + //s.nsStatusItem = unsafe.Pointer(C.systemTrayNew()) + //if s.label != "" { + // C.systemTraySetLabel(s.nsStatusItem, C.CString(s.label)) + //} + //if s.icon != nil { + // s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&s.icon[0]), C.int(len(s.icon)))) + // C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon)) + //} + //if s.menu != nil { + // s.menu.Update() + // // Convert impl to macosMenu object + // s.nsMenu = (s.menu.impl).(*macosMenu).nsMenu + // C.systemTraySetMenu(s.nsStatusItem, s.nsMenu) + //} + panic("implement me") + }) +} + +func (s *windowsSystemTray) setIcon(icon []byte) { + s.icon = icon + globalApplication.dispatchOnMainThread(func() { + //s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon)))) + //C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon)) + }) +} + +func (s *windowsSystemTray) setTemplateIcon(icon []byte) { + // Unsupported - do nothing +} + +func newSystemTrayImpl(s *SystemTray) systemTrayImpl { + return &windowsSystemTray{ + id: s.id, + icon: s.icon, + menu: s.menu, + } +} + +func (s *windowsSystemTray) setLabel(label string) { + // Unsupported - do nothing +} + +func (s *windowsSystemTray) destroy() { + panic("implement me") +} diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go new file mode 100644 index 00000000..f651a773 --- /dev/null +++ b/v3/pkg/application/webview_window_windows.go @@ -0,0 +1,253 @@ +//go:build windows + +package application + +import ( + "unsafe" +) + +var showDevTools = func(window unsafe.Pointer) {} + +type windowsWebviewWindow struct { + windowImpl unsafe.Pointer + parent *WebviewWindow +} + +func (w *windowsWebviewWindow) setTitle(title string) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setSize(width, height int) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setURL(url string) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setResizable(resizable bool) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setMinSize(width, height int) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setMaxSize(width, height int) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) execJS(js string) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) restore() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setBackgroundColour(color *RGBA) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) run() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) center() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) size() (int, int) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) width() int { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) height() int { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) position() (int, int) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) destroy() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) reload() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) forceReload() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) toggleDevTools() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) zoomReset() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) zoomIn() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) zoomOut() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) getZoom() float64 { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setZoom(zoom float64) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) close() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) zoom() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setHTML(html string) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setPosition(x int, y int) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) on(eventID uint) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) minimise() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) unminimise() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) maximise() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) unmaximise() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) fullscreen() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) unfullscreen() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) isMinimised() bool { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) isMaximised() bool { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) isFullscreen() bool { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) disableSizeConstraints() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setFullscreenButtonEnabled(enabled bool) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) show() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) hide() { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) getScreen() (*Screen, error) { + //TODO implement me + panic("implement me") +} + +func (w *windowsWebviewWindow) setFrameless(b bool) { + //TODO implement me + panic("implement me") +} + +func newWindowImpl(parent *WebviewWindow) *windowsWebviewWindow { + result := &windowsWebviewWindow{ + parent: parent, + } + return result +} + +func (w *windowsWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) { + // Create the menu + thisMenu := newMenuImpl(menu) + thisMenu.update() + //C.windowShowMenu(w.nsWindow, thisMenu.nsMenu, C.int(data.X), C.int(data.Y)) +}