diff --git includes/menu.inc includes/menu.inc
index 0d7a821..4d7cdab 100644
--- includes/menu.inc
+++ includes/menu.inc
@@ -2228,6 +2228,66 @@ function _menu_navigation_links_rebuild($menu) {
 }
 
 /**
+ * Clone an array of menu links.
+ *
+ * @param $links
+ *   An array of menu links to clone.
+ * @param $menu_name
+ *   (optional) The name of a menu that the links will be cloned for. If not
+ *   set, the cloned links will be in the same menu as the original set of
+ *   links that were passed in.
+ * @return
+ *   An array of menu links with the same properties as the passed-in array,
+ *   but with the link identifiers removed so that a new link will be created
+ *   when any of them is passed in to menu_link_save().
+ *
+ * @see menu_link_save()
+ */
+function menu_links_clone($links, $menu_name = NULL) {
+  foreach ($links as &$link) {
+    unset($link['mlid']);
+    if (isset($menu_name)) {
+      $link['menu_name'] = $menu_name;
+    }
+  }
+  return $links;
+}
+
+/**
+ * Returns an array containing all links for a menu.
+ *
+ * @param $menu_name
+ *   The name of the menu whose links should be returned.
+ * @return
+ *   An array of menu links.
+ */
+function menu_load_links($menu_name) {
+  $links = db_query("SELECT * FROM {menu_links} WHERE menu_name = :menu_name", array(':menu_name' => $menu_name))->fetchAll(PDO::FETCH_ASSOC);
+  foreach ($links as &$link) {
+    $link['options'] = unserialize($link['options']);
+  }
+  return $links;
+}
+
+/**
+ * Deletes all links for a menu.
+ *
+ * @param $menu_name
+ *   The name of the menu whose links will be deleted.
+ */
+function menu_delete_links($menu_name) {
+  $links = menu_load_links($menu_name);
+  foreach ($links as $link) {
+    // To speed up the deletion process, we reset some link properties that
+    // would trigger re-parenting logic in _menu_delete_item() and
+    // _menu_update_parental_status().
+    $link['has_children'] = FALSE;
+    $link['plid'] = 0;
+    _menu_delete_item($link);
+  }
+}
+
+/**
  * Delete one or several menu links.
  *
  * @param $mlid
diff --git modules/menu/menu.module modules/menu/menu.module
index 5d0fd21..f91a4b7 100644
--- modules/menu/menu.module
+++ modules/menu/menu.module
@@ -271,21 +271,13 @@ function menu_save($menu) {
  *
  * @see menu_load()
  *
- * _menu_delete_item() will take care of clearing the page cache. Other modules
+ * menu_delete_links() will take care of clearing the page cache. Other modules
  * should take care of their menu-related data by implementing
  * hook_menu_delete().
  */
 function menu_delete($menu) {
   // Delete all links from the menu.
-  $links = db_query("SELECT * FROM {menu_links} WHERE menu_name = :menu_name", array(':menu_name' => $menu['menu_name']));
-  foreach ($links as $link) {
-    // To speed up the deletion process, we reset some link properties that
-    // would trigger re-parenting logic in _menu_delete_item() and
-    // _menu_update_parental_status().
-    $link['has_children'] = FALSE;
-    $link['plid'] = 0;
-    _menu_delete_item($link);
-  }
+  menu_delete_links($menu['menu_name']);
 
   // Delete the custom menu.
   db_delete('menu_custom')
diff --git modules/shortcut/shortcut.admin.inc modules/shortcut/shortcut.admin.inc
new file mode 100644
index 0000000..8efb469
--- /dev/null
+++ modules/shortcut/shortcut.admin.inc
@@ -0,0 +1,394 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Administrative page callbacks for the shortcut module.
+ */
+
+/**
+ * Returns the maximum number of shortcut "slots" available per shortcut set.
+ *
+ * This is used as a limitation in the user interface only.
+ *
+ * @return
+ *   The maximum number of shortcuts allowed to be added to a shortcut set.
+ */
+function shortcut_max_slots() {
+  return variable_get('shortcut_max_slots', 7);
+}
+
+/**
+ * Menu callback; Build the form for switching shortcut sets.
+ *
+ * @param $form
+ *   An associative array containing the structure of the form.
+ * @param $form_state
+ *   An associative array containing the current state of the form.
+ * @param $account
+ *   (optional) The user account whose shortcuts will be switched. Defaults to
+ *   the current logged-in user.
+ * @return
+ *   An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_set_switch_submit()
+ */
+function shortcut_set_switch($form, &$form_state, $account = NULL) {
+  global $user;
+  if (!isset($account)) {
+    $account = $user;
+  }
+
+  // Prepare the list of shortcut sets.
+  $sets = shortcut_sets();
+  $current_set = shortcut_current_displayed_set($account);
+  $default_set = shortcut_default_set($account);
+  $options = array();
+  foreach ($sets as $name => $set) {
+    $options[$name] = check_plain($set['title']);
+  }
+
+  // Only administrators can add shortcut sets.
+  $add_access = user_access('administer shortcuts');
+  if ($add_access) {
+    $options['new'] = t('New set');
+  }
+
+  $form['account'] = array(
+    '#type' => 'value',
+    '#value' => $account,
+  );
+
+  $form['set'] = array(
+    '#type' => 'radios',
+    '#title' => t('Choose a set'),
+    '#options' => $options,
+    '#default_value' => $current_set['set_name'],
+  );
+
+  $form['new'] = array(
+    '#type' => 'textfield',
+    '#description' => t('The new set is created by copying items from the @default set.', array('@default' => $default_set['title'])),
+    '#access' => $add_access,
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit', 
+    '#value' => t('Save configuration'),
+  );
+
+  return $form;
+}
+
+/**
+ * Submit handler for the form that switches shortcut sets.
+ */
+function shortcut_set_switch_submit($form, &$form_state) {
+  global $user;
+  $account = $form_state['values']['account'];
+
+  if ($form_state['values']['set'] == 'new') {
+    // Save a new shortcut set with links copied from the default set.
+    $default_set = shortcut_default_set();
+    $set = array(
+      'title' => $form_state['values']['new'],
+      'links' => menu_links_clone($default_set['links']),
+    );
+    shortcut_set_save($set);
+    $replacements = array(
+      '%user' => $account->name,
+      '%set_name' => $set['title'],
+    );
+    drupal_set_message($account->uid == $user->uid ? t('A new shortcut set called %set_name was created with the default shortcut items. You are now using this set.', $replacements) : t('%user is now using a new shortcut set called %set_name with the default shortcut items.', $replacements));
+    $form_state['redirect'] = 'admin/config/system/shortcut/' . $set['set_name'];
+  }
+  else {
+    // Switch to a different shortcut set.
+    $set = shortcut_set_load($form_state['values']['set']);
+    $replacements = array(
+      '%user' => $account->name,
+      '%set_name' => $set['title'],
+    );
+    drupal_set_message($account->uid == $user->uid ? t('You are now using the %set_name shortcut set.', $replacements) : t('%user is now using the %set_name shortcut set.', $replacements));
+  }
+
+  // Assign the shortcut set to the provided user account.
+  shortcut_set_assign_user($set, $account);
+}
+
+/**
+ * Theme function for the form that switches shortcut sets.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - form: An array representing the form.
+ * @return
+ *   A themed HTML string representing the content of the form.
+ *
+ * @ingroup themeable
+ * @see shortcut_set_switch()
+ */
+function theme_shortcut_set_switch($variables) {
+  $form = $variables['form'];
+  drupal_add_css(drupal_get_path('module', 'shortcut') . '/shortcut.admin.css');
+  drupal_add_js(drupal_get_path('module', 'shortcut') . '/shortcut.admin.js');
+  $form['set']['new']['#title'] = t('New set: !textfield', array('!textfield' => drupal_render($form['new'])));
+  return drupal_render_children($form);
+}
+
+/**
+ * Menu callback; Build the form for customizing shortcut sets.
+ *
+ * @param $form
+ *   An associative array containing the structure of the form.
+ * @param $form_state
+ *   An associative array containing the current state of the form.
+ * @param $shortcut_set
+ *   An array representing the shortcut set which is being edited.
+ * @return
+ *   An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_set_customize_submit()
+ */
+function shortcut_set_customize($form, &$form_state, $shortcut_set) {
+  $form['set'] = array(
+    '#markup' => t('Using set "@set"', array('@set' => $set['name'])),
+    '#prefix' => '<h4 class="shortcuts-set">',
+    '#suffix' => '</h4>',
+    '#weight' => -100,
+  );
+
+  $form['change_set'] = array(
+    '#markup' => l(t('Change set'), 'admin/config/system/shortcut'),
+    '#prefix' => '<div class="shortcuts-change-set">(',
+    '#suffix' => ')</div>',
+    '#weight' => -99,
+    '#access' => user_access('switch shortcut sets'),
+  );
+
+  $form['shortcuts']['#tree'] = TRUE;
+  $form['shortcuts']['enabled'] = $form['shortcuts']['disabled'] = array();
+  foreach ($set['links'] as $link) {
+    $mlid = $link['mlid'];
+    $status = $link['hidden'] ? 'disabled' : 'enabled';
+    $form['shortcuts'][$status][$mlid]['name']['#markup'] = l($shortcut['link_title'], $shortcut['link_path']);
+    $form['shortcuts'][$status][$mlid]['weight'] = array(
+      '#type' => 'weight',
+      '#title' => t('Weight'),
+      '#delta' => 50,
+      '#default_value' => $link['weight'],
+      '#attributes' => array('class' => array('shortcut-weight')),
+    );
+    $form['shortcuts'][$status][$mlid]['status'] = array(
+      '#type' => 'select',
+      '#title' => t('Status'),
+      '#options' => array('disabled' => t('Disabled'), 'enabled' => t('Enabled')),
+      '#default_value' => $status,
+      '#attributes' => array('class' => array('shortcut-status-select')),
+    );
+    
+    $form['shortcuts'][$status][$mlid]['edit']['#markup'] = l(t('edit'), 'admin/config/system/shortcut/' . $set['set_name'] . '/link/' . $mlid);
+    $form['shortcuts'][$status][$mlid]['delete']['#markup'] = l(t('delete'), 'admin/config/system/shortcut/' . $set['set_name'] . '/link/' . $mlid . '/delete');
+  }
+
+  $form['submit'] = array(
+    '#type' => 'submit', 
+    '#value' => t('Save Changes'),
+  );
+
+  return $form;
+}
+
+/**
+ * Submit handler for the shortcut set customization form.
+ */
+function shortcut_set_customize_submit($form, &$form_state) {
+  foreach ($form_state['values']['shortcuts'] as $status => $links) {
+    foreach ($links as $mlid => $data) {
+      $link = menu_link_load($mlid);
+      $link['hidden'] = $status == 'enabled' ? FALSE : TRUE;
+      $link['weight'] = $data['weight'];
+      menu_link_save($link);
+    }
+  }
+
+/*
+TODO:
+  // Knock an enabled one out if we have to.
+  $set = toolbar_set_load(shortcut_max_slots(), TRUE);
+  // Too many, knock one out.
+  while (count($set['shortcuts']) >= TOOLBAR_MAX_SLOTS) {
+    $disable = array_pop($set['shortcuts']);
+    $disable['status'] = 0;
+    toolbar_shortcut_save($disable);
+  }
+  $largest_weight = -50;
+  foreach ($set['shortcuts'] as $shortcut) {
+    $largest_weight = max($shortcut['weight'], $largest_weight);
+  }
+  toolbar_shortcut_save(array(
+    'sid'    => toolbar_current_set(),
+    'weight' => $largest_weight + 1,
+    'path'   => $_GET['link'],
+    'name'   => $_GET['name'],
+    'status' => 1,
+  ));
+  drupal_goto('admin/config/system/shortcuts');
+*/
+
+}
+
+/**
+ * Theme function for the shortcut set customization form.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - form: An array representing the form.
+ * @return
+ *   A themed HTML string representing the content of the form.
+ *
+ * @ingroup themeable
+ * @see shortcut_set_customize()
+ */
+function theme_shortcut_set_customize($variables) {
+  $form = $variables['form'];
+  drupal_add_css(drupal_get_path('module', 'shortcut') . '/shortcut.admin.css');
+  drupal_add_js(drupal_get_path('module', 'shortcut') . '/shortcut.admin.js');
+  $map = array('disabled' => t('Disabled'), 'enabled' => t('Enabled'));
+
+  $rows = array();
+  foreach (array('enabled', 'disabled') as $status) {
+    drupal_add_tabledrag('shortcuts', 'match', 'sibling', 'shortcut-status-select');
+    drupal_add_tabledrag('shortcuts', 'order', 'sibling', 'shortcut-weight');
+    $rows[] = array(
+      'data' => array(array(
+        'colspan' => 5,
+        'data' => '<strong>' . $map[$status] . '</strong>',
+      )),
+      'class' => array('toolbar-status', 'toolbar-status-' . $status),
+    );
+    foreach (element_children($form[$status]) as $key) {
+      $shortcut = &$form[$status][$key];
+      $row = array();
+      $row[] = drupal_render($shortcut['link_title']);
+      $row[] = drupal_render($shortcut['weight']);
+      $row[] = drupal_render($shortcut['status']);
+      $row[] = drupal_render($shortcut['edit']);
+      $row[] = drupal_render($shortcut['delete']);
+      $rows[] = array(
+        'data' => $row,
+        'class' => array('draggable'),
+      );
+    }
+    if ($status == 'enabled') {
+      for ($i = 0; $i < shortcut_max_slots(); $i++) {
+        $rows['empty-' . $i] = array(
+          'data' => array(array(
+            'colspan' => 5,
+            'data' => '<em>' . t('Empty') . '</em>',
+          )),
+          'class' => array('toolbar-slot-empty'),
+        );
+      }
+      $count_shortcuts = count(element_children($form[$status]));
+      if (!empty($count_shortcuts)) {
+        for ($i = 0; $i < min($count_shortcuts, shortcut_max_slots()); $i++) {
+          $rows['empty-' . $i]['class'][] = 'toolbar-slot-hidden';
+        }
+      }
+    }
+  }
+  $header = array(t('Name'), t('Weight'), t('Status'), array('data' => t('Operations'), 'colspan' => 2));
+  return theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'shortcuts')));
+}
+
+
+
+
+
+
+
+
+/**
+ * Menu callback; Build the form for adding or editing a shortcut link.
+ *
+ * @param $form
+ *   An associative array containing the structure of the form.
+ * @param $form_state
+ *   An associative array containing the current state of the form.
+ * @param $shortcut_set
+ *   An array representing the shortcut set that the link is assigned to.
+ * @param $shortcut_link
+ *   (optional) An array representing the link that is being edited. If not
+ *   set, the form will allow a new link to be created.
+ * @return
+ *   An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_link_edit_submit()
+ */
+function shortcut_link_edit($form, &$form_state, $shortcut_set, $shortcut_link = NULL) {
+  // TODO: Copy code here.
+}
+
+/**
+ * Submit handler for the shortcut link editing form.
+ */
+function shortcut_link_edit_submit($form, &$form_state) {
+  // TODO: Copy code here.
+}
+
+/**
+ * Menu callback; Build the form for deleting a shortcut link.
+ *
+ * @param $form
+ *   An associative array containing the structure of the form.
+ * @param $form_state
+ *   An associative array containing the current state of the form.
+ * @param $shortcut_link
+ *   An array representing the link that will be deleted.
+ * @return
+ *   An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_link_delete_submit()
+ */
+function shortcut_link_delete($form, &$form_state, $shortcut_link) {
+  // TODO: Copy code here.
+}
+
+/**
+ * Submit handler for the shortcut link deletion form.
+ */
+function shortcut_link_delete_submit($form, &$form_state) {
+  // TODO: Copy code here.
+}
+
+/**
+ * Menu callback; Creates a new link in the provided shortcut set
+ *
+ * After completion, redirects the user back to where they came from.
+ *
+ * @param $shortcut_set
+ *   Returned from shortcut_set_load().
+ */
+function shortcut_add_link($shortcut_set) {
+  if (isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'shortcut-add-link')) {
+    $link = array(
+      'link_title' => $_GET['name'],
+      'link_path' => $_GET['link'],
+    );
+    // Really we should test for a dupe here.
+    $shortcut_set['links'][] = $link;
+    
+    if (shortcut_set_save($shortcut_set)) {
+      drupal_set_message(t('Added a shortcut for %title.', array('%title' => $link['link_title'])));
+      drupal_goto();
+    }
+    else {
+      drupal_set_message(t('Unable to add a shortcut for %title.', array('%title' => $link['link_title'])));
+    }
+  }
+}
diff --git modules/shortcut/shortcut.admin.js modules/shortcut/shortcut.admin.js
new file mode 100644
index 0000000..0d38f6c
--- /dev/null
+++ modules/shortcut/shortcut.admin.js
@@ -0,0 +1,100 @@
+// $Id$
+(function ($) {
+
+/**
+ * Handle the concept of a fixed number of slots.
+ *
+ * This behavior is dependent on the tableDrag behavior, since it uses the
+ * objects initialized in that behavior to update the row.
+ */
+Drupal.behaviors.shortcutDrag = {
+  attach: function (context, settings) {
+    if (Drupal.tableDrag) {
+      var table = $('table#shortcuts'),
+        visibleLength = 0,
+        slots = 0,
+        tableDrag = Drupal.tableDrag.shortcuts;
+      $('> tbody > tr, > tr', table)
+        .filter(':visible')
+          .filter(':odd').filter('.odd')
+            .removeClass('odd').addClass('even')
+          .end().end()
+          .filter(':even').filter('.even')
+            .removeClass('even').addClass('odd')
+          .end().end()
+        .end()
+        .filter('.toolbar-slot-empty').each(function(index) {
+          if ($(this).is(':visible')) {
+            visibleLength++;
+          }
+          slots++;
+        });
+
+      // Add a handler for when a row is swapped.
+      tableDrag.row.prototype.onSwap = function (swappedRow) {
+        var disabledIndex = $(table).find('tr').index($(table).find('tr.toolbar-status-disabled')) - slots - 2,
+          count = 0;
+        $(table).find('tr.toolbar-status-enabled').nextAll().filter(':not(.toolbar-slot-empty)').each(function(index) {
+          if (index < disabledIndex) {
+            count++;
+          }
+        });
+        var total = slots - count;
+        if (total == -1) {
+          var disabled = $(table).find('tr.toolbar-status-disabled');
+          disabled.after(disabled.prevAll().filter(':not(.toolbar-slot-empty)').get(0));
+        }
+        else if (total != visibleLength) {
+          if (total > visibleLength) {
+            // Less slots on screen than needed.
+            $('.toolbar-slot-empty:hidden:last').show();
+            visibleLength++;
+          }
+          else {
+            // More slots on screen than needed.
+            $('.toolbar-slot-empty:visible:last').hide();
+            visibleLength--;
+          }
+        }
+      };
+
+      // Add a handler so when a row is dropped, update fields dropped into new regions.
+      tableDrag.onDrop = function () {
+        // Use "status-message" row instead of "status" row because
+        // "status-{status_name}-message" is less prone to regexp match errors.
+        var statusRow = $(this.rowObject.element).prevAll('tr.toolbar-status').get(0);
+        var statusName = statusRow.className.replace(/([^ ]+[ ]+)*toolbar-status-([^ ]+)([ ]+[^ ]+)*/, '$2');
+        var statusField = $('select.shortcut-status-select', this.rowObject.element);
+        statusField.val(statusName);
+        return true;
+      };
+
+      tableDrag.restripeTable = function () {
+        // :even and :odd are reversed because jQuery counts from 0 and
+        // we count from 1, so we're out of sync.
+        // Match immediate children of the parent element to allow nesting.
+        $('> tbody > tr:visible, > tr:visible', this.table)
+          .filter(':odd').filter('.odd')
+            .removeClass('odd').addClass('even')
+          .end().end()
+          .filter(':even').filter('.even')
+            .removeClass('even').addClass('odd');
+      };
+    }
+  }
+};
+
+/**
+ * Make it so when you enter text into the "New set" textfield, the
+ * corresponding radio button gets selected.
+ */
+Drupal.behaviors.newSet = {
+  attach: function (context, settings) {
+    var selectDefault = function() {
+      $($(this).parents('div.form-item').get(1)).find('> label > input').attr('checked', 'checked');
+    };
+    $('div.form-item-new input').focus(selectDefault).keyup(selectDefault);
+  }
+};
+
+})(jQuery);
diff --git modules/shortcut/shortcut.api.php modules/shortcut/shortcut.api.php
new file mode 100644
index 0000000..355ccb7
--- /dev/null
+++ modules/shortcut/shortcut.api.php
@@ -0,0 +1,40 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Hooks provided by the Shortcut module.
+ */
+
+/**
+ * @addtogroup hooks
+ * @{
+ */
+
+/**
+ * Return the name of a default shortcut set for the provided user.
+ *
+ * This hook allows modules to define default shortcut sets for a particular
+ * user that differ from the site-wide default (for example, a module may want
+ * to define default shortcuts on a per-role basis).
+ *
+ * Note that only one default shortcut set can exist, so when multiple modules
+ * implement this hook, the first module which returns a valid shortcut set
+ * name will prevail.
+ *
+ * @param $account
+ *   The user account whose default shortcut set is being requested.
+ * @return
+ *   The name of the shortcut set that this module recommends for that user, if
+ *   there is one.
+ */
+function hook_shortcut_default_set_name($account) {
+  // Use a special set of default shortcuts for administrators only.
+  if (in_array(variable_get('user_admin_role', 0), $account->roles)) {
+    return variable_get('mymodule_admin_shortcut_default_set_name');
+  }
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
diff --git modules/shortcut/shortcut.css modules/shortcut/shortcut.css
new file mode 100644
index 0000000..8c5adc2
--- /dev/null
+++ modules/shortcut/shortcut.css
@@ -0,0 +1,72 @@
+/* $Id$ */
+
+div#toolbar div.toolbar-shortcuts ul {
+  padding: 5px 0;
+  height: 40px;
+  line-height: 30px;
+  overflow: hidden;
+  float: left;
+  margin-left:5px;
+}
+
+div#toolbar div.toolbar-shortcuts ul li a {
+  -moz-border-radius: 5px;
+  -webkit-border-radius: 5px;
+  padding: 5px 10px 5px 5px;
+  margin-right: 5px;
+}
+
+div#toolbar div.toolbar-shortcuts ul li a:focus,
+div#toolbar div.toolbar-shortcuts ul li a:hover,
+div#toolbar div.toolbar-shortcuts ul li a.active:focus {
+  background: #555;
+}
+
+div#toolbar div.toolbar-shortcuts ul li a.active:hover,
+div#toolbar div.toolbar-shortcuts ul li a.active {
+  background: url(../toolbar/toolbar.png) 0 -20px repeat-x;
+}
+
+div#toolbar div.toolbar-shortcuts span.icon {
+  float: left;
+  background: #444;
+  width: 30px;
+  height: 30px;
+  margin-right: 5px;
+  -moz-border-radius: 5px;
+  -webkit-border-radius: 5px;
+}
+
+div.toolbar-add-to-shortcuts a span.icon {
+  display: block;
+  width: 12px;
+  background: url(../toolbar/toolbar.png) no-repeat -50px -60px;
+  height: 12px;
+  float: left;
+  margin-left:8px;
+}
+
+div.toolbar-add-to-shortcuts a:hover span.icon {
+  background-position: -50px -72px;
+}
+
+div.toolbar-add-to-shortcuts a span.text {
+  float: left;
+  padding-left:10px;
+  display: none;
+}
+
+div.toolbar-add-to-shortcuts a:hover span.text {
+  font-size: 10px;
+  line-height: 12px;
+  color: #fff;
+  background-color: #5f605b;
+  display: block;
+  padding-right: 6px;
+  cursor: pointer;
+  -moz-border-radius-topright: 5px;
+  -moz-border-radius-bottomright: 5px;
+  -webkit-border-top-right-radius: 5px;
+  -webkit-border-bottom-right-radius: 5px;
+}
+
diff --git modules/shortcut/shortcut.info modules/shortcut/shortcut.info
new file mode 100644
index 0000000..65f37c0
--- /dev/null
+++ modules/shortcut/shortcut.info
@@ -0,0 +1,9 @@
+; $Id$
+name = Shortcut
+description = Allows users to manage customizable lists of shortcut links.
+package = Core
+version = VERSION
+core = 7.x
+files[] = shortcut.module
+files[] = shortcut.admin.inc
+files[] = shortcut.install
diff --git modules/shortcut/shortcut.install modules/shortcut/shortcut.install
new file mode 100644
index 0000000..ebf97a7
--- /dev/null
+++ modules/shortcut/shortcut.install
@@ -0,0 +1,110 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Install, update and uninstall functions for the shortcut module.
+ */
+
+/**
+ * Implement hook_enable().
+ */
+function shortcut_enable() {
+  if (shortcut_set_load(SHORTCUT_DEFAULT_SET_NAME)) {
+    // Quit out; this module has already been installed before.
+    return;
+  }
+
+  $t = get_t();
+  // Create an initial default shortcut set.
+  $shortcut_set = array(
+    'title' => $t('Default'),
+    'links' => array(
+      array(
+        'link_path' => 'node/add',
+        'link_title' => $t('Add content'),
+        'weight' => -20,
+      ),
+      array(
+        'link_path' => 'admin/content',
+        'link_title' => $t('Find content'),
+        'weight' => -19,
+      ),
+      array(
+        'link_path' => 'admin/dashboard',
+        'link_title' => $t('Dashboard'),
+        'weight' => -18,
+      ),
+    ),
+  );
+  shortcut_set_save($shortcut_set);
+}
+
+/**
+ * Implement hook_uninstall().
+ */
+function shortcut_uninstall() {
+  // Delete the menu links associated with each shortcut set.
+  foreach (shortcut_sets() as $shortcut_set) {
+    menu_delete_links($shortcut_set['set_name']);
+  }
+}
+
+/**
+ * Implement hook_schema().
+ */
+function shortcut_schema() {
+  $schema['shortcut_set'] = array(
+    'description' => 'Stores information about sets of shortcuts links.',
+    'fields' => array(
+      'set_name' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => "Primary Key: The {menu_links}.menu_name under which the set's links are stored.",
+      ),
+      'title' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'The title of the set.',
+      ),
+    ),
+    'primary key' => array('set_name'),
+    'foreign keys' => array(
+      'set_name' => array('menu_links' => 'menu_name'),
+    ),
+  );
+
+  $schema['shortcut_set_users'] = array(
+    'description' => 'Maps users to shortcut sets.',
+    'fields' => array(
+      'uid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'The {users}.uid for this set.',
+      ),
+      'set_name' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => "The {shortcut_set}.set_name that will be displayed for this user.",
+      ),
+    ),
+    'primary key' => array('uid'),
+    'indexes' => array(
+      'set_name' => array('set_name'),
+    ),
+    'foreign keys' => array(
+      'uid' => array('users' => 'uid'),
+      'set_name' => array('shortcut_set' => 'set_name'),
+    ),
+  );
+
+  return $schema;
+}
diff --git modules/shortcut/shortcut.module modules/shortcut/shortcut.module
new file mode 100644
index 0000000..3c84b34
--- /dev/null
+++ modules/shortcut/shortcut.module
@@ -0,0 +1,462 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Allows users to manage customizable lists of shortcut links.
+ */
+
+/**
+ * The name of the default shortcut set.
+ *
+ * This set will be displayed to any user that does not have another set
+ * assigned.
+ */
+define('SHORTCUT_DEFAULT_SET_NAME', 'shortcut-set-1');
+
+/**
+ * Implement hook_permission().
+ */
+function shortcut_permission() {
+  return array(
+    'administer shortcuts' => array(
+      'title' => t('Administer shortcuts'),
+      'description' => t('Manage shortcuts and shortcut sets regardless of which user they are assigned to.'),
+    ),
+    'customize shortcut links' => array(
+      'title' => t('Customize shortcut links'),
+      'description' => t("Edit, add and delete the links in the user's currently displayed shortcut set."),
+    ),
+    'switch shortcut sets' => array(
+      'title' => t('Choose a different shortcut set'),
+      'description' => t('Choose which set of shortcuts are displayed for the user.')
+    ),
+  );
+}
+
+/**
+ * Implement hook_menu().
+ */
+function shortcut_menu() {
+  $items['admin/config/system/shortcut'] = array(
+    'title' => 'Shortcuts',
+    'description' => 'List the available shortcut sets and switch between them.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('shortcut_set_switch'),
+    'access arguments' => array('administer shortcuts'),
+    'file' => 'shortcut.admin.inc',
+  );
+  $items['admin/config/system/shortcut/%shortcut_set'] = array(
+    'title' => 'Customize shortcuts',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('shortcut_set_customize', 4),
+    'access callback' => 'shortcut_set_access',
+    'access arguments' => array(4),
+    'type' => MENU_CALLBACK,
+    'file' => 'shortcut.admin.inc',
+  );
+  $items['admin/config/system/shortcut/%shortcut_set/add-link'] = array(
+    'title' => 'Add shortcut',
+    'page callback' => 'shortcut_link_edit',
+    'page arguments' => array(4),
+    'access callback' => 'shortcut_set_access',
+    'access arguments' => array(4),
+    'type' => MENU_LOCAL_ACTION,
+    'file' => 'shortcut.admin.inc',
+  );
+  $items['admin/config/system/shortcut/%shortcut_set/add-link-inline'] = array(
+    'title' => 'Add shortcut',
+    'page callback' => 'shortcut_add_link',
+    'page arguments' => array(4),
+    'access callback' => 'shortcut_set_access',
+    'access arguments' => array(4),
+    'type' => MENU_CALLBACK,
+    'file' => 'shortcut.admin.inc',
+  );
+  $items['admin/config/system/shortcut/%shortcut_set/link/%menu_link'] = array(
+    'title' => 'Edit shortcut',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('shortcut_link_edit', 4, 6),
+    'access callback' => 'shortcut_set_access',
+    'access arguments' => array(4),
+    'type' => MENU_CALLBACK,
+    'file' => 'shortcut.admin.inc',
+  );
+  $items['admin/config/system/shortcut/%shorcut_set/link/%menu_link/delete'] = array(
+    'title' => 'Delete shortcut',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('shortcut_link_delete', 6),
+    'access callback' => 'shortcut_set_access',
+    'access arguments' => array(4),
+    'type' => MENU_CALLBACK,
+    'file' => 'shortcut.admin.inc',
+  );
+  $items['user/%user/shortcuts'] = array(
+    'title' => 'Shortcuts',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('shortcut_set_switch', 1),
+    'access callback' => 'shortcut_switch_access',
+    'access arguments' => array(1),
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'shortcut.admin.inc',
+  );
+  return $items;
+}
+
+/**
+ * Implement hook_theme().
+ */
+function shortcut_theme() {
+  return array(
+    'shortcut_set_switch' => array(
+      'arguments' => array('form' => NULL),
+      'file' => 'shortcut.admin.inc',
+    ),
+    'shortcut_set_customize' => array(
+      'arguments' => array('form' => NULL),
+      'file' => 'shortcut.admin.inc',
+    ),
+  );
+}
+
+/**
+ * Implement hook_block_info().
+ */
+function shortcut_block_info() {
+  $blocks['shortcuts']['info'] = t('Shortcuts');
+  // Shortcut blocks can't be cached because each menu item can have a custom
+  // access callback. menu.inc manages its own caching.
+  $blocks['shortcuts']['cache'] = DRUPAL_NO_CACHE;
+  return $blocks;
+}
+
+/**
+ * Implement hook_block_view().
+ */
+function shortcut_block_view($delta = '') {
+  if ($delta == 'shortcuts') {
+    $shortcut_set = shortcut_current_displayed_set();
+    $data['subject'] = t('@shortcut_set shortcuts', array('@shortcut_set' => $shortcut_set['title']));
+    $data['content'] = shortcut_renderable_links($shortcut_set);
+    return $data;
+  }
+}
+
+/**
+ * Access callback for editing a shortcut set.
+ */
+function shortcut_set_access($shortcut_set) {
+  // Sufficiently-privileged users can edit their currently displayed shortcut
+  // set, but not other sets. Shortcut administrators can edit any set.
+  return user_access('administer shortcuts') || (user_access('customize shortcut links') && ($current_set = shortcut_current_displayed_set()) && $current_set['set_name'] == $shortcut_set['set_name']);
+}
+
+/**
+ * Access callback for switching the shortcut set assigned to a user account.
+ */
+function shortcut_switch_access($account) {
+  global $user;
+  // Sufficiently-privileged users can switch their own shortcut sets, but not
+  // those of other users. Shortcut administrators can switch any user's set.
+  return user_access('administer shortcuts') || (user_access('switch shortcut sets') && $user->uid == $account->uid);
+}
+
+/**
+ * Loads the data for a shortcut set.
+ *
+ * @param $set_name
+ *   The name of the shortcut set to load.
+ * @return
+ *   If the shortcut set exists, an array containing the following keys:
+ *   - 'set_name': The internal name of the shortcut set.
+ *   - 'title': The title of the shortcut set.
+ *   - 'links': An array of links associated with this shortcut set.
+ *   If the shortcut set does not exist, the function returns FALSE.
+ */
+function shortcut_set_load($set_name) {
+  $set = db_query("SELECT * FROM {shortcut_set} WHERE set_name = :set_name", array(':set_name' => $set_name))->fetchAssoc();
+  if (!$set) {
+    return FALSE;
+  }
+  $set['links'] = menu_load_links($set_name);
+  return $set;
+}
+
+/**
+ * Saves a shortcut set.
+ *
+ * @param $shortcut_set
+ *   An array containing the following keys:
+ *   - 'title': The title of the shortcut set.
+ *   - 'set_name': (optional) The internal name of the shortcut set. If
+ *     omitted, a new shortcut set will be created, and the 'set_name' key
+ *     will be added to the passed-in array.
+ *   - 'links': (optional) An array of menu links to save for the shortcut set.
+ *     Each link is an array containing at least the following keys (which will
+ *     be expanded to fill in other default values after the shortcut set is
+ *     saved):
+ *     - 'link_path': The Drupal path or external path that the link points to.
+ *     - 'link_title': The title of the link.
+ *     Any other keys accepted by menu_link_save() may also be provided.
+ * @return
+ *   A constant which is either SAVED_NEW or SAVED_UPDATED depending on whether
+ *   a new set was created or an existing one was updated.
+ *
+ * @see menu_link_save()
+ */
+function shortcut_set_save(&$shortcut_set) {
+  // First save the shortcut set itself.
+  if (isset($shortcut_set['set_name'])) {
+    $return = drupal_write_record('shortcut_set', $shortcut_set, 'set_name');
+  }
+  else {
+    $shortcut_set['set_name'] = shortcut_set_get_unique_name();
+    $return = drupal_write_record('shortcut_set', $shortcut_set);
+  }
+  // If links were provided for the set, save them, replacing any that were
+  // there before.
+  if (isset($shortcut_set['links'])) {
+    menu_delete_links($shortcut_set['set_name']);
+    foreach ($shortcut_set['links'] as &$link) {
+      // Do not specifically associate these links with the shortcut module,
+      // since other modules may make them editable via the menu system.
+      // However, we do need to specify the correct menu name.
+      $link['menu_name'] = $shortcut_set['set_name'];
+      menu_link_save($link);
+    }
+    // Make sure that we have a return value, since if the links were updated
+    // but the shortcut set was not, the call to drupal_write_record() above
+    // would not return an indication that anything had changed.
+    if (empty($return)) {
+      $return = SAVED_UPDATED;
+    }
+  }
+  return $return;
+}
+
+/**
+ * Deletes a shortcut set.
+ *
+ * Note that the default set cannot be deleted.
+ *
+ * @param $shortcut_set
+ *   An array representing the shortcut set to delete.
+ * @return
+ *   TRUE if the set was deleted, FALSE otherwise.
+ */
+function shortcut_set_delete($shortcut_set) {
+  // Make sure not to delete the default set.
+  $default_set = shortcut_default_set();
+  if ($shortcut_set['set_name'] == $default_set['set_name']) {
+    return FALSE;
+  }
+  // First, delete any user assignments for this set, so that each of these
+  // users will go back to using whatever default set applies.
+  db_delete('shortcut_set_users')
+    ->condition('set_name', $shortcut_set['set_name'])
+    ->execute();
+  // Next, delete the menu links for this set.
+  menu_delete_links($shortcut_set['set_name']);
+  // Finally, delete the set itself.
+  $deleted = db_delete('shortcut_set')
+    ->condition('set_name', $shortcut_set['set_name'])
+    ->execute();
+  return (bool) $deleted;
+}
+
+/**
+ * Assign a user to a particular shortcut set.
+ *
+ * @param $shortcut_set
+ *   An array representing the shortcut set.
+ * @param $account
+ *   A user account that will be assigned to use the set.
+ */
+function shortcut_set_assign_user($shortcut_set, $account) {
+  db_merge('shortcut_set_users')
+    ->key(array('uid' => $account->uid))
+    ->fields(array('set_name' => $shortcut_set['set_name']))
+    ->execute();
+}
+
+/**
+ * Unassign a user from any shortcut set they may have been assigned to.
+ *
+ * The user will go back to using whatever default set applies.
+ *
+ * @param $account
+ *   A user account that will be removed from the shortcut set assignment.
+ * @return
+ *   TRUE if the user was previously assigned to a shortcut set and has been
+ *   successfully removed from it. FALSE if the user was already not assigned
+ *   to any set.
+ */
+function shortcut_set_unassign_user($account) {
+  $deleted = db_delete('shortcut_set')
+    ->condition('uid', $account->uid)
+    ->execute();
+  return (bool) $deleted;
+}
+
+/**
+ * Returns the current displayed shortcut set for the provided user account.
+ *
+ * @param $account
+ *   (optional) The user account whose shortcuts will be returned. Defaults to
+ *   the current logged-in user.
+ * @return
+ *   An array representing the shortcut set that should be displayed to the
+ *   current user. If the user does not have an explicit shortcut set defined,
+ *   the default set is returned.
+ */
+function shortcut_current_displayed_set($account = NULL) {
+  $shortcut_sets = &drupal_static(__FUNCTION__, array());
+  global $user;
+  if (!isset($account)) {
+    $account = $user;
+  }
+  // Try to return a shortcut set from the static cache.
+  if (isset($shortcut_sets[$account->uid])) {
+    return $shortcut_sets[$account->uid];
+  }
+  // If none was found, try to find a shortcut set that is explicitly assigned
+  // to this user.
+  $query = db_select('shortcut_set', 's');
+  $query->fields('s');
+  $query->join('shortcut_set_users', 'u', 's.set_name = u.set_name');
+  $query->condition('u.uid', $account->uid);
+  $shortcut_set = $query->execute()->fetchAssoc();
+  // Otherwise, use the default set.
+  if (!$shortcut_set) {
+    $shortcut_set = shortcut_default_set($account);
+  }
+  $shortcut_sets[$account->uid] = $shortcut_set;
+  return $shortcut_set;
+}
+
+/**
+ * Returns the default shortcut set for a given user account.
+ *
+ * @param $account
+ *   (optional) The user account whose shortcuts will be returned. Defaults to
+ *   the current logged-in user.
+ * @return
+ *   An array representing the default shortcut set.
+ */
+function shortcut_default_set($account = NULL) {
+  global $user;
+  if (!isset($account)) {
+    $account = $user;
+  }
+  // Allow modules to return a default shortcut set name. Since we can only
+  // have one, we take the first valid result we get. If we don't find one,
+  // fall back on the site-wide default.
+  $shortcut_set_names = array_merge(module_invoke_all('shortcut_default_set_name', $account), array(SHORTCUT_DEFAULT_SET_NAME));
+  foreach ($shortcut_set_names as $name) {
+    if ($shortcut_set = shortcut_set_load($name)) {
+      break;
+    }
+  }
+  return $shortcut_set;
+}
+
+/**
+ * Returns a unique, machine-readable shortcut set name.
+ */
+function shortcut_set_get_unique_name() {
+  // Shortcut sets are numbered sequentially, so we keep trying until we find
+  // one that is available. For better performance, we start with a number
+  // equal to one more than the current number of shortcut sets, so that if
+  // no shortcut sets have been deleted from the database, this will
+  // automatically give us the correct one.
+  $number = db_query("SELECT COUNT(*) FROM {shortcut_set}")->fetchField() + 1;
+  do {
+    $name = shortcut_set_name($number);
+    $number++;
+  } while ($shortcut_set = shortcut_set_load($name));
+  return $name;
+}
+
+/**
+ * Returns the name of a shortcut set, based on a provided number.
+ *
+ * All shortcut sets have names like "shortcut-set-N" so that they can be
+ * matched with a properly-namespaced entry in the {menu_links} table.
+ *
+ * @param $number
+ *   A number representing the shortcut set whose name should be retrieved.
+ * @return
+ *   A string representing the expected shortcut name.
+ */
+function shortcut_set_name($number) {
+  return "shortcut-set-$number";
+}
+
+/**
+ * Returns an array of all shortcut sets, keyed by the set name.
+ */
+function shortcut_sets() {
+  return db_query("SELECT * FROM {shortcut_set}")->fetchAllAssoc('set_name', PDO::FETCH_ASSOC);
+}
+
+/**
+ * Returns an array of shortcut links, suitable for rendering.
+ *
+ * @param $shortcut_set
+ *   (optional) An array representing the set whose links will be displayed.
+ *   If not provided, the user's current set will be displayed.
+ * @return
+ *   An array of shortcut links, in the format returned by the menu system.
+ *
+ * @see menu_tree()
+ */
+function shortcut_renderable_links($shortcut_set = NULL) {
+  if (!isset($shortcut_set)) {
+    $shortcut_set = shortcut_current_displayed_set();
+  }
+  return menu_tree($shortcut_set['set_name']);
+}
+
+/**
+ * Implement hook_page_build().
+ */
+function shortcut_page_build(&$page) {
+  if (user_access('customize shortcut links')) {
+    // $_GET['q'] is the unaliased version.
+    $get = $_GET;
+    unset($get['q']);
+    $link = $_GET['q'];
+    if (!empty($get)) {
+     $link .= '?' . drupal_http_build_query($get);
+    }
+    $query = array(
+     'link' => $link,
+     'name' => drupal_get_title(),
+     'token' => drupal_get_token('shortcut-add-link'),
+    );
+    $query += drupal_get_destination();
+
+    $shortcut_set = shortcut_current_displayed_set();
+
+    $page['add_to_shortcuts'] = array(
+     '#prefix' => '<div class="toolbar-add-to-shortcuts">',
+     '#markup' => l('<span class="icon"></span><span class="text">' . t('Add to %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set['title'])) . '</span>', 'admin/config/system/shortcut/' . $shortcut_set['set_name'] . '/add-link-inline', array('query' => $query, 'html' => TRUE)),
+     '#suffix' => '</div>',
+    );
+  }
+
+  $links = shortcut_renderable_links();
+  $links['#attached'] = array('css' => array(drupal_get_path('module', 'shortcut') . '/shortcut.css'));
+  $links['#prefix'] = '<div class="toolbar-shortcuts">';
+  $links['#suffix'] = '</div>';
+  $page['toolbar_drawer'] = $links;
+}
+
+/**
+ * Implement hook_preprocess_page().
+ */
+function shortcut_preprocess_page(&$vars) {
+  if (user_access('customize toolbar shortcuts')) {
+    $vars['add_to_shortcuts'] = drupal_render($vars['page']['add_to_shortcuts']);
+  }
+}
diff --git modules/toolbar/toolbar.css modules/toolbar/toolbar.css
index d530e8b..12cffff 100644
--- modules/toolbar/toolbar.css
+++ modules/toolbar/toolbar.css
@@ -4,7 +4,7 @@ body.toolbar {
   padding-top: 30px;
 }
 
-body.toolbar-shortcuts {
+body.toolbar-drawer {
   padding-top: 80px;
 }
 
@@ -118,49 +118,13 @@ div#toolbar div.toolbar-menu ul li a.active {
 }
 
 /**
- * Administration shortcuts.
+ * Collapsed drawer of additional toolbar content.
  */
-div#toolbar div.toolbar-shortcuts {
+div#toolbar div.toolbar-drawer {
   position: relative;
   padding: 0 10px;
 }
 
-div#toolbar div.toolbar-shortcuts ul {
-  padding: 5px 0;
-  height: 40px;
-  line-height: 30px;
-  overflow: hidden;
-  float: left;
-}
-
-div#toolbar div.toolbar-shortcuts ul li a {
-  -moz-border-radius: 5px;
-  -webkit-border-radius: 5px;
-  padding: 5px 10px 5px 5px;
-  margin-right: 5px;
-}
-
-div#toolbar div.toolbar-shortcuts ul li a:focus,
-div#toolbar div.toolbar-shortcuts ul li a:hover,
-div#toolbar div.toolbar-shortcuts ul li a.active:focus {
-  background: #555;
-}
-
-div#toolbar div.toolbar-shortcuts ul li a.active:hover,
-div#toolbar div.toolbar-shortcuts ul li a.active {
-  background: url(toolbar.png) 0 -20px repeat-x;
-}
-
-div#toolbar div.toolbar-shortcuts span.icon {
-  float: left;
-  background: #444;
-  width: 30px;
-  height: 30px;
-  margin-right: 5px;
-  -moz-border-radius: 5px;
-  -webkit-border-radius: 5px;
-}
-
 /**
  * IE 6 Fixes.
  *
@@ -168,7 +132,7 @@ div#toolbar div.toolbar-shortcuts span.icon {
  * the behavior of the admin toolbar entirely to static positioning.
  */
 * html body.toolbar,
