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.
37 #include <X11/Xatom.h>
38 #include "hildon-stackable-window.h"
39 #include "hildon-program.h"
40 #include "hildon-window-private.h"
41 #include "hildon-program-private.h"
43 typedef struct _HildonStackableWindowPrivate HildonStackableWindowPrivate;
45 struct _HildonStackableWindowPrivate
50 #define HILDON_STACKABLE_WINDOW_GET_PRIVATE(obj) \
51 (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
52 HILDON_TYPE_STACKABLE_WINDOW, HildonStackableWindowPrivate))
54 G_DEFINE_TYPE (HildonStackableWindow, hildon_stackable_window, HILDON_TYPE_WINDOW);
57 hildon_stackable_window_set_going_home (HildonStackableWindow *self,
60 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
61 priv->going_home = going_home;
65 hildon_stackable_window_get_going_home (HildonStackableWindow *self)
67 HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self);
68 return priv->going_home;
72 get_window_list (GtkWidget *widget)
74 HildonWindowPrivate *wpriv;
75 HildonProgramPrivate *ppriv;
76 GSList *retval = NULL;
77 g_return_val_if_fail (widget != NULL, NULL);
79 wpriv = HILDON_WINDOW_GET_PRIVATE (widget);
80 g_assert (wpriv != NULL);
84 ppriv = HILDON_PROGRAM_GET_PRIVATE (wpriv->program);
85 g_assert (ppriv != NULL);
86 retval = ppriv->windows;
93 get_last_window (GtkWidget *widget)
95 GtkWidget *retval = NULL;
96 GSList *windows = get_window_list (widget);
99 g_return_val_if_fail (windows != NULL, NULL);
101 /* Go to the end of the window list */
102 while (windows->next != NULL)
105 windows = windows->next;
108 if ((windows->data == widget) && (last != NULL))
110 retval = GTK_WIDGET (last->data);
117 hildon_stackable_window_map (GtkWidget *widget)
121 if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->map)
122 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->map (widget);
124 lastwin = get_last_window (widget);
126 if (HILDON_IS_STACKABLE_WINDOW (lastwin) && GTK_WIDGET_VISIBLE (lastwin))
127 gtk_widget_hide (lastwin);
131 hildon_stackable_window_unmap (GtkWidget *widget)
135 if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->unmap)
136 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->unmap (widget);
138 lastwin = get_last_window (widget);
140 if (HILDON_IS_STACKABLE_WINDOW (lastwin) && !GTK_WIDGET_VISIBLE (lastwin) &&
141 !hildon_stackable_window_get_going_home (HILDON_STACKABLE_WINDOW (widget)))
143 gtk_widget_show (lastwin);
148 hildon_stackable_window_unset_program (HildonWindow *hwin)
150 GSList *windows = get_window_list (GTK_WIDGET (hwin));
151 gint l = g_slist_length (windows);
152 GtkWidget *nextwin = GTK_WIDGET (g_slist_nth_data (windows, l - 2));
154 if (HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->unset_program)
155 HILDON_WINDOW_CLASS (hildon_stackable_window_parent_class)->unset_program (hwin);
157 if (HILDON_IS_STACKABLE_WINDOW (nextwin) && !GTK_WIDGET_VISIBLE (nextwin) &&
158 !hildon_stackable_window_get_going_home (HILDON_STACKABLE_WINDOW (nextwin)))
160 gtk_widget_show (nextwin);
165 hildon_stackable_window_realize (GtkWidget *widget)
170 GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->realize (widget);
172 /* Set the window type to "_HILDON_WM_WINDOW_TYPE_STACKABLE", to allow the WM to manage
174 display = gdk_drawable_get_display (widget->window);
175 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_STACKABLE");
176 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
177 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
178 XA_ATOM, 32, PropModeAppend,
183 hildon_stackable_window_class_init (HildonStackableWindowClass *klass)
185 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
186 HildonWindowClass *window_class = HILDON_WINDOW_CLASS (klass);
188 widget_class->map = hildon_stackable_window_map;
189 widget_class->unmap = hildon_stackable_window_unmap;
190 widget_class->realize = hildon_stackable_window_realize;
192 window_class->unset_program = hildon_stackable_window_unset_program;
194 g_type_class_add_private (klass, sizeof (HildonStackableWindowPrivate));
198 hildon_stackable_window_init (HildonStackableWindow *self)
200 hildon_stackable_window_set_going_home (self, FALSE);
204 * hildon_stackable_window_new:
206 * Creates a new #HildonStackableWindow.
208 * Return value: A #HildonStackableWindow
211 hildon_stackable_window_new (void)
213 HildonStackableWindow *newwindow = g_object_new (HILDON_TYPE_STACKABLE_WINDOW, NULL);
215 return GTK_WIDGET (newwindow);
219 * hildon_stackable_window_go_to_root_window:
220 * @self: A #HildonStackableWindow
222 * Will pop out all the stackable windows in the @HildonProgram but the
223 * first one, which can be considered as the "home" window.
226 hildon_stackable_window_go_to_root_window (HildonStackableWindow *self)
228 g_return_if_fail (HILDON_IS_STACKABLE_WINDOW (self));
230 GSList *windows = get_window_list (GTK_WIDGET (self));
232 HildonWindow *rootwin = HILDON_WINDOW (g_slist_nth_data (windows, 0));
234 g_return_if_fail (rootwin != NULL);
236 tmp = g_slist_nth (windows, 1);
239 if (HILDON_IS_STACKABLE_WINDOW (tmp->data))
241 HildonStackableWindow *win = HILDON_STACKABLE_WINDOW (tmp->data);
242 hildon_stackable_window_set_going_home (win, TRUE);
243 gtk_widget_destroy (GTK_WIDGET (win));
246 tmp = g_slist_nth (windows, 1);
249 if (!GTK_WIDGET_VISIBLE (rootwin))
250 gtk_widget_show (GTK_WIDGET (rootwin));