Re: A simple GtkSpinner is very costly in CPU cycles




 

 
Hi Kian

For effeciency, use one of the default cursors.

https://developer.gnome.org/gdk3/stable/gdk3-Cursors.html

If you want, you can try creating your own cursor with animation and using that. I got this working on my 
netbook which isn't a very high powered computer by todays standards and it works fine. I don't see it eating 
up cpu cycles. Give it a try and see if it works.

Eric


//gcc -Wall cursor1.c -o cursor1 `pkg-config gtk+-3.0 --cflags --libs`
//Tested on Ubuntu16.04, GTK3.18.

#include<gtk/gtk.h>

static guint timeout_id=0;
static GdkCursor *cursors[4];

static void initialize_cursors(GtkWidget *window, GdkPixbuf *pixbufs[]);
static void start_cursor(GtkButton *button1, GtkWidget *da);
static void stop_cursor(GtkButton *button2, GtkWidget *da);
static gboolean update_cursor(GtkWidget *da);
static GdkPixbuf* draw_cursor(gint section);

int main(int argc, char *argv[])
  {
    gtk_init(&argc, &argv);

    GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Cursors");
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    //Pixbufs for the different cursors.
    GdkPixbuf *pixbuf1=draw_cursor(1);
    GdkPixbuf *pixbuf2=draw_cursor(2);
    GdkPixbuf *pixbuf3=draw_cursor(3);
    GdkPixbuf *pixbuf4=draw_cursor(4);
    GdkPixbuf *pixbufs[]={pixbuf1, pixbuf2, pixbuf3, pixbuf4};
    g_signal_connect(window, "realize", G_CALLBACK(initialize_cursors), pixbufs);

    GtkWidget *button1=gtk_button_new_with_label("Start Cursor");
    gtk_widget_set_hexpand(button1, TRUE);

    GtkWidget *button2=gtk_button_new_with_label("Stop Cursor");
    gtk_widget_set_hexpand(button2, TRUE);

    //Display the cursor in a drawing area.
    GtkWidget *da=gtk_drawing_area_new();
    gtk_widget_set_hexpand(da, TRUE);
    gtk_widget_set_vexpand(da, TRUE);

    g_signal_connect(button1, "clicked", G_CALLBACK(start_cursor), da);
    g_signal_connect(button2, "clicked", G_CALLBACK(stop_cursor), da);
  
    GtkWidget *grid=gtk_grid_new();
    gtk_grid_attach(GTK_GRID(grid), button1, 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), button2, 1, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), da, 0, 1, 2, 1);
  
    gtk_container_add(GTK_CONTAINER(window), grid);
    gtk_widget_show_all(window);

    gtk_main();

    g_object_unref(pixbuf1); 
    g_object_unref(pixbuf2); 
    g_object_unref(pixbuf3); 
    g_object_unref(pixbuf4); 
    g_object_unref(cursors[0]);
    g_object_unref(cursors[1]);
    g_object_unref(cursors[2]);
    g_object_unref(cursors[3]);

    return 0;
  }
static void initialize_cursors(GtkWidget *window, GdkPixbuf *pixbufs[])
  {
    GdkWindow *win=gtk_widget_get_window(window);
    GdkDisplay *display=gdk_window_get_display(win);
    GdkCursor *cursor1=gdk_cursor_new_from_pixbuf(display, pixbufs[0], 1, 32);
    GdkCursor *cursor2=gdk_cursor_new_from_pixbuf(display, pixbufs[1], 1, 32);
    GdkCursor *cursor3=gdk_cursor_new_from_pixbuf(display, pixbufs[2], 1, 32);
    GdkCursor *cursor4=gdk_cursor_new_from_pixbuf(display, pixbufs[3], 1, 32);
    cursors[0]=cursor1;
    cursors[1]=cursor2;
    cursors[2]=cursor3;
    cursors[3]=cursor4;
  }
static void start_cursor(GtkButton *button1, GtkWidget *da)
  {
    if(timeout_id==0)
      {
        timeout_id=g_timeout_add(300, (GSourceFunc)update_cursor, da);
      }
  }
static void stop_cursor(GtkButton *button2, GtkWidget *da)
  {
    if(timeout_id!=0)
      {
        g_source_remove(timeout_id);
        timeout_id=0;
        GdkWindow *win=gtk_widget_get_window(da);
        gdk_window_set_cursor(win, NULL);
      }
  }
static gboolean update_cursor(GtkWidget *da)
  {
    static gint i=0;

    GdkWindow *win=gtk_widget_get_window(da);
    gdk_window_set_cursor(win, cursors[i]);
    if(i>2) i=0;
    else i++;
 
    return TRUE;
  }
static GdkPixbuf* draw_cursor(gint section)
  { 
    //Create a surface to draw on. 
    cairo_surface_t *surface=cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 64, 64);
    cairo_t *cr=cairo_create(surface);
    
    //Paint the background transparent.
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0);
    cairo_paint(cr);

    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
    cairo_rectangle(cr, 0.0, 0.0, 64.0, 64.0);
    cairo_stroke(cr);

    //Draw from center
    cairo_translate(cr, 64.0/2.0, 64.0/2.0);

    cairo_set_source_rgba(cr, 0.0, 1.0, 1.0, 1.0);
    cairo_arc(cr, 0.0, 0.0, 20.0, 0.0, 2.0*G_PI);
    cairo_fill(cr);

    //Some pie wedges.
    if(section==1)
      {
        cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
        cairo_move_to(cr, 0.0, 0.0);
        cairo_line_to(cr, 20.0, 0.0);
        cairo_stroke_preserve(cr);
        cairo_arc(cr, 0.0, 0.0, 20.0, 0.0, G_PI/2.0);
        cairo_stroke_preserve(cr);
        cairo_close_path(cr);
        cairo_fill(cr);
      }
    else if(section==2)
      {
        cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
        cairo_move_to(cr, 0.0, 0.0);
        cairo_line_to(cr, 0.0, 20.0);
        cairo_stroke_preserve(cr);
        cairo_arc(cr, 0.0, 0.0, 20.0, G_PI/2.0, G_PI);
        cairo_stroke_preserve(cr);
        cairo_close_path(cr);
        cairo_fill(cr);
      }
    else if(section==3)
      {
        cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
        cairo_move_to(cr, 0.0, 0.0);
        cairo_line_to(cr, -20.0, 0.0);
        cairo_stroke_preserve(cr);
        cairo_arc(cr, 0.0, 0.0, 20.0, G_PI, 3.0*G_PI/2.0);
        cairo_stroke_preserve(cr);
        cairo_close_path(cr);
        cairo_fill(cr);
      }
    else
      {
        cairo_set_source_rgb (cr, 1.0, 0.0, 1.0);
        cairo_move_to(cr, 0.0, 0.0);
        cairo_line_to(cr, 0.0, -20.0);
        cairo_stroke_preserve(cr);
        cairo_arc(cr, 0.0, 0.0, 20.0, 3.0*G_PI/2.0, 2.0*G_PI);
        cairo_stroke_preserve(cr);
        cairo_close_path(cr);
        cairo_fill(cr);
      }
    
    GdkPixbuf *cursor_drawing=gdk_pixbuf_get_from_surface(surface, 0, 0, 64, 64);

    cairo_destroy(cr);
    cairo_surface_destroy(surface); 
    return cursor_drawing;
  }




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]