diff --git a/gnome-sudoku/src/lib/game_selector.py b/gnome-sudoku/src/lib/game_selector.py
index d78e8b6..85bebfd 100644
--- a/gnome-sudoku/src/lib/game_selector.py
+++ b/gnome-sudoku/src/lib/game_selector.py
@@ -135,7 +135,8 @@ class NewOrSavedGameSelector (gconf_wrapper.GConfWrapper):
             sdifficulty = sr.difficulty()
             lastPlayedText = _("Last Played %(timeAgo)s") % {'timeAgo': format_friendly_date(g['saved_at'])}
             levelText =  _("%(level)s puzzle")% {'level': sdifficulty.value_string()}
-            durationText = _("Played for %(duration)s") % {'duration': format_time(g['timer.tot_time'],round_at=15,friendly=True)}
+            durationText = _("Played for %(duration)s") % {
+                    'duration': format_time(g['timer.active_time'],round_at=15,friendly=True)}
             desc = "<b><i>%s</i></b>\n<span size='small'><i>%s</i>\n<i>%s.</i></span>"%(
                 levelText,
                 lastPlayedText,
diff --git a/gnome-sudoku/src/lib/saver.py b/gnome-sudoku/src/lib/saver.py
index 8755afe..32bde9a 100644
--- a/gnome-sudoku/src/lib/saver.py
+++ b/gnome-sudoku/src/lib/saver.py
@@ -8,10 +8,26 @@ SAVE_ATTRIBUTES = [('gsd.hints'),
                    ('gsd.impossible_hints'),
                    ('gsd.auto_fills'),
                    ('timer.__absolute_start_time__'),
-                   ('timer.tot_time'),
-                   ('timer.tot_time_complete'),
+                   ('timer.active_time'),
+                   ('timer.total_time'),
                    ]
 
+def validate_saved_attributes (jar):
+    '''Make sure all SAVE_ATTRIBUTES are available and valid.
+    '''
+    for attr in SAVE_ATTRIBUTES:
+        # default to 0, which is reasonable for current SAVE_ATTRIBUTES.
+        if not attr in jar:
+            jar[attr] = 0
+    # special case for timing things
+    if 'timer.tot_time' in jar: # tot_time was renamed to active_time
+        jar['timer.active_time'] = jar['timer.tot_time']
+    if 'timer.tot_time_complete' in jar: # tot_time_complete renamed to total_time
+        jar['timer.total_time'] = jar['timer.tot_time_complete']
+    if not jar['timer.active_time']:
+        # FIXME set to 1 in order to display well at game-selecting page
+        jar['timer.active_time'] = 1
+
 def super_getattr (obj, attr):
     """getattr, following the dots."""
     attrs=attr.split('.')
@@ -44,6 +60,11 @@ def jar_game (ui):
         jar[attr]=super_getattr(ui,attr)
     return jar
 
+def set_value_from_jar (dest, jar):
+    validate_saved_attributes(jar)
+    for attr in SAVE_ATTRIBUTES:
+        super_setattr(dest, attr, jar[attr])
+
 def open_game (ui, jar):
     ui.gsd.load_game(jar['game'])
     # this is a bit easily breakable... we take advantage of the fact
@@ -57,11 +78,7 @@ def open_game (ui, jar):
     for tracker,tracking in jar.get('tracking',{}).items():
         if tracking:
             ui.tracker_ui.select_tracker(tracker)
-    for attr in SAVE_ATTRIBUTES:
-        super_setattr(ui,attr,jar.get(attr,None))
-    for attr in SAVE_ATTRIBUTES:
-        if jar.get(attr,None) == None:
-            super_setattr(ui,attr,0)
+    set_value_from_jar(ui, jar)
     if jar.has_key('notes') and jar['notes']:
         for x,y,top,bot in jar['notes']:
             ui.gsd.__entries__[(x,y)].set_note_text(top,bot)
@@ -213,6 +230,7 @@ class SudokuTracker:
             else:
                 if self.is_valid(jar):
                     jar['saved_at']=os.stat(f)[8]
+                    validate_saved_attributes(jar)
                     games.append(jar)
                 else:
                     print 'Warning: malformed save game',f
@@ -229,4 +247,3 @@ class SudokuTracker:
             return False
 
         return True
-
diff --git a/gnome-sudoku/src/lib/timer.py b/gnome-sudoku/src/lib/timer.py
index de05de9..ee8a2ef 100644
--- a/gnome-sudoku/src/lib/timer.py
+++ b/gnome-sudoku/src/lib/timer.py
@@ -123,61 +123,53 @@ class ActiveTimer (gobject.GObject):
     def __init__ (self, window):
         gobject.GObject.__init__(self)
         self.window = window
-        self.timing_running = False
-        self.__absolute_start_time__ = 0
-        self.tot_time = 0
-        self.tot_time_complete = 0
-        self.window.connect('window-state-event',self.window_state_event_cb)
-        self.window.connect('state-changed',self.window_state_event_cb)
-        self.window.connect('visibility-notify-event',self.window_state_event_cb)
-        self.window.connect('expose-event',self.window_state_event_cb)
-        self.window.connect('no-expose-event',self.window_state_event_cb)
-
-    def window_state_event_cb (self, *args):
-        if self.window.is_active():
-            self.toggle_timing(True)
-        else:
-            self.toggle_timing(False)
-
-    def toggle_timing (self, on):
-        if not self.__absolute_start_time__:
-            return
-
-        if on and not self.timing_running:
-            self.timing_started_at = time.time()
-            self.timing_running = True
+        # whether we have 'start_timing'; affects total_time
+        self.timer_running = False
+        # whether the timer is running/paused; affects active_time
+        self.is_timing = False
+        self.window.connect('focus-in-event',
+                lambda *args: self.resume_timing())
+        self.window.connect('focus-out-event',
+                lambda *args: self.pause_timing())
+
+    def resume_timing (self):
+        if self.timer_running and not self.is_timing:
+            self.is_timing = True
+            self.interval_start = time.time()
             self.emit('timing-started')
 
-        if not on and self.timing_running:
-            end_time = time.time()
-            self.timing_running = False
-            self.tot_time += (end_time - self.timing_started_at)
-            self.tot_time_complete += end_time - self.__absolute_start_time__
+    def pause_timing (self):
+        if self.timer_running and self.is_timing:
+            self.is_timing = False
+            interval_end = time.time()
+            # active_time is composed of intervals between pausing and resuming
+            self.active_time += (interval_end - self.interval_start)
             self.emit('timing-stopped')
 
     def start_timing (self):
-        self.timing_running = False
-        self.__absolute_start_time__ = 0
-        self.tot_time = 0
-        self.tot_time_complete = 0
+        self.timer_running = True
+        self.active_time = 0
+        self.total_time = 0
         self.__absolute_start_time__ = time.time()
-        self.toggle_timing(True)
+        self.resume_timing()
 
     def finish_timing (self):
-        self.toggle_timing(False)
-        if self.tot_time < 1:
-            self.tot_time = 1;
+        self.pause_timing()
+        self.timer_running = False
+        self.total_time = time.time() - self.__absolute_start_time__
+        if self.active_time < 1:
+            self.active_time = 1;
         # dirty hack: never let total time be less than active time
-        if self.tot_time > self.tot_time_complete:
-            self.tot_time_complete = self.tot_time;
+        if self.active_time > self.total_time:
+            self.total_time = self.active_time;
 
     # make sure to call finish_timing before using this function
     def active_time_string (self):
-        return format_time(self.tot_time)
+        return format_time(self.active_time)
 
     # make sure to call finish_timing before using this function
     def total_time_string (self):
-        return format_time(self.tot_time_complete)
+        return format_time(self.total_time)
 
 if gtk.pygtk_version[1]<8: gobject.type_register(ActiveTimer)
 
