6161from autoSettingsUtils .driverSetting import BooleanDriverSetting , NumericDriverSetting
6262from utils .security import objectBelowLockScreenAndWindowsIsLocked
6363import hwIo
64+ from buildVersion import version_year
65+ import NVDAState
6466
6567if TYPE_CHECKING :
6668 from NVDAObjects import NVDAObject
@@ -1569,6 +1571,7 @@ def bufferPosToRegionPos(self, bufferPos):
15691571 raise LookupError ("No such position" )
15701572
15711573 def regionPosToBufferPos (self , region , pos , allowNearest = False ):
1574+ start : int = 0
15721575 for testRegion , start , end in self .regionsWithPositions :
15731576 if region == testRegion :
15741577 if pos < end - start :
@@ -2014,6 +2017,11 @@ class BrailleHandler(baseObject.AutoPropertyObject):
20142017 queuedWrite : Optional [List [int ]] = None
20152018 queuedWriteLock : threading .Lock
20162019 ackTimerHandle : int
2020+ _regionsPendingUpdate : Set [Region ]
2021+ """
2022+ Regions pending an update.
2023+ Regions are added by L{handleUpdate} and L{handleCaretMove} and cleared in L{_handlePendingUpdate}.
2024+ """
20172025
20182026 def __init__ (self ):
20192027 louisHelper .initialize ()
@@ -2032,6 +2040,7 @@ def __init__(self):
20322040 with its previous output.
20332041 If L{decide_enabled} decides to disable the handler, pending output should be cleared.
20342042 """
2043+ self ._regionsPendingUpdate = set ()
20352044
20362045
20372046 self .mainBuffer = BrailleBuffer (self )
@@ -2472,29 +2481,46 @@ def handleCaretMove(
24722481 region = self .mainBuffer .regions [- 1 ] if self .mainBuffer .regions else None
24732482 if region and region .obj == obj :
24742483 region .pendingCaretUpdate = True
2484+ self ._regionsPendingUpdate .add (region )
24752485 elif prevTether == TetherTo .REVIEW .value :
24762486 # The caret moved in a different object than the review position.
24772487 self ._doNewObject (getFocusRegions (obj , review = False ))
24782488
2479- def handlePendingCaretUpdate ( self ):
2480- """Checks to see if the final text region needs its caret updated and if so calls _doCursorMove for the region."""
2481- region = self . mainBuffer . regions [ - 1 ] if self . mainBuffer . regions else None
2482- if isinstance ( region , TextInfoRegion ) and region . pendingCaretUpdate :
2483- try :
2484- self . _doCursorMove ( region )
2485- finally :
2486- region . pendingCaretUpdate = False
2489+ if version_year < 2024 and NVDAState . _allowDeprecatedAPI ( ):
2490+ def handlePendingCaretUpdate ( self ):
2491+ log . warning (
2492+ "braille.BrailleHandler.handlePendingCaretUpdate is now deprecated "
2493+ "with no public replacement. "
2494+ "It will be removed in NVDA 2024.1."
2495+ )
2496+ self . _handlePendingUpdate ()
24872497
2488- def _doCursorMove (self , region ):
2489- self .mainBuffer .saveWindow ()
2490- region .update ()
2491- self .mainBuffer .update ()
2492- self .mainBuffer .restoreWindow ()
2493- self .scrollToCursorOrSelection (region )
2494- if self .buffer is self .mainBuffer :
2495- self .update ()
2496- elif self .buffer is self .messageBuffer and keyboardHandler .keyCounter > self ._keyCountForLastMessage :
2497- self ._dismissMessage ()
2498+ def _handlePendingUpdate (self ):
2499+ """When any region is pending an update, updates the region and the braille display.
2500+ """
2501+ if not self ._regionsPendingUpdate :
2502+ return
2503+ try :
2504+ scrollTo : Optional [TextInfoRegion ] = None
2505+ self .mainBuffer .saveWindow ()
2506+ for region in self ._regionsPendingUpdate :
2507+ region .update ()
2508+ if isinstance (region , TextInfoRegion ) and region .pendingCaretUpdate :
2509+ scrollTo = region
2510+ region .pendingCaretUpdate = False
2511+ self .mainBuffer .update ()
2512+ self .mainBuffer .restoreWindow ()
2513+ if scrollTo is not None :
2514+ self .scrollToCursorOrSelection (scrollTo )
2515+ if self .buffer is self .mainBuffer :
2516+ self .update ()
2517+ elif (
2518+ self .buffer is self .messageBuffer
2519+ and keyboardHandler .keyCounter > self ._keyCountForLastMessage
2520+ ):
2521+ self ._dismissMessage ()
2522+ finally :
2523+ self ._regionsPendingUpdate .clear ()
24982524
24992525 def scrollToCursorOrSelection (self , region ):
25002526 if region .brailleCursorPos is not None :
@@ -2548,14 +2574,7 @@ def handleUpdate(self, obj: "NVDAObject") -> None:
25482574 if isinstance (obj , NVDAObject ) and obj .role == controlTypes .Role .PROGRESSBAR and obj .isInForeground :
25492575 self ._handleProgressBarUpdate (obj )
25502576 return
2551- self .mainBuffer .saveWindow ()
2552- region .update ()
2553- self .mainBuffer .update ()
2554- self .mainBuffer .restoreWindow ()
2555- if self .buffer is self .mainBuffer :
2556- self .update ()
2557- elif self .buffer is self .messageBuffer and keyboardHandler .keyCounter > self ._keyCountForLastMessage :
2558- self ._dismissMessage ()
2577+ self ._regionsPendingUpdate .add (region )
25592578
25602579 def handleReviewMove (self , shouldAutoTether = True ):
25612580 if not self .enabled :
@@ -2567,7 +2586,8 @@ def handleReviewMove(self, shouldAutoTether=True):
25672586 return
25682587 region = self .mainBuffer .regions [- 1 ] if self .mainBuffer .regions else None
25692588 if region and region .obj == reviewPos .obj :
2570- self ._doCursorMove (region )
2589+ region .pendingCaretUpdate = True
2590+ self ._regionsPendingUpdate .add (region )
25712591 else :
25722592 # We're reviewing a different object.
25732593 self ._doNewObject (getFocusRegions (reviewPos .obj , review = True ))
@@ -2720,14 +2740,15 @@ def initialize():
27202740 handler .setDisplayByName (config .conf ["braille" ]["display" ])
27212741
27222742def pumpAll ():
2723- """Runs tasks at the end of each core cycle. For now just caret updates."""
2724- handler .handlePendingCaretUpdate ()
2743+ """Runs tasks at the end of each core cycle. For now just region updates, e.g. for caret movement ."""
2744+ handler ._handlePendingUpdate ()
27252745
27262746def terminate ():
27272747 global handler
27282748 handler .terminate ()
27292749 handler = None
27302750
2751+
27312752class BrailleDisplayDriver (driverHandler .Driver ):
27322753 """Abstract base braille display driver.
27332754 Each braille display driver should be a separate Python module in the root brailleDisplayDrivers directory
0 commit comments