Index: /CKEditor/branches/features/aria/_source/core/dom/node.js
===================================================================
--- /CKEditor/branches/features/aria/_source/core/dom/node.js	(revision 4976)
+++ /CKEditor/branches/features/aria/_source/core/dom/node.js	(revision 4977)
@@ -26,4 +26,8 @@
 		switch ( domNode.nodeType )
 		{
+			// Safari don't consider document as element node type(#3389).
+			case CKEDITOR.NODE_DOCUMENT :
+				return new CKEDITOR.dom.document( domNode );
+
 			case CKEDITOR.NODE_ELEMENT :
 				return new CKEDITOR.dom.element( domNode );
@@ -48,4 +52,11 @@
  */
 CKEDITOR.NODE_ELEMENT = 1;
+
+/**
+ * Document node type.
+ * @constant
+ * @example
+ */
+CKEDITOR.NODE_DOCUMENT = 9;
 
 /**
Index: /CKEditor/branches/features/aria/_source/plugins/contextmenu/plugin.js
===================================================================
--- /CKEditor/branches/features/aria/_source/plugins/contextmenu/plugin.js	(revision 4976)
+++ /CKEditor/branches/features/aria/_source/plugins/contextmenu/plugin.js	(revision 4977)
@@ -82,10 +82,27 @@
 				}, this );
 
-				menu.onEscape = function()
-				{
-					editor.focus();
-
-					if ( CKEDITOR.env.ie )
-						editor.getSelection().unlock( true );
+				menu.onEscape = function( keystroke )
+				{
+					var parent = this.parent;
+					// 1. If it's sub-menu, restore the last focused item
+					// of upper level menu.
+					// 2. In case of a top-menu, close it.
+					if( parent )
+					{
+						parent._.panel.hideChild();
+						// Restore parent block item focus.
+						var parentBlock = parent._.panel._.panel._.currentBlock,
+							parentFocusIndex =  parentBlock._.focusIndex;
+						parentBlock._.markItem( parentFocusIndex );
+					}
+					else if ( keystroke == 27 )
+					{
+						this.hide();
+						editor.focus();
+	
+						if ( CKEDITOR.env.ie )
+							editor.getSelection().unlock( true );
+					}
+					return false;
 				};
 			}
@@ -218,5 +235,5 @@
 					CKEDITOR.tools.setTimeout( function()
 						{
-							this._.onMenu( offsetParent, null, offsetX, offsetY );
+							this.show( offsetParent, null, offsetX, offsetY );
 						},
 						0, this );
Index: /CKEditor/branches/features/aria/_source/plugins/floatpanel/plugin.js
===================================================================
--- /CKEditor/branches/features/aria/_source/plugins/floatpanel/plugin.js	(revision 4976)
+++ /CKEditor/branches/features/aria/_source/plugins/floatpanel/plugin.js	(revision 4977)
@@ -156,8 +156,8 @@
 							// inside the window itself, so we must ensure the
 							// target is out of it.
-							var target = ev.data.getTarget(),
-								targetWindow = target.getWindow && target.getWindow();
-
-							if ( targetWindow && targetWindow.equals( focused ) )
+							var target;
+							if ( CKEDITOR.env.ie && !this.allowBlur()
+								 || ( target = ev.data.getTarget() )
+								      && target.getName && target.getName() != 'iframe' )
 								return;
 
@@ -180,7 +180,8 @@
 				}
 
-				panel.onEscape = CKEDITOR.tools.bind( function()
+				panel.onEscape = CKEDITOR.tools.bind( function( keystroke )
 					{
-						this.onEscape && this.onEscape();
+						if ( this.onEscape && this.onEscape( keystroke ) === false );
+							return false;
 					},
 					this );
Index: /CKEditor/branches/features/aria/_source/plugins/menu/plugin.js
===================================================================
--- /CKEditor/branches/features/aria/_source/plugins/menu/plugin.js	(revision 4976)
+++ /CKEditor/branches/features/aria/_source/plugins/menu/plugin.js	(revision 4977)
@@ -90,4 +90,8 @@
 					return;
 				}
+
+				// Record parent menu focused item first (#3389).
+				var block = this._.panel.getBlock( this.id );
+				block._.focusIndex = index;
 
 				// Create the submenu, if not available, or clean the existing
@@ -101,4 +105,6 @@
 					menu.parent = this;
 					menu.onClick = CKEDITOR.tools.bind( this.onClick, this );
+					// Sub menu use their own scope for binding onEscape.
+					menu.onEscape = this.onEscape;
 				}
 
@@ -155,8 +161,8 @@
 						this._.level );
 
-					panel.onEscape = CKEDITOR.tools.bind( function()
+					panel.onEscape = CKEDITOR.tools.bind( function( keystroke )
 					{
-						this.onEscape && this.onEscape();
-						this.hide();
+						if ( this.onEscape && this.onEscape( keystroke ) === false )
+							return false;
 					},
 					this );
@@ -178,5 +184,5 @@
 					keys[ CKEDITOR.SHIFT + 9 ]	= 'prev';	// SHIFT + TAB
 					keys[ 32 ]	= 'click';					// SPACE
-					keys[ 39 ]	= 'click';					// ARROW-RIGHT
+					keys[ ( editor.lang.dir == 'rtl' ? 37 : 39 ) ]	= 'click';  // ARROW-RIGHT/ARROW-LEFT(rtl)
 
 					element = this._.element = block.element;
Index: /CKEditor/branches/features/aria/_source/plugins/panel/plugin.js
===================================================================
--- /CKEditor/branches/features/aria/_source/plugins/panel/plugin.js	(revision 4976)
+++ /CKEditor/branches/features/aria/_source/plugins/panel/plugin.js	(revision 4977)
@@ -171,5 +171,6 @@
 				doc.on( 'keydown', function( evt )
 					{
-						var keystroke = evt.data.getKeystroke();
+						var keystroke = evt.data.getKeystroke(),
+							dir = this.document.getById( 'cke_' + this.id ).getAttribute( 'dir' );
 
 						// Delegate key processing to block.
@@ -180,6 +181,8 @@
 						}
 
-						if ( keystroke == 27 )		// ESC
-							this.onEscape && this.onEscape();
+						// ESC/ARROW-LEFT(ltr) OR ARROW-RIGHT(rtl)
+						if ( keystroke == 27 || keystroke == ( dir == 'rtl' ? 39 : 37 ) )
+							if ( this.onEscape && this.onEscape( keystroke ) === false );
+								evt.data.preventDefault();
 					},
 					this );
@@ -270,5 +273,23 @@
 	},
 
-	_ : {},
+	_ : {
+		
+		/**
+		 * Mark the item specified by the index as current activated. 
+		 */
+		markItem: function( index )
+		{
+			if ( index == -1 )
+				return;
+			var links = this.element.getElementsByTag( 'a' );
+			var item = links.getItem( this._.focusIndex = index );
+
+			// Safari need focus on the iframe window first(#3389), but we need
+			// lock the blur to avoid hiding the panel.
+			if ( CKEDITOR.env.webkit )
+				item.getDocument().getWindow().focus();
+			item.focus();
+		}
+	},
 
 	proto :
