Added the Fl_Shaped_Window class to support windows of arbitrary shapes.

The new class is fully Doxygen-documented.
Added an example program (example/shapedwindow.cxx) that exercises the new class.
Modified all IDE-supporting files accordingly.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10255 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2014-08-27 11:55:57 +00:00
parent 22beee52af
commit 8997131377
17 changed files with 734 additions and 5 deletions

78
FL/Fl_Shaped_Window.H Normal file
View File

@ -0,0 +1,78 @@
//
// "$Id"
//
// Fl_Shaped_Window header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2014 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems to:
//
// http://www.fltk.org/str.php
//
#ifndef Fl_Shaped_Window_H
#define Fl_Shaped_Window_H
#include <FL/Fl_Window.H>
#if defined(__APPLE__)
#include <FL/x.H>
#endif
class Fl_Bitmap;
class Fl_Pixmap;
/**
The Fl_Shaped_Window is an Fl_Window that can take an arbitrary shape (not just a rectangular region).
The window shape is determined by the argument of the Fl_Shaped_Window::shape(const Fl_Image*)
member function.
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.
On the Mac platform, OS version 10.4 or above is required.
On the unix/linux platform, the SHAPE extension of the X server is required.
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.
*/
class FL_EXPORT Fl_Shaped_Window : public Fl_Window {
private:
int lw_, lh_;
Fl_Image* shape_;
#if defined(__APPLE__)
CGImageRef mask;
#endif
Fl_Bitmap *todelete_;
void shape_bitmap_(Fl_Bitmap*);
void shape_pixmap_(Fl_Pixmap*);
void shape_alpha_(Fl_RGB_Image* img, int offset);
protected:
virtual void draw();
public:
Fl_Shaped_Window(int w, int h, const char* l = 0);
Fl_Shaped_Window(int x, int y, int w, int h, const char* l = 0);
~Fl_Shaped_Window();
void shape(const Fl_Image*);
/** Set the window's shape with an Fl_Image */
inline void shape(const Fl_Image& b) { shape(&b); }
#if ! (defined(WIN32) || defined(__APPLE__) || defined(FL_DOXYGEN))
void combine_mask(void);
#endif
};
#endif // Fl_Shaped_Window_H
//
// End of "$Id".
//

View File

@ -16,7 +16,7 @@
// http://www.fltk.org/str.php
//
/* \file
/** \file
Fl_Window widget . */
#ifndef Fl_Window_H
@ -30,6 +30,7 @@
#define FL_WINDOW 0xF0 ///< window type id all subclasses have type() >= this
#define FL_DOUBLE_WINDOW 0xF1 ///< double window type id
#define FL_SHAPED_WINDOW 0xF2 ///< shaped window type id
class Fl_X;
class Fl_RGB_Image;

125
examples/shapedwindow.cxx Normal file
View File

