Index: wp-includes/js/jquery/jquery.menu-aim.js
===================================================================
--- wp-includes/js/jquery/jquery.menu-aim.js	(revision 0)
+++ wp-includes/js/jquery/jquery.menu-aim.js	(working copy)
@@ -0,0 +1,264 @@
+/**
+ * menu-aim is a jQuery plugin for dropdown menus that can differentiate
+ * between a user trying hover over a dropdown item vs trying to navigate into
+ * a submenu's contents.
+ *
+ * menu-aim assumes that you have are using a menu with submenus that expand
+ * to the menu's right. It will fire events when the user's mouse enters a new
+ * dropdown item *and* when that item is being intentionally hovered over.
+ *
+ * __________________________
+ * | Monkeys  >|   Gorilla  |
+ * | Gorillas >|   Content  |
+ * | Chimps   >|   Here     |
+ * |___________|____________|
+ *
+ * In the above example, "Gorillas" is selected and its submenu content is
+ * being shown on the right. Imagine that the user's cursor is hovering over
+ * "Gorillas." When they move their mouse into the "Gorilla Content" area, they
+ * may briefly hover over "Chimps." This shouldn't close the "Gorilla Content"
+ * area.
+ *
+ * This problem is normally solved using timeouts and delays. menu-aim tries to
+ * solve this by detecting the direction of the user's mouse movement. This can
+ * make for quicker transitions when navigating up and down the menu. The
+ * experience is hopefully similar to amazon.com/'s "Shop by Department"
+ * dropdown.
+ *
+ * Use like so:
+ *
+ *      $("#menu").menuAim({
+ *          activate: $.noop,  // fired on row activation
+ *          deactivate: $.noop,  // fired on row deactivation
+ *      });
+ *
+ *  ...to receive events when a menu's row has been purposefully (de)activated.
+ *
+ * The following options can be passed to menuAim. All functions execute with
+ * the relevant row's HTML element as the execution context ('this'):
+ *
+ *      .menuAim({
+ *          // Function to call when a row is purposefully activated. Use this
+ *          // to show a submenu's content for the activated row.
+ *          activate: function() {},
+ *
+ *          // Function to call when a row is deactivated.
+ *          deactivate: function() {},
+ *
+ *          // Function to call when mouse enters a menu row. Entering a row
+ *          // does not mean the row has been activated, as the user may be
+ *          // mousing over to a submenu.
+ *          enter: function() {},
+ *
+ *          // Function to call when mouse exits a menu row.
+ *          exit: function() {},
+ *
+ *          // Selector for identifying which elements in the menu are rows
+ *          // that can trigger the above events. Defaults to "> li".
+ *          rowSelector: "> li",
+ *
+ *          // You may have some menu rows that aren't submenus and therefore
+ *          // shouldn't ever need to "activate." If so, filter submenu rows w/
+ *          // this selector. Defaults to "*" (all elements).
+ *          submenuSelector: "*"
+ *      });
+ *
+ * https://github.com/kamens/jQuery-menu-aim
+*/
+(function($) {
+    $.fn.menuAim = function(opts) {
+
+        var $menu = $(this),
+            activeRow = null,
+            mouseLocs = [],
+            lastDelayLoc = null,
+            timeoutId = null,
+            options = $.extend({
+                rowSelector: "> li",
+                submenuSelector: "*",
+                tolerance: 75,  // bigger = more forgivey when entering submenu
+                enter: $.noop,
+                exit: $.noop,
+                activate: $.noop,
+                deactivate: $.noop
+            }, opts);
+
+        var MOUSE_LOCS_TRACKED = 3,  // number of past mouse locations to track
+            DELAY = 300;  // ms delay when user appears to be entering submenu
+
+        /**
+         * Keep track of the last few locations of the mouse.
+         */
+        var mousemoveDocument = function(e) {
+                mouseLocs.push({x: e.pageX, y: e.pageY});
+
+                if (mouseLocs.length > MOUSE_LOCS_TRACKED) {
+                    mouseLocs.shift();
+                }
+            };
+
+        /**
+         * Cancel possible row activations when leaving the menu entirely
+         */
+        var mouseleaveMenu = function() {
+                if (timeoutId) {
+                    clearTimeout(timeoutId);
+                }
+            };
+
+        /**
+         * Trigger a possible row activation whenever entering a new row.
+         */
+        var mouseenterRow = function() {
+                if (timeoutId) {
+                    // Cancel any previous activation delays
+                    clearTimeout(timeoutId);
+                }
+
+                options.enter(this);
+                possiblyActivate(this);
+            },
+            mouseleaveRow = function() {
+                options.exit(this);
+            };
+
+        /**
+         * Activate a menu row.
+         */
+        var activate = function(row) {
+                if (row == activeRow) {
+                    return;
+                }
+
+                if (activeRow) {
+                    options.deactivate(activeRow);
+                }
+
+                options.activate(row);
+                activeRow = row;
+            };
+
+        /**
+         * Possibly activate a menu row. If mouse movement indicates that we
+         * shouldn't activate yet because user may be trying to enter
+         * a submenu's content, then delay and check again later.
+         */
+        var possiblyActivate = function(row) {
+                var delay = activationDelay();
+
+                if (delay) {
+                    timeoutId = setTimeout(function() {
+                        possiblyActivate(row);
+                    }, delay);
+                } else {
+                    activate(row);
+                }
+            };
+
+        /**
+         * Return the amount of time that should be used as a delay before the
+         * currently hovered row is activated.
+         *
+         * Returns 0 if the activation should happen immediately. Otherwise,
+         * returns the number of milliseconds that should be delayed before
+         * checking again to see if the row should be activated.
+         */
+        var activationDelay = function() {
+                if (!activeRow || !$(activeRow).is(options.submenuSelector)) {
+                    // If there is no other submenu row already active, then
+                    // go ahead and activate immediately.
+                    return 0;
+                }
+
+                var offset = $menu.offset(),
+                    upperRight = {
+                        x: offset.left + $menu.outerWidth(),
+                        y: offset.top - options.tolerance
+                    },
+                    lowerRight = {
+                        x: offset.left + $menu.outerWidth(),
+                        y: offset.top + $menu.outerHeight() + options.tolerance
+                    },
+                    loc = mouseLocs[mouseLocs.length - 1],
+                    prevLoc = mouseLocs[0];
+
+                if (!loc) {
+                    return 0;
+                }
+
+                if (!prevLoc) {
+                    prevLoc = loc;
+                }
+
+                if (prevLoc.x < offset.left || prevLoc.x > lowerRight.x ||
+                    prevLoc.y < offset.top || prevLoc.y > lowerRight.y) {
+                    // If the previous mouse location was outside of the entire
+                    // menu's bounds, immediately activate.
+                    return 0;
+                }
+
+                if (lastDelayLoc &&
+                        loc.x == lastDelayLoc.x && loc.y == lastDelayLoc.y) {
+                    // If the mouse hasn't moved since the last time we checked
+                    // for activation status, immediately activate.
+                    return 0;
+                }
+
+                // Detect if the user is moving towards the currently activated
+                // submenu.
+                //
+                // If the mouse is heading relatively clearly towards
+                // the submenu's content, we should wait and give the user more
+                // time before activating a new row. If the mouse is heading
+                // elsewhere, we can immediately activate a new row.
+                //
+                // We detect this by calculating the slope formed between the
+                // current mouse location and the upper/lower right points of
+                // the menu. We do the same for the previous mouse location.
+                // If the current mouse location's slopes are
+                // increasing/decreasing appropriately compared to the
+                // previous's, we know the user is moving toward the submenu.
+                //
+                // Note that since the y-axis increases as the cursor moves
+                // down the screen, we are looking for the slope between the
+                // cursor and the upper right corner to decrease over time, not
+                // increase (somewhat counterintuitively).
+                function slope(a, b) {
+                    return (b.y - a.y) / (b.x - a.x);
+                };
+
+                var upperSlope = slope(loc, upperRight),
+                    lowerSlope = slope(loc, lowerRight),
+                    prevUpperSlope = slope(prevLoc, upperRight),
+                    prevLowerSlope = slope(prevLoc, lowerRight);
+
+                if (upperSlope < prevUpperSlope &&
+                        lowerSlope > prevLowerSlope) {
+                    // Mouse is moving from previous location towards the
+                    // currently activated submenu. Delay before activating a
+                    // new menu row, because user may be moving into submenu.
+                    lastDelayLoc = loc;
+                    return DELAY;
+                }
+
+                lastDelayLoc = null;
+                return 0;
+            };
+
+        /**
+         * Hook up initial menu events
+         */
+        var init = function() {
+            $menu
+                .mouseleave(mouseleaveMenu)
+                .find(options.rowSelector)
+                    .mouseenter(mouseenterRow)
+                    .mouseleave(mouseleaveRow);
+
+            $(document).mousemove(mousemoveDocument);
+        };
+
+        init();
+        return this;
+    };
+})(jQuery);
Index: wp-includes/script-loader.php
===================================================================
--- wp-includes/script-loader.php	(revision 23659)
+++ wp-includes/script-loader.php	(working copy)
@@ -66,7 +66,7 @@
 		'time' => (string) time(),
 	) );
 