-* html body.toolbar-shortcuts {
+* html body.toolbar-drawer {
   padding-top: 0;
 }
 
diff --git modules/toolbar/toolbar.info modules/toolbar/toolbar.info
index 60037d8..db85c72 100644
--- modules/toolbar/toolbar.info
+++ modules/toolbar/toolbar.info
@@ -1,9 +1,7 @@
 ; $Id: toolbar.info,v 1.2 2009-07-06 13:54:21 dries Exp $
 name = Toolbar
-description = Toolbar exposing the top level administration menu items
+description = Toolbar exposing the top level administration menu items.
 core = 7.x
 package = Core
 version = VERSION
-files[] = toolbar.install
 files[] = toolbar.module
-dependencies[] = menu
diff --git modules/toolbar/toolbar.js modules/toolbar/toolbar.js
index 7763203..222a4c7 100644
--- modules/toolbar/toolbar.js
+++ modules/toolbar/toolbar.js
@@ -10,7 +10,7 @@ Drupal.behaviors.admin = {
     // Set the intial state of the toolbar.
     $('#toolbar', context).once('toolbar', Drupal.admin.toolbar.init);
 
-    // Toggling of admin shortcuts visibility.
+    // Toggling toolbar drawer.
     $('#toolbar span.toggle', context).once('toolbar-toggle').click(function() {
       Drupal.admin.toolbar.toggle();
       return false;
@@ -44,9 +44,9 @@ Drupal.admin.toolbar.init = function() {
  * Collapse the admin toolbar.
  */
 Drupal.admin.toolbar.collapse = function() {
-  $('#toolbar div.toolbar-shortcuts').addClass('collapsed');
+  $('#toolbar div.toolbar-drawer').addClass('collapsed');
   $('#toolbar span.toggle').removeClass('toggle-active');
-  $('body').removeClass('toolbar-shortcuts');
+  $('body').removeClass('toolbar-drawer');
   $.cookie(
     'Drupal.admin.toolbar.collapsed', 
     1, 
@@ -58,9 +58,9 @@ Drupal.admin.toolbar.collapse = function() {
  * Expand the admin toolbar.
  */
 Drupal.admin.toolbar.expand = function() {
-  $('#toolbar div.toolbar-shortcuts').removeClass('collapsed');
+  $('#toolbar div.toolbar-drawer').removeClass('collapsed');
   $('#toolbar span.toggle').addClass('toggle-active');
-  $('body').addClass('toolbar-shortcuts');
+  $('body').addClass('toolbar-drawer');
   $.cookie(
     'Drupal.admin.toolbar.collapsed', 
     0, 
@@ -72,7 +72,7 @@ Drupal.admin.toolbar.expand = function() {
  * Toggle the admin toolbar.
  */
 Drupal.admin.toolbar.toggle = function() {
-  if ($('#toolbar div.toolbar-shortcuts').is('.collapsed')) {
+  if ($('#toolbar .toolbar-drawer').is('.collapsed')) {
     Drupal.admin.toolbar.expand();
   }
   else {
diff --git modules/toolbar/toolbar.module modules/toolbar/toolbar.module
index 28371ed..36145ef 100644
--- modules/toolbar/toolbar.module
+++ modules/toolbar/toolbar.module
@@ -38,17 +38,18 @@ function toolbar_theme($existing, $type, $theme, $path) {
 function toolbar_page_build(&$page) {
   if (user_access('access toolbar')) {
     $page['page_top']['toolbar'] = toolbar_build();
+    $page['page_top']['toolbar']['toolbar_drawer'] = isset($page['toolbar_drawer']) ? $page['toolbar_drawer'] : array();
   }
 }
 
 /**
- * Implement hook_preprocess_page().
+ * Implement hook_preprocess_html().
  *
  * Add some page classes, so global page theming can adjust to the toolbar.
  */
 function toolbar_preprocess_html(&$vars) {
   if (user_access('access toolbar')) {
-    $vars['classes_array'][] = 'toolbar toolbar-shortcuts';
+    $vars['classes_array'][] = 'toolbar toolbar-drawer';
   }
 }
 
@@ -100,16 +101,6 @@ function toolbar_build() {
     ),
     '#attributes' => array('id' => 'toolbar-user'),
   );
-
-  // Add convenience shortcut links.
-  $shortcuts = menu_tree_all_data('admin_shortcuts');
-  $shortcuts = toolbar_menu_navigation_links($shortcuts);
-  $build['toolbar_shortcuts'] = array(
-    '#theme' => 'links',
-    '#links' => $shortcuts,
-    '#attributes' => array('id' => 'toolbar-shortcuts'),
-  );
-
   return $build;
 }
 
diff --git modules/toolbar/toolbar.png modules/toolbar/toolbar.png
index ffe41ff0f80bed5a7a4be26209bf02466f7c21aa..391d2e7507792751292db5852058dc431bf0a473 100644
GIT binary patch
delta 1052
zcmcc1x|u_<Gr-TCmrII^fq{Y7)59eQNZSE%3I`jIymzJf>O@8LdgiO1E{-7;x8BT&
z_qZG=a{T-q3A@bdfOh7^N{)^qJr@&_x;hUBG#_Aht&)1<xPf&eJNIW-jx7$JF*B-#
zn&nd1gtu%lT=T3YNg+(_tUdoqj~@%NeXd&;3kMb(e-plAD}L_X-@EspmcM^qcYg2p
zKSzAc3=9OA7$+x{my5Ts@YlCG9q2N)*lneKu50rno^$I!)EbNC&8tC__PGZ_YLc@i
z?3>5bq{fzBKsx&Hd1}hVri&Rlhu`SkI?7^my*+Jn)Y@Ej?WJ!XAK1T4tA3^S7VC^%
z9(UQdT+ayG;vgZzUd;H}bBhzF+Bfc7y&jR5><XCbl=rZm&Szt1@6IukK6B<wLyTVg
zqen>wGkpSrgFj2YzwZ=1F?lH~_gA6HDN=9wZ<Vh6{h`7pc!u@t*|WKI#kh5JbPjy`
zW|otid+^U68y;TXiQy|wpE{M7w7agJwQh^Yo;gwH5>5umzb@Oocfs=I>HCdd{WH3G
zuPZM<pM9=hctB`q>XNg%v5y>=&JUFTx_0eaLuog)WpNXAc9$p!TsU{`+@XcN?>au^
zZJ*s071+Po;ZlS4)KfG6{P|Oxy7=|44_m`lFFiBcr)&SK7cV+)p2#t4zpW-*kzZQ6
zb$Va@rpHs3eV(JXY|oxM-no<6WEeG-j1}fwe^|ia$F$;V)`bicksSxFToHM&L|{wf
zwI3_Xzh1o>dg9C(pBD?v&CL@lDkT2Y{hwI9a^=c^@No9b%uIDV<xR!w7sMVezSUAD
zeR}D{+v_||+>+*v^k=m*H)r=-F6`yyrJ%2`pZI_!)u3J?Ati;S>EMI9y-o``t{-o*
zQ+s>C{Y&I$`+cu%FX#Pz^1Czr;;tRBwS|R(F?!eUeMx-x`KQpTDmOQ_kdP1uuT%FX
zXe`fO)qnY_=HiII!pC0SojP^u(#Xij33KQ2evdk1QK?n&<%8jhkX1hpUcYuNp{7P=
zQT$b<?TfODe!DE2GpAnW!t1XOjh>ds<{vV=7(J6Y`Rk&#HZ}=q>E_<v-VZn2-Q5>%
z+a~twcl@E+&&?auFW!#yc=feh?6*gJe7rHxI+h>nBjyU_*1UebKWTkoQ&v`%)n(aV
z_U7kzB!6AEe6B*un!2BtL=FFc5xK+JG-2bfPnU!^Bv<dgEAO}?!q)tIk=CBs72Hlo
zU-kC#Uby*HMdqUF*>!b6YyQ2x9sZ$W*}-3re%47y8#h?$b23ZZTxr8{R`1b7w{`n;
zw0`&p9=z_#dS6WR&UutPQ@8Hkeb>LN`}Z^PF#Pzq;<))0MLl4KXYh3Ob6Mw<&;$U<
C>G`t&

literal 733
zcmeAS@N?(olHy`uVBq!ia0vp^AAmT8gAGXTShV*zkdiEMjVKAuPb(=;EJ|f?Ovz75
zRq)JBOiv9;O-!jQJeg|4z`#`R>EaktaqG<;!+fDYh65kf6JI2Bao;_1w&c>q)`iT?
zIW<g=j+}9S@%%-Qz0+eR=4R&j1DtM|a}FHbaDt)z`?+H`W@PZNpFI7y?&Q-Q%1_tz
z|M~sS!};&GZ)NfgDpxn_7;{a?I`Dfhr^J~94GoObFC?(B0a=m~0tP!;AS|c^Pz);Z
z;q>I1LS9}bHWnTZ2@n=AP)Gn_hXWuCG={Mmh?zkOuqkS2aKxr)m0Urhfke#n)#X1w
zEo!+Q`{eZR*|TTAzF$7?kwn1ChR-YJJ$>E(^V2Vm_5U^F*U8Drf0d{_aevR;5MSN+
zHg_&<n?3J7xEyad#a82USXh=>Yxz9=US;{kg-!PtKU}+Hl`+_X5W5>6ulWC-UuXL1
zg2KYUSDtIGzb+^*7dM-IR{s3lxpQ0N){CDze|~Rt!3iFl`RBVYq-~B|sV?~VP1){+
zarJ+`tK=R3`>2(fdEfs1{Fh&DsgSweeRR<k;Y_pH3opNHiF*57^JwXvzTb_^OmS<&
z5{+iI=$!6)`?oGW=lJQDMq8uSUdY?teY{Y1J5WL2_vMQ(YUFIc?f$!bcdSJJ@uQzp
zckS7u^RDu-)Q{cubseJb?SKFM=jp%d4gbjnpT2{`4H&Snz?~$p|Hj|u#0Hb2|Bw7i
zl2EwYU@y()Vg6u!8{;M3AG;G9N|^6Suz3Xk5&5+i#Mx)WGa>IlJ`eK}=?~h68D6se
zxn$t5i_zX3B)qReQi$)z%ESg2=Dzq#d`n)oGcYr3v^%ruJ`-~&FugK(y85}Sb4q9e
E0LX1a8~^|S

diff --git modules/toolbar/toolbar.tpl.php modules/toolbar/toolbar.tpl.php
index 2bbd893..48ddbc4 100644
--- modules/toolbar/toolbar.tpl.php
+++ modules/toolbar/toolbar.tpl.php
@@ -8,7 +8,7 @@
  * Available variables:
  * - $toolbar['toolbar_user']: User account / logout links.
  * - $toolbar['toolbar_menu']: Top level management menu links.
- * - $toolbar['toolbar_shortcuts']: Convenience shortcuts.
+ * - $toolbar['toolbar_drawer']: A place for extended toolbar content.
  *
  * @see template_preprocess()
  * @see template_preprocess_admin_toolbar()
@@ -21,8 +21,8 @@
     <?php print render($toolbar['toolbar_user']); ?>
   </div>
 
-  <div class="toolbar-shortcuts clearfix">
-    <?php print render($toolbar['toolbar_shortcuts']); ?>
+  <div class="toolbar-drawer clearfix">
+    <?php print render($toolbar['toolbar_drawer']); ?>
   </div>
 
   <div class="shadow"></div>
diff --git profiles/default/default.info profiles/default/default.info
index 12d868f..7c9c040 100644
--- profiles/default/default.info
+++ profiles/default/default.info
@@ -14,6 +14,7 @@ dependencies[] = path
 dependencies[] = taxonomy
 dependencies[] = dblog
 dependencies[] = search
+dependencies[] = shortcut
 dependencies[] = toolbar
 dependencies[] = field_ui
 dependencies[] = file
diff --git sites/default/default.settings.php sites/default/default.settings.php
old mode 100644
new mode 100755
diff --git themes/seven/page.tpl.php themes/seven/page.tpl.php
index 42efe1d..cd46540 100644
--- themes/seven/page.tpl.php
+++ themes/seven/page.tpl.php
@@ -4,6 +4,7 @@
   <div id="branding" class="clearfix">
     <?php print $breadcrumb; ?>
     <?php if ($title): ?><h1 class="page-title"><?php print $title; ?></h1><?php endif; ?>
+    <?php if ($add_to_shortcuts): ?><?php print $add_to_shortcuts; ?><?php endif; ?>
     <?php if ($primary_local_tasks): ?><ul class="tabs primary"><?php print render($primary_local_tasks); ?></ul><?php endif; ?>
   </div>
 
diff --git themes/seven/style.css themes/seven/style.css
index e2d25a0..08c1c36 100644
--- themes/seven/style.css
+++ themes/seven/style.css
@@ -735,3 +735,10 @@ body.overlay #page {
 body.overlay #block-system-main {
   padding: 20px;
 }
+
+/* Shortcut theming */
+div.toolbar-add-to-shortcuts {
+  float: left;
+  margin-left: 6px;
+  margin-top: 6px;
+}
