summaryrefslogtreecommitdiff
path: root/src
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 /src
parent07bb343de7c6b4152a7eb8940da99d5d006f27cd (diff)
parent678c85027294c0ae5162d02b20a59fde758ac77a (diff)
Merge remote-tracking branch 'refs/remotes/origin/master'
Diffstat (limited to 'src')
-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
13 files changed, 124 insertions, 35 deletions
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