diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2016-03-13 22:16:37 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2016-03-13 22:16:37 +0000 |
| commit | b496d18b85917106c48e8e6f74115b3122b603d1 (patch) | |
| tree | 4d96befa4377a81c89c6a32f4d66220199572938 /src | |
| parent | 30756ae3500a62bd8f63b4df3eb3ca8f6b8b0b70 (diff) | |
Fixed 'flush()' code for single, double, and overlay buffering
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11359 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
22 files changed, 593 insertions, 193 deletions
diff --git a/src/Fl.cxx b/src/Fl.cxx index 88f82a151..5e725cfcc 100644 --- a/src/Fl.cxx +++ b/src/Fl.cxx @@ -1826,13 +1826,7 @@ void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) { } Fl::damage(FL_DAMAGE_CHILD); } -void Fl_Window::flush() { - if (!shown()) return; - make_current(); -//if (damage() == FL_DAMAGE_EXPOSE && can_boxcheat(box())) fl_boxcheat = this; - fl_clip_region(i->region); i->region = 0; - draw(); -} + #ifdef WIN32 # include "Fl_win32.cxx" diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx index 49e890e22..701f53274 100644 --- a/src/Fl_Double_Window.cxx +++ b/src/Fl_Double_Window.cxx @@ -56,40 +56,6 @@ void Fl_Double_Window::show() { }*/ -/** - Forces the window to be redrawn. -*/ -void Fl_Double_Window::flush() -{ - flush(0); -} - - -/** - Forces the window to be redrawn. - \param[in] eraseoverlay non-zero to erase overlay, zero to ignore - - Fl_Overlay_Window relies on flush(1) copying the back buffer to the - front everywhere, even if damage() == 0, thus erasing the overlay, - and leaving the clip region set to the entire window. -*/ -void Fl_Double_Window::flush(int eraseoverlay) { - if (!shown()) return; - make_current(); // make sure fl_gc is non-zero - Fl_X *myi = Fl_X::i(this); - if (!myi) return; // window not yet created - int retval = driver()->double_flush(eraseoverlay); - if (retval) return; - if (eraseoverlay) fl_clip_region(0); - // on Irix (at least) it is faster to reduce the area copied to - // the current clip region: - if (myi->other_xid) { - int X,Y,W,H; fl_graphics_driver->clip_box(0,0,w(),h(),X,Y,W,H); - fl_graphics_driver->copy_offscreen(X, Y, W, H, myi->other_xid, X, Y); - } -} - - void Fl_Double_Window::resize(int X,int Y,int W,int H) { int ow = w(); int oh = h(); @@ -108,6 +74,12 @@ void Fl_Double_Window::hide() { } +void Fl_Double_Window::flush() +{ + driver()->flush_double(); +} + + /** The destructor <I>also deletes all the children</I>. This allows a whole tree to be deleted at once, without having to keep a pointer to diff --git a/src/Fl_Overlay_Window.cxx b/src/Fl_Overlay_Window.cxx index c1ae2728e..07065fbb0 100644 --- a/src/Fl_Overlay_Window.cxx +++ b/src/Fl_Overlay_Window.cxx @@ -53,20 +53,9 @@ void Fl_Overlay_Window::hide() { Fl_Double_Window::hide(); } -void Fl_Overlay_Window::flush() { -#ifdef BOXX_BUGS - if (overlay_ && overlay_ != this && overlay_->shown()) { - // all drawing to windows hidden by overlay windows is ignored, fix this - XUnmapWindow(fl_display, fl_xid(overlay_)); - Fl_Double_Window::flush(0); - XMapWindow(fl_display, fl_xid(overlay_)); - return; - } -#endif - int erase_overlay = (damage()&FL_DAMAGE_OVERLAY) | (overlay_ == this); - clear_damage((uchar)(damage()&~FL_DAMAGE_OVERLAY)); - Fl_Double_Window::flush(erase_overlay); - if (overlay_ == this) draw_overlay(); +void Fl_Overlay_Window::flush() +{ + driver()->flush_overlay(); } void Fl_Overlay_Window::resize(int X, int Y, int W, int H) { diff --git a/src/Fl_Printer.cxx b/src/Fl_Printer.cxx index 58db4cca8..47ae9748d 100644 --- a/src/Fl_Printer.cxx +++ b/src/Fl_Printer.cxx @@ -63,6 +63,8 @@ const char *Fl_Printer::property_cancel = NULL; #else +#include "Fl_GDI_Printer.cxx" + // print dialog customization strings /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_title = "Print"; diff --git a/src/Fl_Single_Window.cxx b/src/Fl_Single_Window.cxx index fd871a3b8..c5e37fabc 100644 --- a/src/Fl_Single_Window.cxx +++ b/src/Fl_Single_Window.cxx @@ -31,12 +31,6 @@ void Fl_Single_Window::show() } -void Fl_Single_Window::flush() -{ - Fl_Window::flush(); -} - - Fl_Single_Window::Fl_Single_Window(int W, int H, const char *l) : Fl_Window(W,H,l) { diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx index 97045174b..98882591e 100644 --- a/src/Fl_Window.cxx +++ b/src/Fl_Window.cxx @@ -435,6 +435,46 @@ int Fl_Window::decorated_h() } +void Fl_Window::flush() +{ + driver()->flush_single(); +} + + +void Fl_Window::draw() +{ + pWindowDriver->draw_begin(); + + // The following is similar to Fl_Group::draw(), but ... + // + // - draws the box at (0,0), i.e. with x=0 and y=0 instead of x() and y() + // - does NOT draw the label (text) + // - draws the image only if FL_ALIGN_INSIDE is set + // + // Note: The label (text) of top level windows is drawn in the title bar. + // Other windows do not draw their labels at all, unless drawn by their + // parent widgets or by special draw() methods (derived classes). + + if (damage() & ~FL_DAMAGE_CHILD) { // draw the entire thing + draw_box(box(),0,0,w(),h(),color()); // draw box with x/y = 0 + + if (image() && (align() & FL_ALIGN_INSIDE)) { // draw the image only + Fl_Label l1; + memset(&l1,0,sizeof(l1)); + l1.align_ = align(); + l1.image = image(); + if (!active_r() && l1.image && l1.deimage) l1.image = l1.deimage; + l1.type = labeltype(); + l1.draw(0,0,w(),h(),align()); + } + } + draw_children(); + + pWindowDriver->draw_end(); +} + + + // // End of "$Id$". // diff --git a/src/Fl_Window_Driver.cxx b/src/Fl_Window_Driver.cxx index 9908fde9d..eda8c2901 100644 --- a/src/Fl_Window_Driver.cxx +++ b/src/Fl_Window_Driver.cxx @@ -22,6 +22,7 @@ #include "config_lib.h" #include <FL/Fl_Window_Driver.H> #include <FL/Fl.H> +#include <FL/Fl_Overlay_Window.H> #include <FL/fl_draw.H> @@ -37,41 +38,47 @@ Fl_Window_Driver::~Fl_Window_Driver() } -/* - Used in Fl::focus(Fl_Window). - Default implementation does not need to do anything. - - reimplemented for OS X Cocoa - - reimplemented for X11 - */ void Fl_Window_Driver::take_focus() { + // nothing to do } -int Fl_Window_Driver::double_flush(int eraseoverlay) { - /* This is a working, platform-independent implementation. - Some platforms may re-implement it for their own logic: - - on Mac OS, the system double buffers all windows, so it is - reimplemented to do the same as Fl_Window::flush(), except for - Fl_Overlay_Window's which fall back on this implementation. - - on Xlib, it is reimplemented if the Xdbe extension is available. - */ +void Fl_Window_Driver::flush_single() +{ Fl_X *i = Fl_X::i(pWindow); - - if (!i->other_xid) { - i->other_xid = fl_create_offscreen(pWindow->w(), pWindow->h()); - pWindow->clear_damage(FL_DAMAGE_ALL); - } - if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { - fl_clip_region(i->region); i->region = 0; - fl_begin_offscreen(i->other_xid); - fl_graphics_driver->clip_region( 0 ); - draw(); - fl_end_offscreen(); - } - return 0; + if (!i) return; + fl_clip_region(i->region); + i->region = 0; + pWindow->draw(); } + +void Fl_Window_Driver::flush_double() +{ + flush_single(); +} + + +void Fl_Window_Driver::flush_overlay() +{ + flush_single(); +} + + +void Fl_Window_Driver::draw_begin() +{ + // nothing to do +} + + +void Fl_Window_Driver::draw_end() +{ + // nothing to do +} + + + void Fl_Window_Driver::destroy_double_buffer() { Fl_X *i = Fl_X::i(pWindow); /* This is a working, platform-independent implementation. @@ -113,7 +120,6 @@ void Fl_Window_Driver::draw() { # endif } -void Fl_Window::draw() {pWindowDriver->draw();} /** Assigns a non-rectangular shape to the window. This function gives an arbitrary shape (not just a rectangular region) to an Fl_Window. diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index 94ade1d9e..821ef57bf 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -84,7 +84,7 @@ static unsigned make_current_counts = 0; // if > 0, then Fl_Window::make_current static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y, int w, int h); // make this available on all platforms to make code maintainability easier -class Fl_Widget *fl_selection_requestor; +extern class Fl_Widget *fl_selection_requestor; int fl_mac_os_version = Fl_X::calc_mac_os_version(); // the version number of the running Mac OS X (e.g., 100604 for 10.6.4) diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 0caf501f1..b1715edb2 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -86,7 +86,7 @@ */ // make this available on all platforms to make code maintainability easier -class Fl_Widget *fl_selection_requestor; +extern class Fl_Widget *fl_selection_requestor; // Internal functions static void fl_clipboard_notify_target(HWND wnd); diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H index 419469df7..8a5c8d42e 100644 --- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H +++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H @@ -52,11 +52,13 @@ struct Fl_Window_Driver::shape_data_type { CGImageRef mask; }; + class FL_EXPORT Fl_Cocoa_Window_Driver : public Fl_Window_Driver { private: void shape_bitmap_(Fl_Image* b); void shape_alpha_(Fl_Image* img, int offset); + public: Fl_Cocoa_Window_Driver(Fl_Window*); ~Fl_Cocoa_Window_Driver(); @@ -65,7 +67,14 @@ public: virtual int decorated_w(); virtual int decorated_h(); + // --- window management virtual void take_focus(); + virtual void flush_single(); + virtual void flush_double(); + virtual void flush_overlay(); + virtual void draw_begin(); + virtual void draw_end(); + virtual void shape(const Fl_Image* img); virtual void draw(); // that one is implemented in Fl_Cocoa.mm because it uses Objective-c diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx index 6a4e141d7..0285af9df 100644 --- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx +++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx @@ -20,25 +20,14 @@ #include "../../config_lib.h" #include "Fl_Cocoa_Window_Driver.h" #include <FL/Fl_Double_Window.H> +#include <FL/Fl_Overlay_Window.H> #include <FL/fl_draw.H> #include <FL/Fl.H> -// class used for Fl_Double_Window but not for Fl_Overlay_Window -class Fl_Cocoa_Double_Window_Driver : public Fl_Cocoa_Window_Driver { -public: - Fl_Cocoa_Double_Window_Driver(Fl_Window *w) : Fl_Cocoa_Window_Driver(w) {} - int double_flush(int eraseoverlay) { - draw(); - return 0; - } -}; Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) { - if (w->as_double_window() && !w->as_double_window()->as_overlay_window()) - return new Fl_Cocoa_Double_Window_Driver(w); - else - return new Fl_Cocoa_Window_Driver(w); + return new Fl_Cocoa_Window_Driver(w); } @@ -47,6 +36,7 @@ Fl_Cocoa_Window_Driver::Fl_Cocoa_Window_Driver(Fl_Window *win) { } + Fl_Cocoa_Window_Driver::~Fl_Cocoa_Window_Driver() { if (shape_data_) { @@ -57,8 +47,6 @@ Fl_Cocoa_Window_Driver::~Fl_Cocoa_Window_Driver() } } -extern Fl_Window *fl_xfocus; - void Fl_Cocoa_Window_Driver::take_focus() { @@ -67,6 +55,108 @@ void Fl_Cocoa_Window_Driver::take_focus() } +void Fl_Cocoa_Window_Driver::flush_single() +{ + if (!pWindow->shown()) return; + pWindow->make_current(); + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; // window not yet created + fl_clip_region(i->region); i->region = 0; + pWindow->draw(); +} + + +void Fl_Cocoa_Window_Driver::flush_double() +{ + if (!pWindow->shown()) return; + pWindow->make_current(); + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; // window not yet created + fl_clip_region(i->region); i->region = 0; + pWindow->draw(); +} + + +void Fl_Cocoa_Window_Driver::flush_overlay() +{ + Fl_Overlay_Window *oWindow = pWindow->as_overlay_window(); + if (!oWindow) return flush_single(); + + if (!pWindow->shown()) return; + pWindow->make_current(); // make sure fl_gc is non-zero + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; // window not yet created + + int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY); + pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); + + if (!i->other_xid) { + i->other_xid = fl_create_offscreen(pWindow->w(), pWindow->h()); + pWindow->clear_damage(FL_DAMAGE_ALL); + } + if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { + fl_clip_region(i->region); i->region = 0; + if ( i->other_xid ) { + fl_begin_offscreen( i->other_xid ); + fl_clip_region( 0 ); + draw(); + fl_end_offscreen(); + } else { + draw(); + } + } + if (erase_overlay) fl_clip_region(0); + + int X,Y,W,H; fl_clip_box(0,0,pWindow->w(),pWindow->h(),X,Y,W,H); + if (i->other_xid) fl_copy_offscreen(X, Y, W, H, i->other_xid, X, Y); + + if (oWindow->overlay_ == oWindow) oWindow->draw_overlay(); +} + + +void Fl_Cocoa_Window_Driver::draw_begin() +{ + if (shape_data_) { +# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + if (shape_data_->mask && (&CGContextClipToMask != NULL)) { + CGContextClipToMask(fl_gc, CGRectMake(0,0,pWindow->w(),pWindow->h()), shape_data_->mask); // requires Mac OS 10.4 + } + CGContextSaveGState(fl_gc); +# endif + } +} + + +void Fl_Cocoa_Window_Driver::draw_end() +{ + // on OS X, windows have no frame. Before OS X 10.7, to resize a window, we drag the lower right + // corner. This code draws a little ribbed triangle for dragging. + if (fl_mac_os_version < 100700 && fl_gc && !pWindow->parent() && pWindow->resizable() && + (!pWindow->size_range_set || pWindow->minh!=pWindow->maxh || pWindow->minw!=pWindow->maxw)) { + int dx = Fl::box_dw(pWindow->box())-Fl::box_dx(pWindow->box()); + int dy = Fl::box_dh(pWindow->box())-Fl::box_dy(pWindow->box()); + if (dx<=0) dx = 1; + if (dy<=0) dy = 1; + int x1 = pWindow->w()-dx-1, x2 = x1, y1 = pWindow->h()-dx-1, y2 = y1; + Fl_Color c[4] = { + pWindow->color(), + fl_color_average(pWindow->color(), FL_WHITE, 0.7f), + fl_color_average(pWindow->color(), FL_BLACK, 0.6f), + fl_color_average(pWindow->color(), FL_BLACK, 0.8f), + }; + int i; + for (i=dx; i<12; i++) { + fl_color(c[i&3]); + fl_line(x1--, y1, x2, y2--); + } + } +# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + if (shape_data_) CGContextRestoreGState(fl_gc); +# endif +} + + + static void MyProviderReleaseData (void *info, const void *data, size_t size) { delete[] (uchar*)data; } diff --git a/src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx b/src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx index 914fdafd3..3968ea756 100644 --- a/src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx +++ b/src/drivers/Pico/Fl_Pico_Graphics_Driver.cxx @@ -35,10 +35,10 @@ void Fl_Pico_Graphics_Driver::point(int x, int y) void Fl_Pico_Graphics_Driver::rect(int x, int y, int w, int h) { - line(x, y, x+w, y); - line(x+w, y, x+w, y+h); - line(x+w, y+h, x, y+h); - line(x, y+h, x, y); + line(x, y, x+w-1, y); + line(x+w-1, y, x+w-1, y+h-1); + line(x+w-1, y+h-1, x, y+h-1); + line(x, y+h-1, x, y); } void Fl_Pico_Graphics_Driver::rectf(int x, int y, int w, int h) @@ -231,10 +231,20 @@ static const char *font_data[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */0, /*!*/"\31\34\100\35\36", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, /*B*/"\43\54\45\15\11\41\52\43\13", 0, 0, /*E*/"\51\11\15\55\100\13\43", 0, 0, - /*H*/"\11\15\100\61\65\100\13\63", 0, 0, 0, 0, 0, 0, 0, + /*0*/"\62\51\21\12\14\25\55\64\62\100\52\61", + /*1*/"\22\31\35\100\25\45", + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, + /*A*/"\15\31\55\100\23\43", + /*B*/"\43\54\45\15\11\41\52\43\13", + /*C*/"\62\51\21\12\14\25\55\64", + /*D*/"\11\51\62\64\55\15\11", + /*E*/"\61\11\15\65\100\13\43", + /*F*/"\61\11\15\100\13\43", + /*G*/"\62\51\21\12\14\25\55\64\100\65\63\33", + /*H*/"\11\15\100\61\65\100\13\63", + /*I*/"\21\41\100\31\35\100\25\45", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*T*/"\11\71\100\41\45", 0, 0, /*W*/"\01\15\33\55\61", /*X*/"\15\51\100\11\55", 0, 0, 0, 0, 0, 0, 0, diff --git a/src/drivers/Pico/Fl_Pico_Window_Driver.H b/src/drivers/Pico/Fl_Pico_Window_Driver.H index 51e9db920..40d6457fa 100644 --- a/src/drivers/Pico/Fl_Pico_Window_Driver.H +++ b/src/drivers/Pico/Fl_Pico_Window_Driver.H @@ -37,6 +37,13 @@ public: // --- window data virtual int decorated_w(); virtual int decorated_h(); + + // --- window management + virtual void flush_single(); + virtual void flush_double(); + virtual void flush_overlay(); + virtual void draw_begin(); + virtual void draw_end(); }; diff --git a/src/drivers/Pico/Fl_Pico_Window_Driver.cxx b/src/drivers/Pico/Fl_Pico_Window_Driver.cxx index b14696d6f..bb5b4e612 100644 --- a/src/drivers/Pico/Fl_Pico_Window_Driver.cxx +++ b/src/drivers/Pico/Fl_Pico_Window_Driver.cxx @@ -25,14 +25,6 @@ -// TODO: move this to Fl_Window_Driver -void Fl_X::flush() -{ - w->driver()->flush(); -} - - - Fl_Pico_Window_Driver::Fl_Pico_Window_Driver(Fl_Window *win) : Fl_Window_Driver(win) { @@ -58,6 +50,43 @@ int Fl_Pico_Window_Driver::decorated_h() } +// --- window management +void Fl_Pico_Window_Driver::flush_single() +{ + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; + fl_clip_region(i->region); + i->region = 0; + pWindow->draw(); +} + + +void Fl_Pico_Window_Driver::flush_double() +{ + flush_single(); +} + + +void Fl_Pico_Window_Driver::flush_overlay() +{ + flush_single(); +} + + + + +void Fl_Pico_Window_Driver::draw_begin() +{ + // nothing to do +} + + +void Fl_Pico_Window_Driver::draw_end() +{ + // nothing to do +} + + // // End of "$Id: Fl_Pico_Window_Driver.cxx 11253 2016-03-01 00:54:21Z matt $". //
\ No newline at end of file diff --git a/src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx b/src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx index 6e06c85ab..17957312e 100644 --- a/src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx +++ b/src/drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.cxx @@ -95,6 +95,17 @@ Fl_X *Fl_PicoAndroid_Window_Driver::makeWindow() #include <FL/fl_draw.h> + +void Fl_Window_Driver::draw_begin() +{ +} + + +void Fl_Window_Driver::draw_end() +{ +} + + void Fl_PicoAndroid_Window_Driver::flush() { Fl_PicoAndroid_Screen_Driver *scr = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver(); diff --git a/src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx b/src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx index 82d94dcd5..942c5a523 100644 --- a/src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx +++ b/src/drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx @@ -52,24 +52,27 @@ double Fl_PicoSDL_Screen_Driver::wait(double time_to_wait) switch (e.type) { case SDL_QUIT: exit(0); - case SDL_WINDOWEVENT_EXPOSED: - case SDL_WINDOWEVENT_SHOWN: - { // not happening! - //event->window.windowID - if ( !window ) break;; - Fl_X *i = Fl_X::i(Fl::first_window()); - i->wait_for_expose = 0; - - if ( i->region ) { - XDestroyRegion(i->region); - i->region = 0; + case SDL_WINDOWEVENT: + switch (e.window.event) { + case SDL_WINDOWEVENT_EXPOSED: + case SDL_WINDOWEVENT_SHOWN: + { + //event->window.windowID + if ( !window ) break;; + Fl_X *i = Fl_X::i(Fl::first_window()); + i->wait_for_expose = 0; + + if ( i->region ) { + XDestroyRegion(i->region); + i->region = 0; + } + window->clear_damage(FL_DAMAGE_ALL); + i->flush(); + window->clear_damage(); + Fl_X::first->wait_for_expose = 0; + } + break; } - window->clear_damage(FL_DAMAGE_ALL); - i->flush(); - window->clear_damage(); - Fl_X::first->wait_for_expose = 0; - } - break; case SDL_MOUSEBUTTONDOWN: if (!window) break; Fl::e_is_click = e.button.clicks; @@ -204,6 +207,11 @@ void Fl::remove_fd(int) { } +void Fl_X::flush() +{ + w->flush(); +} + // // End of "$Id: Fl_PicoSDL_Screen_Driver.cxx 11253 2016-03-01 00:54:21Z matt $". diff --git a/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H b/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H index cc4fb81c4..7cb2e7c43 100644 --- a/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H +++ b/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H @@ -40,7 +40,11 @@ public: virtual ~Fl_PicoSDL_Window_Driver(); virtual Fl_X *makeWindow(); - virtual void flush(); + + // --- window management + virtual void flush_single(); + virtual void flush_double(); + virtual void flush_overlay(); }; diff --git a/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx b/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx index a9a7fc95f..346eea241 100644 --- a/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx +++ b/src/drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx @@ -72,7 +72,7 @@ Fl_X *Fl_PicoSDL_Window_Driver::makeWindow() pWindow->set_visible(); pWindow->redraw(); - flush(); + pWindow->flush(); int old_event = Fl::e_number; pWindow->handle(Fl::e_number = FL_SHOW); Fl::e_number = old_event; @@ -81,14 +81,34 @@ Fl_X *Fl_PicoSDL_Window_Driver::makeWindow() } -void Fl_PicoSDL_Window_Driver::flush() +void Fl_PicoSDL_Window_Driver::flush_single() { - SDL_RenderClear((SDL_Renderer*)fl_window); - pWindow->flush(); - SDL_RenderPresent((SDL_Renderer*)fl_window); + if (!pWindow->shown()) return; + pWindow->make_current(); + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; + fl_clip_region(i->region); + i->region = 0; +// SDL_RenderClear((SDL_Renderer*)i->xid); + pWindow->draw(); + SDL_RenderPresent((SDL_Renderer*)i->xid); +} + + +void Fl_PicoSDL_Window_Driver::flush_double() +{ + flush_single(); } +void Fl_PicoSDL_Window_Driver::flush_overlay() +{ + flush_single(); + // draw_overlay(); +} + + + // // End of "$Id: Fl_PicoSDL_Window_Driver.cxx 11253 2016-03-01 00:54:21Z matt $". //
\ No newline at end of file diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H index f4521b5e7..ebcf72440 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H @@ -72,8 +72,14 @@ public: virtual int decorated_w(); virtual int decorated_h(); + // --- window management + virtual void flush_single(); + virtual void flush_double(); + virtual void flush_overlay(); + virtual void draw_begin(); + virtual void draw_end(); + virtual void shape(const Fl_Image* img); - virtual void draw(); virtual void icons(const Fl_RGB_Image *icons[], int count); virtual const void *icon() const; virtual void icon(const void * ic); diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx index 6e7d546da..c1893b841 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx @@ -18,11 +18,13 @@ #include "../../config_lib.h" +#include <FL/fl_draw.H> #include <FL/Fl.H> #include <FL/Fl_Window.H> #include <FL/Fl_Image.H> #include <FL/Fl_Bitmap.H> #include <FL/Fl_Window.H> +#include <FL/Fl_Overlay_Window.H> #include <FL/x.H> #include "Fl_WinAPI_Window_Driver.H" #include <windows.h> @@ -40,6 +42,7 @@ Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win) memset(icon_, 0, sizeof(Fl_Window_Driver::icon_data)); } + Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver() { if (shape_data_) { @@ -96,6 +99,7 @@ int Fl_WinAPI_Window_Driver::decorated_h() } +// --- window management @@ -235,7 +239,8 @@ static HRGN bitmap2region(Fl_Image* image) { } -void Fl_WinAPI_Window_Driver::draw() { +void Fl_WinAPI_Window_Driver::draw_begin() +{ if (shape_data_) { if ((shape_data_->lw_ != pWindow->w() || shape_data_->lh_ != pWindow->h()) && shape_data_->shape_) { // size of window has changed since last time @@ -246,9 +251,84 @@ void Fl_WinAPI_Window_Driver::draw() { SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed delete temp; } - } Fl_Window_Driver::draw(); + } +} + + +void Fl_WinAPI_Window_Driver::draw_end() +{ } + +void Fl_WinAPI_Window_Driver::flush_single() +{ + if (!pWindow->shown()) return; + pWindow->make_current(); // make sure fl_gc is non-zero + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; + fl_clip_region(i->region); + i->region = 0; + pWindow->draw(); +} + + +void Fl_WinAPI_Window_Driver::flush_double() +{ + if (!pWindow->shown()) return; + pWindow->make_current(); // make sure fl_gc is non-zero + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; // window not yet created + + if (!i->other_xid) { + i->other_xid = fl_create_offscreen(pWindow->w(), pWindow->h()); + pWindow->clear_damage(FL_DAMAGE_ALL); + } + if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { + fl_clip_region(i->region); i->region = 0; + fl_begin_offscreen(i->other_xid); + fl_graphics_driver->clip_region( 0 ); + draw(); + fl_end_offscreen(); + } + + int X,Y,W,H; fl_clip_box(0,0,pWindow->w(),pWindow->h(),X,Y,W,H); + if (i->other_xid) fl_copy_offscreen(X, Y, W, H, i->other_xid, X, Y); +} + + +void Fl_WinAPI_Window_Driver::flush_overlay() +{ + Fl_Overlay_Window *oWindow = pWindow->as_overlay_window(); + if (!oWindow) return flush_single(); + + if (!pWindow->shown()) return; + pWindow->make_current(); // make sure fl_gc is non-zero + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; // window not yet created + + int eraseoverlay = (pWindow->damage()&FL_DAMAGE_OVERLAY); + pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); + + if (!i->other_xid) { + i->other_xid = fl_create_offscreen(pWindow->w(), pWindow->h()); + pWindow->clear_damage(FL_DAMAGE_ALL); + } + if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { + fl_clip_region(i->region); i->region = 0; + fl_begin_offscreen(i->other_xid); + fl_graphics_driver->clip_region(0); + draw(); + fl_end_offscreen(); + } + + if (eraseoverlay) fl_clip_region(0); + int X, Y, W, H; fl_clip_box(0, 0, pWindow->w(), pWindow->h(), X, Y, W, H); + if (i->other_xid) fl_copy_offscreen(X, Y, W, H, i->other_xid, X, Y); + + if (oWindow->overlay_ == oWindow) oWindow->draw_overlay(); +} + + void Fl_WinAPI_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) { free_icons(); diff --git a/src/drivers/X11/Fl_X11_Window_Driver.H b/src/drivers/X11/Fl_X11_Window_Driver.H index 02c0de989..126f4b103 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.H +++ b/src/drivers/X11/Fl_X11_Window_Driver.H @@ -75,7 +75,14 @@ public: virtual int decorated_w(); virtual int decorated_h(); + // --- window management virtual void take_focus(); + virtual void flush_single(); + virtual void flush_double(); + virtual void flush_overlay(); + virtual void draw_begin(); + virtual void draw_end(); + virtual void shape(const Fl_Image* img); virtual void draw(); virtual void icons(const Fl_RGB_Image *icons[], int count); diff --git a/src/drivers/X11/Fl_X11_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Window_Driver.cxx index 6ff2158c2..b8ca36480 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Window_Driver.cxx @@ -19,7 +19,9 @@ #include "../../config_lib.h" #include "Fl_X11_Window_Driver.H" + #include <FL/Fl_Shared_Image.H> +#include <FL/Fl_Overlay_Window.H> #include <FL/fl_draw.H> #include <FL/Fl.H> #include <string.h> @@ -32,26 +34,37 @@ #if USE_XDBE #include <X11/extensions/Xdbe.h> -static int can_xdbe(); // forward +// whether the Xdbe extension is usable +// DO NOT call this if the window is not mapped! +static int can_xdbe() +{ + static int tried = 0; + static int use_xdbe = 0; + if (!tried) { + tried = 1; + int event_base, error_base; + fl_open_display(); + if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0; + Drawable root = RootWindow(fl_display,fl_screen); + int numscreens = 1; + XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens); + if (!a) return 0; + for (int j = 0; j < a->count; j++) { + if (a->visinfo[j].visual == fl_visual->visualid) { + use_xdbe = 1; break; + } + } + XdbeFreeVisualInfo(a); + } + return use_xdbe; +} -// class to be used only if Xdbe is used -class Fl_X11_Dbe_Window_Driver : public Fl_X11_Window_Driver { -public: - Fl_X11_Dbe_Window_Driver(Fl_Window *w) : Fl_X11_Window_Driver(w) {} - virtual int double_flush(int eraseoverlay); - virtual void destroy_double_buffer(); -}; #endif // USE_XDBE Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) { -#if USE_XDBE - if (w->as_double_window() && can_xdbe()) - return new Fl_X11_Dbe_Window_Driver(w); - else -#endif - return new Fl_X11_Window_Driver(w); + return new Fl_X11_Window_Driver(w); } @@ -123,63 +136,172 @@ void Fl_X11_Window_Driver::take_focus() Fl_X::activate_window(i->xid); } -#if USE_XDBE -static int can_xdbe() { // whether the Xdbe extension is usable - static int tried; - static int use_xdbe = 0; - if (!tried) { - tried = 1; - int event_base, error_base; - fl_open_display(); - if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0; - Drawable root = RootWindow(fl_display,fl_screen); - int numscreens = 1; - XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens); - if (!a) return 0; - for (int j = 0; j < a->count; j++) { - if (a->visinfo[j].visual == fl_visual->visualid) { - use_xdbe = 1; break; - } +void Fl_X11_Window_Driver::draw_begin() +{ + if (shape_data_) { + if (( shape_data_->lw_ != pWindow->w() || shape_data_->lh_ != pWindow->h() ) && shape_data_->shape_) { + // size of window has changed since last time + combine_mask(); } - XdbeFreeVisualInfo(a); } - return use_xdbe; } -int Fl_X11_Dbe_Window_Driver::double_flush(int eraseoverlay) { + +void Fl_X11_Window_Driver::draw_end() +{ +} + + +void Fl_X11_Window_Driver::flush_single() +{ + if (!pWindow->shown()) return; + pWindow->make_current(); // make sure fl_gc is non-zero + Fl_X *i = Fl_X::i(pWindow); + if (!i) return; + fl_clip_region(i->region); + i->region = 0; + pWindow->draw(); +} + + +void Fl_X11_Window_Driver::flush_double() +{ + if (!pWindow->shown()) return; + pWindow->make_current(); // make sure fl_gc is non-zero Fl_X *i = Fl_X::i(pWindow); - if (!i->other_xid) { - i->other_xid = XdbeAllocateBackBufferName(fl_display, i->xid, XdbeCopied); + if (!i) return; // window not yet created + if (!i->other_xid) { +#if USE_XDBE + if (can_xdbe()) { + i->other_xid = XdbeAllocateBackBufferName(fl_display, fl_xid(pWindow), XdbeCopied); i->backbuffer_bad = 1; - pWindow->clear_damage(FL_DAMAGE_ALL); - } - if (i->backbuffer_bad || eraseoverlay) { + } else +#endif + i->other_xid = fl_create_offscreen(pWindow->w(), pWindow->h()); + pWindow->clear_damage(FL_DAMAGE_ALL); + } +#if USE_XDBE + if (can_xdbe()) { + if (i->backbuffer_bad) { // Make sure we do a complete redraw... if (i->region) {XDestroyRegion(i->region); i->region = 0;} pWindow->clear_damage(FL_DAMAGE_ALL); i->backbuffer_bad = 0; } + // Redraw as needed... if (pWindow->damage()) { fl_clip_region(i->region); i->region = 0; fl_window = i->other_xid; - draw(); + pWindow->draw(); fl_window = i->xid; } + // Copy contents of back buffer to window... XdbeSwapInfo s; - s.swap_window = i->xid; + s.swap_window = fl_xid(pWindow); s.swap_action = XdbeCopied; XdbeSwapBuffers(fl_display, &s, 1); - return 1; + return; + } else +#endif + if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { + fl_clip_region(i->region); i->region = 0; + fl_window = i->other_xid; + pWindow->draw(); + fl_window = i->xid; + } + int X,Y,W,H; fl_clip_box(0,0,pWindow->w(),pWindow->h(),X,Y,W,H); + if (i->other_xid) fl_copy_offscreen(X, Y, W, H, i->other_xid, X, Y); } -void Fl_X11_Dbe_Window_Driver::destroy_double_buffer() { + +void Fl_X11_Window_Driver::flush_overlay() +{ + Fl_Overlay_Window *oWindow = pWindow->as_overlay_window(); + if (!oWindow) return flush_single(); + + if (!pWindow->shown()) return; + pWindow->make_current(); // make sure fl_gc is non-zero Fl_X *i = Fl_X::i(pWindow); - XdbeDeallocateBackBufferName(fl_display, i->other_xid); - i->other_xid = 0; + if (!i) return; // window not yet created + +#ifdef BOXX_BUGS + if (oWindow->overlay_ && oWindow->overlay_ != oWindow && oWindow->overlay_->shown()) { + // all drawing to windows hidden by overlay windows is ignored, fix this + XUnmapWindow(fl_display, fl_xid(oWindow->overlay_)); + flush_double(); + XMapWindow(fl_display, fl_xid(oWindow->overlay_)); + return; + } +#endif + + int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY); + pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); + + if (!i->other_xid) { +#if USE_XDBE + if (can_xdbe()) { + i->other_xid = XdbeAllocateBackBufferName(fl_display, fl_xid(pWindow), XdbeCopied); + i->backbuffer_bad = 1; + } else +#endif + i->other_xid = fl_create_offscreen(pWindow->w(), pWindow->h()); + pWindow->clear_damage(FL_DAMAGE_ALL); + } +#if USE_XDBE + if (can_xdbe()) { + if (i->backbuffer_bad || erase_overlay) { + // Make sure we do a complete redraw... + if (i->region) {XDestroyRegion(i->region); i->region = 0;} + pWindow->clear_damage(FL_DAMAGE_ALL); + i->backbuffer_bad = 0; + } + + // Redraw as needed... + if (pWindow->damage()) { + fl_clip_region(i->region); i->region = 0; + fl_window = i->other_xid; + pWindow->draw(); + fl_window = i->xid; + } + + // Copy contents of back buffer to window... + XdbeSwapInfo s; + s.swap_window = fl_xid(pWindow); + s.swap_action = XdbeCopied; + XdbeSwapBuffers(fl_display, &s, 1); + + pWindow->make_current(); + if (erase_overlay) fl_clip_region(0); + if (oWindow->overlay_ == oWindow) oWindow->draw_overlay(); + + return; + } else +#endif + if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { + fl_clip_region(i->region); i->region = 0; + fl_window = i->other_xid; + pWindow->draw(); + fl_window = i->xid; + } + if (erase_overlay) fl_clip_region(0); + int X,Y,W,H; fl_clip_box(0,0,pWindow->w(),pWindow->h(),X,Y,W,H); + if (i->other_xid) fl_copy_offscreen(X, Y, W, H, i->other_xid, X, Y); + + if (oWindow->overlay_ == oWindow) oWindow->draw_overlay(); } + + + +#if USE_XDBE + +//void Fl_X11_Dbe_Window_Driver::destroy_double_buffer() { +// Fl_X *i = Fl_X::i(pWindow); +// XdbeDeallocateBackBufferName(fl_display, i->other_xid); +// i->other_xid = 0; +//} #endif // USE_XDBE |
