Yeah - what Bill said; peeking ahead in the queue and eliding any KEYUP that is immediately followed by the same KEYDOWN might be the only robust solution?
Dunno...
Interestingly, I actually looked at the docs for Keyboard Events, and it includes this exhortation:
I don't know who wrote that (I'm fairly sure it was not me, at any rate!) but that sounds like exactly the thing... Might be worth a try.
Meanwhile, in the interests of completeness, I added the timer check I proposed earlier. This appears to work just fine (On Windows) but today's another non-Linux day for me, so can't readily test under X11...
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Menu_Bar.H>
static int shown_v = 0;
/*****************************************************************************/
static bool still_pressing = false;
static bool timeout_active = false;
static void check_timeout (void *pv)
{
if (still_pressing == true)
{
still_pressing = false;
Fl::add_timeout(0.2, check_timeout, pv);
}
else
{
timeout_active = false;
Fl_Double_Window *w = (Fl_Double_Window *)pv;
if (shown_v) {
w->hide();
shown_v = 0;
}
else {
w->show();
shown_v = 1;
}
}
} // check_timeout
/*****************************************************************************/
class my_win : public Fl_Double_Window {
int handle (int);
public:
my_win(int x, int y,int w,int h,const char* L) : Fl_Double_Window(x,y,w,h,L) {};
}; // my_win
int my_win::handle (int e) {
int ret = Fl_Double_Window::handle(e);
if (e == FL_KEYDOWN) {
if (Fl::event_state() & (FL_ALT)) {
if (Fl::event_key()=='s') {
still_pressing = true;
if (!timeout_active)
{
Fl::add_timeout(0.2, check_timeout, (void *)this);
timeout_active = true;
}
return 1;
}
}
}
else if (e == FL_KEYUP) {
if (still_pressing)
{
still_pressing = false;
return 1;
}
}
return ret;
} // my_win::handle
static void toggle_win (Fl_Widget*,void* data) {
my_win* w = static_cast<my_win*>(data);
if (shown_v) {
w->hide();
shown_v = 0;
}
else {
w->show();
shown_v = 1;
}
} // toggle_win
int main() {
shown_v = 0;
my_win *win2 = new my_win(0.5*Fl::w()-100,0.5*Fl::h()-100,200,200,"2nd Win");
win2->end();
Fl_Double_Window *win = new Fl_Double_Window(0.5*Fl::w()-200,0.5*Fl::h()-200,400,400,"Main Win");
win->begin();
win->box (FL_FLAT_BOX);
Fl_Menu_Item items[] = {
{"Menu1",0,0,0,FL_SUBMENU,0,0,FL_NORMAL_SIZE,FL_BLACK}, //0
{"Hide/show second window",FL_ALT+'s',toggle_win,win2,0,0,0,FL_NORMAL_SIZE,FL_BLACK},
{0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0}
};
Fl_Menu_Bar *menu = new Fl_Menu_Bar(0, 0, win->w(),25);
menu->box (FL_BORDER_BOX);
menu->menu(items);
win->end();
win->show();
return Fl::run();
} // main
// end of file