2022-09-14 11:30:22 +00:00
|
|
|
|
;;; wallpaper.el --- Change desktop background from Emacs -*- lexical-binding: t; -*-
|
2022-09-13 14:57:01 +00:00
|
|
|
|
|
|
|
|
|
;; Copyright (C) 2022 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
|
|
;; Author: Stefan Kangas <stefankangas@gmail.com>
|
|
|
|
|
;; Keywords: images
|
|
|
|
|
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
|
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
2022-09-14 09:10:10 +00:00
|
|
|
|
;; This library provides the command `wallpaper-set', which sets the
|
|
|
|
|
;; desktop background.
|
2022-09-13 14:57:01 +00:00
|
|
|
|
;;
|
2022-09-14 09:10:10 +00:00
|
|
|
|
;; On GNU/Linux and other Unix-like systems, it uses an external
|
|
|
|
|
;; command to set the desktop background.
|
|
|
|
|
;;
|
|
|
|
|
;; On Haiku, it uses the `haiku-set-wallpaper' function, which does
|
|
|
|
|
;; not rely on any external commands.
|
|
|
|
|
;;
|
|
|
|
|
;; Finding an external command to use is obviously a bit tricky to get
|
|
|
|
|
;; right, as there is no lack of platforms, window managers, desktop
|
|
|
|
|
;; environments and tools. However, it should be detected
|
|
|
|
|
;; automatically in most cases. If it doesn't work in your
|
2022-09-14 10:12:46 +00:00
|
|
|
|
;; environment, customize the user options `wallpaper-command' and
|
|
|
|
|
;; `wallpaper-command-args'.
|
2022-09-13 14:57:01 +00:00
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
2022-09-13 16:28:14 +00:00
|
|
|
|
(eval-when-compile (require 'subr-x))
|
2022-09-14 08:26:07 +00:00
|
|
|
|
(require 'xdg)
|
2022-09-13 16:28:14 +00:00
|
|
|
|
|
2022-09-14 10:12:46 +00:00
|
|
|
|
|
|
|
|
|
;;; Finding the wallpaper command
|
|
|
|
|
|
|
|
|
|
(defvar wallpaper--default-commands
|
2022-09-14 11:22:22 +00:00
|
|
|
|
;; When updating this, also update the custom :type for `wallpaper-command'.
|
2022-09-13 14:57:01 +00:00
|
|
|
|
'(
|
|
|
|
|
;; Sway (Wayland)
|
|
|
|
|
("swaybg" "-o" "*" "-i" "%f" "-m" "fill")
|
2022-09-14 02:44:12 +00:00
|
|
|
|
;; Wayland General
|
2022-09-14 16:12:39 +00:00
|
|
|
|
("wbg" "%f")
|
2022-09-13 14:57:01 +00:00
|
|
|
|
;; Gnome
|
|
|
|
|
("gsettings" "set" "org.gnome.desktop.background" "picture-uri" "file://%f")
|
2022-09-14 08:29:16 +00:00
|
|
|
|
;; KDE Plasma
|
|
|
|
|
("plasma-apply-wallpaperimage" "%f")
|
2022-09-13 14:57:01 +00:00
|
|
|
|
;; Other / General X
|
|
|
|
|
("gm" "display" "-size" "%wx%h" "-window" "root" "%f")
|
|
|
|
|
("display" "-resize" "%wx%h" "-window" "root" "%f")
|
|
|
|
|
("feh" "--bg-max" "%f")
|
2022-09-14 22:53:00 +00:00
|
|
|
|
("fbsetbg" "-a" "%f")
|
2022-09-14 08:41:07 +00:00
|
|
|
|
("xwallpaper" "--zoom" "%f")
|
2022-09-14 16:17:42 +00:00
|
|
|
|
("hsetroot" "-full" "%f")
|
2022-09-13 14:57:01 +00:00
|
|
|
|
("xloadimage" "-onroot" "-fullscreen" "%f")
|
|
|
|
|
("xsetbg" " %f")
|
|
|
|
|
)
|
2022-09-14 11:30:22 +00:00
|
|
|
|
"List of executables and options used for setting the wallpaper.
|
2022-09-14 10:12:46 +00:00
|
|
|
|
This is used by `wallpaper--find-command' to automatically set
|
|
|
|
|
`wallpaper-command', and by `wallpaper--find-command-args' to set
|
|
|
|
|
`wallpaper-command-args'. The commands will be tested in the
|
|
|
|
|
order in which they appear.
|
2022-09-13 14:57:01 +00:00
|
|
|
|
|
|
|
|
|
Every item in the list has the following form:
|
|
|
|
|
|
|
|
|
|
(COMMAND ARG1 .. ARGN)
|
|
|
|
|
|
|
|
|
|
COMMAND is the name of the executable (a string) and ARG1 .. ARGN
|
|
|
|
|
is its command line arguments (also strings).
|
|
|
|
|
|
2022-09-14 10:12:46 +00:00
|
|
|
|
In each of the command line arguments, \"%f\", \"%h\" and \"%w\"
|
|
|
|
|
will be replaced as described in `wallpaper-command-args'.")
|
2022-09-13 14:57:01 +00:00
|
|
|
|
|
|
|
|
|
(cl-defmethod wallpaper--check-command ((_type (eql 'gsettings)))
|
2022-09-14 08:26:07 +00:00
|
|
|
|
(member "GNOME" (xdg-current-desktop)))
|
2022-09-13 14:57:01 +00:00
|
|
|
|
|
2022-09-14 08:29:16 +00:00
|
|
|
|
(cl-defmethod wallpaper--check-command ((_type (eql 'plasma-apply-wallpaperimage)))
|
|
|
|
|
(member "KDE" (xdg-current-desktop)))
|
|
|
|
|
|
2022-09-13 14:57:01 +00:00
|
|
|
|
(cl-defmethod wallpaper--check-command ((_type (eql 'swaybg)))
|
|
|
|
|
(and (getenv "WAYLAND_DISPLAY")
|
|
|
|
|
(getenv "SWAYSOCK")))
|
|
|
|
|
|
2022-09-14 02:44:12 +00:00
|
|
|
|
(cl-defmethod wallpaper--check-command ((_type (eql 'wbg)))
|
|
|
|
|
(getenv "WAYLAND_DISPLAY"))
|
|
|
|
|
|
2022-09-13 14:57:01 +00:00
|
|
|
|
(cl-defmethod wallpaper--check-command (_type)
|
|
|
|
|
t)
|
|
|
|
|
|
|
|
|
|
(defun wallpaper--find-command ()
|
2022-09-14 10:12:46 +00:00
|
|
|
|
"Return a valid command to set the wallpaper in this environment."
|
2022-09-13 14:57:01 +00:00
|
|
|
|
(catch 'found
|
2022-09-14 10:12:46 +00:00
|
|
|
|
(dolist (cmd wallpaper--default-commands)
|
2022-09-13 14:57:01 +00:00
|
|
|
|
(if (and (wallpaper--check-command (intern (car cmd)))
|
|
|
|
|
(executable-find (car cmd)))
|
2022-09-14 10:12:46 +00:00
|
|
|
|
(throw 'found (car cmd))))))
|
|
|
|
|
|
|
|
|
|
(defvar wallpaper-command) ; silence byte-compiler
|
|
|
|
|
(defun wallpaper--find-command-arguments ()
|
|
|
|
|
"Return command line arguments matching `wallpaper-command'."
|
|
|
|
|
(cdr (assoc wallpaper-command wallpaper--default-commands)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Customizable variables
|
|
|
|
|
|
|
|
|
|
(defvar wallpaper-command-args) ; silence byte-compiler
|
|
|
|
|
(defun wallpaper--set-wallpaper-command (sym val)
|
2022-09-14 11:30:22 +00:00
|
|
|
|
"Set `wallpaper-command', and update `wallpaper-command-args'.
|
|
|
|
|
Used to set `wallpaper-command'."
|
|
|
|
|
;; Note: `wallpaper-command' is used by `wallpaper--find-command-arguments'.
|
2022-09-14 10:12:46 +00:00
|
|
|
|
(prog1 (set-default sym val)
|
|
|
|
|
(set-default 'wallpaper-command-args
|
|
|
|
|
(wallpaper--find-command-arguments))))
|
|
|
|
|
|
|
|
|
|
(defcustom wallpaper-command (wallpaper--find-command)
|
|
|
|
|
"Executable used for setting the wallpaper.
|
|
|
|
|
A suitable command for your environment should be detected
|
|
|
|
|
automatically, so there is usually no need to customize this.
|
2022-09-14 11:22:22 +00:00
|
|
|
|
|
|
|
|
|
If you set this to any supported command using customize or
|
|
|
|
|
`setopt', the user option `wallpaper-command-args' is
|
|
|
|
|
automatically updated to match. If you need to change this to an
|
|
|
|
|
unsupported command, you will want to manually customize
|
|
|
|
|
`wallpaper-command-args' to match.
|
2022-09-14 10:12:46 +00:00
|
|
|
|
|
|
|
|
|
Note: If you find that you need to use a command in your
|
|
|
|
|
environment that is not automatically detected, we would love to
|
|
|
|
|
hear about it! Please send an email to bug-gnu-emacs@gnu.org and
|
|
|
|
|
tell us the command (and all options) that worked for you. You
|
2022-09-14 11:30:22 +00:00
|
|
|
|
can also use \\[report-emacs-bug].
|
|
|
|
|
|
|
|
|
|
The value of this variable is ignored on Haiku systems, where a
|
|
|
|
|
native API will be used instead (see `haiku-set-wallpaper')."
|
2022-09-14 11:22:22 +00:00
|
|
|
|
:type
|
|
|
|
|
'(choice
|
|
|
|
|
(radio
|
|
|
|
|
(const :tag "gsettings (GNOME)" "gsettings")
|
|
|
|
|
(const :tag "plasma-apply-wallpaperimage (KDE Plasma)" "plasma-apply-wallpaperimage")
|
|
|
|
|
(const :tag "swaybg (Wayland/Sway)" "swaybg")
|
|
|
|
|
(const :tag "wbg (Wayland)" "wbg")
|
|
|
|
|
(const :tag "gm (X Window System)" "gm")
|
|
|
|
|
(const :tag "display (X Window System)" "display")
|
|
|
|
|
(const :tag "feh (X Window System)" "feh")
|
2022-09-14 22:53:00 +00:00
|
|
|
|
(const :tag "fbsetbg (X Window System)" "fbsetbg")
|
2022-09-14 11:22:22 +00:00
|
|
|
|
(const :tag "xwallpaper (X Window System)" "xwallpaper")
|
2022-09-14 16:17:42 +00:00
|
|
|
|
(const :tag "hsetroot (X Window System)" "hsetroot")
|
2022-09-14 11:22:22 +00:00
|
|
|
|
(const :tag "xloadimage (X Window System)" "xloadimage")
|
|
|
|
|
(const :tag "xsetbg (X Window System)" "xsetbg"))
|
|
|
|
|
(const :tag "Other (specify)" string))
|
2022-09-14 10:12:46 +00:00
|
|
|
|
:set #'wallpaper--set-wallpaper-command
|
|
|
|
|
:group 'image
|
|
|
|
|
:version "29.1")
|
|
|
|
|
|
|
|
|
|
(defcustom wallpaper-command-args (wallpaper--find-command-arguments)
|
|
|
|
|
"Command line arguments for `wallpaper-command'.
|
|
|
|
|
A suitable command for your environment should be detected
|
|
|
|
|
automatically, so there is usually no need to customize this.
|
|
|
|
|
However, if you do need to change this, you might also want to
|
|
|
|
|
customize `wallpaper-command' to match.
|
|
|
|
|
|
|
|
|
|
In each of the command line arguments, \"%f\" will be replaced
|
|
|
|
|
with the full file name, \"%h\" with the height of the selected
|
|
|
|
|
frame's display (as returned by `display-pixel-height'), and
|
|
|
|
|
\"%w\" with the width of the selected frame's display (as
|
2022-09-14 11:30:22 +00:00
|
|
|
|
returned by `display-pixel-width').
|
|
|
|
|
|
|
|
|
|
If `wallpaper-set' is run from a TTY frame, it will prompt for a
|
|
|
|
|
height and width for \"%h\" and \"%w\" instead.
|
|
|
|
|
|
|
|
|
|
The value of this variable is ignored on Haiku systems, where a
|
|
|
|
|
native API will be used instead (see `haiku-set-wallpaper')."
|
2022-09-14 10:12:46 +00:00
|
|
|
|
:type '(repeat string)
|
|
|
|
|
:group 'image
|
|
|
|
|
:version "29.1")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Utility functions
|
|
|
|
|
|
|
|
|
|
(defvar wallpaper-debug nil
|
|
|
|
|
"If non-nil, display debug messages.")
|
|
|
|
|
|
|
|
|
|
(defun wallpaper-debug (&rest args)
|
|
|
|
|
(when wallpaper-debug
|
|
|
|
|
(apply #'message
|
|
|
|
|
(concat "wallpaper-debug: " (car args))
|
|
|
|
|
(cdr args))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; wallpaper-set
|
2022-09-13 14:57:01 +00:00
|
|
|
|
|
2022-09-14 08:52:39 +00:00
|
|
|
|
(defvar wallpaper-default-width 1080
|
|
|
|
|
"Default width used by `wallpaper-set'.
|
|
|
|
|
This is only used when it can't be detected automatically.
|
|
|
|
|
See also `wallpaper-default-height'.")
|
|
|
|
|
|
|
|
|
|
(defvar wallpaper-default-height 1920
|
|
|
|
|
"Default height used by `wallpaper-set'.
|
|
|
|
|
This is only used when it can't be detected automatically.
|
|
|
|
|
See also `wallpaper-default-width'.")
|
|
|
|
|
|
|
|
|
|
(defun wallpaper--get-height-or-width (desc fun default)
|
|
|
|
|
(if (display-graphic-p)
|
|
|
|
|
(funcall fun)
|
|
|
|
|
(read-number (format "Wallpaper %s in pixels: " desc) default)))
|
|
|
|
|
|
2022-09-14 10:12:46 +00:00
|
|
|
|
(declare-function haiku-set-wallpaper "term/haiku-win.el")
|
|
|
|
|
|
2022-09-13 14:57:01 +00:00
|
|
|
|
(defun wallpaper-set (file)
|
2022-09-14 09:10:10 +00:00
|
|
|
|
"Set the desktop background to FILE in a graphical environment.
|
|
|
|
|
|
|
|
|
|
On GNU/Linux and other Unix-like systems, this relies on an
|
2022-09-14 11:30:22 +00:00
|
|
|
|
external command. Which command to use is automatically detected
|
|
|
|
|
in most cases, but can be manually customized with the user
|
|
|
|
|
options `wallpaper-command' and `wallpaper-command-args'.
|
2022-09-14 09:10:10 +00:00
|
|
|
|
|
|
|
|
|
On Haiku, no external command is needed, so the value of
|
|
|
|
|
`wallpaper-commands' is ignored."
|
2022-09-13 14:57:01 +00:00
|
|
|
|
(interactive (list (and
|
|
|
|
|
(display-graphic-p)
|
|
|
|
|
(read-file-name "Set desktop background to: "
|
|
|
|
|
default-directory nil t nil
|
|
|
|
|
(lambda (fn)
|
|
|
|
|
(or (file-directory-p fn)
|
|
|
|
|
(string-match (image-file-name-regexp) fn)))))))
|
|
|
|
|
(when (file-directory-p file)
|
|
|
|
|
(error "Can't set wallpaper to a directory: %s" file))
|
|
|
|
|
(unless (file-exists-p file)
|
|
|
|
|
(error "No such file: %s" file))
|
|
|
|
|
(unless (file-readable-p file)
|
|
|
|
|
(error "File is not readable: %s" file))
|
2022-09-15 11:51:31 +00:00
|
|
|
|
(cond ((eq system-type 'windows-nt)
|
|
|
|
|
(w32-set-wallpaper file))
|
|
|
|
|
((featurep 'haiku)
|
2022-09-14 08:52:39 +00:00
|
|
|
|
(haiku-set-wallpaper file))
|
|
|
|
|
(t
|
2022-09-14 10:12:46 +00:00
|
|
|
|
(let* ((fmt-spec `((?f . ,(expand-file-name file))
|
2022-09-14 08:52:39 +00:00
|
|
|
|
(?h . ,(wallpaper--get-height-or-width
|
|
|
|
|
"height"
|
|
|
|
|
#'display-pixel-height
|
|
|
|
|
wallpaper-default-height))
|
|
|
|
|
(?w . ,(wallpaper--get-height-or-width
|
|
|
|
|
"width"
|
|
|
|
|
#'display-pixel-width
|
|
|
|
|
wallpaper-default-width))))
|
|
|
|
|
(bufname (format " *wallpaper-%s*" (random)))
|
|
|
|
|
(process
|
2022-09-14 10:12:46 +00:00
|
|
|
|
(and wallpaper-command
|
2022-09-14 08:52:39 +00:00
|
|
|
|
(apply #'start-process "set-wallpaper" bufname
|
2022-09-14 10:12:46 +00:00
|
|
|
|
wallpaper-command
|
2022-09-14 08:52:39 +00:00
|
|
|
|
(mapcar (lambda (arg) (format-spec arg fmt-spec))
|
2022-09-14 10:12:46 +00:00
|
|
|
|
wallpaper-command-args)))))
|
|
|
|
|
(unless wallpaper-command
|
|
|
|
|
(error "Couldn't find a suitable command for setting the wallpaper"))
|
|
|
|
|
(wallpaper-debug "Using command %S %S" wallpaper-command
|
|
|
|
|
wallpaper-command-args)
|
2022-09-14 08:52:39 +00:00
|
|
|
|
(setf (process-sentinel process)
|
|
|
|
|
(lambda (process status)
|
|
|
|
|
(unwind-protect
|
|
|
|
|
(unless (and (eq (process-status process) 'exit)
|
|
|
|
|
(zerop (process-exit-status process)))
|
|
|
|
|
(message "command %S %s: %S" (string-join (process-command process) " ")
|
|
|
|
|
(string-replace "\n" "" status)
|
|
|
|
|
(with-current-buffer (process-buffer process)
|
|
|
|
|
(string-clean-whitespace (buffer-string)))))
|
|
|
|
|
(ignore-errors
|
|
|
|
|
(kill-buffer (process-buffer process))))))
|
|
|
|
|
process))))
|
2022-09-13 14:57:01 +00:00
|
|
|
|
|
|
|
|
|
(provide 'wallpaper)
|
|
|
|
|
|
|
|
|
|
;;; wallpaper.el ends here
|