Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9c93c36

Browse files
committed
Implemented modifier-key tracking via sets in MouseEvents
Added support for gtk, qt, tkinter, wx
1 parent 8293708 commit 9c93c36

File tree

6 files changed

+81
-40
lines changed

6 files changed

+81
-40
lines changed

lib/matplotlib/backend_bases.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,8 @@ class MouseEvent(LocationEvent):
15131513
*key*
15141514
the key depressed when the mouse event triggered (see
15151515
:class:`KeyEvent`)
1516+
Note: .key is only processed if the FigureCanvas received keyboard
1517+
focus. For safer retrieval of modifier keys use .modifiers instead
15161518
15171519
*step*
15181520
number of scroll steps (positive for 'up', negative for 'down')
@@ -1891,7 +1893,7 @@ def scroll_event(self, x, y, step, guiEvent=None):
18911893
step=step, guiEvent=guiEvent)
18921894
self.callbacks.process(s, mouseevent)
18931895

1894-
def button_press_event(self, x, y, button, dblclick=False, modifiers=None, guiEvent=None):
1896+
def button_press_event(self, x, y, button, dblclick=False, guiEvent=None, modifiers=None):
18951897
"""
18961898
Backend derived classes should call this function on any mouse
18971899
button press. x,y are the canvas coords: 0,0 is lower, left.
@@ -1905,7 +1907,7 @@ def button_press_event(self, x, y, button, dblclick=False, modifiers=None, guiEv
19051907
s = 'button_press_event'
19061908

19071909
mouseevent = MouseEvent(s, self, x, y, button, self._key,
1908-
dblclick=dblclick, modifiers=modifiers, guiEvent=guiEvent)
1910+
dblclick=dblclick, guiEvent=guiEvent, modifiers=modifiers)
19091911
self.callbacks.process(s, mouseevent)
19101912

19111913
def button_release_event(self, x, y, button, guiEvent=None):

lib/matplotlib/backends/backend_gtk.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ class FigureCanvasGTK (gtk.DrawingArea, FigureCanvasBase):
202202
65406 : 'alt',
203203
65289 : 'tab',
204204
}
205+
modifier_keys = [[gdk.MOD4_MASK, 'super'],
206+
[gdk.MOD1_MASK, 'alt'],
207+
[gdk.CONTROL_MASK, 'ctrl'],
208+
[gdk.SHIFT_MASK, 'shift']]
205209

206210
# Setting this as a static constant prevents
207211
# this resulting expression from leaking
@@ -284,7 +288,9 @@ def button_press_event(self, widget, event):
284288
del self.last_downclick[event.button] # we do not want to eat more than one event.
285289
return False # eat.
286290
self.last_downclick[event.button] = current_time
287-
FigureCanvasBase.button_press_event(self, x, y, event.button, dblclick=dblclick, guiEvent=event)
291+
modifiers = {prefix for key_mask, prefix in modifier_keys if event.state & key_mask}
292+
FigureCanvasBase.button_press_event(self, x, y, event.button,
293+
dblclick=dblclick, guiEvent=event, modifiers=modifiers)
288294
return False # finish event propagation?
289295

290296
def button_release_event(self, widget, event):

lib/matplotlib/backends/backend_gtk3.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ class FigureCanvasGTK3 (Gtk.DrawingArea, FigureCanvasBase):
170170
65439 : 'dec',
171171
65421 : 'enter',
172172
}
173+
modifier_keys = [[gdk.MOD4_MASK, 'super'],
174+
[gdk.MOD1_MASK, 'alt'],
175+
[gdk.CONTROL_MASK, 'ctrl'],
176+
[gdk.SHIFT_MASK, 'shift']]
173177

174178
# Setting this as a static constant prevents
175179
# this resulting expression from leaking
@@ -235,7 +239,8 @@ def button_press_event(self, widget, event):
235239
x = event.x
236240
# flipy so y=0 is bottom of canvas
237241
y = self.get_allocation().height - event.y
238-
FigureCanvasBase.button_press_event(self, x, y, event.button, guiEvent=event)
242+
modifiers = {prefix for key_mask, prefix in modifier_keys if event.state & key_mask}
243+
FigureCanvasBase.button_press_event(self, x, y, event.button, guiEvent=event, modifiers=modifiers)
239244
return False # finish event propagation?
240245

241246
def button_release_event(self, widget, event):

lib/matplotlib/backends/backend_qt5.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,11 @@ def mousePressEvent(self, event):
254254
# flipy so y=0 is bottom of canvas
255255
y = self.figure.bbox.height - event.pos().y()
256256
button = self.buttond.get(event.button())
257-
modifiers = "+".join([name for name, mod_key, qt_key in MODIFIER_KEYS
258-
if (int(event.modifiers()) & mod_key) == mod_key])
257+
modifiers = {name for name, mod_key, qt_key in MODIFIER_KEYS if event.modifiers() & mod_key}
259258
if button is not None:
260259
FigureCanvasBase.button_press_event(self, x, y, button,
261-
modifiers=modifiers,
262-
guiEvent=event)
260+
guiEvent=event,
261+
modifiers=modifiers)
263262
if DEBUG:
264263
print('button pressed:', event.button())
265264

lib/matplotlib/backends/backend_tkagg.py

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,30 @@ def filter_destroy(evt):
260260
self.close_event()
261261
root.bind("<Destroy>", filter_destroy, "+")
262262

263+
# Dictionary for adding modifier keys to the key string.
264+
# Bit details originate from
265+
# http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
266+
# BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004;
267+
# BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080;
268+
# BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400;
269+
# In general, the modifier key is excluded from the modifier flag,
270+
# however this is not the case on "darwin", so double check that
271+
# we aren't adding repeat modifier flags to a modifier key.
272+
if sys.platform == 'win32':
273+
self.MOD_KEYS = [(17, 'alt', 'alt'),
274+
(2, 'ctrl', 'control'),
275+
]
276+
elif sys.platform == 'darwin':
277+
self.MOD_KEYS = [(3, 'super', 'super'),
278+
(4, 'alt', 'alt'),
279+
(2, 'ctrl', 'control'),
280+
]
281+
else:
282+
self.MOD_KEYS = [(6, 'super', 'super'),
283+
(3, 'alt', 'alt'),
284+
(2, 'ctrl', 'control'),
285+
]
286+
263287
self._master = master
264288
self._tkcanvas.focus_set()
265289

@@ -395,16 +419,18 @@ def button_press_event(self, event, dblclick=False):
395419
# flipy so y=0 is bottom of canvas
396420
y = self.figure.bbox.height - event.y
397421
num = getattr(event, 'num', None)
422+
modifiers = self._get_modifiers(event)
398423

399424
if sys.platform=='darwin':
400425
# 2 and 3 were reversed on the OSX platform I
401426
# tested under tkagg
402427
if num==2: num=3
403428
elif num==3: num=2
404429

405-
FigureCanvasBase.button_press_event(self, x, y, num, dblclick=dblclick, guiEvent=event)
430+
FigureCanvasBase.button_press_event(self, x, y, num, dblclick=dblclick,
431+
guiEvent=event, modifiers=modifiers)
406432

407-
def button_dblclick_event(self,event):
433+
def button_dblclick_event(self, event):
408434
self.button_press_event(event,dblclick=True)
409435

410436
def button_release_event(self, event):
@@ -455,37 +481,19 @@ def _get_key(self, event):
455481
else:
456482
key = None
457483

458-
# add modifier keys to the key string. Bit details originate from
459-
# http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
460-
# BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004;
461-
# BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080;
462-
# BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400;
463-
# In general, the modifier key is excluded from the modifier flag,
464-
# however this is not the case on "darwin", so double check that
465-
# we aren't adding repeat modifier flags to a modifier key.
466-
if sys.platform == 'win32':
467-
modifiers = [(17, 'alt', 'alt'),
468-
(2, 'ctrl', 'control'),
469-
]
470-
elif sys.platform == 'darwin':
471-
modifiers = [(3, 'super', 'super'),
472-
(4, 'alt', 'alt'),
473-
(2, 'ctrl', 'control'),
474-
]
475-
else:
476-
modifiers = [(6, 'super', 'super'),
477-
(3, 'alt', 'alt'),
478-
(2, 'ctrl', 'control'),
479-
]
480-
481484
if key is not None:
482485
# note, shift is not added to the keys as this is already accounted for
483-
for bitmask, prefix, key_name in modifiers:
486+
for bitmask, prefix, key_name in self.MOD_KEYS:
484487
if event.state & (1 << bitmask) and key_name not in key:
485488
key = '{0}+{1}'.format(prefix, key)
486489

487490
return key
488491

492+
def _get_modifiers(self, event):
493+
modifiers = {prefix for bitmask, prefix, key_name in self.MOD_KEYS
494+
if event.state & (1 << bitmask)}
495+
return modifiers
496+
489497
def key_press(self, event):
490498
key = self._get_key(event)
491499
FigureCanvasBase.key_press_event(self, key, guiEvent=event)

lib/matplotlib/backends/backend_wx.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,18 @@ def _get_key(self, evt):
10131013

10141014
return key
10151015

1016+
def _get_modifiers(self, evt):
1017+
"""
1018+
Extracts modifier keys from a wx MouseEvent
1019+
"""
1020+
MOD_KEYS = {"AltDown" : "alt",
1021+
"CmdDown" : "ctrl",
1022+
"ControlDown" : "ctrl",
1023+
"ShiftDown" : "shift"
1024+
}
1025+
modifiers = {prefix for attr, prefix in MOD_KEYS if getattr(evt, attr)()}
1026+
return modifiers
1027+
10161028
def _onIdle(self, evt):
10171029
'a GUI idle event'
10181030
evt.Skip()
@@ -1037,16 +1049,19 @@ def _onRightButtonDown(self, evt):
10371049
y = self.figure.bbox.height - evt.GetY()
10381050
evt.Skip()
10391051
self.CaptureMouse()
1040-
FigureCanvasBase.button_press_event(self, x, y, 3, guiEvent=evt)
1052+
modifiers = self._get_modifiers(evt)
1053+
FigureCanvasBase.button_press_event(self, x, y, 3, guiEvent=evt, modifiers=modifiers)
10411054

10421055
def _onRightButtonDClick(self, evt):
10431056
"""Start measuring on an axis."""
10441057
x = evt.GetX()
10451058
y = self.figure.bbox.height - evt.GetY()
10461059
evt.Skip()
10471060
self.CaptureMouse()
1061+
modifiers = self._get_modifiers(evt)
10481062
FigureCanvasBase.button_press_event(self, x, y, 3,
1049-
dblclick=True, guiEvent=evt)
1063+
dblclick=True, guiEvent=evt,
1064+
modifiers=modifiers)
10501065

10511066
def _onRightButtonUp(self, evt):
10521067
"""End measuring on an axis."""
@@ -1063,16 +1078,19 @@ def _onLeftButtonDown(self, evt):
10631078
y = self.figure.bbox.height - evt.GetY()
10641079
evt.Skip()
10651080
self.CaptureMouse()
1066-
FigureCanvasBase.button_press_event(self, x, y, 1, guiEvent=evt)
1081+
modifiers = self._get_modifiers(evt)
1082+
FigureCanvasBase.button_press_event(self, x, y, 1, guiEvent=evt, modifiers=modifiers)
10671083

10681084
def _onLeftButtonDClick(self, evt):
10691085
"""Start measuring on an axis."""
10701086
x = evt.GetX()
10711087
y = self.figure.bbox.height - evt.GetY()
10721088
evt.Skip()
10731089
self.CaptureMouse()
1090+
modifiers = self._get_modifiers(evt)
10741091
FigureCanvasBase.button_press_event(self, x, y, 1,
1075-
dblclick=True, guiEvent=evt)
1092+
dblclick=True, guiEvent=evt,
1093+
modifiers=modifiers)
10761094

10771095
def _onLeftButtonUp(self, evt):
10781096
"""End measuring on an axis."""
@@ -1091,16 +1109,19 @@ def _onMiddleButtonDown(self, evt):
10911109
y = self.figure.bbox.height - evt.GetY()
10921110
evt.Skip()
10931111
self.CaptureMouse()
1094-
FigureCanvasBase.button_press_event(self, x, y, 2, guiEvent=evt)
1112+
modifiers = self._get_modifiers(evt)
1113+
FigureCanvasBase.button_press_event(self, x, y, 2, guiEvent=evt, modifiers=modifiers)
10951114

10961115
def _onMiddleButtonDClick(self, evt):
10971116
"""Start measuring on an axis."""
10981117
x = evt.GetX()
10991118
y = self.figure.bbox.height - evt.GetY()
11001119
evt.Skip()
11011120
self.CaptureMouse()
1121+
modifiers = self._get_modifiers(evt)
11021122
FigureCanvasBase.button_press_event(self, x, y, 2,
1103-
dblclick=True, guiEvent=evt)
1123+
dblclick=True, guiEvent=evt,
1124+
modifiers=modifiers)
11041125

11051126
def _onMiddleButtonUp(self, evt):
11061127
"""End measuring on an axis."""

0 commit comments

Comments
 (0)