Skip to content

Commit 287d171

Browse files
authored
Merge 4bf6ed5 into 4b339e2
2 parents 4b339e2 + 4bf6ed5 commit 287d171

24 files changed

Lines changed: 100 additions & 180 deletions

source/appModuleHandler.py

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,63 @@
5151
post_appSwitch = extensionPoints.Action()
5252

5353

54+
_executableNamesToAppMods: Dict[str, str] = {
55+
# Azure Data Studio (both stable and Insiders versions) should use module for Visual Studio Code
56+
"azuredatastudio": "code",
57+
"azuredatastudio-insiders": "code",
58+
# Windows 11 calculator should use module for the Windows 10 one.
59+
"calculatorapp": "calculator",
60+
# The Insider version of Visual Studio Code should use the module for the stable version.
61+
62+
"code - insiders": "code",
63+
# commsapps is an alias for the Windows 10 mail and calendar.
64+
"commsapps": "hxmail",
65+
# DBeaver is based on Eclipse and should use its appModule.
66+
"dbeaver": "eclipse",
67+
# Preview version of the Adobe Digital Editions should use the module for the stable version.
68+
"digitaleditionspreview": "digitaleditions",
69+
# Esybraille should use module for esysuite.
70+
"esybraille": "esysuite",
71+
# hxoutlook is an alias for Windows 10 mail in Creators update.
72+
"hxoutlook": "hxmail",
73+
# 64-bit versions of Miranda IM should use module for the 32-bit executable.
74+
"miranda64": "miranda32",
75+
# Various incarnations of Media Player Classic.
76+
"mpc-hc": "mplayerc",
77+
"mpc-hc64": "mplayerc",
78+
# searchapp is an alias for searchui in Windows 10 build 18965 and later.
79+
"searchapp": "searchui",
80+
# Windows search in Windows 11.
81+
"searchhost": "searchui",
82+
# Spring Tool Suite is based on Eclipse and should use its appModule.
83+
"springtoolsuite4": "eclipse",
84+
"sts": "eclipse",
85+
# Various versions of Teamtalk.
86+
"teamtalk3": "teamtalk4classic",
87+
# App module for Windows 10/11 Modern Keyboard aka new touch keyboard panel
88+
# should use Composable Shell modern keyboard app module
89+
"textinputhost": "windowsinternal_composableshell_experiences_textinput_inputapp",
90+
# Total Commander X64 should use the module for the 32-bit version.
91+
"totalcmd64": "totalcmd",
92+
# The calculator on Windows Server and LTSB versions of Windows 10
93+
# should use the module for the desktop calculator from the earlier Windows releases.
94+
"win32calc": "calc",
95+
# Windows Mail should use module for Outlook Express.
96+
"winmail": "msimn",
97+
# Zend Eclipse PHP Developer Tools is based on Eclipse and should use its appModule.
98+
"zend-eclipse-php": "eclipse",
99+
# Zend Studio is based on Eclipse and should use its appModule.
100+
"zendstudio": "eclipse",
101+
}
102+
103+
"""Maps names of the executables to the names of the appModule which should be loaded for the given program.
104+
This mapping is needed since:
105+
- Names of some programs are incompatible with the Python's import system (they contain a dot or a plus)
106+
- Sometimes it is necessary to map one module to multiple executables - this map saves us from adding multiple
107+
appModules in such cases.
108+
"""
109+
110+
54111
class processEntry32W(ctypes.Structure):
55112
_fields_ = [
56113
("dwSize",ctypes.wintypes.DWORD),
@@ -65,6 +122,29 @@ class processEntry32W(ctypes.Structure):
65122
("szExeFile", ctypes.c_wchar * 260)
66123
]
67124

