summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2016-03-10 17:19:34 +0000
committerManolo Gouy <Manolo>2016-03-10 17:19:34 +0000
commitd4768073fa67e7f78872bc80f4dff1dd8aa32f69 (patch)
treee49adba4ced816e851cbb74e5cac4f9a995f4189 /src/drivers
parent79f79d292c8ffe7a172237c614345a7bc667de80 (diff)
Implement non-rectangular windows using the Window Driver mechanism.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11336 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H17
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx134
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H12
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx151
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.H15
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.cxx112
6 files changed, 437 insertions, 4 deletions
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
index b0c756aa1..05e0cd93a 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
+++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
@@ -26,7 +26,10 @@
#define FL_COCOA_WINDOW_DRIVER_H
#include <FL/Fl_Window_Driver.H>
+#include <ApplicationServices/ApplicationServices.h>
+class Fl_Image;
+class Fl_Window;
/*
Move everything here that manages the native window interface.
@@ -41,12 +44,26 @@
? where do we handle the interface between OpenGL/DirectX and Cocoa/WIN32/Glx?
*/
+struct Fl_Window_Driver::shape_data_type {
+ int lw_; ///< width of shape image
+ int lh_; ///< height of shape image
+ Fl_Image* shape_; ///< shape image
+ typedef struct CGImage* CGImageRef;
+ CGImageRef mask;
+ Fl_Bitmap *todelete_; ///< auxiliary bitmap image
+};
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();
virtual void take_focus();
+ virtual void shape(const Fl_Image* img);
+ virtual void draw();
};
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
index 4764390ab..8a3644bb1 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
+++ b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
@@ -21,6 +21,7 @@
#include "Fl_Cocoa_Window_Driver.h"
#include <FL/Fl_Double_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 {
@@ -46,6 +47,16 @@ Fl_Cocoa_Window_Driver::Fl_Cocoa_Window_Driver(Fl_Window *win)
{
}
+Fl_Cocoa_Window_Driver::~Fl_Cocoa_Window_Driver()
+{
+ if (shape_data_) {
+ if (shape_data_->todelete_) delete shape_data_->todelete_;
+ if (shape_data_->mask) {
+ CGImageRelease(shape_data_->mask);
+ }
+ delete shape_data_;
+ }
+}
extern Fl_Window *fl_xfocus;
@@ -56,6 +67,129 @@ void Fl_Cocoa_Window_Driver::take_focus()
if (x) x->set_key_window();
}
+
+static void MyProviderReleaseData (void *info, const void *data, size_t size) {
+ delete[] (uchar*)data;
+}
+
+// bitwise inversion of all 4-bit quantities
+static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
+
+static inline uchar swap_byte(const uchar b) {
+ // reverse the order of bits of byte b: 1->8 becomes 8->1
+ return (swapped[b & 0xF] << 4) | swapped[b >> 4];
+}
+
+
+void Fl_Cocoa_Window_Driver::shape_bitmap_(Fl_Image* b) {
+ shape_data_->shape_ = b;
+ if (b) {
+ // complement mask bits and perform bitwise inversion of all bytes and also reverse top and bottom
+ int bytes_per_row = (b->w() + 7)/8;
+ uchar *from = new uchar[bytes_per_row * b->h()];
+ for (int i = 0; i < b->h(); i++) {
+ uchar *p = (uchar*)(*b->data()) + bytes_per_row * i;
+ uchar *last = p + bytes_per_row;
+ uchar *q = from + (b->h() - 1 - i) * bytes_per_row;
+ while (p < last) {
+ *q++ = swap_byte(~*p++);
+ }
+ }
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, bytes_per_row * b->h(), MyProviderReleaseData);
+ shape_data_->mask = CGImageMaskCreate(b->w(), b->h(), 1, 1, bytes_per_row, provider, NULL, false);
+ CFRelease(provider);
+ }
+}
+
+
+void Fl_Cocoa_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
+ int i, d = img->d(), w = img->w(), h = img->h();
+ shape_data_->shape_ = img;
+ if (shape_data_->shape_) {
+ // reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits
+ int bytes_per_row = w * d;
+ uchar *from = new uchar[w * h];
+ for ( i = 0; i < h; i++) {
+ uchar *p = (uchar*)(*img->data()) + bytes_per_row * i + offset;
+ uchar *last = p + bytes_per_row;
+ uchar *q = from + (h - 1 - i) * w;
+ while (p < last) {
+ if (d == 3) {
+ unsigned u = *p++;
+ u += *p++;
+ u += *p++;
+ *q++ = ~(u/3);
+ }
+ else {
+ *q++ = ~(*p);
+ p += d;
+ }
+ }
+ }
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData);
+ shape_data_->mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false);
+ CFRelease(provider);
+ }
+}
+
+
+void Fl_Cocoa_Window_Driver::shape(const Fl_Image* img) {
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (shape_data_) {
+ if (shape_data_->todelete_) { delete shape_data_->todelete_; }
+ if (shape_data_->mask) { CGImageRelease(shape_data_->mask); }
+ }
+ else {
+ shape_data_ = new shape_data_type;
+ }
+ memset(shape_data_, 0, sizeof(shape_data_type));
+ pWindow->border(false);
+ int d = img->d();
+ if (d && img->count() >= 2) shape_pixmap_((Fl_Image*)img);
+ else if (d == 0) shape_bitmap_((Fl_Image*)img);
+ else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
+ else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
+#endif
+}
+
+
+void Fl_Cocoa_Window_Driver::draw()
+{
+ CGContextRef gc = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc();
+ if (shape_data_) {
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (shape_data_->mask && (&CGContextClipToMask != NULL)) {
+ CGContextClipToMask(gc, CGRectMake(0,0, pWindow->w(), pWindow->h()), shape_data_->mask); // requires Mac OS 10.4
+ }
+ CGContextSaveGState(gc);
+# endif
+ }
+ Fl_Window_Driver::draw();
+ // 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 && gc && !pWindow->parent() && pWindow->resizable() ) {
+ 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(gc);
+# endif
+}
+
//
// End of "$Id$".
//
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
index 8a4998753..252550a56 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
@@ -42,10 +42,22 @@
? where do we handle the interface between OpenGL/DirectX and Cocoa/WIN32/Glx?
*/
+struct Fl_Window_Driver::shape_data_type {
+ int lw_; ///< width of shape image
+ int lh_; ///< height of shape image
+ Fl_Image* shape_; ///< shape image
+ Fl_Bitmap *todelete_; ///< auxiliary bitmap image
+};
+
class FL_EXPORT Fl_WinAPI_Window_Driver : public Fl_Window_Driver
{
+private:
+ void shape_bitmap_(Fl_Image* b);
+ void shape_alpha_(Fl_Image* img, int offset);
public:
Fl_WinAPI_Window_Driver(Fl_Window*);
+ virtual void shape(const Fl_Image* img);
+ virtual void draw();
};
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
index c8d18a6c5..4947ff6e2 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
@@ -19,7 +19,7 @@
#include "../../config_lib.h"
#include "Fl_WinAPI_Window_Driver.H"
-
+#include <windows.h>
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
{
@@ -32,6 +32,155 @@ Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win)
{
}
+void Fl_WinAPI_Window_Driver::shape_bitmap_(Fl_Image* b) {
+ shape_data_->shape_ = b;
+}
+
+void Fl_WinAPI_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
+ int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8;
+ unsigned u;
+ uchar byte, onebit;
+ // build an Fl_Bitmap covering the non-fully transparent/black part of the image
+ const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap
+ const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels
+ for (i = 0; i < h; i++) {
+ uchar *p = (uchar*)bits + i * bytesperrow;
+ byte = 0;
+ onebit = 1;
+ for (j = 0; j < w; j++) {
+ if (d == 3) {
+ u = *alpha;
+ u += *(alpha+1);
+ u += *(alpha+2);
+ }
+ else u = *alpha;
+ if (u > 0) { // if the pixel is not fully transparent/black
+ byte |= onebit; // turn on the corresponding bit of the bitmap
+ }
+ onebit = onebit << 1; // move the single set bit one position to the left
+ if (onebit == 0 || j == w-1) {
+ onebit = 1;
+ *p++ = byte; // store in bitmap one pack of bits
+ byte = 0;
+ }
+ alpha += d; // point to alpha value of next pixel
+ }
+ }
+ Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h);
+ bitmap->alloc_array = 1;
+ shape_bitmap_(bitmap);
+ shape_data_->todelete_ = bitmap;
+}
+
+void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) {
+ if (shape_data_) {
+ if (shape_data_->todelete_) { delete shape_data_->todelete_; }
+ }
+ else {
+ shape_data_ = new shape_data_type;
+ }
+ memset(shape_data_, 0, sizeof(shape_data_type));
+ pWindow->border(false);
+ int d = img->d();
+ if (d && img->count() >= 2) shape_pixmap_((Fl_Image*)img);
+ else if (d == 0) shape_bitmap_((Fl_Image*)img);
+ else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
+ else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
+}
+
+
+static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); }
+
+static HRGN bitmap2region(Fl_Image* image) {
+ HRGN hRgn = 0;
+ /* Does this need to be dynamically determined, perhaps? */
+ const int ALLOC_UNIT = 100;
+ DWORD maxRects = ALLOC_UNIT;
+
+ RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects));
+ pData->rdh.dwSize = sizeof(RGNDATAHEADER);
+ pData->rdh.iType = RDH_RECTANGLES;
+ pData->rdh.nCount = pData->rdh.nRgnSize = 0;
+ SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
+
+ const int bytesPerLine = (image->w() + 7)/8;
+ BYTE* p, *data = (BYTE*)*image->data();
+ for (int y = 0; y < image->h(); y++) {
+ // each row, left to right
+ for (int x = 0; x < image->w(); x++) {
+ int x0 = x;
+ while (x < image->w()) {
+ p = data + x / 8;
+ if (!((*p) & bit(x))) break; // transparent pixel
+ x++;
+ }
+ if (x > x0) {
+ RECT *pr;
+ /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
+ * in the region
+ */
+ if (pData->rdh.nCount >= maxRects) {
+ maxRects += ALLOC_UNIT;
+ pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER)
+ + (sizeof(RECT)*maxRects));
+ }
+ pr = (RECT*)&pData->Buffer;
+ SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
+ if (x0 < pData->rdh.rcBound.left)
+ pData->rdh.rcBound.left = x0;
+ if (y < pData->rdh.rcBound.top)
+ pData->rdh.rcBound.top = y;
+ if (x > pData->rdh.rcBound.right)
+ pData->rdh.rcBound.right = x;
+ if (y+1 > pData->rdh.rcBound.bottom)
+ pData->rdh.rcBound.bottom = y+1;
+ pData->rdh.nCount++;
+ /* On Windows98, ExtCreateRegion() may fail if the
+ * number of rectangles is too large (ie: >
+ * 4000). Therefore, we have to create the region by
+ * multiple steps.
+ */
+ if (pData->rdh.nCount == 2000) {
+ HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
+ + (sizeof(RECT)*maxRects), pData);
+ if (hRgn) {
+ CombineRgn(hRgn, hRgn, h, RGN_OR);
+ DeleteObject(h);
+ } else
+ hRgn = h;
+ pData->rdh.nCount = 0;
+ SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
+ }
+ }
+ }
+ /* Go to next row */
+ data += bytesPerLine;
+ }
+ /* Create or extend the region with the remaining rectangles*/
+ HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
+ + (sizeof(RECT)*maxRects), pData);
+ if (hRgn) {
+ CombineRgn(hRgn, hRgn, h, RGN_OR);
+ DeleteObject(h);
+ } else hRgn = h;
+ free(pData); // I've created the region so I can free this now, right?
+ return hRgn;
+}
+
+
+void Fl_WinAPI_Window_Driver::draw() {
+ 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
+ shape_data_->lw_ = pWindow->w();
+ shape_data_->lh_ = pWindow->h();
+ Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
+ HRGN region = bitmap2region(temp);
+ SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed
+ delete temp;
+ }
+ } Fl_Window_Driver::draw();
+}
//
// End of "$Id$".
diff --git a/src/drivers/X11/Fl_X11_Window_Driver.H b/src/drivers/X11/Fl_X11_Window_Driver.H
index 36c5b67cb..458d1bd1c 100644
--- a/src/drivers/X11/Fl_X11_Window_Driver.H
+++ b/src/drivers/X11/Fl_X11_Window_Driver.H
@@ -42,15 +42,28 @@
? where do we handle the interface between OpenGL/DirectX and Cocoa/WIN32/Glx?
*/
+struct Fl_Window_Driver::shape_data_type {
+ int lw_; ///< width of shape image
+ int lh_; ///< height of shape image
+ Fl_Image* shape_; ///< shape image
+ Fl_Bitmap *todelete_; ///< auxiliary bitmap image
+};
+
class FL_EXPORT Fl_X11_Window_Driver : public Fl_Window_Driver
{
+ friend class Fl_X;
+private:
+ void combine_mask();
+ void shape_bitmap_(Fl_Image* b);
+ void shape_alpha_(Fl_Image* img, int offset);
public:
Fl_X11_Window_Driver(Fl_Window*);
virtual void take_focus();
+ virtual void shape(const Fl_Image* img);
+ virtual void draw();
};
-
#endif // FL_X11_WINDOW_DRIVER_H
//
diff --git a/src/drivers/X11/Fl_X11_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Window_Driver.cxx
index 10988bd7c..efaa31851 100644
--- a/src/drivers/X11/Fl_X11_Window_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Window_Driver.cxx
@@ -20,8 +20,16 @@
#include "../../config_lib.h"
#include "Fl_X11_Window_Driver.H"
#include <FL/fl_draw.H>
+#include <string.h>
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#define ShapeBounding 0
+#define ShapeSet 0
+
#if USE_XDBE
#include <X11/extensions/Xdbe.h>
+
static int can_xdbe(); // forward
// class to be used only if Xdbe is used
@@ -31,7 +39,7 @@ public:
virtual int double_flush(int eraseoverlay);
virtual void destroy_double_buffer();
};
-#endif
+#endif // USE_XDBE
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
@@ -68,6 +76,7 @@ static int can_xdbe() { // whether the Xdbe extension is usable
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;
@@ -116,9 +125,108 @@ void Fl_X11_Dbe_Window_Driver::destroy_double_buffer() {
XdbeDeallocateBackBufferName(fl_display, i->other_xid);
i->other_xid = 0;
}
-
#endif // USE_XDBE
+
+void Fl_X11_Window_Driver::shape_bitmap_(Fl_Image* b) {
+ shape_data_->shape_ = b;
+}
+
+void Fl_X11_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
+ int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8;
+ unsigned u;
+ uchar byte, onebit;
+ // build an Fl_Bitmap covering the non-fully transparent/black part of the image
+ const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap
+ const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels
+ for (i = 0; i < h; i++) {
+ uchar *p = (uchar*)bits + i * bytesperrow;
+ byte = 0;
+ onebit = 1;
+ for (j = 0; j < w; j++) {
+ if (d == 3) {
+ u = *alpha;
+ u += *(alpha+1);
+ u += *(alpha+2);
+ }
+ else u = *alpha;
+ if (u > 0) { // if the pixel is not fully transparent/black
+ byte |= onebit; // turn on the corresponding bit of the bitmap
+ }
+ onebit = onebit << 1; // move the single set bit one position to the left
+ if (onebit == 0 || j == w-1) {
+ onebit = 1;
+ *p++ = byte; // store in bitmap one pack of bits
+ byte = 0;
+ }
+ alpha += d; // point to alpha value of next pixel
+ }
+ }
+ Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h);
+ bitmap->alloc_array = 1;
+ shape_bitmap_(bitmap);
+ shape_data_->todelete_ = bitmap;
+}
+
+void Fl_X11_Window_Driver::shape(const Fl_Image* img) {
+ if (shape_data_) {
+ if (shape_data_->todelete_) { delete shape_data_->todelete_; }
+ }
+ else {
+ shape_data_ = new shape_data_type;
+ }
+ memset(shape_data_, 0, sizeof(shape_data_type));
+ pWindow->border(false);
+ int d = img->d();
+ if (d && img->count() >= 2) shape_pixmap_((Fl_Image*)img);
+ else if (d == 0) shape_bitmap_((Fl_Image*)img);
+ else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
+ else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
+}
+
+
+void Fl_X11_Window_Driver::combine_mask()
+{
+ typedef void (*XShapeCombineMask_type)(Display*, int, int, int, int, Pixmap, int);
+ static XShapeCombineMask_type XShapeCombineMask_f = NULL;
+ static int beenhere = 0;
+ typedef Bool (*XShapeQueryExtension_type)(Display*, int*, int*);
+ if (!beenhere) {
+ beenhere = 1;
+#if HAVE_DLSYM && HAVE_DLFCN_H
+ fl_open_display();
+ void *handle = dlopen(NULL, RTLD_LAZY); // search symbols in executable
+ XShapeQueryExtension_type XShapeQueryExtension_f = (XShapeQueryExtension_type)dlsym(handle, "XShapeQueryExtension");
+ XShapeCombineMask_f = (XShapeCombineMask_type)dlsym(handle, "XShapeCombineMask");
+ // make sure that the X server has the SHAPE extension
+ int error_base, shapeEventBase;
+ if ( !( XShapeQueryExtension_f && XShapeCombineMask_f &&
+ XShapeQueryExtension_f(fl_display, &shapeEventBase, &error_base) ) ) XShapeCombineMask_f = NULL;
+#endif
+ }
+ if (!XShapeCombineMask_f) return;
+ shape_data_->lw_ = pWindow->w();
+ shape_data_->lh_ = pWindow->h();
+ Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
+ Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(pWindow),
+ (const char*)*temp->data(),
+ temp->w(), temp->h());
+ XShapeCombineMask_f(fl_display, fl_xid(pWindow), ShapeBounding, 0, 0, pbitmap, ShapeSet);
+ if (pbitmap != None) XFreePixmap(fl_display, pbitmap);
+ delete temp;
+}
+
+
+void Fl_X11_Window_Driver::draw() {
+ 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();
+ }
+ }
+ Fl_Window_Driver::draw();
+}
+
//
// End of "$Id$".
//