Commit afbef274 authored by rniwa@webkit.org's avatar rniwa@webkit.org

2011-05-08 Ryosuke Niwa <rniwa@webkit.org>

        Reviewed by Darin Adler.

        Extract a DragCaretController from FrameSelection
        https://bugs.webkit.org/show_bug.cgi?id=60273

        Extracted CaretBase and DragCaretController from FrameSelection. CaretBase is a base class for
        DragCaretController and FrameSelection and provides functions to paint caret.

        Since DragCaretController doesn't need to store selection, it only holds one VisiblePosition.

        * WebCore.exp.in:
        * editing/FrameSelection.cpp:
        (WebCore::CaretBase::CaretBase): Added.
        (WebCore::DragCaretController::DragCaretController): Added; Set m_caretVisible true.
        (WebCore::DragCaretController::isContentRichlyEditable): Added.
        (WebCore::FrameSelection::FrameSelection): Several member variables are move to CaretBase.
        (WebCore::DragCaretController::setCaretPosition): Extracted from FrameSelection::setSelection.
        (WebCore::FrameSelection::setSelection): Removed an early exit for DragCaretController.
        (WebCore::clearRenderViewSelection): Extracted from FrameSelection::respondToNodeModification.
        (WebCore::DragCaretController::nodeWillBeRemoved): Extracted from FrameSelection::nodeWillBeRemoved
        and respondToNodeModification. Note that the position DragCaretController holds is equivalent to
        FrameSelection's base or start so when removingNodeRemovesPosition returns true for m_position,
        we used to execute the first if clause and cleared render tree selection and DOM tree selection.
        This is exactly what new DragCaretController::nodeWillBeRemoved does.
        (WebCore::FrameSelection::nodeWillBeRemoved): Simplified early exist conditions.
        (WebCore::FrameSelection::respondToNodeModification): Calls clearRenderViewSelection.
        (WebCore::CaretBase::updateCaretRect): Takes document, caretPosition, selection type, and boolean isOrphaned.
        Note that we can't obtain the document from caretPosition because VisiblePosition can be null even if
        FrameSelection's start was not null.
        (WebCore::caretRendersInsideNode): Moved; Made static local.
        (WebCore::CaretBase::caretRenderer): Extracted from FrameSelection::caretRenderer.
        (WebCore::FrameSelection::caretRenderer): Calls CaretBase::caretRenderer.
        (WebCore::DragCaretController::caretRenderer): Ditto.
        (WebCore::FrameSelection::localCaretRect): Calls updateCaretRect with extra arguments.
        (WebCore::CaretBase::absoluteBoundsForLocalRect): Moved from FrameSelection; Takes Node*.
        (WebCore::CaretBase::caretRepaintRect): Ditto.
        (WebCore::FrameSelection::recomputeCaretRect): Calls absoluteBoundsForLocalRect, caretRepaintRect,
        and shouldRepaintCaret with extra arguments.
        (WebCore::CaretBase::shouldRepaintCaret): Takes a boolean isContentEditable.
        (WebCore::FrameSelection::invalidateCaretRect): Calls CaretBase::invalidateCaretRect.
        (WebCore::CaretBase::invalidateCaretRect): Extracted from FrameSelection::invalidateCaretRect.
        (WebCore::FrameSelection::paintCaret): Calls CaretBase::paintCaret.
        (WebCore::CaretBase::paintCaret): Extracted from FrameSelection::paintCaret.
        (WebCore::FrameSelection::updateAppearance): Removed an assertion that this function is never called for
        DragCaretController.
        (WebCore::DragCaretController::paintDragCaret): Moved from FrameSelection::paintDragCaret.
        * editing/FrameSelection.h:
        (WebCore::CaretBase::localCaretRectForPainting): Added.
        (WebCore::DragCaretController::isContentEditable): Added.
        (WebCore::DragCaretController::hasCaret): Added.
        (WebCore::DragCaretController::caretPosition): Added.
        (WebCore::DragCaretController::clear): Added.
        * page/DragController.cpp:
        (WebCore::DragController::tryDocumentDrag): Uses DragCaretController.
        (WebCore::DragController::dispatchTextInputEventFor): Ditto.
        (WebCore::DragController::concludeEditDrag): Ditto.
        (WebCore::DragController::placeDragCaret): Ditto.
        * page/Page.cpp:
        (WebCore::Page::Page): Instantiates DragCaretController instead of FrameSelection.
        * page/Page.h:
        (WebCore::Page::dragCaretController): Returns DragCaretController* instead of FrameSelection*.
        * rendering/RenderBlock.cpp:
        (WebCore::RenderBlock::paintCaret): Uses FrameSelection and DragCaretController.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@86039 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2e498e75
