Fixed version for master branch.
This commit is contained in:
commit
7a87fb51bb
10
install.sh
10
install.sh
@ -1,12 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
#Basic install script for Fenrir.
|
#Basic install script for Fenrir.
|
||||||
read -p "This will install Fenrir. Press ctrl+C to cancel, or enter to continue." continue
|
read -rp "This will install Fenrir. Press ctrl+C to cancel, or enter to continue."
|
||||||
|
|
||||||
# Fenrir main application
|
# Fenrir main application
|
||||||
install -m755 -d /opt/fenrirscreenreader
|
install -m755 -d /opt/fenrirscreenreader
|
||||||
cp -af src/* /opt/fenrirscreenreader
|
cp -af src/* /opt/fenrirscreenreader
|
||||||
|
|
||||||
ln -fs /opt/fenrirscreenreader/fenrir-daemon /usr/bin/fenrir-daemon
|
|
||||||
ln -fs /opt/fenrirscreenreader/fenrir /usr/bin/fenrir
|
ln -fs /opt/fenrirscreenreader/fenrir /usr/bin/fenrir
|
||||||
# tools
|
# tools
|
||||||
install -m755 -d /usr/share/fenrirscreenreader/tools
|
install -m755 -d /usr/share/fenrirscreenreader/tools
|
||||||
@ -33,8 +32,9 @@ cp -af config/sound/template /usr/share/sounds/fenrirscreenreader/template
|
|||||||
# config
|
# config
|
||||||
if [ -f "/etc/fenrirscreenreader/settings/settings.conf" ]; then
|
if [ -f "/etc/fenrirscreenreader/settings/settings.conf" ]; then
|
||||||
echo "Do you want to overwrite your current global settings? (y/n)"
|
echo "Do you want to overwrite your current global settings? (y/n)"
|
||||||
read yn
|
read -r yn
|
||||||
if [ $yn = "Y" -o $yn = "y" ]; then
|
yn="${yn:0:1}"
|
||||||
|
if [[ "${yn^}" == "Y" ]]; then
|
||||||
mv /etc/fenrirscreenreader/settings/settings.conf /etc/fenrirscreenreader/settings/settings.conf.bak
|
mv /etc/fenrirscreenreader/settings/settings.conf /etc/fenrirscreenreader/settings/settings.conf.bak
|
||||||
echo "Your old settings.conf has been backed up to settings.conf.bak."
|
echo "Your old settings.conf has been backed up to settings.conf.bak."
|
||||||
install -m644 -D "config/settings/settings.conf" /etc/fenrirscreenreader/settings/settings.conf
|
install -m644 -D "config/settings/settings.conf" /etc/fenrirscreenreader/settings/settings.conf
|
||||||
|
@ -3,6 +3,6 @@ daemonize>=2.5.0
|
|||||||
dbus-python>=1.2.8
|
dbus-python>=1.2.8
|
||||||
pyudev>=0.21.0
|
pyudev>=0.21.0
|
||||||
pexpect
|
pexpect
|
||||||
ppyperclip
|
pyperclip
|
||||||
pyte>=0.7.0
|
pyte>=0.7.0
|
||||||
rapidfuzz>=2.0.0
|
rapidfuzz>=2.0.0
|
||||||
|
@ -11,6 +11,14 @@ class cursorManager():
|
|||||||
pass
|
pass
|
||||||
def initialize(self, environment):
|
def initialize(self, environment):
|
||||||
self.env = environment
|
self.env = environment
|
||||||
|
def shouldProcessNumpadCommands(self):
|
||||||
|
"""
|
||||||
|
Check if numpad commands should be processed based on numlock state
|
||||||
|
Return True if numlock is OFF (commands should work)
|
||||||
|
Return False if numlock is ON (let keys type numbers)
|
||||||
|
"""
|
||||||
|
# Return False if numlock is ON
|
||||||
|
return not self.env['input']['newNumLock']
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
pass
|
pass
|
||||||
def clearMarks(self):
|
def clearMarks(self):
|
||||||
|
@ -42,6 +42,25 @@ class inputDriver():
|
|||||||
if not self._initialized:
|
if not self._initialized:
|
||||||
return True
|
return True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def forceUngrab(self):
|
||||||
|
"""Emergency method to release grabbed devices in case of failure"""
|
||||||
|
if not self._initialized:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
# Try standard ungrab first
|
||||||
|
return self.ungrabAllDevices()
|
||||||
|
except Exception as e:
|
||||||
|
# Just log the failure and inform the user
|
||||||
|
if hasattr(self, 'env') and 'runtime' in self.env and 'debug' in self.env['runtime']:
|
||||||
|
self.env['runtime']['debug'].writeDebugOut(
|
||||||
|
f"Emergency device release failed: {str(e)}",
|
||||||
|
debug.debugLevel.ERROR
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(f"Emergency device release failed: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
def hasIDevices(self):
|
def hasIDevices(self):
|
||||||
if not self._initialized:
|
if not self._initialized:
|
||||||
return False
|
return False
|
||||||
|
@ -49,6 +49,7 @@ class inputManager():
|
|||||||
return event
|
return event
|
||||||
def setExecuteDeviceGrab(self, newExecuteDeviceGrab = True):
|
def setExecuteDeviceGrab(self, newExecuteDeviceGrab = True):
|
||||||
self.executeDeviceGrab = newExecuteDeviceGrab
|
self.executeDeviceGrab = newExecuteDeviceGrab
|
||||||
|
|
||||||
def handleDeviceGrab(self, force = False):
|
def handleDeviceGrab(self, force = False):
|
||||||
if force:
|
if force:
|
||||||
self.setExecuteDeviceGrab()
|
self.setExecuteDeviceGrab()
|
||||||
@ -61,17 +62,38 @@ class inputManager():
|
|||||||
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
if not self.env['runtime']['settingsManager'].getSettingAsBool('keyboard', 'grabDevices'):
|
||||||
self.executeDeviceGrab = False
|
self.executeDeviceGrab = False
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Add maximum retries to prevent infinite loops
|
||||||
|
maxRetries = 5
|
||||||
|
retryCount = 0
|
||||||
|
grabTimeout = 3 # Timeout in seconds
|
||||||
|
startTime = time.time()
|
||||||
|
|
||||||
if self.env['runtime']['screenManager'].getCurrScreenIgnored():
|
if self.env['runtime']['screenManager'].getCurrScreenIgnored():
|
||||||
while not self.ungrabAllDevices():
|
while not self.ungrabAllDevices():
|
||||||
|
retryCount += 1
|
||||||
|
if retryCount >= maxRetries or (time.time() - startTime) > grabTimeout:
|
||||||
|
self.env['runtime']['debug'].writeDebugOut("Failed to ungrab devices after multiple attempts", debug.debugLevel.ERROR)
|
||||||
|
# Force a release of devices if possible through alternative means
|
||||||
|
try:
|
||||||
|
self.env['runtime']['inputDriver'].forceUngrab()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
break
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
self.env['runtime']['debug'].writeDebugOut("retry ungrabAllDevices " ,debug.debugLevel.WARNING)
|
self.env['runtime']['debug'].writeDebugOut(f"retry ungrabAllDevices {retryCount}/{maxRetries}", debug.debugLevel.WARNING)
|
||||||
self.env['runtime']['debug'].writeDebugOut("All devices ungrabbed" ,debug.debugLevel.INFO)
|
|
||||||
else:
|
else:
|
||||||
while not self.grabAllDevices():
|
while not self.grabAllDevices():
|
||||||
|
retryCount += 1
|
||||||
|
if retryCount >= maxRetries or (time.time() - startTime) > grabTimeout:
|
||||||
|
self.env['runtime']['debug'].writeDebugOut("Failed to grab devices after multiple attempts", debug.debugLevel.ERROR)
|
||||||
|
# Continue without grabbing input - limited functionality but not locked
|
||||||
|
break
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
self.env['runtime']['debug'].writeDebugOut("retry grabAllDevices" ,debug.debugLevel.WARNING)
|
self.env['runtime']['debug'].writeDebugOut(f"retry grabAllDevices {retryCount}/{maxRetries}", debug.debugLevel.WARNING)
|
||||||
self.env['runtime']['debug'].writeDebugOut("All devices grabbed" ,debug.debugLevel.INFO)
|
|
||||||
self.executeDeviceGrab = False
|
self.executeDeviceGrab = False
|
||||||
|
|
||||||
def sendKeys(self, keyMacro):
|
def sendKeys(self, keyMacro):
|
||||||
for e in keyMacro:
|
for e in keyMacro:
|
||||||
key = ''
|
key = ''
|
||||||
@ -252,17 +274,39 @@ class inputManager():
|
|||||||
def getCurrShortcut(self, inputSequence = None):
|
def getCurrShortcut(self, inputSequence = None):
|
||||||
shortcut = []
|
shortcut = []
|
||||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||||
|
|
||||||
|
numpadKeys = ['KEY_KP0', 'KEY_KP1', 'KEY_KP2', 'KEY_KP3', 'KEY_KP4',
|
||||||
|
'KEY_KP5', 'KEY_KP6', 'KEY_KP7', 'KEY_KP8', 'KEY_KP9',
|
||||||
|
'KEY_KPDOT', 'KEY_KPPLUS', 'KEY_KPMINUS', 'KEY_KPASTERISK',
|
||||||
|
'KEY_KPSLASH', 'KEY_KPENTER', 'KEY_KPEQUAL']
|
||||||
if inputSequence:
|
if inputSequence:
|
||||||
|
# Check if any key in the sequence is a numpad key and numlock is ON
|
||||||
|
# If numlock is ON and any key in the sequence is a numpad key, return an empty shortcut
|
||||||
|
if not self.env['runtime']['cursorManager'].shouldProcessNumpadCommands():
|
||||||
|
for key in inputSequence:
|
||||||
|
if key in numpadKeys:
|
||||||
|
# Return an empty/invalid shortcut that won't match any command
|
||||||
|
return "[]"
|
||||||
|
|
||||||
shortcut.append(inputSequence)
|
shortcut.append(inputSequence)
|
||||||
else:
|
else:
|
||||||
|
# Same check for current input
|
||||||
|
|
||||||
|
if not self.env['runtime']['cursorManager'].shouldProcessNumpadCommands():
|
||||||
|
for key in self.env['input']['currInput']:
|
||||||
|
if key in numpadKeys:
|
||||||
|
# Return an empty/invalid shortcut that won't match any command
|
||||||
|
return "[]"
|
||||||
|
|
||||||
shortcut.append(self.env['input']['currInput'])
|
shortcut.append(self.env['input']['currInput'])
|
||||||
|
|
||||||
if len(self.env['input']['prevInput']) < len(self.env['input']['currInput']):
|
if len(self.env['input']['prevInput']) < len(self.env['input']['currInput']):
|
||||||
if self.env['input']['shortcutRepeat'] > 1 and not self.shortcutExists(str(shortcut)):
|
if self.env['input']['shortcutRepeat'] > 1 and not self.shortcutExists(str(shortcut)):
|
||||||
shortcut = []
|
shortcut = []
|
||||||
self.env['input']['shortcutRepeat'] = 1
|
self.env['input']['shortcutRepeat'] = 1
|
||||||
shortcut.append(self.env['input']['shortcutRepeat'])
|
shortcut.append(self.env['input']['shortcutRepeat'])
|
||||||
shortcut.append(self.env['input']['currInput'])
|
shortcut.append(self.env['input']['currInput'])
|
||||||
self.env['runtime']['debug'].writeDebugOut("currShortcut " + str(shortcut) ,debug.debugLevel.INFO)
|
self.env['runtime']['debug'].writeDebugOut("currShortcut " + str(shortcut), debug.debugLevel.INFO)
|
||||||
return str(shortcut)
|
return str(shortcut)
|
||||||
|
|
||||||
def currKeyIsModifier(self):
|
def currKeyIsModifier(self):
|
||||||
|
@ -4,5 +4,5 @@
|
|||||||
# Fenrir TTY screen reader
|
# Fenrir TTY screen reader
|
||||||
# By Chrys, Storm Dragon, and contributers.
|
# By Chrys, Storm Dragon, and contributers.
|
||||||
|
|
||||||
version = "2025.03.02"
|
version = "2025.04.14"
|
||||||
codeName = "master"
|
codeName = "master"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user