diff --git a/slidegtk.py b/slidegtk.py
index b3c49b9635f49ab18f998f1654d71dcee0f34463..b10f1c7528b6cbff9ef1100d8c871d650fce15b7 100755
--- a/slidegtk.py
+++ b/slidegtk.py
@@ -1,38 +1,39 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import re
 import os
 import sys
 import time
 import getopt
-import commands
+import subprocess
 
-import pygtk
-pygtk.require('2.0')
+from gi import pygtkcompat
+pygtkcompat.enable()
+pygtkcompat.enable_gtk(version='3.0')
 import gtk
 import gobject
+import glib
 
 class ImageCache(object):
     def __init__(self, base, width, height):
         if not os.path.isdir(base):
             os.makedirs(base)
-	self.__base = base
-	self.width, self.height = width, height
+        self.__base = base
+        self.width, self.height = width, height
         self.__lru = []
 
     def same_size(self, size):
         return self.width == size.width and self.height == size.height
 
     def compute_filename(self, infile, rotation):
-	return os.path.join(self.__base,
+        return os.path.join(self.__base,
                             "%d-%d-%d-%s" % (
                 self.width, self.height,
                 rotation, infile.replace('/', '-')))
 
     def processed_file(self, infile, rotation = 0):
         if rotation == 0:
-            fp = os.popen("identify -format \"%w %h\""
-                          + commands.mkarg(infile))
+            fp = os.popen("identify -format \"%w %h\" '" + infile + "'")
             words = fp.read().split()
             fp.close()
             w = int(words[0])
@@ -40,7 +41,7 @@ class ImageCache(object):
             if w <= self.width and h <= self.height:
                 return infile
 
-	fn = self.compute_filename(infile, rotation)
+        fn = self.compute_filename(infile, rotation)
         try:
             self.__lru.remove(fn)
         except ValueError:
@@ -49,23 +50,23 @@ class ImageCache(object):
         while len(self.__lru) > 30:
             os.remove(self.__lru[0])
             del self.__lru[0]
-	if not os.path.exists(fn):
-	    if rotation == 0:
-		os.system("djpeg %s"
-			  "|pnmscale -xysize %s %s|cjpeg -optimize > %s" % (
-                              commands.mkarg(infile), self.width, self.height,
-                              commands.mkarg(fn)))
-	    else:
-		os.system("jpegtran -rotate %s %s"
-			  "|djpeg"
-			  "|pnmscale -xysize %s %s|cjpeg -optimize > %s" % (
-                              rotation, commands.mkarg(infile),
+        if not os.path.exists(fn):
+            if rotation == 0:
+                os.system("djpeg '%s'"
+                          "|pnmscale -xysize %s %s|cjpeg -optimize > '%s'" % (
+                              infile, self.width, self.height,
+                              fn))
+            else:
+                os.system("jpegtran -rotate %s %s"
+                          "|djpeg"
+                          "|pnmscale -xysize %s %s|cjpeg -optimize > %s" % (
+                              rotation, subprocess.mkarg(infile),
                               self.width, self.height,
-                              commands.mkarg(fn)))
-	return fn
+                              subprocess.mkarg(fn)))
+        return fn
 
     def hint(self, infile, rotation = 0):
-	self.processed_file(infile, rotation)
+        self.processed_file(infile, rotation)
 
     def hint_images(self, images):
         self.all_wanted_images = set()
@@ -79,21 +80,21 @@ class ImageViewer(object):
             self.cancel_timer()
         fn = self.images[self.index]
         self.image.set_from_file(self.cache.processed_file(fn))
-	if fn in self.stopimages:
-	    self.stopimages.discard(fn)
-	elif timer is not None:
+        if fn in self.stopimages:
+            self.stopimages.discard(fn)
+        elif timer is not None:
             self.start_timer()
-	self.cancel_hint_timer()
-	self.hint_timer = gobject.timeout_add(10, self.hint_cache)
+        self.cancel_hint_timer()
+        self.hint_timer = glib.timeout_add(10, self.hint_cache)
 
     def hint_cache(self):
-	self.cancel_hint_timer()
-	if self.index+1 < len(self.images):
-	    self.cache.hint(self.images[self.index+1])
+        self.cancel_hint_timer()
+        if self.index+1 < len(self.images):
+            self.cache.hint(self.images[self.index+1])
 
     def cancel_hint_timer(self):
         if self.hint_timer is not None:
-            gobject.source_remove(self.hint_timer)
+            glib.source_remove(self.hint_timer)
             self.hint_timer = None
 
     def nextimage(self):
@@ -163,7 +164,7 @@ class ImageViewer(object):
             gtk.main_quit()
             return True
         if event.string == "i":
-            print self.images[self.index]
+            print(self.images[self.index])
         if event.keyval == gtk.keysyms.Left:
             self.previmage()
             self.cancel_timer()
@@ -220,11 +221,11 @@ class ImageViewer(object):
                     period = 0.2
         # gtk counts in milliseconds, not seconds.
         period *= 1000
-        self.timer = gobject.timeout_add(int(period), self.nextimage)
+        self.timer = glib.timeout_add(int(period), self.nextimage)
 
     def cancel_timer(self):
         if self.timer is not None:
-            gobject.source_remove(self.timer)
+            glib.source_remove(self.timer)
             self.timer = None
 
     def close_application(self, widget, event, data=None):
@@ -248,16 +249,16 @@ class ImageViewer(object):
 
     def __init__(self, images, stopimages, fullscreen, width, height):
         self.cache = None
-	self.hint_timer = None
+        self.hint_timer = None
         self.speed = None
         self.timer = None
         self.endtime = None
-	self.stopimages = stopimages
+        self.stopimages = stopimages
         self.autorepeat = False
-        w = gtk.Window(gtk.WINDOW_TOPLEVEL)
+        w = gtk.Window(type=gtk.WINDOW_TOPLEVEL)
         w.set_title("slidegtk")
         self.__fullscreen = fullscreen
-        if fullscreen is 1:
+        if fullscreen == 1:
             w.set_size_request(1920, 1200)
         elif fullscreen:
             w.fullscreen()
@@ -266,7 +267,7 @@ class ImageViewer(object):
             w.move(0, 0)
         w.connect("size-allocate", self.size_allocate)
 
-        w.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color())
+        w.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(red=255, green=0, blue=0))
         w.connect("delete_event", self.close_application)
         w.set_events(w.get_events()
                      | gtk.gdk.BUTTON_PRESS_MASK
@@ -327,10 +328,10 @@ def main(argv):
             endtime = time.time() + 60 * int(arg)
         elif opt == "--seconds":
             endtime = time.time() + int(arg)
-	elif opt == "--stop":
-	    stopimages.add(arg)
-	elif opt == "--crt":
-	    width, height = 1024, 768
+        elif opt == "--stop":
+            stopimages.add(arg)
+        elif opt == "--crt":
+            width, height = 1024, 768
         elif opt == "--stdin":
             use_stdin = True
         elif opt == '-g' or opt == '--geometry':