2009-04-28 Xan Lopez <xlopez@igalia.com>
authorxan@webkit.org <xan@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2009 08:44:40 +0000 (08:44 +0000)
committerxan@webkit.org <xan@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2009 08:44:40 +0000 (08:44 +0000)
        Reviewed by Justin Garcia.

        https://bugs.webkit.org/show_bug.cgi?id=16135
        [GTK] Support caret browsing

        Based on a patch by Alp Toker.

        Implement basic support for caret browsing, active only when the
        corresponding setting is enabled.

        * page/EventHandler.cpp:
        (WebCore::EventHandler::handleMouseReleaseEvent):
        * page/FocusController.cpp:
        (WebCore::FocusController::advanceFocus):
        (WebCore::clearSelectionIfNeeded):
        (WebCore::FocusController::setFocusedNode):
        * page/Frame.cpp:
        (WebCore::Frame::setFocusedNodeIfNeeded):
        (WebCore::Frame::setSelectionFromNone):
        (WebCore::Frame::respondToChangedSelection):
        * page/Settings.cpp:
        (WebCore::Settings::Settings):
        * page/Settings.h:
        * rendering/RenderBlock.cpp:
        (WebCore::RenderBlock::paintCaret):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@42924 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/page/EventHandler.cpp
WebCore/page/FocusController.cpp
WebCore/page/Frame.cpp
WebCore/page/Settings.cpp
WebCore/page/Settings.h
WebCore/rendering/RenderBlock.cpp

index 071eb16..a1fb9d0 100644 (file)
@@ -1,3 +1,31 @@
+2009-04-28  Xan Lopez  <xlopez@igalia.com>
+
+        Reviewed by Justin Garcia.
+
+        https://bugs.webkit.org/show_bug.cgi?id=16135
+        [GTK] Support caret browsing
+
+        Based on a patch by Alp Toker.
+
+        Implement basic support for caret browsing, active only when the
+        corresponding setting is enabled.
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleMouseReleaseEvent):
+        * page/FocusController.cpp:
+        (WebCore::FocusController::advanceFocus):
+        (WebCore::clearSelectionIfNeeded):
+        (WebCore::FocusController::setFocusedNode):
+        * page/Frame.cpp:
+        (WebCore::Frame::setFocusedNodeIfNeeded):
+        (WebCore::Frame::setSelectionFromNone):
+        (WebCore::Frame::respondToChangedSelection):
+        * page/Settings.cpp:
+        (WebCore::Settings::Settings):
+        * page/Settings.h:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paintCaret):
+
 2009-04-27  Eric Roman  <eroman@chromium.org>
 
         Reviewed by Darin Fisher.
index 276fe2a..61abebd 100644 (file)
@@ -565,7 +565,8 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
             && event.event().button() != RightButton) {
         VisibleSelection newSelection;
         Node *node = event.targetNode();
-        if (node && node->isContentEditable() && node->renderer()) {
+        bool caretBrowsing = m_frame->settings()->caretBrowsingEnabled();
+        if (node && (caretBrowsing || node->isContentEditable()) && node->renderer()) {
             VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
             newSelection = VisibleSelection(pos);
         }
index 9760b3c..8ec684f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nuanti Ltd.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,6 +46,7 @@
 #include "RenderObject.h"
 #include "RenderWidget.h"
 #include "SelectionController.h"
+#include "Settings.h"
 #include "Widget.h"
 #include <wtf/Platform.h>
 
@@ -114,9 +116,16 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even
     ASSERT(frame);
     Document* document = frame->document();
 
+    Node* currentNode = document->focusedNode();
+    // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself
+    bool caretBrowsing = focusedOrMainFrame()->settings()->caretBrowsingEnabled();
+
+    if (caretBrowsing && !currentNode)
+        currentNode = frame->selection()->start().node();
+
     Node* node = (direction == FocusDirectionForward)
-        ? document->nextFocusableNode(document->focusedNode(), event)
-        : document->previousFocusableNode(document->focusedNode(), event);
+        ? document->nextFocusableNode(currentNode, event)
+        : document->previousFocusableNode(currentNode, event);
             
     // If there's no focusable node to advance to, move up the frame tree until we find one.
     while (!node && frame) {
@@ -195,6 +204,12 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even
     if (newDocument)
         setFocusedFrame(newDocument->frame());
 
+    if (caretBrowsing) {
+        VisibleSelection newSelection(Position(node, 0), Position(node, 0), DOWNSTREAM);
+        if (frame->shouldChangeSelection(newSelection))
+            frame->selection()->setSelection(newSelection);
+    }
+
     static_cast<Element*>(node)->focus(false);
     return true;
 }
@@ -223,7 +238,11 @@ static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFram
     SelectionController* s = oldFocusedFrame->selection();
     if (s->isNone())
         return;
-    
+
+    bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled();
+    if (caretBrowsing)
+        return;
+
     Node* selectionStartNode = s->selection().start().node();
     if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode) || selectionStartNode->shadowAncestorNode() == newFocusedNode)
         return;
@@ -248,7 +267,8 @@ bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFra
     Node* oldFocusedNode = oldDocument ? oldDocument->focusedNode() : 0;
     if (oldFocusedNode == node)
         return true;
-        
+
+    // FIXME: Might want to disable this check for caretBrowsing
     if (oldFocusedNode && oldFocusedNode->rootEditableElement() == oldFocusedNode && !relinquishesEditingFocus(oldFocusedNode))
         return false;
         
