| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2  * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 
| 3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 
| 4  * | 4  * | 
| 5  * Redistribution and use in source and binary forms, with or without | 5  * Redistribution and use in source and binary forms, with or without | 
| 6  * modification, are permitted provided that the following conditions | 6  * modification, are permitted provided that the following conditions | 
| 7  * are met: | 7  * are met: | 
| 8  * 1. Redistributions of source code must retain the above copyright | 8  * 1. Redistributions of source code must retain the above copyright | 
| 9  *    notice, this list of conditions and the following disclaimer. | 9  *    notice, this list of conditions and the following disclaimer. | 
| 10  * 2. Redistributions in binary form must reproduce the above copyright | 10  * 2. Redistributions in binary form must reproduce the above copyright | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 37 #include "core/frame/LocalFrame.h" | 37 #include "core/frame/LocalFrame.h" | 
| 38 #include "core/html/HTMLTextAreaElement.h" | 38 #include "core/html/HTMLTextAreaElement.h" | 
| 39 #include "core/input/EventHandler.h" | 39 #include "core/input/EventHandler.h" | 
| 40 #include "core/layout/LayoutObject.h" | 40 #include "core/layout/LayoutObject.h" | 
| 41 #include "core/layout/LayoutTheme.h" | 41 #include "core/layout/LayoutTheme.h" | 
| 42 #include "core/page/ChromeClient.h" | 42 #include "core/page/ChromeClient.h" | 
| 43 #include "wtf/Optional.h" | 43 #include "wtf/Optional.h" | 
| 44 | 44 | 
| 45 namespace blink { | 45 namespace blink { | 
| 46 | 46 | 
|  | 47 namespace { | 
|  | 48 | 
|  | 49 void dispatchCompositionUpdateEvent(LocalFrame& frame, const String& text) | 
|  | 50 { | 
|  | 51     Element* target = frame.document()->focusedElement(); | 
|  | 52     if (!target) | 
|  | 53         return; | 
|  | 54 | 
|  | 55     CompositionEvent* event = CompositionEvent::create(EventTypeNames::compositi
     onupdate, frame.domWindow(), text); | 
|  | 56     target->dispatchEvent(event); | 
|  | 57 } | 
|  | 58 | 
|  | 59 void dispatchCompositionEndEvent(LocalFrame& frame, const String& text) | 
|  | 60 { | 
|  | 61     Element* target = frame.document()->focusedElement(); | 
|  | 62     if (!target) | 
|  | 63         return; | 
|  | 64 | 
|  | 65     CompositionEvent* event = CompositionEvent::create(EventTypeNames::compositi
     onend, frame.domWindow(), text); | 
|  | 66     target->dispatchEvent(event); | 
|  | 67 } | 
|  | 68 | 
|  | 69 // Used to insert/replace text during composition update and confirm composition
     . | 
|  | 70 // Procedure: | 
|  | 71 //   1. Fire 'beforeinput' event for (TODO(chongz): deleted composed text) and i
     nserted text | 
|  | 72 //   2. Fire 'compositionupdate' event | 
|  | 73 //   3. Fire TextEvent and modify DOM | 
|  | 74 //   TODO(chongz): 4. Fire 'input' event | 
|  | 75 void insertTextDuringCompositionWithEvents(LocalFrame& frame, const String& text
     , TypingCommand::Options options, TypingCommand::TextCompositionType composition
     Type) | 
|  | 76 { | 
|  | 77     DCHECK(compositionType == TypingCommand::TextCompositionType::TextCompositio
     nUpdate || compositionType == TypingCommand::TextCompositionType::TextCompositio
     nConfirm) | 
|  | 78         << "compositionType should be TextCompositionUpdate or TextCompositionCo
     nfirm, but got " << static_cast<int>(compositionType); | 
|  | 79     if (!frame.document()) | 
|  | 80         return; | 
|  | 81 | 
|  | 82     Element* target = frame.document()->focusedElement(); | 
|  | 83     if (!target) | 
|  | 84         return; | 
|  | 85 | 
|  | 86     // TODO(chongz): Fire 'beforeinput' for the composed text being replaced/del
     eted. | 
|  | 87 | 
|  | 88     // Only the last confirmed text is cancelable. | 
|  | 89     InputEvent::EventCancelable beforeInputCancelable = (compositionType == Typi
     ngCommand::TextCompositionType::TextCompositionUpdate) ? InputEvent::EventCancel
     able::NotCancelable : InputEvent::EventCancelable::IsCancelable; | 
|  | 90     DispatchEventResult result = dispatchBeforeInputFromComposition(target, Inpu
     tEvent::InputType::InsertText, text, beforeInputCancelable); | 
|  | 91 | 
|  | 92     if (beforeInputCancelable == InputEvent::EventCancelable::IsCancelable && re
     sult != DispatchEventResult::NotCanceled) | 
|  | 93         return; | 
|  | 94 | 
|  | 95     // 'beforeinput' event handler may destroy document. | 
|  | 96     if (!frame.document()) | 
|  | 97         return; | 
|  | 98 | 
|  | 99     dispatchCompositionUpdateEvent(frame, text); | 
|  | 100     // 'compositionupdate' event handler may destroy document. | 
|  | 101     if (!frame.document()) | 
|  | 102         return; | 
|  | 103 | 
|  | 104     switch (compositionType) { | 
|  | 105     case TypingCommand::TextCompositionType::TextCompositionUpdate: | 
|  | 106         TypingCommand::insertText(*frame.document(), text, options, compositionT
     ype); | 
|  | 107         break; | 
|  | 108     case TypingCommand::TextCompositionType::TextCompositionConfirm: | 
|  | 109         // TODO(chongz): Use TypingCommand::insertText after TextEvent was remov
     ed. (Removed from spec since 2012) | 
|  | 110         // See TextEvent.idl. | 
|  | 111         frame.eventHandler().handleTextInputEvent(text, 0, TextEventInputComposi
     tion); | 
|  | 112         break; | 
|  | 113     default: | 
|  | 114         NOTREACHED(); | 
|  | 115     } | 
|  | 116     // TODO(chongz): Fire 'input' event. | 
|  | 117 } | 
|  | 118 | 
|  | 119 } // anonymous namespace | 
|  | 120 | 
| 47 InputMethodController::SelectionOffsetsScope::SelectionOffsetsScope(InputMethodC
     ontroller* inputMethodController) | 121 InputMethodController::SelectionOffsetsScope::SelectionOffsetsScope(InputMethodC
     ontroller* inputMethodController) | 
| 48     : m_inputMethodController(inputMethodController) | 122     : m_inputMethodController(inputMethodController) | 
| 49     , m_offsets(inputMethodController->getSelectionOffsets()) | 123     , m_offsets(inputMethodController->getSelectionOffsets()) | 
| 50 { | 124 { | 
| 51 } | 125 } | 
| 52 | 126 | 
| 53 InputMethodController::SelectionOffsetsScope::~SelectionOffsetsScope() | 127 InputMethodController::SelectionOffsetsScope::~SelectionOffsetsScope() | 
| 54 { | 128 { | 
| 55     m_inputMethodController->setSelectionOffsets(m_offsets); | 129     m_inputMethodController->setSelectionOffsets(m_offsets); | 
| 56 } | 130 } | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 89     frame().document()->markers().removeMarkers(DocumentMarker::Composition); | 163     frame().document()->markers().removeMarkers(DocumentMarker::Composition); | 
| 90     m_isDirty = false; | 164     m_isDirty = false; | 
| 91 } | 165 } | 
| 92 | 166 | 
| 93 void InputMethodController::documentDetached() | 167 void InputMethodController::documentDetached() | 
| 94 { | 168 { | 
| 95     clear(); | 169     clear(); | 
| 96     m_compositionRange = nullptr; | 170     m_compositionRange = nullptr; | 
| 97 } | 171 } | 
| 98 | 172 | 
| 99 bool InputMethodController::insertTextForConfirmedComposition(const String& text
     ) |  | 
