summaryrefslogtreecommitdiff
path: root/src/drivers/X11
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2016-03-13 22:16:37 +0000
committerMatthias Melcher <fltk@matthiasm.com>2016-03-13 22:16:37 +0000
commitb496d18b85917106c48e8e6f74115b3122b603d1 (patch)
tree4d96befa4377a81c89c6a32f4d66220199572938 /src/drivers/X11
parent30756ae3500a62bd8f63b4df3eb3ca8f6b8b0b70 (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/drivers/X11')
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.H7
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.cxx212
2 files changed, 174 insertions, 45 deletions
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