Kiosk Application Template #2

This is the second template of the kiosk application template series.

In a typical kiosk application, besides limiting the time each person can spend on a terminal (in the previous example, it's 30 minutes), we also want to automatically exit the main application and return to the login prompt after a certain time of inactivity. Such situation occurs when a person forgets to logout, or he/she simply walks away from the terminal after playing it for a while.

So we extend the codes in kiosk template #1 to include the following new features:

  • If there are 10 minutes of inactivity, the application will auto-logout.
  • Inactivity is indicated by no keyboard or mouse movement.

Note

  • For this sample application, use the following for the login:
    username='user1'
    password='phpgtk2'
  • For keyboard, I used the signal 'key-press-event'.
  • For mouse click, I used the signal 'button-press-event'.
  • For mouse motion (without any click), I used the signal 'motion-notify-event'.
  • It seems that GtkDialog by itself doesn't respond to the 'button-press-event' and 'motion-notify-event' signals. As such, you notice that I stuff an eventbox inside the GtkDialog so that we can receive these two events.

The Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
17   
19   
20   
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   
51   
53   
54   
55   
56   
57   
59   
60   
61   
62   
63   
64   
65   
67   
68   
69   
70   
71   
72   
73   
75   
76   
77   
78   
79   
82   
83   
84   
85   
86   
87   
88   
90   
91   
92   
93   
95   
96   
97   
98   
99   
100   
101   
102   
104   
105   
106   
107   
108   
109   
111   
112   
113   
114   
115   
116   
118   
119   
120   
121   
122   
123   
124   
125   
126   
127   
128   
132   
133   
134   
135   
136   
137   
138   
139   
140   
142   
143   
145   
146   
147   
148   
149   
150   
151   
152   
153   
154   
155   
156   
158   
159   
160   
161   
162   
163   
164   
165   
166   
167   
168   
172   
173   
174   
175   
176   
178   
179   
180   
181   
182   
184   
185   
186   
187   
188   
189   
190   
191   
192   
193   
194   
195   
196   
197   
198   
199   
200   
201   
202   
203   
204   
205   
207   
208   
209   
210   
211   
212   
213   
216   
217   
218   
219   
220   
221   
222   
223   
224   
225   
227   
228   
230   
232   
233   
234   
235   
237   
238   
239   
240   
241   
<?php

define('MAX_USAGE', 30);  // max usage time = 30 min
define('INACTIVITY', 10); // auto logout after 10 min of inactivity

while(1) {
    $login_success = 0;
    while(!$login_success) {
        login();
    }

    // starts the main program only if login successful
    main();
}

// this is your main application
function main() {
    $dialog = new GtkDialog();
    $dialog->fullscreen();
    $eventbox = new GtkEventBox(); // note 1
    $dialog->vbox->pack_start($eventbox); // note 1
    $vbox = new GtkVBox();
    $eventbox->add($vbox);
    $vbox->pack_start(new GtkLabel());

    // display title
    $title = new GtkLabel("This is the main program");
    $title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
    $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
    $title->set_size_request(-1, 40);
    $vbox->pack_start($title, 0);

    $vbox->pack_start(new GtkLabel("User verified"), 0);
    $vbox->pack_start(new GtkLabel("Main application starts..."), 0);
    $vbox->pack_start(new GtkLabel(
        "Note: application will auto-logout after 30 min of usage"), 0);
    $vbox->pack_start(new GtkLabel(
        "or after 10 min of inactivity (i.e. no mouse or keyboard movement)"), 0);
    $vbox->pack_start(new GtkLabel());

    // sets up a logout button
    $vbox->pack_start($hbox = new GtkHBox(), 0);
    $hbox->pack_start(new GtkLabel());
    $button = new GtkButton('Logout');
    $hbox->pack_start($button, 0);
    $button->connect('clicked', 'on_logout_button', $dialog);

    // auto-logout after 30 minutes of usage
    global $start_time, $timeout_maxtime;
    $start_time = time();
    $timeout_maxtime = Gtk::timeout_add(MAX_USAGE * 60 * 1000,
        'logout', $dialog);

    // check for inactivity
    global $last_activity, $timeout_inactivity;
    $last_activity = time(); // note 2
    $dialog->connect('key-press-event', 'on_keypress'); // note 3
    $dialog->connect('button-press-event', 'on_buttonpress');  // note 4
    $dialog->connect('motion-notify-event', 'on_motion'); // note 5
    $timeout_inactivity = Gtk::timeout_add(1000, 
        'check_inactivity', $dialog); // note 6

    $dialog->set_has_separator(false);
    $dialog->show_all();
    $dialog->run();
    $dialog->destroy();
}

function on_logout_button($button, $dialog) {
    logout($dialog);
}

function logout($dialog) {
    global $timeout_maxtime, $timeout_inactivity;
    Gtk::timeout_remove($timeout_maxtime);
    Gtk::timeout_remove($timeout_inactivity);
    $dialog->destroy();
}

function on_keypress($widget, $event) {
    global $last_activity;
    $last_activity = time(); // note 7
    return false;
}

function on_motion($widget, $event) {
    global $last_activity;
    $last_activity = time(); // note 7
    return false;
}

function on_buttonpress($widget, $event) {
    global $last_activity;
    $last_activity = time(); // note 7
    return false;
}

// the login function
function login() {
    $dialog = new GtkDialog('Login', null, Gtk::DIALOG_MODAL);
    $dialog->fullscreen();
    $vbox = $dialog->vbox;
    $vbox->pack_start(new GtkLabel());

    // display title
    $title = new GtkLabel("Login");
    $title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
    $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
    $title->set_size_request(-1, 40);
    $vbox->pack_start($title, 0, 0);


    $field_labels = array("Username:", "Password:");
    $table = new GtkTable();
    $row = 0;
    $input = array();
    foreach ($field_labels as $field_label) {
        $label = new GtkLabel($field_label);
        $label->set_alignment(0,0);
        $table->attach($label, 0, 1, $row, $row+1);
        $input[$row] = new GtkEntry();
        $table->attach($input[$row], 1, 2, $row, $row+1);
        if (eregi("password", $field_label))
            $input[$row]->set_visibility(false);
        ++$row;
    }

    $vbox->pack_start($hbox = new GtkHBox(), 0);
    $vbox->pack_start(new GtkLabel());
    $hbox->pack_start(new GtkLabel());
    $hbox->pack_start($table, 0);
    $hbox->pack_start(new GtkLabel());

    $button_hbox = new GtkHBox();
    $button_ok = GtkButton::new_from_stock(Gtk::STOCK_OK);
    $button_ok->set_size_request(86, -1);
    $button_hbox->pack_start($button_ok, 0);
    $button_hbox->pack_start(new GtkLabel());
    $table->attach($button_hbox, 1, 2, $row, $row+1);
    ++$row;

    $status = new GtkLabel('    ');
    $table->attach($status, 1, 2, $row, $row+1);
    $button_ok->connect('clicked', 'on_button_ok', $dialog, $input, $status);

    $dialog->connect('key-press-event', 'on_key', $button_ok, $status);
    $dialog->set_has_separator(false);
    $dialog->show_all();
    $dialog->run();
    $dialog->destroy();
}

function on_button_ok($button, $dialog, $input, $status) {
    $username = $input[0]->get_text();
    $passwd = $input[1]->get_text();

    if ($username=='') {
        $input[0]->grab_focus();
        return true;
    }
    if ($passwd=='') {
        $input[1]->grab_focus();
        return true;
    }
    if ($username!='' && $passwd!='') {
        if (validate($username, $passwd)) {
            global $login_success;
            $login_success = 1;
            $dialog->destroy();
        } else {
            $status->set_text('invalid username/password');
        }
    }
}

function validate($username, $password) {
    if ($username=='user1' && $password=='phpgtk2') {
        return true;
    } else {
        return false;
    }
}

function on_key($widget, $event, $button_ok, $status) {
    $status->set_text('');
    if ($event->keyval==Gdk::KEY_Return) {
        $button_ok->clicked();
        return true;
    } else {
        return false;
    }
}

function check_inactivity($dialog) {
    global $last_activity;
    $time_elapsed = time() - $last_activity;
    if ($time_elapsed>INACTIVITY * 60 * 1000 ) { // note 8
        echo "no activity. auto-logout...\n";
        logout($dialog); // note 8
        return false;
    } else {
        return true;
    }
}

?>
 

Explanation

The above is based on the code from the kiosk template #1.

What's new here:

  1. Stuff an eventbox inside the GtkDialog.
  2. The variable $last_activity keeps track of the time of last activity.
  3. Register the signal 'key-press-event' to keep track of keyboard activity.
  4. Register the signal 'button-press-event' to keep track of button clicks.
  5. Register the signal 'motion-notify-event' to keep track of mouse movements.
  6. Check for inactivity every one second.
  7. If there are any keyboard or mouse activity, we record the time of the activity.
  8. Check if there is more than 10 minutes of inactivity. If there is, then auto-logout from the main application.

Related Articles


Responses

  1. kksou:
    March 14, 2010 9:09am

    Is this article useful?

    Found any bugs?

    Improvements for the above article?

    Please enter below...

Leave a Reply

Name:
Country: (optional)
Your Comments:
ANTI-SPAM key:
 

Search This Site

Google
Web This Site

Search PHP-GTK2 Manual

Full-text search on php-gtk2 manual

Members Login

Username:
Password:
Key:
What is this?
  Forget Password?