| 100 { |  | 
| 101     return frame().eventHandler().handleTextInputEvent(text, 0, TextEventInputCo
     mposition); |  | 
| 102 } |  | 
| 103 |  | 
| 104 void InputMethodController::selectComposition() const | 173 void InputMethodController::selectComposition() const | 
| 105 { | 174 { | 
| 106     const EphemeralRange range = compositionEphemeralRange(); | 175     const EphemeralRange range = compositionEphemeralRange(); | 
| 107     if (range.isNull()) | 176     if (range.isNull()) | 
| 108         return; | 177         return; | 
| 109 | 178 | 
| 110     // The composition can start inside a composed character sequence, so we hav
     e to override checks. | 179     // The composition can start inside a composed character sequence, so we hav
     e to override checks. | 
| 111     // See <http://bugs.webkit.org/show_bug.cgi?id=15781> | 180     // See <http://bugs.webkit.org/show_bug.cgi?id=15781> | 
| 112     VisibleSelection selection; | 181     VisibleSelection selection; | 
| 113     selection.setWithoutValidation(range.startPosition(), range.endPosition()); | 182     selection.setWithoutValidation(range.startPosition(), range.endPosition()); | 
| 114     frame().selection().setSelection(selection, 0); | 183     frame().selection().setSelection(selection, 0); | 
| 115 } | 184 } | 
| 116 | 185 | 
| 117 bool InputMethodController::confirmComposition() | 186 bool InputMethodController::confirmComposition() | 
| 118 { | 187 { | 
| 119     return confirmComposition(composingText()); | 188     return confirmComposition(composingText()); | 
| 120 } | 189 } | 
| 121 | 190 | 
| 122 static void dispatchCompositionEndEvent(LocalFrame& frame, const String& text) |  | 
| 123 { |  | 
| 124     // We should send this event before sending a TextEvent as written in |  | 
| 125     // Section 6.2.2 and 6.2.3 of the DOM Event specification. |  | 
| 126     Element* target = frame.document()->focusedElement(); |  | 
| 127     if (!target) |  | 
| 128         return; |  | 
| 129 |  | 
| 130     CompositionEvent* event = |  | 
| 131         CompositionEvent::create(EventTypeNames::compositionend, frame.domWindow
     (), text); |  | 
| 132     target->dispatchEvent(event); |  | 
| 133 } |  | 
| 134 |  | 
| 135 bool InputMethodController::confirmComposition(const String& text, ConfirmCompos
     itionBehavior confirmBehavior) | 191 bool InputMethodController::confirmComposition(const String& text, ConfirmCompos
     itionBehavior confirmBehavior) | 
