Merge lp:~blackdaemon/enso/win32-selection-fixes into lp:~communityenso/enso/community-enso

Proposed by blackdaemon
Status: Needs review
Proposed branch: lp:~blackdaemon/enso/win32-selection-fixes
Merge into: lp:~communityenso/enso/community-enso
Diff against target: 548 lines (+218/-90)
4 files modified
enso/platform/win32/selection/FileSelection.py (+16/-11)
enso/platform/win32/selection/TextSelection.py (+43/-20)
enso/platform/win32/selection/_ContextUtils.py (+158/-58)
enso/platform/win32/selection/__init__.py (+1/-1)
To merge this branch: bzr merge lp:~blackdaemon/enso/win32-selection-fixes
Reviewer Review Type Date Requested Status
Community Enso Team Pending
Review via email: mp+27830@code.launchpad.net

Description of the change

Handling of copy/cut/paste for Vim and gVim
Handling of copy/paste for console windows

To post a comment you must log in.
148. By blackdaemon

Small fixes

Unmerged revisions

148. By blackdaemon

Small fixes

147. By blackdaemon

Handling Vim and gVim copy&paste

146. By blackdaemon

Handle copy&paste for console windows using "Alt-space e y" and "Alt-space e p"

145. By blackdaemon

Ignore pylint errors for pywintypes.error

144. By blackdaemon

Added getWindowProcessName()

143. By blackdaemon