-	$scripts->add( 'common', "/wp-admin/js/common$suffix.js", array('jquery', 'hoverIntent', 'utils'), false, 1 );
+	$scripts->add( 'common', "/wp-admin/js/common$suffix.js", array('jquery', 'hoverIntent', 'jquery-menu-aim', 'utils'), false, 1 );
 	did_action( 'init' ) && $scripts->localize( 'common', 'commonL10n', array(
 		'warnDelete' => __("You are about to permanently delete the selected items.\n  'Cancel' to stop, 'OK' to delete.")
 	) );
@@ -185,6 +185,8 @@
 	$scripts->add( 'jquery-table-hotkeys', "/wp-includes/js/jquery/jquery.table-hotkeys$suffix.js", array('jquery', 'jquery-hotkeys'), false, 1 );
 	$scripts->add( 'jquery-touch-punch', "/wp-includes/js/jquery/jquery.ui.touch-punch.js", array('jquery-ui-widget', 'jquery-ui-mouse'), '0.2.2', 1 );
 	$scripts->add( 'jquery-masonry', "/wp-includes/js/jquery/jquery.masonry.min.js", array('jquery'), '2.1.05', 1 );
+	
+	$scripts->add( 'jquery-menu-aim', "/wp-includes/js/jquery/jquery.menu-aim.js", array('jquery'), '1', 1 );
 
 	$scripts->add( 'thickbox', "/wp-includes/js/thickbox/thickbox.js", array('jquery'), '3.1-20121105', 1 );
 	did_action( 'init' ) && $scripts->localize( 'thickbox', 'thickboxL10n', array(
Index: wp-admin/js/common.js
===================================================================
--- wp-admin/js/common.js	(revision 23659)
+++ wp-admin/js/common.js	(working copy)
@@ -218,7 +218,7 @@
 			}
 		});
 	}
