Refactor complete. We should be in very good shape moving forward.
This commit is contained in:
@@ -20,6 +20,7 @@ This repository is a screen reader. Prioritize accessibility, correctness, and s
|
|||||||
- variables: `camelCase`
|
- variables: `camelCase`
|
||||||
- functions/methods: `snake_case`
|
- functions/methods: `snake_case`
|
||||||
- classes: `PascalCase`
|
- classes: `PascalCase`
|
||||||
|
- Keep changes clean and well-structured; avoid layering short-term workarounds when a focused fix is possible.
|
||||||
- Add debug logs where helpful for troubleshooting. When adding timestamps to logs, use: `"Message [timestamp]"` (message first).
|
- Add debug logs where helpful for troubleshooting. When adding timestamps to logs, use: `"Message [timestamp]"` (message first).
|
||||||
|
|
||||||
## Accessibility requirements (high priority)
|
## Accessibility requirements (high priority)
|
||||||
|
|||||||
+21
-4
@@ -255,14 +255,31 @@ def _asString(obj):
|
|||||||
|
|
||||||
return str(obj)
|
return str(obj)
|
||||||
|
|
||||||
|
def _format_tokens(tokens):
|
||||||
|
text = " ".join(map(_asString, tokens))
|
||||||
|
text = re.sub(r"[ \u00A0]+", " ", text)
|
||||||
|
text = re.sub(r" (?=[,.:)])(?![\n])", "", text)
|
||||||
|
return text
|
||||||
|
|
||||||
|
def format_log_message(prefix, message, reason=None):
|
||||||
|
text = f"{prefix}: {message}"
|
||||||
|
if reason:
|
||||||
|
text = f"{text} (reason={reason})"
|
||||||
|
return text
|
||||||
|
|
||||||
|
def print_log(level, prefix, message, reason=None, timestamp=False, stack=False):
|
||||||
|
text = format_log_message(prefix, message, reason)
|
||||||
|
printMessage(level, text, timestamp, stack)
|
||||||
|
|
||||||
|
def print_log_tokens(level, prefix, tokens, reason=None, timestamp=False, stack=False):
|
||||||
|
text = format_log_message(prefix, _format_tokens(tokens), reason)
|
||||||
|
printMessage(level, text, timestamp, stack)
|
||||||
|
|
||||||
def printTokens(level, tokens, timestamp=False, stack=False):
|
def printTokens(level, tokens, timestamp=False, stack=False):
|
||||||
if level < debugLevel:
|
if level < debugLevel:
|
||||||
return
|
return
|
||||||
|
|
||||||
text = " ".join(map(_asString, tokens))
|
println(level, _format_tokens(tokens), timestamp, stack)
|
||||||
text = re.sub(r"[ \u00A0]+", " ", text)
|
|
||||||
text = re.sub(r" (?=[,.:)])(?![\n])", "", text)
|
|
||||||
println(level, text, timestamp, stack)
|
|
||||||
|
|
||||||
def print_tokens(level, tokens, timestamp=False, stack=False):
|
def print_tokens(level, tokens, timestamp=False, stack=False):
|
||||||
return printTokens(level, tokens, timestamp, stack)
|
return printTokens(level, tokens, timestamp, stack)
|
||||||
|
|||||||
@@ -238,12 +238,12 @@ class EventManager:
|
|||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
|
||||||
def _log_ignore(reason, message):
|
def _log_ignore(reason, message):
|
||||||
msg = f"EVENT MANAGER: Ignoring ({reason}) - {message}"
|
debug.print_log(debug.LEVEL_INFO, "EVENT MANAGER",
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
f"Ignoring - {message}", reason, True)
|
||||||
|
|
||||||
def _log_allow(reason, message):
|
def _log_allow(reason, message):
|
||||||
msg = f"EVENT MANAGER: Not ignoring ({reason}) - {message}"
|
debug.print_log(debug.LEVEL_INFO, "EVENT MANAGER",
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
f"Not ignoring - {message}", reason, True)
|
||||||
|
|
||||||
def _ignore_with_reason(reason, message):
|
def _ignore_with_reason(reason, message):
|
||||||
_log_ignore(reason, message)
|
_log_ignore(reason, message)
|
||||||
@@ -1103,8 +1103,8 @@ class EventManager:
|
|||||||
return
|
return
|
||||||
|
|
||||||
setNewActiveScript, reason = self._isActivatableEvent(event, script)
|
setNewActiveScript, reason = self._isActivatableEvent(event, script)
|
||||||
msg = f'EVENT MANAGER: Change active script: {setNewActiveScript} ({reason})'
|
debug.print_log(debug.LEVEL_INFO, "EVENT MANAGER",
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
f"Change active script: {setNewActiveScript}", reason, True)
|
||||||
|
|
||||||
if setNewActiveScript:
|
if setNewActiveScript:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ def _get_ax_utilities():
|
|||||||
from .ax_utilities import AXUtilities
|
from .ax_utilities import AXUtilities
|
||||||
return AXUtilities
|
return AXUtilities
|
||||||
|
|
||||||
|
def _log(message, reason=None, timestamp=True, stack=False):
|
||||||
|
debug.print_log(debug.LEVEL_INFO, "FOCUS MANAGER", message, reason, timestamp, stack)
|
||||||
|
|
||||||
|
def _log_tokens(tokens, reason=None, timestamp=True, stack=False):
|
||||||
|
debug.print_log_tokens(debug.LEVEL_INFO, "FOCUS MANAGER", tokens, reason, timestamp, stack)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .input_event import InputEvent
|
from .input_event import InputEvent
|
||||||
from .scripts import default
|
from .scripts import default
|
||||||
@@ -84,18 +90,14 @@ class FocusManager:
|
|||||||
self._last_cursor_position: tuple[Optional[Atspi.Accessible], int] = (None, -1)
|
self._last_cursor_position: tuple[Optional[Atspi.Accessible], int] = (None, -1)
|
||||||
self._penultimate_cursor_position: tuple[Optional[Atspi.Accessible], int] = (None, -1)
|
self._penultimate_cursor_position: tuple[Optional[Atspi.Accessible], int] = (None, -1)
|
||||||
|
|
||||||
msg = "FOCUS MANAGER: Registering D-Bus commands."
|
_log("Registering D-Bus commands.")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
controller = dbus_service.get_remote_controller()
|
controller = dbus_service.get_remote_controller()
|
||||||
controller.register_decorated_module("FocusManager", self)
|
controller.register_decorated_module("FocusManager", self)
|
||||||
|
|
||||||
def clear_state(self, reason: str = "") -> None:
|
def clear_state(self, reason: str = "") -> None:
|
||||||
"""Clears everything we're tracking."""
|
"""Clears everything we're tracking."""
|
||||||
|
|
||||||
msg = "FOCUS MANAGER: Clearing all state"
|
_log("Clearing all state", reason)
|
||||||
if reason:
|
|
||||||
msg += f": {reason}"
|
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
self._focus = None
|
self._focus = None
|
||||||
self._window = None
|
self._window = None
|
||||||
self._object_of_interest = None
|
self._object_of_interest = None
|
||||||
@@ -109,8 +111,7 @@ class FocusManager:
|
|||||||
"""Returns the focused object in the active window."""
|
"""Returns the focused object in the active window."""
|
||||||
|
|
||||||
result = _get_ax_utilities().get_focused_object(self._window)
|
result = _get_ax_utilities().get_focused_object(self._window)
|
||||||
tokens = ["FOCUS MANAGER: Focused object in", self._window, "is", result]
|
_log_tokens(["Focused object in", self._window, "is", result])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def focus_and_window_are_unknown(self) -> bool:
|
def focus_and_window_are_unknown(self) -> bool:
|
||||||
@@ -118,8 +119,7 @@ class FocusManager:
|
|||||||
|
|
||||||
result = self._focus is None and self._window is None
|
result = self._focus is None and self._window is None
|
||||||
if result:
|
if result:
|
||||||
msg = "FOCUS MANAGER: Focus and window are unknown"
|
_log("Focus and window are unknown")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -129,8 +129,7 @@ class FocusManager:
|
|||||||
if not AXObject.is_dead(self._focus):
|
if not AXObject.is_dead(self._focus):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
msg = "FOCUS MANAGER: Focus is dead"
|
_log("Focus is dead", "dead-focus")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def focus_is_active_window(self) -> bool:
|
def focus_is_active_window(self) -> bool:
|
||||||
@@ -165,8 +164,7 @@ class FocusManager:
|
|||||||
obj.emit("mode-changed::" + mode, 1, "")
|
obj.emit("mode-changed::" + mode, 1, "")
|
||||||
|
|
||||||
if mode != self._active_mode:
|
if mode != self._active_mode:
|
||||||
tokens = ["FOCUS MANAGER: Switching mode from", self._active_mode, "to", mode]
|
_log_tokens(["Switching mode from", self._active_mode, "to", mode])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
self._active_mode = mode
|
self._active_mode = mode
|
||||||
cthulhu_state.activeMode = mode
|
cthulhu_state.activeMode = mode
|
||||||
if mode == FLAT_REVIEW:
|
if mode == FLAT_REVIEW:
|
||||||
@@ -174,15 +172,12 @@ class FocusManager:
|
|||||||
else:
|
else:
|
||||||
braille.setBrlapiPriority()
|
braille.setBrlapiPriority()
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Region of interest:", obj, f"({start_offset}, {end_offset})"]
|
_log_tokens(["Region of interest:", obj, f"({start_offset}, {end_offset})"])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
obj.emit("region-changed", start_offset, end_offset)
|
obj.emit("region-changed", start_offset, end_offset)
|
||||||
|
|
||||||
if obj != self._object_of_interest:
|
if obj != self._object_of_interest:
|
||||||
tokens = ["FOCUS MANAGER: Switching object of interest from",
|
_log_tokens(["Switching object of interest from", self._object_of_interest, "to", obj])
|
||||||
self._object_of_interest, "to", obj]
|
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
self._object_of_interest = obj
|
self._object_of_interest = obj
|
||||||
cthulhu_state.objOfInterest = obj
|
cthulhu_state.objOfInterest = obj
|
||||||
|
|
||||||
@@ -196,32 +191,27 @@ class FocusManager:
|
|||||||
) -> tuple[Optional[str], Optional[Atspi.Accessible]]:
|
) -> tuple[Optional[str], Optional[Atspi.Accessible]]:
|
||||||
"""Returns the current mode and associated object of interest"""
|
"""Returns the current mode and associated object of interest"""
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Active mode:", self._active_mode,
|
_log_tokens(["Active mode:", self._active_mode, "Object of interest:", self._object_of_interest])
|
||||||
"Object of interest:", self._object_of_interest]
|
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return self._active_mode, self._object_of_interest
|
return self._active_mode, self._object_of_interest
|
||||||
|
|
||||||
def get_penultimate_cursor_position(self) -> tuple[Optional[Atspi.Accessible], int]:
|
def get_penultimate_cursor_position(self) -> tuple[Optional[Atspi.Accessible], int]:
|
||||||
"""Returns the penultimate cursor position as a tuple of (object, offset)."""
|
"""Returns the penultimate cursor position as a tuple of (object, offset)."""
|
||||||
|
|
||||||
obj, offset = self._penultimate_cursor_position
|
obj, offset = self._penultimate_cursor_position
|
||||||
tokens = ["FOCUS MANAGER: Penultimate cursor position:", obj, offset]
|
_log_tokens(["Penultimate cursor position:", obj, offset])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return obj, offset
|
return obj, offset
|
||||||
|
|
||||||
def get_last_cursor_position(self) -> tuple[Optional[Atspi.Accessible], int]:
|
def get_last_cursor_position(self) -> tuple[Optional[Atspi.Accessible], int]:
|
||||||
"""Returns the last cursor position as a tuple of (object, offset)."""
|
"""Returns the last cursor position as a tuple of (object, offset)."""
|
||||||
|
|
||||||
obj, offset = self._last_cursor_position
|
obj, offset = self._last_cursor_position
|
||||||
tokens = ["FOCUS MANAGER: Last cursor position:", obj, offset]
|
_log_tokens(["Last cursor position:", obj, offset])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return obj, offset
|
return obj, offset
|
||||||
|
|
||||||
def set_last_cursor_position(self, obj: Optional[Atspi.Accessible], offset: int) -> None:
|
def set_last_cursor_position(self, obj: Optional[Atspi.Accessible], offset: int) -> None:
|
||||||
"""Sets the last cursor position as a tuple of (object, offset)."""
|
"""Sets the last cursor position as a tuple of (object, offset)."""
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Setting last cursor position to", obj, offset]
|
_log_tokens(["Setting last cursor position to", obj, offset])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
self._penultimate_cursor_position = self._last_cursor_position
|
self._penultimate_cursor_position = self._last_cursor_position
|
||||||
self._last_cursor_position = obj, offset
|
self._last_cursor_position = obj, offset
|
||||||
|
|
||||||
@@ -229,22 +219,19 @@ class FocusManager:
|
|||||||
"""Returns the last known cell coordinates as a tuple of (row, column)."""
|
"""Returns the last known cell coordinates as a tuple of (row, column)."""
|
||||||
|
|
||||||
row, column = self._last_cell_coordinates
|
row, column = self._last_cell_coordinates
|
||||||
msg = f"FOCUS MANAGER: Last known cell coordinates: row={row}, column={column}"
|
_log(f"Last known cell coordinates: row={row}, column={column}")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
return row, column
|
return row, column
|
||||||
|
|
||||||
def set_last_cell_coordinates(self, row: int, column: int) -> None:
|
def set_last_cell_coordinates(self, row: int, column: int) -> None:
|
||||||
"""Sets the last known cell coordinates as a tuple of (row, column)."""
|
"""Sets the last known cell coordinates as a tuple of (row, column)."""
|
||||||
|
|
||||||
msg = f"FOCUS MANAGER: Setting last cell coordinates to row={row}, column={column}"
|
_log(f"Setting last cell coordinates to row={row}, column={column}")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
self._last_cell_coordinates = row, column
|
self._last_cell_coordinates = row, column
|
||||||
|
|
||||||
def get_locus_of_focus(self) -> Optional[Atspi.Accessible]:
|
def get_locus_of_focus(self) -> Optional[Atspi.Accessible]:
|
||||||
"""Returns the current locus of focus (i.e. the object with visual focus)."""
|
"""Returns the current locus of focus (i.e. the object with visual focus)."""
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Locus of focus is", self._focus]
|
_log_tokens(["Locus of focus is", self._focus])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return self._focus
|
return self._focus
|
||||||
|
|
||||||
def set_locus_of_focus(
|
def set_locus_of_focus(
|
||||||
@@ -256,8 +243,7 @@ class FocusManager:
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Sets the locus of focus (i.e., the object with visual focus)."""
|
"""Sets the locus of focus (i.e., the object with visual focus)."""
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Request to set locus of focus to", obj]
|
_log_tokens(["Request to set locus of focus to", obj], stack=True)
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True, True)
|
|
||||||
|
|
||||||
# We clear the cache on the locus of focus because too many apps and toolkits fail
|
# We clear the cache on the locus of focus because too many apps and toolkits fail
|
||||||
# to emit the correct accessibility events. We do so recursively on table cells
|
# to emit the correct accessibility events. We do so recursively on table cells
|
||||||
@@ -265,8 +251,7 @@ class FocusManager:
|
|||||||
recursive = _get_ax_utilities().is_table_cell(obj)
|
recursive = _get_ax_utilities().is_table_cell(obj)
|
||||||
AXObject.clear_cache(obj, recursive, "Setting locus of focus.")
|
AXObject.clear_cache(obj, recursive, "Setting locus of focus.")
|
||||||
if not force and obj == self._focus:
|
if not force and obj == self._focus:
|
||||||
msg = "FOCUS MANAGER: Setting locus of focus to existing locus of focus"
|
_log("Setting locus of focus to existing locus of focus", "no-change")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# We save the current row and column of a newly focused or selected table cell so that on
|
# We save the current row and column of a newly focused or selected table cell so that on
|
||||||
@@ -298,26 +283,21 @@ class FocusManager:
|
|||||||
old_focus = None
|
old_focus = None
|
||||||
|
|
||||||
if obj is None:
|
if obj is None:
|
||||||
msg = "FOCUS MANAGER: New locus of focus is null (being cleared)"
|
_log("New locus of focus is null (being cleared)", "clearing")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
self._focus = None
|
self._focus = None
|
||||||
cthulhu_state.locusOfFocus = None
|
cthulhu_state.locusOfFocus = None
|
||||||
return
|
return
|
||||||
|
|
||||||
if AXObject.is_dead(obj):
|
if AXObject.is_dead(obj):
|
||||||
tokens = ["FOCUS MANAGER: New locus of focus (", obj, ") is dead. Not updating."]
|
_log_tokens(["New locus of focus", obj, "is dead. Not updating."], "dead")
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if script is not None:
|
if script is not None:
|
||||||
if not AXObject.is_valid(obj):
|
if not AXObject.is_valid(obj):
|
||||||
tokens = ["FOCUS MANAGER: New locus of focus (", obj, ") is invalid. Not updating."]
|
_log_tokens(["New locus of focus", obj, "is invalid. Not updating."], "invalid")
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Changing locus of focus from", old_focus,
|
_log_tokens(["Changing locus of focus from", old_focus, "to", obj, ". Notify:", notify_script])
|
||||||
"to", obj, ". Notify:", notify_script]
|
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
self._focus = obj
|
self._focus = obj
|
||||||
cthulhu_state.locusOfFocus = obj
|
cthulhu_state.locusOfFocus = obj
|
||||||
|
|
||||||
@@ -325,8 +305,7 @@ class FocusManager:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if script is None:
|
if script is None:
|
||||||
msg = "FOCUS MANAGER: Cannot notify active script because there isn't one"
|
_log("Cannot notify active script because there isn't one", "no-active-script")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self.emit_region_changed(obj, mode=FOCUS_TRACKING)
|
self.emit_region_changed(obj, mode=FOCUS_TRACKING)
|
||||||
@@ -337,15 +316,13 @@ class FocusManager:
|
|||||||
|
|
||||||
AXObject.clear_cache(self._window, False, "Ensuring the active window is really active.")
|
AXObject.clear_cache(self._window, False, "Ensuring the active window is really active.")
|
||||||
is_active = _get_ax_utilities().is_active(self._window)
|
is_active = _get_ax_utilities().is_active(self._window)
|
||||||
tokens = ["FOCUS MANAGER:", self._window, "is active:", is_active]
|
_log_tokens([self._window, "is active:", is_active])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return is_active
|
return is_active
|
||||||
|
|
||||||
def get_active_window(self) -> Optional[Atspi.Accessible]:
|
def get_active_window(self) -> Optional[Atspi.Accessible]:
|
||||||
"""Returns the currently-active window (i.e. without searching or verifying)."""
|
"""Returns the currently-active window (i.e. without searching or verifying)."""
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Active window is", self._window]
|
_log_tokens(["Active window is", self._window], stack=True)
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True, True)
|
|
||||||
return self._window
|
return self._window
|
||||||
|
|
||||||
def set_active_window(
|
def set_active_window(
|
||||||
@@ -357,14 +334,13 @@ class FocusManager:
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Sets the active window."""
|
"""Sets the active window."""
|
||||||
|
|
||||||
tokens = ["FOCUS MANAGER: Request to set active window to", frame]
|
tokens = ["Request to set active window to", frame]
|
||||||
if app is not None:
|
if app is not None:
|
||||||
tokens.extend(["in", app])
|
tokens.extend(["in", app])
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
|
_log_tokens(tokens)
|
||||||
|
|
||||||
if frame == self._window:
|
if frame == self._window:
|
||||||
msg = "FOCUS MANAGER: Setting active window to existing active window"
|
_log("Setting active window to existing active window", "no-change")
|
||||||
debug.print_message(debug.LEVEL_INFO, msg, True)
|
|
||||||
elif frame is None:
|
elif frame is None:
|
||||||
self._window = None
|
self._window = None
|
||||||
cthulhu_state.activeWindow = None
|
cthulhu_state.activeWindow = None
|
||||||
@@ -375,8 +351,7 @@ class FocusManager:
|
|||||||
if set_window_as_focus:
|
if set_window_as_focus:
|
||||||
self.set_locus_of_focus(None, self._window, notify_script)
|
self.set_locus_of_focus(None, self._window, notify_script)
|
||||||
elif not (self.focus_is_active_window() or self.focus_is_in_active_window()):
|
elif not (self.focus_is_active_window() or self.focus_is_in_active_window()):
|
||||||
tokens = ["FOCUS MANAGER: Focus", self._focus, "is not in", self._window]
|
_log_tokens(["Focus", self._focus, "is not in", self._window], stack=True)
|
||||||
debug.print_tokens(debug.LEVEL_INFO, tokens, True, True)
|
|
||||||
|
|
||||||
# Don't update the focus to the active window if we can't get to the active window
|
# Don't update the focus to the active window if we can't get to the active window
|
||||||
# from the focused object. https://bugreports.qt.io/browse/QTBUG-130116
|
# from the focused object. https://bugreports.qt.io/browse/QTBUG-130116
|
||||||
|
|||||||
@@ -796,8 +796,12 @@ class KeyboardEvent(InputEvent):
|
|||||||
"""Returns True if this event should be consumed."""
|
"""Returns True if this event should be consumed."""
|
||||||
|
|
||||||
# Debug logging to understand handler matching
|
# Debug logging to understand handler matching
|
||||||
debugMsg = f"shouldConsume: key='{self.event_string}' hw_code={self.hw_code} modifiers={self.modifiers}"
|
debug.print_log(
|
||||||
debug.printMessage(debug.LEVEL_INFO, debugMsg, True)
|
debug.LEVEL_INFO,
|
||||||
|
"INPUT EVENT",
|
||||||
|
f"shouldConsume: key='{self.event_string}' hw_code={self.hw_code} modifiers={self.modifiers}",
|
||||||
|
timestamp=True,
|
||||||
|
)
|
||||||
|
|
||||||
if not self.timestamp:
|
if not self.timestamp:
|
||||||
return False, 'No timestamp'
|
return False, 'No timestamp'
|
||||||
@@ -810,10 +814,14 @@ class KeyboardEvent(InputEvent):
|
|||||||
self._script = script_manager.get_manager().get_default_script()
|
self._script = script_manager.get_manager().get_default_script()
|
||||||
globalHandlerUsed = True
|
globalHandlerUsed = True
|
||||||
else:
|
else:
|
||||||
debug.printMessage(debug.LEVEL_INFO, "shouldConsume: No active script", True)
|
debug.print_log(debug.LEVEL_INFO, "INPUT EVENT",
|
||||||
|
"shouldConsume: No active script",
|
||||||
|
reason="no-active-script", timestamp=True)
|
||||||
return False, 'No active script when received'
|
return False, 'No active script when received'
|
||||||
|
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"shouldConsume: Active script={self._script.__class__.__name__}", True)
|
debug.print_log(debug.LEVEL_INFO, "INPUT EVENT",
|
||||||
|
f"shouldConsume: Active script={self._script.__class__.__name__}",
|
||||||
|
timestamp=True)
|
||||||
|
|
||||||
if self.is_duplicate:
|
if self.is_duplicate:
|
||||||
return False, 'Is duplicate'
|
return False, 'Is duplicate'
|
||||||
@@ -827,15 +835,21 @@ class KeyboardEvent(InputEvent):
|
|||||||
globalHandlerUsed = globalHandlerUsed or self._resolveHandler()
|
globalHandlerUsed = globalHandlerUsed or self._resolveHandler()
|
||||||
|
|
||||||
if self._handler:
|
if self._handler:
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"shouldConsume: Handler found: {self._handler.description}", True)
|
debug.print_log(debug.LEVEL_INFO, "INPUT EVENT",
|
||||||
|
f"shouldConsume: Handler found: {self._handler.description}",
|
||||||
|
timestamp=True)
|
||||||
else:
|
else:
|
||||||
debug.printMessage(debug.LEVEL_INFO, "shouldConsume: No handler found", True)
|
debug.print_log(debug.LEVEL_INFO, "INPUT EVENT",
|
||||||
|
"shouldConsume: No handler found",
|
||||||
|
reason="no-handler", timestamp=True)
|
||||||
|
|
||||||
self._script.updateKeyboardEventState(self, self._handler)
|
self._script.updateKeyboardEventState(self, self._handler)
|
||||||
scriptConsumes = self._script.shouldConsumeKeyboardEvent(self, self._handler)
|
scriptConsumes = self._script.shouldConsumeKeyboardEvent(self, self._handler)
|
||||||
if globalHandlerUsed:
|
if globalHandlerUsed:
|
||||||
scriptConsumes = True
|
scriptConsumes = True
|
||||||
debug.printMessage(debug.LEVEL_INFO, f"shouldConsume: scriptConsumes={scriptConsumes}", True)
|
debug.print_log(debug.LEVEL_INFO, "INPUT EVENT",
|
||||||
|
f"shouldConsume: scriptConsumes={scriptConsumes}",
|
||||||
|
timestamp=True)
|
||||||
|
|
||||||
if self._isReleaseForLastNonModifierKeyEvent():
|
if self._isReleaseForLastNonModifierKeyEvent():
|
||||||
return scriptConsumes, 'Is release for last non-modifier keyevent'
|
return scriptConsumes, 'Is release for last non-modifier keyevent'
|
||||||
|
|||||||
@@ -41,10 +41,16 @@ def _get_ax_utilities():
|
|||||||
from .ax_utilities import AXUtilities
|
from .ax_utilities import AXUtilities
|
||||||
return AXUtilities
|
return AXUtilities
|
||||||
|
|
||||||
|
def _log(message, reason=None, timestamp=True, stack=False):
|
||||||
|
debug.print_log(debug.LEVEL_INFO, "SCRIPT MANAGER", message, reason, timestamp, stack)
|
||||||
|
|
||||||
|
def _log_tokens(tokens, reason=None, timestamp=True, stack=False):
|
||||||
|
debug.print_log_tokens(debug.LEVEL_INFO, "SCRIPT MANAGER", tokens, reason, timestamp, stack)
|
||||||
|
|
||||||
class ScriptManager:
|
class ScriptManager:
|
||||||
|
|
||||||
def __init__(self, app): # Added app argument
|
def __init__(self, app): # Added app argument
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Initializing", True)
|
_log("Initializing")
|
||||||
self.app = app # Store app instance
|
self.app = app # Store app instance
|
||||||
self.appScripts = {}
|
self.appScripts = {}
|
||||||
self.toolkitScripts = {}
|
self.toolkitScripts = {}
|
||||||
@@ -74,22 +80,22 @@ class ScriptManager:
|
|||||||
|
|
||||||
self.set_active_script(None, "lifecycle: init")
|
self.set_active_script(None, "lifecycle: init")
|
||||||
self._active = False
|
self._active = False
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Initialized", True)
|
_log("Initialized")
|
||||||
|
|
||||||
def activate(self):
|
def activate(self):
|
||||||
"""Called when this script manager is activated."""
|
"""Called when this script manager is activated."""
|
||||||
|
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activating", True)
|
_log("Activating")
|
||||||
self._defaultScript = self.get_script(None)
|
self._defaultScript = self.get_script(None)
|
||||||
self._defaultScript.registerEventListeners()
|
self._defaultScript.registerEventListeners()
|
||||||
self.set_active_script(self._defaultScript, "lifecycle: activate")
|
self.set_active_script(self._defaultScript, "lifecycle: activate")
|
||||||
self._active = True
|
self._active = True
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activated", True)
|
_log("Activated")
|
||||||
|
|
||||||
def deactivate(self):
|
def deactivate(self):
|
||||||
"""Called when this script manager is deactivated."""
|
"""Called when this script manager is deactivated."""
|
||||||
|
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Deactivating", True)
|
_log("Deactivating")
|
||||||
if self._defaultScript:
|
if self._defaultScript:
|
||||||
self._defaultScript.deregisterEventListeners()
|
self._defaultScript.deregisterEventListeners()
|
||||||
self._defaultScript = None
|
self._defaultScript = None
|
||||||
@@ -98,20 +104,18 @@ class ScriptManager:
|
|||||||
self.toolkitScripts = {}
|
self.toolkitScripts = {}
|
||||||
self.customScripts = {}
|
self.customScripts = {}
|
||||||
self._active = False
|
self._active = False
|
||||||
debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Deactivated", True)
|
_log("Deactivated")
|
||||||
|
|
||||||
def get_module_name(self, app):
|
def get_module_name(self, app):
|
||||||
"""Returns the module name of the script to use for application app."""
|
"""Returns the module name of the script to use for application app."""
|
||||||
|
|
||||||
if app is None:
|
if app is None:
|
||||||
msg = "SCRIPT MANAGER: Cannot get module name for null app"
|
_log("Cannot get module name for null app", "null-app")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
name = AXObject.get_name(app)
|
name = AXObject.get_name(app)
|
||||||
if not name:
|
if not name:
|
||||||
msg = "SCRIPT MANAGER: Cannot get module name for nameless app"
|
_log("Cannot get module name for nameless app", "nameless-app")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
pid = AXObject.get_process_id(app)
|
pid = AXObject.get_process_id(app)
|
||||||
@@ -136,8 +140,7 @@ class ScriptManager:
|
|||||||
name = names[0]
|
name = names[0]
|
||||||
break
|
break
|
||||||
|
|
||||||
tokens = ["SCRIPT MANAGER: Mapped", app, "to", name]
|
_log_tokens(["Mapped", app, "to", name])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def _toolkit_for_object(self, obj):
|
def _toolkit_for_object(self, obj):
|
||||||
@@ -169,8 +172,7 @@ class ScriptManager:
|
|||||||
except OSError:
|
except OSError:
|
||||||
debug.examineProcesses()
|
debug.examineProcesses()
|
||||||
|
|
||||||
tokens = ["SCRIPT MANAGER: Found", moduleName]
|
_log_tokens(["Found", moduleName])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
try:
|
try:
|
||||||
if hasattr(module, 'get_script'):
|
if hasattr(module, 'get_script'):
|
||||||
script = module.get_script(app)
|
script = module.get_script(app)
|
||||||
@@ -178,8 +180,7 @@ class ScriptManager:
|
|||||||
script = module.Script(app)
|
script = module.Script(app)
|
||||||
break
|
break
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
tokens = ["SCRIPT MANAGER: Could not load", moduleName, ":", error]
|
_log_tokens(["Could not load", moduleName, ":", error], "load-failed")
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
@@ -202,8 +203,7 @@ class ScriptManager:
|
|||||||
|
|
||||||
if not script:
|
if not script:
|
||||||
script = self.get_default_script(app)
|
script = self.get_default_script(app)
|
||||||
tokens = ["SCRIPT MANAGER: Default script created for", app, "(obj: ", obj, ")"]
|
_log_tokens(["Default script created for", app, "(obj:", obj, ")"])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
@@ -230,14 +230,12 @@ class ScriptManager:
|
|||||||
if newScript:
|
if newScript:
|
||||||
return newScript
|
return newScript
|
||||||
|
|
||||||
tokens = ["WARNING: Failed to get a replacement script for", script.app]
|
_log_tokens(["Failed to get a replacement script for", script.app], "replacement-missing")
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
def get_script_for_mouse_button_event(self, event):
|
def get_script_for_mouse_button_event(self, event):
|
||||||
isActive = _get_ax_utilities().is_active(cthulhu_state.activeWindow)
|
isActive = _get_ax_utilities().is_active(cthulhu_state.activeWindow)
|
||||||
tokens = ["SCRIPT MANAGER:", cthulhu_state.activeWindow, "is active:", isActive]
|
_log_tokens([cthulhu_state.activeWindow, "is active:", isActive])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
|
|
||||||
if isActive and cthulhu_state.activeScript:
|
if isActive and cthulhu_state.activeScript:
|
||||||
return cthulhu_state.activeScript
|
return cthulhu_state.activeScript
|
||||||
@@ -297,8 +295,7 @@ class ScriptManager:
|
|||||||
appScript = self._create_script(app, None)
|
appScript = self._create_script(app, None)
|
||||||
self.appScripts[app] = appScript
|
self.appScripts[app] = appScript
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
tokens = ["SCRIPT MANAGER: Exception getting app script for", app, ":", error]
|
_log_tokens(["Exception getting app script for", app, ":", error], "app-script-error")
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
appScript = self.get_default_script()
|
appScript = self.get_default_script()
|
||||||
|
|
||||||
if customScript:
|
if customScript:
|
||||||
@@ -351,8 +348,7 @@ class ScriptManager:
|
|||||||
from . import cthulhu
|
from . import cthulhu
|
||||||
cthulhu.cthulhuApp.getSignalManager().emitSignal('active-script-changed', newScript)
|
cthulhu.cthulhuApp.getSignalManager().emitSignal('active-script-changed', newScript)
|
||||||
|
|
||||||
tokens = ["SCRIPT MANAGER: Setting active script to", newScript, "reason:", reason]
|
_log_tokens(["Setting active script to", newScript], reason)
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
self._log_active_state(reason)
|
self._log_active_state(reason)
|
||||||
|
|
||||||
def activate_script_for_context(self, app, obj, reason=None):
|
def activate_script_for_context(self, app, obj, reason=None):
|
||||||
@@ -361,14 +357,12 @@ class ScriptManager:
|
|||||||
return script
|
return script
|
||||||
|
|
||||||
def _log_active_state(self, reason=None):
|
def _log_active_state(self, reason=None):
|
||||||
tokens = [
|
_log_tokens(
|
||||||
"SCRIPT MANAGER: Active state:",
|
["Active state:", "window", cthulhu_state.activeWindow,
|
||||||
"window", cthulhu_state.activeWindow,
|
|
||||||
"focus", cthulhu_state.locusOfFocus,
|
"focus", cthulhu_state.locusOfFocus,
|
||||||
"script", cthulhu_state.activeScript,
|
"script", cthulhu_state.activeScript],
|
||||||
"reason", reason
|
reason
|
||||||
]
|
)
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
|
|
||||||
def _get_script_for_app_replicant(self, app):
|
def _get_script_for_app_replicant(self, app):
|
||||||
if not self._active:
|
if not self._active:
|
||||||
@@ -385,8 +379,7 @@ class ScriptManager:
|
|||||||
if a != app and _get_ax_utilities().is_application_in_desktop(a):
|
if a != app and _get_ax_utilities().is_application_in_desktop(a):
|
||||||
if script.app is None:
|
if script.app is None:
|
||||||
script.app = a
|
script.app = a
|
||||||
tokens = ["SCRIPT MANAGER: Script for app replicant:", script, script.app]
|
_log_tokens(["Script for app replicant:", script, script.app])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@@ -396,8 +389,7 @@ class ScriptManager:
|
|||||||
deleting any scripts as necessary.
|
deleting any scripts as necessary.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
msg = "SCRIPT MANAGER: Checking and cleaning up scripts."
|
_log("Checking and cleaning up scripts.")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
|
|
||||||
appList = list(self.appScripts.keys())
|
appList = list(self.appScripts.keys())
|
||||||
for app in appList:
|
for app in appList:
|
||||||
@@ -407,21 +399,17 @@ class ScriptManager:
|
|||||||
try:
|
try:
|
||||||
appScript = self.appScripts.pop(app)
|
appScript = self.appScripts.pop(app)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
tokens = ["SCRIPT MANAGER:", app, "not found in appScripts"]
|
_log_tokens([app, "not found in appScripts"])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tokens = ["SCRIPT MANAGER: Old script for app found:", appScript, appScript.app]
|
_log_tokens(["Old script for app found:", appScript, appScript.app])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
|
|
||||||
newScript = self._get_script_for_app_replicant(app)
|
newScript = self._get_script_for_app_replicant(app)
|
||||||
if newScript:
|
if newScript:
|
||||||
tokens = ["SCRIPT MANAGER: Transferring attributes:", newScript, newScript.app]
|
_log_tokens(["Transferring attributes:", newScript, newScript.app])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
attrs = appScript.getTransferableAttributes()
|
attrs = appScript.getTransferableAttributes()
|
||||||
for attr, value in attrs.items():
|
for attr, value in attrs.items():
|
||||||
tokens = ["SCRIPT MANAGER: Setting", attr, "to", value]
|
_log_tokens(["Setting", attr, "to", value])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
setattr(newScript, attr, value)
|
setattr(newScript, attr, value)
|
||||||
|
|
||||||
del appScript
|
del appScript
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ from .script_utilities import Utilities
|
|||||||
|
|
||||||
_settingsManager = None # Removed - use cthulhu.cthulhuApp.settingsManager
|
_settingsManager = None # Removed - use cthulhu.cthulhuApp.settingsManager
|
||||||
|
|
||||||
|
def _log(message, reason=None, timestamp=True, stack=False):
|
||||||
|
debug.print_log(debug.LEVEL_INFO, "WEB", message, reason, timestamp, stack)
|
||||||
|
|
||||||
|
def _log_tokens(tokens, reason=None, timestamp=True, stack=False):
|
||||||
|
debug.print_log_tokens(debug.LEVEL_INFO, "WEB", tokens, reason, timestamp, stack)
|
||||||
|
|
||||||
|
|
||||||
class Script(default.Script):
|
class Script(default.Script):
|
||||||
|
|
||||||
@@ -126,14 +132,13 @@ class Script(default.Script):
|
|||||||
def activate(self):
|
def activate(self):
|
||||||
"""Called when this script is activated."""
|
"""Called when this script is activated."""
|
||||||
|
|
||||||
tokens = ["WEB: Activating script for", self.app]
|
_log_tokens(["Activating script for", self.app])
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
|
|
||||||
focus = cthulhu_state.locusOfFocus
|
focus = cthulhu_state.locusOfFocus
|
||||||
inApp = AXObject.get_application(focus) == self.app if focus else False
|
inApp = AXObject.get_application(focus) == self.app if focus else False
|
||||||
inDoc = self._focusInDocumentContent()
|
inDoc = self._focusInDocumentContent()
|
||||||
suspend = not (inDoc and inApp)
|
suspend = not (inDoc and inApp)
|
||||||
reason = f"script activation, not in document content in this app: {suspend}"
|
reason = "activation-outside-document" if suspend else "activation-in-document"
|
||||||
|
|
||||||
self._setNavigationSuspended(suspend, reason)
|
self._setNavigationSuspended(suspend, reason)
|
||||||
|
|
||||||
@@ -176,8 +181,7 @@ class Script(default.Script):
|
|||||||
self.structuralNavigation.enabled = self._structNavWasEnabled
|
self.structuralNavigation.enabled = self._structNavWasEnabled
|
||||||
self._structNavWasEnabled = None
|
self._structNavWasEnabled = None
|
||||||
|
|
||||||
tokens = ["WEB: Navigation suspended:", suspend, reason]
|
_log_tokens(["Navigation suspended:", suspend], reason)
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
|
|
||||||
def _focusInDocumentContent(self):
|
def _focusInDocumentContent(self):
|
||||||
focus = cthulhu_state.locusOfFocus
|
focus = cthulhu_state.locusOfFocus
|
||||||
@@ -902,24 +906,20 @@ class Script(default.Script):
|
|||||||
"""Returns True if we should use focus mode in obj."""
|
"""Returns True if we should use focus mode in obj."""
|
||||||
|
|
||||||
if self._focusModeIsSticky:
|
if self._focusModeIsSticky:
|
||||||
msg = "WEB: Using focus mode because focus mode is sticky"
|
_log("Using focus mode", "focus-mode-sticky")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self._browseModeIsSticky:
|
if self._browseModeIsSticky:
|
||||||
msg = "WEB: Not using focus mode because browse mode is sticky"
|
_log("Not using focus mode", "browse-mode-sticky")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.inSayAll():
|
if self.inSayAll():
|
||||||
msg = "WEB: Not using focus mode because we're in SayAll."
|
_log("Not using focus mode", "say-all")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not cthulhu.cthulhuApp.settingsManager.getSetting('structNavTriggersFocusMode') \
|
if not cthulhu.cthulhuApp.settingsManager.getSetting('structNavTriggersFocusMode') \
|
||||||
and self._lastCommandWasStructNav:
|
and self._lastCommandWasStructNav:
|
||||||
msg = "WEB: Not using focus mode due to struct nav settings"
|
_log("Not using focus mode", "struct-nav-settings")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if prevObj and AXObject.is_dead(prevObj):
|
if prevObj and AXObject.is_dead(prevObj):
|
||||||
@@ -928,39 +928,32 @@ class Script(default.Script):
|
|||||||
if not cthulhu.cthulhuApp.settingsManager.getSetting('caretNavTriggersFocusMode') \
|
if not cthulhu.cthulhuApp.settingsManager.getSetting('caretNavTriggersFocusMode') \
|
||||||
and self._lastCommandWasCaretNav \
|
and self._lastCommandWasCaretNav \
|
||||||
and not self.utilities.isNavigableToolTipDescendant(prevObj):
|
and not self.utilities.isNavigableToolTipDescendant(prevObj):
|
||||||
msg = "WEB: Not using focus mode due to caret nav settings"
|
_log("Not using focus mode", "caret-nav-settings")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not cthulhu.cthulhuApp.settingsManager.getSetting('nativeNavTriggersFocusMode') \
|
if not cthulhu.cthulhuApp.settingsManager.getSetting('nativeNavTriggersFocusMode') \
|
||||||
and not (self._lastCommandWasStructNav or self._lastCommandWasCaretNav):
|
and not (self._lastCommandWasStructNav or self._lastCommandWasCaretNav):
|
||||||
msg = "WEB: Not changing focus/browse mode due to native nav settings"
|
_log("Not changing focus/browse mode", "native-nav-settings")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return self._inFocusMode
|
return self._inFocusMode
|
||||||
|
|
||||||
if self.utilities.isFocusModeWidget(obj):
|
if self.utilities.isFocusModeWidget(obj):
|
||||||
tokens = ["WEB: Using focus mode because", obj, "is a focus mode widget"]
|
_log_tokens(["Using focus mode for", obj], "focus-mode-widget")
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
doNotToggle = AXUtilities.is_link(obj) or AXUtilities.is_radio_button(obj)
|
doNotToggle = AXUtilities.is_link(obj) or AXUtilities.is_radio_button(obj)
|
||||||
if self._inFocusMode and doNotToggle and self.utilities.lastInputEventWasUnmodifiedArrow():
|
if self._inFocusMode and doNotToggle and self.utilities.lastInputEventWasUnmodifiedArrow():
|
||||||
tokens = ["WEB: Staying in focus mode due to arrowing in role of", obj]
|
_log_tokens(["Staying in focus mode due to arrowing in role of", obj], "arrowing")
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self._inFocusMode and self.utilities.isWebAppDescendant(obj):
|
if self._inFocusMode and self.utilities.isWebAppDescendant(obj):
|
||||||
if self.utilities.forceBrowseModeForWebAppDescendant(obj):
|
if self.utilities.forceBrowseModeForWebAppDescendant(obj):
|
||||||
tokens = ["WEB: Forcing browse mode for web app descendant", obj]
|
_log_tokens(["Forcing browse mode for web app descendant", obj], "web-app-forced-browse")
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
msg = "WEB: Staying in focus mode because we're inside a web application"
|
_log("Staying in focus mode because we're inside a web application", "web-app-context")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
tokens = ["WEB: Not using focus mode for", obj, "due to lack of cause"]
|
_log_tokens(["Not using focus mode for", obj], "no-cause")
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def speakContents(self, contents, **args):
|
def speakContents(self, contents, **args):
|
||||||
@@ -1209,14 +1202,12 @@ class Script(default.Script):
|
|||||||
|
|
||||||
if not cthulhu.cthulhuApp.settingsManager.getSetting('caretNavigationEnabled'):
|
if not cthulhu.cthulhuApp.settingsManager.getSetting('caretNavigationEnabled'):
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
msg = "WEB: Not using caret navigation: it's not enabled."
|
_log("Not using caret navigation", "disabled")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self._inFocusMode:
|
if self._inFocusMode:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
msg = "WEB: Not using caret navigation: focus mode is active."
|
_log("Not using caret navigation", "focus-mode")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
inDoc = self._focusInDocumentContent()
|
inDoc = self._focusInDocumentContent()
|
||||||
@@ -1226,27 +1217,29 @@ class Script(default.Script):
|
|||||||
self._setNavigationSuspended(False, "focus confirmed in document content")
|
self._setNavigationSuspended(False, "focus confirmed in document content")
|
||||||
else:
|
else:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
msg = "WEB: Not using caret navigation: navigation suspended."
|
_log("Not using caret navigation", "suspended")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not inDoc:
|
if not inDoc:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
tokens = ["WEB: Not using caret navigation: locusOfFocus",
|
_log_tokens(
|
||||||
cthulhu_state.locusOfFocus, "is not in document content."]
|
["Not using caret navigation because locusOfFocus", cthulhu_state.locusOfFocus,
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
"is not in document content."],
|
||||||
|
"focus-not-document"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if keyboardEvent and keyboardEvent.modifiers & keybindings.SHIFT_MODIFIER_MASK:
|
if keyboardEvent and keyboardEvent.modifiers & keybindings.SHIFT_MODIFIER_MASK:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
msg = "WEB: Not using caret navigation: shift was used."
|
_log("Not using caret navigation", "shift-modifier")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
tokens = ["WEB: Using caret navigation: in browse mode and locusOfFocus",
|
_log_tokens(
|
||||||
cthulhu_state.locusOfFocus, "is in document content."]
|
["Using caret navigation with locusOfFocus", cthulhu_state.locusOfFocus,
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
"in document content."],
|
||||||
|
"enabled"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def useStructuralNavigationModel(self, debugOutput=True):
|
def useStructuralNavigationModel(self, debugOutput=True):
|
||||||
@@ -1254,14 +1247,12 @@ class Script(default.Script):
|
|||||||
|
|
||||||
if not self.structuralNavigation.enabled:
|
if not self.structuralNavigation.enabled:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
msg = "WEB: Not using structural navigation: it's not enabled."
|
_log("Not using structural navigation", "disabled")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self._inFocusMode:
|
if self._inFocusMode:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
msg = "WEB: Not using structural navigation: focus mode is active."
|
_log("Not using structural navigation", "focus-mode")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
inDoc = self._focusInDocumentContent()
|
inDoc = self._focusInDocumentContent()
|
||||||
@@ -1271,21 +1262,24 @@ class Script(default.Script):
|
|||||||
self._setNavigationSuspended(False, "focus confirmed in document content")
|
self._setNavigationSuspended(False, "focus confirmed in document content")
|
||||||
else:
|
else:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
msg = "WEB: Not using structural navigation: navigation suspended."
|
_log("Not using structural navigation", "suspended")
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not inDoc:
|
if not inDoc:
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
tokens = ["WEB: Not using structural navigation: locusOfFocus",
|
_log_tokens(
|
||||||
cthulhu_state.locusOfFocus, "is not in document content."]
|
["Not using structural navigation because locusOfFocus",
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
cthulhu_state.locusOfFocus, "is not in document content."],
|
||||||
|
"focus-not-document"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if debugOutput:
|
if debugOutput:
|
||||||
tokens = ["WEB: Using structural navigation: in browse mode and locusOfFocus",
|
_log_tokens(
|
||||||
cthulhu_state.locusOfFocus, "is in document content."]
|
["Using structural navigation with locusOfFocus", cthulhu_state.locusOfFocus,
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
"in document content."],
|
||||||
|
"enabled"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
|
def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user