How to tell which widget called a function.

112 views
Skip to first unread message

Jon Cooper

unread,
Aug 16, 2026, 9:39:24 PMAug 16
to fltk.general
My C, etc, is not very good but if I have 2 widgets that have the same callback function, how can the callback function tell which widget called it? I have successfully done this by passing a char* pointer as the second parameter to the callback so it can check from that, but is there a neater way I can get the info from just the widget itself, rather than having to pass an extra parameter? I tried searching the web, fltk manual and this group but couldn't obviously find the answer, sorry!

Greg Ercolano

unread,
Aug 16, 2026, 11:14:04 PMAug 16
to fltkg...@googlegroups.com

On 8/16/26 18:39, 'Jon Cooper' via fltk.general wrote:

My C, etc, is not very good but if I have 2 widgets that have the same callback function, how can the callback function tell which widget called it? I have successfully done this by passing a char* pointer as the second parameter to the callback so it can check from that, but is there a neater way I can get the info from just the widget itself, rather than having to pass an extra parameter? I tried searching the web, fltk manual and this group but couldn't obviously find the answer, sorry!

    The first parameter to the callback is a pointer to the widget that invoked the callback.

    The callback is invoked with two values:
  • The widget that invoked the callback
  • The optional user data you supply (if any)

Albrecht Schlosser

unread,
Aug 17, 2026, 7:34:25 AMAug 17
to fltkg...@googlegroups.com
The standard signature of a callback is documented here:
https://www.fltk.org/doc-1.4/common.html#common_callbacks
void xyz_callback(Fl_Widget* w, void* data) {
  // ...
}

You should always use exactly this signature in your program for compatibility, don't use, for instance, Fl_Button* as the first parameter type (although this is generally possible, it may cause compiler warnings). A typical callback would cast the arguments to the expected types. Here's a full, working example that uses the second parameter as a struct with additional data.

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <stdio.h>
struct my_struct {
int num;
const char* text;
};
void quit_callback(Fl_Widget* w, void* v) {
Fl_Button* button = static_cast<Fl_Button*>(w);
my_struct* data = static_cast<my_struct*>(v);
printf("Callback called by button \"%s\" with data { %d, \"%s\" }\n",
button->label(), data->num, data->text);
Fl::hide_all_windows();
}
int main(int argc, char** argv) {
auto window = new Fl_Window(340, 140, "callback test");
auto bt = new Fl_Button(20, 20, 300, 100, "Quit");
struct my_struct my_abc{5, "Hello struct"};
bt->callback(quit_callback, &my_abc);
window->end();
window->show(argc, argv);
return Fl::run();
}
// end of file Output: Callback called by button "Quit" with data { 5, "Hello struct" }

Jon Cooper

unread,
Aug 17, 2026, 8:44:24 AMAug 17
to fltk.general
Thank you both very much. Albrecht's example uses the 2nd parameter to indicate this to the callback. 

It's probably an embarrasingly stupid question, but the first parameter is a pointer to / name for a chunk of memory for the widget calling the callback function. Is there any way the callback can extract the humanly readable name of the calling widget from that pointer. 

Do remember my question is very basic, sorry! It is probably just one symbol like & or something, but I could not work it out as my c is so bad. 

Brian Larsen

unread,
Aug 17, 2026, 9:04:14 AMAug 17
to fltk.general
Albrecht's example shows the use of button->label(), which gets the label string of that widget. Is that good enough?
If you want to actually use the name of the widget variable, you could store that string in my_struct, either in the text field or you can create another field to store it in.

Albrecht Schlosser

unread,
Aug 17, 2026, 9:08:54 AMAug 17
to fltkg...@googlegroups.com
On 8/17/26 14:44 'Jon Cooper' via fltk.general wrote:
Thank you both very much. Albrecht's example uses the 2nd parameter to indicate this to the callback.

Hmm, not really. See below.


