Rerouting Events to other Gadgets ?
- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Rerouting Events to other Gadgets ?
Hi,
Is it possible to reroute an Event from one Gadget to another one ?
For instance let says I have a CanvasGadget and a StringGadget and I want to resend the '#PB_EventType_LeftButtonDown' recieved by the CanvasGadget to the StringGadget when I recieve it.
Is it possible directly in PureBasic ?
On Windows I workaround the problem by subclassing the control, but on linux, I'm not sure what to do.
Any idea ?
Cheers,
Guy.
Is it possible to reroute an Event from one Gadget to another one ?
For instance let says I have a CanvasGadget and a StringGadget and I want to resend the '#PB_EventType_LeftButtonDown' recieved by the CanvasGadget to the StringGadget when I recieve it.
Is it possible directly in PureBasic ?
On Windows I workaround the problem by subclassing the control, but on linux, I'm not sure what to do.
Any idea ?
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Re: Rerouting Events to other Gadgets ?
Never mind,
Got the solution:
PB_Gadget_SendGadgetCommand.l(Window.l, EventType.l)
(Internal PB command imported through Import "")
Cheers,
Guy.
Got the solution:
PB_Gadget_SendGadgetCommand.l(Window.l, EventType.l)
(Internal PB command imported through Import "")
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Re: Rerouting Events to other Gadgets ?
Hmm, in fact, it's for Windows only, it does not work for Linux..
So my question is still valid.
If someone has an idea ?
Cheers,
Guy.
So my question is still valid.
If someone has an idea ?
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
Re: Rerouting Events to other Gadgets ?
There are numerous ways to do it but the easiest is to add a signal callback to a gadget
on 32 bit linux you can use
g_signal_connect(gadgetID,Signal$,*function,*userdata)
for 64 bit you need to import it
ImportC "-gtk"
gsignal_connect(instance,signal.p-ascii,*fn,*vdata,destroy=0,flags=0) As "g_signal_connect_data"
EndImport
for details of the signals see http://developer.gnome.org/gtk/2.24/GtkWidget.html
Here's an example of a workaround fix for the calender gadget so it behaves like it does on windows
on 32 bit linux you can use
g_signal_connect(gadgetID,Signal$,*function,*userdata)
for 64 bit you need to import it
ImportC "-gtk"
gsignal_connect(instance,signal.p-ascii,*fn,*vdata,destroy=0,flags=0) As "g_signal_connect_data"
EndImport
for details of the signals see http://developer.gnome.org/gtk/2.24/GtkWidget.html
Here's an example of a workaround fix for the calender gadget so it behaves like it does on windows
Code: Select all
ImportC "-gtk"
gsignal_connect(instance,signal.p-ascii,*fn,*vdata,destroy=0,flags=0) As "g_signal_connect_data"
g_object_set_property(*widget,prop.p-ascii,*val.GValue); ;PB import not defined right for unicode
g_date_new() ;pb import not defined right
g_date_valid(*date.GDate) ;pb import not defined right
EndImport
Macro G_TYPE_MAKE_FUNDAMENTAL(x)
((x) << 2)
EndMacro
#G_TYPE_BOOLEAN = G_TYPE_MAKE_FUNDAMENTAL(5)
Prototype ProtoDateCB(date.s)
Global iCurrentDate.s,idateinvalid.i,ikey
ProcedureC iDateGadgetClick(*editable.GtkEditable,*event.GdkEventButton,*usrdata)
Protected startpos,*entry.GtkEntry,currentdate.s
;get the current date abd set the selection
*entry = *editable
iCurrentdate = PeekS(*entry\text,*entry\text_length,#PB_UTF8)
startpos = gtk_editable_get_position_(*editable)
If (startpos <> 2 And startpos <> 5)
gtk_editable_select_region_(*editable,startpos,startpos+1);
EndIf
EndProcedure
ProcedureC iDateGadgetKeyPress(*editable.GtkEditable,*event.GdkEventKey,*usrdata)
Protected key,startpos,*entry.GtkEntry
Protected *date
;need to test if the key entry is going to result in a valid date
;so check the current entry text and replace the charicter with the new one
key = *event\keyval & $FF
If key >= '0' And key <= '9'
ikey=1
*date = g_date_new()
*entry = *editable
startpos = gtk_editable_get_position_(*editable)
tdate.s = PeekS(*entry\text,*entry\text_length,#PB_UTF8 )
key = *event\keyval & $FF
tdate = Left(tdate,startpos-1) + Chr(key) + Right(tdate,10-startpos)
g_date_set_parse_(*date,tdate)
If g_date_valid(*date)
iCurrentDate = tdate
Else
idateinvalid =1
EndIf
g_date_free_(*date)
EndIf
EndProcedure
ProcedureC iDateGadgetKeyRel(*editable.GtkEditable,*event.GdkEventKey,*usrdata)
Protected key,startpos
;handle arrow keys to move selection
startpos = gtk_editable_get_position_(*editable)
key = *event\keyval & $FF
If startpos > 0
If key = 81
If (startpos <> 3 And startpos <> 6)
startpos -1
Else
startpos-2
EndIf
gtk_editable_select_region_(*editable,startpos,startpos+1);
ElseIf key = 83
If (startpos <> 1 And startpos <> 4)
startpos +1
Else
startpos +2
EndIf
gtk_editable_select_region_(*editable,startpos,startpos+1);
EndIf
EndIf
EndProcedure
ProcedureC iDateChanged(*entry.GtkEntry,*usrdata)
Protected sdate.s, cb.ProtoDateCB
Protected *date
Static eat
cb = *usrdata
If Not idateinvalid
If Not ikey
sdate = Trim(PeekS(*entry\text,*entry\text_length,#PB_UTF8 ))
cb(sdate)
Else
ikey=0
EndIf
Else
;if the date is invalid reset it to the last entry
gtk_entry_set_text_(*entry,iCurrentDate)
idateinvalid = 0
EndIf
EndProcedure
;user functions
Procedure DateGadgetEx(gadget,x,y,width,height,format.s,*cbDateChanged)
Protected *entry,gad
Protected gval.GValue
If gadget = #PB_Any
gad = DateGadget(gadget, x, y, width, height,format)
Else
DateGadget(gadget, x, y, width, height,format)
gad = gadget
EndIf
If *cbDateChanged
*entry = GadgetID(gad);gtk_widget_get_ancestor_(GadgetID(gad), gtk_entry_get_type_());
If *entry
g_value_init_(@gval,#G_TYPE_BOOLEAN)
g_value_set_boolean_(@gval, #True)
g_object_set_property(*entry,"editable",@gval);
gtk_entry_set_max_length_(*entry,10)
gsignal_connect(*entry,"button-release-event",@iDateGadgetClick(),0)
gsignal_connect(*entry,"key-release-event",@iDateGadgetKeyRel(),0)
gsignal_connect(*entry,"key-press-event",@iDateGadgetKeyPress(),0)
gsignal_connect(*entry,"changed",@iDateChanged(),*cbDateChanged)
ProcedureReturn gad
EndIf
EndIf
ProcedureReturn gad
EndProcedure
Procedure DateChanged(sdate.s)
Debug sdate
EndProcedure
If OpenWindow(0, 0, 0, 300, 300, "DateGadgetTest", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
DateGadgetEx(1, 8, 8, 120, 28, "%dd.%mm.%yyyy",@DateChanged())
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Debug "In Linux no event at all"
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
Windows 11, Manjaro, Raspberry Pi OS


- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Re: Rerouting Events to other Gadgets ?
That's exactly what I was looking for.
A big thanks to you.
Cheers,
Guy.
A big thanks to you.
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Re: Rerouting Events to other Gadgets ?
In fact I would need an additional information:
Once I'm in the iDateGadgetClick callback for instance, what should I do to 'pass-through' or 're-send' the same event I just recieve to another Widget ?
Cheers,
Guy.
Once I'm in the iDateGadgetClick callback for instance, what should I do to 'pass-through' or 're-send' the same event I just recieve to another Widget ?
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
Re: Rerouting Events to other Gadgets ?
you can use
and catch the event in the main loop
Code: Select all
gtk_signal_emit_by_name_(GadgetID,"signal",0);
Windows 11, Manjaro, Raspberry Pi OS


- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Re: Rerouting Events to other Gadgets ?
Ah, thanks a lot, it seems to be the solution yes, but strangely when I use it to send to the "other" GadgetID I get an "Invalid Memory Access" (yet the pointer is not null) while when I send it to itself it works ( I get multiple events ).idle wrote:you can use
and catch the event in the main loopCode: Select all
gtk_signal_emit_by_name_(GadgetID,"signal",0);
Yet the "other" GadgetID is used with other gtk api calls without triggering the error. It works.
I'm puzzled.. I'll investigate further..
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Re: Rerouting Events to other Gadgets ?
I've found the solution, I have to make room for the returned values:
gtk_signal_emit_by_name( GadgetID, "button-press-event", @event, @retval )
It does not crash anymore.
However the signal is not resent in the PB event main loop. Are you sure it should appear in the event main loop ?
Cheers,
Guy.
gtk_signal_emit_by_name( GadgetID, "button-press-event", @event, @retval )
It does not crash anymore.
However the signal is not resent in the PB event main loop. Are you sure it should appear in the event main loop ?
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
Re: Rerouting Events to other Gadgets ?
some but not all events will be caught in the main loop.
but I suppose you could connect a callback to handle the emitted signal.
but I suppose you could connect a callback to handle the emitted signal.
Windows 11, Manjaro, Raspberry Pi OS


- grabiller
- Enthusiast

- Posts: 309
- Joined: Wed Jun 01, 2011 9:38 am
- Location: France - 89220 Rogny-Les-Septs-Ecluses
- Contact:
Re: Rerouting Events to other Gadgets ?
That's what I'm doing but then I need to forward the signal to another widget wich does not recieve the user inputs.
Connecting callbacks to this other widget would be useless as it wont recieve events.
Anyway, I'm still investigating but I'm also reconsidering my linux approach.
Until now I was trying to 'port' my windows code wich works perfectly well (very fast, very easy to forward messages, to alter widgets programmaticaly and have immediate update of the layout before it gets painted, wich does not work on linux afaik).
But perhaps I should considere a different way more suitable to linux/gtk. The challenge beeing to achieve the exact same look and behavior of the widgets accross plateforms (and I did not touched Mac OS X yet.. ). This is the foundation of a heavy project and before I go any further I need to do this part absolutely right.
Someone on IRC suggested me to use only GTK on all tree platforms but I'm not convainced. From my experiments, native win32 UI is much faster (but perhaps someone will prove me wrong) and UI performance is also a big concern to me. Cocoa should be faster than gtk too on Mac ( but I did not use it yet so I can't really be sure). Plus, that would defeat the purpose of taking advantage of PureBasic and it's cross-plateform loop/events system (even though there is a need to use natives api calls here and there but this is far different from integrating a all new toolkit on all tree plateforms into PB).
This is not an easy problem, but I want to find the best approach. Perhaps I should forget all about native api calls and only use custom widgets entierly done in PB with the CanvasGadget. That's what I'll experiment next, I'm not sure about the performances of this approach yet but perhaps this is the solution.
Cheers,
Guy.
Connecting callbacks to this other widget would be useless as it wont recieve events.
Anyway, I'm still investigating but I'm also reconsidering my linux approach.
Until now I was trying to 'port' my windows code wich works perfectly well (very fast, very easy to forward messages, to alter widgets programmaticaly and have immediate update of the layout before it gets painted, wich does not work on linux afaik).
But perhaps I should considere a different way more suitable to linux/gtk. The challenge beeing to achieve the exact same look and behavior of the widgets accross plateforms (and I did not touched Mac OS X yet.. ). This is the foundation of a heavy project and before I go any further I need to do this part absolutely right.
Someone on IRC suggested me to use only GTK on all tree platforms but I'm not convainced. From my experiments, native win32 UI is much faster (but perhaps someone will prove me wrong) and UI performance is also a big concern to me. Cocoa should be faster than gtk too on Mac ( but I did not use it yet so I can't really be sure). Plus, that would defeat the purpose of taking advantage of PureBasic and it's cross-plateform loop/events system (even though there is a need to use natives api calls here and there but this is far different from integrating a all new toolkit on all tree plateforms into PB).
This is not an easy problem, but I want to find the best approach. Perhaps I should forget all about native api calls and only use custom widgets entierly done in PB with the CanvasGadget. That's what I'll experiment next, I'm not sure about the performances of this approach yet but perhaps this is the solution.
Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
-
BorisTheOld
- Enthusiast

- Posts: 542
- Joined: Tue Apr 24, 2012 5:08 pm
- Location: Ontario, Canada
Re: Rerouting Events to other Gadgets ?
To avoid the complication of generating events, why not try doing a simple procedure call. We've been using this technique for many years with Visual Basic, Power Basic, and now PB.
If our program needs to create a non-standard or user event in order to process some gadget code, we just call the appropriate procedure and don't bother creating an actual event. This technique allows pseudo-events to be directed at any gadget code we choose. And if timing is an issue then we schedule the call after a known real event, or use a timer set to a short delay.
Another technique is to use standard events in a non-standard way. For example, set up an off-screen gadget that can be used to trap got-focus events, then code its event routine to perform the various functions you need. These events can be initiated from within code by setting focus to the off-screen gadget. You can use this gadget's data word to hold a user message number.
These techniques have the advantage of being cross-platform, because they don't require API code.
If our program needs to create a non-standard or user event in order to process some gadget code, we just call the appropriate procedure and don't bother creating an actual event. This technique allows pseudo-events to be directed at any gadget code we choose. And if timing is an issue then we schedule the call after a known real event, or use a timer set to a short delay.
Another technique is to use standard events in a non-standard way. For example, set up an off-screen gadget that can be used to trap got-focus events, then code its event routine to perform the various functions you need. These events can be initiated from within code by setting focus to the off-screen gadget. You can use this gadget's data word to hold a user message number.
These techniques have the advantage of being cross-platform, because they don't require API code.
For ten years Caesar ruled with an iron hand, then with a wooden foot, and finally with a piece of string.
~ Spike Milligan
~ Spike Milligan
