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

Skip to content

Commit 72f731f

Browse files
committed
More accurate handling of unicode/numpad input in gtk3 backends.
See changelog.
1 parent 8e7c7ab commit 72f731f

File tree

4 files changed

+72
-62
lines changed

4 files changed

+72
-62
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
GTK key name changes
2+
~~~~~~~~~~~~~~~~~~~~
3+
4+
The handling of non-ascii keypresses (as reported in the KeyEvent passed to
5+
``key_press_event``-handlers) in the GTK backends now correctly reports unicode
6+
characters (e.g., €), and respects NumLock on the numpad.
7+
8+
The following key names have changed; the new names are consistent with those
9+
reported by the Qt backends:
10+
11+
- The "Break/Pause" key (keysym 0xff13) is now reported as "pause" instead of
12+
"break" (this is also consistent with the X key name).
13+
- The numpad "delete" key is now reported as "delete" instead of "dec".

lib/matplotlib/backends/backend_gtk3.py

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -88,58 +88,6 @@ def _on_timer(self):
8888
class FigureCanvasGTK3(Gtk.DrawingArea, FigureCanvasBase):
8989
required_interactive_framework = "gtk3"
9090
_timer_cls = TimerGTK3
91-
92-
keyvald = {65507: 'control',
93-
65505: 'shift',
94-
65513: 'alt',
95-
65508: 'control',
96-
65506: 'shift',
97-
65514: 'alt',
98-
65361: 'left',
99-
65362: 'up',
100-
65363: 'right',
101-
65364: 'down',
102-
65307: 'escape',
103-
65470: 'f1',
104-
65471: 'f2',
105-
65472: 'f3',
106-
65473: 'f4',
107-
65474: 'f5',
108-
65475: 'f6',
109-
65476: 'f7',
110-
65477: 'f8',
111-
65478: 'f9',
112-
65479: 'f10',
113-
65480: 'f11',
114-
65481: 'f12',
115-
65300: 'scroll_lock',
116-
65299: 'break',
117-
65288: 'backspace',
118-
65293: 'enter',
119-
65379: 'insert',
120-
65535: 'delete',
121-
65360: 'home',
122-
65367: 'end',
123-
65365: 'pageup',
124-
65366: 'pagedown',
125-
65438: '0',
126-
65436: '1',
127-
65433: '2',
128-
65435: '3',
129-
65430: '4',
130-
65437: '5',
131-
65432: '6',
132-
65429: '7',
133-
65431: '8',
134-
65434: '9',
135-
65451: '+',
136-
65453: '-',
137-
65450: '*',
138-
65455: '/',
139-
65439: 'dec',
140-
65421: 'enter',
141-
}
142-
14391
# Setting this as a static constant prevents
14492
# this resulting expression from leaking
14593
event_mask = (Gdk.EventMask.BUTTON_PRESS_MASK
@@ -257,13 +205,17 @@ def size_allocate(self, widget, allocation):
257205
self.draw_idle()
258206

259207
def _get_key(self, event):
260-
if event.keyval in self.keyvald:
261-
key = self.keyvald[event.keyval]
262-
elif event.keyval < 256:
263-
key = chr(event.keyval)
264-
else:
265-
key = None
266-
208+
key = chr(Gdk.keyval_to_unicode(event.keyval))
209+
if not key.isprintable():
210+
key = Gdk.keyval_name(event.keyval).lower()
211+
if key.startswith("kp_"): # keypad_x (including kp_enter).
212+
key = key[3:]
213+
if key.startswith("page_"): # page_{up,down}
214+
key = key.replace("page_", "page")
215+
if key.endswith(("_l", "_r")): # alt_l, ctrl_l, shift_l.
216+
key = key[:-2]
217+
if key == "enter":
218+
key = "return"
267219
modifiers = [
268220
(Gdk.ModifierType.MOD4_MASK, 'super'),
269221
(Gdk.ModifierType.MOD1_MASK, 'alt'),
@@ -272,7 +224,6 @@ def _get_key(self, event):
272224
for key_mask, prefix in modifiers:
273225
if event.state & key_mask:
274226
key = '{0}+{1}'.format(prefix, key)
275-
276227
return key
277228

278229
def configure_event(self, widget, event):
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from matplotlib import pyplot as plt
2+
3+
import pytest
4+
5+
6+
@pytest.mark.backend("gtk3agg")
7+
def test_correct_key():
8+
from gi.repository import Gdk, Gtk
9+
fig = plt.figure()
10+
buf = []
11+
12+
def send(event):
13+
for key, mod in [
14+
(Gdk.KEY_a, Gdk.ModifierType.SHIFT_MASK),
15+
(Gdk.KEY_a, 0),
16+
(Gdk.KEY_a, Gdk.ModifierType.CONTROL_MASK),
17+
(Gdk.KEY_agrave, 0),
18+
(Gdk.KEY_Control_L, Gdk.ModifierType.MOD1_MASK),
19+
(Gdk.KEY_Alt_L, Gdk.ModifierType.CONTROL_MASK),
20+
(Gdk.KEY_agrave,
21+
Gdk.ModifierType.CONTROL_MASK
22+
| Gdk.ModifierType.MOD1_MASK
23+
| Gdk.ModifierType.MOD4_MASK),
24+
(0xfd16, 0), # KEY_3270_Play.
25+
(Gdk.KEY_BackSpace, 0),
26+
(Gdk.KEY_BackSpace, Gdk.ModifierType.CONTROL_MASK),
27+
]:
28+
# This is not actually really the right API: it depends on the
29+
# actual keymap (e.g. on Azerty, shift+agrave -> 0).
30+
Gtk.test_widget_send_key(fig.canvas, key, mod)
31+
32+
def receive(event):
33+
buf.append(event.key)
34+
if buf == [
35+
"A", "a", "ctrl+a",
36+
"\N{LATIN SMALL LETTER A WITH GRAVE}",
37+
"alt+control", "ctrl+alt",
38+
"ctrl+alt+super+\N{LATIN SMALL LETTER A WITH GRAVE}",
39+
# (No entry for KEY_3270_Play.)
40+
"backspace", "ctrl+backspace",
41+
]:
42+
plt.close(fig)
43+
44+
fig.canvas.mpl_connect("draw_event", send)
45+
fig.canvas.mpl_connect("key_press_event", receive)
46+
plt.show()

lib/matplotlib/tests/test_backend_qt.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ def CustomHandler(signum, frame):
104104
('Key_Alt', ['ControlModifier'], 'ctrl+alt'),
105105
('Key_Aacute', ['ControlModifier', 'AltModifier', 'MetaModifier'],
106106
'ctrl+alt+super+\N{LATIN SMALL LETTER A WITH ACUTE}'),
107+
('Key_Play', [], None),
107108
('Key_Backspace', [], 'backspace'),
108109
('Key_Backspace', ['ControlModifier'], 'ctrl+backspace'),
109-
('Key_Play', [], None),
110110
],
111111
ids=[
112112
'shift',
@@ -117,9 +117,9 @@ def CustomHandler(signum, frame):
117117
'alt_control',
118118
'control_alt',
119119
'modifier_order',
120+
'non_unicode_key',
120121
'backspace',
121122
'backspace_mod',
122-
'non_unicode_key',
123123
]
124124
)
125125
@pytest.mark.parametrize('backend', [

0 commit comments

Comments
 (0)