blob: 900ff8f65dff491cfbf8a350800f19768e1ce3d4 [file] [log] [blame]
DRC2ff39b82011-07-28 08:38:59 +00001//
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.
12//
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.
17//
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.
22//
23// Please report all bugs and problems on the following page:
24//
25// http://www.fltk.org/str.php
26//
27
28
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>
34
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
50
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
56
57#include <FL/Fl.H>
58#include <FL/Fl_Window.H>
59#include <FL/Fl_Tooltip.H>
60#include <FL/x.H>
61
62#include <ctype.h>
63#include <stdio.h>
64#include <stdlib.h>
65#include "flstring.h"
66
67#if defined(DEBUG) || defined(DEBUG_WATCH)
68# include <stdio.h>
69#endif // DEBUG || DEBUG_WATCH
70
71#ifdef WIN32
72# include <ole2.h>
73void fl_free_fonts(void);
74HBRUSH fl_brush_action(int action);
75void fl_cleanup_pens(void);
76void fl_release_dc(HWND,HDC);
77void fl_cleanup_dc_list(void);
78#elif defined(__APPLE__)
79extern double fl_mac_flush_and_wait(double time_to_wait, char in_idle);
80#endif // WIN32
81
82//
83// Globals...
84//
85#if defined(__APPLE__) || defined(FL_DOXYGEN)
86const char *Fl_Mac_App_Menu::about = "About ";
87const char *Fl_Mac_App_Menu::print = "Print Front Window";
88const char *Fl_Mac_App_Menu::services = "Services";
89const char *Fl_Mac_App_Menu::hide = "Hide ";
90const char *Fl_Mac_App_Menu::hide_others = "Hide Others";
91const char *Fl_Mac_App_Menu::show = "Show All";
92const char *Fl_Mac_App_Menu::quit = "Quit ";
93#endif // __APPLE__
94#ifndef FL_DOXYGEN
95Fl_Widget *Fl::belowmouse_,
96 *Fl::pushed_,
97 *Fl::focus_,
98 *Fl::selection_owner_;
99int 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;
113
114char *Fl::e_text = (char *)"";
115int Fl::e_length;
116
117Fl_Event_Dispatch Fl::e_dispatch = 0;
118
119unsigned char Fl::options_[] = { 0, 0 };
120unsigned char Fl::options_read_ = 0;
121
122
123Fl_Window *fl_xfocus; // which window X thinks has focus
124Fl_Window *fl_xmousewin;// which window X thinks has FL_ENTER
125Fl_Window *Fl::grab_; // most recent Fl::grab()
126Fl_Window *Fl::modal_; // topmost modal() window
127
128#endif // FL_DOXYGEN
129
130//
131// 'Fl::version()' - Return the API version number...
132//
133
134double
135/**
136 Returns the compiled-in value of the FL_VERSION constant. This
137 is useful for checking the version of a shared library.
138*/
139Fl::version() {
140 return FL_VERSION;
141}
142
143/**
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.
150*/
151int Fl::scrollbar_size() {
152 return scrollbar_size_;
153}
154
155/**
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.
162*/
163void Fl::scrollbar_size(int W) {
164 scrollbar_size_ = W;
165}
166
167
168/** Returns whether or not the mouse event is inside the given rectangle.
169
170 Returns non-zero if the current Fl::event_x() and Fl::event_y()
171 put it inside the given arbitrary bounding box.
172
173 You should always call this rather than doing your own comparison
174 so you are consistent about edge effects.
175
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 *).
178
179 \param[in] xx,yy,ww,hh bounding box
180 \return non-zero, if mouse event is inside
181*/
182int 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);
186}
187
188/** Returns whether or not the mouse event is inside a given child widget.
189
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.
192
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.
198
199 You must not use it with the window itself as the \p o argument
200 in a window's handle() method.
201
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.
206
207 You should always call this rather than doing your own comparison
208 so you are consistent about edge effects.
209
210 \see Fl::event_inside(int, int, int, int)
211
212 \param[in] o child widget to be tested
213 \return non-zero, if mouse event is inside the widget
214*/
215int 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());
219}
220
221//
222//
223// timer support
224//
225
226#ifdef WIN32
227
228// implementation in Fl_win32.cxx
229
230#elif defined(__APPLE__)
231
232// implementation in Fl_mac.cxx
233
234#else
235
236//
237// X11 timers
238//
239
240
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).
246
247struct Timeout {
248 double time;
249 void (*cb)(void*);
250 void* arg;
251 Timeout* next;
252};
253static Timeout* first_timeout, *free_timeout;
254
255#include <sys/time.h>
256
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.
261static char reset_clock = 1;
262
263static 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;
275 }
276}
277
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:
282static double missed_timeout_by;
283
284void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
285 elapse_timeouts();
286 repeat_timeout(time, cb, argp);
287}
288
289void 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;
296 }
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;
305}
306
307/**
308 Returns true if the timeout exists and has not been called yet.
309*/
310int 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;
314}
315
316/**
317 Removes a timeout callback. It is harmless to remove a timeout
318 callback that no longer exists.
319
320 \note This version removes all matching timeouts, not just the first one.
321 This may change in the future.
322*/
323void 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);
332 }
333 }
334}
335
336#endif
337
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().
345
346struct Check {
347 void (*cb)(void*);
348 void* arg;
349 Check* next;
350};
351static Check *first_check, *next_check, *free_check;
352
353/**
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.
358
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.
365
366 Sample code:
367
368 \code
369 bool state_changed; // anything that changes the display turns this on
370
371 void callback(void*) {
372 if (!state_changed) return;
373 state_changed = false;
374 do_expensive_calculation();
375 widget-&gt;redraw();
376 }
377
378 main() {
379 Fl::add_check(callback);
380 return Fl::run();
381 }
382 \endcode
383*/
384void 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;
393}
394
395/**
396 Removes a check callback. It is harmless to remove a check
397 callback that no longer exists.
398*/
399void 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);
409 }
410 }
411}
412
413/**
414 Returns 1 if the check exists and has not been called yet, 0 otherwise.
415*/
416int 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);
423 }
424 }
425 return 0;
426}
427
428static void run_checks()
429{
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);
437 }
438 next_check = first_check;
439 }
440}
441
442#ifndef WIN32
443static char in_idle;
444#endif
445
446////////////////////////////////////////////////////////////////
447// wait/run/check/ready:
448
449void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions
450
451extern int fl_ready(); // in Fl_<platform>.cxx
452extern int fl_wait(double time); // in Fl_<platform>.cxx
453
454/**
455 See int Fl::wait()
456*/
457double Fl::wait(double time_to_wait) {
458 // delete all widgets that were listed during callbacks
459 do_widget_deletion();
460
461#ifdef WIN32
462
463 return fl_wait(time_to_wait);
464
465#elif defined(__APPLE__)
466
467 run_checks();
468 if (idle) {
469 if (!in_idle) {
470 in_idle = 1;
471 idle();
472 in_idle = 0;
473 }
474 // the idle function may turn off idle, we can then wait:
475 if (idle) time_to_wait = 0.0;
476 }
477 return fl_mac_flush_and_wait(time_to_wait, in_idle);
478
479#else
480
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);
496 }
497 } else {
498 reset_clock = 1; // we are not going to check the clock
499 }
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;
507 }
508 // the idle function may turn off idle, we can then wait:
509 if (idle) time_to_wait = 0.0;
510 }
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);
524 }
525#endif
526}
527
528#define FOREVER 1e20
529
530/**
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();.
536*/
537int Fl::run() {
538 while (Fl_X::first) wait(FOREVER);
539 return 0;
540}
541
542#ifdef WIN32
543
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:
546static char oleInitialized = 0;
547
548// This calls the Windows function OleInitialize() exactly once.
549void fl_OleInitialize() {
550 if (!oleInitialized) {
551 OleInitialize(0L);
552 oleInitialized = 1;
553 }
554}
555
556// This calls the Windows function OleUninitialize() only, if
557// OleInitialize has been called before.
558void fl_OleUninitialize() {
559 if (oleInitialized) {
560 OleUninitialize();
561 oleInitialized = 0;
562 }
563}
564
565class Fl_Win32_At_Exit {
566public:
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();
574 }
575};
576static Fl_Win32_At_Exit win32_at_exit;
577#endif
578
579
580
581/**
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.
586
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.
593
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.
596
597 Fl::wait(time) waits a maximum of \e time seconds.
598 <i>It can return much sooner if something happens.</i>
599
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).
604*/
605int 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
609}
610
611/**
612 Same as Fl::wait(0). Calling this during a big calculation
613 will keep the screen up to date and the interface responsive:
614
615 \code
616 while (!calculation_done()) {
617 calculate();
618 Fl::check();
619 if (user_hit_abort_button()) break;
620 }
621 \endcode
622
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).
626*/
627int Fl::check() {
628 wait(0.0);
629 return Fl_X::first != 0; // return true if there is a window
630}
631
632/**
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()).
638
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;
646 }
647 }
648 \endcode
649*/
650int 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;
657 }
658#endif
659 return fl_ready();
660}
661
662////////////////////////////////////////////////////////////////
663// Window list management:
664
665#ifndef FL_DOXYGEN
666Fl_X* Fl_X::first;
667#endif
668
669Fl_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__
679 {
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;
686 }
687 return window->w;
688 }
689 return 0;
690}
691
692/**
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.
696*/
697Fl_Window* Fl::first_window() {
698 Fl_X* i = Fl_X::first;
699 return i ? i->w : 0;
700}
701
702/**
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
706*/
707Fl_Window* Fl::next_window(const Fl_Window* window) {
708 Fl_X* i = Fl_X::i(window)->next;
709 return i ? i->w : 0;
710}
711
712/**
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.
719 */
720void Fl::first_window(Fl_Window* window) {
721 if (!window || !window->shown()) return;
722 fl_find( Fl_X::i(window)->xid );
723}
724
725/**
726 Redraws all widgets.
727*/
728void Fl::redraw() {
729 for (Fl_X* i = Fl_X::first; i; i = i->next) i->w->redraw();
730}
731
732/**
733 Causes all the windows that need it to be redrawn and graphics forced
734 out through the pipes.
735
736 This is what wait() does before looking for events.
737
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.
742*/
743void 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()) {i->flush(); wi->clear_damage();}
751 // destroy damage regions for windows that don't use them:
752 if (i->region) {XDestroyRegion(i->region); i->region = 0;}
753 }
754 }
755#if defined(USE_X11)
756 if (fl_display) XFlush(fl_display);
757#elif defined(WIN32)
758 GdiFlush();
759#elif defined (__APPLE_QUARTZ__)
760 if (fl_gc)
761 CGContextFlush(fl_gc);
762#else
763# error unsupported platform
764#endif
765}
766
767
768////////////////////////////////////////////////////////////////
769// Event handlers:
770
771
772struct handler_link {
773 int (*handle)(int);
774 handler_link *next;
775};
776
777
778static handler_link *handlers = 0;
779
780
781/**
782 Install a function to parse unrecognized events. If FLTK cannot
783 figure out what to do with an event, it calls each of these functions
784 (most recent first) until one of them returns non-zero. If none of
785 them returns non-zero then the event is ignored. Events that cause
786 this to be called are:
787
788 - FL_SHORTCUT events that are not recognized by any widget.
789 This lets you provide global shortcut keys.
790 - System events that FLTK does not recognize. See fl_xevent.
791 - \e Some other events when the widget FLTK selected returns
792 zero from its handle() method. Exactly which ones may change
793 in future versions, however.
794
795 \see Fl::remove_handler(Fl_Event_Handler)
796 \see Fl::event_dispatch(Fl_Event_Dispatch d)
797 \see Fl::handle(int, Fl_Window*)
798*/
799void Fl::add_handler(Fl_Event_Handler ha) {
800 handler_link *l = new handler_link;
801 l->handle = ha;
802 l->next = handlers;
803 handlers = l;
804}
805
806
807/**
808 Removes a previously added event handler.
809 \see Fl::handle(int, Fl_Window*)
810*/
811void Fl::remove_handler(Fl_Event_Handler ha) {
812 handler_link *l, *p;
813
814 // Search for the handler in the list...
815 for (l = handlers, p = 0; l && l->handle != ha; p = l, l = l->next);
816
817 if (l) {
818 // Found it, so remove it from the list...
819 if (p) p->next = l->next;
820 else handlers = l->next;
821
822 // And free the record...
823 delete l;
824 }
825}
826
827int (*fl_local_grab)(int); // used by fl_dnd.cxx
828
829static int send_handlers(int e) {
830 for (const handler_link *hl = handlers; hl; hl = hl->next)
831 if (hl->handle(e)) return 1;
832 return 0;
833}
834
835////////////////////////////////////////////////////////////////
836
837Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
838
839/**
840 Sets the widget that will receive FL_KEYBOARD events.
841
842 If you change Fl::focus(), the previous widget and all
843 parents (that don't contain the new widget) are sent FL_UNFOCUS
844 events. Changing the focus does \e not send FL_FOCUS to
845 this or any widget, because sending FL_FOCUS is supposed to
846 \e test if the widget wants the focus (by it returning non-zero from
847 handle()).
848
849 \see Fl_Widget::take_focus()
850*/
851void Fl::focus(Fl_Widget *o) {
852 if (o && !o->visible_focus()) return;
853 if (grab()) return; // don't do anything while grab is on
854 Fl_Widget *p = focus_;
855 if (o != p) {
856 Fl::compose_reset();
857 focus_ = o;
858 // make sure that fl_xfocus is set to the top level window
859 // of this widget, or fl_fix_focus will clear our focus again
860 if (o) {
861 Fl_Window *win = 0, *w1 = o->as_window();
862 if (!w1) w1 = o->window();
863 while (w1) { win=w1; w1=win->window(); }
864 if (win) {
865#ifdef __APPLE__
866 if (fl_xfocus != win) {
867 Fl_X *x = Fl_X::i(win);
868 if (x) x->set_key_window();
869 }
870#endif
871 fl_xfocus = win;
872 }
873 }
874 // take focus from the old focused window
875 fl_oldfocus = 0;
876 int old_event = e_number;
877 e_number = FL_UNFOCUS;
878 for (; p; p = p->parent()) {
879 p->handle(FL_UNFOCUS);
880 fl_oldfocus = p;
881 }
882 e_number = old_event;
883 }
884}
885
886static char dnd_flag = 0; // make 'belowmouse' send DND_LEAVE instead of LEAVE
887
888/**
889 Sets the widget that is below the mouse. This is for
890 highlighting buttons. It is not used to send FL_PUSH or
891 FL_MOVE directly, for several obscure reasons, but those events
892 typically go to this widget. This is also the first widget tried for
893 FL_SHORTCUT events.
894
895 If you change the belowmouse widget, the previous one and all
896 parents (that don't contain the new widget) are sent FL_LEAVE
897 events. Changing this does \e not send FL_ENTER to this
898 or any widget, because sending FL_ENTER is supposed to \e test
899 if the widget wants the mouse (by it returning non-zero from
900 handle()).
901*/
902void Fl::belowmouse(Fl_Widget *o) {
903 if (grab()) return; // don't do anything while grab is on
904 Fl_Widget *p = belowmouse_;
905 if (o != p) {
906 belowmouse_ = o;
907 int old_event = e_number;
908 e_number = dnd_flag ? FL_DND_LEAVE : FL_LEAVE;
909 for (; p && !p->contains(o); p = p->parent()) {
910 p->handle(e_number);
911 }
912 e_number = old_event;
913 }
914}
915
916/**
917 Sets the widget that is being pushed. FL_DRAG or
918 FL_RELEASE (and any more FL_PUSH) events will be sent to
919 this widget.
920
921 If you change the pushed widget, the previous one and all parents
922 (that don't contain the new widget) are sent FL_RELEASE
923 events. Changing this does \e not send FL_PUSH to this
924 or any widget, because sending FL_PUSH is supposed to \e test
925 if the widget wants the mouse (by it returning non-zero from
926 handle()).
927*/
928 void Fl::pushed(Fl_Widget *o) {
929 pushed_ = o;
930}
931
932static void nothing(Fl_Widget *) {}
933void (*Fl_Tooltip::enter)(Fl_Widget *) = nothing;
934void (*Fl_Tooltip::exit)(Fl_Widget *) = nothing;
935
936// Update modal(), focus() and other state according to system state,
937// and send FL_ENTER, FL_LEAVE, FL_FOCUS, and/or FL_UNFOCUS events.
938// This is the only function that produces these events in response
939// to system activity.
940// This is called whenever a window is added or hidden, and whenever
941// X says the focus or mouse window have changed.
942
943void fl_fix_focus() {
944#ifdef DEBUG
945 puts("fl_fix_focus();");
946#endif // DEBUG
947
948 if (Fl::grab()) return; // don't do anything while grab is on.
949
950 // set focus based on Fl::modal() and fl_xfocus
951 Fl_Widget* w = fl_xfocus;
952 if (w) {
953 int saved = Fl::e_keysym;
954 if (Fl::e_keysym < (FL_Button + FL_LEFT_MOUSE) ||
955 Fl::e_keysym > (FL_Button + FL_RIGHT_MOUSE))
956 Fl::e_keysym = 0; // make sure widgets don't think a keystroke moved focus
957 while (w->parent()) w = w->parent();
958 if (Fl::modal()) w = Fl::modal();
959 if (!w->contains(Fl::focus()))
960 if (!w->take_focus()) Fl::focus(w);
961 Fl::e_keysym = saved;
962 } else
963 Fl::focus(0);
964
965// MRS: Originally we checked the button state, but a user reported that it
966// broke click-to-focus in FLWM?!?
967// if (!(Fl::event_state() & 0x7f00000 /*FL_BUTTONS*/)) {
968 if (!Fl::pushed()) {
969 // set belowmouse based on Fl::modal() and fl_xmousewin:
970 w = fl_xmousewin;
971 if (w) {
972 if (Fl::modal()) w = Fl::modal();
973 if (!w->contains(Fl::belowmouse())) {
974 int old_event = Fl::e_number;
975 w->handle(Fl::e_number = FL_ENTER);
976 Fl::e_number = old_event;
977 if (!w->contains(Fl::belowmouse())) Fl::belowmouse(w);
978 } else {
979 // send a FL_MOVE event so the enter/leave state is up to date
980 Fl::e_x = Fl::e_x_root-fl_xmousewin->x();
981 Fl::e_y = Fl::e_y_root-fl_xmousewin->y();
982 int old_event = Fl::e_number;
983 w->handle(Fl::e_number = FL_MOVE);
984 Fl::e_number = old_event;
985 }
986 } else {
987 Fl::belowmouse(0);
988 Fl_Tooltip::enter(0);
989 }
990 }
991}
992
993#if !(defined(WIN32) || defined(__APPLE__))
994extern Fl_Widget *fl_selection_requestor; // from Fl_x.cxx
995#endif
996
997// This function is called by ~Fl_Widget() and by Fl_Widget::deactivate()
998// and by Fl_Widget::hide(). It indicates that the widget does not want
999// to receive any more events, and also removes all global variables that
1000// point at the widget.
1001// I changed this from the 1.0.1 behavior, the older version could send
1002// FL_LEAVE or FL_UNFOCUS events to the widget. This appears to not be
1003// desirable behavior and caused flwm to crash.
1004
1005void fl_throw_focus(Fl_Widget *o) {
1006#ifdef DEBUG
1007 printf("fl_throw_focus(o=%p)\n", o);
1008#endif // DEBUG
1009
1010 if (o->contains(Fl::pushed())) Fl::pushed_ = 0;
1011#if !(defined(WIN32) || defined(__APPLE__))
1012 if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0;
1013#endif
1014 if (o->contains(Fl::belowmouse())) Fl::belowmouse_ = 0;
1015 if (o->contains(Fl::focus())) Fl::focus_ = 0;
1016 if (o == fl_xfocus) fl_xfocus = 0;
1017 if (o == Fl_Tooltip::current()) Fl_Tooltip::current(0);
1018 if (o == fl_xmousewin) fl_xmousewin = 0;
1019 Fl_Tooltip::exit(o);
1020 fl_fix_focus();
1021}
1022
1023////////////////////////////////////////////////////////////////
1024
1025// Call to->handle(), but first replace the mouse x/y with the correct
1026// values to account for nested windows. 'window' is the outermost
1027// window the event was posted to by the system:
1028static int send(int event, Fl_Widget* to, Fl_Window* window) {
1029 int dx, dy;
1030 int old_event = Fl::e_number;
1031 if (window) {
1032 dx = window->x();
1033 dy = window->y();
1034 } else {
1035 dx = dy = 0;
1036 }
1037 for (const Fl_Widget* w = to; w; w = w->parent())
1038 if (w->type()>=FL_WINDOW) {dx -= w->x(); dy -= w->y();}
1039 int save_x = Fl::e_x; Fl::e_x += dx;
1040 int save_y = Fl::e_y; Fl::e_y += dy;
1041 int ret = to->handle(Fl::e_number = event);
1042 Fl::e_number = old_event;
1043 Fl::e_y = save_y;
1044 Fl::e_x = save_x;
1045 return ret;
1046}
1047
1048
1049/**
1050 \brief Set a new event dispatch function.
1051
1052 The event dispatch function is called after native events are converted to
1053 FLTK events, but before they are handled by FLTK. If the dispatch function
1054 Fl_Event_Dispatch \p d is set, it is up to the dispatch function to call
1055 Fl::handle_(int, Fl_Window*) or to ignore the event.
1056
1057 The dispatch function itself must return 0 if it ignored the event,
1058 or non-zero if it used the event. If you call Fl::handle_(), then
1059 this will return the correct value.
1060
1061 The event dispatch can be used to handle exceptions in FLTK events and
1062 callbacks before they reach the native event handler:
1063
1064 \code
1065 int myHandler(int e, Fl_Window *w) {
1066 try {
1067 return Fl::handle_(e, w);
1068 } catch () {
1069 ...
1070 }
1071 }
1072
1073 main() {
1074 Fl::event_dispatch(myHandler);
1075 ...
1076 Fl::run();
1077 }
1078 \endcode
1079
1080 \param d new dispatch function, or NULL
1081 \see Fl::add_handler(Fl_Event_Handler)
1082 \see Fl::handle(int, Fl_Window*)
1083 \see Fl::handle_(int, Fl_Window*)
1084 */
1085void Fl::event_dispatch(Fl_Event_Dispatch d)
1086{
1087 e_dispatch = d;
1088}
1089
1090
1091/**
1092 \brief Return the current event dispatch function.
1093 */
1094Fl_Event_Dispatch Fl::event_dispatch()
1095{
1096 return e_dispatch;
1097}
1098
1099
1100/**
1101 \brief Handle events from the window system.
1102
1103 This is called from the native event dispatch after native events have been
1104 converted to FLTK notation. This function calls Fl::handle_(int, Fl_Window*)
1105 unless the user sets a dispatch function. If a user dispatch function is set,
1106 the user must make sure that Fl::handle_() is called, or the event will be
1107 ignored.
1108
1109 \param e the event type (Fl::event_number() is not yet set)
1110 \param window the window that caused this event
1111 \return 0 if the event was not handled
1112
1113 \see Fl::add_handler(Fl_Event_Handler)
1114 \see Fl::event_dispatch(Fl_Event_Dispatch)
1115 */
1116int Fl::handle(int e, Fl_Window* window)
1117{
1118 if (e_dispatch) {
1119 return e_dispatch(e, window);
1120 } else {
1121 return handle_(e, window);
1122 }
1123}
1124
1125
1126/**
1127 \brief Handle events from the window system.
1128
1129 This function is called from the native event dispatch, unless the user sets
1130 another dispatch function. In that case, the user dispatch function must
1131 decide when to call Fl::handle_(int, Fl_Window*)
1132
1133 \param e the event type (Fl::event_number() is not yet set)
1134 \param window the window that caused this event
1135 \return 0 if the event was not handled
1136
1137 \see Fl::event_dispatch(Fl_Event_Dispatch)
1138 */
1139int Fl::handle_(int e, Fl_Window* window)
1140{
1141 e_number = e;
1142 if (fl_local_grab) return fl_local_grab(e);
1143
1144 Fl_Widget* wi = window;
1145
1146 switch (e) {
1147
1148 case FL_CLOSE:
1149 if ( grab() || (modal() && window != modal()) ) return 0;
1150 wi->do_callback();
1151 return 1;
1152
1153 case FL_SHOW:
1154 wi->Fl_Widget::show(); // this calls Fl_Widget::show(), not Fl_Window::show()
1155 return 1;
1156
1157 case FL_HIDE:
1158 wi->Fl_Widget::hide(); // this calls Fl_Widget::hide(), not Fl_Window::hide()
1159 return 1;
1160
1161 case FL_PUSH:
1162#ifdef DEBUG
1163 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1164#endif // DEBUG
1165
1166 if (grab()) wi = grab();
1167 else if (modal() && wi != modal()) return 0;
1168 pushed_ = wi;
1169 Fl_Tooltip::current(wi);
1170 if (send(e, wi, window)) return 1;
1171 // raise windows that are clicked on:
1172 window->show();
1173 return 1;
1174
1175 case FL_DND_ENTER:
1176 case FL_DND_DRAG:
1177 dnd_flag = 1;
1178 break;
1179
1180 case FL_DND_LEAVE:
1181 dnd_flag = 1;
1182 belowmouse(0);
1183 dnd_flag = 0;
1184 return 1;
1185
1186 case FL_DND_RELEASE:
1187 wi = belowmouse();
1188 break;
1189
1190 case FL_MOVE:
1191 case FL_DRAG:
1192 fl_xmousewin = window; // this should already be set, but just in case.
1193 if (pushed()) {
1194 wi = pushed();
1195 if (grab()) wi = grab();
1196 e_number = e = FL_DRAG;
1197 break;
1198 }
1199 if (modal() && wi != modal()) wi = 0;
1200 if (grab()) wi = grab();
1201 { int ret;
1202 Fl_Widget* pbm = belowmouse();
1203#ifdef __APPLE__
1204 if (fl_mac_os_version < 100500) {
1205 // before 10.5, mouse moved events aren't sent to borderless windows such as tooltips
1206 Fl_Window *tooltip = Fl_Tooltip::current_window();
1207 int inside = 0;
1208 if (tooltip && tooltip->shown() ) { // check if a tooltip window is currently opened
1209 // check if mouse is inside the tooltip
1210 inside = (Fl::event_x_root() >= tooltip->x() && Fl::event_x_root() < tooltip->x() + tooltip->w() &&
1211 Fl::event_y_root() >= tooltip->y() && Fl::event_y_root() < tooltip->y() + tooltip->h() );
1212 }
1213 // if inside, send event to tooltip window instead of background window
1214 if (inside) ret = send(e, tooltip, window);
1215 else ret = (wi && send(e, wi, window));
1216 } else
1217#endif
1218 ret = (wi && send(e, wi, window));
1219 if (pbm != belowmouse()) {
1220#ifdef DEBUG
1221 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1222#endif // DEBUG
1223 Fl_Tooltip::enter(belowmouse());
1224 }
1225 return ret;}
1226
1227 case FL_RELEASE: {
1228// printf("FL_RELEASE: window=%p, pushed() = %p, grab() = %p, modal() = %p\n",
1229// window, pushed(), grab(), modal());
1230
1231 if (grab()) {
1232 wi = grab();
1233 pushed_ = 0; // must be zero before callback is done!
1234 } else if (pushed()) {
1235 wi = pushed();
1236 pushed_ = 0; // must be zero before callback is done!
1237 } else if (modal() && wi != modal()) return 0;
1238 int r = send(e, wi, window);
1239 fl_fix_focus();
1240 return r;}
1241
1242 case FL_UNFOCUS:
1243 window = 0;
1244 case FL_FOCUS:
1245 fl_xfocus = window;
1246 fl_fix_focus();
1247 return 1;
1248
1249 case FL_KEYUP:
1250 // Send the key-up to the current focus widget. This is not
1251 // always the same widget that received the corresponding
1252 // FL_KEYBOARD event because focus may have changed.
1253 // Sending the KEYUP to the right KEYDOWN is possible, but
1254 // would require that we track the KEYDOWN for every possible
1255 // key stroke (users may hold down multiple keys!) and then
1256 // make sure that the widget still exists before sending
1257 // a KEYUP there. I believe that the current solution is
1258 // "close enough".
1259 for (wi = grab() ? grab() : focus(); wi; wi = wi->parent())
1260 if (send(FL_KEYUP, wi, window)) return 1;
1261 return 0;
1262
1263 case FL_KEYBOARD:
1264#ifdef DEBUG
1265 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1266#endif // DEBUG
1267
1268 Fl_Tooltip::enter((Fl_Widget*)0);
1269
1270 fl_xfocus = window; // this should not happen! But maybe it does:
1271
1272 // Try it as keystroke, sending it to focus and all parents:
1273 for (wi = grab() ? grab() : focus(); wi; wi = wi->parent())
1274 if (send(FL_KEYBOARD, wi, window)) return 1;
1275
1276 // recursive call to try shortcut:
1277 if (handle(FL_SHORTCUT, window)) return 1;
1278
1279 // and then try a shortcut with the case of the text swapped, by
1280 // changing the text and falling through to FL_SHORTCUT case:
1281 {unsigned char* c = (unsigned char*)event_text(); // cast away const
1282 if (!isalpha(*c)) return 0;
1283 *c = isupper(*c) ? tolower(*c) : toupper(*c);}
1284 e_number = e = FL_SHORTCUT;
1285
1286 case FL_SHORTCUT:
1287 if (grab()) {wi = grab(); break;} // send it to grab window
1288
1289 // Try it as shortcut, sending to mouse widget and all parents:
1290 wi = belowmouse();
1291 if (!wi) {
1292 wi = modal();
1293 if (!wi) wi = window;
1294 } else if (wi->window() != first_window()) {
1295 if (send(FL_SHORTCUT, first_window(), first_window())) return 1;
1296 }
1297
1298 for (; wi; wi = wi->parent()) {
1299 if (send(FL_SHORTCUT, wi, wi->window())) return 1;
1300 }
1301
1302 // try using add_handle() functions:
1303 if (send_handlers(FL_SHORTCUT)) return 1;
1304
1305 // make Escape key close windows:
1306 if (event_key()==FL_Escape) {
1307 wi = modal(); if (!wi) wi = window;
1308 wi->do_callback();
1309 return 1;
1310 }
1311
1312 return 0;
1313
1314 case FL_ENTER:
1315#ifdef DEBUG
1316 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1317#endif // DEBUG
1318
1319 fl_xmousewin = window;
1320 fl_fix_focus();
1321 Fl_Tooltip::enter(belowmouse());
1322 return 1;
1323
1324 case FL_LEAVE:
1325#ifdef DEBUG
1326 printf("Fl::handle(e=%d, window=%p);\n", e, window);
1327#endif // DEBUG
1328
1329 if (!pushed_) {
1330 belowmouse(0);
1331 Fl_Tooltip::enter(0);
1332 }
1333 if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();}
1334 return 1;
1335
1336 case FL_MOUSEWHEEL:
1337 fl_xfocus = window; // this should not happen! But maybe it does:
1338
1339 // Try sending it to the "grab" first
1340 if (grab() && grab()!=modal() && grab()!=window) {
1341 if (send(FL_MOUSEWHEEL, grab(), window)) return 1;
1342 }
1343 // Now try sending it to the "modal" window
1344 if (modal()) {
1345 send(FL_MOUSEWHEEL, modal(), window);
1346 return 1;
1347 }
1348 // Finally try sending it to the window, the event occured in
1349 if (send(FL_MOUSEWHEEL, window, window)) return 1;
1350 default:
1351 break;
1352 }
1353 if (wi && send(e, wi, window)) {
1354 dnd_flag = 0;
1355 return 1;
1356 }
1357 dnd_flag = 0;
1358 return send_handlers(e);
1359}
1360
1361////////////////////////////////////////////////////////////////
1362// hide() destroys the X window, it does not do unmap!
1363
1364#if !defined(WIN32) && USE_XFT
1365extern void fl_destroy_xft_draw(Window);
1366#endif
1367
1368void Fl_Window::hide() {
1369 clear_visible();
1370
1371 if (!shown()) return;
1372
1373 // remove from the list of windows:
1374 Fl_X* ip = i;
1375 Fl_X** pp = &Fl_X::first;
1376 for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return;
1377 *pp = ip->next;
1378#ifdef __APPLE__
1379 ip->unlink();
1380 // MacOS X manages a single pointer per application. Make sure that hiding
1381 // a toplevel window will not leave us with some random pointer shape, or
1382 // worst case, an invisible pointer
1383 if (!parent()) cursor(FL_CURSOR_DEFAULT);
1384#endif
1385 i = 0;
1386
1387 // recursively remove any subwindows:
1388 for (Fl_X *wi = Fl_X::first; wi;) {
1389 Fl_Window* W = wi->w;
1390 if (W->window() == this) {
1391 W->hide();
1392 W->set_visible();
1393 wi = Fl_X::first;
1394 } else wi = wi->next;
1395 }
1396
1397 if (this == Fl::modal_) { // we are closing the modal window, find next one:
1398 Fl_Window* W;
1399 for (W = Fl::first_window(); W; W = Fl::next_window(W))
1400 if (W->modal()) break;
1401 Fl::modal_ = W;
1402 }
1403
1404 // Make sure no events are sent to this window:
1405 fl_throw_focus(this);
1406 handle(FL_HIDE);
1407
1408#if defined(WIN32)
1409 // this little trick keeps the current clipboard alive, even if we are about
1410 // to destroy the window that owns the selection.
1411 if (GetClipboardOwner()==ip->xid) {
1412 Fl_Window *w1 = Fl::first_window();
1413 if (w1 && OpenClipboard(fl_xid(w1))) {
1414 EmptyClipboard();
1415 SetClipboardData(CF_TEXT, NULL);
1416 CloseClipboard();
1417 }
1418 }
1419 // Send a message to myself so that I'll get out of the event loop...
1420 PostMessage(ip->xid, WM_APP, 0, 0);
1421 if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc);
1422 if (ip->xid == fl_window && fl_gc) {
1423 fl_release_dc(fl_window, fl_gc);
1424 fl_window = (HWND)-1;
1425 fl_gc = 0;
1426# ifdef FLTK_USE_CAIRO
1427 if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0);
1428# endif
1429 }
1430#elif defined(__APPLE_QUARTZ__)
1431 Fl_X::q_release_context(ip);
1432 if ( ip->xid == fl_window && !parent() )
1433 fl_window = 0;
1434#endif
1435
1436 if (ip->region) XDestroyRegion(ip->region);
1437
1438#if defined(USE_X11)
1439# if USE_XFT
1440 fl_destroy_xft_draw(ip->xid);
1441# endif
1442 // this test makes sure ip->xid has not been destroyed already
1443 if (ip->xid) XDestroyWindow(fl_display, ip->xid);
1444#elif defined(WIN32)
1445 // this little trickery seems to avoid the popup window stacking problem
1446 HWND p = GetForegroundWindow();
1447 if (p==GetParent(ip->xid)) {
1448 ShowWindow(ip->xid, SW_HIDE);
1449 ShowWindow(p, SW_SHOWNA);
1450 }
1451 XDestroyWindow(fl_display, ip->xid);
1452#elif defined(__APPLE_QUARTZ__)
1453 ip->destroy();
1454#else
1455# error unsupported platform
1456#endif
1457
1458#ifdef WIN32
1459 // Try to stop the annoying "raise another program" behavior
1460 if (non_modal() && Fl::first_window() && Fl::first_window()->shown())
1461 Fl::first_window()->show();
1462#endif
1463 delete ip;
1464}
1465
1466Fl_Window::~Fl_Window() {
1467 hide();
1468 if (xclass_) {
1469 free(xclass_);
1470 }
1471}
1472
1473// FL_SHOW and FL_HIDE are called whenever the visibility of this widget
1474// or any parent changes. We must correctly map/unmap the system's window.
1475
1476// For top-level windows it is assumed the window has already been
1477// mapped or unmapped!!! This is because this should only happen when
1478// Fl_Window::show() or Fl_Window::hide() is called, or in response to
1479// iconize/deiconize events from the system.
1480
1481int Fl_Window::handle(int ev)
1482{
1483 if (parent()) {
1484 switch (ev) {
1485 case FL_SHOW:
1486 if (!shown()) show();
1487 else {
1488#if defined(USE_X11) || defined(WIN32)
1489 XMapWindow(fl_display, fl_xid(this)); // extra map calls are harmless
1490#elif defined(__APPLE_QUARTZ__)
1491 i->map();
1492#else
1493# error unsupported platform
1494#endif // __APPLE__
1495 }
1496 break;
1497 case FL_HIDE:
1498 if (shown()) {
1499 // Find what really turned invisible, if it was a parent window
1500 // we do nothing. We need to avoid unnecessary unmap calls
1501 // because they cause the display to blink when the parent is
1502 // remapped. However if this or any intermediate non-window
1503 // widget has really had hide() called directly on it, we must
1504 // unmap because when the parent window is remapped we don't
1505 // want to reappear.
1506 if (visible()) {
1507 Fl_Widget* p = parent(); for (;p->visible();p = p->parent()) {}
1508 if (p->type() >= FL_WINDOW) break; // don't do the unmap
1509 }
1510#if defined(USE_X11) || defined(WIN32)
1511 XUnmapWindow(fl_display, fl_xid(this));
1512#elif defined(__APPLE_QUARTZ__)
1513 i->unmap();
1514#else
1515# error platform unsupported
1516#endif
1517 }
1518 break;
1519 }
1520// } else if (ev == FL_FOCUS || ev == FL_UNFOCUS) {
1521// Fl_Tooltip::exit(Fl_Tooltip::current());
1522 }
1523
1524 return Fl_Group::handle(ev);
1525}
1526
1527////////////////////////////////////////////////////////////////
1528// Back compatibility cut & paste functions for fltk 1.1 only:
1529
1530/** Back-compatibility only: The single-argument call can be used to
1531 move the selection to another widget or to set the owner to
1532 NULL, without changing the actual text of the
1533 selection. FL_SELECTIONCLEAR is sent to the previous
1534 selection owner, if any.
1535
1536 <i>Copying the buffer every time the selection is changed is
1537 obviously wasteful, especially for large selections. An interface will
1538 probably be added in a future version to allow the selection to be made
1539 by a callback function. The current interface will be emulated on top
1540 of this.</i>
1541*/
1542void Fl::selection_owner(Fl_Widget *owner) {selection_owner_ = owner;}
1543
1544/**
1545 Changes the current selection. The block of text is
1546 copied to an internal buffer by FLTK (be careful if doing this in
1547 response to an FL_PASTE as this \e may be the same buffer
1548 returned by event_text()). The selection_owner()
1549 widget is set to the passed owner.
1550*/
1551void Fl::selection(Fl_Widget &owner, const char* text, int len) {
1552 selection_owner_ = &owner;
1553 Fl::copy(text, len, 0);
1554}
1555
1556/** Backward compatibility only.
1557 This calls Fl::paste(receiver, 0);
1558 \see Fl::paste(Fl_Widget &receiver, int clipboard)
1559*/
1560void Fl::paste(Fl_Widget &receiver) {
1561 Fl::paste(receiver, 0);
1562}
1563
1564////////////////////////////////////////////////////////////////
1565
1566#include <FL/fl_draw.H>
1567
1568void Fl_Widget::redraw() {
1569 damage(FL_DAMAGE_ALL);
1570}
1571
1572void Fl_Widget::redraw_label() {
1573 if (window()) {
1574 if (box() == FL_NO_BOX) {
1575 // Widgets with the FL_NO_BOX boxtype need a parent to
1576 // redraw, since it is responsible for redrawing the
1577 // background...
1578 int X = x() > 0 ? x() - 1 : 0;
1579 int Y = y() > 0 ? y() - 1 : 0;
1580 window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2);
1581 }
1582
1583 if (align() && !(align() & FL_ALIGN_INSIDE) && window()->shown()) {
1584 // If the label is not inside the widget, compute the location of
1585 // the label and redraw the window within that bounding box...
1586 int W = 0, H = 0;
1587 label_.measure(W, H);
1588 W += 5; // Add a little to the size of the label to cover overflow
1589 H += 5;
1590
1591 // FIXME:
1592 // This assumes that measure() returns the correct outline, which it does
1593 // not in all possible cases of alignment combinedwith image and symbols.
1594 switch (align() & 0x0f) {
1595 case FL_ALIGN_TOP_LEFT:
1596 window()->damage(FL_DAMAGE_EXPOSE, x(), y()-H, W, H); break;
1597 case FL_ALIGN_TOP:
1598 window()->damage(FL_DAMAGE_EXPOSE, x()+(w()-W)/2, y()-H, W, H); break;
1599 case FL_ALIGN_TOP_RIGHT:
1600 window()->damage(FL_DAMAGE_EXPOSE, x()+w()-W, y()-H, W, H); break;
1601 case FL_ALIGN_LEFT_TOP:
1602 window()->damage(FL_DAMAGE_EXPOSE, x()-W, y(), W, H); break;
1603 case FL_ALIGN_RIGHT_TOP:
1604 window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y(), W, H); break;
1605 case FL_ALIGN_LEFT:
1606 window()->damage(FL_DAMAGE_EXPOSE, x()-W, y()+(h()-H)/2, W, H); break;
1607 case FL_ALIGN_RIGHT:
1608 window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y()+(h()-H)/2, W, H); break;
1609 case FL_ALIGN_LEFT_BOTTOM:
1610 window()->damage(FL_DAMAGE_EXPOSE, x()-W, y()+h()-H, W, H); break;
1611 case FL_ALIGN_RIGHT_BOTTOM:
1612 window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y()+h()-H, W, H); break;
1613 case FL_ALIGN_BOTTOM_LEFT:
1614 window()->damage(FL_DAMAGE_EXPOSE, x(), y()+h(), W, H); break;
1615 case FL_ALIGN_BOTTOM:
1616 window()->damage(FL_DAMAGE_EXPOSE, x()+(w()-W)/2, y()+h(), W, H); break;
1617 case FL_ALIGN_BOTTOM_RIGHT:
1618 window()->damage(FL_DAMAGE_EXPOSE, x()+w()-W, y()+h(), W, H); break;
1619 default:
1620 window()->damage(FL_DAMAGE_ALL); break;
1621 }
1622 } else {
1623 // The label is inside the widget, so just redraw the widget itself...
1624 damage(FL_DAMAGE_ALL);
1625 }
1626 }
1627}
1628
1629void Fl_Widget::damage(uchar fl) {
1630 if (type() < FL_WINDOW) {
1631 // damage only the rectangle covered by a child widget:
1632 damage(fl, x(), y(), w(), h());
1633 } else {
1634 // damage entire window by deleting the region:
1635 Fl_X* i = Fl_X::i((Fl_Window*)this);
1636 if (!i) return; // window not mapped, so ignore it
1637 if (i->region) {XDestroyRegion(i->region); i->region = 0;}
1638 damage_ |= fl;
1639 Fl::damage(FL_DAMAGE_CHILD);
1640 }
1641}
1642
1643void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) {
1644 Fl_Widget* wi = this;
1645 // mark all parent widgets between this and window with FL_DAMAGE_CHILD:
1646 while (wi->type() < FL_WINDOW) {
1647 wi->damage_ |= fl;
1648 wi = wi->parent();
1649 if (!wi) return;
1650 fl = FL_DAMAGE_CHILD;
1651 }
1652 Fl_X* i = Fl_X::i((Fl_Window*)wi);
1653 if (!i) return; // window not mapped, so ignore it
1654
1655 // clip the damage to the window and quit if none:
1656 if (X < 0) {W += X; X = 0;}
1657 if (Y < 0) {H += Y; Y = 0;}
1658 if (W > wi->w()-X) W = wi->w()-X;
1659 if (H > wi->h()-Y) H = wi->h()-Y;
1660 if (W <= 0 || H <= 0) return;
1661
1662 if (!X && !Y && W==wi->w() && H==wi->h()) {
1663 // if damage covers entire window delete region:
1664 wi->damage(fl);
1665 return;
1666 }
1667
1668 if (wi->damage()) {
1669 // if we already have damage we must merge with existing region:
1670 if (i->region) {
1671#if defined(USE_X11)
1672 XRectangle R;
1673 R.x = X; R.y = Y; R.width = W; R.height = H;
1674 XUnionRectWithRegion(&R, i->region, i->region);
1675#elif defined(WIN32)
1676 Fl_Region R = XRectangleRegion(X, Y, W, H);
1677 CombineRgn(i->region, i->region, R, RGN_OR);
1678 XDestroyRegion(R);
1679#elif defined(__APPLE_QUARTZ__)
1680 CGRect arg = fl_cgrectmake_cocoa(X, Y, W, H);
1681 int j; // don't add a rectangle totally inside the Fl_Region
1682 for(j = 0; j < i->region->count; j++) {
1683 if(CGRectContainsRect(i->region->rects[j], arg)) break;
1684 }
1685 if( j >= i->region->count) {
1686 i->region->rects = (CGRect*)realloc(i->region->rects, (++(i->region->count)) * sizeof(CGRect));
1687 i->region->rects[i->region->count - 1] = arg;
1688 }
1689#else
1690# error unsupported platform
1691#endif
1692 }
1693 wi->damage_ |= fl;
1694 } else {
1695 // create a new region:
1696 if (i->region) XDestroyRegion(i->region);
1697 i->region = XRectangleRegion(X,Y,W,H);
1698 wi->damage_ = fl;
1699 }
1700 Fl::damage(FL_DAMAGE_CHILD);
1701}
1702void Fl_Window::flush() {
1703 make_current();
1704//if (damage() == FL_DAMAGE_EXPOSE && can_boxcheat(box())) fl_boxcheat = this;
1705 fl_clip_region(i->region); i->region = 0;
1706 draw();
1707}
1708
1709#ifdef WIN32
1710# include "Fl_win32.cxx"
1711//#elif defined(__APPLE__)
1712#endif
1713
1714//
1715// The following methods allow callbacks to schedule the deletion of
1716// widgets at "safe" times.
1717//
1718
1719static int num_dwidgets = 0, alloc_dwidgets = 0;
1720static Fl_Widget **dwidgets = 0;
1721
1722/**
1723 Schedules a widget for deletion at the next call to the event loop.
1724 Use this method to delete a widget inside a callback function.
1725
1726 To avoid early deletion of widgets, this function should be called
1727 toward the end of a callback and only after any call to the event
1728 loop (Fl::wait(), Fl::flush(), Fl::check(), fl_ask(), etc.).
1729
1730 When deleting groups or windows, you must only delete the group or
1731 window widget and not the individual child widgets.
1732
1733 \since FLTK 1.3 it is not necessary to remove widgets from their parent
1734 groups or windows before calling this, because it will be done in the
1735 widget's destructor, but it is not a failure to do this nevertheless.
1736
1737 \note In FLTK 1.1 you \b must remove widgets from their parent group
1738 (or window) before deleting them.
1739
1740 \see Fl_Widget::~Fl_Widget()
1741*/
1742void Fl::delete_widget(Fl_Widget *wi) {
1743 if (!wi) return;
1744
1745 if (num_dwidgets >= alloc_dwidgets) {
1746 Fl_Widget **temp;
1747
1748 temp = new Fl_Widget *[alloc_dwidgets + 10];
1749 if (alloc_dwidgets) {
1750 memcpy(temp, dwidgets, alloc_dwidgets * sizeof(Fl_Widget *));
1751 delete[] dwidgets;
1752 }
1753
1754 dwidgets = temp;
1755 alloc_dwidgets += 10;
1756 }
1757
1758 dwidgets[num_dwidgets] = wi;
1759 num_dwidgets ++;
1760}
1761
1762/**
1763 Deletes widgets previously scheduled for deletion.
1764
1765 This is for internal use only. You should never call this directly.
1766
1767 Fl::do_widget_deletion() is called from the FLTK event loop or whenever
1768 you call Fl::wait(). The previously scheduled widgets are deleted in the
1769 same order they were scheduled by calling Fl::delete_widget().
1770
1771 \see Fl::delete_widget(Fl_Widget *wi)
1772*/
1773void Fl::do_widget_deletion() {
1774 if (!num_dwidgets) return;
1775
1776 for (int i = 0; i < num_dwidgets; i ++)
1777 delete dwidgets[i];
1778
1779 num_dwidgets = 0;
1780}
1781
1782static Fl_Widget ***widget_watch = 0;
1783static int num_widget_watch = 0;
1784static int max_widget_watch = 0;
1785
1786/**
1787 Adds a widget pointer to the widget watch list.
1788
1789 \note Internal use only, please use class Fl_Widget_Tracker instead.
1790
1791 This can be used, if it is possible that a widget might be deleted during
1792 a callback or similar function. The widget pointer must be added to the
1793 watch list before calling the callback. After the callback the widget
1794 pointer can be queried, if it is NULL. \e If it is NULL, then the widget has been
1795 deleted during the callback and must not be accessed anymore. If the widget
1796 pointer is \e not NULL, then the widget has not been deleted and can be accessed
1797 safely.
1798
1799 After accessing the widget, the widget pointer must be released from the
1800 watch list by calling Fl::release_widget_pointer().
1801
1802 Example for a button that is clicked (from its handle() method):
1803 \code
1804 Fl_Widget *wp = this; // save 'this' in a pointer variable
1805 Fl::watch_widget_pointer(wp); // add the pointer to the watch list
1806 set_changed(); // set the changed flag
1807 do_callback(); // call the callback
1808 if (!wp) { // the widget has been deleted
1809
1810 // DO NOT ACCESS THE DELETED WIDGET !
1811
1812 } else { // the widget still exists
1813 clear_changed(); // reset the changed flag
1814 }
1815
1816 Fl::release_widget_pointer(wp); // remove the pointer from the watch list
1817 \endcode
1818
1819 This works, because all widgets call Fl::clear_widget_pointer() in their
1820 destructors.
1821
1822 \see Fl::release_widget_pointer()
1823 \see Fl::clear_widget_pointer()
1824
1825 An easier and more convenient method to control widget deletion during
1826 callbacks is to use the class Fl_Widget_Tracker with a local (automatic)
1827 variable.
1828
1829 \see class Fl_Widget_Tracker
1830*/
1831void Fl::watch_widget_pointer(Fl_Widget *&w)
1832{
1833 Fl_Widget **wp = &w;
1834 int i;
1835 for (i=0; i<num_widget_watch; ++i) {
1836 if (widget_watch[i]==wp) return;
1837 }
1838 if (num_widget_watch==max_widget_watch) {
1839 max_widget_watch += 8;
1840 widget_watch = (Fl_Widget***)realloc(widget_watch, sizeof(Fl_Widget**)*max_widget_watch);
1841 }
1842 widget_watch[num_widget_watch++] = wp;
1843#ifdef DEBUG_WATCH
1844 printf ("\nwatch_widget_pointer: (%d/%d) %8p => %8p\n",
1845 num_widget_watch,num_widget_watch,wp,*wp);
1846 fflush(stdout);
1847#endif // DEBUG_WATCH
1848}
1849
1850/**
1851 Releases a widget pointer from the watch list.
1852
1853 This is used to remove a widget pointer that has been added to the watch list
1854 with Fl::watch_widget_pointer(), when it is not needed anymore.
1855
1856 \note Internal use only, please use class Fl_Widget_Tracker instead.
1857
1858 \see Fl::watch_widget_pointer()
1859*/
1860void Fl::release_widget_pointer(Fl_Widget *&w)
1861{
1862 Fl_Widget **wp = &w;
1863 int i,j=0;
1864 for (i=0; i<num_widget_watch; ++i) {
1865 if (widget_watch[i]!=wp) {
1866 if (j<i) widget_watch[j] = widget_watch[i]; // fill gap
1867 j++;
1868 }
1869#ifdef DEBUG_WATCH
1870 else { // found widget pointer
1871 printf ("release_widget_pointer: (%d/%d) %8p => %8p\n",
1872 i+1,num_widget_watch,wp,*wp);
1873 }
1874#endif //DEBUG_WATCH
1875 }
1876 num_widget_watch = j;
1877#ifdef DEBUG_WATCH
1878 printf (" num_widget_watch = %d\n\n",num_widget_watch);
1879 fflush(stdout);
1880#endif // DEBUG_WATCH
1881 return;
1882}
1883/**
1884 Clears a widget pointer \e in the watch list.
1885
1886 This is called when a widget is destroyed (by its destructor). You should never
1887 call this directly.
1888
1889 \note Internal use only !
1890
1891 This method searches the widget watch list for pointers to the widget and
1892 clears each pointer that points to it. Widget pointers can be added to the
1893 widget watch list by calling Fl::watch_widget_pointer() or by using the
1894 helper class Fl_Widget_Tracker (recommended).
1895
1896 \see Fl::watch_widget_pointer()
1897 \see class Fl_Widget_Tracker
1898*/
1899void Fl::clear_widget_pointer(Fl_Widget const *w)
1900{
1901 if (w==0L) return;
1902 int i;
1903 for (i=0; i<num_widget_watch; ++i) {
1904 if (widget_watch[i] && *widget_watch[i]==w) {
1905 *widget_watch[i] = 0L;
1906 }
1907 }
1908}
1909
1910
1911/**
1912 \brief FLTK library options management.
1913
1914 This function needs to be documented in more detail. It can be used for more
1915 optional settings, such as using a native file chooser instead of the FLTK one
1916 wherever possible, disabling tooltips, disabling visible focus, disabling
1917 FLTK file chooser preview, etc. .
1918
1919 There should be a command line option interface.
1920
1921 There should be an application that manages options system wide, per user, and
1922 per application.
1923
1924 \note As of FLTK 1.3.0, options can be managed within fluid, using the menu
1925 <i>Edit/Global FLTK Settings</i>.
1926
1927 \param opt which option
1928 \return true or false
1929 \see enum Fl::Fl_Option
1930 \see Fl::option(Fl_Option, bool)
1931
1932 \since FLTK 1.3.0
1933 */
1934bool Fl::option(Fl_Option opt)
1935{
1936 if (!options_read_) {
1937 int tmp;
1938 { // first, read the system wide preferences
1939 Fl_Preferences prefs(Fl_Preferences::SYSTEM, "fltk.org", "fltk");
1940 Fl_Preferences opt_prefs(prefs, "options");
1941 opt_prefs.get("ArrowFocus", tmp, 0); // default: off
1942 options_[OPTION_ARROW_FOCUS] = tmp;
1943 //opt_prefs.get("NativeFilechooser", tmp, 1); // default: on
1944 //options_[OPTION_NATIVE_FILECHOOSER] = tmp;
1945 //opt_prefs.get("FilechooserPreview", tmp, 1); // default: on
1946 //options_[OPTION_FILECHOOSER_PREVIEW] = tmp;
1947 opt_prefs.get("VisibleFocus", tmp, 1); // default: on
1948 options_[OPTION_VISIBLE_FOCUS] = tmp;
1949 opt_prefs.get("DNDText", tmp, 1); // default: on
1950 options_[OPTION_DND_TEXT] = tmp;
1951 opt_prefs.get("ShowTooltips", tmp, 1); // default: on
1952 options_[OPTION_SHOW_TOOLTIPS] = tmp;
1953 }
1954 { // next, check the user preferences
1955 // override system options only, if the option is set ( >= 0 )
1956 Fl_Preferences prefs(Fl_Preferences::USER, "fltk.org", "fltk");
1957 Fl_Preferences opt_prefs(prefs, "options");
1958 opt_prefs.get("ArrowFocus", tmp, -1);
1959 if (tmp >= 0) options_[OPTION_ARROW_FOCUS] = tmp;
1960 //opt_prefs.get("NativeFilechooser", tmp, -1);
1961 //if (tmp >= 0) options_[OPTION_NATIVE_FILECHOOSER] = tmp;
1962 //opt_prefs.get("FilechooserPreview", tmp, -1);
1963 //if (tmp >= 0) options_[OPTION_FILECHOOSER_PREVIEW] = tmp;
1964 opt_prefs.get("VisibleFocus", tmp, -1);
1965 if (tmp >= 0) options_[OPTION_VISIBLE_FOCUS] = tmp;
1966 opt_prefs.get("DNDText", tmp, -1);
1967 if (tmp >= 0) options_[OPTION_DND_TEXT] = tmp;
1968 opt_prefs.get("ShowTooltips", tmp, -1);
1969 if (tmp >= 0) options_[OPTION_SHOW_TOOLTIPS] = tmp;
1970 }
1971 { // now, if the developer has registered this app, we could as for per-application preferences
1972 }
1973 options_read_ = 1;
1974 }
1975 if (opt<0 || opt>=OPTION_LAST)
1976 return false;
1977 return (bool)(options_[opt]!=0);
1978}
1979
1980/**
1981 \brief Override an option while the application is running.
1982
1983 This function does not change any system or user settings.
1984
1985 \param opt which option
1986 \param val set to true or false
1987 \see enum Fl::Fl_Option
1988 \see bool Fl::option(Fl_Option)
1989 */
1990void Fl::option(Fl_Option opt, bool val)
1991{
1992 if (opt<0 || opt>=OPTION_LAST)
1993 return;
1994 if (!options_read_) {
1995 // first read this option, so we don't override our setting later
1996 option(opt);
1997 }
1998 options_[opt] = val;
1999}
2000
2001
2002// Helper class Fl_Widget_Tracker
2003
2004/**
2005 The constructor adds a widget to the watch list.
2006*/
2007Fl_Widget_Tracker::Fl_Widget_Tracker(Fl_Widget *wi)
2008{
2009 wp_ = wi;
2010 Fl::watch_widget_pointer(wp_); // add pointer to watch list
2011}
2012
2013/**
2014 The destructor removes a widget from the watch list.
2015*/
2016Fl_Widget_Tracker::~Fl_Widget_Tracker()
2017{
2018 Fl::release_widget_pointer(wp_); // remove pointer from watch list
2019}
2020
2021
2022//
2023// End of "$Id: Fl.cxx 8723 2011-05-23 16:49:02Z manolo $".
2024//