| <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <script src="../../resources/accessibility-helper.js"></script> |
| <script src="../../resources/js-test.js"></script> |
| </head> |
| <body> |
| |
| <textarea autofocus id="text" role="textbox">Text😀area with custom cursor handling</textarea> |
| |
| <script> |
| var output = "Tests that we infer intents when JS is used to move the cursor in a text editor; this practice is common in online code editors.\n\n"; |
| |
| const AXTextStateChangeTypeSelectionMove = 2; |
| const AXTextStateChangeTypeSelectionExtend = AXTextStateChangeTypeSelectionMove + 1; |
| |
| const AXTextSelectionDirectionBeginning = 1; |
| const AXTextSelectionDirectionEnd = AXTextSelectionDirectionBeginning + 1; |
| const AXTextSelectionDirectionPrevious = AXTextSelectionDirectionEnd + 1; |
| const AXTextSelectionDirectionNext = AXTextSelectionDirectionPrevious + 1; |
| const AXTextSelectionDirectionDiscontiguous = AXTextSelectionDirectionNext + 1; |
| |
| const AXTextSelectionGranularityCharacter = 1; |
| |
| function notificationCallback(notification, userInfo) { |
| if (notification != "AXSelectedTextChanged") |
| return; |
| |
| let str = ""; |
| let type = userInfo["AXTextStateChangeType"]; |
| if (type == AXTextStateChangeTypeSelectionMove) |
| str += "move"; |
| |
| let dir = userInfo["AXTextSelectionDirection"]; |
| if (dir == AXTextSelectionDirectionNext) |
| str += " next"; |
| else if (dir == AXTextSelectionDirectionPrevious) |
| str += " previous"; |
| else if (dir == AXTextSelectionDirectionDiscontiguous) |
| str += " discontiguous"; |
| |
| let granularity = userInfo["AXTextSelectionGranularity"]; |
| if (granularity == AXTextSelectionGranularityCharacter) |
| str += " character"; |
| |
| str += "\n"; |
| output += str; |
| |
| if (resolveNotificationPromise) |
| resolveNotificationPromise(); |
| } |
| |
| async function moveAndWaitForNotification(offset) { |
| text = document.getElementById("text"); |
| output += "Move to " + offset + "\n"; |
| let promise = new Promise((resolve, reject) => { |
| resolveNotificationPromise = resolve; |
| }); |
| text.setSelectionRange(offset, offset); |
| await promise; |
| resolveNotificationPromise = null; |
| } |
| |
| if (window.accessibilityController) { |
| window.jsTestIsAsync = true; |
| |
| accessibilityController.enableEnhancedAccessibility(true); |
| |
| webArea = accessibilityController.rootElement.childAtIndex(0); |
| var addedNotification = webArea.addNotificationListener(notificationCallback); |
| output += expect("addedNotification", "true"); |
| |
| setTimeout(async function() { |
| await moveAndWaitForNotification(0); |
| await moveAndWaitForNotification(1); |
| await moveAndWaitForNotification(2); |
| await moveAndWaitForNotification(3); |
| await moveAndWaitForNotification(4); |
| |
| await moveAndWaitForNotification(6); // Note single character (emoji) |
| |
| await moveAndWaitForNotification(8); // Discontiguous |
| await moveAndWaitForNotification(9); |
| |
| debug(output); |
| finishJSTest(); |
| }, 0); |
| } |
| </script> |
| </body> |
| </html> |