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
This commit is contained in:
parent
79f79d292c
commit
d4768073fa
@ -41,6 +41,7 @@ class Fl_Overlay_Window;
|
||||
class FL_EXPORT Fl_Double_Window : public Fl_Window {
|
||||
protected:
|
||||
void flush(int eraseoverlay);
|
||||
Fl_Double_Window(int X, int Y, int W, int H, const char *l, Fl_Window_Driver *driver);
|
||||
public:
|
||||
/**
|
||||
Return non-null if this is an Fl_Overlay_Window object.
|
||||
|
@ -101,42 +101,6 @@ class FL_EXPORT Fl_Window : public Fl_Group {
|
||||
// cursor stuff
|
||||
Fl_Cursor cursor_default;
|
||||
|
||||
protected:
|
||||
/** Data supporting a non-rectangular window shape */
|
||||
struct shape_data_type {
|
||||
int lw_; ///< width of shape image
|
||||
int lh_; ///< height of shape image
|
||||
Fl_Image* shape_; ///< shape image
|
||||
#if defined(__APPLE__) // PORTME: Fl_Window_Driver - per-window shape information, move to Fl_X/Fl_Window_Driver
|
||||
typedef struct CGImage* CGImageRef;
|
||||
CGImageRef mask;
|
||||
#elif defined(WIN32)
|
||||
// not needed
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: define storage for a window mask here if needed"
|
||||
#else // X11
|
||||
// not needed
|
||||
#endif
|
||||
Fl_Bitmap *todelete_; ///< auxiliary bitmap image
|
||||
};
|
||||
|
||||
shape_data_type *shape_data_; ///< non-null means the window has a non-rectangular shape
|
||||
private:
|
||||
void shape_bitmap_(Fl_Image* b);
|
||||
void shape_alpha_(Fl_Image* img, int offset);
|
||||
void shape_pixmap_(Fl_Image* pixmap);
|
||||
public:
|
||||
void shape(const Fl_Image* img);
|
||||
/** Set the window's shape with an Fl_Image.
|
||||
\see void shape(const Fl_Image* img)
|
||||
*/
|
||||
inline void shape(const Fl_Image& b) { shape(&b); }
|
||||
#if defined(WIN32) || defined(__APPLE__) || defined(FL_DOXYGEN) // PORTME: Fl_Window_Driver - per-window shape
|
||||
#elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: do you need a combine_mask() function in Fl_Window?"
|
||||
#else // X11
|
||||
void combine_mask(void);
|
||||
#endif
|
||||
private:
|
||||
|
||||
void size_range_();
|
||||
@ -152,7 +116,7 @@ protected:
|
||||
|
||||
/** Stores the last window that was made current. See current() const */
|
||||
static Fl_Window *current_;
|
||||
virtual void draw();
|
||||
void draw();
|
||||
/** Forces the window to be drawn, this window is also made current and calls draw(). */
|
||||
virtual void flush();
|
||||
|
||||
@ -180,6 +144,7 @@ protected:
|
||||
|
||||
void free_icons();
|
||||
|
||||
Fl_Window(int x, int y, int w, int h, const char* title, Fl_Window_Driver *driver);
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -640,9 +605,13 @@ public:
|
||||
Fl_Window_Driver *driver() { return pWindowDriver; }
|
||||
|
||||
/**
|
||||
Return non-null if this is an Fl_Overlay_Window object.
|
||||
Return non-null if this is an Fl_Double_Window object.
|
||||
*/
|
||||
virtual Fl_Double_Window *as_double_window() {return NULL; }
|
||||
virtual Fl_Double_Window *as_double_window() {return NULL;}
|
||||
void shape(const Fl_Image* img);
|
||||
void shape(const Fl_Image& b) ;
|
||||
int is_shaped();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -28,14 +28,18 @@
|
||||
|
||||
|
||||
class Fl_Window;
|
||||
class Fl_Image;
|
||||
|
||||
|
||||
/**
|
||||
\brief A base class for platform specific window handling code.
|
||||
*/
|
||||
class FL_EXPORT Fl_Window_Driver {
|
||||
friend class Fl_Window;
|
||||
protected:
|
||||
Fl_Window *pWindow;
|
||||
struct shape_data_type;
|
||||
shape_data_type *shape_data_; ///< non-null means the window has a non-rectangular shape
|
||||
public:
|
||||
Fl_Window_Driver(Fl_Window *);
|
||||
virtual ~Fl_Window_Driver();
|
||||
@ -47,7 +51,10 @@ public:
|
||||
virtual void take_focus() { }
|
||||
virtual int double_flush(int eraseoverlay);
|
||||
virtual void destroy_double_buffer();
|
||||
void draw();
|
||||
virtual void draw();
|
||||
void shape_pixmap_(Fl_Image* pixmap);
|
||||
virtual void shape(const Fl_Image* img) {}
|
||||
virtual void shape_alpha_(Fl_Image* img, int offset) {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -755,8 +755,7 @@ inline void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int
|
||||
\returns 1 if true alpha blending supported by platform
|
||||
\returns 0 not supported so FLTK will use screen door transparency
|
||||
*/
|
||||
/* note: doxygen comment here to avoid triplication in os-speciic files */
|
||||
FL_EXPORT char fl_can_do_alpha_blending();
|
||||
inline char fl_can_do_alpha_blending() {return Fl_Display_Device::display_device()->driver()->can_do_alpha_blending();}
|
||||
|
||||
/**
|
||||
Reads an RGB(A) image from the current window or off-screen buffer.
|
||||
|
@ -84,7 +84,6 @@ 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
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#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>
|
||||
@ -33,14 +32,20 @@
|
||||
|
||||
|
||||
Fl_Double_Window::Fl_Double_Window(int W, int H, const char *l)
|
||||
: Fl_Window(W,H,l)
|
||||
: Fl_Window(0, 0, W, H, l, Fl_Window_Driver::newWindowDriver(this))
|
||||
{
|
||||
type(FL_DOUBLE_WINDOW);
|
||||
clear_flag(FORCE_POSITION);
|
||||
}
|
||||
|
||||
|
||||
Fl_Double_Window::Fl_Double_Window(int X, int Y, int W, int H, const char *l)
|
||||
: Fl_Window(X,Y,W,H,l)
|
||||
: Fl_Window(X,Y,W,H,l, Fl_Window_Driver::newWindowDriver(this))
|
||||
{
|
||||
type(FL_DOUBLE_WINDOW);
|
||||
}
|
||||
|
||||
Fl_Double_Window::Fl_Double_Window(int x, int y, int w, int h, const char* title, Fl_Window_Driver *driver) : Fl_Window(x,y,w,h,title, driver)
|
||||
{
|
||||
type(FL_DOUBLE_WINDOW);
|
||||
}
|
||||
@ -51,19 +56,9 @@ void Fl_Double_Window::show() {
|
||||
}
|
||||
|
||||
|
||||
/** see fl_copy_offscreen() */
|
||||
void Fl_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy)
|
||||
{
|
||||
fl_begin_offscreen(pixmap);
|
||||
uchar *img = fl_read_image(NULL, srcx, srcy, w, h, 0);
|
||||
fl_end_offscreen();
|
||||
fl_draw_image(img, x, y, w, h, 3, 0);
|
||||
delete[] img;
|
||||
}
|
||||
|
||||
char fl_can_do_alpha_blending() {
|
||||
/*char fl_can_do_alpha_blending() {
|
||||
return Fl_Display_Device::display_device()->driver()->can_do_alpha_blending();
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
Forces the window to be redrawn.
|
||||
@ -94,29 +89,6 @@ void Fl_Double_Window::flush(int eraseoverlay) {
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
void Fl_Double_Window::resize(int X,int Y,int W,int H) {
|
||||
int ow = w();
|
||||
@ -135,16 +107,6 @@ void Fl_Double_Window::hide() {
|
||||
Fl_Window::hide();
|
||||
}
|
||||
|
||||
void Fl_Window_Driver::destroy_double_buffer() {
|
||||
Fl_X *i = Fl_X::i(pWindow);
|
||||
/* 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(i->other_xid);
|
||||
i->other_xid = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The destructor <I>also deletes all the children</I>. This allows a
|
||||
@ -156,20 +118,6 @@ Fl_Double_Window::~Fl_Double_Window() {
|
||||
}
|
||||
|
||||
|
||||
Fl_Overlay_Window::Fl_Overlay_Window(int W, int H, const char *l)
|
||||
: Fl_Double_Window(W,H,l)
|
||||
{
|
||||
overlay_ = 0;
|
||||
image(0);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
image(0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
@ -61,6 +61,16 @@ int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** see fl_copy_offscreen() */
|
||||
void Fl_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy)
|
||||
{
|
||||
fl_begin_offscreen(pixmap);
|
||||
uchar *img = fl_read_image(NULL, srcx, srcy, w, h, 0);
|
||||
fl_end_offscreen();
|
||||
fl_draw_image(img, x, y, w, h, 3, 0);
|
||||
delete[] img;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
|
@ -26,6 +26,23 @@
|
||||
#include <FL/Fl_Overlay_Window.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/Fl_Window_Driver.H>
|
||||
|
||||
|
||||
Fl_Overlay_Window::Fl_Overlay_Window(int W, int H, const char *l)
|
||||
: Fl_Double_Window(0,0,W,H,l,Fl_Window_Driver::newWindowDriver(this))
|
||||
{
|
||||
overlay_ = 0;
|
||||
image(0);
|
||||
clear_flag(FORCE_POSITION);
|
||||
}
|
||||
|
||||
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,Fl_Window_Driver::newWindowDriver(this))
|
||||
{
|
||||
overlay_ = 0;
|
||||
image(0);
|
||||
}
|
||||
|
||||
void Fl_Overlay_Window::show() {
|
||||
Fl_Double_Window::show();
|
||||
|
@ -35,6 +35,7 @@
|
||||
char *Fl_Window::default_xclass_ = 0L;
|
||||
|
||||
void Fl_Window::_Fl_Window() {
|
||||
cursor_default = FL_CURSOR_DEFAULT;
|
||||
type(FL_WINDOW);
|
||||
box(FL_FLAT_BOX);
|
||||
if (Fl::scheme_bg_) {
|
||||
@ -52,7 +53,6 @@ void Fl_Window::_Fl_Window() {
|
||||
resizable(0);
|
||||
size_range_set = 0;
|
||||
minw = maxw = minh = maxh = 0;
|
||||
shape_data_ = NULL;
|
||||
no_fullscreen_x = 0;
|
||||
no_fullscreen_y = 0;
|
||||
no_fullscreen_w = w();
|
||||
@ -68,19 +68,22 @@ Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l) :
|
||||
Fl_Group(X, Y, W, H, l),
|
||||
pWindowDriver(Fl_Window_Driver::newWindowDriver(this))
|
||||
{
|
||||
cursor_default = FL_CURSOR_DEFAULT;
|
||||
|
||||
_Fl_Window();
|
||||
set_flag(FORCE_POSITION);
|
||||
}
|
||||
|
||||
Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l, Fl_Window_Driver *driver) : Fl_Group(X, Y, W, H, l), pWindowDriver(driver)
|
||||
{
|
||||
_Fl_Window();
|
||||
set_flag(FORCE_POSITION);
|
||||
}
|
||||
|
||||
|
||||
Fl_Window::Fl_Window(int W, int H, const char *l) :
|
||||
// fix common user error of a missing end() with current(0):
|
||||
Fl_Group((Fl_Group::current(0),0), 0, W, H, l),
|
||||
pWindowDriver(Fl_Window_Driver::newWindowDriver(this))
|
||||
{
|
||||
cursor_default = FL_CURSOR_DEFAULT;
|
||||
|
||||
_Fl_Window();
|
||||
clear_visible();
|
||||
}
|
||||
@ -92,15 +95,6 @@ Fl_Window::~Fl_Window() {
|
||||
}
|
||||
free_icons();
|
||||
delete icon_;
|
||||
if (shape_data_) {
|
||||
if (shape_data_->todelete_) delete shape_data_->todelete_;
|
||||
#if defined(__APPLE__) // PORTME: Fl_Window_Driver - platform window driver
|
||||
if (shape_data_->mask) {
|
||||
CGImageRelease(shape_data_->mask);
|
||||
}
|
||||
#endif
|
||||
delete shape_data_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,11 +22,13 @@
|
||||
#include "config_lib.h"
|
||||
#include <FL/Fl_Window_Driver.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
|
||||
Fl_Window_Driver::Fl_Window_Driver(Fl_Window *win) :
|
||||
pWindow(win)
|
||||
{
|
||||
shape_data_ = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -34,10 +36,129 @@ Fl_Window_Driver::~Fl_Window_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
void Fl_Window_Driver::draw() {
|
||||
pWindow->draw();
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
void Fl_Window_Driver::destroy_double_buffer() {
|
||||
Fl_X *i = Fl_X::i(pWindow);
|
||||
/* 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(i->other_xid);
|
||||
i->other_xid = 0;
|
||||
}
|
||||
|
||||
void Fl_Window_Driver::draw() {
|
||||
// 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 (pWindow->damage() & ~FL_DAMAGE_CHILD) { // draw the entire thing
|
||||
pWindow->draw_box(pWindow->box(),0,0,pWindow->w(),pWindow->h(),pWindow->color()); // draw box with x/y = 0
|
||||
|
||||
if (pWindow->image() && (pWindow->align() & FL_ALIGN_INSIDE)) { // draw the image only
|
||||
Fl_Label l1;
|
||||
memset(&l1,0,sizeof(l1));
|
||||
l1.align_ = pWindow->align();
|
||||
l1.image = pWindow->image();
|
||||
if (!pWindow->active_r() && l1.image && l1.deimage) l1.image = l1.deimage;
|
||||
l1.type = pWindow->labeltype();
|
||||
l1.draw(0,0,pWindow->w(),pWindow->h(),pWindow->align());
|
||||
}
|
||||
}
|
||||
pWindow->draw_children();
|
||||
|
||||
# if defined(FLTK_USE_CAIRO)
|
||||
Fl::cairo_make_current(this); // checkout if an update is necessary
|
||||
# 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.
|
||||
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.
|
||||
|
||||
The \p img argument can be an Fl_Bitmap, Fl_Pixmap, Fl_RGB_Image or Fl_Shared_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.
|
||||
\li With an Fl_RGB_Image with an alpha channel (depths 2 or 4), the shaped window covers the image part
|
||||
that is not fully transparent.
|
||||
\li With an Fl_RGB_Image of depth 1 (gray-scale) or 3 (RGB), the shaped window covers the non-black image part.
|
||||
\li With an Fl_Shared_Image, the shape is determined by rules above applied to the underlying image.
|
||||
The shared image should not have been scaled through Fl_Shared_Image::scale().
|
||||
|
||||
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.
|
||||
An 8-bit shape-mask is used when \p img is an Fl_RGB_Image:
|
||||
with depths 2 or 4, the image alpha channel becomes the shape mask such that areas with alpha = 0
|
||||
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.
|
||||
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 Fl_Window::border(1).
|
||||
|
||||
A usage example is found at example/shapedwindow.cxx.
|
||||
|
||||
\version 1.3.3 (and requires compilation with FL_ABI_VERSION >= 10303)
|
||||
*/
|
||||
void Fl_Window::shape(const Fl_Image* img) {pWindowDriver->shape(img);}
|
||||
|
||||
|
||||
/** Set the window's shape with an Fl_Image.
|
||||
\see void shape(const Fl_Image* img)
|
||||
*/
|
||||
void Fl_Window::shape(const Fl_Image& img) {pWindowDriver->shape(&img);}
|
||||
|
||||
/** Returns non NULL when the window has been assigned a non-rectangular shape */
|
||||
int Fl_Window::is_shaped() {return pWindowDriver->shape_data_ != NULL;}
|
||||
|
||||
void Fl_Window_Driver::shape_pixmap_(Fl_Image* pixmap) {
|
||||
Fl_RGB_Image* rgba = new Fl_RGB_Image((Fl_Pixmap*)pixmap);
|
||||
shape_alpha_(rgba, 3);
|
||||
delete rgba;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
|
@ -2998,7 +2998,7 @@ void Fl_X::make(Fl_Window* w)
|
||||
[cw setHasShadow:YES];
|
||||
[cw setAcceptsMouseMovedEvents:YES];
|
||||
}
|
||||
if (w->shape_data_) {
|
||||
if (w->is_shaped()) {
|
||||
[cw setOpaque:NO]; // shaped windows must be non opaque
|
||||
[cw setBackgroundColor:[NSColor clearColor]]; // and with transparent background color
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ class Fl_Widget *fl_selection_requestor;
|
||||
# include <stdlib.h>
|
||||
# include "flstring.h"
|
||||
# include "drivers/X11/Fl_X11_Screen_Driver.H"
|
||||
# include "drivers/X11/Fl_X11_Window_Driver.H"
|
||||
# include <unistd.h>
|
||||
# include <time.h>
|
||||
# include <sys/time.h>
|
||||
@ -2557,8 +2558,8 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (win->shape_data_) {
|
||||
win->combine_mask();
|
||||
if (win->is_shaped()) {
|
||||
((Fl_X11_Window_Driver*)win->pWindowDriver)->combine_mask();
|
||||
}
|
||||
XMapWindow(fl_display, xp->xid);
|
||||
if (showit) {
|
||||
|
@ -103,7 +103,6 @@ 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 \
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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$".
|
||||
|
@ -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
|
||||
|
||||
//
|
||||
|
@ -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$".
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user