Fixed the compilation using '--enable-fatal' and '--disable-deprecated' options
[hildon] / hildon / hildon-stackable-window.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2008 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Rodrigo Novo <rodrigo.novo@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 (at your option) 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-stackable-window
27  * @short_description: Stackable top-level window in the Hildon framework.
28  * @see_also: #HildonWindowStack, #HildonProgram, #HildonWindow
29  *
30  * The #HildonStackableWindow is a
31  * top-level window that can be stacked in a #HildonWindowStack. It is derived
32  * from #HildonWindow. Applications that use stackable windows are organized
33  * in a hierarchical way so users can go from any window back to the
34  * application's root window.
35  *
36  * The user can only see and interact with the window on top of the
37  * stack. Although all other windows are mapped and visible, they are
38  * obscured by the topmost one so in practice they appear as if they
39  * were hidden.
40  *
41  * To add a window to the stack, just use gtk_widget_show(). The
42  * previous one will be obscured by the new one. When the new window
43  * is destroyed, the previous one will appear again.
44  *
45  * Alternatively, you can remove a window from the top of the stack
46  * without destroying it by using hildon_window_stack_pop(). The
47  * window will be automatically hidden and the previous one will
48  * appear.
49  *
50  * For advanced details on stack handling, see #HildonWindowStack
51  *
52  * <example>
53  * <title>Basic HildonStackableWindow example</title>
54  * <programlisting>
55  * static void
56  * show_new_window (void)
57  * {
58  *     GtkWidget *win;
59  * <!-- -->
60  *     win = hildon_stackable_window_new ();
61  * <!-- -->
62  *     // ... configure new window
63  * <!-- -->
64  *     gtk_widget_show (win);
65  * }
66  * <!-- -->
67  * int
68  * main (int argc, char **argv)
69  * {
70  *     GtkWidget *win;
71  *     GtkWidget *button;
72  * <!-- -->
73  *     gtk_init (&amp;argc, &amp;args);
74  * <!-- -->
75  *     win = hildon_stackable_window_new ();
76  *     gtk_window_set_title (GTK_WINDOW (win), "Main window);
77  * <!-- -->
78  *     // ... add some widgets to the window
79  * <!-- -->
80  *     g_signal_connect (button, "clicked", G_CALLBACK (show_new_window), NULL);
81  *     g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL);
82  * <!-- -->
83  *     gtk_widget_show_all (win);
84  *     gtk_main ();
85  * <!-- -->
86  *     return 0;
87  * }
88  * </programlisting>
89  * </example>
90  */
91
92 #undef HILDON_DISABLE_DEPRECATED
93
94 #include                                        <X11/X.h>
95 #include                                        <X11/Xatom.h>
96 #include                                        <gdk/gdkx.h>
97
98 #include                                        "hildon-stackable-window.h"
99 #include                                        "hildon-stackable-window-private.h"
100 #include                                        "hildon-window-stack.h"
101 #include                                        "hildon-window-stack-private.h"
102
103 G_DEFINE_TYPE (HildonStackableWindow, hildon_stackable_window, HILDON_TYPE_WINDOW);
104
105 void G_GNUC_INTERNAL
106 hildon_stackable_window_set_stack               (HildonStackableWindow *self,
107                                                  HildonWindowStack     *stack,
108                                                  gint                   position)
109 {
110     HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
111
112     if (stack)
113         g_object_ref (stack);
114
115     if (priv->stack)
116         g_object_unref (priv->stack);
117
118     priv->stack = stack;
119     priv->stack_position = position;
120 }
121
122 /**
123  * hildon_stackable_window_get_stack:
124  * @self: a #HildonStackableWindow
125  *
126  * Returns the stack where window @self is on, or %NULL if the window
127  * is not stacked.
128  *
129  * Return value: a #HildonWindowStack, or %NULL
130  *
131  * Since: 2.2
132  **/
133 HildonWindowStack *
134 hildon_stackable_window_get_stack               (HildonStackableWindow *self)
135 {
136     HildonStackableWindowPrivate *priv;
137
138     g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (self), NULL);
139
140     priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
141
142     return priv->stack;
143 }
144
145 /**
146  * hildon_stackable_window_set_main_menu:
147  * @self: a #HildonStackableWindow
148  * @menu: a #HildonAppMenu to be used for this window
149  *
150  * Sets the menu to be used for this window.
151  *
152  * Deprecated: Hildon 2.2: use hildon_window_set_app_menu()
153  **/
154 void
155 hildon_stackable_window_set_main_menu           (HildonStackableWindow *self,
156                                                  HildonAppMenu *menu)
157 {
158     hildon_window_set_app_menu (HILDON_WINDOW (self), menu);
159 }
160
161 static void
162 hildon_stackable_window_map                     (GtkWidget *widget)
163 {
164     GdkDisplay *display;
165     Atom atom;
166     unsigned long val;
167     HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget);
168
169     val = priv->stack_position;
170
171     /* Set additional property "_HILDON_STACKABLE_WINDOW", to allow the WM to manage
172        it as a stackable window. */
173     display = gdk_drawable_get_display (widget->window);
174     atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_STACKABLE_WINDOW");
175     XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), atom,
176                      XA_INTEGER, 32, PropModeReplace,
177                      (unsigned char *) &val, 1);
178
179     GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->map (widget);
180 }
181
182 static void
183 hildon_stackable_window_show                    (GtkWidget *widget)
184 {
185     HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget);
186
187     /* Stack the window if not already stacked */
188     if (priv->stack == NULL) {
189         HildonWindowStack *stack = hildon_window_stack_get_default ();
190         _hildon_window_stack_do_push (stack, HILDON_STACKABLE_WINDOW (widget));
191     }
192
193     GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->show (widget);
194 }
195
196 static void
197 hildon_stackable_window_hide                    (GtkWidget *widget)
198 {
199     HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget);
200
201     if (priv->stack) {
202         hildon_window_stack_remove (HILDON_STACKABLE_WINDOW (widget));
203     }
204
205     GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->hide (widget);
206 }
207
208 static gboolean
209 hildon_stackable_window_delete_event            (GtkWidget   *widget,
210                                                  GdkEventAny *event)
211 {
212     HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget);
213     gboolean retvalue = FALSE;
214
215     if (priv->stack && hildon_window_stack_peek (priv->stack) != widget) {
216         /* Ignore the delete event if this window is not the topmost one */
217         retvalue = TRUE;
218     } else if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event) {
219         retvalue = GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event (widget, event);
220     }
221
222     return retvalue;
223 }
224
225 static void
226 hildon_stackable_window_class_init              (HildonStackableWindowClass *klass)
227 {
228     GtkWidgetClass    *widget_class = GTK_WIDGET_CLASS (klass);
229
230     widget_class->map               = hildon_stackable_window_map;
231     widget_class->show              = hildon_stackable_window_show;
232     widget_class->hide              = hildon_stackable_window_hide;
233     widget_class->delete_event      = hildon_stackable_window_delete_event;
234
235     g_type_class_add_private (klass, sizeof (HildonStackableWindowPrivate));
236 }
237
238 static void
239 hildon_stackable_window_init                    (HildonStackableWindow *self)
240 {
241     HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
242
243     priv->stack = NULL;
244     priv->stack_position = -1;
245 }
246
247 /**
248  * hildon_stackable_window_new:
249  *
250  * Creates a new #HildonStackableWindow.
251  *
252  * Return value: A #HildonStackableWindow
253  *
254  * Since: 2.2
255  **/
256 GtkWidget*
257 hildon_stackable_window_new                     (void)
258 {
259     HildonStackableWindow *newwindow = g_object_new (HILDON_TYPE_STACKABLE_WINDOW, NULL);
260
261     return GTK_WIDGET (newwindow);
262 }