summaryrefslogtreecommitdiff
path: root/src/Fl_win32.cxx
diff options
context:
space:
mode:
authorMichael R Sweet <michael.r.sweet@gmail.com>2005-10-12 20:19:30 +0000
committerMichael R Sweet <michael.r.sweet@gmail.com>2005-10-12 20:19:30 +0000
commitdc7a14aa9a2842a07740e1ab7573cf850ef753c5 (patch)
tree262149205b827a7fc911a0bfbcea3b4fed18d1ec /src/Fl_win32.cxx
parent592e215dd61d3c71714e522b8975a8d3587d7da0 (diff)
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
Diffstat (limited to 'src/Fl_win32.cxx')
-rw-r--r--src/Fl_win32.cxx224
1 files changed, 183 insertions, 41 deletions
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index ebeed9d67..345d76ea9 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -222,7 +222,6 @@ MSG fl_msg;
// it returns 1.
int fl_wait(double time_to_wait) {
int have_message = 0;
- int timerid;
#ifndef USE_ASYNC_SELECT
if (nfds) {
@@ -260,52 +259,48 @@ int fl_wait(double time_to_wait) {
fl_unlock_function();
- if (time_to_wait < 2147483.648) {
- // Perform the requested timeout...
- have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
- 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);
- }
+ time_to_wait = (time_to_wait > 10000 ? 10000 : time_to_wait);
+ int t_msec = (int) (time_to_wait * 1000.0 + 0.5);
+ int ret_val = MsgWaitForMultipleObjects(0, NULL, FALSE, t_msec, QS_ALLINPUT);
fl_lock_function();
// 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
- if (fl_msg.message == WM_FLSELECT) {
- // Got notification for socket
- for (int i = 0; i < nfds; i ++)
- if (fd[i].fd == (int)fl_msg.wParam) {
- (fd[i].cb)(fd[i].fd, fd[i].arg);
- break;
- }
- // looks like it is best to do the dispatch-message anyway:
- }
+ if (fl_msg.message == WM_FLSELECT) {
+ // Got notification for socket
+ for (int i = 0; i < nfds; i ++)
+ if (fd[i].fd == (int)fl_msg.wParam) {
+ (fd[i].cb)(fd[i].fd, fd[i].arg);
+ break;
+ }
+ // looks like it is best to do the dispatch-message anyway:
+ }
#endif
- if (fl_msg.message == fl_wake_msg) // Used for awaking wait() from another thread
- thread_message_ = (void*)fl_msg.wParam;
+ if (fl_msg.message == fl_wake_msg) // Used for awaking wait() from another thread
+ thread_message_ = (void*)fl_msg.wParam;
+
+ TranslateMessage(&fl_msg);
+ DispatchMessage(&fl_msg);
+ have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ }
+ Fl::flush();
+ }
- TranslateMessage(&fl_msg);
- DispatchMessage(&fl_msg);
- have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ // 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:
return 1;
}
@@ -619,6 +614,45 @@ static int ms2fltk(int vk, int extended) {
extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
#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;
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
Fl::handle(FL_CLOSE, window);
+ PostQuitMessage(0);
return 0;
case WM_SYNCPAINT :
@@ -1149,13 +1184,14 @@ Fl_X* Fl_X::make(Fl_Window* w) {
if (!class_name_list.has_name(class_name)) {
WNDCLASSEX wc;
+ memset(&wc, 0, sizeof(wc));
+ wc.cbSize = sizeof(WNDCLASSEX);
// Documentation states a device context consumes about 800 bytes
// of memory... so who cares? If 800 bytes per window is what it
// 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_OWNDC | CS_DBLCLKS;
wc.lpfnWndProc = (WNDPROC)WndProc;
- wc.cbClsExtra = wc.cbWndExtra = 0;
wc.hInstance = fl_display;
if (!w->icon())
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);
//uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
//wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
wc.lpszClassName = class_name;
- wc.cbSize = sizeof(WNDCLASSEX);
RegisterClassEx(&wc);
class_name_list.add_name(class_name);
}
@@ -1285,6 +1318,115 @@ Fl_X* Fl_X::make(Fl_Window* w) {
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);