wmshutdown: Destroy dialog window before shutting down. This is especially useful...
[dockapps.git] / wmshutdown / wmshutdown.c
blobdf0a83ec9f15516ad045a7103b83db3444636b33
1 /* wmshutdown - dockapp to shutdown or reboot your machine
3 * Copyright 2001, 2002 Rafael V. Aroca <rafael@linuxqos.cjb.net>
4 * Copyright 2014 Doug Torrance <dtorrance@piedmont.edu>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <gtk/gtk.h>
20 #include <gdk/gdkx.h>
21 #include <gio/gio.h>
22 #include "wmshutdown.xpm"
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 enum {
29 GTK_RESPONSE_HALT,
30 GTK_RESPONSE_REBOOT,
31 GTK_RESPONSE_SUSPEND,
32 GTK_RESPONSE_HIBERNATE
35 #define HALT_METHOD "PowerOff"
36 #define REBOOT_METHOD "Reboot"
37 #define SUSPEND_METHOD "Suspend"
38 #define HIBERNATE_METHOD "Hibernate"
39 #define DBUS_PATH "/org/freedesktop/login1"
40 #define DBUS_INTERFACE "org.freedesktop.login1.Manager"
41 #define DBUS_DESTINATION "org.freedesktop.login1"
43 static int showVersion;
44 static gboolean show_suspend = FALSE;
45 static gboolean show_hibernate = FALSE;
47 GtkWidget *dialog = NULL;
49 static GOptionEntry entries[] = {
50 { "version", 'v', 0, G_OPTION_ARG_NONE, &showVersion,
51 "Display version information", NULL },
52 { "suspend", 's', 0, G_OPTION_ARG_NONE, &show_suspend,
53 "Show 'suspend' button", NULL },
54 { "hibernate", 'b', 0, G_OPTION_ARG_NONE, &show_hibernate,
55 "Show 'hibernate' button", NULL },
56 { NULL }
59 /* gtk3 dockapp code based on wmpasman by Brad Jorsch
60 * <anomie@users.sourceforge.net>
61 * http://sourceforge.net/projects/wmpasman */
63 GtkWidget *cria_dock(GtkWidget *mw, unsigned int s)
65 GdkDisplay *display;
66 GtkWidget *foobox;
67 Display *d;
68 Window mainwin, iw, w, p, dummy1, *dummy2;
69 unsigned int dummy3;
70 XWMHints *wmHints;
72 (void) s;
73 display = gdk_display_get_default();
74 foobox = gtk_window_new(GTK_WINDOW_POPUP);
76 gtk_window_set_wmclass(GTK_WINDOW(mw), g_get_prgname(), "DockApp");
77 gtk_widget_set_size_request(foobox, 47, 47);
79 gtk_widget_realize(mw);
80 gtk_widget_realize(foobox);
82 d = GDK_DISPLAY_XDISPLAY(display);
83 mainwin = GDK_WINDOW_XID(gtk_widget_get_window(mw));
84 iw = GDK_WINDOW_XID(gtk_widget_get_window(foobox));
85 XQueryTree(d, mainwin, &dummy1, &p, &dummy2, &dummy3);
86 if (dummy2)
87 XFree(dummy2);
88 w = XCreateSimpleWindow(d, p, 0, 0, 1, 1, 0, 0, 0);
89 XReparentWindow(d, mainwin, w, 0, 0);
90 gtk_widget_show(mw);
91 gtk_widget_show(foobox);
92 wmHints = XGetWMHints(d, mainwin);
93 if (!wmHints)
94 wmHints = XAllocWMHints();
95 wmHints->flags |= IconWindowHint;
96 wmHints->icon_window = iw;
97 XSetWMHints(d, mainwin, wmHints);
98 XFree(wmHints);
99 XReparentWindow(d, mainwin, p, 0, 0);
100 XDestroyWindow(d, w);
102 return foobox;
105 void fecha(void)
107 gtk_widget_destroy(dialog);
108 dialog = NULL;
111 void handle_click(GtkWidget *widget, gpointer data)
113 GDBusConnection *connection;
114 GDBusMessage *message, *reply;
115 GError *error = NULL;
117 gchar *method = (gchar *)data;
119 fecha();
121 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
122 message = g_dbus_message_new_method_call(
123 NULL,
124 DBUS_PATH,
125 DBUS_INTERFACE,
126 method);
127 g_dbus_message_set_body(message, g_variant_new("(b)", TRUE));
128 g_dbus_message_set_destination(message, DBUS_DESTINATION);
129 reply = g_dbus_connection_send_message_with_reply_sync(
130 connection, message, 0, -1, NULL, NULL, &error);
132 if (g_dbus_message_get_message_type(reply) ==
133 G_DBUS_MESSAGE_TYPE_ERROR) {
134 GtkWidget *dialog;
136 dialog = gtk_message_dialog_new(
137 GTK_WINDOW(gtk_widget_get_toplevel(widget)),
138 GTK_DIALOG_DESTROY_WITH_PARENT,
139 GTK_MESSAGE_ERROR,
140 GTK_BUTTONS_CLOSE,
141 "%s",
142 g_strcompress(g_variant_print(
143 g_dbus_message_get_body(reply),
144 TRUE)));
145 gtk_dialog_run(GTK_DIALOG(dialog));
146 gtk_widget_destroy(dialog);
149 g_object_unref(message);
150 g_object_unref(reply);
151 g_object_unref(connection);
154 void button_press(GtkWidget *widget, GdkEvent *event)
156 GtkWidget *label;
157 GtkWidget *halt_button;
158 GtkWidget *reboot_button;
159 GtkWidget *suspend_button;
160 GtkWidget *hibernate_button;
161 GtkWidget *cancel_button;
162 GdkEventButton *bevent;
164 (void) widget;
166 bevent = (GdkEventButton *)event;
167 switch (bevent->button) {
168 case 1:
169 if (dialog != NULL)
170 return;
171 dialog = gtk_dialog_new();
172 label = gtk_label_new("Shutdown confirmation");
173 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(
174 GTK_DIALOG(dialog))),
175 label);
177 gtk_dialog_add_buttons(GTK_DIALOG(dialog),
178 "Halt", GTK_RESPONSE_HALT,
179 "Reboot", GTK_RESPONSE_REBOOT, NULL);
180 halt_button = gtk_dialog_get_widget_for_response(
181 GTK_DIALOG(dialog),
182 GTK_RESPONSE_HALT);
183 reboot_button = gtk_dialog_get_widget_for_response(
184 GTK_DIALOG(dialog),
185 GTK_RESPONSE_REBOOT);
186 g_signal_connect(halt_button,
187 "clicked",
188 G_CALLBACK(handle_click),
189 HALT_METHOD);
190 g_signal_connect(reboot_button,
191 "clicked",
192 G_CALLBACK(handle_click),
193 REBOOT_METHOD);
195 if (show_suspend) {
196 gtk_dialog_add_buttons(GTK_DIALOG(dialog), "Suspend",
197 GTK_RESPONSE_SUSPEND, NULL);
198 suspend_button =
199 gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog),
200 GTK_RESPONSE_SUSPEND);
201 g_signal_connect(suspend_button,
202 "clicked",
203 G_CALLBACK(handle_click),
204 SUSPEND_METHOD);
206 if (show_hibernate) {
207 gtk_dialog_add_buttons(GTK_DIALOG(dialog), "Hibernate",
208 GTK_RESPONSE_HIBERNATE, NULL);
209 hibernate_button =
210 gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog),
211 GTK_RESPONSE_HIBERNATE);
212 g_signal_connect(hibernate_button,
213 "clicked",
214 G_CALLBACK(handle_click),
215 HIBERNATE_METHOD);
218 gtk_dialog_add_buttons(GTK_DIALOG(dialog), "Cancel",
219 GTK_RESPONSE_CANCEL, NULL);
220 cancel_button = gtk_dialog_get_widget_for_response(
221 GTK_DIALOG(dialog),
222 GTK_RESPONSE_CANCEL);
223 g_signal_connect(cancel_button,
224 "clicked",
225 G_CALLBACK(fecha),
226 (gpointer) dialog);
228 g_signal_connect(dialog, "destroy", G_CALLBACK(fecha), NULL);
229 gtk_widget_show_all(dialog);
230 break;
231 default:
232 break;
236 int main(int argc, char *argv[])
238 GError *error = NULL;
239 GOptionContext *context;
240 GdkPixbuf *pixbuf;
241 GtkWidget *gtkiw;
242 GtkWidget *dockArea;
243 GtkWidget *pixmap;
245 gtk_init(&argc, &argv);
247 context = g_option_context_new(
248 "- dockapp to shutdown or reboot your machine");
249 g_option_context_add_main_entries(context, entries, NULL);
250 g_option_context_add_group(context, gtk_get_option_group(TRUE));
251 g_option_context_parse(context, &argc, &argv, &error);
253 if (showVersion) {
254 printf(PACKAGE_STRING"\n");
255 return 0;
258 gtkiw = gtk_window_new(GTK_WINDOW_TOPLEVEL);
259 dockArea = cria_dock(gtkiw, 47);
261 pixbuf = gdk_pixbuf_new_from_xpm_data(image_name);
262 pixmap = gtk_image_new_from_pixbuf(pixbuf);
263 gtk_widget_show(pixmap);
264 gtk_container_add(GTK_CONTAINER(dockArea), pixmap);
266 gtk_widget_add_events(dockArea, GDK_BUTTON_PRESS_MASK);
267 g_signal_connect(dockArea, "button-press-event",
268 G_CALLBACK(button_press), NULL);
270 gtk_main();
272 return 0;