diff --git a/modules/block/block.admin.inc b/modules/block/block.admin.inc
index 181f941ed7d0609787e4bb2fdd4931cffbd8a05d..5902c20b34934ff2b131fac13136805593280fd4 100644
--- a/modules/block/block.admin.inc
+++ b/modules/block/block.admin.inc
@@ -291,6 +291,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
   );
 
   $theme_default = variable_get('theme_default', 'bartik');
+  $admin_theme = variable_get('admin_theme');
   foreach (list_themes() as $key => $theme) {
     // Only display enabled themes
     if ($theme->status) {
@@ -300,9 +301,18 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
         ':theme' => $key,
       ))->fetchField();
 
+      // Use a meaningful title for the main site theme and administrative
+      // theme.
+      $theme_title = $theme->info['name'];
+      if ($key == $theme_default) {
+        $theme_title = t('!theme (default theme)', array('!theme' => $theme_title));
+      }
+      elseif ($admin_theme && $key == $admin_theme) {
+        $theme_title = t('!theme (administration theme)', array('!theme' => $theme_title));
+      }
       $form['regions'][$key] = array(
         '#type' => 'select',
-        '#title' => $theme->info['name'],
+        '#title' => $theme_title,
         '#default_value' => !empty($region) && $region != -1 ? $region : NULL,
         '#empty_value' => BLOCK_REGION_NONE,
         '#options' => system_region_list($key, REGIONS_VISIBLE),
diff --git a/modules/block/block.api.php b/modules/block/block.api.php
index e8a58974253c75e2d2b743714e5f93ec3e9b3ee1..9cc2f602e855ceb4f06fc31f89e3c9acd98307d9 100644
--- a/modules/block/block.api.php
+++ b/modules/block/block.api.php
@@ -57,6 +57,12 @@
  *     - DRUPAL_CACHE_GLOBAL: The block is the same for every user on every
  *       page where it is visible.
  *     - DRUPAL_NO_CACHE: The block should not get cached.
+ *   - 'properties': (optional) Array of additional metadata to add to the
+ *     block. Common properties include:
+ *     - 'administrative': Boolean which categorizes this block as usable in
+ *       an administrative context. This might include blocks which help an
+ *       administrator approve/deny comments, or view recently created
+ *       user accounts.
  *   - 'weight': (optional) Initial value for the ordering weight of this block.
  *     Most modules do not provide an initial value, and any value provided can
  *     be modified by a user on the block configuration screen.
diff --git a/modules/blog/blog.module b/modules/blog/blog.module
index c9360db3e736164ec51091ebc5574c96385a0f61..d99d6860ecedc761825270297834d025e9949945 100644
--- a/modules/blog/blog.module
+++ b/modules/blog/blog.module
@@ -190,6 +190,7 @@ function _blog_post_exists($account) {
  */
 function blog_block_info() {
   $block['recent']['info'] = t('Recent blog posts');
+  $block['recent']['properties']['administrative'] = TRUE;
   return $block;
 }
 
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 4ebe1293d86a8010589bb883b6eb39a348cef97a..03c274c83fb6dd73a9e31d4e4e89f003849d4f0b 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -402,6 +402,7 @@ function comment_permission() {
  */
 function comment_block_info() {
   $blocks['recent']['info'] = t('Recent comments');
+  $blocks['recent']['properties']['administrative'] = TRUE;
 
   return $blocks;
 }
diff --git a/modules/dashboard/dashboard.css b/modules/dashboard/dashboard.css
index b40eaba00efd15889a38db56bf55ff2fdc411120..2134951bfcb66fbdde63b6a56911d00421a76a35 100644
--- a/modules/dashboard/dashboard.css
+++ b/modules/dashboard/dashboard.css
@@ -37,6 +37,10 @@
   -webkit-border-radius: 4px;
 }
 
+#dashboard .dashboard-add-other-blocks {
+  margin: 10px 0 0 0;
+}
+
 #dashboard .ui-sortable {
   border: 2px dashed #ccc;
   padding: 10px;
@@ -66,7 +70,6 @@
   background-color: #E0E0D8;
   border: #ccc 1px solid;
   padding: 10px;
-  min-height: 90px;
 }
 
 #dashboard #disabled-blocks {
