Index: CKEditor/trunk/CHANGES.html
===================================================================
--- CKEditor/trunk/CHANGES.html	(revision 5253)
+++ CKEditor/trunk/CHANGES.html	(revision 5255)
@@ -77,4 +77,5 @@
 		<li><a href="http://dev.fckeditor.net/ticket/4711">#4711</a> : Line break inside preformatted text make it unable to type text at the end of previous line.</li>
 		<li><a href="http://dev.fckeditor.net/ticket/4829">#4829</a> : [IE] Apply style from combo has wrong result on manual created selection.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4830">#4830</a> : Retrieving selected element isn't always right, especially selecting using keyboard (SHIFT+ARROW).</li>
 	</ul>
 	<h3>
Index: CKEditor/trunk/_source/core/dom/range.js
===================================================================
--- CKEditor/trunk/_source/core/dom/range.js	(revision 5253)
+++ CKEditor/trunk/_source/core/dom/range.js	(revision 5255)
@@ -1,3 +1,3 @@
-﻿/*
+/*
 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.html or http://ckeditor.com/license
@@ -1237,4 +1237,96 @@
 
 		/**
+		 *  Descrease the range to make sure that boundaries
+		 *  always anchor beside text nodes or innermost element.
+		 * @param {Number} mode  ( CKEDITOR.SHRINK_ELEMENT | CKEDITOR.SHRINK_TEXT ) The shrinking mode.
+		 */
+		shrink : function( mode )
+		{
+			// Unable to shrink a collapsed range.
+			if ( !this.collapsed )
+			{
+				mode = mode || CKEDITOR.SHRINK_TEXT;
+
+				var walkerRange = this.clone();
+
+				var startContainer = this.startContainer,
+					endContainer = this.endContainer,
+					startOffset = this.startOffset,
+					endOffset = this.endOffset,
+					collapsed = this.collapsed;
+
+				// Whether the start/end boundary is moveable.
+				var moveStart = 1,
+						moveEnd = 1;
+
+				if ( startContainer && startContainer.type == CKEDITOR.NODE_TEXT )
+				{
+					if ( !startOffset )
+						walkerRange.setStartBefore( startContainer );
+					else if ( startOffset >= startContainer.getLength( ) )
+						walkerRange.setStartAfter( startContainer );
+					else
+					{
+						// Enlarge the range properly to avoid walker making
+						// DOM changes caused by triming the text nodes later.
+						walkerRange.setStartBefore( startContainer );
+						moveStart = 0;
+					}
+				}
+				
+				if ( endContainer && endContainer.type == CKEDITOR.NODE_TEXT )
+				{
+					if ( !endOffset )
+						walkerRange.setEndBefore( endContainer );
+					else if ( endOffset >= endContainer.getLength( ) )
+						walkerRange.setEndAfter( endContainer );
+					else
+					{
+						walkerRange.setEndAfter( endContainer );
+						moveEnd = 0;
+					}
+				}
+
+				var walker = new CKEDITOR.dom.walker( walkerRange );
+
+				walker.evaluator = function( node )
+				{
+					return node.type == ( mode == CKEDITOR.SHRINK_ELEMENT ?
+						CKEDITOR.NODE_ELEMENT : CKEDITOR.NODE_TEXT );
+				};
+
+				var currentElement;
+				walker.guard = function( node, movingOut )
+				{
+					// Stop when we're shrink in element mode while encountering a text node.
+					if ( mode == CKEDITOR.SHRINK_ELEMENT && node.type == CKEDITOR.NODE_TEXT )
+						return false;
+
+					// Stop when we've already walked "through" an element.
+					if ( movingOut && node.equals( currentElement ) )
+						return false;
+
+					if ( !movingOut && node.type == CKEDITOR.NODE_ELEMENT )
+						currentElement = node;
+				};
+
+				if ( moveStart )
+				{
+					var textStart = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastForward' : 'next']();
+					textStart && this.setStartBefore( textStart );
+				}
+
+				if ( moveEnd )
+				{
+					walker.reset();
+					var textEnd = walker[ mode == CKEDITOR.SHRINK_ELEMENT ? 'lastBackward' : 'previous']();
+					textEnd && this.setEndAfter( textEnd );
+				}
+
+				return !!( moveStart || moveEnd );
+			}
+		},
+
+		/**
 		 * Inserts a node at the start of the range. The range will be expanded
 		 * the contain the node.
@@ -1734,2 +1826,6 @@
 CKEDITOR.END = 2;
 CKEDITOR.STARTEND = 3;
+
+CKEDITOR.SHRINK_ELEMENT = 1;
+CKEDITOR.SHRINK_TEXT = 2;
+
Index: CKEditor/trunk/_source/core/dom/walker.js
===================================================================
--- CKEditor/trunk/_source/core/dom/walker.js	(revision 5253)
+++ CKEditor/trunk/_source/core/dom/walker.js	(revision 5255)
@@ -102,5 +102,5 @@
 				}
 				else
-					node = ( guard ( node ) === false ) ?
+					node = ( guard ( node, true ) === false ) ?
 						null : node.getPreviousSourceNode( true, type, guard );
 			}
@@ -116,5 +116,5 @@
 				}
 				else
-					node = ( guard ( range.startContainer ) === false ) ?
+					node = ( guard ( range.startContainer, true ) === false ) ?
 						null : range.startContainer.getNextSourceNode( true, type, guard ) ;
 			}
Index: CKEditor/trunk/_source/plugins/selection/plugin.js
===================================================================
--- CKEditor/trunk/_source/plugins/selection/plugin.js	(revision 5253)
+++ CKEditor/trunk/_source/plugins/selection/plugin.js	(revision 5255)
@@ -731,25 +731,30 @@
 				return cache.selectedElement;
 
-			var node;
-
-			if ( this.getType() == CKEDITOR.SELECTION_ELEMENT )
-			{
-				var sel = this.getNative();
-
-				if ( CKEDITOR.env.ie )
-				{
-					try
-					{
-						node = sel.createRange().item(0);
+			var self = this;
+
+			var node = CKEDITOR.tools.tryThese(
+				// Is it native IE control type selection?
+				function()
+				{
+					return self.getNative().createRange().item( 0 );
+				},
+				// Figure it out by checking if there's a single enclosed
+				// node of the range.
+				function()
+				{
+					var range  = self.getRanges()[ 0 ];
+					range.shrink( CKEDITOR.SHRINK_ELEMENT );
+
+					var enclosed;
+					if ( range.startContainer.equals( range.endContainer )
+						&& ( range.endOffset - range.startOffset ) == 1
+						&& styleObjectElements[ ( enclosed = range.startContainer.getChild( range.startOffset ) ).getName() ] )
+					{
+						return enclosed.$;
 					}
-					catch(e) {}
-				}
-				else
-				{
-					var range = sel.getRangeAt( 0 );
-					node = range.startContainer.childNodes[ range.startOffset ];
-				}
-			}
-
+					else
+						throw '';
+				});
+			
 			return cache.selectedElement = ( node ? new CKEDITOR.dom.element( node ) : null );
 		},
