Gestion d'événements
Rédigé: Le 6 août 1997
Rédaction: Jean Vaucher
Traduction: Jocelyn Houle
Version courante: 1.1 (mod. 5 oct. 97)
Introduction
Dans WindowTools, il y a deux sortes d'événements:
- Les événements expédié par XWindow (les XEvents)
- Les événements logiciels envoyés par les
widgets de WindowTools à leur fenêtres
parentes.
Les événements XEvents contiennent:
- EnterNotify, LeaveNotify: quand la souris entre ou
sort d'une fenêtre
- KeyPress, KeyRelease: lorsque l'on appuie ou
relâche une touche
- ButtonPress, ButtonRelease: les cliques de souris
- MotionNotify: quand la souris se déplace
- Exposed: lorsqu'une fenêtre est affichée
Dans WindowTools, nous en avons dérivé des
événements:
- Click: résultat de 2 événements (KeyPress
et KeyRelease) séparés d'un court intervalle
- Alarm: des minuteries générées par UNIX
- ButtonPress: Lorsque l'on appuie sur les
Buttons, etc.
- Refresh: Quand une fenêtre a besoin de redessiner pour
une raison quelconque
La version d'Oslo disposait de plusieurs procédures virtuelles,
lesquelles pouvaient être redéfinies par le programmeur pour
modeler ses désirs. Elles comprenaient:
- Perform & PerformIn
- ClickInButton
- LineChoice & LineChoiceIn
- ClickInRadioPanel
- ButtonChoice
Malgré leur grande utilité dans les cas particuliers, le manque
de [systématisme] les rendait peu compatibles entre elles.
Dans le nouveau WindowTools de Montréal, nous avons
fourni ce que nous croyons être un ensemble plus systématique des
événements qui permet l'usage de capteurs
d'événements (event handlers) ainsi que des routines
d'attente d'un ou de plusieurs types d'événements.
Classes d'événement de WindowTools
Il y a maintenant 7 classes d'événements qu'une fenêtre peut
recevoir; certaines s'appliquent à la fenêtre elle-même,
à ses sous-fenêtres ou aux deux.
- AlarmEvt: |
une minuterie dans une fenêtre |
- ButtonEvt: |
on a appuyé sur un bouton |
- ClickEvt: |
un clique (à l'extérieur d'un bouton) |
- DoubleClickEvt: |
un double-clique quelque-part |
- SelectionEvt: |
lorsque l'on sélectionne dans une sous-fenêtre
(AllowChoice) |
- TypingEvt: |
on a entré du texte dans un champ |
- WakeEvt: |
activation directe d'une fenêtre à l'aide de
W.WakeUp |
Traitement d'événements
La programmation où l'on doit traiter les événements, vous
devez spécifier des capteurs d'événements
(event_handlers). Ces procédures sont automatiquement
appelées lorsque un événement de ce type s'exécute.
Vous pouvez également décider d'attendre pour UN type
d'événement ou le PREMIER parmi PLUSIEURS de ce type. Pour bien
décrire ces approches, nous allons voir comment coder l'attente d'un
bouton par trois approches différentes.
1) Capteurs d'événements
Les capteurs d'événements sont des routines d'interruption
(des procédures ayant un nom et des paramètres précis) que
vous DÉCLAREZ dons votre déclaration de fenêtre. Ils seront
appelés par le systèmes lors De l'exécution. Vous
ÉNONCEZ cette déclaration; vous ne l'APPELEZ pas! Par exemple,
pour saisir le clique d'un bouton, votre classe doit avoir une
déclaration de Handle_ButtonClick. Vous pourriez faire:
FirstWindow class MyWindow;
begin
ref(button) QUIT,YB,NB;
boolean fini;
procedure Handle_ButtonClick(B); ref(button) B;
if B == quit then fini := true;
YB :- MakeButton("OUI");
NB :- MakeButton("NON");
QUIT :- MakeButton("EXIT");
while not Fini do handle_event;
end;
Notez que nous n'avons jamais appelé
handle_buttonClick... Nous l'avons seulement
déclaré, et il a été appelé tout seul.
2) L'attente explicite
Lorsque l'on attend pour un seul type d'événement, il est plus
facile de tout simplement APPELER une procédure Wait. On
coderait ainsi:
FirstWindow class MyWindow;
begin
ref(button) QUIT,YB,NB, B;
YB :- MakeButton("OUI");
NB :- MakeButton("NON");
QUIT :- MakeButton("EXIT");
waitForButtonClick(B);
while B =/= QUIT do begin
.......
waitForButtonClick(B);
end;
end;
3) L'attente de plusieurs événements
Pour attendre plusieurs événements simultanément, il faut
utiliser la procédure WaitFor avec le
Event_Mask composé de l'addition des constantes
(AlarmEvt, ButtonEvt, etc.). Dans l'exemple qui suit, nous
sortons de l'attente dès qu'un bouton est appuyé ou si 30 secondes
se sont écoulées:
FirstWindow class MyWindow;
begin
ref(button) QUIT,YB,NB, B;
YB :- MakeButton("OUI");
NB :- MakeButton("NON");
QUIT :- MakeButton("EXIT");
SetAlarm(30);
WaitFor( AlarmEvt + ButtonEvt );
if TimeOut then outLine("We timed out....");
if ButtonClicked(B) then OutLine("Button Clicked");
end;
Activation Directe: Wait & WakeUp
Une fenêtre en attente W peut toujours être
éveillée en appelant W.WakeUp, peu importe ce qu'elle
attendait. Ceci est également utile pour permettre à un capteur
d'événements (Event_Handler) d'interagir avec une
procédure d'attente (Wait).
Liste des procédures
Ainsi, chaque classe d'événement peut impliquer jusqu'à 3
procédures: une capteur d'événements (à
déclarer), une procédure d'attente (à appeler) et une
fonction booléenne pour vérifier le type de
l'événement.
TYPE |
CAPTEUR (déclaration) |
PROC. D'ATTENTE (appel de
proc.) |
VERIFICATION (appel de
fonction) |
AlarmEvt |
Handle_Alarm |
WaitForAlarm |
TimeOut |
ClickEvt |
Handle_Click |
WaitForClick |
Clicked |
DoubleClickEvt |
Handle_DoubleClick |
WaitForDoubleClick |
DoubleClicked |
ButtonEvt |
Handle_ButtonClick |
WaitForButtonClick |
ButtonClicked |
SelectionEvt |
Handle_Selection |
WaitForSelection |
SelectionIn |
TypingEvt |
Handle_Typing |
WaitForTyping |
TypingIn |
WakeEvt |
|
Wait |
Woken |
Note: |
Pour tous les types d'événement, le traitement doit se
faire SOIT par un capteur d'événement, SOIT par la méthode
explicite de l'attente. Si un capteur d'événement est
présent, il sera prioritaire à l'attente explicite. |
Passons maintenant aux détails... À chaque type, nous donnerons
le prototype de la déclaration du capteur d'événement:
AlarmEvt
 |
