1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2011 Red Hat, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA
18 * 02110-1335, USA.
19 *
20 * Authors:
21 * Colin Walters <walters@verbum.org>
22 */
23
24 #include <config.h>
25
26 #include <glib/gi18n.h>
27
28 #include <gtk/gtkx.h>
29
30 #include "csm-fail-whale-dialog.h"
31
32 #include "csm-icon-names.h"
33 #include "csm-manager.h"
34 #include "csm-util.h"
35
36 #define CSM_FAIL_WHALE_DIALOG_GET_PRIVATE(o) \
37 (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSM_TYPE_FAIL_WHALE_DIALOG, CsmFailWhaleDialogPrivate))
38
39 struct _CsmFailWhaleDialogPrivate
40 {
41 gboolean debug_mode;
42 gboolean allow_logout;
43 GdkRectangle geometry;
44 };
45
46 G_DEFINE_TYPE (CsmFailWhaleDialog, csm_fail_whale_dialog, GTK_TYPE_WINDOW);
47
48 /* derived from tomboy */
49 static void
_window_override_user_time(CsmFailWhaleDialog * window)50 _window_override_user_time (CsmFailWhaleDialog *window)
51 {
52 guint32 ev_time = gtk_get_current_event_time ();
53
54 if (ev_time == 0) {
55 gint ev_mask = gtk_widget_get_events (GTK_WIDGET (window));
56 if (!(ev_mask & GDK_PROPERTY_CHANGE_MASK)) {
57 gtk_widget_add_events (GTK_WIDGET (window),
58 GDK_PROPERTY_CHANGE_MASK);
59 }
60
61 /*
62 * NOTE: Last resort for D-BUS or other non-interactive
63 * openings. Causes roundtrip to server. Lame.
64 */
65 ev_time = gdk_x11_get_server_time (gtk_widget_get_window (GTK_WIDGET (window)));
66 }
67
68 gdk_x11_window_set_user_time (gtk_widget_get_window (GTK_WIDGET (window)), ev_time);
69 }
70
71 /* copied from panel-toplevel.c */
72 static void
_window_move_resize_window(CsmFailWhaleDialog * window,gboolean move,gboolean resize)73 _window_move_resize_window (CsmFailWhaleDialog *window,
74 gboolean move,
75 gboolean resize)
76 {
77 GtkWidget *widget;
78
79 widget = GTK_WIDGET (window);
80
81 g_assert (gtk_widget_get_realized (widget));
82
83 if (window->priv->debug_mode)
84 return;
85
86 g_debug ("Move and/or resize window x=%d y=%d w=%d h=%d",
87 window->priv->geometry.x,
88 window->priv->geometry.y,
89 window->priv->geometry.width,
90 window->priv->geometry.height);
91
92 if (move && resize) {
93 gdk_window_move_resize (gtk_widget_get_window (widget),
94 window->priv->geometry.x,
95 window->priv->geometry.y,
96 window->priv->geometry.width,
97 window->priv->geometry.height);
98 } else if (move) {
99 gdk_window_move (gtk_widget_get_window (widget),
100 window->priv->geometry.x,
101 window->priv->geometry.y);
102 } else if (resize) {
103 gdk_window_resize (gtk_widget_get_window (widget),
104 window->priv->geometry.width,
105 window->priv->geometry.height);
106 }
107 }
108
109 static void
update_geometry(CsmFailWhaleDialog * fail_dialog)110 update_geometry (CsmFailWhaleDialog *fail_dialog)
111 {
112 int monitor;
113 GdkScreen *screen;
114
115 screen = gtk_widget_get_screen (GTK_WIDGET (fail_dialog));
116 monitor = gdk_screen_get_primary_monitor (screen);
117
118 gdk_screen_get_monitor_geometry (screen,
119 monitor,
120 &fail_dialog->priv->geometry);
121 }
122
123 static void
on_screen_size_changed(GdkScreen * screen,CsmFailWhaleDialog * fail_dialog)124 on_screen_size_changed (GdkScreen *screen,
125 CsmFailWhaleDialog *fail_dialog)
126 {
127 gtk_widget_queue_resize (GTK_WIDGET (fail_dialog));
128 }
129
130 static void
csm_fail_whale_dialog_finalize(GObject * object)131 csm_fail_whale_dialog_finalize (GObject *object)
132 {
133 CsmFailWhaleDialog *fail_dialog = CSM_FAIL_WHALE_DIALOG (object);
134
135 G_OBJECT_CLASS (csm_fail_whale_dialog_parent_class)->finalize (object);
136 }
137
138 static void
csm_fail_whale_dialog_realize(GtkWidget * widget)139 csm_fail_whale_dialog_realize (GtkWidget *widget)
140 {
141 if (GTK_WIDGET_CLASS (csm_fail_whale_dialog_parent_class)->realize) {
142 GTK_WIDGET_CLASS (csm_fail_whale_dialog_parent_class)->realize (widget);
143 }
144
145 _window_override_user_time (CSM_FAIL_WHALE_DIALOG (widget));
146 update_geometry (CSM_FAIL_WHALE_DIALOG (widget));
147 _window_move_resize_window (CSM_FAIL_WHALE_DIALOG (widget), TRUE, TRUE);
148
149 g_signal_connect (gtk_window_get_screen (GTK_WINDOW (widget)),
150 "size_changed",
151 G_CALLBACK (on_screen_size_changed),
152 widget);
153 }
154
155 static void
csm_fail_whale_dialog_unrealize(GtkWidget * widget)156 csm_fail_whale_dialog_unrealize (GtkWidget *widget)
157 {
158 g_signal_handlers_disconnect_by_func (gtk_window_get_screen (GTK_WINDOW (widget)),
159 on_screen_size_changed,
160 widget);
161
162 if (GTK_WIDGET_CLASS (csm_fail_whale_dialog_parent_class)->unrealize) {
163 GTK_WIDGET_CLASS (csm_fail_whale_dialog_parent_class)->unrealize (widget);
164 }
165 }
166
167 static void
csm_fail_whale_dialog_size_request(GtkWidget * widget,GtkRequisition * requisition)168 csm_fail_whale_dialog_size_request (GtkWidget *widget,
169 GtkRequisition *requisition)
170 {
171 CsmFailWhaleDialog *fail_dialog;
172 GdkRectangle old_geometry;
173 int position_changed = FALSE;
174 int size_changed = FALSE;
175
176 fail_dialog = CSM_FAIL_WHALE_DIALOG (widget);
177
178 old_geometry = fail_dialog->priv->geometry;
179
180 update_geometry (fail_dialog);
181
182 requisition->width = fail_dialog->priv->geometry.width;
183 requisition->height = fail_dialog->priv->geometry.height;
184
185 if (!gtk_widget_get_realized (widget)) {
186 return;
187 }
188
189 if (old_geometry.width != fail_dialog->priv->geometry.width ||
190 old_geometry.height != fail_dialog->priv->geometry.height) {
191 size_changed = TRUE;
192 }
193
194 if (old_geometry.x != fail_dialog->priv->geometry.x ||
195 old_geometry.y != fail_dialog->priv->geometry.y) {
196 position_changed = TRUE;
197 }
198
199 _window_move_resize_window (fail_dialog,
200 position_changed, size_changed);
201 }
202
203 static void
csm_fail_whale_dialog_get_preferred_width(GtkWidget * widget,gint * minimal_width,gint * natural_width)204 csm_fail_whale_dialog_get_preferred_width (GtkWidget *widget,
205 gint *minimal_width,
206 gint *natural_width)
207 {
208 GtkRequisition requisition;
209
210 csm_fail_whale_dialog_size_request (widget, &requisition);
211
212 *minimal_width = *natural_width = requisition.width;
213 }
214
215 static void
csm_fail_whale_dialog_get_preferred_height(GtkWidget * widget,gint * minimal_height,gint * natural_height)216 csm_fail_whale_dialog_get_preferred_height (GtkWidget *widget,
217 gint *minimal_height,
218 gint *natural_height)
219 {
220 GtkRequisition requisition;
221
222 csm_fail_whale_dialog_size_request (widget, &requisition);
223
224 *minimal_height = *natural_height = requisition.height;
225 }
226
227 static void
csm_fail_whale_dialog_class_init(CsmFailWhaleDialogClass * klass)228 csm_fail_whale_dialog_class_init (CsmFailWhaleDialogClass *klass)
229 {
230 GObjectClass *object_class;
231 GtkWidgetClass *widget_class;
232
233 object_class = G_OBJECT_CLASS (klass);
234 object_class->finalize = csm_fail_whale_dialog_finalize;
235
236 widget_class = GTK_WIDGET_CLASS (klass);
237
238 widget_class->realize = csm_fail_whale_dialog_realize;
239 widget_class->unrealize = csm_fail_whale_dialog_unrealize;
240 widget_class->get_preferred_width = csm_fail_whale_dialog_get_preferred_width;
241 widget_class->get_preferred_height = csm_fail_whale_dialog_get_preferred_height;
242
243 g_type_class_add_private (klass, sizeof (CsmFailWhaleDialogPrivate));
244 }
245
246 static void
csm_fail_whale_dialog_init(CsmFailWhaleDialog * fail_dialog)247 csm_fail_whale_dialog_init (CsmFailWhaleDialog *fail_dialog)
248 {
249 fail_dialog->priv = CSM_FAIL_WHALE_DIALOG_GET_PRIVATE (fail_dialog);
250 }
251
252 void
csm_fail_whale_dialog_we_failed(gboolean debug_mode,gboolean allow_logout)253 csm_fail_whale_dialog_we_failed (gboolean debug_mode,
254 gboolean allow_logout)
255
256 {
257 static gboolean failed = FALSE;
258
259 if (failed) {
260 return;
261 }
262
263 g_critical ("We failed, but the fail whale is dead. Sorry....");
264 failed = TRUE;
265 }
266
267