From 77b59845aca3b7bb773663aeda8094d39725d415 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 8 May 2019 11:52:18 +0200 Subject: ui: get correctly sized system icons --- ui/iconprovider.go | 69 ++++++++++++++++-------------------------------------- 1 file changed, 20 insertions(+), 49 deletions(-) (limited to 'ui/iconprovider.go') diff --git a/ui/iconprovider.go b/ui/iconprovider.go index ac373d90..e2647939 100644 --- a/ui/iconprovider.go +++ b/ui/iconprovider.go @@ -14,41 +14,14 @@ import ( "path" ) -type IconProvider struct { - wireguardIcon *walk.Icon - overlayIconsByState map[service.TunnelState]*walk.Icon -} - -func NewIconProvider() (*IconProvider, error) { - tsip := &IconProvider{overlayIconsByState: make(map[service.TunnelState]*walk.Icon)} - var err error - if tsip.wireguardIcon, err = walk.NewIconFromResource("$wireguard.ico"); err != nil { +func iconWithOverlayForState(state service.TunnelState, size int) (*walk.Icon, error) { + wireguardIcon, err := walk.NewIconFromResourceWithSize("$wireguard.ico", walk.Size{size, size}) + if err != nil { return nil, err } - return tsip, nil -} - -func (tsip *IconProvider) Dispose() { - if tsip.overlayIconsByState != nil { - for _, icon := range tsip.overlayIconsByState { - icon.Dispose() - } - tsip.overlayIconsByState = nil - } - if tsip.wireguardIcon != nil { - tsip.wireguardIcon.Dispose() - tsip.wireguardIcon = nil - } -} - -func (tsip *IconProvider) IconWithOverlayForState(state service.TunnelState) (*walk.Icon, error) { - if icon, ok := tsip.overlayIconsByState[state]; ok { - return icon, nil - } - - size := tsip.wireguardIcon.Size() - - bmp, err := walk.NewBitmapWithTransparentPixels(size) + defer wireguardIcon.Dispose() + iconSize := wireguardIcon.Size() + bmp, err := walk.NewBitmapWithTransparentPixels(iconSize) if err != nil { return nil, err } @@ -60,20 +33,18 @@ func (tsip *IconProvider) IconWithOverlayForState(state service.TunnelState) (*w } defer canvas.Dispose() - if err := canvas.DrawImage(tsip.wireguardIcon, walk.Point{}); err != nil { + if err := canvas.DrawImage(wireguardIcon, walk.Point{}); err != nil { return nil, err } - overlayIcon, err := tsip.IconForState(state) + w := int(float64(iconSize.Width) * 0.65) + h := int(float64(iconSize.Height) * 0.65) + bounds := walk.Rectangle{iconSize.Width - w, iconSize.Height - h, w, h} + overlayIcon, err := iconForState(state, bounds.Width) if err != nil { return nil, err } defer overlayIcon.Dispose() - - w := int(float64(size.Width) * 0.65) - h := int(float64(size.Height) * 0.65) - bounds := walk.Rectangle{size.Width - w, size.Height - h, w, h} - if err := canvas.DrawImageStretched(overlayIcon, bounds); err != nil { return nil, err } @@ -83,32 +54,32 @@ func (tsip *IconProvider) IconWithOverlayForState(state service.TunnelState) (*w if err != nil { return nil, err } - tsip.overlayIconsByState[state] = icon return icon, nil } -func (tsip *IconProvider) IconForState(state service.TunnelState) (icon *walk.Icon, err error) { +func iconForState(state service.TunnelState, size int) (icon *walk.Icon, err error) { switch state { case service.TunnelStarted: - icon, err = loadSystemIcon("imageres", 101) + icon, err = loadSystemIcon("imageres", 101, size) case service.TunnelStopped: - icon, err = walk.NewIconFromResource("dot-gray.ico") //TODO: replace with real icon + icon, err = walk.NewIconFromResourceWithSize("dot-gray.ico", walk.Size{size, size}) //TODO: replace with real icon default: - icon, err = loadSystemIcon("shell32", 238) //TODO: this doesn't look that great overlayed on the app icon + icon, err = loadSystemIcon("shell32", 238, size) //TODO: this doesn't look that great overlayed on the app icon } return } -func loadSystemIcon(dll string, index uint) (*walk.Icon, error) { +func loadSystemIcon(dll string, index int32, size int) (*walk.Icon, error) { system32, err := windows.GetSystemDirectory() if err != nil { return nil, err } - hicon := win.ExtractIcon(win.GetModuleHandle(nil), windows.StringToUTF16Ptr(path.Join(system32, dll+".dll")), int32(index)) - if hicon <= 1 { - return nil, fmt.Errorf("Unable to find icon %d of %s", index, dll) + var hicon win.HICON + ret := win.SHDefExtractIcon(windows.StringToUTF16Ptr(path.Join(system32, dll+".dll")), index, 0, &hicon, nil, uint32(size)) + if ret != 0 { + return nil, fmt.Errorf("Unable to find icon %d of %s due to error %d", index, dll, ret) } return walk.NewIconFromHICON(hicon) } -- cgit v1.2.3-59-g8ed1b