# coding: utf-8
# This file is part of libdesktop
# The MIT License (MIT)
#
# Copyright (c) 2016 Bharadwaj Raju
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import os
import sys
import subprocess as sp
try:
import configparser
except ImportError:
import ConfigParser as configparser
import traceback
import ctypes
from libdesktop import system
from libdesktop import directories
import tempfile
import shutil
import subprocess as sp
from textwrap import dedent
[docs]def get_wallpaper():
'''Get the desktop wallpaper.
Get the current desktop wallpaper.
Returns:
str: The path to the current wallpaper.
'''
desktop_env = system.get_name()
if desktop_env in ['gnome', 'unity', 'cinnamon', 'pantheon', 'mate']:
SCHEMA = 'org.gnome.desktop.background'
KEY = 'picture-uri'
if desktop_env == 'mate':
SCHEMA = 'org.mate.background'
KEY = 'picture-filename'
try:
from gi.repository import Gio
gsettings = Gio.Settings.new(SCHEMA)
return gsettings.get_string(KEY).replace('file://', '')
except ImportError:
try:
return system.get_cmd_out(
['gsettings', 'get', SCHEMA, KEY]).replace('file://', '')
except: # MATE < 1.6
return system.get_cmd_out(
['mateconftool-2', '-t', 'string', '--get',
'/desktop/mate/background/picture_filename']
).replace('file://', '')
elif desktop_env == 'gnome2':
args = ['gconftool-2', '-t', 'string', '--get',
'/desktop/gnome/background/picture_filename']
return system.get_cmd_out(args).replace('file://', '')
elif desktop_env == 'kde':
conf_file = directories.get_config_file(
'plasma-org.kde.plasma.desktop-appletsrc')[0]
with open(conf_file) as f:
contents = f.read()
contents = contents.splitlines()
contents = contents[
contents.index(
'[Containments][8][Wallpaper][org.kde.image][General]') +
1].split(
'=',
1
)
return contents[len(contents) - 1].strip().replace('file://', '')
elif desktop_env == 'xfce4':
# XFCE4's image property is not image-path but last-image (What?)
list_of_properties = system.get_cmd_out(
['xfconf-query', '-R', '-l', '-c', 'xfce4-desktop', '-p',
'/backdrop'])
for i in list_of_properties.split('\n'):
if i.endswith('last-image') and 'workspace' in i:
# The property given is a background property
return system.get_cmd_out(
['xfconf-query', '-c', 'xfce4-desktop', '-p', i])
elif desktop_env == 'razor-qt':
desktop_conf = configparser.ConfigParser()
# Development version
desktop_conf_file = os.path.join(
get_config_dir('razor')[0], 'desktop.conf')
if os.path.isfile(desktop_conf_file):
config_option = r'screens\1\desktops\1\wallpaper'
else:
desktop_conf_file = os.path.join(
os.path.expanduser('~'), '.razor/desktop.conf')
config_option = r'desktops\1\wallpaper'
desktop_conf.read(os.path.join(desktop_conf_file))
try:
if desktop_conf.has_option('razor', config_option):
return desktop_conf.get('razor', config_option)
except:
pass
elif desktop_env in ['fluxbox', 'jwm', 'openbox', 'afterstep', 'i3']:
# feh stores last feh command in '~/.fehbg'
# parse it
with open(os.path.expanduser('~/.fehbg')) as f:
fehbg = f.read()
fehbg = fehbg.split('\n')
for line in fehbg:
if '#!' in line:
fehbg.remove(line)
fehbg = fehbg[0]
for i in fehbg.split(' '):
if not i.startswith("-"):
if not i.startswith('feh'):
if not i in ['', ' ', ' ', '\n']:
return(i.replace("'", ''))
# TODO: way to get wallpaper for desktops which are commented-out below
elif desktop_env == 'icewm':
with open(os.path.expanduser('~/.icewm/preferences')) as f:
for line in f:
if line.startswith('DesktopBackgroundImage'):
return os.path.expanduser(line.strip().split(
'=', 1)[1].strip().replace('"', '').replace("'", ''))
elif desktop_env == 'awesome':
conf_file = os.path.join(
directories.get_config_dir('awesome')[0],
'rc.lua')
with open(conf_file) as f:
for line in f:
if line.startswith('theme_path'):
awesome_theme = line.strip().split('=', 1)
awesome_theme = awesome_theme[
len(awesome_theme) -
1].strip().replace(
'"',
'').replace(
"'",
'')
with open(os.path.expanduser(awesome_theme)) as f:
for line in f:
if line.startswith('theme.wallpaper'):
awesome_wallpaper = line.strip().split('=', 1)
awesome_wallpaper = awesome_wallpaper[
len(awesome_wallpaper) -
1].strip().replace(
'"',
'').replace(
"'",
'')
return os.path.expanduser(awesome_wallpaper)
# elif desktop_env == 'blackbox':
# args = ['bsetbg', '-full', image]
# sp.Popen(args)
#
# elif desktop_env == 'lxde':
# args = 'pcmanfm --set-wallpaper %s --wallpaper-mode=scaled' % image
# sp.Popen(args, shell=True)
#
# elif desktop_env == 'lxqt':
# args = 'pcmanfm-qt --set-wallpaper %s --wallpaper-mode=scaled' % image
# sp.Popen(args, shell=True)
#
# elif desktop_env == 'windowmaker':
# args = 'wmsetbg -s -u %s' % image
# sp.Popen(args, shell=True)
#
# elif desktop_env == 'enlightenment':
# args = 'enlightenment_remote -desktop-bg-add 0 0 0 0 %s' % image
# sp.Popen(args, shell=True)
#
# elif desktop_env == 'awesome':
# with sp.Popen("awesome-client", stdin=sp.PIPE) as awesome_client:
# command = 'local gears = require("gears"); for s = 1, screen.count()
# do gears.wallpaper.maximized("%s", s, true); end;' % image
# awesome_client.communicate(input=bytes(command, 'UTF-8'))
elif desktop_env == 'windows':
WINDOWS_SCRIPT = ('reg query "HKEY_CURRENT_USER\Control'
' Panel\Desktop\Desktop"')
return system.get_cmd_out(WINDOWS_SCRIPT)
elif desktop_env == 'mac':
try:
from appscript import app
app('Finder').desktop_picture.get()
except ImportError:
OSX_SCRIPT = ('tell app "finder" to get posix path'
' of (get desktop picture as alias)')
return system.get_cmd_out(['osascript', OSX_SCRIPT])
[docs]def set_wallpaper(image):
'''Set the desktop wallpaper.
Sets the desktop wallpaper to an image.
Args:
image (str): The path to the image to be set as wallpaper.
'''
desktop_env = system.get_name()
if desktop_env in ['gnome', 'unity', 'cinnamon', 'pantheon', 'mate']:
uri = 'file://%s' % image
SCHEMA = 'org.gnome.desktop.background'
KEY = 'picture-uri'
if desktop_env == 'mate':
uri = image
SCHEMA = 'org.mate.background'
KEY = 'picture-filename'
try:
from gi.repository import Gio
gsettings = Gio.Settings.new(SCHEMA)
gsettings.set_string(KEY, uri)
except ImportError:
try:
gsettings_proc = sp.Popen(
['gsettings', 'set', SCHEMA, KEY, uri])
except: # MATE < 1.6
sp.Popen(['mateconftool-2',
'-t',
'string',
'--set',
'/desktop/mate/background/picture_filename',
'%s' % image],
stdout=sp.PIPE)
finally:
gsettings_proc.communicate()
if gsettings_proc.returncode != 0:
sp.Popen(['mateconftool-2',
'-t',
'string',
'--set',
'/desktop/mate/background/picture_filename',
'%s' % image])
elif desktop_env == 'gnome2':
sp.Popen(
['gconftool-2',
'-t',
'string',
'--set',
'/desktop/gnome/background/picture_filename',
image]
)
elif desktop_env == 'kde':
# This probably only works in Plasma 5+
kde_script = dedent(
'''\
var Desktops = desktops();
for (i=0;i<Desktops.length;i++) {{
d = Desktops[i];
d.wallpaperPlugin = "org.kde.image";
d.currentConfigGroup = Array("Wallpaper",
"org.kde.image",
"General");
d.writeConfig("Image", "file://{}")
}}
''').format(image)
sp.Popen(
['dbus-send',
'--session',
'--dest=org.kde.plasmashell',
'--type=method_call',
'/PlasmaShell',
'org.kde.PlasmaShell.evaluateScript',
'string:{}'.format(kde_script)]
)
elif desktop_env in ['kde3', 'trinity']:
args = 'dcop kdesktop KBackgroundIface setWallpaper 0 "%s" 6' % image
sp.Popen(args, shell=True)
elif desktop_env == 'xfce4':
# XFCE4's image property is not image-path but last-image (What?)
list_of_properties = system.get_cmd_out(
['xfconf-query',
'-R',
'-l',
'-c',
'xfce4-desktop',
'-p',
'/backdrop']
)
for i in list_of_properties.split('\n'):
if i.endswith('last-image'):
# The property given is a background property
sp.Popen(
['xfconf-query -c xfce4-desktop -p %s -s "%s"' %
(i, image)],
shell=True)
sp.Popen(['xfdesktop --reload'], shell=True)
elif desktop_env == 'razor-qt':
desktop_conf = configparser.ConfigParser()
# Development version
desktop_conf_file = os.path.join(
get_config_dir('razor')[0], 'desktop.conf')
if os.path.isfile(desktop_conf_file):
config_option = r'screens\1\desktops\1\wallpaper'
else:
desktop_conf_file = os.path.join(
os.path.expanduser('~'), '.razor/desktop.conf')
config_option = r'desktops\1\wallpaper'
desktop_conf.read(os.path.join(desktop_conf_file))
try:
if desktop_conf.has_option('razor', config_option):
desktop_conf.set('razor', config_option, image)
with codecs.open(desktop_conf_file, 'w', encoding='utf-8', errors='replace') as f:
desktop_conf.write(f)
except:
pass
elif desktop_env in ['fluxbox', 'jwm', 'openbox', 'afterstep', 'i3']:
try:
args = ['feh', '--bg-scale', image]
sp.Popen(args)
except:
sys.stderr.write('Error: Failed to set wallpaper with feh!')
sys.stderr.write('Please make sre that You have feh installed.')
elif desktop_env == 'icewm':
args = ['icewmbg', image]
sp.Popen(args)
elif desktop_env == 'blackbox':
args = ['bsetbg', '-full', image]
sp.Popen(args)
elif desktop_env == 'lxde':
args = 'pcmanfm --set-wallpaper %s --wallpaper-mode=scaled' % image
sp.Popen(args, shell=True)
elif desktop_env == 'lxqt':
args = 'pcmanfm-qt --set-wallpaper %s --wallpaper-mode=scaled' % image
sp.Popen(args, shell=True)
elif desktop_env == 'windowmaker':
args = 'wmsetbg -s -u %s' % image
sp.Popen(args, shell=True)
elif desktop_env == 'enlightenment':
args = 'enlightenment_remote -desktop-bg-add 0 0 0 0 %s' % image
sp.Popen(args, shell=True)
elif desktop_env == 'awesome':
with sp.Popen("awesome-client", stdin=sp.PIPE) as awesome_client:
command = ('local gears = require("gears"); for s = 1,'
' screen.count() do gears.wallpaper.maximized'
'("%s", s, true); end;') % image
awesome_client.communicate(input=bytes(command, 'UTF-8'))
elif desktop_env == 'windows':
WINDOWS_SCRIPT = dedent('''
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" \
/v Wallpaper /t REG_SZ /d %s /f
rundll32.exe user32.dll,UpdatePerUserSystemParameters
''') % image
windows_script_file = os.path.join(
tempfile.gettempdir(), 'wallscript.bat')
with open(windows_script_file, 'w') as f:
f.write(WINDOWS_SCRIPT)
sp.Popen([windows_script_file], shell=True)
# Sometimes the method above works
# and sometimes the one below
SPI_SETDESKWALLPAPER = 20
ctypes.windll.user32.SystemParametersInfoA(
SPI_SETDESKWALLPAPER, 0, image, 0)
elif desktop_env == 'mac':
try:
from appscript import app, mactypes
app('Finder').desktop_picture.set(mactypes.File(image))
except ImportError:
OSX_SCRIPT = dedent(
'''tell application "System Events"
set desktopCount to count of desktops
repeat with desktopNumber from 1 to desktopCount
tell desktop desktopNumber
set picture to POSIX file "%s"
end tell
end repeat
end tell''') % image
sp.Popen(['osascript', OSX_SCRIPT])
else:
try:
sp.Popen(['feh', '--bg-scale', image])
# feh is nearly a catch-all for Linux WMs
except:
pass