[RESOLVED] How to Trap a GTK Event?

Linux specific forum
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

[RESOLVED] How to Trap a GTK Event?

Post by Straker »

Hi all,

I am trying to trap a mouseover event on an ImageGadget in GTK/Linux, but have no idea how to do this. Specifically I am trying to emulate the Firefox Preferences toolbar which highlights graphics when a mouse moves over them, then changes to a darker color when selected. Its the mouseover that I am having trouble with.

Or better yet, can anyone describe how to trap any/all GTK events? (here's a similar windows thread: viewtopic.php?t=12352 )

Here is a screenshot showing the event in Linux:

Image

Thanks
Last edited by Straker on Thu Mar 23, 2006 8:12 pm, edited 1 time in total.
Beach
Enthusiast
Enthusiast
Posts: 677
Joined: Mon Feb 02, 2004 3:16 am
Location: Beyond the sun...

Post by Beach »

I would like to know how to do this also. :)
-Beach
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Thanks Beach. I was getting kinda lonely here by myself.
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

I think you will have to connect a "enter-notify-event" signal and a "leave-notify-event" to the widget and handle you code in the associated callbacks : http://developer.gnome.org/doc/API/2.0/ ... tify-event
for a complete list of events for widgets (the ImageGadget() is a GtkPixmap).
Beach
Enthusiast
Enthusiast
Posts: 677
Joined: Mon Feb 02, 2004 3:16 am
Location: Beyond the sun...

Post by Beach »

Fred wrote:I think you will have to connect a "enter-notify-event" signal and a "leave-notify-event" to the widget and handle you code in the associated callbacks
Nice, thanks Fred!

@Straker; let me know if you figure it out first. :)
-Beach
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

This comes from the top of my head (no linux right now), so expect some mistakes :)

Code: Select all

; Wrapper to call the correct function for both Gtk Versions.
; #GTKVersion must be defined somewhere!
#GtkVersion = 1
;
Procedure GTKSignalConnect(*Widget, Signal$, Function, user_data)
  CompilerIf #GTKVersion = 1
    gtk_signal_connect_(*Widget, @Signal$, Function, user_data)
  CompilerElse
    g_signal_connect_data_(*Widget, @Signal$, Function, user_data, 0, 0)
  CompilerEndIf
EndProcedure


; This is a signal callback. Note the CDLL declaration. that is important.
; the user_data field helps to pass additional data.
;
ProcedureCDLL EventCallback(*Widget, *Event.GdkEventCrossing, user_data)
  If user_data = 1
    Debug "Enter Event"
  Else
    Debug "Leave Event"
  EndIf
EndProcedure


; connect the signals...
GTKSignalConnect(GadgetID(#MyGAdget), "enter-notify-event", @EventCallback(), 1)
GTKSignalConnect(GadgetID(#MyGAdget), "leave-notify-event", @EventCallback(), 2)
Something like that...
quidquid Latine dictum sit altum videtur
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Wow - thanks for the response guys. I will be testing this today. I have been browsing this area as well:

http://lidn.sourceforge.net

I am no C programmer, and am a n00b with regards to callbacks and pointers, but I'll try to cobble some code together and post it back here.

Thanks again.
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

OK - This is not working, however, some things to note:

1) I added the gtk_init_() and gdk_init_() functions which I found in another thread. Don't know if these are required but they don't appear to be harmful.

2) the GtkVersion can be obtained directly with #GTK_MAJOR_VERSION (link).

3) replace "MyImage.s" var below with your own image to test.

4) I just confirmed in a bug report that the ImageGadget on Linux does not appear to be capturing any events. So, I don't know if the following code is not working because of that bug or if the code is wrong (but it compiles and runs without apparent error). More details here.

Code: Select all

gtk_init_(0,0)
gdk_init_(0,0)

