Changeset 116114 in webkit
- Timestamp:
- May 4, 2012 9:49:39 AM (12 years ago)
- Location:
- trunk/Source
- Files:
-
- 5 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r116113 r116114 1 2012-05-03 Martin Robinson <mrobinson@igalia.com> 2 3 [GTK] Rework IME handling to fix bugs and prepare for WebKit2 4 https://bugs.webkit.org/show_bug.cgi?id=84556 5 6 Reviewed by Gustavo Noronha Silva. 7 8 No new tests. This change is already covered by a suite of keyboard 9 handling unit tests in WebKitGTK+. There are some changes in behavior, 10 but they are difficult to test without mocking out an entire GtkIMContext. 11 12 Add a struct, CompositionResults, which is used by PlatformKeyboardEvent 13 to package composition information with a keyboard event. Also add some logic 14 to PlatformKeyboardEvent to give the right information when it has composition 15 results. 16 17 * GNUmakefile.list.am: Added new sources to the list. 18 * platform/PlatformKeyboardEvent.h: Added a new CompositionResults member, 19 getter, and argument to the constructor. 20 * platform/gtk/CompositionResults.h: Added. 21 * platform/gtk/GtkInputMethodFilter.cpp: Added. 22 * platform/gtk/GtkInputMethodFilter.h: Added. 23 * platform/gtk/PlatformKeyboardEventGtk.cpp: 24 (WebCore::PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode): When 25 the key value is void return the VK_PROCESS keycode, which is the keycode 26 that web content expects with keystrokes that trigger composition events. 27 (WebCore::eventTypeForGdkKeyEvent): Abstract out this helper. 28 (WebCore::modifiersForGdkKeyEvent): Abstract out this helper. 29 (WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent): When a PlatformKeyEvent 30 has composition results, use VK_PROCESS as the keycode for this event. 31 (WebCore::PlatformKeyboardEvent::disambiguateKeyDownEvent): When this event is 32 transformed into a Char event, the PlatformKeyboardEvent used for DOM keypress 33 events, and it has composition results clear the text members. This forces the 34 EventHandler code to drop the keypress event. Platform events that change the 35 composition states do not have corresponding keypress DOM events (only keydown 36 and keyup events), so this is necessary to ensure web compatibility. 37 1 38 2012-05-04 Jochen Eisinger <jochen@chromium.org> 2 39 -
trunk/Source/WebCore/GNUmakefile.list.am
r115943 r116114 4710 4710 Source/WebCore/platform/gtk/GtkDragAndDropHelper.cpp \ 4711 4711 Source/WebCore/platform/gtk/GtkDragAndDropHelper.h \ 4712 Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp \ 4713 Source/WebCore/platform/gtk/GtkInputMethodFilter.h \ 4712 4714 Source/WebCore/platform/gtk/GtkUtilities.cpp \ 4713 4715 Source/WebCore/platform/gtk/GtkUtilities.h \ -
trunk/Source/WebCore/platform/PlatformKeyboardEvent.h
r111191 r116114 44 44 #if PLATFORM(GTK) 45 45 typedef struct _GdkEventKey GdkEventKey; 46 #include "CompositionResults.h" 46 47 #endif 47 48 … … 152 153 153 154 #if PLATFORM(GTK) 154 PlatformKeyboardEvent(GdkEventKey*); 155 GdkEventKey* gdkEventKey() const; 155 PlatformKeyboardEvent(GdkEventKey*, const CompositionResults&); 156 GdkEventKey* gdkEventKey() const { return m_gdkEventKey; } 157 const CompositionResults& compositionResults() const { return m_compositionResults; } 156 158 157 159 // Used by WebKit2 … … 201 203 #if PLATFORM(GTK) 202 204 GdkEventKey* m_gdkEventKey; 205 CompositionResults m_compositionResults; 203 206 #endif 204 207 #if PLATFORM(QT) -
trunk/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp
r103643 r116114 511 511 case GDK_F24: 512 512 return VK_F1 + (keycode - GDK_F1); 513 513 case GDK_KEY_VoidSymbol: 514 return VK_PROCESSKEY; 514 515 default: 515 516 return 0; … … 546 547 } 547 548 549 static PlatformEvent::Type eventTypeForGdkKeyEvent(GdkEventKey* event) 550 { 551 return event->type == GDK_KEY_RELEASE ? PlatformEvent::KeyUp : PlatformEvent::KeyDown; 552 } 553 554 static PlatformEvent::Modifiers modifiersForGdkKeyEvent(GdkEventKey* event) 555 { 556 unsigned int modifiers = 0; 557 if (event->state & GDK_SHIFT_MASK || event->keyval == GDK_3270_BackTab) 558 modifiers |= PlatformEvent::ShiftKey; 559 if (event->state & GDK_CONTROL_MASK) 560 modifiers |= PlatformEvent::CtrlKey; 561 if (event->state & GDK_MOD1_MASK) 562 modifiers |= PlatformEvent::AltKey; 563 if (event->state & GDK_META_MASK) 564 modifiers |= PlatformEvent::MetaKey; 565 return static_cast<PlatformEvent::Modifiers>(modifiers); 566 } 567 548 568 // Keep this in sync with the other platform event constructors 549 // TODO: m_gdkEventKey should be refcounted 550 PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event) 551 : PlatformEvent((event->type == GDK_KEY_RELEASE) ? PlatformEvent::KeyUp : PlatformEvent::KeyDown, (event->state & GDK_SHIFT_MASK) || (event->keyval == GDK_3270_BackTab), event->state & GDK_CONTROL_MASK, event->state & GDK_MOD1_MASK, event->state & GDK_META_MASK, currentTime()) 552 , m_text(singleCharacterString(event->keyval)) 553 , m_unmodifiedText(singleCharacterString(event->keyval)) 569 PlatformKeyboardEvent::PlatformKeyboardEvent(GdkEventKey* event, const CompositionResults& compositionResults) 570 : PlatformEvent(eventTypeForGdkKeyEvent(event), modifiersForGdkKeyEvent(event), currentTime()) 571 , m_text(compositionResults.simpleString.length() ? compositionResults.simpleString : singleCharacterString(event->keyval)) 572 , m_unmodifiedText(m_text) 554 573 , m_keyIdentifier(keyIdentifierForGdkKeyCode(event->keyval)) 555 574 , m_windowsVirtualKeyCode(windowsKeyCodeForGdkKeyCode(event->keyval)) … … 560 579 , m_isSystemKey(false) 561 580 , m_gdkEventKey(event) 562 { 581 , m_compositionResults(compositionResults) 582 { 583 // To match the behavior of IE, we return VK_PROCESSKEY for keys that triggered composition results. 584 if (compositionResults.compositionUpdated()) 585 m_windowsVirtualKeyCode = VK_PROCESSKEY; 563 586 } 564 587 … … 573 596 574 597 if (type == PlatformEvent::RawKeyDown) { 598 m_text = String(); 599 m_unmodifiedText = String(); 600 } else if (type == PlatformEvent::Char && m_compositionResults.compositionUpdated()) { 601 // Having empty text, prevents this Char (which is a DOM keypress) event 602 // from going to the DOM. Keys that trigger composition events should not 603 // fire keypress. 575 604 m_text = String(); 576 605 m_unmodifiedText = String(); … … 597 626 } 598 627 599 GdkEventKey* PlatformKeyboardEvent::gdkEventKey() const 600 { 601 return m_gdkEventKey; 602 } 603 604 } 628 } -
trunk/Source/WebKit/gtk/ChangeLog
r115998 r116114 1 2012-05-03 Martin Robinson <mrobinson@igalia.com> 2 3 [GTK] Rework IME handling to fix bugs and prepare for WebKit2 4 https://bugs.webkit.org/show_bug.cgi?id=84556 5 6 Reviewed by Gustavo Noronha Silva. 7 8 Rework input method handling logic into a class called GtkInputMethodFilter. 9 This filter now runs before WebCore event handling, allowing the code to more 10 easily fake simple compositions that should be seen as keystrokes. We can also 11 filter keypresses that should not go to web content at all, such as key up events 12 related to key down events that were filtered. 13 14 Also added is a WebViewInputMethodFilter which is a concrete implementation of 15 GtkInputMethodFilter. This class contains logic for actually sending events to 16 WebCore. In WebKit2 an implementation of GtkInputMethodFilter will send events 17 across the IPC channel. 18 19 * GNUmakefile.am: Add new files to the source list. 20 * WebCoreSupport/ContextMenuClientGtk.cpp: 21 (WebKit::inputMethodsMenuItem): Access the input method context via the filter. 22 * WebCoreSupport/EditorClientGtk.cpp: Remove the tricky logic of input method 23 events from this class, because it's now in the GtkInputMethodFilter. 24 (WebKit::EditorClient::setInputMethodState): Call into the filter. 25 (WebKit::EditorClient::shouldBeginEditing): We no longer need to update the composition here. 26 This is handled by the focus in and focus out logic in the filter. 27 (WebKit::EditorClient::shouldEndEditing): Ditto. 28 (WebKit::EditorClient::respondToChangedSelection): Call into the filter now. 29 (WebKit::EditorClient::handleInputMethodKeyboardEvent): Added this helper which executes 30 any pending composition confirmation or preedit update actions as the default action of 31 the keydown event. 32 (WebKit::EditorClient::handleKeyboardEvent): Call handleInputMethodKeyboardEvent to do 33 any pending composition action. 34 (WebKit::EditorClient::handleInputMethodKeydown): Remove all the logic from this method. 35 Keys are filtered before they are sent to WebCore now and the actual action of input method 36 events happens in the keydown default action to increase compatibility with other browsers. 37 (WebKit::EditorClient::EditorClient): Remove context signal management. 38 (WebKit::EditorClient::~EditorClient): Ditto. 39 * WebCoreSupport/EditorClientGtk.h: 40 (EditorClient): No longer has some members that tracked IME status. 41 * WebCoreSupport/WebViewInputMethodFilter.cpp: Added. 42 * WebCoreSupport/WebViewInputMethodFilter.h: Added. 43 * webkit/webkitwebview.cpp: 44 (webkit_web_view_get_property): Get the context from the filter now. 45 (webkit_web_view_key_press_event): Just send events straight to the filter. 46 The filter will decide whether or not to send them to WebCore. 47 (webkit_web_view_key_release_event): Ditto. 48 (webkit_web_view_button_press_event): Use the filter to handle button press 49 events related to IME. 50 (webkit_web_view_focus_in_event): Notify the filter now. 51 (webkit_web_view_focus_out_event): Ditto. 52 (webkit_web_view_realize): The filter takes care of listening for realize now. 53 (webkit_web_view_init): Set the WebView widget on the filter. 54 * webkit/webkitwebviewprivate.h: Change the GtkIMContext member to be a GtkInputMethodFilter member. 55 1 56 2012-05-03 Fady Samuel <fsamuel@chromium.org> 2 57 -
trunk/Source/WebKit/gtk/GNUmakefile.am
r114865 r116114 213 213 Source/WebKit/gtk/WebCoreSupport/UserMediaClientGtk.cpp \ 214 214 Source/WebKit/gtk/WebCoreSupport/UserMediaClientGtk.h \ 215 Source/WebKit/gtk/WebCoreSupport/WebViewInputMethodFilter.cpp \ 216 Source/WebKit/gtk/WebCoreSupport/WebViewInputMethodFilter.h \ 215 217 Source/WebKit/gtk/webkit/webkitapplicationcache.cpp \ 216 218 Source/WebKit/gtk/webkit/webkitdownload.cpp \ -
trunk/Source/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp
r113147 r116114 65 65 WebKitWebViewPrivate* priv = webView->priv; 66 66 ContextMenu imContextMenu; 67 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(priv->im Context.get()), GTK_MENU_SHELL(imContextMenu.platformDescription()));67 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(priv->imFilter.context()), GTK_MENU_SHELL(imContextMenu.platformDescription())); 68 68 69 69 ContextMenuItem menuItem(ActionType, ContextMenuItemTagInputMethods, contextMenuItemTagInputMethods(), &imContextMenu); -
trunk/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
r114865 r116114 63 63 namespace WebKit { 64 64 65 static void imContextCommitted(GtkIMContext* context, const gchar* compositionString, EditorClient* client)66 {67 Frame* frame = core(static_cast<WebKitWebView*>(client->webView()))->focusController()->focusedOrMainFrame();68 if (!frame || !frame->editor()->canEdit())69 return;70 71 // If this signal fires during a keydown event when we are not in the middle72 // of a composition, then treat this 'commit' as a normal key event and just73 // change the editable area right before the keypress event.74 if (client->treatContextCommitAsKeyEvent()) {75 client->updatePendingComposition(compositionString);76 return;77 }78 79 // If this signal fires during a mousepress event when we are in the middle80 // of a composition, skip this 'commit' because the composition is already confirmed.81 if (client->preventNextCompositionCommit())82 return;83 84 frame->editor()->confirmComposition(String::fromUTF8(compositionString));85 client->clearPendingComposition();86 }87 88 static void imContextPreeditChanged(GtkIMContext* context, EditorClient* client)89 {90 Frame* frame = core(static_cast<WebKitWebView*>(client->webView()))->focusController()->focusedOrMainFrame();91 if (!frame || !frame->editor()->canEdit())92 return;93 94 // We ignore the provided PangoAttrList for now.95 GOwnPtr<gchar> newPreedit(0);96 gtk_im_context_get_preedit_string(context, &newPreedit.outPtr(), 0, 0);97 98 String preeditString = String::fromUTF8(newPreedit.get());99 Vector<CompositionUnderline> underlines;100 underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));101 frame->editor()->setComposition(preeditString, underlines, 0, 0);102 }103 104 105 void EditorClient::updatePendingComposition(const gchar* newComposition)106 {107 // The IMContext may signal more than one completed composition in a row,108 // in which case we want to append them, rather than overwrite the old one.109 if (!m_pendingComposition)110 m_pendingComposition.set(g_strdup(newComposition));111 else112 m_pendingComposition.set(g_strconcat(m_pendingComposition.get(), newComposition, NULL));113 }114 115 65 void EditorClient::willSetInputMethodState() 116 66 { … … 119 69 void EditorClient::setInputMethodState(bool active) 120 70 { 121 WebKitWebViewPrivate* priv = m_webView->priv; 122 123 if (active) 124 gtk_im_context_focus_in(priv->imContext.get()); 125 else 126 gtk_im_context_focus_out(priv->imContext.get()); 71 m_webView->priv->imFilter.setEnabled(active); 127 72 } 128 73 … … 182 127 bool EditorClient::shouldBeginEditing(WebCore::Range* range) 183 128 { 184 clearPendingComposition();185 186 129 gboolean accept = TRUE; 187 130 GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); … … 192 135 bool EditorClient::shouldEndEditing(WebCore::Range* range) 193 136 { 194 clearPendingComposition();195 196 137 gboolean accept = TRUE; 197 138 GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); … … 318 259 return; 319 260 320 if (frame->editor()->ignoreCompositionSelectionChange())321 return;322 323 261 #if PLATFORM(X11) 324 262 setSelectionPrimaryClipboardIfNeeded(m_webView); 325 263 #endif 326 264 327 if ( !frame->editor()->hasComposition())265 if (m_updatingComposition || !frame->editor()->hasComposition() || frame->editor()->ignoreCompositionSelectionChange()) 328 266 return; 329 267 330 268 unsigned start; 331 269 unsigned end; 332 WebKitWebViewPrivate* priv = m_webView->priv; 333 334 if (!frame->editor()->getCompositionSelection(start, end)) { 335 // gtk_im_context_reset() clears the composition for us. 336 gtk_im_context_reset(priv->imContext.get()); 337 frame->editor()->cancelComposition(); 338 } 270 if (!frame->editor()->getCompositionSelection(start, end)) 271 m_webView->priv->imFilter.resetContext(); 339 272 } 340 273 … … 483 416 484 417 m_pendingEditorCommands.clear(); 485 486 // If we successfully completed all editor commands, then487 // this signals a canceling of the composition.488 if (success)489 clearPendingComposition();490 491 418 return success; 419 } 420 421 bool EditorClient::handleInputMethodKeyboardEvent(KeyboardEvent* event) 422 { 423 if (event->type() != eventNames().keydownEvent) 424 return false; 425 426 const PlatformKeyboardEvent* platformEvent = event->keyEvent(); 427 if (!platformEvent) 428 return false; 429 430 Frame* frame = core(m_webView)->focusController()->focusedOrMainFrame(); 431 if (!frame || !frame->editor()->canEdit()) 432 return false; 433 434 const CompositionResults& compositionResults = platformEvent->compositionResults(); 435 if (!compositionResults.compositionUpdated()) 436 return false; 437 438 m_updatingComposition = true; 439 440 // This won't prevent a keypress event alone, but PlatformKeyboardEvent returns 441 // an empty string when there are composition results. That prevents the delivery 442 // of keypress, which is the behavior we want for composition events. See 443 // EventHandler::keyEvent. 444 event->preventDefault(); 445 ASSERT(platformEvent->string().isNull()); 446 447 if (!compositionResults.confirmedComposition.isNull()) 448 frame->editor()->confirmComposition(compositionResults.confirmedComposition); 449 450 String preedit = compositionResults.preedit; 451 if (!preedit.isNull()) { 452 Vector<CompositionUnderline> underlines; 453 underlines.append(CompositionUnderline(0, preedit.length(), Color(1, 1, 1), false)); 454 frame->editor()->setComposition(preedit, underlines, compositionResults.preeditCursorOffset, compositionResults.preeditCursorOffset); 455 } 456 457 m_updatingComposition = false; 458 return true; 492 459 } 493 460 … … 501 468 const PlatformKeyboardEvent* platformEvent = event->keyEvent(); 502 469 if (!platformEvent) 470 return; 471 472 if (handleInputMethodKeyboardEvent(event)) 503 473 return; 504 474 … … 532 502 // until a keypress event happens. This will ensure that the insertion will not 533 503 // be reflected in the contents of the field until the keyup DOM event. 534 if (event->type() == eventNames().keypressEvent) { 535 536 // If we have a pending composition at this point, it happened while 537 // filtering a keypress, so we treat it as a normal text insertion. 538 // This will also ensure that if the keypress event handler changed the 539 // currently focused node, the text is still inserted into the original 540 // node (insertText() has this logic, but confirmComposition() does not). 541 if (m_pendingComposition) { 542 frame->editor()->insertText(String::fromUTF8(m_pendingComposition.get()), event); 543 clearPendingComposition(); 544 event->setDefaultHandled(); 545 546 } else { 547 // Don't insert null or control characters as they can result in unexpected behaviour 548 if (event->charCode() < ' ') 549 return; 550 551 // Don't insert anything if a modifier is pressed 552 if (platformEvent->ctrlKey() || platformEvent->altKey()) 553 return; 554 555 if (frame->editor()->insertText(platformEvent->text(), event)) 556 event->setDefaultHandled(); 557 } 558 } 504 if (event->type() != eventNames().keypressEvent) 505 return; 506 507 // Don't insert null or control characters as they can result in unexpected behaviour 508 if (event->charCode() < ' ') 509 return; 510 511 // Don't insert anything if a modifier is pressed 512 if (platformEvent->ctrlKey() || platformEvent->altKey()) 513 return; 514 515 if (frame->editor()->insertText(platformEvent->text(), event)) 516 event->setDefaultHandled(); 559 517 } 560 518 561 519 void EditorClient::handleInputMethodKeydown(KeyboardEvent* event) 562 520 { 563 Frame* targetFrame = core(m_webView)->focusController()->focusedOrMainFrame(); 564 if (!targetFrame || !targetFrame->editor()->canEdit()) 565 return; 566 567 WebKitWebViewPrivate* priv = m_webView->priv; 568 569 m_preventNextCompositionCommit = false; 570 571 // Some IM contexts (e.g. 'simple') will act as if they filter every 572 // keystroke and just issue a 'commit' signal during handling. In situations 573 // where the 'commit' signal happens during filtering and there is no active 574 // composition, act as if the keystroke was not filtered. The one exception to 575 // this is when the keyval parameter of the GdkKeyEvent is 0, which is often 576 // a key event sent by the IM context for committing the current composition. 577 578 // Here is a typical sequence of events for the 'simple' context: 579 // 1. GDK key press event -> webkit_web_view_key_press_event 580 // 2. Keydown event -> EditorClient::handleInputMethodKeydown 581 // gtk_im_context_filter_keypress returns true, but there is a pending 582 // composition so event->preventDefault is not called (below). 583 // 3. Keydown event bubbles through the DOM 584 // 4. Keydown event -> EditorClient::handleKeyboardEvent 585 // No action taken. 586 // 4. GDK key release event -> webkit_web_view_key_release_event 587 // 5. gtk_im_context_filter_keypress is called on the release event. 588 // Simple does not filter most key releases, so the event continues. 589 // 6. Keypress event bubbles through the DOM. 590 // 7. Keypress event -> EditorClient::handleKeyboardEvent 591 // pending composition is inserted. 592 // 8. Keyup event bubbles through the DOM. 593 // 9. Keyup event -> EditorClient::handleKeyboardEvent 594 // No action taken. 595 596 // There are two situations where we do filter the keystroke: 597 // 1. The IMContext instructed us to filter and we have no pending composition. 598 // 2. The IMContext did not instruct us to filter, but the keystroke caused a 599 // composition in progress to finish. It seems that sometimes SCIM will finish 600 // a composition and not mark the keystroke as filtered. 601 m_treatContextCommitAsKeyEvent = (!targetFrame->editor()->hasComposition()) 602 && event->keyEvent()->gdkEventKey()->keyval; 603 clearPendingComposition(); 604 if ((gtk_im_context_filter_keypress(priv->imContext.get(), event->keyEvent()->gdkEventKey()) && !m_pendingComposition) 605 || (!m_treatContextCommitAsKeyEvent && !targetFrame->editor()->hasComposition())) 606 event->preventDefault(); 607 608 m_treatContextCommitAsKeyEvent = false; 609 } 610 611 void EditorClient::handleInputMethodMousePress() 612 { 613 Frame* targetFrame = core(m_webView)->focusController()->focusedOrMainFrame(); 614 615 if (!targetFrame || !targetFrame->editor()->canEdit()) 616 return; 617 618 WebKitWebViewPrivate* priv = m_webView->priv; 619 620 // When a mouse press fires, the commit signal happens during a composition. 621 // In this case, if the focused node is changed, the commit signal happens in a diffrent node. 622 // Therefore, we need to confirm the current compositon and ignore the next commit signal. 623 GOwnPtr<gchar> newPreedit(0); 624 gtk_im_context_get_preedit_string(priv->imContext.get(), &newPreedit.outPtr(), 0, 0); 625 626 if (g_utf8_strlen(newPreedit.get(), -1)) { 627 targetFrame->editor()->confirmComposition(); 628 m_preventNextCompositionCommit = true; 629 gtk_im_context_reset(priv->imContext.get()); 630 } 521 // Input method results are handled in handleKeyboardEvent, so that we can wait 522 // to trigger composition updates until after the keydown event handler. This better 523 // matches other browsers. 631 524 } 632 525 … … 637 530 #endif 638 531 , m_webView(webView) 639 , m_preventNextCompositionCommit(false)640 , m_treatContextCommitAsKeyEvent(false)641 532 , m_smartInsertDeleteEnabled(false) 642 { 643 WebKitWebViewPrivate* priv = m_webView->priv; 644 g_signal_connect(priv->imContext.get(), "commit", G_CALLBACK(imContextCommitted), this); 645 g_signal_connect(priv->imContext.get(), "preedit-changed", G_CALLBACK(imContextPreeditChanged), this); 533 , m_updatingComposition(false) 534 { 646 535 } 647 536 648 537 EditorClient::~EditorClient() 649 538 { 650 WebKitWebViewPrivate* priv = m_webView->priv;651 g_signal_handlers_disconnect_by_func(priv->imContext.get(), (gpointer)imContextCommitted, this);652 g_signal_handlers_disconnect_by_func(priv->imContext.get(), (gpointer)imContextPreeditChanged, this);653 539 } 654 540 -
trunk/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
r110865 r116114 66 66 ~EditorClient(); 67 67 WebKitWebView* webView() { return m_webView; } 68 bool treatContextCommitAsKeyEvent() { return m_treatContextCommitAsKeyEvent; }69 bool preventNextCompositionCommit() { return m_preventNextCompositionCommit; }70 void clearPendingComposition() { m_pendingComposition.set(0); }71 bool hasPendingComposition() { return m_pendingComposition; }72 68 void addPendingEditorCommand(const char* command) { m_pendingEditorCommands.append(command); } 73 void updatePendingComposition(const char*);74 69 void generateEditorCommands(const WebCore::KeyboardEvent*); 75 70 bool executePendingEditorCommands(WebCore::Frame*, bool); … … 120 115 virtual void handleKeyboardEvent(WebCore::KeyboardEvent*); 121 116 virtual void handleInputMethodKeydown(WebCore::KeyboardEvent*); 122 virtual void handleInputMethodMousePress();123 117 124 118 virtual void textFieldDidBeginEditing(WebCore::Element*); … … 141 135 142 136 private: 137 bool handleInputMethodKeyboardEvent(WebCore::KeyboardEvent*); 138 143 139 #if ENABLE(SPELLCHECK) 144 140 TextCheckerClientGtk m_textCheckerClient; … … 147 143 #endif 148 144 WebKitWebView* m_webView; 149 bool m_preventNextCompositionCommit;150 bool m_treatContextCommitAsKeyEvent;151 GOwnPtr<gchar> m_pendingComposition;152 153 145 WebCore::KeyBindingTranslator m_keyBindingTranslator; 154 146 Vector<WTF::String> m_pendingEditorCommands; 155 156 147 bool m_smartInsertDeleteEnabled; 148 bool m_updatingComposition; 157 149 }; 158 150 } -
trunk/Source/WebKit/gtk/webkit/webkitwebview.cpp
r115672 r116114 274 274 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures); 275 275 276 static GtkIMContext* webkit_web_view_get_im_context(WebKitWebView*);277 278 276 #if ENABLE(CONTEXT_MENUS) 279 277 static void PopupMenuPositionFunc(GtkMenu* menu, gint *x, gint *y, gboolean *pushIn, gpointer userData) … … 582 580 break; 583 581 case PROP_IM_CONTEXT: 584 g_value_set_object(value, web kit_web_view_get_im_context(webView));582 g_value_set_object(value, webView->priv->imFilter.context()); 585 583 break; 586 584 case PROP_VIEW_MODE: … … 711 709 static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* event) 712 710 { 713 WebKitWebView* webView = WEBKIT_WEB_VIEW(widget); 714 715 Frame* frame = core(webView)->focusController()->focusedOrMainFrame(); 716 PlatformKeyboardEvent keyboardEvent(event); 717 718 if (!frame->view()) 719 return FALSE; 720 721 if (frame->eventHandler()->keyEvent(keyboardEvent)) 711 if (WEBKIT_WEB_VIEW(widget)->priv->imFilter.filterKeyEvent(event)) 722 712 return TRUE; 723 724 /* Chain up to our parent class for binding activation */725 713 return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_press_event(widget, event); 726 714 } … … 728 716 static gboolean webkit_web_view_key_release_event(GtkWidget* widget, GdkEventKey* event) 729 717 { 730 WebKitWebView* webView = WEBKIT_WEB_VIEW(widget); 731 732 // GTK+ IM contexts often require us to filter key release events, which 733 // WebCore does not do by default, so we filter the event here. We only block 734 // the event if we don't have a pending composition, because that means we 735 // are using a context like 'simple' which marks every keystroke as filtered. 736 WebKit::EditorClient* client = static_cast<WebKit::EditorClient*>(core(webView)->editorClient()); 737 if (gtk_im_context_filter_keypress(webView->priv->imContext.get(), event) && !client->hasPendingComposition()) 718 if (WEBKIT_WEB_VIEW(widget)->priv->imFilter.filterKeyEvent(event)) 738 719 return TRUE; 739 740 Frame* frame = core(webView)->focusController()->focusedOrMainFrame();741 if (!frame->view())742 return FALSE;743 744 PlatformKeyboardEvent keyboardEvent(event);745 if (frame->eventHandler()->keyEvent(keyboardEvent))746 return TRUE;747 748 /* Chain up to our parent class for binding activation */749 720 return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_release_event(widget, event); 750 721 } … … 774 745 return FALSE; 775 746 747 priv->imFilter.notifyMouseButtonPress(); 776 748 gboolean result = frame->eventHandler()->handleMousePressEvent(platformEvent); 777 // Handle the IM context when a mouse press fires778 static_cast<WebKit::EditorClient*>(core(webView)->editorClient())->handleInputMethodMousePress();779 749 780 750 #if PLATFORM(X11) … … 965 935 // http://bugs.webkit.org/show_bug.cgi?id=16910 966 936 GtkWidget* toplevel = gtk_widget_get_toplevel(widget); 967 if ( widgetIsOnscreenToplevelWindow(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) {968 WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);969 FocusController* focusController = core(webView)->focusController(); 970 971 focusController->setActive(true);972 973 if (focusController->focusedFrame())974 focusController->setFocused(true);975 else976 focusController->setFocusedFrame(core(webView)->mainFrame());977 978 if (focusController->focusedFrame()->editor()->canEdit()) 979 gtk_im_context_focus_in(webView->priv->imContext.get());980 }937 if (!widgetIsOnscreenToplevelWindow(toplevel) || !gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) 938 return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_in_event(widget, event); 939 940 WebKitWebView* webView = WEBKIT_WEB_VIEW(widget); 941 FocusController* focusController = core(webView)->focusController(); 942 943 focusController->setActive(true); 944 if (focusController->focusedFrame()) 945 focusController->setFocused(true); 946 else 947 focusController->setFocusedFrame(core(webView)->mainFrame()); 948 949 if (focusController->focusedFrame()->editor()->canEdit()) 950 webView->priv->imFilter.notifyFocusedIn(); 981 951 return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_in_event(widget, event); 982 952 } … … 988 958 // We may hit this code while destroying the widget, and we might 989 959 // no longer have a page, then. 990 Page* page = core(webView); 991 if (page) { 960 if (Page* page = core(webView)) { 992 961 page->focusController()->setActive(false); 993 962 page->focusController()->setFocused(false); 994 963 } 995 964 996 if (webView->priv->imContext) 997 gtk_im_context_focus_out(webView->priv->imContext.get()); 998 965 webView->priv->imFilter.notifyFocusedOut(); 999 966 return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_out_event(widget, event); 1000 967 } … … 1002 969 static void webkit_web_view_realize(GtkWidget* widget) 1003 970 { 1004 WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(widget)->priv;1005 1006 971 gtk_widget_set_realized(widget, TRUE); 1007 972 … … 1059 1024 gtk_style_context_set_background(gtk_widget_get_style_context(widget), window); 1060 1025 #endif 1061 1062 gtk_im_context_set_client_window(priv->imContext.get(), window);1063 1026 } 1064 1027 … … 1641 1604 } 1642 1605 #endif 1643 1644 static GtkIMContext* webkit_web_view_get_im_context(WebKitWebView* webView)1645 {1646 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);1647 return GTK_IM_CONTEXT(webView->priv->imContext.get());1648 }1649 1606 1650 1607 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) … … 3565 3522 new (priv) WebKitWebViewPrivate(); 3566 3523 3567 priv->im Context = adoptGRef(gtk_im_multicontext_new());3524 priv->imFilter.setWebView(webView); 3568 3525 3569 3526 Page::PageClients pageClients; -
trunk/Source/WebKit/gtk/webkit/webkitwebviewprivate.h
r111696 r116114 30 30 #include "Page.h" 31 31 #include "ResourceHandle.h" 32 #include "WebViewInputMethodFilter.h" 32 33 #include "WidgetBackingStore.h" 33 34 #include <webkit/webkitwebview.h> … … 60 61 61 62 HashSet<GtkWidget*> children; 62 GRefPtr<GtkIMContext> imContext;63 WebKit::WebViewInputMethodFilter imFilter; 63 64 64 65 gboolean transparent;
Note: See TracChangeset
for help on using the changeset viewer.