It's probably an embarrasingly stupid question, but the first parameter is a pointer to / name for a chunk of memory for the widget calling the callback function. Is there any way the callback can extract the humanly readable name of the calling widget from that pointer.

My example kinda does this. It prints the label of the widget which is one way to "extract the humanly readable name" of the widget. If your widget doesn't use a label, then there is no humanly readable "name" stored with the widget itself.

The 2nd argument can be seen as a kind of context information. You may use it or not, a simple use is to just use `(void*)5` which (as you know) just transmits a pointer to an int. My example shows a pointer to an arbitrary struct. This is a more generalized form where you can send an arbitrary amount of "context data". I chose to use an int and a pointer to a string, but you are free to put anything you like into *your* struct if you want to do that. But keep in mind that the (void*) pointer must be valid, i.e. the struct's lifetime must be guaranteed until the callback is actually executed. In my example it's a static struct which is fine.

--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/fltkgeneral/5a243a7d-1a76-489c-b758-f26863af9f46n%40googlegroups.com.

Albrecht Schlosser

unread,
Aug 17, 2026, 9:14:10 AMAug 17
to fltkg...@googlegroups.com
Correction:

On 8/17/26 15:08 'Albrecht Schlosser' wrote:
> just use `(void*)5` which (as you know) just transmits a pointer to an
> int.

Sorry, that's not correct. It's a (void *) pointer with a **value** of
5. You need to cast it back to an int to use it.

imm

unread,
Aug 17, 2026, 9:31:44 AMAug 17
to fltkg...@googlegroups.com
On Mon, 17 Aug 2026 at 13:44, 'Jon Cooper' wrote:
>
> the first parameter is a pointer to / name for a chunk of memory for the widget calling the callback function. Is there any way the callback can extract the humanly readable name of the calling widget from that pointer.
>

Albrecht's example shows how to use the widget pointer you are given
to find the label() string of the button, and you can use that same
approach to call any of the methods the widget supports.

But... is this a question about some sort of introspection, in effect?
Are you trying to find out the actual source-code name of the variable
that was passed?
That's tricker - the C/C++ style languages don't really support that
sort of idiom. (Most C compilers are not that bothered about the
"human" names for things...)
Reading the label is probably the easiest human-friendly thing, I think.

Jose Quinteiro

unread,
Aug 17, 2026, 3:33:40 PMAug 17
to fltkg...@googlegroups.com

On Mon, 17 Aug 2026 05:44:24 -0700 (PDT), 'Jon Cooper' via fltk.general
wrote:
> Thank you both very much. Albrecht's example uses the 2nd parameter
> to
> indicate this to the callback. 
>
> It's probably an embarrasingly stupid question, but the first
> parameter is a pointer to / name for a chunk of memory for the widget
> calling the callback function. Is there any way the callback can
> extract the humanly readable name of the calling widget from that
> pointer. 
>
> Do remember my question is very basic, sorry! It is probably just one
> symbol like & or something, but I could not work it out as my c is so
> bad. 
>
Hopefully I'm understanding your question correctly. Are you looking
for something like this?

struct cbdata {
char* sysctl_name;
Fl_Gauge* gauge;
};

