aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--ui/tray.go233
1 files changed, 55 insertions, 178 deletions
diff --git a/ui/tray.go b/ui/tray.go
index f1fb727e..37c3af25 100644
--- a/ui/tray.go
+++ b/ui/tray.go
@@ -6,41 +6,26 @@
package ui
import (
- "sort"
"strings"
"time"
- "golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/l18n"
"golang.zx2c4.com/wireguard/windows/manager"
"github.com/lxn/walk"
)
-// Status + active CIDRs + separator
-const trayTunnelActionsOffset = 3
-
type Tray struct {
*walk.NotifyIcon
-
- // Current known tunnels by name
- tunnels map[string]*walk.Action
-
- mtw *ManageTunnelsWindow
-
- tunnelChangedCB *manager.TunnelChangeCallback
- tunnelsChangedCB *manager.TunnelsChangeCallback
-
- clicked func()
+ mtw *ManageTunnelsWindow
+ tunnelChangedCB *manager.TunnelChangeCallback
+ clicked func()
}
func NewTray(mtw *ManageTunnelsWindow) (*Tray, error) {
var err error
- tray := &Tray{
- mtw: mtw,
- tunnels: make(map[string]*walk.Action),
- }
+ tray := &Tray{mtw: mtw}
tray.NotifyIcon, err = walk.NewNotifyIcon(mtw)
if err != nil {
@@ -78,6 +63,7 @@ func (tray *Tray) setup() error {
}{
{label: l18n.Sprintf("Status: Unknown")},
{label: l18n.Sprintf("Addresses: None"), hidden: true},
+ {label: l18n.Sprintf("&Deactivate"), handler: tray.onDeactivateTunnel, enabled: true, hidden: true},
{separator: true},
{separator: true},
{label: l18n.Sprintf("&Manage tunnels…"), handler: tray.onManageTunnels, enabled: true, defawlt: true},
@@ -103,8 +89,6 @@ func (tray *Tray) setup() error {
tray.ContextMenu().Actions().Add(action)
}
tray.tunnelChangedCB = manager.IPCClientRegisterTunnelChange(tray.onTunnelChange)
- tray.tunnelsChangedCB = manager.IPCClientRegisterTunnelsChange(tray.onTunnelsChange)
- tray.onTunnelsChange()
globalState, _ := manager.IPCClientGlobalState()
tray.updateGlobalState(globalState)
@@ -116,103 +100,23 @@ func (tray *Tray) Dispose() error {
tray.tunnelChangedCB.Unregister()
tray.tunnelChangedCB = nil
}
- if tray.tunnelsChangedCB != nil {
- tray.tunnelsChangedCB.Unregister()
- tray.tunnelsChangedCB = nil
- }
return tray.NotifyIcon.Dispose()
}
-func (tray *Tray) onTunnelsChange() {
- tunnels, err := manager.IPCClientTunnels()
- if err != nil {
- return
- }
- tray.mtw.Synchronize(func() {
- tunnelSet := make(map[string]bool, len(tunnels))
- for _, tunnel := range tunnels {
- tunnelSet[tunnel.Name] = true
- if tray.tunnels[tunnel.Name] == nil {
- tray.addTunnelAction(&tunnel)
- }
- }
- for trayTunnel := range tray.tunnels {
- if !tunnelSet[trayTunnel] {
- tray.removeTunnelAction(trayTunnel)
- }
- }
- })
-}
-
-func (tray *Tray) addTunnelAction(tunnel *manager.Tunnel) {
- tunnelAction := walk.NewAction()
- tunnelAction.SetText(tunnel.Name)
- tunnelAction.SetEnabled(true)
- tunnelAction.SetCheckable(true)
- tclosure := *tunnel
- tunnelAction.Triggered().Attach(func() {
- tunnelAction.SetChecked(!tunnelAction.Checked())
- go func() {
- oldState, err := tclosure.Toggle()
- if err != nil {
- tray.mtw.Synchronize(func() {
- raise(tray.mtw.Handle())
- tray.mtw.tunnelsPage.listView.selectTunnel(tclosure.Name)
- tray.mtw.tabs.SetCurrentIndex(0)
- if oldState == manager.TunnelUnknown {
- showErrorCustom(tray.mtw, l18n.Sprintf("Failed to determine tunnel state"), err.Error())
- } else if oldState == manager.TunnelStopped {
- showErrorCustom(tray.mtw, l18n.Sprintf("Failed to activate tunnel"), err.Error())
- } else if oldState == manager.TunnelStarted {
- showErrorCustom(tray.mtw, l18n.Sprintf("Failed to deactivate tunnel"), err.Error())
- }
- })
- }
- }()
- })
- tray.tunnels[tunnel.Name] = tunnelAction
-
- var names []string
- for name := range tray.tunnels {
- names = append(names, name)
- }
- sort.SliceStable(names, func(i, j int) bool {
- return conf.TunnelNameIsLess(names[i], names[j])
- })
-
- var (
- idx int
- name string
- )
- for idx, name = range names {
- if name == tunnel.Name {
- break
- }
- }
-
- tray.ContextMenu().Actions().Insert(trayTunnelActionsOffset+idx, tunnelAction)
-
- go func() {
- state, err := tclosure.State()
- if err != nil {
- return
- }
- tray.mtw.Synchronize(func() {
- tray.SetTunnelState(&tclosure, state, false)
- })
- }()
-}
-
-func (tray *Tray) removeTunnelAction(tunnelName string) {
- tray.ContextMenu().Actions().Remove(tray.tunnels[tunnelName])
- delete(tray.tunnels, tunnelName)
-}
-
func (tray *Tray) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
tray.mtw.Synchronize(func() {
tray.updateGlobalState(globalState)
- tray.SetTunnelState(tunnel, state, err == nil)
- if !tray.mtw.Visible() && err != nil {
+ if err == nil {
+ switch state {
+ case manager.TunnelStarted:
+ icon, _ := iconWithOverlayForState(state, 128)
+ tray.ShowCustom(l18n.Sprintf("WireGuard Activated"), l18n.Sprintf("The %s tunnel has been activated.", tunnel.Name), icon)
+
+ case manager.TunnelStopped:
+ icon, _ := loadSystemIcon("imageres", 26, 128) // TODO: this icon isn't very good...
+ tray.ShowCustom(l18n.Sprintf("WireGuard Deactivated"), l18n.Sprintf("The %s tunnel has been deactivated.", tunnel.Name), icon)
+ }
+ } else if !tray.mtw.Visible() {
tray.ShowError(l18n.Sprintf("WireGuard Tunnel Error"), err.Error())
}
})
@@ -225,80 +129,34 @@ func (tray *Tray) updateGlobalState(globalState manager.TunnelState) {
actions := tray.ContextMenu().Actions()
statusAction := actions.At(0)
- activeCIDRsAction := actions.At(1)
-
- setTunnelActionsEnabled := func(enabled bool) {
- for i := 0; i < len(tray.tunnels); i++ {
- action := actions.At(trayTunnelActionsOffset + i)
- action.SetEnabled(enabled)
- }
- }
+ deactivateTunnelAction := actions.At(2)
tray.SetToolTip(l18n.Sprintf("WireGuard: %s", textForState(globalState, true)))
stateText := textForState(globalState, false)
statusAction.SetText(l18n.Sprintf("Status: %s", stateText))
-
- switch globalState {
- case manager.TunnelStarting:
- setTunnelActionsEnabled(false)
-
- case manager.TunnelStarted:
- activeCIDRsAction.SetVisible(true)
- setTunnelActionsEnabled(true)
-
- case manager.TunnelStopping:
- setTunnelActionsEnabled(false)
-
- case manager.TunnelStopped:
- activeCIDRsAction.SetVisible(false)
- setTunnelActionsEnabled(true)
- }
-}
-
-func (tray *Tray) SetTunnelState(tunnel *manager.Tunnel, state manager.TunnelState, showNotifications bool) {
- tunnelAction := tray.tunnels[tunnel.Name]
- if tunnelAction == nil {
- return
- }
-
- actions := tray.ContextMenu().Actions()
- activeCIDRsAction := actions.At(1)
-
- wasChecked := tunnelAction.Checked()
-
- switch state {
- case manager.TunnelStarted:
- activeCIDRsAction.SetText("")
- go func() {
- config, err := tunnel.RuntimeConfig()
- if err == nil {
- var sb strings.Builder
- for i, addr := range config.Interface.Addresses {
- if i > 0 {
- sb.WriteString(l18n.EnumerationSeparator())
+ deactivateTunnelAction.SetVisible(globalState == manager.TunnelStarted)
+ go func() {
+ var addrs []string
+ tunnels, err := manager.IPCClientTunnels()
+ if err == nil {
+ for i := range tunnels {
+ state, err := tunnels[i].State()
+ if err == nil && state == manager.TunnelStarted {
+ config, err := tunnels[i].RuntimeConfig()
+ if err == nil {
+ for _, addr := range config.Interface.Addresses {
+ addrs = append(addrs, addr.String())
+ }
}
-
- sb.WriteString(addr.String())
}
- tray.mtw.Synchronize(func() {
- activeCIDRsAction.SetText(l18n.Sprintf("Addresses: %s", sb.String()))
- })
}
- }()
- tunnelAction.SetEnabled(true)
- tunnelAction.SetChecked(true)
- if !wasChecked && showNotifications {
- icon, _ := iconWithOverlayForState(state, 128)
- tray.ShowCustom(l18n.Sprintf("WireGuard Activated"), l18n.Sprintf("The %s tunnel has been activated.", tunnel.Name), icon)
}
-
- case manager.TunnelStopped:
- tunnelAction.SetChecked(false)
- if wasChecked && showNotifications {
- icon, _ := loadSystemIcon("imageres", 26, 128) // TODO: this icon isn't very good...
- tray.ShowCustom(l18n.Sprintf("WireGuard Deactivated"), l18n.Sprintf("The %s tunnel has been deactivated.", tunnel.Name), icon)
- }
- }
+ tray.mtw.Synchronize(func() {
+ activeCIDRsAction := tray.ContextMenu().Actions().At(1)
+ activeCIDRsAction.SetText(l18n.Sprintf("Addresses: %s", strings.Join(addrs, l18n.EnumerationSeparator())))
+ activeCIDRsAction.SetVisible(len(addrs) > 0)
+ })
+ }()
}
func (tray *Tray) UpdateFound() {
@@ -333,6 +191,25 @@ func (tray *Tray) UpdateFound() {
}
}
+func (tray *Tray) onDeactivateTunnel() {
+ go func() {
+ tunnels, err := manager.IPCClientTunnels()
+ if err == nil {
+ for i := range tunnels {
+ state, err := tunnels[i].State()
+ if err == nil && state != manager.TunnelStopped {
+ err = tunnels[i].Stop()
+ }
+ }
+ }
+ if err != nil {
+ tray.mtw.Synchronize(func() {
+ showErrorCustom(tray.mtw, l18n.Sprintf("Failed to deactivate tunnel"), err.Error())
+ })
+ }
+ }()
+}
+
func (tray *Tray) onManageTunnels() {
tray.mtw.tunnelsPage.listView.SelectFirstActiveTunnel()
tray.mtw.tabs.SetCurrentIndex(0)