wizards/source/scriptforge/SF_Platform.xba    |   28 +++++++---
 wizards/source/scriptforge/script.xlb         |   26 ++++-----
 wizards/source/sfdocuments/SF_Calc.xba        |    7 ++
 wizards/source/sfdocuments/SF_Writer.xba      |    2 
 wizards/source/sfwidgets/SF_Toolbar.xba       |   70 ++++++++++++++++++++++++--
 wizards/source/sfwidgets/SF_ToolbarButton.xba |   26 +++++++--
 6 files changed, 126 insertions(+), 33 deletions(-)

New commits:
commit 1c81dbad870c2befad699e14e3694d684cf3064d
Author:     Jean-Pierre Ledure <[email protected]>
AuthorDate: Tue Sep 30 16:09:54 2025 +0200
Commit:     Xisco Fauli <[email protected]>
CommitDate: Wed Oct 1 12:39:44 2025 +0200

    ScriptForge fix tdf#168409 AccessibleContext
    
    Extract from above bug report:
     The accessibility UNO API is unpublished and
     for LibreOffice-internal use only and
     subject to change by design.
    
    The com.sub.star.accessibility.AccessibleContext
    service is used in ScriptForge to determine
    the location on the screen, in pixels, of
    next window subsets:
    (1) a Calc cell or cellrange
        => calc.XRectangle(range) property
    (2) a toolbarbutton in a docked toolbar
        => toolbar.ToolbarButtons(buttonname) method
    In both situations, SF offers a facility
    to display a well-positioned popup menu
    triggered by a mouse left-  or right-click.
    
    The situation of the API is as follows:
    - fully available in 25.2
    - partially available in 25.8
      (1) is not broken
      (2) is broken
    - fully vanished in 26.2
    
    The gradual phase-out of the API requires,
    to fix the bug, a tiered adaptation of
    the code.
    The choice is made to incorporate, where
    appropriate, a switch to the right code
    snippet based on the run LibreOffice version:
    25.2, 25.8 or 26.2.
    
    Now the behaviours in 25.2 and 25.8 are
    identical. In 26.2, a different location
    is returned for undocked toolbars.
    
    The solution used for 26.2 must be considered
    as still subject to change.
    The emergency is to fix the issue in 25.8,
    which is currently broken.
    
    With the actual patch, the compatibility
    between releases is restored, both in
    Basic and Pythonuser scripts, and does
    not need any documentation revision.
    
    Change-Id: I29b4ccca3f11eca39e5a1841d3cfd744d5eb1fe3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191670
    Tested-by: Jenkins
    Reviewed-by: Jean-Pierre Ledure <[email protected]>
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191708
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/wizards/source/scriptforge/SF_Platform.xba 
b/wizards/source/scriptforge/SF_Platform.xba
index c5baf10f6f4c..d0b40c81161c 100644
--- a/wizards/source/scriptforge/SF_Platform.xba
+++ b/wizards/source/scriptforge/SF_Platform.xba
@@ -347,26 +347,40 @@ Catch:
 End Function   &apos;  ScriptForge.SF_Platform._GetPrinters
 
 REM 
-----------------------------------------------------------------------------
-Public Function _GetProductName() as String
-&apos;&apos;&apos;     Returns Office product and version numbers found in 
configuration registry
+Public Function _GetProductName(Optional ByVal pvNumber As Variant) as Variant
+&apos;&apos;&apos;     Returns Office product and version numbers found in 
configuration registry as a string,
+&apos;&apos;&apos;     or the version number only, as a Single
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             pvNumber: when True (default = False), returns 
the version number as a Single.
+&apos;&apos;&apos;                               For internal use only.
+&apos;&apos;&apos;     
 &apos;&apos;&apos;     Derived from the Tools library
 
 Dim oProdNameAccess as Object          &apos;  configmgr.RootAccess
 Dim sProdName as String
 Dim sVersion as String
+Dim sngVersion As Single
+Dim vVersion As Variant                                &apos;  Array of 
version subcomponents
+Dim sDecimalPoint As String
 Dim sVendor As String
 
        On Local Error GoTo Catch       &apos;  Prevent any error
