5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-04 22:53:19 +08:00

[v3 windows] Move icons to own package, systray dark mode icon, window.Focus(),

This commit is contained in:
Lea Anthony 2023-05-09 19:52:33 +10:00 committed by Misite Bao
parent 6dd092c7a9
commit 9b7626e59e
19 changed files with 138 additions and 100 deletions

View File

@ -32,6 +32,7 @@ Webview Window Interface Methods
| close() | | | Y | | | close() | | | Y | |
| destroy() | | | Y | | | destroy() | | | Y | |
| execJS(js string) | | | Y | | | execJS(js string) | | | Y | |
| focus() | Y | | | |
| forceReload() | | | Y | | | forceReload() | | | Y | |
| fullscreen() | Y | | Y | | | fullscreen() | Y | | Y | |
| getScreen() (*Screen, error) | | | Y | | | getScreen() (*Screen, error) | | | Y | |
@ -120,27 +121,28 @@ Webview Window Interface Methods
| Feature | Windows | Linux | Mac | Notes | | Feature | Windows | Linux | Mac | Notes |
|---------------------|---------|-------|-----|--------------------------------------------------------------------------------------| |---------------------|---------|-------|-----|--------------------------------------------------------------------------------------|
| SetTitle | | | Y | | | SetTitle | Y | | Y | |
| SetSize | | | Y | | | SetSize | Y | | Y | |
| Size | | | Y | | | Size | Y | | Y | |
| SetPosition | | | Y | | | SetPosition | Y | | Y | |
| Position | | | Y | | | Position | Y | | Y | |
| FullScreen | | | Y | | | Focus | Y | | | |
| UnFullscreen | | | Y | | | FullScreen | Y | | Y | |
| Minimise | | | Y | | | UnFullscreen | Y | | Y | |
| UnMinimise | | | Y | | | Minimise | Y | | Y | |
| Maximise | | | Y | | | UnMinimise | Y | | Y | |
| UnMaximise | | | Y | | | Maximise | Y | | Y | |
| Show | | | Y | | | UnMaximise | Y | | Y | |
| Hide | | | Y | | | Show | Y | | Y | |
| Center | | | Y | | | Hide | Y | | Y | |
| SetBackgroundColour | | | Y | https://github.com/MicrosoftEdge/WebView2Feedback/issues/1621#issuecomment-938234294 | | Center | Y | | Y | |
| SetAlwaysOnTop | | | Y | | | SetBackgroundColour | Y | | Y | https://github.com/MicrosoftEdge/WebView2Feedback/issues/1621#issuecomment-938234294 |
| SetResizable | | | Y | | | SetAlwaysOnTop | Y | | Y | |
| SetMinSize | | | Y | | | SetResizable | Y | | Y | |
| SetMaxSize | | | Y | | | SetMinSize | Y | | Y | |
| Width | | | Y | | | SetMaxSize | Y | | Y | |
| Height | | | Y | | | Width | Y | | Y | |
| Height | Y | | Y | |
| ZoomIn | | | Y | Increase view scale | | ZoomIn | | | Y | Increase view scale |
| ZoomOut | | | Y | Decrease view scale | | ZoomOut | | | Y | Decrease view scale |
| ZoomReset | | | Y | Reset view scale | | ZoomReset | | | Y | Reset view scale |
@ -183,6 +185,7 @@ An 'X' indicates that the option is not supported by the platform.
| Zoom | | | | | | Zoom | | | | |
| EnableDragAndDrop | | | | | | EnableDragAndDrop | | | | |
| Windows | | - | - | | | Windows | | - | - | |
| Focused | Y | | | |
### Log ### Log
@ -197,10 +200,10 @@ To log or not to log? System logger vs custom logger.
## Tray Menus ## Tray Menus
| Feature | Windows | Linux | Mac | Notes | | Feature | Windows | Linux | Mac | Notes |
|--------------------|---------|-------|-----|-------| |--------------------|---------|-------|-----|----------------------------------------------------------------------|
| Icon | | | Y | | | Icon | Y | | Y | Windows has default icons for light/dark mode & supports PNG or ICO. |
| Label | | | Y | | | Label | - | | Y | |
| Label (ANSI Codes) | | | | | | Label (ANSI Codes) | - | | | |
| Menu | | | Y | | | Menu | | | Y | |
## Cross Platform Events ## Cross Platform Events
@ -231,7 +234,7 @@ TBD
## Theme ## Theme
| Plugin | Windows | Linux | Mac | Notes | | Mode | Windows | Linux | Mac | Notes |
|--------|---------|-------|-----|-------| |--------|---------|-------|-----|-------|
| Dark | Y | | | | | Dark | Y | | | |
| Light | Y | | | | | Light | Y | | | |