125+
126+
def registerExecutableWithAppModule(executableName: str, appModName: str) -> None:
127+
"""Registers appModule to be used for a given executable.
128+
"""
129+
_executableNamesToAppMods[executableName] = appModName
130+
131+
132+
def unregisterExecutable(executableName: str) -> None:
133+
"""Removes the executable of a given name from the mapping of applications to appModules.
134+
"""
135+
try:
136+
del _executableNamesToAppMods[executableName]
137+
except KeyError:
138+
log.error(f"Executable {executableName} was not previously registered.")
139+
140+
141+
def _getAppModuleNameFromExecutable(executableName: str) -> str:
142+
"""Returns name of the appModule which should be used for a given executable.
143+
If there is no mapping for the given program just returns the executable name.
144+
"""
145+
return _executableNamesToAppMods.get(executableName, executableName)
146+
147+
68148
def getAppNameFromProcessID(processID,includeExt=False):
69149
"""Finds out the application name of the given process.
70150
@param processID: the ID of the process handle of the application you wish to get the name of.
@@ -95,7 +175,10 @@ def getAppNameFromProcessID(processID,includeExt=False):
95175
# This might be an executable which hosts multiple apps.
96176
# Try querying the app module for the name of the app being hosted.
97177
try:
98-
mod = importlib.import_module("appModules.%s" % appName, package="appModules")
178+
mod = importlib.import_module(
179+
f"appModules.{_getAppModuleNameFromExecutable(appName)}",
180+
package="appModules"
181+
)
99182
return mod.getAppNameFromHost(processID)
100183
except (ImportError, AttributeError, LookupError):
101184
pass
@@ -153,25 +236,30 @@ def cleanup():
153236
except:
154237
log.exception("Error terminating app module %r" % deadMod)
155238

156-
def doesAppModuleExist(name):
157-
return any(importer.find_module("appModules.%s" % name) for importer in _importers)
158239

159-
def fetchAppModule(processID,appName):
240+
def doesAppModuleExist(name: str) -> bool:
241+
return any(
242+
importer.find_module(
243+
f"appModules.{_getAppModuleNameFromExecutable(name)}"
244+
) for importer in _importers
245+
)
246+
247+
248+
def fetchAppModule(processID: int, appName: str) -> AppModule:
160249
"""Returns an appModule found in the appModules directory, for the given application name.
161250
@param processID: process ID for it to be associated with
162-
@type processID: integer
163251
@param appName: the application name for which an appModule should be found.
164-
@type appName: str
165252
@returns: the appModule, or None if not found
166-
@rtype: AppModule
167253
"""
168254
# First, check whether the module exists.
169255
# We need to do this separately because even though an ImportError is raised when a module can't be found, it might also be raised for other reasons.
170256
modName = appName
171257

172258
if doesAppModuleExist(modName):
173259
try:
174-
return importlib.import_module("appModules.%s" % modName, package="appModules").AppModule(processID, appName)
260+
return importlib.import_module(
261+
f"appModules.{_getAppModuleNameFromExecutable(modName)}", package="appModules"
262+
).AppModule(processID, appName)
175263
except:
176264
log.exception(f"error in appModule {modName!r}")
177265
import ui
@@ -311,6 +399,10 @@ class AppModule(baseObject.ScriptableObject):
311399
Each app module should be a Python module or a package in the appModules package
312400
named according to the executable it supports;
313401
e.g. explorer.py for the explorer.exe application or firefox/__init__.py for firefox.exe.
402+
If the name of the executable is not compatible with the Python's import system
403+
i.e. contains some special characters such as "." or "+" you can name the module however you like
404+
and then map the executable name to the module name
405+
by adding an entry to `_executableNamesToAppMods` dictionary.
314406
It should containa C{AppModule} class which inherits from this base class.
315407
App modules can implement and bind gestures to scripts.
316408
These bindings will only take effect while an object in the associated application has focus.

source/appModules/azuredatastudio-insiders.py

Lines changed: 0 additions & 11 deletions
This file was deleted.

source/appModules/azuredatastudio.py

Lines changed: 0 additions & 11 deletions
This file was deleted.

source/appModules/calculatorapp.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

source/appModules/code - insiders.py

Lines changed: 0 additions & 11 deletions
This file was deleted.

source/appModules/commsapps.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

source/appModules/dbeaver.py

Lines changed: 0 additions & 11 deletions
This file was deleted.

source/appModules/digitaleditionspreview.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

source/appModules/esybraille.py

Lines changed: 0 additions & 11 deletions
This file was deleted.

source/appModules/hxoutlook.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)