Skip to content

Commit 5fdd68a

Browse files
committed
Tested Tkinter and PySide keys on osx (10.7)
1 parent 74b6489 commit 5fdd68a

File tree

2 files changed

+74
-13
lines changed

2 files changed

+74
-13
lines changed

lib/matplotlib/backends/backend_qt4.py

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class FigureCanvasQT( QtGui.QWidget, FigureCanvasBase ):
123123
keyvald = { QtCore.Qt.Key_Control : 'control',
124124
QtCore.Qt.Key_Shift : 'shift',
125125
QtCore.Qt.Key_Alt : 'alt',
126+
QtCore.Qt.Key_Meta : 'super',
126127
QtCore.Qt.Key_Return : 'enter',
127128
QtCore.Qt.Key_Left : 'left',
128129
QtCore.Qt.Key_Up : 'up',
@@ -146,13 +147,37 @@ class FigureCanvasQT( QtGui.QWidget, FigureCanvasBase ):
146147
QtCore.Qt.Key_PageUp : 'pageup',
147148
QtCore.Qt.Key_PageDown : 'pagedown',
148149
}
150+
151+
# define the modifier keys which are to be collected on keyboard events.
152+
# format is: [(modifier_flag, modifier_name, equivalent_key)
153+
_modifier_keys = [
154+
(QtCore.Qt.MetaModifier, 'super', QtCore.Qt.Key_Meta),
155+
(QtCore.Qt.AltModifier, 'alt', QtCore.Qt.Key_Alt),
156+
(QtCore.Qt.ControlModifier, 'ctrl', QtCore.Qt.Key_Control)
157+
]
158+
159+
if sys.platform == 'darwin':
160+
# in OSX, the control and super (aka cmd/apple) keys are switched, so
161+
# switch them back.
162+
keyvald.update({
163+
QtCore.Qt.Key_Control : 'super', # cmd/apple key
164+
QtCore.Qt.Key_Meta : 'control',
165+
})
166+
167+
_modifier_keys = [
168+
(QtCore.Qt.ControlModifier, 'super', QtCore.Qt.Key_Control),
169+
(QtCore.Qt.AltModifier, 'alt', QtCore.Qt.Key_Alt),
170+
(QtCore.Qt.MetaModifier, 'ctrl', QtCore.Qt.Key_Meta),
171+
]
172+
149173
# map Qt button codes to MouseEvent's ones:
150174
buttond = {QtCore.Qt.LeftButton : 1,
151175
QtCore.Qt.MidButton : 2,
152176
QtCore.Qt.RightButton : 3,
153177
# QtCore.Qt.XButton1 : None,
154178
# QtCore.Qt.XButton2 : None,
155179
}
180+
156181
def __init__( self, figure ):
157182
if DEBUG: print('FigureCanvasQt: ', figure)
158183
_create_qApp()
@@ -295,8 +320,7 @@ def _get_key( self, event ):
295320

296321
if key is not None:
297322
# prepend the ctrl, alt, super keys if appropriate (sorted in that order)
298-
for modifier, Qt_key, prefix in [(QtCore.Qt.AltModifier, QtCore.Qt.Key_Alt, 'alt'),
299-
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Control, 'ctrl')]:
323+
for modifier, prefix, Qt_key in self._modifier_keys:
300324
if event.key() != Qt_key and int(event.modifiers()) & modifier == modifier:
301325
key = '{}+{}'.format(prefix, key)
302326

@@ -368,6 +392,14 @@ def __init__( self, canvas, num ):
368392
self.canvas.setFocusPolicy( QtCore.Qt.StrongFocus )
369393
self.canvas.setFocus()
370394

395+
if sys.platform == 'darwin':
396+
# to make a qt window pop up on top on osx, osascript can be used
397+
# this came from http://sourceforge.net/mailarchive/message.php?msg_id=23718545
398+
cmd = ("""/usr/bin/osascript -e 'tell app "Finder" to set """ + \
399+
"""frontmost of process "%s" to true'""") % \
400+
os.path.basename(sys.executable)
401+
os.system(cmd)
402+
371403
QtCore.QObject.connect( self.window, QtCore.SIGNAL( 'destroyed()' ),
372404
self._widgetclosed )
373405
self.window._destroying = False
@@ -398,9 +430,9 @@ def __init__( self, canvas, num ):
398430
self.canvas.figure.show = lambda *args: self.window.show()
399431