@ -0,0 +1,125 @@
//
// "$Id"
//
// shapedwindow example source file for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2014 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems to:
//
// http://www.fltk.org/str.php
//
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Box.H>
#include <FL/Fl.H>
#include <FL/Fl_Shaped_Window.H>
#include <FL/Fl_Image.H>
#include <FL/Fl_Tiled_Image.H>
#include <FL/Fl_Image_Surface.H>
#include "test/pixmaps/tile.xpm"
void cb(Fl_Widget *w, void *) {
w->window()->hide();
}
class dragbox : public Fl_Box {
public:
dragbox(int x, int y, int w, int h, const char *t=0) : Fl_Box(x,y,w,h,t) {};
int handle(int event) {
static int fromx, fromy, winx, winy;
if (event == FL_PUSH) {
fromx = Fl::event_x_root();
fromy = Fl::event_y_root();
winx = window()->x_root();
winy = window()->y_root();
return 1;
}
else if (event == FL_DRAG) {
int deltax = Fl::event_x_root() - fromx;
int deltay = Fl::event_y_root() - fromy;
window()->resize(winx + deltax, winy + deltay, window()->w(), window()->h());
return 1;
}
return Fl_Box::handle(event);
}
};
const float factor = 1.3;
void shrink(Fl_Widget *wdgt, void *data)
{
Fl_Window *win = wdgt->window();
int old = win->w();
win->size(old/factor, old/factor);
if (win->w() <= *(int*)data) wdgt->deactivate();
}
void enlarge(Fl_Widget *wdgt, void *data)
{
Fl_Window *win = wdgt->window();
int old = win->w();
win->size(old*factor, old*factor);
((Fl_Widget*)data)->activate();
}
Fl_RGB_Image* prepare_shape(int w)
{
// draw a white circle with a hole in it on black background
Fl_Image_Surface *surf = new Fl_Image_Surface(w, w);
Fl_Surface_Device* current = Fl_Surface_Device::surface();
surf->set_current();
fl_color(FL_BLACK);
fl_rectf(-1, -1, w+2, w+2);
fl_color(FL_WHITE);
fl_pie(2,2,w-4,w-4,0,360);
fl_color(FL_BLACK);
fl_pie(0.7*w,w/2,w/4,w/4,0,360);
Fl_RGB_Image* img = surf->image();
delete surf;
current->set_current();
return img; // return depth-3 white image on black background
}
int main(int argc, char **argv) {
int dim = 200;
Fl_Shaped_Window *win = new Fl_Shaped_Window(100, 100, dim, dim, "Testing1");
Fl_RGB_Image *img = prepare_shape(dim);
win->shape(img);
dragbox *box = new dragbox(0, 0, win->w(), win->h());
box->image(new Fl_Tiled_Image(new Fl_Pixmap((const char * const *)tile_xpm)));
Fl_Group *g = new Fl_Group(10, 20, 80, 20);
g->box(FL_NO_BOX);
Fl_Button *b = new Fl_Button(10, 20, 80, 20, "Close");
b->callback(cb);
g->end();
g->resizable(NULL);
g = new Fl_Group(60, 70, 80, 40, "Drag me");
g->box(FL_NO_BOX);
g->align(FL_ALIGN_TOP);
Fl_Button *bs = new Fl_Button(60, 70, 80, 20, "Shrink");
bs->callback(shrink, &dim);
bs->deactivate();
Fl_Button *be = new Fl_Button(60, 90, 80, 20, "Enlarge");
be->callback(enlarge, bs);
g->end();
g->resizable(NULL);
win->end();
win->resizable(win);
win->show(argc, argv);
Fl::run();
delete win;
return 0;
}
//
// End of "$Id".
//

View File

@ -655,6 +655,10 @@
RelativePath="..\..\FL\Fl_Select_Browser.H"
>
</File>
<File
RelativePath="..\..\FL\Fl_Shaped_Window.H"
>
</File>
<File
RelativePath="..\..\FL\Fl_Shared_Image.H"
>
@ -5340,7 +5344,53 @@
/>
</FileConfiguration>
</File>
<File
<File
RelativePath="..\..\src\Fl_Shaped_Window.cxx"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
BrowseInformation="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Cairo|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
BrowseInformation="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Cairo|Win32"
>
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\Fl_Shared_Image.cxx"
>
<FileConfiguration

View File

@ -5005,6 +5005,48 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\Fl_Shaped_Window.cxx"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Cairo|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Cairo|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\Fl_Shared_Image.cxx"
>

View File

@ -256,6 +256,7 @@
<ClInclude Include="..\..\FL\Fl_Scrollbar.H" />
<ClInclude Include="..\..\FL\Fl_Secret_Input.H" />
<ClInclude Include="..\..\FL\Fl_Select_Browser.H" />
<ClInclude Include="..\..\FL\Fl_Shaped_Window.H" />
<ClInclude Include="..\..\FL\Fl_Shared_Image.H" />
<ClInclude Include="..\..\FL\fl_show_colormap.H" />
<ClInclude Include="..\..\FL\fl_show_input.H" />
@ -1855,7 +1856,23 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="..\..\src\Fl_Shared_Image.cxx">
<ClCompile Include="..\..\src\Fl_Shaped_Window.cxx">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
<FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">Neither</FavorSizeOrSpeed>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Neither</FavorSizeOrSpeed>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="..\..\src\Fl_Shared_Image.cxx">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>

View File

@ -268,6 +268,9 @@
<ClInclude Include="..\..\FL\Fl_Select_Browser.H">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="..\..\FL\Fl_Shaped_Window.H">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="..\..\FL\Fl_Shared_Image.H">
<Filter>Headers</Filter>
</ClInclude>
@ -481,6 +484,7 @@
<ClCompile Include="..\..\src\fl_set_font.cxx" />
<ClCompile Include="..\..\src\fl_set_fonts.cxx" />
<ClCompile Include="..\..\src\fl_shadow_box.cxx" />
<ClCompile Include="..\..\src\Fl_Shaped_Window.cxx" />
<ClCompile Include="..\..\src\Fl_Shared_Image.cxx" />
<ClCompile Include="..\..\src\fl_shortcut.cxx" />
<ClCompile Include="..\..\src\fl_show_colormap.cxx" />

