1 /* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Nuanti Ltd. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "FocusController.h" 29 30 #include "AXObjectCache.h" 31 #include "Chrome.h" 32 #include "Document.h" 33 #include "Editor.h" 34 #include "EditorClient.h" 35 #include "Element.h" 36 #include "Event.h" 37 #include "EventHandler.h" 38 #include "EventNames.h" 39 #include "ExceptionCode.h" 40 #include "Frame.h" 41 #include "FrameTree.h" 42 #include "FrameView.h" 43 #include "HTMLFrameOwnerElement.h" 44 #include "HTMLNames.h" 45 #include "KeyboardEvent.h" 46 #include "Page.h" 47 #include "Range.h" 48 #include "RenderObject.h" 49 #include "RenderWidget.h" 50 #include "SelectionController.h" 51 #include "Settings.h" 52 #include "Widget.h" 53 #include <wtf/Platform.h> 54 55 namespace WebCore { 56 57 using namespace HTMLNames; 58 59 static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool focused) 60 { 61 // If we have a focused node we should dispatch blur on it before we blur the window. 62 // If we have a focused node we should dispatch focus on it after we focus the window. 63 // https://bugs.webkit.org/show_bug.cgi?id=27105 64 if (!focused && document->focusedNode()) 65 document->focusedNode()->dispatchBlurEvent(); 66 document->dispatchWindowEvent(Event::create(focused ? eventNames().focusEvent : eventNames().blurEvent, false, false)); 67 if (focused && document->focusedNode()) 68 document->focusedNode()->dispatchFocusEvent(); 69 } 70 71 FocusController::FocusController(Page* page) 72 : m_page(page) 73 , m_isActive(false) 74 , m_isFocused(false) 75 , m_isChangingFocusedFrame(false) 76 { 77 } 78 79 void FocusController::setFocusedFrame(PassRefPtr<Frame> frame) 80 { 81 if (m_focusedFrame == frame || m_isChangingFocusedFrame) 82 return; 83 84 m_isChangingFocusedFrame = true; 85 86 RefPtr<Frame> oldFrame = m_focusedFrame; 87 RefPtr<Frame> newFrame = frame; 88 89 m_focusedFrame = newFrame; 90 91 // Now that the frame is updated, fire events and update the selection focused states of both frames. 92 if (oldFrame && oldFrame->view()) { 93 oldFrame->selection()->setFocused(false); 94 oldFrame->document()->dispatchWindowEvent(Event::create(eventNames().blurEvent, false, false)); 95 } 96 97 if (newFrame && newFrame->view() && isFocused()) { 98 newFrame->selection()->setFocused(true); 99 newFrame->document()->dispatchWindowEvent(Event::create(eventNames().focusEvent, false, false)); 100 } 101 102 m_isChangingFocusedFrame = false; 103 } 104 105 Frame* FocusController::focusedOrMainFrame() 106 { 107 if (Frame* frame = focusedFrame()) 108 return frame; 109 return m_page->mainFrame(); 110 } 111 112 void FocusController::setFocused(bool focused) 113 { 114 if (isFocused() == focused) 115 return; 116 117 m_isFocused = focused; 118 119 if (m_focusedFrame && m_focusedFrame->view()) { 120 m_focusedFrame->selection()->setFocused(focused); 121 dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), focused); 122 } 123 } 124 125 static Node* deepFocusableNode(FocusDirection direction, Node* node, KeyboardEvent* event) 126 { 127 // The node we found might be a HTMLFrameOwnerElement, so descend down the frame tree until we find either: 128 // 1) a focusable node, or 129 // 2) the deepest-nested HTMLFrameOwnerElement 130 while (node && node->isFrameOwnerElement()) { 131 HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node); 132 if (!owner->contentFrame()) 133 break; 134 135 Document* document = owner->contentFrame()->document(); 136 137 node = (direction == FocusDirectionForward) 138 ? document->nextFocusableNode(0, event) 139 : document->previousFocusableNode(0, event); 140 if (!node) { 141 node = owner; 142 break; 143 } 144 } 145 146 return node; 147 } 148 149 bool FocusController::setInitialFocus(FocusDirection direction, KeyboardEvent* event) 150 { 151 return advanceFocus(direction, event, true); 152 } 153 154 bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* event, bool initialFocus) 155 { 156 Frame* frame = focusedOrMainFrame(); 157 ASSERT(frame); 158 Document* document = frame->document(); 159 160 Node* currentNode = document->focusedNode(); 161 // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself 162 bool caretBrowsing = focusedOrMainFrame()->settings()->caretBrowsingEnabled(); 163 164 if (caretBrowsing && !currentNode) 165 currentNode = frame->selection()->start().node(); 166 167 document->updateLayoutIgnorePendingStylesheets(); 168 169 Node* node = (direction == FocusDirectionForward) 170 ? document->nextFocusableNode(currentNode, event) 171 : document->previousFocusableNode(currentNode, event); 172 173 // If there's no focusable node to advance to, move up the frame tree until we find one. 174 while (!node && frame) { 175 Frame* parentFrame = frame->tree()->parent(); 176 if (!parentFrame) 177 break; 178 179 Document* parentDocument = parentFrame->document(); 180 181 HTMLFrameOwnerElement* owner = frame->ownerElement(); 182 if (!owner) 183 break; 184 185 node = (direction == FocusDirectionForward) 186 ? parentDocument->nextFocusableNode(owner, event) 187 : parentDocument->previousFocusableNode(owner, event); 188 189 frame = parentFrame; 190 } 191 192 node = deepFocusableNode(direction, node, event); 193 194 if (!node) { 195 // We didn't find a node to focus, so we should try to pass focus to Chrome. 196 if (!initialFocus && m_page->chrome()->canTakeFocus(direction)) { 197 document->setFocusedNode(0); 198 setFocusedFrame(0); 199 m_page->chrome()->takeFocus(direction); 200 return true; 201 } 202 203 // Chrome doesn't want focus, so we should wrap focus. 204 Document* d = m_page->mainFrame()->document(); 205 node = (direction == FocusDirectionForward) 206 ? d->nextFocusableNode(0, event) 207 : d->previousFocusableNode(0, event); 208 209 node = deepFocusableNode(direction, node, event); 210 211 if (!node) 212 return false; 213 } 214 215 ASSERT(node); 216 217 if (node == document->focusedNode()) 218 // Focus wrapped around to the same node. 219 return true; 220 221 if (!node->isElementNode()) 222 // FIXME: May need a way to focus a document here. 223 return false; 224 225 if (node->isFrameOwnerElement()) { 226 // We focus frames rather than frame owners. 227 // FIXME: We should not focus frames that have no scrollbars, as focusing them isn't useful to the user. 228 HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node); 229 if (!owner->contentFrame()) 230 return false; 231 232 document->setFocusedNode(0); 233 setFocusedFrame(owner->contentFrame()); 234 return true; 235 } 236 237 // FIXME: It would be nice to just be able to call setFocusedNode(node) here, but we can't do 238 // that because some elements (e.g. HTMLInputElement and HTMLTextAreaElement) do extra work in 239 // their focus() methods. 240 241 Document* newDocument = node->document(); 242 243 if (newDocument != document) 244 // Focus is going away from this document, so clear the focused node. 245 document->setFocusedNode(0); 246 247 if (newDocument) 248 setFocusedFrame(newDocument->frame()); 249 250 if (caretBrowsing) { 251 VisibleSelection newSelection(Position(node, 0), Position(node, 0), DOWNSTREAM); 252 if (frame->shouldChangeSelection(newSelection)) 253 frame->selection()->setSelection(newSelection); 254 } 255 256 static_cast<Element*>(node)->focus(false); 257 return true; 258 } 259 260 static bool relinquishesEditingFocus(Node *node) 261 { 262 ASSERT(node); 263 ASSERT(node->isContentEditable()); 264 265 Node* root = node->rootEditableElement(); 266 Frame* frame = node->document()->frame(); 267 if (!frame || !root) 268 return false; 269 270 return frame->editor()->shouldEndEditing(rangeOfContents(root).get()); 271 } 272 273 static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFrame, Node* newFocusedNode) 274 { 275 if (!oldFocusedFrame || !newFocusedFrame) 276 return; 277 278 if (oldFocusedFrame->document() != newFocusedFrame->document()) 279 return; 280 281 SelectionController* s = oldFocusedFrame->selection(); 282 if (s->isNone()) 283 return; 284 285 bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled(); 286 if (caretBrowsing) 287 return; 288 289 Node* selectionStartNode = s->selection().start().node(); 290 if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode) || selectionStartNode->shadowAncestorNode() == newFocusedNode) 291 return; 292 293 if (Node* mousePressNode = newFocusedFrame->eventHandler()->mousePressNode()) 294 if (mousePressNode->renderer() && !mousePressNode->canStartSelection()) 295 if (Node* root = s->rootEditableElement()) 296 if (Node* shadowAncestorNode = root->shadowAncestorNode()) 297 // Don't do this for textareas and text fields, when they lose focus their selections should be cleared 298 // and then restored when they regain focus, to match other browsers. 299 if (!shadowAncestorNode->hasTagName(inputTag) && !shadowAncestorNode->hasTagName(textareaTag)) 300 return; 301 302 s->clear(); 303 } 304 305 bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFrame) 306 { 307 RefPtr<Frame> oldFocusedFrame = focusedFrame(); 308 RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0; 309 310 Node* oldFocusedNode = oldDocument ? oldDocument->focusedNode() : 0; 311 if (oldFocusedNode == node) 312 return true; 313 314 // FIXME: Might want to disable this check for caretBrowsing 315 if (oldFocusedNode && oldFocusedNode->rootEditableElement() == oldFocusedNode && !relinquishesEditingFocus(oldFocusedNode)) 316 return false; 317 318 clearSelectionIfNeeded(oldFocusedFrame.get(), newFocusedFrame.get(), node); 319 320 if (!node) { 321 if (oldDocument) 322 oldDocument->setFocusedNode(0); 323 m_page->editorClient()->setInputMethodState(false); 324 return true; 325 } 326 327 RefPtr<Document> newDocument = node->document(); 328 329 if (newDocument && newDocument->focusedNode() == node) { 330 m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod()); 331 return true; 332 } 333 334 if (oldDocument && oldDocument != newDocument) 335 oldDocument->setFocusedNode(0); 336 337 setFocusedFrame(newFocusedFrame); 338 339 if (newDocument) 340 newDocument->setFocusedNode(node); 341 342 m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod()); 343 344 return true; 345 } 346 347 void FocusController::setActive(bool active) 348 { 349 if (m_isActive == active) 350 return; 351 352 m_isActive = active; 353 354 if (FrameView* view = m_page->mainFrame()->view()) { 355 if (!view->platformWidget()) { 356 view->layoutIfNeededRecursive(); 357 view->updateControlTints(); 358 } 359 } 360 361 focusedOrMainFrame()->selection()->pageActivationChanged(); 362 363 if (m_focusedFrame && isFocused()) 364 dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), active); 365 } 366 367 } // namespace WebCore 368