https://bugs.documentfoundation.org/show_bug.cgi?id=173639

            Bug ID: 173639
           Summary: Accessibility: ~900 AT-SPI events from up to 170
                    objects every time focus moves between two LibreOffice
                    windows (toolbars rebuilt, many sources already
                    defunct)
           Product: LibreOffice
           Version: 25.2.3.2 release
          Hardware: ARM
                OS: Linux (All)
            Status: UNCONFIRMED
          Severity: normal
          Priority: medium
         Component: UI
          Assignee: [email protected]
          Reporter: [email protected]

LibreOffice 25.2.3.2 (Debian 13.7 package 4:25.2.3-2+deb13u6, aarch64), gtk3
VCL plugin (SAL_USE_VCLPLUGIN=gtk3), at-spi2-core 2.56.2, X11 (Xvfb, no window
manager).

Steps to reproduce:
1. In one soffice process open a Writer document and a Calc document (two
windows).
2. Register an AT-SPI event listener for "object:" and "window:" events
(pyatspi).
3. Move X input focus from the Calc window to the Writer window (xdotool
windowfocus), wait 3 seconds, count the events. Then move it back.

Actual results:
Each focus change emits about 890 events from 84 to 167 distinct objects:

  Calc -> Writer: 888 events from 84 objects: object:state-changed 390,
object:property-change 242, object:bounds-changed 146, object:children-changed
108, window:deactivate 1, window:activate 1
  Writer -> Calc: 892 events from 167 objects: object:state-changed 390,
object:property-change 242, object:bounds-changed 149, object:children-changed
108, window:deactivate 1, window:activate 1

The sources are the toolbars, toolbar buttons and panels of both windows: the
toolbars of the window being activated and of the one being deactivated are
torn down and rebuilt (the children-changed events). About 60 of the sources
are already defunct by the time the event is delivered (calling GetApplication
on them raises "The application no longer exists"), and about 36 more have role
"invalid".

Expected results:
Activating a window should not rebuild its toolbars' accessible objects, and
objects that are destroyed should not emit events after their destruction. A
handful of state-changed:active/focused events and the
window:activate/deactivate pair would be the expected cost of a window switch.

Why it matters:
A screen reader or automation client pays for every one of those events on
every Alt-Tab between two LibreOffice windows; a client that re-reads what
changed re-reads two windows' toolbars each time. In our client that switch
costs about a second even after coalescing sources and dropping the defunct
ones.

Reproducer (python3-pyatspi + xdotool, with a Writer and a Calc window open):

  import pyatspi, subprocess, time
  from gi.repository import GLib
  count = {"n": 0, "types": {}, "srcs": set()}
  def spy(e):
      count["n"] += 1
      t = str(e.type); t = t.rsplit(":", 1)[0] if t.count(":") > 1 else t
      count["types"][t] = count["types"].get(t, 0) + 1
      count["srcs"].add(id(e.source))
  for ev in ("object:", "window:"):
      pyatspi.Registry.registerEventListener(spy, ev)
  ctx = GLib.MainContext.default()
  def pump(seconds):
      end = time.time() + seconds
      while time.time() < end:
          while ctx.pending(): ctx.iteration(False)
          time.sleep(0.01)
  def wid(title):
      return subprocess.run(["xdotool", "search", "--onlyvisible", "--name",
title], capture_output=True, text=True).stdout.split()[-1]
  def focus(w):
      subprocess.run(["xdotool", "windowraise", w]); subprocess.run(["xdotool",
"windowfocus", "--sync", w])
  w_writer, w_calc = wid("LibreOffice Writer"), wid("LibreOffice Calc")
  focus(w_calc); pump(2.5)
  for label, w in (("Calc -> Writer", w_writer), ("Writer -> Calc", w_calc)):
      count["n"] = 0; count["types"] = {}; count["srcs"] = set()
      focus(w); pump(3.0)
      print(label, count["n"], "events from", len(count["srcs"]), "objects:",
sorted(count["types"].items(), key=lambda kv: -kv[1]))

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to