def _getControlVersion(self): res = watchdog.cancellableSendMessage(self.windowHandle, AEM_CONTROLVERSION, None, None) major = winUser.LOBYTE(winUser.LOWORD(res)) minor = winUser.HIBYTE(winUser.LOWORD(res)) version = major + (0.1 * minor) return version
def inputTouchWndProc(self, hwnd, msg, wParam, lParam): if msg >= _WM_POINTER_FIRST and msg <= _WM_POINTER_LAST: flags = winUser.HIWORD(wParam) touching = (flags & POINTER_MESSAGE_FLAG_INRANGE) and ( flags & POINTER_MESSAGE_FLAG_FIRSTBUTTON) x = winUser.LOWORD(lParam) y = winUser.HIWORD(lParam) ID = winUser.LOWORD(wParam) if touching: self.trackerManager.update(ID, x, y, False) elif not flags & POINTER_MESSAGE_FLAG_FIRSTBUTTON: self.trackerManager.update(ID, x, y, True) return 0 return windll.user32.DefWindowProcW(hwnd, msg, wParam, lParam)
def consoleWinEventHook(handle,eventID,window,objectID,childID,threadID,timestamp): #We don't want to do anything with the event if the event is not for the window this console is in if window!=consoleObject.windowHandle: return if eventID==winUser.EVENT_CONSOLE_CARET and not eventHandler.isPendingEvents("caret",consoleObject): eventHandler.queueEvent("caret",consoleObject) # It is safe to call this event from this callback. # This avoids an extra core cycle. consoleObject.event_textChange() if eventID==winUser.EVENT_CONSOLE_UPDATE_SIMPLE: x=winUser.LOWORD(objectID) y=winUser.HIWORD(objectID) consoleScreenBufferInfo=wincon.GetConsoleScreenBufferInfo(consoleOutputHandle) if x<consoleScreenBufferInfo.dwCursorPosition.x and (y==consoleScreenBufferInfo.dwCursorPosition.y or y==consoleScreenBufferInfo.dwCursorPosition.y+1): eventHandler.queueEvent("typedCharacter",consoleObject,ch=unichr(winUser.LOWORD(childID)))
def _getPointFromOffset(self, offset): if self.obj.editAPIVersion == 1 or self.obj.editAPIVersion >= 3: processHandle = self.obj.processHandle internalP = winKernel.virtualAllocEx(processHandle, None, ctypes.sizeof(PointLStruct), winKernel.MEM_COMMIT, winKernel.PAGE_READWRITE) try: p = PointLStruct(0, 0) winKernel.writeProcessMemory(processHandle, internalP, ctypes.byref(p), ctypes.sizeof(p), None) watchdog.cancellableSendMessage(self.obj.windowHandle, EM_POSFROMCHAR, internalP, offset) winKernel.readProcessMemory(processHandle, internalP, ctypes.byref(p), ctypes.sizeof(p), None) finally: winKernel.virtualFreeEx(processHandle, internalP, 0, winKernel.MEM_RELEASE) point = textInfos.Point(p.x, p.y) else: res = watchdog.cancellableSendMessage(self.obj.windowHandle, EM_POSFROMCHAR, offset, None) point = textInfos.Point(winUser.LOWORD(res), winUser.HIWORD(res)) (left, top, width, height) = self.obj.location point.x = point.x + left point.y = point.y + top return point
def _getOffsetFromPoint(self,x,y): x, y = winUser.ScreenToClient(self.obj.windowHandle, x, y) if self.obj.editAPIVersion>=1: processHandle=self.obj.processHandle internalP=winKernel.virtualAllocEx(processHandle,None,ctypes.sizeof(PointLStruct),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) try: p=PointLStruct(x,y) winKernel.writeProcessMemory(processHandle,internalP,ctypes.byref(p),ctypes.sizeof(p),None) offset=watchdog.cancellableSendMessage(self.obj.windowHandle,winUser.EM_CHARFROMPOS,0,internalP) finally: winKernel.virtualFreeEx(processHandle,internalP,0,winKernel.MEM_RELEASE) else: p=x+(y<<16) res=watchdog.cancellableSendMessage(self.obj.windowHandle,winUser.EM_CHARFROMPOS,0,p) offset=winUser.LOWORD(res) lineNum=winUser.HIWORD(res) if offset==0xFFFF and lineNum==0xFFFF: raise LookupError("Point outside client area") if self._getStoryLength() > 0xFFFF: # Returned offsets are 16 bits, therefore for large documents, we need to make sure that the correct offset is returned. # We can calculate this by using the start offset of the line with the retrieved line number. lineStart=watchdog.cancellableSendMessage(self.obj.windowHandle,winUser.EM_LINEINDEX,lineNum,0) # Get the last 16 bits of the line number lineStart16=lineStart&0xFFFF if lineStart16 > offset: # There are cases where the last 16 bits of the line start are greater than the # 16 bits offset. For example, this happens when the line start offset is 65534 (0xFFFE) # and the offset we need ought to be 65537 (0x10001), which is a 17 bits number # In that case, add 0x10000 to the offset, which will make the eventual formula return the correct offset, # unless a line has more than 65535 characters, in which case we can't get a reliable offset. offset+=0x10000 offset = (offset - lineStart16) + lineStart return offset
def initialize(): global _remoteLib, _remoteLoader64, localLib, generateBeep, VBuf_getTextInRange, lastLanguageID, lastLayoutString hkl=c_ulong(windll.User32.GetKeyboardLayout(0)).value lastLanguageID=winUser.LOWORD(hkl) KL_NAMELENGTH=9 buf=create_unicode_buffer(KL_NAMELENGTH) res=windll.User32.GetKeyboardLayoutNameW(buf) if res: lastLayoutString=buf.value localLib=cdll.LoadLibrary(os.path.join(versionedLibPath,'nvdaHelperLocal.dll')) for name,func in [ ("nvdaController_speakText",nvdaController_speakText), ("nvdaController_cancelSpeech",nvdaController_cancelSpeech), ("nvdaController_brailleMessage",nvdaController_brailleMessage), ("nvdaControllerInternal_requestRegistration",nvdaControllerInternal_requestRegistration), ("nvdaControllerInternal_inputLangChangeNotify",nvdaControllerInternal_inputLangChangeNotify), ("nvdaControllerInternal_typedCharacterNotify",nvdaControllerInternal_typedCharacterNotify), ("nvdaControllerInternal_displayModelTextChangeNotify",nvdaControllerInternal_displayModelTextChangeNotify), ("nvdaControllerInternal_logMessage",nvdaControllerInternal_logMessage), ("nvdaControllerInternal_inputCompositionUpdate",nvdaControllerInternal_inputCompositionUpdate), ("nvdaControllerInternal_inputCandidateListUpdate",nvdaControllerInternal_inputCandidateListUpdate), ("nvdaControllerInternal_IMEOpenStatusUpdate",nvdaControllerInternal_IMEOpenStatusUpdate), ("nvdaControllerInternal_inputConversionModeUpdate",nvdaControllerInternal_inputConversionModeUpdate), ("nvdaControllerInternal_vbufChangeNotify",nvdaControllerInternal_vbufChangeNotify), ("nvdaControllerInternal_installAddonPackageFromPath",nvdaControllerInternal_installAddonPackageFromPath), ("nvdaControllerInternal_drawFocusRectNotify",nvdaControllerInternal_drawFocusRectNotify), ]: try: _setDllFuncPointer(localLib,"_%s"%name,func) except AttributeError as e: log.error("nvdaHelperLocal function pointer for %s could not be found, possibly old nvdaHelperLocal dll"%name,exc_info=True) raise e localLib.nvdaHelperLocal_initialize() generateBeep=localLib.generateBeep generateBeep.argtypes=[c_char_p,c_float,c_int,c_int,c_int] generateBeep.restype=c_int # The rest of this function (to do with injection) only applies if NVDA is not running as a Windows store application # Handle VBuf_getTextInRange's BSTR out parameter so that the BSTR will be freed automatically. VBuf_getTextInRange = CFUNCTYPE(c_int, c_int, c_int, c_int, POINTER(BSTR), c_int)( ("VBuf_getTextInRange", localLib), ((1,), (1,), (1,), (2,), (1,))) if config.isAppX: log.info("Remote injection disabled due to running as a Windows Store Application") return #Load nvdaHelperRemote.dll but with an altered search path so it can pick up other dlls in lib h=windll.kernel32.LoadLibraryExW(os.path.abspath(os.path.join(versionedLibPath,u"nvdaHelperRemote.dll")),0,0x8) if not h: log.critical("Error loading nvdaHelperRemote.dll: %s" % WinError()) return _remoteLib=CDLL("nvdaHelperRemote",handle=h) if _remoteLib.injection_initialize(globalVars.appArgs.secure) == 0: raise RuntimeError("Error initializing NVDAHelperRemote") if not _remoteLib.installIA2Support(): log.error("Error installing IA2 support") #Manually start the in-process manager thread for this NVDA main thread now, as a slow system can cause this action to confuse WX _remoteLib.initInprocManagerThreadIfNeeded() if os.environ.get('PROCESSOR_ARCHITEW6432') in ('AMD64', 'ARM64'): _remoteLoader64=RemoteLoader64()
def handleScreenOrientationChange(self, lParam): import ui import winUser # Resolution detection comes from an article found at https://msdn.microsoft.com/en-us/library/ms812142.aspx. #The low word is the width and hiword is height. width = winUser.LOWORD(lParam) height = winUser.HIWORD(lParam) self.orientationCoordsCache = (width,height) if width > height: # If the height and width are the same, it's actually a screen flip, and we do want to alert of those! if self.orientationStateCache == self.ORIENTATION_LANDSCAPE and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented so that it is wider than it is tall. ui.message(_("Landscape" )) self.orientationStateCache = self.ORIENTATION_LANDSCAPE else: if self.orientationStateCache == self.ORIENTATION_PORTRAIT and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented in such a way that the height is taller than it is wide. ui.message(_("Portrait")) self.orientationStateCache = self.ORIENTATION_PORTRAIT
def nvdaControllerInternal_inputLangChangeNotify(threadID, hkl, layoutString): global lastLanguageID, lastLayoutString languageID = winUser.LOWORD(hkl) #Simple case where there is no change if languageID == lastLanguageID and layoutString == lastLayoutString: return 0 focus = api.getFocusObject() #This callback can be called before NVDa is fully initialized #So also handle focus object being None as well as checking for sleepMode if not focus or focus.sleepMode: return 0 import NVDAObjects.window #Generally we should not allow input lang changes from threads that are not focused. #But threadIDs for console windows are always wrong so don't ignore for those. if not isinstance(focus, NVDAObjects.window.Window) or ( threadID != focus.windowThreadID and focus.windowClassName != "ConsoleWindowClass"): return 0 import sayAllHandler #Never announce changes while in sayAll (#1676) if sayAllHandler.isRunning(): return 0 import queueHandler import ui buf = create_unicode_buffer(1024) res = windll.kernel32.GetLocaleInfoW(languageID, 2, buf, 1024) # Translators: the label for an unknown language when switching input methods. inputLanguageName = buf.value if res else _("unknown language") layoutStringCodes = [] inputMethodName = None #layoutString can either be a real input method name, a hex string for an input method name in the registry, or an empty string. #If it is a real input method name, then it is used as is. #If it is a hex string or it is empty, then the method name is looked up by trying: #The full hex string, the hkl as a hex string, the low word of the hex string or hkl, the high word of the hex string or hkl. if layoutString: try: int(layoutString, 16) layoutStringCodes.append(layoutString) except ValueError: inputMethodName = layoutString if not inputMethodName: layoutStringCodes.insert( 0, hex(hkl)[2:].rstrip('L').upper().rjust(8, '0')) for stringCode in list(layoutStringCodes): layoutStringCodes.append(stringCode[4:].rjust(8, '0')) if stringCode[0] < 'D': layoutStringCodes.append(stringCode[0:4].rjust(8, '0')) for stringCode in layoutStringCodes: inputMethodName = _lookupKeyboardLayoutNameWithHexString( stringCode) if inputMethodName: break if not inputMethodName: log.debugWarning( "Could not find layout name for keyboard layout, reporting as unknown" ) # Translators: The label for an unknown input method when switching input methods. inputMethodName = _("unknown input method") #Remove the language name if it is in the input method name. if ' - ' in inputMethodName: inputMethodName = "".join(inputMethodName.split(' - ')[1:]) #Include the language only if it changed. if languageID != lastLanguageID: msg = u"{language} - {layout}".format(language=inputLanguageName, layout=inputMethodName) else: msg = inputMethodName lastLanguageID = languageID lastLayoutString = layoutString queueHandler.queueFunction(queueHandler.eventQueue, ui.message, msg) return 0