Index: /CKEditor/trunk/CHANGES.html
===================================================================
--- /CKEditor/trunk/CHANGES.html	(revision 7503)
+++ /CKEditor/trunk/CHANGES.html	(revision 7504)
@@ -45,4 +45,5 @@
 			Fixed issues:</p>
 	<ul>
+		<li><a href="http://dev.ckeditor.com/ticket/8463">#8463</a> : WebKit: Cut/Copy buttons didn't go on "enabled" state.</li>
 		<li><a href="http://dev.ckeditor.com/ticket/9043">#9043</a> : Command newpage didn't return its name when afterCommandExec event was fired.</li>
 		<li><a href="http://dev.ckeditor.com/ticket/9015">#9015</a> : Applied ARIA label on dialog file input element.</li>
Index: /CKEditor/trunk/_source/plugins/clipboard/plugin.js
===================================================================
--- /CKEditor/trunk/_source/plugins/clipboard/plugin.js	(revision 7503)
+++ /CKEditor/trunk/_source/plugins/clipboard/plugin.js	(revision 7504)
@@ -286,20 +286,37 @@
 	}
 
-	var depressBeforeEvent;
+	var depressBeforeEvent,
+		inReadOnly;
 	function stateFromNamedCommand( command, editor )
 	{
-		// IE Bug: queryCommandEnabled('paste') fires also 'beforepaste(copy/cut)',
-		// guard to distinguish from the ordinary sources( either
-		// keyboard paste or execCommand ) (#4874).
-		CKEDITOR.env.ie && ( depressBeforeEvent = 1 );
-
-		var retval = CKEDITOR.TRISTATE_OFF;
-		try { retval = editor.document.$.queryCommandEnabled( command ) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED; }catch( er ){}
-
-		depressBeforeEvent = 0;
-		return retval;
+		var retval;
+
+		if ( inReadOnly && command in { Paste : 1, Cut : 1 } )
+			return CKEDITOR.TRISTATE_DISABLED;
+
+		if ( command == 'Paste' )
+		{
+			// IE Bug: queryCommandEnabled('paste') fires also 'beforepaste(copy/cut)',
+			// guard to distinguish from the ordinary sources (either
+			// keyboard paste or execCommand) (#4874).
+			CKEDITOR.env.ie && ( depressBeforeEvent = 1 );
+			try
+			{
+				// Always return true for Webkit (which always returns false).
+				retval = editor.document.$.queryCommandEnabled( command ) || CKEDITOR.env.webkit;
+			}
+			catch( er ) {}
+			depressBeforeEvent = 0;
+		}
+		// Cut, Copy - check if the selection is not empty
+		else
+		{
+			var ranges = editor.getSelection().getRanges();
+			retval = !( ranges.length == 1 && ranges[ 0 ].collapsed );
+		}
+
+		return retval ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
 	}
 
-	var inReadOnly;
 	function setToolbarStates()
 	{
@@ -307,8 +324,9 @@
 			return;
 
-		this.getCommand( 'cut' ).setState( inReadOnly ? CKEDITOR.TRISTATE_DISABLED : stateFromNamedCommand( 'Cut', this ) );
+		var pasteState = stateFromNamedCommand( 'Paste', this );
+
+		this.getCommand( 'cut' ).setState( stateFromNamedCommand( 'Cut', this ) );
 		this.getCommand( 'copy' ).setState( stateFromNamedCommand( 'Copy', this ) );
-		var pasteState = inReadOnly ? CKEDITOR.TRISTATE_DISABLED :
-						CKEDITOR.env.webkit ? CKEDITOR.TRISTATE_OFF : stateFromNamedCommand( 'Paste', this );
+		this.getCommand( 'paste' ).setState( pasteState );
 		this.fire( 'pasteState', pasteState );
 	}
@@ -462,7 +480,7 @@
 							var readOnly = selection.getRanges()[ 0 ].checkReadOnly();
 							return {
-								cut : !readOnly && stateFromNamedCommand( 'Cut', editor ),
+								cut : stateFromNamedCommand( 'Cut', editor ),
 								copy : stateFromNamedCommand( 'Copy', editor ),
-								paste : !readOnly && ( CKEDITOR.env.webkit ? CKEDITOR.TRISTATE_OFF : stateFromNamedCommand( 'Paste', editor ) )
+								paste : stateFromNamedCommand( 'Paste', editor )
 							};
 						});
