vcl/inc/osx/a11yfactory.h    |    6 
 vcl/inc/osx/a11ywrapper.h    |   16 +
 vcl/inc/osx/salframeview.h   |   44 ++++
 vcl/inc/quartz/salgdi.h      |    2 
 vcl/osx/a11yactionwrapper.h  |    1 
 vcl/osx/a11yactionwrapper.mm |   19 +
 vcl/osx/a11yfactory.mm       |   57 -----
 vcl/osx/a11ywrapper.mm       |  435 +++++++++++++++++++++++++++++++++++++++++--
 vcl/osx/salframe.cxx         |    7 
 vcl/osx/salframeview.mm      |  374 ++++++++++++++++++++++++++++++++++++
 vcl/osx/salgdiutils.cxx      |   36 +++
 11 files changed, 918 insertions(+), 79 deletions(-)

New commits:
commit e103f775501dc0a00fca8724b7e4d2117c80a87c
Author:     Patrick Luby <plub...@neooffice.org>
AuthorDate: Wed Jun 7 13:53:39 2023 -0400
Commit:     Patrick Luby <plub...@neooffice.org>
CommitDate: Mon Jun 12 22:09:19 2023 +0200

    Partial fix tdf#155376 use NSAccessibilityElement instead of NSView
    
    On macOS, accessibility is implemented by creating a native NSView
    for each C++ accessible element. The problem with using an NSView
    for each element is that NSViews are very slow to add to or remove from
    an NSWindow once the number of NSViews is more than a thousand or so.
    
    Fortunately, Apple added a protocol that allows adding a native
    accessible element using the lightweight NSAccessiblityElement class.
    The topmost NSAccessiblityElement elements are connected to the single
    SalFrameView in each NSWindow but since NSAccessiblityElements are not
    NSViews, they are not connected to any of NSWindow's event or draw
    dispatching. This makes NSAccessiblityElements significantly faster to
    add to or remove from an NSWindow with no apparent loss in functionality.
    
    Note: this change is a subset of the LibreOffice 4.4 code changes that I
    wrote for NeoOffice.
    
    Change-Id: I408108d57217db407512dfa3457fe26d2ab455de
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152717
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Reviewed-by: Patrick Luby <plub...@neooffice.org>
    (cherry picked from commit 75dc3a54fca8b2dc775ba007190d8c2e188f1c0a)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152661

diff --git a/vcl/inc/osx/a11yfactory.h b/vcl/inc/osx/a11yfactory.h
index cec49bf93b6d..9ef837dfaa9d 100644
--- a/vcl/inc/osx/a11yfactory.h
+++ b/vcl/inc/osx/a11yfactory.h
@@ -26,14 +26,14 @@
 @interface AquaA11yFactory : NSObject
 {
 }
-+(void)insertIntoWrapperRepository: (NSView *) viewElement 
forAccessibleContext: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext;
++(void)insertIntoWrapperRepository: (AquaA11yWrapper *) element 
forAccessibleContext: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext;
 +(AquaA11yWrapper *)wrapperForAccessible: (css::uno::Reference < 
css::accessibility::XAccessible >) rxAccessible;
 +(AquaA11yWrapper *)wrapperForAccessibleContext: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext;
 +(AquaA11yWrapper *)wrapperForAccessibleContext: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext 
createIfNotExists:(BOOL) bCreate;
 +(AquaA11yWrapper *)wrapperForAccessibleContext: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext 
createIfNotExists:(BOOL) bCreate asRadioGroup:(BOOL) asRadioGroup;
 +(void)removeFromWrapperRepositoryFor: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext;
-+(void)registerView: (NSView *) theView;
-+(void)revokeView: (NSView *) theViewt;
++(void)registerWrapper: (AquaA11yWrapper *) theWrapper;
++(void)revokeWrapper: (AquaA11yWrapper *) theWrapper;
 @end
 
 
diff --git a/vcl/inc/osx/a11ywrapper.h b/vcl/inc/osx/a11ywrapper.h
index 469e50820e19..1eb4039c57e9 100644
--- a/vcl/inc/osx/a11ywrapper.h
+++ b/vcl/inc/osx/a11ywrapper.h
@@ -50,7 +50,19 @@ struct ReferenceWrapper
     css::uno::Reference < css::accessibility::XAccessibleTextMarkup > 
rAccessibleTextMarkup;
 };
 
