#mouseHandler.py #A part of NonVisual Desktop Access (NVDA) #Copyright (C) 2006-2007 NVDA Contributors #This file is covered by the GNU General Public License. #See the file COPYING for more details. import time import tones import ctypes import winUser import queueHandler import api import speech import NVDAObjects.JAB import NVDAObjects.IAccessible import globalVars from logHandler import log import config import IAccessibleHandler import JABHandler import mouseHook WM_MOUSEMOVE=0x0200 WM_LBUTTONDOWN=0x0201 WM_LBUTTONUP=0x0202 WM_LBUTTONDBLCLK=0x0203 WM_RBUTTONDOWN=0x0204 WM_RBUTTONUP=0x0205 WM_RBUTTONDBLCLK=0x0206 curMousePos=(0,0) mouseMoved=False curMouseShape="" mouseShapeChanged=0 #: The time (in seconds) at which the last mouse event occurred. #: @type: float lastMouseEventTime=0 def updateMouseShape(name): global curMouseShape, mouseShapeChanged if not name or name==curMouseShape: return curMouseShape=name mouseShapeChanged=1 def playAudioCoordinates(x, y, detectBrightness=True,blurFactor=0): screenWidth,screenHeight=api.getDesktopObject().location[2:] x=min(max(0,x),screenWidth-1) y=min(max(0,y),screenHeight-1) minPitch=config.conf['mouse']['audioCoordinates_minPitch'] maxPitch=config.conf['mouse']['audioCoordinates_maxPitch'] curPitch=minPitch+((maxPitch-minPitch)*((screenHeight-y)/float(screenHeight))) if detectBrightness: screenDC=ctypes.windll.user32.GetDC(0) brightness=0 for i in range(x-blurFactor,x+blurFactor+1): for j in range(y-blurFactor,y+blurFactor+1): if i>=0 and i=0 and j>16)&0xff)+0.59*((p>>8)&0xff)+0.11*(p&0xff) brightness=(brightness+(grey/255))/2 minBrightness=config.conf['mouse']['audioCoordinates_minVolume'] maxBrightness=config.conf['mouse']['audioCoordinates_maxVolume'] brightness=(brightness*(maxBrightness-minBrightness))+minBrightness ctypes.windll.user32.ReleaseDC(0,screenDC) else: brightness=config.conf['mouse']['audioCoordinates_maxVolume'] leftVolume=(85*((screenWidth-float(x))/screenWidth))*brightness rightVolume=(85*(float(x)/screenWidth))*brightness tones.beep(curPitch,40,left=leftVolume,right=rightVolume) #Internal mouse event def internal_mouseEvent(msg,x,y,injected): global mouseMoved, curMousePos, lastMouseEventTime lastMouseEventTime=time.time() if injected: return True if not config.conf['mouse']['enableMouseTracking']: return True try: curMousePos=(x,y) if msg==WM_MOUSEMOVE and (config.conf['mouse']['reportTextUnderMouse'] or config.conf['mouse']['reportObjectRoleOnMouseEnter'] or config.conf['mouse']['audioCoordinatesOnMouseMove']): mouseMoved=True elif msg in (WM_LBUTTONDOWN,WM_RBUTTONDOWN): queueHandler.queueFunction(queueHandler.eventQueue,speech.cancelSpeech) except: log.error("", exc_info=True) return True def executeMouseMoveEvent(x,y): oldMouseObject=api.getMouseObject() try: (oldLeft,oldTop,oldWidth,oldHeight)=oldMouseObject.location except: oldLeft=oldTop=oldWidth=oldHeight=0 mouseObject=oldMouseObject windowAtPoint=ctypes.windll.user32.WindowFromPoint(x,y) if JABHandler.isRunning and JABHandler.isJavaWindow(windowAtPoint): if not isinstance(oldMouseObject,NVDAObjects.JAB.JAB) or x(oldLeft+oldWidth) or y(oldTop+oldHeight): oldJabContext=JABHandler.JABContext(hwnd=windowAtPoint) else: oldJabContext=oldMouseObject.jabContext res=oldJabContext.getAccessibleContextAt(x,y) if res: mouseObject=NVDAObjects.JAB.JAB(jabContext=res) else: #not a java window if not isinstance(oldMouseObject,NVDAObjects.IAccessible.IAccessible) or x(oldLeft+oldWidth) or y(oldTop+oldHeight): mouseObject=NVDAObjects.IAccessible.getNVDAObjectFromPoint(x,y) else: res=IAccessibleHandler.accHitTest(oldMouseObject.IAccessibleObject,oldMouseObject.IAccessibleChildID,x,y) if res: mouseObject=NVDAObjects.IAccessible.IAccessible(IAccessibleObject=res[0],IAccessibleChildID=res[1]) if not mouseObject: return try: (left,top,width,height)=mouseObject.location except: left=top=width=height=0 if x(left+width) or y(top+height): return api.setMouseObject(mouseObject) try: mouseObject.event_mouseMove(x,y) oldMouseObject=mouseObject except: log.error("api.notifyMouseMoved", exc_info=True) #Register internal mouse event def initialize(): global curMousePos, screenDC, screenWidth, screenHeight (x,y)=winUser.getCursorPos() mouseObj=NVDAObjects.IAccessible.getNVDAObjectFromPoint(x,y) if not mouseObj: mouseObj=api.getDesktopObject() api.setMouseObject(mouseObj) curMousePos=(x,y) screenWidth,screenHeight=api.getDesktopObject().location[2:] mouseHook.initialize(internal_mouseEvent) def pumpAll(): global mouseMoved, curMousePos, mouseShapeChanged, curMouseShape if mouseMoved: mouseMoved=False (x,y)=curMousePos if config.conf["mouse"]["audioCoordinatesOnMouseMove"]: playAudioCoordinates(x,y,config.conf['mouse']['audioCoordinates_detectBrightness'],config.conf['mouse']['audioCoordinates_blurFactor']) executeMouseMoveEvent(x,y) if config.conf["mouse"]["reportMouseShapeChanges"] and mouseShapeChanged>0: if mouseShapeChanged==10: mouseShapeChanged=0 speech.speakMessage(_("%s cursor")%curMouseShape) else: mouseShapeChanged+=1 def terminate(): mouseHook.terminate()