View File

@ -2,6 +2,7 @@ package main
import ( import (
_ "embed" _ "embed"
"github.com/wailsapp/wails/v3/pkg/icons"
"log" "log"
"os" "os"
"runtime" "runtime"
@ -45,7 +46,7 @@ func main() {
dialog := app.InfoDialog() dialog := app.InfoDialog()
dialog.SetTitle("Custom Icon Example") dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon") dialog.SetMessage("Using a custom icon")
dialog.SetIcon(application.DefaultApplicationIcon) dialog.SetIcon(icons.ApplicationDarkMode256)
dialog.Show() dialog.Show()
}) })
@ -85,7 +86,7 @@ func main() {
dialog := app.QuestionDialog() dialog := app.QuestionDialog()
dialog.SetTitle("Custom Icon Example") dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon") dialog.SetMessage("Using a custom icon")
dialog.SetIcon(application.WailsLogoWhiteTransparent) dialog.SetIcon(icons.WailsLogoWhiteTransparent)
dialog.SetDefaultButton(dialog.AddButton("I like it!")) dialog.SetDefaultButton(dialog.AddButton("I like it!"))
dialog.AddButton("Not so keen...") dialog.AddButton("Not so keen...")
dialog.Show() dialog.Show()
@ -112,7 +113,7 @@ func main() {
dialog := app.WarningDialog() dialog := app.WarningDialog()
dialog.SetTitle("Custom Icon Example") dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon") dialog.SetMessage("Using a custom icon")
dialog.SetIcon(application.DefaultApplicationIcon) dialog.SetIcon(icons.ApplicationLightMode256)
dialog.Show() dialog.Show()
}) })
@ -137,7 +138,7 @@ func main() {
dialog := app.ErrorDialog() dialog := app.ErrorDialog()
dialog.SetTitle("Custom Icon Example") dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon") dialog.SetMessage("Using a custom icon")
dialog.SetIcon(application.WailsLogoWhite) dialog.SetIcon(icons.WailsLogoWhite)
dialog.Show() dialog.Show()
}) })

View File

@ -2,6 +2,7 @@ package main
import ( import (
_ "embed" _ "embed"
"github.com/wailsapp/wails/v3/pkg/icons"
"log" "log"
"runtime" "runtime"
"sync" "sync"
@ -62,9 +63,9 @@ func main() {
mySystray := app.NewSystemTray() mySystray := app.NewSystemTray()
mySystray.SetLabel("Wails") mySystray.SetLabel("Wails")
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
mySystray.SetTemplateIcon(application.DefaultMacTemplateIcon) mySystray.SetTemplateIcon(icons.SystrayMacTemplate)
} else { } else {
mySystray.SetIcon(application.DefaultApplicationIcon) mySystray.SetIcon(icons.ApplicationDarkMode256)
} }
myMenu := app.NewMenu() myMenu := app.NewMenu()
myMenu.Add("Item 1") myMenu.Add("Item 1")
@ -102,9 +103,9 @@ func main() {
mySystray := app.NewSystemTray() mySystray := app.NewSystemTray()
mySystray.SetLabel("Wails is awesome") mySystray.SetLabel("Wails is awesome")
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
mySystray.SetTemplateIcon(application.DefaultMacTemplateIcon) mySystray.SetTemplateIcon(icons.SystrayMacTemplate)
} else { } else {
mySystray.SetIcon(application.DefaultApplicationIcon) mySystray.SetIcon(icons.ApplicationDarkMode256)
} }
mySystray.SetMenu(myMenu) mySystray.SetMenu(myMenu)
mySystray.SetIconPosition(application.NSImageLeading) mySystray.SetIconPosition(application.NSImageLeading)

View File

