Index: /CKEditor/trunk/CHANGES.html
===================================================================
--- /CKEditor/trunk/CHANGES.html	(revision 4033)
+++ /CKEditor/trunk/CHANGES.html	(revision 4034)
@@ -224,4 +224,5 @@
 		<li><a href="http://dev.fckeditor.net/ticket/4164">#4164</a> : Now it is possible to paste text 
 			in Source mode even if forcePasteAsPlainText = true.</li>
+		<li><a href="http://dev.fckeditor.net/ticket/4129">#4129</a> : [FF]Unable to remove list with Ctrl-A.</li>
 	</ul>
 	<h3>
Index: /CKEditor/trunk/_source/core/dom/element.js
===================================================================
--- /CKEditor/trunk/_source/core/dom/element.js	(revision 4033)
+++ /CKEditor/trunk/_source/core/dom/element.js	(revision 4034)
@@ -642,14 +642,14 @@
 
 		/**
-		 * @param ignoreEmpty Skip empty text nodes.
-		 */
-		getLast : function( ignoreEmpty )
-		{
-			var $ = this.$.lastChild;
-			if ( ignoreEmpty && $ && ( $.nodeType == CKEDITOR.NODE_TEXT )
-					&& !CKEDITOR.tools.trim( $.nodeValue ) )
-				return new CKEDITOR.dom.node( $ ).getPrevious( true );
-			else
-				return $ ? new CKEDITOR.dom.node( $ ) : null;
+		 * @param {Function} evaluator Filtering the result node.
+		 */
+		getLast : function( evaluator )
+		{
+			var last = this.$.lastChild,
+				retval = last && new CKEDITOR.dom.node( last );
+			if ( retval && evaluator && !evaluator( retval ) )
+				retval = retval.getPrevious( evaluator );
+
+			return retval;
 		},
 
Index: /CKEditor/trunk/_source/core/dom/range.js
===================================================================
--- /CKEditor/trunk/_source/core/dom/range.js	(revision 4033)
+++ /CKEditor/trunk/_source/core/dom/range.js	(revision 4034)
@@ -1609,4 +1609,23 @@
 		},
 
+		/**
+		 * Get the single node enclosed within the range if there's one.
+		 */
+		getEnclosedNode : function()
+		{
+			var walkerRange = this.clone(),
+				walker = new CKEDITOR.dom.walker( walkerRange ),
+				isNotBookmarks = CKEDITOR.dom.walker.bookmark( true ),
+				isNotWhitespaces = CKEDITOR.dom.walker.whitespaces( true ),
+				evaluator = function( node )
+				{
+					return isNotWhitespaces( node ) && isNotBookmarks( node );
+				};
+			walkerRange.evaluator = evaluator;
+			var node = walker.next();
+			walker.reset();
+			return node && node.equals( walker.previous() ) ? node : null;
+		},
+
 		getTouchedStartNode : function()
 		{
Index: /CKEditor/trunk/_source/core/dom/walker.js
===================================================================
--- /CKEditor/trunk/_source/core/dom/walker.js	(revision 4033)
+++ /CKEditor/trunk/_source/core/dom/walker.js	(revision 4034)
@@ -305,4 +305,10 @@
 			{
 				return iterateToLast.call( this, true );
+			},
+
+			reset : function()
+			{
+				delete this.current;
+				this._ = {};
 			}
 
Index: /CKEditor/trunk/_source/plugins/domiterator/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/domiterator/plugin.js	(revision 4033)
+++ /CKEditor/trunk/_source/plugins/domiterator/plugin.js	(revision 4034)
@@ -84,6 +84,6 @@
 				if ( !this._.lastNode )
 				{
-						this._.lastNode = range.document.createText( '' );
-						this._.lastNode.insertAfter( lastNode );
+					this._.lastNode = this._.docEndMarker = range.document.createText( '' );
+					this._.lastNode.insertAfter( lastNode );
 				}
 
@@ -240,4 +240,5 @@
 				if ( !range )
 				{
+					this._.docEndMarker && this._.docEndMarker.remove();
 					this._.nextNode = null;
 					return null;
Index: /CKEditor/trunk/_source/plugins/list/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/list/plugin.js	(revision 4033)
+++ /CKEditor/trunk/_source/plugins/list/plugin.js	(revision 4034)
@@ -403,4 +403,16 @@
 					selection.selectRanges( ranges );
 				}
+				// Maybe a single range there enclosing the whole list,
+				// turn on the list state manually(#4129).
+				else
+				{
+					var range = ranges.length == 1 && ranges[ 0 ],
+						enclosedNode = range && range.getEnclosedNode();
+					if ( enclosedNode && enclosedNode.is
+						&& this.type == enclosedNode.getName() )
+					{
+						setState.call( this, editor, CKEDITOR.TRISTATE_ON );
+					}
+				}
 			}
 
Index: /CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js	(revision 4033)
+++ /CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js	(revision 4034)
@@ -191,5 +191,5 @@
 		// Inserting the padding-br before body if it's preceded by an
 		// unexitable block.
-		var lastNode = body.getLast( true );
+		var lastNode = body.getLast( CKEDITOR.dom.walker.whitespaces( true ) );
 		if ( lastNode && lastNode.getName && ( lastNode.getName() in nonExitableElementNames ) )
 		{
Index: /CKEditor/trunk/_source/tests/core/dom/element.html
===================================================================
--- /CKEditor/trunk/_source/tests/core/dom/element.html	(revision 4033)
+++ /CKEditor/trunk/_source/tests/core/dom/element.html	(revision 4034)
@@ -542,4 +542,17 @@
 			}
 		},
+
+		// Test get last non-spaces child node.
+		test_getLast : function()
+		{
+			var element = new CKEDITOR.dom.element( document.getElementById( 'append' ) );
+			var span1 = new CKEDITOR.dom.element( 'span' );
+			element.append( span1 );
+			element.append( new CKEDITOR.dom.text( ' ' ) );
+			element.append( new CKEDITOR.dom.text( ' ' ) );
+			var last = element.getLast( CKEDITOR.dom.walker.whitespaces( true ) );
+			assert.areSame( span1.$, last.$ );
+		},
+
 
 		name : document.title
Index: /CKEditor/trunk/_source/tests/plugins/list/list.html
===================================================================
--- /CKEditor/trunk/_source/tests/plugins/list/list.html	(revision 4033)
+++ /CKEditor/trunk/_source/tests/plugins/list/list.html	(revision 4034)
@@ -117,4 +117,6 @@
 							var sel = editor.getSelection();
 							sel.selectRanges( [ range ] );
+							editor.selectionChange();
+
 							// Waiting for 'comand state' effected.
 							this.wait( function(){
@@ -149,4 +151,5 @@
 							var sel = editor.getSelection();
 							sel.selectRanges( [ range ] );
+							editor.selectionChange();
 
 							// Waiting for 'comand state' effected.
@@ -182,4 +185,5 @@
 							var sel = editor.getSelection();
 							sel.selectRanges( [ range ] );
+							editor.selectionChange();
 
 							// Waiting for 'comand state' effected.
