Home | History | Annotate | Download | only in editing
      1 /*
      2  * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "SelectionController.h"
     28 
     29 #include "CString.h"
     30 #include "DeleteSelectionCommand.h"
     31 #include "Document.h"
     32 #include "Editor.h"
     33 #include "Element.h"
     34 #include "EventHandler.h"
     35 #include "ExceptionCode.h"
     36 #include "FocusController.h"
     37 #include "FloatQuad.h"
     38 #include "Frame.h"
     39 #include "FrameTree.h"
     40 #include "FrameView.h"
     41 #include "GraphicsContext.h"
     42 #include "HTMLInputElement.h"
     43 #include "HTMLNames.h"
     44 #include "HitTestRequest.h"
     45 #include "HitTestResult.h"
     46 #include "Page.h"
     47 #include "Range.h"
     48 #include "RenderTheme.h"
     49 #include "RenderView.h"
     50 #include "Settings.h"
     51 #include "TextIterator.h"
     52 #include "TypingCommand.h"
     53 #include "htmlediting.h"
     54 #include "visible_units.h"
     55 #include <stdio.h>
     56 
     57 #define EDIT_DEBUG 0
     58 
     59 namespace WebCore {
     60 
     61 using namespace HTMLNames;
     62 
     63 const int NoXPosForVerticalArrowNavigation = INT_MIN;
     64 
     65 SelectionController::SelectionController(Frame* frame, bool isDragCaretController)
     66     : m_frame(frame)
     67     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation)
     68     , m_caretBlinkTimer(this, &SelectionController::caretBlinkTimerFired)
     69     , m_needsLayout(true)
     70     , m_absCaretBoundsDirty(true)
     71     , m_lastChangeWasHorizontalExtension(false)
     72     , m_isDragCaretController(isDragCaretController)
     73     , m_isCaretBlinkingSuspended(false)
     74     , m_focused(frame && frame->page() && frame->page()->focusController()->focusedFrame() == frame)
     75     , m_caretVisible(isDragCaretController)
     76     , m_caretPaint(true)
     77 {
     78 }
     79 
     80 void SelectionController::moveTo(const VisiblePosition &pos, bool userTriggered)
     81 {
     82     setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
     83 }
     84 
     85 void SelectionController::moveTo(const VisiblePosition &base, const VisiblePosition &extent, bool userTriggered)
     86 {
     87     setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity()), true, true, userTriggered);
     88 }
     89 
     90 void SelectionController::moveTo(const Position &pos, EAffinity affinity, bool userTriggered)
     91 {
     92     setSelection(VisibleSelection(pos, affinity), true, true, userTriggered);
     93 }
     94 
     95 void SelectionController::moveTo(const Range *r, EAffinity affinity, bool userTriggered)
     96 {
     97     VisibleSelection selection = r ? VisibleSelection(r->startPosition(), r->endPosition(), affinity) : VisibleSelection(Position(), Position(), affinity);
     98     setSelection(selection, true, true, userTriggered);
     99 }
    100 
    101 void SelectionController::moveTo(const Position &base, const Position &extent, EAffinity affinity, bool userTriggered)
    102 {
    103     setSelection(VisibleSelection(base, extent, affinity), true, true, userTriggered);
    104 }
    105 
    106 void SelectionController::setSelection(const VisibleSelection& s, bool closeTyping, bool clearTypingStyle, bool userTriggered)
    107 {
    108     m_lastChangeWasHorizontalExtension = false;
    109 
    110     if (m_isDragCaretController) {
    111         invalidateCaretRect();
    112         m_selection = s;
    113         m_needsLayout = true;
    114         invalidateCaretRect();
    115         return;
    116     }
    117     if (!m_frame) {
    118         m_selection = s;
    119         return;
    120     }
    121 
    122     Node* baseNode = s.base().node();
    123     Document* document = 0;
    124     if (baseNode)
    125         document = baseNode->document();
    126 
    127     // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at SelectionController::setSelection
    128     // if document->frame() == m_frame we can get into an infinite loop
    129     if (document && document->frame() != m_frame && document != m_frame->document()) {
    130         document->frame()->selection()->setSelection(s, closeTyping, clearTypingStyle, userTriggered);
    131         return;
    132     }
    133 
    134     if (closeTyping)
    135         TypingCommand::closeTyping(m_frame->editor()->lastEditCommand());
    136 
    137     if (clearTypingStyle)
    138         m_frame->clearTypingStyle();
    139 
    140     if (m_selection == s)
    141         return;
    142 
    143     VisibleSelection oldSelection = m_selection;
    144 
    145     m_selection = s;
    146 
    147     m_needsLayout = true;
    148 
    149     if (!s.isNone())
    150         m_frame->setFocusedNodeIfNeeded();
    151 
    152     updateAppearance();
    153 
    154     // Always clear the x position used for vertical arrow navigation.
    155     // It will be restored by the vertical arrow navigation code if necessary.
    156     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
    157     selectFrameElementInParentIfFullySelected();
    158     m_frame->notifyRendererOfSelectionChange(userTriggered);
    159     m_frame->respondToChangedSelection(oldSelection, closeTyping);
    160     if (userTriggered)
    161         m_frame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded, true);
    162 
    163     notifyAccessibilityForSelectionChange();
    164 }
    165 
    166 static bool removingNodeRemovesPosition(Node* node, const Position& position)
    167 {
    168     if (!position.node())
    169         return false;
    170 
    171     if (position.node() == node)
    172         return true;
    173 
    174     if (!node->isElementNode())
    175         return false;
    176 
    177     Element* element = static_cast<Element*>(node);
    178     return element->contains(position.node()) || element->contains(position.node()->shadowAncestorNode());
    179 }
    180 
    181 void SelectionController::nodeWillBeRemoved(Node *node)
    182 {
    183     if (isNone())
    184         return;
    185 
    186     // There can't be a selection inside a fragment, so if a fragment's node is being removed,
    187     // the selection in the document that created the fragment needs no adjustment.
    188     if (node && highestAncestor(node)->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
    189         return;
    190 
    191     bool baseRemoved = removingNodeRemovesPosition(node, m_selection.base());
    192     bool extentRemoved = removingNodeRemovesPosition(node, m_selection.extent());
    193     bool startRemoved = removingNodeRemovesPosition(node, m_selection.start());
    194     bool endRemoved = removingNodeRemovesPosition(node, m_selection.end());
    195 
    196     bool clearRenderTreeSelection = false;
    197     bool clearDOMTreeSelection = false;
    198 
    199     if (startRemoved || endRemoved) {
    200         // FIXME: When endpoints are removed, we should just alter the selection, instead of blowing it away.
    201         clearRenderTreeSelection = true;
    202         clearDOMTreeSelection = true;
    203     } else if (baseRemoved || extentRemoved) {
    204         // The base and/or extent are about to be removed, but the start and end aren't.
    205         // Change the base and extent to the start and end, but don't re-validate the
    206         // selection, since doing so could move the start and end into the node
    207         // that is about to be removed.
    208         if (m_selection.isBaseFirst())
    209             m_selection.setWithoutValidation(m_selection.start(), m_selection.end());
    210         else
    211             m_selection.setWithoutValidation(m_selection.end(), m_selection.start());
    212     // FIXME: This could be more efficient if we had an isNodeInRange function on Ranges.
    213     } else if (comparePositions(m_selection.start(), Position(node, 0)) == -1 && comparePositions(m_selection.end(), Position(node, 0)) == 1) {
    214         // If we did nothing here, when this node's renderer was destroyed, the rect that it
    215         // occupied would be invalidated, but, selection gaps that change as a result of
    216         // the removal wouldn't be invalidated.
    217         // FIXME: Don't do so much unnecessary invalidation.
    218         clearRenderTreeSelection = true;
    219     }
    220 
    221     if (clearRenderTreeSelection) {
    222         RefPtr<Document> document = m_selection.start().node()->document();
    223         document->updateStyleIfNeeded();
    224         if (RenderView* view = toRenderView(document->renderer()))
    225             view->clearSelection();
    226     }
    227 
    228     if (clearDOMTreeSelection)
    229         setSelection(VisibleSelection(), false, false);
    230 }
    231 
    232 void SelectionController::willBeModified(EAlteration alter, EDirection direction)
    233 {
    234     if (alter != EXTEND)
    235         return;
    236     if (m_lastChangeWasHorizontalExtension)
    237         return;
    238 
    239     Position start = m_selection.start();
    240     Position end = m_selection.end();
    241     // FIXME: This is probably not correct for right and left when the direction is RTL.
    242     switch (direction) {
    243         case RIGHT:
    244         case FORWARD:
    245             m_selection.setBase(start);
    246             m_selection.setExtent(end);
    247             break;
    248         case LEFT:
    249         case BACKWARD:
    250             m_selection.setBase(end);
    251             m_selection.setExtent(start);
    252             break;
    253     }
    254 }
    255 
    256 TextDirection SelectionController::directionOfEnclosingBlock()
    257 {
    258     Node* n = m_selection.extent().node();
    259     Node* enclosingBlockNode = enclosingBlock(n);
    260     if (!enclosingBlockNode)
    261         return LTR;
    262     RenderObject* renderer = enclosingBlockNode->renderer();
    263     if (renderer)
    264         return renderer->style()->direction();
    265     return LTR;
    266 }
    267 
    268 VisiblePosition SelectionController::modifyExtendingRight(TextGranularity granularity)
    269 {
    270     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    271 
    272     // The difference between modifyExtendingRight and modifyExtendingForward is:
    273     // modifyExtendingForward always extends forward logically.
    274     // modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
    275     // it extends forward logically if the enclosing block is LTR direction,
    276     // but it extends backward logically if the enclosing block is RTL direction.
    277     switch (granularity) {
    278         case CharacterGranularity:
    279             if (directionOfEnclosingBlock() == LTR)
    280                 pos = pos.next(true);
    281             else
    282                 pos = pos.previous(true);
    283             break;
    284         case WordGranularity:
    285             if (directionOfEnclosingBlock() == LTR)
    286                 pos = nextWordPosition(pos);
    287             else
    288                 pos = previousWordPosition(pos);
    289             break;
    290         case SentenceGranularity:
    291         case LineGranularity:
    292         case ParagraphGranularity:
    293         case SentenceBoundary:
    294         case LineBoundary:
    295         case ParagraphBoundary:
    296         case DocumentBoundary:
    297             // FIXME: implement all of the above?
    298             pos = modifyExtendingForward(granularity);
    299     }
    300     return pos;
    301 }
    302 
    303 VisiblePosition SelectionController::modifyExtendingForward(TextGranularity granularity)
    304 {
    305     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    306     switch (granularity) {
    307         case CharacterGranularity:
    308             pos = pos.next(true);
    309             break;
    310         case WordGranularity:
    311             pos = nextWordPosition(pos);
    312             break;
    313         case SentenceGranularity:
    314             pos = nextSentencePosition(pos);
    315             break;
    316         case LineGranularity:
    317             pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
    318             break;
    319         case ParagraphGranularity:
    320             pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
    321             break;
    322         case SentenceBoundary:
    323             pos = endOfSentence(VisiblePosition(m_selection.end(), m_selection.affinity()));
    324             break;
    325         case LineBoundary:
    326             pos = logicalEndOfLine(VisiblePosition(m_selection.end(), m_selection.affinity()));
    327             break;
    328         case ParagraphBoundary:
    329             pos = endOfParagraph(VisiblePosition(m_selection.end(), m_selection.affinity()));
    330             break;
    331         case DocumentBoundary:
    332             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    333             if (isEditablePosition(pos.deepEquivalent()))
    334                 pos = endOfEditableContent(pos);
    335             else
    336                 pos = endOfDocument(pos);
    337             break;
    338     }
    339 
    340     return pos;
    341 }
    342 
    343 VisiblePosition SelectionController::modifyMovingRight(TextGranularity granularity)
    344 {
    345     VisiblePosition pos;
    346     switch (granularity) {
    347         case CharacterGranularity:
    348             if (isRange())
    349                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    350             else
    351                 pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
    352             break;
    353         case WordGranularity:
    354         case SentenceGranularity:
    355         case LineGranularity:
    356         case ParagraphGranularity:
    357         case SentenceBoundary:
    358         case LineBoundary:
    359         case ParagraphBoundary:
    360         case DocumentBoundary:
    361             // FIXME: Implement all of the above.
    362             pos = modifyMovingForward(granularity);
    363             break;
    364     }
    365     return pos;
    366 }
    367 
    368 VisiblePosition SelectionController::modifyMovingForward(TextGranularity granularity)
    369 {
    370     VisiblePosition pos;
    371     // FIXME: Stay in editable content for the less common granularities.
    372     switch (granularity) {
    373         case CharacterGranularity:
    374             if (isRange())
    375                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    376             else
    377                 pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(true);
    378             break;
    379         case WordGranularity:
    380             pos = nextWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    381             break;
    382         case SentenceGranularity:
    383             pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    384             break;
    385         case LineGranularity: {
    386             // down-arrowing from a range selection that ends at the start of a line needs
    387             // to leave the selection at that line start (no need to call nextLinePosition!)
    388             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    389             if (!isRange() || !isStartOfLine(pos))
    390                 pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(START));
    391             break;
    392         }
    393         case ParagraphGranularity:
    394             pos = nextParagraphPosition(VisiblePosition(m_selection.end(), m_selection.affinity()), xPosForVerticalArrowNavigation(START));
    395             break;
    396         case SentenceBoundary:
    397             pos = endOfSentence(VisiblePosition(m_selection.end(), m_selection.affinity()));
    398             break;
    399         case LineBoundary:
    400             pos = logicalEndOfLine(VisiblePosition(m_selection.end(), m_selection.affinity()));
    401             break;
    402         case ParagraphBoundary:
    403             pos = endOfParagraph(VisiblePosition(m_selection.end(), m_selection.affinity()));
    404             break;
    405         case DocumentBoundary:
    406             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    407             if (isEditablePosition(pos.deepEquivalent()))
    408                 pos = endOfEditableContent(pos);
    409             else
    410                 pos = endOfDocument(pos);
    411             break;
    412 
    413     }
    414     return pos;
    415 }
    416 
    417 VisiblePosition SelectionController::modifyExtendingLeft(TextGranularity granularity)
    418 {
    419     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    420 
    421     // The difference between modifyExtendingLeft and modifyExtendingBackward is:
    422     // modifyExtendingBackward always extends backward logically.
    423     // modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
    424     // it extends backward logically if the enclosing block is LTR direction,
    425     // but it extends forward logically if the enclosing block is RTL direction.
    426     switch (granularity) {
    427         case CharacterGranularity:
    428             if (directionOfEnclosingBlock() == LTR)
    429                 pos = pos.previous(true);
    430             else
    431                 pos = pos.next(true);
    432             break;
    433         case WordGranularity:
    434             if (directionOfEnclosingBlock() == LTR)
    435                 pos = previousWordPosition(pos);
    436             else
    437                 pos = nextWordPosition(pos);
    438             break;
    439         case SentenceGranularity:
    440         case LineGranularity:
    441         case ParagraphGranularity:
    442         case SentenceBoundary:
    443         case LineBoundary:
    444         case ParagraphBoundary:
    445         case DocumentBoundary:
    446             pos = modifyExtendingBackward(granularity);
    447     }
    448     return pos;
    449 }
    450 
    451 VisiblePosition SelectionController::modifyExtendingBackward(TextGranularity granularity)
    452 {
    453     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    454 
    455     // Extending a selection backward by word or character from just after a table selects
    456     // the table.  This "makes sense" from the user perspective, esp. when deleting.
    457     // It was done here instead of in VisiblePosition because we want VPs to iterate
    458     // over everything.
    459     switch (granularity) {
    460         case CharacterGranularity:
    461             pos = pos.previous(true);
    462             break;
    463         case WordGranularity:
    464             pos = previousWordPosition(pos);
    465             break;
    466         case SentenceGranularity:
    467             pos = previousSentencePosition(pos);
    468             break;
    469         case LineGranularity:
    470             pos = previousLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
    471             break;
    472         case ParagraphGranularity:
    473             pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
    474             break;
    475         case SentenceBoundary:
    476             pos = startOfSentence(VisiblePosition(m_selection.start(), m_selection.affinity()));
    477             break;
    478         case LineBoundary:
    479             pos = logicalStartOfLine(VisiblePosition(m_selection.start(), m_selection.affinity()));
    480             break;
    481         case ParagraphBoundary:
    482             pos = startOfParagraph(VisiblePosition(m_selection.start(), m_selection.affinity()));
    483             break;
    484         case DocumentBoundary:
    485             pos = VisiblePosition(m_selection.start(), m_selection.affinity());
    486             if (isEditablePosition(pos.deepEquivalent()))
    487                 pos = startOfEditableContent(pos);
    488             else
    489                 pos = startOfDocument(pos);
    490             break;
    491     }
    492     return pos;
    493 }
    494 
    495 VisiblePosition SelectionController::modifyMovingLeft(TextGranularity granularity)
    496 {
    497     VisiblePosition pos;
    498     switch (granularity) {
    499         case CharacterGranularity:
    500             if (isRange())
    501                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
    502             else
    503                 pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
    504             break;
    505         case WordGranularity:
    506         case SentenceGranularity:
    507         case LineGranularity:
    508         case ParagraphGranularity:
    509         case SentenceBoundary:
    510         case LineBoundary:
    511         case ParagraphBoundary:
    512         case DocumentBoundary:
    513             // FIXME: Implement all of the above.
    514             pos = modifyMovingBackward(granularity);
    515             break;
    516     }
    517     return pos;
    518 }
    519 
    520 VisiblePosition SelectionController::modifyMovingBackward(TextGranularity granularity)
    521 {
    522     VisiblePosition pos;
    523     switch (granularity) {
    524         case CharacterGranularity:
    525             if (isRange())
    526                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
    527             else
    528                 pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(true);
    529             break;
    530         case WordGranularity:
    531             pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    532             break;
    533         case SentenceGranularity:
    534             pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    535             break;
    536         case LineGranularity:
    537             pos = previousLinePosition(VisiblePosition(m_selection.start(), m_selection.affinity()), xPosForVerticalArrowNavigation(START));
    538             break;
    539         case ParagraphGranularity:
    540             pos = previousParagraphPosition(VisiblePosition(m_selection.start(), m_selection.affinity()), xPosForVerticalArrowNavigation(START));
    541             break;
    542         case SentenceBoundary:
    543             pos = startOfSentence(VisiblePosition(m_selection.start(), m_selection.affinity()));
    544             break;
    545         case LineBoundary:
    546             pos = logicalStartOfLine(VisiblePosition(m_selection.start(), m_selection.affinity()));
    547             break;
    548         case ParagraphBoundary:
    549             pos = startOfParagraph(VisiblePosition(m_selection.start(), m_selection.affinity()));
    550             break;
    551         case DocumentBoundary:
    552             pos = VisiblePosition(m_selection.start(), m_selection.affinity());
    553             if (isEditablePosition(pos.deepEquivalent()))
    554                 pos = startOfEditableContent(pos);
    555             else
    556                 pos = startOfDocument(pos);
    557             break;
    558     }
    559     return pos;
    560 }
    561 
    562 bool SelectionController::modify(EAlteration alter, EDirection dir, TextGranularity granularity, bool userTriggered)
    563 {
    564     if (userTriggered) {
    565         SelectionController trialSelectionController;
    566         trialSelectionController.setSelection(m_selection);
    567         trialSelectionController.setLastChangeWasHorizontalExtension(m_lastChangeWasHorizontalExtension);
    568         trialSelectionController.modify(alter, dir, granularity, false);
    569 
    570         bool change = m_frame->shouldChangeSelection(trialSelectionController.selection());
    571         if (!change)
    572             return false;
    573     }
    574 
    575     if (m_frame)
    576         m_frame->setSelectionGranularity(granularity);
    577 
    578     willBeModified(alter, dir);
    579 
    580     VisiblePosition pos;
    581     switch (dir) {
    582         case RIGHT:
    583             if (alter == MOVE)
    584                 pos = modifyMovingRight(granularity);
    585             else
    586                 pos = modifyExtendingRight(granularity);
    587             break;
    588         case FORWARD:
    589             if (alter == EXTEND)
    590                 pos = modifyExtendingForward(granularity);
    591             else
    592                 pos = modifyMovingForward(granularity);
    593             break;
    594         case LEFT:
    595             if (alter == MOVE)
    596                 pos = modifyMovingLeft(granularity);
    597             else
    598                 pos = modifyExtendingLeft(granularity);
    599             break;
    600         case BACKWARD:
    601             if (alter == EXTEND)
    602                 pos = modifyExtendingBackward(granularity);
    603             else
    604                 pos = modifyMovingBackward(granularity);
    605             break;
    606     }
    607 
    608     if (pos.isNull())
    609         return false;
    610 
    611     // Some of the above operations set an xPosForVerticalArrowNavigation.
    612     // Setting a selection will clear it, so save it to possibly restore later.
    613     // Note: the START position type is arbitrary because it is unused, it would be
    614     // the requested position type if there were no xPosForVerticalArrowNavigation set.
    615     int x = xPosForVerticalArrowNavigation(START);
    616 
    617     switch (alter) {
    618         case MOVE:
    619             moveTo(pos, userTriggered);
    620             break;
    621         case EXTEND:
    622             setExtent(pos, userTriggered);
    623             break;
    624     }
    625 
    626     if (granularity == LineGranularity || granularity == ParagraphGranularity)
    627         m_xPosForVerticalArrowNavigation = x;
    628 
    629     if (userTriggered) {
    630         // User modified selection change also sets the granularity back to character.
    631         // NOTE: The one exception is that we need to keep word granularity to
    632         // preserve smart delete behavior when extending by word (e.g. double-click),
    633         // then shift-option-right arrow, then delete needs to smart delete, per TextEdit.
    634         if (!(alter == EXTEND && granularity == WordGranularity && m_frame->selectionGranularity() == WordGranularity))
    635             m_frame->setSelectionGranularity(CharacterGranularity);
    636     }
    637 
    638     setNeedsLayout();
    639 
    640     m_lastChangeWasHorizontalExtension = alter == EXTEND;
    641 
    642     return true;
    643 }
    644 
    645 // FIXME: Maybe baseline would be better?
    646 static bool absoluteCaretY(const VisiblePosition &c, int &y)
    647 {
    648     IntRect rect = c.absoluteCaretBounds();
    649     if (rect.isEmpty())
    650         return false;
    651     y = rect.y() + rect.height() / 2;
    652     return true;
    653 }
    654 
    655 bool SelectionController::modify(EAlteration alter, int verticalDistance, bool userTriggered)
    656 {
    657     if (verticalDistance == 0)
    658         return false;
    659 
    660     if (userTriggered) {
    661         SelectionController trialSelectionController;
    662         trialSelectionController.setSelection(m_selection);
    663         trialSelectionController.setLastChangeWasHorizontalExtension(m_lastChangeWasHorizontalExtension);
    664         trialSelectionController.modify(alter, verticalDistance, false);
    665 
    666         bool change = m_frame->shouldChangeSelection(trialSelectionController.selection());
    667         if (!change)
    668             return false;
    669     }
    670 
    671     bool up = verticalDistance < 0;
    672     if (up)
    673         verticalDistance = -verticalDistance;
    674 
    675     willBeModified(alter, up ? BACKWARD : FORWARD);
    676 
    677     VisiblePosition pos;
    678     int xPos = 0;
    679     switch (alter) {
    680         case MOVE:
    681             pos = VisiblePosition(up ? m_selection.start() : m_selection.end(), m_selection.affinity());
    682             xPos = xPosForVerticalArrowNavigation(up ? START : END);
    683             m_selection.setAffinity(up ? UPSTREAM : DOWNSTREAM);
    684             break;
    685         case EXTEND:
    686             pos = VisiblePosition(m_selection.extent(), m_selection.affinity());
    687             xPos = xPosForVerticalArrowNavigation(EXTENT);
    688             m_selection.setAffinity(DOWNSTREAM);
    689             break;
    690     }
    691 
    692     int startY;
    693     if (!absoluteCaretY(pos, startY))
    694         return false;
    695     if (up)
    696         startY = -startY;
    697     int lastY = startY;
    698 
    699     VisiblePosition result;
    700     VisiblePosition next;
    701     for (VisiblePosition p = pos; ; p = next) {
    702         next = (up ? previousLinePosition : nextLinePosition)(p, xPos);
    703         if (next.isNull() || next == p)
    704             break;
    705         int nextY;
    706         if (!absoluteCaretY(next, nextY))
    707             break;
    708         if (up)
    709             nextY = -nextY;
    710         if (nextY - startY > verticalDistance)
    711             break;
    712         if (nextY >= lastY) {
    713             lastY = nextY;
    714             result = next;
    715         }
    716     }
    717 
    718     if (result.isNull())
    719         return false;
    720 
    721     switch (alter) {
    722         case MOVE:
    723             moveTo(result, userTriggered);
    724             break;
    725         case EXTEND:
    726             setExtent(result, userTriggered);
    727             break;
    728     }
    729 
    730     if (userTriggered)
    731         m_frame->setSelectionGranularity(CharacterGranularity);
    732 
    733     m_lastChangeWasHorizontalExtension = alter == EXTEND;
    734 
    735     return true;
    736 }
    737 
    738 bool SelectionController::expandUsingGranularity(TextGranularity granularity)
    739 {
    740     if (isNone())
    741         return false;
    742 
    743     m_selection.expandUsingGranularity(granularity);
    744     m_needsLayout = true;
    745     return true;
    746 }
    747 
    748 int SelectionController::xPosForVerticalArrowNavigation(EPositionType type)
    749 {
    750     int x = 0;
    751 
    752     if (isNone())
    753         return x;
    754 
    755     Position pos;
    756     switch (type) {
    757         case START:
    758             pos = m_selection.start();
    759             break;
    760         case END:
    761             pos = m_selection.end();
    762             break;
    763         case BASE:
    764             pos = m_selection.base();
    765             break;
    766         case EXTENT:
    767             pos = m_selection.extent();
    768             break;
    769     }
    770 
    771     Frame *frame = pos.node()->document()->frame();
    772     if (!frame)
    773         return x;
    774 
    775     if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation) {
    776         VisiblePosition visiblePosition(pos, m_selection.affinity());
    777         // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
    778         // after the selection is created and before this function is called.
    779         x = visiblePosition.isNotNull() ? visiblePosition.xOffsetForVerticalNavigation() : 0;
    780         m_xPosForVerticalArrowNavigation = x;
    781     }
    782     else
    783         x = m_xPosForVerticalArrowNavigation;
    784 
    785     return x;
    786 }
    787 
    788 void SelectionController::clear()
    789 {
    790     setSelection(VisibleSelection());
    791 }
    792 
    793 void SelectionController::setBase(const VisiblePosition &pos, bool userTriggered)
    794 {
    795     setSelection(VisibleSelection(pos.deepEquivalent(), m_selection.extent(), pos.affinity()), true, true, userTriggered);
    796 }
    797 
    798 void SelectionController::setExtent(const VisiblePosition &pos, bool userTriggered)
    799 {
    800     setSelection(VisibleSelection(m_selection.base(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);
    801 }
    802 
    803 void SelectionController::setBase(const Position &pos, EAffinity affinity, bool userTriggered)
    804 {
    805     setSelection(VisibleSelection(pos, m_selection.extent(), affinity), true, true, userTriggered);
    806 }
    807 
    808 void SelectionController::setExtent(const Position &pos, EAffinity affinity, bool userTriggered)
    809 {
    810     setSelection(VisibleSelection(m_selection.base(), pos, affinity), true, true, userTriggered);
    811 }
    812 
    813 void SelectionController::setNeedsLayout(bool flag)
    814 {
    815     m_needsLayout = flag;
    816 }
    817 
    818 void SelectionController::layout()
    819 {
    820     if (isNone() || !m_selection.start().node()->inDocument() || !m_selection.end().node()->inDocument()) {
    821         m_caretRect = IntRect();
    822         return;
    823     }
    824 
    825     m_selection.start().node()->document()->updateStyleIfNeeded();
    826 
    827     m_caretRect = IntRect();
    828 
    829     if (isCaret()) {
    830         VisiblePosition pos(m_selection.start(), m_selection.affinity());
    831         if (pos.isNotNull()) {
    832             ASSERT(pos.deepEquivalent().node()->renderer());
    833 
    834             // First compute a rect local to the renderer at the selection start
    835             RenderObject* renderer;
    836             IntRect localRect = pos.localCaretRect(renderer);
    837 
    838             // Get the renderer that will be responsible for painting the caret (which
    839             // is either the renderer we just found, or one of its containers)
    840             RenderObject* caretPainter = caretRenderer();
    841 
    842             // Compute an offset between the renderer and the caretPainter
    843             IntSize offsetFromPainter;
    844             bool unrooted = false;
    845             while (renderer != caretPainter) {
    846                 RenderObject* containerObject = renderer->container();
    847                 if (!containerObject) {
    848                     unrooted = true;
    849                     break;
    850                 }
    851                 offsetFromPainter += renderer->offsetFromContainer(containerObject);
    852                 renderer = containerObject;
    853             }
    854 
    855             if (!unrooted) {
    856                 // Move the caret rect to the coords of the painter
    857                 localRect.move(offsetFromPainter);
    858                 m_caretRect = localRect;
    859             }
    860 
    861             m_absCaretBoundsDirty = true;
    862         }
    863     }
    864 
    865     m_needsLayout = false;
    866 }
    867 
    868 RenderObject* SelectionController::caretRenderer() const
    869 {
    870     Node* node = m_selection.start().node();
    871     if (!node)
    872         return 0;
    873 
    874     RenderObject* renderer = node->renderer();
    875     if (!renderer)
    876         return 0;
    877 
    878     // if caretNode is a block and caret is inside it then caret should be painted by that block
    879     bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node);
    880     return paintedByBlock ? renderer : renderer->containingBlock();
    881 }
    882 
    883 IntRect SelectionController::localCaretRect() const
    884 {
    885     if (m_needsLayout)
    886         const_cast<SelectionController*>(this)->layout();
    887 
    888     return m_caretRect;
    889 }
    890 
    891 IntRect SelectionController::absoluteBoundsForLocalRect(const IntRect& rect) const
    892 {
    893     RenderObject* caretPainter = caretRenderer();
    894     if (!caretPainter)
    895         return IntRect();
    896 
    897     return caretPainter->localToAbsoluteQuad(FloatRect(rect)).enclosingBoundingBox();
    898 }
    899 
    900 IntRect SelectionController::absoluteCaretBounds()
    901 {
    902     recomputeCaretRect();
    903     return m_absCaretBounds;
    904 }
    905 
    906 static IntRect repaintRectForCaret(IntRect caret)
    907 {
    908     if (caret.isEmpty())
    909         return IntRect();
    910     // Ensure that the dirty rect intersects the block that paints the caret even in the case where
    911     // the caret itself is just outside the block. See <https://bugs.webkit.org/show_bug.cgi?id=19086>.
    912     caret.inflateX(1);
    913     return caret;
    914 }
    915 
    916 IntRect SelectionController::caretRepaintRect() const
    917 {
    918     return absoluteBoundsForLocalRect(repaintRectForCaret(localCaretRect()));
    919 }
    920 
    921 bool SelectionController::recomputeCaretRect()
    922 {
    923     if (!m_frame)
    924         return false;
    925 
    926     FrameView* v = m_frame->document()->view();
    927     if (!v)
    928         return false;
    929 
    930     if (!m_needsLayout)
    931         return false;
    932 
    933     IntRect oldRect = m_caretRect;
    934     IntRect newRect = localCaretRect();
    935     if (oldRect == newRect && !m_absCaretBoundsDirty)
    936         return false;
    937 
    938     IntRect oldAbsCaretBounds = m_absCaretBounds;
    939     // FIXME: Rename m_caretRect to m_localCaretRect.
    940     m_absCaretBounds = absoluteBoundsForLocalRect(m_caretRect);
    941     m_absCaretBoundsDirty = false;
    942 
    943     if (oldAbsCaretBounds == m_absCaretBounds)
    944         return false;
    945 
    946     IntRect oldAbsoluteCaretRepaintBounds = m_absoluteCaretRepaintBounds;
    947     // We believe that we need to inflate the local rect before transforming it to obtain the repaint bounds.
    948     m_absoluteCaretRepaintBounds = caretRepaintRect();
    949 
    950     if (RenderView* view = toRenderView(m_frame->document()->renderer())) {
    951         // FIXME: make caret repainting container-aware.
    952         view->repaintRectangleInViewAndCompositedLayers(oldAbsoluteCaretRepaintBounds, false);
    953         view->repaintRectangleInViewAndCompositedLayers(m_absoluteCaretRepaintBounds, false);
    954     }
    955 
    956     return true;
    957 }
    958 
    959 void SelectionController::invalidateCaretRect()
    960 {
    961     if (!isCaret())
    962         return;
    963 
    964     Document* d = m_selection.start().node()->document();
    965 
    966     // recomputeCaretRect will always return false for the drag caret,
    967     // because its m_frame is always 0.
    968     bool caretRectChanged = recomputeCaretRect();
    969 
    970     // EDIT FIXME: This is an unfortunate hack.
    971     // Basically, we can't trust this layout position since we
    972     // can't guarantee that the check to see if we are in unrendered
    973     // content will work at this point. We may have to wait for
    974     // a layout and re-render of the document to happen. So, resetting this
    975     // flag will cause another caret layout to happen the first time
    976     // that we try to paint the caret after this call. That one will work since
    977     // it happens after the document has accounted for any editing
    978     // changes which may have been done.
    979     // And, we need to leave this layout here so the caret moves right
    980     // away after clicking.
    981     m_needsLayout = true;
    982 
    983     if (!caretRectChanged) {
    984         if (RenderView* view = toRenderView(d->renderer()))
    985             view->repaintRectangleInViewAndCompositedLayers(caretRepaintRect(), false);
    986     }
    987 }
    988 
    989 void SelectionController::paintCaret(GraphicsContext* context, int tx, int ty, const IntRect& clipRect)
    990 {
    991 #if ENABLE(TEXT_CARET)
    992     if (!m_caretVisible)
    993         return;
    994     if (!m_caretPaint)
    995         return;
    996     if (!m_selection.isCaret())
    997         return;
    998 
    999     IntRect drawingRect = localCaretRect();
   1000     drawingRect.move(tx, ty);
   1001     IntRect caret = intersection(drawingRect, clipRect);
   1002     if (caret.isEmpty())
   1003         return;
   1004 
   1005     Color caretColor = Color::black;
   1006     ColorSpace colorSpace = DeviceColorSpace;
   1007     Element* element = rootEditableElement();
   1008     if (element && element->renderer()) {
   1009         caretColor = element->renderer()->style()->color();
   1010         colorSpace = element->renderer()->style()->colorSpace();
   1011     }
   1012 
   1013     context->fillRect(caret, caretColor, colorSpace);
   1014 #endif
   1015 }
   1016 
   1017 void SelectionController::debugRenderer(RenderObject *r, bool selected) const
   1018 {
   1019     if (r->node()->isElementNode()) {
   1020         Element *element = static_cast<Element *>(r->node());
   1021         fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
   1022     }
   1023     else if (r->isText()) {
   1024         RenderText* textRenderer = toRenderText(r);
   1025         if (textRenderer->textLength() == 0 || !textRenderer->firstTextBox()) {
   1026             fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");
   1027             return;
   1028         }
   1029 
   1030         static const int max = 36;
   1031         String text = textRenderer->text();
   1032         int textLength = text.length();
   1033         if (selected) {
   1034             int offset = 0;
   1035             if (r->node() == m_selection.start().node())
   1036                 offset = m_selection.start().deprecatedEditingOffset();
   1037             else if (r->node() == m_selection.end().node())
   1038                 offset = m_selection.end().deprecatedEditingOffset();
   1039 
   1040             int pos;
   1041             InlineTextBox *box = textRenderer->findNextInlineTextBox(offset, pos);
   1042             text = text.substring(box->start(), box->len());
   1043 
   1044             String show;
   1045             int mid = max / 2;
   1046             int caret = 0;
   1047 
   1048             // text is shorter than max
   1049             if (textLength < max) {
   1050                 show = text;
   1051                 caret = pos;
   1052             }
   1053 
   1054             // too few characters to left
   1055             else if (pos - mid < 0) {
   1056                 show = text.left(max - 3) + "...";
   1057                 caret = pos;
   1058             }
   1059 
   1060             // enough characters on each side
   1061             else if (pos - mid >= 0 && pos + mid <= textLength) {
   1062                 show = "..." + text.substring(pos - mid + 3, max - 6) + "...";
   1063                 caret = mid;
   1064             }
   1065 
   1066             // too few characters on right
   1067             else {
   1068                 show = "..." + text.right(max - 3);
   1069                 caret = pos - (textLength - show.length());
   1070             }
   1071 
   1072             show.replace('\n', ' ');
   1073             show.replace('\r', ' ');
   1074             fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);
   1075             fprintf(stderr, "           ");
   1076             for (int i = 0; i < caret; i++)
   1077                 fprintf(stderr, " ");
   1078             fprintf(stderr, "^\n");
   1079         }
   1080         else {
   1081             if ((int)text.length() > max)
   1082                 text = text.left(max - 3) + "...";
   1083             else
   1084                 text = text.left(max);
   1085             fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());
   1086         }
   1087     }
   1088 }
   1089 
   1090 bool SelectionController::contains(const IntPoint& point)
   1091 {
   1092     Document* document = m_frame->document();
   1093 
   1094     // Treat a collapsed selection like no selection.
   1095     if (!isRange())
   1096         return false;
   1097     if (!document->renderer())
   1098         return false;
   1099 
   1100     HitTestRequest request(HitTestRequest::ReadOnly |
   1101                            HitTestRequest::Active);
   1102     HitTestResult result(point);
   1103     document->renderView()->layer()->hitTest(request, result);
   1104     Node* innerNode = result.innerNode();
   1105     if (!innerNode || !innerNode->renderer())
   1106         return false;
   1107 
   1108     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));
   1109     if (visiblePos.isNull())
   1110         return false;
   1111 
   1112     if (m_selection.visibleStart().isNull() || m_selection.visibleEnd().isNull())
   1113         return false;
   1114 
   1115     Position start(m_selection.visibleStart().deepEquivalent());
   1116     Position end(m_selection.visibleEnd().deepEquivalent());
   1117     Position p(visiblePos.deepEquivalent());
   1118 
   1119     return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
   1120 }
   1121 
   1122 // Workaround for the fact that it's hard to delete a frame.
   1123 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
   1124 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
   1125 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
   1126 // mouse or the keyboard after setting the selection.
   1127 void SelectionController::selectFrameElementInParentIfFullySelected()
   1128 {
   1129     // Find the parent frame; if there is none, then we have nothing to do.
   1130     Frame* parent = m_frame->tree()->parent();
   1131     if (!parent)
   1132         return;
   1133     Page* page = m_frame->page();
   1134     if (!page)
   1135         return;
   1136 
   1137     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
   1138     if (!isRange())
   1139         return;
   1140     if (!isStartOfDocument(selection().visibleStart()))
   1141         return;
   1142     if (!isEndOfDocument(selection().visibleEnd()))
   1143         return;
   1144 
   1145     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
   1146     Document* doc = m_frame->document();
   1147     Element* ownerElement = doc->ownerElement();
   1148     if (!ownerElement)
   1149         return;
   1150     Node* ownerElementParent = ownerElement->parentNode();
   1151     if (!ownerElementParent)
   1152         return;
   1153 
   1154     // This method's purpose is it to make it easier to select iframes (in order to delete them).  Don't do anything if the iframe isn't deletable.
   1155     if (!ownerElementParent->isContentEditable())
   1156         return;
   1157 
   1158     // Create compute positions before and after the element.
   1159     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
   1160     VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));
   1161     VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));
   1162 
   1163     // Focus on the parent frame, and then select from before this element to after.
   1164     VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
   1165     if (parent->shouldChangeSelection(newSelection)) {
   1166         page->focusController()->setFocusedFrame(parent);
   1167         parent->selection()->setSelection(newSelection);
   1168     }
   1169 }
   1170 
   1171 void SelectionController::selectAll()
   1172 {
   1173     Document* document = m_frame->document();
   1174 
   1175     if (document->focusedNode() && document->focusedNode()->canSelectAll()) {
   1176         document->focusedNode()->selectAll();
   1177         return;
   1178     }
   1179 
   1180     Node* root = 0;
   1181     if (isContentEditable())
   1182         root = highestEditableRoot(m_selection.start());
   1183     else {
   1184         root = shadowTreeRootNode();
   1185         if (!root)
   1186             root = document->documentElement();
   1187     }
   1188     if (!root)
   1189         return;
   1190     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root));
   1191     if (m_frame->shouldChangeSelection(newSelection))
   1192         setSelection(newSelection);
   1193     selectFrameElementInParentIfFullySelected();
   1194     m_frame->notifyRendererOfSelectionChange(true);
   1195 }
   1196 
   1197 bool SelectionController::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping)
   1198 {
   1199     if (!range)
   1200         return false;
   1201 
   1202     ExceptionCode ec = 0;
   1203     Node* startContainer = range->startContainer(ec);
   1204     if (ec)
   1205         return false;
   1206 
   1207     Node* endContainer = range->endContainer(ec);
   1208     if (ec)
   1209         return false;
   1210 
   1211     ASSERT(startContainer);
   1212     ASSERT(endContainer);
   1213     ASSERT(startContainer->document() == endContainer->document());
   1214 
   1215     m_frame->document()->updateLayoutIgnorePendingStylesheets();
   1216 
   1217     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
   1218     // they start at the beginning of the next line instead
   1219     bool collapsed = range->collapsed(ec);
   1220     if (ec)
   1221         return false;
   1222 
   1223     int startOffset = range->startOffset(ec);
   1224     if (ec)
   1225         return false;
   1226 
   1227     int endOffset = range->endOffset(ec);
   1228     if (ec)
   1229         return false;
   1230 
   1231     // FIXME: Can we provide extentAffinity?
   1232     VisiblePosition visibleStart(startContainer, startOffset, collapsed ? affinity : DOWNSTREAM);
   1233     VisiblePosition visibleEnd(endContainer, endOffset, SEL_DEFAULT_AFFINITY);
   1234     setSelection(VisibleSelection(visibleStart, visibleEnd), closeTyping);
   1235     return true;
   1236 }
   1237 
   1238 bool SelectionController::isInPasswordField() const
   1239 {
   1240     Node* startNode = start().node();
   1241     if (!startNode)
   1242         return false;
   1243 
   1244     startNode = startNode->shadowAncestorNode();
   1245     if (!startNode)
   1246         return false;
   1247 
   1248     if (!startNode->hasTagName(inputTag))
   1249         return false;
   1250 
   1251     return static_cast<HTMLInputElement*>(startNode)->inputType() == HTMLInputElement::PASSWORD;
   1252 }
   1253 
   1254 bool SelectionController::caretRendersInsideNode(Node* node) const
   1255 {
   1256     if (!node)
   1257         return false;
   1258     return !isTableElement(node) && !editingIgnoresContent(node);
   1259 }
   1260 
   1261 void SelectionController::focusedOrActiveStateChanged()
   1262 {
   1263     bool activeAndFocused = isFocusedAndActive();
   1264 
   1265     // Because RenderObject::selectionBackgroundColor() and
   1266     // RenderObject::selectionForegroundColor() check if the frame is active,
   1267     // we have to update places those colors were painted.
   1268     if (RenderView* view = toRenderView(m_frame->document()->renderer()))
   1269         view->repaintRectangleInViewAndCompositedLayers(enclosingIntRect(m_frame->selectionBounds()));
   1270 
   1271     // Caret appears in the active frame.
   1272     if (activeAndFocused)
   1273         m_frame->setSelectionFromNone();
   1274     setCaretVisible(activeAndFocused);
   1275 
   1276     // Update for caps lock state
   1277     m_frame->eventHandler()->capsLockStateMayHaveChanged();
   1278 
   1279     // Because CSSStyleSelector::checkOneSelector() and
   1280     // RenderTheme::isFocused() check if the frame is active, we have to
   1281     // update style and theme state that depended on those.
   1282     if (Node* node = m_frame->document()->focusedNode()) {
   1283         node->setNeedsStyleRecalc();
   1284         if (RenderObject* renderer = node->renderer())
   1285             if (renderer && renderer->style()->hasAppearance())
   1286                 renderer->theme()->stateChanged(renderer, FocusState);
   1287     }
   1288 
   1289     // Secure keyboard entry is set by the active frame.
   1290     if (m_frame->document()->useSecureKeyboardEntryWhenActive())
   1291         m_frame->setUseSecureKeyboardEntry(activeAndFocused);
   1292 }
   1293 
   1294 void SelectionController::pageActivationChanged()
   1295 {
   1296     focusedOrActiveStateChanged();
   1297 }
   1298 
   1299 void SelectionController::setFocused(bool flag)
   1300 {
   1301     if (m_focused == flag)
   1302         return;
   1303     m_focused = flag;
   1304 
   1305     focusedOrActiveStateChanged();
   1306 }
   1307 
   1308 bool SelectionController::isFocusedAndActive() const
   1309 {
   1310     return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive();
   1311 }
   1312 
   1313 void SelectionController::updateAppearance()
   1314 {
   1315     ASSERT(!m_isDragCaretController);
   1316 
   1317 #if ENABLE(TEXT_CARET)
   1318     bool caretRectChanged = recomputeCaretRect();
   1319 
   1320     bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
   1321     bool shouldBlink = m_caretVisible
   1322         && isCaret() && (isContentEditable() || caretBrowsing);
   1323 
   1324     // If the caret moved, stop the blink timer so we can restart with a
   1325     // black caret in the new location.
   1326     if (caretRectChanged || !shouldBlink)
   1327         m_caretBlinkTimer.stop();
   1328 
   1329     // Start blinking with a black caret. Be sure not to restart if we're
   1330     // already blinking in the right location.
   1331     if (shouldBlink && !m_caretBlinkTimer.isActive()) {
   1332         if (double blinkInterval = m_frame->page()->theme()->caretBlinkInterval())
   1333             m_caretBlinkTimer.startRepeating(blinkInterval);
   1334 
   1335         if (!m_caretPaint) {
   1336             m_caretPaint = true;
   1337             invalidateCaretRect();
   1338         }
   1339     }
   1340 #endif
   1341 
   1342     RenderView* view = m_frame->contentRenderer();
   1343     if (!view)
   1344         return;
   1345 
   1346     VisibleSelection selection = this->selection();
   1347 
   1348     if (!selection.isRange()) {
   1349         view->clearSelection();
   1350         return;
   1351     }
   1352 
   1353     // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
   1354     // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
   1355     // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
   1356     // and will fill the gap before 'bar'.
   1357     Position startPos = selection.start();
   1358     Position candidate = startPos.downstream();
   1359     if (candidate.isCandidate())
   1360         startPos = candidate;
   1361     Position endPos = selection.end();
   1362     candidate = endPos.upstream();
   1363     if (candidate.isCandidate())
   1364         endPos = candidate;
   1365 
   1366     // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
   1367     // because we don't yet notify the SelectionController of text removal.
   1368     if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
   1369         RenderObject* startRenderer = startPos.node()->renderer();
   1370         RenderObject* endRenderer = endPos.node()->renderer();
   1371         view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset());
   1372     }
   1373 }
   1374 
   1375 void SelectionController::setCaretVisible(bool flag)
   1376 {
   1377     if (m_caretVisible == flag)
   1378         return;
   1379     clearCaretRectIfNeeded();
   1380     m_caretVisible = flag;
   1381     updateAppearance();
   1382 }
   1383 
   1384 void SelectionController::clearCaretRectIfNeeded()
   1385 {
   1386 #if ENABLE(TEXT_CARET)
   1387     if (!m_caretPaint)
   1388         return;
   1389     m_caretPaint = false;
   1390     invalidateCaretRect();
   1391 #endif
   1392 }
   1393 
   1394 void SelectionController::caretBlinkTimerFired(Timer<SelectionController>*)
   1395 {
   1396 #if ENABLE(TEXT_CARET)
   1397     ASSERT(m_caretVisible);
   1398     ASSERT(isCaret());
   1399     bool caretPaint = m_caretPaint;
   1400     if (isCaretBlinkingSuspended() && caretPaint)
   1401         return;
   1402     m_caretPaint = !caretPaint;
   1403     invalidateCaretRect();
   1404 #endif
   1405 }
   1406 
   1407 #ifndef NDEBUG
   1408 
   1409 void SelectionController::formatForDebugger(char* buffer, unsigned length) const
   1410 {
   1411     m_selection.formatForDebugger(buffer, length);
   1412 }
   1413 
   1414 void SelectionController::showTreeForThis() const
   1415 {
   1416     m_selection.showTreeForThis();
   1417 }
   1418 
   1419 #endif
   1420 
   1421 }
   1422 
   1423 #ifndef NDEBUG
   1424 
   1425 void showTree(const WebCore::SelectionController& sel)
   1426 {
   1427     sel.showTreeForThis();
   1428 }
   1429 
   1430 void showTree(const WebCore::SelectionController* sel)
   1431 {
   1432     if (sel)
   1433         sel->showTreeForThis();
   1434 }
   1435 
   1436 #endif
   1437