4444UNICODE_BRAILLE_PROTECTED = u"⣿" # All dots down
4545
4646
47+ def _isDebugForBrailleInput ():
48+ return config .conf ["debugLog" ]["brailleInput" ]
49+
50+
4751class BrailleInputHandler (AutoPropertyObject ):
4852 """Handles braille input.
4953 """
@@ -118,7 +122,21 @@ def _get_currentFocusIsTextObj(self):
118122 useContractedForCurrentFocus : bool
119123
120124 def _get_useContractedForCurrentFocus (self ):
121- return self ._table .contracted and self .currentFocusIsTextObj and not self .currentModifiers
125+ return self ._table .contracted and not self .inputKeysUsingEmulation
126+
127+ # Provided by auto property: L{_get_inputKeysUsingEmulation}
128+ inputKeysUsingEmulation : bool
129+
130+ def _get_inputKeysUsingEmulation (self ):
131+ """
132+ Returns whether keyboard gesture emulation should be used to input keyboard keys.
133+ If this is C{False}, L{sendChars} is used.
134+ This should only apply when:
135+ * No modifiers are pressed
136+ * We are in a text field
137+ """
138+ return not self .currentFocusIsTextObj or self .currentModifiers
139+
122140
123141 def _translate (self , endWord : bool ) -> bool :
124142 """Translate buffered braille up to the cursor.
@@ -134,48 +152,64 @@ def _translate(self, endWord: bool) -> bool:
134152 pos = self .untranslatedStart + self .untranslatedCursorPos
135153 data = u"" .join ([chr (cell | LOUIS_DOTS_IO_START ) for cell in self .bufferBraille [:pos ]])
136154 mode = louis .dotsIO | louis .noUndefinedDots
137- if ( not self .currentFocusIsTextObj or self . currentModifiers ) and self ._table .contracted :
155+ if self .inputKeysUsingEmulation and self ._table .contracted :
138156 mode |= louis .partialTrans
139157 self .bufferText = louis .backTranslate (
140158 [os .path .join (brailleTables .TABLES_DIR , self ._table .fileName ),
141159 "braille-patterns.cti" ],
142160 data , mode = mode )[0 ]
143161 newText = self .bufferText [oldTextLen :]
162+ if _isDebugForBrailleInput ():
163+ log .debug (f"bufferText after translation = { self .bufferText } , newText = { newText } " )
144164 if newText :
145165 # New text was generated by the cells just entered.
146166 if self .useContractedForCurrentFocus or self .currentModifiers :
147167 # For contracted braille, an entire word is sent at once.
148168 # Don't speak characters as this is sent.
149169 # Also, suppress typed characters when emulating a command gesture.
170+ if _isDebugForBrailleInput ():
171+ log .debug ("Suppressing typed characters for contracted input" )
150172 speech ._suppressSpeakTypedCharacters (len (newText ))
151173 else :
152174 self ._uncontSentTime = time .time ()
153175 self .untranslatedStart = pos
154176 self .untranslatedCursorPos = 0
155- if self .currentModifiers or not self .currentFocusIsTextObj :
177+ if _isDebugForBrailleInput ():
178+ log .debug (
179+ f"currentModifiers = { self .currentModifiers } , currentFocusIsTextObj = { self .currentFocusIsTextObj } "
180+ )
181+ if self .inputKeysUsingEmulation :
156182 if len (newText )> 1 :
157183 # Emulation of multiple characters at once is unsupported
158184 # Clear newText, so this function returns C{False} if not at end of word
185+ if _isDebugForBrailleInput ():
186+ log .debug (f"Clearing newText, was { newText } " )
159187 newText = u""
160188 else :
161189 self .emulateKey (newText )
162190 else :
163191 self .sendChars (newText )
164192
165- if endWord or (newText and (not self .currentFocusIsTextObj or self .currentModifiers )):
193+ if endWord or (newText and (self .currentModifiers or not self .useContractedForCurrentFocus )):
166194 # We only need to buffer one word.
167195 # Clear the previous word (anything before the cursor) from the buffer.
196+ if _isDebugForBrailleInput ():
197+ log .debug (f"Clearing previous word from buffer" )
168198 del self .bufferBraille [:pos ]
169- self .bufferText = u ""
199+ self .bufferText = ""
170200 self .cellsWithText .clear ()
171201 self .currentModifiers .clear ()
172202 self .untranslatedStart = 0
173203 self .untranslatedCursorPos = 0
174204
175205 if newText or endWord :
176206 self ._updateUntranslated ()
207+ if _isDebugForBrailleInput ():
208+ log .debug ("Translate returning True" )
177209 return True
178210
211+ if _isDebugForBrailleInput ():
212+ log .debug ("Translate returning False" )
179213 return False
180214
181215 def _translateForReportContractedCell (self , pos ):
@@ -237,8 +271,12 @@ def _reportUntranslated(self, pos):
237271 def input (self , dots : int ):
238272 """Handle one cell of braille input.
239273 """
274+ if _isDebugForBrailleInput ():
275+ log .debug (f"Braille input received: 0X{ dots :02x} " )
240276 # Insert the newly entered cell into the buffer at the cursor position.
241277 pos = self .untranslatedStart + self .untranslatedCursorPos
278+ if _isDebugForBrailleInput ():
279+ log .debug (f"Inserting 0X{ dots :02x} at position { pos } in bufferBraille" )
242280 self .bufferBraille .insert (pos , dots )
243281 self .untranslatedCursorPos += 1
244282 # Space ends the word.
@@ -249,10 +287,17 @@ def input(self, dots: int):
249287 # This is because later cells can change characters produced by previous cells.
250288 # For example, in English grade 2, "tg" produces just "tg",
251289 # but "tgr" produces "together".
290+ if _isDebugForBrailleInput ():
291+ log .debug (
292+ f"useContractedForCurrentFocus = { self .useContractedForCurrentFocus } , "
293+ f"input is end of word = { endWord } "
294+ )
252295 if not self .useContractedForCurrentFocus or endWord :
253296 if self ._translate (endWord ):
254297 if not endWord :
255298 self .cellsWithText .add (pos )
299+ if _isDebugForBrailleInput ():
300+ log .debug (f"Added { pos } to cellsWithText, now { self .cellsWithText } " )
256301 elif self .bufferText and not self .useContractedForCurrentFocus :
257302 # Translators: Reported when translation didn't succeed due to unsupported input.
258303 speech .speakMessage (_ ("Unsupported input" ))
@@ -374,6 +419,8 @@ def emulateKey(self, key: str, withModifiers: bool = True):
374419 @param withModifiers: Whether this key emulation should include the modifiers that are held virtually.
375420 Note that this method does not take care of clearing L{self.currentModifiers}.
376421 """
422+ if _isDebugForBrailleInput ():
423+ log .debug (f"Emulating { key } " )
377424 if withModifiers :
378425 # The emulated key should be the last item in the identifier string.
379426 keys = list (self .currentModifiers )
@@ -384,13 +431,19 @@ def emulateKey(self, key: str, withModifiers: bool = True):
384431 try :
385432 inputCore .manager .emulateGesture (keyboardHandler .KeyboardInputGesture .fromName (gesture ))
386433 except :
387- log .debugWarning ("Unable to emulate %r, falling back to sending unicode characters" % gesture , exc_info = True )
434+ if _isDebugForBrailleInput ():
435+ log .debugWarning (
436+ f"Unable to emulate { gesture } , falling back to sending unicode characters" ,
437+ exc_info = True
438+ )
388439 self .sendChars (key )
389440
390441 def sendChars (self , chars : str ):
391442 """Sends the provided unicode characters to the system.
392443 @param chars: The characters to send to the system.
393444 """
445+ if _isDebugForBrailleInput ():
446+ log .debug (f"Sending characters: { chars } " )
394447 inputs = []
395448 chars = '' .join (
396449 ch if ord (ch ) <= 0xffff else '' .join (
0 commit comments