root/projects/WinDictator/trunk/windictator/linux/keyer.py

Revision 19, 3.8 kB (checked in by edsuom, 2 years ago)

Importing windictator into the global FOSS repo

Line 
1 # WinDictator:
2 # Dictate in Windows, have the text typed in Linux via X faked keystroke events
3 #
4 # Copyright (C) 2005-2006 by Edwin A. Suominen, http://www.eepatents.com
5 #
6 # This program is free software; you can redistribute it and/or modify it under
7 # the terms of the GNU General Public License as published by the Free Software
8 # Foundation; either version 2 of the License, or (at your option) any later
9 # version.
10 #
11 # This program is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 # FOR A PARTICULAR PURPOSE.  See the file COPYING for more details.
14 #
15 # You should have received a copy of the GNU General Public License along with
16 # this program; if not, write to the Free Software Foundation, Inc., 51
17 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18
19
20 """
21 Keyer for the virtual typist
22 """
23
24 import os, warnings
25 from twisted.internet import defer, protocol, reactor
26
27 from protocol import ProcessProtocol
28
29 BINARY = "/usr/local/bin/typist"
30
31
32 class Keyer:
33     """
34     I send fake keystrokes to the currently active window using the I{typist}
35     process.
36     """
37     def __init__(self):
38         self.dStop = defer.Deferred()
39    
40     def __del__(self):
41         """
42         Closes the pipe to the typist process
43         """
44         self.shutdown()
45
46     def startup(self):
47         """
48         Opens a pipe to the typist process, which executes a keystroke with
49         each new line sent and returns the keycode used on stdout.
50         """
51         def ready(transport):
52             self.dStack = []
53             self.process = transport
54
55         def error(self, failure):
56             print "Error running typist process:", failure.printTraceback()
57             return failure
58            
59         d = defer.Deferred()
60         d.addCallbacks(ready, error)
61         p = ProcessProtocol(d, self.dStop, self.whatTyped)
62         reactor.spawnProcess(p, BINARY, ('typist',), env=os.environ)
63         return d
64
65     def shutdown(self):
66         if hasattr(self, 'process'):
67             self.process.loseConnection()
68             del self.process
69             return self.dStop
70         else:
71             return defer.succeed(None)
72
73     def pressKey(self, keySym):
74         """
75         Instructs the typist process to depress the specified I{keySym}.
76         """
77         return self.key('d', keySym)
78
79     def releaseKey(self, keySym):
80         """
81         Instructs the typist process to release the specified I{keySym}.
82         """
83         return self.key('u', keySym)
84
85     def key(self, du, keySym):
86         """
87         Sends a key press (I{d}) or release (I{u}) command to the typist
88         process via STDIN. Returns a C{Deferred} that fires with the keycode
89         for the pressed or released key.
90         """
91         def send(null):
92             self.process.write("%s %s\n" % (du, keySym))
93             d = defer.Deferred()
94             if self.dStack:
95                 warnings.warn(
96                     "New keystroke being sent before previous one confirmed",
97                     stacklevel=2)
98             self.dStack.append(d)
99             return d
100
101         if hasattr(self, 'process'):
102             return send(None)
103         else:
104             d = self.startup()
105             d.addCallback(send)
106             return d
107
108     def whatTyped(self, line):
109         """
110         Callback for STDOUT feedback from the I{typist} process, with a line
111         containing the keycode of the keysym that it has accepted.
112
113         Fires the C{Deferred} for the last-sent keystroke with the integer
114         keycode if returned from the I{typist} process, or with C{None} if the
115         keystroke wasn't accepted.
116         """
117         d = self.dStack.pop()
118         try:
119             result = int(line.strip())
120         except:
121             result = None
122         d.callback(result)
123        
124        
125        
126        
Note: See TracBrowser for help on using the browser.