diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml index a71adcee26..ca8558dc29 100644 --- a/demos/gtk-demo/demo.gresource.xml +++ b/demos/gtk-demo/demo.gresource.xml @@ -37,6 +37,9 @@ theming.ui + + themes.ui + css_pixbufs.css cssview.css @@ -212,6 +215,7 @@ textview.c textscroll.c theming_style_classes.c + themes.c transparent.c tree_store.c textmask.c diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build index aba44c976c..87e5ae4f85 100644 --- a/demos/gtk-demo/meson.build +++ b/demos/gtk-demo/meson.build @@ -70,6 +70,7 @@ demos = files([ 'textmask.c', 'textview.c', 'textscroll.c', + 'themes.c', 'theming_style_classes.c', 'transparent.c', 'tree_store.c', diff --git a/demos/gtk-demo/themes.c b/demos/gtk-demo/themes.c new file mode 100644 index 0000000000..bfffc3a69a --- /dev/null +++ b/demos/gtk-demo/themes.c @@ -0,0 +1,203 @@ +/* Benchmark/Themes + * + * This demo switches themes like a maniac, like some of you. + */ + +#include + +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) +{ + GtkBuilder *builder = data; + GtkWidget *header; + GtkWidget *label; + 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); + + header = GTK_WIDGET (gtk_builder_get_object (builder, "header")); + name = g_strconcat (next.name, next.dark ? " (dark)" : NULL, NULL); + gtk_header_bar_set_title (GTK_HEADER_BAR (header), name); + g_free (name); + + label = GTK_WIDGET (gtk_builder_get_object (builder, "fps")); + 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; + const 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); + gdk_event_get_state (event, &state); + + 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); + } + } +} + +GtkWidget * +do_themes (GtkWidget *do_widget) +{ + static GtkWidget *window = NULL; + + if (!window) + { + GtkBuilder *builder; + GtkWidget *header; + GtkGesture *gesture; + + builder = gtk_builder_new_from_resource ("/themes/themes.ui"); + window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), &window); + gtk_window_set_display (GTK_WINDOW (window), + gtk_widget_get_display (do_widget)); + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), &window); + header = GTK_WIDGET (gtk_builder_get_object (builder, "header")); + gesture = gtk_gesture_click_new (); + g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), builder); + gtk_widget_add_controller (header, GTK_EVENT_CONTROLLER (gesture)); + + gtk_widget_realize (window); + } + + if (!gtk_widget_get_visible (window)) + gtk_widget_show (window); + else + gtk_widget_destroy (window); + + return window; +} diff --git a/demos/gtk-demo/themes.ui b/demos/gtk-demo/themes.ui new file mode 100644 index 0000000000..db6f1ebf98 --- /dev/null +++ b/demos/gtk-demo/themes.ui @@ -0,0 +1,241 @@ + + + + 0 + + + 1 + + + + + + + + + 10 + 10 + vertical + + + 1 + 0 + + + + 1 + Normal + 1 + 1 + edit-find + + + + + 1 + Active + 1 + 1 + edit-find + 1 + + + + + 1 + 0 + Insensitive + 1 + 1 + edit-find + + + + + 1 + Raised + 1 + 1 + edit-find + + + + + + 1 + Raised Active + 1 + 1 + edit-find + 1 + + + + + + 1 + 0 + Insensitive Active + 1 + edit-find + 1 + 1 + + + + + + + 1 + 10 + + Search... + edit-find-symbolic + + + + + + + + + 1 + center + Switch it + + + + + + + + + center + center + + + + Hi, I am a button + 1 + 1 + + + + + And I'm another button + 1 + 1 + + + + + This is a button party! + 1 + 1 + + + + + + + 1 + icons + + + + 1 + Normal + 1 + list-add-symbolic + + + + + 1 + Normal + 1 + list-add-symbolic + + + + + 1 + Active + 1 + list-remove-symbolic + 1 + + + + + 1 + Active + 1 + list-remove-symbolic + 1 + + + + + 1 + 0 + Insensitive + 1 + edit-find-symbolic + + + + + 1 + 0 + Insensitive Active + 1 + go-up-symbolic + 1 + + + + + + + 10 + + + Plain + end + 1 + 1 + + + + + Destructive + + + + + + Suggested + + + + + + + + +