Index: /CKEditor/branches/prototype/_source/dialogs/testOnly/dialog.js
===================================================================
--- /CKEditor/branches/prototype/_source/dialogs/testOnly/dialog.js	(revision 2650)
+++ /CKEditor/branches/prototype/_source/dialogs/testOnly/dialog.js	(revision 2651)
@@ -17,5 +17,6 @@
 								label : 'Test Text 1',
 								id : 'testText1',
-								'default' : 'hello world!'
+								'default' : 'hello world!',
+								accessKey : 'R'
 							},
 
@@ -94,4 +95,5 @@
 										label : 'Enable this',
 										title : 'Shake it up, just like bad medicine!',
+										accessKey : 'T',
 										checked : false
 									},
@@ -114,4 +116,5 @@
 										title : 'Trying to include a library in LOLCODE.',
 										'default' : 'stdio',
+										accessKey : 'Y',
 										items : [
 											[ 'Standard I/O', 'stdio', 'You need this to write Hello World.' ],
@@ -126,4 +129,5 @@
 										label : 'Click Me',
 										title : 'Click me plz!',
+										accessKey : 'U',
 										onClick : function( evt )
 										{
Index: /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js	(revision 2650)
+++ /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js	(revision 2651)
@@ -96,5 +96,6 @@
 			size : { width : 0, height : 0 },
 			contents : {},
-			buttons : {}
+			buttons : {},
+			accessKeyMap : {}
 		}, true );
 
@@ -410,4 +411,5 @@
 
 		// Maintain the dialog ordering and dialog cover.
+		// Also register key handlers if first dialog.
 		if ( CKEDITOR.dialog._.currentTop == null )
 		{
@@ -415,4 +417,7 @@
 			this._.parentDialog = null;
 			CKEDITOR.dialog._.addCover( this._.editor );
+
+			CKEDITOR.document.on( 'keydown', CKEDITOR.dialog._.accessKeyDownHandler );
+			CKEDITOR.document.on( 'keyup', CKEDITOR.dialog._.accessKeyUpHandler );
 		}
 		else
@@ -447,4 +452,7 @@
 		element.remove();
 
+		// Unregister all access keys associated with this dialog.
+		CKEDITOR.dialog._.unregisterAccessKey( this );
+
 		// Maintain dialog ordering and remove cover if needed.
 		if ( this._.parentDialog == null )
@@ -461,4 +469,8 @@
 		{
 			CKEDITOR.dialog._.currentZIndex = null;
+
+			// Remove access key handlers.
+			CKEDITOR.document.removeListener( 'keydown', CKEDITOR.dialog._.accessKeyDownHandler );
+			CKEDITOR.document.removeListener( 'keyup', CKEDITOR.dialog._.accessKeyUpHandler );
 
 			// Restore focus and (if not already restored) selection in the editing area.
@@ -534,4 +546,12 @@
 		tab.setAttribute( 'id', contents.id + '_' + CKEDITOR.tools.getNextNumber() );
 		page.setAttribute( 'name', contents.id );
+
+		// Add access key handlers if access key is defined.
+		if ( contents.accessKey )
+		{
+			CKEDITOR.dialog._.registerAccessKey( this, this, contents.accessKey,
+				CKEDITOR.dialog._.tabAccessKeyDown, CKEDITOR.dialog._.tabAccessKeyUp );
+			this._.accessKeyMap[ contents.accessKey ] = contents.id;
+		}
 	},
 
@@ -1162,4 +1182,71 @@
 				});
 		CKEDITOR.tools.extend( this, contentDefinition );