-
+/*
 	menu.find('li.wp-has-submenu').hoverIntent({
 		over: function(e){
 			var b, h, o, f, m = $(this).find('.wp-submenu'), menutop, wintop, maxtop, top = parseInt( m.css('top'), 10 );
@@ -256,7 +256,50 @@
 		sensitivity: 7,
 		interval: 90
 	});
+*/
 
+	menu.menuAim({
+		activate: function(row){
+			var b, h, o, f, m = $(row).find('.wp-submenu'), menutop, wintop, maxtop, top = parseInt( m.css('top'), 10 );
+
+			if ( isNaN(top) || top > -5 ) // meaning the submenu is visible
+				return;
+
+			menutop = $(row).offset().top;
+			wintop = $(window).scrollTop();
+			maxtop = menutop - wintop - 30; // max = make the top of the sub almost touch admin bar
+
+			b = menutop + m.height() + 1; // Bottom offset of the menu
+			h = $('#wpwrap').height(); // Height of the entire page
+			o = 60 + b - h;
+			f = $(window).height() + wintop - 15; // The fold
+
+			if ( f < (b - o) )
+				o = b - f;
+
+			if ( o > maxtop )
+				o = maxtop;
+
+			if ( o > 1 )
+				m.css('margin-top', '-'+o+'px');
+			else
+				m.css('margin-top', '');
+
+			menu.find('li.menu-top').removeClass('opensub');
+			$(row).addClass('opensub');
+		},
+
+		deactivate: function(row) {
+			$(row).removeClass('opensub').find('.wp-submenu').css('margin-top', '');
+		},
+		rowSelector: "> li.menu-top",
+		submenuSelector: "*"
+	});
+
+	menu.on( 'mouseleave', function() {
+		$('.opensub', menu).removeClass('opensub');
+	});
+
 	menu.on('focus.adminmenu', '.wp-submenu a', function(e){
 		$(e.target).closest('li.menu-top').addClass('opensub');
 	}).on('blur.adminmenu', '.wp-submenu a', function(e){
