From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/events/IMEStateManager.h | 494 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 dom/events/IMEStateManager.h (limited to 'dom/events/IMEStateManager.h') diff --git a/dom/events/IMEStateManager.h b/dom/events/IMEStateManager.h new file mode 100644 index 0000000000..1320fef8cc --- /dev/null +++ b/dom/events/IMEStateManager.h @@ -0,0 +1,494 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_IMEStateManager_h_ +#define mozilla_IMEStateManager_h_ + +#include "mozilla/EventForwards.h" +#include "mozilla/Maybe.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/dom/BrowserParent.h" +#include "nsIWidget.h" + +class nsIContent; +class nsINode; +class nsPresContext; + +namespace mozilla { + +class EditorBase; +class EventDispatchingCallback; +class IMEContentObserver; +class TextCompositionArray; +class TextComposition; + +namespace dom { +class Element; +class Selection; +} // namespace dom + +/** + * IMEStateManager manages InputContext (e.g., active editor type, IME enabled + * state and IME open state) of nsIWidget instances, manages IMEContentObserver + * and provides useful API for IME. + */ + +class IMEStateManager { + typedef dom::BrowserParent BrowserParent; + typedef widget::IMEMessage IMEMessage; + typedef widget::IMENotification IMENotification; + typedef widget::IMEState IMEState; + typedef widget::InputContext InputContext; + typedef widget::InputContextAction InputContextAction; + + public: + static void Init(); + static void Shutdown(); + + /** + * GetActiveBrowserParent() returns a pointer to a BrowserParent instance + * which is managed by the focused content (sFocusedElement). If the focused + * content isn't managing another process, this returns nullptr. + */ + static BrowserParent* GetActiveBrowserParent() { + // If menu has pseudo focus, we should ignore active child process. + if (sInstalledMenuKeyboardListener) { + return nullptr; + } + // If we know focused browser parent, use it for making any events related + // to composition go to same content process. + if (sFocusedIMEBrowserParent) { + return sFocusedIMEBrowserParent; + } + return BrowserParent::GetFocused(); + } + + /** + * DoesBrowserParentHaveIMEFocus() returns true when aBrowserParent has IME + * focus, i.e., the BrowserParent sent "focus" notification but not yet sends + * "blur". Note that this doesn't check if the remote processes are same + * because if another BrowserParent has focus, committing composition causes + * firing composition events in different BrowserParent. (Anyway, such case + * shouldn't occur.) + */ + static bool DoesBrowserParentHaveIMEFocus( + const BrowserParent* aBrowserParent) { + MOZ_ASSERT(aBrowserParent); + return sFocusedIMEBrowserParent == aBrowserParent; + } + + /** + * If CanSendNotificationToWidget() returns false (it should occur + * only in a content process), we shouldn't notify the widget of + * any focused editor changes since the content process was blurred. + * Also, even if content process, widget has native text event dispatcher such + * as Android, it still notify it. + */ + static bool CanSendNotificationToWidget() { +#ifdef MOZ_WIDGET_ANDROID + return true; +#else + return !sCleaningUpForStoppingIMEStateManagement; +#endif + } + + /** + * Focus moved between browsers from aBlur to aFocus. (nullptr means the + * chrome process.) + */ + static void OnFocusMovedBetweenBrowsers(BrowserParent* aBlur, + BrowserParent* aFocus); + + /** + * Called when aWidget is being deleted. + */ + static void WidgetDestroyed(nsIWidget* aWidget); + + /** + * Called when a widget exists when the app is quitting + */ + static void WidgetOnQuit(nsIWidget* aWidget); + + /** + * GetWidgetForActiveInputContext() returns a widget which IMEStateManager + * is managing input context with. If a widget instance needs to cache + * the last input context for nsIWidget::GetInputContext() or something, + * it should check if its cache is valid with this method before using it + * because if this method returns another instance, it means that + * IMEStateManager may have already changed shared input context via the + * widget. + */ + static nsIWidget* GetWidgetForActiveInputContext() { + return sActiveInputContextWidget; + } + + /** + * SetIMEContextForChildProcess() is called when aBrowserParent receives + * SetInputContext() from the remote process. + */ + static void SetInputContextForChildProcess(BrowserParent* aBrowserParent, + const InputContext& aInputContext, + const InputContextAction& aAction); + + /** + * StopIMEStateManagement() is called when the process should stop managing + * IME state. + */ + static void StopIMEStateManagement(); + + /** + * MaybeStartOffsetUpdatedInChild() is called when composition start offset + * is maybe updated in the child process. I.e., even if it's not updated, + * this is called and never called if the composition is in this process. + * @param aWidget The widget whose native IME context has the + * composition. + * @param aStartOffset New composition start offset with native + * linebreaks. + */ + static void MaybeStartOffsetUpdatedInChild(nsIWidget* aWidget, + uint32_t aStartOffset); + + MOZ_CAN_RUN_SCRIPT static nsresult OnDestroyPresContext( + nsPresContext& aPresContext); + MOZ_CAN_RUN_SCRIPT static nsresult OnRemoveContent( + nsPresContext& aPresContext, dom::Element& aElement); + /** + * OnChangeFocus() should be called when focused content is changed or + * IME enabled state is changed. If nobody has focus, set both aPresContext + * and aContent nullptr. E.g., all windows are deactivated. Otherwise, + * set focused element (even if it won't receive `focus`event) and + * corresponding nsPresContext for it. Then, IMEStateManager can avoid + * handling delayed notifications from the others with verifying the + * focused element. + */ + MOZ_CAN_RUN_SCRIPT static nsresult OnChangeFocus( + nsPresContext* aPresContext, dom::Element* aElement, + InputContextAction::Cause aCause); + + /** + * OnInstalledMenuKeyboardListener() is called when menu keyboard listener + * is installed or uninstalled in the process. So, even if menu keyboard + * listener was installed in chrome process, this won't be called in content + * processes. + * + * @param aInstalling true if menu keyboard listener is installed. + * Otherwise, i.e., menu keyboard listener is + * uninstalled, false. + */ + MOZ_CAN_RUN_SCRIPT static void OnInstalledMenuKeyboardListener( + bool aInstalling); + + // These two methods manage focus and selection/text observers. + // They are separate from OnChangeFocus above because this offers finer + // control compared to having the two methods incorporated into OnChangeFocus + + // Get the focused editor's selection and root + static nsresult GetFocusSelectionAndRootElement(dom::Selection** aSel, + dom::Element** aRootElement); + // This method updates the current IME state. However, if the enabled state + // isn't changed by the new state, this method does nothing. + // Note that this method changes the IME state of the active element in the + // widget. So, the caller must have focus. + // XXX Changing this to MOZ_CAN_RUN_SCRIPT requires too many callers to be + // marked too. Probably, we should initialize IMEContentObserver + // asynchronously. + enum class UpdateIMEStateOption { + ForceUpdate, + DontCommitComposition, + }; + using UpdateIMEStateOptions = EnumSet; + MOZ_CAN_RUN_SCRIPT static void UpdateIMEState( + const IMEState& aNewIMEState, dom::Element* aElement, + EditorBase& aEditorBase, const UpdateIMEStateOptions& aOptions = {}); + + // This method is called when user operates mouse button in focused editor + // and before the editor handles it. + // Returns true if IME consumes the event. Otherwise, false. + MOZ_CAN_RUN_SCRIPT static bool OnMouseButtonEventInEditor( + nsPresContext& aPresContext, dom::Element* aElement, + WidgetMouseEvent& aMouseEvent); + + // This method is called when user clicked in an editor. + // aElement must be: + // If the editor is for or