View File

@ -1552,6 +1552,18 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="..\..\src\Fl_Shaped_Window.cxx">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="..\..\src\Fl_Shared_Image.cxx">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

View File

@ -515,6 +515,10 @@ SOURCE=..\..\src\fl_shadow_box.cxx
# End Source File
# Begin Source File
SOURCE=..\..\src\Fl_Shaped_Window.cxx
# End Source File
# Begin Source File
SOURCE=..\..\src\Fl_Shared_Image.cxx
# End Source File
# Begin Source File

View File

@ -533,6 +533,10 @@ SOURCE=..\..\src\fl_shadow_box.cxx
# End Source File
# Begin Source File
SOURCE=..\..\src\Fl_Shaped_Window.cxx
# End Source File
# Begin Source File
SOURCE=..\..\src\Fl_Shared_Image.cxx
# End Source File
# Begin Source File

View File

@ -331,6 +331,7 @@
7F74F393190D7F0500C56950 /* fl_gleam.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 299E717718BC503400FF83F2 /* fl_gleam.cxx */; };
7F76E016192FAD420071728B /* Fl_Copy_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7F76E015192FAD420071728B /* Fl_Copy_Surface.cxx */; };
7F76E018192FAD590071728B /* Fl_Image_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7F76E017192FAD590071728B /* Fl_Image_Surface.cxx */; };
7FD807F719ADD610007622B2 /* Fl_Shaped_Window.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FD807F619ADD610007622B2 /* Fl_Shaped_Window.cxx */; };
7FFDE4AD171D8AA3008753A3 /* Fl_Sys_Menu_Bar.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7FFDE4AC171D8AA3008753A3 /* Fl_Sys_Menu_Bar.mm */; };
812129561A1981D6DEFBCBFB /* Fl_Positioner.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 05BBBFE4BED0452E5D6A81F7 /* Fl_Positioner.cxx */; };
812761E94039F13357F56EE6 /* fltk_png.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 98A16A4EC098BA7DB21E13DC /* fltk_png.framework */; };
@ -4347,6 +4348,8 @@
7F784151AF1B748D0F3DB1C0 /* forms.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = forms.cxx; path = ../../test/forms.cxx; sourceTree = SOURCE_ROOT; };
7FAC914955D699539F73B996 /* bitmap.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bitmap.cxx; path = ../../test/bitmap.cxx; sourceTree = SOURCE_ROOT; };
7FC91721DA7888C8A1FD762E /* input_choice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = input_choice.app; sourceTree = BUILT_PRODUCTS_DIR; };
7FD807F419ADD5F4007622B2 /* Fl_Shaped_Window.H */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Fl_Shaped_Window.H; path = ../../FL/Fl_Shaped_Window.H; sourceTree = SOURCE_ROOT; };
7FD807F619ADD610007622B2 /* Fl_Shaped_Window.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Shaped_Window.cxx; path = ../../src/Fl_Shaped_Window.cxx; sourceTree = SOURCE_ROOT; };
7FFDE4AC171D8AA3008753A3 /* Fl_Sys_Menu_Bar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Sys_Menu_Bar.mm; path = ../../src/Fl_Sys_Menu_Bar.mm; sourceTree = SOURCE_ROOT; };
800E34DEF9E503C5EC6C4FA5 /* Fl_XBM_Image.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_XBM_Image.cxx; path = ../../src/Fl_XBM_Image.cxx; sourceTree = SOURCE_ROOT; };
806103D71A8CD0075BF8E1DA /* Fl_Group.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Group.cxx; path = ../../src/Fl_Group.cxx; sourceTree = SOURCE_ROOT; };
@ -5505,6 +5508,7 @@
13BCF00369D5254F0CE49599 /* Fl_Round_Button.cxx */,
3F60A41762817C834FF38947 /* Fl_Scroll.cxx */,
A5B9A5CE605BB8A57F66A2E6 /* Fl_Scrollbar.cxx */,
7FD807F619ADD610007622B2 /* Fl_Shaped_Window.cxx */,
57639C1D5415FB55436556A2 /* Fl_Shared_Image.cxx */,
9D942824B8FC886F6FCD853D /* Fl_Single_Window.cxx */,
5AF5119D08DFC92EA1032671 /* Fl_Slider.cxx */,
@ -6293,6 +6297,7 @@
28F3E4EBB6E5F8420624A5DA /* Fl_Scrollbar.H */,
42FEA3A2967D04217C27FA61 /* Fl_Secret_Input.H */,
9DA766AE10DC532F3D0401A2 /* Fl_Select_Browser.H */,
7FD807F419ADD5F4007622B2 /* Fl_Shaped_Window.H */,
A46A39199806D09CE0ABEE59 /* Fl_Shared_Image.H */,
9B57B581401BD8575BFAF2F1 /* Fl_Simple_Counter.H */,
0EC11A5CAD4E3607A72BEF84 /* Fl_Single_Window.H */,
@ -9527,6 +9532,7 @@
01C68DB0192C6089000BD75C /* Fl_sleep.cxx in Sources */,
7F76E016192FAD420071728B /* Fl_Copy_Surface.cxx in Sources */,
7F76E018192FAD590071728B /* Fl_Image_Surface.cxx in Sources */,
7FD807F719ADD610007622B2 /* Fl_Shaped_Window.cxx in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -330,6 +330,7 @@
7F66B1DB12BB924C00C67B59 /* Fl_Quartz_Printer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D812BB924C00C67B59 /* Fl_Quartz_Printer.mm */; };
7FA5C2BE192FAEBB00519823 /* Fl_Copy_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FA5C2BD192FAEBB00519823 /* Fl_Copy_Surface.cxx */; };
7FA5C2C0192FAECA00519823 /* Fl_Image_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FA5C2BF192FAECA00519823 /* Fl_Image_Surface.cxx */; };
7FD8085119ADD6F2007622B2 /* Fl_Shaped_Window.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FD8085019ADD6F2007622B2 /* Fl_Shaped_Window.cxx */; };
7FDBB8F416B2D1EA00AE76EF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F92032516B1A90A000FC50F /* Localizable.strings */; };
7FDBB8F516B2D1EE00AE76EF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F92032216B1A909000FC50F /* Localizable.strings */; };
7FDBB8F616B2D1FA00AE76EF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F92031F16B1A909000FC50F /* Localizable.strings */; };
@ -4342,6 +4343,8 @@
7FA5C2C2192FAEF200519823 /* Fl_Copy_Surface.H */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Fl_Copy_Surface.H; path = ../../FL/Fl_Copy_Surface.H; sourceTree = SOURCE_ROOT; };
7FAC914955D699539F73B996 /* bitmap.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bitmap.cxx; path = ../../test/bitmap.cxx; sourceTree = SOURCE_ROOT; };
7FC91721DA7888C8A1FD762E /* input_choice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = input_choice.app; sourceTree = BUILT_PRODUCTS_DIR; };
7FD8084F19ADD6DE007622B2 /* Fl_Shaped_Window.H */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Fl_Shaped_Window.H; path = ../../FL/Fl_Shaped_Window.H; sourceTree = SOURCE_ROOT; };
7FD8085019ADD6F2007622B2 /* Fl_Shaped_Window.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Shaped_Window.cxx; path = ../../src/Fl_Shaped_Window.cxx; sourceTree = SOURCE_ROOT; };
7FFDE551171D8D0D008753A3 /* Fl_Sys_Menu_Bar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Sys_Menu_Bar.mm; path = ../../src/Fl_Sys_Menu_Bar.mm; sourceTree = SOURCE_ROOT; };
800E34DEF9E503C5EC6C4FA5 /* Fl_XBM_Image.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_XBM_Image.cxx; path = ../../src/Fl_XBM_Image.cxx; sourceTree = SOURCE_ROOT; };
806103D71A8CD0075BF8E1DA /* Fl_Group.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Group.cxx; path = ../../src/Fl_Group.cxx; sourceTree = SOURCE_ROOT; };
@ -5499,6 +5502,7 @@
13BCF00369D5254F0CE49599 /* Fl_Round_Button.cxx */,
3F60A41762817C834FF38947 /* Fl_Scroll.cxx */,
A5B9A5CE605BB8A57F66A2E6 /* Fl_Scrollbar.cxx */,
7FD8085019ADD6F2007622B2 /* Fl_Shaped_Window.cxx */,
57639C1D5415FB55436556A2 /* Fl_Shared_Image.cxx */,
9D942824B8FC886F6FCD853D /* Fl_Single_Window.cxx */,
5AF5119D08DFC92EA1032671 /* Fl_Slider.cxx */,
@ -6332,6 +6336,7 @@
28F3E4EBB6E5F8420624A5DA /* Fl_Scrollbar.H */,
42FEA3A2967D04217C27FA61 /* Fl_Secret_Input.H */,
9DA766AE10DC532F3D0401A2 /* Fl_Select_Browser.H */,
7FD8084F19ADD6DE007622B2 /* Fl_Shaped_Window.H */,
A46A39199806D09CE0ABEE59 /* Fl_Shared_Image.H */,
9B57B581401BD8575BFAF2F1 /* Fl_Simple_Counter.H */,
0EC11A5CAD4E3607A72BEF84 /* Fl_Single_Window.H */,
@ -9564,6 +9569,7 @@
299CB8A2848CB844BCEC7829 /* Fl_Paged_Device.cxx in Sources */,
7FA5C2BE192FAEBB00519823 /* Fl_Copy_Surface.cxx in Sources */,
7FA5C2C0192FAECA00519823 /* Fl_Image_Surface.cxx in Sources */,
7FD8085119ADD6F2007622B2 /* Fl_Shaped_Window.cxx in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -55,6 +55,7 @@ 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

369
src/Fl_Shaped_Window.cxx Normal file
View File

@ -0,0 +1,369 @@
//
// "$Id"
//
// Fl_Shaped_Window source file for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-2014 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems to:
//
// http://www.fltk.org/str.php
//
#include <FL/x.H>
#include <FL/Fl_Shaped_Window.H>
#include <FL/Fl_Bitmap.H>
#include <FL/Fl_Pixmap.H>
#ifdef WIN32
# include <malloc.h> // needed for VisualC2010
#elif !defined(__APPLE__)
#include <dlfcn.h>
#define ShapeBounding 0
#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__)
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_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)); }
static HRGN bitmap2region(Fl_Bitmap* 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->array;
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_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()
{
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*);
int error_base, shapeEventBase;
if (!beenhere) {
beenhere = 1;
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
if ( !( XShapeQueryExtension_f && XShapeCombineMask_f &&
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_);
Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(this),
(const char*)temp->array,
temp->w(), temp->h());
XShapeCombineMask_f(fl_display, fl_xid(this), ShapeBounding, 0, 0, pbitmap, ShapeSet);
if (pbitmap != None) XFreePixmap(fl_display, pbitmap);
delete temp;
}
#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
#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;
uchar *from = new uchar[bytes_per_row * b->h()];
for (int i = 0; i < b->h(); i++) {
uchar *p = (uchar*)b->array + 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);
mask = CGImageMaskCreate(b->w(), b->h(), 1, 1, bytes_per_row, provider, NULL, false);
CFRelease(provider);
}
#endif
}
#if defined(__APPLE__) // on the mac, use an 8-bit mask
/* 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) {
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_) {
// 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->array + 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);
mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false);
CFRelease(provider);
}
}
#else
/* 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) {
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 = img->array + 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);
todelete_ = bitmap;
}
#endif
void Fl_Shaped_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.
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.
\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.
On some platforms, 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.
*/
void Fl_Shaped_Window::shape(const Fl_Image* img) {
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);
}
//
// End of "$Id".
//

