Skip to content

Instantly share code, notes, and snippets.

@jaspervdj
Created January 19, 2012 11:37
Show Gist options
  • Save jaspervdj/1639530 to your computer and use it in GitHub Desktop.
Save jaspervdj/1639530 to your computer and use it in GitHub Desktop.
Setup dual-screen and create a multi-monitor wallpaper using xrandr en RMagick
#!/usr/bin/ruby
# This script reads your monitor settings using the `xrandr` tool. It selects a
# random wallpaper for each monitor from a specified directory. A large image is
# created to fit all monitors, which can then be set using any tool.
require 'RMagick'
class Screen
attr_reader :name, :width, :height, :offset_x, :offset_y
def initialize(name, width, height, offset_x, offset_y)
@name = name
@width = width
@height = height
@offset_x = offset_x
@offset_y = offset_y
end
end
class Plane
attr_reader :width, :height, :screens
def initialize()
@width = 0
@height = 0
@screens = []
end
def add_screen(screen)
@width = [@width, screen.offset_x + screen.width].max
@height = [@height, screen.offset_y+ screen.height].max
screens << screen
end
def print()
puts "Plane #{width}x#{height}"
screens.each do |s|
puts " Screen #{s.name}: " +
"#{s.width}x#{s.height} at #{s.offset_x},#{s.offset_y}"
end
end
end
def plane_from_xrandr()
plane = Plane.new()
`xrandr`.lines.each do |line|
if line =~ /^(.+) connected (\d+)x(\d+)\+(\d+)\+(\d+)/ then
screen = Screen.new($1, $2.to_i, $3.to_i, $4.to_i, $5.to_i)
plane.add_screen(screen)
end
end
return plane
end
def random_files(dir, n)
files = Dir.entries(dir).collect { |f| File.join(dir, f) }.select do |f|
File.file? f
end
files.shuffle.take(n)
end
def dual_screen()
plane = plane_from_xrandr()
plane.print()
if plane.screens.size == 2 then
primary = plane.screens.find { |s| s.name =~ /LVDS/ }.name
secondary = plane.screens.find { |s| s.name =~ /VGA/ }.name
`xrandr --output #{primary} --auto --primary`
`xrandr --output #{secondary} --auto --right-of #{primary}`
end
end
def make_wallpaper(wallpaper_dir, output_file)
plane = plane_from_xrandr()
plane.print()
wallpapers = random_files(wallpaper_dir, plane.screens.size)
image = Magick::Image.new(plane.width, plane.height)
plane.screens.each_with_index do |screen, i|
puts "Selected wallpaper #{wallpapers[i]} for screen #{i}"
wallpaper = Magick::Image.read(wallpapers[i]).first
wallpaper = wallpaper.resize_to_fill(screen.width, screen.height)
image = image.composite(wallpaper, screen.offset_x, screen.offset_y,
Magick::CopyCompositeOp)
end
puts "Writing to #{output_file}..."
image.write(output_file)
end
if ARGV.size >= 2 then
make_wallpaper(ARGV[0], ARGV[1])
elsif ARGV.size == 0 then
dual_screen()
else
puts "Usage:"
puts "#{$0} <wallpaper dir> <output image> Generate a wallpaper"
puts "#{$0} Default dual-screen setup"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment