vcl/qt5/QtAccessibleWidget.cxx |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

New commits:
commit dd58b893f0734916919b14dcfc9941bb9dc3575b
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Oct 1 15:24:25 2024 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Tue Oct 1 19:54:39 2024 +0200

    tdf#160837 qt a11y: Don't report window role for non-top-level
    
    Quoting from offapi/com/sun/star/accessibility/AccessibleRole.idl,
    AccessibleRole::Frame is for:
    
    > A top level window with a title bar, border, menu bar, etc.
    > It is often used as the primary window for an application.
    
    However, the FRAME role also gets used for frames that
    are not actually top-levels at least with the Qt-based
    VCL plugins, where there is an object of role FRAME as a
    child of the actual top-level for e.g. the Writer main
    window. (The actual top-level is a QtMainWindow.)
    That frame contains the window content starting right
    below the (native) menu bar.
    
    Mapping the AccessibleRole::FRAME a11y role to
    the Qt equivalent QAccessible::Window would result
    in window-relative positions reported via AT-SPI
    to be relative to that frame, instead of the actual
    top-level, s. the implementation in qtbase's
    AtSpiAdaptor::translateFromScreenCoordinates [1]
    which calculates the relative position to the
    first top-level in its a11y hierarchy.
    
    This resulted in Accerciser's highlighting of the
    currently selected object to be too far up, as the
    "window-relative position" was missing the menu
    bar height in the y coordinate when window-relative
    positions are used, which is the case on Wayland,
    s.a. the commit message of
    
        commit a499874d9c0685d79b629b4bb246394b6b15691a
        Author: Michael Weghorn <m.wegh...@posteo.de>
        Date:   Thu Sep 26 18:22:12 2024 +0200
    
            tdf#160837 qt: Rely on toolkit for frame positions, drop menubar 
hack
    
    for more background.
    
    To fix this, prevent reporting an invalid top-level
    window role for frames that are not actually top-levels:
    When mapping AccessibleRole::FRAME to a corresponding
    Qt a11y role, take into account whether the
    frame still has another (real) top-level window as a parent.
    
    This makes the highlighted area in Accerciser become correct
    when using LO with the qt6 VCL plugin and Accerciser with
    ACCERCISER_WINDOW_MANAGER=kwin in a KDE Plasma Wayland session.
    
    The same would generally make sense for
    AccessibleRole::DIALOG. However, there that
    would currently result in the additional
    semantics of this being a dialog (not
    another kind of top-level window) getting lost
    when doing so. As dialogs usually don't have a separate
    menu bar, at least the incorrect reporting of window-relative positions
    is less relevant.
    
    Leave dialog unchanged for now, maybe reconsider later
    as needed.
    
    Ultimately, using native Qt widgets for dialogs (see tdf#130857)
    should presumably fix the underlying problem of the extra frame
    on VCL side being used altogether.
    
    [1] 
https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/accessible/linux/atspiadaptor.cpp?id=da4a6cf78ff42a4f69c2775997ff174ef647f3f3#n2401
    
    Change-Id: I5ae066bd996f042b370b067a30213d3a1045480e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174350
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Jenkins

diff --git a/vcl/qt5/QtAccessibleWidget.cxx b/vcl/qt5/QtAccessibleWidget.cxx
index fc2846fc34f3..819e1d26228c 100644
--- a/vcl/qt5/QtAccessibleWidget.cxx
+++ b/vcl/qt5/QtAccessibleWidget.cxx
@@ -431,7 +431,16 @@ QAccessible::Role QtAccessibleWidget::role() const
             return QAccessible::Footer;
         case AccessibleRole::FOOTNOTE:
             return QAccessible::Note;
-        case AccessibleRole::FRAME: // top-level window with title bar
+        case AccessibleRole::FRAME:
+            // report Pane instead of Window role for a frame that's not 
actually
+            // an accessible frame (top-level window with title bar) itself,
+            // but a child of the real top-level
+            if (QAccessibleInterface* pParent = parent())
+            {
+                const QAccessible::Role eParentRole = pParent->role();
+                if (eParentRole == QAccessible::Window || eParentRole == 
QAccessible::Dialog)
+                    return QAccessible::Pane;
+            }
             return QAccessible::Window;
         case AccessibleRole::GLASS_PANE:
             return QAccessible::UserRole;

Reply via email to