- procedure Handle_Alarm;
- Aucun paramètre.
|
 |
- procedure WaitForAlarm;
- On attend un TimeOut.
|
 |
- boolean procedure TimeOut;
- Retourne TRUE si le dernier événement est un
TimeOut.
|
ButtonEvt
 |
- procedure Handle_ButtonClick(B); ref(Button) B;
- Est appelé lorsqu'un bouton est pressé.
|
 |
- procedure WaitForButtonClick(B); ref(Button) B;
- On attend qu'un bouton soit appuyé.
|
 |
- boolean procedure ButtonClicked(B); ref(Button) B;
- Retourne TRUE si un bouton a été appuyé
et B pointera vers ce bouton.
|
Compatibilité: Les procédures suivantes, présentes
dans les versions d'Oslo, devraient encore fonctionner:
ClickInButton(B);
ButtonChoice
ClickEvt
Il s'agit de clicks dans la fenêtre courante et NON dans une
sous-fenêtre ni un bouton. Nous obtiendrons les coordonnées
X et Y du click.
 |
- procedure Handle_Click(X, Y); integer X, Y;
- Est appelé lorsqu'on appuie sur un bouton de la souris.
|
 |
- procedure WaitForClick(X, Y); integer X, Y;
- On attend que la souris soit appuyée; les coordonnées
(x, y) du click seront retournées.
|
 |
