OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <atlbase.h> | 5 #include <atlbase.h> |
6 #include <atlcom.h> | 6 #include <atlcom.h> |
7 #include <limits.h> | 7 #include <limits.h> |
8 #include <oleacc.h> | 8 #include <oleacc.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
(...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 case ui::AX_ROLE_SWITCH: | 1499 case ui::AX_ROLE_SWITCH: |
1500 return "switch"; | 1500 return "switch"; |
1501 | 1501 |
1502 default: | 1502 default: |
1503 return ""; | 1503 return ""; |
1504 } | 1504 } |
1505 | 1505 |
1506 return ""; | 1506 return ""; |
1507 } | 1507 } |
1508 | 1508 |
| 1509 bool AXPlatformNodeWin::ShouldNodeHaveReadonlyState( |
| 1510 const AXNodeData& data) const { |
| 1511 if (data.GetBoolAttribute(ui::AX_ATTR_ARIA_READONLY)) |
| 1512 return true; |
| 1513 |
| 1514 if (!data.HasState(ui::AX_STATE_READ_ONLY)) |
| 1515 return false; |
| 1516 |
| 1517 switch (data.role) { |
| 1518 case ui::AX_ROLE_ARTICLE: |
| 1519 case ui::AX_ROLE_BUSY_INDICATOR: |
| 1520 case ui::AX_ROLE_DEFINITION: |
| 1521 case ui::AX_ROLE_DESCRIPTION_LIST: |
| 1522 case ui::AX_ROLE_DESCRIPTION_LIST_TERM: |
| 1523 case ui::AX_ROLE_DOCUMENT: |
| 1524 case ui::AX_ROLE_IFRAME: |
| 1525 case ui::AX_ROLE_IMAGE: |
| 1526 case ui::AX_ROLE_IMAGE_MAP: |
| 1527 case ui::AX_ROLE_IMAGE_MAP_LINK: |
| 1528 case ui::AX_ROLE_LIST: |
| 1529 case ui::AX_ROLE_LIST_ITEM: |
| 1530 case ui::AX_ROLE_PROGRESS_INDICATOR: |
| 1531 case ui::AX_ROLE_ROOT_WEB_AREA: |
| 1532 case ui::AX_ROLE_RULER: |
| 1533 case ui::AX_ROLE_SCROLL_AREA: |
| 1534 case ui::AX_ROLE_TERM: |
| 1535 case ui::AX_ROLE_TIMER: |
| 1536 case ui::AX_ROLE_TOOLBAR: |
| 1537 case ui::AX_ROLE_TOOLTIP: |
| 1538 case ui::AX_ROLE_WEB_AREA: |
| 1539 return true; |
| 1540 |
| 1541 case ui::AX_ROLE_GRID: |
| 1542 // TODO(aleventhal) this changed between ARIA 1.0 and 1.1, |
| 1543 // need to determine whether grids/treegrids should really be readonly |
| 1544 // or editable by default |
| 1545 // msaa_state |= STATE_SYSTEM_READONLY; |
| 1546 break; |
| 1547 |
| 1548 case ui::AX_ROLE_TEXT_FIELD: |
| 1549 case ui::AX_ROLE_SEARCH_BOX: |
| 1550 if (data.HasState(ui::AX_STATE_READ_ONLY)) |
| 1551 return true; |
| 1552 |
| 1553 default: |
| 1554 break; |
| 1555 } |
| 1556 return false; |
| 1557 } |
| 1558 |
| 1559 bool AXPlatformNodeWin::ShouldNodeHaveFocusableState( |
| 1560 const AXNodeData& data) const { |
| 1561 switch (data.role) { |
| 1562 case ui::AX_ROLE_DOCUMENT: |
| 1563 case ui::AX_ROLE_ROOT_WEB_AREA: |
| 1564 case ui::AX_ROLE_WEB_AREA: |
| 1565 return true; |
| 1566 |
| 1567 case ui::AX_ROLE_IFRAME: |
| 1568 return false; |
| 1569 |
| 1570 case ui::AX_ROLE_LIST_BOX_OPTION: |
| 1571 case ui::AX_ROLE_MENU_LIST_OPTION: |
| 1572 if (data.HasState(ui::AX_STATE_SELECTABLE)) |
| 1573 return true; |
| 1574 |
| 1575 default: |
| 1576 break; |
| 1577 } |
| 1578 |
| 1579 return data.HasState(ui::AX_STATE_FOCUSABLE); |
| 1580 } |
| 1581 |
1509 int AXPlatformNodeWin::MSAAState() { | 1582 int AXPlatformNodeWin::MSAAState() { |
1510 const AXNodeData& data = GetData(); | 1583 const AXNodeData& data = GetData(); |
1511 const uint32_t state = data.state; | 1584 int msaa_state = 0; |
1512 | 1585 |
1513 int msaa_state = 0; | 1586 // Map the AXState to MSAA state. Note that some of the states are not |
1514 if (state & (1 << ui::AX_STATE_COLLAPSED)) | 1587 // currently handled. |
| 1588 |
| 1589 if (data.HasState(ui::AX_STATE_BUSY)) |
| 1590 msaa_state |= STATE_SYSTEM_BUSY; |
| 1591 |
| 1592 if (data.HasState(ui::AX_STATE_COLLAPSED)) |
1515 msaa_state |= STATE_SYSTEM_COLLAPSED; | 1593 msaa_state |= STATE_SYSTEM_COLLAPSED; |
1516 if (state & (1 << ui::AX_STATE_DEFAULT)) | 1594 |
| 1595 if (data.HasState(ui::AX_STATE_DEFAULT)) |
1517 msaa_state |= STATE_SYSTEM_DEFAULT; | 1596 msaa_state |= STATE_SYSTEM_DEFAULT; |
1518 if (state & (1 << ui::AX_STATE_EXPANDED)) | 1597 |
| 1598 if (data.HasState(ui::AX_STATE_DISABLED)) |
| 1599 msaa_state |= STATE_SYSTEM_UNAVAILABLE; |
| 1600 |
| 1601 // TODO(dougt) unhandled ux::AX_STATE_EDITABLE |
| 1602 |
| 1603 if (data.HasState(ui::AX_STATE_EXPANDED)) |
1519 msaa_state |= STATE_SYSTEM_EXPANDED; | 1604 msaa_state |= STATE_SYSTEM_EXPANDED; |
1520 if (state & (1 << ui::AX_STATE_FOCUSABLE)) | 1605 |
| 1606 if (ShouldNodeHaveFocusableState(data)) |
1521 msaa_state |= STATE_SYSTEM_FOCUSABLE; | 1607 msaa_state |= STATE_SYSTEM_FOCUSABLE; |
1522 if (state & (1 << ui::AX_STATE_HASPOPUP)) | 1608 |
| 1609 if (data.HasState(ui::AX_STATE_HASPOPUP)) |
1523 msaa_state |= STATE_SYSTEM_HASPOPUP; | 1610 msaa_state |= STATE_SYSTEM_HASPOPUP; |
1524 if (state & (1 << ui::AX_STATE_HOVERED)) | 1611 |
1525 msaa_state |= STATE_SYSTEM_HOTTRACKED; | 1612 // TODO(dougt) unhandled ux::AX_STATE_HORIZONTAL |
1526 if (state & (1 << ui::AX_STATE_INVISIBLE) || | 1613 |
| 1614 if (data.HasState(ui::AX_STATE_HOVERED)) { |
| 1615 // Expose whether or not the mouse is over an element, but suppress |
| 1616 // this for tests because it can make the test results flaky depending |
| 1617 // on the position of the mouse. |
| 1618 if (delegate_->ShouldIgnoreHoveredStateForTesting()) |
| 1619 msaa_state |= STATE_SYSTEM_HOTTRACKED; |
| 1620 } |
| 1621 |
| 1622 // TODO(dougt) Why do we set any state on AX_ROLE_IGNORED? |
| 1623 if (data.HasState(ui::AX_STATE_INVISIBLE) || |
1527 GetData().role == ui::AX_ROLE_IGNORED) { | 1624 GetData().role == ui::AX_ROLE_IGNORED) { |
1528 msaa_state |= STATE_SYSTEM_INVISIBLE; | 1625 msaa_state |= STATE_SYSTEM_INVISIBLE; |
1529 } | 1626 } |
1530 if (state & (1 << ui::AX_STATE_LINKED)) | 1627 if (data.HasState(ui::AX_STATE_LINKED)) |
1531 msaa_state |= STATE_SYSTEM_LINKED; | 1628 msaa_state |= STATE_SYSTEM_LINKED; |
1532 if (state & (1 << ui::AX_STATE_OFFSCREEN)) | 1629 |
| 1630 // TODO(dougt) unhandled ux::AX_STATE_MULTILINE |
| 1631 |
| 1632 if (data.HasState(ui::AX_STATE_MULTISELECTABLE)) { |
| 1633 msaa_state |= STATE_SYSTEM_EXTSELECTABLE; |
| 1634 msaa_state |= STATE_SYSTEM_MULTISELECTABLE; |
| 1635 } |
| 1636 |
| 1637 if (data.HasState(ui::AX_STATE_OFFSCREEN)) |
1533 msaa_state |= STATE_SYSTEM_OFFSCREEN; | 1638 msaa_state |= STATE_SYSTEM_OFFSCREEN; |
1534 if (state & (1 << ui::AX_STATE_PROTECTED)) | 1639 |
| 1640 if (data.HasState(ui::AX_STATE_PROTECTED)) |
1535 msaa_state |= STATE_SYSTEM_PROTECTED; | 1641 msaa_state |= STATE_SYSTEM_PROTECTED; |
1536 if (state & (1 << ui::AX_STATE_READ_ONLY)) | 1642 |
| 1643 // READONLY state is complex on windows. We set STATE_SYSTEM_READONLY |
| 1644 // on *some* roles even if the node data isn't marked as AX_STATE_READ_ONLY. |
| 1645 if (ShouldNodeHaveReadonlyState(data)) |
1537 msaa_state |= STATE_SYSTEM_READONLY; | 1646 msaa_state |= STATE_SYSTEM_READONLY; |
1538 if (state & (1 << ui::AX_STATE_SELECTABLE)) | 1647 |
| 1648 // TODO(dougt) unhandled ux::AX_STATE_REQUIRED |
| 1649 // TODO(dougt) unhandled ux::AX_STATE_RICHLY_EDITABLE |
| 1650 |
| 1651 if (data.HasState(ui::AX_STATE_SELECTABLE)) |
1539 msaa_state |= STATE_SYSTEM_SELECTABLE; | 1652 msaa_state |= STATE_SYSTEM_SELECTABLE; |
1540 if (state & (1 << ui::AX_STATE_SELECTED)) | 1653 |
| 1654 if (data.HasState(ui::AX_STATE_SELECTED)) |
1541 msaa_state |= STATE_SYSTEM_SELECTED; | 1655 msaa_state |= STATE_SYSTEM_SELECTED; |
1542 if (state & (1 << ui::AX_STATE_DISABLED)) | |
1543 msaa_state |= STATE_SYSTEM_UNAVAILABLE; | |
1544 | 1656 |
| 1657 // TODO(dougt) unhandled VERTICAL |
| 1658 |
| 1659 if (data.HasState(ui::AX_STATE_VISITED)) |
| 1660 msaa_state |= STATE_SYSTEM_TRAVERSED; |
| 1661 |
| 1662 // |
1545 // Checked state | 1663 // Checked state |
| 1664 // |
1546 const auto checked_state = static_cast<ui::AXCheckedState>( | 1665 const auto checked_state = static_cast<ui::AXCheckedState>( |
1547 GetIntAttribute(ui::AX_ATTR_CHECKED_STATE)); | 1666 GetIntAttribute(ui::AX_ATTR_CHECKED_STATE)); |
1548 switch (checked_state) { | 1667 switch (checked_state) { |
1549 case ui::AX_CHECKED_STATE_TRUE: | 1668 case ui::AX_CHECKED_STATE_TRUE: |
1550 msaa_state |= data.role == ui::AX_ROLE_TOGGLE_BUTTON | 1669 msaa_state |= data.role == ui::AX_ROLE_TOGGLE_BUTTON |
1551 ? STATE_SYSTEM_PRESSED | 1670 ? STATE_SYSTEM_PRESSED |
1552 : STATE_SYSTEM_CHECKED; | 1671 : STATE_SYSTEM_CHECKED; |
1553 break; | 1672 break; |
1554 case ui::AX_CHECKED_STATE_MIXED: | 1673 case ui::AX_CHECKED_STATE_MIXED: |
1555 msaa_state |= STATE_SYSTEM_MIXED; | 1674 msaa_state |= STATE_SYSTEM_MIXED; |
1556 break; | 1675 break; |
1557 default: | 1676 default: |
1558 break; | 1677 break; |
1559 } | 1678 } |
1560 | 1679 |
| 1680 // |
| 1681 // Handle STATE_SYSTEM_FOCUSED |
| 1682 // |
1561 gfx::NativeViewAccessible focus = delegate_->GetFocus(); | 1683 gfx::NativeViewAccessible focus = delegate_->GetFocus(); |
1562 if (focus == GetNativeViewAccessible()) | 1684 if (focus == GetNativeViewAccessible()) |
1563 msaa_state |= STATE_SYSTEM_FOCUSED; | 1685 msaa_state |= STATE_SYSTEM_FOCUSED; |
1564 | 1686 |
1565 // On Windows, the "focus" bit should be set on certain containers, like | 1687 // On Windows, the "focus" bit should be set on certain containers, like |
1566 // menu bars, when visible. | 1688 // menu bars, when visible. |
1567 // | 1689 // |
1568 // TODO(dmazzoni): this should probably check if focus is actually inside | 1690 // TODO(dmazzoni): this should probably check if focus is actually inside |
1569 // the menu bar, but we don't currently track focus inside menu pop-ups, | 1691 // the menu bar, but we don't currently track focus inside menu pop-ups, |
1570 // and Chrome only has one menu visible at a time so this works for now. | 1692 // and Chrome only has one menu visible at a time so this works for now. |
1571 if (data.role == ui::AX_ROLE_MENU_BAR && | 1693 if (data.role == ui::AX_ROLE_MENU_BAR && |
1572 !(state & (1 << ui::AX_STATE_INVISIBLE))) { | 1694 !(data.HasState(ui::AX_STATE_INVISIBLE))) { |
1573 msaa_state |= STATE_SYSTEM_FOCUSED; | 1695 msaa_state |= STATE_SYSTEM_FOCUSED; |
1574 } | 1696 } |
1575 | 1697 |
| 1698 // Handle STATE_SYSTEM_LINKED |
| 1699 if (GetData().role == ui::AX_ROLE_IMAGE_MAP_LINK || |
| 1700 GetData().role == ui::AX_ROLE_LINK) { |
| 1701 msaa_state |= STATE_SYSTEM_LINKED; |
| 1702 } |
| 1703 |
1576 return msaa_state; | 1704 return msaa_state; |
1577 } | 1705 } |
1578 | 1706 |
1579 int AXPlatformNodeWin::MSAAEvent(ui::AXEvent event) { | 1707 int AXPlatformNodeWin::MSAAEvent(ui::AXEvent event) { |
1580 switch (event) { | 1708 switch (event) { |
1581 case ui::AX_EVENT_ALERT: | 1709 case ui::AX_EVENT_ALERT: |
1582 return EVENT_SYSTEM_ALERT; | 1710 return EVENT_SYSTEM_ALERT; |
1583 case ui::AX_EVENT_FOCUS: | 1711 case ui::AX_EVENT_FOCUS: |
1584 return EVENT_OBJECT_FOCUS; | 1712 return EVENT_OBJECT_FOCUS; |
1585 case ui::AX_EVENT_MENU_START: | 1713 case ui::AX_EVENT_MENU_START: |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1699 | 1827 |
1700 AXPlatformNodeBase* base = | 1828 AXPlatformNodeBase* base = |
1701 FromNativeViewAccessible(node->GetNativeViewAccessible()); | 1829 FromNativeViewAccessible(node->GetNativeViewAccessible()); |
1702 if (base && !IsDescendant(base)) | 1830 if (base && !IsDescendant(base)) |
1703 base = nullptr; | 1831 base = nullptr; |
1704 | 1832 |
1705 return static_cast<AXPlatformNodeWin*>(base); | 1833 return static_cast<AXPlatformNodeWin*>(base); |
1706 } | 1834 } |
1707 | 1835 |
1708 } // namespace ui | 1836 } // namespace ui |
OLD | NEW |