diff --git a/.fpm b/.fpm index 747df4e..247b8cf 100644 --- a/.fpm +++ b/.fpm @@ -3,4 +3,5 @@ --license agpl3 --description "Wallpaper manager for i3" --url "https://gitnet.fr/deblan/i3-wallpaper-manager" +--deb-recommends "feh" --maintainer "Simon Vieille " diff --git a/.gitea/issue_template/FEATURE_TEMPLATE.yml b/.gitea/issue_template/FEATURE_TEMPLATE.yml new file mode 100644 index 0000000..3d687c5 --- /dev/null +++ b/.gitea/issue_template/FEATURE_TEMPLATE.yml @@ -0,0 +1,34 @@ +name: New feature +about: Use this template if you want to request a feature +title: "[FEATURE] " +labels: + - Kind/Enhancement +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this feature request! + + - type: textarea + id: description + attributes: + label: Description + description: Describe the feature. + validations: + required: true + + - type: textarea + id: benefits + attributes: + label: Benefits + description: Describe the benefits of this feature. + validations: + required: true + + - type: textarea + id: extra + attributes: + label: More informations + description: If you want to share more things, this is here! + validations: + required: false diff --git a/.gitea/issue_template/ISSUE_TEMPLATE.yml b/.gitea/issue_template/ISSUE_TEMPLATE.yml new file mode 100644 index 0000000..0a703fd --- /dev/null +++ b/.gitea/issue_template/ISSUE_TEMPLATE.yml @@ -0,0 +1,63 @@ +name: New issue +about: Use this template if you have a bug +title: "[Bug] " +labels: + - Kind/Bug +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + - type: textarea + id: environment + attributes: + label: Environment + value: | + * i3 wallpaper manager version: + * i3-wm version: + * Operating system and version: + validations: + required: true + + - type: textarea + id: configuration + attributes: + label: Configuration + value: | + ``` + ``` + validations: + required: false + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: How reproduce the bug? + validations: + required: false + + - type: textarea + id: resuts + attributes: + label: Observed Results + description: What happened? + validations: + required: false + + - type: textarea + id: expected + attributes: + label: Expected Results + description: What should happen? + validations: + required: false + + - type: textarea + id: extra + attributes: + label: More informations + description: If you want to share more things, this is here! + validations: + required: false diff --git a/.gitea/issue_template/QUESTION_TEMPLATE.yml b/.gitea/issue_template/QUESTION_TEMPLATE.yml new file mode 100644 index 0000000..30fd73c --- /dev/null +++ b/.gitea/issue_template/QUESTION_TEMPLATE.yml @@ -0,0 +1,26 @@ +name: New question +about: Use this template when you don't know how to do something +title: "[Question] " +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill information. + + - type: textarea + id: environment + attributes: + label: Environment + value: | + * i3 wallpaper manager version: + * i3-wm version: + * Operating system and version: + validations: + required: true + + - type: textarea + id: question + attributes: + label: Question + validations: + required: true diff --git a/.gitea/issue_template/config.yml b/.gitea/issue_template/config.yml new file mode 100644 index 0000000..d3fdf27 --- /dev/null +++ b/.gitea/issue_template/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Documentation + url: https://gitnet.fr/deblan/i3-wallpaper-manager + about: Official documentation web site + - name: Ask a question in our Matrix room + about: If you prefer a chat-like conversation or in need for quick help, this might be an alternative to opening an issue. + url: https://matrix.to/#/!QDcaVhvLZlhptPkGVi:neutralnetwork.org?via=neutralnetwork.org diff --git a/CHANGELOG.md b/CHANGELOG.md index c4cb91a..7aab162 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ [Unreleased] +## v1.2.1 +### Added +- Add debian packaging deb-recommends +### Fixed +- Fix #1: add cache of latest command to not run wallpaper update when it's already up to date + +## v1.2.0 +### Added +- Add `callback` option + +## v1.1.1 +### Fixed +- Update wallpapers on start + +## v1.1.0 +### Changed +- Refactoring + ## v1.0.0 ### Added - First release! diff --git a/README.md b/README.md index f3951b6..4bfe0b1 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,23 @@ -# 🖥️ i3 wallpaper manager +# 🖥️ i3 Wallpaper Manager -**i3 wallpaper manager** is a command-line tool designed to change the wallpaper depending of active workspaces on [i3](https://i3wm.org/). +**i3 Wallpaper Manager** is a command-line tool designed to change the wallpaper depending of active workspaces on [i3](https://i3wm.org/). This tool works on one or multiple screens. + + + +_Thanks [AZProductions](https://github.com/AZProductions/AbstractCollection/)!_ ## 📗 How to install the project +### Dependencies + +- [Feh](https://feh.finalrewind.org/) (by default) + +### Pre-compiled versions + Pre-compiled versions are available in the [Releases](https://gitnet.fr/deblan/i3-wallpaper-manager/releases). For Debian users, a package is also provided. +### From source + If you want to compile the project from source, you will need at least the GO compiler version 1.22. Clone the project and run the make command. The compiled output will be located in the `build` directory. ``` @@ -17,7 +29,7 @@ $ make To start, you need to create a configuration file in YAML format. This file consists of two keys: `default` to define the path of the default wallpaper, and `workspaces` which allows you to associate each workspace with its corresponding wallpaper. -``` +```yaml default: /home/alice/wallpapers/default.jpg workspaces: "Name of the workspace 1": /home/alice/wallpapers/1.jpg @@ -25,14 +37,34 @@ workspaces: "Name of the workspace 3": /home/alice/wallpapers/3.jpg ``` -Next, you simply need to run `i3-wallpaper-manager` while specify the path to the configuration file. +Next, you simply need to run `i3-wallpaper-manager` and specify the path to the configuration file. -``` -i3-wallpaper-manager /path/to/config.yaml +```bash +DISPLAY=:0 i3-wallpaper-manager /path/to/config.yaml ``` To run it when i3 starts, add this to your i3 configuration: +```bash +exec --no-startup-id DISPLAY=:0 i3-wallpaper-manager /path/to/config.yaml ``` -exec_always i3-wallpaper-manager /path/to/config.yaml + +If you wish to use a program other than `feh`, set the `callback` parameter by specifying the path to your script. + +```yaml +callback: /path/to/custom.sh +``` + +```bash +#!/bin/sh +# /path/to/custom.sh + +SCREEN_1="$1" +WALLPAPER_1="$2" + +SCREEN_2="$3" +WALLPAPER_2="$4" +# etc. + +# Do stuff... ``` diff --git a/callback.go b/callback.go new file mode 100644 index 0000000..270c942 --- /dev/null +++ b/callback.go @@ -0,0 +1,19 @@ +package main + +import ( + "os" + "os/exec" +) + +func CallbackUpdateWallpapers(callback string, files, screens []string) *exec.Cmd { + args := []string{} + + for key, file := range files { + args = append(args, screens[key], file) + } + + cmd := exec.Command(callback, args...) + cmd.Env = os.Environ() + + return cmd +} diff --git a/config.go b/config.go new file mode 100644 index 0000000..e90166f --- /dev/null +++ b/config.go @@ -0,0 +1,30 @@ +package main + +import ( + "os" + + "gopkg.in/yaml.v3" +) + +type Config struct { + Default string `yaml:"default"` + Callback string `yaml:"callback"` + Workspaces map[string]string `yaml:"workspaces"` +} + +func LoadConfiguration(file string) (Config, error) { + data, err := os.ReadFile(os.Args[1]) + config := Config{} + + if err != nil { + return config, err + } + + err = yaml.Unmarshal(data, &config) + + if err != nil { + return config, err + } + + return config, nil +} diff --git a/config.yaml.example b/config.yaml.example index 5e50253..0cf69eb 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -3,3 +3,4 @@ workspaces: "Name of the workspace 1": /home/alice/wallpapers/1.jpg "Name of the workspace 2": /home/alice/wallpapers/2.jpg "Name of the workspace 3": /home/alice/wallpapers/3.jpg +# callback: /path/to/custom.sh diff --git a/feh.go b/feh.go new file mode 100644 index 0000000..9e8b562 --- /dev/null +++ b/feh.go @@ -0,0 +1,19 @@ +package main + +import ( + "os" + "os/exec" +) + +func FehUpdateWallpapers(files []string) *exec.Cmd { + args := []string{} + + for _, file := range files { + args = append(args, "--bg-fill", file) + } + + cmd := exec.Command("feh", args...) + cmd.Env = os.Environ() + + return cmd +} diff --git a/main.go b/main.go index 44161f5..81c8d3e 100644 --- a/main.go +++ b/main.go @@ -1,78 +1,36 @@ package main import ( - "fmt" "log" "os" - "os/exec" "go.i3wm.org/i3" - "gopkg.in/yaml.v3" ) -type Config struct { - Default string `yaml:"default"` - Workspaces map[string]string `yaml:"workspaces"` -} - -func getWallpaper(workspace string, config Config) string { - file := config.Default - workspaceFile := config.Workspaces[workspace] - - if workspaceFile != "" { - file = workspaceFile - } - - return file -} - func main() { recv := i3.Subscribe(i3.WorkspaceEventType) if len(os.Args) != 2 { - fmt.Errorf("Configuration required!") + log.Printf("[ERROR] Configuration required!") os.Exit(1) } - data, err := os.ReadFile(os.Args[1]) - config := Config{} + config, err := LoadConfiguration(os.Args[1]) if err != nil { - log.Printf("[error] %s", err.Error()) + log.Printf("[ERROR] %s", err.Error()) + os.Exit(1) } - err = yaml.Unmarshal(data, &config) + var lastCommand string - if err != nil { - log.Printf("[error] %s", err.Error()) - } + UpdateWallapers(config, &lastCommand) for recv.Next() { event := recv.Event().(*i3.WorkspaceEvent) - if event.Change != "focus" { - continue - } - - outputs, err := i3.GetOutputs() - args := []string{} - - if err == nil { - for _, output := range outputs { - if output.CurrentWorkspace != "" { - args = append(args, "--bg-fill", getWallpaper(output.CurrentWorkspace, config)) - } - } - - cmd := exec.Command("feh", args...) - cmd.Env = os.Environ() - log.Printf("[UPDATE] %s", cmd.String()) - - if err := cmd.Run(); err != nil { - log.Printf("[ERROR] %s", err.Error()) - } - } else { - log.Printf("[ERROR] %s", err.Error()) + if event.Change == "focus" { + UpdateWallapers(config, &lastCommand) } } } diff --git a/wallpaper.go b/wallpaper.go new file mode 100644 index 0000000..bec24d4 --- /dev/null +++ b/wallpaper.go @@ -0,0 +1,71 @@ +package main + +import ( + "log" + "os/exec" + + "go.i3wm.org/i3" +) + +func GetWorkspaceWallpaper(workspace string, config Config) string { + file := config.Default + workspaceFile := config.Workspaces[workspace] + + if workspaceFile != "" { + file = workspaceFile + } + + return file +} + +func GetOutputsWallpapers(config Config) ([]string, []string, error) { + files := []string{} + screens := []string{} + outputs, err := i3.GetOutputs() + if err != nil { + return files, screens, err + } + + for _, output := range outputs { + if output.CurrentWorkspace != "" { + file := GetWorkspaceWallpaper(output.CurrentWorkspace, config) + + if file != "" { + files = append(files, file) + screens = append(screens, output.Name) + } + } + } + + return files, screens, nil +} + +func UpdateWallapers(config Config, lastCommand *string) { + files, screens, err := GetOutputsWallpapers(config) + if err != nil { + log.Printf("[ERROR] %s", err.Error()) + return + } + + var cmd *exec.Cmd + + if config.Callback == "" { + cmd = FehUpdateWallpapers(files) + } else { + cmd = CallbackUpdateWallpapers(config.Callback, files, screens) + } + + if cmd.String() == *lastCommand { + log.Printf("[INFO] wallapaper(s) already up to date") + return + } + + err = cmd.Run() + + if err != nil { + log.Printf("[ERROR] cmd=%s error=%s", cmd.String(), err.Error()) + } else { + log.Printf("[SUCCESS] cmd=%s", cmd.String()) + *lastCommand = cmd.String() + } +}