1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
---|
2 | /* e-gtk-utils.c |
---|
3 | * |
---|
4 | * Copyright (C) 2000 Ximian, Inc. |
---|
5 | * |
---|
6 | * This program is free software; you can redistribute it and/or |
---|
7 | * modify it under the terms of version 2 of the GNU General Public |
---|
8 | * License as published by the Free Software Foundation. |
---|
9 | * |
---|
10 | * This program is distributed in the hope that it will be useful, |
---|
11 | * but 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 |
---|
16 | * License along with this program; if not, write to the |
---|
17 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
18 | * Boston, MA 02111-1307, USA. |
---|
19 | * |
---|
20 | * Author: Ettore Perazzoli |
---|
21 | */ |
---|
22 | |
---|
23 | |
---|
24 | #ifdef HAVE_CONFIG_H |
---|
25 | #include <config.h> |
---|
26 | #endif |
---|
27 | |
---|
28 | #include <gtk/gtklayout.h> |
---|
29 | #include <gtk/gtksignal.h> |
---|
30 | #include <gtk/gtkwidget.h> |
---|
31 | |
---|
32 | #include <gdk/gdkx.h> |
---|
33 | |
---|
34 | #include <X11/Xlib.h> |
---|
35 | |
---|
36 | #include "e-gtk-utils.h" |
---|
37 | |
---|
38 | |
---|
39 | /* (Cut and pasted from Gtk.) */ |
---|
40 | |
---|
41 | typedef struct DisconnectInfo { |
---|
42 | unsigned int signal_handler; |
---|
43 | |
---|
44 | GtkObject *object1; |
---|
45 | unsigned int disconnect_handler1; |
---|
46 | |
---|
47 | GtkObject *object2; |
---|
48 | unsigned int disconnect_handler2; |
---|
49 | } DisconnectInfo; |
---|
50 | |
---|
51 | static unsigned int |
---|
52 | alive_disconnecter (GtkObject *object, |
---|
53 | DisconnectInfo *info) |
---|
54 | { |
---|
55 | g_assert (info != NULL); |
---|
56 | |
---|
57 | gtk_signal_disconnect (info->object1, info->disconnect_handler1); |
---|
58 | gtk_signal_disconnect (info->object1, info->signal_handler); |
---|
59 | gtk_signal_disconnect (info->object2, info->disconnect_handler2); |
---|
60 | |
---|
61 | g_free (info); |
---|
62 | |
---|
63 | return 0; |
---|
64 | } |
---|
65 | |
---|
66 | /** |
---|
67 | * e_gtk_signal_connect_full_while_alive: |
---|
68 | * @object: |
---|
69 | * @name: |
---|
70 | * @func: |
---|
71 | * @marshal: |
---|
72 | * @data: |
---|
73 | * @destroy_func: |
---|
74 | * @object_signal: |
---|
75 | * @after: |
---|
76 | * @alive_object: |
---|
77 | * |
---|
78 | * Connect a signal like `gtk_signal_connect_while_alive()', but with full |
---|
79 | * params like `gtk_signal_connect_full()'. |
---|
80 | **/ |
---|
81 | void |
---|
82 | e_gtk_signal_connect_full_while_alive (GtkObject *object, |
---|
83 | const char *name, |
---|
84 | GtkSignalFunc func, |
---|
85 | GtkCallbackMarshal marshal, |
---|
86 | void *data, |
---|
87 | GtkDestroyNotify destroy_func, |
---|
88 | gboolean object_signal, |
---|
89 | gboolean after, |
---|
90 | GtkObject *alive_object) |
---|
91 | { |
---|
92 | DisconnectInfo *info; |
---|
93 | |
---|
94 | g_return_if_fail (GTK_IS_OBJECT (object)); |
---|
95 | g_return_if_fail (name != NULL); |
---|
96 | g_return_if_fail (func != NULL); |
---|
97 | g_return_if_fail (GTK_IS_OBJECT (alive_object)); |
---|
98 | |
---|
99 | info = g_new (DisconnectInfo, 1); |
---|
100 | |
---|
101 | info->signal_handler = gtk_signal_connect_full (object, name, |
---|
102 | func, marshal, data, |
---|
103 | destroy_func, |
---|
104 | object_signal, after); |
---|
105 | |
---|
106 | info->object1 = object; |
---|
107 | info->disconnect_handler1 = gtk_signal_connect (object, "destroy", |
---|
108 | GTK_SIGNAL_FUNC (alive_disconnecter), info); |
---|
109 | |
---|
110 | info->object2 = alive_object; |
---|
111 | info->disconnect_handler2 = gtk_signal_connect (alive_object, "destroy", |
---|
112 | GTK_SIGNAL_FUNC (alive_disconnecter), info); |
---|
113 | } |
---|
114 | |
---|
115 | |
---|
116 | /* BackingStore support. */ |
---|
117 | |
---|
118 | static void |
---|
119 | widget_realize_callback_for_backing_store (GtkWidget *widget, |
---|
120 | void *data) |
---|
121 | { |
---|
122 | XSetWindowAttributes attributes; |
---|
123 | GdkWindow *window; |
---|
124 | |
---|
125 | if (GTK_IS_LAYOUT (widget)) |
---|
126 | window = GTK_LAYOUT (widget)->bin_window; |
---|
127 | else |
---|
128 | window = widget->window; |
---|
129 | |
---|
130 | attributes.backing_store = Always; |
---|
131 | XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XWINDOW (window), |
---|
132 | CWBackingStore, &attributes); |
---|
133 | } |
---|
134 | |
---|
135 | /** |
---|
136 | * e_make_widget_backing_stored: |
---|
137 | * @widget: A GtkWidget |
---|
138 | * |
---|
139 | * Make sure that the window for @widget has the BackingStore attribute set to |
---|
140 | * Always when realized. This will allow the widget to be refreshed by the X |
---|
141 | * server even if the application is currently not responding to X events (this |
---|
142 | * is e.g. very useful for the splash screen). |
---|
143 | * |
---|
144 | * Notice that this will not work 100% in all cases as the server might not |
---|
145 | * support that or just refuse to do so. |
---|
146 | **/ |
---|
147 | void |
---|
148 | e_make_widget_backing_stored (GtkWidget *widget) |
---|
149 | { |
---|
150 | gtk_signal_connect (GTK_OBJECT (widget), "realize", |
---|
151 | GTK_SIGNAL_FUNC (widget_realize_callback_for_backing_store), NULL); |
---|
152 | } |
---|