diff -u -r1.1 optionwidgets.module
--- modules/optionwidgets/optionwidgets.module	5 Oct 2010 12:08:38 -0000	1.1
+++ modules/optionwidgets/optionwidgets.module	10 Dec 2010 21:32:53 -0000
@@ -373,9 +373,27 @@
 
   $values = array_values($items);
 
-  if ($element['#type'] == 'optionwidgets_onoff' && ($values[0] === 0)) {
-    $keys = array_keys($options);
-    $values = array(array_key_exists(0, $keys) ? $keys[0] : NULL);
+  if ($element['#type'] == 'optionwidgets_onoff') {
+    // Set $values = array(allowed_option_key).
+    // The first item from $keys ("allowed options") always contains the key
+    // for the "unchecked" state, the second item contains the key for the
+    // "checked" state.
+    // We need to deal with the following cases:
+    // 1. Value from posted form:
+    // 1a. unchecked checkbox is reported as $items = array(0 => 0).
+    // 1b. checked checkbox in reported as $items = array(0 => 'option_key_value').
+    // 2. Value from #default_value (e.g. due to #access = FALSE on form element)
+    // 2a. unchecked checkbox is reported as $items = array(0 => FALSE).
+    // 2b. checked checkbox is reported as $items = array(0 => TRUE).
+
+    if ($values[0] === 0 || $values[0] === FALSE) {
+      $keys = array_keys($options);
+      $values = array(count($keys) >= 0 ? $keys[0] : NULL);
+    }
+    else if ($values[0] === TRUE) {
+      $keys = array_keys($options);
+      $values = array(count($keys) >= 1 ? $keys[1] : NULL);
+    }
   }
 
   if (empty($values)) {
