2 // "$Id: Fl.cxx 8723 2011-05-23 16:49:02Z manolo $"
4 // Main event handling code for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 // warning: the Apple Quartz version still uses some Quickdraw calls,
30 // mostly to get around the single active context in QD and
31 // to implement clipping. This should be changed into pure
32 // Quartz calls in the near future.
35 /* We require Windows 2000 features (e.g. VK definitions) */
37 # if !defined(WINVER) || (WINVER < 0x0500)
41 # define WINVER 0x0500
43 # if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
47 # define _WIN32_WINNT 0x0500
52 #include <FL/Fl_Cairo.H>
55 // recent versions of MinGW warn: "Please include winsock2.h before windows.h",
56 // hence we must include winsock2.h before FL/Fl.H (A.S. Dec. 2010, IMM May 2011)
57 #if defined(WIN32) && !defined(__CYGWIN__)
58 # include <winsock2.h>
62 #include <FL/Fl_Window.H>
63 #include <FL/Fl_Tooltip.H>
71 #if defined(DEBUG) || defined(DEBUG_WATCH)
73 #endif // DEBUG || DEBUG_WATCH
77 void fl_free_fonts(void);
78 HBRUSH
fl_brush_action(int action
);
79 void fl_cleanup_pens(void);
80 void fl_release_dc(HWND
,HDC
);
81 void fl_cleanup_dc_list(void);
82 #elif defined(__APPLE__)
83 extern double fl_mac_flush_and_wait(double time_to_wait
, char in_idle
);
89 #if defined(__APPLE__) || defined(FL_DOXYGEN)
90 const char *Fl_Mac_App_Menu::about
= "About ";
91 const char *Fl_Mac_App_Menu::print
= "Print Front Window";
92 const char *Fl_Mac_App_Menu::services
= "Services";
93 const char *Fl_Mac_App_Menu::hide
= "Hide ";
94 const char *Fl_Mac_App_Menu::hide_others
= "Hide Others";
95 const char *Fl_Mac_App_Menu::show
= "Show All";
96 const char *Fl_Mac_App_Menu::quit
= "Quit ";
99 Fl_Widget
*Fl::belowmouse_
,
102 *Fl::selection_owner_
;
115 Fl::e_original_keysym
,
116 Fl::scrollbar_size_
= 16;
118 char *Fl::e_text
= (char *)"";
121 Fl_Event_Dispatch
Fl::e_dispatch
= 0;
123 unsigned char Fl::options_
[] = { 0, 0 };
124 unsigned char Fl::options_read_
= 0;
127 Fl_Window
*fl_xfocus
; // which window X thinks has focus
128 Fl_Window
*fl_xmousewin
;// which window X thinks has FL_ENTER
129 Fl_Window
*Fl::grab_
; // most recent Fl::grab()
130 Fl_Window
*Fl::modal_
; // topmost modal() window
135 // 'Fl::version()' - Return the API version number...
140 Returns the compiled-in value of the FL_VERSION constant. This
141 is useful for checking the version of a shared library.
148 Gets the default scrollbar size used by
152 Fl_Text_Display widgets.
153 \returns The default size for widget scrollbars, in pixels.
155 int Fl::scrollbar_size() {
156 return scrollbar_size_
;
160 Sets the default scrollbar size that is used by the
164 Fl_Text_Display widgets.
165 \param[in] W The new default size for widget scrollbars, in pixels.
167 void Fl::scrollbar_size(int W
) {
172 /** Returns whether or not the mouse event is inside the given rectangle.
174 Returns non-zero if the current Fl::event_x() and Fl::event_y()
175 put it inside the given arbitrary bounding box.
177 You should always call this rather than doing your own comparison
178 so you are consistent about edge effects.
180 To find out, whether the event is inside a child widget of the
181 current window, you can use Fl::event_inside(const Fl_Widget *).
183 \param[in] xx,yy,ww,hh bounding box
184 \return non-zero, if mouse event is inside
186 int Fl::event_inside(int xx
,int yy
,int ww
,int hh
) /*const*/ {
189 return (mx
>= 0 && mx
< ww
&& my
>= 0 && my
< hh
);
192 /** Returns whether or not the mouse event is inside a given child widget.
194 Returns non-zero if the current Fl::event_x() and Fl::event_y()
195 put it inside the given child widget's bounding box.
197 This method can only be used to check whether the mouse event is
198 inside a \b child widget of the window that handles the event, and
199 there must not be an intermediate subwindow (i.e. the widget must
200 not be inside a subwindow of the current window). However, it is
201 valid if the widget is inside a nested Fl_Group.
203 You must not use it with the window itself as the \p o argument
204 in a window's handle() method.
206 \note The mentioned restrictions are necessary, because this method
207 does not transform coordinates of child widgets, and thus the given
208 widget \p o must be within the \e same window that is handling the
209 current event. Otherwise the results are undefined.
211 You should always call this rather than doing your own comparison
212 so you are consistent about edge effects.
214 \see Fl::event_inside(int, int, int, int)
216 \param[in] o child widget to be tested
217 \return non-zero, if mouse event is inside the widget
219 int Fl::event_inside(const Fl_Widget
*o
) /*const*/ {
220 int mx
= e_x
- o
->x();
221 int my
= e_y
- o
->y();
222 return (mx
>= 0 && mx
< o
->w() && my
>= 0 && my
< o
->h());
232 // implementation in Fl_win32.cxx
234 #elif defined(__APPLE__)
236 // implementation in Fl_mac.cxx
245 ////////////////////////////////////////////////////////////////////////
246 // Timeouts are stored in a sorted list (*first_timeout), so only the
247 // first one needs to be checked to see if any should be called.
248 // Allocated, but unused (free) Timeout structs are stored in another
249 // linked list (*free_timeout).
257 static Timeout
* first_timeout
, *free_timeout
;
259 #include <sys/time.h>
261 // I avoid the overhead of getting the current time when we have no
262 // timeouts by setting this flag instead of getting the time.
263 // In this case calling elapse_timeouts() does nothing, but records
264 // the current time, and the next call will actually elapse time.
265 static char reset_clock
= 1;
267 static void elapse_timeouts() {
268 static struct timeval prevclock
;
269 struct timeval newclock
;
270 gettimeofday(&newclock
, NULL
);
271 double elapsed
= newclock
.tv_sec
- prevclock
.tv_sec
+
272 (newclock
.tv_usec
- prevclock
.tv_usec
)/1000000.0;
273 prevclock
.tv_sec
= newclock
.tv_sec
;
274 prevclock
.tv_usec
= newclock
.tv_usec
;
277 } else if (elapsed
> 0) {
278 for (Timeout
* t
= first_timeout
; t
; t
= t
->next
) t
->time
-= elapsed
;
282 // Continuously-adjusted error value, this is a number <= 0 for how late
283 // we were at calling the last timeout. This appears to make repeat_timeout
284 // very accurate even when processing takes a significant portion of the
286 static double missed_timeout_by
;
288 void Fl::add_timeout(double time
, Fl_Timeout_Handler cb
, void *argp
) {
290 repeat_timeout(time
, cb
, argp
);
293 void Fl::repeat_timeout(double time
, Fl_Timeout_Handler cb
, void *argp
) {
294 time
+= missed_timeout_by
; if (time
< -.05) time
= 0;
295 Timeout
* t
= free_timeout
;
297 free_timeout
= t
->next
;
304 // insert-sort the new timeout:
305 Timeout
** p
= &first_timeout
;
306 while (*p
&& (*p
)->time
<= time
) p
= &((*p
)->next
);
312 Returns true if the timeout exists and has not been called yet.
314 int Fl::has_timeout(Fl_Timeout_Handler cb
, void *argp
) {
315 for (Timeout
* t
= first_timeout
; t
; t
= t
->next
)
316 if (t
->cb
== cb
&& t
->arg
== argp
) return 1;
321 Removes a timeout callback. It is harmless to remove a timeout
322 callback that no longer exists.
324 \note This version removes all matching timeouts, not just the first one.
325 This may change in the future.
327 void Fl::remove_timeout(Fl_Timeout_Handler cb
, void *argp
) {
328 for (Timeout
** p
= &first_timeout
; *p
;) {
330 if (t
->cb
== cb
&& (t
->arg
== argp
|| !argp
)) {
332 t
->next
= free_timeout
;
342 ////////////////////////////////////////////////////////////////
343 // Checks are just stored in a list. They are called in the reverse
344 // order that they were added (this may change in the future).
345 // This is a bit messy because I want to allow checks to be added,
346 // removed, and have wait() called from inside them. To do this
347 // next_check points at the next unprocessed one for the outermost
348 // call to Fl::wait().
355 static Check
*first_check
, *next_check
, *free_check
;
358 FLTK will call this callback just before it flushes the display and
359 waits for events. This is different than an idle callback because it
360 is only called once, then FLTK calls the system and tells it not to
361 return until an event happens.
363 This can be used by code that wants to monitor the
364 application's state, such as to keep a display up to date. The
365 advantage of using a check callback is that it is called only when no
366 events are pending. If events are coming in quickly, whole blocks of
367 them will be processed before this is called once. This can save
368 significant time and avoid the application falling behind the events.
373 bool state_changed; // anything that changes the display turns this on
375 void callback(void*) {
376 if (!state_changed) return;
377 state_changed = false;
378 do_expensive_calculation();
383 Fl::add_check(callback);
388 void Fl::add_check(Fl_Timeout_Handler cb
, void *argp
) {
389 Check
* t
= free_check
;
390 if (t
) free_check
= t
->next
;
394 t
->next
= first_check
;
395 if (next_check
== first_check
) next_check
= t
;
400 Removes a check callback. It is harmless to remove a check
401 callback that no longer exists.
403 void Fl::remove_check(Fl_Timeout_Handler cb
, void *argp
) {
404 for (Check
** p
= &first_check
; *p
;) {
406 if (t
->cb
== cb
&& t
->arg
== argp
) {
407 if (next_check
== t
) next_check
= t
->next
;
409 t
->next
= free_check
;
418 Returns 1 if the check exists and has not been called yet, 0 otherwise.
420 int Fl::has_check(Fl_Timeout_Handler cb
, void *argp
) {
421 for (Check
** p
= &first_check
; *p
;) {
423 if (t
->cb
== cb
&& t
->arg
== argp
) {
432 static void run_checks()
434 // checks are a bit messy so that add/remove and wait may be called
435 // from inside them without causing an infinite loop:
436 if (next_check
== first_check
) {
438 Check
* checkp
= next_check
;
439 next_check
= checkp
->next
;
440 (checkp
->cb
)(checkp
->arg
);
442 next_check
= first_check
;
450 ////////////////////////////////////////////////////////////////
451 // wait/run/check/ready:
453 void (*Fl::idle
)(); // see Fl::add_idle.cxx for the add/remove functions
455 extern int fl_ready(); // in Fl_<platform>.cxx
456 extern int fl_wait(double time
); // in Fl_<platform>.cxx
461 double Fl::wait(double time_to_wait
) {
462 // delete all widgets that were listed during callbacks
463 do_widget_deletion();
467 return fl_wait(time_to_wait
);
469 #elif defined(__APPLE__)
478 // the idle function may turn off idle, we can then wait:
479 if (idle
) time_to_wait
= 0.0;
481 return fl_mac_flush_and_wait(time_to_wait
, in_idle
);
488 while ((t
= first_timeout
)) {
489 if (t
->time
> 0) break;
490 // The first timeout in the array has expired.
491 missed_timeout_by
= t
->time
;
492 // We must remove timeout from array before doing the callback:
493 void (*cb
)(void*) = t
->cb
;
495 first_timeout
= t
->next
;
496 t
->next
= free_timeout
;
498 // Now it is safe for the callback to do add_timeout:
502 reset_clock
= 1; // we are not going to check the clock
505 // if (idle && !fl_ready()) {
512 // the idle function may turn off idle, we can then wait:
513 if (idle
) time_to_wait
= 0.0;
515 if (first_timeout
&& first_timeout
->time
< time_to_wait
)
516 time_to_wait
= first_timeout
->time
;
517 if (time_to_wait
<= 0.0) {
518 // do flush second so that the results of events are visible:
519 int ret
= fl_wait(0.0);
523 // do flush first so that user sees the display:
525 if (idle
&& !in_idle
) // 'idle' may have been set within flush()
527 return fl_wait(time_to_wait
);
535 As long as any windows are displayed this calls Fl::wait()
536 repeatedly. When all the windows are closed it returns zero
537 (supposedly it would return non-zero on any errors, but FLTK calls
538 exit directly for these). A normal program will end main()
539 with return Fl::run();.
542 while (Fl_X::first
) wait(FOREVER
);
548 // Function to initialize COM/OLE for usage. This must be done only once.
549 // We define a flag to register whether we called it:
550 static char oleInitialized
= 0;
552 // This calls the Windows function OleInitialize() exactly once.
553 void fl_OleInitialize() {
554 if (!oleInitialized
) {
560 // This calls the Windows function OleUninitialize() only, if
561 // OleInitialize has been called before.
562 void fl_OleUninitialize() {
563 if (oleInitialized
) {
569 class Fl_Win32_At_Exit
{
571 Fl_Win32_At_Exit() { }
572 ~Fl_Win32_At_Exit() {
573 fl_free_fonts(); // do some WIN32 cleanup
575 fl_OleUninitialize();
577 fl_cleanup_dc_list();
580 static Fl_Win32_At_Exit win32_at_exit
;
586 Waits until "something happens" and then returns. Call this
587 repeatedly to "run" your program. You can also check what happened
588 each time after this returns, which is quite useful for managing
591 What this really does is call all idle callbacks, all elapsed
592 timeouts, call Fl::flush() to get the screen to update, and
593 then wait some time (zero if there are idle callbacks, the shortest of
594 all pending timeouts, or infinity), for any events from the user or
595 any Fl::add_fd() callbacks. It then handles the events and
596 calls the callbacks and then returns.
598 The return value of Fl::wait() is non-zero if there are any
599 visible windows - this may change in future versions of FLTK.
601 Fl::wait(time) waits a maximum of \e time seconds.
602 <i>It can return much sooner if something happens.</i>
604 The return value is positive if an event or fd happens before the
605 time elapsed. It is zero if nothing happens (on Win32 this will only
606 return zero if \e time is zero). It is negative if an error
607 occurs (this will happen on UNIX if a signal happens).
610 if (!Fl_X::first
) return 0;
612 return Fl_X::first
!= 0; // return true if there is a window
616 Same as Fl::wait(0). Calling this during a big calculation
617 will keep the screen up to date and the interface responsive:
620 while (!calculation_done()) {
623 if (user_hit_abort_button()) break;
627 This returns non-zero if any windows are displayed, and 0 if no
628 windows are displayed (this is likely to change in future versions of
633 return Fl_X::first
!= 0; // return true if there is a window
637 This is similar to Fl::check() except this does \e not
638 call Fl::flush() or any callbacks, which is useful if your
639 program is in a state where such callbacks are illegal. This returns
640 true if Fl::check() would do anything (it will continue to
641 return true until you call Fl::check() or Fl::wait()).
644 while (!calculation_done()) {
647 do_expensive_cleanup();
649 if (user_hit_abort_button()) break;
655 #if ! defined( WIN32 ) && ! defined(__APPLE__)
658 if (first_timeout
->time
<= 0) return 1;
666 ////////////////////////////////////////////////////////////////
667 // Window list management:
673 Fl_Window
* fl_find(Window xid
) {
675 for (Fl_X
**pp
= &Fl_X::first
; (window
= *pp
); pp
= &window
->next
)
676 #if defined(WIN32) || defined(USE_X11)
677 if (window
->xid
== xid
)
678 #elif defined(__APPLE_QUARTZ__)
679 if (window
->xid
== xid
&& !window
->w
->window())
681 # error unsupported platform
684 if (window
!= Fl_X::first
&& !Fl::modal()) {
685 // make this window be first to speed up searches
686 // this is not done if modal is true to avoid messing up modal stack
688 window
->next
= Fl_X::first
;
689 Fl_X::first
= window
;
697 Returns the first top-level window in the list of shown() windows. If
698 a modal() window is shown this is the top-most modal window, otherwise
699 it is the most recent window to get an event.
701 Fl_Window
* Fl::first_window() {
702 Fl_X
* i
= Fl_X::first
;
707 Returns the next top-level window in the list of shown() windows.
708 You can use this call to iterate through all the windows that are shown().
709 \param[in] window must be shown and not NULL
711 Fl_Window
* Fl::next_window(const Fl_Window
* window
) {
712 Fl_X
* i
= Fl_X::i(window
)->next
;
717 Sets the window that is returned by first_window().
718 The window is removed from wherever it is in the
719 list and inserted at the top. This is not done if Fl::modal()
720 is on or if the window is not shown(). Because the first window
721 is used to set the "parent" of modal windows, this is often
724 void Fl::first_window(Fl_Window
* window
) {
725 if (!window
|| !window
->shown()) return;
726 fl_find( Fl_X::i(window
)->xid
);
733 for (Fl_X
* i
= Fl_X::first
; i
; i
= i
->next
) i
->w
->redraw();
737 Causes all the windows that need it to be redrawn and graphics forced
738 out through the pipes.
740 This is what wait() does before looking for events.
742 Note: in multi-threaded applications you should only call Fl::flush()
743 from the main thread. If a child thread needs to trigger a redraw event,
744 it should instead call Fl::awake() to get the main thread to process the
750 for (Fl_X
* i
= Fl_X::first
; i
; i
= i
->next
) {
751 if (i
->wait_for_expose
) {damage_
= 1; continue;}
752 Fl_Window
* wi
= i
->w
;
753 if (!wi
->visible_r()) continue;
754 if (wi
->damage()) {wi
->make_current(); i
->flush(); wi
->clear_damage();}
755 // destroy damage regions for windows that don't use them:
758 cairo_region_destroy( i
->region
);
764 if (fl_display
) XFlush(fl_display
);
767 #elif defined (__APPLE_QUARTZ__)
769 CGContextFlush(fl_gc
);
771 # error unsupported platform
776 ////////////////////////////////////////////////////////////////
780 struct handler_link
{
786 static handler_link
*handlers
= 0;
790 Install a function to parse unrecognized events. If FLTK cannot
791 figure out what to do with an event, it calls each of these functions
792 (most recent first) until one of them returns non-zero. If none of
793 them returns non-zero then the event is ignored. Events that cause
794 this to be called are:
796 - FL_SHORTCUT events that are not recognized by any widget.
797 This lets you provide global shortcut keys.
798 - System events that FLTK does not recognize. See fl_xevent.
799 - \e Some other events when the widget FLTK selected returns
800 zero from its handle() method. Exactly which ones may change
801 in future versions, however.
803 \see Fl::remove_handler(Fl_Event_Handler)
804 \see Fl::event_dispatch(Fl_Event_Dispatch d)
805 \see Fl::handle(int, Fl_Window*)
807 void Fl::add_handler(Fl_Event_Handler ha
) {
808 handler_link
*l
= new handler_link
;
816 Removes a previously added event handler.
817 \see Fl::handle(int, Fl_Window*)
819 void Fl::remove_handler(Fl_Event_Handler ha
) {
822 // Search for the handler in the list...
823 for (l
= handlers
, p
= 0; l
&& l
->handle
!= ha
; p
= l
, l
= l
->next
);
826 // Found it, so remove it from the list...
827 if (p
) p
->next
= l
->next
;
828 else handlers
= l
->next
;
830 // And free the record...
835 int (*fl_local_grab
)(int); // used by fl_dnd.cxx
837 static int send_handlers(int e
) {
838 for (const handler_link
*hl
= handlers
; hl
; hl
= hl
->next
)
839 if (hl
->handle(e
)) return 1;
843 ////////////////////////////////////////////////////////////////
845 Fl_Widget
* fl_oldfocus
; // kludge for Fl_Group...
848 Sets the widget that will receive FL_KEYBOARD events.
850 If you change Fl::focus(), the previous widget and all
851 parents (that don't contain the new widget) are sent FL_UNFOCUS
852 events. Changing the focus does \e not send FL_FOCUS to
853 this or any widget, because sending FL_FOCUS is supposed to
854 \e test if the widget wants the focus (by it returning non-zero from
857 \see Fl_Widget::take_focus()
859 void Fl::focus(Fl_Widget
*o
) {
860 if (o
&& !o
->visible_focus()) return;
861 if (grab()) return; // don't do anything while grab is on
862 Fl_Widget
*p
= focus_
;
866 // make sure that fl_xfocus is set to the top level window
867 // of this widget, or fl_fix_focus will clear our focus again
869 Fl_Window
*win
= 0, *w1
= o
->as_window();
870 if (!w1
) w1
= o
->window();
871 while (w1
) { win
=w1
; w1
=win
->window(); }
874 if (fl_xfocus
!= win
) {
875 Fl_X
*x
= Fl_X::i(win
);
876 if (x
) x
->set_key_window();
882 // take focus from the old focused window
884 int old_event
= e_number
;
885 e_number
= FL_UNFOCUS
;
886 for (; p
; p
= p
->parent()) {
887 p
->handle(FL_UNFOCUS
);
890 e_number
= old_event
;
894 static char dnd_flag
= 0; // make 'belowmouse' send DND_LEAVE instead of LEAVE
897 Sets the widget that is below the mouse. This is for
898 highlighting buttons. It is not used to send FL_PUSH or
899 FL_MOVE directly, for several obscure reasons, but those events
900 typically go to this widget. This is also the first widget tried for
903 If you change the belowmouse widget, the previous one and all
904 parents (that don't contain the new widget) are sent FL_LEAVE
905 events. Changing this does \e not send FL_ENTER to this
906 or any widget, because sending FL_ENTER is supposed to \e test
907 if the widget wants the mouse (by it returning non-zero from
910 void Fl::belowmouse(Fl_Widget
*o
) {
911 if (grab()) return; // don't do anything while grab is on
912 Fl_Widget
*p
= belowmouse_
;
915 int old_event
= e_number
;
916 e_number
= dnd_flag
? FL_DND_LEAVE
: FL_LEAVE
;
917 for (; p
&& !p
->contains(o
); p
= p
->parent()) {
920 e_number
= old_event
;
925 Sets the widget that is being pushed. FL_DRAG or
926 FL_RELEASE (and any more FL_PUSH) events will be sent to
929 If you change the pushed widget, the previous one and all parents
930 (that don't contain the new widget) are sent FL_RELEASE
931 events. Changing this does \e not send FL_PUSH to this
932 or any widget, because sending FL_PUSH is supposed to \e test
933 if the widget wants the mouse (by it returning non-zero from
936 void Fl::pushed(Fl_Widget
*o
) {
940 static void nothing(Fl_Widget
*) {}
941 void (*Fl_Tooltip::enter
)(Fl_Widget
*) = nothing
;
942 void (*Fl_Tooltip::exit
)(Fl_Widget
*) = nothing
;
944 // Update modal(), focus() and other state according to system state,
945 // and send FL_ENTER, FL_LEAVE, FL_FOCUS, and/or FL_UNFOCUS events.
946 // This is the only function that produces these events in response
947 // to system activity.
948 // This is called whenever a window is added or hidden, and whenever
949 // X says the focus or mouse window have changed.
951 void fl_fix_focus() {
953 puts("fl_fix_focus();");
956 if (Fl::grab()) return; // don't do anything while grab is on.
958 // set focus based on Fl::modal() and fl_xfocus
959 Fl_Widget
* w
= fl_xfocus
;
961 int saved
= Fl::e_keysym
;
962 if (Fl::e_keysym
< (FL_Button
+ FL_LEFT_MOUSE
) ||
963 Fl::e_keysym
> (FL_Button
+ FL_RIGHT_MOUSE
))
964 Fl::e_keysym
= 0; // make sure widgets don't think a keystroke moved focus
965 while (w
->parent()) w
= w
->parent();
966 if (Fl::modal()) w
= Fl::modal();
967 if (!w
->contains(Fl::focus()))
968 if (!w
->take_focus()) Fl::focus(w
);
969 Fl::e_keysym
= saved
;
973 // MRS: Originally we checked the button state, but a user reported that it
974 // broke click-to-focus in FLWM?!?
975 // if (!(Fl::event_state() & 0x7f00000 /*FL_BUTTONS*/)) {
977 // set belowmouse based on Fl::modal() and fl_xmousewin:
980 if (Fl::modal()) w
= Fl::modal();
981 if (!w
->contains(Fl::belowmouse())) {
982 int old_event
= Fl::e_number
;
983 w
->handle(Fl::e_number
= FL_ENTER
);
984 Fl::e_number
= old_event
;
985 if (!w
->contains(Fl::belowmouse())) Fl::belowmouse(w
);
987 // send a FL_MOVE event so the enter/leave state is up to date
988 Fl::e_x
= Fl::e_x_root
-fl_xmousewin
->x();
989 Fl::e_y
= Fl::e_y_root
-fl_xmousewin
->y();
990 int old_event
= Fl::e_number
;
991 w
->handle(Fl::e_number
= FL_MOVE
);
992 Fl::e_number
= old_event
;
996 Fl_Tooltip::enter(0);
1001 #if !(defined(WIN32) || defined(__APPLE__))
1002 extern Fl_Widget
*fl_selection_requestor
; // from Fl_x.cxx
1005 // This function is called by ~Fl_Widget() and by Fl_Widget::deactivate()
1006 // and by Fl_Widget::hide(). It indicates that the widget does not want
1007 // to receive any more events, and also removes all global variables that
1008 // point at the widget.
1009 // I changed this from the 1.0.1 behavior, the older version could send
1010 // FL_LEAVE or FL_UNFOCUS events to the widget. This appears to not be
1011 // desirable behavior and caused flwm to crash.
1013 void fl_throw_focus(Fl_Widget
*o
) {
1015 printf("fl_throw_focus(o=%p)\n", o
);
1018 if (o
->contains(Fl::pushed())) Fl::pushed_
= 0;
1019 #if !(defined(WIN32) || defined(__APPLE__))
1020 if (o
->contains(fl_selection_requestor
)) fl_selection_requestor
= 0;
1022 if (o
->contains(Fl::belowmouse())) Fl::belowmouse_
= 0;
1023 if (o
->contains(Fl::focus())) Fl::focus_
= 0;
1024 if (o
== fl_xfocus
) fl_xfocus
= 0;
1025 if (o
== Fl_Tooltip::current()) Fl_Tooltip::current(0);
1026 if (o
== fl_xmousewin
) fl_xmousewin
= 0;
1027 Fl_Tooltip::exit(o
);
1031 ////////////////////////////////////////////////////////////////
1033 // Call to->handle(), but first replace the mouse x/y with the correct
1034 // values to account for nested windows. 'window' is the outermost
1035 // window the event was posted to by the system:
1036 static int send(int event
, Fl_Widget
* to
, Fl_Window
* window
) {
1038 int old_event
= Fl::e_number
;
1045 for (const Fl_Widget
* w
= to
; w
; w
= w
->parent())
1046 if (w
->type()>=FL_WINDOW
) {dx
-= w
->x(); dy
-= w
->y();}
1047 int save_x
= Fl::e_x
; Fl::e_x
+= dx
;
1048 int save_y
= Fl::e_y
; Fl::e_y
+= dy
;
1049 int ret
= to
->handle(Fl::e_number
= event
);
1050 Fl::e_number
= old_event
;
1058 \brief Set a new event dispatch function.
1060 The event dispatch function is called after native events are converted to
1061 FLTK events, but before they are handled by FLTK. If the dispatch function
1062 Fl_Event_Dispatch \p d is set, it is up to the dispatch function to call
1063 Fl::handle_(int, Fl_Window*) or to ignore the event.
1065 The dispatch function itself must return 0 if it ignored the event,
1066 or non-zero if it used the event. If you call Fl::handle_(), then
1067 this will return the correct value.
1069 The event dispatch can be used to handle exceptions in FLTK events and
1070 callbacks before they reach the native event handler:
1073 int myHandler(int e, Fl_Window *w) {
1075 return Fl::handle_(e, w);
1082 Fl::event_dispatch(myHandler);
1088 \param d new dispatch function, or NULL
1089 \see Fl::add_handler(Fl_Event_Handler)
1090 \see Fl::handle(int, Fl_Window*)
1091 \see Fl::handle_(int, Fl_Window*)
1093 void Fl::event_dispatch(Fl_Event_Dispatch d
)
1100 \brief Return the current event dispatch function.
1102 Fl_Event_Dispatch
Fl::event_dispatch()
1109 \brief Handle events from the window system.
1111 This is called from the native event dispatch after native events have been
1112 converted to FLTK notation. This function calls Fl::handle_(int, Fl_Window*)
1113 unless the user sets a dispatch function. If a user dispatch function is set,
1114 the user must make sure that Fl::handle_() is called, or the event will be
1117 \param e the event type (Fl::event_number() is not yet set)
1118 \param window the window that caused this event
1119 \return 0 if the event was not handled
1121 \see Fl::add_handler(Fl_Event_Handler)
1122 \see Fl::event_dispatch(Fl_Event_Dispatch)
1124 int Fl::handle(int e
, Fl_Window
* window
)
1127 return e_dispatch(e
, window
);
1129 return handle_(e
, window
);
1135 \brief Handle events from the window system.
1137 This function is called from the native event dispatch, unless the user sets
1138 another dispatch function. In that case, the user dispatch function must
1139 decide when to call Fl::handle_(int, Fl_Window*)
1141 \param e the event type (Fl::event_number() is not yet set)
1142 \param window the window that caused this event
1143 \return 0 if the event was not handled
1145 \see Fl::event_dispatch(Fl_Event_Dispatch)
1147 int Fl::handle_(int e
, Fl_Window
* window
)
1150 if (fl_local_grab
) return fl_local_grab(e
);
1152 Fl_Widget
* wi
= window
;
1157 if ( grab() || (modal() && window
!= modal()) ) return 0;
1162 wi
->Fl_Widget::show(); // this calls Fl_Widget::show(), not Fl_Window::show()
1166 wi
->Fl_Widget::hide(); // this calls Fl_Widget::hide(), not Fl_Window::hide()
1171 printf("Fl::handle(e=%d, window=%p);\n", e
, window
);
1174 if (grab()) wi
= grab();
1175 else if (modal() && wi
!= modal()) return 0;
1177 Fl_Tooltip::current(wi
);
1178 if (send(e
, wi
, window
)) return 1;
1179 // raise windows that are clicked on:
1194 case FL_DND_RELEASE
:
1200 fl_xmousewin
= window
; // this should already be set, but just in case.
1203 if (grab()) wi
= grab();
1204 e_number
= e
= FL_DRAG
;
1207 if (modal() && wi
!= modal()) wi
= 0;
1208 if (grab()) wi
= grab();
1210 Fl_Widget
* pbm
= belowmouse();
1212 if (fl_mac_os_version
< 100500) {
1213 // before 10.5, mouse moved events aren't sent to borderless windows such as tooltips
1214 Fl_Window
*tooltip
= Fl_Tooltip::current_window();
1216 if (tooltip
&& tooltip
->shown() ) { // check if a tooltip window is currently opened
1217 // check if mouse is inside the tooltip
1218 inside
= (Fl::event_x_root() >= tooltip
->x() && Fl::event_x_root() < tooltip
->x() + tooltip
->w() &&
1219 Fl::event_y_root() >= tooltip
->y() && Fl::event_y_root() < tooltip
->y() + tooltip
->h() );
1221 // if inside, send event to tooltip window instead of background window
1222 if (inside
) ret
= send(e
, tooltip
, window
);
1223 else ret
= (wi
&& send(e
, wi
, window
));
1226 ret
= (wi
&& send(e
, wi
, window
));
1227 if (pbm
!= belowmouse()) {
1229 printf("Fl::handle(e=%d, window=%p);\n", e
, window
);
1231 Fl_Tooltip::enter(belowmouse());
1236 // printf("FL_RELEASE: window=%p, pushed() = %p, grab() = %p, modal() = %p\n",
1237 // window, pushed(), grab(), modal());
1241 pushed_
= 0; // must be zero before callback is done!
1242 } else if (pushed()) {
1244 pushed_
= 0; // must be zero before callback is done!
1245 } else if (modal() && wi
!= modal()) return 0;
1246 int r
= send(e
, wi
, window
);
1258 // Send the key-up to the current focus widget. This is not
1259 // always the same widget that received the corresponding
1260 // FL_KEYBOARD event because focus may have changed.
1261 // Sending the KEYUP to the right KEYDOWN is possible, but
1262 // would require that we track the KEYDOWN for every possible
1263 // key stroke (users may hold down multiple keys!) and then
1264 // make sure that the widget still exists before sending
1265 // a KEYUP there. I believe that the current solution is
1267 for (wi
= grab() ? grab() : focus(); wi
; wi
= wi
->parent())
1268 if (send(FL_KEYUP
, wi
, window
)) return 1;
1273 printf("Fl::handle(e=%d, window=%p);\n", e
, window
);
1276 Fl_Tooltip::enter((Fl_Widget
*)0);
1278 fl_xfocus
= window
; // this should not happen! But maybe it does:
1280 // Try it as keystroke, sending it to focus and all parents:
1281 for (wi
= grab() ? grab() : focus(); wi
; wi
= wi
->parent())
1282 if (send(FL_KEYBOARD
, wi
, window
)) return 1;
1284 // recursive call to try shortcut:
1285 if (handle(FL_SHORTCUT
, window
)) return 1;
1287 // and then try a shortcut with the case of the text swapped, by
1288 // changing the text and falling through to FL_SHORTCUT case:
1289 {unsigned char* c
= (unsigned char*)event_text(); // cast away const
1290 if (!isalpha(*c
)) return 0;
1291 *c
= isupper(*c
) ? tolower(*c
) : toupper(*c
);}
1292 e_number
= e
= FL_SHORTCUT
;
1295 if (grab()) {wi
= grab(); break;} // send it to grab window
1297 // Try it as shortcut, sending to mouse widget and all parents:
1301 if (!wi
) wi
= window
;
1302 } else if (wi
->window() != first_window()) {
1303 if (send(FL_SHORTCUT
, first_window(), first_window())) return 1;
1306 for (; wi
; wi
= wi
->parent()) {
1307 if (send(FL_SHORTCUT
, wi
, wi
->window())) return 1;
1310 // try using add_handle() functions:
1311 if (send_handlers(FL_SHORTCUT
)) return 1;
1313 // make Escape key close windows:
1314 if (event_key()==FL_Escape
) {
1315 wi
= modal(); if (!wi
) wi
= window
;
1324 printf("Fl::handle(e=%d, window=%p);\n", e
, window
);
1327 fl_xmousewin
= window
;
1329 Fl_Tooltip::enter(belowmouse());
1334 printf("Fl::handle(e=%d, window=%p);\n", e
, window
);
1339 Fl_Tooltip::enter(0);
1341 if (window
== fl_xmousewin
) {fl_xmousewin
= 0; fl_fix_focus();}
1345 fl_xfocus
= window
; // this should not happen! But maybe it does:
1347 // Try sending it to the "grab" first
1348 if (grab() && grab()!=modal() && grab()!=window
) {
1349 if (send(FL_MOUSEWHEEL
, grab(), window
)) return 1;
1351 // Now try sending it to the "modal" window
1353 send(FL_MOUSEWHEEL
, modal(), window
);
1356 // Finally try sending it to the window, the event occured in
1357 if (send(FL_MOUSEWHEEL
, window
, window
)) return 1;
1361 if (wi
&& send(e
, wi
, window
)) {
1366 return send_handlers(e
);
1369 ////////////////////////////////////////////////////////////////
1370 // hide() destroys the X window, it does not do unmap!
1372 #if !defined(WIN32) && USE_XFT
1373 extern void fl_destroy_xft_draw(Window
);
1376 void Fl_Window::hide() {
1379 if (!shown()) return;
1381 // remove from the list of windows:
1383 Fl_X
** pp
= &Fl_X::first
;
1384 for (; *pp
!= ip
; pp
= &(*pp
)->next
) if (!*pp
) return;
1388 // MacOS X manages a single pointer per application. Make sure that hiding
1389 // a toplevel window will not leave us with some random pointer shape, or
1390 // worst case, an invisible pointer
1391 if (!parent()) cursor(FL_CURSOR_DEFAULT
);
1395 // recursively remove any subwindows:
1396 for (Fl_X
*wi
= Fl_X::first
; wi
;) {
1397 Fl_Window
* W
= wi
->w
;
1398 if (W
->window() == this) {
1402 } else wi
= wi
->next
;
1405 if (this == Fl::modal_
) { // we are closing the modal window, find next one:
1407 for (W
= Fl::first_window(); W
; W
= Fl::next_window(W
))
1408 if (W
->modal()) break;
1412 // Make sure no events are sent to this window:
1413 fl_throw_focus(this);
1417 // this little trick keeps the current clipboard alive, even if we are about
1418 // to destroy the window that owns the selection.
1419 if (GetClipboardOwner()==ip
->xid
) {
1420 Fl_Window
*w1
= Fl::first_window();
1421 if (w1
&& OpenClipboard(fl_xid(w1
))) {
1423 SetClipboardData(CF_TEXT
, NULL
);
1427 // Send a message to myself so that I'll get out of the event loop...
1428 PostMessage(ip
->xid
, WM_APP
, 0, 0);
1429 if (ip
->private_dc
) fl_release_dc(ip
->xid
, ip
->private_dc
);
1430 if (ip
->xid
== fl_window
&& fl_gc
) {
1431 fl_release_dc(fl_window
, fl_gc
);
1432 fl_window
= (HWND
)-1;
1435 #elif defined(__APPLE_QUARTZ__)
1436 Fl_X::q_release_context(ip
);
1437 if ( ip
->xid
== fl_window
&& !parent() )
1442 cairo_region_destroy( ip
->region
);
1446 #if defined(USE_X11)
1448 cairo_destroy( ip
->cc
); ip
->cc
= 0;
1449 cairo_surface_destroy( ip
->cs
); ip
->cs
= 0;
1452 fl_destroy_xft_draw(ip
->xid
);
1454 // this test makes sure ip->xid has not been destroyed already
1455 if (ip
->xid
) XDestroyWindow(fl_display
, ip
->xid
);
1456 #elif defined(WIN32)
1457 // this little trickery seems to avoid the popup window stacking problem
1458 HWND p
= GetForegroundWindow();
1459 if (p
==GetParent(ip
->xid
)) {
1460 ShowWindow(ip
->xid
, SW_HIDE
);
1461 ShowWindow(p
, SW_SHOWNA
);
1463 XDestroyWindow(fl_display
, ip
->xid
);
1464 #elif defined(__APPLE_QUARTZ__)
1467 # error unsupported platform
1471 // Try to stop the annoying "raise another program" behavior
1472 if (non_modal() && Fl::first_window() && Fl::first_window()->shown())
1473 Fl::first_window()->show();
1478 Fl_Window::~Fl_Window() {
1485 // FL_SHOW and FL_HIDE are called whenever the visibility of this widget
1486 // or any parent changes. We must correctly map/unmap the system's window.
1488 // For top-level windows it is assumed the window has already been
1489 // mapped or unmapped!!! This is because this should only happen when
1490 // Fl_Window::show() or Fl_Window::hide() is called, or in response to
1491 // iconize/deiconize events from the system.
1493 int Fl_Window::handle(int ev
)
1498 if (!shown()) show();
1500 #if defined(USE_X11) || defined(WIN32)
1501 XMapWindow(fl_display
, fl_xid(this)); // extra map calls are harmless
1502 #elif defined(__APPLE_QUARTZ__)
1505 # error unsupported platform
1511 // Find what really turned invisible, if it was a parent window
1512 // we do nothing. We need to avoid unnecessary unmap calls
1513 // because they cause the display to blink when the parent is
1514 // remapped. However if this or any intermediate non-window
1515 // widget has really had hide() called directly on it, we must
1516 // unmap because when the parent window is remapped we don't
1517 // want to reappear.
1519 Fl_Widget
* p
= parent(); for (;p
->visible();p
= p
->parent()) {}
1520 if (p
->type() >= FL_WINDOW
) break; // don't do the unmap
1522 #if defined(USE_X11) || defined(WIN32)
1523 XUnmapWindow(fl_display
, fl_xid(this));
1524 #elif defined(__APPLE_QUARTZ__)
1527 # error platform unsupported
1532 // } else if (ev == FL_FOCUS || ev == FL_UNFOCUS) {
1533 // Fl_Tooltip::exit(Fl_Tooltip::current());
1536 return Fl_Group::handle(ev
);
1539 ////////////////////////////////////////////////////////////////
1540 // Back compatibility cut & paste functions for fltk 1.1 only:
1542 /** Back-compatibility only: The single-argument call can be used to
1543 move the selection to another widget or to set the owner to
1544 NULL, without changing the actual text of the
1545 selection. FL_SELECTIONCLEAR is sent to the previous
1546 selection owner, if any.
1548 <i>Copying the buffer every time the selection is changed is
1549 obviously wasteful, especially for large selections. An interface will
1550 probably be added in a future version to allow the selection to be made
1551 by a callback function. The current interface will be emulated on top
1554 void Fl::selection_owner(Fl_Widget
*owner
) {selection_owner_
= owner
;}
1557 Changes the current selection. The block of text is
1558 copied to an internal buffer by FLTK (be careful if doing this in
1559 response to an FL_PASTE as this \e may be the same buffer
1560 returned by event_text()). The selection_owner()
1561 widget is set to the passed owner.
1563 void Fl::selection(Fl_Widget
&owner
, const char* text
, int len
) {
1564 selection_owner_
= &owner
;
1565 Fl::copy(text
, len
, 0);
1568 /** Backward compatibility only.
1569 This calls Fl::paste(receiver, 0);
1570 \see Fl::paste(Fl_Widget &receiver, int clipboard)
1572 void Fl::paste(Fl_Widget
&receiver
) {
1573 Fl::paste(receiver
, 0);
1576 ////////////////////////////////////////////////////////////////
1578 #include <FL/fl_draw.H>
1580 void Fl_Widget::redraw() {
1581 damage(FL_DAMAGE_ALL
);
1584 void Fl_Widget::redraw_label() {
1586 if (box() == FL_NO_BOX
) {
1587 // Widgets with the FL_NO_BOX boxtype need a parent to
1588 // redraw, since it is responsible for redrawing the
1590 int X
= x() > 0 ? x() - 1 : 0;
1591 int Y
= y() > 0 ? y() - 1 : 0;
1592 window()->damage(FL_DAMAGE_ALL
, X
, Y
, w() + 2, h() + 2);
1595 if (align() && !(align() & FL_ALIGN_INSIDE
) && window()->shown()) {
1596 // If the label is not inside the widget, compute the location of
1597 // the label and redraw the window within that bounding box...
1599 label_
.measure(W
, H
);
1600 W
+= 5; // Add a little to the size of the label to cover overflow
1604 // This assumes that measure() returns the correct outline, which it does
1605 // not in all possible cases of alignment combinedwith image and symbols.
1606 switch (align() & 0x0f) {
1607 case FL_ALIGN_TOP_LEFT
:
1608 window()->damage(FL_DAMAGE_EXPOSE
, x(), y()-H
, W
, H
); break;
1610 window()->damage(FL_DAMAGE_EXPOSE
, x()+(w()-W
)/2, y()-H
, W
, H
); break;
1611 case FL_ALIGN_TOP_RIGHT
:
1612 window()->damage(FL_DAMAGE_EXPOSE
, x()+w()-W
, y()-H
, W
, H
); break;
1613 case FL_ALIGN_LEFT_TOP
:
1614 window()->damage(FL_DAMAGE_EXPOSE
, x()-W
, y(), W
, H
); break;
1615 case FL_ALIGN_RIGHT_TOP
:
1616 window()->damage(FL_DAMAGE_EXPOSE
, x()+w(), y(), W
, H
); break;
1618 window()->damage(FL_DAMAGE_EXPOSE
, x()-W
, y()+(h()-H
)/2, W
, H
); break;
1619 case FL_ALIGN_RIGHT
:
1620 window()->damage(FL_DAMAGE_EXPOSE
, x()+w(), y()+(h()-H
)/2, W
, H
); break;
1621 case FL_ALIGN_LEFT_BOTTOM
:
1622 window()->damage(FL_DAMAGE_EXPOSE
, x()-W
, y()+h()-H
, W
, H
); break;
1623 case FL_ALIGN_RIGHT_BOTTOM
:
1624 window()->damage(FL_DAMAGE_EXPOSE
, x()+w(), y()+h()-H
, W
, H
); break;
1625 case FL_ALIGN_BOTTOM_LEFT
:
1626 window()->damage(FL_DAMAGE_EXPOSE
, x(), y()+h(), W
, H
); break;
1627 case FL_ALIGN_BOTTOM
:
1628 window()->damage(FL_DAMAGE_EXPOSE
, x()+(w()-W
)/2, y()+h(), W
, H
); break;
1629 case FL_ALIGN_BOTTOM_RIGHT
:
1630 window()->damage(FL_DAMAGE_EXPOSE
, x()+w()-W
, y()+h(), W
, H
); break;
1632 window()->damage(FL_DAMAGE_ALL
); break;
1635 // The label is inside the widget, so just redraw the widget itself...
1636 damage(FL_DAMAGE_ALL
);
1641 void Fl_Widget::damage(fl_damage_t fl
) {
1642 if (type() < FL_WINDOW
) {
1643 // damage only the rectangle covered by a child widget:
1644 damage(fl
, x(), y(), w(), h());
1646 // damage entire window by deleting the region:
1647 Fl_X
* i
= Fl_X::i((Fl_Window
*)this);
1648 if (!i
) return; // window not mapped, so ignore it
1651 cairo_region_destroy( i
->region
);
1655 Fl::damage(FL_DAMAGE_CHILD
);
1659 void Fl_Widget::damage(fl_damage_t fl
, int X
, int Y
, int W
, int H
) {
1660 Fl_Widget
* wi
= this;
1661 // mark all parent widgets between this and window with FL_DAMAGE_CHILD:
1662 /* mark as exposed all parent widgets between this one and the window, stopping at the first widget to have FL_FLAT_BOX (and therefore be completely opaque!
1663 FIXME: check the color for an alpha less than 1! */
1665 bool hit_opaque_widget
= false;
1667 while (wi
->type() < FL_WINDOW
)
1671 switch ( wi
->box() )
1675 hit_opaque_widget
= true;
1681 if ( ! ( wi
= wi
->parent() ) )
1684 /* we use FL_DAMAGE_EXPOSE now because of alpha blending and FL_NO_BOX and frames... */
1685 // fl = FL_DAMAGE_EXPOSE;
1687 fl
= hit_opaque_widget
? FL_DAMAGE_CHILD
: FL_DAMAGE_ALL
;
1690 fl
= FL_DAMAGE_CHILD
;
1692 if ( ! hit_opaque_widget
)
1693 fl
|= FL_DAMAGE_BACKGROUND
;
1695 /* at this point 'wi' is the window */
1697 Fl_X
* i
= Fl_X::i((Fl_Window
*)wi
);
1698 if (!i
) return; // window not mapped, so ignore it
1700 // clip the damage to the window and quit if none:
1701 if (X
< 0) {W
+= X
; X
= 0;}
1702 if (Y
< 0) {H
+= Y
; Y
= 0;}
1703 if (W
> wi
->w()-X
) W
= wi
->w()-X
;
1704 if (H
> wi
->h()-Y
) H
= wi
->h()-Y
;
1705 if (W
<= 0 || H
<= 0) return;
1707 if (!X
&& !Y
&& W
==wi
->w() && H
==wi
->h()) {
1708 // if damage covers entire window delete region:
1714 // if we already have damage we must merge with existing region:
1716 #if defined(USE_X11)
1718 cairo_rectangle_int_t rect
;
1725 cairo_region_union_rectangle( i
->region
, &rect
);
1726 #elif defined(WIN32)
1727 Fl_Region R
= XRectangleRegion(X
, Y
, W
, H
);
1728 CombineRgn(i
->region
, i
->region
, R
, RGN_OR
);
1730 #elif defined(__APPLE_QUARTZ__)
1731 CGRect arg
= fl_cgrectmake_cocoa(X
, Y
, W
, H
);
1732 int j
; // don't add a rectangle totally inside the Fl_Region
1733 for(j
= 0; j
< i
->region
->count
; j
++) {
1734 if(CGRectContainsRect(i
->region
->rects
[j
], arg
)) break;
1736 if( j
>= i
->region
->count
) {
1737 i
->region
->rects
= (CGRect
*)realloc(i
->region
->rects
, (++(i
->region
->count
)) * sizeof(CGRect
));
1738 i
->region
->rects
[i
->region
->count
- 1] = arg
;
1741 # error unsupported platform
1749 cairo_region_destroy( i
->region
);
1751 i
->region
= cairo_region_create();
1752 cairo_rectangle_int_t rect
;
1759 cairo_region_union_rectangle( i
->region
, &rect
);
1763 Fl::damage(FL_DAMAGE_CHILD
);
1765 void Fl_Window::flush() {
1769 cairo_surface_flush( i
->cs
);
1774 # include "Fl_win32.cxx"
1775 //#elif defined(__APPLE__)
1779 // The following methods allow callbacks to schedule the deletion of
1780 // widgets at "safe" times.
1783 static int num_dwidgets
= 0, alloc_dwidgets
= 0;
1784 static Fl_Widget
**dwidgets
= 0;
1787 Schedules a widget for deletion at the next call to the event loop.
1788 Use this method to delete a widget inside a callback function.
1790 To avoid early deletion of widgets, this function should be called
1791 toward the end of a callback and only after any call to the event
1792 loop (Fl::wait(), Fl::flush(), Fl::check(), fl_ask(), etc.).
1794 When deleting groups or windows, you must only delete the group or
1795 window widget and not the individual child widgets.
1797 \since FLTK 1.3 it is not necessary to remove widgets from their parent
1798 groups or windows before calling this, because it will be done in the
1799 widget's destructor, but it is not a failure to do this nevertheless.
1801 \note In FLTK 1.1 you \b must remove widgets from their parent group
1802 (or window) before deleting them.
1804 \see Fl_Widget::~Fl_Widget()
1806 void Fl::delete_widget(Fl_Widget
*wi
) {
1809 if (num_dwidgets
>= alloc_dwidgets
) {
1812 temp
= new Fl_Widget
*[alloc_dwidgets
+ 10];
1813 if (alloc_dwidgets
) {
1814 memcpy(temp
, dwidgets
, alloc_dwidgets
* sizeof(Fl_Widget
*));
1819 alloc_dwidgets
+= 10;
1822 dwidgets
[num_dwidgets
] = wi
;
1827 Deletes widgets previously scheduled for deletion.
1829 This is for internal use only. You should never call this directly.
1831 Fl::do_widget_deletion() is called from the FLTK event loop or whenever
1832 you call Fl::wait(). The previously scheduled widgets are deleted in the
1833 same order they were scheduled by calling Fl::delete_widget().
1835 \see Fl::delete_widget(Fl_Widget *wi)
1837 void Fl::do_widget_deletion() {
1838 if (!num_dwidgets
) return;
1840 for (int i
= 0; i
< num_dwidgets
; i
++)
1846 static Fl_Widget
***widget_watch
= 0;
1847 static int num_widget_watch
= 0;
1848 static int max_widget_watch
= 0;
1851 Adds a widget pointer to the widget watch list.
1853 \note Internal use only, please use class Fl_Widget_Tracker instead.
1855 This can be used, if it is possible that a widget might be deleted during
1856 a callback or similar function. The widget pointer must be added to the
1857 watch list before calling the callback. After the callback the widget
1858 pointer can be queried, if it is NULL. \e If it is NULL, then the widget has been
1859 deleted during the callback and must not be accessed anymore. If the widget
1860 pointer is \e not NULL, then the widget has not been deleted and can be accessed
1863 After accessing the widget, the widget pointer must be released from the
1864 watch list by calling Fl::release_widget_pointer().
1866 Example for a button that is clicked (from its handle() method):
1868 Fl_Widget *wp = this; // save 'this' in a pointer variable
1869 Fl::watch_widget_pointer(wp); // add the pointer to the watch list
1870 set_changed(); // set the changed flag
1871 do_callback(); // call the callback
1872 if (!wp) { // the widget has been deleted
1874 // DO NOT ACCESS THE DELETED WIDGET !
1876 } else { // the widget still exists
1877 clear_changed(); // reset the changed flag
1880 Fl::release_widget_pointer(wp); // remove the pointer from the watch list
1883 This works, because all widgets call Fl::clear_widget_pointer() in their
1886 \see Fl::release_widget_pointer()
1887 \see Fl::clear_widget_pointer()
1889 An easier and more convenient method to control widget deletion during
1890 callbacks is to use the class Fl_Widget_Tracker with a local (automatic)
1893 \see class Fl_Widget_Tracker
1895 void Fl::watch_widget_pointer(Fl_Widget
*&w
)
1897 Fl_Widget
**wp
= &w
;
1899 for (i
=0; i
<num_widget_watch
; ++i
) {
1900 if (widget_watch
[i
]==wp
) return;
1902 if (num_widget_watch
==max_widget_watch
) {
1903 max_widget_watch
+= 8;
1904 widget_watch
= (Fl_Widget
***)realloc(widget_watch
, sizeof(Fl_Widget
**)*max_widget_watch
);
1906 widget_watch
[num_widget_watch
++] = wp
;
1908 printf ("\nwatch_widget_pointer: (%d/%d) %8p => %8p\n",
1909 num_widget_watch
,num_widget_watch
,wp
,*wp
);
1911 #endif // DEBUG_WATCH
1915 Releases a widget pointer from the watch list.
1917 This is used to remove a widget pointer that has been added to the watch list
1918 with Fl::watch_widget_pointer(), when it is not needed anymore.
1920 \note Internal use only, please use class Fl_Widget_Tracker instead.
1922 \see Fl::watch_widget_pointer()
1924 void Fl::release_widget_pointer(Fl_Widget
*&w
)
1926 Fl_Widget
**wp
= &w
;
1928 for (i
=0; i
<num_widget_watch
; ++i
) {
1929 if (widget_watch
[i
]!=wp
) {
1930 if (j
<i
) widget_watch
[j
] = widget_watch
[i
]; // fill gap
1934 else { // found widget pointer
1935 printf ("release_widget_pointer: (%d/%d) %8p => %8p\n",
1936 i
+1,num_widget_watch
,wp
,*wp
);
1938 #endif //DEBUG_WATCH
1940 num_widget_watch
= j
;
1942 printf (" num_widget_watch = %d\n\n",num_widget_watch
);
1944 #endif // DEBUG_WATCH
1948 Clears a widget pointer \e in the watch list.
1950 This is called when a widget is destroyed (by its destructor). You should never
1953 \note Internal use only !
1955 This method searches the widget watch list for pointers to the widget and
1956 clears each pointer that points to it. Widget pointers can be added to the
1957 widget watch list by calling Fl::watch_widget_pointer() or by using the
1958 helper class Fl_Widget_Tracker (recommended).
1960 \see Fl::watch_widget_pointer()
1961 \see class Fl_Widget_Tracker
1963 void Fl::clear_widget_pointer(Fl_Widget
const *w
)
1967 for (i
=0; i
<num_widget_watch
; ++i
) {
1968 if (widget_watch
[i
] && *widget_watch
[i
]==w
) {
1969 *widget_watch
[i
] = 0L;
1976 \brief FLTK library options management.
1978 This function needs to be documented in more detail. It can be used for more
1979 optional settings, such as using a native file chooser instead of the FLTK one
1980 wherever possible, disabling tooltips, disabling visible focus, disabling
1981 FLTK file chooser preview, etc. .
1983 There should be a command line option interface.
1985 There should be an application that manages options system wide, per user, and
1988 \note As of FLTK 1.3.0, options can be managed within fluid, using the menu
1989 <i>Edit/Global FLTK Settings</i>.
1991 \param opt which option
1992 \return true or false
1993 \see enum Fl::Fl_Option
1994 \see Fl::option(Fl_Option, bool)
1998 bool Fl::option(Fl_Option opt
)
2000 if (!options_read_
) {
2002 { // first, read the system wide preferences
2003 Fl_Preferences
prefs(Fl_Preferences::SYSTEM
, "fltk.org", "fltk");
2004 Fl_Preferences
opt_prefs(prefs
, "options");
2005 opt_prefs
.get("ArrowFocus", tmp
, 0); // default: off
2006 options_
[OPTION_ARROW_FOCUS
] = tmp
;
2007 //opt_prefs.get("NativeFilechooser", tmp, 1); // default: on
2008 //options_[OPTION_NATIVE_FILECHOOSER] = tmp;
2009 //opt_prefs.get("FilechooserPreview", tmp, 1); // default: on
2010 //options_[OPTION_FILECHOOSER_PREVIEW] = tmp;
2011 opt_prefs
.get("VisibleFocus", tmp
, 1); // default: on
2012 options_
[OPTION_VISIBLE_FOCUS
] = tmp
;
2013 opt_prefs
.get("DNDText", tmp
, 1); // default: on
2014 options_
[OPTION_DND_TEXT
] = tmp
;
2015 opt_prefs
.get("ShowTooltips", tmp
, 1); // default: on
2016 options_
[OPTION_SHOW_TOOLTIPS
] = tmp
;
2018 { // next, check the user preferences
2019 // override system options only, if the option is set ( >= 0 )
2020 Fl_Preferences
prefs(Fl_Preferences::USER
, "fltk.org", "fltk");
2021 Fl_Preferences
opt_prefs(prefs
, "options");
2022 opt_prefs
.get("ArrowFocus", tmp
, -1);
2023 if (tmp
>= 0) options_
[OPTION_ARROW_FOCUS
] = tmp
;
2024 //opt_prefs.get("NativeFilechooser", tmp, -1);
2025 //if (tmp >= 0) options_[OPTION_NATIVE_FILECHOOSER] = tmp;
2026 //opt_prefs.get("FilechooserPreview", tmp, -1);
2027 //if (tmp >= 0) options_[OPTION_FILECHOOSER_PREVIEW] = tmp;
2028 opt_prefs
.get("VisibleFocus", tmp
, -1);
2029 if (tmp
>= 0) options_
[OPTION_VISIBLE_FOCUS
] = tmp
;
2030 opt_prefs
.get("DNDText", tmp
, -1);
2031 if (tmp
>= 0) options_
[OPTION_DND_TEXT
] = tmp
;
2032 opt_prefs
.get("ShowTooltips", tmp
, -1);
2033 if (tmp
>= 0) options_
[OPTION_SHOW_TOOLTIPS
] = tmp
;
2035 { // now, if the developer has registered this app, we could as for per-application preferences
2039 if (opt
<0 || opt
>=OPTION_LAST
)
2041 return (bool)(options_
[opt
]!=0);
2045 \brief Override an option while the application is running.
2047 This function does not change any system or user settings.
2049 \param opt which option
2050 \param val set to true or false
2051 \see enum Fl::Fl_Option
2052 \see bool Fl::option(Fl_Option)
2054 void Fl::option(Fl_Option opt
, bool val
)
2056 if (opt
<0 || opt
>=OPTION_LAST
)
2058 if (!options_read_
) {
2059 // first read this option, so we don't override our setting later
2062 options_
[opt
] = val
;
2066 // Helper class Fl_Widget_Tracker
2069 The constructor adds a widget to the watch list.
2071 Fl_Widget_Tracker::Fl_Widget_Tracker(Fl_Widget
*wi
)
2074 Fl::watch_widget_pointer(wp_
); // add pointer to watch list
2078 The destructor removes a widget from the watch list.
2080 Fl_Widget_Tracker::~Fl_Widget_Tracker()
2082 Fl::release_widget_pointer(wp_
); // remove pointer from watch list
2087 // End of "$Id: Fl.cxx 8723 2011-05-23 16:49:02Z manolo $".