| 136 { | 192 { | 
| 137     if (!hasComposition()) | 193     if (!hasComposition()) | 
| 138         return false; | 194         return false; | 
| 139 | 195 | 
| 140     Optional<Editor::RevealSelectionScope> revealSelectionScope; | 196     Optional<Editor::RevealSelectionScope> revealSelectionScope; | 
| 141     if (confirmBehavior == KeepSelection) | 197     if (confirmBehavior == KeepSelection) | 
| 142         revealSelectionScope.emplace(&editor()); | 198         revealSelectionScope.emplace(&editor()); | 
| 143 | 199 | 
| 144     // If the composition was set from existing text and didn't change, then | 200     // If the composition was set from existing text and didn't change, then | 
| 145     // there's nothing to do here (and we should avoid doing anything as that | 201     // there's nothing to do here (and we should avoid doing anything as that | 
| 146     // may clobber multi-node styled text). | 202     // may clobber multi-node styled text). | 
| 147     if (!m_isDirty && composingText() == text) { | 203     if (!m_isDirty && composingText() == text) { | 
| 148         clear(); | 204         clear(); | 
| 149         return true; | 205         return true; | 
| 150     } | 206     } | 
| 151 | 207 | 
| 152     // Select the text that will be deleted or replaced. | 208     // Select the text that will be deleted or replaced. | 
| 153     selectComposition(); | 209     selectComposition(); | 
| 154 | 210 | 
| 155     if (frame().selection().isNone()) | 211     if (frame().selection().isNone()) | 
| 156         return false; | 212         return false; | 
| 157 | 213 | 
| 158     dispatchCompositionEndEvent(frame(), text); |  | 
| 159 |  | 
| 160     if (!frame().document()) | 214     if (!frame().document()) | 
| 161         return false; | 215         return false; | 
| 162 | 216 | 
| 163     // If text is empty, then delete the old composition here. If text is | 217     // If text is empty, then delete the old composition here. If text is | 
| 164     // non-empty, InsertTextCommand::input will delete the old composition with | 218     // non-empty, InsertTextCommand::input will delete the old composition with | 
| 165     // an optimized replace operation. | 219     // an optimized replace operation. | 
| 166     if (text.isEmpty()) | 220     if (text.isEmpty()) | 
| 167         TypingCommand::deleteSelection(*frame().document(), 0); | 221         TypingCommand::deleteSelection(*frame().document(), 0); | 
| 168 | 222 | 
| 169     clear(); | 223     clear(); | 
| 170 | 224 | 
| 171     // TODO(chongz): DOM update should happen before 'compositionend' and along 
     with 'compositionupdate'. | 225     insertTextDuringCompositionWithEvents(frame(), text, 0, TypingCommand::TextC
     ompositionType::TextCompositionConfirm); | 
| 172     // https://crbug.com/575294 | 226     // Event handler might destroy document. | 
| 173     if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text
     ) != DispatchEventResult::NotCanceled) | 227     if (!frame().document()) | 