View File

@ -2361,6 +2361,7 @@ void Fl_X::flush()
fl_x_to_redraw = NULL;
}
//bool Fl_X::make_shaped = false;
/*
* go ahead, create that (sub)window
@ -2517,6 +2518,10 @@ void Fl_X::make(Fl_Window* w)
[cw setFrameOrigin:crect.origin];
[cw setHasShadow:YES];
[cw setAcceptsMouseMovedEvents:YES];
if (w->type() == FL_SHAPED_WINDOW) {
[cw setOpaque:NO]; // shaped windows must be non opaque
[cw setBackgroundColor:[NSColor clearColor]]; // and with transparent background color
}
x->xid = cw;
x->w = w; w->i = x;
x->wait_for_expose = 1;
@ -2645,7 +2650,7 @@ void Fl_Window::show() {
labeltype(FL_NO_LABEL);
}
Fl_Tooltip::exit(this);
if (!shown() || !i) {
if (!shown()) {
Fl_X::make(this);
} else {
if ( !parent() ) {

View File

@ -35,6 +35,7 @@
# 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>
@ -2511,6 +2512,9 @@ 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();
}
XMapWindow(fl_display, xp->xid);
if (showit) {
win->set_visible();
@ -2836,7 +2840,7 @@ void Fl_Window::show() {
if (!shown()) {
fl_open_display();
// Don't set background pixel for double-buffered windows...
if (type() == FL_WINDOW && can_boxcheat(box())) {
if (type() != FL_DOUBLE_WINDOW && can_boxcheat(box())) {
fl_background_pixel = int(fl_xpixel(color()));
}
Fl_X::make_xid(this);

View File

@ -71,6 +71,7 @@ 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 \