#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 wx import tones import ctypes import winUser import queueHandler import api import screenBitmap import speech import globalVars import eventHandler from logHandler import log import config import winInputHook import core import ui 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="" _shapeTimer=None scrBmpObj=None #: The time (in seconds) at which the last mouse event occurred. #: @type: float lastMouseEventTime=0 SHAPE_REPORT_DELAY = 100 def updateMouseShape(name): global curMouseShape if not name or name==curMouseShape: return curMouseShape=name if config.conf["mouse"]["reportMouseShapeChanges"]: # Delay reporting to avoid unnecessary/excessive verbosity. _shapeTimer.Stop() _shapeTimer.Start(SHAPE_REPORT_DELAY, True) def playAudioCoordinates(x, y, screenWidth, screenHeight, detectBrightness=True,blurFactor=0): minPitch=config.conf['mouse']['audioCoordinates_minPitch'] maxPitch=config.conf['mouse']['audioCoordinates_maxPitch'] curPitch=minPitch+((maxPitch-minPitch)*((screenHeight-y)/float(screenHeight))) if detectBrightness: startX=min(max(x-blurFactor,0),screenWidth) width=min((x+blurFactor+1)-startX,screenWidth) startY=min(max(y-blurFactor,0),screenHeight) height=min((y+blurFactor+1)-startY,screenHeight) grey=screenBitmap.rgbPixelBrightness(scrBmpObj.captureImage(startX,startY,width,height)[0][0]) brightness=grey/255.0 minBrightness=config.conf['mouse']['audioCoordinates_minVolume'] maxBrightness=config.conf['mouse']['audioCoordinates_maxVolume'] brightness=(brightness*(maxBrightness-minBrightness))+minBrightness else: brightness=config.conf['mouse']['audioCoordinates_maxVolume'] leftVolume=int((85*((screenWidth-float(x))/screenWidth))*brightness) rightVolume=int((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: mouseMoved=True core.requestPump() 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): global currentMouseWindow desktopObject=api.getDesktopObject() screenLeft,screenTop,screenWidth,screenHeight=desktopObject.location x=min(max(screenLeft,x),(screenLeft+screenWidth)-1) y=min(max(screenTop,y),(screenTop+screenHeight)-1) if config.conf["mouse"]["audioCoordinatesOnMouseMove"]: playAudioCoordinates(x,y,screenWidth,screenHeight,config.conf['mouse']['audioCoordinates_detectBrightness'],config.conf['mouse']['audioCoordinates_blurFactor']) oldMouseObject=api.getMouseObject() mouseObject=desktopObject.objectFromPoint(x,y) while mouseObject and mouseObject.beTransparentToMouse: mouseObject=mouseObject.parent if not mouseObject: return if oldMouseObject==mouseObject: mouseObject=oldMouseObject else: api.setMouseObject(mouseObject) try: eventHandler.executeEvent("mouseMove",mouseObject,x=x,y=y) oldMouseObject=mouseObject except: log.error("api.notifyMouseMoved", exc_info=True) #Register internal mouse event def initialize(): global curMousePos, scrBmpObj, _shapeTimer scrBmpObj=screenBitmap.ScreenBitmap(1,1) (x,y)=winUser.getCursorPos() desktopObject=api.getDesktopObject() try: mouseObject=desktopObject.objectFromPoint(x,y) except: log.exception("Error retrieving initial mouse object") mouseObject=None if not mouseObject: mouseObject=api.getDesktopObject() api.setMouseObject(mouseObject) curMousePos=(x,y) winInputHook.initialize() winInputHook.setCallbacks(mouse=internal_mouseEvent) _shapeTimer = wx.PyTimer(_reportShape) def _reportShape(): # Translators: Reported when mouse cursor shape changes (example output: edit cursor). ui.message(_("%s cursor")%curMouseShape) def pumpAll(): global mouseMoved, curMousePos if mouseMoved: mouseMoved=False (x,y)=curMousePos executeMouseMoveEvent(x,y) def terminate(): global scrBmpObj, _shapeTimer scrBmpObj=None winInputHook.terminate() _shapeTimer.Stop() _shapeTimer = None