Re: gdkmm: how to destroy gdk window?



Thank you, Kjell.

Frankly speaking I do not remember why I made my widget pretend windowless. I've changed the code according to the examples and everything seems to work now.

But it's really very strange to have such an API. I can think at least of two issues about it.

First is what if a custom widget has more than one window? It can set one of them as the widget's window with Widget::set_window() and then when it's time to unrealise the resources it will be destroyed by Widget::unrealize() function. But what about the others? Does the user have to destroy them with direct gdk_window_destroy() call?

The other thought is about the symmetry of the API. The user herself creates the window with Gdk::Window::create() but then it is supposed to be destroyed implicitly. It's really not obvious from the documentation. Also there is a pitfall in GTK+ docs. Although it is not stated in the API description gtk_widget_realize() and gtk_widget_unrealize() are not really complete antagonists. I mean if you want to call Gtk::Widget::realize() (or gtk_widget_realize(), doesn't matter) from you custom widget's on_realize() method then you can do this only if your widget is windowless. But unlike realize method it appears that you have to call Gtk::Widget::unrealize() if your widget is both window or no-window widget.

This is just thinking out loud. Maybe GTK+/gtkmm developers will pay attention to this.

С уважением,
Кирсанов Виталий
ICQ: 193259120


2013/4/18 Kjell Ahlstedt <kjell ahlstedt bredband net>
Have you looked at the custom widget example in the gtkmm tutorial?

https://developer.gnome.org/gtkmm-tutorial/stable/sec-custom-widgets.html.en
https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/custom/custom_widget/mywidget.cc

Two differences between your code and the custom widget example strike me.

1. In on_realize() you have set_window(get_parent_window()) instead of set_window(_event_window).

2. In on_unrealize() you have set_realized(false) where the custom widget example has Gtk::Widget::on_unrealize().
   Gtk::Widget::on_unrealize() calls gtk_widget_real_unrealize() which among other things calls gdk_window_destroy().

The custom widget example is written for gtkmm3. I don't know if some details are different in gtkmm2.

This bug discusses the warning that you get: https://bugzilla.gnome.org/show_bug.cgi?id=606903
I have written some of the comments in that bug, but I don't remember all the details now.

Kjell

2013-04-17 23:01, Виталий Кирсанов skrev:
Please call me an earth worm if I'm using this mailing list inapropriately. But maybe somebody can help me.

Status quo: I have a custom widget (MyWidget) with an event window.
Problem: if I create, show and then, later, hide and destroy the widget I get the following message from the application:

Gdk-WARNING **: losing last reference to undestroyed window

What I've found out: I've had a look in gdkwindow.c file and this message is reported whenGDK_WINDOW_DESTROYED(window) == FALSE. So the thing I do not understand is how I should destroy my window correctly so that eventually gdk_window_destroy() function is called. I thought that the best place to call it was the Gdk::~Window() destructor. But it's empty. And moreovergdk_window_destroy() is absent in gdkwindow.cc file at all.

The on_realize() and on_unrealize() call-backs are below.

class MyWidget
 : public Gtk::Widget
{
...
private:
    Glib::RefPtr<Gdk::Window>   _event_window;
...
};

void Gtk::MyWidget::on_realize()
{
    GdkWindowAttr       attributes;
    const Allocation    & allocation = get_allocation();

    attributes.event_mask = GDK_BUTTON_PRESS_MASK;

    attributes.x = allocation.get_x();
    attributes.y = allocation.get_y();
    attributes.width = allocation.get_width();
    attributes.height = allocation.get_height();
    attributes.wclass = GDK_INPUT_ONLY;
    attributes.window_type = GDK_WINDOW_CHILD;

    _event_window = Gdk::Window::create(get_parent_window(), &attributes, GDK_WA_X | GDK_WA_Y);
    _event_window->set_user_data(Widget::gobj());

    set_window(get_parent_window());

    set_realized();
}

void Gtk::MyWidget::on_unrealize()
{
    _event_window->set_user_data(NULL);
    _event_window.reset();

    set_realized(false);
}

Best regards,
Vitaly Kirsanov
ICQ: 193259120





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]