summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-04-03 11:23:57 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-04-03 11:23:57 +0200
commit71caca84d92161792861fb33381f7a9c2be05343 (patch)
tree0a9bd0ef23ba4051af4070dba1afcf87111ec7b6
parent07bb343de7c6b4152a7eb8940da99d5d006f27cd (diff)
parent678c85027294c0ae5162d02b20a59fde758ac77a (diff)
Merge remote-tracking branch 'refs/remotes/origin/master'
-rw-r--r--CMake/fl_debug_var.cmake18
-rw-r--r--CMake/options.cmake4
-rw-r--r--CMakeLists.txt17
-rw-r--r--FL/Enumerations.H24
-rw-r--r--FL/Fl_Choice.H4
-rw-r--r--FL/Fl_Menu_Bar.H4
-rw-r--r--FL/Fl_Menu_Button.H4
-rw-r--r--FL/Fl_Menu_Item.H28
-rw-r--r--FL/Fl_Tooltip.H12
-rw-r--r--FL/Fl_Tree_Item.H4
-rw-r--r--FL/names.h8
-rw-r--r--README.abi-version.txt5
-rw-r--r--README.macOS.md254
-rw-r--r--documentation/CMakeLists.txt26
-rwxr-xr-xdocumentation/make_pdf.in (renamed from documentation/make_pdf)9
-rw-r--r--documentation/src/fltk-title.tex.in2
-rw-r--r--fltk-config.in8
-rw-r--r--fluid/CMakeLists.txt13
-rw-r--r--fluid/tools/autodoc.cxx2
-rw-r--r--src/Fl_Choice.cxx2
-rw-r--r--src/Fl_Input_Choice.cxx5
-rw-r--r--src/Fl_MacOS_Sys_Menu_Bar.mm2
-rw-r--r--src/Fl_Menu.cxx21
-rw-r--r--src/Fl_Menu_.cxx7
-rw-r--r--src/Fl_Menu_Bar.cxx2
-rw-r--r--src/Fl_Menu_Button.cxx1
-rw-r--r--src/Fl_Screen_Driver.cxx4
-rw-r--r--src/Fl_Tooltip.cxx81
-rw-r--r--src/Fl_Tree_Item.cxx6
-rw-r--r--src/Fl_cocoa.mm12
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx3
-rw-r--r--src/fl_write_png.cxx13
-rw-r--r--test/color_chooser.cxx28
-rw-r--r--test/fractals.cxx2
-rw-r--r--test/menubar.cxx47
-rw-r--r--test/terminal.fl10
36 files changed, 361 insertions, 331 deletions
diff --git a/CMake/fl_debug_var.cmake b/CMake/fl_debug_var.cmake
index 815e97dc1..d583d7d0c 100644
--- a/CMake/fl_debug_var.cmake
+++ b/CMake/fl_debug_var.cmake
@@ -117,16 +117,20 @@ function(fl_debug_target name)
### INTERFACE_LOCATION)
### endif()
- list(APPEND _props
+ if(NOT _type STREQUAL "INTERFACE_LIBRARY" OR CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
+ # Before 3.19: "INTERFACE_LIBRARY targets may only have whitelisted properties"
+ list(APPEND _props
INCLUDE_DIRECTORIES
LINK_DIRECTORIES
LINK_LIBRARIES
- COMPILE_DEFINITIONS
- INTERFACE_COMPILE_DEFINITIONS
- INTERFACE_COMPILE_FEATURES
- INTERFACE_INCLUDE_DIRECTORIES
- INTERFACE_LINK_DIRECTORIES
- INTERFACE_LINK_LIBRARIES)
+ COMPILE_DEFINITIONS)
+ endif()
+
+ list(APPEND _props
+ INTERFACE_COMPILE_DEFINITIONS
+ INTERFACE_INCLUDE_DIRECTORIES
+ INTERFACE_LINK_DIRECTORIES
+ INTERFACE_LINK_LIBRARIES)
foreach(prop ${_props})
get_target_property(${prop} ${name} ${prop})
diff --git a/CMake/options.cmake b/CMake/options.cmake
index d2fa392f7..8411b92ec 100644
--- a/CMake/options.cmake
+++ b/CMake/options.cmake
@@ -739,11 +739,11 @@ if(FLTK_USE_PTHREADS)
include(FindThreads)
- if(CMAKE_HAVE_THREADS_LIBRARY)
+ if(Threads_FOUND)
add_definitions("-D_THREAD_SAFE -D_REENTRANT")
set(USE_THREADS 1)
set(FLTK_THREADS_FOUND TRUE)
- endif(CMAKE_HAVE_THREADS_LIBRARY)
+ endif(Threads_FOUND)
if(CMAKE_USE_PTHREADS_INIT AND NOT WIN32)
set(HAVE_PTHREAD 1)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 420e379c1..08548b2b4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,23 @@
#
#######################################################################
+# Prevent building in the source tree - don't pollute the sources
+#######################################################################
+
+if("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
+ message("")
+ message(STATUS "=======================================================================")
+ message(STATUS " NOTE: In-source builds of FLTK are disabled to prevent writing to the")
+ message(STATUS " NOTE: source tree. Please create a subfolder (e.g. 'build') and use")
+ message(STATUS " NOTE: `cmake ..` inside it or use for instance `cmake . -B build`.")
+ message(STATUS " NOTE: CMake will, however, create CMakeCache.txt and CMakeFiles/* .")
+ message(STATUS " NOTE: You must delete CMakeCache.txt and CMakeFiles/* manually.")
+ message(STATUS "=======================================================================")
+ message("")
+ message(FATAL_ERROR "*** In-source builds are disabled, please read notes above! ***")
+endif()
+
+#######################################################################
# Set CMake minimum version first: must be set before `project()`
#######################################################################
diff --git a/FL/Enumerations.H b/FL/Enumerations.H
index 1a8b219bd..5bc2951aa 100644
--- a/FL/Enumerations.H
+++ b/FL/Enumerations.H
@@ -153,11 +153,15 @@
This is done to prevent users from defining an illegal ABI version.
Rule: FL_MAJOR_VERSION * 10000 + FL_MINOR_VERSION * 100
- <= FL_ABI_VERSION <= FL_API_VERSION.
+ <= FL_ABI_VERSION <= FL_API_VERSION + 1.
- Example (FLTK 1.3.4):
+ Since FLTK 1.4.2+ (Git commits after release 1.4.2) FL_ABI_VERSION is
+ allowed to be one higher than FL_API_VERSION so ABI changes in Git
+ targeted at the *next* release (e.g. 1.4.3) can be used.
- 10300 <= FL_ABI_VERSION <= 10304
+ Example: Commits after release FLTK 1.4.2 (before release 1.4.3):
+
+ 10400 <= FL_ABI_VERSION <= 10403
Note: configure + CMake can be used to define FL_ABI_VERSION, but they
do not check validity. This is done here.
@@ -168,10 +172,10 @@
# undef FL_ABI_VERSION
# define FL_ABI_VERSION (FL_MAJOR_VERSION*10000 + FL_MINOR_VERSION*100)
-#elif FL_ABI_VERSION > FL_API_VERSION
+#elif FL_ABI_VERSION > FL_API_VERSION + 1
# undef FL_ABI_VERSION
-# define FL_ABI_VERSION FL_API_VERSION
+# define FL_ABI_VERSION FL_API_VERSION + 1
#endif
@@ -410,7 +414,15 @@ enum Fl_Event { // events
/** A zoom event (ctrl/+/-/0/ or cmd/+/-/0/) was processed.
Use Fl::add_handler() to be notified of this event.
*/
- FL_ZOOM_EVENT = 27
+ FL_ZOOM_EVENT = 27,
+ /** A tooltip is about to pop up for this widget. The mouse coordinates are
+ available in Fl::event_x() and Fl::event_y(). Change the widget tooltip
+ as needed. */
+ FL_BEFORE_TOOLTIP = 28,
+ /** Triggered just before a menu is displayed. Widgets derived from Fl_Menu_
+ receive this event right before the menu appears, providing an opportunity
+ to update menu item states and activation. */
+ FL_BEFORE_MENU = 29
// DEV NOTE: Keep this list in sync with FL/names.h
};
diff --git a/FL/Fl_Choice.H b/FL/Fl_Choice.H
index 944f4d3a4..2434a9ac3 100644
--- a/FL/Fl_Choice.H
+++ b/FL/Fl_Choice.H
@@ -100,6 +100,10 @@
}
\endcode
+ FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
+ displaying the menu. This event provides an opportunity to update menu
+ item states and activation. See `test/menubar.cxx`, class `Dynamic_Choice`
+ "Flip" and "Flop" for a usage example.
*/
class FL_EXPORT Fl_Choice : public Fl_Menu_ {
protected:
diff --git a/FL/Fl_Menu_Bar.H b/FL/Fl_Menu_Bar.H
index 26c08539d..4e7af0d6e 100644
--- a/FL/Fl_Menu_Bar.H
+++ b/FL/Fl_Menu_Bar.H
@@ -61,6 +61,10 @@
Typing the shortcut() of any of the menu items will cause
callbacks exactly the same as when you pick the item with the mouse.
+
+ FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
+ displaying the menu. This event provides an opportunity to update menu
+ item states and activation.
*/
class FL_EXPORT Fl_Menu_Bar : public Fl_Menu_ {
friend class Fl_Sys_Menu_Bar_Driver;
diff --git a/FL/Fl_Menu_Button.H b/FL/Fl_Menu_Button.H
index 0e1036450..3f52593b4 100644
--- a/FL/Fl_Menu_Button.H
+++ b/FL/Fl_Menu_Button.H
@@ -52,6 +52,10 @@
is done instead, along with any userdata configured for it.
The callback can determine which item was picked using
value(), mvalue(), item_pathname(), etc.
+
+ FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
+ displaying the menu. This event provides an opportunity to update menu
+ item states and activation.
*/
class FL_EXPORT Fl_Menu_Button : public Fl_Menu_ {
protected:
diff --git a/FL/Fl_Menu_Item.H b/FL/Fl_Menu_Item.H
index 3073dd2d0..6eaf0a9d2 100644
--- a/FL/Fl_Menu_Item.H
+++ b/FL/Fl_Menu_Item.H
@@ -34,7 +34,8 @@ enum { // values for flags:
FL_SUBMENU_POINTER = 0x20, ///< Indicates user_data() is a pointer to another menu array
FL_SUBMENU = 0x40, ///< Item is a submenu to other items
FL_MENU_DIVIDER = 0x80, ///< Creates divider line below this item. Also ends a group of radio buttons
- FL_MENU_HORIZONTAL = 0x100 ///< ??? -- reserved, internal (do not use)
+ FL_MENU_HORIZONTAL = 0x100, ///< reserved, do not use
+ FL_MENU_CHATTY = 0x200 ///< Menu Item receives additional callbacks
///< Note: \b ALL other bits in \p flags are reserved: do not use them for your own purposes!
};
@@ -67,7 +68,8 @@ class Fl_Menu_;
FL_SUBMENU_POINTER = 0x20, // Indicates user_data() is a pointer to another menu array
FL_SUBMENU = 0x40, // This item is a submenu to other items
FL_MENU_DIVIDER = 0x80, // Creates divider line below this item. Also ends a group of radio buttons.
- FL_MENU_HORIZONTAL = 0x100 // ??? -- reserved, internal (do not use)
+ FL_MENU_HORIZONTAL = 0x100 // reserved, do not use
+ FL_MENU_CHATTY = 0x200 ///< Menu Item receives additional callbacks
};
\endcode
@@ -120,6 +122,16 @@ class Fl_Menu_;
variants copies the entire menu to internal storage. Using the
memory of a static menu array after that would access unused (but not
released) memory and thus have no effect.
+
+ When a menu item is selected by the user and a callback is set, the callback
+ will be called with FL_REASON_SELECTED. The Fl_Widget pointer is set to the
+ widget that opened the menu, a copy of the menu item's user data. If no menu
+ item callback is set, the callback of the managing widget is called instead.
+
+ If the FL_MENU_CHATTY flag is set, the menu item callback may be called for
+ additional reasons. When a menu item is highlighted, the callback is called
+ with FL_REASON_GOT_FOCUS. If it is no longer highlighted,
+ FL_REASON_LOST_FOCUS is sent.
*/
struct FL_EXPORT Fl_Menu_Item {
const char *text; ///< menu item text, returned by label()
@@ -490,14 +502,18 @@ struct FL_EXPORT Fl_Menu_Item {
The callback is called with the stored user_data() as its second argument.
You must first check that callback() is non-zero before calling this.
*/
- void do_callback(Fl_Widget* o) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, user_data_);}
+ void do_callback(Fl_Widget* o, Fl_Callback_Reason reason=FL_REASON_UNKNOWN) const {
+ Fl::callback_reason_ = reason; callback_(o, user_data_);
+ }
/**
Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument.
This call overrides the callback's second argument with the given value \p arg.
You must first check that callback() is non-zero before calling this.
*/
- void do_callback(Fl_Widget* o,void* arg) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, arg);}
+ void do_callback(Fl_Widget* o, void* arg, Fl_Callback_Reason reason=FL_REASON_UNKNOWN) const {
+ Fl::callback_reason_ = reason; callback_(o, arg);
+ }
/**
Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument.
@@ -506,7 +522,9 @@ struct FL_EXPORT Fl_Menu_Item {
the callback.
You must first check that callback() is non-zero before calling this.
*/
- void do_callback(Fl_Widget* o,long arg) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, (void*)(fl_intptr_t)arg);}
+ void do_callback(Fl_Widget* o, long arg, Fl_Callback_Reason reason=FL_REASON_UNKNOWN) const {
+ Fl::callback_reason_ = FL_REASON_SELECTED; callback_(o, (void*)(fl_intptr_t)arg);
+ }
/** Back compatibility only.
\deprecated
diff --git a/FL/Fl_Tooltip.H b/FL/Fl_Tooltip.H
index b79d93149..592371651 100644
--- a/FL/Fl_Tooltip.H
+++ b/FL/Fl_Tooltip.H
@@ -95,6 +95,8 @@ public:
static void wrap_width(int v) { wrap_width_ = v; }
/** Returns the window that is used for tooltips */
static Fl_Window* current_window(void);
+ /** \brief Temporarily Override Tooltip Text during an FL_BEFORE_TOOLTIP event. */
+ static int override_text(const char *new_text);
// These should not be public, but Fl_Widget::tooltip() needs them...
// fabien: made it private with only a friend function access
@@ -104,20 +106,22 @@ private:
static void enter_(Fl_Widget* w);
static void exit_(Fl_Widget *w);
static void set_enter_exit_once_();
+ static void tooltip_timeout_(void*);
private:
- static float delay_; //!< delay before a tooltip is shown
- static float hidedelay_; //!< delay until tooltip is closed again
- static float hoverdelay_; //!< delay between tooltips
+ static float delay_; //!< delay before a tooltip is shown
+ static float hidedelay_; //!< delay until tooltip is closed again
+ static float hoverdelay_; //!< delay between tooltips
static Fl_Color color_;
static Fl_Color textcolor_;
static Fl_Font font_;
static Fl_Fontsize size_;
- static Fl_Widget* widget_; //!< Keeps track of the current target widget
+ static Fl_Widget* widget_; //!< Keeps track of the current target widget
static int margin_width_; //!< distance around tooltip text left+right
static int margin_height_; //!< distance around tooltip text top+bottom
static int wrap_width_; //!< maximum width of tooltip text before it word wraps
static const int draw_symbols_; // 1 = draw @-symbols in tooltips, 0 = no
+ static char *override_text_; //!< a copy of the last text for an overridden tooltip
};
#endif
diff --git a/FL/Fl_Tree_Item.H b/FL/Fl_Tree_Item.H
index b76395334..8cdd6ee10 100644
--- a/FL/Fl_Tree_Item.H
+++ b/FL/Fl_Tree_Item.H
@@ -93,8 +93,8 @@ protected:
void _Init(const Fl_Tree_Prefs &prefs, Fl_Tree *tree);
void show_widgets();
void hide_widgets();
- void draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs);
- void draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs);
+ virtual void draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs);
+ virtual void draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs);
void recalc_tree();
int calc_item_height(const Fl_Tree_Prefs &prefs) const;
Fl_Color drawfgcolor() const;
diff --git a/FL/names.h b/FL/names.h
index 984afbfe0..90ef231e7 100644
--- a/FL/names.h
+++ b/FL/names.h
@@ -73,9 +73,11 @@ const char * const fl_eventnames[] =
"FL_FULLSCREEN",
"FL_ZOOM_GESTURE",
"FL_ZOOM_EVENT",
- "FL_EVENT_28", // not yet defined, just in case it /will/ be defined ...
- "FL_EVENT_29", // not yet defined, just in case it /will/ be defined ...
- "FL_EVENT_30" // not yet defined, just in case it /will/ be defined ...
+ "FL_BEFORE_TOOLTIP",
+ "FL_BEFORE_MENU",
+ "FL_EVENT_30", // not yet defined, just in case it /will/ be defined ...
+ "FL_EVENT_31", // not yet defined, just in case it /will/ be defined ...
+ "FL_EVENT_32" // not yet defined, just in case it /will/ be defined ...
};
/**
diff --git a/README.abi-version.txt b/README.abi-version.txt
index f6a87019f..10729a959 100644
--- a/README.abi-version.txt
+++ b/README.abi-version.txt
@@ -45,6 +45,11 @@ The default ABI version is always the lowest version (e.g. 10400). All
following examples are written for FLTK 1.4.1, hence we use "10401" for
the version number.
+Note: Since FLTK 1.4.3 (Git branch-1.4 after release 1.4.2) the highest
+selectable ABI version is FL_API_VERSION + 1 so you can use ABI features
+designated for the *next* FLTK release when using FLTK from Git with new
+ABI features included for the next release.
+
How to select the ABI version with CMake
----------------------------------------
diff --git a/README.macOS.md b/README.macOS.md
index 686d89e24..e2157a978 100644
--- a/README.macOS.md
+++ b/README.macOS.md
@@ -25,15 +25,6 @@ _README.macOS.md - Building FLTK under Apple macOS_
* [Installing FLTK](#bcm_install)
* [Creating new Projects](#bcm_new_projects)
-* [How to Build FLTK Using _autoconf_ and _make_](#build_autoconf_make)
- * [Prerequisites](#bam_prerequisites)
- * [Downloading FLTK and Unpacking](#bam_download)
- * [Configuring FLTK](#bam_config)
- * [Building FLTK](#bam_build)
- * [Testing FLTK](#bam_test)
- * [Installing FLTK](#bam_install)
- * [Creating new Projects](#bam_new_projects)
-
* [Make an Application Launchable by Dropping Files on its Icon](#dropstart)
* [Document History](#doc_history)
@@ -42,15 +33,14 @@ _README.macOS.md - Building FLTK under Apple macOS_
## Introduction
FLTK supports macOS version 10.3 Panther and above. At the time of writing (Feb. 2022),
-FLTK compiles and runs fine on the most recent macOS 12 Monterey for both Intel and
-the new M1 Apple Silicon (Arm) processors.
+FLTK compiles and runs fine on the most recent macOS 12 Monterey for both Intel
+processors and Apple Silicon.
-FLTK 1.4 supports the following build environments on the macOS
+FLTK 1.5 supports the following build environments on the macOS
platform:
* [_cmake_ and _Xcode_](#build_cmake_xcode), no shell needed
* [_cmake_ and _make_](#build_cmake_make) from the command line
-* [_autoconf_ and _make_](#build_autoconf_make) from the command line
All environments will generate Unix style static libraries and macOS style app bundles.
@@ -84,7 +74,7 @@ the Finder window opens, drag the _CMake_ icon into the Applications folder.
<a name="bcx_download"></a>
### Downloading FLTK and Unpacking (CMake, Xcode)
-FLTK 1.4 is currently (as of May 2021) available as a source code repository via GitHub.
+FLTK 1.5 is currently (as of Mar 2025) available as a source code repository via GitHub.
You will need to clone the repository to check out the source code onto your machine. This
has the great benefit that the source code can be updated later simply by telling _git_ to
_pull_ the newest release.
@@ -94,7 +84,7 @@ Weekly snapshots ("tarballs") can be downloaded from https://www.fltk.org/softwa
If you want to use _Xcode_ to clone the FLTK GitHub repository, you will have to give _Xcode_
access to your GitHub Account in the _Xcode_ preferences. If you don't have a GitHub
account, or don't want to share your credentials with _Xcode_, you can use still the command
-line `git clone https://github.com/fltk/fltk.git fltk-1.4`
+line `git clone https://github.com/fltk/fltk.git fltk-1.5`
to check out the repo.
Start _Xcode_. Select `Source Control >> Clone...` in the main menu.
@@ -104,7 +94,7 @@ the search field. A list of matching repositories appears. The first one should
and be owned by `fltk`. Select it and click _Clone_.
A file chooser appears. Navigate to your home directory. Create a new folder named
-`dev`. Enter `fltk-1.4` in the _Save As:_ field and click _Clone_, then _Done_ in the
+`dev`. Enter `fltk-1.5` in the _Save As:_ field and click _Clone_, then _Done_ in the
previous dialog.
The local copy of your repository can be updated by loading it into _Xcode_ and selecting
@@ -117,23 +107,23 @@ Launch _CMake_ by pressing Command+Spacebar, then type _CMake_ and press return.
_CMake_ should open with a large dialog box.
The first input field is labeled with _Where is the source code:_ . Click on _Browse Source..._
-and navigate to your home folder, then `dev`, then `fltk-1.4`. Click _Open_.
+and navigate to your home folder, then `dev`, then `fltk-1.5`. Click _Open_.
The next input field is marked _Where to build the binaries:_. Click _Browse Build..._
-and navigate to your home folder, then `dev`, then `fltk-1.4`, then use _New Folder_
+and navigate to your home folder, then `dev`, then `fltk-1.5`, then use _New Folder_
to create a folder named `build`, and inside that, create a folder named `Xcode`. Click _Open_.
The top two input fields should read
```
-/Users/your_name/dev/fltk-1.4
+/Users/your_name/dev/fltk-1.5
```
and
```
-/Users/your_name/dev/fltk-1.4/build/Xcode
+/Users/your_name/dev/fltk-1.5/build/Xcode
```
Back in the _CMake_ main window, click _Configure_, select _Xcode_ as the generator and
-click _Done_. _CMake_ will now analyse your system and find tools and dependencies. When
+click _Done_. _CMake_ will now analyze your system and find tools and dependencies. When
done, the upper list field in _CMake_ will show CMAKE and FLTK. Open the FLTK field and
adjust options if you like. Note that the bundled image libraries are built by default.
Further options are available under the CMAKE field.
@@ -153,7 +143,7 @@ _CMake_ will be smart enough to update the build files as well.
Now this is easy if all the previous steps were successful. If you are still in _CMake_, just click
_Open Project_ and _CMake_ will launch _XCode_ for you. If not, just launch _XCode_ and
-open `Macintosh HD⁩ ▸ ⁨Users⁩ ▸ your_name⁩ ▸ ⁨dev⁩ ▸ ⁨fltk-1.4⁩ ▸ ⁨build⁩ ▸ ⁨Xcode⁩ ▸ ⁨FLTK.xcodeproj`.
+open `Macintosh HD⁩ ▸ ⁨Users⁩ ▸ your_name⁩ ▸ ⁨dev⁩ ▸ ⁨fltk-1.5 ▸ ⁨build⁩ ▸ ⁨Xcode⁩ ▸ ⁨FLTK.xcodeproj`.
_XCode_ may or may not ask to Autocreate Schemes. Click _Automatically Create Schemes_.
@@ -184,9 +174,9 @@ See README.CMake.txt
<a name="build_cmake_make"></a>
## How to Build FLTK Using _CMake_ and _make_
-This option is best for users who like to develop their apps without using Apple's Xcode IDE,
-but like the advantages of _CMake_ over _autoconf_. Users should be comfortable with
-using `bash` or `tcsh` in a terminal window.
+This option is best for users who like to develop their apps without using
+Apple's Xcode IDE. Users should be comfortable with using `bash` or `tcsh` in
+a terminal window.
This option requires neither administrator rights, nor an Apple ID.
@@ -234,20 +224,10 @@ Downloading FLTK is explained [here](#bam_download).
Using your shell in the terminal, make sure that you are in the root directory of your
FLTK source code tree.
-Create a directory where all FLTK binaries will be built:
-
-```bash
-mkdir build
-cd build
-mkdir Makefile
-cd Makefile
-```
-Now configure your FLTK installation:
+Configure your FLTK installation. CMake will create the required directories for you:
```bash
-cmake -G "Unix Makefiles" \
- -D CMAKE_BUILD_TYPE=Debug \
- ../..
+cmake -B build/Makefile -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug .
```
Replace 'Debug' with 'Release' if you want to build a release version.
@@ -256,31 +236,37 @@ _CMake_ runs a number of tests to find external headers, libraries, and tools.
The configuration summary should not show any errors. You can now continue to build FLTK.
For the advanced user there are a few more options to the _CMake_ setup. Type
-`cmake -L ../..` to get a complete list of options. These should be pretty
+`cmake -L .` to get a complete list of options. These should be pretty
self-explanatory. Some more details can be found in
[online documentation](https://www.fltk.org/doc-1.5/intro.html#intro_cmake).
<a name="bcm_build"></a>
### Building FLTK (CMake, make)
-Now this is easy if all the previous steps were successful. Stay in your `build/Makefiles`
-directory and type:
+Now this is easy if all the previous steps were successful. Stay in the root
+directory of your FLTK source code tree and type:
```bash
-make
+cmake --build build/Makefile
```
The entire FLTK toolkit including many test programs will be built for you. No
warnings should appear, but "ranlib" may complain about a few modules having no
symbols. This is normal and can safely be ignored.
+To build individual targets, you can use:
+
+```bash
+cmake --build build/Makefile --target hello
+```
+
<a name="bcm_test"></a>
### Testing FLTK (CMake, make)
After a successful build, you can test FLTK's capabilities by running
```bash
-open bin/test/demo.app
+open build/Makefile/bin/test/demo.app
```
<a name="bcm_install"></a>
@@ -290,7 +276,7 @@ If you did not change any of the configuration settings, FLTK will be installed
in `/usr/local/include`, `/usr/local/lib`, and `/usr/local/bin` by typing
```bash
-sudo make install
+sudo cmake --build build/Makefile --target install
```
It is possible to install FLTK without superuser privileges by changing the
@@ -315,187 +301,6 @@ fltk-config --compile myProgram.cxx
`PATH` variable.
-<a name="build_autoconf_make"></a>
-## How to Build FLTK Using _autoconf_ and _make_
-
-This option is best for users who like to develop their apps without using Apple's Xcode IDE
-and prefer minimal dependencies of a _Makefile_ over _CMake_. Users should be comfortable
-with using `bash` or `tcsh` in a terminal window.
-
-This option requires administrator rights, but no Apple ID.
-
-<a name="bam_prerequisites"></a>
-### Prerequisites (autoconf, make)
-
-In order to build FLTK from the command line, you need to install a C++ compiler
-environment, `make` and `autoconf`. Installing the _Xcode_ command line tools is the easiest
-way to get all prerequisites in one simple step.
-
-<a name="xcode_command_line_tools"></a>
-Launch _Terminal.app_ by pressing Command+Spacebar and typing `Terminal` and pressing _return_.
-I like to keep the Terminal in the Dock for future use (launch Terminal, right-click or control-click
-on the Terminal icon that is now in the docking bar, and choose _Options_->_Keep in Dock_).
-
-Installing the _Xcode_ command line tools is pretty straight forward. Just enter this
-and follow the dialogs:
-
-```bash
-xcode-select --install
-```
-
-On older versions of macOS, you will have to install _Xcode_ from the
-[App Store](https://itunes.apple.com/de/app/xcode/id497799835?l=en&mt=12)
-and then install the command line tools from within _Xcode_.
-
-Apple no longer includes _autoconf_ in the _Xcode_ command line tools. To install
-_autoconf_, we first need to install _brew_ by typing this rather cryptic command in the shell
-(you will need to type the password of an administrator account):
-
-```bash
-ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
-```
-
-After a few minutes, we can now build and install all other tools from one simple command:
-
-```bash
-brew install autoconf
-```
-
-Alternatively, _autoconf_ can be installed without _brew_ as follows :
-
-- Download file _autoconf-latest.tar.gz_ from the <a href=https://ftp.gnu.org/gnu/autoconf/>autoconf ftp site</a>
-- Uncompress it to get directory _autoconf-x.xx/_ (where x's indicate autoconf's version number)
-- Set this directory as your current directory in the Terminal app and type :
-
-```bash
-./configure
-make
-sudo make install
-```
-
-
-<a name="bam_download"></a>
-### Downloading and Unpacking (autoconf, make)
-
-FLTK 1.4 is currently (as of May 2021) available as a source code repository via GitHub.
-You will need to clone the repository to check out the source code onto your machine. This
-has the great benefit that the source code can be updated later simply by telling _git_ to
-_pull_ the newest release.
-
-As an alternative weekly snapshots ("tarballs") can be downloaded from
-https://www.fltk.org/software.php .
-
-Start your terminal. If you have not set up a developer directory yet, I recommend to use
-`~/dev` and put all your projects there:
-
-```bash
-# make sure we are in the home directory
-cd ~
-# create our developer directory and go there
-mkdir dev
-cd dev
-```
-Now create a copy of the source code archive at Github on your local file system:
-
-```bash
-git clone https://github.com/fltk/fltk.git fltk-1.4
-cd fltk-1.4
-```
-
-<a name="bam_config"></a>
-### Configuring FLTK (autoconf, make)
-
-Using your shell in the terminal, make sure that you are in the root directory of your
-FLTK source code tree.
-
-If you are configuring fltk for the first time, you need to instruct FLTK to create some
-very basic configuration files. Type:
-
-```bash
-autoconf
-```
-This creates the configure script.
-
-Now configure your FLTK installation. Stay in your FLTK source-code directory
-and type
-
-```bash
-./configure
-```
-
-The configuration script runs a number of tests to find external headers, libraries, and tools.
-The configuration summary should not show any errors. You can now continue to build FLTK.
-
-For the advanced user there are a few more options to the _configure_ script. Type
-`./configure --help` to get a complete list of options. These should be pretty
-self-explanatory. Some more details can be found in
-[online documentation](https://www.fltk.org/doc-1.5/intro.html#intro_cmake).
-
-<a name="bam_build"></a>
-### Building FLTK (autoconf, make)
-
-Now this is easy if all the previous steps were successful. Stay in your FLTK source-code
-directory and type:
-
-```bash
-make
-```
-
-The entire FLTK toolkit including many test programs will be built for you. No
-warnings should appear, but "ranlib" may complain about a few modules having no
-symbols. This is normal and can safely be ignored.
-
-<a name="bam_test"></a>
-### Testing FLTK (autoconf, make)
-
-After a successful build, you can test FLTK's capabilities by running
-
-```bash
-test/demo
-```
-
-<a name="bam_install"></a>
-### Installing FLTK (autoconf, make)
-
-If you did not change any of the configuration settings, FLTK will be installed
-in `/usr/local/include`, `/usr/local/lib`, and `/usr/local/bin` by typing:
-
-```bash
-sudo make install
-```
-
-It is possible to install FLTK without superuser privileges by changing the
-installation path to a location within the user account by adding the
-`--prefix=PREFIX` parameter to the `./configure` command.
-
-<a name="bam_new_projects"></a>
-### Creating new Projects (autoconf, make)
-
-FLTK provides a neat script named `fltk-config` that can provide all the flags
-needed to build FLTK applications using the same flags that were used to build
-the library itself. Running `fltk-config` without arguments will print a list
-of options. The easiest call to compile an FLTK application from a single source
-file is:
-
-```bash
-cat << EOF > main.cxx
- #include <FL/Fl.H>
- #include <FL/Fl_Window.H>
- int main(int argc, char **argv) {
- Fl_Window *win = new Fl_Window(600, 400, "Hello, world!");
- win->show(argc, argv);
- return Fl::run();
- }
-EOF
-fltk-config --compile main.cxx
-./main
-```
-
-`fltk-config` and our user interface designer `fluid` will be installed in
-`/usr/local/bin/` by default. I recommend that you add this directory to the shell
-`PATH` variable.
-
-
<a name="dropstart"></a>
## Make an Application Launchable by Dropping Files on its Icon
@@ -535,3 +340,4 @@ to the Info.plist file you have prepared.
- Dec 28 2018 - Matt: complete rework for FLTK 1.4
- Mar 01 2021 - Albrecht: minor updates, macOS Big Sur and Apple Silicon M1 (ARM)
- Feb 23 2022 - Manolo: install autoconf without brew
+- Mar 22 2025 - Matt: update for FLTK 1.5
diff --git a/documentation/CMakeLists.txt b/documentation/CMakeLists.txt
index f93d0cba5..6cd1d1462 100644
--- a/documentation/CMakeLists.txt
+++ b/documentation/CMakeLists.txt
@@ -37,16 +37,12 @@ if(GENERATE_DOCS)
# create required variables
- execute_process(COMMAND date "+%Y"
- OUTPUT_VARIABLE YEAR
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
+ string(TIMESTAMP YEAR "%Y" UTC)
# note: current locale is used for abbreviated month
- execute_process(COMMAND date "+%b %d, %Y"
- OUTPUT_VARIABLE CURRENT_DATE
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
+ string(TIMESTAMP CURRENT_DATE "%b %d, %Y" UTC)
+ string(TIMESTAMP PDF_DATE "D:%Y%m%d%H%M%SZ" UTC)
+ string(TIMESTAMP TODAY "%B %d, %Y" UTC)
+ string(REPLACE " 0" " " TODAY "${TODAY}")
# Find "short" doxygen version if it was built from Git
# Note: this is still needed in CMake 3.15 but later CMake versions
@@ -77,6 +73,8 @@ if(GENERATE_DOCS)
if(0) # debug
fl_debug_var(YEAR)
fl_debug_var(CURRENT_DATE)
+ fl_debug_var(PDF_DATE)
+ fl_debug_var(TODAY)
fl_debug_var(FLTK_GIT_REVISION)
fl_debug_var(DOXYGEN_FOUND)
fl_debug_var(DOXYGEN_EXECUTABLE)
@@ -179,7 +177,7 @@ if(FLTK_BUILD_PDF_DOCS)
COMMENT "Converting ${DOXYFILE} to doxygen version ${DOXYGEN_VERSION_SHORT}" VERBATIM
)
- # generate LaTeX title fltk-title.tex
+ # generate LaTeX title fltk-title.tex and make_pdf script
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/src/fltk-title.tex.in
@@ -187,6 +185,12 @@ if(FLTK_BUILD_PDF_DOCS)
@ONLY
)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/make_pdf.in
+ ${CMAKE_CURRENT_BINARY_DIR}/make_pdf
+ @ONLY
+ )
+
# generate fltk.pdf
add_custom_command(
@@ -196,7 +200,7 @@ if(FLTK_BUILD_PDF_DOCS)
${CMAKE_CURRENT_BINARY_DIR}/fltk-title.tex
${CMAKE_CURRENT_BINARY_DIR}/fltk-book.tex
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE}
- COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/make_pdf
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/make_pdf
COMMAND cp -f latex/refman.pdf fltk.pdf
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}
${CMAKE_CURRENT_BINARY_DIR}/fltk-title.tex
diff --git a/documentation/make_pdf b/documentation/make_pdf.in
index a5487bae4..c0e5fad8a 100755
--- a/documentation/make_pdf
+++ b/documentation/make_pdf.in
@@ -26,10 +26,15 @@
#
# Used in: Makefile and CMakeLists.txt
+run_pdflatex() {
+ pdflatex --interaction=nonstopmode \
+ "\pdfinfo{/CreationDate(@PDF_DATE@)/ModDate(@PDF_DATE@)}\input{refman.tex}"
+}
+
( cd latex
- pdflatex --interaction=nonstopmode refman.tex
+ run_pdflatex
makeindex refman.idx
- pdflatex --interaction=nonstopmode refman.tex
+ run_pdflatex
latex_count=5
while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log \
&& [ $latex_count -gt 0 ]
diff --git a/documentation/src/fltk-title.tex.in b/documentation/src/fltk-title.tex.in
index cc7f853c9..5096461c2 100644
--- a/documentation/src/fltk-title.tex.in
+++ b/documentation/src/fltk-title.tex.in
@@ -25,7 +25,7 @@ provided this copyright and permission notice are preserved.}\\
\vspace*{1.5cm}
{\large Generated by Doxygen @DOXY_VERSION@}\\
\vspace*{0.5cm}
-\today{}\\
+@TODAY@\\
\vspace*{0.5cm}
{\small Git revision @FLTK_GIT_REVISION@}\\
\end{center}
diff --git a/fltk-config.in b/fltk-config.in
index ee16204b5..c23b79ce6 100644
--- a/fltk-config.in
+++ b/fltk-config.in
@@ -2,7 +2,7 @@
#
# FLTK configuration utility.
#
-# Copyright 2000-2024 by Bill Spitzak and others.
+# Copyright 2000-2025 by Bill Spitzak and others.
# Original version Copyright 2000 by James Dean Palmer
# Adapted by Vincent Penne and Michael Sweet
#
@@ -17,7 +17,7 @@
# https://www.fltk.org/bugs.php
#
-# Variables and constants generated by configure or CMake:
+# Variables and constants generated by CMake:
# version numbers
MAJOR_VERSION=@FLTK_VERSION_MAJOR@
@@ -41,7 +41,7 @@ OPTIM="@OPTIM@"
CAIROFLAGS="@CAIROFLAGS@"
# BINARY_DIR: this is only set for CMake builds in the CMake build directory,
-# otherwise it is an empty string
+# otherwise it is an empty string (for instance in the install directory)
BINARY_DIR=@BINARY_DIR@
prefix="@prefix@"
@@ -121,7 +121,7 @@ Options telling what information we request:
[--cxxflags] return flags to compile C++ using FLTK
[--ldflags] return flags to link against FLTK
[--ldstaticflags] return flags to link against static FLTK library
- even if there are DSOs installed
+ even if there are DSOs installed
[--libs] return FLTK libraries full path for dependencies
[--prefix] return FLTK install time --prefix directory
[--includedir] return FLTK install time include directory
diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt
index bb28c2b9a..d1900b297 100644
--- a/fluid/CMakeLists.txt
+++ b/fluid/CMakeLists.txt
@@ -255,16 +255,3 @@ if(UNIX)
)
endforeach()
endif(UNIX)
-
-# Additional warnings during development
-
-if(APPLE)
- if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
- target_compile_options(fluid-lib PRIVATE
- -Wall -Wextra -Wpedantic -Werror
- -Wno-zero-as-null-pointer-constant
- -Wno-missing-field-initializers
- -Wno-unused-parameter
- )
- endif()
-endif(APPLE)
diff --git a/fluid/tools/autodoc.cxx b/fluid/tools/autodoc.cxx
index c87b59bc2..d7d8b14e4 100644
--- a/fluid/tools/autodoc.cxx
+++ b/fluid/tools/autodoc.cxx
@@ -418,7 +418,7 @@ void run_autodoc(const std::string &target_dir) {
// explain widget browser
// explain widget browser entry
Fluid.main_window->size(350, 320);
- fl_snapshot((target_dir + "Fluid.main_window.png").c_str(), Fluid.main_window, win_margin, win_blend);
+ fl_snapshot((target_dir + "main_window.png").c_str(), Fluid.main_window, win_margin, win_blend);
fl_snapshot((target_dir + "main_menubar.png").c_str(), Fluid.main_menubar, row_margin, row_blend);
fl_snapshot((target_dir + "main_browser.png").c_str(), widget_browser, FL_SNAP_AREA_CLEAR,
Fl_Rect(0, 30, FL_SNAP_TO_WINDOW, 100), row_blend, 2.0);
diff --git a/src/Fl_Choice.cxx b/src/Fl_Choice.cxx
index e5a0276af..ac9a260cf 100644
--- a/src/Fl_Choice.cxx
+++ b/src/Fl_Choice.cxx
@@ -195,6 +195,7 @@ int Fl_Choice::handle(int e) {
J1:
if (Fl::scheme()
|| fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) != textcolor()) {
+ handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this);
if (wp.deleted()) return 1;
} else {
@@ -202,6 +203,7 @@ int Fl_Choice::handle(int e) {
// temporarily override the color() of this widget...
Fl_Color c = color();
color(FL_BACKGROUND2_COLOR);
+ handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this);
if (wp.deleted()) return 1;
color(c);
diff --git a/src/Fl_Input_Choice.cxx b/src/Fl_Input_Choice.cxx
index 77a7d937e..4183b3e65 100644
--- a/src/Fl_Input_Choice.cxx
+++ b/src/Fl_Input_Choice.cxx
@@ -54,6 +54,10 @@
- 1: the user picked a different item in the choice menu
- 0: the user typed or pasted directly into the input field
+ FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
+ displaying the menu. This event provides an opportunity to update menu
+ item states and activation.
+
\par Example Use of Fl_Input_Choice
\code
#include <stdio.h>
@@ -152,6 +156,7 @@ void Fl_Input_Choice::InputMenuButton::draw() {
// Make pulldown menu appear under entire width of widget
const Fl_Menu_Item* Fl_Input_Choice::InputMenuButton::popup() {
+ handle(FL_BEFORE_MENU);
menu_end();
redraw();
Fl_Widget_Tracker mb(this);
diff --git a/src/Fl_MacOS_Sys_Menu_Bar.mm b/src/Fl_MacOS_Sys_Menu_Bar.mm
index b76deb27e..87c5089cd 100644
--- a/src/Fl_MacOS_Sys_Menu_Bar.mm
+++ b/src/Fl_MacOS_Sys_Menu_Bar.mm
@@ -167,7 +167,7 @@ const char *Fl_Mac_App_Menu::quit = "Quit %@";
{
fl_lock_function();
Fl_Menu_Item *item = (Fl_Menu_Item *)[(NSData*)[self representedObject] bytes];
- if ( item && item->callback() ) item->do_callback(NULL);
+ if ( item && item->callback() ) item->do_callback(NULL, FL_REASON_SELECTED);
fl_unlock_function();
}
- (void) setKeyEquivalentModifierMask:(int)value
diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx
index 500b20a5c..a91666ad3 100644
--- a/src/Fl_Menu.cxx
+++ b/src/Fl_Menu.cxx
@@ -146,6 +146,7 @@ class menuwindow : public window_with_items {
public:
menutitle* title;
int handle(int) FL_OVERRIDE;
+ void hide() override;
int itemheight; // zero == menubar
int numitems;
int selected;
@@ -480,6 +481,11 @@ menuwindow::~menuwindow() {
delete title;
}
+void menuwindow::hide() {
+ set_selected(-1);
+ window_with_items::hide();
+}
+
void menuwindow::position(int X, int Y) {
if (title) {title->position(X, title->y()+Y-y());}
Fl_Menu_Window::position(X, Y);
@@ -592,7 +598,20 @@ void menuwindow::draw() {
}
void menuwindow::set_selected(int n) {
- if (n != selected) {selected = n; damage(FL_DAMAGE_CHILD);}
+ if (n != selected) {
+ if ((selected!=-1) && (menu)) {
+ const Fl_Menu_Item *mi = menu->next(selected);
+ if ((mi) && (mi->callback_) && (mi->flags & FL_MENU_CHATTY))
+ mi->do_callback(this, FL_REASON_LOST_FOCUS);
+ }
+ selected = n;
+ if ((selected!=-1) && (menu)) {
+ const Fl_Menu_Item *mi = menu->next(selected);
+ if ((mi) && (mi->callback_) && (mi->flags & FL_MENU_CHATTY))
+ mi->do_callback(this, FL_REASON_GOT_FOCUS);
+ }
+ damage(FL_DAMAGE_CHILD);
+ }
}
////////////////////////////////////////////////////////////////
diff --git a/src/Fl_Menu_.cxx b/src/Fl_Menu_.cxx
index 20964e748..6a34278ff 100644
--- a/src/Fl_Menu_.cxx
+++ b/src/Fl_Menu_.cxx
@@ -401,8 +401,11 @@ const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
value_ = v;
if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) {
if (changed() || when()&FL_WHEN_NOT_CHANGED) {
- if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this);
- else do_callback();
+ if (value_ && value_->callback_) {
+ value_->do_callback((Fl_Widget*)this, value_->user_data(), FL_REASON_SELECTED);
+ } else {
+ do_callback(FL_REASON_SELECTED);
+ }
}
}
}
diff --git a/src/Fl_Menu_Bar.cxx b/src/Fl_Menu_Bar.cxx
index b26131b01..3a7530bee 100644
--- a/src/Fl_Menu_Bar.cxx
+++ b/src/Fl_Menu_Bar.cxx
@@ -49,6 +49,7 @@ int Fl_Menu_Bar::handle(int event) {
case FL_PUSH:
v = 0;
J1:
+ handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
picked(v);
return 1;
@@ -71,6 +72,7 @@ Fl_Menu_Bar::Fl_Menu_Bar(int X, int Y, int W, int H,const char *l)
void Fl_Menu_Bar::play_menu(const Fl_Menu_Item *v) {
if (v) {
+ handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
picked(v);
}
diff --git a/src/Fl_Menu_Button.cxx b/src/Fl_Menu_Button.cxx
index 22a85f52d..5321dbf48 100644
--- a/src/Fl_Menu_Button.cxx
+++ b/src/Fl_Menu_Button.cxx
@@ -59,6 +59,7 @@ void Fl_Menu_Button::draw() {
\see Fl_Menu_::menu_end()
*/
const Fl_Menu_Item* Fl_Menu_Button::popup() {
+ handle(FL_BEFORE_MENU);
menu_end();
const Fl_Menu_Item* m;
pressed_menu_button_ = this;
diff --git a/src/Fl_Screen_Driver.cxx b/src/Fl_Screen_Driver.cxx
index 05461a2a1..d7a794726 100644
--- a/src/Fl_Screen_Driver.cxx
+++ b/src/Fl_Screen_Driver.cxx
@@ -385,7 +385,7 @@ void Fl_Screen_Driver::rescale_all_windows_from_screen(int screen, float f, floa
Fl_Window *win = Fl::first_window();
while (win) {
if (!win->parent() && (Fl_Window_Driver::driver(win)->screen_num() == screen) &&
- win->user_data() != &Fl_Screen_Driver::transient_scale_display) {
+ win->user_data() != (void*)&Fl_Screen_Driver::transient_scale_display) {
count++;
}
win = Fl::next_window(win);
@@ -396,7 +396,7 @@ void Fl_Screen_Driver::rescale_all_windows_from_screen(int screen, float f, floa
win = Fl::first_window(); // memorize all top-level windows
while (win) {
if (!win->parent() && (Fl_Window_Driver::driver(win)->screen_num() == screen) &&
- win->user_data() != &Fl_Screen_Driver::transient_scale_display) {
+ win->user_data() != (void*)&Fl_Screen_Driver::transient_scale_display) {
win_array[i++] = win;
}
win = Fl::next_window(win);
diff --git a/src/Fl_Tooltip.cxx b/src/Fl_Tooltip.cxx
index 674c57a49..572d763d1 100644
--- a/src/Fl_Tooltip.cxx
+++ b/src/Fl_Tooltip.cxx
@@ -25,6 +25,9 @@
#include <stdio.h>
+
+// #define DEBUG
+
float Fl_Tooltip::delay_ = 1.0f;
float Fl_Tooltip::hidedelay_ = 12.0f;
float Fl_Tooltip::hoverdelay_ = 0.2f;
@@ -38,6 +41,7 @@ int Fl_Tooltip::margin_width_ = 3;
int Fl_Tooltip::margin_height_ = 3;
int Fl_Tooltip::wrap_width_ = 400;
const int Fl_Tooltip::draw_symbols_ = 1;
+char *Fl_Tooltip::override_text_ = nullptr;
static const char* tip;
@@ -154,14 +158,49 @@ static void tooltip_hide_timeout(void*) {
recent_tooltip = 0;
}
-static void tooltip_timeout(void*) {
+/**
+ Use this method to temporarily change the tooltip text before it is displayed.
+
+ When FLTK sends an FL_BEFORE_TOOLTIP event to the widget under the mouse
+ pointer, you can handle this event to modify the tooltip text dynamically.
+ The provided text will be copied into a local buffer. To apply the override,
+ the event handler must return 1.
+
+ To disable the tooltip for the current event, set the override text to nullptr
+ or an empty string ("") and return 1.
+
+ \param[in] new_text a C string that will be copied into a buffer
+ \return always 1, so this call can finish the FL_BEFORE_TOOLTIP event handling.
+
+ \see void Fl_Widget::tooltip(const char *text).
+
+ \see `test/color_chooser.cxx` for a usage example.
+*/
+int Fl_Tooltip::override_text(const char *new_text) {
+ if (new_text != override_text_) {
+ if (window && window->label()==override_text_)
+ ((Fl_Widget *) window)->label(nullptr);
+ if (override_text_)
+ ::free(override_text_);
+ override_text_ = nullptr;
+ if (new_text)
+ override_text_ = ::strdup(new_text);
+ }
+ return 1;
+}
+
+void Fl_Tooltip::tooltip_timeout_(void*) {
#ifdef DEBUG
- puts("tooltip_timeout();");
+ puts("tooltip_timeout_();");
#endif // DEBUG
if (recursion) return;
recursion = 1;
if (!top_win_iconified_()) { // no tooltip if top win iconified (STR #3157)
+ if (Fl_Tooltip::current()) {
+ if (Fl_Tooltip::current()->handle(FL_BEFORE_TOOLTIP))
+ tip = Fl_Tooltip::override_text_;
+ }
if (!tip || !*tip) {
if (window) window->hide();
Fl::remove_timeout(tooltip_hide_timeout);
@@ -253,7 +292,7 @@ void Fl_Tooltip::exit_(Fl_Widget *w) {
if (!widget_ || (w && w == window)) return;
widget_ = 0;
- Fl::remove_timeout(tooltip_timeout);
+ Fl::remove_timeout(tooltip_timeout_);
Fl::remove_timeout(recent_timeout);
if (window && window->visible()) {
window->hide();
@@ -298,7 +337,7 @@ void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char*
}
// do nothing if it is the same:
if (wid==widget_ /*&& x==X && y==currentTooltipY && w==W && h==currentTooltipH*/ && t==tip) return;
- Fl::remove_timeout(tooltip_timeout);
+ Fl::remove_timeout(tooltip_timeout_);
Fl::remove_timeout(recent_timeout);
// remember it:
widget_ = wid; currentTooltipY = y; currentTooltipH = h; tip = t;
@@ -308,7 +347,7 @@ void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char*
window->hide();
Fl::remove_timeout(tooltip_hide_timeout);
}
- Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout);
+ Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout_);
} else if (Fl_Tooltip::delay() < .1) {
// possible fix for the Windows titlebar, it seems to want the
// window to be destroyed, moving it messes up the parenting:
@@ -316,13 +355,13 @@ void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char*
window->hide();
Fl::remove_timeout(tooltip_hide_timeout);
}
- tooltip_timeout(0);
+ tooltip_timeout_(nullptr);
} else {
if (window && window->visible()) {
window->hide();
Fl::remove_timeout(tooltip_hide_timeout);
}
- Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout);
+ Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout_);
}
#ifdef DEBUG
@@ -341,19 +380,25 @@ void Fl_Tooltip::set_enter_exit_once_() {
}
/**
- Sets the current tooltip text.
+ Sets the Tooltip Text for a Widget.
- Sets a string of text to display in a popup tooltip window when the user
- hovers the mouse over the widget. The string is <I>not</I> copied, so
- make sure any formatted string is stored in a static, global,
- or allocated buffer. If you want a copy made and managed for you,
- use the copy_tooltip() method, which will manage the tooltip string
- automatically.
+ Assigns a tooltip string that appears in a popup when the user hovers over
+ the widget. The provided string is not copied. The caller must eensure it
+ remains valid by storing it in a static, global, or dynamically allocated
+ buffer. If you need the tooltip string to be copied and managed automatically,
+ use copy_tooltip().
+
+ By default, a widget inherits the tooltip of its parent if none is explicitly
+ set. If you assign a tooltip to a group but not to its child widgets, the
+ child widgets will display the group’s tooltip. To prevent inheritance, set
+ the child’s tooltip to an empty string ("").
+
+ Tooltips can be updated dynamically before they are displayed. When a tooltip
+ is about to be shown, FLTK sends an `FL_BEFORE_TOOLTIP` event to the widget’s
+ `handle()` method. Developers can override the tooltip text temporarily
+ using `Fl_Tooltip::override_text(const char* new_text)` and returning 1 from
+ `handle()` to apply the change.
- If no tooltip is set, the tooltip of the parent is inherited. Setting a
- tooltip for a group and setting no tooltip for a child will show the
- group's tooltip instead. To avoid this behavior, you can set the child's
- tooltip to an empty string ("").
\param[in] text New tooltip text (no copy is made)
\see copy_tooltip(const char*), tooltip()
*/
diff --git a/src/Fl_Tree_Item.cxx b/src/Fl_Tree_Item.cxx
index 616a77392..5234bbd3c 100644
--- a/src/Fl_Tree_Item.cxx
+++ b/src/Fl_Tree_Item.cxx
@@ -705,7 +705,8 @@ int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) {
return(0);
}
-/// Internal: Horizontal connector line based on preference settings.
+/// Horizontal connector line based on preference settings.
+/// This method can be overridden to implement custom connection line drawing.
/// \param[in] x1 The left hand X position of the horizontal connector
/// \param[in] x2 The right hand X position of the horizontal connector
/// \param[in] y The vertical position of the horizontal connector
@@ -730,7 +731,8 @@ void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tre
}
}
-/// Internal: Vertical connector line based on preference settings.
+/// Vertical connector line based on preference settings.
+/// This method can be overridden to implement custom connection line drawing.
/// \param[in] x The x position of the vertical connector
/// \param[in] y1 The top of the vertical connector
/// \param[in] y2 The bottom of the vertical connector
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 468c4b0d0..1e3e68637 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -686,7 +686,7 @@ void Fl_Cocoa_Screen_Driver::breakMacEventLoop()
}
return self;
}
-- (Fl_Window *)getFl_Window;
+- (Fl_Window *)getFl_Window
{
return w;
}
@@ -1525,13 +1525,13 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
Fl::handle(FL_HIDE, window);
fl_unlock_function();
}
-- (void)windowWillEnterFullScreen:(NSNotification *)notif;
+- (void)windowWillEnterFullScreen:(NSNotification *)notif
{
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *window = [nsw getFl_Window];
window->_set_fullscreen();
}
-- (void)windowWillExitFullScreen:(NSNotification *)notif;
+- (void)windowWillExitFullScreen:(NSNotification *)notif
{
FLWindow *nsw = (FLWindow*)[notif object];
Fl_Window *window = [nsw getFl_Window];
@@ -3251,7 +3251,7 @@ void Fl_Cocoa_Window_Driver::makeWindow()
w->set_visible();
if ( w->border() || (!w->modal() && !w->tooltip_window() &&
- w->user_data() != &Fl_Screen_Driver::transient_scale_display) ) Fl::handle(FL_FOCUS, w);
+ w->user_data() != (void*)&Fl_Screen_Driver::transient_scale_display) ) Fl::handle(FL_FOCUS, w);
[cw setDelegate:[FLWindowDelegate singleInstance]];
if (show_iconic()) {
show_iconic(0);
@@ -4747,7 +4747,7 @@ static CGImageRef capture_decorated_window_SCK(NSWindow *nswin) {
}
win = Fl::next_window(win);
}
- CGWindowID target_id = [nswin windowNumber];
+ CGWindowID target_id = (CGWindowID)[nswin windowNumber];
NSRect r = [nswin frame];
int W = r.size.width, H = r.size.height;
[SCShareableContent getCurrentProcessShareableContentWithCompletionHandler: // macOS 14.4
@@ -4791,7 +4791,7 @@ static CGImageRef capture_decorated_window_SCK(NSWindow *nswin) {
while (!capture_err && !capture) CFRunLoopRun();
if (capture_err) return NULL;
// ScreenCaptureKit bug cont'd: restore modified styleMasks.
- for (int i = 0, count = [xid_array count]; i < count; i++) {
+ for (int i = 0, count = (int)[xid_array count]; i < count; i++) {
NSUInteger mask;
[(NSData*)[mask_array objectAtIndex:i] getBytes:&mask length:sizeof(NSUInteger)];
NSWindow *xid = (NSWindow*)[xid_array objectAtIndex:i];
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
index 552f26dfc..88eb2cdca 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
@@ -441,6 +441,7 @@ void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) {
extern void fl_clipboard_notify_retarget(HWND wnd);
extern void fl_update_clipboard(void);
+extern char fl_i_own_selection[2];
void Fl_WinAPI_Window_Driver::hide() {
Fl_X* ip = Fl_X::flx(pWindow);
@@ -474,6 +475,8 @@ void Fl_WinAPI_Window_Driver::hide() {
// Issue #569: undo RegisterDragDrop()
RevokeDragDrop((HWND)ip->xid);
+
+ fl_i_own_selection[1] = 0; // issue #1233
// make sure any custom icons get freed
// icons(NULL, 0); // free_icons() is called by the Fl_Window destructor
diff --git a/src/fl_write_png.cxx b/src/fl_write_png.cxx
index 0f980476a..855e03551 100644
--- a/src/fl_write_png.cxx
+++ b/src/fl_write_png.cxx
@@ -1,7 +1,7 @@
//
// Fl_PNG_Image support functions for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2005-2021 by Bill Spitzak and others.
+// Copyright 2005-2025 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
@@ -18,9 +18,16 @@
#include <FL/Fl_PNG_Image.H>
#include <FL/Fl_RGB_Image.H>
#include <FL/fl_string_functions.h>
-#include <FL/fl_utf8.h> // fl_fopen()
+#include <FL/fl_utf8.h> // fl_fopen()
#include <stdio.h>
-#include <time.h> // hack to restore "configure --enable-x11" on macOS ≥ 11
+
+// FIXME: see original commit 2db94dcb4c5bf2ef3fa92f1cd6a41f3f90105361
+// ... about building X11 backend on macOS ≥ 11:
+// "The error happens only if png.h is included without time.h having
+// been included before. The fix is to #include time.h before png.h.
+// A better fix than his hack is desirable."
+
+#include <time.h>
// PNG library include files
diff --git a/test/color_chooser.cxx b/test/color_chooser.cxx
index 61fbc4caf..263cad28a 100644
--- a/test/color_chooser.cxx
+++ b/test/color_chooser.cxx
@@ -21,6 +21,7 @@
#include <FL/fl_show_colormap.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_Image.H>
+#include <FL/Fl_Tooltip.H>
#include <FL/platform.H>
#include <FL/fl_draw.H>
@@ -84,10 +85,35 @@ void cb2(Fl_Widget *, void *v) {
bx->parent()->redraw();
}
+class Sample_Box: public Fl_Box {
+public:
+ Sample_Box(int x, int y, int w, int h, const char *label = nullptr)
+ : Fl_Box(x, y, w, h, label) { }
+ int handle(int event) override {
+ if (event == FL_BEFORE_TOOLTIP) {
+ char buf[128];
+ uchar r, g, b;
+ Fl::get_color(color(), r, g, b);
+ if ((color()&255) && (color()!=16)) {
+ ::snprintf(buf, 127,
+ "Background color is:\n"
+ "palette no. %d = r:%d, g:%d, b:%d", color(), r, g, b);
+ } else {
+ ::snprintf(buf, 127,
+ "Background color is:\n"
+ "r:%d, g:%d, b:%d", r, g, b);
+ }
+ return Fl_Tooltip::override_text(buf);
+ }
+ return Fl_Box::handle(event);
+ }
+};
+
int main(int argc, char ** argv) {
Fl::set_color(fullcolor_cell,145,159,170);
Fl_Window window(400,400);
- Fl_Box box(30,30,340,340);
+ Sample_Box box(30,30,340,340);
+ box.tooltip("Show RGB values");
box.box(FL_THIN_DOWN_BOX);
c = fullcolor_cell;
box.color(c);
diff --git a/test/fractals.cxx b/test/fractals.cxx
index d9cf9905f..5e3839d03 100644
--- a/test/fractals.cxx
+++ b/test/fractals.cxx
@@ -70,7 +70,7 @@ int main(int, char**) {
# define srand48(x) (srand((x)))
#elif defined __APPLE__
# define drand48() (((float) rand())/((float) RAND_MAX))
-# define srand48(x) (srand((x)))
+# define srand48(x) (srand((int)(x)))
#endif
typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF,
diff --git a/test/menubar.cxx b/test/menubar.cxx
index a5ccfc234..355921eba 100644
--- a/test/menubar.cxx
+++ b/test/menubar.cxx
@@ -61,7 +61,19 @@ void test_cb(Fl_Widget* w, void*) {
G_tty->printf("%s\n", m->label());
}
-void quit_cb(Fl_Widget*, void*) {exit(0);}
+void quit_cb(Fl_Widget*, void*) {
+ switch (Fl::callback_reason()) {
+ case FL_REASON_SELECTED:
+ exit(0);
+ case FL_REASON_GOT_FOCUS:
+ G_tty->printf("Selecting this menu item will quit this application!\n");
+ break;
+ case FL_REASON_LOST_FOCUS:
+ G_tty->printf("Risk of quitting averted.\n");
+ break;
+ default: break;
+ }
+}
Fl_Menu_Item hugemenu[100];
@@ -70,7 +82,7 @@ Fl_Menu_Item menutable[] = {
{"&File",0,0,0,FL_SUBMENU},
{"&Open", FL_ALT+'o', 0, 0, FL_MENU_INACTIVE},
{"&Close", 0, 0},
- {"&Quit", FL_ALT+'q', quit_cb, 0, FL_MENU_DIVIDER},
+ {"&Quit", FL_ALT+'q', quit_cb, 0, FL_MENU_DIVIDER|FL_MENU_CHATTY},
#if (OVERRIDE_SCALING_SHORTCUTS)
{"CTRL/0", FL_COMMAND+'0', 0},
@@ -210,7 +222,7 @@ void menu_location_cb(Fl_Widget* w, void* data)
if (((Fl_Choice*)w)->value() == 1) { // switch to system menu bar
menubar->hide();
const Fl_Menu_Item *menu = menubar->menu();
- smenubar = new Fl_Sys_Menu_Bar(0,0,0,30);
+ smenubar = new Fl_Sys_Menu_Bar(0,0,0,30);
smenubar->menu(menu);
smenubar->callback(test_cb);
}
@@ -236,6 +248,30 @@ void about_cb(Fl_Widget*, void*) {
fl_message("The menubar test app.");
}
+class Dynamic_Choice: public Fl_Choice {
+public:
+ Dynamic_Choice(int x, int y, int w, int h, const char *label=nullptr)
+ : Fl_Choice(x, y, w, h, label) { }
+ int handle(int event) override {
+ static int flip_flop = 0;
+ if (event == FL_BEFORE_MENU) {
+ // The following line is legal because we used `copy()` to create a
+ // writable copy of the menu array when creating this Choice.
+ Fl_Menu_Item *mi = const_cast<Fl_Menu_Item*>(menu());
+ if (flip_flop == 1) {
+ mi[7].flags |= FL_MENU_INACTIVE;
+ mi[8].flags &= ~FL_MENU_INACTIVE;
+ flip_flop = 0;
+ } else {
+ mi[7].flags &= ~FL_MENU_INACTIVE;
+ mi[8].flags |= FL_MENU_INACTIVE;
+ flip_flop = 1;
+ }
+ }
+ return Fl_Choice::handle(event);
+ }
+};
+
int main(int argc, char **argv) {
for (int i=0; i<99; i++) {
char buf[100];
@@ -256,7 +292,10 @@ int main(int argc, char **argv) {
mb1.tooltip("this is a menu button");
mb1.callback(test_cb);
menus[1] = &mb1;
- Fl_Choice ch(300,100,80,25,"&choice:"); ch.menu(pulldown);
+ Dynamic_Choice ch(300,100,80,25,"&choice:");
+ ch.copy(pulldown);
+ ch.add("Flip");
+ ch.add("Flop");
ch.tooltip("this is a choice menu");
ch.callback(test_cb);
menus[2] = &ch;
diff --git a/test/terminal.fl b/test/terminal.fl
index b2c0d4d1f..3c9186b68 100644
--- a/test/terminal.fl
+++ b/test/terminal.fl
@@ -452,8 +452,7 @@ const char *test[] = {
};
if (reset) { index = 0; return 0; }
-return show_test(test, index);} {selected
- }
+return show_test(test, index);} {}
}
Function {test_esc_rgbcolors(bool reset)} {
comment {--- 0020: Test RGB Colors} return_type {static int}
@@ -1373,7 +1372,7 @@ for ( int t=0; t<count; t++ )
}
Function {do_command(const char *cmd)} {
comment {Run the command, output appends to terminal
-} return_type void
+} open return_type void
} {
code {// Run command in pipe, return output to tty
// TODO: This should probably be reimplemented as a thread.
@@ -1420,13 +1419,14 @@ while (1) {
Fl::wait(0.05);
SSIZE_T bytes = READ(fd, s, sizeof(s)); // shout in uppercase so windows can hear us
if (bytes == -1 && errno == EAGAIN) continue; // no data yet
- else if (bytes > 0) G_tty->append(s, bytes); // write block to terminal, handles utf8
+ else if (bytes > 0) G_tty->append(s, (int)bytes); // write block to terminal, handles utf8
else break; // pipe closed
}
PCLOSE(fp);
G_tty->append_ascii("\\033[33;2m<<END_OF_OUTPUT>>\\033[0m\\n");
-G_tty->redraw();} {}
+G_tty->redraw();} {selected
+ }
}
decl {////// GUI LAYOUT //////} {private local
}