1 |
|
# Orca |
2 |
|
# |
3 |
|
# Copyright 2005-2007 Sun Microsystems Inc. |
4 |
|
# |
5 |
|
# This library is free software; you can redistribute it and/or |
6 |
|
# modify it under the terms of the GNU Library General Public |
7 |
|
# License as published by the Free Software Foundation; either |
8 |
|
# version 2 of the License, or (at your option) any later version. |
9 |
|
# |
10 |
|
# This library is distributed in the hope that it will be useful, |
11 |
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 |
|
# Library General Public License for more details. |
14 |
|
# |
15 |
|
# You should have received a copy of the GNU Library General Public |
16 |
|
# License along with this library; if not, write to the |
17 |
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
|
# Boston, MA 02111-1307, USA. |
19 |
|
|
20 |
|
"""The gnome-terminal script mainly handles the unique interaction model |
21 |
|
of manipulating text - both the user and the system put text into the |
22 |
1 |
system and we try to determine which was which and why.""" |
23 |
|
|
24 |
1 |
__id__ = "$Id: gnome-terminal.py 2126 2007-03-06 21:35:17Z richb $" |
25 |
1 |
__version__ = "$Revision: 2126 $" |
26 |
1 |
__date__ = "$Date: 2007-03-06 13:35:17 -0800 (Tue, 06 Mar 2007) $" |
27 |
1 |
__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc." |
28 |
1 |
__license__ = "LGPL" |
29 |
|
|
30 |
1 |
import orca.atspi as atspi |
31 |
1 |
import orca.debug as debug |
32 |
1 |
import orca.default as default |
33 |
1 |
import orca.input_event as input_event |
34 |
1 |
import orca.orca_state as orca_state |
35 |
1 |
import orca.rolenames as rolenames |
36 |
1 |
import orca.settings as settings |
37 |
1 |
import orca.speech as speech |
38 |
|
|
39 |
|
######################################################################## |
40 |
|
# # |
41 |
|
# The GnomeTerminal script class. # |
42 |
|
# # |
43 |
|
######################################################################## |
44 |
|
|
45 |
2 |
class Script(default.Script): |
46 |
|
|
47 |
1 |
def __init__(self, app): |
48 |
|
"""Creates a new script for the given application. |
49 |
|
|
50 |
|
Arguments: |
51 |
|
- app: the application to create a script for. |
52 |
|
""" |
53 |
|
|
54 |
11 |
default.Script.__init__(self, app) |
55 |
|
|
56 |
|
# By default, don't present if gnome-terminal is not the active |
57 |
|
# application. |
58 |
|
# |
59 |
11 |
self.presentIfInactive = False |
60 |
|
|
61 |
|
#def onWindowActivated(self, event): |
62 |
|
# # Sets the context to the top level window first, so we can |
63 |
|
# # get information about it the window we just moved to. |
64 |
|
# # |
65 |
|
# orca.setLocusOfFocus(event, event.source) |
66 |
|
# |
67 |
|
# # Now we find the focused object and set the locus of focus to it. |
68 |
|
# # |
69 |
|
# obj = self.findFocusedObject(self.app) |
70 |
|
# if obj: |
71 |
|
# orca.setLocusOfFocus(event, obj) |
72 |
|
# else: |
73 |
|
# default.Script.onWindowActivated(self, event) |
74 |
|
|
75 |
1 |
def onTextDeleted(self, event): |
76 |
|
"""Called whenever text is deleted from an object. |
77 |
|
|
78 |
|
Arguments: |
79 |
|
- event: the Event |
80 |
|
""" |
81 |
|
|
82 |
18 |
if orca_state.lastInputEvent \ |
83 |
|
and isinstance(orca_state.lastInputEvent, |
84 |
18 |
input_event.KeyboardEvent): |
85 |
18 |
event_string = orca_state.lastInputEvent.event_string |
86 |
|
else: |
87 |
0 |
event_string = None |
88 |
|
|
89 |
|
# We only do special things when people press backspace |
90 |
|
# in terminals. |
91 |
|
# |
92 |
18 |
if (event.source.role != rolenames.ROLE_TERMINAL) \ |
93 |
|
or (event_string != "BackSpace"): |
94 |
18 |
default.Script.onTextDeleted(self, event) |
95 |
18 |
return |
96 |
|
|
97 |
|
# Ignore text deletions from non-focused objects, unless the |
98 |
|
# currently focused object is the parent of the object from which |
99 |
|
# text was deleted. |
100 |
|
# |
101 |
0 |
if (event.source != orca_state.locusOfFocus) \ |
102 |
|
and (event.source.parent != orca_state.locusOfFocus): |
103 |
0 |
return |
104 |
|
|
105 |
0 |
self.updateBraille(event.source) |
106 |
|
|
107 |
|
# Speak the character that has just been deleted. |
108 |
|
# |
109 |
0 |
character = event.any_data.decode("UTF-8")[0].encode("UTF-8") |
110 |
0 |
if character.isupper(): |
111 |
0 |
speech.speak(character, self.voices[settings.UPPERCASE_VOICE]) |
112 |
|
else: |
113 |
0 |
speech.speak(character) |
114 |
|
|
115 |
1 |
def onTextInserted(self, event): |
116 |
|
"""Called whenever text is inserted into an object. |
117 |
|
|
118 |
|
Arguments: |
119 |
|
- event: the Event |
120 |
|
""" |
121 |
|
|
122 |
|
# We only do special things for terminals. |
123 |
|
# |
124 |
67 |
if event.source.role != rolenames.ROLE_TERMINAL: |
125 |
27 |
default.Script.onTextInserted(self, event) |
126 |
27 |
return |
127 |
|
|
128 |
|
# Ignore text insertions from non-focused objects, unless the |
129 |
|
# currently focused object is the parent of the object from which |
130 |
|
# text was inserted. |
131 |
|
# |
132 |
40 |
if (event.source != orca_state.locusOfFocus) \ |
133 |
|
and (event.source.parent != orca_state.locusOfFocus): |
134 |
0 |
return |
135 |
|
|
136 |
40 |
self.updateBraille(event.source) |
137 |
|
|
138 |
40 |
text = event.any_data |
139 |
|
|
140 |
|
# When one does a delete in a terminal, the remainder of the |
141 |
|
# line is "inserted" instead of being shifted left. We will |
142 |
|
# detect this by seeing if the keystring was a delete action. |
143 |
|
# If we run into this case, we don't really want to speak the |
144 |
|
# rest of the line. |
145 |
|
# |
146 |
|
# We'll let our super class handle "Delete". We'll handle Ctrl+D. |
147 |
|
# |
148 |
|
|
149 |
40 |
if not orca_state.lastInputEvent or \ |
150 |
|
not isinstance(orca_state.lastInputEvent, |
151 |
39 |
input_event.KeyboardEvent): |
152 |
1 |
return |
153 |
|
|
154 |
39 |
keyString = orca_state.lastInputEvent.event_string |
155 |
|
|
156 |
39 |
controlPressed = orca_state.lastInputEvent.modifiers \ |
157 |
|
& (1 << atspi.Accessibility.MODIFIER_CONTROL) |
158 |
|
|
159 |
39 |
if (keyString == "Delete") or (keyString == "BackSpace"): |
160 |
0 |
return |
161 |
39 |
elif (keyString == "D") and controlPressed: |
162 |
0 |
text = text.decode("UTF-8")[0].decode("UTF-8") |
163 |
|
|
164 |
|
# If the last input event was a keyboard event, check to see if |
165 |
|
# the text for this event matches what the user typed. If it does, |
166 |
|
# then don't speak it. |
167 |
|
# |
168 |
|
# Note that the text widgets sometimes compress their events, |
169 |
|
# thus we might get a longer string from a single text inserted |
170 |
|
# event, while we also get individual keyboard events for the |
171 |
|
# characters used to type the string. This is ugly. We attempt |
172 |
|
# to handle it here by only echoing text if we think it was the |
173 |
|
# result of a command (e.g., a paste operation). |
174 |
|
# |
175 |
|
# Note that we have to special case the space character as it |
176 |
|
# comes across as "space" in the keyboard event and " " in the |
177 |
|
# text event. |
178 |
|
# |
179 |
|
# For terminal, Return usually ends up in more text from the |
180 |
|
# system, which we want to hear. Tab is also often used for |
181 |
|
# command line completion, so we want to hear that, too. |
182 |
|
# |
183 |
|
# Finally, if we missed some command and the system is giving |
184 |
|
# us a string typically longer than what the length of a |
185 |
|
# compressed string is (we choose 5 here), then output that. |
186 |
|
# |
187 |
39 |
matchFound = False |
188 |
39 |
if isinstance(orca_state.lastInputEvent, input_event.KeyboardEvent): |
189 |
39 |
wasCommand = orca_state.lastInputEvent.modifiers \ |
190 |
|
& (1 << atspi.Accessibility.MODIFIER_CONTROL \ |
191 |
|
| 1 << atspi.Accessibility.MODIFIER_ALT \ |
192 |
|
| 1 << atspi.Accessibility.MODIFIER_META \ |
193 |
|
| 1 << atspi.Accessibility.MODIFIER_META2 \ |
194 |
|
| 1 << atspi.Accessibility.MODIFIER_META3) |
195 |
39 |
wasCommand = wasCommand \ |
196 |
|
or (keyString == "Return") \ |
197 |
|
or (keyString == "Tab") |
198 |
39 |
if (text == " " and keyString == "space") \ |
199 |
|
or (text == keyString): |
200 |
28 |
matchFound = True |
201 |
28 |
pass |
202 |
11 |
elif wasCommand or (len(text) > 5): |
203 |
11 |
if text.isupper(): |
204 |
0 |
speech.speak(text, self.voices[settings.UPPERCASE_VOICE]) |
205 |
|
else: |
206 |
11 |
speech.speak(text) |
207 |
|
|
208 |
39 |
if settings.enableEchoByWord \ |
209 |
|
and self.isWordDelimiter(text.decode("UTF-8")[-1:]): |
210 |
0 |
if matchFound: |
211 |
0 |
self.echoPreviousWord(event.source) |