themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl.cxx
blob214aea7bef0f3250e4fc3b13d1730da610b54257
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 // recent versions of MinGW warn: "Please include winsock2.h before windows.h",
52 // hence we must include winsock2.h before FL/Fl.H (A.S. Dec. 2010, IMM May 2011)
53 #if defined(WIN32) && !defined(__CYGWIN__)
54 # include <winsock2.h>
55 #endif
57 #include <FL/Fl.H>
58 #include <FL/Fl_Window.H>
59 #include <FL/Fl_Tooltip.H>
60 #include <FL/x.H>
62 #include <ctype.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include "flstring.h"
67 #if defined(DEBUG) || defined(DEBUG_WATCH)
68 # include <stdio.h>
69 #endif // DEBUG || DEBUG_WATCH
71 #ifdef WIN32
72 # include <ole2.h>
73 void fl_free_fonts(void);
74 HBRUSH fl_brush_action(int action);
75 void fl_cleanup_pens(void);
76 void fl_release_dc(HWND,HDC);
77 void fl_cleanup_dc_list(void);
78 #elif defined(__APPLE__)
79 extern double fl_mac_flush_and_wait(double time_to_wait, char in_idle);
80 #endif // WIN32
83 // Globals...
85 #if defined(__APPLE__) || defined(FL_DOXYGEN)
86 const char *Fl_Mac_App_Menu::about = "About ";
87 const char *Fl_Mac_App_Menu::print = "Print Front Window";
88 const char *Fl_Mac_App_Menu::services = "Services";
89 const char *Fl_Mac_App_Menu::hide = "Hide ";
90 const char *Fl_Mac_App_Menu::hide_others = "Hide Others";
91 const char *Fl_Mac_App_Menu::show = "Show All";
92 const char *Fl_Mac_App_Menu::quit = "Quit ";
93 #endif // __APPLE__
94 #ifndef FL_DOXYGEN
95 Fl_Widget *Fl::belowmouse_,
96 *Fl::pushed_,
97 *Fl::focus_,
98 *Fl::selection_owner_;
99 int Fl::damage_,
100 Fl::e_number,
101 Fl::e_x,
102 Fl::e_y,
103 Fl::e_x_root,
104 Fl::e_y_root,
105 Fl::e_dx,
106 Fl::e_dy,
107 Fl::e_state,
108 Fl::e_clicks,
109 Fl::e_is_click,
110 Fl::e_keysym,
111 Fl::e_original_keysym,
112 Fl::scrollbar_size_ = 16;
114 char *Fl::e_text = (char *)"";
115 int Fl::e_length;
117 Fl_Event_Dispatch Fl::e_dispatch = 0;
119 unsigned char Fl::options_[] = { 0, 0 };
120 unsigned char Fl::options_read_ = 0;
123 Fl_Window *fl_xfocus; // which window X thinks has focus
124 Fl_Window *fl_xmousewin;// which window X thinks has FL_ENTER
125 Fl_Window *Fl::grab_; // most recent Fl::grab()
126 Fl_Window *Fl::modal_; // topmost modal() window
128 #endif // FL_DOXYGEN
131 // 'Fl::version()' - Return the API version number...
134 double
136 Returns the compiled-in value of the FL_VERSION constant. This
137 is useful for checking the version of a shared library.
139 Fl::version() {
140 return FL_VERSION;
144 Gets the default scrollbar size used by
145 Fl_Browser_,
146 Fl_Help_View,
147 Fl_Scroll, and
148 Fl_Text_Display widgets.
149 \returns The default size for widget scrollbars, in pixels.
151 int Fl::scrollbar_size() {
152 return scrollbar_size_;
156 Sets the default scrollbar size that is used by the
157 Fl_Browser_,
158 Fl_Help_View,
159 Fl_Scroll, and
160 Fl_Text_Display widgets.
161 \param[in] W The new default size for widget scrollbars, in pixels.
163 void Fl::scrollbar_size(int W) {
164 scrollbar_size_ = W;
168 /** Returns whether or not the mouse event is inside the given rectangle.
170 Returns non-zero if the current Fl::event_x() and Fl::event_y()
171 put it inside the given arbitrary bounding box.
173 You should always call this rather than doing your own comparison
174 so you are consistent about edge effects.
176 To find out, whether the event is inside a child widget of the
177 current window, you can use Fl::event_inside(const Fl_Widget *).
179 \param[in] xx,yy,ww,hh bounding box
180 \return non-zero, if mouse event is inside
182 int Fl::event_inside(int xx,int yy,int ww,int hh) /*const*/ {
183 int mx = e_x - xx;
184 int my = e_y - yy;
185 return (mx >= 0 && mx < ww && my >= 0 && my < hh);
188 /** Returns whether or not the mouse event is inside a given child widget.
190 Returns non-zero if the current Fl::event_x() and Fl::event_y()
191 put it inside the given child widget's bounding box.
193 This method can only be used to check whether the mouse event is
194 inside a \b child widget of the window that handles the event, and
195 there must not be an intermediate subwindow (i.e. the widget must
196 not be inside a subwindow of the current window). However, it is
197 valid if the widget is inside a nested Fl_Group.
199 You must not use it with the window itself as the \p o argument
200 in a window's handle() method.
202 \note The mentioned restrictions are necessary, because this method
203 does not transform coordinates of child widgets, and thus the given
204 widget \p o must be within the \e same window that is handling the
205 current event. Otherwise the results are undefined.
207 You should always call this rather than doing your own comparison
208 so you are consistent about edge effects.
210 \see Fl::event_inside(int, int, int, int)
212 \param[in] o child widget to be tested
213 \return non-zero, if mouse event is inside the widget
215 int Fl::event_inside(const Fl_Widget *o) /*const*/ {
216 int mx = e_x - o->x();
217 int my = e_y - o->y();
218 return (mx >= 0 && mx < o->w() && my >= 0 && my < o->h());
223 // timer support
226 #ifdef WIN32
228 // implementation in Fl_win32.cxx
230 #elif defined(__APPLE__)
232 // implementation in Fl_mac.cxx
234 #else
237 // X11 timers
241 ////////////////////////////////////////////////////////////////////////
242 // Timeouts are stored in a sorted list (*first_timeout), so only the
243 // first one needs to be checked to see if any should be called.
244 // Allocated, but unused (free) Timeout structs are stored in another
245 // linked list (*free_timeout).
247 struct Timeout {
248 double time;
249 void (*cb)(void*);
250 void* arg;
251 Timeout* next;
253 static Timeout* first_timeout, *free_timeout;
255 #include <sys/time.h>
257 // I avoid the overhead of getting the current time when we have no
258 // timeouts by setting this flag instead of getting the time.
259 // In this case calling elapse_timeouts() does nothing, but records
260 // the current time, and the next call will actually elapse time.
261 static char reset_clock = 1;
263 static void elapse_timeouts() {
264 static struct timeval prevclock;
265 struct timeval newclock;
266 gettimeofday(&newclock, NULL);
267 double elapsed = newclock.tv_sec - prevclock.tv_sec +
268 (newclock.tv_usec - prevclock.tv_usec)/1000000.0;
269 prevclock.tv_sec = newclock.tv_sec;
270 prevclock.tv_usec = newclock.tv_usec;
271 if (reset_clock) {
272 reset_clock = 0;
273 } else if (elapsed > 0) {
274 for (Timeout* t = first_timeout; t; t = t->next) t->time -= elapsed;
278 // Continuously-adjusted error value, this is a number <= 0 for how late
279 // we were at calling the last timeout. This appears to make repeat_timeout
280 // very accurate even when processing takes a significant portion of the
281 // time interval:
282 static double missed_timeout_by;
284 void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
285 elapse_timeouts();
286 repeat_timeout(time, cb, argp);
289 void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
290 time += missed_timeout_by; if (time < -.05) time = 0;
291 Timeout* t = free_timeout;
292 if (t) {
293 free_timeout = t->next;
294 } else {
295 t = new Timeout;
297 t->time = time;
298 t->cb = cb;
299 t->arg = argp;
300 // insert-sort the new timeout:
301 Timeout** p = &first_timeout;
302 while (*p && (*p)->time <= time) p = &((*p)->next);
303 t->next = *p;
304 *p = t;
308 Returns true if the timeout exists and has not been called yet.
310 int Fl::has_timeout(Fl_Timeout_Handler cb, void *argp) {
311 for (Timeout* t = first_timeout; t; t = t->next)
312 if (t->cb == cb && t->arg == argp) return 1;
313 return 0;
317 Removes a timeout callback. It is harmless to remove a timeout
318 callback that no longer exists.
320 \note This version removes all matching timeouts, not just the first one.
321 This may change in the future.
323 void Fl::remove_timeout(Fl_Timeout_Handler cb, void *argp) {
324 for (Timeout** p = &first_timeout; *p;) {
325 Timeout* t = *p;
326 if (t->cb == cb && (t->arg == argp || !argp)) {
327 *p = t->next;
328 t->next = free_timeout;
329 free_timeout = t;
330 } else {
331 p = &(t->next);
336 #endif
338 ////////////////////////////////////////////////////////////////
339 // Checks are just stored in a list. They are called in the reverse
340 // order that they were added (this may change in the future).
341 // This is a bit messy because I want to allow checks to be added,
342 // removed, and have wait() called from inside them. To do this
343 // next_check points at the next unprocessed one for the outermost
344 // call to Fl::wait().
346 struct Check {
347 void (*cb)(void*);
348 void* arg;
349 Check* next;
351 static Check *first_check, *next_check, *free_check;
354 FLTK will call this callback just before it flushes the display and
355 waits for events. This is different than an idle callback because it
356 is only called once, then FLTK calls the system and tells it not to
357 return until an event happens.
359 This can be used by code that wants to monitor the
360 application's state, such as to keep a display up to date. The
361 advantage of using a check callback is that it is called only when no
362 events are pending. If events are coming in quickly, whole blocks of
363 them will be processed before this is called once. This can save
364 significant time and avoid the application falling behind the events.
366 Sample code:
368 \code
369 bool state_changed; // anything that changes the display turns this on
371 void callback(void*) {
372 if (!state_changed) return;
373 state_changed = false;
374 do_expensive_calculation();
375 widget-&gt;redraw();
378 main() {
379 Fl::add_check(callback);
380 return Fl::run();
382 \endcode
384 void Fl::add_check(Fl_Timeout_Handler cb, void *argp) {
385 Check* t = free_check;
386 if (t) free_check = t->next;
387 else t = new Check;
388 t->cb = cb;
389 t->arg = argp;
390 t->next = first_check;
391 if (next_check == first_check) next_check = t;
392 first_check = t;
396 Removes a check callback. It is harmless to remove a check
397 callback that no longer exists.
399 void Fl::remove_check(Fl_Timeout_Handler cb, void *argp) {
400 for (Check** p = &first_check; *p;) {
401 Check* t = *p;
402 if (t->cb == cb && t->arg == argp) {
403 if (next_check == t) next_check = t->next;
404 *p = t->next;
405 t->next = free_check;
406 free_check = t;
407 } else {
408 p = &(t->next);
414 Returns 1 if the check exists and has not been called yet, 0 otherwise.
416 int Fl::has_check(Fl_Timeout_Handler cb, void *argp) {
417 for (Check** p = &first_check; *p;) {
418 Check* t = *p;
419 if (t->cb == cb && t->arg == argp) {
420 return 1;
421 } else {
422 p = &(t->next);
425 return 0;
428 static void run_checks()
430 // checks are a bit messy so that add/remove and wait may be called
431 // from inside them without causing an infinite loop:
432 if (next_check == first_check) {
433 while (next_check) {
434 Check* checkp = next_check;
435 next_check = checkp->next;
436 (checkp->cb)(checkp->arg);
438 next_check = first_check;
442 #ifndef WIN32
443 static char in_idle;
444 #endif
446 ////////////////////////////////////////////////////////////////
447 // wait/run/check/ready:
449 void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions
451 extern int fl_ready(); // in Fl_<platform>.cxx
452 extern int fl_wait(double time); // in Fl_<platform>.cxx
455 See int Fl::wait()
457 double Fl::wait(double time_to_wait) {
458 // delete all widgets that were listed during callbacks
459 do_widget_deletion();
461 #ifdef WIN32
463 return fl_wait(time_to_wait);
465 #elif defined(__APPLE__)
467 run_checks();
468 if (idle) {
469 if (!in_idle) {
470 in_idle = 1;
471 idle();
472 in_idle = 0;
474 // the idle function may turn off idle, we can then wait:
475 if (idle) time_to_wait = 0.0;
477 return fl_mac_flush_and_wait(time_to_wait, in_idle);
479 #else
481 if (first_timeout) {
482 elapse_timeouts();
483 Timeout *t;
484 while ((t = first_timeout)) {
485 if (t->time > 0) break;
486 // The first timeout in the array has expired.
487 missed_timeout_by = t->time;
488 // We must remove timeout from array before doing the callback:
489 void (*cb)(void*) = t->cb;
490 void *argp = t->arg;
491 first_timeout = t->next;
492 t->next = free_timeout;
493 free_timeout = t;
494 // Now it is safe for the callback to do add_timeout:
495 cb(argp);
497 } else {
498 reset_clock = 1; // we are not going to check the clock
500 run_checks();
501 // if (idle && !fl_ready()) {
502 if (idle) {
503 if (!in_idle) {
504 in_idle = 1;
505 idle();
506 in_idle = 0;
508 // the idle function may turn off idle, we can then wait:
509 if (idle) time_to_wait = 0.0;
511 if (first_timeout && first_timeout->time < time_to_wait)
512 time_to_wait = first_timeout->time;
513 if (time_to_wait <= 0.0) {
514 // do flush second so that the results of events are visible:
515 int ret = fl_wait(0.0);
516 flush();
517 return ret;
518 } else {
519 // do flush first so that user sees the display:
520 flush();
521 if (idle && !in_idle) // 'idle' may have been set within flush()
522 time_to_wait = 0.0;
523 return fl_wait(time_to_wait);
525 #endif
528 #define FOREVER 1e20
531 As long as any windows are displayed this calls Fl::wait()
532 repeatedly. When all the windows are closed it returns zero
533 (supposedly it would return non-zero on any errors, but FLTK calls
534 exit directly for these). A normal program will end main()
535 with return Fl::run();.
537 int Fl::run() {
538 while (Fl_X::first) wait(FOREVER);
539 return 0;
542 #ifdef WIN32
544 // Function to initialize COM/OLE for usage. This must be done only once.
545 // We define a flag to register whether we called it:
546 static char oleInitialized = 0;
548 // This calls the Windows function OleInitialize() exactly once.
549 void fl_OleInitialize() {
550 if (!oleInitialized) {
551 OleInitialize(0L);
552 oleInitialized = 1;
556 // This calls the Windows function OleUninitialize() only, if
557 // OleInitialize has been called before.
558 void fl_OleUninitialize() {
559 if (oleInitialized) {
560 OleUninitialize();
561 oleInitialized = 0;
565 class Fl_Win32_At_Exit {
566 public:
567 Fl_Win32_At_Exit() { }
568 ~Fl_Win32_At_Exit() {
569 fl_free_fonts(); // do some WIN32 cleanup
570 fl_cleanup_pens();
571 fl_OleUninitialize();
572 fl_brush_action(1);
573 fl_cleanup_dc_list();
576 static Fl_Win32_At_Exit win32_at_exit;
577 #endif
582 Waits until "something happens" and then returns. Call this
583 repeatedly to "run" your program. You can also check what happened
584 each time after this returns, which is quite useful for managing
585 program state.
587 What this really does is call all idle callbacks, all elapsed
588 timeouts, call Fl::flush() to get the screen to update, and
589 then wait some time (zero if there are idle callbacks, the shortest of
590 all pending timeouts, or infinity), for any events from the user or
591 any Fl::add_fd() callbacks. It then handles the events and
592 calls the callbacks and then returns.
594 The return value of Fl::wait() is non-zero if there are any
595 visible windows - this may change in future versions of FLTK.
597 Fl::wait(time) waits a maximum of \e time seconds.
598 <i>It can return much sooner if something happens.</i>
600 The return value is positive if an event or fd happens before the
601 time elapsed. It is zero if nothing happens (on Win32 this will only
602 return zero if \e time is zero). It is negative if an error
603 occurs (this will happen on UNIX if a signal happens).
605 int Fl::wait() {
606 if (!Fl_X::first) return 0;
607 wait(FOREVER);
608 return Fl_X::first != 0; // return true if there is a window
612 Same as Fl::wait(0). Calling this during a big calculation
613 will keep the screen up to date and the interface responsive:
615 \code
616 while (!calculation_done()) {
617 calculate();
618 Fl::check();
619 if (user_hit_abort_button()) break;
621 \endcode
623 This returns non-zero if any windows are displayed, and 0 if no
624 windows are displayed (this is likely to change in future versions of
625 FLTK).
627 int Fl::check() {
628 wait(0.0);
629 return Fl_X::first != 0; // return true if there is a window
633 This is similar to Fl::check() except this does \e not
634 call Fl::flush() or any callbacks, which is useful if your
635 program is in a state where such callbacks are illegal. This returns
636 true if Fl::check() would do anything (it will continue to
637 return true until you call Fl::check() or Fl::wait()).
639 \code
640 while (!calculation_done()) {
641 calculate();
642 if (Fl::ready()) {
643 do_expensive_cleanup();
644 Fl::check();
645 if (user_hit_abort_button()) break;
648 \endcode
650 int Fl::ready() {
651 #if ! defined( WIN32 ) && ! defined(__APPLE__)
652 if (first_timeout) {
653 elapse_timeouts();
654 if (first_timeout->time <= 0) return 1;
655 } else {
656 reset_clock = 1;
658 #endif
659 return fl_ready();
662 ////////////////////////////////////////////////////////////////
663 // Window list management:
665 #ifndef FL_DOXYGEN
666 Fl_X* Fl_X::first;
667 #endif
669 Fl_Window* fl_find(Window xid) {
670 Fl_X *window;
671 for (Fl_X **pp = &Fl_X::first; (window = *pp); pp = &window->next)
672 #if defined(WIN32) || defined(USE_X11)
673 if (window->xid == xid)
674 #elif defined(__APPLE_QUARTZ__)
675 if (window->xid == xid && !window->w->window())
676 #else
677 # error unsupported platform
678 #endif // __APPLE__
680 if (window != Fl_X::first && !Fl::modal()) {
681 // make this window be first to speed up searches
682 // this is not done if modal is true to avoid messing up modal stack
683 *pp = window->next;
684 window->next = Fl_X::first;
685 Fl_X::first = window;
687 return window->w;
689 return 0;
693 Returns the first top-level window in the list of shown() windows. If
694 a modal() window is shown this is the top-most modal window, otherwise
695 it is the most recent window to get an event.
697 Fl_Window* Fl::first_window() {
698 Fl_X* i = Fl_X::first;
699 return i ? i->w : 0;
703 Returns the next top-level window in the list of shown() windows.
704 You can use this call to iterate through all the windows that are shown().
705 \param[in] window must be shown and not NULL
707 Fl_Window* Fl::next_window(const Fl_Window* window) {
708 Fl_X* i = Fl_X::i(window)->next;
709 return i ? i->w : 0;
713 Sets the window that is returned by first_window().
714 The window is removed from wherever it is in the
715 list and inserted at the top. This is not done if Fl::modal()
716 is on or if the window is not shown(). Because the first window
717 is used to set the "parent" of modal windows, this is often
718 useful.
720 void Fl::first_window(Fl_Window* window) {
721 if (!window || !window->shown()) return;
722 fl_find( Fl_X::i(window)->xid );
726 Redraws all widgets.
728 void Fl::redraw() {
729 for (Fl_X* i = Fl_X::first; i; i = i->next) i->w->redraw();
733 Causes all the windows that need it to be redrawn and graphics forced
734 out through the pipes.
736 This is what wait() does before looking for events.
738 Note: in multi-threaded applications you should only call Fl::flush()
739 from the main thread. If a child thread needs to trigger a redraw event,
740 it should instead call Fl::awake() to get the main thread to process the
741 event queue.
743 void Fl::flush() {
744 if (damage()) {
745 damage_ = 0;
746 for (Fl_X* i = Fl_X::first; i; i = i->next) {
747 if (i->wait_for_expose) {damage_ = 1; continue;}
748 Fl_Window* wi = i->w;
749 if (!wi->visible_r()) continue;
750 if (wi->damage()) {wi->make_current(); i->flush(); wi->clear_damage();}
751 // destroy damage regions for windows that don't use them:
752 if ( i->region )
754 cairo_region_destroy( i->region );
755 i->region = 0;
759 #if defined(USE_X11)
760 if (fl_display) XFlush(fl_display);
761 #elif defined(WIN32)
762 GdiFlush();
763 #elif defined (__APPLE_QUARTZ__)
764 if (fl_gc)
765 CGContextFlush(fl_gc);
766 #else
767 # error unsupported platform
768 #endif
772 ////////////////////////////////////////////////////////////////
773 // Event handlers:
776 struct handler_link {
777 int (*handle)(int);
778 handler_link *next;
782 static handler_link *handlers = 0;
786 Install a function to parse unrecognized events. If FLTK cannot
787 figure out what to do with an event, it calls each of these functions
788 (most recent first) until one of them returns non-zero. If none of
789 them returns non-zero then the event is ignored. Events that cause
790 this to be called are:
792 - FL_SHORTCUT events that are not recognized by any widget.
793 This lets you provide global shortcut keys.
794 - System events that FLTK does not recognize. See fl_xevent.
795 - \e Some other events when the widget FLTK selected returns
796 zero from its handle() method. Exactly which ones may change
797 in future versions, however.
799 \see Fl::remove_handler(Fl_Event_Handler)
800 \see Fl::event_dispatch(Fl_Event_Dispatch d)
801 \see Fl::handle(int, Fl_Window*)
803 void Fl::add_handler(Fl_Event_Handler ha) {
804 handler_link *l = new handler_link;
805 l->handle = ha;
806 l->next = handlers;
807 handlers = l;
812 Removes a previously added event handler.
813 \see Fl::handle(int, Fl_Window*)
815 void Fl::remove_handler(Fl_Event_Handler ha) {
816 handler_link *l, *p;
818 // Search for the handler in the list...
819 for (l = handlers, p = 0; l && l->handle != ha; p = l, l = l->next);
821 if (l) {
822 // Found it, so remove it from the list...
823 if (p) p->next = l->next;
824 else handlers = l->next;
826 // And free the record...
827 delete l;
831 int (*fl_local_grab)(int); // used by fl_dnd.cxx
833 static int send_handlers(int e) {
834 for (const handler_link *hl = handlers; hl; hl = hl->next)
835 if (hl->handle(e)) return 1;
836 return 0;
839 ////////////////////////////////////////////////////////////////
841 Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
844 Sets the widget that will receive FL_KEYBOARD events.
846 If you change Fl::focus(), the previous widget and all
847 parents (that don't contain the new widget) are sent FL_UNFOCUS
848 events. Changing the focus does \e not send FL_FOCUS to
849 this or any widget, because sending FL_FOCUS is supposed to
850 \e test if the widget wants the focus (by it returning non-zero from
851 handle()).
853 \see Fl_Widget::take_focus()
855 void Fl::focus(Fl_Widget *o) {
856 if (o && !o->visible_focus()) return;
857 if (grab()) return; // don't do anything while grab is on
858 Fl_Widget *p = focus_;
859 if (o != p) {
860 Fl::compose_reset();
861 focus_ = o;
862 // make sure that fl_xfocus is set to the top level window
863 // of this widget, or fl_fix_focus will clear our focus again
864 if (o) {
865 Fl_Window *win = 0, *w1 = o->as_window();
866 if (!w1) w1 = o->window();
867 while (w1) { win=w1; w1=win->window(); }
868 if (win) {
869 #ifdef __APPLE__
870 if (fl_xfocus != win) {
871 Fl_X *x = Fl_X::i(win);
872 if (x) x->set_key_window();
874 #endif
875 fl_xfocus = win;
878 // take focus from the old focused window
879 fl_oldfocus = 0;
880 int old_event = e_number;
881 e_number = FL_UNFOCUS;
882 for (; p; p = p->parent()) {
883 p->handle(FL_UNFOCUS);
884 fl_oldfocus = p;
886 e_number = old_event;
890 static char dnd_flag = 0; // make 'belowmouse' send DND_LEAVE instead of LEAVE
893 Sets the widget that is below the mouse. This is for
894 highlighting buttons. It is not used to send FL_PUSH or
895 FL_MOVE directly, for several obscure reasons, but those events
896 typically go to this widget. This is also the first widget tried for
897 FL_SHORTCUT events.
899 If you change the belowmouse widget, the previous one and all
900 parents (that don't contain the new widget) are sent FL_LEAVE
901 events. Changing this does \e not send FL_ENTER to this
902 or any widget, because sending FL_ENTER is supposed to \e test
903 if the widget wants the mouse (by it returning non-zero from
904 handle()).
906 void Fl::belowmouse(Fl_Widget *o) {
907 if (grab()) return; // don't do anything while grab is on
908 Fl_Widget *p = belowmouse_;
909 if (o != p) {
910 belowmouse_ = o;
911 int old_event = e_number;
912 e_number = dnd_flag ? FL_DND_LEAVE : FL_LEAVE;
913 for (; p && !p->contains(o); p = p->parent()) {
914 p->handle(e_number);
916 e_number = old_event;
921 Sets the widget that is being pushed. FL_DRAG or
922 FL_RELEASE (and any more FL_PUSH) events will be sent to
923 this widget.
925 If you change the pushed widget, the previous one and all parents
926 (that don't contain the new widget) are sent FL_RELEASE
927 events. Changing this does \e not send FL_PUSH to this
928 or any widget, because sending FL_PUSH is supposed to \e test
929 if the widget wants the mouse (by it returning non-zero from
930 handle()).
932 void Fl::pushed(Fl_Widget *o) {
933 pushed_ = o;
936 static void nothing(Fl_Widget *) {}
937 void (*Fl_Tooltip::enter)(Fl_Widget *) = nothing;
938 void (*Fl_Tooltip::exit)(Fl_Widget *) = nothing;
940 // Update modal(), focus() and other state according to system state,
941 // and send FL_ENTER, FL_LEAVE, FL_FOCUS, and/or FL_UNFOCUS events.
942 // This is the only function that produces these events in response
943 // to system activity.
944 // This is called whenever a window is added or hidden, and whenever
945 // X says the focus or mouse window have changed.
947 void fl_fix_focus() {
948 #ifdef DEBUG
949 puts("fl_fix_focus();");
950 #endif // DEBUG
952 if (Fl::grab()) return; // don't do anything while grab is on.
954 // set focus based on Fl::modal() and fl_xfocus
955 Fl_Widget* w = fl_xfocus;
956 if (w) {
957 int saved = Fl::e_keysym;
958 if (Fl::e_keysym < (FL_Button + FL_LEFT_MOUSE) ||
959 Fl::e_keysym > (FL_Button + FL_RIGHT_MOUSE))
960 Fl::e_keysym = 0; // make sure widgets don't think a keystroke moved focus
961 while (w->parent()) w = w->parent();
962 if (Fl::modal()) w = Fl::modal();
963 if (!w->contains(Fl::focus()))
964 if (!w->take_focus()) Fl::focus(w);
965 Fl::e_keysym = saved;
966 } else
967 Fl::focus(0);
969 // MRS: Originally we checked the button state, but a user reported that it
970 // broke click-to-focus in FLWM?!?
971 // if (!(Fl::event_state() & 0x7f00000 /*FL_BUTTONS*/)) {
972 if (!Fl::pushed()) {
973 // set belowmouse based on Fl::modal() and fl_xmousewin:
974 w = fl_xmousewin;
975 if (w) {
976 if (Fl::modal()) w = Fl::modal();
977 if (!w->contains(Fl::belowmouse())) {
978 int old_event = Fl::e_number;
979 w->handle(Fl::e_number = FL_ENTER);
980 Fl::e_number = old_event;
981 if (!w->contains(Fl::belowmouse())) Fl::belowmouse(w);
982 } else {
983 // send a FL_MOVE event so the enter/leave state is up to date
984 Fl::e_x = Fl::e_x_root-fl_xmousewin->x();
985 Fl::e_y = Fl::e_y_root-fl_xmousewin->y();
986 int old_event = Fl::e_number;
987 w->handle(Fl::e_number = FL_MOVE);
988 Fl::e_number = old_event;
990 } else {
991 Fl::belowmouse(0);
992 Fl_Tooltip::enter(0);
997 #if !(defined(WIN32) || defined(__APPLE__))
998 extern Fl_Widget *fl_selection_requestor; // from Fl_x.cxx
999 #endif
1001 // This function is called by ~Fl_Widget() and by Fl_Widget::deactivate()
1002 // and by Fl_Widget::hide(). It indicates that the widget does not want
1003 // to receive any more events, and also removes all global variables that
1004 // point at the widget.
1005 // I changed this from the 1.0.1 behavior, the older version could send
1006 // FL_LEAVE or FL_UNFOCUS events to the widget. This appears to not be
1007 // desirable behavior and caused flwm to crash.
1009 void fl_throw_focus(Fl_Widget *o) {
1010 #ifdef DEBUG
1011 printf("fl_throw_focus(o=%p)\n", o);
1012 #endif // DEBUG
1014 if (o->contains(Fl::pushed())) Fl::pushed_ = 0;
1015 #if !(defined(WIN32) || defined(__APPLE__))
1016 if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0;
1017 #endif
1018 if (o->contains(Fl::belowmouse())) Fl::belowmouse_ = 0;
1019 if (o->contains(Fl::focus())) Fl::focus_ = 0;
1020 if (o == fl_xfocus) fl_xfocus = 0;
1021 if (o == Fl_Tooltip::current()) Fl_Tooltip::current(0);
1022 if (o == fl_xmousewin) fl_xmousewin = 0;
1023 Fl_Tooltip::exit(o);
1024 fl_fix_focus();
1027 ////////////////////////////////////////////////////////////////
1029 // Call to->handle(), but first replace the mouse x/y with the correct
1030 // values to account for nested windows. 'window' is the outermost
1031 // window the event was posted to by the system:
1032 static int send(int event, Fl_Widget* to, Fl_Window* window) {
1033 int dx, dy;
1034 int old_event = Fl::e_number;
1035 if (window) {
1036 dx = window->x();
1037 dy = window->y();
1038 } else {
1039 dx = dy = 0;
1041 for (const Fl_Widget* w = to; w; w = w->parent())
1042 if (w->type()>=FL_WINDOW) {dx -= w->x(); dy -= w->y();}
1043 int save_x = Fl::e_x; Fl::e_x += dx;
1044 int save_y = Fl::e_y; Fl::e_y += dy;
1045 int ret = to->handle(Fl::e_number = event);
1046 Fl::e_number = old_event;
1047 Fl::e_y = save_y;
1048 Fl::e_x = save_x;
1049 return ret;
1054 \brief Set a new event dispatch function.
1056 The event dispatch function is called after native events are converted to
1057 FLTK events, but before they are handled by FLTK. If the dispatch function
1058 Fl_Event_Dispatch \p d is set, it is up to the dispatch function to call
1059 Fl::handle_(int, Fl_Window*) or to ignore the event.
1061 The dispatch function itself must return 0 if it ignored the event,
1062 or non-zero if it used the event. If you call Fl::handle_(), then
1063 this will return the correct value.
1065 The event dispatch can be used to handle exceptions in FLTK events and
1066 callbacks before they reach the native event handler:
1068 \code
1069 int myHandler(int e, Fl_Window *w) {
1070 try {
1071 return Fl::handle_(e, w);
1072 } catch () {
1077 main() {
1078 Fl::event_dispatch(myHandler);
1080 Fl::run();
1082 \endcode
1084 \param d new dispatch function, or NULL
1085 \see Fl::add_handler(Fl_Event_Handler)
1086 \see Fl::handle(int, Fl_Window*)
1087 \see Fl::handle_(int, Fl_Window*)
1089 void Fl::event_dispatch(Fl_Event_Dispatch d)
1091 e_dispatch = d;
1096 \brief Return the current event dispatch function.
1098 Fl_Event_Dispatch Fl::event_dispatch()
1100 return e_dispatch;
1105 \brief Handle events from the window system.
1107 This is called from the native event dispatch after native events have been
1108 converted to FLTK notation. This function calls Fl::handle_(int, Fl_Window*)
1109 unless the user sets a dispatch function. If a user dispatch function is set,
1110 the user must make sure that Fl::handle_() is called, or the event will be
1111 ignored.
1113 \param e the event type (Fl::event_number() is not yet set)
1114 \param window the window that caused this event
1115 \return 0 if the event was not handled
1117 \see Fl::add_handler(Fl_Event_Handler)
1118 \see Fl::event_dispatch(Fl_Event_Dispatch)
1120 int Fl::handle(int e, Fl_Window* window)
1122 if (e_dispatch) {
1123 return e_dispatch(e, window);
1124 } else {
1125 return handle_(e, window);
1131 \brief Handle events from the window system.
1133 This function is called from the native event dispatch, unless the user sets
1134 another dispatch function. In that case, the user dispatch function must
1135 decide when to call Fl::handle_(int, Fl_Window*)
1137 \param e the event type (Fl::event_number() is not yet set)
1138 \param window the window that caused this event
1139 \return 0 if the event was not handled
1141 \see Fl::event_dispatch(Fl_Event_Dispatch)
1143 int Fl::handle_(int e, Fl_Window* window)
1145 e_number = e;
1146 if (fl_local_grab) return fl_local_grab(e);
1148 Fl_Widget* wi = window;
1150 switch (e) {
1152 case FL_CLOSE:
1153 if ( grab() || (modal() && window != modal()) ) return 0;
1154 wi->do_callback();
1155 return 1;
1157 case FL_SHOW:
1158 wi->Fl_Widget::show(); // this calls Fl_Widget::show(), not Fl_Window::show()
1159 return 1;
1161 case FL_HIDE:
1162 wi->Fl_Widget::hide(); // this calls Fl_Widget::hide(), not Fl_Window::hide()
1163 return 1;
1165 case FL_PUSH:
1166 #ifdef DEBUG
1167 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1168 #endif // DEBUG
1170 if (grab()) wi = grab();
1171 else if (modal() && wi != modal()) return 0;
1172 pushed_ = wi;
1173 Fl_Tooltip::current(wi);
1174 if (send(e, wi, window)) return 1;
1175 // raise windows that are clicked on:
1176 window->show();
1177 return 1;
1179 case FL_DND_ENTER:
1180 case FL_DND_DRAG:
1181 dnd_flag = 1;
1182 break;
1184 case FL_DND_LEAVE:
1185 dnd_flag = 1;
1186 belowmouse(0);
1187 dnd_flag = 0;
1188 return 1;
1190 case FL_DND_RELEASE:
1191 wi = belowmouse();
1192 break;
1194 case FL_MOVE:
1195 case FL_DRAG:
1196 fl_xmousewin = window; // this should already be set, but just in case.
1197 if (pushed()) {
1198 wi = pushed();
1199 if (grab()) wi = grab();
1200 e_number = e = FL_DRAG;
1201 break;
1203 if (modal() && wi != modal()) wi = 0;
1204 if (grab()) wi = grab();
1205 { int ret;
1206 Fl_Widget* pbm = belowmouse();
1207 #ifdef __APPLE__
1208 if (fl_mac_os_version < 100500) {
1209 // before 10.5, mouse moved events aren't sent to borderless windows such as tooltips
1210 Fl_Window *tooltip = Fl_Tooltip::current_window();
1211 int inside = 0;
1212 if (tooltip && tooltip->shown() ) { // check if a tooltip window is currently opened
1213 // check if mouse is inside the tooltip
1214 inside = (Fl::event_x_root() >= tooltip->x() && Fl::event_x_root() < tooltip->x() + tooltip->w() &&
1215 Fl::event_y_root() >= tooltip->y() && Fl::event_y_root() < tooltip->y() + tooltip->h() );
1217 // if inside, send event to tooltip window instead of background window
1218 if (inside) ret = send(e, tooltip, window);
1219 else ret = (wi && send(e, wi, window));
1220 } else
1221 #endif
1222 ret = (wi && send(e, wi, window));
1223 if (pbm != belowmouse()) {
1224 #ifdef DEBUG
1225 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1226 #endif // DEBUG
1227 Fl_Tooltip::enter(belowmouse());
1229 return ret;}
1231 case FL_RELEASE: {
1232 // printf("FL_RELEASE: window=%p, pushed() = %p, grab() = %p, modal() = %p\n",
1233 // window, pushed(), grab(), modal());
1235 if (grab()) {
1236 wi = grab();
1237 pushed_ = 0; // must be zero before callback is done!
1238 } else if (pushed()) {
1239 wi = pushed();
1240 pushed_ = 0; // must be zero before callback is done!
1241 } else if (modal() && wi != modal()) return 0;
1242 int r = send(e, wi, window);
1243 fl_fix_focus();
1244 return r;}
1246 case FL_UNFOCUS:
1247 window = 0;
1248 case FL_FOCUS:
1249 fl_xfocus = window;
1250 fl_fix_focus();
1251 return 1;
1253 case FL_KEYUP:
1254 // Send the key-up to the current focus widget. This is not
1255 // always the same widget that received the corresponding
1256 // FL_KEYBOARD event because focus may have changed.
1257 // Sending the KEYUP to the right KEYDOWN is possible, but
1258 // would require that we track the KEYDOWN for every possible
1259 // key stroke (users may hold down multiple keys!) and then
1260 // make sure that the widget still exists before sending
1261 // a KEYUP there. I believe that the current solution is
1262 // "close enough".
1263 for (wi = grab() ? grab() : focus(); wi; wi = wi->parent())
1264 if (send(FL_KEYUP, wi, window)) return 1;
1265 return 0;
1267 case FL_KEYBOARD:
1268 #ifdef DEBUG
1269 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1270 #endif // DEBUG
1272 Fl_Tooltip::enter((Fl_Widget*)0);
1274 fl_xfocus = window; // this should not happen! But maybe it does:
1276 // Try it as keystroke, sending it to focus and all parents:
1277 for (wi = grab() ? grab() : focus(); wi; wi = wi->parent())
1278 if (send(FL_KEYBOARD, wi, window)) return 1;
1280 // recursive call to try shortcut:
1281 if (handle(FL_SHORTCUT, window)) return 1;
1283 // and then try a shortcut with the case of the text swapped, by
1284 // changing the text and falling through to FL_SHORTCUT case:
1285 {unsigned char* c = (unsigned char*)event_text(); // cast away const
1286 if (!isalpha(*c)) return 0;
1287 *c = isupper(*c) ? tolower(*c) : toupper(*c);}
1288 e_number = e = FL_SHORTCUT;
1290 case FL_SHORTCUT:
1291 if (grab()) {wi = grab(); break;} // send it to grab window
1293 // Try it as shortcut, sending to mouse widget and all parents:
1294 wi = belowmouse();
1295 if (!wi) {
1296 wi = modal();
1297 if (!wi) wi = window;
1298 } else if (wi->window() != first_window()) {
1299 if (send(FL_SHORTCUT, first_window(), first_window())) return 1;
1302 for (; wi; wi = wi->parent()) {
1303 if (send(FL_SHORTCUT, wi, wi->window())) return 1;
1306 // try using add_handle() functions:
1307 if (send_handlers(FL_SHORTCUT)) return 1;
1309 // make Escape key close windows:
1310 if (event_key()==FL_Escape) {
1311 wi = modal(); if (!wi) wi = window;
1312 wi->do_callback();
1313 return 1;
1316 return 0;
1318 case FL_ENTER:
1319 #ifdef DEBUG
1320 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1321 #endif // DEBUG
1323 fl_xmousewin = window;
1324 fl_fix_focus();
1325 Fl_Tooltip::enter(belowmouse());
1326 return 1;
1328 case FL_LEAVE:
1329 #ifdef DEBUG
1330 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1331 #endif // DEBUG
1333 if (!pushed_) {
1334 belowmouse(0);
1335 Fl_Tooltip::enter(0);
1337 if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();}
1338 return 1;
1340 case FL_MOUSEWHEEL:
1341 fl_xfocus = window; // this should not happen! But maybe it does:
1343 // Try sending it to the "grab" first
1344 if (grab() && grab()!=modal() && grab()!=window) {
1345 if (send(FL_MOUSEWHEEL, grab(), window)) return 1;
1347 // Now try sending it to the "modal" window
1348 if (modal()) {
1349 send(FL_MOUSEWHEEL, modal(), window);
1350 return 1;
1352 // Finally try sending it to the window, the event occured in
1353 if (send(FL_MOUSEWHEEL, window, window)) return 1;
1354 default:
1355 break;
1357 if (wi && send(e, wi, window)) {
1358 dnd_flag = 0;
1359 return 1;
1361 dnd_flag = 0;
1362 return send_handlers(e);
1365 ////////////////////////////////////////////////////////////////
1366 // hide() destroys the X window, it does not do unmap!
1368 #if !defined(WIN32) && USE_XFT
1369 extern void fl_destroy_xft_draw(Window);
1370 #endif
1372 void Fl_Window::hide() {
1373 clear_visible();
1375 if (!shown()) return;
1377 // remove from the list of windows:
1378 Fl_X* ip = i;
1379 Fl_X** pp = &Fl_X::first;
1380 for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return;
1381 *pp = ip->next;
1382 #ifdef __APPLE__
1383 ip->unlink();
1384 // MacOS X manages a single pointer per application. Make sure that hiding
1385 // a toplevel window will not leave us with some random pointer shape, or
1386 // worst case, an invisible pointer
1387 if (!parent()) cursor(FL_CURSOR_DEFAULT);
1388 #endif
1389 i = 0;
1391 // recursively remove any subwindows:
1392 for (Fl_X *wi = Fl_X::first; wi;) {
1393 Fl_Window* W = wi->w;
1394 if (W->window() == this) {
1395 W->hide();
1396 W->set_visible();
1397 wi = Fl_X::first;
1398 } else wi = wi->next;
1401 if (this == Fl::modal_) { // we are closing the modal window, find next one:
1402 Fl_Window* W;
1403 for (W = Fl::first_window(); W; W = Fl::next_window(W))
1404 if (W->modal()) break;
1405 Fl::modal_ = W;
1408 // Make sure no events are sent to this window:
1409 fl_throw_focus(this);
1410 handle(FL_HIDE);
1412 #if defined(WIN32)
1413 // this little trick keeps the current clipboard alive, even if we are about
1414 // to destroy the window that owns the selection.
1415 if (GetClipboardOwner()==ip->xid) {
1416 Fl_Window *w1 = Fl::first_window();
1417 if (w1 && OpenClipboard(fl_xid(w1))) {
1418 EmptyClipboard();
1419 SetClipboardData(CF_TEXT, NULL);
1420 CloseClipboard();
1423 // Send a message to myself so that I'll get out of the event loop...
1424 PostMessage(ip->xid, WM_APP, 0, 0);
1425 if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc);
1426 if (ip->xid == fl_window && fl_gc) {
1427 fl_release_dc(fl_window, fl_gc);
1428 fl_window = (HWND)-1;
1429 fl_gc = 0;
1431 #elif defined(__APPLE_QUARTZ__)
1432 Fl_X::q_release_context(ip);
1433 if ( ip->xid == fl_window && !parent() )
1434 fl_window = 0;
1435 #endif
1437 if (ip->region) cairo_region_destroy( ip->region ); ip->region = 0;
1439 #if defined(USE_X11)
1440 if ( ip->cc )
1441 cairo_destroy( ip->cc ); ip->cc = 0;
1442 # if USE_XFT
1443 fl_destroy_xft_draw(ip->xid);
1444 # endif
1445 // this test makes sure ip->xid has not been destroyed already
1446 if (ip->xid) XDestroyWindow(fl_display, ip->xid);
1447 #elif defined(WIN32)
1448 // this little trickery seems to avoid the popup window stacking problem
1449 HWND p = GetForegroundWindow();
1450 if (p==GetParent(ip->xid)) {
1451 ShowWindow(ip->xid, SW_HIDE);
1452 ShowWindow(p, SW_SHOWNA);
1454 XDestroyWindow(fl_display, ip->xid);
1455 #elif defined(__APPLE_QUARTZ__)
1456 ip->destroy();
1457 #else
1458 # error unsupported platform
1459 #endif
1461 #ifdef WIN32
1462 // Try to stop the annoying "raise another program" behavior
1463 if (non_modal() && Fl::first_window() && Fl::first_window()->shown())
1464 Fl::first_window()->show();
1465 #endif
1466 delete ip;
1469 Fl_Window::~Fl_Window() {
1470 hide();
1471 if (xclass_) {
1472 free(xclass_);
1476 // FL_SHOW and FL_HIDE are called whenever the visibility of this widget
1477 // or any parent changes. We must correctly map/unmap the system's window.
1479 // For top-level windows it is assumed the window has already been
1480 // mapped or unmapped!!! This is because this should only happen when
1481 // Fl_Window::show() or Fl_Window::hide() is called, or in response to
1482 // iconize/deiconize events from the system.
1484 int Fl_Window::handle(int ev)
1486 if (parent()) {
1487 switch (ev) {
1488 case FL_SHOW:
1489 if (!shown()) show();
1490 else {
1491 #if defined(USE_X11) || defined(WIN32)
1492 XMapWindow(fl_display, fl_xid(this)); // extra map calls are harmless
1493 #elif defined(__APPLE_QUARTZ__)
1494 i->map();
1495 #else
1496 # error unsupported platform
1497 #endif // __APPLE__
1499 break;
1500 case FL_HIDE:
1501 if (shown()) {
1502 // Find what really turned invisible, if it was a parent window
1503 // we do nothing. We need to avoid unnecessary unmap calls
1504 // because they cause the display to blink when the parent is
1505 // remapped. However if this or any intermediate non-window
1506 // widget has really had hide() called directly on it, we must
1507 // unmap because when the parent window is remapped we don't
1508 // want to reappear.
1509 if (visible()) {
1510 Fl_Widget* p = parent(); for (;p->visible();p = p->parent()) {}
1511 if (p->type() >= FL_WINDOW) break; // don't do the unmap
1513 #if defined(USE_X11) || defined(WIN32)
1514 XUnmapWindow(fl_display, fl_xid(this));
1515 #elif defined(__APPLE_QUARTZ__)
1516 i->unmap();
1517 #else
1518 # error platform unsupported
1519 #endif
1521 break;
1523 // } else if (ev == FL_FOCUS || ev == FL_UNFOCUS) {
1524 // Fl_Tooltip::exit(Fl_Tooltip::current());
1527 return Fl_Group::handle(ev);
1530 ////////////////////////////////////////////////////////////////
1531 // Back compatibility cut & paste functions for fltk 1.1 only:
1533 /** Back-compatibility only: The single-argument call can be used to
1534 move the selection to another widget or to set the owner to
1535 NULL, without changing the actual text of the
1536 selection. FL_SELECTIONCLEAR is sent to the previous
1537 selection owner, if any.
1539 <i>Copying the buffer every time the selection is changed is
1540 obviously wasteful, especially for large selections. An interface will
1541 probably be added in a future version to allow the selection to be made
1542 by a callback function. The current interface will be emulated on top
1543 of this.</i>
1545 void Fl::selection_owner(Fl_Widget *owner) {selection_owner_ = owner;}
1548 Changes the current selection. The block of text is
1549 copied to an internal buffer by FLTK (be careful if doing this in
1550 response to an FL_PASTE as this \e may be the same buffer
1551 returned by event_text()). The selection_owner()
1552 widget is set to the passed owner.
1554 void Fl::selection(Fl_Widget &owner, const char* text, int len) {
1555 selection_owner_ = &owner;
1556 Fl::copy(text, len, 0);
1559 /** Backward compatibility only.
1560 This calls Fl::paste(receiver, 0);
1561 \see Fl::paste(Fl_Widget &receiver, int clipboard)
1563 void Fl::paste(Fl_Widget &receiver) {
1564 Fl::paste(receiver, 0);
1567 ////////////////////////////////////////////////////////////////
1569 #include <FL/fl_draw.H>
1571 void Fl_Widget::redraw() {
1572 damage(FL_DAMAGE_ALL);
1575 void Fl_Widget::redraw_label() {
1576 if (window()) {
1577 if (box() == FL_NO_BOX) {
1578 // Widgets with the FL_NO_BOX boxtype need a parent to
1579 // redraw, since it is responsible for redrawing the
1580 // background...
1581 int X = x() > 0 ? x() - 1 : 0;
1582 int Y = y() > 0 ? y() - 1 : 0;
1583 window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2);
1586 if (align() && !(align() & FL_ALIGN_INSIDE) && window()->shown()) {
1587 // If the label is not inside the widget, compute the location of
1588 // the label and redraw the window within that bounding box...
1589 int W = 0, H = 0;
1590 label_.measure(W, H);
1591 W += 5; // Add a little to the size of the label to cover overflow
1592 H += 5;
1594 // FIXME:
1595 // This assumes that measure() returns the correct outline, which it does
1596 // not in all possible cases of alignment combinedwith image and symbols.
1597 switch (align() & 0x0f) {
1598 case FL_ALIGN_TOP_LEFT:
1599 window()->damage(FL_DAMAGE_EXPOSE, x(), y()-H, W, H); break;
1600 case FL_ALIGN_TOP:
1601 window()->damage(FL_DAMAGE_EXPOSE, x()+(w()-W)/2, y()-H, W, H); break;
1602 case FL_ALIGN_TOP_RIGHT:
1603 window()->damage(FL_DAMAGE_EXPOSE, x()+w()-W, y()-H, W, H); break;
1604 case FL_ALIGN_LEFT_TOP:
1605 window()->damage(FL_DAMAGE_EXPOSE, x()-W, y(), W, H); break;
1606 case FL_ALIGN_RIGHT_TOP:
1607 window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y(), W, H); break;
1608 case FL_ALIGN_LEFT:
1609 window()->damage(FL_DAMAGE_EXPOSE, x()-W, y()+(h()-H)/2, W, H); break;
1610 case FL_ALIGN_RIGHT:
1611 window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y()+(h()-H)/2, W, H); break;
1612 case FL_ALIGN_LEFT_BOTTOM:
1613 window()->damage(FL_DAMAGE_EXPOSE, x()-W, y()+h()-H, W, H); break;
1614 case FL_ALIGN_RIGHT_BOTTOM:
1615 window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y()+h()-H, W, H); break;
1616 case FL_ALIGN_BOTTOM_LEFT:
1617 window()->damage(FL_DAMAGE_EXPOSE, x(), y()+h(), W, H); break;
1618 case FL_ALIGN_BOTTOM:
1619 window()->damage(FL_DAMAGE_EXPOSE, x()+(w()-W)/2, y()+h(), W, H); break;
1620 case FL_ALIGN_BOTTOM_RIGHT:
1621 window()->damage(FL_DAMAGE_EXPOSE, x()+w()-W, y()+h(), W, H); break;
1622 default:
1623 window()->damage(FL_DAMAGE_ALL); break;
1625 } else {
1626 // The label is inside the widget, so just redraw the widget itself...
1627 damage(FL_DAMAGE_ALL);
1632 void Fl_Widget::damage(fl_damage_t fl) {
1633 if (type() < FL_WINDOW) {
1634 // damage only the rectangle covered by a child widget:
1635 damage(fl, x(), y(), w(), h());
1636 } else {
1637 // damage entire window by deleting the region:
1638 Fl_X* i = Fl_X::i((Fl_Window*)this);
1639 if (!i) return; // window not mapped, so ignore it
1640 if ( i->region )
1642 cairo_region_destroy( i->region );
1643 i->region = 0;
1645 damage_ |= fl;
1646 Fl::damage(FL_DAMAGE_CHILD);
1650 void Fl_Widget::damage(fl_damage_t fl, int X, int Y, int W, int H) {
1651 Fl_Widget* wi = this;
1652 // mark all parent widgets between this and window with FL_DAMAGE_CHILD:
1653 /* 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!
1654 FIXME: check the color for an alpha less than 1! */
1656 bool hit_opaque_widget = false;
1658 while (wi->type() < FL_WINDOW )
1660 wi->damage_ |= fl;
1662 switch ( wi->box() )
1664 case FL_FLAT_BOX:
1665 case FL_BORDER_BOX:
1666 hit_opaque_widget = true;
1667 break;
1668 default:
1669 break;
1672 if ( ! ( wi = wi->parent() ) )
1673 return;
1675 /* we use FL_DAMAGE_EXPOSE now because of alpha blending and FL_NO_BOX and frames... */
1676 // fl = FL_DAMAGE_EXPOSE;
1678 fl = hit_opaque_widget ? FL_DAMAGE_CHILD : FL_DAMAGE_ALL;
1681 /* at this point 'wi' is the window */
1683 Fl_X* i = Fl_X::i((Fl_Window*)wi);
1684 if (!i) return; // window not mapped, so ignore it
1686 // clip the damage to the window and quit if none:
1687 if (X < 0) {W += X; X = 0;}
1688 if (Y < 0) {H += Y; Y = 0;}
1689 if (W > wi->w()-X) W = wi->w()-X;
1690 if (H > wi->h()-Y) H = wi->h()-Y;
1691 if (W <= 0 || H <= 0) return;
1693 if (!X && !Y && W==wi->w() && H==wi->h()) {
1694 // if damage covers entire window delete region:
1695 wi->damage(fl);
1696 return;
1699 if (wi->damage()) {
1700 // if we already have damage we must merge with existing region:
1701 if (i->region) {
1702 #if defined(USE_X11)
1704 cairo_rectangle_int_t rect;
1706 rect.x = X;
1707 rect.y = Y;
1708 rect.width = W;
1709 rect.height = H;
1711 cairo_region_union_rectangle( i->region, &rect );
1712 #elif defined(WIN32)
1713 Fl_Region R = XRectangleRegion(X, Y, W, H);
1714 CombineRgn(i->region, i->region, R, RGN_OR);
1715 XDestroyRegion(R);
1716 #elif defined(__APPLE_QUARTZ__)
1717 CGRect arg = fl_cgrectmake_cocoa(X, Y, W, H);
1718 int j; // don't add a rectangle totally inside the Fl_Region
1719 for(j = 0; j < i->region->count; j++) {
1720 if(CGRectContainsRect(i->region->rects[j], arg)) break;
1722 if( j >= i->region->count) {
1723 i->region->rects = (CGRect*)realloc(i->region->rects, (++(i->region->count)) * sizeof(CGRect));
1724 i->region->rects[i->region->count - 1] = arg;
1726 #else
1727 # error unsupported platform
1728 #endif
1730 wi->damage_ |= fl;
1731 } else {
1734 if ( i->region )
1735 cairo_region_destroy( i->region );
1737 i->region = cairo_region_create();
1738 cairo_rectangle_int_t rect;
1740 rect.x = X;
1741 rect.y = Y;
1742 rect.width = W;
1743 rect.height = H;
1745 cairo_region_union_rectangle( i->region, &rect );
1747 wi->damage_ = fl;
1749 Fl::damage(FL_DAMAGE_CHILD);
1751 void Fl_Window::flush() {
1752 draw();
1755 #ifdef WIN32
1756 # include "Fl_win32.cxx"
1757 //#elif defined(__APPLE__)
1758 #endif
1761 // The following methods allow callbacks to schedule the deletion of
1762 // widgets at "safe" times.
1765 static int num_dwidgets = 0, alloc_dwidgets = 0;
1766 static Fl_Widget **dwidgets = 0;
1769 Schedules a widget for deletion at the next call to the event loop.
1770 Use this method to delete a widget inside a callback function.
1772 To avoid early deletion of widgets, this function should be called
1773 toward the end of a callback and only after any call to the event
1774 loop (Fl::wait(), Fl::flush(), Fl::check(), fl_ask(), etc.).
1776 When deleting groups or windows, you must only delete the group or
1777 window widget and not the individual child widgets.
1779 \since FLTK 1.3 it is not necessary to remove widgets from their parent
1780 groups or windows before calling this, because it will be done in the
1781 widget's destructor, but it is not a failure to do this nevertheless.
1783 \note In FLTK 1.1 you \b must remove widgets from their parent group
1784 (or window) before deleting them.
1786 \see Fl_Widget::~Fl_Widget()
1788 void Fl::delete_widget(Fl_Widget *wi) {
1789 if (!wi) return;
1791 if (num_dwidgets >= alloc_dwidgets) {
1792 Fl_Widget **temp;
1794 temp = new Fl_Widget *[alloc_dwidgets + 10];
1795 if (alloc_dwidgets) {
1796 memcpy(temp, dwidgets, alloc_dwidgets * sizeof(Fl_Widget *));
1797 delete[] dwidgets;
1800 dwidgets = temp;
1801 alloc_dwidgets += 10;
1804 dwidgets[num_dwidgets] = wi;
1805 num_dwidgets ++;
1809 Deletes widgets previously scheduled for deletion.
1811 This is for internal use only. You should never call this directly.
1813 Fl::do_widget_deletion() is called from the FLTK event loop or whenever
1814 you call Fl::wait(). The previously scheduled widgets are deleted in the
1815 same order they were scheduled by calling Fl::delete_widget().
1817 \see Fl::delete_widget(Fl_Widget *wi)
1819 void Fl::do_widget_deletion() {
1820 if (!num_dwidgets) return;
1822 for (int i = 0; i < num_dwidgets; i ++)
1823 delete dwidgets[i];
1825 num_dwidgets = 0;
1828 static Fl_Widget ***widget_watch = 0;
1829 static int num_widget_watch = 0;
1830 static int max_widget_watch = 0;
1833 Adds a widget pointer to the widget watch list.
1835 \note Internal use only, please use class Fl_Widget_Tracker instead.
1837 This can be used, if it is possible that a widget might be deleted during
1838 a callback or similar function. The widget pointer must be added to the
1839 watch list before calling the callback. After the callback the widget
1840 pointer can be queried, if it is NULL. \e If it is NULL, then the widget has been
1841 deleted during the callback and must not be accessed anymore. If the widget
1842 pointer is \e not NULL, then the widget has not been deleted and can be accessed
1843 safely.
1845 After accessing the widget, the widget pointer must be released from the
1846 watch list by calling Fl::release_widget_pointer().
1848 Example for a button that is clicked (from its handle() method):
1849 \code
1850 Fl_Widget *wp = this; // save 'this' in a pointer variable
1851 Fl::watch_widget_pointer(wp); // add the pointer to the watch list
1852 set_changed(); // set the changed flag
1853 do_callback(); // call the callback
1854 if (!wp) { // the widget has been deleted
1856 // DO NOT ACCESS THE DELETED WIDGET !
1858 } else { // the widget still exists
1859 clear_changed(); // reset the changed flag
1862 Fl::release_widget_pointer(wp); // remove the pointer from the watch list
1863 \endcode
1865 This works, because all widgets call Fl::clear_widget_pointer() in their
1866 destructors.
1868 \see Fl::release_widget_pointer()
1869 \see Fl::clear_widget_pointer()
1871 An easier and more convenient method to control widget deletion during
1872 callbacks is to use the class Fl_Widget_Tracker with a local (automatic)
1873 variable.
1875 \see class Fl_Widget_Tracker
1877 void Fl::watch_widget_pointer(Fl_Widget *&w)
1879 Fl_Widget **wp = &w;
1880 int i;
1881 for (i=0; i<num_widget_watch; ++i) {
1882 if (widget_watch[i]==wp) return;
1884 if (num_widget_watch==max_widget_watch) {
1885 max_widget_watch += 8;
1886 widget_watch = (Fl_Widget***)realloc(widget_watch, sizeof(Fl_Widget**)*max_widget_watch);
1888 widget_watch[num_widget_watch++] = wp;
1889 #ifdef DEBUG_WATCH
1890 printf ("\nwatch_widget_pointer: (%d/%d) %8p => %8p\n",
1891 num_widget_watch,num_widget_watch,wp,*wp);
1892 fflush(stdout);
1893 #endif // DEBUG_WATCH
1897 Releases a widget pointer from the watch list.
1899 This is used to remove a widget pointer that has been added to the watch list
1900 with Fl::watch_widget_pointer(), when it is not needed anymore.
1902 \note Internal use only, please use class Fl_Widget_Tracker instead.
1904 \see Fl::watch_widget_pointer()
1906 void Fl::release_widget_pointer(Fl_Widget *&w)
1908 Fl_Widget **wp = &w;
1909 int i,j=0;
1910 for (i=0; i<num_widget_watch; ++i) {
1911 if (widget_watch[i]!=wp) {
1912 if (j<i) widget_watch[j] = widget_watch[i]; // fill gap
1913 j++;
1915 #ifdef DEBUG_WATCH
1916 else { // found widget pointer
1917 printf ("release_widget_pointer: (%d/%d) %8p => %8p\n",
1918 i+1,num_widget_watch,wp,*wp);
1920 #endif //DEBUG_WATCH
1922 num_widget_watch = j;
1923 #ifdef DEBUG_WATCH
1924 printf (" num_widget_watch = %d\n\n",num_widget_watch);
1925 fflush(stdout);
1926 #endif // DEBUG_WATCH
1927 return;
1930 Clears a widget pointer \e in the watch list.
1932 This is called when a widget is destroyed (by its destructor). You should never
1933 call this directly.
1935 \note Internal use only !
1937 This method searches the widget watch list for pointers to the widget and
1938 clears each pointer that points to it. Widget pointers can be added to the
1939 widget watch list by calling Fl::watch_widget_pointer() or by using the
1940 helper class Fl_Widget_Tracker (recommended).
1942 \see Fl::watch_widget_pointer()
1943 \see class Fl_Widget_Tracker
1945 void Fl::clear_widget_pointer(Fl_Widget const *w)
1947 if (w==0L) return;
1948 int i;
1949 for (i=0; i<num_widget_watch; ++i) {
1950 if (widget_watch[i] && *widget_watch[i]==w) {
1951 *widget_watch[i] = 0L;
1958 \brief FLTK library options management.
1960 This function needs to be documented in more detail. It can be used for more
1961 optional settings, such as using a native file chooser instead of the FLTK one
1962 wherever possible, disabling tooltips, disabling visible focus, disabling
1963 FLTK file chooser preview, etc. .
1965 There should be a command line option interface.
1967 There should be an application that manages options system wide, per user, and
1968 per application.
1970 \note As of FLTK 1.3.0, options can be managed within fluid, using the menu
1971 <i>Edit/Global FLTK Settings</i>.
1973 \param opt which option
1974 \return true or false
1975 \see enum Fl::Fl_Option
1976 \see Fl::option(Fl_Option, bool)
1978 \since FLTK 1.3.0
1980 bool Fl::option(Fl_Option opt)
1982 if (!options_read_) {
1983 int tmp;
1984 { // first, read the system wide preferences
1985 Fl_Preferences prefs(Fl_Preferences::SYSTEM, "fltk.org", "fltk");
1986 Fl_Preferences opt_prefs(prefs, "options");
1987 opt_prefs.get("ArrowFocus", tmp, 0); // default: off
1988 options_[OPTION_ARROW_FOCUS] = tmp;
1989 //opt_prefs.get("NativeFilechooser", tmp, 1); // default: on
1990 //options_[OPTION_NATIVE_FILECHOOSER] = tmp;
1991 //opt_prefs.get("FilechooserPreview", tmp, 1); // default: on
1992 //options_[OPTION_FILECHOOSER_PREVIEW] = tmp;
1993 opt_prefs.get("VisibleFocus", tmp, 1); // default: on
1994 options_[OPTION_VISIBLE_FOCUS] = tmp;
1995 opt_prefs.get("DNDText", tmp, 1); // default: on
1996 options_[OPTION_DND_TEXT] = tmp;
1997 opt_prefs.get("ShowTooltips", tmp, 1); // default: on
1998 options_[OPTION_SHOW_TOOLTIPS] = tmp;
2000 { // next, check the user preferences
2001 // override system options only, if the option is set ( >= 0 )
2002 Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "fltk");
2003 Fl_Preferences opt_prefs(prefs, "options");
2004 opt_prefs.get("ArrowFocus", tmp, -1);
2005 if (tmp >= 0) options_[OPTION_ARROW_FOCUS] = tmp;
2006 //opt_prefs.get("NativeFilechooser", tmp, -1);
2007 //if (tmp >= 0) options_[OPTION_NATIVE_FILECHOOSER] = tmp;
2008 //opt_prefs.get("FilechooserPreview", tmp, -1);
2009 //if (tmp >= 0) options_[OPTION_FILECHOOSER_PREVIEW] = tmp;
2010 opt_prefs.get("VisibleFocus", tmp, -1);
2011 if (tmp >= 0) options_[OPTION_VISIBLE_FOCUS] = tmp;
2012 opt_prefs.get("DNDText", tmp, -1);
2013 if (tmp >= 0) options_[OPTION_DND_TEXT] = tmp;
2014 opt_prefs.get("ShowTooltips", tmp, -1);
2015 if (tmp >= 0) options_[OPTION_SHOW_TOOLTIPS] = tmp;
2017 { // now, if the developer has registered this app, we could as for per-application preferences
2019 options_read_ = 1;
2021 if (opt<0 || opt>=OPTION_LAST)
2022 return false;
2023 return (bool)(options_[opt]!=0);
2027 \brief Override an option while the application is running.
2029 This function does not change any system or user settings.
2031 \param opt which option
2032 \param val set to true or false
2033 \see enum Fl::Fl_Option
2034 \see bool Fl::option(Fl_Option)
2036 void Fl::option(Fl_Option opt, bool val)
2038 if (opt<0 || opt>=OPTION_LAST)
2039 return;
2040 if (!options_read_) {
2041 // first read this option, so we don't override our setting later
2042 option(opt);
2044 options_[opt] = val;
2048 // Helper class Fl_Widget_Tracker
2051 The constructor adds a widget to the watch list.
2053 Fl_Widget_Tracker::Fl_Widget_Tracker(Fl_Widget *wi)
2055 wp_ = wi;
2056 Fl::watch_widget_pointer(wp_); // add pointer to watch list
2060 The destructor removes a widget from the watch list.
2062 Fl_Widget_Tracker::~Fl_Widget_Tracker()
2064 Fl::release_widget_pointer(wp_); // remove pointer from watch list
2069 // End of "$Id: Fl.cxx 8723 2011-05-23 16:49:02Z manolo $".