1/* -*- Mode: IDL; 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#include "nsISupports.idl" 7 8interface mozIDOMWindow; 9interface nsITextInputProcessorCallback; 10 11webidl Event; 12 13/** 14 * An nsITextInputProcessor instance is associated with a top level widget which 15 * handles native IME. It's associated by calling beginInputTransaction() or 16 * beginInputTransactionForTests(). While an instance has composition, nobody 17 * can steal the rights to make composition on the top level widget. In other 18 * words, if another instance is composing on a top level widget, either 19 * beginInputTransaction() or beginInputTransactionForTests() returns false 20 * (i.e., not throws an exception). 21 * 22 * NOTE: See nsITextInputProcessorCallback.idl for examples of |callback| in 23 * following examples, 24 * 25 * Example #1 JS-IME can start composition like this: 26 * 27 * var TIP = Components.classes["@mozilla.org/text-input-processor;1"]. 28 * createInstance(Components.interfaces.nsITextInputProcessor); 29 * if (!TIP.beginInputTransaction(window, callback)) { 30 * return; // You failed to get the rights to make composition 31 * } 32 * // Create a keyboard event if the following compositionc change is caused 33 * // by a key event. 34 * var keyEvent = 35 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 36 * // Set new composition string first 37 * TIP.setPendingCompositionString("some-words-are-inputted"); 38 * // Set clause information. 39 * TIP.appendClauseToPendingComposition(23, TIP.ATTR_RAW_CLAUSE); 40 * // Set caret position, this is optional. 41 * TIP.setCaretInPendingComposition(23); 42 * // Flush the pending composition 43 * if (!TIP.flushPendingComposition(keyEvent)) { 44 * // If it returns false, it fails to start composition. 45 * return; 46 * } 47 * 48 * Example #2 JS-IME can separate composition string to two or more clauses: 49 * 50 * // Create a keyboard event if the following compositionc change is caused 51 * // by a key event. 52 * var keyEvent = 53 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 54 * // First, set composition string again 55 * TIP.setPendingCompositionString("some-words-are-inputted"); 56 * // Then, if "are" is selected to convert, there are 3 clauses: 57 * TIP.appendClauseToPendingComposition(11, TIP.ATTR_CONVERTED_CLAUSE); 58 * TIP.appendClauseToPendingComposition(3, TIP.ATTR_SELECTED_CLAUSE); 59 * TIP.appendClauseToPendingComposition(9, TIP.ATTR_CONVERTED_CLAUSE); 60 * // Show caret at the beginning of the selected clause 61 * TIP.setCaretInPendingComposition(11); 62 * // Flush the pending composition. Note that if there is a composition, 63 * // flushPendingComposition() won't return false. 64 * TIP.flushPendingComposition(keyEvent); 65 * 66 * Example #3 JS-IME can commit composition with specific string with this: 67 * 68 * // Create a keyboard event if the following compositionc change is caused 69 * // by a key event. 70 * var keyEvent1 = 71 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 72 * // First, there is a composition. 73 * TIP.setPendingCompositionString("some-words-directly-inputted"); 74 * TIP.appendClauseToPendingComposition(28, TIP.ATTR_RAW_CLAUSE); 75 * TIP.flushPendingComposition(keyEvent1); 76 * // Create a keyboard event if the following commit composition is caused 77 * // by a key event. 78 * var keyEvent2 = 79 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 80 * // This is useful when user selects a commit string from candidate list UI 81 * // which is provided by JS-IME. 82 * TIP.commitCompositionWith("selected-words-from-candidate-list", keyEvent2); 83 * 84 * Example #4 JS-IME can commit composition with the last composition string 85 * without specifying commit string: 86 * 87 * // Create a keyboard event if the following compositionc change is caused 88 * // by a key event. 89 * var keyEvent1 = 90 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 91 * // First, there is a composition. 92 * TIP.setPendingCompositionString("some-words-will-be-commited"); 93 * TIP.appendClauseToPendingComposition(27, TIP.ATTR_RAW_CLAUSE); 94 * TIP.flushPendingComposition(keyEvent1); 95 * // Create a keyboard event if the following commit is caused by a key 96 * // event. 97 * var keyEvent2 = 98 * new KeyboardEvent("", { key: "Enter", code: "Enter", 99 keyCode: KeyboardEvent.DOM_VK_RETURN }); 100 * // This is useful when user just type Enter key. 101 * TIP.commitComposition(keyEvent2); 102 * 103 * Example #5 JS-IME can cancel composition with this: 104 * 105 * // Create a keyboard event if the following composition change is caused 106 * // by a key event. 107 * var keyEvent1 = 108 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 109 * // First, there is a composition. 110 * TIP.setPendingCompositionString("some-words-will-be-canceled"); 111 * TIP.appendClauseToPendingComposition(27, TIP.ATTR_RAW_CLAUSE); 112 * TIP.flushPendingComposition(keyEvent1); 113 * // Create a keyboard event if the following canceling composition is 114 * // caused by a key event. 115 * var keyEvent2 = 116 * new KeyboardEvent("", { key: "Escape", code: "Escape", 117 keyCode: KeyboardEvent.DOM_VK_ESCAPE }); 118 * // This is useful when user doesn't want to commit the composition. 119 * // FYI: This is same as TIP.commitCompositionWith("") for now. 120 * TIP.cancelComposition(keyEvent2); 121 * 122 * Example #6 JS-IME can insert text only with commitCompositionWith(): 123 * 124 * // Create a keyboard event if the following inserting text is caused by a 125 * // key event. 126 * var keyEvent1 = 127 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 128 * if (!TIP.beginInputTransaction(window, callback)) { 129 * return; // You failed to get the rights to make composition 130 * } 131 * TIP.commitCompositionWith("Some words", keyEvent1); 132 * 133 * Example #7 JS-IME can start composition explicitly: 134 * 135 * if (!TIP.beginInputTransaction(window, callback)) { 136 * return; // You failed to get the rights to make composition 137 * } 138 * // Create a keyboard event if the following starting composition is caused 139 * // by a key event. 140 * var keyEvent1 = 141 * new KeyboardEvent("", { key: "foo", code: "bar", keyCode: buzz }); 142 * // If JS-IME don't want to show composing string in the focused editor, 143 * // JS-IME can dispatch only compositionstart event with this. 144 * if (!TIP.startComposition(keyEvent1)) { 145 * // Failed to start composition. 146 * return; 147 * } 148 * // And when user selects a result from UI of JS-IME, commit with it. 149 * // Then, the key event should be null. 150 * TIP.commitCompositionWith("selected-words"); 151 * 152 * Example #8 JS-IME or JS-Keyboard should dispatch key events even during 153 * composition (non-printable key case): 154 * 155 * if (!TIP.beginInputTransaction(window, callback)) { 156 * return; // You failed to get the rights to dispatch key events 157 * } 158 * 159 * // You don't need to specify .keyCode value if it's non-printable key 160 * // because it can be computed from .key value. 161 * // If you specify non-zero value to .keyCode, it'll be used. 162 * var keyEvent = new KeyboardEvent("", { code: "Enter", key: "Enter" }); 163 * if (TIP.keydown(keyEvent)) { 164 * // Handle its default action 165 * } 166 * 167 * // Even if keydown event was consumed, keyup event should be dispatched. 168 * if (TIP.keyup(keyEvent)) { 169 * // Handle its default action 170 * } 171 * 172 * Example #9 JS-IME or JS-Keyboard should dispatch key events even during 173 * composition (printable key case): 174 * 175 * if (!TIP.beginInputTransaction(window, callback)) { 176 * return; // You failed to get the rights to dispatch key events 177 * } 178 * 179 * // You need to specify .keyCode value if it's printable key. 180 * // The rules of .keyCode value is documented in MDN: 181 * // https://developer.mozilla.org/docs/Web/API/KeyboardEvent.keyCode 182 * // 183 * // #1 If the key location is DOM_KEY_LOCATION_NUMPAD and NumLock is 184 * // active, you should specify DOM_VK_NUMPAD[0-9], DOM_VK_MULTIPLY, 185 * // DOM_VK_ADD, DOM_VK_SEPARATOR, DOM_VK_SUBTRACT, DOM_VK_DECIMAL or 186 * // DOM_VK_DIVIDE. 187 * // #2 If the key is Spacebar, use DOM_VK_SPACE. 188 * // 189 * // Following rules are printable keys in DOM_KEY_LOCATION_STANDARD. 190 * // .keyCode value for a key shouldn't be changed by modifier states: 191 * // #1 If the key can input [0-9] with any modifier state (except 192 * // NumLock state), the value should be DOM_VK_[0-9]. 193 * // #2 Otherwise, and if the key inputs an ASCII alphabet with no 194 * // active modifiers, use DOM_VK_[A-Z]. 195 * // #3 Otherwise, and if the key inputs an ASCII alphabet with no 196 * // active modifiers except Shift key state, use DOM_VK_[A-Z] for 197 * // the shifted character. E.g., if a key causes non-alphabet 198 * // character such as "@" or a Unicode character without Shift key 199 * // but "a" is inputted when Shift key is pressed, the proper 200 * // keyCode is DOM_VK_A. 201 * // #4 Otherwise, and if the key inputs another ASCII character with 202 * // no modifier states, use a proper value for the character. E.g., 203 * // if the key inputs "*" without Shift key state, it should be 204 * // DOM_VK_ASTERISK. 205 * // #5 Otherwise, and if the key inputs another ASCII character with 206 * // Shift key state, use a proper value for the character. E.g., 207 * // if a key causes a Unicode character without Shift key but "&" 208 * // is inputted when Shift key is pressed, the proper keyCode is 209 * // DOM_VK_AMPERSAND. 210 * // See above document for the other cases. 211 * // 212 * // NOTE: If the software keyboard is 10-key like simple phone, 213 * // We don't have common rules to decide its .keyCode value. 214 * // Above rules should be used when the JS-Keyboard emulates PC 215 * // keyboard. 216 * // .key value should be inputting character by the key with current 217 * // modifier state. 218 * // .code value should be empty string if the JS-Keyboard isn't emulating 219 * // physical keyboard. Otherwise, use same value with physical keyboard's 220 * // same key. 221 * var keyEvent = new KeyboardEvent("", { code: "KeyA", key: "a", 222 * keyCode: KeyboardEvent.DOM_VK_A }); 223 * if (TIP.keydown(keyEvent)) { 224 * // Handle its default action 225 * } 226 * 227 * // Even if keydown event was consumed, keyup event should be dispatched. 228 * if (TIP.keyup(keyEvent)) { 229 * // Handle its default action 230 * } 231 * 232 * Example #10 JS-Keyboard doesn't need to initialize modifier states at 233 * calling either keydown() or keyup(). 234 * 235 * // Neither beginInputTransaction() nor beginInputTransactionForTests() 236 * // resets modifier state. 237 * if (!TIP.beginInputTransaction(window, callback)) { 238 * return; // You failed to get the rights to dispatch key events 239 * } 240 * 241 * var leftShift = new KeyboardEvent("", { code: "ShiftLeft", key: "Shift" }); 242 * 243 * // This causes following key events will be shifted automatically. 244 * TIP.keydown(leftShift); 245 * 246 * var rightShift = 247 * new KeyboardEvent("", { code: "ShiftRight", key: "Shift" }); 248 * 249 * TIP.keydown(rightShift); 250 * 251 * // keyup of one of shift key doesn't cause inactivating "Shift" state. 252 * TIP.keyup(rightShift); 253 * 254 * // This causes inactivating "Shift" state completely. 255 * TIP.keyup(leftShift); 256 */ 257 258[scriptable, builtinclass, uuid(47ae2181-2e98-4d58-84a2-b8db6764ce9a)] 259interface nsITextInputProcessor : nsISupports 260{ 261 /** 262 * Returns true if this instance was dispatched compositionstart but hasn't 263 * dispatched compositionend yet. 264 */ 265 readonly attribute boolean hasComposition; 266 267 /** 268 * When you create an instance, you must call beginInputTransaction() first 269 * except when you created the instance for automated tests. 270 * 271 * @param aWindow A DOM window. The instance will look for a top 272 * level widget from this. 273 * @param aCallback Callback interface which handles requests to 274 * IME and notifications to IME. This must not be 275 * null. 276 * @return If somebody uses internal text input service for a 277 * composition, this returns false. Otherwise, returns 278 * true. I.e., only your TIP can create composition 279 * when this returns true. If this returns false, 280 * your TIP should wait next chance. 281 */ 282 boolean beginInputTransaction(in mozIDOMWindow aWindow, 283 in nsITextInputProcessorCallback aCallback); 284 285 /** 286 * When you create an instance for automated test, you must call 287 * beginInputTransaction(), first. See beginInputTransaction() for more 288 * detail of this. 289 * Note that aCallback can be null. If it's null, nsITextInputProcessor 290 * implementation will handle them automatically. 291 */ 292 [optional_argc] boolean 293 beginInputTransactionForTests( 294 in mozIDOMWindow aWindow, 295 [optional] in nsITextInputProcessorCallback aCallback); 296 297 /** 298 * startComposition() dispatches compositionstart event explicitly. 299 * IME does NOT need to call this typically since compositionstart event 300 * is automatically dispatched by sendPendingComposition() if 301 * compositionstart event hasn't been dispatched yet. If this is called 302 * when compositionstart has already been dispatched, this throws an 303 * exception. 304 * 305 * @param aKeyboardEvent Key event which causes starting composition. 306 * If its type value is "keydown", this method 307 * dispatches only keydown event first. Otherwise, 308 * dispatches keydown first and keyup at last. 309 * key value and keyCode values of keydown event 310 * are set to "Process" and DOM_VK_PROCESSKEY 311 * automatically. You can prevent this behavior 312 * with KEY_DONT_MARK_KEYDOWN_AS_PROCESSED. 313 * @param aKeyFlags See KEY_* constants. 314 * @return Returns true if composition starts normally. 315 * Otherwise, returns false because it might be 316 * canceled by the web application. 317 */ 318 [can_run_script, optional_argc] 319 boolean startComposition([optional] in Event aKeyboardEvent, 320 [optional] in unsigned long aKeyFlags); 321 322 /** 323 * Set new composition string. Pending composition will be flushed by 324 * a call of flushPendingComposition(). However, if the new composition 325 * string isn't empty, you need to call appendClauseToPendingComposition() to 326 * fill all characters of aString with one or more clauses before flushing. 327 * Note that if you need to commit or cancel composition, use 328 * commitComposition(), commitCompositionWith() or cancelComposition(). 329 */ 330 void setPendingCompositionString(in AString aString); 331 332 // ATTR_RAW_CLAUSE means that the clause hasn't been selected nor converted 333 // yet. 334 const unsigned long ATTR_RAW_CLAUSE = 0x02; 335 // ATTR_SELECTED_RAW_CLAUSE means that the clause hasn't been converted yet 336 // but is selected for converting to the other string. 337 const unsigned long ATTR_SELECTED_RAW_CLAUSE = 0x03; 338 // ATTR_CONVERTED_CLAUSE means that the clause has already been converted but 339 // is not selected. This does NOT mean that this clause isn't modifiable. 340 const unsigned long ATTR_CONVERTED_CLAUSE = 0x04; 341 // ATTR_SELECTED_CLAUSE means that the clause has already been converted and 342 // is selected. In other words, the clause is being converted. 343 const unsigned long ATTR_SELECTED_CLAUSE = 0x05; 344 345 /** 346 * Append a clause to the pending composition. 347 * 348 * If you need to fill the pending composition string with a clause, you 349 * should call this once. For example: 350 * appendClauseToPendingComposition(compositionString.length, 351 * ATTR_RAW_CLAUSE); 352 * is enough. If you need to separate the pending composition string to 353 * multiple clauses, you need to call this multiple times. For example, 354 * if your pending composition string has three clauses and the second clause 355 * is being converted: 356 * appendClauseToPendingComposition(firstClauseLength, 357 * ATTR_CONVERTED_CLAUSE); 358 * appendClauseToPendingComposition(secondClauseLength, 359 * ATTR_SELECTED_CLAUSE); 360 * appendClauseToPendingComposition(thirdClauseLength, 361 * ATTR_CONVERTED_CLAUSE); 362 * Note that if sum of aLength mismatches length of the pending composition 363 * string, flushPendingComposition() will throw an exception. I.e., 364 * |firstClauseLength + secondClauseLength + thirdClauseLength| must be 365 * same as the length of pending composition string. 366 * 367 * TODO: Should be able to specify custom clause style. 368 * 369 * @param aLength Length of the clause. 370 * @param aAttribute One of ATTR_* constants. 371 */ 372 void appendClauseToPendingComposition(in unsigned long aLength, 373 in unsigned long aAttribute); 374 375 /** 376 * Set caret offset in the pending composition string. If you don't need to 377 * show a caret, you don't need to call this. 378 * 379 * @param aOffset Caret offset in the pending composition string. 380 * This must be between 0 and length of the pending 381 * composition string. 382 */ 383 void setCaretInPendingComposition(in unsigned long aOffset); 384 385 /** 386 * flushPendingComposition() must be called after 387 * setPendingCompositionString() and appendClauseToPendingComposition() 388 * (setCaretInPendingComposition() is optional) are called. 389 * 390 * Note that compositionstart will be automatically dispatched if this is 391 * called when there is no composition. 392 * 393 * Note that if sum of lengths of appended clauses are not same as composition 394 * string or caret offset is larger than the composition string length, this 395 * throws an exception. 396 * 397 * @param aKeyboardEvent Key event which causes the composition string. 398 * If its type value is "keydown", this method 399 * dispatches only keydown event first. Otherwise, 400 * dispatches keydown first and keyup at last. 401 * key value and keyCode values of keydown event 402 * are set to "Process" and DOM_VK_PROCESSKEY 403 * automatically. You can prevent this behavior 404 * with KEY_DONT_MARK_KEYDOWN_AS_PROCESSED. 405 * @param aKeyFlags See KEY_* constants. 406 * @return Returns true if there is a composition already or 407 * starting composition automatically. 408 * Otherwise, i.e., if it cannot start composition 409 * automatically, e.g., canceled by web apps, returns 410 * false. 411 */ 412 [can_run_script, optional_argc] 413 boolean flushPendingComposition( 414 [optional] in Event aKeyboardEvent, 415 [optional] in unsigned long aKeyFlags); 416 417 /** 418 * commitComposition() will commit composition with the last composition 419 * string. If there is no composition, this will throw an exception. 420 * 421 * @param aKeyboardEvent Key event which causes the commit composition. 422 * If its type value is "keydown", this method 423 * dispatches only keydown event first. Otherwise, 424 * dispatches keydown first and keyup at last. 425 * key value and keyCode values of keydown event 426 * are set to "Process" and DOM_VK_PROCESSKEY 427 * automatically. You can prevent this behavior 428 * with KEY_DONT_MARK_KEYDOWN_AS_PROCESSED. 429 * @param aKeyFlags See KEY_* constants. 430 */ 431 [can_run_script, optional_argc] 432 void commitComposition([optional] in Event aKeyboardEvent, 433 [optional] in unsigned long aKeyFlags); 434 435 /** 436 * commitCompositionWith() will commit composition with the specific string. 437 * If there is no composition, this will start composition and commit it 438 * with the specified string. 439 * 440 * @param aCommitString The string to be committed. 441 * @param aKeyboardEvent Key event which causes the commit composition. 442 * If its type value is "keydown", this method 443 * dispatches only keydown event first. Otherwise, 444 * dispatches keydown first and keyup at last. 445 * key value and keyCode values of keydown event 446 * are set to "Process" and DOM_VK_PROCESSKEY 447 * automatically. You can prevent this behavior 448 * with KEY_DONT_MARK_KEYDOWN_AS_PROCESSED. 449 * @param aKeyFlags See KEY_* constants. 450 * @return Returns true if there is a composition already or 451 * starting composition automatically. 452 * Otherwise, i.e., if it cannot start composition 453 * automatically, e.g., canceled by web apps, returns 454 * false. 455 */ 456 [can_run_script, optional_argc] 457 boolean commitCompositionWith(in AString aCommitString, 458 [optional] in Event aKeyboardEvent, 459 [optional] in unsigned long aKeyFlags); 460 461 /** 462 * cancelComposition() will cancel composition. This is for now the same as 463 * calling commitComposition(""). However, in the future, this might work 464 * better. If your IME needs to cancel composition, use this instead of 465 * commitComposition(). 466 * 467 * Note that if you tries to cancel composition when there is no composition, 468 * this throws an exception. 469 * 470 * @param aKeyboardEvent Key event which causes the canceling composition. 471 * If its type value is "keydown", this method 472 * dispatches only keydown event first. Otherwise, 473 * dispatches keydown first and keyup at last. 474 * key value and keyCode values of keydown event 475 * are set to "Process" and DOM_VK_PROCESSKEY 476 * automatically. You can prevent this behavior 477 * with KEY_DONT_MARK_KEYDOWN_AS_PROCESSED. 478 * @param aKeyFlags See KEY_* constants. 479 */ 480 [can_run_script, optional_argc] 481 void cancelComposition([optional] in Event aKeyboardEvent, 482 [optional] in unsigned long aKeyFlags); 483 484 // Specifying KEY_DEFAULT_PREVENTED can dispatch key events whose 485 // defaultPrevented are true. Note that if this is specified, keypress event 486 // won't be fired. 487 const unsigned long KEY_DEFAULT_PREVENTED = 0x00000001; 488 // If KEY_NON_PRINTABLE_KEY is specified and the .key value isn't valid 489 // key name, the methods will throws an exception. In other words, this 490 // flag prevents to dispatch key events with wrong key values and to cause 491 // such key events input the key values as text. 492 const unsigned long KEY_NON_PRINTABLE_KEY = 0x00000002; 493 // If KEY_FORCE_PRINTABLE_KEY is specified and even if the .key value is a 494 // registered key name, it's treated as inputting text value. 495 const unsigned long KEY_FORCE_PRINTABLE_KEY = 0x00000004; 496 // If KEY_KEEP_KEY_LOCATION_STANDARD is specified when its .location is not 497 // initialized or initialized with 0, the value isn't computed with .code 498 // value. Note that if .location is initialized with non-zero value, 499 // this flag causes throwing an exception. 500 // NOTE: This is not recommended to use except for tests. 501 const unsigned long KEY_KEEP_KEY_LOCATION_STANDARD = 0x00000008; 502 // If KEY_KEEP_KEYCODE_ZERO is specified when its .keyCode is not initialized 503 // or initialized with 0, the value isn't computed with .key value when it 504 // represents non-printable key. Note that if .keyCode is initialized with 505 // non-zero value, this flag causes throwing an exception. 506 const unsigned long KEY_KEEP_KEYCODE_ZERO = 0x00000010; 507 // If KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT is specified when the key event is 508 // a modifier key's, keydown() and keyup() only modifies its modifier state 509 // without dispatching key events. This is useful for testing odd behavior 510 // or emulating legacy API behavior. 511 const unsigned long KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT = 0x00000020; 512 // If KEY_DONT_MARK_KEYDOWN_AS_PROCESSED is specified, key value and keyCode 513 // value of keydown event are not changed to "Process" and DOM_VK_PROCESSKEY. 514 const unsigned long KEY_DONT_MARK_KEYDOWN_AS_PROCESSED = 0x00000040; 515 // If KEY_MARK_KEYUP_AS_PROCESSED is specified, key value and keyCode value 516 // of keyup event are changed to "Process" and DOM_VK_PROCESSKEY. 517 const unsigned long KEY_MARK_KEYUP_AS_PROCESSED = 0x00000080; 518 519 // These values can be used to do bitwise operation with the return value of 520 // the keydown() method. 521 const unsigned long KEYEVENT_NOT_CONSUMED = 0x00000000; 522 const unsigned long KEYDOWN_IS_CONSUMED = 0x00000001; 523 const unsigned long KEYPRESS_IS_CONSUMED = 0x00000002; 524 525 /** 526 * keydown() may dispatch a keydown event and some keypress events if 527 * preceding keydown event isn't consumed and they are necessary. 528 * Note that even if this is called during composition, key events may not 529 * be dispatched. In this case, this returns false. 530 * 531 * You should initialize at least .key value and .code value of the event. 532 * Additionally, if you try to emulate a printable key, .keyCode value should 533 * be specified if there is proper key value. See the comment of above 534 * example how to decide .keyCode value of a printable key. On the other 535 * hand, .keyCode value is automatically computed when you try to emulate 536 * non-printable key. However, if you try to emulate physical keyboard of 537 * desktop platform, you need to specify proper value explicitly because 538 * the mapping table of this API isn't enough to emulate the behavior of 539 * Gecko for desktop platforms. 540 * 541 * NOTE: Even if this has composition, JS-Keyboard should call keydown() and 542 * keyup(). Although, with the default preferences and normal 543 * conditions, DOM key events won't be fired during composition. 544 * However, they MAY be dispatched for some reasons, e.g., the web 545 * content listens only key events, or if the standard DOM event spec 546 * will be changed in the future. 547 * 548 * @param aKeyboardEvent Must be a keyboard event which should be dispatched 549 * as a keydown event and keypress events. 550 * #1 Note that you don't need to set charCode value 551 * because it's computed from its key value. 552 * #2 If code value is set properly and location value 553 * isn't specified (i.e., 0), the location value will 554 * be guessed from the code value. 555 * #3 Non-defined code names are not allowed. If your 556 * key isn't registered, file a bug. If your key isn't 557 * defined by any standards, use "" (empty string). 558 * #4 .keyCode is guessed from .key value if the key 559 * name is registered and .keyCode isn't initialized. 560 * #5 modifier key states, e.g., .shiftKey, are 561 * ignored. Instead, modifier states are managed by 562 * each instance and set automatically. 563 * @param aKeyFlags Special flags. The values can be some of KEY_* 564 * constants. 565 * @return KEYEVENT_NOT_CONSUMED, if the keydown event nor 566 * the following keypress event(s) are consumed. 567 * KEYDOWN_IS_CONSUMED, if the keydown event is 568 * consumed. No keypress event will be dispatched in 569 * this case. 570 * KEYPRESS_IS_CONSUMED, if the keypress event(s) is 571 * consumed when dispatched. 572 * Note that keypress event is always consumed by 573 * native code for the printable keys (indicating the 574 * default action has been taken). 575 */ 576 [can_run_script, optional_argc] 577 unsigned long keydown(in Event aKeyboardEvent, 578 [optional] in unsigned long aKeyFlags); 579 580 /** 581 * Similar to keydown(), but this dispatches only a keyup event. 582 */ 583 [optional_argc] 584 boolean keyup(in Event aKeyboardEvent, 585 [optional] in unsigned long aKeyFlags); 586 587 /** 588 * getModifierState() returns modifier state managed by this instance. 589 * 590 * @param aModifier One of modifier key names. This doesn't support 591 * virtual modifiers like "Accel". 592 * @return true if the modifier key is active. Otherwise, 593 * false. 594 */ 595 boolean getModifierState(in AString aModifierKey); 596 597 /** 598 * shareModifierStateOf() makes the instance shares modifier state of 599 * another instance. When this is called, the instance refers the modifier 600 * state of another instance. After that, changes to either this and the 601 * other instance's modifier state is synchronized. 602 * 603 * @param aOther Another instance which will be referred by the 604 * instance. If this is null, the instance restarts 605 * to manage modifier state independently. 606 */ 607 void shareModifierStateOf(in nsITextInputProcessor aOther); 608 609 /** 610 * Helper method to get usual |.code| value of non-printable keys. 611 * 612 * @param aKeyValue A predefined key value such as "Enter". 613 * If this is not a proper non-printable key value 614 * or a proper key value but not in usual keyboard of 615 * the platform, this returns empty string. 616 * @param aLocation The |.location| value. This is important if 617 * the key may be in different location. 618 * E.g., Left vs. Right or Standard vs. Numpad. 619 * If this is undefined or null, it'll be treated 620 * as Standard or Left. 621 * @return One of a code value of well-known key on usual 622 * keyboard on the platform, or empty string. 623 */ 624 [optional_argc] 625 AString computeCodeValueOfNonPrintableKey( 626 in AString aKeyValue, 627 [optional] in jsval aLocation); 628 629 /** 630 * Helper method to guess |.code| value of a printable key which is in usual 631 * keyboard of the platform and when active keyboard layout is US-English. 632 * Note that this is not aware of option key mapping on macOS. 633 * 634 * @param aKeyValue The key value. Must be a character which can 635 * be inputted with US-English keyboard layout. 636 * @param aLocation The location of the key. This is important 637 * to distinguish whether the key is in Standard 638 * or Numpad. If this is undefined or null, will 639 * be treated as Standard. 640 * @return Returns empty string if there is no proper key. 641 */ 642 [optional_argc] 643 AString guessCodeValueOfPrintableKeyInUSEnglishKeyboardLayout( 644 in AString aKeyValue, 645 [optional] in jsval aLocation); 646 647 /** 648 * Helper method to guess |.keyCode| value of a printable key which is in 649 * usual keyboard of the platform and when active keyboard layout is 650 * US-English. 651 * Note that this is not aware of option key mapping on macOS. 652 * 653 * @param aKeyValue The key value. Must be a character which can 654 * be inputted with US-English keyboard layout. 655 * @param aLocation The location of the key. This is important 656 * to distinguish whether the key is in Standard 657 * our Numpad. If this is undefined or null, 658 * will be treated as Standard. 659 * @return Returns 0 if there is no proper key to input 660 * aKeyValue with US-English keyboard layout. 661 */ 662 [optional_argc] 663 unsigned long guessKeyCodeValueOfPrintableKeyInUSEnglishKeyboardLayout( 664 in AString aKeyValue, 665 [optional] in jsval aLocation); 666}; 667 668%{C++ 669#define TEXT_INPUT_PROCESSOR_CID \ 670 { 0xcaaab47f, 0x1e31, 0x478e, \ 671 { 0x89, 0x19, 0x97, 0x09, 0x04, 0xe9, 0xcb, 0x72 } } 672#define TEXT_INPUT_PROCESSOR_CONTRACTID \ 673 "@mozilla.org/text-input-processor;1" 674%} 675