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