diff --git a/modules/dashboard/dashboard.module b/modules/dashboard/dashboard.module
index b1e66e531a5d4caad091954778002bfc78487413..1917c873d058d08ee20ca588ab57b4d4c1bb6320 100644
--- a/modules/dashboard/dashboard.module
+++ b/modules/dashboard/dashboard.module
@@ -9,7 +9,7 @@ function dashboard_help($path, $arg) {
     case 'admin/help#dashboard':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The Dashboard module provides a <a href="@dashboard">Dashboard page</a> in the administrative interface for organizing administrative tasks and navigation, and tracking information within your site. The Dashboard page contains blocks, which you can add to and arrange using the drag and drop interface that appears when you click on the <em>Customize dashboard</em> link. For more information, see the online handbook entry for <a href="@handbook">Dashboard module</a>.', array('@handbook' => 'http://drupal.org/handbook/modules/dashboard', '@dashboard' => url('admin/dashboard'))) . '</p>';
+      $output .= '<p>' . t('The Dashboard module provides a <a href="@dashboard">Dashboard page</a> in the administrative interface for organizing administrative tasks and navigation, and tracking information within your site. The Dashboard page contains blocks, which you can add to and arrange using the drag-and-drop interface that appears when you click on the <em>Customize dashboard</em> link. Within this interface, blocks that are not primarily used for site administration do not appear by default, but can be added via the <em>Add other blocks</em> link. For more information, see the online handbook entry for <a href="@handbook">Dashboard module</a>.', array('@handbook' => 'http://drupal.org/handbook/modules/dashboard', '@dashboard' => url('admin/dashboard'))) . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('Tracking user activity') . '</dt>';
@@ -22,7 +22,7 @@ function dashboard_help($path, $arg) {
     case 'admin/dashboard/configure':
       // @todo This assumes the current page is being displayed using the same
       //   theme that the dashboard is displayed in.
-      $output = '<p>' . t('Rearrange blocks for display on the <a href="@dashboard-url">dashboard</a>. Disabling a block makes it available on the main <a href="@blocks-url">blocks administration page</a>.', array('@dashboard-url' => url('admin/dashboard'), '@blocks-url' => url("admin/structure/block/list/{$GLOBALS['theme_key']}"))) . '</p>';
+      $output = '<p>' . t('Rearrange blocks for display on the <a href="@dashboard-url">Dashboard page</a>. Blocks placed in the <em>Dashboard (inactive)</em> region are not displayed when viewing the Dashboard page, but are available within its <em>Customize dashboard</em> interface. Removing a block from active dashboard display makes it available on the main <a href="@blocks-url">blocks administration page</a>.', array('@dashboard-url' => url('admin/dashboard'), '@blocks-url' => url("admin/structure/block/list/{$GLOBALS['theme_key']}"))) . '</p>';
       return $output;
   }
 }
@@ -89,6 +89,25 @@ function dashboard_permission() {
   );
 }
 
