Fl_Gl_Window does not set drawbuffer(BACKBUFFER) for single-buffered
windows. Fl_Input::replace(...) correctly updates the display if the replaced region does not include the mark, point, or selected region. Added Fl::add_check(...), Fl::remove_check, and Fl::has_check. These are similar to idle callbacks but are only called just before it waits for new events. They can be used to watch for changes in global state and respond to them. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.0@1347 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
0d0b066230
commit
f5375b6ab6
7
FL/Fl.H
7
FL/Fl.H
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: Fl.H,v 1.8.2.9 2000/06/21 17:36:33 bill Exp $"
|
||||
// "$Id: Fl.H,v 1.8.2.10 2000/12/12 08:57:29 spitzak Exp $"
|
||||
//
|
||||
// Main header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
@ -94,6 +94,9 @@ public:
|
||||
static FL_EXPORT void repeat_timeout(double t, Fl_Timeout_Handler,void* = 0);
|
||||
static FL_EXPORT int has_timeout(Fl_Timeout_Handler, void* = 0);
|
||||
static FL_EXPORT void remove_timeout(Fl_Timeout_Handler, void* = 0);
|
||||
static FL_EXPORT void add_check(Fl_Timeout_Handler, void* = 0);
|
||||
static FL_EXPORT int has_check(Fl_Timeout_Handler, void* = 0);
|
||||
static FL_EXPORT void remove_check(Fl_Timeout_Handler, void* = 0);
|
||||
static FL_EXPORT void add_fd(int fd, int when, void (*cb)(int,void*),void* =0);
|
||||
static FL_EXPORT void add_fd(int fd, void (*cb)(int, void*), void* = 0);
|
||||
static FL_EXPORT void remove_fd(int, int when);
|
||||
@ -214,5 +217,5 @@ public:
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl.H,v 1.8.2.9 2000/06/21 17:36:33 bill Exp $".
|
||||
// End of "$Id: Fl.H,v 1.8.2.10 2000/12/12 08:57:29 spitzak Exp $".
|
||||
//
|
||||
|
10
FL/glut.H
10
FL/glut.H
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: glut.H,v 1.6.2.7 2000/12/06 15:45:12 easysw Exp $"
|
||||
// "$Id: glut.H,v 1.6.2.8 2000/12/12 08:57:30 spitzak Exp $"
|
||||
//
|
||||
// GLUT emulation header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
@ -430,16 +430,14 @@ extern "C" {
|
||||
|
||||
extern int APIENTRY glutExtensionSupported(char *name);
|
||||
|
||||
/* Stroke font opaque addresses (use constants instead in source code). */
|
||||
extern void *glutStrokeRoman;
|
||||
extern void *glutStrokeMonoRoman;
|
||||
|
||||
/* Stroke font constants (use these in GLUT program). */
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# define GLUT_STROKE_ROMAN ((void*)0)
|
||||
# define GLUT_STROKE_MONO_ROMAN ((void*)1)
|
||||
#else
|
||||
extern void *glutStrokeRoman;
|
||||
# define GLUT_STROKE_ROMAN (&glutStrokeRoman)
|
||||
extern void *glutStrokeMonoRoman;
|
||||
# define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman)
|
||||
#endif
|
||||
|
||||
@ -472,5 +470,5 @@ extern void APIENTRY glutSolidIcosahedron();
|
||||
#endif /* __glut_h__ */
|
||||
|
||||
//
|
||||
// End of "$Id: glut.H,v 1.6.2.7 2000/12/06 15:45:12 easysw Exp $".
|
||||
// End of "$Id: glut.H,v 1.6.2.8 2000/12/12 08:57:30 spitzak Exp $".
|
||||
//
|
||||
|
@ -326,9 +326,39 @@ fair degree of accuracy:
|
||||
|
||||
main() {
|
||||
Fl::add_timeout(1.0,callback);
|
||||
for (;;) Fl::wait();
|
||||
return Fl::run();
|
||||
}</PRE></UL>
|
||||
|
||||
<h3><A name=add_timeout>static void Fl::add_check(void (*cb)(void*),void*v=0)</A></h3>
|
||||
|
||||
Fltk will call this callback just before it flushes the display and
|
||||
waits for events. This is different than an idle callback because it
|
||||
is only called once, then fltk calls the system and tells it not to
|
||||
return until an event happens.
|
||||
|
||||
<p>This can be used by code that wants to monitor the
|
||||
application's state, such as to keep a display up to date. The
|
||||
advantage of using a check callback is that it is called only when no
|
||||
events are pending. If events are coming in quickly, whole blocks of
|
||||
them will be processed before this is called once. This can save
|
||||
significant time and avoid the application falling behind the events.
|
||||
|
||||
<p>Sample code:
|
||||
|
||||
<ul><pre>bool state_changed; // anything that changes the display turns this on
|
||||
|
||||
void callback(void*) {
|
||||
if (!state_changed) return;
|
||||
state_changed = false;
|
||||
do_expensive_calculation();
|
||||
widget->redraw();
|
||||
}
|
||||
|
||||
main() {
|
||||
Fl::add_check(1.0,callback);
|
||||
return Fl::run();
|
||||
}</pre></ul>
|
||||
|
||||
<h3><A name=arg>static int Fl::arg(int argc, char **argv, int &i)</A></h3>
|
||||
|
||||
Consume a single switch from <tt>argv</tt>, starting at word i.
|
||||
@ -867,6 +897,15 @@ Returns true if the timeout exists and has not been called yet.
|
||||
Removes a timeout callback. It is harmless to remove a timeout
|
||||
callback that no longer exists.
|
||||
|
||||
<h3><A name=has_check>static int Fl::has_check(void (*cb)(void*), void* = 0)</A></h3>
|
||||
|
||||
Returns true if the check exists and has not been called yet.
|
||||
|
||||
<h3><A name=remove_check>static void Fl::remove_check(void (*cb)(void*), void* = 0)</A></h3>
|
||||
|
||||
Removes a check callback. It is harmless to remove a check
|
||||
callback that no longer exists.
|
||||
|
||||
<h3><A name=run>static Fl::run()</A></h3>
|
||||
|
||||
As long as any windows are displayed this calls <tt>Fl::wait()</tt>
|
||||
|
215
src/Fl.cxx
215
src/Fl.cxx
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: Fl.cxx,v 1.24.2.34 2000/11/20 19:02:20 easysw Exp $"
|
||||
// "$Id: Fl.cxx,v 1.24.2.35 2000/12/12 08:57:30 spitzak Exp $"
|
||||
//
|
||||
// Main event handling code for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
@ -67,23 +67,16 @@ int Fl::event_inside(const Fl_Widget *o) /*const*/ {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Timeouts and Fl::wait()
|
||||
|
||||
void (*Fl::idle)();
|
||||
|
||||
// Timeouts are insert-sorted into order. This works good if there
|
||||
// are only a small number:
|
||||
|
||||
static struct Timeout {
|
||||
// Timeouts are stored in a sorted list, so only the first one needs
|
||||
// to be checked to see if any should be called.
|
||||
|
||||
struct Timeout {
|
||||
double time;
|
||||
void (*cb)(void*);
|
||||
void* arg;
|
||||
} * timeout;
|
||||
static int numtimeouts;
|
||||
static int timeout_array_size;
|
||||
|
||||
extern int fl_wait(double time); // warning: assummes time >= 0.0
|
||||
extern int fl_ready();
|
||||
Timeout* next;
|
||||
};
|
||||
static Timeout* first_timeout, *free_timeout;
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
@ -96,68 +89,152 @@ extern int fl_ready();
|
||||
static char reset_clock = 1;
|
||||
|
||||
static void elapse_timeouts() {
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
unsigned long newclock = GetTickCount();
|
||||
static unsigned long prevclock;
|
||||
if (reset_clock) {
|
||||
prevclock = newclock;
|
||||
reset_clock = 0;
|
||||
return;
|
||||
}
|
||||
if (newclock <= prevclock) return;
|
||||
double elapsed = (newclock-prevclock)/1000.0;
|
||||
prevclock = newclock;
|
||||
|
||||
#else
|
||||
|
||||
static struct timeval prevclock;
|
||||
struct timeval newclock;
|
||||
gettimeofday(&newclock, NULL);
|
||||
if (reset_clock) {
|
||||
prevclock.tv_sec = newclock.tv_sec;
|
||||
prevclock.tv_usec = newclock.tv_usec;
|
||||
reset_clock = 0;
|
||||
return;
|
||||
}
|
||||
double elapsed = newclock.tv_sec - prevclock.tv_sec +
|
||||
(newclock.tv_usec - prevclock.tv_usec)/1000000.0;
|
||||
prevclock.tv_sec = newclock.tv_sec;
|
||||
prevclock.tv_usec = newclock.tv_usec;
|
||||
if (elapsed <= 0) return;
|
||||
|
||||
#endif
|
||||
|
||||
for (int i=0; i<numtimeouts; i++) timeout[i].time -= elapsed;
|
||||
if (reset_clock) {
|
||||
reset_clock = 0;
|
||||
} else if (elapsed > 0) {
|
||||
for (Timeout* t = first_timeout; t; t = t->next) t->time -= elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *arg) {
|
||||
elapse_timeouts();
|
||||
repeat_timeout(time, cb, arg);
|
||||
}
|
||||
|
||||
void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *arg) {
|
||||
elapse_timeouts();
|
||||
Timeout* t = free_timeout;
|
||||
if (t) free_timeout = t->next;
|
||||
else t = new Timeout;
|
||||
t->time = time;
|
||||
t->cb = cb;
|
||||
t->arg = arg;
|
||||
// insert-sort the new timeout:
|
||||
Timeout** p = &first_timeout;
|
||||
while (*p && (*p)->time <= time) p = &((*p)->next);
|
||||
t->next = *p;
|
||||
*p = t;
|
||||
}
|
||||
|
||||
int Fl::has_timeout(Fl_Timeout_Handler cb, void *arg) {
|
||||
for (Timeout* t = first_timeout; t; t = t->next)
|
||||
if (t->cb == cb && t->arg == arg) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fl::remove_timeout(Fl_Timeout_Handler cb, void *arg) {
|
||||
// This version removes all matching timeouts, not just the first one.
|
||||
// This may change in the future.
|
||||
for (Timeout** p = &first_timeout; *p;) {
|
||||
Timeout* t = *p;
|
||||
if (t->cb == cb && t->arg == arg) {
|
||||
*p = t->next;
|
||||
t->next = free_timeout;
|
||||
free_timeout = t;
|
||||
} else {
|
||||
p = &(t->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Checks are just stored in a list. They are called in the reverse
|
||||
// order that they were added (this may change in the future).
|
||||
// This is a bit messy because I want to allow checks to be added,
|
||||
// removed, and have wait() called from inside them, to do this
|
||||
// next_check points at the next unprocessed one for the outermost
|
||||
// call to Fl::wait().
|
||||
|
||||
struct Check {
|
||||
void (*cb)(void*);
|
||||
void* arg;
|
||||
Check* next;
|
||||
};
|
||||
static Check* first_check, *next_check, *free_check;
|
||||
|
||||
void Fl::add_check(Fl_Timeout_Handler cb, void *arg) {
|
||||
Check* t = free_check;
|
||||
if (t) free_check = t->next;
|
||||
else t = new Check;
|
||||
t->cb = cb;
|
||||
t->arg = arg;
|
||||
t->next = first_check;
|
||||
if (next_check == first_check) next_check = t;
|
||||
first_check = t;
|
||||
}
|
||||
|
||||
void Fl::remove_check(Fl_Timeout_Handler cb, void *arg) {
|
||||
for (Check** p = &first_check; *p;) {
|
||||
Check* t = *p;
|
||||
if (t->cb == cb && t->arg == arg) {
|
||||
if (next_check == t) next_check = t->next;
|
||||
*p = t->next;
|
||||
t->next = free_check;
|
||||
free_check = t;
|
||||
} else {
|
||||
p = &(t->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// wait/run/check/ready:
|
||||
|
||||
void (*Fl::idle)(); // see Fl_add_idle.cxx for the add/remove functions
|
||||
|
||||
extern int fl_wait(double time); // in Fl_x.cxx or Fl_win32.cxx
|
||||
|
||||
static char in_idle;
|
||||
|
||||
double Fl::wait(double time_to_wait) {
|
||||
if (numtimeouts) {
|
||||
if (first_timeout) {
|
||||
elapse_timeouts();
|
||||
if (timeout[0].time <= time_to_wait) time_to_wait = timeout[0].time;
|
||||
while (numtimeouts) {
|
||||
if (timeout[0].time > 0) break;
|
||||
while (Timeout* t = first_timeout) {
|
||||
if (t->time > 0) break;
|
||||
// The first timeout in the array has expired.
|
||||
// We must remove timeout from array before doing the callback:
|
||||
void (*cb)(void*) = timeout[0].cb;
|
||||
void *arg = timeout[0].arg;
|
||||
numtimeouts--;
|
||||
if (numtimeouts)
|
||||
memmove(timeout, timeout+1, numtimeouts*sizeof(Timeout));
|
||||
void (*cb)(void*) = t->cb;
|
||||
void *arg = t->arg;
|
||||
first_timeout = t->next;
|
||||
t->next = free_timeout;
|
||||
free_timeout = t;
|
||||
// Now it is safe for the callback to do add_timeout:
|
||||
cb(arg);
|
||||
}
|
||||
} else {
|
||||
reset_clock = 1; // we are not going to check the clock
|
||||
}
|
||||
// checks are a bit messy so that add/remove and wait may be called
|
||||
// from inside them without causing an infinite loop:
|
||||
if (next_check == first_check) {
|
||||
while (next_check) {
|
||||
Check* check = next_check;
|
||||
next_check = check->next;
|
||||
(check->cb)(check->arg);
|
||||
}
|
||||
next_check = first_check;
|
||||
}
|
||||
if (idle) {
|
||||
if (!in_idle) {in_idle = 1; idle(); in_idle = 0;}
|
||||
// the idle function may turn off idle, we can then wait:
|
||||
if (idle) time_to_wait = 0.0;
|
||||
}
|
||||
if (first_timeout && first_timeout->time < time_to_wait)
|
||||
time_to_wait = first_timeout->time;
|
||||
if (time_to_wait <= 0.0) {
|
||||
// do flush second so that the results of events are visible:
|
||||
int ret = fl_wait(0.0);
|
||||
@ -187,58 +264,18 @@ int Fl::check() {
|
||||
return Fl_X::first != 0; // return true if there is a window
|
||||
}
|
||||
|
||||
extern int fl_ready();
|
||||
|
||||
int Fl::ready() {
|
||||
if (numtimeouts) {
|
||||
if (first_timeout) {
|
||||
elapse_timeouts();
|
||||
if (timeout[0].time <= 0) return 1;
|
||||
if (first_timeout->time <= 0) return 1;
|
||||
} else {
|
||||
reset_clock = 1;
|
||||
}
|
||||
return fl_ready();
|
||||
}
|
||||
|
||||
void Fl::add_timeout(double t, Fl_Timeout_Handler cb, void *v) {
|
||||
elapse_timeouts();
|
||||
repeat_timeout(t, cb, v);
|
||||
}
|
||||
|
||||
void Fl::repeat_timeout(double t, Fl_Timeout_Handler cb, void *v) {
|
||||
|
||||
if (numtimeouts >= timeout_array_size) {
|
||||
timeout_array_size = 2*timeout_array_size+1;
|
||||
timeout = (Timeout*)realloc(timeout, timeout_array_size*sizeof(Timeout));
|
||||
}
|
||||
|
||||
// insert-sort the new timeout:
|
||||
int i;
|
||||
for (i=0; i<numtimeouts; i++) {
|
||||
if (timeout[i].time > t) {
|
||||
for (int j=numtimeouts; j>i; j--) timeout[j] = timeout[j-1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
timeout[i].time = t;
|
||||
timeout[i].cb = cb;
|
||||
timeout[i].arg = v;
|
||||
|
||||
numtimeouts++;
|
||||
}
|
||||
|
||||
int Fl::has_timeout(Fl_Timeout_Handler cb, void *v) {
|
||||
for (int i=0; i<numtimeouts; i++)
|
||||
if (timeout[i].cb == cb && timeout[i].arg==v) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fl::remove_timeout(Fl_Timeout_Handler cb, void *v) {
|
||||
int i,j;
|
||||
for (i=j=0; i<numtimeouts; i++) {
|
||||
if (timeout[i].cb == cb && timeout[i].arg==v) ;
|
||||
else {if (j<i) timeout[j]=timeout[i]; j++;}
|
||||
}
|
||||
numtimeouts = j;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Window list management:
|
||||
|
||||
@ -734,5 +771,5 @@ void Fl_Window::flush() {
|
||||
}
|
||||
|
||||
//
|
||||
// End of "$Id: Fl.cxx,v 1.24.2.34 2000/11/20 19:02:20 easysw Exp $".
|
||||
// End of "$Id: Fl.cxx,v 1.24.2.35 2000/12/12 08:57:30 spitzak Exp $".
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: Fl_Gl_Window.cxx,v 1.12.2.18 2000/12/06 15:45:13 easysw Exp $"
|
||||
// "$Id: Fl_Gl_Window.cxx,v 1.12.2.19 2000/12/12 08:57:30 spitzak Exp $"
|
||||
//
|
||||
// OpenGL window code for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
@ -122,7 +122,7 @@ void Fl_Gl_Window::make_current() {
|
||||
RealizePalette(fl_gc);
|
||||
}
|
||||
#endif // USE_COLORMAP
|
||||
glDrawBuffer(GL_BACK);
|
||||
if (g->d) glDrawBuffer(GL_BACK);
|
||||
current_ = this;
|
||||
}
|
||||
|
||||
@ -337,5 +337,5 @@ void Fl_Gl_Window::draw_overlay() {}
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Gl_Window.cxx,v 1.12.2.18 2000/12/06 15:45:13 easysw Exp $".
|
||||
// End of "$Id: Fl_Gl_Window.cxx,v 1.12.2.19 2000/12/12 08:57:30 spitzak Exp $".
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: Fl_Input_.cxx,v 1.21.2.9 2000/09/19 07:21:19 spitzak Exp $"
|
||||
// "$Id: Fl_Input_.cxx,v 1.21.2.10 2000/12/12 08:57:30 spitzak Exp $"
|
||||
//
|
||||
// Common input widget routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
@ -586,7 +586,7 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
|
||||
size_ += ilen;
|
||||
}
|
||||
undowidget = this;
|
||||
mark_ = position_ = undoat = b+ilen;
|
||||
undoat = b+ilen;
|
||||
|
||||
#ifdef WORDWRAP
|
||||
// Insertions into the word at the end of the line will cause it to
|
||||
@ -597,8 +597,15 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
|
||||
if (type() == FL_MULTILINE_INPUT)
|
||||
while (b > 0 && !isspace(index(b))) b--;
|
||||
#endif
|
||||
|
||||
|
||||
// make sure we redraw the old selection or cursor:
|
||||
if (mark_ < b) b = mark_;
|
||||
if (position_ < b) b = position_;
|
||||
|
||||
minimal_update(b);
|
||||
|
||||
mark_ = position_ = undoat;
|
||||
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(); else set_changed();
|
||||
return 1;
|
||||
}
|
||||
@ -810,5 +817,5 @@ Fl_Input_::~Fl_Input_() {
|
||||
}
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Input_.cxx,v 1.21.2.9 2000/09/19 07:21:19 spitzak Exp $".
|
||||
// End of "$Id: Fl_Input_.cxx,v 1.21.2.10 2000/12/12 08:57:30 spitzak Exp $".
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user