You are not logged in.
Goodbye shows a GTK window with 4 buttons: shutdown, reboot, suspend, hibernate. If you click one of these buttons, the respective action is performed.
That is all.
I searched for a simple shutdown dialog that uses GTK and D-Bus (so you don't need to type your password just to shut down the system), so I dived into the GTK and GIO documentation and created one.
See the README on github for more information.
Screenshot with the Faenza icon theme and the Atolm GTK theme:
Github page:
https://github.com/guelfey/goodbye
AUR package:
http://aur.archlinux.org/packages.php?ID=58654
Offline
Very nice job - thanks.
Offline
You should use the extra gpointer parameter of g_signal_connect to explicitly send the action to the callback:
diff --git a/goodbye.c b/goodbye.c
index 9b84ffd..3198c16 100644
--- a/goodbye.c
+++ b/goodbye.c
@@ -85,21 +85,12 @@ void usage(int exit_val) {
void handle_clicked(GtkWidget *widget, gpointer data) {
const char *dest = NULL, *path = NULL, *interface = NULL, *method = NULL;
- const gchar* label;
GDBusConnection *connection = NULL;
GDBusMessage *message = NULL, *reply = NULL;
GError *error = NULL;
int action = -1;
- /* figure out which button was pressed */
- label = gtk_button_get_label(GTK_BUTTON(widget));
- for (int i = 0; i < 4; ++i) {
- if (!strcmp(label, names[i][Label])) {
- action = i;
- break;
- }
- }
-
+ action = *((int *)data);
assert(action >= 0);
dest = names[action][Destination];
@@ -186,7 +177,7 @@ int main(int argc, char *argv[]) {
/* add the signals */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
for (int i = 0; i < 4; ++i)
- g_signal_connect(buttons[i], "clicked", G_CALLBACK(handle_clicked), NULL);
+ g_signal_connect(buttons[i], "clicked", G_CALLBACK(handle_clicked), &i);
/* show window and quit */
gtk_widget_show_all(window);
Offline
I have already thought about using the gpointer, but I'm not sure whether yoir version would work.
Correct me if I'm wrong, but the way I see it, handle_clicked() would get the same address everytime.
Thus, its content would be whatever was in it by the last call of g_signal_connect() (so, "action" would be 3).
Still, I'm gonna test this.
If you really wanted to use the gpointer paramenter, you could either allocate an array with the numbers 0-3 or abuse the pointer as an integer.
Both options didn't seem like proper coding to me.
EDIT: I just tested it; clicking one of the buttons creates a segfault. After running gdb, I saw that "action" was 4 (the number at which the for-loop stopped), so all the parameters for the dbus call were invalid, and it segfaulted trying to print the error message. as both "reply" and "error" were NULL.
Last edited by guelfi (2012-04-29 08:23:35)
Offline
Yeah, you should just put the number in data, not the address of i, and that should work. I don't think that's abusing the pointer or anything though...
diff --git a/goodbye.c b/goodbye.c
index 9b84ffd..3198c16 100644
--- a/goodbye.c
+++ b/goodbye.c
@@ -85,21 +85,12 @@ void usage(int exit_val) {
void handle_clicked(GtkWidget *widget, gpointer data) {
const char *dest = NULL, *path = NULL, *interface = NULL, *method = NULL;
- const gchar* label;
GDBusConnection *connection = NULL;
GDBusMessage *message = NULL, *reply = NULL;
GError *error = NULL;
int action = -1;
- /* figure out which button was pressed */
- label = gtk_button_get_label(GTK_BUTTON(widget));
- for (int i = 0; i < 4; ++i) {
- if (!strcmp(label, names[i][Label])) {
- action = i;
- break;
- }
- }
-
+ action = GPOINTER_TO_INT (data);
assert(action >= 0);
dest = names[action][Destination];
@@ -186,7 +177,7 @@ int main(int argc, char *argv[]) {
/* add the signals */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
for (int i = 0; i < 4; ++i)
- g_signal_connect(buttons[i], "clicked", G_CALLBACK(handle_clicked), NULL);
+ g_signal_connect(buttons[i], "clicked", G_CALLBACK(handle_clicked), GINT_TO_POINTER (i));
/* show window and quit */
gtk_widget_show_all(window);
Offline
Oh, didn't know that Glib provides macros for using gpointers as ints. Always thought that Glib would discourage something like that.
Added.
Offline
Sorry for the bump, I guess, but the icons don't work for me until I manually enable them within the GTK settings like so:
diff --git a/goodbye.c b/goodbye.c
index aa1cd25..698e224 100644
--- a/goodbye.c
+++ b/goodbye.c
@@ -140,6 +140,9 @@ int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
+ g_type_class_unref(g_type_class_ref(GTK_TYPE_BUTTON));
+ g_object_set(gtk_settings_get_default(), "gtk-button-images", TRUE, NULL);
+
if (argc > 1) {
if (argc > 2)
usage(1);
Newer versions of GTK, or maybe GNOME, seem to disable images on buttons by default.
The *class_unref is because GTK whines about the "type not being used" or something. It seemed to work without it in GTK3, but not GTK2.
Offline