+/**
+ * Implements hook_block_info_alter().
+ */
+function dashboard_block_info_alter(&$blocks, $theme, $code_blocks) {
+  $admin_theme = variable_get('admin_theme');
+  if (($admin_theme && $theme == $admin_theme) || (!$admin_theme && $theme == variable_get('theme_default', 'bartik'))) {
+    foreach ($blocks as $module => &$module_blocks) {
+      foreach ($module_blocks as $delta => &$block) {
+        // Make administrative blocks that are not already in use elsewhere
+        // available for the dashboard.
+        if (empty($block['status']) && (empty($block['region']) || $block['region'] == BLOCK_REGION_NONE) && !empty($code_blocks[$module][$delta]['properties']['administrative'])) {
+          $block['status'] = 1;
+          $block['region'] = 'dashboard_inactive';
+        }
+      }
+    }
+  }
+}
+
 /**
  * Implements hook_block_list_alter().
  *
@@ -121,6 +140,10 @@ function dashboard_page_build(&$page) {
     // region into it.
     $page['content']['dashboard'] = array('#theme_wrappers' => array('dashboard'));
     foreach (dashboard_regions() as $region) {
+      // Do not show dashboard blocks that are disabled.
+      if ($region == 'dashboard_inactive') {
+        continue;
+      }
       // Insert regions even when they are empty, so that they will be
       // displayed when the dashboard is being configured.
       $page['content']['dashboard'][$region] = !empty($page[$region]) ? $page[$region] : array();
@@ -177,7 +200,15 @@ function dashboard_page_build(&$page) {
  */
 function dashboard_system_info_alter(&$info, $file, $type) {
   if ($type == 'theme') {
-    $info['regions'] += dashboard_region_descriptions();
+    // Add the dashboard regions (the "inactive" region should always appear
+    // last in the list, for usability reasons).
+    $dashboard_regions = dashboard_region_descriptions();
+    if (isset($dashboard_regions['dashboard_inactive'])) {
+      $inactive_region = $dashboard_regions['dashboard_inactive'];
+      unset($dashboard_regions['dashboard_inactive']);
+      $dashboard_regions['dashboard_inactive'] = $inactive_region;
+    }
+    $info['regions'] += $dashboard_regions;
     // Indicate that these regions are intended to be displayed whenever the
     // dashboard is displayed in an overlay. This information is provided for
     // any module that might need to use it, not just the core Overlay module.
@@ -312,12 +343,23 @@ function dashboard_form_block_admin_display_form_alter(&$form, &$form_state, $fo
     $form['block_regions']['#value'] = array_diff_key($form['block_regions']['#value'], $dashboard_regions);
     foreach (element_children($form['blocks']) as $i) {
       $block = &$form['blocks'][$i];
-      if (isset($block['region']['#default_value']) && isset($dashboard_regions[$block['region']['#default_value']])) {
+      if (isset($block['region']['#default_value']) && isset($dashboard_regions[$block['region']['#default_value']]) && $block['region']['#default_value'] != 'dashboard_inactive') {
         $block['#access'] = FALSE;
       }
       elseif (isset($block['region']['#options'])) {
         $block['region']['#options'] = array_diff_key($block['region']['#options'], $dashboard_regions);
       }
+      // Show inactive dashboard blocks as disabled on the main block
+      // administration form, so that they are available to place in other
+      // regions of the theme. Note that when the form is submitted, any such
+      // blocks which still remain disabled will immediately be put back in the
+      // 'dashboard_inactive' region, because dashboard_block_info_alter() is
+      // called when the blocks are rehashed. Fortunately, this is the exact
+      // behavior we want.
+      if ($block['region']['#default_value'] == 'dashboard_inactive') {
+        // @todo These do not wind up in correct alphabetical order.
+        $block['region']['#default_value'] = NULL;
+      }
     }
   }
 }
@@ -370,6 +412,9 @@ function dashboard_form_block_add_block_form_alter(&$form, &$form_state) {
  */
 function template_preprocess_dashboard_admin_display_form(&$variables) {
   template_preprocess_block_admin_display_form($variables);
+  if (isset($variables['block_regions'][BLOCK_REGION_NONE])) {
+    $variables['block_regions'][BLOCK_REGION_NONE] = t('Other blocks');
+  }
 }
 
 /**
@@ -431,8 +476,9 @@ function dashboard_regions() {
  */
 function dashboard_dashboard_regions() {
   return array(
-    'dashboard_main' => 'Dashboard main',
-    'dashboard_sidebar' => 'Dashboard sidebar',
+    'dashboard_main' => 'Dashboard (main)',
+    'dashboard_sidebar' => 'Dashboard (sidebar)',
+    'dashboard_inactive' => 'Dashboard (inactive)',
   );
 }
 
@@ -445,9 +491,9 @@ function dashboard_show_disabled() {
   // Blocks are not necessarily initialized at this point.
   $blocks = _block_rehash();
 
-  // Limit the list to disabled blocks for the current theme.
+  // Limit the list to blocks that are marked as disabled for the dashboard.
   foreach ($blocks as $key => $block) {
-    if ($block['theme'] != $theme_key || (!empty($block['status']) && !empty($block['region']))) {
+    if ($block['theme'] != $theme_key || $block['region'] != 'dashboard_inactive') {
       unset($blocks[$key]);
     }
   }
@@ -496,7 +542,7 @@ function dashboard_update() {
     parse_str($_REQUEST['regions'], $regions);
     foreach ($regions as $region_name => $blocks) {
       if ($region_name == 'disabled_blocks') {
-        $region_name = '';
+        $region_name = 'dashboard_inactive';
       }
       foreach ($blocks as $weight => $block_string) {
         // Parse the query string to determine the block's module and delta.
@@ -507,12 +553,7 @@ function dashboard_update() {
 
         $block->region = $region_name;
         $block->weight = $weight;
-        if (empty($region_name)) {
-          $block->status = 0;
-        }
-        else {
-          $block->status = 1;
-        }
+        $block->status = 1;
 
         db_merge('block')
           ->key(array(
@@ -603,6 +644,8 @@ function theme_dashboard_disabled_blocks($variables) {
   foreach ($blocks as $block) {
     $output .= theme('dashboard_disabled_block', array('block' => $block));
   }
+  $output .= '<div class="clearfix"></div>';
+  $output .= '<p class="dashboard-add-other-blocks">' . l(t('Add other blocks'), 'admin/dashboard/configure') . '</p>';
   $output .= '</div></div></div>';
   return $output;
 }
diff --git a/modules/dashboard/dashboard.test b/modules/dashboard/dashboard.test
index 420a5a3f7eaab884bfa6929535b5c656b334bfd7..89a3932303586ac6874db4eecef2ebda770c4570 100644
--- a/modules/dashboard/dashboard.test
+++ b/modules/dashboard/dashboard.test
@@ -112,4 +112,30 @@ class DashboardBlocksTestCase extends DrupalWebTestCase {
     $this->drupalGet('admin/dashboard');
     $this->assertRaw($custom_block['title'], t('Block still appears on the dashboard.'));
   }
+
+  /**
+   * Test that defining a block with ['properties']['administrative'] = TRUE
+   * adds it as an available block for the dashboard.
+   */
+  function testBlockAvailability() {
+    // Test "Recent comments", which should be available (defined as
+    // "administrative") but not enabled.
+    $this->drupalGet('admin/dashboard');
+    $this->assertNoText(t('Recent comments'), t('"Recent comments" not on dashboard.'));
+    $this->drupalGet('admin/dashboard/drawer');
+    $this->assertText(t('Recent comments'), t('Drawer of disabled blocks includes a block defined as "administrative".'));
+    $this->assertNoText(t('Syndicate'), t('Drawer of disabled blocks excludes a block not defined as "administrative".'));
+    $this->drupalGet('admin/dashboard/configure');
+    $elements = $this->xpath('//select[@id=:id]//option[@selected="selected"]', array(':id' => 'edit-blocks-comment-recent-region'));
+    $this->assertTrue($elements[0]['value'] == 'dashboard_inactive', t('A block defined as "administrative" defaults to dashboard_inactive.'));
+
+    // Now enable the block on the dashboard.
+    $values = array();
+    $values['blocks[comment_recent][region]'] = 'dashboard_main';
+    $this->drupalPost('admin/dashboard/configure', $values, t('Save blocks'));
+    $this->drupalGet('admin/dashboard');
+    $this->assertText(t('Recent comments'), t('"Recent comments" was placed on dashboard.'));
+    $this->drupalGet('admin/dashboard/drawer');
+    $this->assertNoText(t('Recent comments'), t('Drawer of disabled blocks excludes enabled blocks.'));
+  }
 }
diff --git a/modules/forum/forum.module b/modules/forum/forum.module
index d84473bd4b03d206524b2cd207c8bb87d7f37e79..20622a3bef4f50f904b1589b68ccb261aa615804 100644
--- a/modules/forum/forum.module
+++ b/modules/forum/forum.module
@@ -623,10 +623,12 @@ function forum_block_info() {
   $blocks['active'] = array(
     'info' => t('Active forum topics'),
     'cache' => DRUPAL_CACHE_CUSTOM,
+    'properties' => array('administrative' => TRUE),
   );
   $blocks['new'] = array(
     'info' => t('New forum topics'),
     'cache' => DRUPAL_CACHE_CUSTOM,
+    'properties' => array('administrative' => TRUE),
   );
   return $blocks;
 }
diff --git a/modules/node/node.module b/modules/node/node.module
index 956102cee3fb92c13f8a9754b6927d6b3c2d70f7..2097a915a33f27488a5a763988fe9fb096850801 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -2075,6 +2075,7 @@ function node_block_info() {
   $blocks['syndicate']['cache'] = DRUPAL_NO_CACHE;
 
   $blocks['recent']['info'] = t('Recent content');
+  $blocks['recent']['properties']['administrative'] = TRUE;
 
   return $blocks;
 }
diff --git a/modules/poll/poll.module b/modules/poll/poll.module
index 602940ea552e121c37c901ad0f18a53d6ad1b208..e82adfeacad879340475dcc554aa42bf0ff0c709 100644
--- a/modules/poll/poll.module
+++ b/modules/poll/poll.module
@@ -133,6 +133,7 @@ function _poll_menu_access($node, $perm, $inspect_allowvotes) {
  */
 function poll_block_info() {
   $blocks['recent']['info'] = t('Most recent poll');
+  $blocks['recent']['properties']['administrative'] = TRUE;
   return $blocks;
 }
 
diff --git a/modules/search/search.module b/modules/search/search.module
index 65c3a7122687ed21a74f3dced2a2c3313f6f8873..82eb65d37fe2f9ad2384ec7a61665caba4af4392 100644
--- a/modules/search/search.module
+++ b/modules/search/search.module
@@ -143,6 +143,7 @@ function search_block_info() {
   $blocks['form']['info'] = t('Search form');
   // Not worth caching.
   $blocks['form']['cache'] = DRUPAL_NO_CACHE;
+  $blocks['form']['properties']['administrative'] = TRUE;
   return $blocks;
 }
 
diff --git a/modules/user/user.module b/modules/user/user.module
index c0372e6588136f3349704eb9215f09bd505366d9..6c6519b80914669575562ec8d78379965f1679ce 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -1273,10 +1273,13 @@ function user_block_info() {
   $blocks['login']['cache'] = DRUPAL_NO_CACHE;
 
   $blocks['new']['info'] = t('Who\'s new');
+  $blocks['new']['properties']['administrative'] = TRUE;
 
   // Too dynamic to cache.
   $blocks['online']['info'] = t('Who\'s online');
   $blocks['online']['cache'] = DRUPAL_NO_CACHE;
+  $blocks['online']['properties']['administrative'] = TRUE;
+
   return $blocks;
 }