Fl_Panzoomer: Always draw box.
[ntk.git] / src / Fl.cxx
blob4263f3cda730801b8ada3d5f724e45c3129d75f9
1 //
2 // "$Id: Fl.cxx 8723 2011-05-23 16:49:02Z manolo $"
3 //
4 // Main event handling code for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
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
21 // USA.
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.
33 #include <config.h>
35 /* We require Windows 2000 features (e.g. VK definitions) */
36 #if defined(WIN32)
37 # if !defined(WINVER) || (WINVER < 0x0500)
38 # ifdef WINVER
39 # undef WINVER
40 # endif
41 # define WINVER 0x0500
42 # endif
43 # if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
44 # ifdef _WIN32_WINNT
45 # undef _WIN32_WINNT
46 # endif
47 # define _WIN32_WINNT 0x0500
48 # endif
49 #endif
51 #if FLTK_HAVE_CAIRO
52 #include <FL/Fl_Cairo.H>
53 #endif
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>
59 #endif
61 #include <FL/Fl.H>
62 #include <FL/Fl_Window.H>
63 #include <FL/Fl_Tooltip.H>
64 #include <FL/x.H>
66 #include <ctype.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include "flstring.h"
71 #if defined(DEBUG) || defined(DEBUG_WATCH)
72 # include <stdio.h>
73 #endif // DEBUG || DEBUG_WATCH
75 #ifdef WIN32
76 # include <ole2.h>
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);
84 #endif // WIN32
87 // Globals...
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 ";
97 #endif // __APPLE__
98 #ifndef FL_DOXYGEN
99 Fl_Widget *Fl::belowmouse_,
100 *Fl::pushed_,
101 *Fl::focus_,
102 *Fl::selection_owner_;
103 int Fl::damage_,
104 Fl::e_number,
105 Fl::e_x,
106 Fl::e_y,
107 Fl::e_x_root,
108 Fl::e_y_root,
109 Fl::e_dx,
110 Fl::e_dy,
111 Fl::e_state,
112 Fl::e_clicks,
113 Fl::e_is_click,
114 Fl::e_keysym,
115 Fl::e_original_keysym,
116 Fl::scrollbar_size_ = 16;
118 char *Fl::e_text = (char *)"";
119 int Fl::e_length;
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
132 #endif // FL_DOXYGEN
135 // 'Fl::version()' - Return the API version number...
138 double
140 Returns the compiled-in value of the FL_VERSION constant. This
141 is useful for checking the version of a shared library.
143 Fl::version() {
144 return FL_VERSION;
148 Gets the default scrollbar size used by
149 Fl_Browser_,
150 Fl_Help_View,
151 Fl_Scroll, and
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
161 Fl_Browser_,
162 Fl_Help_View,
163 Fl_Scroll, and
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) {
168 scrollbar_size_ = 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*/ {
187 int mx = e_x - xx;
188 int my = e_y - yy;
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());
227 // timer support
230 #ifdef WIN32
232 // implementation in Fl_win32.cxx
234 #elif defined(__APPLE__)
236 // implementation in Fl_mac.cxx
238 #else
241 // X11 timers
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).
251 struct Timeout {
252 double time;
253 void (*cb)(void*);
254 void* arg;
255 Timeout* next;
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;
275 if (reset_clock) {
276 reset_clock = 0;
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
285 // time interval:
286 static double missed_timeout_by;
288 void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
289 elapse_timeouts();
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;
296 if (t) {
297 free_timeout = t->next;
298 } else {
299 t = new Timeout;
301 t->time = time;
302 t->cb = cb;
303 t->arg = argp;
304 // insert-sort the new timeout:
305 Timeout** p = &first_timeout;
306 while (*p && (*p)->time <= time) p = &((*p)->next);
307 t->next = *p;
308 *p = t;
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;
317 return 0;
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;) {
329 Timeout* t = *p;
330 if (t->cb == cb && (t->arg == argp || !argp)) {
331 *p = t->next;
332 t->next = free_timeout;
333 free_timeout = t;
334 } else {
335 p = &(t->next);
340 #endif
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().
350 struct Check {
351 void (*cb)(void*);
352 void* arg;
353 Check* next;
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.
370 Sample code:
372 \code
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();
379 widget-&gt;redraw();
382 main() {
383 Fl::add_check(callback);
384 return Fl::run();
386 \endcode
388 void Fl::add_check(Fl_Timeout_Handler cb, void *argp) {
389 Check* t = free_check;
390 if (t) free_check = t->next;
391 else t = new Check;
392 t->cb = cb;
393 t->arg = argp;
394 t->next = first_check;
395 if (next_check == first_check) next_check = t;
396 first_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;) {
405 Check* t = *p;
406 if (t->cb == cb && t->arg == argp) {
407 if (next_check == t) next_check = t->next;
408 *p = t->next;
409 t->next = free_check;
410 free_check = t;
411 } else {
412 p = &(t->next);
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;) {
422 Check* t = *p;
423 if (t->cb == cb && t->arg == argp) {
424 return 1;
425 } else {
426 p = &(t->next);
429 return 0;
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) {
437 while (next_check) {
438 Check* checkp = next_check;
439 next_check = checkp->next;
440 (checkp->cb)(checkp->arg);
442 next_check = first_check;
446 #ifndef WIN32
447 static char in_idle;
448 #endif
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
459 See int Fl::wait()
461 double Fl::wait(double time_to_wait) {
462 // delete all widgets that were listed during callbacks
463 do_widget_deletion();
465 #ifdef WIN32
467 return fl_wait(time_to_wait);
469 #elif defined(__APPLE__)
471 run_checks();
472 if (idle) {
473 if (!in_idle) {
474 in_idle = 1;
475 idle();
476 in_idle = 0;
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);
483 #else
485 if (first_timeout) {
486 elapse_timeouts();
487 Timeout *t;
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;
494 void *argp = t->arg;
495 first_timeout = t->next;
496 t->next = free_timeout;
497 free_timeout = t;
498 // Now it is safe for the callback to do add_timeout:
499 cb(argp);
501 } else {
502 reset_clock = 1; // we are not going to check the clock
504 run_checks();
505 // if (idle && !fl_ready()) {
506 if (idle) {
507 if (!in_idle) {
508 in_idle = 1;
509 idle();
510 in_idle = 0;
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);
520 flush();
521 return ret;
522 } else {
523 // do flush first so that user sees the display:
524 flush();
525 if (idle && !in_idle) // 'idle' may have been set within flush()
526 time_to_wait = 0.0;
527 return fl_wait(time_to_wait);
529 #endif
532 #define FOREVER 1e20
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();.
541 int Fl::run() {
542 while (Fl_X::first) wait(FOREVER);
543 return 0;
546 #ifdef WIN32
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) {
555 OleInitialize(0L);
556 oleInitialized = 1;
560 // This calls the Windows function OleUninitialize() only, if
561 // OleInitialize has been called before.
562 void fl_OleUninitialize() {
563 if (oleInitialized) {
564 OleUninitialize();
565 oleInitialized = 0;
569 class Fl_Win32_At_Exit {
570 public:
571 Fl_Win32_At_Exit() { }
572 ~Fl_Win32_At_Exit() {
573 fl_free_fonts(); // do some WIN32 cleanup
574 fl_cleanup_pens();
575 fl_OleUninitialize();
576 fl_brush_action(1);
577 fl_cleanup_dc_list();
580 static Fl_Win32_At_Exit win32_at_exit;
581 #endif
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
589 program state.
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).
609 int Fl::wait() {
610 if (!Fl_X::first) return 0;
611 wait(FOREVER);
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:
619 \code
620 while (!calculation_done()) {
621 calculate();
622 Fl::check();
623 if (user_hit_abort_button()) break;
625 \endcode
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
629 FLTK).
631 int Fl::check() {
632 wait(0.0);
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()).
643 \code
644 while (!calculation_done()) {
645 calculate();
646 if (Fl::ready()) {
647 do_expensive_cleanup();
648 Fl::check();
649 if (user_hit_abort_button()) break;
652 \endcode
654 int Fl::ready() {
655 #if ! defined( WIN32 ) && ! defined(__APPLE__)
656 if (first_timeout) {
657 elapse_timeouts();
658 if (first_timeout->time <= 0) return 1;
659 } else {
660 reset_clock = 1;
662 #endif
663 return fl_ready();
666 ////////////////////////////////////////////////////////////////
667 // Window list management:
669 #ifndef FL_DOXYGEN
670 Fl_X* Fl_X::first;
671 #endif
673 Fl_Window* fl_find(Window xid) {
674 Fl_X *window;
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())
680 #else
681 # error unsupported platform
682 #endif // __APPLE__
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
687 *pp = window->next;
688 window->next = Fl_X::first;
689 Fl_X::first = window;
691 return window->w;
693 return 0;
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;
703 return i ? i->w : 0;
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;
713 return i ? i->w : 0;
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
722 useful.
724 void Fl::first_window(Fl_Window* window) {
725 if (!window || !window->shown()) return;
726 fl_find( Fl_X::i(window)->xid );
730 Redraws all widgets.
732 void Fl::redraw() {
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
745 event queue.
747 void Fl::flush() {
748 if (damage()) {
749 damage_ = 0;
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:
756 if ( i->region )
758 cairo_region_destroy( i->region );
759 i->region = 0;
763 #if defined(USE_X11)
764 if (fl_display) XFlush(fl_display);
765 #elif defined(WIN32)
766 GdiFlush();
767 #elif defined (__APPLE_QUARTZ__)
768 if (fl_gc)
769 CGContextFlush(fl_gc);
770 #else
771 # error unsupported platform
772 #endif
776 ////////////////////////////////////////////////////////////////
777 // Event handlers:
780 struct handler_link {
781 int (*handle)(int);
782 handler_link *next;
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;
809 l->handle = ha;
810 l->next = handlers;
811 handlers = l;
816 Removes a previously added event handler.
817 \see Fl::handle(int, Fl_Window*)
819 void Fl::remove_handler(Fl_Event_Handler ha) {
820 handler_link *l, *p;
822 // Search for the handler in the list...
823 for (l = handlers, p = 0; l && l->handle != ha; p = l, l = l->next);
825 if (l) {
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...
831 delete l;
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;
840 return 0;
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
855 handle()).
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_;
863 if (o != p) {
864 Fl::compose_reset();
865 focus_ = o;
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
868 if (o) {
869 Fl_Window *win = 0, *w1 = o->as_window();
870 if (!w1) w1 = o->window();
871 while (w1) { win=w1; w1=win->window(); }
872 if (win) {
873 #ifdef __APPLE__
874 if (fl_xfocus != win) {
875 Fl_X *x = Fl_X::i(win);
876 if (x) x->set_key_window();
878 #endif
879 fl_xfocus = win;
882 // take focus from the old focused window
883 fl_oldfocus = 0;
884 int old_event = e_number;
885 e_number = FL_UNFOCUS;
886 for (; p; p = p->parent()) {
887 p->handle(FL_UNFOCUS);
888 fl_oldfocus = p;
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
901 FL_SHORTCUT events.
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
908 handle()).
910 void Fl::belowmouse(Fl_Widget *o) {
911 if (grab()) return; // don't do anything while grab is on
912 Fl_Widget *p = belowmouse_;
913 if (o != p) {
914 belowmouse_ = o;
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()) {
918 p->handle(e_number);
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
927 this widget.
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
934 handle()).
936 void Fl::pushed(Fl_Widget *o) {
937 pushed_ = 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() {
952 #ifdef DEBUG
953 puts("fl_fix_focus();");
954 #endif // DEBUG
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;
960 if (w) {
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;
970 } else
971 Fl::focus(0);
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*/)) {
976 if (!Fl::pushed()) {
977 // set belowmouse based on Fl::modal() and fl_xmousewin:
978 w = fl_xmousewin;
979 if (w) {
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);
986 } else {
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;
994 } else {
995 Fl::belowmouse(0);
996 Fl_Tooltip::enter(0);
1001 #if !(defined(WIN32) || defined(__APPLE__))
1002 extern Fl_Widget *fl_selection_requestor; // from Fl_x.cxx
1003 #endif
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) {
1014 #ifdef DEBUG
1015 printf("fl_throw_focus(o=%p)\n", o);
1016 #endif // DEBUG
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;
1021 #endif
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);
1028 fl_fix_focus();
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) {
1037 int dx, dy;
1038 int old_event = Fl::e_number;
1039 if (window) {
1040 dx = window->x();
1041 dy = window->y();
1042 } else {
1043 dx = dy = 0;
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;
1051 Fl::e_y = save_y;
1052 Fl::e_x = save_x;
1053 return ret;
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:
1072 \code
1073 int myHandler(int e, Fl_Window *w) {
1074 try {
1075 return Fl::handle_(e, w);
1076 } catch () {
1081 main() {
1082 Fl::event_dispatch(myHandler);
1084 Fl::run();
1086 \endcode
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)
1095 e_dispatch = d;
1100 \brief Return the current event dispatch function.
1102 Fl_Event_Dispatch Fl::event_dispatch()
1104 return e_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
1115 ignored.
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)
1126 if (e_dispatch) {
1127 return e_dispatch(e, window);
1128 } else {
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)
1149 e_number = e;
1150 if (fl_local_grab) return fl_local_grab(e);
1152 Fl_Widget* wi = window;
1154 switch (e) {
1156 case FL_CLOSE:
1157 if ( grab() || (modal() && window != modal()) ) return 0;
1158 wi->do_callback();
1159 return 1;
1161 case FL_SHOW:
1162 wi->Fl_Widget::show(); // this calls Fl_Widget::show(), not Fl_Window::show()
1163 return 1;
1165 case FL_HIDE:
1166 wi->Fl_Widget::hide(); // this calls Fl_Widget::hide(), not Fl_Window::hide()
1167 return 1;
1169 case FL_PUSH:
1170 #ifdef DEBUG
1171 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1172 #endif // DEBUG
1174 if (grab()) wi = grab();
1175 else if (modal() && wi != modal()) return 0;
1176 pushed_ = wi;
1177 Fl_Tooltip::current(wi);
1178 if (send(e, wi, window)) return 1;
1179 // raise windows that are clicked on:
1180 window->show();
1181 return 1;
1183 case FL_DND_ENTER:
1184 case FL_DND_DRAG:
1185 dnd_flag = 1;
1186 break;
1188 case FL_DND_LEAVE:
1189 dnd_flag = 1;
1190 belowmouse(0);
1191 dnd_flag = 0;
1192 return 1;
1194 case FL_DND_RELEASE:
1195 wi = belowmouse();
1196 break;
1198 case FL_MOVE:
1199 case FL_DRAG:
1200 fl_xmousewin = window; // this should already be set, but just in case.
1201 if (pushed()) {
1202 wi = pushed();
1203 if (grab()) wi = grab();
1204 e_number = e = FL_DRAG;
1205 break;
1207 if (modal() && wi != modal()) wi = 0;
1208 if (grab()) wi = grab();
1209 { int ret;
1210 Fl_Widget* pbm = belowmouse();
1211 #ifdef __APPLE__
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();
1215 int inside = 0;
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));
1224 } else
1225 #endif
1226 ret = (wi && send(e, wi, window));
1227 if (pbm != belowmouse()) {
1228 #ifdef DEBUG
1229 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1230 #endif // DEBUG
1231 Fl_Tooltip::enter(belowmouse());
1233 return ret;}
1235 case FL_RELEASE: {
1236 // printf("FL_RELEASE: window=%p, pushed() = %p, grab() = %p, modal() = %p\n",
1237 // window, pushed(), grab(), modal());
1239 if (grab()) {
1240 wi = grab();
1241 pushed_ = 0; // must be zero before callback is done!
1242 } else if (pushed()) {
1243 wi = 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);
1247 fl_fix_focus();
1248 return r;}
1250 case FL_UNFOCUS:
1251 window = 0;
1252 case FL_FOCUS:
1253 fl_xfocus = window;
1254 fl_fix_focus();
1255 return 1;
1257 case FL_KEYUP:
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
1266 // "close enough".
1267 for (wi = grab() ? grab() : focus(); wi; wi = wi->parent())
1268 if (send(FL_KEYUP, wi, window)) return 1;
1269 return 0;
1271 case FL_KEYBOARD:
1272 #ifdef DEBUG
1273 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1274 #endif // DEBUG
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;
1294 case 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:
1298 wi = belowmouse();
1299 if (!wi) {
1300 wi = modal();
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;
1316 wi->do_callback();
1317 return 1;
1320 return 0;
1322 case FL_ENTER:
1323 #ifdef DEBUG
1324 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1325 #endif // DEBUG
1327 fl_xmousewin = window;
1328 fl_fix_focus();
1329 Fl_Tooltip::enter(belowmouse());
1330 return 1;
1332 case FL_LEAVE:
1333 #ifdef DEBUG
1334 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1335 #endif // DEBUG
1337 if (!pushed_) {
1338 belowmouse(0);
1339 Fl_Tooltip::enter(0);
1341 if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();}
1342 return 1;
1344 case FL_MOUSEWHEEL:
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
1352 if (modal()) {
1353 send(FL_MOUSEWHEEL, modal(), window);
1354 return 1;
1356 // Finally try sending it to the window, the event occured in
1357 if (send(FL_MOUSEWHEEL, window, window)) return 1;
1358 default:
1359 break;
1361 if (wi && send(e, wi, window)) {
1362 dnd_flag = 0;
1363 return 1;
1365 dnd_flag = 0;
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);
1374 #endif
1376 void Fl_Window::hide() {
1377 clear_visible();
1379 if (!shown()) return;
1381 // remove from the list of windows:
1382 Fl_X* ip = i;
1383 Fl_X** pp = &Fl_X::first;
1384 for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return;
1385 *pp = ip->next;
1386 #ifdef __APPLE__
1387 ip->unlink();
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);
1392 #endif
1393 i = 0;
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) {
1399 W->hide();
1400 W->set_visible();
1401 wi = Fl_X::first;
1402 } else wi = wi->next;
1405 if (this == Fl::modal_) { // we are closing the modal window, find next one:
1406 Fl_Window* W;
1407 for (W = Fl::first_window(); W; W = Fl::next_window(W))
1408 if (W->modal()) break;
1409 Fl::modal_ = W;
1412 // Make sure no events are sent to this window:
1413 fl_throw_focus(this);
1414 handle(FL_HIDE);
1416 #if defined(WIN32)
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))) {
1422 EmptyClipboard();
1423 SetClipboardData(CF_TEXT, NULL);
1424 CloseClipboard();
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;
1433 fl_gc = 0;
1435 #elif defined(__APPLE_QUARTZ__)
1436 Fl_X::q_release_context(ip);
1437 if ( ip->xid == fl_window && !parent() )
1438 fl_window = 0;
1439 #endif
1440 if (ip->region)
1442 cairo_region_destroy( ip->region );
1443 ip->region = 0;
1446 #if defined(USE_X11)
1447 #if FLTK_HAVE_CAIRO
1448 cairo_destroy( ip->cc ); ip->cc = 0;
1449 cairo_surface_destroy( ip->cs ); ip->cs = 0;
1450 #endif
1451 # if USE_XFT
1452 fl_destroy_xft_draw(ip->xid);
1453 # endif
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__)
1465 ip->destroy();
1466 #else
1467 # error unsupported platform
1468 #endif
1470 #ifdef WIN32
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();
1474 #endif
1475 delete ip;
1478 Fl_Window::~Fl_Window() {
1479 hide();
1480 if (xclass_) {
1481 free(xclass_);
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)
1495 if (parent()) {
1496 switch (ev) {
1497 case FL_SHOW:
1498 if (!shown()) show();
1499 else {
1500 #if defined(USE_X11) || defined(WIN32)
1501 XMapWindow(fl_display, fl_xid(this)); // extra map calls are harmless
1502 #elif defined(__APPLE_QUARTZ__)
1503 i->map();
1504 #else
1505 # error unsupported platform
1506 #endif // __APPLE__
1508 break;
1509 case FL_HIDE:
1510 if (shown()) {
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.
1518 if (visible()) {
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__)
1525 i->unmap();
1526 #else
1527 # error platform unsupported
1528 #endif
1530 break;
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
1552 of this.</i>
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() {
1585 if (window()) {
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
1589 // background...
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...
1598 int W = 0, H = 0;
1599 label_.measure(W, H);
1600 W += 5; // Add a little to the size of the label to cover overflow
1601 H += 5;
1603 // FIXME:
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;
1609 case FL_ALIGN_TOP:
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;
1617 case FL_ALIGN_LEFT:
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;
1631 default:
1632 window()->damage(FL_DAMAGE_ALL); break;
1634 } else {
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());
1645 } else {
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
1649 if ( i->region )
1651 cairo_region_destroy( i->region );
1652 i->region = 0;
1654 damage_ |= fl;
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 )
1669 wi->damage_ |= fl;
1671 switch ( wi->box() )
1673 case FL_FLAT_BOX:
1674 case FL_BORDER_BOX:
1675 hit_opaque_widget = true;
1676 break;
1677 default:
1678 break;
1681 if ( ! ( wi = wi->parent() ) )
1682 return;
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:
1709 wi->damage(fl);
1710 return;
1713 if (wi->damage()) {
1714 // if we already have damage we must merge with existing region:
1715 if (i->region) {
1716 #if defined(USE_X11)
1718 cairo_rectangle_int_t rect;
1720 rect.x = X;
1721 rect.y = Y;
1722 rect.width = W;
1723 rect.height = H;
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);
1729 XDestroyRegion(R);
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;
1740 #else
1741 # error unsupported platform
1742 #endif
1744 wi->damage_ |= fl;
1745 } else {
1748 if ( i->region )
1749 cairo_region_destroy( i->region );
1751 i->region = cairo_region_create();
1752 cairo_rectangle_int_t rect;
1754 rect.x = X;
1755 rect.y = Y;
1756 rect.width = W;
1757 rect.height = H;
1759 cairo_region_union_rectangle( i->region, &rect );
1761 wi->damage_ = fl;
1763 Fl::damage(FL_DAMAGE_CHILD);
1765 void Fl_Window::flush() {
1766 draw();
1768 #if FLTK_HAVE_CAIRO
1769 cairo_surface_flush( i->cs );
1770 #endif
1773 #ifdef WIN32
1774 # include "Fl_win32.cxx"
1775 //#elif defined(__APPLE__)
1776 #endif
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) {
1807 if (!wi) return;
1809 if (num_dwidgets >= alloc_dwidgets) {
1810 Fl_Widget **temp;
1812 temp = new Fl_Widget *[alloc_dwidgets + 10];
1813 if (alloc_dwidgets) {
1814 memcpy(temp, dwidgets, alloc_dwidgets * sizeof(Fl_Widget *));
1815 delete[] dwidgets;
1818 dwidgets = temp;
1819 alloc_dwidgets += 10;
1822 dwidgets[num_dwidgets] = wi;
1823 num_dwidgets ++;
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 ++)
1841 delete dwidgets[i];
1843 num_dwidgets = 0;
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
1861 safely.
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):
1867 \code
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
1881 \endcode
1883 This works, because all widgets call Fl::clear_widget_pointer() in their
1884 destructors.
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)
1891 variable.
1893 \see class Fl_Widget_Tracker
1895 void Fl::watch_widget_pointer(Fl_Widget *&w)
1897 Fl_Widget **wp = &w;
1898 int i;
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;
1907 #ifdef DEBUG_WATCH
1908 printf ("\nwatch_widget_pointer: (%d/%d) %8p => %8p\n",
1909 num_widget_watch,num_widget_watch,wp,*wp);
1910 fflush(stdout);
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;
1927 int i,j=0;
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
1931 j++;
1933 #ifdef DEBUG_WATCH
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;
1941 #ifdef DEBUG_WATCH
1942 printf (" num_widget_watch = %d\n\n",num_widget_watch);
1943 fflush(stdout);
1944 #endif // DEBUG_WATCH
1945 return;
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
1951 call this directly.
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)
1965 if (w==0L) return;
1966 int i;
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
1986 per application.
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)
1996 \since FLTK 1.3.0
1998 bool Fl::option(Fl_Option opt)
2000 if (!options_read_) {
2001 int tmp;
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
2037 options_read_ = 1;
2039 if (opt<0 || opt>=OPTION_LAST)
2040 return false;
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)
2057 return;
2058 if (!options_read_) {
2059 // first read this option, so we don't override our setting later
2060 option(opt);
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)
2073 wp_ = 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 $".