Procedure GTKSignalConnect(*Widget, Signal$, Function, user_data)
  CompilerIf #GTK_MAJOR_VERSION = 1
    gtk_signal_connect_(*Widget, @Signal$, Function, user_data)
  CompilerElse
    g_signal_connect_data_(*Widget, @Signal$, Function, user_data, 0, 0)
  CompilerEndIf
EndProcedure


; This is a signal callback. Note the CDLL declaration. that is important.
; the user_data field helps to pass additional data.
;
ProcedureCDLL EventCallback(*Widget, *Event.GdkEventCrossing, user_data)
  If user_data = 1
    Debug "Enter Event"
  Else
    Debug "Leave Event"
  EndIf
EndProcedure

UseJPEGImageDecoder()
#MyGAdget = 0
MyImage.s = "r2d2.jpg"

  If OpenWindow(0,0,0,345,105,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"ImageGadget") And CreateGadgetList(WindowID(0))
    If LoadImage(0, MyImage.s)    ; change 2nd parameter to the path/filename of your image
      ImageGadget(#MyGAdget, 10,10,100,83,UseImage(0))                      ; imagegadget standard
      ;ImageGadget(1,130,10,100,83,UseImage(0),#PB_Image_Border)     ; imagegadget with border
      ButtonGadget(1, 200, 10, 100, 30, "Test")
      ; connect the signals...
      GTKSignalConnect(GadgetID(#MyGAdget), "enter-notify-event", @EventCallback(), 1)
      GTKSignalConnect(GadgetID(#MyGAdget), "leave-notify-event", @EventCallback(), 2) 


   Repeat
     EventID = WaitWindowEvent()
     
     Select EventID
     
       Case #PB_Event_Gadget
         Select EventGadgetID()
           Case 0 : Debug "Image 0 clicked!"
           Case 1 : Debug "Button 1 clicked!"
         EndSelect
     
     EndSelect
   Until EventID = #PB_Event_CloseWindow


    EndIf
    
  EndIf
Any comments are appreciated.

Thanks again.
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

Sorry, i did not read about the ImageGadget part...

The fact is that a GtkPixmap (ImageGadget) does not have an associated gdk window
like the other widgets have. (the contents seem to be directly drawn on the parent)
So you cannot receive such events from the ImageGadget.
Its not PB's fault.. its a Gtk thing.

What you have to do is put it on a ContainerGadget with the same size and
register the callback for that gadget.
I did the same for the IDE colorpicker and it works well.

About the gtk_init_(). It is called PB's initialisation functions once you use
any of the Gadget/Window commands afaik.
quidquid Latine dictum sit altum videtur
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Thanks freak. But I am not having any luck with the container gadget either. The button gadget works fine with your code however. Run the following test program to see the difference.

Code: Select all

Procedure GTKSignalConnect(*Widget, Signal$, Function, user_data)
  CompilerIf #GTK_MAJOR_VERSION = 1
    gtk_signal_connect_(*Widget, @Signal$, Function, user_data)
  CompilerElse
    g_signal_connect_data_(*Widget, @Signal$, Function, user_data, 0, 0)
  CompilerEndIf
EndProcedure

; This is a signal callback. Note the CDLL declaration. that is important.
; the user_data field helps to pass additional data.
;
ProcedureCDLL EventCallback(*Widget, *Event.GdkEventCrossing, user_data)
  Select user_data
   Case 1 : Debug "container enter event"
   Case 2 : Debug "container leave event"
   Case 3 : Debug "button enter event"
   Case 4 : Debug "button leave event"
  EndSelect
EndProcedure

#MyContainer = 10
#MyButton = 11

If OpenWindow(0,0,0,345,105,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Event Test") And CreateGadgetList(WindowID(0))
  ButtonGadget(#MyButton, 200, 10, 100, 30, "Test")
  ContainerGadget(#MyContainer, 10,10,100,83,#PB_Container_Raised)
    
  ; connect the signals...
  GTKSignalConnect(*GadgetID(#MyContainer), "enter-notify-event", @EventCallback(), 1)
  GTKSignalConnect(*GadgetID(#MyContainer), "leave-notify-event", @EventCallback(), 2) 

  GTKSignalConnect(*GadgetID(#MyButton), "enter-notify-event", @EventCallback(), 3)
  GTKSignalConnect(*GadgetID(#MyButton), "leave-notify-event", @EventCallback(), 4) 

  Repeat
     EventID = WaitWindowEvent()
          
     Select EventID
     
       Case #PB_Event_Gadget
         Select EventGadgetID()
           Case #MyContainer : Debug "Container clicked!"
           Case #MyButton : Debug "Button clicked!"
         EndSelect
     
     EndSelect
   Until EventID = #PB_Event_CloseWindow
    
EndIf

End
I have also been experimenting with GtkEventBox but to no avail.

Thanks.
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

Any news on this?
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Not as of yet. I did PM another member about it - but never got a response.

Maybe DarkDragon can shed some light on this, as I know he has been digging into the GTK/GDK interfaces.

If not - I was planning on converting this C code which does this, but so far, I have not been able to get it to work either. If anyone wants to take a shot at it here it is:

http://www.gtk.org/tutorial/c1247.html

If we can figure out how to bind GTK EventBoxes, then we should be able to map any event to any control.
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

ATM, it is difficult to me to find enough spare time on coding :(
I ll let you know if i could dig a bit.
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
Straker
Enthusiast
Enthusiast
Posts: 701
Joined: Wed Apr 13, 2005 10:45 pm
Location: Idaho, USA

Post by Straker »

Thanks for the reply.
KarLKoX wrote:ATM, it is difficult to me to find enough spare time on coding :(
I am also in this situation right now.

Cheers.
StanDan
User
User
Posts: 57
Joined: Sun Feb 26, 2006 3:43 am
Location: Missouri, United States

Possible solution?

Post by StanDan »

I tried a couple different things. Including using an evenbox.

Code: Select all

Procedure GTKSignalConnect(*Widget, Signal$, Function, user_data)
  CompilerIf #GTK_MAJOR_VERSION = 1
    gtk_signal_connect_(*Widget, @Signal$, Function, user_data)
  CompilerElse
    g_signal_connect_data_(*Widget, @Signal$, Function, user_data, 0, 0)
  CompilerEndIf
EndProcedure

; This is a signal callback. Note the CDLL declaration. that is important.
; the user_data field helps to pass additional data.
;
ProcedureCDLL EventCallback(*Widget, *Event.GdkEventCrossing, user_data)
  Select user_data
   Case 1 : Debug "container enter event"
   Case 2 : Debug "container leave event"
   Case 3 : Debug "button enter event"
   Case 4 : Debug "button leave event"
  EndSelect
EndProcedure

#MyContainer = 10
#MyButton = 11

If OpenWindow(0,0,0,345,105,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Event Test") And CreateGadgetList(WindowID(0))
  ButtonGadget(#MyButton, 200, 10, 100, 30, "Test")
  ContainerGadget(#MyContainer, 10,10,100,83,#PB_Container_Raised)
  *event_box.GtkWidget = gtk_event_box_new_()
  gtk_container_add_(*GadgetID(#MyContainer), *event_box)
  gtk_widget_show_(*event_box)
  ; connect the signals...
  
  gtk_widget_set_events_(*event_box, #GDK_ENTER_NOTIFY_MASK | #GDK_LEAVE_NOTIFY_MASK);
  GTKSignalConnect(*event_box, "enter-notify-event", @EventCallback(), 1)
  GTKSignalConnect(*event_box, "leave-notify-event", @EventCallback(), 2)

  GTKSignalConnect(*GadgetID(#MyButton), "enter-notify-event", @EventCallback(), 3)
  GTKSignalConnect(*GadgetID(#MyButton), "leave-notify-event", @EventCallback(), 4)
  gtk_widget_realize_(*event_box);
  Repeat
     EventID = WaitWindowEvent()
         
     Select EventID
     
       Case #PB_Event_Gadget
         Select EventGadgetID()
           Case #MyContainer : Debug "Container clicked!"
           Case #MyButton : Debug "Button clicked!"
         EndSelect
     
     EndSelect
   Until EventID = #PB_Event_CloseWindow
   
EndIf

End 
But this doesn't work. Very frusterating.

Anyway, did you try just using a button and packing the stuff into it? This actually does work.

Code: Select all

Procedure GTKSignalConnect(*Widget, Signal$, Function, user_data)
  CompilerIf #GTK_MAJOR_VERSION = 1
    gtk_signal_connect_(*Widget, @Signal$, Function, user_data)
  CompilerElse
    g_signal_connect_data_(*Widget, @Signal$, Function, user_data, 0, 0)
  CompilerEndIf
EndProcedure

; This is a signal callback. Note the CDLL declaration. that is important.
; the user_data field helps to pass additional data.
;
ProcedureCDLL EventCallback(*Widget, *Event.GdkEventCrossing, user_data)
  Select user_data
   Case 1 : Debug "container enter event"
   Case 2 : Debug "container leave event"
   Case 3 : Debug "button enter event"
   Case 4 : Debug "button leave event"
  EndSelect
EndProcedure

; from the GTK+ tutorial
Procedure.l xpm_label_box( xpm_filename$, label_text$ )
    *box.GtkWidget;
    *label.GtkWidget;
    *image.GtkWidget;

    ;/* Create box For image And label */
    *box = gtk_hbox_new_(#FALSE, 0);
    gtk_container_set_border_width_(*box, 2);

    ;/* Now on To the image stuff */
    *image = gtk_image_new_from_file_(xpm_filename$);

    ;/* Create a label For the button */
    *label = gtk_label_new_(label_text$);

    ;/* Pack the image And label into the box */
    gtk_box_pack_start_(*box, *image, #FALSE, #FALSE, 3);
    gtk_box_pack_start_(*box, *label, #FALSE, #FALSE, 3);

    gtk_widget_show_(*image);
    gtk_widget_show_(*label);

    ProcedureReturn *box
EndProcedure

#MyContainer = 10
#MyButton = 11

If OpenWindow(0,0,0,345,105,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Event Test") And CreateGadgetList(WindowID(0))
  ButtonGadget(#MyButton, 200, 10, 100, 30, "Test")
  ContainerGadget(#MyContainer, 10,10,100,83,#PB_Container_Raised)
  *box.GtkWidget = xpm_label_box("/tmp/test.xpm", "Testing!")
  *button.GtkWidget = gtk_button_new_()
  ; /* Pack And show all our widgets */
  gtk_widget_show_(*box);
  gtk_container_add_(*button, *box);

  gtk_container_add_(*GadgetID(#MyContainer), *button)
  gtk_widget_show_(*button)
  ; connect the signals...
  
  GTKSignalConnect(*button, "enter-notify-event", @EventCallback(), 1)
  GTKSignalConnect(*button, "leave-notify-event", @EventCallback(), 2)

  GTKSignalConnect(*GadgetID(#MyButton), "enter-notify-event", @EventCallback(), 3)
  GTKSignalConnect(*GadgetID(#MyButton), "leave-notify-event", @EventCallback(), 4)
  gtk_widget_realize_(*event_box);
  Repeat
     EventID = WaitWindowEvent()
         
     Select EventID
     
       Case #PB_Event_Gadget
         Select EventGadgetID()
           Case #MyContainer : Debug "Container clicked!"
           Case #MyButton : Debug "Button clicked!"
         EndSelect
     
     EndSelect
   Until EventID = #PB_Event_CloseWindow
   
EndIf

End 
You could set the colors in the callback.
Post Reply