-@interface AquaA11yWrapper : NSView
+@interface AquaA11yWrapper : NSAccessibilityElement
+    <NSAccessibilityElement,
+     NSAccessibilityGroup,
+     NSAccessibilityButton,
+     NSAccessibilitySwitch,
+     NSAccessibilityRadioButton,
+     NSAccessibilityCheckBox,
+     NSAccessibilityStaticText,
+     NSAccessibilityNavigableStaticText,
+     NSAccessibilityProgressIndicator,
+     NSAccessibilityStepper,
+     NSAccessibilitySlider,
+     NSAccessibilityImage>
 {
     ReferenceWrapper maReferenceWrapper;
     BOOL mActsAsRadioGroup;
@@ -68,6 +80,7 @@ struct ReferenceWrapper
 -(id)accessibilityFocusedUIElement;
 -(NSString *)accessibilityActionDescription:(NSString *)action;
 -(void)accessibilityPerformAction:(NSString *)action;
+-(BOOL)performAction:(NSString *)action;
 -(NSArray *)accessibilityActionNames;
 -(id)accessibilityHitTest:(NSPoint)point;
 // Attribute values
@@ -86,6 +99,7 @@ struct ReferenceWrapper
 -(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup;
 -(BOOL)actsAsRadioGroup;
 -(NSWindow*)windowForParent;
+-(id)init;
 -(id)initWithAccessibleContext: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) anAccessibleContext;
 -(void) setDefaults: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext;
 +(void)setPopupMenuOpen:(BOOL)popupMenuOpen;
diff --git a/vcl/inc/osx/salframeview.h b/vcl/inc/osx/salframeview.h
index 1282eb10cbee..f9eca27e305c 100644
--- a/vcl/inc/osx/salframeview.h
+++ b/vcl/inc/osx/salframeview.h
@@ -70,11 +70,22 @@ enum class SalEvent;
 -(void)endExtTextInput:(EndExtTextInputFlags)nFlags;
 
 -(void)windowDidResizeWithTimer:(NSTimer *)pTimer;
+
+-(BOOL)isIgnoredWindow;
+
+// NSAccessibilityElement overrides
+-(id)accessibilityApplicationFocusedUIElement;
+-(id)accessibilityFocusedUIElement;
+-(BOOL)accessibilityIsIgnored;
+-(BOOL)isAccessibilityElement;
+
 @end
 
-@interface SalFrameView : AquaA11yWrapper <NSTextInputClient>
+@interface SalFrameView : NSView <NSTextInputClient>
 {
     AquaSalFrame*       mpFrame;
+    AquaA11yWrapper*    mpChildWrapper;
+    BOOL                mbNeedChildWrapper;
 
     // for NSTextInput/NSTextInputClient
     NSEvent*        mpLastEvent;
@@ -228,6 +239,37 @@ enum class SalEvent;
 -(void)endExtTextInput:(EndExtTextInputFlags)nFlags;
 -(void)deleteTextInputWantsNonRepeatKeyDown;
 
+-(void)insertRegisteredWrapperIntoWrapperRepository;
+-(void)registerWrapper;
+-(void)revokeWrapper;
+
+// NSAccessibilityElement overrides
+-(id)accessibilityAttributeValue:(NSString *)pAttribute;
+-(BOOL)accessibilityIsIgnored;
+-(NSArray *)accessibilityAttributeNames;
+-(BOOL)accessibilityIsAttributeSettable:(NSString *)pAttribute;
+-(NSArray *)accessibilityParameterizedAttributeNames;
+-(BOOL)accessibilitySetOverrideValue:(id)pValue forAttribute:(NSString 
*)pAttribute;
+-(void)accessibilitySetValue:(id)pValue forAttribute:(NSString *)pAttribute;
+-(id)accessibilityAttributeValue:(NSString *)pAttribute 
forParameter:(id)pParameter;
+-(id)accessibilityFocusedUIElement;
+-(NSString *)accessibilityActionDescription:(NSString *)pAction;
+-(void)accessibilityPerformAction:(NSString *)pAction;
+-(NSArray *)accessibilityActionNames;
+-(id)accessibilityHitTest:(NSPoint)aPoint;
+-(NSArray *)accessibilityVisibleChildren;
+-(NSArray *)accessibilitySelectedChildren;
+-(NSArray *)accessibilityChildren;
+-(NSArray <id<NSAccessibilityElement>> 
*)accessibilityChildrenInNavigationOrder;
+
+@end
+
+@interface SalFrameViewA11yWrapper : AquaA11yWrapper
+{
+    SalFrameView*       mpParentView;
+}
+-(id)initWithParent:(SalFrameView*)pParentView 
accessibleContext:(::com::sun::star::uno::Reference<::com::sun::star::accessibility::XAccessibleContext>&)rxAccessibleContext;
+-(void)dealloc;
 @end
 
 #endif // INCLUDED_VCL_INC_OSX_SALFRAMEVIEW_H
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index be5075e18a55..df9eabad936f 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -133,6 +133,8 @@ private:
 
 namespace sal::aqua
 {
+NSRect getTotalScreenBounds();
+void resetTotalScreenBounds();
 float getWindowScaling();
 void resetWindowScaling();
 }
diff --git a/vcl/osx/a11yactionwrapper.h b/vcl/osx/a11yactionwrapper.h
index 51da8a2caf38..9afc08b6b970 100644
--- a/vcl/osx/a11yactionwrapper.h
+++ b/vcl/osx/a11yactionwrapper.h
@@ -28,6 +28,7 @@
 }
 + (NSArray*)actionNamesForElement:(AquaA11yWrapper*)wrapper;
 + (void)doAction:(NSString*)action ofElement:(AquaA11yWrapper*)wrapper;
++ (NSAccessibilityActionName)actionNameForSelector:(SEL)aSelector;
 @end
 
 #endif // INCLUDED_VCL_OSX_A11YACTIONWRAPPER_H
diff --git a/vcl/osx/a11yactionwrapper.mm b/vcl/osx/a11yactionwrapper.mm
index 8af087edf75e..9bea25c11934 100644
--- a/vcl/osx/a11yactionwrapper.mm
+++ b/vcl/osx/a11yactionwrapper.mm
@@ -72,6 +72,25 @@
     }
 }
 