Added handling of some special keys ([, ])
Fixed sending of extended keys (Ins, Del, Home, [, ], etc)
Added typeShiftKey
Added possibility to send key as string or virtual-code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'enso/platform/win32/selection/FileSelection.py'
--- enso/platform/win32/selection/FileSelection.py 2008-04-27 11:12:38 +0000
+++ enso/platform/win32/selection/FileSelection.py 2010-07-30 13:46:41 +0000
@@ -44,8 +44,10 @@
44# Imports44# Imports
45# ----------------------------------------------------------------------------45# ----------------------------------------------------------------------------
4646
47import os
47import win32con48import win32con
48import win32clipboard49import win32clipboard
50import win32gui
49import pywintypes51import pywintypes
50import logging52import logging
5153
@@ -144,9 +146,8 @@
144 value = win32clipboard.GetClipboardData(146 value = win32clipboard.GetClipboardData(
145 win32con.CF_HDROP147 win32con.CF_HDROP
146 )148 )
147 except pywintypes.error, e:149 except pywintypes.error, e: #IGNORE:E1101
148 logging.warn( "Error getting CF_HDROP from clipboard: %s" \150 logging.warn( "Error getting CF_HDROP from clipboard: %s", str(e) )
149 % ( str(e) ) )
150 value = None151 value = None
151 else:152 else:
152 logging.info( "Clipboard type CF_HDROP not in clipboard." )153 logging.info( "Clipboard type CF_HDROP not in clipboard." )
@@ -167,13 +168,17 @@
167 subclass which is appropriate to the currently active application.168 subclass which is appropriate to the currently active application.
168 """169 """
169 170
170 windowClass = ContextUtils.getForegroundClassNameUnicode()171 hwnd = win32gui.GetForegroundWindow()
171172 className = ContextUtils.getWindowClassName(hwnd)
172 if windowClass == u"ConsoleWindowClass":173 processName = ContextUtils.getWindowProcessName(hwnd)
173 fsContext = NullFileSelectionContext()174
174 elif windowClass == u"Emacs":175 fsContext = DefaultFileSelectionContext()
175 fsContext = NullFileSelectionContext()176
176 else:177 if className == u"Emacs":
177 fsContext = DefaultFileSelectionContext()178 fsContext = NullFileSelectionContext()
179 elif className == u"ConsoleWindowClass":
180 fsContext = NullFileSelectionContext()
181 elif className == u"Vim" and os.path.basename(processName).lower() == "gvim.exe":
182 fsContext = NullFileSelectionContext()
178183
179 return fsContext184 return fsContext
180185
=== modified file 'enso/platform/win32/selection/TextSelection.py'
--- enso/platform/win32/selection/TextSelection.py 2009-02-20 00:39:06 +0000
+++ enso/platform/win32/selection/TextSelection.py 2010-07-30 13:46:41 +0000
@@ -42,6 +42,8 @@
42# Imports42# Imports
43# ----------------------------------------------------------------------------43# ----------------------------------------------------------------------------
4444
45import os
46import win32gui
45import win32clipboard47import win32clipboard
46import win32con48import win32con
47import logging49import logging
@@ -103,6 +105,7 @@
103 newDict[ "text" ] = newPlainText105 newDict[ "text" ] = newPlainText
104 if len( newHtml ) > 0:106 if len( newHtml ) > 0:
105 newDict[ "html" ] = newHtml107 newDict[ "html" ] = newHtml
108 return newDict
106109
107def _textDictToAscii( textDict ):110def _textDictToAscii( textDict ):
108 text = textDict.get( "text", u"" )111 text = textDict.get( "text", u"" )
@@ -407,7 +410,7 @@
407class NonReplacingTextSelection( DefaultTextSelection ):410class NonReplacingTextSelection( DefaultTextSelection ):
408 """411 """
409 In some applications, notably MoonEdit and Emacs, a paste412 In some applications, notably MoonEdit and Emacs, a paste
410 does not replace selected tet: it inserts413 does not replace selected text: it inserts
411 at the cursor. This is the selection context to use for414 at the cursor. This is the selection context to use for
412 those applications.415 those applications.
413 """416 """
@@ -473,20 +476,6 @@
473 these functions are no-ops.476 these functions are no-ops.
474 """477 """
475478
476 def getSelection( self ):
477 """
478 Always blank.
479 """
480 return {}
481
482 def replaceSelection( self, textDict ):
483 """
484 Text in the command prompt window is immutable, so
485 the replacement behavior is impossible to achieve.
486 Return False to indicate failure.
487 """
488 return False
489
490 def simulatePasteKeystroke( self ):479 def simulatePasteKeystroke( self ):
491 # Alt-space pops up the window menu (the thing you get480 # Alt-space pops up the window menu (the thing you get
492 # by clicking in the upper-left corner). Then typing481 # by clicking in the upper-left corner). Then typing
@@ -495,7 +484,11 @@
495 ContextUtils.typeSequence( "e p" )484 ContextUtils.typeSequence( "e p" )
496485
497 def simulateCopyKeystroke( self ):486 def simulateCopyKeystroke( self ):
498 pass487 # Alt-space pops up the window menu (the thing you get
488 # by clicking in the upper-left corner). Then typing
489 # e and then y selects edit->copy.
490 ContextUtils.typeAltKey( " " )
491 ContextUtils.typeSequence( "e y" )
499 492
500 def simulateCutKeystroke( self ):493 def simulateCutKeystroke( self ):
501 pass494 pass
@@ -509,6 +502,28 @@
509 return self._pasteText( textDict )502 return self._pasteText( textDict )
510503
511 504
505class VimTextSelection( DefaultTextSelection ):
506 """
507 Returned if the currently active application is a Windows Vim/gVim.
508 """
509
510 def simulatePasteKeystroke( self ):
511 # Shift-Insert should work by default in Windows version of Vim/gVim
512 ContextUtils.typeShiftKey(win32con.VK_INSERT)
513
514 def simulateCopyKeystroke( self ):
515 # Ctrl-Insert should work by default in Windows version of Vim/gVim
516 # But yanking the selection will also clear it. So the sequence is:
517 # copy text to clipboard: Ctrl-Insert
518 # get to normal mode 2x: Ctrl-[ Ctrl-[
519 # return to last selection: gv
520 ContextUtils.typeSequence('CD INS [ [ CU g v')
521
522 def simulateCutKeystroke( self ):
523 # Ctrl-Del should work by default in Windows version of Vim/gVim
524 ContextUtils.typeCommandKey(win32con.VK_DELETE)
525
526
512# ----------------------------------------------------------------------------527# ----------------------------------------------------------------------------
513# Public Function528# Public Function
514# ----------------------------------------------------------------------------529# ----------------------------------------------------------------------------
@@ -521,16 +536,24 @@
521 If no text is selected, this must return a TextSelection object with536 If no text is selected, this must return a TextSelection object with
522 no text in it -- NOT a None.537 no text in it -- NOT a None.
523 """538 """
539 hwnd = win32gui.GetForegroundWindow()
540 className = ContextUtils.getWindowClassName(hwnd)
524541
525 className = ContextUtils.getForegroundClassNameUnicode()542 tsContext = DefaultTextSelection()
526543
527 if className == u"Emacs":544 if className == u"Emacs":
528 tsContext = EmacsTextSelection()545 tsContext = EmacsTextSelection()
529 elif className == u"MoonEdit":546 elif className == u"MoonEdit":
530 tsContext = NonReplacingTextSelection()547 tsContext = NonReplacingTextSelection()
531 elif className == u"ConsoleWindowClass":548 elif className == u"ConsoleWindowClass":
532 tsContext = CommandPromptTextSelection()549 processName = ContextUtils.getWindowProcessName(hwnd)
533 else:550 if os.path.basename(processName).lower() == "vim.exe":
534 tsContext = DefaultTextSelection()551 tsContext = VimTextSelection()
552 else:
553 tsContext = CommandPromptTextSelection()
554 elif className == u"Vim":
555 processName = ContextUtils.getWindowProcessName(hwnd)
556 if os.path.basename(processName).lower() == "gvim.exe":
557 tsContext = VimTextSelection()
535558
536 return tsContext559 return tsContext
537560
=== modified file 'enso/platform/win32/selection/_ContextUtils.py'
--- enso/platform/win32/selection/_ContextUtils.py 2008-04-27 11:12:38 +0000
+++ enso/platform/win32/selection/_ContextUtils.py 2010-07-30 13:46:41 +0000
@@ -1,6 +1,6 @@
1# Copyright (c) 2008, Humanized, Inc.1# Copyright (c) 2008, Humanized, Inc.
2# All rights reserved.2# All rights reserved.
3# 3#
4# Redistribution and use in source and binary forms, with or without4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are met:5# modification, are permitted provided that the following conditions are met:
6#6#
@@ -14,7 +14,7 @@
14# 3. Neither the name of Enso nor the names of its contributors may14# 3. Neither the name of Enso nor the names of its contributors may
15# be used to endorse or promote products derived from this15# be used to endorse or promote products derived from this
16# software without specific prior written permission.16# software without specific prior written permission.
17# 17#
18# THIS SOFTWARE IS PROVIDED BY Humanized, Inc. ``AS IS'' AND ANY18# THIS SOFTWARE IS PROVIDED BY Humanized, Inc. ``AS IS'' AND ANY
19# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED19# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -37,10 +37,12 @@
37# Imports37# Imports
38# ----------------------------------------------------------------------------38# ----------------------------------------------------------------------------
3939
40import os
40import win32api41import win32api
41import win32con42import win32con
42import win32gui43import win32gui
43import win32clipboard44import win32clipboard
45import win32process
44import ctypes46import ctypes
45import pywintypes47import pywintypes
46import time48import time
@@ -95,6 +97,55 @@
95# key is being depressed."97# key is being depressed."
96KEYEVENTF_KEYDOWN = 098KEYEVENTF_KEYDOWN = 0
97KEYEVENTF_KEYUP = win32con.KEYEVENTF_KEYUP99KEYEVENTF_KEYUP = win32con.KEYEVENTF_KEYUP
100KEYEVENTF_EXTENDEDKEY = win32con.KEYEVENTF_EXTENDEDKEY
101
102VK_LBRACKET = 0xDB
103VK_RBRACKET = 0xDD
104
105KEY_MAPPING = { "F1" : win32con.VK_F1,
106 "F2" : win32con.VK_F2,
107 "F3" : win32con.VK_F3,
108 "F4" : win32con.VK_F4,
109 "F5" : win32con.VK_F5,
110 "F6" : win32con.VK_F6,
111 "F7" : win32con.VK_F7,
112 "F8" : win32con.VK_F8,
113 "F9" : win32con.VK_F9,
114 "F10": win32con.VK_F10,
115 "F11": win32con.VK_F11,
116 "F12": win32con.VK_F12,
117 "CD" : win32con.VK_LCONTROL,
118 "CU" : win32con.VK_LCONTROL,
119 "SD" : win32con.VK_LSHIFT,
120 "SU" : win32con.VK_LSHIFT,
121 "AD" : win32con.VK_MENU,
122 "AU" : win32con.VK_MENU,
123 "ID" : win32con.VK_LWIN,
124 "IU" : win32con.VK_LWIN,
125 "LA": win32con.VK_LEFT,
126 "RA": win32con.VK_RIGHT,
127 "ESC": win32con.VK_ESCAPE,
128 "INS": win32con.VK_INSERT,
129 "DEL": win32con.VK_DELETE,
130 "[": VK_LBRACKET,
131 "]": VK_RBRACKET,
132 "LBRACKET": VK_LBRACKET,
133 "RBRACKET": VK_RBRACKET
134 }
135
136# List of keys that need to have the win32con.KEYEVENTF_EXTENDEDKEY flag set
137KEYS_EXTENDED = [
138 win32con.VK_UP,
139 win32con.VK_DOWN,
140 win32con.VK_LEFT,
141 win32con.VK_RIGHT,
142 win32con.VK_HOME,
143 win32con.VK_END,
144 win32con.VK_PRIOR, # PgUp
145 win32con.VK_NEXT, # PgDn
146 win32con.VK_INSERT,
147 win32con.VK_DELETE
148]
98149
99# ----------------------------------------------------------------------------150# ----------------------------------------------------------------------------
100# Private Module Variables151# Private Module Variables
@@ -125,10 +176,14 @@
125 # win32all does not provide access to MapVirtualKey, so we have to use176 # win32all does not provide access to MapVirtualKey, so we have to use
126 # ctypes to access the DLL directly, and have to append "A" to the name177 # ctypes to access the DLL directly, and have to append "A" to the name
127 # since the function is implemented in Unicode and ANSI versions.178 # since the function is implemented in Unicode and ANSI versions.
128 179
129 # This gives a hardware scancode for the virtual key.180 # This gives a hardware scancode for the virtual key.
130 scanCode = ctypes.windll.user32.MapVirtualKeyA( vkCode, 0 )181 scanCode = ctypes.windll.user32.MapVirtualKeyA( vkCode, 0 )
131182
183 # Some keys needs the 'extended-key' attribute
184 if vkCode in KEYS_EXTENDED:
185 eventType |= KEYEVENTF_EXTENDEDKEY
186
132 # This creates the keyboard event (this function is the one called187 # This creates the keyboard event (this function is the one called
133 # by keyboard driver interupt handlers, so it's as low-level as it gets)188 # by keyboard driver interupt handlers, so it's as low-level as it gets)
134 win32api.keybd_event( vkCode, scanCode, eventType, 0 )189 win32api.keybd_event( vkCode, scanCode, eventType, 0 )
@@ -157,7 +212,7 @@
157 try:212 try:
158 win32clipboard.OpenClipboard( 0 )213 win32clipboard.OpenClipboard( 0 )
159 success = True214 success = True
160 except pywintypes.error:215 except pywintypes.error: #IGNORE:E1101
161 if totalTime < CLIPBOARD_OPEN_WAIT_AMOUNT:216 if totalTime < CLIPBOARD_OPEN_WAIT_AMOUNT:
162 sleepForMs( CLIPBOARD_OPEN_WAIT_INTERVAL )217 sleepForMs( CLIPBOARD_OPEN_WAIT_INTERVAL )
163 totalTime += CLIPBOARD_OPEN_WAIT_INTERVAL218 totalTime += CLIPBOARD_OPEN_WAIT_INTERVAL
@@ -186,10 +241,10 @@
186241
187 # Postconditions:242 # Postconditions:
188 assert( _hasTheClipboardOpen() )243 assert( _hasTheClipboardOpen() )
189 244
190 try:245 try:
191 win32clipboard.CloseClipboard()246 win32clipboard.CloseClipboard()
192 except pywintypes.error:247 except pywintypes.error: #IGNORE:E1101
193 logging.warn( "Attempted to close clipboard when not open." )248 logging.warn( "Attempted to close clipboard when not open." )
194 global _contextUtilsHasTheClipboardOpen249 global _contextUtilsHasTheClipboardOpen
195 _contextUtilsHasTheClipboardOpen = False250 _contextUtilsHasTheClipboardOpen = False
@@ -205,7 +260,7 @@
205 function, then closes it when the wrapped function is done,260 function, then closes it when the wrapped function is done,
206 whether or not the wrapped function throws an exception.261 whether or not the wrapped function throws an exception.
207 """262 """
208 263
209 def wrapperFunc( *args, **kwargs ):264 def wrapperFunc( *args, **kwargs ):
210 # If safeOpenClipboard() raises an exception, this function will do265 # If safeOpenClipboard() raises an exception, this function will do
211 # nothing but allow it to be raised. (We shouldn't attempt to close266 # nothing but allow it to be raised. (We shouldn't attempt to close
@@ -231,7 +286,7 @@
231 the CF_CLIPBOARD_VIEWER_IGNORE format so that clipboard viewers286 the CF_CLIPBOARD_VIEWER_IGNORE format so that clipboard viewers
232 will ignore this alteration of the clipboard.287 will ignore this alteration of the clipboard.
233 """288 """
234 289
235 win32clipboard.EmptyClipboard()290 win32clipboard.EmptyClipboard()
236 setClipboardDataViewerIgnore()291 setClipboardDataViewerIgnore()
237292
@@ -264,7 +319,7 @@
264 """319 """
265 LONGTERM TODO: This is kept around for debugging but can be deleted from320 LONGTERM TODO: This is kept around for debugging but can be deleted from
266 production code.321 production code.
267 322
268 Given a format code (of the kind returned from the windows clipboard323 Given a format code (of the kind returned from the windows clipboard
269 functions), returns a string describing the meaning of that324 functions), returns a string describing the meaning of that
270 format code.325 format code.
@@ -333,8 +388,18 @@
333 """388 """
334389
335 _keyboardEvent( win32con.VK_CONTROL, KEYEVENTF_KEYDOWN )390 _keyboardEvent( win32con.VK_CONTROL, KEYEVENTF_KEYDOWN )
336 _keyboardEvent( ord(key.upper()), KEYEVENTF_KEYDOWN )391
337 _keyboardEvent( ord(key.upper()), KEYEVENTF_KEYUP )392 if isinstance(key, basestring):
393 if key in KEY_MAPPING:
394 key_code = KEY_MAPPING[key]
395 else:
396 key_code = ord(key.upper())
397 else:
398 key_code = key
399
400 _keyboardEvent( key_code, KEYEVENTF_KEYDOWN )
401 _keyboardEvent( key_code, KEYEVENTF_KEYUP )
402
338 _keyboardEvent( win32con.VK_CONTROL, KEYEVENTF_KEYUP )403 _keyboardEvent( win32con.VK_CONTROL, KEYEVENTF_KEYUP )
339 logging.info( "I am in typeCommandKey and I just typed " + key )404 logging.info( "I am in typeCommandKey and I just typed " + key )
340405
@@ -344,18 +409,50 @@
344 Given a character literal, simulates holding the Alt key down409 Given a character literal, simulates holding the Alt key down
345 and typing that character.410 and typing that character.
346 """411 """
347 412
348 _keyboardEvent( win32con.VK_MENU, KEYEVENTF_KEYDOWN )413 _keyboardEvent( win32con.VK_MENU, KEYEVENTF_KEYDOWN )
349 _keyboardEvent( ord(key.upper()), KEYEVENTF_KEYDOWN )414
350 _keyboardEvent( ord(key.upper()), KEYEVENTF_KEYUP )415 if isinstance(key, basestring):
416 if key in KEY_MAPPING:
417 key_code = KEY_MAPPING[key]
418 else:
419 key_code = ord(key.upper())
420 else:
421 key_code = key
422
423 _keyboardEvent( key_code, KEYEVENTF_KEYDOWN )
424 _keyboardEvent( key_code, KEYEVENTF_KEYUP )
425
351 _keyboardEvent( win32con.VK_MENU, KEYEVENTF_KEYUP )426 _keyboardEvent( win32con.VK_MENU, KEYEVENTF_KEYUP )
352427
353428
429def typeShiftKey( key ):
430 """
431 Given a character literal, simulates holding the Shift key down
432 and typing that character.
433 """
434
435 _keyboardEvent( win32con.VK_LSHIFT, KEYEVENTF_KEYDOWN )
436
437 if isinstance(key, basestring):
438 if key in KEY_MAPPING:
439 key_code = KEY_MAPPING[key]
440 else:
441 key_code = ord(key.upper())
442 else:
443 key_code = key
444
445 _keyboardEvent( key_code, KEYEVENTF_KEYDOWN )
446 _keyboardEvent( key_code, KEYEVENTF_KEYUP )
447
448 _keyboardEvent( win32con.VK_LSHIFT, KEYEVENTF_KEYUP )
449
450
354def tapKey( keyCode ):451def tapKey( keyCode ):
355 """452 """
356 Given a virtual key code, simulates tapping that key.453 Given a virtual key code, simulates tapping that key.
357 """454 """
358 455
359 _keyboardEvent( keyCode, KEYEVENTF_KEYDOWN )456 _keyboardEvent( keyCode, KEYEVENTF_KEYDOWN )
360 _keyboardEvent( keyCode, KEYEVENTF_KEYUP )457 _keyboardEvent( keyCode, KEYEVENTF_KEYUP )
361458
@@ -384,43 +481,10 @@
384 # keydown, keyup, keypress, and pauses.481 # keydown, keyup, keypress, and pauses.
385482
386 keys = keys.split( " " )483 keys = keys.split( " " )
387 mapping = { "F1" : win32con.VK_F1,
388 "F2" : win32con.VK_F2,
389 "F3" : win32con.VK_F3,
390 "F4" : win32con.VK_F4,
391 "F5" : win32con.VK_F5,
392 "F6" : win32con.VK_F6,
393 "F7" : win32con.VK_F7,
394 "F8" : win32con.VK_F8,
395 "F9" : win32con.VK_F9,
396 "F10": win32con.VK_F10,
397 "F11": win32con.VK_F11,
398 "F12": win32con.VK_F12,
399 "CD" : win32con.VK_LCONTROL,
400 "CU" : win32con.VK_LCONTROL,
401 "SD" : win32con.VK_LSHIFT,
402 "SU" : win32con.VK_LSHIFT,
403 "AD" : win32con.VK_MENU,
404 "AU" : win32con.VK_MENU,
405 "ID" : win32con.VK_LWIN,
406 "IU" : win32con.VK_LWIN,
407 "LA": win32con.VK_LEFT,
408 "RA": win32con.VK_RIGHT,
409 "ESC": win32con.VK_ESCAPE,
410 "INS": win32con.VK_INSERT,
411 "DEL": win32con.VK_DELETE
412 }
413484
414 for key in keys:485 for key in keys:
415 key = key.upper()486 key = key.upper()
416 487
417 # Any one-character code means tap and release that literal key.
418 if len(key) == 1:
419 key_code = ord( key )
420 _keyboardEvent( key_code, KEYEVENTF_KEYDOWN )
421 _keyboardEvent( key_code, KEYEVENTF_KEYUP )
422 continue
423
424 # "W##" means wait488 # "W##" means wait
425 if key[0] == "W":489 if key[0] == "W":
426 time.sleep( float(key[1:]) )490 time.sleep( float(key[1:]) )
@@ -430,26 +494,30 @@
430 # keybd_event function, and therefore don't use our keyboard494 # keybd_event function, and therefore don't use our keyboard
431 # event wrapper.495 # event wrapper.
432 if key in ["SD", "AD", "ID", "CD"]:496 if key in ["SD", "AD", "ID", "CD"]:
433 win32api.keybd_event( mapping[key], 0, KEYEVENTF_KEYDOWN, 0 )497 win32api.keybd_event( KEY_MAPPING[key], 0, KEYEVENTF_KEYDOWN, 0 )
434 continue498 continue
435 if key in ["SU", "AU", "IU", "CU"]:499 if key in ["SU", "AU", "IU", "CU"]:
436 win32api.keybd_event( mapping[key], 0, KEYEVENTF_KEYUP, 0 )500 win32api.keybd_event( KEY_MAPPING[key], 0, KEYEVENTF_KEYUP, 0 )
437 continue501 continue
438502
439 # Any other multi-character code means look up the code503 # Any one-character code means tap and release that literal key.
440 # in the table above, and tap the key.504 if key in KEY_MAPPING:
441 key_code = mapping[key]505 key_code = KEY_MAPPING[key]
506 else:
507 key_code = ord(key.upper())
442 _keyboardEvent( key_code, KEYEVENTF_KEYDOWN )508 _keyboardEvent( key_code, KEYEVENTF_KEYDOWN )
443 _keyboardEvent( key_code, KEYEVENTF_KEYUP )509 _keyboardEvent( key_code, KEYEVENTF_KEYUP )
444510
445511
446def getForegroundClassNameUnicode():512def getForegroundClassNameUnicode(hwnd = None):
447 """513 """
448 Returns a unicode string containing the class name of the frontmost514 Returns a unicode string containing the class name of the specified
449 application window.515 application window.
516 If hwnd parameter is None, frontmost window will be queried.
450 """517 """
451518
452 hwnd = win32gui.GetForegroundWindow()519 if hwnd is None:
520 hwnd = win32gui.GetForegroundWindow()
453521
454 # Maximum number of chars we'll accept for the class name; the522 # Maximum number of chars we'll accept for the class name; the
455 # rest will be truncated if it's longer than this.523 # rest will be truncated if it's longer than this.
@@ -466,6 +534,38 @@
466 return classNameBuf.value534 return classNameBuf.value
467535
468536
537def getWindowClassName(hwnd = None):
538 """
539 Returns a unicode string containing the class name of the specified
540 application window.
541 If hwnd parameter is None, frontmost window will be queried.
542 """
543 return getForegroundClassNameUnicode(hwnd)
544
545
546def getWindowProcessName(hwnd = None):
547 """
548 Returns a unicode string containing the process name of the specified
549 application window (executable path).
550 If hwnd parameter is None, frontmost window will be queried.
551 """
552 if hwnd is None:
553 hwnd = win32gui.GetForegroundWindow()
554 # Get PID so we can get process name
555 _, process_id = win32process.GetWindowThreadProcessId(hwnd)
556 # Get process name
557 phandle = win32api.OpenProcess(
558 win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ,
559 False,
560 process_id)
561 if phandle:
562 pexe = win32process.GetModuleFileNameEx(phandle, 0)
563 pexe = os.path.normcase(os.path.normpath(pexe))
564 return pexe
565 else:
566 return None
567
568
469# ----------------------------------------------------------------------------569# ----------------------------------------------------------------------------
470# Exception570# Exception
471# ----------------------------------------------------------------------------571# ----------------------------------------------------------------------------
@@ -475,5 +575,5 @@
475 Exception raised if the clipboard was unable to be opened after575 Exception raised if the clipboard was unable to be opened after
476 multiple attempts.576 multiple attempts.
477 """577 """
478 578
479 pass579 pass
480580
=== modified file 'enso/platform/win32/selection/__init__.py'
--- enso/platform/win32/selection/__init__.py 2008-04-27 11:12:38 +0000
+++ enso/platform/win32/selection/__init__.py 2010-07-30 13:46:41 +0000
@@ -70,7 +70,7 @@
70 textSelContext = TextSelection.get()70 textSelContext = TextSelection.get()
71 71
72 # Trying to "set" a file selection doesn't do anything.72 # Trying to "set" a file selection doesn't do anything.
73 textSelContext.replaceSelection( sel_dict )73 return textSelContext.replaceSelection( sel_dict )
7474
7575
76# ----------------------------------------------------------------------------76# ----------------------------------------------------------------------------

Subscribers

People subscribed via source and target branches

to status/vote changes: