diff --git a/core/misc/states.js b/core/misc/states.js
index 30b63ba..f79b519 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -104,13 +104,25 @@ states.Dependent.prototype = {
         // Initialize the value of this state.
         this.values[selector][state.name] = null;
 
+        var arg;
+        if (selector == 'window') {
+          arg = window;
+        }
+        else if (selector == 'document') {
+          arg = document;
+        }
+        else {
+          arg = selector;
+        }
+        var element = $(arg);
+
         // Monitor state changes of the specified state for this dependee.
-        $(selector).bind('state:' + state, $.proxy(function (e) {
+        $(arg).bind('state:' + state, $.proxy(function (e) {
           this.update(selector, state, e.value);
         }, this));
 
         // Make sure the event we just bound ourselves to is actually fired.
-        new states.Trigger({ selector: selector, state: state });
+        new states.Trigger({ selector: selector, element: element, state: state });
       }
     }
   },
@@ -303,8 +315,6 @@ states.Trigger = function (args) {
   $.extend(this, args);
 
   if (this.state in states.Trigger.states) {
-    this.element = $(this.selector);
-
     // Only call the trigger initializer when it wasn't yet attached to this
     // element. Otherwise we'd end up with duplicate events.
     if (!this.element.data('trigger:' + this.state)) {
@@ -370,6 +380,12 @@ states.Trigger.states = {
     }
   },
 
+  hash: {
+    'hashchange': function() {
+      return location.hash;
+    }
+  },
+
   checked: {
     'change': function () {
       // prop() and attr() only takes the first element into account. To support
@@ -514,7 +530,13 @@ $(document).bind('state:required', function(e) {
 
 $(document).bind('state:visible', function(e) {
   if (e.trigger) {
-    $(e.target).closest('.form-item, .form-submit, .form-wrapper').toggle(e.value);
+    var element = $(e.target);
+    // Also hide the wrapper of form items.
+    var wrapper = element.closest('.form-item, .form-submit, .form-wrapper');
+    if (wrapper.length > 0) {
+      element = wrapper;
+    }
+    element.toggle(e.value);
   }
 });
 
diff --git a/core/modules/openid/openid.css b/core/modules/openid/openid.css
index 913d496..dd33208 100644
--- a/core/modules/openid/openid.css
+++ b/core/modules/openid/openid.css
@@ -5,40 +5,15 @@
   background-repeat: no-repeat;
   padding-left: 20px; /* LTR */
 }
-div.form-item-openid-identifier {
-  display: block;
-}
-.js #user-login-form div.form-item-openid-identifier,
-.js #user-login div.form-item-openid-identifier {
-  display: none;
-}
-#user-login-form ul {
-  margin-top: 0;
-}
-#user-login ul {
-  margin: 0 0 5px;
-}
-#user-login ul li {
-  margin: 0;
-}
-#user-login-form .openid-links {
-  padding-bottom: 0;
-}
-#user-login .openid-links {
-  padding-left: 0; /* LTR */
-}
-#user-login-form .openid-links li,
-#user-login .openid-links li {
+#block-user-login a.openid-link,
+#block-user-login a.user-link {
   display: none;
-  list-style: none;
 }
-.js #user-login-form li.openid-link,
-.js #user-login li.openid-link {
+.js #block-user-login a.openid-link,
+.js #block-user-login a.user-link {
   display: block;
-  margin-left: 0; /* LTR */
 }
-#user-login-form li.openid-link a,
-#user-login li.openid-link a {
+#block-user-login a.openid-link {
   background-image: url("login-bg.png");
   background-position: left top; /* LTR */
   background-repeat: no-repeat;