| 174         return false; | 228         return false; | 
| 175 | 229 | 
| 176     insertTextForConfirmedComposition(text); | 230     // No DOM update after 'compositionend'. | 
|  | 231     dispatchCompositionEndEvent(frame(), text); | 
| 177 | 232 | 
| 178     return true; | 233     return true; | 
| 179 } | 234 } | 
| 180 | 235 | 
| 181 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C
     onfirmCompositionBehavior confirmBehavior) | 236 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C
     onfirmCompositionBehavior confirmBehavior) | 
| 182 { | 237 { | 
| 183     if (!hasComposition()) { | 238     if (!hasComposition()) { | 
| 184         if (!text.length()) | 239         if (!text.length()) | 
| 185             return false; | 240             return false; | 
| 186 | 241 | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 206 void InputMethodController::cancelComposition() | 261 void InputMethodController::cancelComposition() | 
| 207 { | 262 { | 
| 208     if (!hasComposition()) | 263     if (!hasComposition()) | 
| 209         return; | 264         return; | 
| 210 | 265 | 
| 211     Editor::RevealSelectionScope revealSelectionScope(&editor()); | 266     Editor::RevealSelectionScope revealSelectionScope(&editor()); | 
| 212 | 267 | 
| 213     if (frame().selection().isNone()) | 268     if (frame().selection().isNone()) | 
| 214         return; | 269         return; | 
| 215 | 270 | 
| 216     dispatchCompositionEndEvent(frame(), emptyString()); |  | 
| 217     clear(); | 271     clear(); | 
| 218     insertTextForConfirmedComposition(emptyString()); | 272 | 
|  | 273     // TODO(chongz): Update InputType::DeleteComposedCharacter with latest discu
     ssion. | 
|  | 274     dispatchBeforeInputFromComposition(frame().document()->focusedElement(), Inp
     utEvent::InputType::DeleteComposedCharacter, emptyString(), InputEvent::EventCan
     celable::NotCancelable); | 
|  | 275     dispatchCompositionUpdateEvent(frame(), emptyString()); | 
|  | 276     insertTextDuringCompositionWithEvents(frame(), emptyString(), 0, TypingComma
     nd::TextCompositionType::TextCompositionConfirm); | 
|  | 277     // Event handler might destroy document. | 
|  | 278     if (!frame().document()) | 
|  | 279         return; | 
| 219 | 280 | 
| 220     // An open typing command that disagrees about current selection would cause | 281     // An open typing command that disagrees about current selection would cause | 
| 221     // issues with typing later on. | 282     // issues with typing later on. | 
| 222     TypingCommand::closeTyping(m_frame); | 283     TypingCommand::closeTyping(m_frame); | 
|  | 284 | 
|  | 285     // No DOM update after 'compositionend'. | 
|  | 286     dispatchCompositionEndEvent(frame(), emptyString()); | 
| 223 } | 287 } | 
| 224 | 288 | 
| 225 void InputMethodController::cancelCompositionIfSelectionIsInvalid() | 289 void InputMethodController::cancelCompositionIfSelectionIsInvalid() | 
| 226 { | 290 { | 
| 227     if (!hasComposition() || editor().preventRevealSelection()) | 291     if (!hasComposition() || editor().preventRevealSelection()) | 
| 228         return; | 292         return; | 
| 229 | 293 | 
| 230     // Check if selection start and selection end are valid. | 294     // Check if selection start and selection end are valid. | 
| 231     FrameSelection& selection = frame().selection(); | 295     FrameSelection& selection = frame().selection(); | 
| 232     if (!selection.isNone() && !m_compositionRange->collapsed()) { | 296     if (!selection.isNone() && !m_compositionRange->collapsed()) { | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 246     // Updates styles before setting selection for composition to prevent | 310     // Updates styles before setting selection for composition to prevent | 
| 247     // inserting the previous composition text into text nodes oddly. | 311     // inserting the previous composition text into text nodes oddly. | 
| 248     // See https://bugs.webkit.org/show_bug.cgi?id=46868 | 312     // See https://bugs.webkit.org/show_bug.cgi?id=46868 | 
| 249     frame().document()->updateStyleAndLayoutTree(); | 313     frame().document()->updateStyleAndLayoutTree(); | 
| 250 | 314 | 
| 251     selectComposition(); | 315     selectComposition(); | 
| 252 | 316 | 
| 253     if (frame().selection().isNone()) | 317     if (frame().selection().isNone()) | 
| 254         return; | 318         return; | 
| 255 | 319 | 
| 256     if (Element* target = frame().document()->focusedElement()) { | 320     Element* target = frame().document()->focusedElement(); | 
| 257         // Dispatch an appropriate composition event to the focused node. | 321     if (!target) | 
| 258         // We check the composition status and choose an appropriate composition
      event since this | 322         return; | 
| 259         // function is used for three purposes: | 323 | 
| 260         // 1. Starting a new composition. | 324     // Dispatch an appropriate composition event to the focused node. | 
| 261         //    Send a compositionstart and a compositionupdate event when this fu
     nction creates | 325     // We check the composition status and choose an appropriate composition eve
     nt since this | 
| 262         //    a new composition node, i.e. | 326     // function is used for three purposes: | 
| 263         //    !hasComposition() && !text.isEmpty(). | 327     // 1. Starting a new composition. | 
| 264         //    Sending a compositionupdate event at this time ensures that at lea
     st one | 328     //    Send a compositionstart and a compositionupdate event when this functi
     on creates | 
| 265         //    compositionupdate event is dispatched. | 329     //    a new composition node, i.e. | 
| 266         // 2. Updating the existing composition node. | 330     //    !hasComposition() && !text.isEmpty(). | 
| 267         //    Send a compositionupdate event when this function updates the exis
     ting composition | 331     //    Sending a compositionupdate event at this time ensures that at least o
     ne | 
| 268         //    node, i.e. hasComposition() && !text.isEmpty(). | 332     //    compositionupdate event is dispatched. | 
| 269         // 3. Canceling the ongoing composition. | 333     // 2. Updating the existing composition node. | 
| 270         //    Send a compositionend event when function deletes the existing com
     position node, i.e. | 334     //    Send a compositionupdate event when this function updates the existing
      composition | 
| 271         //    !hasComposition() && test.isEmpty(). | 335     //    node, i.e. hasComposition() && !text.isEmpty(). | 
| 272         CompositionEvent* event = nullptr; | 336     // 3. Canceling the ongoing composition. | 
| 273         if (!hasComposition()) { | 337     //    Send a compositionend event when function deletes the existing composi
     tion node, i.e. | 
| 274             // We should send a compositionstart event only when the given text 
     is not empty because this | 338     //    !hasComposition() && test.isEmpty(). | 
| 275             // function doesn't create a composition node when the text is empty
     . | 339     if (text.isEmpty()) { | 
| 276             if (!text.isEmpty()) { | 340         if (hasComposition()) { | 
| 277                 target->dispatchEvent(CompositionEvent::create(EventTypeNames::c
     ompositionstart, frame().domWindow(), frame().selectedText())); | 341             confirmComposition(emptyString()); | 
| 278                 event = CompositionEvent::create(EventTypeNames::compositionupda
     te, frame().domWindow(), text); | 342             return; | 
| 279             } |  | 
| 280         } else { |  | 
| 281             if (!text.isEmpty()) |  | 
| 282                 event = CompositionEvent::create(EventTypeNames::compositionupda
     te, frame().domWindow(), text); |  | 
| 283             else |  | 
| 284                 event = CompositionEvent::create(EventTypeNames::compositionend,
      frame().domWindow(), text); |  | 
| 285         } | 343         } | 
| 286         if (event) { | 344         // It's weird to call |setComposition()| with empty text outside composi
     tion, however some IME | 
| 287             // TODO(chongz): Support canceling IME composition. | 345         // (e.g. Japanese IBus-Anthy) did this, so we simply delete selection wi
     thout sending extra events. | 
| 288             // TODO(chongz): Should fire InsertText or DeleteComposedCharacter b
     ased on action. | 346         TypingCommand::deleteSelection(*frame().document(), TypingCommand::Preve
     ntSpellChecking); | 
| 289             if (event->type() == EventTypeNames::compositionupdate) | 347         return; | 
| 290                 dispatchBeforeInputFromComposition(target, InputEvent::InputType
     ::InsertText, text); |  | 
| 291             target->dispatchEvent(event); |  | 
| 292         } |  | 
| 293     } | 348     } | 
| 294 | 349 | 
| 295     // If text is empty, then delete the old composition here. If text is non-em
     pty, InsertTextCommand::input | 350     // We should send a 'compositionstart' event only when the given text is not
      empty because this | 
| 296     // will delete the old composition with an optimized replace operation. | 351     // function doesn't create a composition node when the text is empty. | 
| 297     if (text.isEmpty()) { | 352     if (!hasComposition()) { | 
| 298         DCHECK(frame().document()); | 353         target->dispatchEvent(CompositionEvent::create(EventTypeNames::compositi
     onstart, frame().domWindow(), frame().selectedText())); | 
| 299         TypingCommand::deleteSelection(*frame().document(), TypingCommand::Preve
     ntSpellChecking); | 354         if (!frame().document()) | 
|  | 355             return; | 
| 300     } | 356     } | 
| 301 | 357 | 
|  | 358     DCHECK(!text.isEmpty()); | 
|  | 359 | 
| 302     clear(); | 360     clear(); | 
| 303 | 361 | 
| 304     if (text.isEmpty()) | 362     insertTextDuringCompositionWithEvents(frame(), text, TypingCommand::SelectIn
     sertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextComposition
     Update); | 
|  | 363     // Event handlers might destroy document. | 
|  | 364     if (!frame().document()) | 
| 305         return; | 365         return; | 
| 306     DCHECK(frame().document()); |  | 
| 307     TypingCommand::insertText(*frame().document(), text, TypingCommand::SelectIn
     sertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextComposition
     Update); |  | 
| 308 | 366 | 
| 309     // Find out what node has the composition now. | 367     // Find out what node has the composition now. | 
| 310     Position base = mostForwardCaretPosition(frame().selection().base()); | 368     Position base = mostForwardCaretPosition(frame().selection().base()); | 
| 311     Node* baseNode = base.anchorNode(); | 369     Node* baseNode = base.anchorNode(); | 
| 312     if (!baseNode || !baseNode->isTextNode()) | 370     if (!baseNode || !baseNode->isTextNode()) | 
| 313         return; | 371         return; | 
| 314 | 372 | 
| 315     Position extent = frame().selection().extent(); | 373     Position extent = frame().selection().extent(); | 
| 316     Node* extentNode = extent.anchorNode(); | 374     Node* extentNode = extent.anchorNode(); | 
| 317     if (baseNode != extentNode) | 375     if (baseNode != extentNode) | 
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 489     TypingCommand::deleteSelection(*frame().document()); | 547     TypingCommand::deleteSelection(*frame().document()); | 
| 490 } | 548 } | 
| 491 | 549 | 
| 492 DEFINE_TRACE(InputMethodController) | 550 DEFINE_TRACE(InputMethodController) | 
| 493 { | 551 { | 
| 494     visitor->trace(m_frame); | 552     visitor->trace(m_frame); | 
| 495     visitor->trace(m_compositionRange); | 553     visitor->trace(m_compositionRange); | 
| 496 } | 554 } | 
| 497 | 555 | 
| 498 } // namespace blink | 556 } // namespace blink | 
| OLD | NEW | 
|---|