Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check Z-Order for making content accessible on the lock screen. #14416

Merged
merged 28 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6039b53
Check Z-Order for making content accessible on the lock screen.
seanbudd Nov 10, 2022
b78dc61
add unit tests for lockscreen order tracking
seanbudd Dec 5, 2022
25e5b4c
improve temp documentation
seanbudd Dec 5, 2022
cb47620
improve test docs
seanbudd Dec 6, 2022
cea66f3
improve docs and testing
seanbudd Dec 6, 2022
3b31a3c
improve tests
seanbudd Dec 7, 2022
da56e3f
fix up typing
seanbudd Dec 7, 2022
49e6de0
use bi-directional search
seanbudd Dec 8, 2022
f35fe01
add missing tests
seanbudd Dec 8, 2022
7070762
remove redundant initialization changes
seanbudd Dec 8, 2022
f8fb374
make approach more robust
seanbudd Dec 8, 2022
452babc
walk backwards algorithm
seanbudd Dec 9, 2022
a69a4a2
fix up algorithm and tests
seanbudd Dec 12, 2022
962c26f
fix up docstring
seanbudd Dec 12, 2022
7e99d81
address review comments
seanbudd Dec 13, 2022
828ccea
minor further fixups
seanbudd Dec 13, 2022
544fa7a
fix up todos
seanbudd Dec 14, 2022
97d86ad
search for lock app appmodule in core pump
seanbudd Dec 15, 2022
c4b3f8e
refer as below instead of above
seanbudd Dec 15, 2022
dfa30dd
fixup comment from review suggestions
seanbudd Dec 15, 2022
0a73109
fix up suggestion
seanbudd Dec 15, 2022
a979250
fixup incorrect comment
seanbudd Dec 15, 2022
a951ebe
Merge branch 'try-new-lock-tracking' of https://github.com/nvaccess/n…
seanbudd Dec 15, 2022
49cc36a
fix up comment
seanbudd Dec 15, 2022
0b305bc
fix unit tests
seanbudd Dec 15, 2022
363a1a2
Use lock screen window class names instead of checking for lockapp pr…
seanbudd Dec 15, 2022
d9565d6
log as exception
seanbudd Dec 16, 2022
cc14d58
update changes
seanbudd Dec 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions source/NVDAObjects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
TreeInterceptor,
)
import braille
from utils.security import _isObjectAboveLockScreen
import vision
import globalPluginHandler
import brailleInput
Expand Down Expand Up @@ -1433,3 +1434,11 @@ def getSelectedItemsCount(self,maxCount=2):
For performance, this method will only count up to the given maxCount number, and if there is one more above that, then sys.maxint is returned stating that many items are selected.
"""
return 0

#: Type definition for auto prop '_get_isAboveLockScreen'
isAboveLockScreen: bool

def _get_isAboveLockScreen(self) -> bool:
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
if not isWindowsLocked():
return True
return _isObjectAboveLockScreen(self)
5 changes: 4 additions & 1 deletion source/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,10 @@ def setReviewPosition(
@param isCaret: Whether the review position is changed due to caret following.
@param isMouse: Whether the review position is changed due to mouse following.
"""
if _isSecureObjectWhileLockScreenActivated(reviewPosition.obj):
reviewObj = reviewPosition.obj
if isinstance(reviewObj, treeInterceptorHandler.TreeInterceptor):
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
reviewObj = reviewObj.rootNVDAObject
if _isSecureObjectWhileLockScreenActivated(reviewObj):
return False
globalVars.reviewPosition=reviewPosition.copy()
globalVars.reviewPositionObj=reviewPosition.obj
Expand Down
30 changes: 26 additions & 4 deletions source/baseObject.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2007-2020 NV Access Limited, Christopher Toth, Babbage B.V., Julien Cochuyt
# Copyright (C) 2007-2022 NV Access Limited, Christopher Toth, Babbage B.V., Julien Cochuyt
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

"""Contains the base classes that many of NVDA's classes such as NVDAObjects, virtualBuffers, appModules, synthDrivers inherit from. These base classes provide such things as auto properties, and methods and properties for scripting and key binding.
"""

from typing import (
Any,
Callable,
Optional,
Set,
Union,
)
import weakref
import garbageHandler
from logHandler import log
from abc import ABCMeta, abstractproperty

GetterReturnT = Any
GetterMethodT = Callable[["AutoPropertyObject"], GetterReturnT]