@ -2,12 +2,21 @@ package main
import ( import (
_ "embed" _ "embed"
"fmt"
"github.com/wailsapp/wails/v3/pkg/icons"
"log" "log"
"runtime" "runtime"
"github.com/wailsapp/wails/v3/pkg/application" "github.com/wailsapp/wails/v3/pkg/application"
) )
var counter int
func clickCount() int {
counter++
return counter
}
func main() { func main() {
app := application.New(application.Options{ app := application.New(application.Options{
Name: "Systray Demo", Name: "Systray Demo",
@ -21,7 +30,7 @@ func main() {
systemTray := app.NewSystemTray() systemTray := app.NewSystemTray()
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
systemTray.SetIcon(application.DefaultMacTemplateIcon) systemTray.SetIcon(icons.SystrayMacTemplate)
} }
myMenu := app.NewMenu() myMenu := app.NewMenu()
@ -40,7 +49,8 @@ func main() {
systemTray.SetMenu(myMenu) systemTray.SetMenu(myMenu)
systemTray.OnClick(func() { systemTray.OnClick(func() {
window.Show() window.SetTitle(fmt.Sprintf("Clicked %d times", clickCount()))
window.Show().Focus()
}) })
err := app.Run() err := app.Run()

View File

@ -1,6 +1,7 @@
package application package application
import ( import (
"github.com/wailsapp/wails/v3/pkg/icons"
"log" "log"
"net/http" "net/http"
"os" "os"
@ -97,7 +98,7 @@ func mergeApplicationDefaults(o *Options) {
o.Description = "An application written using Wails" o.Description = "An application written using Wails"
} }
if o.Icon == nil { if o.Icon == nil {
o.Icon = DefaultApplicationIcon o.Icon = icons.ApplicationLightMode256
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -39,6 +39,7 @@ type WebviewWindowOptions struct {
EnableDragAndDrop bool EnableDragAndDrop bool
Mac MacWindow Mac MacWindow
Windows WindowsWindow Windows WindowsWindow
Focused bool
} }
var WebviewWindowDefaults = &WebviewWindowOptions{ var WebviewWindowDefaults = &WebviewWindowOptions{

View File

@ -50,7 +50,6 @@ func NewSystemTray(id uint) *SystemTray {
id: id, id: id,
label: "", label: "",
iconPosition: NSImageLeading, iconPosition: NSImageLeading,
icon: DefaultApplicationIcon,
} }
} }

View File

@ -3,6 +3,7 @@
package application package application
import ( import (
"github.com/wailsapp/wails/v3/pkg/icons"
"syscall" "syscall"
"unsafe" "unsafe"
@ -70,14 +71,14 @@ func (s *windowsSystemTray) run() {
} }
if s.parent.icon != nil { if s.parent.icon != nil {
s.lightModeIcon = lo.Must(w32.CreateHIconFromPNG(s.parent.icon)) s.lightModeIcon = lo.Must(w32.CreateHIconFromImage(s.parent.icon))
} else { } else {
s.lightModeIcon = lo.Must(w32.CreateHIconFromPNG(DefaultApplicationIcon)) s.lightModeIcon = lo.Must(w32.CreateHIconFromImage(icons.SystrayLight))
} }
if s.parent.darkModeIcon != nil { if s.parent.darkModeIcon != nil {
s.darkModeIcon = lo.Must(w32.CreateHIconFromPNG(s.parent.darkModeIcon)) s.darkModeIcon = lo.Must(w32.CreateHIconFromImage(s.parent.darkModeIcon))
} else { } else {
s.darkModeIcon = s.lightModeIcon s.darkModeIcon = lo.Must(w32.CreateHIconFromImage(icons.SystrayDark))
} }
s.uid = nid.UID s.uid = nid.UID
@ -144,7 +145,7 @@ func (s *windowsSystemTray) newNotifyIconData() w32.NOTIFYICONDATA {
func (s *windowsSystemTray) setIcon(icon []byte) { func (s *windowsSystemTray) setIcon(icon []byte) {
var err error var err error
s.lightModeIcon, err = w32.CreateHIconFromPNG(icon) s.lightModeIcon, err = w32.CreateHIconFromImage(icon)
if err != nil { if err != nil {
panic(syscall.GetLastError()) panic(syscall.GetLastError())
} }
@ -156,7 +157,7 @@ func (s *windowsSystemTray) setIcon(icon []byte) {
} }
func (s *windowsSystemTray) setDarkModeIcon(icon []byte) { func (s *windowsSystemTray) setDarkModeIcon(icon []byte) {
var err error var err error
s.darkModeIcon, err = w32.CreateHIconFromPNG(icon) s.darkModeIcon, err = w32.CreateHIconFromImage(icon)
if err != nil { if err != nil {
panic(syscall.GetLastError()) panic(syscall.GetLastError())
} }

View File

@ -55,6 +55,7 @@ type (
isNormal() bool isNormal() bool
isVisible() bool isVisible() bool
setFullscreenButtonEnabled(enabled bool) setFullscreenButtonEnabled(enabled bool)
focus()
show() show()
hide() hide()
getScreen() (*Screen, error) getScreen() (*Screen, error)
@ -807,3 +808,11 @@ func (w *WebviewWindow) NativeWindowHandle() (uintptr, error) {
} }
return w.impl.nativeWindowHandle(), nil return w.impl.nativeWindowHandle(), nil
} }
func (w *WebviewWindow) Focus() {
if w.impl == nil {
w.options.Focused = true
return
}
invokeSync(w.impl.focus)
}

View File

@ -188,7 +188,9 @@ func (w *windowsWebviewWindow) run() {
w.center() w.center()
} }
w.setForeground() if options.Focused {
w.Focus()
}
if !options.Hidden { if !options.Hidden {
w.show() w.show()
@ -223,7 +225,7 @@ func (w *windowsWebviewWindow) size() (int, int) {
return width, height return width, height
} }
func (w *windowsWebviewWindow) setForeground() { func (w *windowsWebviewWindow) Focus() {
w32.SetForegroundWindow(w.hwnd) w32.SetForegroundWindow(w.hwnd)
} }
@ -418,6 +420,10 @@ func (w *windowsWebviewWindow) setFullscreenButtonEnabled(_ bool) {
// Unused in Windows // Unused in Windows
} }
func (w *windowsWebviewWindow) focus() {
w32.SetForegroundWindow(w.hwnd)
}
func (w *windowsWebviewWindow) show() { func (w *windowsWebviewWindow) show() {
w32.ShowWindow(w.hwnd, w32.SW_SHOW) w32.ShowWindow(w.hwnd, w32.SW_SHOW)
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

30
v3/pkg/icons/icons.go Normal file
View File

@ -0,0 +1,30 @@
package icons
import _ "embed"
//go:embed DefaultMacTemplateIcon.png
var SystrayMacTemplate []byte
//go:embed systray-light.png
var SystrayLight []byte
//go:embed systray-dark.png
var SystrayDark []byte
//go:embed ApplicationDarkMode-256.png
var ApplicationDarkMode256 []byte
//go:embed ApplicationLightMode-256.png
var ApplicationLightMode256 []byte
//go:embed WailsLogoBlack.png
var WailsLogoBlack []byte
//go:embed WailsLogoBlackTransparent.png
var WailsLogoBlackTransparent []byte
//go:embed WailsLogoWhite.png
var WailsLogoWhite []byte
//go:embed WailsLogoWhiteTransparent.png
var WailsLogoWhiteTransparent []byte

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -3,6 +3,7 @@
package w32 package w32
import ( import (
"fmt"
"unsafe" "unsafe"
) )
@ -27,13 +28,34 @@ func CreateIconFromResourceEx(presbits uintptr, dwResSize uint32, isIcon bool, v
return r, nil return r, nil
} }
// CreateHIconFromPNG creates a HICON from a PNG file func isPNG(fileData []byte) bool {
func CreateHIconFromPNG(pngData []byte) (HICON, error) { if len(fileData) < 4 {
return false
}
return string(fileData[:4]) == "\x89PNG"
}
func isICO(fileData []byte) bool {
if len(fileData) < 4 {
return false
}
return string(fileData[:4]) == "\x00\x00\x01\x00"
}
// CreateHIconFromImage creates a HICON from a PNG or ICO file
func CreateHIconFromImage(fileData []byte) (HICON, error) {
if len(fileData) < 8 {
return 0, fmt.Errorf("invalid file format")
}
if !isPNG(fileData) && !isICO(fileData) {
return 0, fmt.Errorf("unsupported file format")
}
iconWidth := GetSystemMetrics(SM_CXSMICON) iconWidth := GetSystemMetrics(SM_CXSMICON)
iconHeight := GetSystemMetrics(SM_CYSMICON) iconHeight := GetSystemMetrics(SM_CYSMICON)
icon, err := CreateIconFromResourceEx( icon, err := CreateIconFromResourceEx(
uintptr(unsafe.Pointer(&pngData[0])), uintptr(unsafe.Pointer(&fileData[0])),
uint32(len(pngData)), uint32(len(fileData)),
true, true,
0x00030000, 0x00030000,
iconWidth, iconWidth,

View File

@ -1,7 +1,7 @@
version: '3' version: '3'
tasks: tasks:
generate: generate:events:
dir: ./events dir: ./events
cmds: cmds:
- go run generate.go - go run generate.go

View File

@ -1,38 +0,0 @@
package main
import (
"bytes"
"os"
"strconv"
)
func main() {
if len(os.Args) != 2 {
println("Please provide a filename")
os.Exit(1)
}
data, err := os.ReadFile(os.Args[1])
if err != nil {
println("Error reading file:", err.Error())
os.Exit(1)
}
var buffer bytes.Buffer
buffer.WriteString("var image = []byte{")
// Iterate over the bytes and print them out in decimal
for _, b := range data {
// convert byte to decimal
buffer.WriteString(strconv.Itoa(int(b)) + ", ")
}
buffer.WriteString("}\n")
// write to file
err = os.WriteFile(os.Args[1]+".go", buffer.Bytes(), 0644)
if err != nil {
println("Error writing file:", err.Error())
os.Exit(1)
}
}