Changeset 18187 in webkit


Ignore:
Timestamp:
Dec 12, 2006 2:11:18 PM (17 years ago)
Author:
ggaren
Message:

Reviewed by Adam Roben, Dave Hyatt, Darin Adler.


Factored focus control into a FocusController class. I inted to use this
class for handling window active state and the focused frame, as well.

Layout tests pass.

  • WebCore.xcodeproj/project.pbxproj:
  • dom/Document.cpp: (WebCore::Document::view): (WebCore::Document::page): New helper function.
  • dom/Document.h: Moved setters before getters. (WebCore::Document::hoverNode): (WebCore::Document::activeNode):
  • dom/Node.cpp: (WebCore::Node::detach): Use the FocusController.
  • page/FocusController.cpp: Added. (WebCore::shouldFocus): renamed and refactored this helper function. (WebCore::shouldUnfocus): ditto.
  • page/FocusController.h: Added.
Location:
trunk/WebCore
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r18186 r18187  
     12006-12-12  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Reviewed by Adam Roben, Dave Hyatt, Darin Adler.
     4       
     5        Factored focus control into a FocusController class. I inted to use this
     6        class for handling window active state and the focused frame, as well.
     7
     8        Layout tests pass.
     9
     10        * WebCore.xcodeproj/project.pbxproj:
     11        * dom/Document.cpp:
     12        (WebCore::Document::view):
     13        (WebCore::Document::page): New helper function.
     14        * dom/Document.h: Moved setters before getters.
     15        (WebCore::Document::hoverNode):
     16        (WebCore::Document::activeNode):
     17        * dom/Node.cpp:
     18        (WebCore::Node::detach): Use the FocusController.
     19        * page/FocusController.cpp: Added.
     20        (WebCore::shouldFocus): renamed and refactored this helper function.
     21        (WebCore::shouldUnfocus): ditto.
     22        * page/FocusController.h: Added.
     23
    1242006-12-12  Anders Carlsson  <acarlsson@apple.com>
    225
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r18184 r18187  
    5050                148AFDA60AF58360008CC700 /* ExceptionHandlers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 148AFDA40AF58360008CC700 /* ExceptionHandlers.mm */; };
    5151                148CF65E0B00561400A997FC /* Screen.h in Headers */ = {isa = PBXBuildFile; fileRef = 148CF65D0B00561400A997FC /* Screen.h */; settings = {ATTRIBUTES = (Private, ); }; };
     52                14993BE50B2F2B1C0050497F /* FocusController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14993BE30B2F2B1C0050497F /* FocusController.cpp */; };
     53                14993BE60B2F2B1C0050497F /* FocusController.h in Headers */ = {isa = PBXBuildFile; fileRef = 14993BE40B2F2B1C0050497F /* FocusController.h */; };
    5254                14CF78A409F58CBF00EB3665 /* JSCSSValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14CF78A309F58CBF00EB3665 /* JSCSSValue.cpp */; };
    5355                14CF78A609F58CD800EB3665 /* JSCSSValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 14CF78A509F58CD800EB3665 /* JSCSSValue.h */; };
     
    30303032                148AFDA40AF58360008CC700 /* ExceptionHandlers.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = ExceptionHandlers.mm; sourceTree = "<group>"; };
    30313033                148CF65D0B00561400A997FC /* Screen.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Screen.h; sourceTree = "<group>"; };
     3034                14993BE30B2F2B1C0050497F /* FocusController.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FocusController.cpp; sourceTree = "<group>"; };
     3035                14993BE40B2F2B1C0050497F /* FocusController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FocusController.h; sourceTree = "<group>"; };
    30323036                14CF787109F587CA00EB3665 /* CSSValue.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = CSSValue.idl; sourceTree = "<group>"; };
    30333037                14CF78A309F58CBF00EB3665 /* JSCSSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSCSSValue.cpp; sourceTree = "<group>"; };
     
    66966700                                93C09A520B064DB3005ABD4D /* EventHandler.h */,
    66976701                                93C09A800B064F00005ABD4D /* EventHandler.cpp */,
     6702                                14993BE40B2F2B1C0050497F /* FocusController.h */,
     6703                                14993BE30B2F2B1C0050497F /* FocusController.cpp */,
    66986704                                65BF02290974816300C43196 /* Frame.cpp */,
    66996705                                65BF022A0974816300C43196 /* Frame.h */,
     
    1084110847                                93E241FF0B2B4E4000C732A1 /* HTMLFrameOwnerElement.h in Headers */,
    1084210848                                E11D51930B2E7A5F0056C188 /* Base64.h in Headers */,
     10849                                14993BE60B2F2B1C0050497F /* FocusController.h in Headers */,
    1084310850                        );
    1084410851                        runOnlyForDeploymentPostprocessing = 0;
     
    1216112168                                B25DFAAF0B2E2929000E6510 /* JSSVGMatrixCustom.cpp in Sources */,
    1216212169                                E11D51940B2E7A5F0056C188 /* Base64.cpp in Sources */,
     12170                                14993BE50B2F2B1C0050497F /* FocusController.cpp in Sources */,
    1216312171                        );
    1216412172                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/WebCore/dom/Document.cpp

    r18175 r18187  
    4646#include "EventNames.h"
    4747#include "ExceptionCode.h"
     48#include "FocusController.h"
    4849#include "Frame.h"
    4950#include "FrameLoader.h"
     
    811812}
    812813
     814FrameView* Document::view() const
     815{
     816    return m_view;
     817}
     818
    813819Frame* Document::frame() const
    814820{
    815821    return m_view ? m_view->frame() : 0;
     822}
     823
     824Page* Document::page() const
     825{
     826    Frame* frame = this->frame();
     827    return frame ? frame->page() : 0;   
    816828}
    817829
     
    19441956}
    19451957
     1958void Document::focusedNodeDetached(Node* node)
     1959{
     1960    Page* page = this->page();
     1961    if (!page)
     1962        return;
     1963    page->focusController()->focusedNodeDetached(node);
     1964}
     1965
    19461966void Document::hoveredNodeDetached(Node* node)
    19471967{
     
    19812001bool Document::setFocusedNode(PassRefPtr<Node> node)
    19822002{
    1983     Frame* frame = this->frame();
    1984     if (!frame)
    1985         return false;
    1986    
    1987     Page* page = frame->page();
     2003    Page* page = this->page();
    19882004    if (!page)
    19892005        return false;
    19902006   
    1991     return page->setFocusedNode(node);
     2007    return page->focusController()->setFocusedNode(node);
    19922008}
    19932009
    19942010Node* Document::focusedNode() const
    19952011{
    1996     Frame* frame = this->frame();
    1997     if (!frame)
    1998         return 0;
    1999    
    2000     Page* page = frame->page();
     2012    Page* page = this->page();
    20012013    if (!page)
    20022014        return 0;
    20032015   
    2004     return page->focusedNode();
     2016    return page->focusController()->focusedNode();
    20052017}
    20062018
  • trunk/WebCore/dom/Document.h

    r18175 r18187  
    7575    class NodeIterator;
    7676    class NodeList;
     77    class Page;
    7778    class PlatformMouseEvent;
    7879    class ProcessingInstruction;
     
    279280    bool takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state);
    280281
    281     FrameView* view() const { return m_view; }
    282     Frame* frame() const;
     282    FrameView* view() const; // can be NULL
     283    Frame* frame() const; // can be NULL
     284    Page* page() const; // can be NULL
    283285
    284286    PassRefPtr<Range> createRange();
     
    403405    void setSelectedStylesheetSet(const String&);
    404406
     407    // Convenience functions for accessing the page's focused node.
    405408    bool setFocusedNode(PassRefPtr<Node>);
    406409    Node* focusedNode() const;
    407410
     411    // Hover and active are still per-document, not per-page.
     412    void setHoverNode(PassRefPtr<Node>);
    408413    Node* hoverNode() const { return m_hoverNode.get(); }
    409     void setHoverNode(PassRefPtr<Node>);
     414
     415    void setActiveNode(PassRefPtr<Node>);
     416    Node* activeNode() const { return m_activeNode.get(); }
     417
     418    void focusedNodeDetached(Node*);
    410419    void hoveredNodeDetached(Node*);
    411420    void activeChainNodeDetached(Node*);
    412    
    413     Node* activeNode() const { return m_activeNode.get(); }
    414     void setActiveNode(PassRefPtr<Node>);
    415421
    416422    // Updates for :target (CSS3 selector).
  • trunk/WebCore/dom/Node.cpp

    r18175 r18187  
    718718    Document* doc = document();
    719719    if (m_focused)
    720         doc->setFocusedNode(0);
     720        doc->focusedNodeDetached(this);
    721721    if (m_hovered)
    722722        doc->hoveredNodeDetached(this);
  • trunk/WebCore/page/Page.cpp

    r18175 r18187  
    2222#include "Page.h"
    2323
    24 #include "AXObjectCache.h"
    2524#include "Chrome.h"
    2625#include "ChromeClient.h"
    2726#include "ContextMenuClient.h"
    2827#include "ContextMenuController.h"
    29 #include "Document.h"
    30 #include "Editor.h"
    3128#include "EditorClient.h"
    32 #include "Element.h"
    33 #include "Event.h"
    34 #include "EventNames.h"
     29#include "FocusController.h"
    3530#include "Frame.h"
    3631#include "FrameLoader.h"
    3732#include "FrameTree.h"
    38 #include "FrameView.h"
    39 #include "RenderWidget.h"
    4033#include "SelectionController.h"
    4134#include "StringHash.h"
     
    5245static HashMap<String, HashSet<Page*>*>* frameNamespaces;
    5346
    54 using namespace EventNames;
    55 
    56 static bool shouldAcquireEditingFocus(Node* node)
    57 {
    58     ASSERT(node);
    59     ASSERT(node->isContentEditable());
    60 
    61     Node* root = node->rootEditableElement();
    62     if (!root || !root->document()->frame())
    63         return false;
    64 
    65     return root->document()->frame()->editor()->shouldBeginEditing(rangeOfContents(root).get());
    66 }
    67 
    68 static bool shouldRelinquishEditingFocus(Node* node)
    69 {
    70     ASSERT(node);
    71     ASSERT(node->isContentEditable());
    72 
    73     Node* root = node->rootEditableElement();
    74     if (!root || !root->document()->frame())
    75         return false;
    76 
    77     return root->document()->frame()->editor()->shouldEndEditing(rangeOfContents(root).get());
    78 }
    79 
    80 static void clearSelectionIfNeeded(Node* oldFocusedNode, Node* newFocusedNode)
    81 {
    82     Frame* frame = oldFocusedNode ? oldFocusedNode->document()->frame() : 0;
    83     if (!frame)
    84         return;
    85 
    86     // Clear the selection when changing the focus node to null or to a node that is not
    87     // contained by the current selection.
    88     Node *startContainer = frame->selectionController()->start().node();
    89     if (!newFocusedNode || (startContainer && startContainer != newFocusedNode && !(startContainer->isDescendantOf(newFocusedNode)) && startContainer->shadowAncestorNode() != newFocusedNode))
    90         frame->selectionController()->clear();
    91 }
    92 
    93 static Widget* widgetForNode(Node* node)
    94 {
    95     if (!node)
    96         return 0;
    97     RenderObject* renderer = node->renderer();
    98     if (!renderer || !renderer->isWidget())
    99         return 0;
    100     return static_cast<RenderWidget*>(renderer)->widget();
    101 }
    102 
    10347Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient)
    104     : m_dragCaretController(new SelectionController(0, true))
    105     , m_chrome(new Chrome(this, chromeClient))
     48    : m_chrome(new Chrome(this, chromeClient))
     49    , m_dragCaretController(new SelectionController(0, true))
     50    , m_focusController(new FocusController)
    10651    , m_contextMenuController(new ContextMenuController(this, contextMenuClient))
    10752    , m_editorClient(editorClient)
     
    169114}
    170115
    171 bool Page::setFocusedNode(PassRefPtr<Node> newFocusedNode)
    172 {   
    173     if (m_focusedNode == newFocusedNode)
    174         return true;
    175 
    176     if (m_focusedNode && m_focusedNode == m_focusedNode->rootEditableElement() && !shouldRelinquishEditingFocus(m_focusedNode.get()))
    177         return false;
    178 
    179     bool focusChangeBlocked = false;
    180     RefPtr<Node> oldFocusedNode = m_focusedNode;
    181     m_focusedNode = 0;
    182     clearSelectionIfNeeded(oldFocusedNode.get(), newFocusedNode.get());
    183 
    184     // Remove focus from the existing focus node (if any)
    185     if (oldFocusedNode && !oldFocusedNode->inDetach()) {
    186         if (oldFocusedNode->active())
    187             oldFocusedNode->setActive(false);
    188 
    189         oldFocusedNode->setFocus(false);
    190                
    191         // Dispatch a change event for text fields or textareas that have been edited
    192         RenderObject *r = static_cast<RenderObject*>(oldFocusedNode->renderer());
    193         if (r && (r->isTextArea() || r->isTextField()) && r->isEdited()) {
    194             EventTargetNodeCast(oldFocusedNode.get())->dispatchHTMLEvent(changeEvent, true, false);
    195             if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer())))
    196                 r->setEdited(false);
    197         }
    198 
    199         // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
    200         EventTargetNodeCast(oldFocusedNode.get())->dispatchBlurEvent();
    201 
    202         if (m_focusedNode) {
    203             // handler shifted focus
    204             focusChangeBlocked = true;
    205             newFocusedNode = 0;
    206         }
    207         clearSelectionIfNeeded(oldFocusedNode.get(), newFocusedNode.get());
    208         EventTargetNodeCast(oldFocusedNode.get())->dispatchUIEvent(DOMFocusOutEvent);
    209         if (m_focusedNode) {
    210             // handler shifted focus
    211             focusChangeBlocked = true;
    212             newFocusedNode = 0;
    213         }
    214         clearSelectionIfNeeded(oldFocusedNode.get(), newFocusedNode.get());
    215         if ((oldFocusedNode == oldFocusedNode->document()) && oldFocusedNode->hasOneRef())
    216             return true;
    217 
    218         if (oldFocusedNode == oldFocusedNode->rootEditableElement())
    219             oldFocusedNode->document()->frame()->editor()->didEndEditing();
    220     }
    221 
    222     if (newFocusedNode) {
    223         if (newFocusedNode == newFocusedNode->rootEditableElement() && !shouldAcquireEditingFocus(newFocusedNode.get())) {
    224             // delegate blocks focus change
    225             focusChangeBlocked = true;
    226             goto SetFocusedNodeDone;
    227         }
    228         // Set focus on the new node
    229         m_focusedNode = newFocusedNode.get();
    230 
    231         // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
    232         EventTargetNodeCast(m_focusedNode.get())->dispatchFocusEvent();
    233 
    234         if (m_focusedNode != newFocusedNode) {
    235             // handler shifted focus
    236             focusChangeBlocked = true;
    237             goto SetFocusedNodeDone;
    238         }
    239         EventTargetNodeCast(m_focusedNode.get())->dispatchUIEvent(DOMFocusInEvent);
    240         if (m_focusedNode != newFocusedNode) {
    241             // handler shifted focus
    242             focusChangeBlocked = true;
    243             goto SetFocusedNodeDone;
    244         }
    245         m_focusedNode->setFocus();
    246        
    247         if (m_focusedNode.get() == m_focusedNode->rootEditableElement())
    248             m_focusedNode->document()->frame()->editor()->didBeginEditing();
    249        
    250         // This only matters for searchfield
    251         if (m_focusedNode->document()->view()) {
    252             Widget* focusWidget = widgetForNode(m_focusedNode.get());
    253             if (focusWidget) {
    254                 // Make sure a widget has the right size before giving it focus.
    255                 // Otherwise, we are testing edge cases of the Widget code.
    256                 // Specifically, in WebCore this does not work well for text fields.
    257                 m_focusedNode->document()->updateLayout();
    258                 // Re-get the widget in case updating the layout changed things.
    259                 focusWidget = widgetForNode(m_focusedNode.get());
    260             }
    261             if (focusWidget)
    262                 focusWidget->setFocus();
    263             else
    264                 m_focusedNode->document()->view()->setFocus();
    265         }
    266    }
    267 
    268 #if PLATFORM(MAC)
    269     if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled())
    270         m_focusedNode->document()->axObjectCache()->handleFocusedUIElementChanged();
    271 #endif
    272 
    273 SetFocusedNodeDone:
    274     Document::updateDocumentsRendering();
    275     return !focusChangeBlocked;
    276 }
    277 
    278116const HashSet<Page*>* Page::frameNamespace() const
    279117{
  • trunk/WebCore/page/Page.h

    r18175 r18187  
    3737    class ContextMenuController;
    3838    class EditorClient;
     39    class FocusController;
    3940    class Frame;
    4041    class FrameNamespace;
     
    5859        String groupName() const { return m_groupName; }
    5960
    60         bool setFocusedNode(PassRefPtr<Node>);
    61         Node* focusedNode() const { return m_focusedNode.get(); }
    62 
    6361        const HashSet<Page*>* frameNamespace() const;
    6462        static const HashSet<Page*>* frameNamespace(const String&);
     
    7169        static void setNeedsReapplyStylesForSettingsChange(Settings*);
    7270
     71        Chrome* chrome() { return m_chrome.get(); }
    7372        SelectionController* dragCaretController() { return m_dragCaretController.get(); }
    74         Chrome* chrome() { return m_chrome.get(); }
     73        FocusController* focusController() { return m_focusController.get(); }
    7574        ContextMenuController* contextMenuController() { return m_contextMenuController.get(); }
    7675
     
    8584
    8685    private:
     86        OwnPtr<Chrome> m_chrome;
    8787        OwnPtr<SelectionController> m_dragCaretController;
    88         OwnPtr<Chrome> m_chrome;
     88        OwnPtr<FocusController> m_focusController;
    8989        OwnPtr<ContextMenuController> m_contextMenuController;
    9090
Note: See TracChangeset for help on using the changeset viewer.