/* Copyright (C) 2002 Stanislav Ievlev Copyright (C) 2002, 2005 Dmitry V. Levin GUI implementation of dialog functions This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "gui.h" #define _(arg) gettext(arg) #define PIXMAP_PREFIX "/usr/share/pixmaps/consolehelper-" static void ungrab_focus(void) { gdk_keyboard_ungrab(GDK_CURRENT_TIME); gdk_pointer_ungrab(GDK_CURRENT_TIME); gdk_flush(); } volatile static sig_atomic_t timed_out; static void alarm_handler(int signo) { timed_out = 1; } static void grab_focus(GtkWidget * widget) { GtkWidget *toplevel = gtk_widget_get_toplevel(widget); struct sigaction action; action.sa_handler = alarm_handler; action.sa_flags = SA_RESTART; sigemptyset(&action.sa_mask); if (sigaction(SIGALRM, &action, 0) < 0) error(EXIT_FAILURE, errno, "sigaction"); timed_out = 0; alarm(1); while (!timed_out) { if (!gdk_pointer_grab (toplevel->window, TRUE, 0, NULL, NULL, GDK_CURRENT_TIME)) { alarm(0); timed_out = 0; break; } } if (timed_out) { ungrab_focus(); error(EXIT_FAILURE, 0, "Could not grab pointer"); } timed_out = 0; alarm(1); while (!timed_out) { if (!gdk_keyboard_grab (toplevel->window, FALSE, GDK_CURRENT_TIME)) { alarm(0); timed_out = 0; break; } } if (timed_out) { ungrab_focus(); error(EXIT_FAILURE, 0, "Could not grab keyboard"); } } /* * display dialog with some message */ static int display_dialog(const char *pixname, const char *message, const char *title) { if (!message) return 0; /* window */ GtkWidget *window = gtk_dialog_new_with_buttons(title ? : "consolehelper", NULL, 0, GTK_STOCK_GO_BACK, 1, GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT, NULL); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_window_set_decorated(GTK_WINDOW(window), TRUE); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS); gtk_window_set_keep_above(GTK_WINDOW(window), TRUE); /* hbox */ GtkWidget *hbox = gtk_hbox_new (FALSE, 20); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), hbox, FALSE, FALSE, 10); /* pixmap */ GtkWidget *pix = gtk_image_new_from_file(pixname); gtk_box_pack_start(GTK_BOX(hbox), pix, FALSE, FALSE, 5); /* label */ GtkWidget *label = gtk_label_new(message); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_box_pack_end(GTK_BOX(hbox), label, TRUE, TRUE, 5); /* run */ gtk_widget_show_all(window); int rc = gtk_dialog_run(GTK_DIALOG(window)); gtk_widget_destroy(window); return rc == 1; } int gui_display_error(const char *message, const char *title) { return display_dialog(PIXMAP_PREFIX "critical.png", message, title); } /* * ask for password */ static char * get_pw(const char *title, const char *message, const char *prompt, const char *pixfile) { GtkWidget *window; GtkWidget *entry, *entry_label, *entry_hbox; GtkWidget *pix, *message_label, *message_hbox; char *pw = 0; void entry_activated(GtkDialog * dialog) { gtk_dialog_response(dialog, GTK_RESPONSE_ACCEPT); } /* window */ window = gtk_dialog_new_with_buttons(title ? : "consolehelper", NULL, GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_window_set_decorated(GTK_WINDOW(window), TRUE); gtk_window_set_keep_above(GTK_WINDOW(window), TRUE); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS); gtk_container_set_border_width(GTK_CONTAINER(window), 5); /* message_hbox */ message_hbox = gtk_hbox_new(FALSE, 10); /* pixmap */ pix = gtk_image_new_from_file(pixfile); gtk_box_pack_start(GTK_BOX(message_hbox), pix, FALSE, FALSE, 0); /* message_label */ message_label = gtk_label_new(message); gtk_label_set_line_wrap(GTK_LABEL(message_label), TRUE); gtk_box_pack_end(GTK_BOX(message_hbox), message_label, TRUE, TRUE, 5); /* entry_hbox */ entry_hbox = gtk_hbox_new(FALSE, 10); /* entry_label */ entry_label = gtk_label_new(prompt); gtk_box_pack_start(GTK_BOX(entry_hbox), entry_label, TRUE, TRUE, 5); /* entry */ entry = gtk_entry_new(); gtk_box_pack_end(GTK_BOX(entry_hbox), entry, FALSE, FALSE, 5); gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); gtk_signal_connect_object(GTK_OBJECT(entry), "activate", (GtkSignalFunc) entry_activated, (gpointer) GTK_DIALOG(window)); /* window */ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), message_hbox, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), entry_hbox, FALSE, FALSE, 5); gtk_widget_grab_focus(entry); g_signal_connect(G_OBJECT(window), "map_event", G_CALLBACK(grab_focus), (gpointer) window); gtk_widget_show_all(window); int rc = gtk_dialog_run(GTK_DIALOG(window)); if (rc == GTK_RESPONSE_ACCEPT) { if (asprintf (&pw, "%s\n", gtk_entry_get_text(GTK_ENTRY(entry))) < 0) error(EXIT_FAILURE, errno, "asprintf"); gtk_entry_set_text(GTK_ENTRY(entry), ""); #ifdef DEBUG printf("pw entered: %s", pw); #endif } gtk_widget_destroy(window); ungrab_focus(); return pw; } /* * ask for user password */ const char * gui_get_user_pw(const char *username) { char *message1, *message2; const char *pw; if (asprintf (&message1, _ ("In order to run \"%s\",\nadditional information is required."), program_invocation_short_name) < 0) error(EXIT_FAILURE, errno, "asprintf"); if (asprintf(&message2, _("Enter password for %s %s: "), (strcmp(username, "root") ? _("user") : _("administrator")), username) < 0) error(EXIT_FAILURE, errno, "asprintf"); pw = get_pw(_("Enter password"), message1, message2, PIXMAP_PREFIX "keyring.png"); free(message2); free(message1); if (!pw) exit(EXIT_FAILURE); return pw; }