3.4.1 ΕΚΚΙΝΗΣΗ ΚΑΙ ΧΕΙΡΙΣΜΟΣ ΤΩΝ ΓΕΓΟΝΟΤΩΝ


Μέχρι στιγμής έχουμε αναφερθεί στο πως μπορούμε να δημιουργήσουμε με τη χρήση της Xlib παράθυρα, σχήματα, κείμενο και χρώματα. Στην παράγραφο αυτή θα αναφερθούμε στο τρόπο επικοινωνίας του προγράμματός μας με το περιβάλλον του. Η επικοινωνία αυτή γίνεται μέσω του εξυπηρετητή (server) των Χ Windows με τον μηχανισμό των γενονότων (events). Όπως αναφέρθηκε και στην εισαγωγή το μοντέλο των γεγονότων (event-model) λειτουργεί ως εξής, ο εξυπηρετητής των Χ Windows έχει υπό τον έλεγχο του τις μονάδες εισόδου - εξόδου του συστήματος (ποντίκι, πληκτρολόγιο, οθόνη), όταν συμβαίνει ένα γεγονός (κίνηση του ποντικιού, πάτημα ενός πλήκτρου, εμφάνιση ενός παραθύρου) ο εξυπηρετητής στέλνει ένα αντίστοιχο μήνυμα στα προγράμματα που το χρειάζονται.

Τα προγράμματα αυτά με την σειρά τους το λαμβάνουν, το επεξεργάζονται και αντιδρούν αναλόγως. Με τον τρόπο αυτό τόσο ο εξυπηρετητής όσο και τα προγράμματα - πελάτες του βρίσκονται σε συνεχώς είτε σε κατάσταση αναμονής μηνυμάτων, είτε σε κατάσταση αντίδρασης σε αυτά. Προγραμματιστικά το μοντέλο αυτό υλοποιείται με ένα βρόχο αναμονής μηνυμάτων, ο οποίος σε περίπτωση λήψης μηνύματος μεταβιβάζει τον έλεγχο στο τμήμα εκείνο του προγράμματος που εξυπηρετεί το συγκεκριμένο μήνυμα. Στο τέλος της εξυπηρέτησης ο έλεγχος επιστρέφει στο βρόχο αναμονής για το επόμενο μήνυμα.

Τα γεγονότα που συμβαίνουν κατά την λειτουργία των Χ Windows είναι πολλά και ποικίλα. To κάθε πρόγραμμα πρέπει να ορίζει, κατά την εκκίνησή του , για ποιά γεγονότα θέλει να ενημερώνεται από τον εξυπηρετητή των Χ Windows. Για το σκοπό αυτό υπάρχει η συνάρτηση XSelectInput:

    XSelectInput(
        Display*  /* display */,
        Window    /* window */,
        long      /* event_mask */
    );
Η XSelectInput παίρνει τρία ορίσματα, το display, το παράθυρο του προγράμματος και μια μάσκα που ορίζει για το τι τύπου γεγονότα να ενημερώνεται το πρόγραμμα. Η τιμή της μάσκας σχηματίζεται με τον γνωστό τρόπο με βάση προκαθορισμένες σταθερές που ορίζονται στο αρχείο Χ.h. Για παράδειγμα με την επόμενη εντολή ορίζουμε πως το παράθυρο window θα ειδοποιείται όταν πατηθεί κάποιο κουμπί του ποντικιού (ButtonPressMask), κάποιο πλήκτρο του πληκτρολογίου (KeyPressMask) ή όταν εμφανιστεί το παράθυρο:

    XSelectInput( display, newwindow,
        ButtonPressMask | KeyPressMask | ExposureMask );
Από τη στιγμή που ορίζουμε τι μηνύματα θέλουμε να έρχονται στο πρόγραμμά μας και εμφανίσουμε (map) το παράθυρο που θα τα λαμβάνει είμαστε έτοιμοι να τα δεχθούμε. Η λήψη των γεγονότων - μηνυμάτων γίνεται με τη συνάρτηση XNextEvent:

    XNextEvent(
        Display*  /* display */,
        XEvent*   /* event_return */
    );
Η XNextEvent μπλοκάρει το πρόγραμμά μας περιμένοντας να λάβει κάποιο γεγονός. Όταν αυτό φθάσει μεταφέρει τις πληροφορίες του σε μια ένωση (union) XEvent (το δεύτερο όρισμα). Η ένωση XEvent, η οποία ορίζεται στο αρχείο Xlib, έχει περισσότερα από τριάντα πεδία στα οποία περιέχει όλες τις αναγκαίες πληροφορίες για τον τύπο του γεγονότους και τον τρόπο που προκλήθηκε. Σημαντικότερο πεδίο είναι το πρώτο (XEvent.type) που προσδιορίζει τον τύπο του γεγονότους (πάτημα πλήκτρου, κουμπιού του ποντικιού κτλ.). Το κάθε ένα από τα υπόλοιπα πεδία αφορά ένα συγκεκριμένο τύπο γεγονότους. Σε κάθε περίπτωση η ένωση XEvent περιέχει το πρώτο πεδίο με τον τύπο του γεγονότους και ένα μόνο δεύτερο πεδίο αυτό που αντιστοιχεί στο γεγονός. Η τιμή του πρώτου πεδίου είναι μια από τις προκαθορισμένες σταθερές, ονόματα των γεγονότων, που ορίζονται στο αρχείο Χ.h. Με βάση την τιμή αυτή το πρόγραμμα ενεργεί αναλόγως, όπως στο παράδειγμα που ακολουθεί σαν συνέχεια της παραπάνω εντολής XSelectInput:

    XEvent  xevent;
    int     done = 0;
    .
    .
    .
    while( !done )
    {
        XNextEvent( display, &xevent );
        switch( xevent.type )
        {
            case ButtonPress:
                done = buttonpressed( &xevent );
                break;
            case KeyPress:
                done = keypressed( &xevent );
                break;
            case Expose:
                redrawwindow();
                break;
        }
    }
    .
    .
    .
Στο παραπάνω απόσπασμα η XNextEvent περιμένει για το γεγονός. Όταν αυτό έρθει μεταφέρονται τα στοιχεία του στην xevent και ο έλεγχος μεταβαίνει στην εντολή switch. Εκεί αναλόγως με το είδος του γεγονότους (ButtonPress, KeyPress ή Expose) εκτελείται η αντίστοιχη συνάρτηση του προγράμματος. Στις συναρτήσεις αυτές περνάμε σαν όρισμα την xevent για να είναι δυνατή η περαιτέρω διερεύνηση του γεγονότους. Η διαδικασία αυτή συνεχίζεται συνεχώς μέσα στο while ώσπου να γίνει η done διάφορη του μηδενός.


[prev] [up] [next] [contents] [index]