diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2025-04-03 11:23:57 +0200 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2025-04-03 11:23:57 +0200 |
| commit | 71caca84d92161792861fb33381f7a9c2be05343 (patch) | |
| tree | 0a9bd0ef23ba4051af4070dba1afcf87111ec7b6 /src | |
| parent | 07bb343de7c6b4152a7eb8940da99d5d006f27cd (diff) | |
| parent | 678c85027294c0ae5162d02b20a59fde758ac77a (diff) | |
Merge remote-tracking branch 'refs/remotes/origin/master'
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Choice.cxx | 2 | ||||
| -rw-r--r-- | src/Fl_Input_Choice.cxx | 5 | ||||
| -rw-r--r-- | src/Fl_MacOS_Sys_Menu_Bar.mm | 2 | ||||
| -rw-r--r-- | src/Fl_Menu.cxx | 21 | ||||
| -rw-r--r-- | src/Fl_Menu_.cxx | 7 | ||||
| -rw-r--r-- | src/Fl_Menu_Bar.cxx | 2 | ||||
| -rw-r--r-- | src/Fl_Menu_Button.cxx | 1 | ||||
| -rw-r--r-- | src/Fl_Screen_Driver.cxx | 4 | ||||
| -rw-r--r-- | src/Fl_Tooltip.cxx | 81 | ||||
| -rw-r--r-- | src/Fl_Tree_Item.cxx | 6 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 12 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx | 3 | ||||
| -rw-r--r-- | src/fl_write_png.cxx | 13 |
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 |
