49aafde5640090b3090619bffc5035c1f42f9ee9
[hildon] / hildon / hildon-program.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2006 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-program
27  * @short_description: Application abstraction in the Hildon framework.
28  * @see_also: #HildonWindow, #HildonStackableWindow
29  *
30  * #HildonProgram is an object used to represent an application running
31  * in the Hildon framework.
32  *
33  * Applications can have one or more #HildonWindow<!-- -->s. These
34  * can be registered in the #HildonProgram with hildon_program_add_window(),
35  * and can be unregistered similarly with hildon_program_remove_window().
36  *
37  * #HildonProgram provides the programmer with commodities such
38  * as applying a common toolbar and menu to all registered
39  * #HildonWindow<!-- -->s. This is done with hildon_program_set_common_menu(),
40  * hildon_program_set_common_app_menu() and hildon_program_set_common_toolbar().
41  *
42  * #HildonProgram is also used to apply program-wide properties that
43  * are specific to the Hildon framework. For instance
44  * hildon_program_set_can_hibernate() sets whether or not an application
45  * can be set to hibernate by the Hildon task navigator, in situations of
46  * low memory.
47  *
48  * <example>
49  * <programlisting>
50  * HildonProgram *program;
51  * HildonWindow *window1;
52  * HildonWindow *window2;
53  * GtkToolbar *common_toolbar, *window_specific_toolbar;
54  * HildonAppMenu *menu;
55  * <!-- -->
56  * program = HILDON_PROGRAM (hildon_program_get_instance ());
57  * <!-- -->
58  * window1 = HILDON_WINDOW (hildon_window_new ());
59  * window2 = HILDON_WINDOW (hildon_window_new ());
60  * <!-- -->
61  * common_toolbar = create_common_toolbar ();
62  * window_specific_toolbar = create_window_specific_toolbar ();
63  * <!-- -->
64  * menu = create_menu ();
65  * <!-- -->
66  * hildon_program_add_window (program, window1);
67  * hildon_program_add_window (program, window2);
68  * <!-- -->
69  * hildon_program_set_common_app_menu (program, menu);
70  * <!-- -->
71  * hildon_program_set_common_toolbar (program, common_toolbar);
72  * hildon_window_add_toolbar (window1, window_specific_toolbar);
73  * <!-- -->
74  * hildon_program_set_can_hibernate (program, TRUE);
75  * </programlisting>
76  * </example>
77  */
78
79 #undef                                          HILDON_DISABLE_DEPRECATED
80
81 #ifdef                                          HAVE_CONFIG_H
82 #include                                        <config.h>
83 #endif
84
85 #include                                        <X11/Xatom.h>
86
87 #include                                        "hildon-program.h"
88 #include                                        "hildon-program-private.h"
89 #include                                        "hildon-window-private.h"
90 #include                                        "hildon-window-stack.h"
91 #include                                        "hildon-app-menu-private.h"
92
93 static void
94 hildon_program_init                             (HildonProgram *self);
95
96 static void
97 hildon_program_finalize                         (GObject *self);
98
99 static void
100 hildon_program_class_init                       (HildonProgramClass *self);
101
102 static void
103 hildon_program_get_property                     (GObject *object, 
104                                                  guint property_id,
105                                                  GValue *value, 
106                                                  GParamSpec *pspec);
107 static void
108 hildon_program_set_property                     (GObject *object, 
109                                                  guint property_id,
110                                                  const GValue *value, 
111                                                  GParamSpec *pspec);
112
113 enum
114 {
115     PROP_0,
116     PROP_IS_TOPMOST,
117     PROP_KILLABLE
118 };
119
120 GType G_GNUC_CONST
121 hildon_program_get_type                         (void)
122 {
123     static GType program_type = 0;
124
125     if (! program_type)
126     {
127         static const GTypeInfo program_info =
128         {
129             sizeof (HildonProgramClass),
130             NULL,       /* base_init */
131             NULL,       /* base_finalize */
132             (GClassInitFunc) hildon_program_class_init,
133             NULL,       /* class_finalize */
134             NULL,       /* class_data */
135             sizeof (HildonProgram),
136             0,  /* n_preallocs */
137             (GInstanceInitFunc) hildon_program_init,
138         };
139         program_type = g_type_register_static(G_TYPE_OBJECT,
140                 "HildonProgram", &program_info, 0);
141     }
142     return program_type;
143 }
144
145 static void
146 hildon_program_init                             (HildonProgram *self)
147 {
148     HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (self);
149     g_assert (priv);
150     
151     priv->killable = FALSE;
152     priv->window_count = 0;
153     priv->is_topmost = FALSE;
154     priv->window_group = GDK_WINDOW_XID (gdk_display_get_default_group (gdk_display_get_default()));
155     priv->common_menu = NULL;
156     priv->common_app_menu = NULL;
157     priv->common_toolbar = NULL;
158     priv->windows = NULL;
159 }
160
161 static void
162 hildon_program_finalize                         (GObject *self)
163 {
164     HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (HILDON_PROGRAM (self));
165     g_assert (priv);
166     
167     if (priv->common_toolbar)
168     {
169         g_object_unref (priv->common_toolbar);
170         priv->common_toolbar = NULL;
171     }
172
173     if (priv->common_menu)
174     {
175         g_object_unref (priv->common_menu);
176         priv->common_menu = NULL;
177     }
178 }
179
180 static void
181 hildon_program_class_init                       (HildonProgramClass *self)
182 {
183     GObjectClass *object_class = G_OBJECT_CLASS (self);
184
185     g_type_class_add_private (self, sizeof (HildonProgramPrivate));
186
187     /* Set up object virtual functions */
188     object_class->finalize      = hildon_program_finalize;
189     object_class->set_property  = hildon_program_set_property;
190     object_class->get_property  = hildon_program_get_property;
191
192     /* Install properties */
193
194     /**
195      * HildonProgram:is-topmost:
196      *
197      * Whether one of the program's window or dialog currently
198      * is activated by window manager. 
199      */
200     g_object_class_install_property (object_class, PROP_IS_TOPMOST,
201                 g_param_spec_boolean ("is-topmost",
202                 "Is top-most",
203                 "Whether one of the program's window or dialog currently "
204                 "is activated by window manager",
205                 FALSE,
206                 G_PARAM_READABLE)); 
207
208     /**
209      * HildonProgram:can-hibernate:
210      *
211      * Whether the program should be set to hibernate by the Task
212      * Navigator in low memory situation.
213      */
214     g_object_class_install_property (object_class, PROP_KILLABLE,
215                 g_param_spec_boolean ("can-hibernate",
216                 "Can hibernate",
217                 "Whether the program should be set to hibernate by the Task "
218                 "Navigator in low memory situation",
219                 FALSE,
220                 G_PARAM_READWRITE)); 
221     return;
222 }
223
224 static void
225 hildon_program_set_property                     (GObject *object, 
226                                                  guint property_id,
227                                                  const GValue *value, 
228                                                  GParamSpec *pspec)
229 {
230     switch (property_id) {
231
232         case PROP_KILLABLE:
233             hildon_program_set_can_hibernate (HILDON_PROGRAM (object), g_value_get_boolean (value));
234             break;
235             
236         default:
237             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
238             break;
239     }
240
241 }
242
243 static void
244 hildon_program_get_property                     (GObject *object, 
245                                                  guint property_id,
246                                                  GValue *value, 
247                                                  GParamSpec *pspec)
248 {
249     HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (object);
250     g_assert (priv);
251
252     switch (property_id)
253     {
254         case PROP_KILLABLE:
255             g_value_set_boolean (value, priv->killable);
256             break;
257
258         case PROP_IS_TOPMOST:
259             g_value_set_boolean (value, priv->is_topmost);
260             break;
261
262         default:
263             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
264             break;
265     }
266 }
267
268 /**
269  * hildon_program_pop_window_stack:
270  * @self: A #HildonProgram
271  *
272  * Pops a window from the stack.
273  *
274  * Deprecated: Use hildon_window_stack_pop() instead
275  *
276  * Returns: A #HildonStackableWindow, or %NULL
277  *
278  * Since: 2.2
279  */
280 HildonStackableWindow *
281 hildon_program_pop_window_stack                 (HildonProgram *self)
282 {
283     HildonWindowStack *stack = hildon_window_stack_get_default ();
284     GtkWidget *win = hildon_window_stack_pop_1 (stack);
285     g_warning ("%s: this function is deprecated. Use hildon_window_stack_pop() instead", __FUNCTION__);
286     return win ? HILDON_STACKABLE_WINDOW (win) : NULL;
287 }
288
289 /**
290  * hildon_program_peek_window_stack:
291  * @self: A #HildonProgram
292  *
293  * Deprecated: Use hildon_window_stack_peek() instead
294  *
295  * Returns: A #HildonStackableWindow, or %NULL
296  *
297  * Since: 2.2
298  */
299 HildonStackableWindow *
300 hildon_program_peek_window_stack                (HildonProgram *self)
301 {
302     HildonWindowStack *stack = hildon_window_stack_get_default ();
303     GtkWidget *win = hildon_window_stack_peek (stack);
304     g_warning ("%s: this function is deprecated. Use hildon_window_stack_peek() instead", __FUNCTION__);
305     return win ? HILDON_STACKABLE_WINDOW (win) : NULL;
306 }
307
308 /* Utilities */
309 static gint 
310 hildon_program_window_list_compare              (gconstpointer window_a, 
311                                                  gconstpointer window_b)
312 {
313     g_return_val_if_fail (HILDON_IS_WINDOW(window_a) && 
314                           HILDON_IS_WINDOW(window_b), 1);
315
316     return window_a != window_b;
317 }
318
319 /*
320  * foreach function, checks if a window is topmost and acts consequently
321  */
322 static void
323 hildon_program_window_list_is_is_topmost        (gpointer data, 
324                                                  gpointer window_id_)
325 {
326     if (data && HILDON_IS_WINDOW (data))
327     {
328         HildonWindow *window = HILDON_WINDOW (data);
329         Window window_id = * (Window*)window_id_;
330
331         hildon_window_update_topmost (window, window_id);
332     }
333 }
334
335 /*
336  * Check the _MB_CURRENT_APP_WINDOW on the root window, and update
337  * the top_most status accordingly
338  */
339 static void
340 hildon_program_update_top_most                  (HildonProgram *program)
341 {
342     gboolean is_topmost;
343     Window active_window;
344     HildonProgramPrivate *priv;
345
346     priv = HILDON_PROGRAM_GET_PRIVATE (program);
347     g_assert (priv);
348     
349     active_window = hildon_window_get_active_window();
350     is_topmost = FALSE;
351
352     if (active_window)
353     {
354       gint xerror;
355       XWMHints *wm_hints;
356       
357       gdk_error_trap_push ();
358       wm_hints = XGetWMHints (GDK_DISPLAY (), active_window);
359       xerror = gdk_error_trap_pop ();
360       if (xerror)
361       {
362         if (wm_hints)
363           XFree (wm_hints);
364         return;
365       }
366
367       if (wm_hints)
368       {
369         is_topmost = (wm_hints->window_group == priv->window_group);
370         XFree (wm_hints);
371       }
372     }
373
374     /* Send notification if is_topmost has changed */
375     if (!priv->is_topmost != !is_topmost)
376     {
377       priv->is_topmost = is_topmost;
378       g_object_notify (G_OBJECT (program), "is-topmost");
379     }
380
381     /* Check each window if it was is_topmost */
382     g_slist_foreach (priv->windows, 
383             (GFunc)hildon_program_window_list_is_is_topmost, &active_window);
384 }
385
386 /*
387  * We keep track of the _MB_CURRENT_APP_WINDOW property on the root window,
388  * to detect when a window belonging to this program was is_topmost. This
389  * is based on the window group WM hint.
390  */
391 static GdkFilterReturn
392 hildon_program_root_window_event_filter         (GdkXEvent *xevent,
393                                                  GdkEvent *event,
394                                                  gpointer data)
395 {
396     XAnyEvent *eventti = xevent;
397     HildonProgram *program = HILDON_PROGRAM (data);
398     Atom active_app_atom =
399             XInternAtom (GDK_DISPLAY (), "_MB_CURRENT_APP_WINDOW", False);
400
401     if (eventti->type == PropertyNotify)
402     {
403         XPropertyEvent *pevent = xevent;
404
405         if (pevent->atom == active_app_atom)
406         {
407             hildon_program_update_top_most (program);
408         }
409     }
410
411     return GDK_FILTER_CONTINUE;
412 }
413
414 /* 
415  * Checks if the window is the topmost window of the program and in
416  * that case forces the window to take the common toolbar.
417  */
418 static void
419 hildon_program_common_toolbar_topmost_window    (gpointer window, 
420                                                  gpointer data)
421 {
422     if (HILDON_IS_WINDOW (window) && hildon_window_get_is_topmost (HILDON_WINDOW (window)))
423         hildon_window_take_common_toolbar (HILDON_WINDOW (window));
424 }
425
426 /**
427  * hildon_program_get_instance:
428  *
429  * Returns the #HildonProgram for the current process. The object is
430  * created on the first call. Note that you're not supposed to unref
431  * the returned object since it's not reffed in the first place.
432  *
433  * Return value: the #HildonProgram.
434  **/
435 HildonProgram*
436 hildon_program_get_instance                     (void)
437 {
438     static HildonProgram *program = NULL;
439
440     if (! program)
441     {
442         program = g_object_new (HILDON_TYPE_PROGRAM, NULL);
443     }
444
445     return program;
446 }
447
448 /**
449  * hildon_program_add_window:
450  * @self: The #HildonProgram to which the window should be registered
451  * @window: A #HildonWindow to be added
452  *
453  * Registers a #HildonWindow as belonging to a given #HildonProgram. This
454  * allows to apply program-wide settings as all the registered windows,
455  * such as hildon_program_set_common_menu(), hildon_program_set_common_app_menu()
456  * and hildon_program_set_common_toolbar().
457  **/
458 void
459 hildon_program_add_window                       (HildonProgram *self, 
460                                                  HildonWindow *window)
461 {
462     HildonProgramPrivate *priv;
463     
464     g_return_if_fail (HILDON_IS_PROGRAM (self));
465     g_return_if_fail (HILDON_IS_WINDOW (window));
466     
467     priv = HILDON_PROGRAM_GET_PRIVATE (self);
468     g_assert (priv);
469
470     if (g_slist_find_custom (priv->windows, window,
471            hildon_program_window_list_compare) )
472     {
473         /* We already have that window */
474         return;
475     }
476
477     if (!priv->window_count)
478     {
479         hildon_program_update_top_most (self);
480         
481         /* Now that we have a window we should start keeping track of
482          * the root window */
483         gdk_window_set_events (gdk_get_default_root_window (),
484                 gdk_window_get_events (gdk_get_default_root_window ()) | GDK_PROPERTY_CHANGE_MASK);
485
486         gdk_window_add_filter (gdk_get_default_root_window (),
487                 hildon_program_root_window_event_filter, self );
488     }
489     
490     hildon_window_set_can_hibernate_property (window, &priv->killable);
491
492     hildon_window_set_program (window, G_OBJECT (self));
493
494     priv->windows = g_slist_append (priv->windows, window);
495     priv->window_count ++;
496 }
497
498 /**
499  * hildon_program_remove_window:
500  * @self: The #HildonProgram to which the window should be unregistered
501  * @window: The #HildonWindow to unregister
502  *
503  * Used to unregister a window from the program. Subsequent calls to
504  * hildon_program_set_common_menu(), hildon_program_set_common_app_menu()
505  * and hildon_program_set_common_toolbar() will not affect the window.
506  **/
507 void
508 hildon_program_remove_window                    (HildonProgram *self, 
509                                                  HildonWindow *window)
510 {
511     HildonProgramPrivate *priv;
512     
513     g_return_if_fail (HILDON_IS_PROGRAM (self));
514     g_return_if_fail (HILDON_IS_WINDOW (window));
515     
516     priv = HILDON_PROGRAM_GET_PRIVATE (self);
517     g_assert (priv);
518     
519     g_return_if_fail (g_slist_find (priv->windows, window));
520
521     hildon_window_unset_program (window);
522
523     priv->windows = g_slist_remove (priv->windows, window);
524
525     priv->window_count --;
526
527     if (! priv->window_count)
528         gdk_window_remove_filter (gdk_get_default_root_window(),
529                 hildon_program_root_window_event_filter,
530                 self);
531 }
532
533 /**
534  * hildon_program_set_can_hibernate:
535  * @self: The #HildonProgram which can hibernate or not
536  * @can_hibernate: whether or not the #HildonProgram can hibernate
537  *
538  * Used to set whether or not the Hildon task navigator should
539  * be able to set the program to hibernation in case of low memory
540  **/
541 void
542 hildon_program_set_can_hibernate                (HildonProgram *self, 
543                                                  gboolean can_hibernate)
544 {
545     HildonProgramPrivate *priv;
546     
547     g_return_if_fail (HILDON_IS_PROGRAM (self));
548     
549     priv = HILDON_PROGRAM_GET_PRIVATE (self);
550     g_assert (priv);
551
552     if (priv->killable != can_hibernate)
553     {
554         g_slist_foreach (priv->windows, 
555                 (GFunc) hildon_window_set_can_hibernate_property, &can_hibernate);
556     }
557
558     priv->killable = can_hibernate;
559 }
560
561 /**
562  * hildon_program_get_can_hibernate:
563  * @self: The #HildonProgram which can hibernate or not
564  *
565  * Returns whether the #HildonProgram is set to be support hibernation
566  * from the Hildon task navigator
567  *
568  * Return value: %TRUE if the program can hibernate, %FALSE otherwise.
569  **/
570 gboolean
571 hildon_program_get_can_hibernate                (HildonProgram *self)
572 {
573     HildonProgramPrivate *priv;
574     
575     g_return_val_if_fail (HILDON_IS_PROGRAM (self), FALSE);
576    
577     priv = HILDON_PROGRAM_GET_PRIVATE (self);
578     g_assert (priv);
579
580     return priv->killable;
581 }
582
583 /**
584  * hildon_program_set_common_menu:
585  * @self: The #HildonProgram in which the common menu should be used
586  * @menu: A #GtkMenu to use as common menu for the program
587  *
588  * Sets a #GtkMenu that will appear in all #HildonWindow<!-- -->s
589  * registered with the #HildonProgram. Only one common #GtkMenu can be
590  * set, further calls will detach the previous common #GtkMenu. A
591  * #HildonWindow can use its own #GtkMenu with
592  * hildon_window_set_menu()
593  *
594  * This method does not support #HildonAppMenu<!-- -->s. See
595  * hildon_program_set_common_app_menu() for that.
596  *
597  * Since: 2.2
598  **/
599 void
600 hildon_program_set_common_menu                  (HildonProgram *self, 
601                                                  GtkMenu *menu)
602 {
603     HildonProgramPrivate *priv;
604
605     g_return_if_fail (HILDON_IS_PROGRAM (self));
606
607     priv = HILDON_PROGRAM_GET_PRIVATE (self);
608     g_assert (priv);
609
610     if (priv->common_menu)
611     {
612         if (GTK_WIDGET_VISIBLE (priv->common_menu))
613         {
614             gtk_menu_popdown (priv->common_menu);
615             gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->common_menu));
616         }
617
618         if (gtk_menu_get_attach_widget (priv->common_menu))
619         {
620             gtk_menu_detach (priv->common_menu);
621         }
622         else
623         {
624             g_object_unref (priv->common_menu);
625         }
626     }
627
628     priv->common_menu = menu;
629
630     if (priv->common_menu)
631     {
632         g_object_ref (menu);
633         gtk_object_sink (GTK_OBJECT (menu));
634         gtk_widget_show_all (GTK_WIDGET (menu));
635     }
636 }
637
638 /**
639  * hildon_program_get_common_menu:
640  * @self: The #HildonProgram from which to retrieve the common menu
641  *
642  * Returns the #GtkMenu that was set as common menu for this
643  * #HildonProgram.
644  *
645  * Return value: the #GtkMenu or %NULL of no common menu was set.
646  **/
647 GtkMenu*
648 hildon_program_get_common_menu                  (HildonProgram *self)
649 {
650     HildonProgramPrivate *priv;
651
652     g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL);
653
654     priv = HILDON_PROGRAM_GET_PRIVATE (self);
655     g_assert (priv);
656
657     return priv->common_menu;
658 }
659
660 /**
661  * hildon_program_set_common_app_menu:
662  * @self: The #HildonProgram in which the common menu should be used
663  * @menu: A #HildonAppMenu to use as common menu for the program
664  *
665  * Sets a #HildonAppMenu that will appear in all
666  * #HildonWindow<!-- -->s registered with the #HildonProgram. Only
667  * one common #HildonAppMenu can be set, further calls will detach the
668  * previous common #HildonAppMenu. A #HildonWindow can use its own
669  * #HildonAppMenu with hildon_window_set_app_menu()
670  *
671  * This method does not support #GtkMenu<!-- -->s. See
672  * hildon_program_set_common_menu() for that.
673  *
674  * Since: 2.2
675  **/
676 void
677 hildon_program_set_common_app_menu              (HildonProgram *self,
678                                                  HildonAppMenu *menu)
679 {
680     HildonProgramPrivate *priv;
681     HildonAppMenu *old_menu;
682
683     g_return_if_fail (HILDON_IS_PROGRAM (self));
684     g_return_if_fail (menu == NULL || HILDON_IS_APP_MENU (menu));
685
686     priv = HILDON_PROGRAM_GET_PRIVATE (self);
687     g_assert (priv);
688
689     old_menu = priv->common_app_menu;
690
691     /* Set new menu */
692     priv->common_app_menu = menu;
693     if (menu)
694         g_object_ref_sink (menu);
695
696     /* Hide and unref old menu */
697     if (old_menu) {
698         hildon_app_menu_set_parent_window (old_menu, NULL);
699         g_object_unref (old_menu);
700     }
701 }
702
703 /**
704  * hildon_program_get_common_app_menu:
705  * @self: The #HildonProgram from which to retrieve the common app menu
706  *
707  * Returns the #HildonAppMenu that was set as common menu for this
708  * #HildonProgram.
709  *
710  * Return value: the #HildonAppMenu or %NULL of no common app menu was
711  * set.
712  *
713  * Since: 2.2
714  **/
715 HildonAppMenu*
716 hildon_program_get_common_app_menu              (HildonProgram *self)
717 {
718     HildonProgramPrivate *priv;
719
720     g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL);
721
722     priv = HILDON_PROGRAM_GET_PRIVATE (self);
723     g_assert (priv);
724
725     return priv->common_app_menu;
726 }
727
728 /**
729  * hildon_program_set_common_toolbar:
730  * @self: The #HildonProgram in which the common toolbar should be used
731  * @toolbar: A #GtkToolbar to use as common toolbar for the program
732  *
733  * Sets a #GtkToolbar that will appear in all the #HildonWindow registered
734  * to the #HildonProgram. Only one common #GtkToolbar can be set, further
735  * call will detach the previous common #GtkToolbar. A #HildonWindow
736  * can use its own #GtkToolbar with hildon_window_add_toolbar(). Both
737  * #HildonProgram and #HildonWindow specific toolbars will be shown
738  **/
739 void
740 hildon_program_set_common_toolbar               (HildonProgram *self, 
741                                                  GtkToolbar *toolbar)
742 {
743     HildonProgramPrivate *priv;
744
745     g_return_if_fail (HILDON_IS_PROGRAM (self));
746
747     priv = HILDON_PROGRAM_GET_PRIVATE (self);
748     g_assert (priv);
749
750     if (priv->common_toolbar)
751     {
752         if (priv->common_toolbar->parent)
753         {
754             gtk_container_remove (GTK_CONTAINER (priv->common_toolbar->parent), 
755                                   priv->common_toolbar);
756         }
757         
758         g_object_unref (priv->common_toolbar);
759     }
760
761     priv->common_toolbar = GTK_WIDGET (toolbar);
762
763     if (priv->common_toolbar)
764     {
765         g_object_ref (priv->common_toolbar);
766         gtk_object_sink (GTK_OBJECT (priv->common_toolbar) );
767     }
768
769     /* if the program is the topmost we have to update the common
770        toolbar right now for the topmost window */
771     if (priv->is_topmost)
772       {
773         g_slist_foreach (priv->windows, 
774                          (GFunc) hildon_program_common_toolbar_topmost_window, NULL);
775       }
776 }
777
778 /**
779  * hildon_program_get_common_toolbar:
780  * @self: The #HildonProgram from which to retrieve the common toolbar
781  *
782  * Returns the #GtkToolbar that was set as common toolbar for this
783  * #HildonProgram.
784  *
785  * Return value: the #GtkToolbar or %NULL of no common toolbar was
786  * set.
787  **/
788 GtkToolbar*
789 hildon_program_get_common_toolbar               (HildonProgram *self)
790 {
791     HildonProgramPrivate *priv;
792
793     g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL);
794
795     priv = HILDON_PROGRAM_GET_PRIVATE (self);
796     g_assert (priv);
797
798     return priv->common_toolbar ? GTK_TOOLBAR (priv->common_toolbar) : NULL;
799 }
800
801 /**
802  * hildon_program_get_is_topmost:
803  * @self: A #HildonWindow
804  *
805  * Returns whether one of the program's windows or dialogs is
806  * currently activated by the window manager.
807  *
808  * Return value: %TRUE if a window or dialog is topmost, %FALSE
809  * otherwise.
810  **/
811 gboolean
812 hildon_program_get_is_topmost                   (HildonProgram *self)
813 {
814     HildonProgramPrivate *priv;
815
816     g_return_val_if_fail (HILDON_IS_PROGRAM (self), FALSE);
817     
818     priv = HILDON_PROGRAM_GET_PRIVATE (self);
819     g_assert (priv);
820
821     return priv->is_topmost;
822 }
823
824 /**
825  * hildon_program_go_to_root_window:
826  * @self: A #HildonProgram
827  *
828  * Goes to the root window of the stack.
829  *
830  * Deprecated: See #HildonWindowStack
831  *
832  * Since: 2.2
833  */
834 void
835 hildon_program_go_to_root_window                (HildonProgram *self)
836 {
837     HildonWindowStack *stack = hildon_window_stack_get_default ();
838     gint n = hildon_window_stack_size (stack);
839     g_warning ("%s: this function is deprecated. Use hildon_window_stack_pop() instead.", __FUNCTION__);
840     if (n > 1) {
841         hildon_window_stack_pop (stack, n-1, NULL);
842     }
843 }