- boolean procedure Clicked(X, Y); integer X, Y;
- Retourne TRUE si un a appuyé sur la souris, et X et
Y corresponderont aux corrdonnées (x, y) du click.
|
DoubleClickEvt
Il s'agit de double-clicks dans la fenêtre courante ou dans une
sous-fenêtre. Nous obtiendrons les coordonnées X et
Y du click.
 |
- procedure Handle_DoubleClick(W); ref(XWindow) W;
- Est appelé lorsqu'on double-clique dans une fenêtre ou
une sous-fenêtre.
|
 |
- procedure WaitForDoubleClick(W); ref(XWindow) W;
- On attend un double-clique; W pointera vers la fenêtre
dans laquelle on a double-cliqué.
|
 |
- boolean procedure DoubleClicked(W); ref(XWindow) W;
- Retourne TRUE si on a appuyé sur la souris, et on
changera le paramètre W pour qu'il pointe vers la fenêtre
où ça s'est produit.
|
SelectionEvt
Ces événements sont utiles dans les sous-fenêtres de texte et les menus de différentes sortes.
Ils retournent 3 éléments d'information: la fenêtre
où ça s'est produit, le texte correspondant à la ligne
sélectionnée, ainsi que le numéro de la ligne.
 |
- procedure Handle_Selection(W, Item, ItemN); ref(XWindow) W;
text Item; integer ItemN;
- Est appelé lorsqu'on double-clique dans une fenêtre ou
une sous-fenêtre.
W pointera vers la fenêtre oz s'est produit le
changement
Item contiendra le texte correspondant à la
sélection effectuée
ItemN correspondera au numéro de ligne de la
sélection
|
 |
- procedure WaitForSelection(W, Item, ItemN); ref(XWindow) W;
text Item; integer ItemN;
- On attend une sélection, puis les paramètres prennent
les valeurs appropriées.
|
 |
- boolean procedure SelectionIn(W, Item, ItemN); ref(XWindow)
W; text Item; integer ItemN;
- Vérifie si l'événement est une sélection,
puis retourne les valeurs appropriées.
|
TypingEvt
Cet événement indique à la fenêtre parente qu'une
ItemWindow a été modifiée. La
fenêtre parente peut alors faire une vérification
ultérieure.
 |
- procedure Handle_Typing(W); ref(XWindow) W;
- Est appelé lorsqu'il y a une insertion effectuée dans
une fenêtre ou ses sous-fenêtres.
|
 |
- procedure WaitForTyping(W); ref(XWindow) W;
- On attend une insertion dans une ItemWindow, puis on
fait pointer W vers cette fenêtre.
|
 |
- boolean procedure TypingIn(W); ref(XWindow) W;
- Vérifie s'il y a modification dans une
ItemWindow et retourne la fenêtre appropriée.
|
WakeEvt
N'importe quel Wait peut être interrompu à l'aide de la
procédure WakeUp soit directement (par un capteur du type
approprié), soit par un autre objet (par notation pointée:
W.WakeUp). Les procédures associées sont:
 |
