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, use hildon_program_add_window(). Once
36 * you show the new window, the previous one will be automatically
37 * hidden. When the new window is destroyed, the previous one will
43 * show_first_window (void)
45 * HildonProgram *program;
48 * program = hildon_program_get_instance ();
49 * win1 = hildon_stackable_window_new ();
51 * // ... configure first window
53 * hildon_program_add_window (program, HILDON_WINDOW (win1));
54 * gtk_widget_show (win1);
58 * show_second_window (void)
60 * HildonProgram *program;
63 * program = hildon_program_get_instance ();
64 * win2 = hildon_stackable_window_new ();
66 * // ... configure second window
68 * hildon_program_add_window (program, HILDON_WINDOW (win2));
69 * gtk_widget_show (win2);
76 #include <X11/Xatom.h>
77 #include "hildon-stackable-window.h"
78 #include "hildon-stackable-window-private.h"
79 #include "hildon-program.h"
80 #include "hildon-window-private.h"
81 #include "hildon-program-private.h"
83 G_DEFINE_TYPE (HildonStackableWindow, hildon_stackable_window, HILDON_TYPE_WINDOW);
86 hildon_stackable_window_set_going_home (HildonStackableWindow *self,
89 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
90 priv->going_home = going_home;
93 gboolean G_GNUC_INTERNAL
94 hildon_stackable_window_get_going_home (HildonStackableWindow *self)
96 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
97 return priv->going_home;
101 get_window_list (GtkWidget *widget)
103 HildonWindowPrivate *wpriv;
104 HildonProgramPrivate *ppriv;
105 GSList *retval = NULL;
106 g_return_val_if_fail (widget != NULL, NULL);
108 wpriv = HILDON_WINDOW_GET_PRIVATE (widget);
109 g_assert (wpriv != NULL);
113 ppriv = HILDON_PROGRAM_GET_PRIVATE (wpriv->program);
114 g_assert (ppriv != NULL);
115 retval = ppriv->windows;
122 get_previous_window_if_last (GtkWidget *widget)
124 GtkWidget *retval = NULL;
125 GSList *iter = get_window_list (widget);
126 GSList *previous = NULL;
128 /* Return NULL if the window hasn't been added to the HildonProgram */
134 /* Go to the end of the window list */
135 while (iter->next != NULL)
141 if ((iter->data == widget) && (previous != NULL))
143 retval = GTK_WIDGET (previous->data);
150 hildon_stackable_window_map (GtkWidget *widget)
152 GtkWidget *previous = get_previous_window_if_last (widget);
154 if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->map)
155 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->map (widget);
157 if (HILDON_IS_STACKABLE_WINDOW (previous) && GTK_WIDGET_VISIBLE (previous))
158 gtk_widget_hide (previous);
162 hildon_stackable_window_unmap (GtkWidget *widget)
164 GtkWidget *previous = get_previous_window_if_last (widget);
166 if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->unmap)
167 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->unmap (widget);
169 if (HILDON_IS_STACKABLE_WINDOW (previous) && !GTK_WIDGET_VISIBLE (previous) &&
170 !hildon_stackable_window_get_going_home (HILDON_STACKABLE_WINDOW (widget)))
172 gtk_widget_show (previous);
177 hildon_stackable_window_unset_program (HildonWindow *hwin)
179 GtkWidget *previous = get_previous_window_if_last (GTK_WIDGET (hwin));
181 if (HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->unset_program)
182 HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->unset_program (hwin);
184 if (HILDON_IS_STACKABLE_WINDOW (previous) && !GTK_WIDGET_VISIBLE (previous) &&
185 !hildon_stackable_window_get_going_home (HILDON_STACKABLE_WINDOW (hwin)))
187 gtk_widget_show (previous);
192 hildon_stackable_window_set_main_menu (HildonStackableWindow *self,
195 HildonStackableWindowPrivate *priv;
197 g_return_if_fail (HILDON_IS_STACKABLE_WINDOW (self));
198 g_return_if_fail (!menu || HILDON_IS_APP_MENU (menu));
199 priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
201 /* Remove reference to old menu */
203 g_object_unref (priv->app_menu);
206 priv->app_menu = menu;
208 g_object_ref (priv->app_menu);
212 hildon_stackable_window_toggle_menu (HildonWindow *self,
216 HildonStackableWindowPrivate *priv;
218 g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (self), FALSE);
219 priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
220 g_assert (priv != NULL);
224 if (GTK_WIDGET_MAPPED (GTK_WIDGET (priv->app_menu)))
225 gtk_widget_hide (GTK_WIDGET (priv->app_menu));
227 gtk_widget_show (GTK_WIDGET (priv->app_menu));
231 else if (HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->toggle_menu)
233 return HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->toggle_menu (self, button, time);
242 hildon_stackable_window_realize (GtkWidget *widget)
247 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->realize (widget);
249 /* Set the window type to "_HILDON_WM_WINDOW_TYPE_STACKABLE", to allow the WM to manage
251 display = gdk_drawable_get_display (widget->window);
252 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_STACKABLE");
253 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
254 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
255 XA_ATOM, 32, PropModeAppend,
260 hildon_stackable_window_delete_event (GtkWidget *widget,
263 GSList *list = get_window_list (widget);
264 list = g_slist_find (list, widget);
266 /* Ignore the delete event if this is not the topmost window */
267 if (list != NULL && list->next != NULL)
269 else if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event)
270 return GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event (widget, event);
276 hildon_stackable_window_finalize (GObject *object)
278 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (object);
280 if (priv->app_menu) {
281 gtk_widget_destroy (GTK_WIDGET (priv->app_menu));
286 hildon_stackable_window_class_init (HildonStackableWindowClass *klass)
288 GObjectClass *obj_class = G_OBJECT_CLASS (klass);
289 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
290 HildonWindowClass *window_class = HILDON_WINDOW_CLASS (klass);
292 obj_class->finalize = hildon_stackable_window_finalize;
294 widget_class->map = hildon_stackable_window_map;
295 widget_class->unmap = hildon_stackable_window_unmap;
296 widget_class->realize = hildon_stackable_window_realize;
297 widget_class->delete_event = hildon_stackable_window_delete_event;
299 window_class->unset_program = hildon_stackable_window_unset_program;
300 window_class->toggle_menu = hildon_stackable_window_toggle_menu;
302 g_type_class_add_private (klass, sizeof (HildonStackableWindowPrivate));
306 hildon_stackable_window_init (HildonStackableWindow *self)
308 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
310 priv->going_home = FALSE;
311 priv->app_menu = NULL;
315 * hildon_stackable_window_new:
317 * Creates a new #HildonStackableWindow.
319 * Return value: A #HildonStackableWindow
322 hildon_stackable_window_new (void)
324 HildonStackableWindow *newwindow = g_object_new (HILDON_TYPE_STACKABLE_WINDOW, NULL);
326 return GTK_WIDGET (newwindow);