mirror of
https://github.com/fltk/fltk.git
synced 2026-06-02 15:46:52 +08:00
Rework event loop handling on all platforms for better timer and idle
processing (STR #861) git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@4589 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
+167
-24
@@ -35,6 +35,7 @@
|
|||||||
#include <FL/x.H>
|
#include <FL/x.H>
|
||||||
#include <FL/Fl_Tooltip.H>
|
#include <FL/Fl_Tooltip.H>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "flstring.h"
|
#include "flstring.h"
|
||||||
|
|
||||||
@@ -104,6 +105,124 @@ int Fl::event_inside(const Fl_Widget *o) /*const*/ {
|
|||||||
return (mx >= 0 && mx < o->w() && my >= 0 && my < o->h());
|
return (mx >= 0 && mx < o->w() && my >= 0 && my < o->h());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// timer support
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
/// implementation in Fl_win32.cxx
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
//
|
||||||
|
// MacOS X timers
|
||||||
|
//
|
||||||
|
|
||||||
|
struct MacTimeout {
|
||||||
|
Fl_Timeout_Handler callback;
|
||||||
|
void* data;
|
||||||
|
EventLoopTimerRef timer;
|
||||||
|
};
|
||||||
|
static MacTimeout* mac_timers;
|
||||||
|
static int mac_timer_alloc;
|
||||||
|
static int mac_timer_used;
|
||||||
|
|
||||||
|
|
||||||
|
static void realloc_timers()
|
||||||
|
{
|
||||||
|
if (mac_timer_alloc == 0) {
|
||||||
|
mac_timer_alloc = 8;
|
||||||
|
}
|
||||||
|
MacTimeout* new_timers = new MacTimeout[mac_timer_alloc * 2];
|
||||||
|
memmove(new_timers, mac_timers, sizeof(MacTimeout) * mac_timer_used);
|
||||||
|
MacTimeout* delete_me = mac_timers;
|
||||||
|
mac_timers = new_timers;
|
||||||
|
delete [] delete_me;
|
||||||
|
mac_timer_alloc *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delete_timer(MacTimeout& t)
|
||||||
|
{
|
||||||
|
RemoveEventLoopTimer(t.timer);
|
||||||
|
memset(&t, 0, sizeof(MacTimeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static pascal void do_timer(EventLoopTimerRef timer, void* data)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mac_timer_used; ++i) {
|
||||||
|
MacTimeout& t = mac_timers[i];
|
||||||
|
if (t.timer == timer && t.data == data) {
|
||||||
|
return (*t.callback)(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
int timer_id = -1;
|
||||||
|
for (int i = 0; i < mac_timer_used; ++i) {
|
||||||
|
if ( !mac_timers[i].timer ) {
|
||||||
|
timer_id = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timer_id == -1) {
|
||||||
|
if (mac_timer_used == mac_timer_alloc) {
|
||||||
|
realloc_timers();
|
||||||
|
}
|
||||||
|
timer_id = mac_timer_used++;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventTimerInterval fireDelay = (EventTimerInterval) time;
|
||||||
|
EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(do_timer);
|
||||||
|
EventLoopTimerRef timerRef;
|
||||||
|
OSStatus err = InstallEventLoopTimer(GetMainEventLoop(), fireDelay, 0, timerUPP, data, &timerRef);
|
||||||
|
if (err == noErr) {
|
||||||
|
mac_timers[timer_id].callback = cb;
|
||||||
|
mac_timers[timer_id].data = data;
|
||||||
|
mac_timers[timer_id].timer = timerRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
remove_timeout(cb, data);
|
||||||
|
add_timeout(time, cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fl::has_timeout(Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mac_timer_used; ++i) {
|
||||||
|
MacTimeout& t = mac_timers[i];
|
||||||
|
if (t.callback == cb && t.data == data) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mac_timer_used; ++i) {
|
||||||
|
MacTimeout& t = mac_timers[i];
|
||||||
|
if (t.callback == cb && ( t.data == data || data == NULL)) {
|
||||||
|
delete_timer(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
//
|
||||||
|
// X11 timers
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// Timeouts are stored in a sorted list, so only the first one needs
|
// Timeouts are stored in a sorted list, so only the first one needs
|
||||||
// to be checked to see if any should be called.
|
// to be checked to see if any should be called.
|
||||||
@@ -115,10 +234,9 @@ struct Timeout {
|
|||||||
Timeout* next;
|
Timeout* next;
|
||||||
};
|
};
|
||||||
static Timeout* first_timeout, *free_timeout;
|
static Timeout* first_timeout, *free_timeout;
|
||||||
|
static int first_timeout_count, free_timeout_count;
|
||||||
|
|
||||||
#ifndef WIN32
|
#include <sys/time.h>
|
||||||
# include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// I avoid the overhead of getting the current time when we have no
|
// I avoid the overhead of getting the current time when we have no
|
||||||
// timeouts by setting this flag instead of getting the time.
|
// timeouts by setting this flag instead of getting the time.
|
||||||
@@ -127,12 +245,6 @@ static Timeout* first_timeout, *free_timeout;
|
|||||||
static char reset_clock = 1;
|
static char reset_clock = 1;
|
||||||
|
|
||||||
static void elapse_timeouts() {
|
static void elapse_timeouts() {
|
||||||
#ifdef WIN32
|
|
||||||
unsigned long newclock = GetTickCount();
|
|
||||||
static unsigned long prevclock;
|
|
||||||
double elapsed = (newclock-prevclock)/1000.0;
|
|
||||||
prevclock = newclock;
|
|
||||||
#else
|
|
||||||
static struct timeval prevclock;
|
static struct timeval prevclock;
|
||||||
struct timeval newclock;
|
struct timeval newclock;
|
||||||
gettimeofday(&newclock, NULL);
|
gettimeofday(&newclock, NULL);
|
||||||
@@ -140,7 +252,6 @@ static void elapse_timeouts() {
|
|||||||
(newclock.tv_usec - prevclock.tv_usec)/1000000.0;
|
(newclock.tv_usec - prevclock.tv_usec)/1000000.0;
|
||||||
prevclock.tv_sec = newclock.tv_sec;
|
prevclock.tv_sec = newclock.tv_sec;
|
||||||
prevclock.tv_usec = newclock.tv_usec;
|
prevclock.tv_usec = newclock.tv_usec;
|
||||||
#endif
|
|
||||||
if (reset_clock) {
|
if (reset_clock) {
|
||||||
reset_clock = 0;
|
reset_clock = 0;
|
||||||
} else if (elapsed > 0) {
|
} else if (elapsed > 0) {
|
||||||
@@ -162,8 +273,12 @@ void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
|
|||||||
void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
|
void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
|
||||||
time += missed_timeout_by; if (time < -.05) time = 0;
|
time += missed_timeout_by; if (time < -.05) time = 0;
|
||||||
Timeout* t = free_timeout;
|
Timeout* t = free_timeout;
|
||||||
if (t) free_timeout = t->next;
|
if (t) {
|
||||||
else t = new Timeout;
|
free_timeout = t->next;
|
||||||
|
--free_timeout_count;
|
||||||
|
} else {
|
||||||
|
t = new Timeout;
|
||||||
|
}
|
||||||
t->time = time;
|
t->time = time;
|
||||||
t->cb = cb;
|
t->cb = cb;
|
||||||
t->arg = argp;
|
t->arg = argp;
|
||||||
@@ -195,6 +310,8 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void *argp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// Checks are just stored in a list. They are called in the reverse
|
// Checks are just stored in a list. They are called in the reverse
|
||||||
// order that they were added (this may change in the future).
|
// order that they were added (this may change in the future).
|
||||||
@@ -208,7 +325,7 @@ struct Check {
|
|||||||
void* arg;
|
void* arg;
|
||||||
Check* next;
|
Check* next;
|
||||||
};
|
};
|
||||||
static Check* first_check, *next_check, *free_check;
|
static Check *first_check, *next_check, *free_check;
|
||||||
|
|
||||||
void Fl::add_check(Fl_Timeout_Handler cb, void *argp) {
|
void Fl::add_check(Fl_Timeout_Handler cb, void *argp) {
|
||||||
Check* t = free_check;
|
Check* t = free_check;
|
||||||
@@ -235,6 +352,20 @@ void Fl::remove_check(Fl_Timeout_Handler cb, void *argp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void run_checks()
|
||||||
|
{
|
||||||
|
// 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* checkp = next_check;
|
||||||
|
next_check = checkp->next;
|
||||||
|
(checkp->cb)(checkp->arg);
|
||||||
|
}
|
||||||
|
next_check = first_check;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// wait/run/check/ready:
|
// wait/run/check/ready:
|
||||||
|
|
||||||
@@ -249,6 +380,17 @@ double Fl::wait(double time_to_wait) {
|
|||||||
// delete all widgets that were listed during callbacks
|
// delete all widgets that were listed during callbacks
|
||||||
do_widget_deletion();
|
do_widget_deletion();
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
return fl_wait(time_to_wait);
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
flush();
|
||||||
|
return fl_wait(time_to_wait);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
if (first_timeout) {
|
if (first_timeout) {
|
||||||
elapse_timeouts();
|
elapse_timeouts();
|
||||||
Timeout *t;
|
Timeout *t;
|
||||||
@@ -262,22 +404,15 @@ double Fl::wait(double time_to_wait) {
|
|||||||
first_timeout = t->next;
|
first_timeout = t->next;
|
||||||
t->next = free_timeout;
|
t->next = free_timeout;
|
||||||
free_timeout = t;
|
free_timeout = t;
|
||||||
|
++free_timeout_count;
|
||||||
|
--first_timeout_count;
|
||||||
// Now it is safe for the callback to do add_timeout:
|
// Now it is safe for the callback to do add_timeout:
|
||||||
cb(argp);
|
cb(argp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reset_clock = 1; // we are not going to check the clock
|
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
|
run_checks();
|
||||||
// from inside them without causing an infinite loop:
|
|
||||||
if (next_check == first_check) {
|
|
||||||
while (next_check) {
|
|
||||||
Check* checkp = next_check;
|
|
||||||
next_check = checkp->next;
|
|
||||||
(checkp->cb)(checkp->arg);
|
|
||||||
}
|
|
||||||
next_check = first_check;
|
|
||||||
}
|
|
||||||
// if (idle && !fl_ready()) {
|
// if (idle && !fl_ready()) {
|
||||||
if (idle) {
|
if (idle) {
|
||||||
if (!in_idle) {
|
if (!in_idle) {
|
||||||
@@ -300,9 +435,10 @@ double Fl::wait(double time_to_wait) {
|
|||||||
flush();
|
flush();
|
||||||
return fl_wait(time_to_wait);
|
return fl_wait(time_to_wait);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FOREVER 1e20
|
#define FOREVER 0.01 //1e20
|
||||||
|
|
||||||
int Fl::run() {
|
int Fl::run() {
|
||||||
while (Fl_X::first) wait(FOREVER);
|
while (Fl_X::first) wait(FOREVER);
|
||||||
@@ -327,12 +463,14 @@ int Fl::check() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Fl::ready() {
|
int Fl::ready() {
|
||||||
|
#if ! defined( WIN32 ) && ! defined(__APPLE__)
|
||||||
if (first_timeout) {
|
if (first_timeout) {
|
||||||
elapse_timeouts();
|
elapse_timeouts();
|
||||||
if (first_timeout->time <= 0) return 1;
|
if (first_timeout->time <= 0) return 1;
|
||||||
} else {
|
} else {
|
||||||
reset_clock = 1;
|
reset_clock = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return fl_ready();
|
return fl_ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,6 +1237,11 @@ void Fl_Window::flush() {
|
|||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# include "Fl_win32.cxx"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
# include "Fl_mac.cxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following methods allow callbacks to schedule the deletion of
|
// The following methods allow callbacks to schedule the deletion of
|
||||||
|
|||||||
+183
-41
@@ -222,7 +222,6 @@ MSG fl_msg;
|
|||||||
// it returns 1.
|
// it returns 1.
|
||||||
int fl_wait(double time_to_wait) {
|
int fl_wait(double time_to_wait) {
|
||||||
int have_message = 0;
|
int have_message = 0;
|
||||||
int timerid;
|
|
||||||
|
|
||||||
#ifndef USE_ASYNC_SELECT
|
#ifndef USE_ASYNC_SELECT
|
||||||
if (nfds) {
|
if (nfds) {
|
||||||
@@ -260,52 +259,48 @@ int fl_wait(double time_to_wait) {
|
|||||||
|
|
||||||
fl_unlock_function();
|
fl_unlock_function();
|
||||||
|
|
||||||
if (time_to_wait < 2147483.648) {
|
time_to_wait = (time_to_wait > 10000 ? 10000 : time_to_wait);
|
||||||
// Perform the requested timeout...
|
int t_msec = (int) (time_to_wait * 1000.0 + 0.5);
|
||||||
have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
|
int ret_val = MsgWaitForMultipleObjects(0, NULL, FALSE, t_msec, QS_ALLINPUT);
|
||||||
if (!have_message) {
|
|
||||||
int t = (int)(time_to_wait * 1000.0 + .5);
|
|
||||||
if (t <= 0) { // too short to measure
|
|
||||||
fl_lock_function();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
timerid = SetTimer(NULL, 0, t, NULL);
|
|
||||||
have_message = GetMessage(&fl_msg, NULL, 0, 0);
|
|
||||||
KillTimer(NULL, timerid);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// make sure that we don't lock up if there are no more windows
|
|
||||||
// that could receive messages, but still handle pending messages.
|
|
||||||
if (!Fl_X::first)
|
|
||||||
have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
|
|
||||||
else
|
|
||||||
have_message = GetMessage(&fl_msg, NULL, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fl_lock_function();
|
fl_lock_function();
|
||||||
|
|
||||||
// Execute the message we got, and all other pending messages:
|
// Execute the message we got, and all other pending messages:
|
||||||
while (have_message) {
|
have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
|
||||||
|
if (have_message > 0) {
|
||||||
|
while (have_message != 0 && have_message != -1) {
|
||||||
#ifdef USE_ASYNC_SELECT
|
#ifdef USE_ASYNC_SELECT
|
||||||
if (fl_msg.message == WM_FLSELECT) {
|
if (fl_msg.message == WM_FLSELECT) {
|
||||||
// Got notification for socket
|
// Got notification for socket
|
||||||
for (int i = 0; i < nfds; i ++)
|
for (int i = 0; i < nfds; i ++)
|
||||||
if (fd[i].fd == (int)fl_msg.wParam) {
|
if (fd[i].fd == (int)fl_msg.wParam) {
|
||||||
(fd[i].cb)(fd[i].fd, fd[i].arg);
|
(fd[i].cb)(fd[i].fd, fd[i].arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// looks like it is best to do the dispatch-message anyway:
|
// looks like it is best to do the dispatch-message anyway:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fl_msg.message == fl_wake_msg) // Used for awaking wait() from another thread
|
if (fl_msg.message == fl_wake_msg) // Used for awaking wait() from another thread
|
||||||
thread_message_ = (void*)fl_msg.wParam;
|
thread_message_ = (void*)fl_msg.wParam;
|
||||||
|
|
||||||
TranslateMessage(&fl_msg);
|
TranslateMessage(&fl_msg);
|
||||||
DispatchMessage(&fl_msg);
|
DispatchMessage(&fl_msg);
|
||||||
have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
|
have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
|
||||||
|
}
|
||||||
|
Fl::flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// idle processing
|
||||||
|
static char in_idle;
|
||||||
|
if (Fl::idle && !in_idle) {
|
||||||
|
in_idle = 1;
|
||||||
|
Fl::idle();
|
||||||
|
in_idle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
run_checks();
|
||||||
|
|
||||||
// This should return 0 if only timer events were handled:
|
// This should return 0 if only timer events were handled:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -619,6 +614,45 @@ static int ms2fltk(int vk, int extended) {
|
|||||||
extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
|
extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Win32 timers
|
||||||
|
///
|
||||||
|
|
||||||
|
struct Win32Timer
|
||||||
|
{
|
||||||
|
UINT_PTR handle;
|
||||||
|
Fl_Timeout_Handler callback;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
static Win32Timer* win32_timers;
|
||||||
|
static int win32_timer_alloc;
|
||||||
|
static int win32_timer_used;
|
||||||
|
static HWND s_TimerWnd;
|
||||||
|
|
||||||
|
static void realloc_timers()
|
||||||
|
{
|
||||||
|
if (win32_timer_alloc == 0) {
|
||||||
|
win32_timer_alloc = 8;
|
||||||
|
}
|
||||||
|
size_t size = sizeof(Win32Timer);
|
||||||
|
Win32Timer* new_timers = new Win32Timer[win32_timer_alloc * 2];
|
||||||
|
memmove(new_timers, win32_timers, sizeof(Win32Timer) * win32_timer_used);
|
||||||
|
Win32Timer* delete_me = win32_timers;
|
||||||
|
win32_timers = new_timers;
|
||||||
|
delete [] delete_me;
|
||||||
|
win32_timer_alloc *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delete_timer(Win32Timer& t)
|
||||||
|
{
|
||||||
|
KillTimer(s_TimerWnd, t.handle);
|
||||||
|
memset(&t, 0, sizeof(Win32Timer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// END TIMERS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static Fl_Window* resize_bug_fix;
|
static Fl_Window* resize_bug_fix;
|
||||||
|
|
||||||
extern void fl_save_pen(void);
|
extern void fl_save_pen(void);
|
||||||
@@ -646,6 +680,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||||||
|
|
||||||
case WM_CLOSE: // user clicked close box
|
case WM_CLOSE: // user clicked close box
|
||||||
Fl::handle(FL_CLOSE, window);
|
Fl::handle(FL_CLOSE, window);
|
||||||
|
PostQuitMessage(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case WM_SYNCPAINT :
|
case WM_SYNCPAINT :
|
||||||
@@ -1149,13 +1184,14 @@ Fl_X* Fl_X::make(Fl_Window* w) {
|
|||||||
|
|
||||||
if (!class_name_list.has_name(class_name)) {
|
if (!class_name_list.has_name(class_name)) {
|
||||||
WNDCLASSEX wc;
|
WNDCLASSEX wc;
|
||||||
|
memset(&wc, 0, sizeof(wc));
|
||||||
|
wc.cbSize = sizeof(WNDCLASSEX);
|
||||||
// Documentation states a device context consumes about 800 bytes
|
// Documentation states a device context consumes about 800 bytes
|
||||||
// of memory... so who cares? If 800 bytes per window is what it
|
// of memory... so who cares? If 800 bytes per window is what it
|
||||||
// takes to speed things up, I'm game.
|
// takes to speed things up, I'm game.
|
||||||
//wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS;
|
//wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS;
|
||||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
|
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
|
||||||
wc.lpfnWndProc = (WNDPROC)WndProc;
|
wc.lpfnWndProc = (WNDPROC)WndProc;
|
||||||
wc.cbClsExtra = wc.cbWndExtra = 0;
|
|
||||||
wc.hInstance = fl_display;
|
wc.hInstance = fl_display;
|
||||||
if (!w->icon())
|
if (!w->icon())
|
||||||
w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
|
w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
|
||||||
@@ -1163,10 +1199,7 @@ Fl_X* Fl_X::make(Fl_Window* w) {
|
|||||||
wc.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW);
|
wc.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
//uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
|
//uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
|
||||||
//wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
|
//wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
|
||||||
wc.hbrBackground = NULL;
|
|
||||||
wc.lpszMenuName = NULL;
|
|
||||||
wc.lpszClassName = class_name;
|
wc.lpszClassName = class_name;
|
||||||
wc.cbSize = sizeof(WNDCLASSEX);
|
|
||||||
RegisterClassEx(&wc);
|
RegisterClassEx(&wc);
|
||||||
class_name_list.add_name(class_name);
|
class_name_list.add_name(class_name);
|
||||||
}
|
}
|
||||||
@@ -1285,6 +1318,115 @@ Fl_X* Fl_X::make(Fl_Window* w) {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Win32 timers
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
static LRESULT CALLBACK s_TimerProc(HWND hwnd, UINT msg,
|
||||||
|
WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg) {
|
||||||
|
case WM_TIMER:
|
||||||
|
{
|
||||||
|
unsigned int id = wParam - 1;
|
||||||
|
if (id < win32_timer_used && win32_timers[id].handle) {
|
||||||
|
Fl_Timeout_Handler cb = win32_timers[id].callback;
|
||||||
|
void* data = win32_timers[id].data;
|
||||||
|
delete_timer(win32_timers[id]);
|
||||||
|
if (cb) {
|
||||||
|
(*cb)(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
repeat_timeout(time, cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
int timer_id = -1;
|
||||||
|
for (int i = 0; i < win32_timer_used; ++i) {
|
||||||
|
if ( !win32_timers[i].handle ) {
|
||||||
|
timer_id = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timer_id == -1) {
|
||||||
|
if (win32_timer_used == win32_timer_alloc) {
|
||||||
|
realloc_timers();
|
||||||
|
}
|
||||||
|
timer_id = win32_timer_used++;
|
||||||
|
}
|
||||||
|
unsigned int elapsed = (unsigned int)(time * 1000);
|
||||||
|
|
||||||
|
if ( !s_TimerWnd ) {
|
||||||
|
const char* timer_class = "FLTimer";
|
||||||
|
WNDCLASSEX wc;
|
||||||
|
memset(&wc, 0, sizeof(wc));
|
||||||
|
wc.cbSize = sizeof (wc);
|
||||||
|
wc.style = CS_CLASSDC;
|
||||||
|
wc.lpfnWndProc = (WNDPROC)s_TimerProc;
|
||||||
|
wc.hInstance = fl_display;
|
||||||
|
wc.lpszClassName = timer_class;
|
||||||
|
ATOM atom = RegisterClassEx(&wc);
|
||||||
|
|
||||||
|
s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW,
|
||||||
|
timer_class, "",
|
||||||
|
WS_POPUP,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, 1, 1,
|
||||||
|
NULL, NULL, fl_display, NULL);
|
||||||
|
ShowWindow(s_TimerWnd, SW_SHOWNOACTIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
win32_timers[timer_id].callback = cb;
|
||||||
|
win32_timers[timer_id].data = data;
|
||||||
|
|
||||||
|
win32_timers[timer_id].handle =
|
||||||
|
SetTimer(s_TimerWnd, timer_id + 1, elapsed, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fl::has_timeout(Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < win32_timer_used; ++i) {
|
||||||
|
Win32Timer& t = win32_timers[i];
|
||||||
|
if (t.handle && t.callback == cb && t.data == data) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < win32_timer_used; ++i) {
|
||||||
|
Win32Timer& t = win32_timers[i];
|
||||||
|
if (t.handle && t.callback == cb &&
|
||||||
|
(t.data == data || data == NULL)) {
|
||||||
|
delete_timer(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// END TIMERS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HINSTANCE fl_display = GetModuleHandle(NULL);
|
HINSTANCE fl_display = GetModuleHandle(NULL);
|
||||||
|
|||||||
+2
-2
@@ -26,9 +26,9 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include "Fl_win32.cxx"
|
//# include "Fl_win32.cxx"
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
# include "Fl_mac.cxx"
|
//# include "Fl_mac.cxx"
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# define CONSOLIDATE_MOTION 1
|
# define CONSOLIDATE_MOTION 1
|
||||||
|
|||||||
Reference in New Issue
Block a user