forked from AuroraMiddleware/gtk
15257e3922
The themes demo was leaking its builder, and therefore couldn't be closed.
229 lines
5.9 KiB
C
229 lines
5.9 KiB
C
/* Benchmark/Themes
|
|
*
|
|
* This demo switches themes like a maniac, like some of you.
|
|
*/
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
static guint tick_cb;
|
|
|
|
static gint64
|
|
guess_refresh_interval (GdkFrameClock *frame_clock)
|
|
{
|
|
gint64 interval;
|
|
gint64 i;
|
|
|
|
interval = G_MAXINT64;
|
|
|
|
for (i = gdk_frame_clock_get_history_start (frame_clock);
|
|
i < gdk_frame_clock_get_frame_counter (frame_clock);
|
|
i++)
|
|
{
|
|
GdkFrameTimings *t, *before;
|
|
gint64 ts, before_ts;
|
|
|
|
t = gdk_frame_clock_get_timings (frame_clock, i);
|
|
before = gdk_frame_clock_get_timings (frame_clock, i - 1);
|
|
if (t == NULL || before == NULL)
|
|
continue;
|
|
|
|
ts = gdk_frame_timings_get_frame_time (t);
|
|
before_ts = gdk_frame_timings_get_frame_time (before);
|
|
if (ts == 0 || before_ts == 0)
|
|
continue;
|
|
|
|
interval = MIN (interval, ts - before_ts);
|
|
}
|
|
|
|
if (interval == G_MAXINT64)
|
|
return 0;
|
|
|
|
return interval;
|
|
}
|
|
|
|
static double
|
|
frame_clock_get_fps (GdkFrameClock *frame_clock)
|
|
{
|
|
GdkFrameTimings *start, *end;
|
|
gint64 start_counter, end_counter;
|
|
gint64 start_timestamp, end_timestamp;
|
|
gint64 interval;
|
|
|
|
start_counter = gdk_frame_clock_get_history_start (frame_clock);
|
|
end_counter = gdk_frame_clock_get_frame_counter (frame_clock);
|
|
start = gdk_frame_clock_get_timings (frame_clock, start_counter);
|
|
for (end = gdk_frame_clock_get_timings (frame_clock, end_counter);
|
|
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
|
|
end = gdk_frame_clock_get_timings (frame_clock, end_counter))
|
|
end_counter--;
|
|
if (end_counter - start_counter < 4)
|
|
return 0.0;
|
|
|
|
start_timestamp = gdk_frame_timings_get_presentation_time (start);
|
|
end_timestamp = gdk_frame_timings_get_presentation_time (end);
|
|
if (start_timestamp == 0 || end_timestamp == 0)
|
|
{
|
|
start_timestamp = gdk_frame_timings_get_frame_time (start);
|
|
end_timestamp = gdk_frame_timings_get_frame_time (end);
|
|
}
|
|
interval = gdk_frame_timings_get_refresh_interval (end);
|
|
if (interval == 0)
|
|
{
|
|
interval = guess_refresh_interval (frame_clock);
|
|
if (interval == 0)
|
|
return 0.0;
|
|
}
|
|
|
|
return ((double) end_counter - start_counter) * G_USEC_PER_SEC / (end_timestamp - start_timestamp);
|
|
}
|
|
|
|
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", 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
|
|
clicked (GtkGestureClick *gesture,
|
|
int n_press,
|
|
double x,
|
|
double y,
|
|
gpointer data)
|
|
{
|
|
GtkWidget *window;
|
|
GdkEvent *event;
|
|
GdkModifierType state;
|
|
|
|
window = gtk_widget_get_ancestor (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)), GTK_TYPE_WINDOW);
|
|
|
|
event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), NULL);
|
|
state = gdk_event_get_modifier_state (event);
|
|
|
|
if (state & GDK_CONTROL_MASK)
|
|
{
|
|
if (tick_cb)
|
|
{
|
|
gtk_widget_remove_tick_callback (window, tick_cb);
|
|
tick_cb = 0;
|
|
}
|
|
|
|
change_theme (window, NULL, data);
|
|
}
|
|
else
|
|
{
|
|
if (tick_cb)
|
|
{
|
|
gtk_widget_remove_tick_callback (window, tick_cb);
|
|
tick_cb = 0;
|
|
}
|
|
else
|
|
{
|
|
tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
toggle_cycle (GObject *button,
|
|
GParamSpec *pspec,
|
|
gpointer 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)
|
|
{
|
|
tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL);
|
|
}
|
|
else if (!active && tick_cb)
|
|
{
|
|
gtk_widget_remove_tick_callback (window, tick_cb);
|
|
tick_cb = 0;
|
|
}
|
|
}
|
|
|
|
GtkWidget *
|
|
do_themes (GtkWidget *do_widget)
|
|
{
|
|
static GtkWidget *window = NULL;
|
|
|
|
if (!window)
|
|
{
|
|
GtkBuilder *builder;
|
|
GtkWidget *header;
|
|
GtkWidget *button;
|
|
GtkWidget *label;
|
|
GtkGesture *gesture;
|
|
|
|
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));
|
|
|
|
header = GTK_WIDGET (gtk_builder_get_object (builder, "header"));
|
|
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
|
|
|
|
gesture = gtk_gesture_click_new ();
|
|
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), label);
|
|
gtk_widget_add_controller (header, GTK_EVENT_CONTROLLER (gesture));
|
|
|
|
button = GTK_WIDGET (gtk_builder_get_object (builder, "toggle"));
|
|
g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), label);
|
|
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;
|
|
}
|