aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAlexander Neumann <an2048@gmail.com>2019-07-25 15:12:04 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-07-29 09:45:07 +0200
commit0dce279a896c604054f835ac921faa20af26b610 (patch)
treeb267dbf46cd412aa6f13b7d87ca7a586aed08d84
parentui: use now exposed ItemCountChanged event (diff)
downloadwireguard-windows-0dce279a896c604054f835ac921faa20af26b610.tar.xz
wireguard-windows-0dce279a896c604054f835ac921faa20af26b610.zip
ui: improve error handling
Signed-off-by: Alexander Neumann <an2048@gmail.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--ui/aboutdialog.go52
-rw-r--r--ui/confview.go254
-rw-r--r--ui/editdialog.go84
-rw-r--r--ui/filesave.go2
-rw-r--r--ui/logpage.go9
-rw-r--r--ui/managewindow.go12
-rw-r--r--ui/raise.go3
-rw-r--r--ui/tray.go6
-rw-r--r--ui/tunnelspage.go67
-rw-r--r--ui/ui.go22
-rw-r--r--ui/updatepage.go28
11 files changed, 401 insertions, 138 deletions
diff --git a/ui/aboutdialog.go b/ui/aboutdialog.go
index 8109b159..b56389bb 100644
--- a/ui/aboutdialog.go
+++ b/ui/aboutdialog.go
@@ -20,11 +20,22 @@ import (
var easterEggIndex = -1
func onAbout(owner walk.Form) {
+ showError(runAboutDialog(owner), owner)
+}
+
+func runAboutDialog(owner walk.Form) error {
vbl := walk.NewVBoxLayout()
vbl.SetMargins(walk.Margins{80, 20, 80, 20})
vbl.SetSpacing(10)
- dlg, _ := walk.NewDialogWithFixedSize(owner)
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
+ dlg, err := walk.NewDialogWithFixedSize(owner)
+ if err != nil {
+ return err
+ }
+ disposables.Add(dlg)
dlg.SetTitle("About WireGuard")
dlg.SetLayout(vbl)
if icon, err := loadLogoIcon(32); err == nil {
@@ -34,7 +45,10 @@ func onAbout(owner walk.Form) {
font, _ := walk.NewFont("Segoe UI", 9, 0)
dlg.SetFont(font)
- iv, _ := walk.NewImageView(dlg)
+ iv, err := walk.NewImageView(dlg)
+ if err != nil {
+ return err
+ }
iv.SetCursor(walk.CursorHand())
iv.MouseUp().Attach(func(x, y int, button walk.MouseButton) {
if button == walk.LeftButton {
@@ -55,34 +69,52 @@ func onAbout(owner walk.Form) {
iv.SetImage(logo)
}
- wgLbl, _ := walk.NewTextLabel(dlg)
+ wgLbl, err := walk.NewTextLabel(dlg)
+ if err != nil {
+ return err
+ }
wgFont, _ := walk.NewFont("Segoe UI", 16, walk.FontBold)
wgLbl.SetFont(wgFont)
wgLbl.SetTextAlignment(walk.AlignHCenterVNear)
wgLbl.SetText("WireGuard")
- detailsLbl, _ := walk.NewTextLabel(dlg)
+ detailsLbl, err := walk.NewTextLabel(dlg)
+ if err != nil {
+ return err
+ }
detailsLbl.SetTextAlignment(walk.AlignHCenterVNear)
detailsLbl.SetText(fmt.Sprintf("App version: %s\nGo backend version: %s\nGo version: %s\nOperating system: %s\nArchitecture: %s", version.RunningVersion(), device.WireGuardGoVersion, strings.TrimPrefix(runtime.Version(), "go"), version.OsName(), runtime.GOARCH))
- copyrightLbl, _ := walk.NewTextLabel(dlg)
+ copyrightLbl, err := walk.NewTextLabel(dlg)
+ if err != nil {
+ return err
+ }
copyrightFont, _ := walk.NewFont("Segoe UI", 7, 0)
copyrightLbl.SetFont(copyrightFont)
copyrightLbl.SetTextAlignment(walk.AlignHCenterVNear)
copyrightLbl.SetText("Copyright © 2015-2019 Jason A. Donenfeld. All Rights Reserved.")
- buttonCP, _ := walk.NewComposite(dlg)
+ buttonCP, err := walk.NewComposite(dlg)
+ if err != nil {
+ return err
+ }
hbl := walk.NewHBoxLayout()
hbl.SetMargins(walk.Margins{VNear: 10})
buttonCP.SetLayout(hbl)
walk.NewHSpacer(buttonCP)
- closePB, _ := walk.NewPushButton(buttonCP)
+ closePB, err := walk.NewPushButton(buttonCP)
+ if err != nil {
+ return err
+ }
closePB.SetAlignment(walk.AlignHCenterVNear)
closePB.SetText("Close")
closePB.Clicked().Attach(func() {
dlg.Accept()
})
- donatePB, _ := walk.NewPushButton(buttonCP)
+ donatePB, err := walk.NewPushButton(buttonCP)
+ if err != nil {
+ return err
+ }
donatePB.SetAlignment(walk.AlignHCenterVNear)
donatePB.SetText("♥ Donate!")
donatePB.Clicked().Attach(func() {
@@ -97,5 +129,9 @@ func onAbout(owner walk.Form) {
dlg.SetDefaultButton(donatePB)
dlg.SetCancelButton(closePB)
+ disposables.Spare()
+
dlg.Run()
+
+ return nil
}
diff --git a/ui/confview.go b/ui/confview.go
index 5a2e5dab..6d088fdc 100644
--- a/ui/confview.go
+++ b/ui/confview.go
@@ -98,25 +98,46 @@ func (lsl *labelStatusLine) update(state manager.TunnelState) {
lsl.statusLabel.SetTextSelection(s, e)
}
-func newLabelStatusLine(parent walk.Container) *labelStatusLine {
+func (lsl *labelStatusLine) Dispose() {
+ lsl.label.Dispose()
+ lsl.statusComposite.Dispose()
+}
+
+func newLabelStatusLine(parent walk.Container) (*labelStatusLine, error) {
+ var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
lsl := new(labelStatusLine)
- lsl.label, _ = walk.NewTextLabel(parent)
+ if lsl.label, err = walk.NewTextLabel(parent); err != nil {
+ return nil, err
+ }
+ disposables.Add(lsl.label)
lsl.label.SetText("Status:")
lsl.label.SetTextAlignment(walk.AlignHFarVNear)
- lsl.statusComposite, _ = walk.NewComposite(parent)
+ if lsl.statusComposite, err = walk.NewComposite(parent); err != nil {
+ return nil, err
+ }
+ disposables.Add(lsl.statusComposite)
layout := walk.NewHBoxLayout()
layout.SetMargins(walk.Margins{})
layout.SetAlignment(walk.AlignHNearVNear)
layout.SetSpacing(0)
lsl.statusComposite.SetLayout(layout)
- lsl.statusImage, _ = walk.NewImageView(lsl.statusComposite)
+ if lsl.statusImage, err = walk.NewImageView(lsl.statusComposite); err != nil {
+ return nil, err
+ }
+ disposables.Add(lsl.statusImage)
lsl.statusImage.SetMargin(2)
lsl.statusImage.SetMode(walk.ImageViewModeIdeal)
- lsl.statusLabel, _ = walk.NewLineEdit(lsl.statusComposite)
+ if lsl.statusLabel, err = walk.NewLineEdit(lsl.statusComposite); err != nil {
+ return nil, err
+ }
+ disposables.Add(lsl.statusLabel)
win.SetWindowLong(lsl.statusLabel.Handle(), win.GWL_EXSTYLE, win.GetWindowLong(lsl.statusLabel.Handle(), win.GWL_EXSTYLE)&^win.WS_EX_CLIENTEDGE)
lsl.statusLabel.SetReadOnly(true)
lsl.statusLabel.SetBackground(walk.NullBrush())
@@ -125,7 +146,9 @@ func newLabelStatusLine(parent walk.Container) *labelStatusLine {
})
lsl.update(manager.TunnelUnknown)
- return lsl
+ disposables.Spare()
+
+ return lsl, nil
}
func (lt *labelTextLine) widgets() (walk.Widget, walk.Widget) {
@@ -146,14 +169,30 @@ func (lt *labelTextLine) hide() {
lt.text.SetVisible(false)
}
-func newLabelTextLine(fieldName string, parent walk.Container) *labelTextLine {
+func (lt *labelTextLine) Dispose() {
+ lt.label.Dispose()
+ lt.text.Dispose()
+}
+
+func newLabelTextLine(fieldName string, parent walk.Container) (*labelTextLine, error) {
+ var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
lt := new(labelTextLine)
- lt.label, _ = walk.NewTextLabel(parent)
+
+ if lt.label, err = walk.NewTextLabel(parent); err != nil {
+ return nil, err
+ }
+ disposables.Add(lt.label)
lt.label.SetText(fieldName + ":")
lt.label.SetTextAlignment(walk.AlignHFarVNear)
lt.label.SetVisible(false)
- lt.text, _ = walk.NewTextEdit(parent)
+ if lt.text, err = walk.NewTextEdit(parent); err != nil {
+ return nil, err
+ }
+ disposables.Add(lt.text)
win.SetWindowLong(lt.text.Handle(), win.GWL_EXSTYLE, win.GetWindowLong(lt.text.Handle(), win.GWL_EXSTYLE)&^win.WS_EX_CLIENTEDGE)
lt.text.SetCompactHeight(true)
lt.text.SetReadOnly(true)
@@ -162,7 +201,10 @@ func newLabelTextLine(fieldName string, parent walk.Container) *labelTextLine {
lt.text.FocusedChanged().Attach(func() {
lt.text.SetTextSelection(0, 0)
})
- return lt
+
+ disposables.Spare()
+
+ return lt, nil
}
func (tal *toggleActiveLine) widgets() (walk.Widget, walk.Widget) {
@@ -191,67 +233,121 @@ func (tal *toggleActiveLine) update(state manager.TunnelState) {
tal.button.SetVisible(state != manager.TunnelUnknown)
}
-func newToggleActiveLine(parent walk.Container) *toggleActiveLine {
+func (tal *toggleActiveLine) Dispose() {
+ tal.composite.Dispose()
+}
+
+func newToggleActiveLine(parent walk.Container) (*toggleActiveLine, error) {
+ var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
tal := new(toggleActiveLine)
- tal.composite, _ = walk.NewComposite(parent)
+ if tal.composite, err = walk.NewComposite(parent); err != nil {
+ return nil, err
+ }
+ disposables.Add(tal.composite)
layout := walk.NewHBoxLayout()
layout.SetMargins(walk.Margins{0, 0, 0, 6})
tal.composite.SetLayout(layout)
- tal.button, _ = walk.NewPushButton(tal.composite)
+ if tal.button, err = walk.NewPushButton(tal.composite); err != nil {
+ return nil, err
+ }
+ disposables.Add(tal.button)
walk.NewHSpacer(tal.composite)
tal.update(manager.TunnelStopped)
- return tal
-}
-
-func newInterfaceView(parent walk.Container) *interfaceView {
- iv := &interfaceView{
- newLabelStatusLine(parent),
- newLabelTextLine("Public key", parent),
- newLabelTextLine("Listen port", parent),
- newLabelTextLine("MTU", parent),
- newLabelTextLine("Addresses", parent),
- newLabelTextLine("DNS servers", parent),
- newToggleActiveLine(parent),
- nil,
- }
- iv.lines = []widgetsLine{
- iv.status,
- iv.publicKey,
- iv.listenPort,
- iv.mtu,
- iv.addresses,
- iv.dns,
- iv.toggleActive,
+ disposables.Spare()
+
+ return tal, nil
+}
+
+type labelTextLineItem struct {
+ label string
+ ptr **labelTextLine
+}
+
+func createLabelTextLines(items []labelTextLineItem, parent walk.Container, disposables *walk.Disposables) ([]widgetsLine, error) {
+ var err error
+ var disps walk.Disposables
+ defer disps.Treat()
+
+ wls := make([]widgetsLine, len(items))
+ for i, item := range items {
+ if *item.ptr, err = newLabelTextLine(item.label, parent); err != nil {
+ return nil, err
+ }
+ disps.Add(*item.ptr)
+ if disposables != nil {
+ disposables.Add(*item.ptr)
+ }
+ wls[i] = *item.ptr
+ }
+
+ disps.Spare()
+
+ return wls, nil
+}
+
+func newInterfaceView(parent walk.Container) (*interfaceView, error) {
+ var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
+ iv := new(interfaceView)
+
+ if iv.status, err = newLabelStatusLine(parent); err != nil {
+ return nil, err
+ }
+ disposables.Add(iv.status)
+
+ items := []labelTextLineItem{
+ {"Public key", &iv.publicKey},
+ {"Listen port", &iv.listenPort},
+ {"MTU", &iv.mtu},
+ {"Addresses", &iv.addresses},
+ {"DNS servers", &iv.dns},
+ }
+ if iv.lines, err = createLabelTextLines(items, parent, &disposables); err != nil {
+ return nil, err
+ }
+
+ if iv.toggleActive, err = newToggleActiveLine(parent); err != nil {
+ return nil, err
}
+ disposables.Add(iv.toggleActive)
+
+ iv.lines = append([]widgetsLine{iv.status}, append(iv.lines, iv.toggleActive)...)
+
layoutInGrid(iv, parent.Layout().(*walk.GridLayout))
- return iv
-}
-
-func newPeerView(parent walk.Container) *peerView {
- pv := &peerView{
- newLabelTextLine("Public key", parent),
- newLabelTextLine("Preshared key", parent),
- newLabelTextLine("Allowed IPs", parent),
- newLabelTextLine("Endpoint", parent),
- newLabelTextLine("Persistent keepalive", parent),
- newLabelTextLine("Latest handshake", parent),
- newLabelTextLine("Transfer", parent),
- nil,
- }
- pv.lines = []widgetsLine{
- pv.publicKey,
- pv.presharedKey,
- pv.allowedIPs,
- pv.endpoint,
- pv.persistentKeepalive,
- pv.latestHandshake,
- pv.transfer,
+
+ disposables.Spare()
+
+ return iv, nil
+}
+
+func newPeerView(parent walk.Container) (*peerView, error) {
+ pv := new(peerView)
+
+ items := []labelTextLineItem{
+ {"Public key", &pv.publicKey},
+ {"Preshared key", &pv.presharedKey},
+ {"Allowed IPs", &pv.allowedIPs},
+ {"Endpoint", &pv.endpoint},
+ {"Persistent keepalive", &pv.persistentKeepalive},
+ {"Latest handshake", &pv.latestHandshake},
+ {"Transfer", &pv.transfer},
}
+ var err error
+ if pv.lines, err = createLabelTextLines(items, parent, nil); err != nil {
+ return nil, err
+ }
+
layoutInGrid(pv, parent.Layout().(*walk.GridLayout))
- return pv
+
+ return pv, nil
}
func layoutInGrid(view widgetsLinesView, layout *walk.GridLayout) {
@@ -381,18 +477,32 @@ func newPaddedGroupGrid(parent walk.Container) (group *walk.GroupBox, err error)
}
func NewConfView(parent walk.Container) (*ConfView, error) {
+ var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
cv := new(ConfView)
- cv.ScrollView, _ = walk.NewScrollView(parent)
+ if cv.ScrollView, err = walk.NewScrollView(parent); err != nil {
+ return nil, err
+ }
+ disposables.Add(cv)
vlayout := walk.NewVBoxLayout()
vlayout.SetMargins(walk.Margins{5, 0, 5, 0})
cv.SetLayout(vlayout)
- cv.name, _ = newPaddedGroupGrid(cv)
- cv.interfaze = newInterfaceView(cv.name)
+ if cv.name, err = newPaddedGroupGrid(cv); err != nil {
+ return nil, err
+ }
+ if cv.interfaze, err = newInterfaceView(cv.name); err != nil {
+ return nil, err
+ }
cv.interfaze.toggleActive.button.Clicked().Attach(cv.onToggleActiveClicked)
cv.peers = make(map[conf.Key]*peerView)
cv.tunnelChangedCB = manager.IPCClientRegisterTunnelChange(cv.onTunnelChanged)
cv.SetTunnel(nil)
- globalState, _ := manager.IPCClientGlobalState()
+ globalState, err := manager.IPCClientGlobalState()
+ if err != nil {
+ return nil, err
+ }
cv.interfaze.toggleActive.updateGlobal(globalState)
if err := walk.InitWrapperWindow(cv); err != nil {
@@ -421,6 +531,9 @@ func NewConfView(parent walk.Container) (*ConfView, error) {
}
}
}()
+
+ disposables.Spare()
+
return cv, nil
}
@@ -443,11 +556,11 @@ func (cv *ConfView) onToggleActiveClicked() {
if err != nil {
cv.Synchronize(func() {
if oldState == manager.TunnelUnknown {
- walk.MsgBox(cv.Form(), "Failed to determine tunnel state", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(cv.Form(), "Failed to determine tunnel state", err.Error())
} else if oldState == manager.TunnelStopped {
- walk.MsgBox(cv.Form(), "Failed to activate tunnel", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(cv.Form(), "Failed to activate tunnel", err.Error())
} else if oldState == manager.TunnelStarted {
- walk.MsgBox(cv.Form(), "Failed to deactivate tunnel", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(cv.Form(), "Failed to deactivate tunnel", err.Error())
}
})
}
@@ -543,9 +656,16 @@ func (cv *ConfView) setTunnel(tunnel *manager.Tunnel, config *conf.Config, state
pv.apply(&peer)
inverse[pv] = false
} else {
- group, _ := newPaddedGroupGrid(cv)
+ group, err := newPaddedGroupGrid(cv)
+ if err != nil {
+ continue
+ }
group.SetTitle("Peer")
- pv := newPeerView(group)
+ pv, err := newPeerView(group)
+ if err != nil {
+ group.Dispose()
+ continue
+ }
pv.apply(&peer)
cv.peers[peer.PublicKey] = pv
}
diff --git a/ui/editdialog.go b/ui/editdialog.go
index f27ab60f..8bcbbfeb 100644
--- a/ui/editdialog.go
+++ b/ui/editdialog.go
@@ -28,8 +28,25 @@ type EditDialog struct {
blockUntunneledTraficCheckGuard bool
}
-func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
- dlg := &EditDialog{}
+func runEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
+ dlg, err := newEditDialog(owner, tunnel)
+ if showError(err, owner) {
+ return nil
+ }
+
+ if dlg.Run() == walk.DlgCmdOK {
+ return &dlg.config
+ }
+
+ return nil
+}
+
+func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) {
+ var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
+ dlg := new(EditDialog)
var title string
if tunnel == nil {
@@ -51,7 +68,10 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
layout.SetMargins(walk.Margins{10, 10, 10, 10})
layout.SetColumnStretchFactor(1, 3)
- dlg.Dialog, _ = walk.NewDialog(owner)
+ if dlg.Dialog, err = walk.NewDialog(owner); err != nil {
+ return nil, err
+ }
+ disposables.Add(dlg)
dlg.SetIcon(owner.Icon())
dlg.SetTitle(title)
dlg.SetLayout(layout)
@@ -60,34 +80,51 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
dlg.SetIcon(icon)
}
- nameLabel, _ := walk.NewTextLabel(dlg)
+ nameLabel, err := walk.NewTextLabel(dlg)
+ if err != nil {
+ return nil, err
+ }
layout.SetRange(nameLabel, walk.Rectangle{0, 0, 1, 1})
nameLabel.SetTextAlignment(walk.AlignHFarVCenter)
nameLabel.SetText("Name:")
- dlg.nameEdit, _ = walk.NewLineEdit(dlg)
+ if dlg.nameEdit, err = walk.NewLineEdit(dlg); err != nil {
+ return nil, err
+ }
layout.SetRange(dlg.nameEdit, walk.Rectangle{1, 0, 1, 1})
dlg.nameEdit.SetText(dlg.config.Name)
- pubkeyLabel, _ := walk.NewTextLabel(dlg)
+ pubkeyLabel, err := walk.NewTextLabel(dlg)
+ if err != nil {
+ return nil, err
+ }
layout.SetRange(pubkeyLabel, walk.Rectangle{0, 1, 1, 1})
pubkeyLabel.SetTextAlignment(walk.AlignHFarVCenter)
pubkeyLabel.SetText("Public key:")
- dlg.pubkeyEdit, _ = walk.NewLineEdit(dlg)
+ if dlg.pubkeyEdit, err = walk.NewLineEdit(dlg); err != nil {
+ return nil, err
+ }
layout.SetRange(dlg.pubkeyEdit, walk.Rectangle{1, 1, 1, 1})
dlg.pubkeyEdit.SetReadOnly(true)
dlg.pubkeyEdit.SetText("(unknown)")
- dlg.syntaxEdit, _ = syntax.NewSyntaxEdit(dlg)
+ if dlg.syntaxEdit, err = syntax.NewSyntaxEdit(dlg); err != nil {
+ return nil, err
+ }
layout.SetRange(dlg.syntaxEdit, walk.Rectangle{0, 2, 2, 1})
- buttonsContainer, _ := walk.NewComposite(dlg)
+ buttonsContainer, err := walk.NewComposite(dlg)
+ if err != nil {
+ return nil, err
+ }
layout.SetRange(buttonsContainer, walk.Rectangle{0, 3, 2, 1})
buttonsContainer.SetLayout(walk.NewHBoxLayout())
buttonsContainer.Layout().SetMargins(walk.Margins{})
- dlg.blockUntunneledTrafficCB, _ = walk.NewCheckBox(buttonsContainer)
+ if dlg.blockUntunneledTrafficCB, err = walk.NewCheckBox(buttonsContainer); err != nil {
+ return nil, err
+ }
dlg.blockUntunneledTrafficCB.SetText("Block untunneled traffic (kill-switch)")
dlg.blockUntunneledTrafficCB.SetToolTipText("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface, with special exceptions for DHCP and NDP.")
dlg.blockUntunneledTrafficCB.SetVisible(false)
@@ -95,11 +132,16 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
walk.NewHSpacer(buttonsContainer)
- dlg.saveButton, _ = walk.NewPushButton(buttonsContainer)
+ if dlg.saveButton, err = walk.NewPushButton(buttonsContainer); err != nil {
+ return nil, err
+ }
dlg.saveButton.SetText("Save")
dlg.saveButton.Clicked().Attach(dlg.onSaveButtonClicked)
- cancelButton, _ := walk.NewPushButton(buttonsContainer)
+ cancelButton, err := walk.NewPushButton(buttonsContainer)
+ if err != nil {
+ return nil, err
+ }
cancelButton.SetText("Cancel")
cancelButton.Clicked().Attach(dlg.Cancel)
@@ -118,11 +160,9 @@ func runTunnelEditDialog(owner walk.Form, tunnel *manager.Tunnel) *conf.Config {
})
}
- if dlg.Run() == walk.DlgCmdOK {
- return &dlg.config
- }
+ disposables.Spare()
- return nil
+ return dlg, nil
}
func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
@@ -217,7 +257,7 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
return
err:
- walk.MsgBox(dlg, "Invalid configuration", "Unable to toggle untunneled traffic blocking state.", walk.MsgBoxIconWarning)
+ showErrorCustom(dlg, "Invalid configuration", "Unable to toggle untunneled traffic blocking state.")
dlg.blockUntunneledTrafficCB.SetVisible(false)
}
@@ -252,11 +292,11 @@ func (dlg *EditDialog) onSyntaxEditPrivateKeyChanged(privateKey string) {
func (dlg *EditDialog) onSaveButtonClicked() {
newName := dlg.nameEdit.Text()
if newName == "" {
- walk.MsgBox(dlg, "Invalid name", "A name is required.", walk.MsgBoxIconWarning)
+ showWarningCustom(dlg, "Invalid name", "A name is required.")
return
}
if !conf.TunnelNameIsValid(newName) {
- walk.MsgBox(dlg, "Invalid name", fmt.Sprintf("Tunnel name ‘%s’ is invalid.", newName), walk.MsgBoxIconWarning)
+ showWarningCustom(dlg, "Invalid name", fmt.Sprintf("Tunnel name ‘%s’ is invalid.", newName))
return
}
newNameLower := strings.ToLower(newName)
@@ -264,12 +304,12 @@ func (dlg *EditDialog) onSaveButtonClicked() {
if newNameLower != strings.ToLower(dlg.config.Name) {
existingTunnelList, err := manager.IPCClientTunnels()
if err != nil {
- walk.MsgBox(dlg, "Unable to list existing tunnels", err.Error(), walk.MsgBoxIconError)
+ showWarningCustom(dlg, "Unable to list existing tunnels", err.Error())
return
}
for _, tunnel := range existingTunnelList {
if strings.ToLower(tunnel.Name) == newNameLower {
- walk.MsgBox(dlg, "Tunnel already exists", fmt.Sprintf("Another tunnel already exists with the name ‘%s’.", newName), walk.MsgBoxIconWarning)
+ showWarningCustom(dlg, "Tunnel already exists", fmt.Sprintf("Another tunnel already exists with the name ‘%s’.", newName))
return
}
}
@@ -277,7 +317,7 @@ func (dlg *EditDialog) onSaveButtonClicked() {
cfg, err := conf.FromWgQuick(dlg.syntaxEdit.Text(), newName)
if err != nil {
- walk.MsgBox(dlg, "Unable to create new configuration", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(dlg, "Unable to create new configuration", err.Error())
return
}
diff --git a/ui/filesave.go b/ui/filesave.go
index b17f106c..5f78cfee 100644
--- a/ui/filesave.go
+++ b/ui/filesave.go
@@ -18,7 +18,7 @@ func writeFileWithOverwriteHandling(owner walk.Form, filePath string, write func
return false
}
- walk.MsgBox(owner, "Writing file failed", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(owner, "Writing file failed", err.Error())
return true
}
diff --git a/ui/logpage.go b/ui/logpage.go
index 2eb27fa8..e4cfe603 100644
--- a/ui/logpage.go
+++ b/ui/logpage.go
@@ -24,11 +24,10 @@ const (
func NewLogPage() (*LogPage, error) {
lp := &LogPage{}
+ var err error
var disposables walk.Disposables
defer disposables.Treat()
- var err error
-
if lp.TabPage, err = walk.NewTabPage(); err != nil {
return nil, err
}
@@ -47,7 +46,11 @@ func NewLogPage() (*LogPage, error) {
lp.logView.SetAlternatingRowBGColor(walk.Color(win.GetSysColor(win.COLOR_BTNFACE)))
lp.logView.SetLastColumnStretched(true)
- contextMenu, _ := walk.NewMenu()
+ contextMenu, err := walk.NewMenu()
+ if err != nil {
+ return nil, err
+ }
+ lp.logView.AddDisposable(contextMenu)
copyAction := walk.NewAction()
copyAction.SetText("&Copy")
copyAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyC})
diff --git a/ui/managewindow.go b/ui/managewindow.go
index 7c643aba..60664abb 100644
--- a/ui/managewindow.go
+++ b/ui/managewindow.go
@@ -40,6 +40,8 @@ func init() {
func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
font, err := walk.NewFont("Segoe UI", 9, 0)
if err != nil {
@@ -53,6 +55,7 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
if err != nil {
return nil, err
}
+ disposables.Add(mtw)
win.ChangeWindowMessageFilterEx(mtw.Handle(), raiseMsg, win.MSGFLT_ALLOW, nil)
mtw.SetPersistent(true)
@@ -60,7 +63,6 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
mtw.SetIcon(icon)
}
mtw.SetTitle("WireGuard")
- mtw.AddDisposable(font)
mtw.SetFont(font)
mtw.SetSize(walk.Size{670, 525})
mtw.SetMinMaxSize(walk.Size{500, 400}, walk.Size{0, 0})
@@ -85,7 +87,9 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
}
})
- mtw.tabs, _ = walk.NewTabWidget(mtw)
+ if mtw.tabs, err = walk.NewTabWidget(mtw); err != nil {
+ return nil, err
+ }
if mtw.tunnelsPage, err = NewTunnelsPage(); err != nil {
return nil, err
@@ -118,6 +122,8 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) {
})
}
+ disposables.Spare()
+
return mtw, nil
}
@@ -157,7 +163,7 @@ func (mtw *ManageTunnelsWindow) onTunnelChange(tunnel *manager.Tunnel, state man
if len(errMsg) > 0 && errMsg[len(errMsg)-1] != '.' {
errMsg += "."
}
- walk.MsgBox(mtw, "Tunnel Error", errMsg+"\n\nPlease consult the log for more information.", walk.MsgBoxIconWarning)
+ showWarningCustom(mtw, "Tunnel Error", errMsg+"\n\nPlease consult the log for more information.")
}
})
}
diff --git a/ui/raise.go b/ui/raise.go
index 6d08c6bb..b74b5ed6 100644
--- a/ui/raise.go
+++ b/ui/raise.go
@@ -10,7 +10,6 @@ import (
"os"
"runtime"
- "github.com/lxn/walk"
"github.com/lxn/win"
"golang.org/x/sys/windows"
)
@@ -54,7 +53,7 @@ func WaitForRaiseUIThenQuit() {
return 0
}, 0, 0, win.WINEVENT_SKIPOWNPROCESS|win.WINEVENT_OUTOFCONTEXT)
if err != nil {
- walk.MsgBox(nil, "WireGuard Detection Error", fmt.Sprintf("Unable to wait for WireGuard window to appear: %v", err), walk.MsgBoxIconError)
+ showErrorCustom(nil, "WireGuard Detection Error", fmt.Sprintf("Unable to wait for WireGuard window to appear: %v", err))
}
for {
var msg win.MSG
diff --git a/ui/tray.go b/ui/tray.go
index 26e06c4d..93b12c4c 100644
--- a/ui/tray.go
+++ b/ui/tray.go
@@ -160,11 +160,11 @@ func (tray *Tray) addTunnelAction(tunnel *manager.Tunnel) {
tray.mtw.tunnelsPage.listView.selectTunnel(tclosure.Name)
tray.mtw.tabs.SetCurrentIndex(0)
if oldState == manager.TunnelUnknown {
- walk.MsgBox(tray.mtw, "Failed to determine tunnel state", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(tray.mtw, "Failed to determine tunnel state", err.Error())
} else if oldState == manager.TunnelStopped {
- walk.MsgBox(tray.mtw, "Failed to activate tunnel", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(tray.mtw, "Failed to activate tunnel", err.Error())
} else if oldState == manager.TunnelStarted {
- walk.MsgBox(tray.mtw, "Failed to deactivate tunnel", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(tray.mtw, "Failed to deactivate tunnel", err.Error())
}
})
}
diff --git a/ui/tunnelspage.go b/ui/tunnelspage.go
index 2eaad53d..09acec3d 100644
--- a/ui/tunnelspage.go
+++ b/ui/tunnelspage.go
@@ -36,7 +36,6 @@ type TunnelsPage struct {
func NewTunnelsPage() (*TunnelsPage, error) {
var err error
-
var disposables walk.Disposables
defer disposables.Treat()
@@ -55,18 +54,20 @@ func NewTunnelsPage() (*TunnelsPage, error) {
vlayout.SetSpacing(0)
tp.listContainer.SetLayout(vlayout)
- // TODO: deal with remaining disposables in case the next line fails
-
if tp.listView, err = NewListView(tp.listContainer); err != nil {
return nil, err
}
- tp.currentTunnelContainer, _ = walk.NewComposite(tp)
+ if tp.currentTunnelContainer, err = walk.NewComposite(tp); err != nil {
+ return nil, err
+ }
vlayout = walk.NewVBoxLayout()
vlayout.SetMargins(walk.Margins{})
tp.currentTunnelContainer.SetLayout(vlayout)
- tp.fillerContainer, _ = walk.NewComposite(tp)
+ if tp.fillerContainer, err = walk.NewComposite(tp); err != nil {
+ return nil, err
+ }
tp.fillerContainer.SetVisible(false)
hlayout := walk.NewHBoxLayout()
hlayout.SetMargins(walk.Margins{})
@@ -79,15 +80,23 @@ func NewTunnelsPage() (*TunnelsPage, error) {
}
})
- tp.confView, _ = NewConfView(tp.currentTunnelContainer)
+ if tp.confView, err = NewConfView(tp.currentTunnelContainer); err != nil {
+ return nil, err
+ }
- controlsContainer, _ := walk.NewComposite(tp.currentTunnelContainer)
+ controlsContainer, err := walk.NewComposite(tp.currentTunnelContainer)
+ if err != nil {
+ return nil, err
+ }
controlsContainer.SetLayout(walk.NewHBoxLayout())
controlsContainer.Layout().SetMargins(walk.Margins{})
walk.NewHSpacer(controlsContainer)
- editTunnel, _ := walk.NewPushButton(controlsContainer)
+ editTunnel, err := walk.NewPushButton(controlsContainer)
+ if err != nil {
+ return nil, err
+ }
editTunnel.SetEnabled(false)
tp.listView.CurrentIndexChanged().Attach(func() {
editTunnel.SetEnabled(tp.listView.CurrentIndex() > -1)
@@ -107,22 +116,30 @@ func NewTunnelsPage() (*TunnelsPage, error) {
return tp, nil
}
-func (tp *TunnelsPage) CreateToolbar() {
+func (tp *TunnelsPage) CreateToolbar() error {
if tp.listToolbar != nil {
- return
+ return nil
}
// HACK: Because of https://github.com/lxn/walk/issues/481
// we need to put the ToolBar into its own Composite.
- toolBarContainer, _ := walk.NewComposite(tp.listContainer)
+ toolBarContainer, err := walk.NewComposite(tp.listContainer)
+ if err != nil {
+ return err
+ }
toolBarContainer.SetDoubleBuffering(true)
hlayout := walk.NewHBoxLayout()
hlayout.SetMargins(walk.Margins{})
toolBarContainer.SetLayout(hlayout)
- tp.listToolbar, _ = walk.NewToolBarWithOrientationAndButtonStyle(toolBarContainer, walk.Horizontal, walk.ToolBarButtonImageBeforeText)
+ if tp.listToolbar, err = walk.NewToolBarWithOrientationAndButtonStyle(toolBarContainer, walk.Horizontal, walk.ToolBarButtonImageBeforeText); err != nil {
+ return err
+ }
- addMenu, _ := walk.NewMenu()
+ addMenu, err := walk.NewMenu()
+ if err != nil {
+ return err
+ }
tp.AddDisposable(addMenu)
importAction := walk.NewAction()
importAction.SetText("Import tunnel(s) from file...")
@@ -172,7 +189,11 @@ func (tp *TunnelsPage) CreateToolbar() {
fixContainerWidthToToolbarWidth()
tp.listToolbar.SizeChanged().Attach(fixContainerWidthToToolbarWidth)
- contextMenu, _ := walk.NewMenu()
+ contextMenu, err := walk.NewMenu()
+ if err != nil {
+ return err
+ }
+ tp.listView.AddDisposable(contextMenu)
toggleAction := walk.NewAction()
toggleAction.SetText("&Toggle")
toggleAction.SetDefault(true)
@@ -238,6 +259,8 @@ func (tp *TunnelsPage) CreateToolbar() {
tp.listView.model.RowsRemoved().Attach(setExportRange)
tp.listView.model.RowsReset().Attach(setExport)
setExport()
+
+ return nil
}
func (tp *TunnelsPage) updateConfView() {
@@ -383,7 +406,7 @@ func (tp *TunnelsPage) exportTunnels(filePath string) {
func (tp *TunnelsPage) addTunnel(config *conf.Config) {
_, err := manager.IPCClientNewTunnel(config)
if err != nil {
- walk.MsgBox(tp.Form(), "Unable to create tunnel", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(tp.Form(), "Unable to create tunnel", err.Error())
}
}
@@ -400,11 +423,11 @@ func (tp *TunnelsPage) onTunnelsViewItemActivated() {
if err != nil {
tp.Synchronize(func() {
if oldState == manager.TunnelUnknown {
- walk.MsgBox(tp.Form(), "Failed to determine tunnel state", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(tp.Form(), "Failed to determine tunnel state", err.Error())
} else if oldState == manager.TunnelStopped {
- walk.MsgBox(tp.Form(), "Failed to activate tunnel", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(tp.Form(), "Failed to activate tunnel", err.Error())
} else if oldState == manager.TunnelStarted {
- walk.MsgBox(tp.Form(), "Failed to deactivate tunnel", err.Error(), walk.MsgBoxIconError)
+ showErrorCustom(tp.Form(), "Failed to deactivate tunnel", err.Error())
}
})
return
@@ -418,7 +441,7 @@ func (tp *TunnelsPage) onEditTunnel() {
return
}
- if config := runTunnelEditDialog(tp.Form(), tunnel); config != nil {
+ if config := runEditDialog(tp.Form(), tunnel); config != nil {
go func() {
priorState, err := tunnel.State()
tunnel.Delete()
@@ -432,7 +455,7 @@ func (tp *TunnelsPage) onEditTunnel() {
}
func (tp *TunnelsPage) onAddTunnel() {
- if config := runTunnelEditDialog(tp.Form(), nil); config != nil {
+ if config := runEditDialog(tp.Form(), nil); config != nil {
// Save new
tp.addTunnel(config)
}
@@ -493,9 +516,9 @@ func (tp *TunnelsPage) onDelete() {
if len(errors) > 0 {
tp.listView.Synchronize(func() {
if len(errors) == 1 {
- walk.MsgBox(tp.Form(), "Unable to delete tunnel", fmt.Sprintf("A tunnel was unable to be removed: %s", errors[0].Error()), walk.MsgBoxIconError)
+ showErrorCustom(tp.Form(), "Unable to delete tunnel", fmt.Sprintf("A tunnel was unable to be removed: %s", errors[0].Error()))
} else {
- walk.MsgBox(tp.Form(), "Unable to delete tunnels", fmt.Sprintf("%d tunnels were unable to be removed.", len(errors)), walk.MsgBoxIconError)
+ showErrorCustom(tp.Form(), "Unable to delete tunnels", fmt.Sprintf("%d tunnels were unable to be removed.", len(errors)))
}
})
}
diff --git a/ui/ui.go b/ui/ui.go
index aa0c7528..c98edf18 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -26,7 +26,7 @@ func RunUI() {
runtime.LockOSThread()
defer func() {
if err := recover(); err != nil {
- walk.MsgBox(nil, "Panic", fmt.Sprint(err, "\n\n", string(debug.Stack())), walk.MsgBoxIconError)
+ showErrorCustom(nil, "Panic", fmt.Sprint(err, "\n\n", string(debug.Stack())))
panic(err)
}
}()
@@ -95,7 +95,7 @@ func RunUI() {
if shouldQuitManagerWhenExiting {
_, err := manager.IPCClientQuit(true)
if err != nil {
- walk.MsgBox(nil, "Error Exiting WireGuard", fmt.Sprintf("Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.", err), walk.MsgBoxIconError)
+ showErrorCustom(nil, "Error Exiting WireGuard", fmt.Sprintf("Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.", err))
}
}
}
@@ -104,3 +104,21 @@ func onQuit() {
shouldQuitManagerWhenExiting = true
walk.App().Exit(0)
}
+
+func showError(err error, owner walk.Form) bool {
+ if err == nil {
+ return false
+ }
+
+ showErrorCustom(owner, "Error", err.Error())
+
+ return true
+}
+
+func showErrorCustom(owner walk.Form, title, message string) {
+ walk.MsgBox(owner, title, message, walk.MsgBoxIconError)
+}
+
+func showWarningCustom(owner walk.Form, title, message string) {
+ walk.MsgBox(owner, title, message, walk.MsgBoxIconWarning)
+}
diff --git a/ui/updatepage.go b/ui/updatepage.go
index 95657798..9e73781f 100644
--- a/ui/updatepage.go
+++ b/ui/updatepage.go
@@ -19,12 +19,16 @@ type UpdatePage struct {
}
func NewUpdatePage() (*UpdatePage, error) {
- up := &UpdatePage{}
var err error
+ var disposables walk.Disposables
+ defer disposables.Treat()
+
+ up := &UpdatePage{}
if up.TabPage, err = walk.NewTabPage(); err != nil {
return nil, err
}
+ disposables.Add(up)
up.SetTitle("An Update is Available!")
@@ -33,18 +37,30 @@ func NewUpdatePage() (*UpdatePage, error) {
up.SetLayout(walk.NewVBoxLayout())
- instructions, _ := walk.NewTextLabel(up)
+ instructions, err := walk.NewTextLabel(up)
+ if err != nil {
+ return nil, err
+ }
instructions.SetText("An update to WireGuard is available. It is highly advisable to update without delay.")
instructions.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0})
- status, _ := walk.NewTextLabel(up)
+ status, err := walk.NewTextLabel(up)
+ if err != nil {
+ return nil, err
+ }
status.SetText("Status: Waiting for user")
status.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0})
- bar, _ := walk.NewProgressBar(up)
+ bar, err := walk.NewProgressBar(up)
+ if err != nil {
+ return nil, err
+ }
bar.SetVisible(false)
- button, _ := walk.NewPushButton(up)
+ button, err := walk.NewPushButton(up)
+ if err != nil {
+ return nil, err
+ }
updateIcon, _ := loadSystemIcon("shell32", 46, 32)
button.SetImage(updateIcon)
button.SetText("Update Now")
@@ -113,5 +129,7 @@ func NewUpdatePage() (*UpdatePage, error) {
})
})
+ disposables.Spare()
+
return up, nil
}