diff --git a/examples/example-debug.config b/examples/example-debug.config index 33a5aec..f7896c0 100644 --- a/examples/example-debug.config +++ b/examples/example-debug.config @@ -5,5 +5,6 @@ fromvar:url.regex='.*fromvar.com.*' # Comment that should be ignored echo 'matched by url {}':url.regex='.*url.com.*' -echo 'matched by class {}':app.class=gnome-terminal-server +echo 'matched by Alacritty class {}':app.class=Alacritty +echo 'matched by gnome class {}':app.class=gnome-terminal-server echo 'matched by fallback {}':fallback \ No newline at end of file diff --git a/linux/go.mod b/linux/go.mod index db63cf2..f2667b0 100644 --- a/linux/go.mod +++ b/linux/go.mod @@ -6,6 +6,16 @@ require github.com/labi-le/hyprland-ipc-client v1.0.3 require github.com/pltanton/autobrowser/common v0.0.0 -require github.com/godbus/dbus/v5 v5.1.0 +require ( + github.com/godbus/dbus/v5 v5.1.0 + github.com/joshuarubin/go-sway v1.2.0 +) + +require ( + github.com/joshuarubin/lifecycle v1.0.0 // indirect + go.uber.org/atomic v1.3.2 // indirect + go.uber.org/multierr v1.1.0 // indirect + golang.org/x/sync v0.0.0-20190412183630-56d357773e84 // indirect +) replace github.com/pltanton/autobrowser/common => ../common diff --git a/linux/go.sum b/linux/go.sum index 43ff35a..a60fdd0 100644 --- a/linux/go.sum +++ b/linux/go.sum @@ -1,4 +1,21 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/joshuarubin/go-sway v1.2.0 h1:t3eqW504//uj9PDwFf0+IVfkD+WoOGaDX5gYIe0BHyM= +github.com/joshuarubin/go-sway v1.2.0/go.mod h1:qcDd6f25vJ0++wICwA1BainIcRC67p2Mb4lsrZ0k3/k= +github.com/joshuarubin/lifecycle v1.0.0 h1:N/lPEC8f+dBZ1Tn99vShqp36LwB+LI7XNAiNadZeLUQ= +github.com/joshuarubin/lifecycle v1.0.0/go.mod h1:sRy++ATvR9Ee21tkRdFkQeywAWvDsue66V70K0Dnl54= github.com/labi-le/hyprland-ipc-client v1.0.3 h1:NvfazDlMf/pKl8sAqAO7BUwLEo3xxBcGgMP8PKT7R6g= github.com/labi-le/hyprland-ipc-client v1.0.3/go.mod h1:JZ+LBSfp0aO33qOm6TMYqe7qD8CO9d8jMpGpqz6Yf3I= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84 h1:IqXQ59gzdXv58Jmm2xn0tSOR9i6HqroaOFRQ3wR/dJQ= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/linux/internal/deinfo/deinfo.go b/linux/internal/deinfo/deinfo.go index 07b4f7b..d1c7659 100644 --- a/linux/internal/deinfo/deinfo.go +++ b/linux/internal/deinfo/deinfo.go @@ -36,6 +36,8 @@ func New(appMode envx.AppMode) *DeInfoProvider { switch appMode { case envx.HYPRLAND: provider = newHyprlandProvider() + case envx.SWAY: + provider = newSwayProvider() case envx.GNOME: provider = newGnomeProvider() case envx.UNKNOWN: diff --git a/linux/internal/deinfo/hyprland.go b/linux/internal/deinfo/hyprland.go index d36bb12..ea50c90 100644 --- a/linux/internal/deinfo/hyprland.go +++ b/linux/internal/deinfo/hyprland.go @@ -19,7 +19,7 @@ func newHyprlandProvider() deInfoProvider { } func (h *hyprlandProvider) fetchActiveApp() (App, error) { - slog.Debug("Fetch active app from gnome") + slog.Debug("Fetch active app from hyprland") window, err := h.c.ActiveWindow() if err != nil { diff --git a/linux/internal/deinfo/sway.go b/linux/internal/deinfo/sway.go new file mode 100644 index 0000000..5937df8 --- /dev/null +++ b/linux/internal/deinfo/sway.go @@ -0,0 +1,53 @@ +package deinfo + +import ( + "context" + "fmt" + "log/slog" + "time" + + sway "github.com/joshuarubin/go-sway" +) + +type swayProvider struct{} + +// fetchActiveApp implements deInfoProvider. +func (s *swayProvider) fetchActiveApp() (App, error) { + slog.Debug("Fetch active app from sway") + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + defer cancel() + + client, err := sway.New(ctx) + if err != nil { + return App{}, fmt.Errorf("failed to create new sway client: %w", err) + } + + node, err := client.GetTree(context.Background()) + if err != nil { + return App{}, fmt.Errorf("failed to get sway tree: %w", err) + } + + focusedNode := node.FocusedNode() + + var class string + var title string = focusedNode.Name + + if focusedNode.WindowProperties != nil { + // For xwayland clients + class = focusedNode.WindowProperties.Class + title = focusedNode.WindowProperties.Title + } else if focusedNode.AppID != nil { + class = *focusedNode.AppID + } + + return App{ + Title: title, + Class: class, + }, nil +} + +func newSwayProvider() deInfoProvider { + return &swayProvider{} +} + +var _ deInfoProvider = &swayProvider{} diff --git a/linux/internal/envx/envx.go b/linux/internal/envx/envx.go index 85819b9..3473041 100644 --- a/linux/internal/envx/envx.go +++ b/linux/internal/envx/envx.go @@ -25,6 +25,7 @@ func init() { HyprlandMode bool GnomeMode bool + SwayMode bool LogLevel string }{} @@ -34,15 +35,16 @@ func init() { flag.StringVar(&flags.Url, "url", "", "url to open") flag.StringVar(&flags.LogLevel, "log", "INFO", "log level: DEBUG, INFO, WARN, ERROR") - flag.BoolVar(&flags.HyprlandMode, "hyprland", false, "use hyprland for app matcher") - flag.BoolVar(&flags.GnomeMode, "gnome", false, "use gnome for app matcher") + flag.BoolVar(&flags.HyprlandMode, "hyprland", false, "use hyprland IPC for app matcher") + flag.BoolVar(&flags.GnomeMode, "gnome", false, "use gnome DBUS protocol for app matcher") + flag.BoolVar(&flags.SwayMode, "sway", false, "use sway IPC for app matcher") flag.Parse() options = Options{ ConfigPath: flags.ConfigPath, Url: flags.Url, - Mode: getAppMode(flags.HyprlandMode, flags.GnomeMode), + Mode: getAppMode(flags.HyprlandMode, flags.GnomeMode, flags.SwayMode), LogLevel: flags.LogLevel, } } @@ -53,18 +55,23 @@ const ( UNKNOWN AppMode = iota HYPRLAND GNOME + SWAY ) -func getAppMode(hyprlandFlag, gnomeFlag bool) AppMode { +func getAppMode(hyprlandFlag, gnomeFlag, swayFlag bool) AppMode { switch { case hyprlandFlag: return HYPRLAND case gnomeFlag: return GNOME + case swayFlag: + return SWAY } // Try to determine it then switch { + case os.Getenv("SWAYSOCK") != "": + return SWAY case os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") != "": return HYPRLAND case os.Getenv("DESKTOP_SESSION") == "gnome": diff --git a/nix/linux.nix b/nix/linux.nix index febe3f4..0d9662f 100644 --- a/nix/linux.nix +++ b/nix/linux.nix @@ -2,7 +2,7 @@ buildGoModule { pname = "autobrowser"; version = "0"; - vendorHash = "sha256-4vLAS5eQyvE5bsQ35q0PYdu1zUxYT34Y0gC/6nSfPI8="; + vendorHash = "sha256-GWrflGa6evgehcHQujac67llQJWnRIQbBFna26DYizk="; meta = with lib; { homepage = "https://github.com/pltanton/autobrowser"; description = "Automatically determine browser depending on provided rules";