Skip to content

Commit

Permalink
You can now have different settings for different situations using co…
Browse files Browse the repository at this point in the history
…nfiguration profiles. Profiles can be activated manually or automatically (e.g. for a particular application).

Fixes #87, #667, #1913.
  • Loading branch information
jcsteh committed Oct 16, 2013
2 parents 01e75f9 + 0ab70c0 commit d92358e
Show file tree
Hide file tree
Showing 17 changed files with 1,439 additions and 206 deletions.
15 changes: 4 additions & 11 deletions source/api.py
Expand Up @@ -23,6 +23,7 @@
import eventHandler
import braille
import watchdog
import appModuleHandler

#User functions

Expand Down Expand Up @@ -65,7 +66,7 @@ def setFocusObject(obj):
#add the old focus to the old focus ancestors, but only if its not None (is none at NVDA initialization)
if globalVars.focusObject:
oldFocusLine.append(globalVars.focusObject)
oldAppModuleSet=set(o.appModule for o in oldFocusLine if o and o.appModule)
oldAppModules=[o.appModule for o in oldFocusLine if o and o.appModule]
ancestors=[]
tempObj=obj
matchedOld=False
Expand Down Expand Up @@ -105,18 +106,10 @@ def setFocusObject(obj):
container=tempObj.container
tempObj.container=container # Cache the parent.
tempObj=container
newAppModules=[o.appModule for o in ancestors if o and o.appModule]
#Remove the final new ancestor as this will be the new focus object
del ancestors[-1]
newAppModuleSet=set(o.appModule for o in ancestors+[obj] if o and o.appModule)
for removedMod in oldAppModuleSet-newAppModuleSet:
if not removedMod.sleepMode and hasattr(removedMod,'event_appModule_loseFocus'):
try:
removedMod.event_appModule_loseFocus()
except watchdog.CallCancelled:
pass
for addedMod in newAppModuleSet-oldAppModuleSet:
if not addedMod.sleepMode and hasattr(addedMod,'event_appModule_gainFocus'):
addedMod.event_appModule_gainFocus()
appModuleHandler.handleAppSwitch(oldAppModules,newAppModules)
try:
treeInterceptorHandler.cleanup()
except watchdog.CallCancelled:
Expand Down
66 changes: 66 additions & 0 deletions source/appModuleHandler.py
Expand Up @@ -25,6 +25,7 @@
import NVDAObjects #Catches errors before loading default appModule
import api
import appModules
import watchdog

#Dictionary of processID:appModule paires used to hold the currently running modules
runningTable={}
Expand Down Expand Up @@ -176,6 +177,64 @@ def terminate():
log.exception("Error terminating app module %r" % app)
runningTable.clear()

def handleAppSwitch(oldMods, newMods):
newModsSet = set(newMods)
processed = set()
nextStage = []

# Determine all apps that are losing focus and fire appropriate events.
for mod in reversed(oldMods):
if mod in processed:
# This app has already been handled.
continue
processed.add(mod)
if mod in newModsSet:
# This app isn't losing focus.
continue
processed.add(mod)
# This app is losing focus.
nextStage.append(mod)
if not mod.sleepMode and hasattr(mod,'event_appModule_loseFocus'):
try:
mod.event_appModule_loseFocus()
except watchdog.CallCancelled:
pass

nvdaGuiLostFocus = nextStage and nextStage[-1].appName == "nvda"
if not nvdaGuiLostFocus and (not oldMods or oldMods[-1].appName != "nvda") and newMods[-1].appName == "nvda":
# NVDA's GUI just got focus.
import gui
if gui.shouldConfigProfileTriggersBeSuspended():
config.conf.suspendProfileTriggers()

with config.conf.atomicProfileSwitch():
# Exit triggers for apps that lost focus.
for mod in nextStage:
mod._configProfileTrigger.exit()
mod._configProfileTrigger = None

nextStage = []
# Determine all apps that are gaining focus and enter triggers.
for mod in newMods:
if mod in processed:
# This app isn't gaining focus or it has already been handled.
continue
processed.add(mod)
# This app is gaining focus.
nextStage.append(mod)
trigger = mod._configProfileTrigger = AppProfileTrigger(mod.appName)
trigger.enter()

if nvdaGuiLostFocus:
import gui
if not gui.shouldConfigProfileTriggersBeSuspended():
config.conf.resumeProfileTriggers()

# Fire appropriate events for apps gaining focus.
for mod in nextStage:
if not mod.sleepMode and hasattr(mod,'event_appModule_gainFocus'):
mod.event_appModule_gainFocus()

#base class for appModules
class AppModule(baseObject.ScriptableObject):
"""Base app module.
Expand Down Expand Up @@ -257,3 +316,10 @@ def _get_is64BitProcess(self):
return False
self.is64BitProcess = not res
return self.is64BitProcess

class AppProfileTrigger(config.ProfileTrigger):
"""A configuration profile trigger for when a particular application has focus.
"""

def __init__(self, appName):
self.spec = "app:%s" % appName
6 changes: 6 additions & 0 deletions source/appModules/nvda.py
Expand Up @@ -9,6 +9,8 @@
import controlTypes
import versionInfo
from NVDAObjects.IAccessible import IAccessible
import gui
import config

nvdaMenuIaIdentity = None

Expand Down Expand Up @@ -41,3 +43,7 @@ def event_gainFocus(self, obj, nextHandler):

# Silence invisible unknowns for stateChange as well.
event_stateChange = event_gainFocus

def event_foreground (self, obj, nextHandler):
if not gui.shouldConfigProfileTriggersBeSuspended():
config.conf.resumeProfileTriggers()
5 changes: 5 additions & 0 deletions source/braille.py
Expand Up @@ -1462,6 +1462,11 @@ def handleReviewMove(self):
# We're reviewing a different object.
self._doNewObject(getFocusRegions(reviewPos.obj, review=True))

def handleConfigProfileSwitch(self):
display = config.conf["braille"]["display"]
if display != self.display.name:
self.setDisplayByName(display)

def initialize():
global handler
config.addConfigDirsToPythonPackagePath(brailleDisplayDrivers)
Expand Down

0 comments on commit d92358e

Please sign in to comment.