Okay, well, tonight I decided to check for timer functions and found them and 
came up with the following.  The only quesiton I have is if the Stop() routine 
loop of 4 checks is okay or if slow X server/client communcations would matter? 
 Wouldn't it all just be sent down? maybe use Fl::flush instead?

//
// class to keep FLTK splash windows alive
//
class CFLTKKeepAlive
{
  // IMPORTANT NOTE:  Even though this using custom timer values
  // SIGRTMIN through SIGRTMAX and not SIGALRM, it causes sleep,
  // usleep, etc.. to return as soon as the signal occurs.  see
  // the manual for sleep and usleep, which only discus SIGALRM,
  // for details.

  protected:
    static timer_t TimerID;           // timer id created

    // signal handler
    static void SignalHandler(int signo, siginfo_t *info, void *context);

  public:
    static int SigNum;                // signal number being used

    // start the keep alive timer.
    static int Start(int signum=SIGRTMIN, unsigned intervalms=250);
    // stop the keep alive timer
    static void Stop();
};



//-------------------
// static variables
//-------------------
timer_t CFLTKKeepAlive::TimerID=0;
int CFLTKKeepAlive::SigNum=0;

//-------------------------------------------------------------------------
// Purpose: Start the keep alive process
//
// Input:   signum    - [i] custom signum to use (SIGRTMIN to SIGRTMAX)
//
// Output:  -1 on failure (with errno set) otherwise 0.
//
// Notes:   sleep/usleep within same thread will return as soon as a
//          signal is issued from this keep alive process.  see sleep
//          and usleep documentation for details.
//
int CFLTKKeepAlive::Start(int signum, unsigned intervalms)
{
  // presume failure
  int result=-1;

  // setup the sigaction first to ensure our callback is used
  struct sigaction sigact;
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags=SA_SIGINFO;
  sigact.sa_sigaction=CFLTKKeepAlive::SignalHandler;

  if (sigaction(signum, &sigact, NULL)!=-1) {
    // call back setup for signum so init tracking variable
    SigNum=signum;

    // now we need to create a timer that will cause a signal
    struct sigevent sigev;
    sigev.sigev_notify=SIGEV_SIGNAL;
    sigev.sigev_signo=SigNum;
    sigev.sigev_value.sival_ptr=&TimerID;

    if (timer_create(CLOCK_REALTIME, &sigev, &TimerID)==0) {

      // setup the internval
      struct itimerspec itval;
      struct itimerspec oitval;

      itval.it_value.tv_sec=intervalms/1000;
      itval.it_value.tv_nsec=(intervalms%1000)*1000000;

      itval.it_interval.tv_sec=itval.it_value.tv_sec;
      itval.it_interval.tv_nsec=itval.it_value.tv_nsec;

      // set and start the timer interval
      if (timer_settime(TimerID, 0, &itval, &oitval)==0) {
        result=0;
      }
      else Stop();
    }
    else Stop();
  }
  // indicate if keep alive setup completed
  return result;
}

//-------------------------------------------------------------------------
// Purpose: Stop the keep alive process
//
// Input:   na
//
// Output:  na
//
// Notes:
//
void CFLTKKeepAlive::Stop()
{
  // determine if timer appears started
  if (TimerID!=0) {
    timer_delete(TimerID);
    TimerID=0;
  }

  // reassign signal to be ignored
  if (SigNum!=0) {
    signal(SigNum, SIG_IGN);
    SigNum=0;
  }

  // ensure window is removed and background drawn
  for (UINT i=0;i<4;i++) {
    Fl::check();
  }
}

//-------------------------------------------------------------------------
// Purpose: Signal handler to keep FLTK popup splash windows responsive
//
// Input:   signum   - [i] signal number occuring
//          info     - [i]
//          context  - [i]
//
// Output:  na
//
// Notes:
//
void CFLTKKeepAlive::SignalHandler(int signum, siginfo_t *info, void *context)
{
  if (signum==SigNum) {
    Fl::check();
  }
}

_______________________________________________
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to