index 7ca8cec..7387fc3 100644 (file)
@@ -71,6 +71,7 @@
 #include "TextResourceDecoder.h"
 #include "XMLNames.h"
 #include "ScriptController.h"
+#include "htmlediting.h"
 #include "npruntime_impl.h"
 #include "visible_units.h"
 #include <wtf/RefCountedLeakCounter.h>
@@ -572,6 +573,15 @@ void Frame::setFocusedNodeIfNeeded()
     if (selection()->isNone() || !selection()->isFocusedAndActive())
         return;
 
+    bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
+    if (caretBrowsing) {
+        Node* anchor = enclosingAnchorElement(selection()->base());
+        if (anchor) {
+            page()->focusController()->setFocusedNode(anchor, this);
+            return;
+        }
+    }
+
     Node* target = selection()->rootEditableElement();
     if (target) {
         RenderObject* renderer = target->renderer();
@@ -592,6 +602,9 @@ void Frame::setFocusedNodeIfNeeded()
         }
         document()->setFocusedNode(0);
     }
+
+    if (caretBrowsing)
+        page()->focusController()->setFocusedNode(0, this);
 }
 
 void Frame::selectionLayoutChanged()
@@ -599,8 +612,9 @@ void Frame::selectionLayoutChanged()
     bool caretRectChanged = selection()->recomputeCaretRect();
 
 #if ENABLE(TEXT_CARET)
+    bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
     bool shouldBlink = m_caretVisible
-        && selection()->isCaret() && selection()->isContentEditable();
+        && selection()->isCaret() && (selection()->isContentEditable() || caretBrowsing);
 
     // If the caret moved, stop the blink timer so we can restart with a
     // black caret in the new location.
@@ -1335,7 +1349,8 @@ void Frame::setSelectionFromNone()
     // Put a caret inside the body if the entire frame is editable (either the 
     // entire WebView is editable or designMode is on for this document).
     Document *doc = document();
-    if (!selection()->isNone() || !isContentEditable())
+    bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
+    if (!selection()->isNone() || !(isContentEditable() || caretBrowsing))
         return;
         
     Node* node = doc->documentElement();
@@ -1657,7 +1672,8 @@ void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool
     if (isContinuousSpellCheckingEnabled) {
         VisibleSelection newAdjacentWords;
         VisibleSelection newSelectedSentence;
-        if (selection()->selection().isContentEditable()) {
+        bool caretBrowsing = settings() && settings()->caretBrowsingEnabled();
+        if (selection()->selection().isContentEditable() || caretBrowsing) {
             VisiblePosition newStart(selection()->selection().visibleStart());
             newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
             if (isContinuousGrammarCheckingEnabled)
index 7cb835f..128c57f 100644 (file)
@@ -92,6 +92,7 @@ Settings::Settings(Page* page)
     , m_enforceCSSMIMETypeInStrictMode(true)
     , m_usesEncodingDetector(false)
     , m_allowScriptsToCloseWindows(false)
+    , m_caretBrowsingEnabled(false)
     , m_editingBehavior(
 #if PLATFORM(MAC)
         EditingMacBehavior
@@ -444,4 +445,9 @@ void Settings::setAllowScriptsToCloseWindows(bool allowScriptsToCloseWindows)
     m_allowScriptsToCloseWindows = allowScriptsToCloseWindows;
 }
 
+void Settings::setCaretBrowsingEnabled(bool caretBrowsingEnabled)
+{
+    m_caretBrowsingEnabled = caretBrowsingEnabled;
+}
+
 } // namespace WebCore
index 0834064..a8919a5 100644 (file)
@@ -127,7 +127,10 @@ namespace WebCore {
 
         void setPrivateBrowsingEnabled(bool);
         bool privateBrowsingEnabled() const { return m_privateBrowsingEnabled; }
-        
+
+        void setCaretBrowsingEnabled(bool);
+        bool caretBrowsingEnabled() const { return m_caretBrowsingEnabled; }
+
         void setDefaultTextEncodingName(const String&);
         const String& defaultTextEncodingName() const { return m_defaultTextEncodingName; }
         
@@ -255,6 +258,7 @@ namespace WebCore {
         bool m_isJavaEnabled : 1;
         bool m_loadsImagesAutomatically : 1;
         bool m_privateBrowsingEnabled : 1;
+        bool m_caretBrowsingEnabled : 1;
         bool m_arePluginsEnabled : 1;
         bool m_databasesEnabled : 1;
         bool m_localStorageEnabled : 1;
index 8e50381..3bbb6ee 100644 (file)
@@ -1723,9 +1723,10 @@ void RenderBlock::paintCaret(PaintInfo& paintInfo, int tx, int ty, CaretType typ
 {
     SelectionController* selection = type == CursorCaret ? document()->frame()->selection() : document()->frame()->dragCaretController();
 
-    // Ask the SelectionController if the caret should be painted by this block
+    // Paint the caret if the SelectionController says so or if caret browsing is enabled
+    bool caretBrowsing = document()->frame()->settings() && document()->frame()->settings()->caretBrowsingEnabled();
     RenderObject* caretPainter = selection->caretRenderer();
-    if (caretPainter == this && selection->isContentEditable()) {
+    if (caretPainter == this && (selection->isContentEditable() || caretBrowsing)) {
         // Convert the painting offset into the local coordinate system of this renderer,
         // to match the localCaretRect computed by the SelectionController
         offsetForContents(tx, ty);