GtkEventBox - X window

I have a Question where I am not sure that I am clearly Understand it.

If I need to catch events on a widget which has no window, then I need an EventBox.
An EventBox create (provide) a window for those widgets, and here is the part where I am not sure.

To actually have a X Window, one needs the following function call:

gtk_widget_realize ( event_box );

Now if is so, why I am getting

The EventBox has a Window

in the scroll_callback funcion where I am checking:

if ( gtk_widget_get_has_window ( widget )

Because the gtk_widget_realize call is commented.

Here is the program:

#include <gtk/gtk.h>

gboolean scroll_callback ( GtkWidget *widget, GdkEvent  *event, gpointer data );

int main ( void )
{
    GtkWidget *window;
    GtkWidget *event_box;
    gtk_init ( NULL, NULL );
    /// ***
    window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
    gtk_window_set_default_size ( GTK_WINDOW ( window ), 300, 250 );
    g_signal_connect ( window, "destroy", gtk_main_quit, NULL );
    gtk_container_set_border_width ( GTK_CONTAINER ( window ), 50 );
    /// ***
    event_box = gtk_event_box_new();
    gtk_widget_set_events ( event_box, GDK_SCROLL_MASK );
    gtk_container_add ( GTK_CONTAINER ( window ), event_box );
    ///gtk_widget_realize ( event_box );
    /// ***
    g_signal_connect ( event_box, "scroll_event", G_CALLBACK ( scroll_callback ), window );
    /// ***
    gtk_widget_show_all ( window );
    gtk_main();
}

gboolean scroll_callback ( GtkWidget *widget, GdkEvent  *event, gpointer data )
{
    if ( gtk_widget_get_has_window ( widget ) )
    {
        printf ( "\n\tThe EventBox has a Window\n" );

        if ( event->type == GDK_SCROLL ) /// Scroll the was Catched
        {
            if ( event->scroll.direction == GDK_SCROLL_DOWN )
            {
                g_print ( "Scroll-Down Detected\n" );
                gtk_window_set_title ( GTK_WINDOW ( data ), "Scroll-Down Detected" );
            }

            if ( event->scroll.direction == GDK_SCROLL_UP )
            {
                g_print ( "Scroll-UP Detected\n" );
                gtk_window_set_title ( GTK_WINDOW ( data ), "Scroll-UP Detected" );
            }

            return FALSE;
        }
    }

    printf ( "\n\tThe EventBox has NO Window\n" );
    return TRUE;
}

You are not telling us what you really intent.

A GtkEventBox is generally be used when you want to get events from a widget that does not offer getting events, like GtkLabel. So you put the label as child into the eventbox. The eventbox has a window, you can get events from the eventbox. There is generally no need to call
gtk_widget_realize() in your code. That is as I remember it from the A. Krause book – have never used a GtkEventBox myself. For GTK4 it may be different, don’t know.

I know exactly how EventBox works and I think you are wrong. From what I know is that this does not apply to GtkEventBox and they have no window during creation.
Please check the following code and you will understand that it might be other way you think it is:

#include <gtk/gtk.h>

void load_css ( void );

int main ( void )
{
GtkWidget *window;
GdkWindow *display;
GdkCursor *cursor;
GtkWidget *event_box;
GtkWidget *label;
/// ***
gtk_init ( NULL, NULL );
load_css();
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
gtk_window_set_default_size ( GTK_WINDOW ( window ), 400, 250 );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 50 );
/// ***
event_box = gtk_event_box_new();
gtk_widget_show ( event_box );
gtk_container_add ( GTK_CONTAINER ( window ), event_box );
gtk_event_box_set_above_child ( GTK_EVENT_BOX ( event_box ), TRUE );
gtk_event_box_set_visible_window ( GTK_EVENT_BOX ( event_box ), FALSE );
gtk_widget_set_events ( event_box, GDK_BUTTON_PRESS_MASK );
/// ***
label = gtk_label_new_with_mnemonic ( “_Quit” );
gtk_container_add ( GTK_CONTAINER ( event_box ), label );
/// ***
///gtk_widget_realize ( event_box );
/// ***
g_signal_connect ( window, “destroy”, gtk_main_quit, NULL );
/// ***
cursor = gdk_cursor_new_for_display ( gdk_display_get_default(), GDK_CROSSHAIR );
display = gtk_widget_get_window ( event_box );
gdk_window_set_cursor ( display, cursor );
/// ***
gtk_widget_show_all ( window );
gtk_main();
}

void load_css ( void )
{
GtkCssProvider *provider;
GdkDisplay *display;
GdkScreen *screen;
/// ***
const gchar *css_style_file = “style.css”;
GFile *css_fp = g_file_new_for_path ( css_style_file );
GError *error = 0;
/// ***
provider = gtk_css_provider_new ();
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen ( display );
/// ***
gtk_style_context_add_provider_for_screen ( screen, GTK_STYLE_PROVIDER ( provider ), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION );
gtk_css_provider_load_from_file ( provider, css_fp, &error );
/// ***
g_object_unref ( provider );
}

That may be true, it is more than 10 years ago when I read the Krause book, and that was still GTK2 only.

1 Like

gtk_widget_get_has_window() only returns what was set with gtk_widget_set_has_window() (defaults to true). If false, the widget is not expected to create a GdkWindow in realize.

A better test would be gtk_widget_get_realized(). You could possibly connect_after the "realize" signal if you want to set the initial cursor.

1 Like

So this means that at the creation time where:

`event_box = gtk_event_box_new();`

takes place, the eventbox has no window?

Anyway if is so, then I still do not understand why

   `if ( gtk_widget_get_has_window ( widget )`

returns TRUE, because I did not called
gtk_widget_set_has_window();
Or
gtk_widget_realize ( event_box );
So this is my problem here.
Why I am getting TRUE and not how do I properly check it.

The widget implementation calls set_has_window(), not you. GtkEventBox in particular can be used in both modes depending on its visible-window property.

In other words, gtk_widget_get_has_window() tells you whether the window returned by gtk_widget_get_window() after the realize signal belongs to the widget or to a parent. Before the realize signal, it should be NULL for any widget. If you wanted to generically check for an existing GdkWindow that belongs to the widget, you could use:

if (gtk_widget_get_has_window (widget) && gtk_widget_get_realized (widget))

But typically, you should know whether a given widget has its own window; it’s not going to change at runtime unless you change something like the aforementioned GtkEventBox visible-window property.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.