+       If IsMissing(pvNumber) Or IsEmpty(pvNumber) Then pvNumber = False
        _GetProductName = &quot;&quot;
 
 Try:
        Set oProdNameAccess = 
SF_Utils._GetRegistryKeyContent(&quot;org.openoffice.Setup/Product&quot;)
 
-       sProdName = oProdNameAccess.ooName
-       sVersion = oProdNameAccess.ooSetupVersionAboutBox
-       sVendor = oProdNameAccess.ooVendor
-
-       _GetProductName = sProdName &amp; &quot; &quot; &amp; sVersion &amp; 
&quot; (&quot; &amp; sVendor &amp; &quot;)&quot;
+       If pvNumber Then        &apos;  Return the version number
+               vVersion = Split(oProdNameAccess.ooSetupVersionAboutBox, 
&quot;.&quot;)
+               sDecimalPoint = Mid(CStr(1.2), 2, 1)
+               If UBound(vVersion) &gt; 0 Then _GetProductName = 
CSng(vVersion(0) &amp; sDecimalPoint &amp; vVersion(1)) Else _GetProductName = 
CSng(0.0)
+       Else                            &apos;  Return the verbose version 
string
+               sProdName = oProdNameAccess.ooName
+               sVersion = oProdNameAccess.ooSetupVersionAboutBox
+               sVendor = oProdNameAccess.ooVendor
+               _GetProductName = sProdName &amp; &quot; &quot; &amp; sVersion 
&amp; &quot; (&quot; &amp; sVendor &amp; &quot;)&quot;
+       End If
 
 Finally:
        Exit Function
diff --git a/wizards/source/scriptforge/script.xlb 
b/wizards/source/scriptforge/script.xlb
index af8f6a75dc96..0a510dbc4109 100644
--- a/wizards/source/scriptforge/script.xlb
+++ b/wizards/source/scriptforge/script.xlb
@@ -2,22 +2,22 @@
 <!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 
1.0//EN" "library.dtd">
 <library:library xmlns:library="http://openoffice.org/2000/library"; 
library:name="ScriptForge" library:readonly="false" 
library:passwordprotected="false">
  <library:element library:name="_CodingConventions"/>
- <library:element library:name="_ModuleModel"/>
- <library:element library:name="SF_String"/>
- <library:element library:name="__License"/>
- <library:element library:name="SF_Root"/>
+ <library:element library:name="SF_Session"/>
+ <library:element library:name="SF_Dictionary"/>
+ <library:element library:name="SF_Exception"/>
+ <library:element library:name="SF_UI"/>
+ <library:element library:name="SF_Services"/>
+ <library:element library:name="SF_PythonHelper"/>
+ <library:element library:name="SF_Platform"/>
+ <library:element library:name="SF_Array"/>
  <library:element library:name="SF_TextStream"/>
  <library:element library:name="SF_Utils"/>
- <library:element library:name="SF_Platform"/>
- <library:element library:name="SF_PythonHelper"/>
+ <library:element library:name="SF_String"/>
+ <library:element library:name="_ModuleModel"/>
  <library:element library:name="SF_L10N"/>
  <library:element library:name="SF_Region"/>
- <library:element library:name="SF_Array"/>
- <library:element library:name="SF_UI"/>
- <library:element library:name="SF_Services"/>
- <library:element library:name="SF_Session"/>
- <library:element library:name="SF_Exception"/>
- <library:element library:name="SF_Dictionary"/>
+ <library:element library:name="SF_Root"/>
+ <library:element library:name="__License"/>
  <library:element library:name="SF_FileSystem"/>
  <library:element library:name="SF_Timer"/>
-</library:library>
\ No newline at end of file
+</library:library>
diff --git a/wizards/source/sfdocuments/SF_Calc.xba 
b/wizards/source/sfdocuments/SF_Calc.xba
index b627413c8164..69f17353e2ed 100644
--- a/wizards/source/sfdocuments/SF_Calc.xba
+++ b/wizards/source/sfdocuments/SF_Calc.xba
@@ -5374,7 +5374,12 @@ Try:
        Set oController = _Component.CurrentController
        Set oXRange = _ParseAddress(psRange).XCellRange
        &apos;  Grab the window location on the screen
