Currently, if an event is consumed in the main process, EventStateManager
does not send it to remote process. However, this is unexpected behavior
for some WidgetKeyboardEvent dispatchers. OS sometimes has consumed native
key events before sending applications. For example, Alt key on Windows
should activate menu bar of focused window but Alt key may be consumed before
focused window receives the event. In such case, we mark Alt keyboard event
as "consumed before dispatch", and chrome treat it like as its preventDefault()
is called in web content. (Note that for compatibility with other browsers,
the consumed state is not exposed to web content. So, Event.defaultPrevented
returns false in web content.)
Therefore, we need to treat "consumed" state and "cross process forwarding"
state separately. This patch makes calling WidgetEvent::PreventDefault()
always stops cross process forwarding for backward compatibility. Additionally,
for the special case mentioned above, this patch makes
WidgetEvent::PreventDefaultBeforeDispatch() take additional argument,
|aIfStopCrossProcessForwarding|. If this is CrossProcessForwarding::eStop,
the event won't be sent to remote process as same as calling PreventDefault().
Otherwise, CrossProcessForwarding::eHold, PreventDefaultBeforeDispatch() call
does not change "cross process forwarding" state. I.e., if the event's
StopCrossProcessForwarding() and PreventDefault() are not called until
EventStateManager::PostHandleEvent(), the event will be sent to remote process
as usual.
MozReview-Commit-ID: IQGWJvXetxV
UI Events declares that keypress event should be fired only when the keydown
sequence produces some characters. For conforming to UI Events and
compatibility with the other browsers, we should stop dispatching keypress
events for non-printable keys.
For getting regression reports, we should enable this new behavior only
on Nightly.
However, some web apps actually broken with the standardized behavior. For
protecting testers from known broken web apps, this patch introduces a
blacklist to take the traditional behavior under specific domain (and path in
it, optionally). Currently, docs.google.com and mail.google.com are set by
default.
MozReview-Commit-ID: HSrYX8LUB0p
For confirming to UI Events spec, we should dispatch "keydown" event and
"keyup" event even during in composition.
This patch makes only Nightly and early Beta start to dispatch those events
during a composition.
MozReview-Commit-ID: 8md7NtSdurJ
We have stopped dispatching "keypress" events for non-printable keys
and key combinations for conforming to UI Events and following the
other browsers.
However, this change hits a serious bugs of Google Docs, Google
Spreadsheets and Gmail. Until they will fix their bugs, we should
take back the traditional behavior for keeping Nightly usable for
any Nightly testers.
MozReview-Commit-ID: 9CyEbsFit1S
UI Events declares that keypress event should be fired only when the keydown
sequence produces some characters. For conforming to UI Events and
compatibility with the other browsers, we should stop dispatching keypress
events for non-printable keys.
For getting regression reports, we should enable this new behavior only
on Nightly and early Beta.
MozReview-Commit-ID: 5IIL9huejXH
Currently, we dispatch keypress event when Enter is pressed without modifiers
or only with Shift key. However, the other browsers dispatch keypress event
for Ctrl + Enter in any platforms even if it doesn't cause any text input.
So, we should fire keypress event for Ctrl + Enter even in strict keypress
dispatching mode.
Note that with other modifiers, it depends on browser and/or platform.
So, anyway, web developers shouldn't use keypress event to catch
Alt + Enter, Meta + Enter and two or more modifiers + Enter.
MozReview-Commit-ID: 3uUMkhL5VfJ
Chromium dispatches a keypress event when pressing Enter or Shift+Enter.
Actually, when user press them in <pre> element of HTML editor, ツ・n is inserted.
It makes sense to treat the key combinations as inputting text.
MozReview-Commit-ID: Hvx87MZtZkn
UI Events declares that keypress event should be fired when the keypress event
causes some text input. However, we're keeping our traditional behavior for
historical reasons because our internal event handlers (including event
handlers of Thunderbird) handles keypress events for any keys. Therefore,
for minimizing the side effect, we should stop kicking keypress event handlers
in the default event group in web content.
This patch adds new pref for enabling the standard behavior in web content.
Additionally, creates WidgetKeyboardEvent::IsInputtingText() for sharing the
check logic between TextEventDispatcher and TextEditor/HTMLEditor.
MozReview-Commit-ID: 3rtXdLBPeVC
When composition events are handled by content actually, widget receives
NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED notification. If focused content
is in a remote process, this is notified only when all sending composition
events are handled in the remote process. So, when widget receives the
notification can there is no composition in IME, that means that nobody is
composing composition at that time.
This patch adds TextEventDispatcher::IsHandlingComposition() which returns
false only when nobody has composition and makes TSFTextStore refer this
method because TSFTextStore needs to know if focused content has composition
in any cases.
MozReview-Commit-ID: F1ZZgFJAArD
In the parent process, every nsIWidget instance like nsWindow has TextEventDispatcher instance after dispatching a keyboard event or a composition event. Then, TextEventDispatcher manages whether there is composition and handles NotifyIME. However, PuppetWidget doesn't have it unless it synthesizes keyboard events or composition events for tests.
This causes PuppetWidget implementing nsIWidget::NotifyIME() with nsBaseWidget::NotifyIMEInternal() which is a virtual method only implemented by PuppetWidget. For consistent implementation around here, we should move NotifyIMEInternal() implementation to TextEventDispatcherListener::NotifyIME() which is called by TextEventDispatcher::NotifyIME(). Then, PuppetWidget can handle NotifyIME() easier.
This patch creates TextEventDispatcher::BeginInputTransactionFor() which takes pointer to a dispatching event and pointer to PuppetWidget. It emulates each corresponding event dispatcher method for managing composing state and begins input transaction for the dispatching event.
Unfortunately, this implementation is ugly due to duplicated code. However, this is enough for now. When we need to make TextEventDispatcher manage more states, we should add methods which are shared by both BeginInputTransactionFor() and event dispatcher method.
MozReview-Commit-ID: GeP028luZjR
IMEContentObserver may need to change notifications to send when TextInputProcessor begins input transaction. In current design, IMEContentObserver needs to retrieve IMENotificationRequests at every change. However, if nsIWidget returns a reference to its IMENotificationRequests, IMEContentObserver can call it only once.
For that purpose, this patch changes nsIWidget::GetIMENotificationRequests() to nsIWidget::IMENotificationRequestsRef() and make it return |const IMENotificationRequests&|. However, if the lifetime of the instance of IMENotificationRequest is shorter than the widget instance's, it's dangerous. Therefore, it always returns TextEventDispatcher::mIMENotificationRequests. TextEventDispatcher's lifetime is longer than the widget. Therefore, this guarantees the lifetime.
On the other hand, widget needs to update TextEventDispatcher::mIMENotificationRequests before calls of nsIWidget::IMENotificationRequestsRef(). Therefore, this patch makes TextEventDispatcher update proper IMENotificationRequests when it gets focus or starts new input transaction and clear mIMENotificationRequests when it loses focus.
Note that TextEventDispatcher gets proper requests both from native text event dispatcher listener (typically, implemented by native IME handler class) and TextInputProcessor when TextInputProcessor has input transaction because even if TextInputProcessor overrides native IME, native IME still needs to know the content changes since they may get new input transaction after that.
However, there may not be native IME handler in content process. If it runs in Android, PuppetWidget may have native IME handler because widget directly handles IME in e10s mode for Android. Otherwise, native IME handler is in its parent process. So, if TextInputHandler has input transaction in content process, PuppetWidget needs to behave as native event handler. Therefore, this patch makes PuppetWidget inherit TextEventDispatcherListener and implements PuppetWidget::IMENotificationRequestsRef().
MozReview-Commit-ID: 2SW3moONTOX
According to ATOK's behavior, IME may send different line breaker from its platform's standard. Therefore, we should treat \r as \n too.
Additionally, currently, TextComposition doesn't allow to input \n with composition. However, this was added for preventing to see odd control characters as boxes with code point. Therefore, we should allow \n for IMEs. (It was allowed, this limitation is unexpected when I reviewed the patch to reject control characters in TextComposition.)
MozReview-Commit-ID: DzGSMgp89Av
So, finally, Flush() should replace native line breakers in the composition string before dispatching composition events. However, if the composition string was set by Set(), i.e., it's already been replaced with native line breakers, we shouldn't try to do it again due to performance reason. Therefore, this patch adds |mReplacedNativeLineBreakers| to manage if it's already been called.
MozReview-Commit-ID: 5Y7ULWeP153
First of all, replacing native line breakers with XP line breakers needs to adjust offset and length of each TextRange. Therefore, we cannot just duplicate the code into TextEventDispatcher::PendingComposition::Flush().
For creating a new method to replace the native line breakers in PendingComposition::mString, we should separate range adjustment code to a static method, AdjustRange(), because we cannot use for loop simply because we need to adjust both mClauses and mCaret.
MozReview-Commit-ID: 5ycsN8EAs45
This patch creates NativeKey::DispatchKeyPressEventsWithRetrievedCharMessages() for dispatching eKeyPress event with mCommittedCharsAndModifiers when it stores following printable WM_(SYS)CHAR messages.
Using loop for dispatching eKeyPress event for every WM_(SYS)CHAR message is wrong because WidgetKeyboardEvent::mKeyValue is initialized with mCommittedCharsAndModifiers and it causes TextEventDispatcher dispatching multiple eKeyPress events at every call of MaybeDispatchKeypressEvents(). Therefore, if mKeyValue is "^^", eKeyPress event is dispatched 4 times --for the first message, eKeyPress events are fired for each "^" and for the second message, eKeyPress events are fired again for each "^"--. Therefore, when it handles WM_(SYS)KEYDOWN and it causes inputting one or more printable characters, it's the easiest way not to use HandleCharMessage().
The new method calls TextEventDispatcher::MaybeDispatchKeypressEvents() only once and it requests to call the callback method with new argument of MaybeDispatchKeypressEvents() when it needs to dispatch 2 or more eKeyPress events. Then, NativeKey::WillDispatchKeyboardEvent() can set each eKeyPress event to raw information of the message and proper modifier state.
With this change, we can dispatch multiple eKeyPress events with retrieved WM_(SYS)CHAR message information rather than retrieved information from active keyboard layout. Therefore, NeedsToHandleWithoutFollowingCharMessages() doesn't return true even when mCommittedCharsAndModifiers stores two or more characters.
FYI: there is a bug in test_keycodes.xul. That is, Alt+'A' of Greek keyboard layout should cause WM_SYSCHAR with a corresponding Greek character but ASCII characters are specified. Therefore, this patch includes the fix of these bugs
MozReview-Commit-ID: JVm7ZJVug0O
For making our code clearer by the stronger type check, we should change the anonymous enum for NS_TEXTRANGE_* to enum class whose name is "TextRangeType" and whose type is "RawTextRangeType" which is an alias of uint8_t.
Additionally, this also adds some utility methods for them.
Note that some lines which are changed by this patch become over 80 characters but it will be fixed by the following patches.
MozReview-Commit-ID: 76izA1WqTkp
If a plugin process posts native key events to the widget, it needs to check if the key combination is reserved by chrome because if it's reserved by chrome, the reserved shortcut key handler should be executed and the event shouldn't be handled by the focused plugin.
This patches add eKeyDownOnPlugin and eKeyUpOnPlugin. nsXBLWindowKeyHandler will listen to them and handle them as normal keydown and keypress or keyup event. Note that these events won't be fired on content in the default event group and won't be sent to the remote process.
MozReview-Commit-ID: H5OKPLtVdr6
mDefaultPreventedByChrome is hacky. When PresShell handles Escape key events in fullscreen mode, it prevents default of every Escape key events and dispatch it only into chrome. After that, it check mDefaultPreventedByChrome if at least one call of preventDefault() occurred in chrome. Therefore, if we shouldn't set both mDefaultPreventedByChrome and mDefaultPreventedByContent to true before dispatching an event. This the reason why we need a special method, PreventDefaultBeforeDispatch() is needed for setting only mDefaultPrevented to true.
MozReview-Commit-ID: BPSq68GnWw6
The bulk of this commit was generated with a script, executed at the top
level of a typical source code checkout. The only non-machine-generated
part was modifying MFBT's moz.build to reflect the new naming.
CLOSED TREE makes big refactorings like this a piece of cake.
# The main substitution.
find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \
xargs perl -p -i -e '
s/nsRefPtr\.h/RefPtr\.h/g; # handle includes
s/nsRefPtr ?</RefPtr</g; # handle declarations and variables
'
# Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h.
perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h
# Handle nsRefPtr.h itself, a couple places that define constructors
# from nsRefPtr, and code generators specially. We do this here, rather
# than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename
# things like nsRefPtrHashtable.
perl -p -i -e 's/nsRefPtr/RefPtr/g' \
mfbt/nsRefPtr.h \
xpcom/glue/nsCOMPtr.h \
xpcom/base/OwningNonNull.h \
ipc/ipdl/ipdl/lower.py \
ipc/ipdl/ipdl/builtin.py \
dom/bindings/Codegen.py \
python/lldbutils/lldbutils/utils.py
# In our indiscriminate substitution above, we renamed
# nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up.
find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \
xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g'
if [ -d .git ]; then
git mv mfbt/nsRefPtr.h mfbt/RefPtr.h
else
hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h
fi