summaryrefslogtreecommitdiff
path: root/demos/gtk-demo/themes.c
blob: 8af63b463f218b309171ca6dbe82b284f108a218 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Benchmark/Themes
 *
 * This demo continuously switches themes, like some of you.
 *
 * Warning: This demo involves rapidly flashing changes and may
 * be hazardous to photosensitive viewers.
 */

#include <gtk/gtk.h>

static guint tick_cb;

typedef struct {
  const char *name;
  gboolean dark;
} Theme;

static Theme themes[] = {
  { "Adwaita", FALSE },
  { "Adwaita", TRUE },
  { "HighContrast", FALSE },
  { "HighContrastInverse", FALSE }
};

static int theme;

static gboolean
change_theme (GtkWidget     *widget,
              GdkFrameClock *frame_clock,
              gpointer       data)
{
  GtkWidget *label = data;
  Theme next = themes[theme++ % G_N_ELEMENTS (themes)];
  char *name;

  g_object_set (gtk_settings_get_default (),
                "gtk-theme-name", next.name,
                "gtk-application-prefer-dark-theme", next.dark,
                NULL);

  name = g_strconcat (next.name, next.dark ? " (dark)" : NULL, NULL);
  gtk_window_set_title (GTK_WINDOW (widget), name);
  g_free (name);

  if (frame_clock)
    {
      char *fps;

      fps = g_strdup_printf ("%.2f fps", gdk_frame_clock_get_fps (frame_clock));
      gtk_label_set_label (GTK_LABEL (label), fps);
      g_free (fps);
    }
  else
    gtk_label_set_label (GTK_LABEL (label), "");

  return G_SOURCE_CONTINUE;
}

static void
toggle_cycle (GObject    *button,
              GParamSpec *pspec,
              gpointer    data)
{
  GtkWidget *warning = data;
  gboolean active;
  GtkWidget *window;

  g_object_get (button, "active", &active, NULL);

  window = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW);

  if (active && !tick_cb)
    {
      gtk_window_present (GTK_WINDOW (warning));
    }
  else if (!active && tick_cb)
    {
      gtk_widget_remove_tick_callback (window, tick_cb);
      tick_cb = 0;
    }
}

static void
warning_closed (GtkDialog *warning,
                int        response_id,
                gpointer   data)
{
  GtkWidget *window;
  GtkWidget *button;

  gtk_widget_hide (GTK_WIDGET (warning));

  window = gtk_widget_get_ancestor (GTK_WIDGET (data), GTK_TYPE_WINDOW);
  button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "button"));

  if (response_id == GTK_RESPONSE_OK)
    tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL);
  else
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
}

GtkWidget *
do_themes (GtkWidget *do_widget)
{
  static GtkWidget *window = NULL;

  if (!window)
    {
      GtkBuilder *builder;
      GtkWidget *button;
      GtkWidget *label;
      GtkWidget *warning;

      builder = gtk_builder_new_from_resource ("/themes/themes.ui");
      window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
      g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
      gtk_window_set_display (GTK_WINDOW (window),
                              gtk_widget_get_display (do_widget));

      label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
      warning = GTK_WIDGET (gtk_builder_get_object (builder, "warning"));
      g_signal_connect (warning, "response", G_CALLBACK (warning_closed), label);

      button = GTK_WIDGET (gtk_builder_get_object (builder, "toggle"));
      g_object_set_data (G_OBJECT (window), "button", button);
      g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), warning);
      gtk_widget_realize (window);

      g_object_unref (builder);
    }

  if (!gtk_widget_get_visible (window))
    gtk_widget_show (window);
  else
    gtk_window_destroy (GTK_WINDOW (window));

  return window;
}