2 * This file is part of hildon-libs
4 * Copyright (C) 2005 Nokia Corporation.
6 * Contact: Luc Pionchon <luc.pionchon@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; either 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
28 #include <X11/Xatom.h>
29 #include "gtk-infoprint.h"
30 #include "hildon-defines.h"
31 #include "hildon-app.h"
33 #define INFOPRINT_MIN_WIDTH 39
34 #define INFOPRINT_MAX_WIDTH 334
35 #define BANNER_MIN_WIDTH 35
36 #define BANNER_MAX_WIDTH 375
37 #define DEFAULT_WIDTH 20
38 #define DEFAULT_HEIGHT 28 /* 44-8-8 = 28 */
39 #define WINDOW_WIDTH 600
40 #define MESSAGE_TIMEOUT 2500
41 #define GTK_INFOPRINT_STOCK "gtk-infoprint"
42 #define GTK_INFOPRINT_ICON_THEME "qgn_note_infoprint"
44 #define BANNER_PROGRESSBAR_MIN_WIDTH 83
45 #define INFOPRINT_MIN_SIZE 50
46 #define INFOPRINT_WINDOW_Y 73
47 #define INFOPRINT_WINDOW_FS_Y 20
48 #define INFOPRINT_WINDOW_X 15
51 #define DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a"
53 static gboolean gtk_infoprint_temporal_wrap_disable_flag = FALSE;
69 static GtkWidget *global_banner = NULL;
70 static GtkWidget *global_infoprint = NULL;
72 static GQueue *cbanner_queue = NULL;
73 static InfoprintState *current_ibanner = NULL;
74 static InfoprintState *current_pbanner = NULL;
75 static guint pbanner_refs = 0;
77 static gboolean compare_icons(GtkImage *image1, GtkImage *image2);
78 static void queue_new_cbanner(GtkWindow *parent,
81 static void gtk_msg_window_init(GtkWindow * parent, GQuark type,
82 const gchar * text, GtkWidget * main_item);
83 static gchar *three_lines_truncate(GtkWindow * parent,
85 gint * max_width, gint * resulting_lines);
87 static gboolean infoprint_idle_before_timer (GtkWidget *widget,
88 GdkEventExpose *event,
90 static gboolean infoprint_start_timer (gpointer data);
92 /* Getters/initializers for needed quarks */
93 static GQuark banner_quark(void)
95 static GQuark quark = 0;
98 quark = g_quark_from_static_string("banner");
103 static GQuark infoprint_quark(void)
105 static GQuark quark = 0;
108 quark = g_quark_from_static_string("infoprint");
113 static GQuark type_quark(void)
115 static GQuark quark = 0;
118 quark = g_quark_from_static_string("Message window type");
123 static GQuark label_quark(void)
125 static GQuark quark = 0;
128 quark = g_quark_from_static_string("Message window text");
133 static GQuark item_quark(void)
135 static GQuark quark = 0;
139 g_quark_from_static_string("Message window graphical item");
144 static GQuark confirmation_banner_quark(void)
146 static GQuark quark = 0;
149 quark = g_quark_from_static_string("confirmation_banner");
154 /* Returns the infoprint/banner linked to the specific window */
155 static GtkWindow *gtk_msg_window_get(GtkWindow * parent, GQuark quark)
159 if (parent == NULL) {
160 if (quark == banner_quark()) {
161 return GTK_WINDOW(global_banner);
163 return GTK_WINDOW(global_infoprint);
166 return GTK_WINDOW(g_object_get_qdata(G_OBJECT(parent), quark));
169 /* Returns the given widget from banner type of message window.
170 This is used when the banner data is updated in later stage.
172 static GtkWidget *gtk_banner_get_widget(GtkWindow * parent,
175 GtkWindow *window = gtk_msg_window_get(parent, banner_quark());
179 GTK_WIDGET(g_object_get_qdata(G_OBJECT(window), widget_quark));
184 /* Timed destroy. Removing this callback is done in other place. */
185 static gboolean gtk_msg_window_destroy(gpointer pointer)
187 g_return_val_if_fail(GTK_IS_WINDOW(pointer), TRUE);
188 gtk_widget_destroy(GTK_WIDGET(pointer));
193 static gboolean gtk_msg_window_real_destroy(gpointer pointer)
198 g_return_val_if_fail(GTK_IS_WINDOW(pointer), TRUE);
200 parent = G_OBJECT(gtk_window_get_transient_for(GTK_WINDOW(pointer)));
201 quark = (GQuark) g_object_get_qdata((GObject *) pointer, type_quark());
203 if (quark == infoprint_quark() && current_ibanner) {
204 gtk_widget_unref(current_ibanner->main_item);
205 g_free(current_ibanner->text);
206 g_free(current_ibanner);
207 current_ibanner = NULL;
208 } else if (quark == banner_quark() && current_pbanner) {
210 * If the destroy signal is not emited via gkt_banner_close()
211 * (for example when the banner is being destroyed with the parent)
212 * the reference counter will have a value larger than 0 and the
213 * reference counter should be decremented.
216 if (pbanner_refs > 0)
219 gtk_widget_unref(current_pbanner->main_item);
220 g_free(current_pbanner->text);
221 g_free(current_pbanner);
222 current_pbanner = NULL;
223 } else if (quark == confirmation_banner_quark() &&
224 !g_queue_is_empty(cbanner_queue)) {
225 InfoprintState *cbanner = g_queue_pop_head(cbanner_queue);
227 gtk_widget_unref(cbanner->main_item);
228 g_free(cbanner->text);
231 if (!g_queue_is_empty(cbanner_queue)) {
232 cbanner = g_queue_peek_head(cbanner_queue);
233 gtk_msg_window_init(cbanner->parent, confirmation_banner_quark(),
234 cbanner->text, cbanner->main_item);
236 g_queue_free(cbanner_queue);
237 cbanner_queue = NULL;
242 g_object_set_qdata(parent, quark, NULL);
244 if (quark == banner_quark()) {
245 global_banner = NULL;
247 global_infoprint = NULL;
255 /* Get window ID of top window from _NET_ACTIVE_WINDOW property */
256 static Window get_active_window( void )
263 Atom atom_net_active = gdk_x11_get_xatom_by_name ("_NET_ACTIVE_WINDOW");
265 Window win_result = None;
266 guchar *data_return = NULL;
268 status = XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
269 atom_net_active, 0L, 16L,
270 0, XA_WINDOW, &realType, &format,
274 if ( status == Success && realType == XA_WINDOW
275 && format == 32 && n == 1 && data_return != NULL )
277 win_result = ((Window*) data_return)[0];
278 /* g_print("_NET_ACTIVE_WINDOW id %d\n", ((gint *)data_return)[0] );*/
287 /* Checks if a window is in fullscreen state or not */
288 static gboolean check_fullscreen_state( Window window )
292 int format, status, i;
293 guchar *data_return = NULL;
296 Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
297 Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN");
299 if ( window == None )
302 /* in some cases XGetWindowProperty seems to generate BadWindow,
303 so at the moment this function does not always work perfectly */
304 gdk_error_trap_push();
305 status = XGetWindowProperty(GDK_DISPLAY(), window,
306 atom_window_state, 0L, 1000000L,
307 0, XA_ATOM, &realType, &format,
308 &n, &extra, &data_return);
310 if (gdk_error_trap_pop())
313 if (status == Success && realType == XA_ATOM && format == 32 && n > 0)
316 if ( ((Atom*)data_return)[i] &&
317 ((Atom*)data_return)[i] == atom_fullscreen)
319 if (data_return) XFree(data_return);
332 compare_icons(GtkImage *image1, GtkImage *image2)
334 GtkImageType type = gtk_image_get_storage_type(image1);
335 gchar *name1, *name2;
336 const gchar *icon_name1, *icon_name2;
337 GtkIconSize size1, size2;
339 if (gtk_image_get_storage_type(image2) != type)
343 case GTK_IMAGE_STOCK:
344 gtk_image_get_stock(image1, &name1, &size1);
345 gtk_image_get_stock(image2, &name2, &size2);
346 return ((g_utf8_collate(name1, name2) == 0) && (size1 == size2));
347 case GTK_IMAGE_ICON_NAME:
348 gtk_image_get_icon_name(image1, &icon_name1, &size1);
349 gtk_image_get_icon_name(image2, &icon_name2, &size2);
350 return ((g_utf8_collate(icon_name1, icon_name2) == 0) && (size1 == size2));
351 case GTK_IMAGE_ANIMATION:
352 /* there is only one possible animation */
355 /* other types of icons are actually not even supported */
360 /* confirmation banners are queued so that all of them will
361 be shown eventually for the appropriate amount of time */
363 queue_new_cbanner(GtkWindow *parent, const gchar *text, GtkWidget *image)
365 InfoprintState *cbanner;
367 if (cbanner_queue == NULL)
368 cbanner_queue = g_queue_new();
370 /* identical consecutive cbanners are collapsed to just one cbanner */
371 if ((cbanner = g_queue_peek_tail(cbanner_queue)) != NULL &&
372 g_utf8_collate(cbanner->text, text) == 0 &&
373 compare_icons(GTK_IMAGE(image), GTK_IMAGE(cbanner->main_item))) {
374 g_source_remove(cbanner->timeout);
376 cbanner->timeout = g_timeout_add(MESSAGE_TIMEOUT,
377 gtk_msg_window_destroy,
379 g_signal_connect_swapped(cbanner->window, "destroy",
380 G_CALLBACK(g_source_remove),
381 GUINT_TO_POINTER(cbanner->timeout));
382 gtk_object_sink(GTK_OBJECT(image));
386 cbanner = g_new0(InfoprintState, 1);
387 cbanner->parent = parent;
388 cbanner->text = g_strdup(text);
389 cbanner->main_item = image;
390 gtk_widget_ref(cbanner->main_item);
392 g_queue_push_tail(cbanner_queue, cbanner);
394 if (g_queue_get_length(cbanner_queue) == 1)
395 gtk_msg_window_init(parent, confirmation_banner_quark(), text, image);
399 /* gtk_msg_window_init
401 * @parent -- The parent window
402 * @type -- The enumerated type of message window
403 * @text -- The displayed text
404 * @item -- The item to be loaded, or NULL if default
405 * (used only in INFOPRINT_WITH_ICON)
408 gtk_msg_window_init(GtkWindow * parent, GQuark type,
409 const gchar * text, GtkWidget * main_item)
418 g_return_if_fail((GTK_IS_WINDOW(parent) || parent == NULL));
420 if (type == banner_quark())
423 /* information banners: just reset the timeout if trying
424 to recreate the currently visible information banner */
425 if (type == infoprint_quark() && current_ibanner) {
427 /* caller is trying to recreate current information banner */
428 if (g_utf8_collate(current_ibanner->text, text) == 0 &&
429 compare_icons(GTK_IMAGE(main_item),
430 GTK_IMAGE(current_ibanner->main_item))) {
431 /* If previous timer has been created, replace it with a new one */
432 if (current_ibanner->timeout > 0) {
433 g_source_remove(current_ibanner->timeout);
434 current_ibanner->timeout = g_timeout_add(MESSAGE_TIMEOUT,
435 gtk_msg_window_destroy,
436 current_ibanner->window);
438 g_signal_connect_swapped(current_ibanner->window, "destroy",
439 G_CALLBACK(g_source_remove),
440 GUINT_TO_POINTER(current_ibanner->timeout));
442 gtk_object_sink(GTK_OBJECT(main_item));
446 /* If the timer has already been set -> remove it */
447 if (current_ibanner->timeout > 0)
448 g_source_remove(current_ibanner->timeout);
450 gtk_msg_window_destroy(current_ibanner->window);
453 if (type == banner_quark() && current_pbanner) {
454 if (g_utf8_collate(current_pbanner->text, text) == 0) {
455 if (GTK_IS_PROGRESS_BAR(main_item) &&
456 GTK_IS_PROGRESS_BAR(current_pbanner->main_item)) {
457 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(current_pbanner->main_item), 0.0);
458 gtk_object_sink(GTK_OBJECT(main_item));
460 } else if (GTK_IS_IMAGE(main_item) &&
461 GTK_IS_IMAGE(current_pbanner->main_item) &&
462 compare_icons(GTK_IMAGE(main_item),
463 GTK_IMAGE(current_pbanner->main_item))) {
464 gtk_object_sink(GTK_OBJECT(main_item));
470 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
471 gtk_window_set_accept_focus(GTK_WINDOW(window), FALSE);
472 g_signal_connect(window, "destroy", G_CALLBACK(gtk_msg_window_real_destroy), window);
474 hbox = gtk_hbox_new(FALSE, 5);
476 if (current_pbanner && type == banner_quark()) {
478 * The destroy substracts one from the reference counter,
479 * so adding one to keep the counter working
482 gtk_msg_window_destroy(current_pbanner->window);
486 gtk_window_set_transient_for(GTK_WINDOW(window), parent);
487 gtk_window_set_destroy_with_parent(GTK_WINDOW(window), TRUE);
489 g_object_set_qdata(G_OBJECT(parent), type, (gpointer) window);
491 if (type == banner_quark()) {
492 global_banner = window;
494 global_infoprint = window;
498 gtk_widget_realize(window);
500 if ((type == confirmation_banner_quark()) || (type == banner_quark()))
501 gtk_infoprint_temporal_wrap_disable_flag = TRUE;
503 if (type == banner_quark()) {
504 max_width = BANNER_MAX_WIDTH;
506 max_width = INFOPRINT_MAX_WIDTH;
509 if (parent == NULL) {
510 gdk_window_set_transient_for(GDK_WINDOW(window->window),
511 GDK_WINDOW(gdk_get_default_root_window()));
512 str = three_lines_truncate(GTK_WINDOW(window), text, &max_width, NULL);
514 str = three_lines_truncate(parent, text, &max_width, NULL);
517 gtk_infoprint_temporal_wrap_disable_flag = FALSE;
519 label = gtk_label_new(str);
522 if (max_width < INFOPRINT_MIN_WIDTH) {
523 gtk_widget_set_size_request(GTK_WIDGET(label),
524 (max_width < INFOPRINT_MIN_WIDTH) ?
525 INFOPRINT_MIN_WIDTH : -1,
529 if ((type == confirmation_banner_quark()) || (type == banner_quark()))
530 gtk_widget_set_name(label, "hildon-banner-label");
532 g_object_set_qdata(G_OBJECT(window), type_quark(), (gpointer) type);
533 g_object_set_qdata(G_OBJECT(window), label_quark(), (gpointer) label);
534 g_object_set_qdata(G_OBJECT(window), item_quark(),
535 (gpointer) main_item);
537 gtk_container_add(GTK_CONTAINER(window), hbox);
539 if (type == banner_quark()) {
540 gtk_box_pack_start_defaults(GTK_BOX(hbox), label);
542 if (GTK_IS_PROGRESS_BAR(main_item)) {
543 gtk_widget_set_size_request(GTK_WIDGET(main_item),
544 BANNER_PROGRESSBAR_MIN_WIDTH,
547 gtk_box_pack_start_defaults(GTK_BOX(hbox), main_item);
552 GTK_ALIGNMENT(gtk_alignment_new(0, 0, 0, 0));
553 gtk_widget_set_size_request(GTK_WIDGET(main_item),
556 gtk_container_add(GTK_CONTAINER(ali), GTK_WIDGET(main_item));
557 gtk_box_pack_start_defaults(GTK_BOX(hbox), GTK_WIDGET(ali));
559 gtk_box_pack_start_defaults(GTK_BOX(hbox), label);
562 gtk_window_set_default_size(GTK_WINDOW(window),
563 DEFAULT_WIDTH, DEFAULT_HEIGHT);
565 /* Positioning of the infoprint */
567 gint y = INFOPRINT_WINDOW_Y;
568 gint x = gdk_screen_width() + INFOPRINT_WINDOW_X;
570 /* Check if the active application is in fullscreen */
571 if( check_fullscreen_state(get_active_window()) )
572 y = INFOPRINT_WINDOW_FS_Y;
573 /* this should be fixed to use theme dependant infoprint border size */
575 gtk_window_move(GTK_WINDOW(window), x, y);
578 gdk_window_set_type_hint(window->window, GDK_WINDOW_TYPE_HINT_MESSAGE);
580 gtk_widget_show_all(window);
582 if (type == infoprint_quark()) {
583 current_ibanner = g_new0(InfoprintState, 1);
584 current_ibanner->parent = parent;
585 current_ibanner->window = window;
586 current_ibanner->text = g_strdup(text);
587 current_ibanner->main_item = main_item;
588 gtk_widget_ref(current_ibanner->main_item);
590 else if (type == banner_quark()) {
591 current_pbanner = g_new0(InfoprintState, 1);
592 current_pbanner->parent = parent;
593 current_pbanner->window = window;
594 current_pbanner->text = g_strdup(text);
595 current_pbanner->main_item = main_item;
596 gtk_widget_ref(current_pbanner->main_item);
599 /* If the type is an infoprint we set the timer after the expose-event */
600 if (type == infoprint_quark()) {
601 g_signal_connect_after(window, "expose-event",
602 G_CALLBACK(infoprint_idle_before_timer), NULL);
604 else if (type == confirmation_banner_quark()) {
605 InfoprintState *current_cbanner = g_queue_peek_head(cbanner_queue);
607 current_cbanner->window = window;
608 current_cbanner->timeout = g_timeout_add(MESSAGE_TIMEOUT,
609 gtk_msg_window_destroy,
610 current_cbanner->window);
611 g_signal_connect_swapped(window, "destroy",
612 G_CALLBACK(g_source_remove),
613 GUINT_TO_POINTER(current_cbanner->timeout));
617 static gchar *three_lines_truncate(GtkWindow * parent, const gchar * str,
618 gint * max_width, gint * resulting_lines)
620 gchar *result = NULL;
622 PangoContext *context;
627 if (GTK_IS_WIDGET(parent)) {
628 context = gtk_widget_get_pango_context(GTK_WIDGET(parent));
630 if (gdk_screen_get_default() != NULL) {
631 context = gdk_pango_context_get_for_screen
632 (gdk_screen_get_default());
634 g_print("GtkInfoprint : Could not get default screen.\n");
644 layout = pango_layout_new(context);
645 pango_layout_set_text(layout, str, -1);
646 if (gtk_infoprint_temporal_wrap_disable_flag == FALSE) {
647 pango_layout_set_width(layout, *max_width * PANGO_SCALE);
649 pango_layout_set_width(layout, -1);
651 pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
653 if (pango_layout_get_line_count(layout) >= 2) {
654 PangoLayoutLine *line = pango_layout_get_line(layout, 0);
657 line1 = g_strndup(str, line->length);
659 line = pango_layout_get_line(layout, 1);
662 line2 = g_strndup((gchar *) ((gint) str + line->start_index),
665 line = pango_layout_get_line(layout, 2);
668 line3 = g_strdup((gchar *) ((gint) str + line->start_index));
670 g_object_unref(layout);
671 layout = pango_layout_new(context);
672 pango_layout_set_text(layout, line3 ? line3 : "", -1);
677 if (pango_layout_get_line_count(layout) > 1) {
678 gchar *templine = NULL;
680 line = pango_layout_get_line(layout, 0);
681 templine = g_strndup(line3, line->length);
683 line3 = g_strconcat(templine, "\342\200\246", NULL);
687 if (pango_layout_xy_to_index(layout,
688 *max_width * PANGO_SCALE,
693 PangoLayout *ellipsis = pango_layout_new(context);
695 pango_layout_set_text(ellipsis, "\342\200\246", -1);
696 pango_layout_get_size(ellipsis, &ellipsiswidth, NULL);
697 pango_layout_xy_to_index(layout,
698 *max_width * PANGO_SCALE -
701 g_object_unref(G_OBJECT(ellipsis));
702 tempresult = g_strndup(line3, index);
704 line3 = g_strconcat(tempresult, "\342\200\246", NULL);
710 line1 = g_strdup(str);
713 PangoLayout *templayout = pango_layout_new(context);
715 pango_layout_set_text(templayout, line1, -1);
716 if (pango_layout_get_line_count(templayout) < 3
718 result = g_strconcat(line1, "\n", line2, "\n", line3, NULL);
719 } else if (pango_layout_get_line_count(templayout) < 2
721 result = g_strconcat(line1, "\n", line2, line3, NULL);
723 result = g_strconcat(line1, line2, line3, NULL);
725 g_object_unref(templayout);
732 g_object_unref(layout);
734 if (gtk_infoprint_temporal_wrap_disable_flag == TRUE) {
736 PangoLayout *templayout = pango_layout_new(context);
738 pango_layout_set_text(templayout, result, -1);
740 if (pango_layout_get_line_count(templayout) >= 2) {
741 PangoLayoutLine *line =
742 pango_layout_get_line(templayout, 0);
743 gchar *templine = g_strndup(result, line->length);
746 result = g_strconcat(templine, "\342\200\246", NULL);
748 pango_layout_set_text(templayout, result, -1);
751 if (pango_layout_xy_to_index
752 (templayout, *max_width * PANGO_SCALE, 0, &index,
756 PangoLayout *ellipsis = pango_layout_new(context);
758 pango_layout_set_text(ellipsis, "\342\200\246", -1);
759 pango_layout_get_size(ellipsis, &ellipsiswidth, NULL);
760 pango_layout_xy_to_index(templayout,
761 *max_width * PANGO_SCALE -
762 ellipsiswidth, 0, &index, NULL);
763 g_object_unref(G_OBJECT(ellipsis));
764 tempresult = g_strndup(result, index);
766 result = g_strconcat(tempresult, "\342\200\246", NULL);
769 g_object_unref(templayout);
774 PangoLayout *templayout = pango_layout_new(context);
776 pango_layout_set_text(templayout, result, -1);
777 pango_layout_get_size(templayout, max_width, NULL);
778 if (resulting_lines != NULL)
779 *resulting_lines = pango_layout_get_line_count(templayout);
780 g_object_unref(templayout);
784 result = g_strdup(str);
789 /**************************************************/
791 /**************************************************/
795 * @parent: The transient window for the infoprint.
796 * @text: The text in infoprint
798 * Opens a new infoprint with @text content.
800 * If parent is %NULL, the infoprint is a system infoprint.
801 * Normally you should use your application window
802 * or dialog as a transient parent and avoid passing %NULL.
804 void gtk_infoprint(GtkWindow * parent, const gchar * text)
806 gtk_infoprint_with_icon_name(parent, text, NULL);
810 * gtk_infoprint_with_icon_stock:
811 * @parent: The transient window for the infoprint.
812 * @text: The text in infoprint
813 * @stock_id: The stock id of the custom icon
815 * Opens a new infoprint with @text content.
816 * With this function you can also set a custom icon
817 * by giving a stock id as last parameter.
819 * If parent is %NULL, the infoprint is a system infoprint.
820 * Normally you should use your application window
821 * or dialog as a transient parent and avoid passing %NULL.
824 gtk_infoprint_with_icon_stock(GtkWindow * parent,
825 const gchar * text, const gchar * stock_id)
830 image = gtk_image_new_from_stock(stock_id, HILDON_ICON_SIZE_NOTE);
832 image = gtk_image_new_from_stock(GTK_INFOPRINT_STOCK,
833 HILDON_ICON_SIZE_NOTE);
836 gtk_msg_window_init(parent, infoprint_quark(), text, image);
840 * gtk_infoprint_with_icon_name:
841 * @parent: The transient window for the infoprint.
842 * @text: The text in infoprint
843 * @icon_name: The name of the icon
845 * Opens a new infoprint with @text content.
846 * With this function you can also set a custom icon
847 * by giving a icon name as last parameter.
849 * If parent is %NULL, the infoprint is a system infoprint.
850 * Normally you should use your application window
851 * or dialog as a transient parent and avoid passing %NULL.
854 gtk_infoprint_with_icon_name(GtkWindow * parent,
855 const gchar * text, const gchar * icon_name)
860 image = gtk_image_new_from_icon_name(icon_name, HILDON_ICON_SIZE_NOTE);
862 image = gtk_image_new_from_icon_name(GTK_INFOPRINT_ICON_THEME,
863 HILDON_ICON_SIZE_NOTE);
866 gtk_msg_window_init(parent, infoprint_quark(), text, image);
871 * @parent: The transient window for the infoprint.
872 * @format: Format of the text.
873 * @Varargs: List of parameters.
875 * Opens a new infoprint with @text printf-style formatting
876 * string and comma-separated list of parameters.
878 * If parent is %NULL, the infoprint is a system infoprint.
879 * This version of infoprint allow you to make printf-like formatting
882 void gtk_infoprintf(GtkWindow * parent, const gchar * format, ...)
887 va_start(args, format);
888 message = g_strdup_vprintf(format, args);
891 gtk_infoprint(parent, message);
897 * gtk_infoprint_temporarily_disable_wrap:
899 * Will disable wrapping for the next shown infoprint. This only
900 * affects next infoprint shown in this application.
902 void gtk_infoprint_temporarily_disable_wrap(void)
904 gtk_infoprint_temporal_wrap_disable_flag = TRUE;
908 * gtk_confirmation_banner:
909 * @parent: The transient window for the confirmation banner.
910 * @text: The text in confirmation banner
911 * @stock_id: The stock id of the custom icon
913 * Opens a new confirmation banner with @text content.
914 * With this function you can also set a custom icon
915 * by giving a stock id as last parameter.
917 * If parent is %NULL, the banner is a system banner.
918 * Normally you should use your application window
919 * or dialog as a transient parent and avoid passing %NULL.
921 * This function is otherwise similar to
922 * gtk_infoprint_with_icon_stock except in always restricts
923 * the text to one line and the font is emphasized.
926 gtk_confirmation_banner(GtkWindow * parent, const gchar * text,
927 const gchar * stock_id)
932 image = gtk_image_new_from_stock(stock_id, HILDON_ICON_SIZE_NOTE);
934 image = gtk_image_new_from_stock(GTK_INFOPRINT_STOCK,
935 HILDON_ICON_SIZE_NOTE);
938 queue_new_cbanner(parent, text, image);
942 * gtk_confirmation_banner_with_icon_name:
943 * @parent: The transient window for the confirmation banner.
944 * @text: The text in confirmation banner
945 * @icon_name: The name of the custom icon in icon theme
947 * Opens a new confirmation banner with @text content.
948 * With this function you can also set a custom icon
949 * by giving a icon theme's icon name as last parameter.
951 * If parent is %NULL, the banner is a system banner.
952 * Normally you should use your application window
953 * or dialog as a transient parent and avoid passing %NULL.
955 * This function is otherwise similar to
956 * gtk_infoprint_with_icon_name except in always restricts
957 * the text to one line and the font is emphasized.
960 gtk_confirmation_banner_with_icon_name(GtkWindow * parent, const gchar * text,
961 const gchar * icon_name)
966 image = gtk_image_new_from_icon_name(icon_name, HILDON_ICON_SIZE_NOTE);
968 image = gtk_image_new_from_stock(GTK_INFOPRINT_STOCK,
969 HILDON_ICON_SIZE_NOTE);
972 queue_new_cbanner(parent, text, image);
976 * gtk_banner_show_animation:
977 * @parent: #GtkWindow
978 * @text: #const gchar *
980 * The @text is the text shown in banner.
981 * Creates a new banner with the animation.
983 void gtk_banner_show_animation(GtkWindow * parent, const gchar * text)
989 theme = gtk_icon_theme_get_default();
991 info = gtk_icon_theme_lookup_icon(theme, DEFAULT_PROGRESS_ANIMATION,
992 HILDON_ICON_SIZE_NOTE, 0);
995 const gchar *filename = gtk_icon_info_get_filename(info);
996 item = gtk_image_new_from_file(filename);
998 g_print("icon theme lookup for icon failed!\n");
999 item = gtk_image_new();
1002 gtk_icon_info_free(info);
1004 gtk_msg_window_init(parent, banner_quark(), text, item);
1008 * gtk_banner_show_bar
1009 * @parent: #GtkWindow
1010 * @text: #const gchar *
1012 * The @text is the text shown in banner.
1013 * Creates a new banner with the progressbar.
1015 void gtk_banner_show_bar(GtkWindow * parent, const gchar * text)
1017 gtk_msg_window_init(parent, banner_quark(),
1018 text, gtk_progress_bar_new());
1022 * gtk_banner_set_text
1023 * @parent: #GtkWindow
1024 * @text: #const gchar *
1026 * The @text is the text shown in banner.
1027 * Sets the banner text.
1029 void gtk_banner_set_text(GtkWindow * parent, const gchar * text)
1033 g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL);
1035 item = gtk_banner_get_widget(parent, label_quark());
1037 if (GTK_IS_LABEL(item))
1038 gtk_label_set_text(GTK_LABEL(item), text);
1042 * gtk_banner_set_fraction:
1043 * @parent: #GtkWindow
1044 * @fraction: #gdouble
1046 * The fraction is the completion of progressbar,
1047 * the scale is from 0.0 to 1.0.
1048 * Sets the amount of fraction the progressbar has.
1050 void gtk_banner_set_fraction(GtkWindow * parent, gdouble fraction)
1054 g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL);
1056 item = gtk_banner_get_widget(parent, item_quark());
1058 if (GTK_IS_PROGRESS_BAR(item))
1059 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(item), fraction);
1064 * @parent: #GtkWindow
1066 * Destroys the banner
1068 void gtk_banner_close(GtkWindow * parent)
1070 g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL);
1072 if (pbanner_refs > 0) {
1074 if (pbanner_refs == 0 && current_pbanner) {
1075 gtk_msg_window_destroy(current_pbanner->window);
1081 * gtk_banner_temporarily_disable_wrap
1083 * Will disable wrapping for the next shown banner. This only
1084 * affects next banner shown in this application.
1086 void gtk_banner_temporarily_disable_wrap(void)
1088 /* The below variable name is intentional. There's no real need for
1089 having two different variables for this functionality. */
1090 gtk_infoprint_temporal_wrap_disable_flag = TRUE;
1093 /* We want the timer to be launched only after the infoprint is fully drawn.
1094 * As an approximation, we wait for an idle moment before starting
1095 * the timer. This method is not exact, since it does not guarantee that
1096 * the x-server has gotten around to drawing the window. The only way to be
1097 * sure would require syncing with the x-server, but this should be close
1100 static gboolean infoprint_idle_before_timer (GtkWidget *widget,
1101 GdkEventExpose *event,
1104 g_idle_add(infoprint_start_timer, widget);
1108 /* Start the actual timer for the infoprint */
1109 static gboolean infoprint_start_timer (gpointer data)
1111 if (GTK_IS_WIDGET (data)) {
1112 current_ibanner->timeout = g_timeout_add(MESSAGE_TIMEOUT,
1113 gtk_msg_window_destroy,
1114 current_ibanner->window);
1115 g_signal_connect_swapped(GTK_WIDGET(data), "destroy",
1116 G_CALLBACK(g_source_remove),
1117 GUINT_TO_POINTER(current_ibanner->timeout));