void gaugecb(void* p_data) {
struct cbdata* data = (struct cbdata*)p_data;

if (0 == (sysctlbyname(data->sysctl_name, &t_dK, &size, NULL, 0))) {
...

struct cbdata l_cbdata[4];
Fl_Gauge* gauge;

for(int i = 0; i < 4; i++)
{
asprintf(&temp, "CPU%d", i);
gauge = new Fl_Gauge(10 + i * 140, 20, 130, 130, temp);
...
asprintf(&temp, "dev.cpu.%d.temperature", i);
l_cbdata[i].sysctl_name = temp;
l_cbdata[i].gauge = gauge;
}
...
for(int i = 0; i < 4; i++)
{
Fl::add_timeout(1.0, gaugecb, &(l_cbdata[i]));
}
...

Full example:
https://forums.freebsd.org/threads/fltk-displaying-a-sysctl-value.100619/page-4#post-732185

HTH,
Jose

> On Monday, 17 August 2026 at 12:34:25 UTC+1 Albrecht-S wrote:
>
>> On 8/17/26 05:14 Greg Ercolano wrote:
>>
>>> On 8/16/26 18:39, Jon Cooper via fltk.general wrote:
>>>
>>>> My C, etc, is not very good but if I have 2 widgets that have
>>>> the same callback function, how can the callback function tell
>>>> which widget called it? I have successfully done this by passing
>>>> a char* pointer as the second parameter to the callback so it
>>>> can check from that, but is there a neater way I can get the
>>>> info from just the widget itself, rather than having to pass an
>>>> extra parameter? I tried searching the web, fltk manual and this
>>>> group but couldnt obviously find the answer, sorry!
>>>
>>>     The first parameter to the callback is a pointer to the
>>> widget that invoked the callback.
>>>
>>>     The callback is invoked with two values:
>>>
>>> * The widget that invoked the callback
>>> * The optional user data you supply (if any)
>>
>> The standard signature of a callback is documented here:
>> https://www.fltk.org/doc-1.4/common.html#common_callbacks [1]
>>
>> void xyz_callback(Fl_Widget* w, void* data) {
>> // ...
>> }
>>
>> You should always use _EXACTLY THIS SIGNATURE_ in your program for
>> compatibility, dont use, for instance, Fl_Button* as the first
>> parameter type (although this is generally possible, it may cause
>> compiler warnings). A typical callback would cast the arguments to
>> the expected types. Heres a full, working example that uses the
>> second parameter as a struct with additional data.
>>
>> #include
>> #include
>> #include
>> #include
>> struct my_struct {
>> int num;
>> const char* text;
>> };
>> void quit_callback(Fl_Widget* w, void* v) {
>> Fl_Button* button = static_cast(w);
>> my_struct* data = static_cast(v);
>> printf("Callback called by button "%s" with data { %d, "%s" }n",
>> button->label(), data->num, data->text);
>> Fl::hide_all_windows();
>> }
>> int main(int argc, char** argv) {
>> auto window = new Fl_Window(340, 140, "callback test");
>> auto bt = new Fl_Button(20, 20, 300, 100, "Quit");
>> struct my_struct my_abc{5, "Hello struct"};
>> bt->callback(quit_callback, &my_abc);
>> window->end();
>> window->show(argc, argv);
>> return Fl::run();
>> }// end of file Output: Callback called by button "Quit" with data {
>> 5, "Hello struct" }
>
> --
> You received this message because you are subscribed to the Google
> Groups "fltk.general" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to fltkgeneral...@googlegroups.com [2].
> [3].
>
>
> Links:
> ------
> [1] https://www.fltk.org/doc-1.4/common.html#common_callbacks
> [2] mailto:fltkgeneral...@googlegroups.com
> [3]
>
> https://groups.google.com/d/msgid/fltkgeneral/5a243a7d-1a76-489c-b758-f26863af9f46n%40googlegroups.com?utm_medium=email&utm_source=footer

Jon Cooper

unread,
Aug 17, 2026, 5:01:19 PMAug 17
to fltk.general
Thank you very much for the info. Lots of lovely code examples there, much appreciated. Getting the widget label does work for me now. I swear couldn't do it before! This:

cout<<w->label()<<"\n";

does it for my purposes. Thanks for all the info about type casting - I will work on that.

Greg Ercolano

unread,
Aug 17, 2026, 6:55:25 PMAug 17
to fltkg...@googlegroups.com
    Yes, that's right.

    BTW, if you're starting out with FLTK, here's a couple of old (but still relevant) videos on using FLTK:
Intro to using FLTK:
https://www.seriss.com/people/erco/fltk-videos/tutorial-fltk-hello.html

Intro to using Fluid:
https://www.seriss.com/people/erco/fltk-videos/fluid-intro.html
Reply all
Reply to author
Forward
0 new messages