diff --git a/core/modules/openid/openid.js b/core/modules/openid/openid.js
index 754efb1..7bac543 100644
--- a/core/modules/openid/openid.js
+++ b/core/modules/openid/openid.js
@@ -3,48 +3,31 @@
 Drupal.behaviors.openid = {
   attach: function (context) {
     var $context = $(context);
-    var loginElements = $('.form-item-name, .form-item-pass, li.openid-link');
-    var openidElements = $('.form-item-openid-identifier, li.user-link');
-    var cookie = $.cookie('Drupal.visitor.openid_identifier');
 
-    // This behavior attaches by ID, so is only valid once on a page.
-    if (cookie || location.hash == '#openid-login') {
-      $edit_openid_identifier = $('#edit-openid-identifier');
-      if (cookie) {
-        $edit_openid_identifier.val(cookie);
-      }
-      $edit_openid_identifier.once('openid', function() {
-        loginElements.hide();
-        // Use .css('display', 'block') instead of .show() to be Konqueror friendly.
-        openidElements.css('display', 'block');
-      });
+    var cookie = $.cookie('Drupal.visitor.openid_identifier');
+    if (cookie) {
+      $context.find('#edit-openid-identifier').once('openid').val(cookie);
+      location.hash = '#openid-login';
     }
 
+    // This is invoked when the user switches between the default login form and
+    // the OpenID login form.
+    $context.find('#block-user-login').once('openid').bind('state:visible', function(e) {
+      // Process the form when it becomes visible.
+      if (e.value) {
+        // Reset error state.
+        $('#messages div.error').hide();
+        $('#block-user-login input').removeClass('error');
 
-    $context.find('li.openid-link')
-      .once('openid')
-      .click(function () {
-        loginElements.hide();
-        openidElements.css('display', 'block');
-        // Remove possible error message.
-        $('#edit-name, #edit-pass').removeClass('error');
-        $('div.messages.error').hide();
-        // Set focus on OpenID Identifier field.
-        $('#edit-openid-identifier')[0].focus();
-        return false;
-      });
-    $context.find('li.user-link')
-      .once('openid')
-      .click(function () {
-        openidElements.hide();
-        loginElements.css('display', 'block');
-        // Clear OpenID Identifier field and remove possible error message.
-        $('#edit-openid-identifier').val('').removeClass('error');
-        $('div.messages.error').css('display', 'block');
-        // Set focus on username field.
-        $('#edit-name')[0].focus();
-        return false;
-      });
+        // Forget saved identifier.
+        $.cookie('Drupal.visitor.openid_identifier', null);
+
+        // Wait for the input field to become visible before setting focus.
+        window.setTimeout(function() {
+          $(e.target).find('input').first().focus();
+        }, 1);
+      }
+    });
   }
 };
 
diff --git a/core/modules/openid/openid.module b/core/modules/openid/openid.module
index 141a3ab..d045eff 100644
--- a/core/modules/openid/openid.module
+++ b/core/modules/openid/openid.module
@@ -16,6 +16,13 @@ function openid_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'openid.pages.inc',
   );
