add resizing based on monitor size

This commit is contained in:
2025-10-24 22:20:36 -07:00
parent b4b00c4564
commit b78b6b6582
3 changed files with 146 additions and 6 deletions

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"image"
"io" "io"
"math/rand" "math/rand"
"net/http" "net/http"
@@ -14,6 +15,12 @@ import (
"sort" "sort"
"strings" "strings"
"time" "time"
_ "image/gif"
"image/jpeg"
"image/png"
"golang.org/x/image/draw"
) )
const ( const (
@@ -66,6 +73,12 @@ type WallhavenResponse struct {
} `json:"data"` } `json:"data"`
} }
type monitor struct {
Name string `json:"name"`
Width int `json:"width"`
Height int `json:"height"`
}
func main() { func main() {
// Initialize random source // Initialize random source
r := rand.New(rand.NewSource(time.Now().UnixNano())) r := rand.New(rand.NewSource(time.Now().UnixNano()))
@@ -213,27 +226,150 @@ func downloadRandomWallpaper(wallpaperPath string, r *rand.Rand, topics []string
return filepath, displayName return filepath, displayName
} }
func activeMonitors() ([]monitor, error) {
out, err := exec.Command("hyprctl", "-j", "monitors").Output()
if err != nil {
return nil, err
}
var monitors []monitor
if err := json.Unmarshal(out, &monitors); err != nil {
return nil, err
}
return monitors, nil
}
func ensureSized(wallpaperPath string) (string, error) {
monitors, err := activeMonitors()
if err != nil {
return "", err
}
if len(monitors) == 0 {
return wallpaperPath, nil
}
targetWidth := 0
targetHeight := 0
for _, m := range monitors {
if m.Width > targetWidth {
targetWidth = m.Width
}
if m.Height > targetHeight {
targetHeight = m.Height
}
}
if targetWidth == 0 || targetHeight == 0 {
return wallpaperPath, nil
}
file, err := os.Open(wallpaperPath)
if err != nil {
return "", err
}
defer file.Close()
src, format, err := image.Decode(file)
if err != nil {
return "", err
}
if src.Bounds().Dx() == targetWidth && src.Bounds().Dy() == targetHeight {
return wallpaperPath, nil
}
dst := image.NewRGBA(image.Rect(0, 0, targetWidth, targetHeight))
draw.CatmullRom.Scale(dst, dst.Bounds(), src, src.Bounds(), draw.Over, nil)
var ext string
switch format {
case "jpeg":
ext = ".jpg"
case "png":
ext = ".png"
case "gif":
ext = ".png"
default:
ext = filepath.Ext(wallpaperPath)
if ext == "" {
ext = ".jpg"
}
}
base := strings.TrimSuffix(filepath.Base(wallpaperPath), filepath.Ext(wallpaperPath))
resizedPath := filepath.Join(filepath.Dir(wallpaperPath), fmt.Sprintf("%s-%dx%d%s", base, targetWidth, targetHeight, ext))
outFile, err := os.Create(resizedPath)
if err != nil {
return "", err
}
defer outFile.Close()
switch format {
case "png", "gif":
if err := png.Encode(outFile, dst); err != nil {
return "", err
}
default:
if err := jpeg.Encode(outFile, dst, &jpeg.Options{Quality: 90}); err != nil {
return "", err
}
}
return resizedPath, nil
}
func changeWallpaper(wallpaperPath, topic string) { func changeWallpaper(wallpaperPath, topic string) {
resizedPath, err := ensureSized(wallpaperPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error resizing wallpaper: %v\n", err)
resizedPath = wallpaperPath
}
if resizedPath == "" {
resizedPath = wallpaperPath
}
// Save current wallpaper path // Save current wallpaper path
homeDir, _ := os.UserHomeDir() homeDir, _ := os.UserHomeDir()
wallpaperFile := filepath.Join(homeDir, ".wallpaper") wallpaperFile := filepath.Join(homeDir, ".wallpaper")
if err := os.WriteFile(wallpaperFile, []byte(wallpaperPath), 0644); err != nil { if err := os.WriteFile(wallpaperFile, []byte(resizedPath), 0644); err != nil {
fmt.Fprintf(os.Stderr, "Error saving wallpaper path: %v\n", err) fmt.Fprintf(os.Stderr, "Error saving wallpaper path: %v\n", err)
} }
// Change wallpaper using hyprctl monitors, monitorErr := activeMonitors()
cmd := exec.Command("hyprctl", "hyprpaper", "reload", ","+wallpaperPath) if monitorErr != nil {
fmt.Fprintf(os.Stderr, "Error getting monitors: %v\n", monitorErr)
}
cmd := exec.Command("hyprctl", "hyprpaper", "preload", resizedPath)
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Error changing wallpaper: %v\n", err) fmt.Fprintf(os.Stderr, "Error preloading wallpaper: %v\n", err)
}
if monitorErr != nil || len(monitors) == 0 {
cmd = exec.Command("hyprctl", "hyprpaper", "wallpaper", ","+resizedPath)
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Error applying wallpaper: %v\n", err)
}
} else {
for _, m := range monitors {
cmd = exec.Command("hyprctl", "hyprpaper", "wallpaper", fmt.Sprintf("%s,%s", m.Name, resizedPath))
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Error applying wallpaper for monitor %s: %v\n", m.Name, err)
}
}
}
cmd = exec.Command("hyprctl", "hyprpaper", "reload")
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Error reloading hyprpaper: %v\n", err)
} }
// Send notification with wallpaper as icon // Send notification with wallpaper as icon
filename := filepath.Base(wallpaperPath) filename := filepath.Base(resizedPath)
message := fmt.Sprintf("Wallpaper changed to %s", filename) message := fmt.Sprintf("Wallpaper changed to %s", filename)
if topic != "" { if topic != "" {
message += fmt.Sprintf(" (%s)", topic) message += fmt.Sprintf(" (%s)", topic)
} }
notifyWithIcon(message, "normal", wallpaperPath) notifyWithIcon(message, "normal", resizedPath)
} }
func notify(message, urgency string) { func notify(message, urgency string) {

2
go.mod
View File

@@ -1,3 +1,5 @@
module gitea.suda.codes/sudacode/change-wallpaper module gitea.suda.codes/sudacode/change-wallpaper
go 1.24.2 go 1.24.2
require golang.org/x/image v0.32.0 // indirect

2
go.sum Normal file
View File

@@ -0,0 +1,2 @@
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=
golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc=