Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1d0fcb5

Browse filesBrowse files
committed
More accurate handling of unicode/numpad input in gtk3 backends.
See changelog.
1 parent 0bdc2ab commit 1d0fcb5
Copy full SHA for 1d0fcb5

File tree

Expand file treeCollapse file tree

4 files changed

+77
-62
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+77
-62
lines changed
+13Lines 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

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_gtk3.py
+11-60Lines 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
@@ -259,13 +207,17 @@ def size_allocate(self, widget, allocation):
259207
self.draw_idle()
260208

261209
def _get_key(self, event):
262-
if event.keyval in self.keyvald:
263-
key = self.keyvald[event.keyval]
264-
elif event.keyval < 256:
265-
key = chr(event.keyval)
266-
else:
267-
key = None
268-
210+
key = chr(Gdk.keyval_to_unicode(event.keyval))
211+
if not key.isprintable():
212+
key = Gdk.keyval_name(event.keyval).lower()
213+
if key.startswith("kp_"): # keypad_x (including kp_enter).
214+
key = key[3:]
215+
if key.startswith("page_"): # page_{up,down}
216+
key = key.replace("page_", "page")
217+
if key.endswith(("_l", "_r")): # alt_l, ctrl_l, shift_l.
218+
key = key[:-2]
219+
if key == "enter":
220+
key = "return"
269221
modifiers = [
270222
(Gdk.ModifierType.MOD4_MASK, 'super'),
271223
(Gdk.ModifierType.MOD1_MASK, 'alt'),
@@ -274,7 +226,6 @@ def _get_key(self, event):
274226
for key_mask, prefix in modifiers:
275227
if event.state & key_mask:
276228
key = '{0}+{1}'.format(prefix, key)
277-
278229
return key
279230

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

‎lib/matplotlib/tests/test_backend_qt.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_backend_qt.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ def CustomHandler(signum, frame):
110110
('Key_Alt', ['ControlModifier'], 'ctrl+alt'),
111111
('Key_Aacute', ['ControlModifier', 'AltModifier', 'MetaModifier'],
112112
'ctrl+alt+super+\N{LATIN SMALL LETTER A WITH ACUTE}'),
113+
('Key_Play', [], None),
113114
('Key_Backspace', [], 'backspace'),
114115
('Key_Backspace', ['ControlModifier'], 'ctrl+backspace'),
115-
('Key_Play', [], None),
116116
],
117117
ids=[
118118
'shift',
@@ -123,9 +123,9 @@ def CustomHandler(signum, frame):
123123
'alt_control',
124124
'control_alt',
125125
'modifier_order',
126+
'non_unicode_key',
126127
'backspace',
127128
'backspace_mod',
128-
'non_unicode_key',
129129
]
130130
)
131131
@pytest.mark.parametrize('backend', [

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.