-       Set oLocation = 
oController.ComponentWindow.AccessibleContext.LocationOnScreen
+       Select Case ScriptForge.SF_Platform._GetProductName(True)       &apos;  
Get a sortable release number
+               Case &lt;= 25.8
+                       Set oLocation = 
oController.ComponentWindow.AccessibleContext.LocationOnScreen
+               Case Else
+                       Set oLocation = 
oController.ComponentWindow.getProperty(&quot;XAccessible&quot;).LocationOnScreen
+       End Select
 
        With oRect
                .X = oXRange.Position.X
diff --git a/wizards/source/sfdocuments/SF_Writer.xba 
b/wizards/source/sfdocuments/SF_Writer.xba
index 307f9f6682c4..dab61fcfe0d6 100644
--- a/wizards/source/sfdocuments/SF_Writer.xba
+++ b/wizards/source/sfdocuments/SF_Writer.xba
@@ -1047,7 +1047,7 @@ Dim i As Long
                                End Select
 
                        &apos;  Body
-                       Case oStr.IsRegex(psTextRange, 
&quot;\|0\s*?BODY\s*\|?&quot;)
+                       Case oStr.IsRegex(psTextRange, 
&quot;\|?\s*BODY\s*\|?&quot;)
                                Set .Text = _Component.Text
                                Set .Anchor = .Text.Start
                                Set .Cursor = .Text.createTextCursor()
diff --git a/wizards/source/sfwidgets/SF_Toolbar.xba 
b/wizards/source/sfwidgets/SF_Toolbar.xba
index 1f8329ed1423..6ed2a7fa1ca7 100644
--- a/wizards/source/sfwidgets/SF_Toolbar.xba
+++ b/wizards/source/sfwidgets/SF_Toolbar.xba
@@ -67,7 +67,7 @@ Private _Component                            As Object       
        &apos; com.sun.star.lang.XComponent
 Private _ResourceURL                   As String               &apos; Toolbar 
internal name
 Private _UIName                                        As String               
&apos; Toolbar external name, may be &quot;&quot;
 Private _UIConfigurationManager        As Object               &apos; 
com.sun.star.ui.XUIConfigurationManager
-Private _ElementsInfoIndex             As Long                 &apos; Index of 
the toolbar in the getElementsInfo(0) array
+Private _ElementsInfoIndex             As Long                 &apos; Index of 
the toolbar in the UIConfigurationManager.getElementsInfo(0) array
 Private _Storage                               As Long                 &apos; 
One of the toolbar location constants
 Private _LayoutManager                 As Object               &apos; 
com.sun.star.comp.framework.LayoutManager
 
@@ -342,8 +342,8 @@ REM 
=========================================================== PRIVATE FUNCTION
 REM 
-----------------------------------------------------------------------------
 Private Sub _CollectAllButtons()
 &apos;&apos;&apos;     Stores a SF_Dictionary object instance, with
-&apos;&apos;&apos;     - key = name of the button
-&apos;&apos;&apos;     - item = a _ButtonDesc object type
+&apos;&apos;&apos;             - key = name of the button
+&apos;&apos;&apos;             - item = a _ButtonDesc object type
 &apos;&apos;&apos;     into _ToolbarButtons, a cache for all buttons.
 &apos;&apos;&apos;     The toolbar is made visible before collecting the 
buttons.
 &apos;&apos;&apos;
@@ -358,6 +358,7 @@ Dim oElement As Object                              &apos;  
com.sun.star.ui.XUIElement
 Dim oSettings As Object                                &apos;  
com.sun.star.container.XIndexAccess
 Dim vProperties() As Variant           &apos;  Array of property values
 Dim iType As Integer                           &apos;  Separators have type = 
1, others have Type = 0
+Dim oAccessibleContext As Object       &apos;  Toolbar&apos;s 
com.sun.star.accessibility.XAccessibleContext
 Dim oAccessible As Object                      &apos;  