++(NSAccessibilityActionName)actionNameForSelector:(SEL)aSelector
+{
+    NSAccessibilityActionName pRet = nil;
+
+    if ( aSelector == @selector(accessibilityPerformDecrement) ) {
+        pRet = NSAccessibilityDecrementAction;
+    } else if ( aSelector == @selector(accessibilityPerformIncrement) ) {
+        pRet = NSAccessibilityIncrementAction;
+    } else if ( aSelector == @selector(accessibilityPerformPick) ) {
+        pRet = NSAccessibilityPickAction;
+    } else if ( aSelector == @selector(accessibilityPerformPress) ) {
+        pRet = NSAccessibilityPressAction;
+    } else if ( aSelector == @selector(accessibilityPerformShowMenu) ) {
+        pRet = NSAccessibilityShowMenuAction;
+    }
+
+    return pRet;
+}
+
 @end
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/osx/a11yfactory.mm b/vcl/osx/a11yfactory.mm
index 56ffa9f7e008..0783252c7e1f 100644
--- a/vcl/osx/a11yfactory.mm
+++ b/vcl/osx/a11yfactory.mm
@@ -155,75 +155,36 @@ static bool enabled = false;
         #endif
         {
             [ dAllWrapper setObject: aWrapper forKey: nKey ];
-            /* fdo#67410: Accessibility notifications are not delivered on 
NSView subclasses that do not
-               "reasonably" participate in NSView hierarchy (perhaps the only 
important point is
-               that the view is a transitive subview of the NSWindow's content 
view, but I
-               did not try to verify that).
-
-               So let the superview-subviews relationship mirror the 
AXParent-AXChildren relationship.
-            */
-            id parent = [aWrapper 
accessibilityAttributeValue:NSAccessibilityParentAttribute];
-            if (parent) {
-                if ([parent isKindOfClass:[NSView class]]) {
-                    NSView *parentView = static_cast<NSView *>(parent);
-
-                    // tdf#146765 Fix infinite recursion in -[NSView 
visibleRect]
-                    // HACK: Adding a subview to an NSView that is not attached
-                    // to an NSWindow leads to infinite recursion in the native
-                    // NSViewGetVisibleRect() function. This seems to be a new
-                    // behavior starting with macOS 12.6.2.
-                    // In the case of tdf#146765, we end up here because
-                    // -[AquaA11yWrapper childrenAttribute] is called by a
-                    // wrapper that is already attached to an NSWindow. That is
-                    // normal. What isn't normal is that the child wrapper's
-                    // unignored accessible parent is a different wrapper than
-                    // the caller and that different wrapper is not yet
-                    // attached to an NSWindow.
-                    // TODO: switch the AquaA11yWrapper class to inherit the
-                    // lightweight NSAccessibilityElement class instead of the
-                    // NSView class to possibly avoid the need for this hack.
-                    NSWindow *window = [parentView window];
-                    SAL_WARN_IF(!window, "vcl.a11y","Can't add subview. Parent 
view's window is nil!");
-                    if (window)
-                        [parentView addSubview:aWrapper 
positioned:NSWindowBelow relativeTo:nil];
-                } else if ([parent 
isKindOfClass:NSClassFromString(@"SalFrameWindow")]) {
-                    NSWindow *window = static_cast<NSWindow *>(parent);
-                    NSView *salView = [window contentView];
-                    [salView addSubview:aWrapper positioned:NSWindowBelow 
relativeTo:nil];
-                }
-            }
         }
     }
     return aWrapper;
 }
 
