So based on what I wrote last.  Here's the improved CFLTKKeepAlive class should 
anyone else find it useful for popup splash windows in the same thread under 
Linux/X.

//
// 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(unsigned waitms=0);
};

//-------------------
// 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(0);
    }
    else Stop(0);
  }
  // indicate if keep alive setup completed
  return result;
}

//-------------------------------------------------------------------------
// Purpose: Stop the keep alive process
//
// Input:   waitms - [i] time wait for x event to be reported
//
// Output:  na
//
// Notes:
//
void CFLTKKeepAlive::Stop(unsigned waitms)
{
  // 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;
  }

  // wait for events from xserver due to removed window
  unsigned i;
  for (i=0;i<waitms && !Fl::wait(0.001);i++);
  // wait for no more events or timeout
  // (at minimum there needs to be one Fl::check after the loop above
  // for fltk to send the draws to the server)
  for (;i<waitms && Fl::wait(0.001);i++);
}

//-------------------------------------------------------------------------
// 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