com.sun.star.accessibility.XAccessible
 Dim sLabel As String                           &apos;  Label in static 
description
 Dim sAccessibleName As String          &apos;  Name in AccessibleContext
@@ -373,7 +374,15 @@ Try:
        Visible = True
 
        Set _ToolbarButtons = 
ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Dictionary&quot;, 
True)     &apos;  with case-sensitive comparison of keys
+
+       &apos;  Find the com.sun.star.ui.XUIElement of the toolbar
        Set oElement = _LayoutManager.getElement(_ResourceURL)
+
+       &apos;  Determine the accessible context of the toolbar
+       Set oAccessibleContext = _GetAccessibleContext(oElement)
+       If IsNull(oAccessibleContext) Then GoTo Catch
+
+       &apos;  The settings contain the info that we need
        Set oSettings = oElement.getSettings(True)
 
        With oSettings
@@ -383,7 +392,7 @@ Try:
                        If iType = 0 Then               &apos;  Usual button
                                sLabel = 
ScriptForge.SF_Utils._GetPropertyValue(vProperties, &quot;Label&quot;)
                                If Len(sLabel) = 0 Then
-                                       Set oAccessible = 
oElement.RealInterface.AccessibleContext.getAccessibleChild(i)
+                                       Set oAccessible = 
oAccessibleContext.getAccessibleChild(i)
                                        sAccessibleName = 
oAccessible.AccessibleName
                                Else
                                        sAccessibleName = &quot;&quot;
@@ -414,12 +423,63 @@ Catch:
        GoTo Finally
 End Sub                        &apos;  SFWidgets.SF_Toolbar._CollectAllButtons
 
+REM 
-----------------------------------------------------------------------------
+Public Function _GetAccessibleContext(poElement As Object) As Object
+&apos;&apos;&apos;     Determine the accessible context of the toolbar
+&apos;&apos;&apos;             See bug 
https://bugs.documentfoundation.org/show_bug.cgi?id=168409
+&apos;&apos;&apos;             Finding the accessible context is 
release-dependent due to phase-out of unpublished API
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             poElement: the com.sun.star.ui.XUIElement 
describing the toolbar
+
+Dim dVersion As Single                         &apos;  LibreOffice release 
number
+Dim oElement As Object                         &apos;  
com.sun.star.ui.XUIElement
+Dim bFloating As Boolean                       &apos;  True when poElement is 
not docked
+Dim lIndex As Long                                     &apos;  Index of the 
toolbar in the LayoutManager.getElements array
+Dim oAccessibleContext As Object       &apos;  Toolbar&apos;s 
com.sun.star.accessibility.XAccessibleContext
+
+Check:
+       On Local Error GoTo Catch
+       Set oAccessibleContext = Nothing
+       If IsNull(poElement) Then GoTo Catch
+
+Try:
+       dVersion = ScriptForge.SF_Platform._GetProductName(True)        &apos;  
Get a sortable release number
+
+       With poElement.RealInterface
+               Select Case dVersion
+                       Case &lt;= 25.2 :       Set oAccessibleContext = 
.AccessibleContext
+                       Case 25.8
+                               &apos;  Find the com.sun.star.ui.XUIElement of 
the toolbar and its index in the list
+                               lIndex = -1
+                               bFloating = poElement.RealInterface.isFloating()
+                               For Each oElement In 
_LayoutManager.getElements()
+                                       &apos;  When undocked, count undocked 
elements only, otherwise count all elements
+                                       If bFloating Then
+                                               If 
oElement.RealInterface.isFloating() Then lIndex = lIndex + 1
+                                       Else
+                                               lIndex = lIndex + 1
+                                       End If
+                                       If oElement.ResourceURL = _ResourceURL 
Then Exit For
+                               Next oElement
+                               Set oAccessibleContext = 
.AccessibleContext.AccessibleParent.AccessibleContext.getAccessibleChild(lIndex)
+                       Case &gt;= 26.2 :       Set oAccessibleContext = 
.getProperty(&quot;XAccessible&quot;)
+                       Case Else               :       GoTo Catch
+               End Select
+       End With
+
+Finally:
+       Set _GetAccessibleContext = oAccessibleContext
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  &apos;  SFWidgets.SF_Toolbar._GetAccessibleContext
+
 REM 
-----------------------------------------------------------------------------
 Public Sub _Initialize(ByRef poToolbar As Object)
 &apos;&apos;&apos;     Complete the object creation process:
 &apos;&apos;&apos;             - Initialize the toolbar descriptioner use
 &apos;&apos;&apos;     Args:
-&apos;&apos;&apos;             poToolbar: the toolbar description as a 
ui._Toolbr object
+&apos;&apos;&apos;             poToolbar: the toolbar description as a 
ui._Toolbar object
 
 Try:
        &apos;  Store the static description
diff --git a/wizards/source/sfwidgets/SF_ToolbarButton.xba 
b/wizards/source/sfwidgets/SF_ToolbarButton.xba
index a5c3ccd03064..07ae7eaaa0a1 100644
--- a/wizards/source/sfwidgets/SF_ToolbarButton.xba
+++ b/wizards/source/sfwidgets/SF_ToolbarButton.xba
@@ -400,19 +400,33 @@ Dim oRect As Object                                       
                &apos;  Return value As com.sun.star.awt.Rectangle
 Try:
        Set oElement = _Element.GetSettings(True).getByIndex(_Index)
        Set oRect = CreateUnoStruct(&quot;com.sun.star.awt.Rectangle&quot;)
+
+       &apos;  The button must be visible
        If ScriptForge.SF_Utils._GetPropertyValue(oElement, 
&quot;IsVisible&quot;) Then
-               Set oAccessible = 
_Element.getRealInterface().getAccessibleContext()    &apos;  Toolbar level
+               Set oAccessible = [_Parent]._GetAccessibleContext(_Element)     
                        &apos;  Toolbar level
                Set oAccessibleParent = oAccessible.getAccessibleParent()       
                        &apos;  Window level
                Set oAccessibleButton = oAccessible.getAccessibleChild(_Index)  
                &apos;  Toolbar button level
+
                &apos;  The X and Y coordinates are always computed correctly 
when the toolbar is docked.
                &apos;  When the toolbar is floating, the Y ordinate may be 
overestimated with the height of
-               &apos;  the tabbed bar or similar. However no mean has been 
found to get that height via code.
+               &apos;  the tabbed bar. However no mean has been found to get 
that height via code.
                With oRect
-                       .X = oAccessible.Location.X + 
oAccessibleButton.Location.X + oAccessibleParent.PosSize.X
-                       .Y = oAccessible.Location.Y + 
oAccessibleButton.Location.Y + oAccessibleParent.PosSize.Y
-                       .Height = oAccessibleButton.Size.Height
-                       .Width = oAccessibleButton.Size.Width
+                       &apos;  See bug 
https://bugs.documentfoundation.org/show_bug.cgi?id=168409
+                       &apos;  Finding the button coordinates is 
release-dependent due to phase-out of unpublished API
+                       Select case 
ScriptForge.SF_Platform._GetProductName(True)       &apos;  Get a sortable 
release number
+                               Case &lt;= 25.8
+                                       .X = oAccessible.Location.X + 
oAccessibleButton.Location.X + oAccessibleParent.PosSize.X
+                                       .Y = oAccessible.Location.Y + 
oAccessibleButton.Location.Y + oAccessibleParent.PosSize.Y
+                               Case Else               &apos;  &gt;= 26.2
+                                       .X = oAccessible.LocationOnScreen.X + 
oAccessibleButton.Location.X - oAccessibleParent.LocationOnScreen.X
+                                       .Y = oAccessible.LocationOnScreen.Y + 
oAccessibleButton.Location.Y - oAccessibleParent.LocationOnScreen.Y
+                       End Select
+                       If _Height = 0 Then _Height = 
oAccessibleButton.Size.Height
+                       .Height = _Height
+                       If _Width = 0 Then _Width = oAccessibleButton.Size.Width
+                       .Width = _Width
                End With
+
        Else
                With oRect
                        .X = -1 :       .Y = -1 :       .Height = 0     :       
.Width = 0

Reply via email to