+	},
+
+	accessKeyDownHandler : function( evt )
+	{
+		var ctrl = evt.data.$.ctrlKey || evt.data.$.metaKey,
+			key = String.fromCharCode( evt.data.$.keyCode ),
+			keyProcessor = CKEDITOR.dialog._.accessKeyProcessors[key];
+
+		if ( !ctrl || !keyProcessor || !keyProcessor.length )
+			return;
+
+		keyProcessor = keyProcessor[keyProcessor.length - 1];
+		keyProcessor.keydown.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key );
+		evt.data.preventDefault();
+	},
+
+	accessKeyUpHandler : function( evt )
+	{
+		var ctrl = evt.data.$.ctrlKey || evt.data.$.metaKey,
+			key = String.fromCharCode( evt.data.$.keyCode ),
+			keyProcessor = CKEDITOR.dialog._.accessKeyProcessors[key];
+
+		if ( !ctrl || !keyProcessor || !keyProcessor.length )
+			return;
+
+		keyProcessor = keyProcessor[keyProcessor.length - 1];
+		keyProcessor.keyup.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key );
+		evt.data.preventDefault();
+	},
+
+	registerAccessKey : function( uiElement, dialog, key, downFunc, upFunc )
+	{
+		var procList = this.accessKeyProcessors[key] || ( this.accessKeyProcessors[key] = [] );
+		procList.push( {
+				uiElement : uiElement,
+				dialog : dialog,
+				key : key,
+				keyup : upFunc || uiElement.accessKeyUp,
+				keydown : downFunc || uiElement.accessKeyDown
+			} );
+	},
+
+	unregisterAccessKey : function( obj )
+	{
+		for ( var i in this.accessKeyProcessors )
+		{
+			var list = this.accessKeyProcessors[i];
+			for ( var j = list.length - 1 ; j >= 0 ; j-- )
+			{
+				if ( list[j].dialog == obj || list[j].uiElement == obj )
+					list.splice( j, 1 );
+			}
+			if ( list.length == 0 )
+				delete this.accessKeyProcessors[i];
+		}
+	}, 
+
+	accessKeyProcessors : {},
+
+	tabAccessKeyUp : function( dialog, key )
+	{
+		if ( dialog._.accessKeyMap[key] )
+			dialog.selectPage( dialog._.accessKeyMap[key] );
+	},
+
+	tabAccessKeyDown : function( dialog, key )
+	{
 	}
 };
@@ -1418,4 +1505,6 @@
 			// Add events.
 			this.registerEvents( elementDefinition );
+			if ( this.accessKeyUp && this.accessKeyDown && elementDefinition.accessKey )
+				CKEDITOR.dialog._.registerAccessKey( this, dialog, elementDefinition.accessKey );
 		},
 
@@ -1623,4 +1712,13 @@
 			dialog.on( 'load', func, this, null, CKEDITOR.tools.getNextNumber() );
 		}
+	},
+
+	accessKeyDown : function( dialog, key )
+	{
+		this.focus();
+	},
+
+	accessKeyUp : function( dialog, key )
+	{
 	}
 };
Index: /CKEditor/branches/prototype/_source/plugins/dialogui/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/dialogui/plugin.js	(revision 2650)
+++ /CKEditor/branches/prototype/_source/plugins/dialogui/plugin.js	(revision 2651)
@@ -424,5 +424,16 @@
 							this.on( 'click', func );
 						}
-					}, true )
+					}, true ),
+
+				accessKeyUp : function()
+				{
+					this.getElement().removeClass( 'active' );
+					this.click();
+				},
+
+				accessKeyDown : function()
+				{
+					this.getElement().addClass( 'active' );
+				},
 			}, true );
 
@@ -448,4 +459,9 @@
 					this.focus();
 					this.getElement().$.select();
+				},
+
+				accessKeyUp : function()
+				{
+					this.select();
 				}
 			}, commonPrototype, true );
@@ -482,4 +498,9 @@
 				{
 					return this.getElement().$.checked;
+				},
+
+				accessKeyUp : function()
+				{
+					this.setValue( !this.getValue() );
 				}
 			}, commonPrototype, true );
@@ -498,7 +519,5 @@
 						item;
 					for ( var i = 0 ; ( i < children.length ) && ( item = children[i] ) ; i++ )
-					{
 						item.getElement().$.checked = ( item.getValue() == value );
-					}
 				},
 
@@ -517,4 +536,32 @@
 					}
 					return null;
+				},
+
+				accessKeyUp : function()
+				{
+					var children = this._.children, i;
+					for ( i = 0 ; i < children.length ; i++ )
+					{
+						if ( children[i].getElement().$.checked )
+						{
+							this.setValue( children[ ( i + 1 ) % children.length ].getValue() );
+							return;
+						}
+					}
+					this.setValue( children[0].getValue() );
+				},
+
+				accessKeyDown : function()
+				{
+					var children = this._.children, i;
+					for ( i = 0 ; i < children.length ; i++ )
+					{
+						if ( children[i].getElement().$.checked )
+						{
+							children[ ( i + 1 ) % children.length ].getElement().focus();
+							return;
+						}
+					}
+					children[0].getElement().focus();
 				}
 			}, commonPrototype, true );
