New, driver-based Fl_Double_Window implementation.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11303 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
7e2dc9daf5
commit
acfeee6d78
@ -40,11 +40,11 @@
|
||||
class FL_EXPORT Fl_Double_Window : public Fl_Window {
|
||||
protected:
|
||||
void flush(int eraseoverlay);
|
||||
public:
|
||||
/**
|
||||
Force double buffering, even if the OS already buffers windows
|
||||
(overlays need that on MacOS and Windows2000)
|
||||
Return non-null if this is an Fl_Overlay_Window object.
|
||||
*/
|
||||
char force_doublebuffering_;
|
||||
virtual Fl_Double_Window *as_overlay_window() {return NULL; }
|
||||
public:
|
||||
void show();
|
||||
void show(int a, char **b) {Fl_Window::show(a,b);}
|
||||
|
@ -53,7 +53,6 @@ class FL_EXPORT Fl_Image_Surface : public Fl_Widget_Surface {
|
||||
private:
|
||||
class Helper;
|
||||
Helper *platform_surface;
|
||||
Fl_Offscreen offscreen();
|
||||
protected:
|
||||
void translate(int x, int y);
|
||||
void untranslate();
|
||||
@ -69,6 +68,7 @@ public:
|
||||
void origin(int x, int y);
|
||||
int printable_rect(int *w, int *h);
|
||||
Fl_Offscreen get_offscreen_before_delete();
|
||||
Fl_Offscreen offscreen();
|
||||
};
|
||||
|
||||
#endif // Fl_Image_Surface_H
|
||||
|
@ -72,6 +72,7 @@ protected:
|
||||
Fl_Overlay_Window(int X, int Y, int W, int H, const char *l=0);
|
||||
public:
|
||||
void show(int a, char **b) {Fl_Double_Window::show(a,b);}
|
||||
virtual Fl_Double_Window *as_overlay_window() {return this; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -40,6 +40,9 @@ public:
|
||||
static Fl_Window_Driver *newWindowDriver(Fl_Window *);
|
||||
|
||||
virtual void take_focus() { }
|
||||
virtual int double_flush(int eraseoverlay);
|
||||
virtual void destroy_double_buffer();
|
||||
void draw() {w->draw();}
|
||||
};
|
||||
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <src/drivers/GDI/Fl_GDI_Copy_Surface.H>
|
||||
|
||||
#elif defined(USE_SDL)
|
||||
#include <src/drivers/SDL/Fl_SDL_Copy_Surface.H>
|
||||
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: implement class Fl_Copy_Surface::Helper for your platform"
|
||||
|
@ -19,58 +19,28 @@
|
||||
Fl_Double_Window implementation.
|
||||
*/
|
||||
|
||||
#include "config_lib.h"
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Overlay_Window.H>
|
||||
#include <FL/Fl_Printer.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/Fl_Window_Driver.H>
|
||||
|
||||
// On systems that support double buffering "naturally" the base
|
||||
// Fl_Window class will probably do double-buffer and this subclass
|
||||
// does nothing.
|
||||
|
||||
#if USE_XDBE
|
||||
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
|
||||
static int use_xdbe;
|
||||
|
||||
static int can_xdbe() {
|
||||
static int tried;
|
||||
if (!tried) {
|
||||
tried = 1;
|
||||
int event_base, error_base;
|
||||
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
|
||||
/*&& a->visinfo[j].perflevel > 0*/) {
|
||||
use_xdbe = 1; break;
|
||||
}
|
||||
}
|
||||
XdbeFreeVisualInfo(a);
|
||||
}
|
||||
return use_xdbe;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Fl_Double_Window::Fl_Double_Window(int W, int H, const char *l)
|
||||
: Fl_Window(W,H,l),
|
||||
force_doublebuffering_(0)
|
||||
: Fl_Window(W,H,l)
|
||||
{
|
||||
type(FL_DOUBLE_WINDOW);
|
||||
}
|
||||
|
||||
|
||||
Fl_Double_Window::Fl_Double_Window(int X, int Y, int W, int H, const char *l)
|
||||
: Fl_Window(X,Y,W,H,l),
|
||||
force_doublebuffering_(0)
|
||||
: Fl_Window(X,Y,W,H,l)
|
||||
{
|
||||
type(FL_DOUBLE_WINDOW);
|
||||
}
|
||||
@ -111,126 +81,68 @@ void Fl_Double_Window::flush() {flush(0);}
|
||||
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);
|
||||
Fl_Window_Driver *myi = (Fl_Window_Driver*)Fl_X::i(this);
|
||||
if (!myi) return; // window not yet created
|
||||
if (!myi->other_xid) {
|
||||
#if USE_XDBE
|
||||
if (can_xdbe()) {
|
||||
myi->other_xid = XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeCopied);
|
||||
myi->backbuffer_bad = 1;
|
||||
} else
|
||||
#endif
|
||||
#if defined(USE_X11) || defined(WIN32)
|
||||
myi->other_xid = fl_create_offscreen(w(), h());
|
||||
clear_damage(FL_DAMAGE_ALL);
|
||||
#elif defined(__APPLE_QUARTZ__) // PORTME: platform double buffering
|
||||
if (force_doublebuffering_) {
|
||||
myi->other_xid = fl_create_offscreen(w(), h());
|
||||
clear_damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: Fl_Window_Driver - call a function to clear any graphics port damage flags"
|
||||
#else
|
||||
# error unsupported platform
|
||||
#endif
|
||||
}
|
||||
#if USE_XDBE
|
||||
if (use_xdbe) {
|
||||
if (myi->backbuffer_bad || eraseoverlay) {
|
||||
// Make sure we do a complete redraw...
|
||||
if (myi->region) {XDestroyRegion(myi->region); myi->region = 0;}
|
||||
clear_damage(FL_DAMAGE_ALL);
|
||||
myi->backbuffer_bad = 0;
|
||||
}
|
||||
|
||||
// Redraw as needed...
|
||||
if (damage()) {
|
||||
fl_clip_region(myi->region); myi->region = 0;
|
||||
fl_window = myi->other_xid;
|
||||
draw();
|
||||
fl_window = myi->xid;
|
||||
}
|
||||
|
||||
// Copy contents of back buffer to window...
|
||||
XdbeSwapInfo s;
|
||||
s.swap_window = fl_xid(this);
|
||||
s.swap_action = XdbeCopied;
|
||||
XdbeSwapBuffers(fl_display, &s, 1);
|
||||
return;
|
||||
} else
|
||||
#endif
|
||||
if (damage() & ~FL_DAMAGE_EXPOSE) {
|
||||
fl_clip_region(myi->region); myi->region = 0;
|
||||
#ifdef WIN32
|
||||
void* _sgc = fl_graphics_driver->gc();
|
||||
HDC gc = fl_makeDC(myi->other_xid);
|
||||
fl_graphics_driver->gc(gc);
|
||||
int save = SaveDC(gc);
|
||||
fl_restore_clip(); // duplicate region into new gc
|
||||
draw();
|
||||
RestoreDC(gc, save);
|
||||
DeleteDC(gc);
|
||||
fl_graphics_driver->gc(_sgc);
|
||||
//# if defined(FLTK_USE_CAIRO)
|
||||
//if Fl::cairo_autolink_context() Fl::cairo_make_current(this); // capture gc changes automatically to update the cairo context adequately
|
||||
//# endif
|
||||
#elif defined(__APPLE__) // PORTME: Fl_Window_Driver - platform double buffering
|
||||
if ( myi->other_xid ) {
|
||||
fl_begin_offscreen( myi->other_xid );
|
||||
fl_clip_region( 0 );
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
} else {
|
||||
draw();
|
||||
}
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: manage double buffered drawing"
|
||||
#else // X:
|
||||
fl_window = myi->other_xid;
|
||||
draw();
|
||||
fl_window = myi->xid;
|
||||
#endif
|
||||
}
|
||||
int retval = myi->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:
|
||||
int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H);
|
||||
if (myi->other_xid) fl_graphics_driver->copy_offscreen(X, Y, W, H, myi->other_xid, X, Y);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
if (!other_xid) {
|
||||
other_xid = fl_create_offscreen(w->w(), w->h());
|
||||
w->clear_damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
if (w->damage() & ~FL_DAMAGE_EXPOSE) {
|
||||
fl_clip_region(region); region = 0;
|
||||
fl_begin_offscreen(other_xid);
|
||||
fl_graphics_driver->clip_region( 0 );
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fl_Double_Window::resize(int X,int Y,int W,int H) {
|
||||
int ow = w();
|
||||
int oh = h();
|
||||
Fl_Window::resize(X,Y,W,H);
|
||||
#if USE_XDBE
|
||||
if (use_xdbe) {
|
||||
Fl_X* myi = Fl_X::i(this);
|
||||
if (myi && myi->other_xid && (ow < w() || oh < h())) {
|
||||
// STR #2152: Deallocate the back buffer to force creation of a new one.
|
||||
XdbeDeallocateBackBufferName(fl_display,myi->other_xid);
|
||||
myi->other_xid = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Fl_X* myi = Fl_X::i(this);
|
||||
if (myi && myi->other_xid && (ow != w() || oh != h())) {
|
||||
fl_delete_offscreen(myi->other_xid);
|
||||
myi->other_xid = 0;
|
||||
}
|
||||
Fl_Window_Driver *myi = (Fl_Window_Driver*)Fl_X::i(this);
|
||||
if (myi && myi->other_xid && (ow < w() || oh < h()))
|
||||
myi->destroy_double_buffer();
|
||||
}
|
||||
|
||||
void Fl_Double_Window::hide() {
|
||||
Fl_X* myi = Fl_X::i(this);
|
||||
Fl_Window_Driver *myi = (Fl_Window_Driver*)Fl_X::i(this);
|
||||
if (myi && myi->other_xid) {
|
||||
#if USE_XDBE
|
||||
if (!use_xdbe)
|
||||
#endif
|
||||
fl_delete_offscreen(myi->other_xid);
|
||||
myi->destroy_double_buffer();
|
||||
}
|
||||
Fl_Window::hide();
|
||||
}
|
||||
|
||||
void Fl_Window_Driver::destroy_double_buffer() {
|
||||
/* This is a working, platform-independent implementation.
|
||||
Some platforms may re-implement it for their own logic:
|
||||
- on Xlib, it is reimplemented if the Xdbe extension is available.
|
||||
*/
|
||||
fl_delete_offscreen(other_xid);
|
||||
other_xid = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
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
|
||||
@ -245,7 +157,6 @@ Fl_Overlay_Window::Fl_Overlay_Window(int W, int H, const char *l)
|
||||
: Fl_Double_Window(W,H,l)
|
||||
{
|
||||
overlay_ = 0;
|
||||
force_doublebuffering_=1;
|
||||
image(0);
|
||||
}
|
||||
|
||||
@ -254,7 +165,6 @@ Fl_Overlay_Window::Fl_Overlay_Window(int X, int Y, int W, int H, const char *l)
|
||||
: Fl_Double_Window(X,Y,W,H,l)
|
||||
{
|
||||
overlay_ = 0;
|
||||
force_doublebuffering_=1;
|
||||
image(0);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <src/drivers/GDI/Fl_GDI_Image_Surface.H>
|
||||
|
||||
#elif defined(USE_SDL)
|
||||
#include <src/drivers/SDL/Fl_SDL_Image_Surface.H>
|
||||
|
||||
|
||||
#elif defined(FL_PORTING)
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include "../../config_lib.h"
|
||||
#include "Fl_Cocoa_Window_Driver.h"
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
|
||||
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
|
||||
@ -41,6 +43,15 @@ void Fl_Cocoa_Window_Driver::take_focus()
|
||||
set_key_window();
|
||||
}
|
||||
|
||||
int Fl_Cocoa_Window_Driver::double_flush(int eraseoverlay) {
|
||||
if ( ((Fl_Double_Window*)w)->as_overlay_window() ) {
|
||||
Fl_Window_Driver::double_flush(eraseoverlay);
|
||||
} else {
|
||||
draw();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
|
@ -47,6 +47,7 @@ class FL_EXPORT Fl_Cocoa_Window_Driver : public Fl_Window_Driver
|
||||
public:
|
||||
Fl_Cocoa_Window_Driver(Fl_Window*);
|
||||
virtual void take_focus();
|
||||
int double_flush(int eraseoverlay);
|
||||
};
|
||||
|
||||
|
||||
|
@ -19,11 +19,29 @@
|
||||
|
||||
#include "../../config_lib.h"
|
||||
#include "Fl_X11_Window_Driver.H"
|
||||
#include <FL/fl_draw.H>
|
||||
#if USE_XDBE
|
||||
#include <X11/extensions/Xdbe.h>
|
||||
static int can_xdbe(); // forward
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
|
||||
{
|
||||
return new Fl_X11_Window_Driver(w);
|
||||
#if USE_XDBE
|
||||
if (can_xdbe()) // strictly necessary only for Fl_Double_Window, but does no harm for Fl_Window
|
||||
return new Fl_X11_Dbe_Window_Driver(w);
|
||||
else
|
||||
#endif
|
||||
return new Fl_X11_Window_Driver(w);
|
||||
}
|
||||
|
||||
|
||||
@ -41,6 +59,62 @@ void Fl_X11_Window_Driver::take_focus()
|
||||
Fl_X::activate_window(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;
|
||||
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;
|
||||
}
|
||||
|
||||
int Fl_X11_Dbe_Window_Driver::double_flush(int eraseoverlay) {
|
||||
if (!other_xid) {
|
||||
other_xid = XdbeAllocateBackBufferName(fl_display, xid, XdbeCopied);
|
||||
backbuffer_bad = 1;
|
||||
w->clear_damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
if (backbuffer_bad || eraseoverlay) {
|
||||
// Make sure we do a complete redraw...
|
||||
if (region) {XDestroyRegion(region); region = 0;}
|
||||
w->clear_damage(FL_DAMAGE_ALL);
|
||||
backbuffer_bad = 0;
|
||||
}
|
||||
// Redraw as needed...
|
||||
if (w->damage()) {
|
||||
fl_clip_region(region); region = 0;
|
||||
fl_window = other_xid;
|
||||
draw();
|
||||
fl_window = xid;
|
||||
}
|
||||
// Copy contents of back buffer to window...
|
||||
XdbeSwapInfo s;
|
||||
s.swap_window = xid;
|
||||
s.swap_action = XdbeCopied;
|
||||
XdbeSwapBuffers(fl_display, &s, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Fl_X11_Dbe_Window_Driver::destroy_double_buffer() {
|
||||
XdbeDeallocateBackBufferName(fl_display, other_xid);
|
||||
other_xid = 0;
|
||||
}
|
||||
|
||||
#endif // USE_XDBE
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
|
Loading…
Reference in New Issue
Block a user