From f268ef204360b354c141a9267256e033ca2ec6c0 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 3 May 2019 11:26:36 +0200 Subject: ui: fix up confview ticker and list sync logic --- ui/confview.go | 44 ++++++++++++++++++++++++++++++++++++++------ ui/listview.go | 18 +++++++++++------- ui/tunnelspage.go | 48 +++++++++++++++--------------------------------- 3 files changed, 64 insertions(+), 46 deletions(-) (limited to 'ui') diff --git a/ui/confview.go b/ui/confview.go index 6fe02f66..8f7b82c5 100644 --- a/ui/confview.go +++ b/ui/confview.go @@ -9,6 +9,7 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/lxn/walk" "github.com/lxn/win" @@ -65,12 +66,12 @@ type peerView struct { type ConfView struct { *walk.ScrollView - name *walk.GroupBox - interfaze *interfaceView - peers map[conf.Key]*peerView - + name *walk.GroupBox + interfaze *interfaceView + peers map[conf.Key]*peerView tunnelChangedCB *service.TunnelChangeCallback tunnel *service.Tunnel + updateTicker *time.Ticker } func (lsl *labelStatusLine) widgets() (walk.Widget, walk.Widget) { @@ -409,6 +410,24 @@ func NewConfView(parent walk.Container) (*ConfView, error) { return nil, err } cv.SetDoubleBuffering(true) + cv.updateTicker = time.NewTicker(time.Second) + go func() { + for range cv.updateTicker.C { + if cv.tunnel != nil { + var state service.TunnelState + var config conf.Config + if state, _ = cv.tunnel.State(); state == service.TunnelStarted { + config, _ = cv.tunnel.RuntimeConfig() + } + if config.Name == "" { + config, _ = cv.tunnel.StoredConfig() + } + cv.Synchronize(func() { + cv.setTunnel(cv.tunnel, &config, state) + }) + } + } + }() return cv, nil } @@ -417,7 +436,10 @@ func (cv *ConfView) Dispose() { cv.tunnelChangedCB.Unregister() cv.tunnelChangedCB = nil } - + if cv.updateTicker != nil { + cv.updateTicker.Stop() + cv.updateTicker = nil + } cv.ScrollView.Dispose() } @@ -447,10 +469,20 @@ func (cv *ConfView) onTunnelChanged(tunnel *service.Tunnel, state service.Tunnel cv.interfaze.toggleActive.update(state) } }) + var config conf.Config + if state == service.TunnelStarted { + config, _ = tunnel.RuntimeConfig() + } + if config.Name == "" { + config, _ = tunnel.StoredConfig() + } + cv.Synchronize(func() { + cv.setTunnel(tunnel, &config, state) + }) } func (cv *ConfView) SetTunnel(tunnel *service.Tunnel) { - cv.tunnel = tunnel + cv.tunnel = tunnel //XXX: This races with the read in the updateTicker, but it's pointer-sized! var config conf.Config var state service.TunnelState diff --git a/ui/listview.go b/ui/listview.go index 4d196bba..78e53fda 100644 --- a/ui/listview.go +++ b/ui/listview.go @@ -68,10 +68,6 @@ func NewListView(parent walk.Container) (*ListView, error) { tv.SetDoubleBuffering(true) model := new(ListModel) - if model.tunnels, err = service.IPCClientTunnels(); err != nil { - return nil, err - } - tv.SetModel(model) tv.SetLastColumnStretched(true) tv.SetHeaderHidden(true) @@ -88,7 +84,6 @@ func NewListView(parent walk.Container) (*ListView, error) { tunnelsView.tunnelChangedCB = service.IPCClientRegisterTunnelChange(tunnelsView.onTunnelChange) tunnelsView.tunnelsChangedCB = service.IPCClientRegisterTunnelsChange(tunnelsView.onTunnelsChange) - tunnelsView.onTunnelsChange() return tunnelsView, nil } @@ -152,11 +147,15 @@ func (tv *ListView) onTunnelChange(tunnel *service.Tunnel, state service.TunnelS } func (tv *ListView) onTunnelsChange() { + tv.Load(true) +} + +func (tv *ListView) Load(asyncUI bool) { tunnels, err := service.IPCClientTunnels() if err != nil { return } - tv.Synchronize(func() { + doUI := func() { newTunnels := make(map[service.Tunnel]bool, len(tunnels)) oldTunnels := make(map[service.Tunnel]bool, len(tv.model.tunnels)) for _, tunnel := range tunnels { @@ -197,7 +196,12 @@ func (tv *ListView) onTunnelsChange() { tv.selectTunnel(firstTunnelName) } } - }) + } + if asyncUI { + tv.Synchronize(doUI) + } else { + doUI() + } } func (tv *ListView) selectTunnel(tunnelName string) { diff --git a/ui/tunnelspage.go b/ui/tunnelspage.go index 4ae6bd4b..36aa80fa 100644 --- a/ui/tunnelspage.go +++ b/ui/tunnelspage.go @@ -8,16 +8,14 @@ package ui import ( "archive/zip" "fmt" + "github.com/lxn/walk" + "golang.zx2c4.com/wireguard/windows/conf" + "golang.zx2c4.com/wireguard/windows/service" "io/ioutil" "os" "path/filepath" "sort" "strings" - "time" - - "github.com/lxn/walk" - "golang.zx2c4.com/wireguard/windows/conf" - "golang.zx2c4.com/wireguard/windows/service" ) type TunnelsPage struct { @@ -58,8 +56,6 @@ func NewTunnelsPage() (*TunnelsPage, error) { if tp.tunnelsView, err = NewListView(listContainer); err != nil { return nil, err } - tp.tunnelsView.ItemActivated().Attach(tp.onTunnelsViewItemActivated) - tp.tunnelsView.CurrentIndexChanged().Attach(tp.updateConfView) // HACK: Because of https://github.com/lxn/walk/issues/481 // we need to put the ToolBar into its own Composite. @@ -121,7 +117,7 @@ func NewTunnelsPage() (*TunnelsPage, error) { exportAction.Triggered().Attach(tp.onExportTunnels) listToolbar.Actions().Add(exportAction) - listContainerWidth := listToolbar.MinSizeHint().Width + tp.DPI() / 10 // TODO: calculate these margins correctly instead + listContainerWidth := listToolbar.MinSizeHint().Width + tp.DPI()/10 // TODO: calculate these margins correctly instead listContainer.SetMinMaxSize(walk.Size{listContainerWidth, 0}, walk.Size{listContainerWidth, 0}) tp.currentTunnelContainer, _ = walk.NewComposite(tp) @@ -131,9 +127,9 @@ func NewTunnelsPage() (*TunnelsPage, error) { tp.fillerContainer, _ = walk.NewComposite(tp) tp.fillerContainer.SetVisible(false) - tp.fillerContainer.SetLayout(walk.NewHBoxLayout()) - tp.fillerContainer.Layout().SetMargins(walk.Margins{}) - walk.NewHSpacer(tp.fillerContainer) + hlayout = walk.NewHBoxLayout() + hlayout.SetMargins(walk.Margins{}) + tp.fillerContainer.SetLayout(hlayout) tp.fillerButton, _ = walk.NewPushButton(tp.fillerContainer) buttonWidth := tp.DPI() * 2 //TODO: Use dynamic DPI tp.fillerButton.SetMinMaxSize(walk.Size{buttonWidth, 0}, walk.Size{buttonWidth, 0}) @@ -142,25 +138,9 @@ func NewTunnelsPage() (*TunnelsPage, error) { tp.fillerHandler() } }) - walk.NewHSpacer(tp.fillerContainer) - - //TODO: expose walk.TableView.itemCountChangedPublisher.Event() - tp.tunnelsView.Property("ItemCount").Changed().Attach(tp.onTunnelsChanged) - tp.onTunnelsChanged() - tp.tunnelsView.SelectedIndexesChanged().Attach(tp.onSelectedTunnelsChanged) tp.confView, _ = NewConfView(tp.currentTunnelContainer) - updateConfViewTicker := time.NewTicker(time.Second) - tp.Disposing().Attach(updateConfViewTicker.Stop) - go func() { - for range updateConfViewTicker.C { - tp.Synchronize(func() { - tp.updateConfView() - }) - } - }() - controlsContainer, _ := walk.NewComposite(tp.currentTunnelContainer) controlsContainer.SetLayout(walk.NewHBoxLayout()) controlsContainer.Layout().SetMargins(walk.Margins{}) @@ -175,18 +155,20 @@ func NewTunnelsPage() (*TunnelsPage, error) { editTunnel.SetText("Edit") editTunnel.Clicked().Attach(tp.onEditTunnel) - tp.tunnelsView.SetCurrentIndex(0) - disposables.Spare() + //TODO: expose walk.TableView.itemCountChangedPublisher.Event() + tp.tunnelsView.Property("ItemCount").Changed().Attach(tp.onTunnelsChanged) + tp.tunnelsView.SelectedIndexesChanged().Attach(tp.onSelectedTunnelsChanged) + tp.tunnelsView.ItemActivated().Attach(tp.onTunnelsViewItemActivated) + tp.tunnelsView.CurrentIndexChanged().Attach(tp.updateConfView) + tp.tunnelsView.Load(false) + tp.onTunnelsChanged() + return tp, nil } func (tp *TunnelsPage) updateConfView() { - if !tp.Visible() || !tp.currentTunnelContainer.Visible() { - return - } - tp.confView.SetTunnel(tp.tunnelsView.CurrentTunnel()) } -- cgit v1.2.3-59-g8ed1b