2 * This file is a part of hildon
4 * Copyright (C) 2008 Nokia Corporation, all rights reserved.
6 * Contact: Karl Lattimer <karl.lattimer@nokia.com>
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.
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.
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
26 * SECTION:hildon-stackable-window
27 * @short_description: Widget representing a stackable, top-level window in the Hildon framework.
29 * The #HildonStackableWindow is a GTK+ widget which represents a
30 * top-level window in the Hildon framework. It is derived from
31 * #HildonWindow. Applications that use stackable windows are organized
32 * in a hierarchical way so users can go from any window back to the
33 * application's root window.
35 * To add a window to the stack, just use gtk_widget_show(). The
36 * previous one will be automatically hidden. When the new window is
37 * destroyed, the previous one will appear again.
39 * Alternatively, you can remove a window from the top of the stack
40 * without destroying it by using
41 * hildon_program_pop_window_stack(). The window will be automatically
42 * hidden and the previous one will appear.
45 * <title>Basic HildonStackableWindow example</title>
48 * show_new_window (void)
52 * win = hildon_stackable_window_new ();
54 * // ... configure new window
56 * // This automatically hides the previous window
57 * gtk_widget_show (win);
61 * main (int argc, char **argv)
66 * gtk_init (&argc, &args);
68 * win = hildon_stackable_window_new ();
69 * gtk_window_set_title (GTK_WINDOW (win), "Main window);
71 * // ... add some widgets to the window
73 * g_signal_connect (button, "clicked", G_CALLBACK (show_new_window), NULL);
74 * g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL);
76 * gtk_widget_show_all (win);
86 #include <X11/Xatom.h>
88 #include "hildon-stackable-window.h"
89 #include "hildon-stackable-window-private.h"
90 #include "hildon-program.h"
91 #include "hildon-window-private.h"
92 #include "hildon-program-private.h"
94 G_DEFINE_TYPE (HildonStackableWindow, hildon_stackable_window, HILDON_TYPE_WINDOW);
97 hildon_stackable_window_set_going_home (HildonStackableWindow *self,
100 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
101 priv->going_home = going_home;
104 gboolean G_GNUC_INTERNAL
105 hildon_stackable_window_get_going_home (HildonStackableWindow *self)
107 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
108 return priv->going_home;
112 * hildon_stackable_window_set_main_menu:
113 * @self: a #HildonStackableWindow
114 * @menu: a #HildonAppMenu to be used for this window
116 * Sets the menu to be used for this window. Pass %NULL to remove the
117 * current menu. #HildonStackableWindow takes ownership of the passed
118 * menu and you're not supposed to free it or reuse it anymore.
120 * Note that #HildonStackableWindow widgets use #HildonAppMenu rather
121 * than #GtkMenu, so you're not supposed to use
122 * hildon_window_set_main_menu() with a #HildonStackableWindow.
125 hildon_stackable_window_set_main_menu (HildonStackableWindow *self,
128 HildonStackableWindowPrivate *priv;
130 g_return_if_fail (HILDON_IS_STACKABLE_WINDOW (self));
131 g_return_if_fail (!menu || HILDON_IS_APP_MENU (menu));
132 priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
134 /* Destroy old menu */
136 gtk_widget_destroy (GTK_WIDGET (priv->app_menu));
139 priv->app_menu = menu;
143 hildon_stackable_window_toggle_menu (HildonWindow *self,
147 HildonStackableWindowPrivate *priv;
149 g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (self), FALSE);
150 priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
151 g_assert (priv != NULL);
155 if (GTK_WIDGET_MAPPED (GTK_WIDGET (priv->app_menu)))
156 gtk_widget_hide (GTK_WIDGET (priv->app_menu));
158 gtk_widget_show (GTK_WIDGET (priv->app_menu));
162 else if (HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->toggle_menu)
164 return HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->toggle_menu (self, button, time);
173 hildon_stackable_window_realize (GtkWidget *widget)
178 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->realize (widget);
180 /* Set the window type to "_HILDON_WM_WINDOW_TYPE_STACKABLE", to allow the WM to manage
182 display = gdk_drawable_get_display (widget->window);
183 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_STACKABLE");
184 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
185 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
186 XA_ATOM, 32, PropModeAppend,
191 hildon_stackable_window_show (GtkWidget *widget)
193 HildonProgram *program = hildon_program_get_instance ();
194 HildonStackableWindow *current_win = HILDON_STACKABLE_WINDOW (widget);
195 HildonStackableWindow *previous_win = hildon_program_peek_window_stack (program);
197 if (previous_win != current_win)
198 _hildon_program_add_to_stack (program, current_win);
200 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->show (widget);
202 if (previous_win != NULL && previous_win != current_win)
203 gtk_widget_hide (GTK_WIDGET (previous_win));
207 hildon_stackable_window_destroy (GtkObject *obj)
209 HildonProgram *program = hildon_program_get_instance ();
210 HildonStackableWindow *topmost = hildon_program_peek_window_stack (program);
212 if (_hildon_program_remove_from_stack (program, HILDON_STACKABLE_WINDOW (obj)))
214 if (topmost != NULL && GTK_OBJECT (topmost) == obj)
216 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (obj);
217 topmost = hildon_program_peek_window_stack (program);
218 if (topmost != NULL && !priv->going_home)
219 gtk_widget_show (GTK_WIDGET (topmost));
223 GTK_OBJECT_CLASS (hildon_stackable_window_parent_class)->destroy (obj);
227 hildon_stackable_window_finalize (GObject *object)
229 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (object);
232 gtk_widget_destroy (GTK_WIDGET (priv->app_menu));
234 if (G_OBJECT_CLASS (hildon_stackable_window_parent_class)->finalize)
235 G_OBJECT_CLASS (hildon_stackable_window_parent_class)->finalize (object);
239 hildon_stackable_window_class_init (HildonStackableWindowClass *klass)
241 GObjectClass *obj_class = G_OBJECT_CLASS (klass);
242 GtkObjectClass *gtk_obj_class = GTK_OBJECT_CLASS (klass);
243 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
244 HildonWindowClass *window_class = HILDON_WINDOW_CLASS (klass);
246 obj_class->finalize = hildon_stackable_window_finalize;
248 gtk_obj_class->destroy = hildon_stackable_window_destroy;
250 widget_class->realize = hildon_stackable_window_realize;
251 widget_class->show = hildon_stackable_window_show;
253 window_class->toggle_menu = hildon_stackable_window_toggle_menu;
255 g_type_class_add_private (klass, sizeof (HildonStackableWindowPrivate));
259 hildon_stackable_window_init (HildonStackableWindow *self)
261 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
263 priv->going_home = FALSE;
264 priv->app_menu = NULL;
268 * hildon_stackable_window_new:
270 * Creates a new #HildonStackableWindow.
272 * Return value: A #HildonStackableWindow
275 hildon_stackable_window_new (void)
277 HildonStackableWindow *newwindow = g_object_new (HILDON_TYPE_STACKABLE_WINDOW, NULL);
279 return GTK_WIDGET (newwindow);