source: trunk/athena/bin/gathlogout/gathlogout.c @ 19038

Revision 19038, 5.9 KB checked in by ghudson, 22 years ago (diff)
New program, gathlogout. Similar to panel-wrapper.
Line 
1/* gathlogout.c - gnome-session logout substitute for Athena
2   Written by Greg Hudson <ghudson@mit.edu>
3   Copyright (C) MIT
4
5   User interface code based heavily on gnome-session's logout.c
6   Written by Owen Taylor <otaylor@redhat.com>
7   Copyright (C) Red Hat
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2, or (at your option)
12   any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22   02111-1307, USA.  */
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <ctype.h>
27#include <unistd.h>
28#include <signal.h>
29#include <errno.h>
30
31#include <glib.h>
32#include <gtk/gtk.h>
33#include <gtk/gtkinvisible.h>
34#include <gdk/gdkx.h>
35
36/* Some globals for rendering the iris.  */
37static GdkRectangle iris_rect;
38static gint iris_block = 0;
39static GdkGC *iris_gc = NULL;
40
41static gint
42iris_callback(gpointer data)
43{
44  gint i;
45  gint width_step;
46  gint height_step;
47  GdkPoint points[5];
48  static gchar dash_list[2] = {1, 1};
49
50  width_step = MIN(iris_rect.width / 2, iris_block);
51  height_step = MIN(iris_rect.width / 2, iris_block);
52
53  for (i = 0; i < MIN(width_step, height_step); i++)
54    {
55      gdk_gc_set_dashes(iris_gc, i % 1, dash_list, 2);
56
57      points[0].x = iris_rect.x + i;
58      points[0].y = iris_rect.y + i;
59      points[1].x = iris_rect.x + iris_rect.width - i;
60      points[1].y = iris_rect.y + i;
61      points[2].x = iris_rect.x + iris_rect.width - i;
62      points[2].y = iris_rect.y + iris_rect.height - i;
63      points[3].x = iris_rect.x + i;
64      points[3].y = iris_rect.y + iris_rect.height - i;
65      points[4].x = iris_rect.x + i;
66      points[4].y = iris_rect.y + i;
67
68      gdk_draw_lines(GDK_ROOT_PARENT(), iris_gc, points, 5);
69    }
70
71  gdk_flush();
72
73  iris_rect.x += width_step;
74  iris_rect.y += width_step;
75  iris_rect.width -= MIN(iris_rect.width, iris_block * 2);
76  iris_rect.height -= MIN(iris_rect.height, iris_block * 2);
77
78  if (iris_rect.width == 0 || iris_rect.height == 0)
79    {
80      gtk_main_quit();
81      return FALSE;
82    }
83  else
84    return TRUE;
85}
86
87static void
88iris(void)
89{
90  iris_rect.x = 0;
91  iris_rect.y = 0;
92  iris_rect.width = gdk_screen_width();
93  iris_rect.height = gdk_screen_height();
94
95  if (!iris_gc)
96    {
97      GdkGCValues values;
98
99      values.line_style = GDK_LINE_ON_OFF_DASH;
100      values.subwindow_mode = GDK_INCLUDE_INFERIORS;
101
102      iris_gc = gdk_gc_new_with_values(GDK_ROOT_PARENT(),
103                                       &values,
104                                       GDK_GC_LINE_STYLE | GDK_GC_SUBWINDOW);
105    }
106
107  /* Plan for a time of 0.5 seconds for effect */
108  iris_block = iris_rect.height / (500 / 20);
109  if (iris_block < 8)
110    iris_block = 8;
111
112  gtk_timeout_add(20, iris_callback, NULL);
113
114  gtk_main();
115}
116
117static void
118refresh_screen(void)
119{
120  GdkWindowAttr attributes;
121  GdkWindow *window;
122
123  attributes.x = 0;
124  attributes.y = 0;
125  attributes.width = gdk_screen_width();
126  attributes.height = gdk_screen_height();
127  attributes.window_type = GDK_WINDOW_TOPLEVEL;
128  attributes.wclass = GDK_INPUT_OUTPUT;
129  attributes.override_redirect = TRUE;
130  attributes.event_mask = 0;
131 
132  window = gdk_window_new(NULL, &attributes,
133                          GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR);
134
135  gdk_window_show(window);
136  gdk_flush();
137  gdk_window_hide(window);
138}
139
140static gboolean
141display_gui(void)
142{
143  GtkWidget *box, *invisible;
144  gint result;
145  gboolean accessibility_enabled;
146
147  gtk_rc_reparse_all();
148
149  /* It's really bad here if someone else has the pointer grabbed, so
150   * we first grab the pointer and keyboard to an offscreen window,
151   * and then once we have the server grabbed, move that to our
152   * dialog.
153   */
154  invisible = gtk_invisible_new();
155  gtk_widget_show(invisible);
156
157  while (1)
158    {
159      if (gdk_pointer_grab(invisible->window, FALSE, 0, NULL, NULL,
160                           GDK_CURRENT_TIME) == Success)
161        {
162          if (gdk_keyboard_grab(invisible->window, FALSE,
163                                GDK_CURRENT_TIME) == Success)
164            break;
165          gdk_pointer_ungrab(GDK_CURRENT_TIME);
166        }
167      sleep(1);
168    }
169
170  box = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_QUESTION,
171                               GTK_BUTTONS_OK_CANCEL,
172                               "Are you sure you want to log out?");
173  g_object_set(G_OBJECT(box), "type", GTK_WINDOW_POPUP, NULL);
174  gtk_dialog_set_default_response(GTK_DIALOG(box), GTK_RESPONSE_OK);
175  gtk_window_set_resizable(GTK_WINDOW(box), FALSE);
176  gtk_window_set_position(GTK_WINDOW(box), GTK_WIN_POS_CENTER);
177
178  /* Don't shade the screen if accessibility is enabled; grabbing the
179   * server doesn't work in that case.
180   */
181  accessibility_enabled = GTK_IS_ACCESSIBLE(gtk_widget_get_accessible(box));
182  if (!accessibility_enabled)
183    {
184      XGrabServer(GDK_DISPLAY());
185      iris();
186    }
187
188  gtk_widget_show_all(box);
189
190  /* Move the grabs to our message box */
191  gdk_pointer_grab(box->window, TRUE, 0, NULL, NULL, GDK_CURRENT_TIME);
192  gdk_keyboard_grab(box->window, FALSE, GDK_CURRENT_TIME);
193  XSetInputFocus(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(box->window),
194                 RevertToParent, CurrentTime);
195
196  result = gtk_dialog_run(GTK_DIALOG(box));
197
198  if (!accessibility_enabled)
199    {
200      refresh_screen();
201      XUngrabServer(GDK_DISPLAY());
202    }
203
204  gdk_pointer_ungrab(GDK_CURRENT_TIME);
205  gdk_keyboard_ungrab(GDK_CURRENT_TIME);
206
207  gdk_flush();
208
209  return (result == GTK_RESPONSE_OK);
210}
211
212int main(int argc, char **argv)
213{
214  const char *pidstr;
215
216  gtk_init(&argc, &argv);
217  if (display_gui())
218    {
219      pidstr = getenv("XSESSION");
220      if (pidstr && isdigit(*pidstr))
221        kill(atoi(pidstr), SIGHUP);
222      else
223        execlp("/usr/athena/bin/end_session", "end_session", (char *) NULL);
224      return 0;
225    }
226
227  return 1;
228}
Note: See TracBrowser for help on using the repository browser.