From e7d805a88ca71a0e6499fe72830e58fe594ef05b Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Tue, 6 Oct 1998 18:46:47 +0000 Subject: Commited Gustavo Hime's NT patches/fixes. git-svn-id: file:///fltk/svn/fltk/trunk@7 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl.cxx | 1131 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 565 insertions(+), 566 deletions(-) (limited to 'src/Fl.cxx') diff --git a/src/Fl.cxx b/src/Fl.cxx index 06a0c62b1..17973ded6 100644 --- a/src/Fl.cxx +++ b/src/Fl.cxx @@ -1,566 +1,565 @@ -// Fl.C - -// fltk (Fast Light Tool Kit) version 0.99 -// Copyright (C) 1998 Bill Spitzak - -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Library General Public License for more details. - -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA. - -// Written by Bill Spitzak spitzak@d2.com - -#include -#include -#include -#include - -int Fl::damage_; -Fl_Widget *Fl::belowmouse_; -Fl_Widget *Fl::pushed_; -Fl_Widget *Fl::focus_; -Fl_Widget *Fl::selection_owner_; -int Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root; -int Fl::e_state; -int Fl::e_clicks; -int Fl::e_is_click; -int Fl::e_keysym; -char *Fl::e_text; -int Fl::e_length; - -int Fl::event_inside(int x,int y,int w,int h) /*const*/ { - int mx = event_x(); - int my = event_y(); - return (mx >= x && mx < x+w && my >= y && my < y+h); -} - -int Fl::event_inside(const Fl_Widget *o) /*const*/ { - return event_inside(o->x(),o->y(),o->w(),o->h()); -} - -// Timeouts are insert-sorted into order. This works good if there -// are only a small number: - -#define MAXTIMEOUT 8 - -static struct { - double time; - void (*cb)(void*); - void* arg; -} timeout[MAXTIMEOUT+1]; -static int numtimeouts; - -void Fl::add_timeout(double t, void (*cb)(void *), void *v) { - int i; - if (numtimeouts t) { - for (int j=numtimeouts-1; j>i; j--) timeout[j] = timeout[j-1]; - break; - } - } - timeout[i].time = t; - timeout[i].cb = cb; - timeout[i].arg = v; -} - -void Fl::remove_timeout(void (*cb)(void *), void *v) { - int i,j; - for (i=j=0; i 0) return; - struct { - void (*cb)(void *); - void *arg; - } temp[MAXTIMEOUT]; - int i,j,k; - // copy all expired timeouts to temp array: - for (i=j=0; jnext) { - if (x->w->damage() && x->w->visible()) { - x->flush(); - x->w->clear_damage(); - } - } - } -#ifndef WIN32 - if (fl_display) XFlush(fl_display); -#endif -} - -extern double fl_wait(int timeout_flag, double timeout); -extern int fl_ready(); - -static int initclock; // if false we didn't call fl_elapsed() last time - -#ifndef WIN32 -#include -#endif - -// fl_elapsed must return the amount of time since the last time it was -// called. To reduce the number of system calls the to get the -// current time, the "initclock" symbol is turned on by an indefinate -// wait. This should then reset the measured-from time and return zero -static double fl_elapsed() { - -#ifdef WIN32 - - unsigned long newclock = fl_msg.time; // NOT YET IMPLEMENTED! - const int TICKS_PER_SECOND = 1000; // divisor of the value to get seconds - static unsigned long prevclock; - if (!initclock) {prevclock = newclock; initclock = 1; return 0.0;} - double t = double(newclock-prevclock)/TICKS_PER_SECOND; - prevclock = newclock; - -#else - - static struct timeval prevclock; - struct timeval newclock; - gettimeofday(&newclock, 0); - if (!initclock) { - prevclock.tv_sec = newclock.tv_sec; - prevclock.tv_usec = newclock.tv_usec; - initclock = 1; - return 0.0; - } - double t = 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; - -#endif - - // expire any timeouts: - if (t > 0.0) for (int i=0; inext) - if (window->xid == xid) { - if (window != Fl_X::first && !Fl::modal()) { - // make this window be first to speed up searches - // this is not done if modal is true to avoid messing up modal stack - *pp = window->next; - window->next = Fl_X::first; - Fl_X::first = window; - } - return window->w; - } - return 0; -} - -void Fl::redraw() { - for (Fl_X* x = Fl_X::first; x; x = x->next) x->w->redraw(); -} - -Fl_Window* Fl::first_window() {Fl_X* x = Fl_X::first; return x ? x->w : 0;} - -Fl_Window* Fl::next_window(const Fl_Window* w) { - Fl_X* x = Fl_X::i(w)->next; return x ? x->w : 0;} - -//////////////////////////////////////////////////////////////// -// Event handlers: - -struct handler_link { - int (*handle)(int); - const handler_link *next; -}; - -static const handler_link *handlers = 0; - -void Fl::add_handler(int (*h)(int)) { - handler_link *l = new handler_link; - l->handle = h; - l->next = handlers; - handlers = l; -} - -static int send_handlers(int event) { - for (const handler_link *h = handlers; h; h = h->next) - if (h->handle(event)) return 1; - return 0; -} - -//////////////////////////////////////////////////////////////// - -Fl_Widget* fl_oldfocus; // kludge for Fl_Group... - -void Fl::focus(Fl_Widget *o) { - Fl_Widget *p = focus_; - if (o != p) { - focus_ = o; - fl_oldfocus = 0; - for (; p && !p->contains(o); p = p->parent()) { - p->handle(FL_UNFOCUS); - fl_oldfocus = p; - } - } -} - -void Fl::belowmouse(Fl_Widget *o) { - Fl_Widget *p = belowmouse_; - if (o != p) { - event_is_click(0); - belowmouse_ = o; - for (; p && !p->contains(o); p = p->parent()) p->handle(FL_LEAVE); - } -} - -// Because mouse events are posted to the outermost window we need to -// adjust them for child windows if they are pushed(). This should also -// be done for the focus() but that is nyi. -static int mouse_dx; -static int mouse_dy; - -void Fl::pushed(Fl_Widget *o) { - pushed_ = o; - mouse_dx = 0; - mouse_dy = 0; - if (o) for (Fl_Widget* w = o; w->parent(); w = w->parent()) { - if (w->type()>=FL_WINDOW) {mouse_dx -= w->x(); mouse_dy -= w->y();} - } -} - -Fl_Window *fl_xfocus; // which window X thinks has focus -Fl_Window *fl_xmousewin; // which window X thinks has FL_ENTER -Fl_Window *Fl::grab_; // most recent Fl::grab() -Fl_Window *Fl::modal_; - -// Update modal(), focus() and other state according to system state. -// This is called whenever a window is added or hidden, and whenever -// X says the focus or mouse window have changed, and when grab_ is -// changed. -void fl_fix_focus() { - - // set Fl::modal() based on grab or any modal windows displayed: - if (Fl::grab_) - Fl::modal_ = Fl::grab_; - else { - Fl_Window* w = Fl::first_window(); - while (w && w->parent()) w = Fl::next_window(w); - Fl::modal_ = w && w->modal() ? w : 0; - } - - // set focus based on Fl::modal() and fl_xfocus - Fl_Window *w = fl_xfocus; - while (w && w->parent()) w = w->window(); - if (w) { - if (Fl::modal()) w = Fl::modal(); - if (!w->contains(Fl::focus())) - if (!w->take_focus()) Fl::focus(w); - } else - Fl::focus(0); - - if (Fl::pushed()) { - - // move pushed() to modal window (necessary for menus): - if (Fl::modal() && !Fl::modal()->contains(Fl::pushed())) - Fl::pushed_ = Fl::modal(); - - } else { // set belowmouse only when pushed() is false - - // set belowmouse based on Fl::modal() and fl_xmousewin: - w = fl_xmousewin; - if (w) { - if (Fl::modal()) w = Fl::modal(); - if (!w->contains(Fl::belowmouse())) { - Fl::belowmouse(w); w->handle(FL_ENTER);} - } else - Fl::belowmouse(0); - } -} - -//////////////////////////////////////////////////////////////// - -int Fl::handle(int event, Fl_Window* window) -{ - Fl_Widget* w = window; - - switch (event) { - - case FL_CLOSE: - if (modal() && window != modal()) return 0; - w->do_callback(); - return 1; - - case FL_SHOW: - ((Fl_Widget*)w)->show(); - return 1; - - case FL_HIDE: - ((Fl_Widget*)w)->hide(); - return 1; - - case FL_PUSH: - if (Fl::grab()) w = Fl::grab(); - else if (Fl::modal() && w != Fl::modal()) return 0; - Fl::pushed_ = w; mouse_dx = mouse_dy = 0; - if (w->handle(event)) return 1; - // raise windows that are clicked on: - window->show(); - return 1; - - case FL_MOVE: - case FL_DRAG: - if (window != fl_xmousewin) { - // this should not happen if enter/leave events were reported - // correctly by the system, but just in case... - fl_xmousewin = window; fl_fix_focus(); - } - if (Fl::pushed()) { - Fl::e_x += mouse_dx; - Fl::e_y += mouse_dy; - event = FL_DRAG; - w = Fl::pushed(); - } else if (Fl::grab()) - w = Fl::grab(); - else if (Fl::modal() && w != Fl::modal()) - w = 0; - break; - - case FL_RELEASE: { - if (Fl::pushed_) w = Fl::pushed_; Fl::pushed_ = 0; - int r = w->handle(event); - fl_fix_focus(); - if (fl_xmousewin) fl_xmousewin->handle(FL_MOVE); - return r;} - - case FL_UNFOCUS: - window = 0; - case FL_FOCUS: - fl_xfocus = window; - Fl::e_keysym = 0; // make sure it is not confused with navigation key - fl_fix_focus(); - return 1; - - case FL_KEYBOARD: - if (window != fl_xfocus) { - // this should not happen if enter/leave events were reported - // correctly by the system, but just in case... - fl_xfocus = window; fl_fix_focus(); - } - // Try it as keystroke, sending it to focus and all parents: - for (w = Fl::focus(); w; w = w->parent()) - if (w->handle(FL_KEYBOARD)) return 1; - - // Try it as shortcut, sending to mouse widget and all parents: - w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;} - for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1; - - // try using add_handle() functions: - if (send_handlers(FL_SHORTCUT)) return 1; - - // Try swapping the case of the text in the shortcut: - if (isalpha(Fl::event_text()[0])) { - *(char*)(Fl::event_text()) ^= ('A'^'a'); - w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;} - for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1; - if (send_handlers(FL_SHORTCUT)) return 1; - } - - // make Escape key close windows: - if (Fl::event_key()==FL_Escape) { - window->do_callback(); - return 1; - } - - return 0; - - case FL_ENTER: - fl_xmousewin = window; fl_fix_focus(); - return 1; - - case FL_LEAVE: - if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();} - return 1; - - default: - break; - } - if (w && w->handle(event)) return 1; - return send_handlers(event); -} - -//////////////////////////////////////////////////////////////// -// hide() destroys the X window, it does not do unmap! - -void fl_throw_focus(Fl_Widget*); // in Fl_x.C - -void Fl_Window::hide() { - if (!shown()) return; - - // remove from the list of windows: - Fl_X* x = i; - Fl_X** pp = &Fl_X::first; - for (; *pp != x; pp = &(*pp)->next) if (!*pp) return; - *pp = x->next; - i = 0; - - // recursively remove any subwindows: - for (Fl_X *w = Fl_X::first; w;) { - Fl_Window* W = w->w; - if (W->window() == this) { - W->hide(); - W->set_visible(); - w = Fl_X::first; - } else w = w->next; - } - - // Make sure no events are sent to this window: - if (this == fl_xmousewin) fl_xmousewin = 0; - if (this == fl_xfocus) fl_xfocus = 0; - fl_throw_focus(this); - handle(FL_HIDE); - -#ifdef WIN32 - if (x->private_dc) ReleaseDC(x->xid,x->private_dc); - if (x->xid == fl_window) fl_GetDC(0); // releases dc belonging to window -#else - if (x->region) XDestroyRegion(x->region); -#endif - XDestroyWindow(fl_display, x->xid); - - delete x; -} - -Fl_Window::~Fl_Window() { - hide(); -} - -// Child windows must respond to FL_SHOW and FL_HIDE by actually -// doing unmap operations. Outer windows assumme FL_SHOW & FL_HIDE -// are messages from X: - -int Fl_Window::handle(int event) { - if (parent()) switch (event) { - case FL_SHOW: - if (!shown()) show(); - else XMapWindow(fl_display, fl_xid(this)); - break; - case FL_HIDE: - if (shown()) XUnmapWindow(fl_display, fl_xid(this)); - break; - } - return Fl_Group::handle(event); -} - -//////////////////////////////////////////////////////////////// -// ~Fl_Widget() calls this: this function must get rid of any -// global pointers to the widget. This is also called by hide() -// and deactivate(). - -// call this to free a selection (or change the owner): -void Fl::selection_owner(Fl_Widget *owner) { - if (selection_owner_ && owner != selection_owner_) - selection_owner_->handle(FL_SELECTIONCLEAR); - selection_owner_ = owner; -} - -#ifndef WIN32 -Fl_Widget *fl_selection_requestor; // from Fl_cutpaste.C -#endif - -void fl_throw_focus(Fl_Widget *o) { - if (o->contains(Fl::pushed())) Fl::pushed(0); - if (o->contains(Fl::selection_owner())) Fl::selection_owner(0); -#ifndef WIN32 - if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0; -#endif - int fix = 0; - if (o->contains(Fl::belowmouse())) {Fl::belowmouse(0); fix = 1;} - if (o->contains(Fl::focus())) {Fl::focus(0); fix = 1;} - if (fix) fl_fix_focus(); -} - -// End of Fl.C // +// Fl.C + +// fltk (Fast Light Tool Kit) version 0.99 +// Copyright (C) 1998 Bill Spitzak + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. + +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. + +// Written by Bill Spitzak spitzak@d2.com + +#include +#include +#include +#include + +int Fl::damage_; +Fl_Widget *Fl::belowmouse_; +Fl_Widget *Fl::pushed_; +Fl_Widget *Fl::focus_; +Fl_Widget *Fl::selection_owner_; +int Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root; +int Fl::e_state; +int Fl::e_clicks; +int Fl::e_is_click; +int Fl::e_keysym; +char *Fl::e_text; +int Fl::e_length; + +int Fl::event_inside(int x,int y,int w,int h) /*const*/ { + int mx = event_x(); + int my = event_y(); + return (mx >= x && mx < x+w && my >= y && my < y+h); +} + +int Fl::event_inside(const Fl_Widget *o) /*const*/ { + return event_inside(o->x(),o->y(),o->w(),o->h()); +} + +// Timeouts are insert-sorted into order. This works good if there +// are only a small number: + +#define MAXTIMEOUT 8 + +static struct { + double time; + void (*cb)(void*); + void* arg; +} timeout[MAXTIMEOUT+1]; +static int numtimeouts; + +void Fl::add_timeout(double t, void (*cb)(void *), void *v) { + int i; + if (numtimeouts t) { + for (int j=numtimeouts-1; j>i; j--) timeout[j] = timeout[j-1]; + break; + } + } + timeout[i].time = t; + timeout[i].cb = cb; + timeout[i].arg = v; +} + +void Fl::remove_timeout(void (*cb)(void *), void *v) { + int i,j; + for (i=j=0; i 0) return; + struct { + void (*cb)(void *); + void *arg; + } temp[MAXTIMEOUT]; + int i,j,k; + // copy all expired timeouts to temp array: + for (i=j=0; jnext) { + if (x->w->damage() && x->w->visible()) { + x->flush(); + x->w->clear_damage(); + } + } + } +#ifndef WIN32 + if (fl_display) XFlush(fl_display); +#endif +} + +extern double fl_wait(int timeout_flag, double timeout); +extern int fl_ready(); + +static int initclock; // if false we didn't call fl_elapsed() last time + +#ifndef WIN32 +#include +#endif + +// fl_elapsed must return the amount of time since the last time it was +// called. To reduce the number of system calls the to get the +// current time, the "initclock" symbol is turned on by an indefinate +// wait. This should then reset the measured-from time and return zero +static double fl_elapsed() { + +#ifdef WIN32 + + unsigned long newclock = fl_msg.time; // NOT YET IMPLEMENTED! + const int TICKS_PER_SECOND = 1000; // divisor of the value to get seconds + static unsigned long prevclock; + if (!initclock) {prevclock = newclock; initclock = 1; return 0.0;} + double t = double(newclock-prevclock)/TICKS_PER_SECOND; + prevclock = newclock; + +#else + + static struct timeval prevclock; + struct timeval newclock; + gettimeofday(&newclock, 0); + if (!initclock) { + prevclock.tv_sec = newclock.tv_sec; + prevclock.tv_usec = newclock.tv_usec; + initclock = 1; + return 0.0; + } + double t = 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; + +#endif + + // expire any timeouts: + if (t > 0.0) for (int i=0; inext) + if (window->xid == xid) { + if (window != Fl_X::first && !Fl::modal()) { + // make this window be first to speed up searches + // this is not done if modal is true to avoid messing up modal stack + *pp = window->next; + window->next = Fl_X::first; + Fl_X::first = window; + } + return window->w; + } + return 0; +} + +void Fl::redraw() { + for (Fl_X* x = Fl_X::first; x; x = x->next) x->w->redraw(); +} + +Fl_Window* Fl::first_window() {Fl_X* x = Fl_X::first; return x ? x->w : 0;} + +Fl_Window* Fl::next_window(const Fl_Window* w) { + Fl_X* x = Fl_X::i(w)->next; return x ? x->w : 0;} + +//////////////////////////////////////////////////////////////// +// Event handlers: + +struct handler_link { + int (*handle)(int); + const handler_link *next; +}; + +static const handler_link *handlers = 0; + +void Fl::add_handler(int (*h)(int)) { + handler_link *l = new handler_link; + l->handle = h; + l->next = handlers; + handlers = l; +} + +static int send_handlers(int event) { + for (const handler_link *h = handlers; h; h = h->next) + if (h->handle(event)) return 1; + return 0; +} + +//////////////////////////////////////////////////////////////// + +Fl_Widget* fl_oldfocus; // kludge for Fl_Group... + +void Fl::focus(Fl_Widget *o) { + Fl_Widget *p = focus_; + if (o != p) { + focus_ = o; + fl_oldfocus = 0; + for (; p && !p->contains(o); p = p->parent()) { + p->handle(FL_UNFOCUS); + fl_oldfocus = p; + } + } +} + +void Fl::belowmouse(Fl_Widget *o) { + Fl_Widget *p = belowmouse_; + if (o != p) { + event_is_click(0); + belowmouse_ = o; + for (; p && !p->contains(o); p = p->parent()) p->handle(FL_LEAVE); + } +} + +// Because mouse events are posted to the outermost window we need to +// adjust them for child windows if they are pushed(). This should also +// be done for the focus() but that is nyi. +static int mouse_dx; +static int mouse_dy; + +void Fl::pushed(Fl_Widget *o) { + pushed_ = o; + mouse_dx = 0; + mouse_dy = 0; + if (o) for (Fl_Widget* w = o; w->parent(); w = w->parent()) { + if (w->type()>=FL_WINDOW) {mouse_dx -= w->x(); mouse_dy -= w->y();} + } +} + +Fl_Window *fl_xfocus; // which window X thinks has focus +Fl_Window *fl_xmousewin; // which window X thinks has FL_ENTER +Fl_Window *Fl::grab_; // most recent Fl::grab() +Fl_Window *Fl::modal_; + +// Update modal(), focus() and other state according to system state. +// This is called whenever a window is added or hidden, and whenever +// X says the focus or mouse window have changed, and when grab_ is +// changed. +void fl_fix_focus() { + + // set Fl::modal() based on grab or any modal windows displayed: + if (Fl::grab_) + Fl::modal_ = Fl::grab_; + else { + Fl_Window* w = Fl::first_window(); + while (w && w->parent()) w = Fl::next_window(w); + Fl::modal_ = w && w->modal() ? w : 0; + } + + // set focus based on Fl::modal() and fl_xfocus + Fl_Window *w = fl_xfocus; + while (w && w->parent()) w = w->window(); + if (w) { + if (Fl::modal()) w = Fl::modal(); + if (!w->contains(Fl::focus())) + if (!w->take_focus()) Fl::focus(w); + } else + Fl::focus(0); + + if (Fl::pushed()) { + + // move pushed() to modal window (necessary for menus): + if (Fl::modal() && !Fl::modal()->contains(Fl::pushed())) + Fl::pushed_ = Fl::modal(); + + } else { // set belowmouse only when pushed() is false + + // set belowmouse based on Fl::modal() and fl_xmousewin: + w = fl_xmousewin; + if (w) { + if (Fl::modal()) w = Fl::modal(); + if (!w->contains(Fl::belowmouse())) { + Fl::belowmouse(w); w->handle(FL_ENTER);} + } else + Fl::belowmouse(0); + } +} + +//////////////////////////////////////////////////////////////// + +int Fl::handle(int event, Fl_Window* window) +{ + Fl_Widget* w = window; + + switch (event) { + + case FL_CLOSE: + if (modal() && window != modal()) return 0; + w->do_callback(); + return 1; + + case FL_SHOW: + ((Fl_Widget*)w)->show(); + return 1; + + case FL_HIDE: + ((Fl_Widget*)w)->hide(); + return 1; + + case FL_PUSH: + if (Fl::grab()) w = Fl::grab(); + else if (Fl::modal() && w != Fl::modal()) return 0; + Fl::pushed_ = w; mouse_dx = mouse_dy = 0; + if (w->handle(event)) return 1; + // raise windows that are clicked on: + window->show(); + return 1; + + case FL_MOVE: + case FL_DRAG: + if (window != fl_xmousewin) { + // this should not happen if enter/leave events were reported + // correctly by the system, but just in case... + fl_xmousewin = window; fl_fix_focus(); + } + if (Fl::pushed()) { + Fl::e_x += mouse_dx; + Fl::e_y += mouse_dy; + event = FL_DRAG; + w = Fl::pushed(); + } else if (Fl::grab()) + w = Fl::grab(); + else if (Fl::modal() && w != Fl::modal()) + w = 0; + break; + + case FL_RELEASE: { + if (Fl::pushed_) w = Fl::pushed_; Fl::pushed_ = 0; + int r = w->handle(event); + fl_fix_focus(); + if (fl_xmousewin) fl_xmousewin->handle(FL_MOVE); + return r;} + + case FL_UNFOCUS: + window = 0; + case FL_FOCUS: + fl_xfocus = window; + Fl::e_keysym = 0; // make sure it is not confused with navigation key + fl_fix_focus(); + return 1; + + case FL_KEYBOARD: + if (window != fl_xfocus) { + // this should not happen if enter/leave events were reported + // correctly by the system, but just in case... + fl_xfocus = window; fl_fix_focus(); + } + // Try it as keystroke, sending it to focus and all parents: + for (w = Fl::focus(); w; w = w->parent()) + if (w->handle(FL_KEYBOARD)) return 1; + + // Try it as shortcut, sending to mouse widget and all parents: + w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;} + for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1; + + // try using add_handle() functions: + if (send_handlers(FL_SHORTCUT)) return 1; + + // Try swapping the case of the text in the shortcut: + if (isalpha(Fl::event_text()[0])) { + *(char*)(Fl::event_text()) ^= ('A'^'a'); + w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;} + for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1; + if (send_handlers(FL_SHORTCUT)) return 1; + } + + // make Escape key close windows: + if (Fl::event_key()==FL_Escape) { + window->do_callback(); + return 1; + } + + return 0; + + case FL_ENTER: + fl_xmousewin = window; fl_fix_focus(); + return 1; + + case FL_LEAVE: + if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();} + return 1; + + default: + break; + } + if (w && w->handle(event)) return 1; + return send_handlers(event); +} + +//////////////////////////////////////////////////////////////// +// hide() destroys the X window, it does not do unmap! + +void fl_throw_focus(Fl_Widget*); // in Fl_x.C + +void Fl_Window::hide() { + if (!shown()) return; + + // remove from the list of windows: + Fl_X* x = i; + Fl_X** pp = &Fl_X::first; + for (; *pp != x; pp = &(*pp)->next) if (!*pp) return; + *pp = x->next; + i = 0; + + // recursively remove any subwindows: + for (Fl_X *w = Fl_X::first; w;) { + Fl_Window* W = w->w; + if (W->window() == this) { + W->hide(); + W->set_visible(); + w = Fl_X::first; + } else w = w->next; + } + + // Make sure no events are sent to this window: + if (this == fl_xmousewin) fl_xmousewin = 0; + if (this == fl_xfocus) fl_xfocus = 0; + fl_throw_focus(this); + handle(FL_HIDE); + +#ifdef WIN32 + if (x->private_dc) ReleaseDC(x->xid,x->private_dc); + if (x->xid == fl_window) fl_GetDC(0); // releases dc belonging to window +#endif + if (x->region) XDestroyRegion(x->region); + XDestroyWindow(fl_display, x->xid); + + delete x; +} + +Fl_Window::~Fl_Window() { + hide(); +} + +// Child windows must respond to FL_SHOW and FL_HIDE by actually +// doing unmap operations. Outer windows assumme FL_SHOW & FL_HIDE +// are messages from X: + +int Fl_Window::handle(int event) { + if (parent()) switch (event) { + case FL_SHOW: + if (!shown()) show(); + else XMapWindow(fl_display, fl_xid(this)); + break; + case FL_HIDE: + if (shown()) XUnmapWindow(fl_display, fl_xid(this)); + break; + } + return Fl_Group::handle(event); +} + +//////////////////////////////////////////////////////////////// +// ~Fl_Widget() calls this: this function must get rid of any +// global pointers to the widget. This is also called by hide() +// and deactivate(). + +// call this to free a selection (or change the owner): +void Fl::selection_owner(Fl_Widget *owner) { + if (selection_owner_ && owner != selection_owner_) + selection_owner_->handle(FL_SELECTIONCLEAR); + selection_owner_ = owner; +} + +#ifndef WIN32 +Fl_Widget *fl_selection_requestor; // from Fl_cutpaste.C +#endif + +void fl_throw_focus(Fl_Widget *o) { + if (o->contains(Fl::pushed())) Fl::pushed(0); + if (o->contains(Fl::selection_owner())) Fl::selection_owner(0); +#ifndef WIN32 + if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0; +#endif + int fix = 0; + if (o->contains(Fl::belowmouse())) {Fl::belowmouse(0); fix = 1;} + if (o->contains(Fl::focus())) {Fl::focus(0); fix = 1;} + if (fix) fl_fix_focus(); +} + +// End of Fl.C // -- cgit v1.2.3