GTK3, 26 draw calls for one button

Yes, I may have asked a similar question already, maybe 4 years ago. Can not really remember, but this one is different, as I am doing some custom drawing.

Yesterday I created a plain ColorPicker Button in Nim, which is just an ordinary GtkButton without text, and I do connect-after() to draw signal to draw a circle on it with its color. Works fine.

But then I noticed again that draw callback is called many, many times. Its a waste of resources, so question is why it occurs, and is there a chance for my app that I have to draw my colored circle not 26 times whenever user clicks button or moves mouse pointer over button. And, will GTK4 do fewer calls? This is for Gnome Wayland.

Here is a C code example based on ZCode – move mouse pointer over a button or click button.

// http://zetcode.com/gui/gtk2/gtkwidgets/
// gcc -o buttons buttons.c `pkg-config --libs --cflags gtk+-3.0`
#include <gtk/gtk.h>
#include <cairo.h>
int draw(cairo_t *cr) {
  printf("draw\n");
  return GDK_EVENT_PROPAGATE;
}

int main(int argc, char *argv[]) {
    
  GtkWidget *window;
  GtkWidget *box;
  GtkWidget *btn;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "GtkButton");
  gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
  gtk_container_set_border_width(GTK_CONTAINER(window), 15);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

  box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
  gtk_container_add(GTK_CONTAINER(window), box);

  btn = gtk_button_new_with_label("B1");
  gtk_widget_set_size_request(btn, 70, 30);
  g_signal_connect(G_OBJECT(btn), "draw", 
      G_CALLBACK(draw), NULL);
  gtk_container_add(GTK_CONTAINER(box), btn);

  btn = gtk_button_new_with_label("B2");
  gtk_widget_set_size_request(btn, 70, 30);
  g_signal_connect(G_OBJECT(btn), "draw", 
      G_CALLBACK(draw), NULL);
  gtk_container_add(GTK_CONTAINER(box), btn);

  //g_signal_connect(G_OBJECT(btn), "clicked", 
  //    G_CALLBACK(gtk_main_quit), G_OBJECT(window));

  g_signal_connect(G_OBJECT(window), "destroy", 
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

That’s fine. It’s due to CSS transitions. For example Adwaita defines a transition on the background property for when the mouse cursor is over a button (button:hover). You can see the background switch gradually to lighter colors on hover. If that’s undesirable, you can either:

  • Disable transitions and animations from the theme with custom CSS (see below). Can be applied to a particular widget, to all widgets of the same type, or for every widget.
  • Make use of a CSS theme that doesn’t define transitions or animations.
  • Disable animations altogether: call g_object_set(gtk_settings_get_default(), "gtk-enable-animations", FALSE, NULL)); (after gtk_init()). I do not recommend this. Also affects non-CSS animations like e.g. popovers and stacks.

If you want to disable transitions / animations for a particular widget (say, a button), add this CSS snippet (I have not tested this):

button {
  transition-property: none !important;
  animation: none !important;
}

See here: https://onezeronull.com/2016/10/06/disable-css-transitions-and-animations-temporarily-or-permanently/

Thank you very much for that fast and detailed answer, it is really helpful!

1 Like

There’s no need to specify !important: GTK’s CSS parser does not support it anyway.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.