2011-05-08 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Darin Adler.
Extract a DragCaretController from FrameSelection
https://bugs.webkit.org/show_bug.cgi?id=60273
Extracted CaretBase and DragCaretController from FrameSelection. CaretBase is a base class for
DragCaretController and FrameSelection and provides functions to paint caret.
Since DragCaretController doesn't need to store selection, it only holds one VisiblePosition.
* WebCore.exp.in:
* editing/FrameSelection.cpp:
(WebCore::CaretBase::CaretBase): Added.
(WebCore::DragCaretController::DragCaretController): Added; Set m_caretVisible true.
(WebCore::DragCaretController::isContentRichlyEditable): Added.
(WebCore::FrameSelection::FrameSelection): Several member variables are move to CaretBase.
(WebCore::DragCaretController::setCaretPosition): Extracted from FrameSelection::setSelection.
(WebCore::FrameSelection::setSelection): Removed an early exit for DragCaretController.
(WebCore::clearRenderViewSelection): Extracted from FrameSelection::respondToNodeModification.
(WebCore::DragCaretController::nodeWillBeRemoved): Extracted from FrameSelection::nodeWillBeRemoved
and respondToNodeModification. Note that the position DragCaretController holds is equivalent to
FrameSelection's base or start so when removingNodeRemovesPosition returns true for m_position,
we used to execute the first if clause and cleared render tree selection and DOM tree selection.
This is exactly what new DragCaretController::nodeWillBeRemoved does.
(WebCore::FrameSelection::nodeWillBeRemoved): Simplified early exist conditions.
(WebCore::FrameSelection::respondToNodeModification): Calls clearRenderViewSelection.
(WebCore::CaretBase::updateCaretRect): Takes document, caretPosition, selection type, and boolean isOrphaned.
Note that we can't obtain the document from caretPosition because VisiblePosition can be null even if
FrameSelection's start was not null.
(WebCore::caretRendersInsideNode): Moved; Made static local.
(WebCore::CaretBase::caretRenderer): Extracted from FrameSelection::caretRenderer.
(WebCore::FrameSelection::caretRenderer): Calls CaretBase::caretRenderer.
(WebCore::DragCaretController::caretRenderer): Ditto.
(WebCore::FrameSelection::localCaretRect): Calls updateCaretRect with extra arguments.
(WebCore::CaretBase::absoluteBoundsForLocalRect): Moved from FrameSelection; Takes Node*.
(WebCore::CaretBase::caretRepaintRect): Ditto.
(WebCore::FrameSelection::recomputeCaretRect): Calls absoluteBoundsForLocalRect, caretRepaintRect,
and shouldRepaintCaret with extra arguments.
(WebCore::CaretBase::shouldRepaintCaret): Takes a boolean isContentEditable.
(WebCore::FrameSelection::invalidateCaretRect): Calls CaretBase::invalidateCaretRect.
(WebCore::CaretBase::invalidateCaretRect): Extracted from FrameSelection::invalidateCaretRect.
(WebCore::FrameSelection::paintCaret): Calls CaretBase::paintCaret.
(WebCore::CaretBase::paintCaret): Extracted from FrameSelection::paintCaret.
(WebCore::FrameSelection::updateAppearance): Removed an assertion that this function is never called for
DragCaretController.
(WebCore::DragCaretController::paintDragCaret): Moved from FrameSelection::paintDragCaret.
* editing/FrameSelection.h:
(WebCore::CaretBase::localCaretRectForPainting): Added.
(WebCore::DragCaretController::isContentEditable): Added.
(WebCore::DragCaretController::hasCaret): Added.
(WebCore::DragCaretController::caretPosition): Added.
(WebCore::DragCaretController::clear): Added.
* page/DragController.cpp:
(WebCore::DragController::tryDocumentDrag): Uses DragCaretController.
(WebCore::DragController::dispatchTextInputEventFor): Ditto.
(WebCore::DragController::concludeEditDrag): Ditto.
(WebCore::DragController::placeDragCaret): Ditto.
* page/Page.cpp:
(WebCore::Page::Page): Instantiates DragCaretController instead of FrameSelection.
* page/Page.h:
(WebCore::Page::dragCaretController): Returns DragCaretController* instead of FrameSelection*.
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintCaret): Uses FrameSelection and DragCaretController.
2011-05-08 Dan Bernstein <mitz@apple.com>
Reviewed by Darin Adler.
......@@ -356,7 +356,7 @@ __ZN7WebCore14FrameSelection20setSelectionFromNoneEv
__ZN7WebCore14FrameSelection6modifyENS0_11EAlterationENS_18SelectionDirectionENS_15TextGranularityEb
__ZN7WebCore14FrameSelection5clearEv
__ZN7WebCore14FrameSelection9selectAllEv
__ZN7WebCore14FrameSelectionC1EPNS_5FrameEb
__ZN7WebCore14FrameSelectionC1EPNS_5FrameE
__ZN7WebCore14ResourceHandle12releaseProxyEv
__ZN7WebCore14ResourceHandle20forceContentSniffingEv
__ZN7WebCore14ResourceLoader14cancelledErrorEv
......
......@@ -70,18 +70,31 @@ using namespace HTMLNames;
const int NoXPosForVerticalArrowNavigation = INT_MIN;
FrameSelection::FrameSelection(Frame* frame, bool isDragCaretController)
CaretBase::CaretBase()
: m_caretRectNeedsUpdate(true)
, m_absCaretBoundsDirty(true)
, m_caretVisible(false)
, m_caretPaint(true)
{
}
DragCaretController::DragCaretController()
{
m_caretVisible = true;
}
bool DragCaretController::isContentRichlyEditable() const
{
return isRichlyEditablePosition(m_position.deepEquivalent());
}
FrameSelection::FrameSelection(Frame* frame)
: m_frame(frame)
, m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation)
, m_granularity(CharacterGranularity)
, m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired)
, m_caretRectNeedsUpdate(true)
, m_absCaretBoundsDirty(true)
, m_isDragCaretController(isDragCaretController)
, m_isCaretBlinkingSuspended(false)
, m_focused(frame && frame->page() && frame->page()->focusController()->focusedFrame() == frame)
, m_caretVisible(isDragCaretController)
, m_caretPaint(true)
{
setIsDirectional(false);
}
......@@ -127,6 +140,23 @@ void FrameSelection::moveTo(const Position &base, const Position &extent, EAffin
setSelection(VisibleSelection(base, extent, affinity), options);
}
void DragCaretController::setCaretPosition(const VisiblePosition& position)
{
if (m_position == position)
return;
if (Node* node = m_position.deepEquivalent().containerNode())
invalidateCaretRect(node);
m_position = position;
m_caretRectNeedsUpdate = true;
Document* document = 0;
if (Node* node = m_position.deepEquivalent().containerNode()) {
invalidateCaretRect(node);
document = node->document();
}
updateCaretRect(document, m_position, m_position.isNotNull() ? VisibleSelection::CaretSelection : VisibleSelection::NoSelection, m_position.isOrphan());
}
void FrameSelection::setSelection(const VisibleSelection& s, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity, DirectionalityPolicy directionalityPolicy)
{
m_granularity = granularity;
......@@ -137,14 +167,6 @@ void FrameSelection::setSelection(const VisibleSelection& s, SetSelectionOptions
setIsDirectional(directionalityPolicy == MakeDirectionalSelection);
if (m_isDragCaretController) {
invalidateCaretRect();
m_selection = s;
m_caretRectNeedsUpdate = true;
invalidateCaretRect();
updateCaretRect();
return;
}
if (!m_frame) {
m_selection = s;
return;
......@@ -219,14 +241,31 @@ static bool removingNodeRemovesPosition(Node* node, const Position& position)
return element->contains(position.anchorNode()) || element->contains(position.anchorNode()->shadowAncestorNode());
}
void FrameSelection::nodeWillBeRemoved(Node *node)
static void clearRenderViewSelection(const Position& position)
{
if (isNone())
RefPtr<Document> document = position.anchorNode()->document();
document->updateStyleIfNeeded();
if (RenderView* view = toRenderView(document->renderer()))
view->clearSelection();
}
void DragCaretController::nodeWillBeRemoved(Node* node)
{
if (!hasCaret() || (node && !node->inDocument()))
return;
if (!removingNodeRemovesPosition(node, m_position.deepEquivalent()))
return;
clearRenderViewSelection(m_position.deepEquivalent());
clear();
}
void FrameSelection::nodeWillBeRemoved(Node* node)
{
// There can't be a selection inside a fragment, so if a fragment's node is being removed,
// the selection in the document that created the fragment needs no adjustment.
if (node && highestAncestor(node)->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
if (isNone() || (node && !node->inDocument()))
return;
respondToNodeModification(node, removingNodeRemovesPosition(node, m_selection.base()), removingNodeRemovesPosition(node, m_selection.extent()),
......@@ -263,12 +302,8 @@ void FrameSelection::respondToNodeModification(Node* node, bool baseRemoved, boo
}
}
if (clearRenderTreeSelection) {
RefPtr<Document> document = m_selection.start().anchorNode()->document();
document->updateStyleIfNeeded();
if (RenderView* view = toRenderView(document->renderer()))
view->clearSelection();
}
if (clearRenderTreeSelection)
clearRenderViewSelection(m_selection.start());
if (clearDOMTreeSelection)
setSelection(VisibleSelection(), 0);
......@@ -1031,29 +1066,28 @@ void FrameSelection::setCaretRectNeedsUpdate(bool flag)
m_caretRectNeedsUpdate = flag;
}
void FrameSelection::updateCaretRect()
void CaretBase::updateCaretRect(Document* document, const VisiblePosition& caretPosition, VisibleSelection::SelectionType type, bool isOrphaned)
{
if (isNone() || !m_selection.start().anchorNode()->inDocument() || !m_selection.end().anchorNode()->inDocument()) {
if (type == VisibleSelection::NoSelection || isOrphaned) {
m_caretRect = IntRect();
return;
}
m_selection.start().anchorNode()->document()->updateStyleIfNeeded();
document->updateStyleIfNeeded();
m_caretRect = IntRect();
if (isCaret()) {
VisiblePosition pos(m_selection.start(), m_selection.affinity());
if (pos.isNotNull()) {
ASSERT(pos.deepEquivalent().deprecatedNode()->renderer());
if (type == VisibleSelection::CaretSelection) {
if (caretPosition.isNotNull()) {
ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());
// First compute a rect local to the renderer at the selection start
RenderObject* renderer;
IntRect localRect = pos.localCaretRect(renderer);
IntRect localRect = caretPosition.localCaretRect(renderer);
// Get the renderer that will be responsible for painting the caret (which
// is either the renderer we just found, or one of its containers)
RenderObject* caretPainter = caretRenderer();
RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent().deprecatedNode());
// Compute an offset between the renderer and the caretPainter
bool unrooted = false;
......@@ -1077,9 +1111,13 @@ void FrameSelection::updateCaretRect()
m_caretRectNeedsUpdate = false;
}
RenderObject* FrameSelection::caretRenderer() const
static inline bool caretRendersInsideNode(Node* node)
{
return node && !isTableElement(node) && !editingIgnoresContent(node);
}
RenderObject* CaretBase::caretRenderer(Node* node) const
{
Node* node = m_selection.start().deprecatedNode();
if (!node)
return 0;
......@@ -1092,17 +1130,29 @@ RenderObject* FrameSelection::caretRenderer() const
return paintedByBlock ? renderer : renderer->containingBlock();
}
RenderObject* FrameSelection::caretRenderer() const
{
return CaretBase::caretRenderer(m_selection.start().deprecatedNode());
}
RenderObject* DragCaretController::caretRenderer() const
{
return CaretBase::caretRenderer(m_position.deepEquivalent().deprecatedNode());
}
IntRect FrameSelection::localCaretRect()
{
if (m_caretRectNeedsUpdate)
updateCaretRect();
if (m_caretRectNeedsUpdate) {
bool isOrphaned = !isNone() && (!m_selection.start().anchorNode()->inDocument() || !m_selection.end().anchorNode()->inDocument());
updateCaretRect(m_frame->document(), VisiblePosition(m_selection.start(), m_selection.affinity()), m_selection.selectionType(), isOrphaned);
}
return m_caretRect;
}
IntRect FrameSelection::absoluteBoundsForLocalRect(const IntRect& rect) const
IntRect CaretBase::absoluteBoundsForLocalRect(Node* node, const IntRect& rect) const
{
RenderObject* caretPainter = caretRenderer();
RenderObject* caretPainter = caretRenderer(node);
if (!caretPainter)
return IntRect();
......@@ -1128,9 +1178,9 @@ static IntRect repaintRectForCaret(IntRect caret)
return caret;
}
IntRect FrameSelection::caretRepaintRect() const
IntRect CaretBase::caretRepaintRect(Node* node) const
{
return absoluteBoundsForLocalRect(repaintRectForCaret(localCaretRectForPainting()));
return absoluteBoundsForLocalRect(node, repaintRectForCaret(localCaretRectForPainting()));
}
bool FrameSelection::recomputeCaretRect()
......@@ -1140,7 +1190,7 @@ bool FrameSelection::recomputeCaretRect()
if (!m_frame)
return false;
FrameView* v = m_frame->document()->view();
if (!v)
return false;
......@@ -1152,7 +1202,7 @@ bool FrameSelection::recomputeCaretRect()
IntRect oldAbsCaretBounds = m_absCaretBounds;
// FIXME: Rename m_caretRect to m_localCaretRect.
m_absCaretBounds = absoluteBoundsForLocalRect(m_caretRect);
m_absCaretBounds = absoluteBoundsForLocalRect(m_selection.start().deprecatedNode(), m_caretRect);
m_absCaretBoundsDirty = false;
if (oldAbsCaretBounds == m_absCaretBounds)
......@@ -1160,25 +1210,25 @@ bool FrameSelection::recomputeCaretRect()
IntRect oldAbsoluteCaretRepaintBounds = m_absoluteCaretRepaintBounds;
// We believe that we need to inflate the local rect before transforming it to obtain the repaint bounds.
m_absoluteCaretRepaintBounds = caretRepaintRect();
m_absoluteCaretRepaintBounds = caretRepaintRect(m_selection.start().deprecatedNode());
#if ENABLE(TEXT_CARET)
if (RenderView* view = toRenderView(m_frame->document()->renderer())) {
// FIXME: make caret repainting container-aware.
view->repaintRectangleInViewAndCompositedLayers(oldAbsoluteCaretRepaintBounds, false);
if (shouldRepaintCaret(view))
if (shouldRepaintCaret(view, isContentEditable()))
view->repaintRectangleInViewAndCompositedLayers(m_absoluteCaretRepaintBounds, false);
}
#endif
return true;
}
bool FrameSelection::shouldRepaintCaret(const RenderView* view) const
bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditable) const
{
ASSERT(view);
Frame* frame = view->frameView() ? view->frameView()->frame() : 0; // The frame where the selection started.
bool caretBrowsing = frame && frame->settings() && frame->settings()->caretBrowsingEnabled();
return (caretBrowsing || isContentEditable());
return (caretBrowsing || isContentEditable);
}
void FrameSelection::invalidateCaretRect()
......@@ -1186,12 +1236,11 @@ void FrameSelection::invalidateCaretRect()
if (!isCaret())
return;
Document* d = m_selection.start().anchorNode()->document();
// recomputeCaretRect will always return false for the drag caret,
// because its m_frame is always 0.
bool caretRectChanged = recomputeCaretRect();
CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect());
}
void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
{
// EDIT FIXME: This is an unfortunate hack.
// Basically, we can't trust this layout position since we
// can't guarantee that the check to see if we are in unrendered
......@@ -1206,25 +1255,32 @@ void FrameSelection::invalidateCaretRect()
m_caretRectNeedsUpdate = true;
if (!caretRectChanged) {
RenderView* view = toRenderView(d->renderer());
if (view && shouldRepaintCaret(view))
view->repaintRectangleInViewAndCompositedLayers(caretRepaintRect(), false);
RenderView* view = toRenderView(node->document()->renderer());
if (view && shouldRepaintCaret(view, node->isContentEditable()))
view->repaintRectangleInViewAndCompositedLayers(caretRepaintRect(node), false);
}
}
void FrameSelection::paintCaret(GraphicsContext* context, int tx, int ty, const IntRect& clipRect)
{
if (!m_selection.isCaret())
return;
CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, tx, ty, clipRect);
}
void CaretBase::paintCaret(Node* node, GraphicsContext* context, int tx, int ty, const IntRect& clipRect) const
{
#if ENABLE(TEXT_CARET)
if (!m_caretVisible)
return;
if (!m_caretPaint)
return;
if (!m_selection.isCaret())
return;
IntRect drawingRect = localCaretRectForPainting();
if (caretRenderer() && caretRenderer()->isBox())
toRenderBox(caretRenderer())->flipForWritingMode(drawingRect);
RenderObject* renderer = caretRenderer(node);
if (renderer && renderer->isBox())
toRenderBox(renderer)->flipForWritingMode(drawingRect);
drawingRect.move(tx, ty);
IntRect caret = intersection(drawingRect, clipRect);
if (caret.isEmpty())
......@@ -1232,7 +1288,7 @@ void FrameSelection::paintCaret(GraphicsContext* context, int tx, int ty, const
Color caretColor = Color::black;
ColorSpace colorSpace = ColorSpaceDeviceRGB;
Element* element = rootEditableElement();
Element* element = node->rootEditableElement();
if (element && element->renderer()) {
caretColor = element->renderer()->style()->visitedDependentColor(CSSPropertyColor);
colorSpace = element->renderer()->style()->colorSpace();
......@@ -1240,6 +1296,7 @@ void FrameSelection::paintCaret(GraphicsContext* context, int tx, int ty, const
context->fillRect(caret, caretColor, colorSpace);
#else
UNUSED_PARAM(node);
UNUSED_PARAM(context);
UNUSED_PARAM(tx);
UNUSED_PARAM(ty);
......@@ -1480,13 +1537,6 @@ bool FrameSelection::isInPasswordField() const
return static_cast<HTMLInputElement*>(startNode)->isPasswordField();
}
bool FrameSelection::caretRendersInsideNode(Node* node) const
{
if (!node)
return false;
return !isTableElement(node) && !editingIgnoresContent(node);
}
void FrameSelection::focusedOrActiveStateChanged()
{
bool activeAndFocused = isFocusedAndActive();
......@@ -1555,8 +1605,6 @@ bool FrameSelection::isFocusedAndActive() const
void FrameSelection::updateAppearance()
{
ASSERT(!m_isDragCaretController);
#if ENABLE(TEXT_CARET)
bool caretRectChanged = recomputeCaretRect();
......@@ -1709,13 +1757,11 @@ void FrameSelection::setFocusedNodeIfNeeded()
m_frame->page()->focusController()->setFocusedNode(0, m_frame);
}
void FrameSelection::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const
void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const
{
#if ENABLE(TEXT_CARET)
FrameSelection* dragCaretController = m_frame->page()->dragCaretController();
ASSERT(dragCaretController->selection().isCaret());
if (dragCaretController->selection().start().anchorNode()->document()->frame() == m_frame)
dragCaretController->paintCaret(p, tx, ty, clipRect);
if (m_position.deepEquivalent().deprecatedNode()->document()->frame() == frame)
paintCaret(m_position.deepEquivalent().deprecatedNode(), p, tx, ty, clipRect);
#else
UNUSED_PARAM(p);
UNUSED_PARAM(tx);
......
......@@ -48,7 +48,58 @@ class VisiblePosition;
enum DirectionalityPolicy { MakeNonDirectionalSelection, MakeDirectionalSelection };
class FrameSelection {
class CaretBase {
WTF_MAKE_NONCOPYABLE(CaretBase);
WTF_MAKE_FAST_ALLOCATED;
protected:
CaretBase();
void invalidateCaretRect(Node*, bool caretRectChanged = false);
void updateCaretRect(Document*, const VisiblePosition& caretPosition, VisibleSelection::SelectionType, bool isOrphaned);
IntRect absoluteBoundsForLocalRect(Node*, const IntRect&) const;
IntRect absoluteCaretBounds(bool isContentEditable);
IntRect caretRepaintRect(Node*) const;
bool shouldRepaintCaret(const RenderView*, bool isContentEditable) const;
IntRect localCaretRectForPainting() const { return m_caretRect; }
void paintCaret(Node*, GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
RenderObject* caretRenderer(Node*) const;
IntRect m_caretRect; // caret rect in coords local to the renderer responsible for painting the caret
IntRect m_absCaretBounds; // absolute bounding rect for the caret
IntRect m_absoluteCaretRepaintBounds;
bool m_caretRectNeedsUpdate; // true if m_caretRect and m_absCaretBounds need to be calculated
bool m_absCaretBoundsDirty;
bool m_caretVisible;
bool m_caretPaint;
};
class DragCaretController : private CaretBase {
WTF_MAKE_NONCOPYABLE(DragCaretController);
WTF_MAKE_FAST_ALLOCATED;
public:
DragCaretController();
RenderObject* caretRenderer() const;
void paintDragCaret(Frame*, GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
bool isContentEditable() const { return m_position.rootEditableElement(); }
bool isContentRichlyEditable() const;
bool hasCaret() const { return m_position.isNotNull(); }
const VisiblePosition& caretPosition() { return m_position; }
void setCaretPosition(const VisiblePosition&);
void clear() { setCaretPosition(VisiblePosition()); }
void nodeWillBeRemoved(Node*);
private:
VisiblePosition m_position;
};
class FrameSelection : private CaretBase {
WTF_MAKE_NONCOPYABLE(FrameSelection);
WTF_MAKE_FAST_ALLOCATED;
public:
......@@ -63,7 +114,7 @@ public:
};
typedef unsigned SetSelectionOptions;
FrameSelection(Frame* = 0, bool isDragCaretController = false);
FrameSelection(Frame* = 0);
Element* rootEditableElement() const { return m_selection.rootEditableElement(); }
bool isContentEditable() const { return m_selection.isContentEditable(); }
......@@ -114,7 +165,6 @@ public:
// Caret rect local to the caret's renderer
IntRect localCaretRect();
IntRect localCaretRectForPainting() const { return m_caretRect; }
// Bounds of (possibly transformed) caret in absolute coords
IntRect absoluteCaretBounds();
......@@ -139,7 +189,7 @@ public:
void setCaretVisible(bool = true);
void clearCaretRectIfNeeded();
bool recomputeCaretRect(); // returns true if caret rect moved
bool recomputeCaretRect();
void invalidateCaretRect();
void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect);
......@@ -203,18 +253,11 @@ private:
VisiblePosition modifyMovingLeft(TextGranularity);
VisiblePosition modifyMovingBackward(TextGranularity);
void updateCaretRect();
IntRect caretRepaintRect() const;
bool shouldRepaintCaret(const RenderView* view) const;
int xPosForVerticalArrowNavigation(EPositionType);
void notifyAccessibilityForSelectionChange();
void focusedOrActiveStateChanged();
bool caretRendersInsideNode(Node*) const;
IntRect absoluteBoundsForLocalRect(const IntRect&) const;
void caretBlinkTimerFired(Timer<FrameSelection>*);
......@@ -231,18 +274,9 @@ private:
Timer<FrameSelection> m_caretBlinkTimer;
IntRect m_caretRect; // caret rect in coords local to the renderer responsible for painting the caret
IntRect m_absCaretBounds; // absolute bounding rect for the caret
IntRect m_absoluteCaretRepaintBounds;
bool m_caretRectNeedsUpdate; // true if m_caretRect and m_absCaretBounds need to be calculated
bool m_absCaretBoundsDirty;
bool m_isDirectional;
bool m_isDragCaretController;
bool m_isCaretBlinkingSuspended;
bool m_focused;
bool m_caretVisible;
bool m_caretPaint;
};
inline EditingStyle* FrameSelection::typingStyle() const
......
......@@ -330,10 +330,8 @@ bool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction a
Element* element = elementUnderMouse(m_documentUnderMouse.get(), point);
if (!element)
return false;
if (!asFileInput(element)) {
VisibleSelection dragCaret = m_documentUnderMouse->frame()->visiblePositionForPoint(point);
m_page->dragCaretController()->setSelection(dragCaret);
}
if (!asFileInput(element))
m_page->dragCaretController()->setCaretPosition(m_documentUnderMouse->frame()->visiblePositionForPoint(point));
Frame* innerFrame = element->document()->frame();
operation = dragIsMove(innerFrame->selection(), dragData) ? DragOperationMove : DragOperationCopy;
......@@ -372,10 +370,9 @@ static bool setSelectionToDragCaret(Frame* frame, VisibleSelection& dragCaret, R
bool DragController::dispatchTextInputEventFor(Frame* innerFrame, DragData* dragData)
{
ASSERT(!m_page->dragCaretController()->isNone());
VisibleSelection dragCaret(m_page->dragCaretController()->selection());
String text = dragCaret.isContentRichlyEditable() ? "" : dragData->asPlainText(innerFrame);
Node* target = innerFrame->editor()->findEventTargetFrom(dragCaret);
ASSERT(m_page->dragCaretController()->hasCaret());
String text = m_page->dragCaretController()->isContentRichlyEditable() ? "" : dragData->asPlainText(innerFrame);
Node* target = innerFrame->editor()->findEventTargetFrom(m_page->dragCaretController()->caretPosition());
ExceptionCode ec = 0;
return target->dispatchEvent(TextEvent::createForDrop(innerFrame->domWindow(), text), ec);
}
......@@ -395,7 +392,7 @@ bool DragController::concludeEditDrag(DragData* dragData)
Frame* innerFrame = element->ownerDocument()->frame();
ASSERT(innerFrame);
if (!m_page->dragCaretController()->isNone() && !dispatchTextInputEventFor(innerFrame, dragData))
if (m_page->dragCaretController()->hasCaret() && !dispatchTextInputEventFor(innerFrame, dragData))
return true;
if (dragData->containsColor()) {
......@@ -441,7 +438,7 @@ bool DragController::concludeEditDrag(DragData* dragData)
return true;