Improved support for mumble. Mumble chat messages are now in the message history list. Also, for message review, add shift to copy the message to the clipboard.
This commit is contained in:
+37
-3
@@ -315,6 +315,7 @@ class Chat:
|
||||
self.messageKeys = \
|
||||
["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"]
|
||||
self.messageKeyModifier = keybindings.CTHULHU_MODIFIER_MASK
|
||||
self.messageCopyKeyModifier = keybindings.CTHULHU_SHIFT_MODIFIER_MASK
|
||||
self.inputEventHandlers = {}
|
||||
self.setupInputEventHandlers()
|
||||
self.keyBindings = self.getKeyBindings()
|
||||
@@ -356,6 +357,11 @@ class Chat:
|
||||
self.readPreviousMessage,
|
||||
cmdnames.CHAT_PREVIOUS_MESSAGE)
|
||||
|
||||
self.inputEventHandlers["copyMessage"] = \
|
||||
input_event.InputEventHandler(
|
||||
self.copyPreviousMessage,
|
||||
cmdnames.CHAT_COPY_PREVIOUS_MESSAGE)
|
||||
|
||||
return
|
||||
|
||||
def getKeyBindings(self):
|
||||
@@ -396,6 +402,14 @@ class Chat:
|
||||
keybindings.CTHULHU_MODIFIER_MASK,
|
||||
self.inputEventHandlers["reviewMessage"]))
|
||||
|
||||
for messageKey in self.messageKeys:
|
||||
keyBindings.add(
|
||||
keybindings.KeyBinding(
|
||||
messageKey,
|
||||
self.messageCopyKeyModifier,
|
||||
self.messageCopyKeyModifier,
|
||||
self.inputEventHandlers["copyMessage"]))
|
||||
|
||||
return keyBindings
|
||||
|
||||
def getAppPreferencesGUI(self):
|
||||
@@ -558,6 +572,27 @@ class Chat:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
message, chatRoomName = self._get_message_for_index(index)
|
||||
if message and chatRoomName:
|
||||
self.utterMessage(chatRoomName, message, True)
|
||||
|
||||
def copyPreviousMessage(self, script, inputEvent=None, index=0):
|
||||
"""Copy a previous chat room message to the clipboard."""
|
||||
|
||||
try:
|
||||
index = self.messageKeys.index(inputEvent.event_string)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
message, chatRoomName = self._get_message_for_index(index)
|
||||
if not message:
|
||||
return
|
||||
|
||||
self._script.utilities.setClipboardText(message)
|
||||
line = f"Copied {message} to clipboard."
|
||||
self._script.presentMessage(line)
|
||||
|
||||
def _get_message_for_index(self, index):
|
||||
messageNumber = self.messageListLength - (index + 1)
|
||||
message, chatRoomName = None, None
|
||||
|
||||
@@ -570,8 +605,7 @@ class Chat:
|
||||
message, chatRoomName = \
|
||||
self._conversationList.getNthMessageAndName(messageNumber)
|
||||
|
||||
if message and chatRoomName:
|
||||
self.utterMessage(chatRoomName, message, True)
|
||||
return message, chatRoomName
|
||||
|
||||
def utterMessage(self, chatRoomName, message, focused=True):
|
||||
""" Speak/braille a chat room message.
|
||||
@@ -816,7 +850,7 @@ class Chat:
|
||||
# things working. And people should not be in multiple chat
|
||||
# rooms with identical names anyway. :-)
|
||||
#
|
||||
if (AXUtilities.is_text(obj) or AXObject.is_entry(obj)) \
|
||||
if (AXUtilities.is_text(obj) or AXUtilities.is_entry(obj)) \
|
||||
and AXUtilities.is_editable(obj):
|
||||
name = self.getChatRoomName(obj)
|
||||
|
||||
|
||||
@@ -606,6 +606,11 @@ BYPASS_NEXT_COMMAND = \
|
||||
# keyboard commands used to review those previous messages.
|
||||
CHAT_PREVIOUS_MESSAGE = _("Speak and braille a previous chat room message")
|
||||
|
||||
# Translators: Cthulhu has a command to copy a previous chat room message to
|
||||
# the clipboard. This string is associated with the keyboard commands used to
|
||||
# copy those messages.
|
||||
CHAT_COPY_PREVIOUS_MESSAGE = _("Copy a previous chat room message to clipboard")
|
||||
|
||||
# Translators: In chat applications, it is often possible to see that a "buddy"
|
||||
# is typing currently (e.g. via a keyboard icon or status text). Some users like
|
||||
# to have this typing status announced by Cthulhu; others find that announcement
|
||||
|
||||
@@ -19,6 +19,7 @@ from cthulhu import debug
|
||||
from cthulhu import settings
|
||||
from cthulhu import settings_manager
|
||||
from cthulhu.ax_object import AXObject
|
||||
from cthulhu.ax_utilities import AXUtilities
|
||||
from cthulhu.ax_text import AXText
|
||||
|
||||
# Import Cthulhu's sound system
|
||||
@@ -489,6 +490,25 @@ class IndentationAudio(Plugin):
|
||||
except Exception as e:
|
||||
logger.error(f"IndentationAudio: Error generating tone: {e}")
|
||||
debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Exception in _generate_indentation_tone: {e}", True)
|
||||
|
||||
@staticmethod
|
||||
def _get_indentation_key(obj):
|
||||
if obj is None:
|
||||
return "global"
|
||||
|
||||
document = None
|
||||
try:
|
||||
document = AXObject.find_ancestor(obj, AXUtilities.is_document)
|
||||
except Exception:
|
||||
document = None
|
||||
|
||||
if document is None:
|
||||
document = obj
|
||||
|
||||
try:
|
||||
return f"{id(document)}"
|
||||
except Exception:
|
||||
return str(document)
|
||||
|
||||
def check_indentation_change(self, obj, line_text):
|
||||
"""Check if indentation has changed and play audio cue if needed.
|
||||
@@ -502,7 +522,7 @@ class IndentationAudio(Plugin):
|
||||
|
||||
try:
|
||||
# Get object identifier for tracking
|
||||
obj_id = str(obj) if obj else "unknown"
|
||||
obj_id = self._get_indentation_key(obj)
|
||||
|
||||
# Calculate current indentation data
|
||||
indentation, columns, levels = self._get_indentation_data(line_text)
|
||||
@@ -523,6 +543,8 @@ class IndentationAudio(Plugin):
|
||||
change_mode = _settingsManager.getSetting('indentationChangeMode') \
|
||||
or settings.indentationChangeMode
|
||||
only_if_changed = _settingsManager.getSetting('speakIndentationOnlyIfChanged')
|
||||
if only_if_changed is None:
|
||||
only_if_changed = settings.speakIndentationOnlyIfChanged
|
||||
|
||||
if not only_if_changed:
|
||||
changed = True
|
||||
@@ -543,10 +565,30 @@ class IndentationAudio(Plugin):
|
||||
|
||||
# Play audio cue if indentation changed
|
||||
if changed:
|
||||
indent_debug = indentation.replace("\t", "\\t").replace(" ", ".")
|
||||
debug.printMessage(
|
||||
debug.LEVEL_INFO,
|
||||
(
|
||||
f"IndentationAudio: Reporting indentation key={obj_id} "
|
||||
f"units={current_units} levels={levels} columns={columns} "
|
||||
f"mode={change_mode} onlyIfChanged={only_if_changed} "
|
||||
f"indent='{indent_debug}'"
|
||||
),
|
||||
True,
|
||||
)
|
||||
self._generate_indentation_tone(current_units, previous_units)
|
||||
|
||||
debug_msg = f"IndentationAudio: Indentation units changed from {previous_units} to {current_units}"
|
||||
debug.printMessage(debug.LEVEL_INFO, debug_msg, True)
|
||||
else:
|
||||
debug.printMessage(
|
||||
debug.LEVEL_INFO,
|
||||
(
|
||||
"IndentationAudio: No indentation change; skipping tone "
|
||||
f"key={obj_id} units={current_units} levels={levels} columns={columns}"
|
||||
),
|
||||
True,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"IndentationAudio: Error checking indentation change: {e}")
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2024 Stormux
|
||||
# Copyright (c) 2010-2012 The Orca Team
|
||||
# Copyright (c) 2012 Igalia, S.L.
|
||||
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||
# Boston MA 02110-1301 USA.
|
||||
#
|
||||
# Forked from Orca screen reader.
|
||||
# Cthulhu project: https://git.stormux.org/storm/cthulhu
|
||||
|
||||
from .script import Script
|
||||
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2024 Stormux
|
||||
# Copyright (c) 2010-2012 The Orca Team
|
||||
# Copyright (c) 2012 Igalia, S.L.
|
||||
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||
# Boston MA 02110-1301 USA.
|
||||
#
|
||||
# Forked from Orca screen reader.
|
||||
# Cthulhu project: https://git.stormux.org/storm/cthulhu
|
||||
|
||||
"""Custom chat module for Mumble."""
|
||||
|
||||
__id__ = "$Id$"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2024 Stormux."
|
||||
__license__ = "LGPL"
|
||||
|
||||
import re
|
||||
|
||||
import cthulhu.chat as chat
|
||||
import cthulhu.keybindings as keybindings
|
||||
import cthulhu.cthulhu_state as cthulhu_state
|
||||
import cthulhu.settings_manager as settings_manager
|
||||
from cthulhu.ax_object import AXObject
|
||||
from cthulhu.ax_selection import AXSelection
|
||||
from cthulhu.ax_utilities import AXUtilities
|
||||
|
||||
_settingsManager = settings_manager.getManager()
|
||||
|
||||
|
||||
class Chat(chat.Chat):
|
||||
"""Mumble-specific chat helpers."""
|
||||
|
||||
def __init__(self, script):
|
||||
super().__init__(script, [])
|
||||
|
||||
# Mumble can have more than nine recent messages that are useful to review.
|
||||
self.messageKeys = [
|
||||
"F1", "F2", "F3", "F4", "F5", "F6",
|
||||
"F7", "F8", "F9", "F10", "F11", "F12",
|
||||
]
|
||||
self.messageKeyModifier = keybindings.CTHULHU_MODIFIER_MASK
|
||||
self.inputEventHandlers = {}
|
||||
self.setupInputEventHandlers()
|
||||
self.keyBindings = self.getKeyBindings()
|
||||
self.messageListLength = len(self.messageKeys)
|
||||
self._conversationList = chat.ConversationList(self.messageListLength)
|
||||
|
||||
self._channelTree = None
|
||||
|
||||
def isChatRoomMsg(self, obj):
|
||||
if not obj:
|
||||
return False
|
||||
|
||||
name = AXObject.get_name(obj)
|
||||
if name != "Activity log":
|
||||
return False
|
||||
|
||||
if AXUtilities.is_label(obj) or AXUtilities.is_text(obj):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def getMessageFromEvent(self, event):
|
||||
message = event.any_data or ""
|
||||
message = message.replace("\u2028", " ")
|
||||
message = re.sub(r"[\ufdd0-\ufdef]", "", message)
|
||||
message = " ".join(message.split())
|
||||
if not message:
|
||||
return ""
|
||||
|
||||
if re.match(r"^\[\d{2}:\d{2}:\d{2}\]$", message):
|
||||
return ""
|
||||
|
||||
message = re.sub(r"^\[\d{2}:\d{2}:\d{2}\]\s*", "", message)
|
||||
return message.strip()
|
||||
|
||||
def _get_message_for_index(self, index):
|
||||
messageNumber = self.messageListLength - (index + 1)
|
||||
message, chatRoomName = None, None
|
||||
|
||||
if _settingsManager.getSetting('chatRoomHistories'):
|
||||
conversation = self.getConversation(cthulhu_state.locusOfFocus)
|
||||
if conversation:
|
||||
message = conversation.getNthMessage(messageNumber)
|
||||
chatRoomName = conversation.name
|
||||
|
||||
if not message:
|
||||
message, chatRoomName = \
|
||||
self._conversationList.getNthMessageAndName(messageNumber)
|
||||
|
||||
return message, chatRoomName
|
||||
|
||||
def getChatRoomName(self, obj):
|
||||
channelName = self._get_selected_channel_name()
|
||||
return channelName or "Mumble"
|
||||
|
||||
def _get_selected_channel_name(self):
|
||||
channelTree = self._get_channel_tree()
|
||||
if not channelTree:
|
||||
return ""
|
||||
|
||||
selectedChildren = AXSelection.get_selected_children(channelTree)
|
||||
for child in selectedChildren:
|
||||
childName = AXObject.get_name(child)
|
||||
if not childName:
|
||||
continue
|
||||
if childName.lower().startswith("channel "):
|
||||
return childName.replace("channel ", "", 1).strip()
|
||||
|
||||
for child in selectedChildren:
|
||||
channelAncestor = AXObject.find_ancestor(
|
||||
child,
|
||||
lambda x: (AXObject.get_name(x) or "").lower().startswith("channel ")
|
||||
)
|
||||
if channelAncestor:
|
||||
ancestorName = AXObject.get_name(channelAncestor)
|
||||
return ancestorName.replace("channel ", "", 1).strip()
|
||||
|
||||
return ""
|
||||
|
||||
def _get_channel_tree(self):
|
||||
if self._channelTree and not AXUtilities.is_defunct(self._channelTree):
|
||||
return self._channelTree
|
||||
|
||||
activeWindow = cthulhu_state.activeWindow
|
||||
if not activeWindow:
|
||||
return None
|
||||
|
||||
def is_channels_tree(obj):
|
||||
return AXUtilities.is_tree(obj) and AXObject.get_name(obj) == "Channels and users"
|
||||
|
||||
self._channelTree = AXObject.find_descendant(activeWindow, is_channels_tree)
|
||||
return self._channelTree
|
||||
@@ -0,0 +1,11 @@
|
||||
mumble_python_sources = files([
|
||||
'__init__.py',
|
||||
'chat.py',
|
||||
'script.py',
|
||||
'script_utilities.py',
|
||||
])
|
||||
|
||||
python3.install_sources(
|
||||
mumble_python_sources,
|
||||
subdir: 'cthulhu/scripts/apps/Mumble'
|
||||
)
|
||||
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2024 Stormux
|
||||
# Copyright (c) 2010-2012 The Orca Team
|
||||
# Copyright (c) 2012 Igalia, S.L.
|
||||
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||
# Boston MA 02110-1301 USA.
|
||||
#
|
||||
# Forked from Orca screen reader.
|
||||
# Cthulhu project: https://git.stormux.org/storm/cthulhu
|
||||
|
||||
"""Custom script for Mumble."""
|
||||
|
||||
__id__ = "$Id$"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2024 Stormux."
|
||||
__license__ = "LGPL"
|
||||
|
||||
import time
|
||||
|
||||
import cthulhu.debug as debug
|
||||
import cthulhu.scripts.toolkits.Qt.script as Qt
|
||||
from cthulhu.ax_object import AXObject
|
||||
from cthulhu.ax_utilities import AXUtilities
|
||||
|
||||
from .chat import Chat
|
||||
from .script_utilities import Utilities
|
||||
|
||||
|
||||
class Script(Qt.Script):
|
||||
"""Mumble-specific script tweaks."""
|
||||
|
||||
def __init__(self, app):
|
||||
self._lastConnectFocusName = ""
|
||||
self._lastConnectFocusRole = None
|
||||
self._lastConnectFocusTime = 0.0
|
||||
self._lastMessageDialogId = None
|
||||
|
||||
super().__init__(app)
|
||||
|
||||
def getChat(self):
|
||||
return Chat(self)
|
||||
|
||||
def getUtilities(self):
|
||||
return Utilities(self)
|
||||
|
||||
def setupInputEventHandlers(self):
|
||||
super().setupInputEventHandlers()
|
||||
self.inputEventHandlers.update(self.chat.inputEventHandlers)
|
||||
|
||||
def getAppKeyBindings(self):
|
||||
return self.chat.keyBindings
|
||||
|
||||
def getAppPreferencesGUI(self):
|
||||
return self.chat.getAppPreferencesGUI()
|
||||
|
||||
def getPreferencesFromGUI(self):
|
||||
return self.chat.getPreferencesFromGUI()
|
||||
|
||||
def onTextInserted(self, event):
|
||||
if self.chat.presentInsertedText(event):
|
||||
return
|
||||
|
||||
super().onTextInserted(event)
|
||||
|
||||
def onFocusedChanged(self, event):
|
||||
if self._should_ignore_connect_dialog_focus(event):
|
||||
return
|
||||
|
||||
super().onFocusedChanged(event)
|
||||
|
||||
def onCaretMoved(self, event):
|
||||
super().onCaretMoved(event)
|
||||
self._maybe_announce_message_dialog_input(event.source)
|
||||
|
||||
def _should_ignore_connect_dialog_focus(self, event):
|
||||
if not event.detail1:
|
||||
return False
|
||||
|
||||
obj = event.source
|
||||
if not self._is_in_connect_dialog(obj):
|
||||
return False
|
||||
|
||||
objName = AXObject.get_name(obj) or ""
|
||||
if not objName:
|
||||
return False
|
||||
|
||||
role = AXObject.get_role(obj)
|
||||
now = time.time()
|
||||
if self._lastConnectFocusName == objName \
|
||||
and self._lastConnectFocusRole == role \
|
||||
and (now - self._lastConnectFocusTime) < 0.35:
|
||||
msg = "MUMBLE: Ignoring duplicate focus event in connect dialog"
|
||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||
return True
|
||||
|
||||
self._lastConnectFocusName = objName
|
||||
self._lastConnectFocusRole = role
|
||||
self._lastConnectFocusTime = now
|
||||
return False
|
||||
|
||||
def _is_in_connect_dialog(self, obj):
|
||||
dialog = AXObject.find_ancestor(obj, AXUtilities.is_dialog)
|
||||
return bool(dialog) and AXObject.get_name(dialog) == "Mumble Server Connect"
|
||||
|
||||
def _maybe_announce_message_dialog_input(self, obj):
|
||||
if not obj or not AXUtilities.is_text(obj):
|
||||
return
|
||||
|
||||
if not AXUtilities.is_editable(obj):
|
||||
return
|
||||
|
||||
if AXObject.get_name(obj):
|
||||
return
|
||||
|
||||
dialog = AXObject.find_ancestor(obj, AXUtilities.is_dialog)
|
||||
if not dialog:
|
||||
return
|
||||
|
||||
dialogName = AXObject.get_name(dialog) or ""
|
||||
if not dialogName.startswith("Sending message to "):
|
||||
return
|
||||
|
||||
dialogHash = hash(dialog)
|
||||
if dialogHash == self._lastMessageDialogId:
|
||||
return
|
||||
|
||||
self._lastMessageDialogId = dialogHash
|
||||
label = "Message"
|
||||
voice = self.speechGenerator.voice(string=label)
|
||||
self.speakMessage(label, voice=voice)
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2024 Stormux
|
||||
# Copyright (c) 2010-2012 The Orca Team
|
||||
# Copyright (c) 2012 Igalia, S.L.
|
||||
# Copyright (c) 2005-2010 Sun Microsystems Inc.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
|
||||
# Boston MA 02110-1301 USA.
|
||||
#
|
||||
# Forked from Orca screen reader.
|
||||
# Cthulhu project: https://git.stormux.org/storm/cthulhu
|
||||
|
||||
"""Custom script utilities for Mumble."""
|
||||
|
||||
__id__ = "$Id$"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2024 Stormux."
|
||||
__license__ = "LGPL"
|
||||
|
||||
import cthulhu.scripts.toolkits.Qt.script_utilities as Qt
|
||||
from cthulhu.ax_object import AXObject
|
||||
from cthulhu.ax_utilities import AXUtilities
|
||||
|
||||
|
||||
class Utilities(Qt.Utilities):
|
||||
"""Mumble-specific script utilities."""
|
||||
|
||||
def shouldReadFullRow(self, obj):
|
||||
if self._is_connect_server_list_cell(obj):
|
||||
return False
|
||||
|
||||
return super().shouldReadFullRow(obj)
|
||||
|
||||
def _is_connect_server_list_cell(self, obj):
|
||||
if not AXUtilities.is_table_cell_or_header(obj):
|
||||
return False
|
||||
|
||||
dialog = AXObject.find_ancestor(obj, AXUtilities.is_dialog)
|
||||
if not dialog or AXObject.get_name(dialog) != "Mumble Server Connect":
|
||||
return False
|
||||
|
||||
tree = AXObject.find_ancestor(
|
||||
obj,
|
||||
lambda x: AXUtilities.is_tree(x) and AXObject.get_name(x) == "Server list"
|
||||
)
|
||||
return tree is not None
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
__all__ = ['Banshee',
|
||||
'Eclipse',
|
||||
'Mumble',
|
||||
'epiphany',
|
||||
'evince',
|
||||
'evolution',
|
||||
|
||||
@@ -9,6 +9,7 @@ python3.install_sources(
|
||||
|
||||
subdir('Banshee')
|
||||
subdir('Eclipse')
|
||||
subdir('Mumble')
|
||||
subdir('SeaMonkey')
|
||||
subdir('Thunderbird')
|
||||
subdir('epiphany')
|
||||
@@ -26,4 +27,4 @@ subdir('pidgin')
|
||||
subdir('soffice')
|
||||
subdir('smuxi-frontend-gnome')
|
||||
subdir('steamwebhelper')
|
||||
subdir('xfwm4')
|
||||
subdir('xfwm4')
|
||||
|
||||
Reference in New Issue
Block a user