400432
def notify_axes_change( fig ):
401-
# This will be called whenever the current axes is changed
402-
if self.toolbar is not None:
403-
self.toolbar.update()
433+
# This will be called whenever the current axes is changed
434+
if self.toolbar is not None:
435+
self.toolbar.update()
404436
self.canvas.figure.add_axobserver( notify_axes_change )
405437

406438
@QtCore.Slot()
@@ -409,10 +441,10 @@ def _show_message(self,s):
409441
self.window.statusBar().showMessage(s)
410442

411443
def full_screen_toggle(self):
412-
if self.window.isFullScreen():
413-
self.window.showNormal()
414-
else:
415-
self.window.showFullScreen()
444+
if self.window.isFullScreen():
445+
self.window.showNormal()
446+
else:
447+
self.window.showFullScreen()
416448

417449
def _widgetclosed( self ):
418450
if self.window._destroying: return

lib/matplotlib/backends/backend_tkagg.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,17 @@ class FigureCanvasTkAgg(FigureCanvasAgg):
174174
65439 : 'dec',
175175
65421 : 'enter',
176176
}
177+
178+
_keycode_lookup = {
179+
262145: 'control',
180+
524320: 'alt',
181+
524352: 'alt',
182+
1048584: 'super',
183+
1048592: 'super',
184+
131074: 'shift',
185+
131076: 'shift',
186+
}
187+
"""_keycode_lookup is used for badly mapped keys on apple keyboards."""
177188

178189
def __init__(self, figure, master=None, resize_callback=None):
179190
FigureCanvasAgg.__init__(self, figure)
@@ -217,7 +228,15 @@ def filter_destroy(evt):
217228

218229
self._master = master
219230
self._tkcanvas.focus_set()
220-
231+
232+
if sys.platform == 'darwin':
233+
# to make a tkagg window pop up on top on osx, osascript can be used
234+
# this came from http://sourceforge.net/mailarchive/message.php?msg_id=23718545
235+
cmd = ("""/usr/bin/osascript -e 'tell app "Finder" to set """ + \
236+
"""frontmost of process "%s" to true'""") % \
237+
os.path.basename(sys.executable)
238+
os.system(cmd)
239+
221240
def resize(self, event):
222241
width, height = event.width, event.height
223242
if self._resize_callback is not None:
@@ -399,20 +418,30 @@ def _get_key(self, event):
399418
val = event.keysym_num
400419
if val in self.keyvald:
401420
key = self.keyvald[val]
421+
elif val == 0 and sys.platform == 'darwin' and \
422+
event.keycode in self._keycode_lookup:
423+
key = self._keycode_lookup[event.keycode]
402424
elif val < 256:
403425
key = chr(val)
404426
else:
405427
key = None
406-
428+
407429
# add modifier keys to the key string. Bit details originate from
408430
# http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
409431
# BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004;
410432
# BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080;
411433
# BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400;
434+
# In general, the modifier key is excluded from the modifier flag,
435+
# however this is not the case on "darwin", so double check that
436+
# we aren't adding repeat modifier flags to a modifier key.
437+
modifiers = (3, 'alt', 'alt'), (2, 'ctrl', 'control'),
438+
if sys.platform == 'darwin':
439+
modifiers = (3, 'super', 'super'), (4, 'alt', 'alt'), (2, 'ctrl', 'control'),
440+
412441
if key is not None:
413442
# note, shift is not added to the keys as this is already accounted for
414-
for bitmask, prefix in [(3, 'alt'), (2, 'ctrl'), ]:
415-
if event.state & (1 << bitmask):
443+
for bitmask, prefix, key_name in modifiers:
444+
if event.state & (1 << bitmask) and key_name not in key:
416445
key = '{}+{}'.format(prefix, key)
417446

418447
return key

0 commit comments

Comments
 (0)