include/svx/ShapeTypeHandler.hxx | 10 - svx/source/accessibility/AccessibleControlShape.cxx | 134 ++++++++++---------- svx/source/accessibility/ShapeTypeHandler.cxx | 21 --- vcl/unx/gtk3/fpicker/SalGtkPicker.cxx | 13 + 4 files changed, 80 insertions(+), 98 deletions(-)
New commits: commit 93010de73bd96090389411f4d78361cc94f2d6e3 Author: Michael Weghorn <[email protected]> AuthorDate: Wed May 21 14:28:32 2025 +0200 Commit: Michael Weghorn <[email protected]> CommitDate: Thu May 22 05:50:31 2025 +0200 svx a11y: Merge both ShapeTypeHandler::GetSlotId Change-Id: I140488bcdf9ae4df9e42170ce6d6a5a55f66c29c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185612 Reviewed-by: Michael Weghorn <[email protected]> Tested-by: Jenkins diff --git a/include/svx/ShapeTypeHandler.hxx b/include/svx/ShapeTypeHandler.hxx index 750adbfedeb0..ee6335e0f470 100644 --- a/include/svx/ShapeTypeHandler.hxx +++ b/include/svx/ShapeTypeHandler.hxx @@ -170,16 +170,6 @@ private: typedef std::unordered_map<OUString,ShapeTypeId> tServiceNameToSlotId; mutable tServiceNameToSlotId maServiceNameToSlotId; - /** Determine the slot id of the specified shape type. With this id - internal methods can access the associated type descriptor. - @param aServiceName - Service name of the shape for which to return the slot id. - @return - Returns the slot id of the shape with the given service name or - 0 when the service name is not known. - */ - SVX_DLLPRIVATE tools::Long GetSlotId (const OUString& aServiceName) const; - /** Determine the slot id of the specified shape type. With this id internal methods can access the associated type descriptor. @param rxShape diff --git a/svx/source/accessibility/ShapeTypeHandler.cxx b/svx/source/accessibility/ShapeTypeHandler.cxx index 1b169c761a3e..06b8332f524b 100644 --- a/svx/source/accessibility/ShapeTypeHandler.cxx +++ b/svx/source/accessibility/ShapeTypeHandler.cxx @@ -166,25 +166,16 @@ void ShapeTypeHandler::AddShapeTypeList (int nDescriptorCount, } } - -tools::Long ShapeTypeHandler::GetSlotId (const OUString& aServiceName) const +tools::Long ShapeTypeHandler::GetSlotId(const uno::Reference<drawing::XShape>& rxShape) const { - tServiceNameToSlotId::const_iterator I (maServiceNameToSlotId.find (aServiceName)); - if (I != maServiceNameToSlotId.end()) - return I->second; - else + if (!rxShape.is()) return 0; -} + tServiceNameToSlotId::const_iterator I (maServiceNameToSlotId.find(rxShape->getShapeType())); + if (I != maServiceNameToSlotId.end()) + return I->second; -// Extract the given shape's service name and forward request to appropriate -// method. -tools::Long ShapeTypeHandler::GetSlotId (const uno::Reference<drawing::XShape>& rxShape) const -{ - if (rxShape.is()) - return GetSlotId (rxShape->getShapeType()); - else - return 0; + return 0; } /// get the accessible base name for an object commit 3f6564fc6f0f18104d800c66a3e70f854059f234 Author: Michael Weghorn <[email protected]> AuthorDate: Wed May 21 14:07:59 2025 +0200 Commit: Michael Weghorn <[email protected]> CommitDate: Thu May 22 05:50:24 2025 +0200 svx a11y: Flatten AccessibleControlShape::Init Return early. Change-Id: Ia1e6f1ce0eb012685b240ba7cd9d2613a0e8ed63 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185611 Reviewed-by: Michael Weghorn <[email protected]> Tested-by: Jenkins diff --git a/svx/source/accessibility/AccessibleControlShape.cxx b/svx/source/accessibility/AccessibleControlShape.cxx index 84df1087e890..379156cedd04 100644 --- a/svx/source/accessibility/AccessibleControlShape.cxx +++ b/svx/source/accessibility/AccessibleControlShape.cxx @@ -179,82 +179,82 @@ void AccessibleControlShape::Init() SdrView* pView = maShapeTreeInfo.GetSdrView(); OSL_ENSURE( pView && pViewWindow && pUnoObjectImpl, "AccessibleControlShape::Init: no view, or no view window, no SdrUnoObj!" ); - if ( pView && pViewWindow && pUnoObjectImpl ) - { - // get the context of the control - it will be our "inner" context - m_xUnoControl = pUnoObjectImpl->GetUnoControl( *pView, *pViewWindow->GetOutDev() ); + if (!pView || !pViewWindow || !pUnoObjectImpl) + return; + + // get the context of the control - it will be our "inner" context + m_xUnoControl = pUnoObjectImpl->GetUnoControl( *pView, *pViewWindow->GetOutDev() ); - if ( !m_xUnoControl.is() ) + if ( !m_xUnoControl.is() ) + { + // the control has not yet been created. Though speaking strictly, it is a bug that + // our instance here is created without an existing control (because an AccessibleControlShape + // is a representation of a view object, and can only live if the view it should represent + // is complete, which implies a living control), it's by far the easiest and most riskless way + // to fix this here in this class. + // Okay, we will add as listener to the control container where we expect our control to appear. + OSL_ENSURE( !m_bWaitingForControl, "AccessibleControlShape::Init: already waiting for the control!" ); + + Reference< XContainer > xControlContainer = lcl_getControlContainer( pViewWindow->GetOutDev(), maShapeTreeInfo.GetSdrView() ); + OSL_ENSURE( xControlContainer.is(), "AccessibleControlShape::Init: unable to find my ControlContainer!" ); + if ( xControlContainer.is() ) { - // the control has not yet been created. Though speaking strictly, it is a bug that - // our instance here is created without an existing control (because an AccessibleControlShape - // is a representation of a view object, and can only live if the view it should represent - // is complete, which implies a living control), it's by far the easiest and most riskless way - // to fix this here in this class. - // Okay, we will add as listener to the control container where we expect our control to appear. - OSL_ENSURE( !m_bWaitingForControl, "AccessibleControlShape::Init: already waiting for the control!" ); - - Reference< XContainer > xControlContainer = lcl_getControlContainer( pViewWindow->GetOutDev(), maShapeTreeInfo.GetSdrView() ); - OSL_ENSURE( xControlContainer.is(), "AccessibleControlShape::Init: unable to find my ControlContainer!" ); - if ( xControlContainer.is() ) - { - xControlContainer->addContainerListener( this ); - m_bWaitingForControl = true; - } + xControlContainer->addContainerListener( this ); + m_bWaitingForControl = true; } - else + } + else + { + Reference< XModeChangeBroadcaster > xControlModes( m_xUnoControl, UNO_QUERY ); + Reference< XAccessible > xControlAccessible( xControlModes, UNO_QUERY ); + Reference< XAccessibleContext > xNativeControlContext; + if ( xControlAccessible.is() ) + xNativeControlContext = xControlAccessible->getAccessibleContext(); + OSL_ENSURE( xNativeControlContext.is(), "AccessibleControlShape::Init: no AccessibleContext for the control!" ); + m_aControlContext = WeakReference< XAccessibleContext >( xNativeControlContext ); + + // add as listener to the context - we want to multiplex some states + if ( isAliveMode( m_xUnoControl ) && xNativeControlContext.is() ) + { // (but only in alive mode) + startStateMultiplexing( ); + } + + // now that we have all information about our control, do some adjustments + adjustAccessibleRole(); + initializeComposedState(); + + // some initialization for our child manager, which is used in alive mode only + if ( isAliveMode( m_xUnoControl ) ) { - Reference< XModeChangeBroadcaster > xControlModes( m_xUnoControl, UNO_QUERY ); - Reference< XAccessible > xControlAccessible( xControlModes, UNO_QUERY ); - Reference< XAccessibleContext > xNativeControlContext; - if ( xControlAccessible.is() ) - xNativeControlContext = xControlAccessible->getAccessibleContext(); - OSL_ENSURE( xNativeControlContext.is(), "AccessibleControlShape::Init: no AccessibleContext for the control!" ); - m_aControlContext = WeakReference< XAccessibleContext >( xNativeControlContext ); - - // add as listener to the context - we want to multiplex some states - if ( isAliveMode( m_xUnoControl ) && xNativeControlContext.is() ) - { // (but only in alive mode) - startStateMultiplexing( ); - } + sal_Int64 nStates( getAccessibleStateSet( ) ); + m_pChildManager->setTransientChildren( nStates & AccessibleStateType::MANAGES_DESCENDANTS ); + } - // now that we have all information about our control, do some adjustments - adjustAccessibleRole(); - initializeComposedState(); + // finally, aggregate a proxy for the control context + // first a factory for the proxy + Reference< XProxyFactory > xFactory = ProxyFactory::create( comphelper::getProcessComponentContext() ); + // then the proxy itself + if ( xNativeControlContext.is() ) + { + m_xControlContextProxy = xFactory->createProxy( xNativeControlContext ); + m_xControlContextTypeAccess.set( xNativeControlContext, UNO_QUERY_THROW ); + m_xControlContextComponent.set( xNativeControlContext, UNO_QUERY_THROW ); - // some initialization for our child manager, which is used in alive mode only - if ( isAliveMode( m_xUnoControl ) ) + // aggregate the proxy + osl_atomic_increment( &m_refCount ); + if ( m_xControlContextProxy.is() ) { - sal_Int64 nStates( getAccessibleStateSet( ) ); - m_pChildManager->setTransientChildren( nStates & AccessibleStateType::MANAGES_DESCENDANTS ); + // At this point in time, the proxy has a ref count of exactly one - in m_xControlContextProxy. + // Remember to _not_ reset this member unless the delegator of the proxy has been reset, too! + m_xControlContextProxy->setDelegator( *this ); } + osl_atomic_decrement( &m_refCount ); - // finally, aggregate a proxy for the control context - // first a factory for the proxy - Reference< XProxyFactory > xFactory = ProxyFactory::create( comphelper::getProcessComponentContext() ); - // then the proxy itself - if ( xNativeControlContext.is() ) - { - m_xControlContextProxy = xFactory->createProxy( xNativeControlContext ); - m_xControlContextTypeAccess.set( xNativeControlContext, UNO_QUERY_THROW ); - m_xControlContextComponent.set( xNativeControlContext, UNO_QUERY_THROW ); - - // aggregate the proxy - osl_atomic_increment( &m_refCount ); - if ( m_xControlContextProxy.is() ) - { - // At this point in time, the proxy has a ref count of exactly one - in m_xControlContextProxy. - // Remember to _not_ reset this member unless the delegator of the proxy has been reset, too! - m_xControlContextProxy->setDelegator( *this ); - } - osl_atomic_decrement( &m_refCount ); - - m_bDisposeNativeContext = true; - - // Finally, we need to add ourself as mode listener to the control. In case the mode switches, - // we need to dispose ourself. - xControlModes->addModeChangeListener( this ); - } + m_bDisposeNativeContext = true; + + // Finally, we need to add ourself as mode listener to the control. In case the mode switches, + // we need to dispose ourself. + xControlModes->addModeChangeListener( this ); } } } commit 5cbd1c00c61cbda91adb836d4cd100be7bdde125 Author: Michael Weghorn <[email protected]> AuthorDate: Wed May 21 12:13:33 2025 +0200 Commit: Michael Weghorn <[email protected]> CommitDate: Thu May 22 05:50:16 2025 +0200 gtk3: Don't depend on a11y to detect tooltip win In RunDialog::windowOpened, don't rely on the the VCLXWindow currently usually is also being the XAccessible for a vcl::Window, which is an implementation detail and subject to change, see commit messsage of Change-Id: Id81ab5f90955ecc600e179164b5f9c7a771182d1 Author: Michael Weghorn <[email protected]> Date: Wed May 21 11:03:56 2025 +0200 sw a11y test: Don't rely on XWindow being XAccessible for further background. Instead, retrieve the vcl::Window and check the window type of that one directly to detect a tooltip. (See the mapping from window type to accessible role in Window::getDefaultAccessibleRole.) If continuing to use the a11y layer were necessary for any reason, an alternative could be to get the vcl::Window's XAccessible without it relying on it being the VCLXWindow, see the above-mentioned commit for an example. Sample scenario that triggers this code path and still behaves the same as without this commit in place: * start Writer with the gtk3 VCL plugin on Linux, create new doc * press Ctrl+N to create another new document * press Ctrl+S to open the file dialog for the second doc * switch back to the first doc * press Ctrl+N to open yet another doc -> The file dialog is popped down after a few moments because the logic in RunDialog::windowOpened still detects that the new window isn't a tooltip. Change-Id: I66c9d4c87c7ba96502d08ebc8ec52fdaabe132ba Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185603 Reviewed-by: Michael Weghorn <[email protected]> Tested-by: Jenkins diff --git a/vcl/unx/gtk3/fpicker/SalGtkPicker.cxx b/vcl/unx/gtk3/fpicker/SalGtkPicker.cxx index 0e81b9149eab..5bbf94d7b74f 100644 --- a/vcl/unx/gtk3/fpicker/SalGtkPicker.cxx +++ b/vcl/unx/gtk3/fpicker/SalGtkPicker.cxx @@ -26,6 +26,7 @@ #include <sal/log.hxx> #include <utility> #include <vcl/svapp.hxx> +#include <vcl/toolkit/unowrap.hxx> #include <tools/urlobj.hxx> #include <vcl/window.hxx> @@ -122,14 +123,14 @@ void SAL_CALL RunDialog::windowOpened(const css::lang::EventObject& e) //Don't popdown dialogs if a tooltip appears elsewhere, that's ok, but do pop down //if another dialog/frame is launched. - css::uno::Reference<css::accessibility::XAccessible> xAccessible(e.Source, css::uno::UNO_QUERY); - if (xAccessible.is()) + css::uno::Reference<css::awt::XWindow> xWindow(e.Source, css::uno::UNO_QUERY); + if (xWindow.is()) { - css::uno::Reference<css::accessibility::XAccessibleContext> xContext(xAccessible->getAccessibleContext()); - if (xContext.is() && xContext->getAccessibleRole() == css::accessibility::AccessibleRole::TOOL_TIP) - { + UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper(); + assert(pWrapper); + VclPtr<vcl::Window> pWindow = pWrapper->GetWindow(xWindow); + if (pWindow && pWindow->GetType() == WindowType::HELPTEXTWINDOW) return; - } } g_timeout_add_full(G_PRIORITY_HIGH_IDLE, 0, reinterpret_cast<GSourceFunc>(canceldialog), this, nullptr);
