code: function checkSelectionChange() {
  		// A possibly available fake-selection.
  		var sel = this._.fakeSelection,
  			realSel;
  
  		if ( sel ) {
  			realSel = this.getSelection( 1 );
  
  			// If real (not locked/stored) selection was moved from hidden container,
  			// then the fake-selection must be invalidated.
  			if ( !realSel || !realSel.isHidden() ) {
  				// Remove the cache from fake-selection references in use elsewhere.
  				sel.reset();
  
  				// Have the code using the native selection.
  				sel = 0;
  			}
  		}
  
  		// If not fake-selection is available then get the native selection.
  		if ( !sel ) {
  			sel = realSel || this.getSelection( 1 );
  
  			// Editor may have no selection at all.
  			if ( !sel || sel.getType() == CKEDITOR.SELECTION_NONE )
  				return;
  		}
  
  		this.fire( 'selectionCheck', sel );
  
  		var currentPath = this.elementPath();
  		if ( !currentPath.compare( this._.selectionPreviousPath ) ) {
  			// Cache the active element, which we'll eventually lose on Webkit.
  			if ( CKEDITOR.env.webkit )
  				this._.previousActive = this.document.getActive();
  
  			this._.selectionPreviousPath = currentPath;
  			this.fire( 'selectionChange', { selection: sel, path: currentPath } );
  		}
  	}
docs: The selection change check basically saves the element parent tree of the current node and check it on successive requests. If there is any change on the tree, then the selectionChange event gets fired.