implementing a delayed "busy" cursor



hi --

i want the mouse cursor in my app to only switch to "busy" after
a brief delay (perhaps 1 second).  i have an implementation that
works in some places, but not others, and i'm wondering if
there's a better/safer way.

in my first cut at implementing this i fell back on old habits,
namely, signal handlers.  i know using signals within gui apps is
risky -- and in fact the app implements the "handle signals via
an event pipe" trick to deal with SIGTERM, for this very reason. 
but that trick won't work for the busy cursor delay, which really
needs to be asynchronous to program execution.

here's my current code:

    void busy_cursor_handler(int signal)
    {
       set_my_cursor (CURSOR_BUSY);
    }

    void set_my_cursor (int newcursor)
    {
       GdkCursor *cursor;
       static int lastcursor;
       static int delayed;

       if (delayed) {
          alarm(0);
          delayed = 0;
       }

       if (newcursor == CURSOR_BUSY_WITH_DELAY) {
          signal(SIGALRM, busy_cursor_handler);
          alarm(1);
          delayed = 1;
          return;
       }

       if (newcursor == lastcursor)
          return;
       lastcursor = newcursor;

       switch (newcursor) {

       case CURSOR_NORMAL:
          cursor = NULL;
          break;

       case CURSOR_BUSY:
          cursor = gdk_cursor_new(GDK_WATCH);
          break;
       }

       gdk_window_set_cursor(MainWindow->window, cursor);

       if (cursor) {
          gdk_cursor_destroy(cursor);
       }
       gdk_flush();
    }


the app looks roughly like:

    ...

    set_my_cursor(CURSOR_BUSY_WITH_DELAY);

    ...do stuff that may or may not take a long time (the program
     is a mapping program, so processing the data which needs to
     be rendered can be costly), which includes calls to gdk and
     gtk drawing functions made to update a DrawingArea widget. 
     the final call is to gtk_widget_draw() to paint it on the
     screen...

    set_my_cursor(CURSOR_NORMAL);

    ...

this all seems to work very solidly in "current" (as in, ubuntu
feisty up-to-date) versions of both GTK 1.2 (1.2.10-18) and GTK2
(2.10.11).  this testing was done on a modern x86 laptop (1.6Ghz)

but when i run it on an older GTK 1.2 (1.2.10-17) from debian
sarge, i regularly get lockups, with the app spinning in a loop
down in the X libraries somewhere (i don't have a backtrace
handy).  this testing was on a slow handheld device (400Mhz
au1100 mips).

is it possible that the minor revision difference for gtk1.2
could have fixed this problem?  somehow i'm skeptical, and
suspect that the problem exists everywhere, but is being exposed
on the older slower hardware.

i tried modifying the above code so that only the gdk_flush()
happened during the signal handler (i even tried changing it
to "XFlush(GDK_DISPLAY())"), but i still get the lockups.

i figure i have several choices:

    - live with restricting the feature to newer versions of GTK,
	if indeed it's a problem that's been fixed in newer
	releases, and if i can easily determine the version
	level at runtime.

    - add a user-configurable option to suppress the delay
	feature if the user determines it causes lockups.  (ugh.)

    - implement the delayed busy cursor in a different way
	guaranteed to work everywhere.  is my implementation
	using signals way off base?  is there a more standard way
	of doing this?  my googling came up short.

many thanks.

paul
=---------------------
 paul fox, pgf foxharp boston ma us (arlington, ma, where it's 69.4 degrees)
 '02 V-Strom, DoD #1462, AMA #545601




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