1/* Benchmark/Themes
2 *
3 * This demo continuously switches themes, like some of you.
4 *
5 * Warning: This demo involves rapidly flashing changes and may
6 * be hazardous to photosensitive viewers.
7 */
8
9#include <gtk/gtk.h>
10
11static guint tick_cb;
12
13typedef struct {
14 const char *name;
15 gboolean dark;
16} Theme;
17
18static Theme themes[] = {
19 { "Adwaita", FALSE },
20 { "Adwaita", TRUE },
21 { "HighContrast", FALSE },
22 { "HighContrastInverse", FALSE }
23};
24
25static int theme;
26
27static gboolean
28change_theme (GtkWidget *widget,
29 GdkFrameClock *frame_clock,
30 gpointer data)
31{
32 GtkWidget *label = data;
33 Theme next = themes[theme++ % G_N_ELEMENTS (themes)];
34 char *name;
35
36 g_object_set (object: gtk_settings_get_default (),
37 first_property_name: "gtk-theme-name", next.name,
38 "gtk-application-prefer-dark-theme", next.dark,
39 NULL);
40
41 name = g_strconcat (string1: next.name, next.dark ? " (dark)" : NULL, NULL);
42 gtk_window_set_title (GTK_WINDOW (widget), title: name);
43 g_free (mem: name);
44
45 if (frame_clock)
46 {
47 char *fps;
48
49 fps = g_strdup_printf (format: "%.2f fps", gdk_frame_clock_get_fps (frame_clock));
50 gtk_label_set_label (GTK_LABEL (label), str: fps);
51 g_free (mem: fps);
52 }
53 else
54 gtk_label_set_label (GTK_LABEL (label), str: "");
55
56 return G_SOURCE_CONTINUE;
57}
58
59static void
60toggle_cycle (GObject *button,
61 GParamSpec *pspec,
62 gpointer data)
63{
64 GtkWidget *warning = data;
65 gboolean active;
66 GtkWidget *window;
67
68 g_object_get (object: button, first_property_name: "active", &active, NULL);
69
70 window = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW);
71
72 if (active && !tick_cb)
73 {
74 gtk_window_present (GTK_WINDOW (warning));
75 }
76 else if (!active && tick_cb)
77 {
78 gtk_widget_remove_tick_callback (widget: window, id: tick_cb);
79 tick_cb = 0;
80 }
81}
82
83static void
84warning_closed (GtkDialog *warning,
85 int response_id,
86 gpointer data)
87{
88 GtkWidget *window;
89 GtkWidget *button;
90
91 gtk_widget_hide (GTK_WIDGET (warning));
92
93 window = gtk_widget_get_ancestor (GTK_WIDGET (data), GTK_TYPE_WINDOW);
94 button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "button"));
95
96 if (response_id == GTK_RESPONSE_OK)
97 tick_cb = gtk_widget_add_tick_callback (widget: window, callback: change_theme, user_data: data, NULL);
98 else
99 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
100}
101
102GtkWidget *
103do_themes (GtkWidget *do_widget)
104{
105 static GtkWidget *window = NULL;
106
107 if (!window)
108 {
109 GtkBuilder *builder;
110 GtkWidget *button;
111 GtkWidget *label;
112 GtkWidget *warning;
113
114 builder = gtk_builder_new_from_resource (resource_path: "/themes/themes.ui");
115 window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
116 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
117 gtk_window_set_display (GTK_WINDOW (window),
118 display: gtk_widget_get_display (widget: do_widget));
119
120 label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
121 warning = GTK_WIDGET (gtk_builder_get_object (builder, "warning"));
122 g_signal_connect (warning, "response", G_CALLBACK (warning_closed), label);
123
124 button = GTK_WIDGET (gtk_builder_get_object (builder, "toggle"));
125 g_object_set_data (G_OBJECT (window), key: "button", data: button);
126 g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), warning);
127 gtk_widget_realize (widget: window);
128
129 g_object_unref (object: builder);
130 }
131
132 if (!gtk_widget_get_visible (widget: window))
133 gtk_widget_show (widget: window);
134 else
135 gtk_window_destroy (GTK_WINDOW (window));
136
137 return window;
138}
139

source code of gtk/demos/gtk-demo/themes.c