blob: f75a3d9419a44cc3cf23095278cc3a801d105f9d [file] [log] [blame]
DRC2ff39b82011-07-28 08:38:59 +00001//
2// "$Id: Fl_Overlay_Window.cxx 8198 2011-01-06 10:24:58Z manolo $"
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; 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/** \fn virtual void Fl_Overlay_Window::draw_overlay() = 0
29 You must subclass Fl_Overlay_Window and provide this method.
30 It is just like a draw() method, except it draws the overlay.
31 The overlay will have already been "cleared" when this is called. You
32 can use any of the routines described in <FL/fl_draw.H>.
33*/
34
35// A window using double-buffering and able to draw an overlay
36// on top of that. Uses the hardware to draw the overlay if
37// possible, otherwise it just draws in the front buffer.
38
39#include <config.h>
40#include <FL/Fl.H>
41#include <FL/Fl_Overlay_Window.H>
42#include <FL/fl_draw.H>
43#include <FL/x.H>
44
45void Fl_Overlay_Window::show() {
46 Fl_Double_Window::show();
47 if (overlay_ && overlay_ != this) overlay_->show();
48}
49
50void Fl_Overlay_Window::hide() {
51 Fl_Double_Window::hide();
52}
53
54void Fl_Overlay_Window::flush() {
55#ifdef BOXX_BUGS
56 if (overlay_ && overlay_ != this && overlay_->shown()) {
57 // all drawing to windows hidden by overlay windows is ignored, fix this
58 XUnmapWindow(fl_display, fl_xid(overlay_));
59 Fl_Double_Window::flush(0);
60 XMapWindow(fl_display, fl_xid(overlay_));
61 return;
62 }
63#endif
64 int erase_overlay = (damage()&FL_DAMAGE_OVERLAY) | (overlay_ == this);
65 clear_damage((uchar)(damage()&~FL_DAMAGE_OVERLAY));
66 Fl_Double_Window::flush(erase_overlay);
67 if (overlay_ == this) draw_overlay();
68}
69
70void Fl_Overlay_Window::resize(int X, int Y, int W, int H) {
71 Fl_Double_Window::resize(X,Y,W,H);
72 if (overlay_ && overlay_!=this) overlay_->resize(0,0,w(),h());
73}
74
75/**
76 Destroys the window and all child widgets.
77*/
78Fl_Overlay_Window::~Fl_Overlay_Window() {
79 hide();
80// delete overlay; this is done by ~Fl_Group
81}
82
83#if !HAVE_OVERLAY
84
85int Fl_Overlay_Window::can_do_overlay() {return 0;}
86
87/**
88 Call this to indicate that the overlay data has changed and needs to
89 be redrawn. The overlay will be clear until the first time this is
90 called, so if you want an initial display you must call this after
91 calling show().
92*/
93void Fl_Overlay_Window::redraw_overlay() {
94 overlay_ = this;
95 clear_damage((uchar)(damage()|FL_DAMAGE_OVERLAY));
96 Fl::damage(FL_DAMAGE_CHILD);
97}
98
99#else
100
101extern XVisualInfo *fl_find_overlay_visual();
102extern XVisualInfo *fl_overlay_visual;
103extern Colormap fl_overlay_colormap;
104extern unsigned long fl_transparent_pixel;
105static GC gc; // the GC used by all X windows
106extern uchar fl_overlay; // changes how fl_color(x) works
107
108class _Fl_Overlay : public Fl_Window {
109 friend class Fl_Overlay_Window;
110 void flush();
111 void show();
112public:
113 _Fl_Overlay(int x, int y, int w, int h) :
114 Fl_Window(x,y,w,h) {set_flag(INACTIVE);}
115};
116
117int Fl_Overlay_Window::can_do_overlay() {
118 return fl_find_overlay_visual() != 0;
119}
120
121void _Fl_Overlay::show() {
122 if (shown()) {Fl_Window::show(); return;}
123 fl_background_pixel = int(fl_transparent_pixel);
124 Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap);
125 fl_background_pixel = -1;
126 // find the outermost window to tell wm about the colormap:
127 Fl_Window *w = window();
128 for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;}
129 XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1);
130}
131
132void _Fl_Overlay::flush() {
133 fl_window = fl_xid(this);
134 if (!gc) {
135 gc = XCreateGC(fl_display, fl_xid(this), 0, 0);
136 }
137 fl_gc = gc;
138#if defined(FLTK_USE_CAIRO)
139 if (Fl::cairo_autolink_context()) Fl::cairo_make_current(this); // capture gc changes automatically to update the cairo context adequately
140#endif
141 fl_overlay = 1;
142 Fl_Overlay_Window *w = (Fl_Overlay_Window *)parent();
143 Fl_X *myi = Fl_X::i(this);
144 if (damage() != FL_DAMAGE_EXPOSE) XClearWindow(fl_display, fl_xid(this));
145 fl_clip_region(myi->region); myi->region = 0;
146 w->draw_overlay();
147 fl_overlay = 0;
148}
149
150void Fl_Overlay_Window::redraw_overlay() {
151 if (!fl_display) return; // this prevents fluid -c from opening display
152 if (!overlay_) {
153 if (can_do_overlay()) {
154 Fl_Group::current(this);
155 overlay_ = new _Fl_Overlay(0,0,w(),h());
156 Fl_Group::current(0);
157 } else {
158 overlay_ = this; // fake the overlay
159 }
160 }
161 if (shown()) {
162 if (overlay_ == this) {
163 clear_damage(damage()|FL_DAMAGE_OVERLAY);
164 Fl::damage(FL_DAMAGE_CHILD);
165 } else if (!overlay_->shown())
166 overlay_->show();
167 else
168 overlay_->redraw();
169 }
170}
171
172#endif
173
174//
175// End of "$Id: Fl_Overlay_Window.cxx 8198 2011-01-06 10:24:58Z manolo $".
176//