diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 3d0e9f583319..869b887784c4 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -1606,10 +1606,15 @@ class MouseEvent(LocationEvent): key : None, or str the key depressed when the mouse event triggered (see :class:`KeyEvent`) + Note: .key is only processed if the FigureCanvas received keyboard + focus. For safer retrieval of modifier keys use .modifiers instead step : scalar number of scroll steps (positive for 'up', negative for 'down') + modifiers : set + modifier keys depressed when mouse event is triggered + Examples -------- Usage:: @@ -1620,17 +1625,18 @@ def on_press(event): cid = fig.canvas.mpl_connect('button_press_event', on_press) """ - x = None # x position - pixels from left of canvas - y = None # y position - pixels from right of canvas - button = None # button pressed None, 1, 2, 3 - dblclick = None # whether or not the event is the result of a double click - inaxes = None # the Axes instance if mouse us over axes - xdata = None # x coord of mouse in data coords - ydata = None # y coord of mouse in data coords - step = None # scroll steps for scroll events + x = None # x position - pixels from left of canvas + y = None # y position - pixels from right of canvas + button = None # button pressed None, 1, 2, 3 + dblclick = None # whether or not the event is the result of a double click + inaxes = None # the Axes instance if mouse us over axes + xdata = None # x coord of mouse in data coords + ydata = None # y coord of mouse in data coords + step = None # scroll steps for scroll events + modifiers = None # depressed modifier keys def __init__(self, name, canvas, x, y, button=None, key=None, - step=0, dblclick=False, guiEvent=None): + step=0, dblclick=False, guiEvent=None, modifiers=None): """ x, y in figure coords, 0,0 = bottom, left button pressed None, 1, 2, 3, 'up', 'down' @@ -1640,6 +1646,7 @@ def __init__(self, name, canvas, x, y, button=None, key=None, self.key = key self.step = step self.dblclick = dblclick + self.modifiers = modifiers def __str__(self): return ("MPL MouseEvent: xy=(%d,%d) xydata=(%s,%s) button=%s " + @@ -1921,7 +1928,7 @@ def scroll_event(self, x, y, step, guiEvent=None): step=step, guiEvent=guiEvent) self.callbacks.process(s, mouseevent) - def button_press_event(self, x, y, button, dblclick=False, guiEvent=None): + def button_press_event(self, x, y, button, dblclick=False, guiEvent=None, modifiers=None): """ Backend derived classes should call this function on any mouse button press. x,y are the canvas coords: 0,0 is lower, left. @@ -1932,8 +1939,9 @@ def button_press_event(self, x, y, button, dblclick=False, guiEvent=None): """ self._button = button s = 'button_press_event' + mouseevent = MouseEvent(s, self, x, y, button, self._key, - dblclick=dblclick, guiEvent=guiEvent) + dblclick=dblclick, guiEvent=guiEvent, modifiers=modifiers) self.callbacks.process(s, mouseevent) def button_release_event(self, x, y, button, guiEvent=None): diff --git a/lib/matplotlib/backends/backend_gtk.py b/lib/matplotlib/backends/backend_gtk.py index b3f7ec504bca..c518400c5cb6 100644 --- a/lib/matplotlib/backends/backend_gtk.py +++ b/lib/matplotlib/backends/backend_gtk.py @@ -163,6 +163,10 @@ class FigureCanvasGTK (gtk.DrawingArea, FigureCanvasBase): 65406 : 'alt', 65289 : 'tab', } + modifier_keys = [[gdk.MOD4_MASK, 'super'], + [gdk.MOD1_MASK, 'alt'], + [gdk.CONTROL_MASK, 'ctrl'], + [gdk.SHIFT_MASK, 'shift']] # Setting this as a static constant prevents # this resulting expression from leaking @@ -250,7 +254,9 @@ def button_press_event(self, widget, event): del self.last_downclick[event.button] # we do not want to eat more than one event. return False # eat. self.last_downclick[event.button] = current_time - FigureCanvasBase.button_press_event(self, x, y, event.button, dblclick=dblclick, guiEvent=event) + modifiers = {prefix for key_mask, prefix in modifier_keys if event.state & key_mask} + FigureCanvasBase.button_press_event(self, x, y, event.button, + dblclick=dblclick, guiEvent=event, modifiers=modifiers) return False # finish event propagation? def button_release_event(self, widget, event): diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index a5f223a38753..cd4a4ad1f151 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -151,6 +151,10 @@ class FigureCanvasGTK3(Gtk.DrawingArea, FigureCanvasBase): 65439 : 'dec', 65421 : 'enter', } + modifier_keys = [[gdk.MOD4_MASK, 'super'], + [gdk.MOD1_MASK, 'alt'], + [gdk.CONTROL_MASK, 'ctrl'], + [gdk.SHIFT_MASK, 'shift']] # Setting this as a static constant prevents # this resulting expression from leaking @@ -212,7 +216,8 @@ def button_press_event(self, widget, event): x = event.x # flipy so y=0 is bottom of canvas y = self.get_allocation().height - event.y - FigureCanvasBase.button_press_event(self, x, y, event.button, guiEvent=event) + modifiers = {prefix for key_mask, prefix in modifier_keys if event.state & key_mask} + FigureCanvasBase.button_press_event(self, x, y, event.button, guiEvent=event, modifiers=modifiers) return False # finish event propagation? def button_release_event(self, widget, event): diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 2345d2fe1640..2864e011c119 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -237,17 +237,23 @@ def mouseEventCoords(self, pos): def mousePressEvent(self, event): x, y = self.mouseEventCoords(event.pos()) button = self.buttond.get(event.button()) + modifiers = {name for name, mod_key, qt_key in MODIFIER_KEYS + if event.modifiers() & mod_key} if button is not None: FigureCanvasBase.button_press_event(self, x, y, button, - guiEvent=event) + guiEvent=event, + modifiers=modifiers) def mouseDoubleClickEvent(self, event): x, y = self.mouseEventCoords(event.pos()) button = self.buttond.get(event.button()) + modifiers = {name for name, mod_key, qt_key in MODIFIER_KEYS + if event.modifiers() & mod_key} if button is not None: FigureCanvasBase.button_press_event(self, x, y, button, dblclick=True, - guiEvent=event) + guiEvent=event, + modifiers=modifiers) def mouseMoveEvent(self, event): x, y = self.mouseEventCoords(event) diff --git a/lib/matplotlib/backends/backend_tkagg.py b/lib/matplotlib/backends/backend_tkagg.py index f6190d4f369e..7694686d8c2e 100644 --- a/lib/matplotlib/backends/backend_tkagg.py +++ b/lib/matplotlib/backends/backend_tkagg.py @@ -209,6 +209,30 @@ def filter_destroy(evt): self.close_event() root.bind("", filter_destroy, "+") + # Dictionary for adding modifier keys to the key string. + # Bit details originate from + # http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm + # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004; + # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080; + # BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400; + # In general, the modifier key is excluded from the modifier flag, + # however this is not the case on "darwin", so double check that + # we aren't adding repeat modifier flags to a modifier key. + if sys.platform == 'win32': + self.MOD_KEYS = [(17, 'alt', 'alt'), + (2, 'ctrl', 'control'), + ] + elif sys.platform == 'darwin': + self.MOD_KEYS = [(3, 'super', 'super'), + (4, 'alt', 'alt'), + (2, 'ctrl', 'control'), + ] + else: + self.MOD_KEYS = [(6, 'super', 'super'), + (3, 'alt', 'alt'), + (2, 'ctrl', 'control'), + ] + self._master = master self._tkcanvas.focus_set() @@ -344,6 +368,7 @@ def button_press_event(self, event, dblclick=False): # flipy so y=0 is bottom of canvas y = self.figure.bbox.height - event.y num = getattr(event, 'num', None) + modifiers = self._get_modifiers(event) if sys.platform=='darwin': # 2 and 3 were reversed on the OSX platform I @@ -351,9 +376,10 @@ def button_press_event(self, event, dblclick=False): if num==2: num=3 elif num==3: num=2 - FigureCanvasBase.button_press_event(self, x, y, num, dblclick=dblclick, guiEvent=event) + FigureCanvasBase.button_press_event(self, x, y, num, dblclick=dblclick, + guiEvent=event, modifiers=modifiers) - def button_dblclick_event(self,event): + def button_dblclick_event(self, event): self.button_press_event(event,dblclick=True) def button_release_event(self, event): @@ -404,37 +430,19 @@ def _get_key(self, event): else: key = None - # add modifier keys to the key string. Bit details originate from - # http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm - # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004; - # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080; - # BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400; - # In general, the modifier key is excluded from the modifier flag, - # however this is not the case on "darwin", so double check that - # we aren't adding repeat modifier flags to a modifier key. - if sys.platform == 'win32': - modifiers = [(17, 'alt', 'alt'), - (2, 'ctrl', 'control'), - ] - elif sys.platform == 'darwin': - modifiers = [(3, 'super', 'super'), - (4, 'alt', 'alt'), - (2, 'ctrl', 'control'), - ] - else: - modifiers = [(6, 'super', 'super'), - (3, 'alt', 'alt'), - (2, 'ctrl', 'control'), - ] - if key is not None: # note, shift is not added to the keys as this is already accounted for - for bitmask, prefix, key_name in modifiers: + for bitmask, prefix, key_name in self.MOD_KEYS: if event.state & (1 << bitmask) and key_name not in key: key = '{0}+{1}'.format(prefix, key) return key + def _get_modifiers(self, event): + modifiers = {prefix for bitmask, prefix, key_name in self.MOD_KEYS + if event.state & (1 << bitmask)} + return modifiers + def key_press(self, event): key = self._get_key(event) FigureCanvasBase.key_press_event(self, key, guiEvent=event) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index f7df0707e637..00a8ad95ff23 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1004,6 +1004,19 @@ def _get_key(self, evt): return key + def _get_modifiers(self, evt): + """ + Extracts modifier keys from a wx MouseEvent + """ + MOD_KEYS = {"AltDown": "alt", + "CmdDown": "ctrl", + "ControlDown": "ctrl", + "ShiftDown": "shift" + } + modifiers = {prefix for attr, prefix in MOD_KEYS + if getattr(evt, attr)()} + return modifiers + def _onKeyDown(self, evt): """Capture key press.""" key = self._get_key(evt) @@ -1034,7 +1047,10 @@ def _onRightButtonDown(self, evt): y = self.figure.bbox.height - evt.GetY() evt.Skip() self._set_capture(True) - FigureCanvasBase.button_press_event(self, x, y, 3, guiEvent=evt) + modifiers = self._get_modifiers(evt) + FigureCanvasBase.button_press_event(self, x, y, 3, + guiEvent=evt, + modifiers=modifiers) def _onRightButtonDClick(self, evt): """Start measuring on an axis.""" @@ -1042,8 +1058,10 @@ def _onRightButtonDClick(self, evt): y = self.figure.bbox.height - evt.GetY() evt.Skip() self._set_capture(True) + modifiers = self._get_modifiers(evt) FigureCanvasBase.button_press_event(self, x, y, 3, - dblclick=True, guiEvent=evt) + dblclick=True, guiEvent=evt, + modifiers=modifiers) def _onRightButtonUp(self, evt): """End measuring on an axis.""" @@ -1059,7 +1077,10 @@ def _onLeftButtonDown(self, evt): y = self.figure.bbox.height - evt.GetY() evt.Skip() self._set_capture(True) - FigureCanvasBase.button_press_event(self, x, y, 1, guiEvent=evt) + modifiers = self._get_modifiers(evt) + FigureCanvasBase.button_press_event(self, x, y, 1, + guiEvent=evt, + modifiers=modifiers) def _onLeftButtonDClick(self, evt): """Start measuring on an axis.""" @@ -1067,8 +1088,10 @@ def _onLeftButtonDClick(self, evt): y = self.figure.bbox.height - evt.GetY() evt.Skip() self._set_capture(True) + modifiers = self._get_modifiers(evt) FigureCanvasBase.button_press_event(self, x, y, 1, - dblclick=True, guiEvent=evt) + dblclick=True, guiEvent=evt, + modifiers=modifiers) def _onLeftButtonUp(self, evt): """End measuring on an axis.""" @@ -1086,7 +1109,10 @@ def _onMiddleButtonDown(self, evt): y = self.figure.bbox.height - evt.GetY() evt.Skip() self._set_capture(True) - FigureCanvasBase.button_press_event(self, x, y, 2, guiEvent=evt) + modifiers = self._get_modifiers(evt) + FigureCanvasBase.button_press_event(self, x, y, 2, + guiEvent=evt, + modifiers=modifiers) def _onMiddleButtonDClick(self, evt): """Start measuring on an axis.""" @@ -1094,8 +1120,10 @@ def _onMiddleButtonDClick(self, evt): y = self.figure.bbox.height - evt.GetY() evt.Skip() self._set_capture(True) + modifiers = self._get_modifiers(evt) FigureCanvasBase.button_press_event(self, x, y, 2, - dblclick=True, guiEvent=evt) + dblclick=True, guiEvent=evt, + modifiers=modifiers) def _onMiddleButtonUp(self, evt): """End measuring on an axis.""" diff --git a/src/_macosx.m b/src/_macosx.m index 1e5c49c39cf5..23985ce5ba4f 100644 --- a/src/_macosx.m +++ b/src/_macosx.m @@ -2332,21 +2332,23 @@ - (void)mouseDown:(NSEvent *)event location = [self convertPoint: location fromView: nil]; x = location.x * device_scale; y = location.y * device_scale; + + unsigned int modifier = [event modifierFlags]; + PyObject* modifiers = PySet_New(NULL); + if (modifier & NSControlKeyMask) + PySet_Add(modifiers, PyString_FromString("ctrl")); + if (modifier & NSAlternateKeyMask) + PySet_Add(modifiers, PyString_FromString("alt")); + if (modifier & NSShiftKeyMask) + PySet_Add(modifiers, PyString_FromString("shift")); + if (modifier & NSCommandKeyMask) + PySet_Add(modifiers, PyString_FromString("cmd")); + switch ([event type]) { case NSLeftMouseDown: - { unsigned int modifier = [event modifierFlags]; - if (modifier & NSControlKeyMask) - /* emulate a right-button click */ - num = 3; - else if (modifier & NSAlternateKeyMask) - /* emulate a middle-button click */ - num = 2; - else - { - num = 1; - if ([NSCursor currentCursor]==[NSCursor openHandCursor]) + { if ([NSCursor currentCursor]==[NSCursor openHandCursor]) [[NSCursor closedHandCursor] set]; - } + num = 1; break; } case NSOtherMouseDown: num = 2; break; @@ -2357,7 +2359,8 @@ - (void)mouseDown:(NSEvent *)event dblclick = 1; } gstate = PyGILState_Ensure(); - result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick); + result = PyObject_CallMethod(canvas, "button_press_event", "iiii", + x, y, num, dblclick, Py_None, modifiers); if(result) Py_DECREF(result); else @@ -2445,7 +2448,18 @@ - (void)rightMouseDown:(NSEvent *)event if ([event clickCount] == 2) { dblclick = 1; } - result = PyObject_CallMethod(canvas, "button_press_event", "iiii", x, y, num, dblclick); + unsigned int modifier = [event modifierFlags]; + PyObject* modifiers = PySet_New(NULL); + if (modifier & NSControlKeyMask) + PySet_Add(modifiers, PyString_FromString("ctrl")); + if (modifier & NSAlternateKeyMask) + PySet_Add(modifiers, PyString_FromString("alt")); + if (modifier & NSShiftKeyMask) + PySet_Add(modifiers, PyString_FromString("shift")); + if (modifier & NSCommandKeyMask) + PySet_Add(modifiers, PyString_FromString("cmd")); + result = PyObject_CallMethod(canvas, "button_press_event", "iiii", + x, y, num, dblclick, Py_None, modifiers); if(result) Py_DECREF(result); else pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy