mouseHandler.py
4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#mouseHandler.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
#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