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