diff --git a/FL/Fl_Shaped_Window.H b/FL/Fl_Shaped_Window.H deleted file mode 100644 index fb3296fae..000000000 --- a/FL/Fl_Shaped_Window.H +++ /dev/null @@ -1,78 +0,0 @@ -// -// "$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 -#if defined(__APPLE__) -#include -#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$". -// diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H index 03c82789e..4020b8a86 100644 --- a/FL/Fl_Window.H +++ b/FL/Fl_Window.H @@ -27,14 +27,16 @@ #endif #include "Fl_Group.H" +#include "Fl_Bitmap.H" +#include #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; + /** This widget produces an actual window. This can either be a main window, with a border and title and all the window management controls, @@ -117,6 +119,40 @@ class FL_EXPORT Fl_Window : public Fl_Group { // legacy, not used Fl_Color cursor_fg, cursor_bg; #endif + +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__) + typedef struct CGImage* CGImageRef; + CGImageRef mask; +#endif + Fl_Bitmap *todelete_; ///< auxiliary bitmap image + }; + +#if FLTK_ABI_VERSION < 10303 && !defined(FL_DOXYGEN) + static +#endif + shape_data_type *shape_data_; ///< non-null means the window has a non-rectangular shape +private: + void shape_bitmap_(Fl_Bitmap* b); + void shape_alpha_(Fl_RGB_Image* img, int offset); + void shape_pixmap_(Fl_Pixmap* 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)) + void combine_mask(void); +#endif +private: + + void size_range_(); void _Fl_Window(); // constructor innards void fullscreen_x(); // platform-specific part of sending a window to full screen @@ -280,7 +316,7 @@ public: /** Returns true if this window is a menu window. */ unsigned int menu_window() const {return flags() & MENU_WINDOW;} - + /** Marks the window as a tooltip window. diff --git a/examples/shapedwindow.cxx b/examples/shapedwindow.cxx index 0c489a31e..bcfabd20c 100644 --- a/examples/shapedwindow.cxx +++ b/examples/shapedwindow.cxx @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -91,7 +91,7 @@ Fl_RGB_Image* prepare_shape(int w) int main(int argc, char **argv) { int dim = 200; - Fl_Shaped_Window *win = new Fl_Shaped_Window(100, 100, dim, dim, "Testing1"); + Fl_Double_Window *win = new Fl_Double_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()); diff --git a/ide/Xcode3/FLTK.xcodeproj/project.pbxproj b/ide/Xcode3/FLTK.xcodeproj/project.pbxproj index 3d69ae916..cf839e607 100644 --- a/ide/Xcode3/FLTK.xcodeproj/project.pbxproj +++ b/ide/Xcode3/FLTK.xcodeproj/project.pbxproj @@ -328,10 +328,10 @@ 7F66B1D912BB924C00C67B59 /* Fl_cocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D612BB924C00C67B59 /* Fl_cocoa.mm */; }; 7F66B1DA12BB924C00C67B59 /* Fl_Native_File_Chooser_MAC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D712BB924C00C67B59 /* Fl_Native_File_Chooser_MAC.mm */; }; 7F66B1DB12BB924C00C67B59 /* Fl_Quartz_Printer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D812BB924C00C67B59 /* Fl_Quartz_Printer.mm */; }; + 7F6F526219CF0F530075F408 /* Fl_Window_shape.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7F6F526119CF0F530075F408 /* Fl_Window_shape.cxx */; }; 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 */; }; 7FFDD15A19BE072000779AD1 /* Fl_PostScript.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FFDD15919BE072000779AD1 /* Fl_PostScript.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 */; }; @@ -4340,6 +4340,7 @@ 7F66B1D612BB924C00C67B59 /* Fl_cocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_cocoa.mm; path = ../../src/Fl_cocoa.mm; sourceTree = SOURCE_ROOT; }; 7F66B1D712BB924C00C67B59 /* Fl_Native_File_Chooser_MAC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Native_File_Chooser_MAC.mm; path = ../../src/Fl_Native_File_Chooser_MAC.mm; sourceTree = SOURCE_ROOT; }; 7F66B1D812BB924C00C67B59 /* Fl_Quartz_Printer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Quartz_Printer.mm; path = ../../src/Fl_Quartz_Printer.mm; sourceTree = SOURCE_ROOT; }; + 7F6F526119CF0F530075F408 /* Fl_Window_shape.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Window_shape.cxx; path = ../../src/Fl_Window_shape.cxx; sourceTree = ""; }; 7F76E015192FAD420071728B /* Fl_Copy_Surface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Copy_Surface.cxx; path = ../../src/Fl_Copy_Surface.cxx; sourceTree = SOURCE_ROOT; }; 7F76E017192FAD590071728B /* Fl_Image_Surface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Image_Surface.cxx; path = ../../src/Fl_Image_Surface.cxx; sourceTree = SOURCE_ROOT; }; 7F76E019192FAD740071728B /* 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; }; @@ -4347,8 +4348,6 @@ 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; }; 7FFDD15919BE072000779AD1 /* Fl_PostScript.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_PostScript.cxx; path = ../../src/Fl_PostScript.cxx; sourceTree = ""; }; 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; }; @@ -5508,7 +5507,6 @@ 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 */, @@ -5534,6 +5532,7 @@ F42EEFA08A75F71B33094D50 /* Fl_Window_fullscreen.cxx */, CC2482EC04B752BF38D4DBE2 /* Fl_Window_hotspot.cxx */, 9E22773911BDBADEA86730D4 /* Fl_Window_iconize.cxx */, + 7F6F526119CF0F530075F408 /* Fl_Window_shape.cxx */, 9951B49F640C2C15321EED9C /* Fl_Wizard.cxx */, 800E34DEF9E503C5EC6C4FA5 /* Fl_XBM_Image.cxx */, 0CBC6DC7942212D47B70681B /* Fl_XPM_Image.cxx */, @@ -6297,7 +6296,6 @@ 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 */, @@ -9438,6 +9436,7 @@ DB29DA4D89702B490E69B569 /* Fl_Table.cxx in Sources */, 644FEEF43A0CCBD89E2CE6FC /* Fl_Table_Row.cxx in Sources */, CDCB453B3493D8E96E80DFF7 /* Fl_Tabs.cxx in Sources */, + 7F6F526219CF0F530075F408 /* Fl_Window_shape.cxx in Sources */, FB93EB94C997FC6F8C5D389D /* Fl_Text_Buffer.cxx in Sources */, 4536387C357FBA58B3C5258B /* Fl_Text_Display.cxx in Sources */, 8F77031B8CCFF315D4CB151E /* Fl_Text_Editor.cxx in Sources */, @@ -9534,7 +9533,6 @@ 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; }; diff --git a/ide/Xcode4/FLTK.xcodeproj/project.pbxproj b/ide/Xcode4/FLTK.xcodeproj/project.pbxproj index 4933aea10..a988702da 100644 --- a/ide/Xcode4/FLTK.xcodeproj/project.pbxproj +++ b/ide/Xcode4/FLTK.xcodeproj/project.pbxproj @@ -328,9 +328,9 @@ 7F66B1D912BB924C00C67B59 /* Fl_cocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D612BB924C00C67B59 /* Fl_cocoa.mm */; }; 7F66B1DA12BB924C00C67B59 /* Fl_Native_File_Chooser_MAC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D712BB924C00C67B59 /* Fl_Native_File_Chooser_MAC.mm */; }; 7F66B1DB12BB924C00C67B59 /* Fl_Quartz_Printer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D812BB924C00C67B59 /* Fl_Quartz_Printer.mm */; }; + 7F6F526419CF0FED0075F408 /* Fl_Window_shape.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7F6F526319CF0FED0075F408 /* Fl_Window_shape.cxx */; }; 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 */; }; @@ -4330,6 +4330,7 @@ 7F66B1D612BB924C00C67B59 /* Fl_cocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_cocoa.mm; path = ../../src/Fl_cocoa.mm; sourceTree = SOURCE_ROOT; }; 7F66B1D712BB924C00C67B59 /* Fl_Native_File_Chooser_MAC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Native_File_Chooser_MAC.mm; path = ../../src/Fl_Native_File_Chooser_MAC.mm; sourceTree = SOURCE_ROOT; }; 7F66B1D812BB924C00C67B59 /* Fl_Quartz_Printer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Quartz_Printer.mm; path = ../../src/Fl_Quartz_Printer.mm; sourceTree = SOURCE_ROOT; }; + 7F6F526319CF0FED0075F408 /* Fl_Window_shape.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Window_shape.cxx; path = ../../src/Fl_Window_shape.cxx; sourceTree = ""; }; 7F784151AF1B748D0F3DB1C0 /* forms.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = forms.cxx; path = ../../test/forms.cxx; sourceTree = SOURCE_ROOT; }; 7F92031A16B1A909000FC50F /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = Localizable.strings; sourceTree = ""; }; 7F92031D16B1A909000FC50F /* French */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = French; path = Localizable.strings; sourceTree = ""; }; @@ -4342,8 +4343,6 @@ 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; }; 7FFDD15B19BE08A800779AD1 /* Fl_PostScript.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_PostScript.cxx; path = ../../src/Fl_PostScript.cxx; sourceTree = ""; }; 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; }; @@ -5502,7 +5501,6 @@ 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 */, @@ -5528,6 +5526,7 @@ F42EEFA08A75F71B33094D50 /* Fl_Window_fullscreen.cxx */, CC2482EC04B752BF38D4DBE2 /* Fl_Window_hotspot.cxx */, 9E22773911BDBADEA86730D4 /* Fl_Window_iconize.cxx */, + 7F6F526319CF0FED0075F408 /* Fl_Window_shape.cxx */, 9951B49F640C2C15321EED9C /* Fl_Wizard.cxx */, 800E34DEF9E503C5EC6C4FA5 /* Fl_XBM_Image.cxx */, 0CBC6DC7942212D47B70681B /* Fl_XPM_Image.cxx */, @@ -6336,7 +6335,6 @@ 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 */, @@ -9526,6 +9524,7 @@ 7FFDD15C19BE08A800779AD1 /* Fl_PostScript.cxx in Sources */, 2C8EFE6F2A1297FB4B263B2A /* fl_cursor.cxx in Sources */, 5DE5BC3242C44595E62FA505 /* fl_curve.cxx in Sources */, + 7F6F526419CF0FED0075F408 /* Fl_Window_shape.cxx in Sources */, CD2C6C2797C19E76EA67D308 /* fl_diamond_box.cxx in Sources */, BDB3A4C9B2AC519DC6A95D84 /* fl_dnd.cxx in Sources */, 93E6F83B3B6E8F6473DE0FFC /* fl_draw.cxx in Sources */, @@ -9570,7 +9569,6 @@ 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; }; 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 similarity index 61% rename from src/Fl_Shaped_Window.cxx rename to 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 +#include #include -#include +#include #include #include +#include #ifdef WIN32 # include // 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 # include # include -# include # include # include # include @@ -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 \