2006-09-12 Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
[hildon] / hildon-widgets / hildon-dialoghelp.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; version 2.1 of
11  * the License or any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 /**
26  * SECTION:hildon-dialoghelp
27  * @short_description: A helper which contains a button in a normal dialog to 
28  * open a help if required
29  * 
30  * #HildonDialoghelp is a helper that provides an API for enabling or
31  * disabling a help button in the titlebar area of normal dialogs that
32  * are derived from GtkDialog. 
33  */
34
35 #include <stdlib.h>
36 #include <gdk/gdkx.h>
37 #include "hildon-dialoghelp.h"
38
39 static guint help_signal = 0;
40
41 static GdkFilterReturn
42 handle_xevent(GdkXEvent * xevent, GdkEvent * event, gpointer dialog)
43 {
44     XAnyEvent *eventti = xevent;
45
46     if (eventti->type == ClientMessage) {
47         Atom help_atom, wm_atom;
48         Display *disp;
49         XClientMessageEvent *cm;
50
51         disp = GDK_DISPLAY();
52         cm = xevent;
53
54         help_atom = XInternAtom(disp, "_NET_WM_CONTEXT_HELP", True);
55         wm_atom = XInternAtom(disp, "WM_PROTOCOLS", True);
56
57         if (cm->message_type == wm_atom && cm->data.l[0] == help_atom) {
58             /* XClientMessageEvent *cm = xevent; */
59             g_signal_emit(G_OBJECT(dialog), help_signal, 0);
60         }
61
62         return GDK_FILTER_REMOVE;       /* Event handled, don't process
63                                            further */
64     }
65
66     return GDK_FILTER_CONTINUE; /* Event not handled */
67 }
68
69 /**
70  * gtk_dialog_help_enable:
71  * @dialog: The dialog for which help is to be enabled.
72  *
73  * Enables context help button for a given dialog. The signal "help" can be
74  * connected to handler by normal GTK methods. Note that this function
75  * has to be called before the dialog is shown.
76  *
77  * The "help" signal itself has no other parameters than the dialog where
78  * it is connected to, ie.:
79  * void user_function(GtkDialog *dialog, gpointer user_data);
80  */
81 void gtk_dialog_help_enable(GtkDialog * dialog)
82 {
83     GdkWindow *window;
84     GdkDisplay *display;
85     Atom *protocols;
86     Atom *list;
87     Atom helpatom;
88     int amount = 0;
89     int n = 0;
90     int i = 0;
91     int help_enabled = 0;
92     
93     /* Create help signal if it didn't exist */   
94     if (help_signal == 0) {
95         help_signal = g_signal_new("help", GTK_TYPE_DIALOG,
96                                    G_SIGNAL_ACTION, (guint) - 1, NULL,
97                                    NULL, g_cclosure_marshal_VOID__VOID,
98                                    G_TYPE_NONE, 0);
99     }
100
101     g_return_if_fail(GTK_IS_DIALOG(dialog));
102
103     gtk_widget_realize(GTK_WIDGET(dialog));
104     window = GTK_WIDGET(dialog)->window;
105     display = gdk_drawable_get_display (window);
106
107     /* Create a list of atoms stored in GdkWindow */
108     XGetWMProtocols(GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
109                     &list, &amount);
110     
111     protocols = (Atom *) malloc ((amount+1) * sizeof (Atom));
112     helpatom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_CONTEXT_HELP");
113
114     /* Enable the dialoghelp if help_atom is in the atoms' list */
115     for (i=0; i<amount; i++)
116     {
117             protocols[n++] = list[i];
118             if (list[i] == helpatom)
119             {
120                     help_enabled = 1;
121             }
122     }
123     XFree (list);
124
125     /* Add the help_atom to the atoms' list if it was not in it */ 
126     if (!help_enabled)
127     {
128             protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_CONTEXT_HELP");
129     }
130     
131     /* Replace the protocol property of the GdkWindow with the new atoms' list */
132     XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
133     free (protocols);
134     
135     /* Add a callback function as event filter */ 
136     gdk_window_add_filter(window, handle_xevent, dialog);
137 }
138
139
140 /**
141  * gtk_dialog_help_disable:
142  * @dialog: The dialog for which help is to be disabled.
143  *
144  * Disables context help button for the given dialog.
145  **/
146 void gtk_dialog_help_disable(GtkDialog * dialog)
147 {
148     GdkWindow *window=NULL;
149     GdkDisplay *display;
150     Atom *protocols;
151     Atom *list;
152     Atom helpatom;
153     int amount = 0;
154     int n = 0;
155     int i = 0;
156     
157     g_return_if_fail(GTK_IS_DIALOG(dialog));
158
159     gtk_widget_realize(GTK_WIDGET(dialog));
160     window = GTK_WIDGET(dialog)->window;
161     display = gdk_drawable_get_display (window);
162
163     /* Create a list of atoms stored in GdkWindow */
164     XGetWMProtocols(GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
165                     &list, &amount);
166     
167     helpatom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_CONTEXT_HELP");
168     protocols = (Atom *) malloc (amount * sizeof (Atom));
169
170     /* Remove the help_atom if it is in the atoms' list */
171     for (i=0; i<amount; i++)
172     {
173             if (list[i] != helpatom)
174             {
175                     protocols[n++] = list[i];
176             }
177     }
178     XFree (list);
179     
180     /* Replace the protocol property of the GdkWindow with the new atoms' list */
181     XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
182     free (protocols);
183
184     /* Remove the event filter */
185     gdk_window_remove_filter(window, handle_xevent, dialog);
186 }
187
188
189
190