- procedure Wait;
- Attend un événement WakeUp (d'un capteur
d'événement).
|
 |
- boolean procedure Woken;
- Retourne TRUE si on a reçu un événement
WakeUp.
|
Délégation d'événements
Si une fenêtre ne fait rien avec les événements qu'elle
reçoit, elle peut les déléguer à sa fenêtre
parente. Voici les délégations par défaut des
différents événements par défaut de
WindowTools.
ButtonEvt: |
Envoyé au parent |
DoubleClickEvt: |
Envoyé au parent |
ClickEvt: |
Envoyé au parent |
AlarmEvt: |
PAS envoyé au parent |
SelectionEvt: |
PAS envoyé au parent |
TypingEvt: |
PAS envoyé au parent |
WakeUpEvt: |
PAS envoyé au parent |
XEvents
Les systèmes de gestion d'événements de X-Windows (ou
encore X11) génère quelques 30 sortes distinctes
d'événements en réaction aux actions de l'usager sur un
terminal ainsi qu'aux interactions entre les fenêtres des applications.
WindowTools et les widgets en faisant partie se charge de la
plupart d'eux de façon automatique. Toutefois, il peut arriver qu'un
programmeur ait besoin d'intercepter ces événements. Les
événements X ne sont cependant générés que
pour les fenêtres en faisant la demande. WindowTools
possède donc une série de procédures permettant de filtrer
les événements qu'on veut qu'une fenêtre reçoive ou
non (e.g. key_sensitize & key_desensitize).
Voici une liste d'événements X et des procédures de
WindowTools appelées en ces occasions.
Événements du clavier
KeyPress |
- Handle_Key_Down(C) |
|
- Handle_Special_Key_Down(Code) |
|
|
- Handle_Left_Arrow
|
|
|
- Handle_Right_Arrow
|
|
|
- Handle_Up_Arrow
|
|
|
- Handle_Down_Arrow
|
Cet événement se produit lorsqu'une touche du clavier est
appuyée. S'il s'agit d'un caractère ASCII, alors
handle_key_down sera appelé, sinon
handle_special_key_down sera appelé, lequel appelle par
défaut les procédures de traitement des flèche.
KeyRelease |
- Handle_Key_Up(C) |
|
- Handle_Special_Key_Up(Code) |
[Masquage: Key_Sensitize & Key_Desensitize]
Événements de la souris
ButtonPress |
- Handle_Button_Down ( button_number ) |
ButtonRelease |
- Handle_Special_Key_Up ( button_number ) |
Les boutons, ici, correspondent aux entités physiques de la souris, et
non les boutons de WindowTools. Si on appuie, puis
relâche un bouton de la souris à moins de 400 ms et 10 pixels
d'intervalle, il y a génération d'un autre événement
également: un Click. Et si un second suit rapidement, un
DoubleClick sera généré.
Click |
- Handle_Click(X, Y) |
|
- Handle_DoubleClick(X, Y) |
[Masquage: Button_Sensitize & Button_Desensitize]
MotionNotify |
- Handle_Pointer_Motion(X, Y) |
Est appelé régulièrement lorsque le pointeur se
déplace, et si la fenêtre est sensible au déplacement du
pointeur.
[Masquage: Pointer_Motion_Sensitize &
Pointer_Motion_Desensitize]
EnterNotify |
- Handle_Enter_Window |
LeaveNotify |
- Handle_Leave_Window |
Appelé lorsque le pointeur entre ou sort d'une fenêtre.
[Masquage: Enter_And_Leave_Sensitize &
Enter_And_Leave_Desensitize]
Visibilité de la fenêtre
MapNotify |
Appelé par X lorsqu'il a affiché une fenêtre
à l'écran |
UnmapNotify |
Appelé par X lorsqu'il a effacé une fenêtre de
l'écran |
Ces événements sont généré lors des appels
Show et Hide. Dans WindowTools, ces
événements mettent à jour des flags
(Mapped) et les appels Show et Hide attendent que le
résultat de leur action se répercutent à l'écran
avant de retourner le contrôle au programme.
ConfigureNotify |
- GetActualGeometry |
|
- ReplaceSubWindows |
Un événement ConfigureEvent est
généré lorsque fait un Resize à une
fenêtre. Habituellement, le programmeur ne désire pas le savoir,
mais dans ce cas, un événement Expose est
généré (voir ci-bas).
Cet événement indique que la fenêtre devrait être
redessinée en partie au au complet, pour une raison ou une autre. La
plupart du temps, c'est qu'une fenêtre est déplacée par
dessus une autre... Par défaut, X remplit la fenêtre avec la
couleur de fond (background). Pour les widgets de
WindowTools, un rafraîssement automatique est
effectué, mais les éléments graphiques des fenêtres
de l'usager devront être redessinés.
Minuterie & AlarmNotify
X n'a rien à ce sujet, mais WindowTools gère une
liste d'alertes et utilise des primitives UNIX pour générer des
ALARMS intégrées dans la structure de message-clients de
X.
[Retour à l'index de WindowTools...]