1 //
2 // "$Id$"
3 //
4 // Overlay window 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. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file.  If this
10 // file is missing or damaged, see the license at:
11 //
12 //     http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 //     http://www.fltk.org/str.php
17 //
18 
19 
20 // A window using double-buffering and able to draw an overlay
21 // on top of that.  Uses the hardware to draw the overlay if
22 // possible, otherwise it just draws in the front buffer.
23 
24 #include <config.h>
25 #include <FL/Fl.H>
26 #include <FL/Fl_Overlay_Window.H>
27 #include <FL/fl_draw.H>
28 #include <FL/x.H>
29 
show()30 void Fl_Overlay_Window::show() {
31   Fl_Double_Window::show();
32   if (overlay_ && overlay_ != this) overlay_->show();
33 }
34 
hide()35 void Fl_Overlay_Window::hide() {
36   Fl_Double_Window::hide();
37 }
38 
flush()39 void Fl_Overlay_Window::flush() {
40 #ifdef BOXX_BUGS
41   if (overlay_ && overlay_ != this && overlay_->shown()) {
42     // all drawing to windows hidden by overlay windows is ignored, fix this
43     XUnmapWindow(fl_display, fl_xid(overlay_));
44     Fl_Double_Window::flush(0);
45     XMapWindow(fl_display, fl_xid(overlay_));
46     return;
47   }
48 #endif
49   int erase_overlay = (damage()&FL_DAMAGE_OVERLAY) | (overlay_ == this);
50   clear_damage((uchar)(damage()&~FL_DAMAGE_OVERLAY));
51   Fl_Double_Window::flush(erase_overlay);
52   if (overlay_ == this) draw_overlay();
53 }
54 
resize(int X,int Y,int W,int H)55 void Fl_Overlay_Window::resize(int X, int Y, int W, int H) {
56   Fl_Double_Window::resize(X,Y,W,H);
57   if (overlay_ && overlay_!=this) overlay_->resize(0,0,w(),h());
58 }
59 
60 /**
61   Destroys the window and all child widgets.
62 */
~Fl_Overlay_Window()63 Fl_Overlay_Window::~Fl_Overlay_Window() {
64   hide();
65 //  delete overlay; this is done by ~Fl_Group
66 }
67 
68 #if !HAVE_OVERLAY
69 
can_do_overlay()70 int Fl_Overlay_Window::can_do_overlay() {return 0;}
71 
72 /**
73   Call this to indicate that the overlay data has changed and needs to
74   be redrawn.  The overlay will be clear until the first time this is
75   called, so if you want an initial display you must call this after
76   calling show().
77 */
redraw_overlay()78 void Fl_Overlay_Window::redraw_overlay() {
79   overlay_ = this;
80   clear_damage((uchar)(damage()|FL_DAMAGE_OVERLAY));
81   Fl::damage(FL_DAMAGE_CHILD);
82 }
83 
84 #else
85 
86 extern XVisualInfo *fl_find_overlay_visual();
87 extern XVisualInfo *fl_overlay_visual;
88 extern Colormap fl_overlay_colormap;
89 extern unsigned long fl_transparent_pixel;
90 static GC gc;	// the GC used by all X windows
91 extern uchar fl_overlay; // changes how fl_color(x) works
92 
93 class _Fl_Overlay : public Fl_Window {
94   friend class Fl_Overlay_Window;
95   void flush();
96   void show();
97 public:
_Fl_Overlay(int x,int y,int w,int h)98   _Fl_Overlay(int x, int y, int w, int h) :
99     Fl_Window(x,y,w,h) {set_flag(INACTIVE);}
100 };
101 
can_do_overlay()102 int Fl_Overlay_Window::can_do_overlay() {
103   return fl_find_overlay_visual() != 0;
104 }
105 
show()106 void _Fl_Overlay::show() {
107   if (shown()) {Fl_Window::show(); return;}
108   fl_background_pixel = int(fl_transparent_pixel);
109   Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap);
110   fl_background_pixel = -1;
111   // find the outermost window to tell wm about the colormap:
112   Fl_Window *w = window();
113   for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;}
114   XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1);
115 }
116 
flush()117 void _Fl_Overlay::flush() {
118   fl_window = fl_xid(this);
119   if (!gc) {
120 	  gc = XCreateGC(fl_display, fl_xid(this), 0, 0);
121   }
122   fl_gc = gc;
123 #if defined(FLTK_USE_CAIRO)
124       if (Fl::cairo_autolink_context()) Fl::cairo_make_current(this); // capture gc changes automatically to update the cairo context adequately
125 #endif
126   fl_overlay = 1;
127   Fl_Overlay_Window *w = (Fl_Overlay_Window *)parent();
128   Fl_X *myi = Fl_X::i(this);
129   if (damage() != FL_DAMAGE_EXPOSE) XClearWindow(fl_display, fl_xid(this));
130   fl_clip_region(myi->region); myi->region = 0;
131   w->draw_overlay();
132   fl_overlay = 0;
133 }
134 
redraw_overlay()135 void Fl_Overlay_Window::redraw_overlay() {
136   if (!fl_display) return; // this prevents fluid -c from opening display
137   if (!overlay_) {
138     if (can_do_overlay()) {
139       Fl_Group::current(this);
140       overlay_ = new _Fl_Overlay(0,0,w(),h());
141       Fl_Group::current(0);
142     } else {
143       overlay_ = this;	// fake the overlay
144     }
145   }
146   if (shown()) {
147     if (overlay_ == this) {
148       clear_damage(damage()|FL_DAMAGE_OVERLAY);
149       Fl::damage(FL_DAMAGE_CHILD);
150     } else if (!overlay_->shown())
151       overlay_->show();
152     else
153       overlay_->redraw();
154   }
155 }
156 
157 #endif
158 
159 //
160 // End of "$Id$".
161 //
162