class Getter(object):

def __init__(self,fget, abstract=False):
self.fget=fget
if abstract:
self._abstract = self.__isabstractmethod__ = abstract

def __get__(self,instance,owner):
def __get__(
self,
instance: Union[Any, None, "AutoPropertyObject"],
owner,
) -> Union[GetterReturnT, "Getter"]:
if isinstance(self.fget, classmethod):
return self.fget.__get__(instance, owner)()
elif instance is None:
Expand All @@ -31,16 +46,22 @@ def setter(self,func):
def deleter(self,func):
return (abstractproperty if self._abstract else property)(fget=self.fget,fdel=func)


class CachingGetter(Getter):

def __get__(self, instance, owner):
def __get__(
self,
instance: Union[Any, None, "AutoPropertyObject"],
owner,
) -> Union[GetterReturnT, "CachingGetter"]:
if isinstance(self.fget, classmethod):
log.warning("Class properties do not support caching")
return self.fget.__get__(instance, owner)()
elif instance is None:
return self
return instance._getPropertyViaCache(self.fget)


class AutoPropertyType(ABCMeta):

def __init__(self,name,bases,dict):
Expand Down Expand Up @@ -125,6 +146,7 @@ class AutoPropertyObject(garbageHandler.TrackedObject, metaclass=AutoPropertyTyp
#: @type: bool
cachePropertiesByDefault = False

_propertyCache: Set[GetterMethodT]

def __new__(cls, *args, **kwargs):
self = super(AutoPropertyObject, cls).__new__(cls)
Expand All @@ -134,7 +156,7 @@ def __new__(cls, *args, **kwargs):
self.__instances[self]=None
return self

def _getPropertyViaCache(self,getterMethod=None):
def _getPropertyViaCache(self, getterMethod: Optional[GetterMethodT] = None) -> GetterReturnT:
if not getterMethod:
raise ValueError("getterMethod is None")
missing=False
Expand Down
22 changes: 5 additions & 17 deletions source/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,6 @@ def onEndSession(evt):
wx.CallAfter(audioDucking.initialize)

from winAPI.messageWindow import WindowMessage
from winAPI import sessionTracking
import winUser
# #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR.
# NVDA uses the main frame to check for and quit another instance of NVDA.
Expand Down Expand Up @@ -630,27 +629,12 @@ def __init__(self, windowName=None):
self.orientationCoordsCache = (0,0)
self.handlePowerStatusChange()

# Call must be paired with a call to sessionTracking.unregister
if not sessionTracking.register(self.handle):
import utils.security
wx.CallAfter(utils.security.warnSessionLockStateUnknown)

def destroy(self):
"""
NVDA must unregister session tracking before destroying the message window.
"""
# Requires an active message window and a handle to unregister.
sessionTracking.unregister(self.handle)
super().destroy()

def windowProc(self, hwnd, msg, wParam, lParam):
post_windowMessageReceipt.notify(msg=msg, wParam=wParam, lParam=lParam)
if msg == WindowMessage.POWER_BROADCAST and wParam == self.PBT_APMPOWERSTATUSCHANGE:
self.handlePowerStatusChange()
elif msg == winUser.WM_DISPLAYCHANGE:
self.handleScreenOrientationChange(lParam)
elif msg == WindowMessage.WTS_SESSION_CHANGE:
sessionTracking.handleSessionChange(sessionTracking.WindowsTrackedSession(wParam), lParam)

def handleScreenOrientationChange(self, lParam):
# TODO: move to winAPI
Expand Down Expand Up @@ -809,7 +793,8 @@ def run(self):
mouseHandler.pumpAll()
braille.pumpAll()
vision.pumpAll()
except:
sessionTracking.pumpAll()
except Exception:
log.exception("errors in this core pump cycle")
baseObject.AutoPropertyObject.invalidateCaches()
watchdog.asleep()
Expand All @@ -832,6 +817,9 @@ def run(self):
log.debug("initializing updateCheck")
updateCheck.initialize()

from winAPI import sessionTracking
sessionTracking.initialize()

_TrackNVDAInitialization.markInitializationComplete()

log.info("NVDA initialized")
Expand Down
3 changes: 2 additions & 1 deletion source/globalVars.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import typing

if typing.TYPE_CHECKING:
import documentBase # noqa: F401 used for type checking only
import NVDAObjects # noqa: F401 used for type checking only


Expand Down Expand Up @@ -70,7 +71,7 @@ class DefaultAppArgs(argparse.Namespace):
mouseOldY=None
navigatorObject: typing.Optional['NVDAObjects.NVDAObject'] = None
reviewPosition=None
reviewPositionObj=None
reviewPositionObj: typing.Optional["documentBase.TextContainerObject"] = None
lastProgressValue=0
appArgs = DefaultAppArgs()
unknownAppArgs: typing.List[str] = []
Expand Down
12 changes: 9 additions & 3 deletions source/nvda.pyw
Original file line number Diff line number Diff line change
Expand Up @@ -350,13 +350,19 @@ if mutex is None:
sys.exit(1)


if _isSecureDesktop():
def _serviceDebugEnabled() -> bool:
import winreg
try:
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\NVDA")
if not winreg.QueryValueEx(k, u"serviceDebug")[0]:
globalVars.appArgs.secure = True
if winreg.QueryValueEx(k, "serviceDebug")[0]:
return True
except WindowsError:
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
pass
return False


if _isSecureDesktop():
if not _serviceDebugEnabled():
globalVars.appArgs.secure = True
globalVars.appArgs.changeScreenReaderFlag = False
globalVars.appArgs.minimal = True
Expand Down
14 changes: 10 additions & 4 deletions source/textInfos/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# A part of NonVisual Desktop Access (NVDA)
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
# Copyright (C) 2006-2021 NV Access Limited, Babbage B.V., Accessolutions, Julien Cochuyt
# Copyright (C) 2006-2022 NV Access Limited, Babbage B.V., Accessolutions, Julien Cochuyt

"""Framework for accessing text content in widgets.
The core component of this framework is the L{TextInfo} class.
Expand Down Expand Up @@ -31,8 +31,10 @@
from logHandler import log

if typing.TYPE_CHECKING:
import documentBase # noqa: F401 used for type checking only
import NVDAObjects


SpeechSequence = List[Union[Any, str]]

class Field(dict):
Expand Down Expand Up @@ -307,7 +309,11 @@ class TextInfo(baseObject.AutoPropertyObject):
@type bookmark: L{Bookmark}
"""

def __init__(self,obj,position):
def __init__(
self,
obj: "documentBase.TextContainerObject",
position
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
):
"""Constructor.
Subclasses must extend this, calling the superclass method first.
@param position: The initial position of this range; one of the POSITION_* constants or a position object supported by the implementation.
Expand Down Expand Up @@ -338,9 +344,9 @@ def _set_end(self, otherEndpoint: "TextInfoEndpoint"):
self.end.moveTo(otherEndpoint)

#: Typing information for auto-property: _get_obj
obj: "NVDAObjects.NVDAObject"
obj: "documentBase.TextContainerObject"

def _get_obj(self) -> "NVDAObjects.NVDAObject":
def _get_obj(self) -> "documentBase.TextContainerObject":
"""The object containing the range of text being represented."""
return self._obj()

Expand Down
18 changes: 12 additions & 6 deletions source/treeInterceptorHandler.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# treeInterceptorHandler.py
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2006-2020 NV Access Limited, Davy Kager, Accessolutions, Julien Cochuyt
# Copyright (C) 2006-2022 NV Access Limited, Davy Kager, Accessolutions, Julien Cochuyt
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

from typing import Optional, Dict
from typing import (
TYPE_CHECKING,
Dict,
Optional,
)

from logHandler import log
import baseObject
Expand All @@ -18,6 +21,10 @@
from speech.types import SpeechSequence
from controlTypes import OutputReason

if TYPE_CHECKING:
import NVDAObjects


runningTable=set()

def getTreeInterceptor(obj):
Expand Down Expand Up @@ -84,12 +91,11 @@ class TreeInterceptor(baseObject.ScriptableObject):

shouldTrapNonCommandGestures=False #: If true then gestures that do not have a script and are not a command gesture should be trapped from going through to Windows.

def __init__(self, rootNVDAObject):
def __init__(self, rootNVDAObject: "NVDAObjects.NVDAObject"):
super(TreeInterceptor, self).__init__()
self._passThrough = False
#: The root object of the tree wherein events and scripts are intercepted.
#: @type: L{NVDAObjects.NVDAObject}
self.rootNVDAObject = rootNVDAObject
self.rootNVDAObject: "NVDAObjects.NVDAObject" = rootNVDAObject

def terminate(self):
"""Terminate this interceptor.
Expand Down
Loading