You are not logged in.
Hey all,
I've come across this situation a few times before but I have always ignored it because I came up with a different approach. This time though my curiosity got the better of me (and I don't yet have another approach ) so I want to know why this happens.
I have my program here: GXMS. When you compile it, it says:
gxms.c: In function ‘keypress’:
gxms.c:38:31: let op: unused parameter ‘widget’ [-Wunused-parameter]
gboolean keypress (GtkWidget *widget, GdkEventKey *event) {
The thing is, when I remove that so-called "unused" parameter, the program doesn't function anymore! This function is supposed to bring up the searchbar, but it does not anymore. Here is the function:
gboolean keypress (GtkWidget *widget, GdkEventKey *event) {
guint(g) = event->keyval;
if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) {
switch (g) {
case GDK_KEY_f:
show_search(TRUE);
return TRUE;
break;
default:
return FALSE;
break;
}
}
if (gtk_widget_has_focus (searchbar)) {
if (g == GDK_KEY_Escape) {
show_search (FALSE);
gtk_widget_grab_focus (view);
return TRUE;
}
if ((g == GDK_KEY_Return) && (event->state & GDK_MOD1_MASK) == GDK_MOD1_MASK)
search ();
}
return FALSE;
}
When I define *widget inside the function, like below, it doesn't work anymore either:
gboolean keypress (GdkEventKey *event) {
GtkWidget *widget;
<snip>
Is this a bug in my code, in the compiler, or just one of my mistakes?
Last edited by Unia (2013-04-09 18:39:42)
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
You likely pass keypress() as a callback to a function, do you? Well, this function will call your function with 2 parameters. If your function can take only one bad things happen. If you're lucky your compiler may warn you, but don't rely on that - just look up what the callback is supposed to look like. The Gtk+ Docs will tell you for example.
To suppress the warning you can do either:
// Poor man's approach
void func(int arg) {
(void) arg;
}
// Place this in some header
#if !defined(SPARSE) && defined(__GNUC__)
#define unused __attribute__((unused))
#else
#define unused
#endif
void func(unused int arg) {
}
See also this.
Offline
I call keypress() from within the create_window function, like so:
g_signal_connect (window, "key-press-event", G_CALLBACK(keypress), NULL);
AFAIK, that doesn't actually pass any parameters to keypress().
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
You seem to have trouble to understand callbacks/gtk's event system it seems.
You don't call keypress in this snippet. You pass it as a function pointer to g_signal_connect.
G_CALLBACK is just a macro that casts your function pointer into the GCallback Type, it does not call the function.
keypress() gets always called once "key-press-event" happens.
Offline
You seem to have trouble to understand callbacks/gtk's event system it seems.
You don't call keypress in this snippet. You pass it as a function pointer to g_signal_connect.
G_CALLBACK is just a macro that casts your function pointer into the GCallback Type, it does not call the function.
keypress() gets always called once "key-press-event" happens.
I had that vague idea, yes But I'm still not getting why I need that "unused" variable *widget. My keypress() function does not use it, but it won't work without it.
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
Looks to me like you need to write your keypress function a little differently, but it's been ages since I've done any gtk programming.
Something like:
if widget == searchbar
do some stuff
else if widget == view
do other stuff
You're just jealous because the voices only talk to me.
Offline
Well, let's summarize:
...your callback is registered by g_signal_connect, by passing a function pointer to it.
...your applications enters the gtk_main_loop() at some point.
...when the mainloop notices a key-press-event on the widget you registered the callback on, it will take your registered callback and call it with two parameters: The widget the event happened on, and the event that happened.
...The reason you have to take 2 arguments: Gtk+ demands it. If your function doesn't take 2 arguments the best thing that will happen is a crash.
Offline
Moetunes: Indeed, that works
gboolean keypress (GtkWidget *widget, GdkEventKey *event) {
guint(g) = event->keyval;
if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) {
switch (g) {
case GDK_KEY_f:
show_search(TRUE);
return TRUE;
break;
default:
return FALSE;
break;
}
}
+ if (widget != searchbar) {
if (gtk_widget_has_focus (searchbar)) {
if (g == GDK_KEY_Escape) {
show_search (FALSE);
gtk_widget_grab_focus (view);
return TRUE;
}
if ((g == GDK_KEY_Return) && (event->state & GDK_MOD1_MASK) == GDK_MOD1_MASK)
search ();
}
+ }
return FALSE;
}
SahibBommelig: And thanks to you too! Now I know why the above works and I understand the system I'm using a bit more!
Thanks guys!
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
Offline
One last thing: You don't need this check actually, since you could most likely do:
g_signal_connect (searchbar, "key-press-event", G_CALLBACK(keypress), NULL);
I cant, since I need to capture CTRL+F in view, and not in searchbar, right?
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
The main point being you have multiple widgets defined so you have to do something to check which one the keypress comes from.
You're just jealous because the voices only talk to me.
Offline
The main point being you have multiple widgets defined so you have to do something to check which one the keypress comes from.
Exactly, I get that now
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
Is it really necessary to break; switch statement. you return just before break?
if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) {
switch (g) {
case GDK_KEY_f:
show_search(TRUE);
return TRUE;
break; // This is not needed
default:
return FALSE;
break; // This is not needed
}
}
Offline
Will see about that! Thanks for your suggestion
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
You were right Boogie, code is updated
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline