1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef WinIMEHandler_h_ 7 #define WinIMEHandler_h_ 8 9 #include "nscore.h" 10 #include "nsWindow.h" 11 #include "npapi.h" 12 #include <windows.h> 13 #include <inputscope.h> 14 15 #define NS_WM_IMEFIRST WM_IME_SETCONTEXT 16 #define NS_WM_IMELAST WM_IME_KEYUP 17 18 class nsWindow; 19 20 namespace mozilla { 21 namespace widget { 22 23 struct MSGResult; 24 25 /** 26 * IMEHandler class is a mediator class. On Windows, there are two IME API 27 * sets: One is IMM which is legacy API set. The other is TSF which is modern 28 * API set. By using this class, non-IME handler classes don't need to worry 29 * that we're in which mode. 30 */ 31 class IMEHandler final { 32 private: 33 /** 34 * Initialize() initializes both TSF modules and IMM modules. Some TIPs 35 * may require a normal window (i.e., not message window) belonging to 36 * this process. Therefore, this is called immediately after first normal 37 * window is created. 38 */ 39 static void Initialize(); 40 41 public: 42 static void Terminate(); 43 44 /** 45 * Returns TSF related native data or native IME context. 46 */ 47 static void* GetNativeData(nsWindow* aWindow, uint32_t aDataType); 48 49 /** 50 * ProcessRawKeyMessage() message is called before calling TranslateMessage() 51 * and DispatchMessage(). If this returns true, the message is consumed. 52 * Then, caller must not perform TranslateMessage() nor DispatchMessage(). 53 */ 54 static bool ProcessRawKeyMessage(const MSG& aMsg); 55 56 /** 57 * When the message is not needed to handle anymore by the caller, this 58 * returns true. Otherwise, false. 59 */ 60 static bool ProcessMessage(nsWindow* aWindow, UINT aMessage, WPARAM& aWParam, 61 LPARAM& aLParam, MSGResult& aResult); 62 63 /** 64 * IsA11yHandlingNativeCaret() returns true if a11y is handling 65 * native caret. In such case, IME modules shouldn't touch native caret. 66 **/ 67 static bool IsA11yHandlingNativeCaret(); 68 69 /** 70 * NeedsToCreateNativeCaret() returns true if IME handler needs to create 71 * native caret for other applications which requests OBJID_CARET with 72 * WM_GETOBJECT and a11y module isn't active (if a11y module is active, 73 * it always creates native caret, i.e., even if no editor has focus). 74 */ NeedsToCreateNativeCaret()75 static bool NeedsToCreateNativeCaret() { 76 return sHasNativeCaretBeenRequested && !IsA11yHandlingNativeCaret(); 77 } 78 79 /** 80 * CreateNativeCaret() create native caret if this has been created it. 81 * 82 * @param aWindow The window which owns the caret. 83 * @param aCaretRect The caret rect relative to aWindow. 84 */ 85 static bool CreateNativeCaret(nsWindow* aWindow, 86 const LayoutDeviceIntRect& aCaretRect); 87 88 /** 89 * MaybeDestroyNativeCaret() destroies native caret if it has been created 90 * by IMEHandler. 91 */ 92 static void MaybeDestroyNativeCaret(); 93 94 /** 95 * HasNativeCaret() returns true if there is native caret and it was created 96 * by IMEHandler. 97 */ HasNativeCaret()98 static bool HasNativeCaret() { return sNativeCaretIsCreated; } 99 100 /** 101 * When there is a composition, returns true. Otherwise, false. 102 */ 103 static bool IsComposing(); 104 105 /** 106 * When there is a composition and it's in the window, returns true. 107 * Otherwise, false. 108 */ 109 static bool IsComposingOn(nsWindow* aWindow); 110 111 /** 112 * Notifies IME of the notification (a request or an event). 113 */ 114 static nsresult NotifyIME(nsWindow* aWindow, 115 const IMENotification& aIMENotification); 116 117 /** 118 * Returns notification requests of IME. 119 */ 120 static IMENotificationRequests GetIMENotificationRequests(); 121 122 /** 123 * Returns native text event dispatcher listener. 124 */ 125 static TextEventDispatcherListener* GetNativeTextEventDispatcherListener(); 126 127 /** 128 * Returns IME open state on the window. 129 */ 130 static bool GetOpenState(nsWindow* aWindow); 131 132 /** 133 * Called when the window is destroying. 134 */ 135 static void OnDestroyWindow(nsWindow* aWindow); 136 137 /** 138 * Called when nsIWidget::SetInputContext() is called before the window's 139 * InputContext is modified actually. 140 */ 141 static void SetInputContext(nsWindow* aWindow, InputContext& aInputContext, 142 const InputContextAction& aAction); 143 144 /** 145 * Associate or disassociate IME context to/from the aWindowBase. 146 */ 147 static void AssociateIMEContext(nsWindow* aWindowBase, bool aEnable); 148 149 /** 150 * Called when the window is created. 151 */ 152 static void InitInputContext(nsWindow* aWindow, InputContext& aInputContext); 153 154 /** 155 * This is called by TSFStaticSink when active IME is changed. 156 */ 157 static void OnKeyboardLayoutChanged(); 158 159 #ifdef DEBUG 160 /** 161 * Returns true when current keyboard layout has IME. Otherwise, false. 162 */ 163 static bool CurrentKeyboardLayoutHasIME(); 164 #endif // #ifdef DEBUG 165 166 /** 167 * Append InputScope values from inputmode string. 168 */ 169 static void AppendInputScopeFromInputmode(const nsAString& aInputmode, 170 nsTArray<InputScope>& aScopes); 171 172 /** 173 * Append InputScope values from type attreibute string of input element 174 */ 175 static void AppendInputScopeFromType(const nsAString& aInputType, 176 nsTArray<InputScope>& aScopes); 177 178 private: 179 static nsWindow* sFocusedWindow; 180 static InputContextAction::Cause sLastContextActionCause; 181 182 static bool sMaybeEditable; 183 static bool sForceDisableCurrentIMM_IME; 184 static bool sNativeCaretIsCreated; 185 static bool sHasNativeCaretBeenRequested; 186 187 /** 188 * MaybeCreateNativeCaret() may create native caret over our caret if 189 * focused content is text editable and we need to create native caret 190 * for other applications. 191 * 192 * @param aWindow The window which owns the native caret. 193 */ 194 static bool MaybeCreateNativeCaret(nsWindow* aWindow); 195 196 static decltype(SetInputScopes)* sSetInputScopes; 197 static void SetInputScopeForIMM32(nsWindow* aWindow, 198 const nsAString& aHTMLInputType, 199 const nsAString& aHTMLInputInputmode, 200 bool aInPrivateBrowsing); 201 static bool sIsInTSFMode; 202 // If sIMMEnabled is false, any IME messages are not handled in TSF mode. 203 // Additionally, IME context is always disassociated from focused window. 204 static bool sIsIMMEnabled; 205 static bool sAssociateIMCOnlyWhenIMM_IMEActive; 206 IsTSFAvailable()207 static bool IsTSFAvailable() { return sIsInTSFMode; } 208 static bool IsIMMActive(); 209 210 static bool IsOnScreenKeyboardSupported(); 211 212 static void MaybeShowOnScreenKeyboard(nsWindow* aWindow, 213 const InputContext& aInputContext); 214 enum class Sync { Yes, No }; 215 static void MaybeDismissOnScreenKeyboard(nsWindow* aWindow, 216 Sync aSync = Sync::No); 217 static bool WStringStartsWithCaseInsensitive(const std::wstring& aHaystack, 218 const std::wstring& aNeedle); 219 static bool NeedOnScreenKeyboard(); 220 static bool IsKeyboardPresentOnSlate(); 221 static bool IsInTabletMode(); 222 static bool AutoInvokeOnScreenKeyboardInDesktopMode(); 223 static bool NeedsToAssociateIMC(); 224 static bool NeedsSearchInputScope(); 225 226 /** 227 * Show the Windows on-screen keyboard. Only allowed for 228 * chrome documents and Windows 8 and higher. 229 */ 230 static void ShowOnScreenKeyboard(nsWindow* aWindow); 231 232 /** 233 * Dismiss the Windows on-screen keyboard. Only allowed for 234 * Windows 8 and higher. 235 */ 236 static void DismissOnScreenKeyboard(nsWindow* aWindow); 237 }; 238 239 } // namespace widget 240 } // namespace mozilla 241 242 #endif // #ifndef WinIMEHandler_h_ 243