DRC | 2ff39b8 | 2011-07-28 08:38:59 +0000 | [diff] [blame] | 1 | // |
| 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 | |
| 45 | void Fl_Overlay_Window::show() { |
| 46 | Fl_Double_Window::show(); |
| 47 | if (overlay_ && overlay_ != this) overlay_->show(); |
| 48 | } |
| 49 | |
| 50 | void Fl_Overlay_Window::hide() { |
| 51 | Fl_Double_Window::hide(); |
| 52 | } |
| 53 | |
| 54 | void 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 | |
| 70 | void 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 | */ |
| 78 | Fl_Overlay_Window::~Fl_Overlay_Window() { |
| 79 | hide(); |
| 80 | // delete overlay; this is done by ~Fl_Group |
| 81 | } |
| 82 | |
| 83 | #if !HAVE_OVERLAY |
| 84 | |
| 85 | int 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 | */ |
| 93 | void 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 | |
| 101 | extern XVisualInfo *fl_find_overlay_visual(); |
| 102 | extern XVisualInfo *fl_overlay_visual; |
| 103 | extern Colormap fl_overlay_colormap; |
| 104 | extern unsigned long fl_transparent_pixel; |
| 105 | static GC gc; // the GC used by all X windows |
| 106 | extern uchar fl_overlay; // changes how fl_color(x) works |
| 107 | |
| 108 | class _Fl_Overlay : public Fl_Window { |
| 109 | friend class Fl_Overlay_Window; |
| 110 | void flush(); |
| 111 | void show(); |
| 112 | public: |
| 113 | _Fl_Overlay(int x, int y, int w, int h) : |
| 114 | Fl_Window(x,y,w,h) {set_flag(INACTIVE);} |
| 115 | }; |
| 116 | |
| 117 | int Fl_Overlay_Window::can_do_overlay() { |
| 118 | return fl_find_overlay_visual() != 0; |
| 119 | } |
| 120 | |
| 121 | void _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 | |
| 132 | void _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 | |
| 150 | void 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 | // |