+  $items['user/login/openid'] = array(
+    'title' => 'Log in using OpenID',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('openid_login_form'),
+    'access callback' => 'user_is_anonymous',
+    'type' => MENU_LOCAL_TASK,
+  );
   $items['user/%user/openid'] = array(
     'title' => 'OpenID identities',
     'page callback' => 'openid_user_identities',
@@ -41,7 +48,7 @@ function openid_menu() {
  */
 function openid_menu_site_status_alter(&$menu_site_status, $path) {
   // Allow access to openid/authenticate even if site is in offline mode.
-  if ($menu_site_status == MENU_SITE_OFFLINE && user_is_anonymous() && $path == 'openid/authenticate') {
+  if ($menu_site_status == MENU_SITE_OFFLINE && user_is_anonymous() && in_array($path, array('openid/authenticate', 'user/login/openid'))) {
     $menu_site_status = MENU_SITE_ONLINE;
   }
 }
@@ -120,58 +127,77 @@ function openid_user_logout($account) {
 }
 
 /**
- * Implements hook_form_FORM_ID_alter().
+ * Implements hook_block_view_MODULE_DELTA_alter().
+ *
+ * Adds the OpenID login form to the user login block.
  */
-function openid_form_user_login_block_alter(&$form, &$form_state) {
-  _openid_user_login_form_alter($form, $form_state);
+function openid_block_view_user_login_alter(&$block) {
+  // Only alter the block when it is non-empty, i.e. when no user is logged in.
+  if (!isset($block['content'])) {
+    return;
+  }
+
+  $block['content']['openid_login_form'] = drupal_get_form('openid_login_form');
+  $block['content']['openid_login_form']['#action'] .= '#openid-login';
+  $block['content']['openid_login_form']['openid_identifier']['#size'] = $block['content']['user_login']['name']['#size'];
+
+  // Add links between the forms.
+  $block['content']['user_login']['openid_link'] = array(
+    '#type' => 'link',
+    '#title' => t('Log in using OpenID'),
+    '#href' => '#openid-login',
+    '#options' => array('external' => TRUE),
+    '#attributes' => array('class' => array('openid-link')),
+    '#attached' => array('css' => array(
+      drupal_get_path('module', 'openid') . '/openid.css'),
+    ),
+    '#weight' => 10,
+  );
+  $block['content']['openid_login_form']['user_link'] = array(
+    '#type' => 'link',
+    '#title' => t('Cancel OpenID login'),
+    '#href' => '#',
+    '#options' => array('external' => TRUE),
+    '#attributes' => array('class' => array('user-link')),
+    '#weight' => 10,
+  );
+  $block['content']['openid_login_form']['#states'] = array(
+    'visible' => array(
+      'window' => array('hash' => '#openid-login'),
+    ),
+  );
+  $block['content']['user_login']['#states'] = array(
+    'invisible' => array(
+      'window' => array('hash' => '#openid-login'),
+    ),
+  );
 }
 
 /**
- * Implements hook_form_FORM_ID_alter().
+ * Form constructor for the OpenID login form.
  */
-function openid_form_user_login_alter(&$form, &$form_state) {
-  _openid_user_login_form_alter($form, $form_state);
-}
-
-function _openid_user_login_form_alter(&$form, &$form_state) {
+function openid_login_form($form) {
   $form['#attached']['css'][] = drupal_get_path('module', 'openid') . '/openid.css';
   $form['#attached']['js'][] = drupal_get_path('module', 'openid') . '/openid.js';
   $form['#attached']['library'][] = array('system', 'jquery.cookie');
-  if (!empty($form_state['input']['openid_identifier'])) {
-    $form['name']['#required'] = FALSE;
-    $form['pass']['#required'] = FALSE;
-    unset($form['#submit']);
-    $form['#validate'] = array('openid_login_validate');
-  }
-
-  $items = array();
-  $items[] = array(
-    'data' => l(t('Log in using OpenID'), '#openid-login', array('external' => TRUE)),
-    'class' => array('openid-link'),
-  );
-  $items[] = array(
-    'data' => l(t('Cancel OpenID login'), '#', array('external' => TRUE)),
-    'class' => array('user-link'),
-  );
-
-  $form['openid_links'] = array(
-    '#theme' => 'item_list',
-    '#items' => $items,
-    '#attributes' => array('class' => array('openid-links')),
-    '#weight' => 1,
-  );
-
-  $form['links']['#weight'] = 2;
 
   $form['openid_identifier'] = array(
     '#type' => 'textfield',
-    '#title' => t('Log in using OpenID'),
-    '#size' => $form['name']['#size'],
+    '#title' => t('OpenID'),
     '#maxlength' => 255,
-    '#weight' => -1,
     '#description' => l(t('What is OpenID?'), 'http://openid.net/', array('external' => TRUE)),
+    '#required' => TRUE,
   );
-  $form['openid.return_to'] = array('#type' => 'hidden', '#value' => url('openid/authenticate', array('absolute' => TRUE, 'query' => user_login_destination())));
+
+  $form['openid.return_to'] = array(
+    '#type' => 'hidden',
+    '#value' => url('openid/authenticate', array('absolute' => TRUE, 'query' => user_login_destination())),
+  );
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Log in'));
+
+  return $form;
 }
 
 /**
@@ -291,9 +317,9 @@ function openid_form_user_register_form_alter(&$form, &$form_state) {
 }
 
 /**
- * Login form _validate hook
+ * Form submit handler for openid_login_form().
  */
-function openid_login_validate($form, &$form_state) {
+function openid_login_form_submit($form, &$form_state) {
   $return_to = $form_state['values']['openid.return_to'];
   if (empty($return_to)) {
     $return_to = url('', array('absolute' => TRUE));
diff --git a/core/modules/openid/openid.test b/core/modules/openid/openid.test
index 24e643f..2131b03 100644
--- a/core/modules/openid/openid.test
+++ b/core/modules/openid/openid.test
@@ -47,7 +47,7 @@ abstract class OpenIDWebTestCase extends DrupalWebTestCase {
   function submitLoginForm($identity) {
     // Fill out and submit the login form.
     $edit = array('openid_identifier' => $identity);
-    $this->drupalPost('', $edit, t('Log in'));
+    $this->drupalPost('', $edit, t('Log in'), array(), array(), 'openid-login-form');
 
     // Check we are on the OpenID redirect form.
     $this->assertTitle(t('OpenID redirect'), t('OpenID redirect page was displayed.'));
@@ -82,7 +82,10 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
   }
 
   function setUp() {
-    parent::setUp('openid', 'openid_test');
+    parent::setUp('openid', 'openid_test', 'node');
+
+    // Use a different front page than login page.
+    variable_set('site_frontpage', 'node');
 
     // User doesn't need special permissions; only the ability to log in.
     $this->web_user = $this->drupalCreateUser(array());
@@ -207,9 +210,9 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
 
     $this->drupalLogout();
 
-    // Test logging in via the user/login page.
+    // Test logging in via the user/login/openid page.
     $edit = array('openid_identifier' => $identity);
-    $this->drupalPost('user/login', $edit, t('Log in'));
+    $this->drupalPost('user/login/openid', $edit, t('Log in'));
 
     // Check we are on the OpenID redirect form.
     $this->assertTitle(t('OpenID redirect'), t('OpenID redirect page was displayed.'));
@@ -219,7 +222,8 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
 
     $this->assertLink(t('Log out'), 0, t('User was logged in.'));
 
-    // Verify user was redirected away from user/login to an accessible page.
+    // Verify user was redirected away from user/login/openid to an accessible
+    // page.
     $this->assertResponse(200);
 
     $this->drupalLogout();
@@ -249,9 +253,9 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
     // Enable maintenance mode.
     variable_set('maintenance_mode', 1);
 
-    // Test logging in via the user/login page while the site is offline.
+    // Test logging in via the user/login/openid page while the site is offline.
     $edit = array('openid_identifier' => $identity);
-    $this->drupalPost('user/login', $edit, t('Log in'));
+    $this->drupalPost('user/login/openid', $edit, t('Log in'));
 
     // Check we are on the OpenID redirect form.
     $this->assertTitle(t('OpenID redirect'), t('OpenID redirect page was displayed.'));
@@ -261,7 +265,8 @@ class OpenIDFunctionalTestCase extends OpenIDWebTestCase {
 
     $this->assertLink(t('Log out'), 0, t('User was logged in.'));
 
-    // Verify user was redirected away from user/login to an accessible page.
+    // Verify user was redirected away from user/login/openid to an accessible
+    // page.
     $this->assertText(t('Operating in maintenance mode.'));
     $this->assertResponse(200);
   }
@@ -454,8 +459,11 @@ class OpenIDRegistrationTestCase extends OpenIDWebTestCase {
 
   function setUp() {
     // Add language module too to test with some non-built-in languages.
-    parent::setUp('openid', 'openid_test', 'language');
+    parent::setUp('openid', 'openid_test', 'language', 'node');
     variable_set('user_register', USER_REGISTER_VISITORS);
+
+    // Use a different front page than login page.
+    variable_set('site_frontpage', 'node');
   }
 
   /**
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 3b1d9cb..5fc2a2a 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1185,33 +1185,22 @@ function user_user_presave(&$edit, $account) {
   }
 }
 
-function user_login_block($form) {
-  $form['#action'] = url($_GET['q'], array('query' => drupal_get_destination()));
-  $form['#id'] = 'user-login-form';
-  $form['#validate'] = user_login_default_validators();
-  $form['#submit'][] = 'user_login_submit';
-  $form['name'] = array('#type' => 'textfield',
-    '#title' => t('Username'),
-    '#maxlength' => USERNAME_MAX_LENGTH,
-    '#size' => 15,
-    '#required' => TRUE,
-  );
-  $form['pass'] = array('#type' => 'password',
-    '#title' => t('Password'),
-    '#maxlength' => 60,
-    '#size' => 15,
-    '#required' => TRUE,
-  );
-  $form['actions'] = array('#type' => 'actions');
-  $form['actions']['submit'] = array('#type' => 'submit',
-    '#value' => t('Log in'),
-  );
+function user_login_block() {
+  $form['user_login'] = drupal_get_form('user_login');
+  $form['user_login']['#action'] = url($_GET['q'], array('query' => drupal_get_destination()));
+
+  $form['user_login']['name']['#size'] = 15;
+  $form['user_login']['pass']['#size'] = 15;
+  unset($form['user_login']['name']['#description']);
+  unset($form['user_login']['pass']['#description']);
+
   $items = array();
   if (variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)) {
     $items[] = l(t('Create new account'), 'user/register', array('attributes' => array('title' => t('Create a new user account.'))));
   }
   $items[] = l(t('Request new password'), 'user/password', array('attributes' => array('title' => t('Request new password via e-mail.'))));
-  $form['links'] = array('#theme' => 'item_list', '#items' => $items);
+  $form['links'] = array('#theme' => 'item_list', '#items' => $items, '#weight' => 100);
+
   return $form;
 }
 
@@ -1292,7 +1281,7 @@ function user_block_view($delta = '') {
       if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {
 
         $block['subject'] = t('User login');
-        $block['content'] = drupal_get_form('user_login_block');
+        $block['content'] = user_login_block();
       }
       return $block;
 
@@ -1643,6 +1632,12 @@ function user_menu() {
     'access callback' => 'user_is_anonymous',
     'type' => MENU_DEFAULT_LOCAL_TASK,
   );
+  // Other authentication methods may add pages below user/login/.
+  $items['user/login/default'] = array(
+    'title' => 'Log in using username and password',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -1,
+  );
 
   $items['user/register'] = array(
     'title' => 'Create new account',
@@ -3856,7 +3851,8 @@ function user_modules_uninstalled($modules) {
  */
 function user_login_destination() {
   $destination = drupal_get_destination();
-  if ($destination['destination'] == 'user/login') {
+  // Modules may provide login pages under the "user/login/" path prefix.
+  if (preg_match('@^user/login(/.*|)$@', $destination['destination'])) {
     $destination['destination'] = 'user';
   }
   return $destination;
