Repository navigation
Expand file tree
/
Copy pathgesture_trigger_core.py
More file actions
245 lines (215 loc) · 13.1 KB
/
Copy pathgesture_trigger_core.py
File metadata and controls
245 lines (215 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
"""Logique métier pure du déclenchement des menus contextuels (zéro import Gtk/Gio).
Point 3 de l'audit session-29 (`docs/gtk4-migration.md` §3.6-ter), inventorié
en détail par la session-38 (§3.6-septies) : migration du déclenchement
`button-press-event`/`Gdk.EventButton` vers `Gtk.GestureMultiPress` (GTK3) /
`Gtk.GestureClick` (GTK4), commune aux trois familles de sites identifiées
(`on_tvServers_button_press_event`, `on_terminal_click` × 2, et
`NotebookTabLabel.popupmenu`). Contrairement aux menus eux-mêmes (un fichier
`_core.py` par menu : `tab_context_menu_core.py`, `folder_context_menu_core.py`,
`popup_menu_core.py`), ce chantier est transversal à plusieurs widgets — ce
module rassemble donc, site par site et session après session, la logique de
classification d'un clic (bouton + nombre de pressions) que chaque ancien
gestionnaire `button-press-event` encodait dans son `if`/`else`, pour rester
testable sans stub GTK conformément à `CONSIGNES-AGENTS-IA.md` section 5.
Portée de la session-39 : un seul site, `treeServers`/`popupMenuFolder`
(`Wmain.on_tvServers_pressed`, anciennement `on_tvServers_button_press_event`)
— retenu par la proposition d'ordre de la session-38 comme le plus simple des
trois (aucune branche dépendant d'un modificateur clavier). Les deux sites
restants (`on_terminal_click`, `NotebookTabLabel.popupmenu`) auront chacun
leur propre fonction de classification ajoutée ici lors de leur portage,
plutôt qu'un nouveau fichier par site — voir `docs/gtk4-migration.md`
§3.6-octies pour le détail du portage et une correction importante apportée
à l'audit session-38 (disponibilité réelle de `get_current_event()`/
`get_current_event_state()` en GTK3).
Portée de la session-40 : deuxième des trois sites, `on_terminal_click`
(2 points de connexion identiques, voir `docs/gtk4-migration.md`
§3.6-nonies) — retenu par la proposition d'ordre de la session-38 comme
deuxième (après `treeServers`, seule des trois sans branche dépendant d'un
modificateur clavier ; avant l'étiquette d'onglet, seule à alimenter aussi
le menu RDP/VNC/SPICE encore non porté). Contrairement à
`classify_tree_servers_press`, `classify_terminal_click` a besoin d'un
paramètre supplémentaire (`ctrl_pressed`) car l'ancien gestionnaire
distinguait un troisième cas (Ctrl+clic gauche, détection d'URL) non
présent sur `treeServers` — voir sa docstring pour le détail complet de la
correspondance avec l'ancien `if`/`elif`.
Portée de la session-41 : troisième et dernier des trois sites,
`NotebookTabLabel.popupmenu` (`widgets.py`) — voir `docs/gtk4-migration.md`
§3.6-decies. Comme `classify_tree_servers_press`, `classify_tab_label_click`
n'a besoin d'aucun paramètre de modificateur clavier (aucune branche Ctrl
sur ce site) ; comme `classify_terminal_click`, aucune issue `"swallow"`
(l'ancien code ne testait que `event.type == Gdk.EventType.BUTTON_PRESS`,
jamais `_2BUTTON_PRESS`/`_3BUTTON_PRESS`). Différence propre à ce site :
l'asymétrie de `Gtk.EventSequenceState.CLAIMED` entre les issues (l'ancien
code retournait `True` sur le clic droit et sur un clic milieu annulé par
confirmation, mais pas quand l'onglet était effectivement fermé) est une
décision de l'appelant, prise à l'exécution une fois `msgconfirm()` connu
— hors de portée d'une fonction pure, donc non représentée ici. Les trois
sites de l'audit session-38 (point 3) sont désormais tous portés.
"""
#: Issues possibles de la classification d'un clic sur treeServers, voir
#: :func:`classify_tree_servers_press`.
TREE_SERVERS_PRESS_OUTCOMES = ("open-menu", "swallow", "propagate")
def classify_tree_servers_press(*, button, n_press):
"""Classifie un clic sur treeServers selon le bouton et le nombre de pressions.
Reproduit à l'identique les deux branches de l'ancien gestionnaire
`button-press-event` (`Wmain.on_tvServers_button_press_event`, avant son
portage session-39 vers `Gtk.GestureMultiPress` — voir
`docs/gtk4-migration.md` §3.6-octies) :
- ``event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3``
(clic droit simple) devient ``button == 3 and n_press == 1``
→ ``"open-menu"`` : ouvrir popupMenuFolder.
- Sinon, ``event.type in (Gdk.EventType._2BUTTON_PRESS,
Gdk.EventType._3BUTTON_PRESS)`` (double/triple clic, tous boutons
confondus) devient ``n_press >= 2`` → ``"swallow"`` : avaler
l'évènement sans action (l'ancien code retournait ``True`` dans les
deux cas ci-dessus pour arrêter la propagation).
- Tout le reste (clic simple, bouton différent de 3 — typiquement le
clic gauche qui sélectionne une ligne) → ``"propagate"`` : ne rien
faire et laisser le traitement par défaut du widget suivre son cours
(l'ancien code retournait ``False``).
Note de conception : `Gtk.GestureMultiPress`/`Gtk.GestureClick` livrent
un signal `pressed` par pression physique (`n_press` incrémente à
chaque pression), alors que GDK délivrait pour un double-clic à la fois
un évènement `BUTTON_PRESS` et, juste après, un évènement de type
`_2BUTTON_PRESS` distinct pour la même pression physique. Les deux
mécanismes convergent malgré tout vers le même verdict pour chaque
pression prise isolément — voir `docs/gtk4-migration.md` §3.6-octies
pour la table de correspondance complète.
Args:
button (int): Numéro du bouton de la souris à l'origine du clic,
tel que renvoyé par `Gtk.GestureSingle.get_current_button()`
(1 = gauche, 2 = milieu, 3 = droit).
n_press (int): Nombre de pressions consécutives, tel que transmis
par le paramètre `n_press` du signal `pressed` de
`Gtk.GestureMultiPress`/`Gtk.GestureClick` (1 = clic simple,
2 = double clic, 3 = triple clic).
Returns:
str: Une valeur de :data:`TREE_SERVERS_PRESS_OUTCOMES` — voir
ci-dessus pour la signification de chacune.
"""
if button == 3 and n_press == 1:
return "open-menu"
if n_press >= 2:
return "swallow"
return "propagate"
#: Issues possibles de la classification d'un clic sur un terminal VTE, voir
#: :func:`classify_terminal_click`.
TERMINAL_CLICK_OUTCOMES = ("paste", "open-menu", "check-url", "propagate")
def classify_terminal_click(*, button, n_press, ctrl_pressed, paste_on_right_click):
"""Classifie un clic sur un terminal VTE selon le bouton, les pressions et Ctrl.
Reproduit à l'identique les deux branches `if`/`elif` de l'ancien
gestionnaire `button-press-event` (`Wmain.on_terminal_click`, avant son
portage session-40 vers `Gtk.GestureMultiPress` — voir
`docs/gtk4-migration.md` §3.6-nonies) :
- ``event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3``
(clic droit simple) devient ``button == 3 and n_press == 1`` →
``"paste"`` si `PASTE_ON_RIGHT_CLICK` est actif, sinon ``"open-menu"``
(ouvrir popupMenu). L'ancien code retournait ``True`` dans les deux
cas pour empêcher le code de mise au focus, en bas de la fonction, de
s'exécuter.
- Sinon, ``event.type == Gdk.EventType.BUTTON_PRESS and event.button
== 1 and event.get_state() & Gdk.ModifierType.CONTROL_MASK`` (Ctrl+clic
gauche simple) devient ``button == 1 and n_press == 1 and
ctrl_pressed`` → ``"check-url"`` : détecter et ouvrir un lien sous le
curseur. Contrairement au cas précédent, l'ancien code ne retournait
rien ici (`None`, implicitement falsy) — le code de mise au focus
s'exécutait donc quand même après.
- Tout le reste (clic simple sans Ctrl, double/triple clic quel que
soit le bouton — laissé à la sélection native de VTE, mot/ligne au
double/triple-clic) → ``"propagate"`` : même traitement que
``"check-url"`` du point de vue de la mise au focus (elle s'exécute
toujours), mais aucune action supplémentaire.
Note de conception : à la différence de
:func:`classify_tree_servers_press`, aucune issue n'« avale »
(`swallow`) un double/triple-clic ici — l'ancien code ne testait que
`event.type == Gdk.EventType.BUTTON_PRESS`, jamais `_2BUTTON_PRESS`/
`_3BUTTON_PRESS`, laissant VTE traiter nativement ces pressions
(sélection d'un mot puis d'une ligne). Un `"swallow"` sur ce site
casserait donc cette sélection native — voir `docs/gtk4-migration.md`
§3.6-nonies pour la mise en garde complète.
Args:
button (int): Numéro du bouton de la souris à l'origine du clic,
tel que renvoyé par `Gtk.GestureSingle.get_current_button()`
(1 = gauche, 2 = milieu, 3 = droit).
n_press (int): Nombre de pressions consécutives, tel que transmis
par le paramètre `n_press` du signal `pressed` de
`Gtk.GestureMultiPress`/`Gtk.GestureClick` (1 = clic simple,
2 = double clic, 3 = triple clic).
ctrl_pressed (bool): `True` si le modificateur Ctrl était actif au
moment du clic — anciennement lu directement sur
`event.get_state()`, désormais sur l'évènement renvoyé par
`Gtk.Gesture.get_last_event(None)` (voir la mise en garde
§3.6-octies : ni `get_current_event()` ni
`get_current_event_state()` n'existent en GTK3).
paste_on_right_click (bool): Valeur de la préférence
`conf.PASTE_ON_RIGHT_CLICK` au moment du clic, passée
explicitement plutôt que lue sur un global
(`CONSIGNES-AGENTS-IA.md` section 2).
Returns:
str: Une valeur de :data:`TERMINAL_CLICK_OUTCOMES` — voir ci-dessus
pour la signification de chacune.
"""
if button == 3 and n_press == 1:
return "paste" if paste_on_right_click else "open-menu"
if button == 1 and n_press == 1 and ctrl_pressed:
return "check-url"
return "propagate"
#: Issues possibles de la classification d'un clic sur l'étiquette d'un
#: onglet, voir :func:`classify_tab_label_click`.
TAB_LABEL_CLICK_OUTCOMES = ("open-menu", "close-tab", "propagate")
def classify_tab_label_click(*, button, n_press):
"""Classifie un clic sur l'étiquette d'un onglet selon le bouton et le nombre de pressions.
Reproduit à l'identique les deux branches `if`/`elif` de l'ancien
gestionnaire `button-press-event` (`widgets.NotebookTabLabel.popupmenu`,
avant son portage session-41 vers `Gtk.GestureMultiPress` — voir
`docs/gtk4-migration.md` §3.6-decies) :
- `event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3`
(clic droit simple) devient `button == 3 and n_press == 1` →
`"open-menu"` : ouvrir le menu contextuel de l'onglet — celui du
bureau distant (`Gtk.Menu` legacy de
`build_remote_desktop_context_menu()`) si l'onglet en est un,
sinon `TabContextMenu`. Ce choix entre les deux menus reste une
décision de l'appelant (`NotebookTabLabel._get_remote_desktop_widget()`
lit un état d'instance hors de portée d'une fonction pure) —
`classify_tab_label_click()` ne distingue que le déclenchement, pas
la destination.
- `event.type == Gdk.EventType.BUTTON_PRESS and event.button == 2`
(clic milieu simple) devient `button == 2 and n_press == 1` →
`"close-tab"` : fermer l'onglet, après confirmation éventuelle
(`conf.CONFIRM_ON_CLOSE_TAB_MIDDLE`) — également une décision de
l'appelant, hors de portée ici.
- Tout le reste (clic gauche, bouton > 3, double/triple-clic quel que
soit le bouton) → `"propagate"` : ne rien faire. Même mapping que
`classify_terminal_click()` pour les pressions multiples : l'ancien
code ne testait que `event.type == Gdk.EventType.BUTTON_PRESS`,
jamais `_2BUTTON_PRESS`/`_3BUTTON_PRESS` — aucune branche dédiée au
multi-clic à reproduire ici, contrairement à
`classify_tree_servers_press()`.
Note de conception — asymétrie de `Gtk.EventSequenceState.CLAIMED`
(gérée côté appelant, pas ici) : l'ancien code retournait `True`
(stop de propagation) sur le clic droit et sur un clic milieu annulé
par confirmation, mais **pas** quand l'onglet était effectivement
fermé (chute en fin de fonction, après `self.close_tab(...)`, sans
`return`). Cette asymétrie ne peut pas être repliée dans cette
fonction pure : elle dépend du résultat de `msgconfirm()`, connu
seulement à l'exécution — voir `NotebookTabLabel.on_label_pressed`
pour sa reproduction fidèle.
Args:
button (int): Numéro du bouton de la souris à l'origine du clic,
tel que renvoyé par `Gtk.GestureSingle.get_current_button()`
(1 = gauche, 2 = milieu, 3 = droit).
n_press (int): Nombre de pressions consécutives, tel que transmis
par le paramètre `n_press` du signal `pressed` de
`Gtk.GestureMultiPress`/`Gtk.GestureClick` (1 = clic simple,
2 = double clic, 3 = triple clic).
Returns:
str: Une valeur de :data:`TAB_LABEL_CLICK_OUTCOMES` — voir
ci-dessus pour la signification de chacune.
"""
if button == 3 and n_press == 1:
return "open-menu"
if button == 2 and n_press == 1:
return "close-tab"
return "propagate"