-+(void)insertIntoWrapperRepository: (NSView *) viewElement 
forAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext {
++(void)insertIntoWrapperRepository: (AquaA11yWrapper *) element 
forAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext {
     NSMutableDictionary * dAllWrapper = [ AquaA11yFactory allWrapper ];
-    [ dAllWrapper setObject: viewElement forKey: [ AquaA11yFactory 
keyForAccessibleContext: rxAccessibleContext ] ];
+    [ dAllWrapper setObject: element forKey: [ AquaA11yFactory 
keyForAccessibleContext: rxAccessibleContext ] ];
 }
 
 +(void)removeFromWrapperRepositoryFor: (css::uno::Reference < 
css::accessibility::XAccessibleContext >) rxAccessibleContext {
     // TODO: when RADIO_BUTTON search for associated RadioGroup-wrapper and 
delete that as well
     AquaA11yWrapper * theWrapper = [ AquaA11yFactory 
wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: NO ];
     if ( theWrapper != nil ) {
-        if (![theWrapper isKindOfClass:NSClassFromString(@"SalFrameView")]) {
-            [theWrapper removeFromSuperview];
-        }
+        NSAccessibilityPostNotification( theWrapper, 
NSAccessibilityUIElementDestroyedNotification );
         [ [ AquaA11yFactory allWrapper ] removeObjectForKey: [ AquaA11yFactory 
keyForAccessibleContext: rxAccessibleContext ] ];
         [ theWrapper release ];
     }
 }
 
-+(void)registerView: (NSView *) theView {
-    if ( enabled && [ theView isKindOfClass: [ AquaA11yWrapper class ] ] ) {
++(void)registerWrapper: (AquaA11yWrapper *) theWrapper {
+    if ( enabled && theWrapper ) {
         // insertIntoWrapperRepository gets called from SalFrameView itself to 
bootstrap the bridge initially
-        [ static_cast<AquaA11yWrapper *>(theView) accessibleContext ];
+        [ theWrapper accessibleContext ];
     }
 }
 
-+(void)revokeView: (NSView *) theView {
-    if ( enabled && [ theView isKindOfClass: [ AquaA11yWrapper class ] ] ) {
-        [ AquaA11yFactory removeFromWrapperRepositoryFor: [ 
static_cast<AquaA11yWrapper *>(theView) accessibleContext ] ];
++(void)revokeWrapper: (AquaA11yWrapper *) theWrapper {
+    if ( enabled && theWrapper ) {
+        [ AquaA11yFactory removeFromWrapperRepositoryFor: [ theWrapper 
accessibleContext ] ];
     }
 }
 
diff --git a/vcl/osx/a11ywrapper.mm b/vcl/osx/a11ywrapper.mm
index 75763a65a131..06967df5aa3e 100644
--- a/vcl/osx/a11ywrapper.mm
+++ b/vcl/osx/a11ywrapper.mm
@@ -26,6 +26,7 @@
 #include <osx/a11yfactory.h>
 #include <osx/a11yfocustracker.hxx>
 
+#include <quartz/salgdi.h>
 #include <quartz/utils.h>
 
 #include "a11yfocuslistener.hxx"
@@ -65,11 +66,15 @@ static std::ostream &operator<<(std::ostream &s, NSObject 
*obj) {
     return s << [[obj description] UTF8String];
 }
 
-@implementation AquaA11yWrapper : NSView
+@implementation AquaA11yWrapper
 
 #pragma mark -
 #pragma mark Init and dealloc
 
+-(id)init {
+    return [ super init ];
+}
+
 -(id)initWithAccessibleContext: (Reference < XAccessibleContext >) 
rxAccessibleContext {
     self = [ super init ];
     if ( self ) {
@@ -716,20 +721,27 @@ static std::ostream &operator<<(std::ostream &s, NSObject 
*obj) {
         return NO;
     }
     bool ignored = false;
-    sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole();
-    switch ( nRole ) {
-        //case AccessibleRole::PANEL:
-        case AccessibleRole::FRAME:
-        case AccessibleRole::ROOT_PANE:
-        case AccessibleRole::SEPARATOR:
-        case AccessibleRole::FILLER:
-        case AccessibleRole::DIALOG:
-            ignored = true;
-            break;
-        default:
-            ignored = ! ( [ self accessibleContext ] -> 
getAccessibleStateSet() & AccessibleStateType::VISIBLE );
-            break;
+    try {
+        sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole();
+        switch ( nRole ) {
+            //case AccessibleRole::PANEL:
+            case AccessibleRole::FRAME:
+            case AccessibleRole::ROOT_PANE:
+            case AccessibleRole::SEPARATOR:
+            case AccessibleRole::FILLER:
+            case AccessibleRole::DIALOG:
+                ignored = true;
+                break;
+            default:
+                ignored = ! ( [ self accessibleContext ] -> 
getAccessibleStateSet() & AccessibleStateType::VISIBLE );
+                break;
+        }
+    } catch ( DisposedException& ) {
+        ignored = true;
+    } catch ( RuntimeException& ) {
+        ignored = true;
     }
+
     return ignored; // TODO: to be completed
 }
 
@@ -965,6 +977,10 @@ static std::ostream &operator<<(std::ostream &s, NSObject 
*obj) {
 }
 
 -(void)accessibilityPerformAction:(NSString *)action {
+    [ self performAction: action ];
+}
+
+-(BOOL)performAction:(NSString *)action {
     // Related: tdf#148453 Acquire solar mutex during native accessibility 
calls
     SolarMutexGuard aGuard;
 
@@ -972,7 +988,9 @@ static std::ostream &operator<<(std::ostream &s, NSObject 
*obj) {
     AquaA11yWrapper * actionResponder = [ self actionResponder ];
     if ( actionResponder ) {
         [ AquaA11yActionWrapper doAction: action ofElement: actionResponder ];
+        return YES;
     }
+    return NO;
 }
 
 -(NSArray *)accessibilityActionNames {
@@ -1170,7 +1188,7 @@ static Reference < XAccessibleContext > hitTestRunner ( 
css::awt::Point point,
 }
 
 -(NSWindow*)windowForParent {
-    return [self window];
+    return nil;
 }
 
 -(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup {
@@ -1185,6 +1203,393 @@ static Reference < XAccessibleContext > hitTestRunner ( 
css::awt::Point point,
     isPopupMenuOpen = popupMenuOpen;
 }
 
+// NSAccessibility selectors
+
+- (BOOL)isAccessibilityElement
+{
+    return ! [ self accessibilityIsIgnored ];
+}
+
+- (BOOL)isAccessibilityFocused
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilityFocusedAttribute ];
+    if ( pNumber )
+        return [ pNumber boolValue ];
+    else
+        return NO;
+}
+
+- (id)accessibilityTopLevelUIElement
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityTopLevelUIElementAttribute ];
+}
+
+- (id)accessibilityValue
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityValueAttribute ];
+}
+
+- (NSArray *)accessibilityVisibleChildren
+{
+    return [ self accessibilityChildren ];
+}
+
+- (NSAccessibilitySubrole)accessibilitySubrole
+{
+    return [ self accessibilityAttributeValue: NSAccessibilitySubroleAttribute 
];
+}
+
+- (NSString *)accessibilityTitle
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityTitleAttribute ];
+}
+
+- (id)accessibilityTitleUIElement
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityTitleUIElementAttribute ];
+}
+
+- (NSAccessibilityOrientation)accessibilityOrientation
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilityOrientationAttribute ];
+    if ( pNumber )
+        return (NSAccessibilityOrientation)[ pNumber integerValue ];
+    else
+        return NSAccessibilityOrientationUnknown;
+}
+
+- (id)accessibilityParent
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityParentAttribute 
];
+}
+
+- (NSAccessibilityRole)accessibilityRole
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityRoleAttribute ];
+}
+
+- (NSString *)accessibilityRoleDescription
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityRoleDescriptionAttribute ];
+}
+
+- (BOOL)isAccessibilitySelected
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilitySelectedAttribute ];
+    if ( pNumber )
+        return [ pNumber boolValue ];
+    else
+        return NO;
+}
+
+- (NSArray *)accessibilitySelectedChildren
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilitySelectedChildrenAttribute ];
+}
+
+- (NSArray *)accessibilityServesAsTitleForUIElements
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityServesAsTitleForUIElementsAttribute ];
+}
+
+- (id)accessibilityMinValue
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityMinValueAttribute ];
+}
+
+- (id)accessibilityMaxValue
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityMaxValueAttribute ];
+}
+
+- (id)accessibilityWindow
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityWindowAttribute 
];
+}
+
+- (NSString *)accessibilityHelp
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityHelpAttribute ];
+}
+
+- (BOOL)isAccessibilityExpanded
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilityExpandedAttribute ];
+    if ( pNumber )
+        return [ pNumber boolValue ];
+    else
+        return NO;
+}
+
+- (BOOL)isAccessibilityEnabled
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilityEnabledAttribute ];
+    if ( pNumber )
+        return [ pNumber boolValue ];
+    else
+        return NO;
+}
+
+- (NSArray *)accessibilityChildren
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityChildrenAttribute ];
+}
+
+- (NSArray <id<NSAccessibilityElement>> 
*)accessibilityChildrenInNavigationOrder
+{
+    return [ self accessibilityChildren ];
+}
+
+- (NSArray *)accessibilityContents
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityContentsAttribute ];
+}
+
+- (NSString *)accessibilityLabel
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityDescriptionAttribute ];
+}
+
+- (id)accessibilityApplicationFocusedUIElement
+{
+    return [ self accessibilityFocusedUIElement ];
+}
+
+- (BOOL)isAccessibilityDisclosed
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilityDisclosingAttribute ];
+    if ( pNumber )
+        return [ pNumber boolValue ];
+    else
+        return NO;
+}
+
+- (id)accessibilityHorizontalScrollBar
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityHorizontalScrollBarAttribute ];
+}
+
+- (id)accessibilityVerticalScrollBar
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityVerticalScrollBarAttribute ];
+}
+
+- (NSArray *)accessibilityTabs
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityTabsAttribute ];
+}
+
+- (NSArray *)accessibilityColumns
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityColumnsAttribute 
];
+}
+
+- (NSArray *)accessibilityRows
+{
+    return [ self accessibilityAttributeValue: NSAccessibilityRowsAttribute ];
+}
+
+- (NSRange)accessibilitySharedCharacterRange
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilitySharedCharacterRangeAttribute ];
+    if ( pValue )
+        return [ pValue rangeValue ];
+    else
+        return NSMakeRange( NSNotFound, 0 );
+}
+
+- (NSArray *)accessibilitySharedTextUIElements
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilitySharedTextUIElementsAttribute ];
+}
+
+- (NSRange)accessibilityVisibleCharacterRange
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilityVisibleCharacterRangeAttribute ];
+    if ( pValue )
+        return [ pValue rangeValue ];
+    else
+        return NSMakeRange( NSNotFound, 0 );
+}
+
+- (NSInteger)accessibilityNumberOfCharacters
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilityNumberOfCharactersAttribute ];
+    if ( pNumber )
+        return [ pNumber integerValue ];
+    else
+        return 0;
+}
+
+- (NSString *)accessibilitySelectedText
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilitySelectedTextAttribute ];
+}
+
+- (NSRange)accessibilitySelectedTextRange
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilitySelectedTextRangeAttribute ];
+    if ( pValue )
+        return [ pValue rangeValue ];
+    else
+        return NSMakeRange( NSNotFound, 0 );
+}
+
+- (NSAttributedString *)accessibilityAttributedStringForRange:(NSRange)aRange
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter: [ 
NSValue valueWithRange: aRange ] ];
+}
+
+- (NSRange)accessibilityRangeForLine:(NSInteger)nLine
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilityRangeForLineParameterizedAttribute forParameter: [NSNumber 
numberWithInteger: nLine ] ];
+    if ( pValue )
+        return [ pValue rangeValue ];
+    else
+        return NSMakeRange( NSNotFound, 0 );
+}
+
+- (NSString *)accessibilityStringForRange:(NSRange)aRange
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityStringForRangeParameterizedAttribute forParameter: [ NSValue 
valueWithRange: aRange ] ];
+}
+
+- (NSRange)accessibilityRangeForPosition:(NSPoint)aPoint
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilityRangeForPositionParameterizedAttribute forParameter: [ NSValue 
valueWithPoint: aPoint ] ];
+    if ( pValue )
+        return [ pValue rangeValue ];
+    else
+        return NSMakeRange( NSNotFound, 0 );
+}
+
+- (NSRange)accessibilityRangeForIndex:(NSInteger)nIndex
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilityRangeForIndexParameterizedAttribute forParameter: [ NSNumber 
numberWithInteger: nIndex ] ];
+    if ( pValue )
+        return [ pValue rangeValue ];
+    else
+        return NSMakeRange( NSNotFound, 0 );
+}
+
+- (NSRect)accessibilityFrameForRange:(NSRange)aRange
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilityBoundsForRangeParameterizedAttribute forParameter: [ NSValue 
valueWithRange: aRange ] ];
+    if ( pValue )
+        return [ pValue rectValue ];
+    else
+        return NSZeroRect;
+}
+
+- (NSData *)accessibilityRTFForRange:(NSRange)aRange
+{
+    return [ self accessibilityAttributeValue: 
NSAccessibilityRTFForRangeParameterizedAttribute forParameter: [ NSValue 
valueWithRange: aRange ] ];
+}
+
+- (NSRange)accessibilityStyleRangeForIndex:(NSInteger)nIndex
+{
+    NSValue *pValue = [ self accessibilityAttributeValue: 
NSAccessibilityStyleRangeForIndexParameterizedAttribute forParameter: [ 
NSNumber numberWithInteger: nIndex ] ];
+    if ( pValue )
+        return [ pValue rangeValue ];
+    else
+        return NSMakeRange( NSNotFound, 0 );
+}
+
+- (NSInteger)accessibilityLineForIndex:(NSInteger)nIndex
+{
+    NSNumber *pNumber = [ self accessibilityAttributeValue: 
NSAccessibilityLineForIndexParameterizedAttribute forParameter: [ NSNumber 
numberWithInteger: nIndex ] ];
+    if ( pNumber )
+        return [ pNumber integerValue ];
+    else
+        return 0;
+}
+
+- (BOOL)accessibilityPerformDecrement
+{
+    return [ self performAction: NSAccessibilityDecrementAction ];
+}
+
+- (BOOL)accessibilityPerformPick
+{
+    return [ self performAction: NSAccessibilityPickAction ];
+}
+
+- (BOOL)accessibilityPerformShowMenu
+{
+    return [ self performAction: NSAccessibilityShowMenuAction ];
+}
+
+- (BOOL)accessibilityPerformPress
+{
+    return [ self performAction: NSAccessibilityPressAction ];
+}
+
+- (BOOL)accessibilityPerformIncrement
+{
+    return [ self performAction: NSAccessibilityIncrementAction ];
+}
+
+// NSAccessibilityElement selectors
+
+- (NSRect)accessibilityFrame
+{
+    // Related: tdf#148453 Acquire solar mutex during native accessibility 
calls
+    SolarMutexGuard aGuard;
+
+    try {
+        XAccessibleComponent *pAccessibleComponent = [ self 
accessibleComponent ];
+        if ( pAccessibleComponent ) {
+            com::sun::star::awt::Point location = 
pAccessibleComponent->getLocationOnScreen();
+            com::sun::star::awt::Size size = pAccessibleComponent->getSize();
+            NSRect screenRect = sal::aqua::getTotalScreenBounds();
+            NSRect frame = NSMakeRect( (float)location.X, (float)( 
screenRect.size.height - size.Height - location.Y ), (float)size.Width, 
(float)size.Height );
+            return frame;
+        }
+    } catch ( DisposedException& ) {
+    } catch ( RuntimeException& ) {
+    }
+
+    return NSZeroRect;
+}
+
+- (BOOL)accessibilityNotifiesWhenDestroyed
+{
+    return YES;
+}
+
+- (BOOL)isAccessibilitySelectorAllowed:(SEL)aSelector
+{
+    if ( ! aSelector )
+        return NO;
+
+    if ( [ self respondsToSelector: aSelector ] ) {
+        // Ignore actions if action is not supported
+        NSAccessibilityActionName pActionName = [ AquaA11yActionWrapper 
actionNameForSelector: aSelector ];
+        if ( pActionName ) {
+            NSArray *pActionNames = [ self accessibilityActionNames ];
+            if ( ! pActionNames || ! [ pActionNames containsObject: 
pActionName ] )
+                return NO;
+        } else {
+            // Ignore "setAccessibility" selectors if attribute is not settable
+            static NSString *pSetPrefix = @"setAccessibility";
+            NSString *pSelName = NSStringFromSelector( aSelector );
+            if ( pSelName && [ pSelName hasPrefix: pSetPrefix ] && [ pSelName 
hasSuffix: @":" ] ) {
+                NSAccessibilityAttributeName pAttrName = [ pSelName 
substringToIndex: [ pSelName length ] - 1 ];
+                if ( pAttrName && [ pAttrName length ] > [ pSetPrefix length ] 
) {
+                    pAttrName = [ pAttrName substringFromIndex: [ pSetPrefix 
length ] ];
+                    if ( pAttrName && [ pAttrName length ] ) {
+                        pAttrName = [ @"AX" stringByAppendingString: pAttrName 
];
+                        if ( pAttrName && [ pAttrName length ] && ! [ self 
accessibilityIsAttributeSettable: pAttrName ] )
+                                return NO;
+                    }
+                }
+            }
+        }
+    }
+
+    return [ super isAccessibilitySelectorAllowed: aSelector ];
+}
+
 @end
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx
index b4a2d07463b8..18ab569ad7a6 100644
--- a/vcl/osx/salframe.cxx
+++ b/vcl/osx/salframe.cxx
@@ -156,7 +156,8 @@ AquaSalFrame::~AquaSalFrame()
         }
     }
     if ( mpNSView ) {
-        [AquaA11yFactory revokeView: mpNSView];
+        if ([mpNSView isKindOfClass:[SalFrameView class]])
+            [static_cast<SalFrameView*>(mpNSView) revokeWrapper];
         [mpNSView release];
     }
     if ( mpNSWindow )
@@ -287,6 +288,7 @@ void AquaSalFrame::screenParametersChanged()
 {
     OSX_SALDATA_RUNINMAIN( screenParametersChanged() )
 
+    sal::aqua::resetTotalScreenBounds();
     sal::aqua::resetWindowScaling();
 
     UpdateFrameGeometry();
@@ -429,7 +431,8 @@ void AquaSalFrame::initShow()
     }
 
     // make sure the view is present in the wrapper list before any children 
receive focus
-    [AquaA11yFactory registerView: mpNSView];
+    if (mpNSView && [mpNSView isKindOfClass:[SalFrameView class]])
+        [static_cast<SalFrameView*>(mpNSView) registerWrapper];
 }
 
 void AquaSalFrame::SendPaintEvent( const tools::Rectangle* pRect )
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index ad4dd40cfebb..0ccdb048d190 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -165,6 +165,39 @@ static AquaSalFrame* getMouseContainerFrame()
     return pDispatchFrame;
 }
 
+static NSArray *getMergedAccessibilityChildren(NSArray *pDefaultChildren, 
NSArray *pUnignoredChildrenToAdd)
+{
+    NSArray *pRet = pDefaultChildren;
+
+    if (pUnignoredChildrenToAdd && [pUnignoredChildrenToAdd count])
+    {
+        NSMutableArray *pNewChildren = [NSMutableArray arrayWithCapacity:(pRet 
? [pRet count] : 0) + 1];
+        if (pNewChildren)
+        {
+            if (pRet)
+                [pNewChildren addObjectsFromArray:pRet];
+
+            for (AquaA11yWrapper *pWrapper : pUnignoredChildrenToAdd)
+            {
+                if (pWrapper && ![pNewChildren containsObject:pWrapper])
+                    [pNewChildren addObject:pWrapper];
+            }
+
+            pRet = pNewChildren;
+        }
+        else
+        {
+            pRet = pUnignoredChildrenToAdd;
+        }
+    }
+
+    return pRet;
+}
+
+@interface NSResponder (SalFrameWindow)
+-(BOOL)accessibilityIsIgnored;
+@end
+
 @implementation SalFrameWindow
 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
 {
@@ -541,6 +574,44 @@ static AquaSalFrame* getMouseContainerFrame()
     return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext();
 }
 
+-(BOOL)isIgnoredWindow
+{
+    SolarMutexGuard aGuard;
+
+    // Treat tooltip windows as ignored
+    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
+        return (mpFrame->mnStyle & SalFrameStyleFlags::TOOLTIP) != 
SalFrameStyleFlags::NONE;
+    return YES;
+}
+
+-(id)accessibilityApplicationFocusedUIElement
+{
+    return [self accessibilityFocusedUIElement];
+}
+
+-(id)accessibilityFocusedUIElement
+{
+    // Treat tooltip windows as ignored
+    if ([self isIgnoredWindow])
+        return nil;
+
+    return [super accessibilityFocusedUIElement];
+}
+
+-(BOOL)accessibilityIsIgnored
+{
+    // Treat tooltip windows as ignored
+    if ([self isIgnoredWindow])
+        return YES;
+
+    return [super accessibilityIsIgnored];
+}
+
+-(BOOL)isAccessibilityElement
+{
+    return ![self accessibilityIsIgnored];
+}
+
 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
 {
   return [mDraggingDestinationHandler draggingEntered: sender];
@@ -615,6 +686,8 @@ static AquaSalFrame* getMouseContainerFrame()
     {
         mDraggingDestinationHandler = nil;
         mpFrame = pFrame;
+        mpChildWrapper = nil;
+        mbNeedChildWrapper = NO;
         mpLastEvent = nil;
         mMarkedRange = NSMakeRange(NSNotFound, 0);
         mSelectedRange = NSMakeRange(NSNotFound, 0);
@@ -635,6 +708,7 @@ static AquaSalFrame* getMouseContainerFrame()
 {
     [self clearLastEvent];
     [self clearLastMarkedText];
+    [self revokeWrapper];
 
     [super dealloc];
 }
@@ -2053,16 +2127,13 @@ static AquaSalFrame* getMouseContainerFrame()
 
 -(css::accessibility::XAccessibleContext *)accessibleContext
 {
-    if ( !maReferenceWrapper.rAccessibleContext ) {
-        // some frames never become visible ..
-        vcl::Window *pWindow = mpFrame -> GetWindow();
-        if ( ! pWindow )
-            return nil;
+    SolarMutexGuard aGuard;
 
-        maReferenceWrapper.rAccessibleContext =  pWindow -> 
/*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
-        [ AquaA11yFactory insertIntoWrapperRepository: self 
forAccessibleContext: maReferenceWrapper.rAccessibleContext ];
-    }
-    return [ super accessibleContext ];
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibleContext];
+
+    return nil;
 }
 
 -(NSWindow*)windowForParent
@@ -2213,6 +2284,291 @@ static AquaSalFrame* getMouseContainerFrame()
     }
 }
 
+-(void)insertRegisteredWrapperIntoWrapperRepository
+{
+    SolarMutexGuard aGuard;
+
+    if (!mbNeedChildWrapper)
+        return;
+
+    vcl::Window *pWindow = mpFrame->GetWindow();
+    if (!pWindow)
+        return;
+
+    mbNeedChildWrapper = NO;
+
+    ::com::sun::star::uno::Reference< 
::com::sun::star::accessibility::XAccessibleContext > xAccessibleContext( 
pWindow->GetAccessible()->getAccessibleContext() );
+    assert(!mpChildWrapper);
+    mpChildWrapper = [[SalFrameViewA11yWrapper alloc] initWithParent:self 
accessibleContext:xAccessibleContext];
+    [AquaA11yFactory insertIntoWrapperRepository:mpChildWrapper 
forAccessibleContext:xAccessibleContext];
+}
+
+-(void)registerWrapper
+{
+    [self revokeWrapper];
+
+    mbNeedChildWrapper = YES;
+}
+
+-(void)revokeWrapper
+{
+    mbNeedChildWrapper = NO;
+
+    if (mpChildWrapper)
+    {
+        [AquaA11yFactory revokeWrapper:mpChildWrapper];
+        [mpChildWrapper setAccessibilityParent:nil];
+        [mpChildWrapper release];
+        mpChildWrapper = nil;
+    }
+}
+
+-(id)accessibilityAttributeValue:(NSString *)pAttribute
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityAttributeValue:pAttribute];
+    else
+        return nil;
+}
+
+-(BOOL)accessibilityIsIgnored
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityIsIgnored];
+    else
+        return YES;
+}
+
+-(NSArray *)accessibilityAttributeNames
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityAttributeNames];
+    else
+        return [NSArray array];
+}
+
+-(BOOL)accessibilityIsAttributeSettable:(NSString *)pAttribute
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityIsAttributeSettable:pAttribute];
+    else
+        return NO;
+}
+
+-(NSArray *)accessibilityParameterizedAttributeNames
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityParameterizedAttributeNames];
+    else
+        return [NSArray array];
+}
+
+-(BOOL)accessibilitySetOverrideValue:(id)pValue forAttribute:(NSString 
*)pAttribute
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilitySetOverrideValue:pValue 
forAttribute:pAttribute];
+    else
+        return NO;
+}
+
+-(void)accessibilitySetValue:(id)pValue forAttribute:(NSString *)pAttribute
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        [mpChildWrapper accessibilitySetValue:pValue forAttribute:pAttribute];
+}
+
+-(id)accessibilityAttributeValue:(NSString *)pAttribute 
forParameter:(id)pParameter
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityAttributeValue:pAttribute 
forParameter:pParameter];
+    else
+        return nil;
+}
+
+-(id)accessibilityFocusedUIElement
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityFocusedUIElement];
+    else
+        return nil;
+}
+
+-(NSString *)accessibilityActionDescription:(NSString *)pAction
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityActionDescription:pAction];
+    else
+        return nil;
+}
+
+-(void)accessibilityPerformAction:(NSString *)pAction
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        [mpChildWrapper accessibilityPerformAction:pAction];
+}
+
+-(NSArray *)accessibilityActionNames
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityActionNames];
+    else
+        return [NSArray array];
+}
+
+-(id)accessibilityHitTest:(NSPoint)aPoint
+{
+    SolarMutexGuard aGuard;
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        return [mpChildWrapper accessibilityHitTest:aPoint];
+    else
+        return nil;
+}
+
+-(id)accessibilityParent
+{
+    return [self window];
+}
+
+-(NSArray *)accessibilityVisibleChildren
+{
+    return [self accessibilityChildren];
+}
+
+-(NSArray *)accessibilitySelectedChildren
+{
+    SolarMutexGuard aGuard;
+
+    NSArray *pRet = [super accessibilityChildren];
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        pRet = getMergedAccessibilityChildren(pRet, [mpChildWrapper 
accessibilitySelectedChildren]);
+
+    return pRet;
+}
+
+-(NSArray *)accessibilityChildren
+{
+    SolarMutexGuard aGuard;
+
+    NSArray *pRet = [super accessibilityChildren];
+
+    [self insertRegisteredWrapperIntoWrapperRepository];
+    if (mpChildWrapper)
+        pRet = getMergedAccessibilityChildren(pRet, [mpChildWrapper 
accessibilityChildren]);
+
+    return pRet;
+}
+
+-(NSArray <id<NSAccessibilityElement>> *)accessibilityChildrenInNavigationOrder
+{
+    return [self accessibilityChildren];
+}
+
+@end
+
+@implementation SalFrameViewA11yWrapper
+
+-(id)initWithParent:(SalFrameView *)pParentView 
accessibleContext:(::com::sun::star::uno::Reference< 
::com::sun::star::accessibility::XAccessibleContext >&)rxAccessibleContext
+{
+    [super init];
+
+    maReferenceWrapper.rAccessibleContext = rxAccessibleContext;
+
+    mpParentView = pParentView;
+    if (mpParentView)
+    {
+        [mpParentView retain];
+        [self setAccessibilityParent:mpParentView];
+    }
+
+    return self;
+}
+
+-(void)dealloc
+{
+    if (mpParentView)
+        [mpParentView release];
+
+    [super dealloc];
+}
+
+-(id)parentAttribute
+{
+    if (mpParentView)
+        return NSAccessibilityUnignoredAncestor(mpParentView);
+    else
+        return nil;
+}
+
+-(void)setAccessibilityParent:(id)pObject
+{
+    if (mpParentView)
+    {
+        [mpParentView release];
+        mpParentView = nil;
+    }
+
+    if (pObject && [pObject isKindOfClass:[SalFrameView class]])
+    {
+        mpParentView = (SalFrameView *)pObject;
+        [mpParentView retain];
+    }
+
+    [super setAccessibilityParent:mpParentView];
+}
+
+-(id)windowAttribute
+{
+    if (mpParentView)
+        return [mpParentView window];
+    else
+        return nil;
+}
+
+-(NSWindow *)windowForParent
+{
+    return [self windowAttribute];
+}
+
 @end
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/osx/salgdiutils.cxx b/vcl/osx/salgdiutils.cxx
index d65897e25a83..7e4bd23baac9 100644
--- a/vcl/osx/salgdiutils.cxx
+++ b/vcl/osx/salgdiutils.cxx
@@ -40,6 +40,9 @@
 #include <vcl/skia/SkiaHelper.hxx>
 #endif
 
+static bool bTotalScreenBounds = false;
+static NSRect aTotalScreenBounds = NSZeroRect;
+
 // TODO: Scale will be set to 2.0f as default after implementation of full 
scaled display support . This will allow moving of
 // windows between non retina and retina displays without blurry text and 
graphics. Static variables have to be removed thereafter.
 
@@ -53,6 +56,39 @@ static float fWindowScale = 1.0f;
 
 namespace sal::aqua
 {
+NSRect getTotalScreenBounds()
+{
+    if (!bTotalScreenBounds)
+    {
+        aTotalScreenBounds = NSZeroRect;
+
+        NSArray *aScreens = [NSScreen screens];
+        if (aScreens != nullptr)
+        {
+            for (NSScreen *aScreen : aScreens)
+            {
+                // Calculate total screen bounds
+                NSRect aScreenFrame = [aScreen frame];
+                if (!NSIsEmptyRect(aScreenFrame))
+                {
+                    if (NSIsEmptyRect(aTotalScreenBounds))
+                        aTotalScreenBounds = aScreenFrame;
+                    else
+                        aTotalScreenBounds = NSUnionRect( aScreenFrame, 
aTotalScreenBounds );
+                }
+            }
+            bTotalScreenBounds = true;
+        }
+    }
+    return aTotalScreenBounds;
+}
+
+void resetTotalScreenBounds()
+{
+    bTotalScreenBounds = false;
+    getTotalScreenBounds();
+}
+
 float getWindowScaling()
 {
     // Related: tdf#147342 Any changes to this function must be copied to the

Reply via email to