I'm writing an FLTK chess client (using 1.1.9) which lets two people connect
over a TCP/IP connection and play a game of chess. It work pretty well but I
have found one bug which I think is a result of the way FLTK is handling
events. I have an option that lets a play request an undo. When this option is
selected a modal window will pop up on the opponents screen and say something
like "opponent requests an undo." with a "yes" and "no" button. Most of the
time this works fine. The problem is if the player receiving the undo request
is in a menu (that is, the menu bar item is active and being drawn): when the
pop-up window appears the program locks up. The mouse works and everything, but
it seems that neither the menu nor the window (or any other widget) is able to
receive mouse or keyboard events. Does anyone have an idea of a fix around this
problem? I'd also like to understand what widgets (if any) are suppose to
receive events in a case like this.
One simple thing that I did think of trying is simply forcefully closing the
menu before the window pops up, but I can't seem to find a Fl_Widget or
Fl_Menu_* function that does what I want.
Here's a small program that recreates the problem. Start it up and hit the 'z'
key and you'll see a window. Hit yes or no, and the window should close fine.
Now click on the "File" menu and while the menu bar is open hit the 'z' key
again. The program should lockup at this point.
main.cpp:
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Menu_Bar.H>
// callback for the "yes" button
void yes_cb(Fl_Widget* o, void* p)
{
// store a value of true in the response window user_data
Fl_Window* w = (Fl_Window*)p;
bool* b = (bool*)(w->user_data());
*b=true;
w->hide();
}
// callback for the "no" button
void no_cb(Fl_Widget* o, void* p)
{
// store a value of false in the response window user_data
Fl_Window* w = (Fl_Window*)p;
bool* b = (bool*)(w->user_data());
*b=false;
w->hide();
}
// this creates the pop up window
bool getResponse()
{
Fl_Window* responseWindow = new Fl_Window(100,100,100,100,"Please Pick One");
Fl_Button* yesButton = new Fl_Button(10,10,80,20,"Yes");
Fl_Button* noButton = new Fl_Button(10,40,80,20,"No");
yesButton->callback(yes_cb,responseWindow);
noButton ->callback(no_cb,responseWindow);
responseWindow->end();
responseWindow->set_modal();
responseWindow->show();
bool response = false;
responseWindow->user_data((void*)&response);
// Here's where it hangs
while (responseWindow->shown())
Fl::wait();
delete responseWindow;
return response;
}
// keystroke handler to capture the 'z' key
// I just do this so you can call a function while browsing in a menu bar
int myHandler(int e)
{
if (e==FL_SHORTCUT)
{
if (Fl::event_key()==122)
{
getResponse();
return 1;
}
return 0;
}
return 0;
}
int main(int argc, char **argv) {
Fl_Window *mainWindow = new Fl_Window(500,500);
Fl_Menu_Item menuitems[] = {
{ "&File", 0, 0, 0, FL_SUBMENU },
{ "E&xit", 0, 0, 0 },
{ 0 },{ 0 }
};
Fl_Menu_Bar *m = new Fl_Menu_Bar(0, 0, 640, 30);
m->copy(menuitems);
mainWindow->end();
mainWindow->show(argc, argv);
Fl::add_handler(myHandler);
return Fl::run();
}
I know I can use a call to fl_choice() to accomplish a similar task but I'd
prefer to have the pop up window be custom. Also, I feel like the way I store
the response in the window user_data might be kind of kludgy. If you have any
suggestions on a better way to do this, it'd be greatly appreciated as well.
Thanks in advance for any help you can provide.
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs