summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Fl.cxx8
-rw-r--r--src/Fl_Window.cxx60
-rw-r--r--src/Fl_Window_shape.cxx (renamed from src/Fl_Shaped_Window.cxx)254
-rw-r--r--src/Fl_cocoa.mm2
-rw-r--r--src/Fl_x.cxx5
-rw-r--r--src/Makefile2
7 files changed, 168 insertions, 165 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f50cda627..b662bb39d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -56,7 +56,6 @@ set(CPPFILES
Fl_Round_Button.cxx
Fl_Scroll.cxx
Fl_Scrollbar.cxx
- Fl_Shaped_Window.cxx
Fl_Shared_Image.cxx
Fl_Single_Window.cxx
Fl_Slider.cxx
@@ -82,6 +81,7 @@ set(CPPFILES
Fl_Window_fullscreen.cxx
Fl_Window_hotspot.cxx
Fl_Window_iconize.cxx
+ Fl_Window_shape.cxx
Fl_Wizard.cxx
Fl_XBM_Image.cxx
Fl_XPM_Image.cxx
diff --git a/src/Fl.cxx b/src/Fl.cxx
index ecfbaaca6..bb1079ca4 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -1596,14 +1596,6 @@ void Fl_Window::hide() {
delete ip;
}
-Fl_Window::~Fl_Window() {
- hide();
- if (xclass_) {
- free(xclass_);
- }
- free_icons();
- delete icon_;
-}
// FL_SHOW and FL_HIDE are called whenever the visibility of this widget
// or any parent changes. We must correctly map/unmap the system's window.
diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx
index 6b8f167de..5c2f5d6d7 100644
--- a/src/Fl_Window.cxx
+++ b/src/Fl_Window.cxx
@@ -52,6 +52,7 @@ void Fl_Window::_Fl_Window() {
resizable(0);
size_range_set = 0;
minw = maxw = minh = maxh = 0;
+ shape_data_ = NULL;
#if FLTK_ABI_VERSION >= 10301
no_fullscreen_x = 0;
no_fullscreen_y = 0;
@@ -78,6 +79,25 @@ Fl_Window::Fl_Window(int W, int H, const char *l)
clear_visible();
}
+Fl_Window::~Fl_Window() {
+ hide();
+ if (xclass_) {
+ free(xclass_);
+ }
+ free_icons();
+ delete icon_;
+ if (shape_data_) {
+ if (shape_data_->todelete_) delete shape_data_->todelete_;
+#if defined(__APPLE__)
+ if (shape_data_->mask) {
+ CGImageRelease(shape_data_->mask);
+ }
+#endif
+ delete shape_data_;
+ }
+}
+
+
/** Returns a pointer to the nearest parent window up the widget hierarchy.
This will return sub-windows if there are any, or the parent window if there's no sub-windows.
If this widget IS the top-level window, NULL is returned.
@@ -133,46 +153,6 @@ int Fl_Window::y_root() const {
return y();
}
-void Fl_Window::draw() {
-
- // The following is similar to Fl_Group::draw(), but ...
- // - we draw the box with x=0 and y=0 instead of x() and y()
- // - we don't draw a label
-
- if (damage() & ~FL_DAMAGE_CHILD) { // draw the entire thing
- draw_box(box(),0,0,w(),h(),color()); // draw box with x/y = 0
- }
- draw_children();
-
-#ifdef __APPLE_QUARTZ__
- // 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 && !parent() && resizable() &&
- (!size_range_set || minh!=maxh || minw!=maxw)) {
- int dx = Fl::box_dw(box())-Fl::box_dx(box());
- int dy = Fl::box_dh(box())-Fl::box_dy(box());
- if (dx<=0) dx = 1;
- if (dy<=0) dy = 1;
- int x1 = w()-dx-1, x2 = x1, y1 = h()-dx-1, y2 = y1;
- Fl_Color c[4] = {
- color(),
- fl_color_average(color(), FL_WHITE, 0.7f),
- fl_color_average(color(), FL_BLACK, 0.6f),
- fl_color_average(color(), FL_BLACK, 0.8f),
- };
- int i;
- for (i=dx; i<12; i++) {
- fl_color(c[i&3]);
- fl_line(x1--, y1, x2, y2--);
- }
- }
-#endif
-
-# if defined(FLTK_USE_CAIRO)
- Fl::cairo_make_current(this); // checkout if an update is necessary
-# endif
-}
-
void Fl_Window::label(const char *name) {
label(name, iconlabel()); // platform dependent
}
diff --git a/src/Fl_Shaped_Window.cxx b/src/Fl_Window_shape.cxx
index d16a23173..7aaa629a4 100644
--- a/src/Fl_Shaped_Window.cxx
+++ b/src/Fl_Window_shape.cxx
@@ -1,7 +1,7 @@
//
// "$Id$"
//
-// Fl_Shaped_Window source file for the Fast Light Tool Kit (FLTK).
+// implementation of Fl_Window::shape(Fl_Image*) for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-2014 by Bill Spitzak and others.
//
@@ -16,10 +16,13 @@
// http://www.fltk.org/str.php
//
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
#include <FL/x.H>
-#include <FL/Fl_Shaped_Window.H>
+#include <FL/Fl_Window.H>
#include <FL/Fl_Bitmap.H>
#include <FL/Fl_Pixmap.H>
+#include <string.h>
#ifdef WIN32
# include <malloc.h> // needed for VisualC2010
@@ -29,36 +32,6 @@
#define ShapeSet 0
#endif
-/** Create a shaped window with the given size and title */
-Fl_Shaped_Window::Fl_Shaped_Window(int w, int h, const char* title)
- : Fl_Window(w, h, title), lw_(0), lh_(0), shape_(0), todelete_(0) {
- type(FL_SHAPED_WINDOW);
- border(false);
-#if defined(__APPLE__)
- mask = NULL;
-#endif
- }
-
-/** Create a shaped window with the given position, size and title */
-Fl_Shaped_Window::Fl_Shaped_Window(int x, int y, int w, int h, const char* title)
- : Fl_Window(x, y, w, h, title), lw_(0), lh_(0), shape_(0), todelete_(0) {
- type(FL_SHAPED_WINDOW);
- border(false);
-#if defined(__APPLE__)
- mask = NULL;
-#endif
- }
-
-/** Destroys the shaped window but not its associated Fl_Image */
-Fl_Shaped_Window::~Fl_Shaped_Window() {
- if (todelete_) delete todelete_;
-#if defined(__APPLE__)
- if (mask) {
- CGImageRelease(mask);
- }
-#endif
-}
-
#if defined(__APPLE__)
@@ -74,17 +47,6 @@ static inline uchar swap_byte(const uchar b) {
return (swapped[b & 0xF] << 4) | swapped[b >> 4];
}
-void Fl_Shaped_Window::draw() {
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if (mask && (CGContextClipToMask != NULL)) CGContextClipToMask(fl_gc, CGRectMake(0,0,w(),h()), mask); // requires Mac OS 10.4
- CGContextSaveGState(fl_gc);
-# endif
- Fl_Window::draw();
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- CGContextRestoreGState(fl_gc);
-# endif
- }
-
#elif defined(WIN32)
static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); }
@@ -165,24 +127,10 @@ static HRGN bitmap2region(Fl_Bitmap* image) {
return hRgn;
}
-void Fl_Shaped_Window::draw() {
- if ((lw_ != w() || lh_ != h()) && shape_) {
- // size of window has changed since last time
- lw_ = w();
- lh_ = h();
- Fl_Bitmap* temp = (Fl_Bitmap*)shape_->copy(lw_, lh_);
- HRGN region = bitmap2region(temp);
- SetWindowRgn(fl_xid(this), region, TRUE); // the system deletes the region when it's no longer needed
- delete temp;
- }
- Fl_Window::draw();
-}
-
#else
-
#ifndef FL_DOXYGEN
-void Fl_Shaped_Window::combine_mask()
+void Fl_Window::combine_mask()
{
typedef void (*XShapeCombineMask_type)(Display*, int, int, int, int, Pixmap, int);
static XShapeCombineMask_type XShapeCombineMask_f = NULL;
@@ -200,9 +148,9 @@ void Fl_Shaped_Window::combine_mask()
XShapeQueryExtension_f(fl_display, &shapeEventBase, &error_base) ) ) XShapeCombineMask_f = NULL;
}
if (!XShapeCombineMask_f) return;
- lw_ = w();
- lh_ = h();
- Fl_Bitmap* temp = (Fl_Bitmap*)shape_->copy(lw_, lh_);
+ shape_data_->lw_ = w();
+ shape_data_->lh_ = h();
+ Fl_Bitmap* temp = (Fl_Bitmap*)shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(this),
(const char*)temp->array,
temp->w(), temp->h());
@@ -212,26 +160,12 @@ void Fl_Shaped_Window::combine_mask()
}
#endif // !FL_DOXYGEN
-void Fl_Shaped_Window::draw() {
- if (( lw_ != w() || lh_ != h() ) && shape_) {
- // size of window has changed since last time
- combine_mask();
- }
- Fl_Window::draw();
-}
-
#endif // __APPLE__
-void Fl_Shaped_Window::shape_bitmap_(Fl_Bitmap* b) {
- if (todelete_) { delete todelete_; todelete_ = NULL; }
- shape_ = b;
- lw_ = lh_ = 0; // so change in mask is detected
+void Fl_Window::shape_bitmap_(Fl_Bitmap* b) {
+ shape_data_->shape_ = b;
#if defined(__APPLE__)
- if (mask) {
- CGImageRelease(mask);
- mask = NULL;
- }
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;
@@ -241,11 +175,11 @@ void Fl_Shaped_Window::shape_bitmap_(Fl_Bitmap* b) {
uchar *last = p + bytes_per_row;
uchar *q = from + (b->h() - 1 - i) * bytes_per_row;
while (p < last) {
- *q++ = swap_byte(~*p++);
+ *q++ = swap_byte(~*p++);
}
}
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, bytes_per_row * b->h(), MyProviderReleaseData);
- mask = CGImageMaskCreate(b->w(), b->h(), 1, 1, bytes_per_row, provider, NULL, false);
+ shape_data_->mask = CGImageMaskCreate(b->w(), b->h(), 1, 1, bytes_per_row, provider, NULL, false);
CFRelease(provider);
}
#endif
@@ -256,16 +190,10 @@ void Fl_Shaped_Window::shape_bitmap_(Fl_Bitmap* b) {
/* the image can be of any depth
offset gives the byte offset from the pixel start to the byte used to construct the shape
*/
-void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
+void Fl_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
int i, d = img->d(), w = img->w(), h = img->h();
- if (todelete_) { delete todelete_; todelete_ = NULL; }
- shape_ = img;
- lw_ = lh_ = 0; // so change in mask is detected
- if (mask) {
- CGImageRelease(mask);
- mask = NULL;
- }
- if (shape_) {
+ 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];
@@ -274,20 +202,20 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int 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;
- }
+ 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);
- mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false);
+ shape_data_->mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false);
CFRelease(provider);
}
}
@@ -297,7 +225,7 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
/* the img image can be of any depth
offset gives the byte offset from the pixel start to the byte used to construct the shape
*/
-void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
+void Fl_Window::shape_alpha_(Fl_RGB_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;
@@ -310,19 +238,19 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
onebit = 1;
for (j = 0; j < w; j++) {
if (d == 3) {
- u = *alpha;
- u += *(alpha+1);
- u += *(alpha+2);
+ 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
+ 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;
+ onebit = 1;
+ *p++ = byte; // store in bitmap one pack of bits
+ byte = 0;
}
alpha += d; // point to alpha value of next pixel
}
@@ -330,19 +258,41 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h);
bitmap->alloc_array = 1;
shape_bitmap_(bitmap);
- todelete_ = bitmap;
+ shape_data_->todelete_ = bitmap;
}
#endif
-void Fl_Shaped_Window::shape_pixmap_(Fl_Pixmap* pixmap) {
+void Fl_Window::shape_pixmap_(Fl_Pixmap* pixmap) {
Fl_RGB_Image* rgba = new Fl_RGB_Image(pixmap);
shape_alpha_(rgba, 3);
delete rgba;
}
-/** Set the window's shape with an image.
+#if FLTK_ABI_VERSION < 10303 && !defined(FL_DOXYGEN)
+shape_data_type* Fl_Window::shape_data_ = NULL;
+#endif
+
+/** Assigns a non-rectangular shape to the window.
+ This function gives an arbitrary shape (not just a rectangular region) to an Fl_Window.
+ An Fl_Image of any dimension can be used as mask; it is rescaled to the window's dimension as needed.
+
+ The layout and widgets inside are unaware of the mask shape, and most will act as though the window's
+ rectangular bounding box is available
+ to them. It is up to you to make sure they adhere to the bounds of their masking shape.
+
+ Platform details:
+ \li On the unix/linux platform, the SHAPE extension of the X server is required.
+ This function does control the shape of Fl_GL_Window instances.
+ \li On the MSWindows platform, this function does nothing with class Fl_GL_Window.
+ \li On the Mac platform, OS version 10.4 or above is required. This function does nothing with class Fl_GL_Window.
+
+ The window borders and caption created by the window system are turned off by default. They
+ can be re-enabled by calling void Fl_Window::border(1).
+
+ A usage example is found at example/shapedwindow.cxx.
+
The \p img argument can be an Fl_Bitmap, Fl_Pixmap or Fl_RGB_Image.
\li With Fl_Bitmap or Fl_Pixmap, the shaped window covers the image part where bitmap bits equal one,
or where the pixmap is not fully transparent.
@@ -355,15 +305,97 @@ void Fl_Shaped_Window::shape_pixmap_(Fl_Pixmap* pixmap) {
are out of the shaped window;
with depths 1 or 3, white and black are in and out of the
shaped window, respectively, and other colors give intermediate masking scores.
+ \version 1.3.3 (and requires compilation with -DFLTK_ABI_VERSION = 10303)
*/
-void Fl_Shaped_Window::shape(const Fl_Image* img) {
+void Fl_Window::shape(const Fl_Image* img) {
+#if FLTK_ABI_VERSION >= 10303
+ if (shape_data_) {
+ if (shape_data_->todelete_) { delete shape_data_->todelete_; }
+#if defined(__APPLE__)
+ if (shape_data_->mask) { CGImageRelease(shape_data_->mask); }
+#endif
+ }
+ else {
+ shape_data_ = new shape_data_type;
+ }
+ memset(shape_data_, 0, sizeof(shape_data_type));
+ border(false);
int d = img->d();
if (d && img->count() >= 2) shape_pixmap_((Fl_Pixmap*)img);
else if (d == 0) shape_bitmap_((Fl_Bitmap*)img);
else if (d == 2 || d == 4) shape_alpha_((Fl_RGB_Image*)img, d - 1);
else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_RGB_Image*)img, 0);
+#endif
}
+void Fl_Window::draw() {
+ if (shape_data_) {
+# if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (shape_data_->mask && (CGContextClipToMask != NULL)) {
+ CGContextClipToMask(fl_gc, CGRectMake(0,0,w(),h()), shape_data_->mask); // requires Mac OS 10.4
+ }
+ CGContextSaveGState(fl_gc);
+#elif defined(WIN32)
+ if ((shape_data_->lw_ != w() || shape_data_->lh_ != h()) && shape_data_->shape_) {
+ // size of window has changed since last time
+ shape_data_->lw_ = w();
+ shape_data_->lh_ = h();
+ Fl_Bitmap* temp = (Fl_Bitmap*)shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
+ HRGN region = bitmap2region(temp);
+ SetWindowRgn(fl_xid(this), region, TRUE); // the system deletes the region when it's no longer needed
+ delete temp;
+ }
+#elif !(defined(__APPLE__) || defined(WIN32))
+ if (( shape_data_->lw_ != w() || shape_data_->lh_ != h() ) && shape_data_->shape_) {
+ // size of window has changed since last time
+ combine_mask();
+ }
+# endif
+ }
+
+ // The following is similar to Fl_Group::draw(), but ...
+ // - we draw the box with x=0 and y=0 instead of x() and y()
+ // - we don't draw a label
+
+ if (damage() & ~FL_DAMAGE_CHILD) { // draw the entire thing
+ draw_box(box(),0,0,w(),h(),color()); // draw box with x/y = 0
+ }
+ draw_children();
+
+#ifdef __APPLE_QUARTZ__
+ // 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 && !parent() && resizable() &&
+ (!size_range_set || minh!=maxh || minw!=maxw)) {
+ int dx = Fl::box_dw(box())-Fl::box_dx(box());
+ int dy = Fl::box_dh(box())-Fl::box_dy(box());
+ if (dx<=0) dx = 1;
+ if (dy<=0) dy = 1;
+ int x1 = w()-dx-1, x2 = x1, y1 = h()-dx-1, y2 = y1;
+ Fl_Color c[4] = {
+ color(),
+ fl_color_average(color(), FL_WHITE, 0.7f),
+ fl_color_average(color(), FL_BLACK, 0.6f),
+ fl_color_average(color(), FL_BLACK, 0.8f),
+ };
+ int i;
+ for (i=dx; i<12; i++) {
+ fl_color(c[i&3]);
+ fl_line(x1--, y1, x2, y2--);
+ }
+ }
+#endif
+# if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if (shape_data_) CGContextRestoreGState(fl_gc);
+# endif
+
+# if defined(FLTK_USE_CAIRO)
+ Fl::cairo_make_current(this); // checkout if an update is necessary
+# endif
+}
+
+
+
//
// End of "$Id$".
//
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 6b8e20ed6..134a677f4 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -2667,7 +2667,7 @@ void Fl_X::make(Fl_Window* w)
[cw setFrameOrigin:crect.origin];
[cw setHasShadow:YES];
[cw setAcceptsMouseMovedEvents:YES];
- if (w->type() == FL_SHAPED_WINDOW) {
+ if (w->shape_data_) {
[cw setOpaque:NO]; // shaped windows must be non opaque
[cw setBackgroundColor:[NSColor clearColor]]; // and with transparent background color
}
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 653938d6b..b1406a4b9 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -35,7 +35,6 @@
# include <FL/fl_draw.H>
# include <FL/Fl_Paged_Device.H>
# include <FL/Fl_Shared_Image.H>
-# include <FL/Fl_Shaped_Window.H>
# include <FL/fl_ask.H>
# include <FL/filename.H>
# include <stdio.h>
@@ -2549,8 +2548,8 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
}
#endif
- if (win->type() == FL_SHAPED_WINDOW) {
- ((Fl_Shaped_Window*)win)->combine_mask();
+ if (win->shape_data_) {
+ win->combine_mask();
}
XMapWindow(fl_display, xp->xid);
if (showit) {
diff --git a/src/Makefile b/src/Makefile
index fb7caf191..0247ed793 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -72,7 +72,6 @@ CPPFILES = \
Fl_Round_Button.cxx \
Fl_Scroll.cxx \
Fl_Scrollbar.cxx \
- Fl_Shaped_Window.cxx \
Fl_Shared_Image.cxx \
Fl_Single_Window.cxx \
Fl_Slider.cxx \
@@ -98,6 +97,7 @@ CPPFILES = \
Fl_Window_fullscreen.cxx \
Fl_Window_hotspot.cxx \
Fl_Window_iconize.cxx \
+ Fl_Window_shape.cxx \
Fl_Wizard.cxx \
Fl_XBM_Image.cxx \
Fl_XPM_Image.cxx \