Skip to content

Commit

Permalink
feat: notify about layer changes in toast overlay
Browse files Browse the repository at this point in the history
  • Loading branch information
rszyma committed Feb 10, 2024
1 parent 280d952 commit c14d98c
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 13 deletions.
19 changes: 14 additions & 5 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/getlantern/systray"
"github.com/skratchdot/open-golang/open"

"github.com/rszyma/kanata-tray/app/notifications"
"github.com/rszyma/kanata-tray/icons"
"github.com/rszyma/kanata-tray/runner"
)
Expand All @@ -23,8 +24,9 @@ type SysTrayApp struct {
layerIcons LayerIcons
selectedConfig int
selectedExec int
cfgChangeCh chan int
exeChangeCh chan int

cfgChangeCh chan int
exeChangeCh chan int

// Menu items

Expand All @@ -41,7 +43,12 @@ type SysTrayApp struct {
}

func NewSystrayApp(menuTemplate *MenuTemplate, layerIcons LayerIcons) *SysTrayApp {
t := &SysTrayApp{menuTemplate: menuTemplate, layerIcons: layerIcons, selectedConfig: -1, selectedExec: -1}
t := &SysTrayApp{
menuTemplate: menuTemplate,
layerIcons: layerIcons,
selectedConfig: -1,
selectedExec: -1,
}

systray.SetIcon(icons.Default)
systray.SetTitle("kanata-tray")
Expand Down Expand Up @@ -152,7 +159,7 @@ func (t *SysTrayApp) runWithSelectedOptions(runner *runner.KanataRunner) {
}
}

func (t *SysTrayApp) StartProcessingLoop(runner *runner.KanataRunner, runRightAway bool, configFolder string) {
func (t *SysTrayApp) StartProcessingLoop(runner *runner.KanataRunner, notifier notifications.INotifier, runRightAway bool, configFolder string) {
if runRightAway {
t.runWithSelectedOptions(runner)
} else {
Expand All @@ -166,8 +173,10 @@ func (t *SysTrayApp) StartProcessingLoop(runner *runner.KanataRunner, runRightAw
case event := <-serverMessageCh:
// fmt.Println("Received an event from kanata!")
if event.LayerChange != nil {
icon := t.layerIcons.IconForLayerName(event.LayerChange.NewLayer)
newLayer := event.LayerChange.NewLayer
icon := t.layerIcons.IconForLayerName(newLayer)
systray.SetIcon(icon)
notifier.LayerChange(newLayer)
}
case err := <-runner.RetCh:
if err != nil {
Expand Down
100 changes: 100 additions & 0 deletions app/notifications/gtk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//go:build gtk_overlay

package notifications

import (
"fmt"
"time"

"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
)

type GtkOverlay struct {
windowVisibilityDuration time.Duration

label *gtk.Label
refreshWindowVisibilityDuration chan time.Time
}

func InitGtkOverlay(width int, height int, positionOffsetX int, positionOffsetY int, visibilityDuration time.Duration) (*GtkOverlay, error) {
gtk.Init(nil)

// Create a new window
win, err := gtk.WindowNew(gtk.WINDOW_POPUP)
if err != nil {
return nil, fmt.Errorf("unable to create window: %v", err)
}
win.SetDefaultSize(width, height)
win.Connect("destroy", func() {
gtk.MainQuit()
})
win.SetAcceptFocus(false) // not respected in Hyprland
win.SetCanFocus(false) // not respected in Hyprland
win.SetDecorated(false)
win.SetTypeHint(gdk.WINDOW_TYPE_HINT_NOTIFICATION)
win.SetDeletable(false) // not respected in Hyprland
win.SetSkipTaskbarHint(false)
win.SetSkipPagerHint(false)
win.SetResizable(false) // not respected in Hyprland
win.SetFocusOnMap(false)
win.SetFocusOnClick(false)
win.SetCanDefault(false)
// win.SetOpacity(0.5) // not respected in Hyprland

win.SetPosition(gtk.WIN_POS_CENTER) // temporary position
centerX, centerY := win.GetPosition()

// Create a label for displaying the layer name
label, err := gtk.LabelNew("Layer Switched!")
if err != nil {
return nil, fmt.Errorf("unable to create label: %v", err)
}

// Add the label to the window
win.Add(label)

refreshVisibilityCh := make(chan time.Time)

go func() {
for {
hideTime := <-refreshVisibilityCh
timer := time.NewTimer(time.Until(hideTime))

// needs to be set every time window gets hidden, otherwise it's not respected by gtk
win.Move(centerX+positionOffsetX, centerY+positionOffsetY)
win.ShowAll()

loop:
for {
select {
case newHideTime := <-refreshVisibilityCh:
if !timer.Stop() {
<-timer.C
}
timer.Stop()
timer.Reset(time.Until(newHideTime))
case <-timer.C:
break loop
}
}

win.Hide()
}
}()

// Start the GTK main loop
go gtk.Main()

return &GtkOverlay{
windowVisibilityDuration: visibilityDuration,
label: label,
refreshWindowVisibilityDuration: refreshVisibilityCh,
}, nil
}

func (n *GtkOverlay) LayerChange(newLayer string) error {
n.label.SetText(newLayer)
n.refreshWindowVisibilityDuration <- time.Now().Add(n.windowVisibilityDuration)
return nil
}
18 changes: 18 additions & 0 deletions app/notifications/no_gtk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//go:build !gtk_overlay

package notifications

import (
"fmt"
"time"
)

type GtkOverlay struct{}

func InitGtkOverlay(width int, height int, positionOffsetX int, positionOffsetY int, visibilityDuration time.Duration) (*GtkOverlay, error) {
return nil, fmt.Errorf("'gtk_overlay' compilation flag was not enabled for this build")
}

func (n *GtkOverlay) LayerChange(newLayer string) error {
return nil
}
11 changes: 11 additions & 0 deletions app/notifications/notifications.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package notifications

type INotifier interface {
LayerChange(newLayer string) error
}

type Disabled struct{}

func (n *Disabled) LayerChange(_ string) error {
return nil
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
golang.org/x/text v0.3.7 // indirect
)

Expand All @@ -24,6 +25,8 @@ require (
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
github.com/gotk3/gotk3 v0.6.3
github.com/k0kubun/pp/v3 v3.2.0
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
github.com/pelletier/go-toml/v2 v2.1.1
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE=
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gotk3/gotk3 v0.6.3 h1:+Ke4WkM1TQUNOlM2TZH6szqknqo+zNbX3BZWVXjSHYw=
github.com/gotk3/gotk3 v0.6.3/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
github.com/k0kubun/pp/v3 v3.2.0 h1:h33hNTZ9nVFNP3u2Fsgz8JXiF5JINoZfFq4SvKJwNcs=
github.com/k0kubun/pp/v3 v3.2.0/go.mod h1:ODtJQbQcIRfAD3N+theGCV1m/CBxweERz2dapdz1EwA=
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f h1:dKccXx7xA56UNqOcFIbuqFjAWPVtP688j5QMgmo6OHU=
Expand All @@ -49,6 +53,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
Expand Down
19 changes: 12 additions & 7 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@

set windows-powershell := true

just:
just -l

run:
CGO_ENABLED=1 GO111MODULE=on go run . -ldflags "-H=windowsgui"
CGO_ENABLED=1 GO111MODULE=on go run .

build_release tags="gtk_overlay" version="latest":
just _build_release_{{os()}} {{tags}} {{version}}

build_release_linux version="latest":
GOOS=linux CGO_ENABLED=1 GO111MODULE=on go build -ldflags "-s -w -X 'main.buildVersion={{version}}' -X 'main.buildHash=$(git rev-parse HEAD)' -X 'main.buildDate=$(date -u)'" -trimpath -o dist/kanata-tray
_build_release_linux tags version:
GOOS=linux CGO_ENABLED=1 GO111MODULE=on go build -tags={{tags}} -ldflags "-s -w -X 'main.buildVersion={{version}}' -X 'main.buildHash=$(git rev-parse HEAD)' -X 'main.buildDate=$(date -u)'" -trimpath -o dist/kanata-tray

build_release_windows version="latest":
GOOS=windows CGO_ENABLED=1 GO111MODULE=on go build -ldflags "-H=windowsgui -s -w -X 'main.buildVersion={{version}}' -X 'main.buildHash=$(git rev-parse HEAD)' -X 'main.buildDate=$(date -u)'" -trimpath -o dist/kanata-tray.exe
# CGO cross-compilation is not supported with 'gtk_overlay' tag
_build_release_windows tags version:
GOOS=windows CGO_ENABLED=1 GO111MODULE=on go build -tags={{tags}} -ldflags "-H=windowsgui -s -w -X 'main.buildVersion={{version}}' -X 'main.buildHash=$(git rev-parse HEAD)' -X 'main.buildDate=$(date -u)'" -trimpath -o dist/kanata-tray.exe

# e.g. "push_tag v0.1.0"
push_tag tag:
git tag {{tag}}
git push --tags
git push --tags
11 changes: 10 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"os"
"path/filepath"
"runtime"
"time"

"github.com/getlantern/systray"
"github.com/kirsle/configdir"

"github.com/rszyma/kanata-tray/app"
"github.com/rszyma/kanata-tray/app/notifications"
"github.com/rszyma/kanata-tray/config"
"github.com/rszyma/kanata-tray/icons"
"github.com/rszyma/kanata-tray/runner"
Expand Down Expand Up @@ -69,9 +71,16 @@ func mainImpl() error {
layerIcons := app.ResolveIcons(configFolder, cfg.LayerIcons, icons.Default)
runner := runner.NewKanataRunner()

var notifier notifications.INotifier
notifier, err = notifications.InitGtkOverlay(300, 50, 0, 70, 1*time.Second)
if err != nil {
fmt.Printf("Failed to initialize gtk notifications window. Layer change notifications will be disabled. Error: %v\n", err)
notifier = &notifications.Disabled{}
}

onReady := func() {
app := app.NewSystrayApp(&menuTemplate, layerIcons)
go app.StartProcessingLoop(&runner, cfg.General.LaunchOnStart, configFolder)
go app.StartProcessingLoop(&runner, notifier, cfg.General.LaunchOnStart, configFolder)
}

onExit := func() {
Expand Down

0 comments on commit c14d98c

Please sign in to comment.